...
This commit is contained in:
@@ -23,6 +23,18 @@ namespace Hushian.Application.Services
|
|||||||
private readonly GroupService _groupService;
|
private readonly GroupService _groupService;
|
||||||
private readonly ExperService _experService;
|
private readonly ExperService _experService;
|
||||||
private readonly IHubContext<ChatNotificationHub> _hubContext;
|
private readonly IHubContext<ChatNotificationHub> _hubContext;
|
||||||
|
|
||||||
|
public ChatService(IGenericRepository<Conversation> conversationRepository, IGenericRepository<ConversationResponse> conversationResponseRepository, CompanyService companyService, UserService userService, GroupService groupService, ExperService experService, IHubContext<ChatNotificationHub> hubContext)
|
||||||
|
{
|
||||||
|
_ConversationRepository = conversationRepository;
|
||||||
|
_ConversationResponseRepository = conversationResponseRepository;
|
||||||
|
_companyService = companyService;
|
||||||
|
_userService = userService;
|
||||||
|
_groupService = groupService;
|
||||||
|
_experService = experService;
|
||||||
|
_hubContext = hubContext;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<List<ChatItemDto>> GeChatsByExperID(int ExperID, ConversationStatus status)
|
public async Task<List<ChatItemDto>> GeChatsByExperID(int ExperID, ConversationStatus status)
|
||||||
=> await _ConversationRepository.Get()
|
=> await _ConversationRepository.Get()
|
||||||
.Include(inc => inc.Group)
|
.Include(inc => inc.Group)
|
||||||
@@ -257,5 +269,35 @@ namespace Hushian.Application.Services
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> MarkAsReadChatItem(int ID, ConversationType Type, int? ExperID)
|
||||||
|
{
|
||||||
|
var item = await _ConversationResponseRepository.Get()
|
||||||
|
.Include(inc => inc.conversation).FirstOrDefaultAsync(w => w.ID == ID && !w.ExperID.HasValue
|
||||||
|
&& w.conversation.Status != ConversationStatus.Finished);
|
||||||
|
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
if (Type != item.Type)
|
||||||
|
{
|
||||||
|
if (Type != ConversationType.UE && item.conversation.Status == ConversationStatus.Recorded)
|
||||||
|
{
|
||||||
|
item.conversation.Status = ConversationStatus.InProgress;
|
||||||
|
await _ConversationRepository.UPDATE(item.conversation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!item.IsRead)
|
||||||
|
{
|
||||||
|
item.IsRead = true;
|
||||||
|
item.ReadDateTime = DateTime.Now;
|
||||||
|
item.ExperID = ExperID;
|
||||||
|
return (await _ConversationResponseRepository.UPDATE(item)) != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,11 +16,12 @@ namespace Hushian.Application.Services
|
|||||||
private readonly VerificationService _VerificationService;
|
private readonly VerificationService _VerificationService;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
public ExperService(IGenericRepository<Exper> experRepository, VerificationService verificationService, IMapper mapper)
|
public ExperService(IGenericRepository<Exper> experRepository, VerificationService verificationService, IMapper mapper, IGenericRepository<Company> companyRepository)
|
||||||
{
|
{
|
||||||
_ExperRepository = experRepository;
|
_ExperRepository = experRepository;
|
||||||
_VerificationService = verificationService;
|
_VerificationService = verificationService;
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
|
_CompanyRepository = companyRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ResponseBase<bool>> ADDExper(ADD_ExperDto dto, int CompanyID)
|
public async Task<ResponseBase<bool>> ADDExper(ADD_ExperDto dto, int CompanyID)
|
||||||
|
@@ -13,6 +13,13 @@ namespace Hushian.WebApi.Controllers.v1
|
|||||||
public class ChatController : ControllerBase
|
public class ChatController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ChatService _chatService; private readonly ExperService _experService;
|
private readonly ChatService _chatService; private readonly ExperService _experService;
|
||||||
|
|
||||||
|
public ChatController(ChatService chatService, ExperService experService)
|
||||||
|
{
|
||||||
|
_chatService = chatService;
|
||||||
|
_experService = experService;
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("MyChats")]
|
[HttpPost("MyChats")]
|
||||||
[Authorize(Roles = "Company,Exper")]
|
[Authorize(Roles = "Company,Exper")]
|
||||||
public async Task<ActionResult> MyChats([FromBody] ConversationStatus status)
|
public async Task<ActionResult> MyChats([FromBody] ConversationStatus status)
|
||||||
@@ -100,5 +107,32 @@ namespace Hushian.WebApi.Controllers.v1
|
|||||||
return await _chatService.FinishChat(ChatID) ? NoContent()
|
return await _chatService.FinishChat(ChatID) ? NoContent()
|
||||||
: BadRequest(new List<string> { "خطا در بروزرسانی وضعیت" });
|
: BadRequest(new List<string> { "خطا در بروزرسانی وضعیت" });
|
||||||
}
|
}
|
||||||
|
[HttpPut("MarkAsReadChatItem/{ConversationItemID}")]
|
||||||
|
[Authorize(Roles = "Company,User,Exper")]
|
||||||
|
public async Task<ActionResult> MarkAsReadChatItem(int ConversationItemID)
|
||||||
|
{
|
||||||
|
int? ExperID = null;
|
||||||
|
ConversationType Type = ConversationType.UE;
|
||||||
|
if (User.IsInRole("Exper"))
|
||||||
|
{
|
||||||
|
string strExperID = User.Claims.Where(w => w.Type == CustomClaimTypes.Uid).Select(s => s.Value).First();
|
||||||
|
ExperID = Convert.ToInt32(strExperID);
|
||||||
|
Type = ConversationType.EU;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (User.IsInRole("User"))
|
||||||
|
{
|
||||||
|
Type = ConversationType.UE;
|
||||||
|
}
|
||||||
|
else if (User.IsInRole("Company"))
|
||||||
|
{
|
||||||
|
Type = ConversationType.CU;
|
||||||
|
}
|
||||||
|
else return Unauthorized();
|
||||||
|
|
||||||
|
return await _chatService.MarkAsReadChatItem(ConversationItemID, Type, ExperID) ? NoContent()
|
||||||
|
: BadRequest(new List<string>() { "خطا در بروزرسانی گفتگو" });
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
@page "/Chant"
|
@page "/Chat"
|
||||||
@using Common.Dtos.Conversation
|
@using Common.Dtos.Conversation
|
||||||
@using Common.Dtos.Group
|
@using Common.Dtos.Group
|
||||||
@using Common.Enums
|
@using Common.Enums
|
||||||
@@ -158,7 +158,44 @@
|
|||||||
<!-- B1: Chat area -->
|
<!-- B1: Chat area -->
|
||||||
<div class="flex-fill border p-2 overflow-auto" id="B1" style="height: 300px; overflow-y: auto;">
|
<div class="flex-fill border p-2 overflow-auto" id="B1" style="height: 300px; overflow-y: auto;">
|
||||||
@if (ChatCurrent != null && ChatCurrent.Responses != null)
|
@if (ChatCurrent != null && ChatCurrent.Responses != null)
|
||||||
{ @B1Content }
|
{
|
||||||
|
<div class="chat-container p-3">
|
||||||
|
@{
|
||||||
|
bool target = false;
|
||||||
|
}
|
||||||
|
@foreach (var msg in ChatCurrent?.Responses)
|
||||||
|
{
|
||||||
|
@if (!target && ((!msg.IsRead && msg.Type == Common.Enums.ConversationType.UE) || ChatCurrent.Responses.Last() == msg))
|
||||||
|
{
|
||||||
|
target = true;
|
||||||
|
<div id="target" style="text-align: center;">
|
||||||
|
@if (!msg.IsRead && msg.Type == Common.Enums.ConversationType.UE)
|
||||||
|
{
|
||||||
|
<p>ـــــــــــــــــــــــــ</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="d-flex mb-2 @(msg.Type==Common.Enums.ConversationType.UE ? "justify-content-end" : "justify-content-start")">
|
||||||
|
<div class="chat-bubble @(msg.Type==Common.Enums.ConversationType.UE ? "chat-mine": "chat-other")" data-id="@msg.ID"> @msg.text </div>
|
||||||
|
@if (msg.Type == Common.Enums.ConversationType.EU)
|
||||||
|
{
|
||||||
|
if (msg.IsRead)
|
||||||
|
{
|
||||||
|
<Icon Style="align-self: self-end;" Name="IconName.CheckAll" Size="IconSize.x5" Color="IconColor.Success" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<Icon Style="align-self: self-end;" Name="IconName.CheckLg" Size="IconSize.x5" />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@{
|
||||||
|
target = false;
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<div class="d-flex justify-content-center align-items-center flex-column" style="height: 80%;">
|
<div class="d-flex justify-content-center align-items-center flex-column" style="height: 80%;">
|
||||||
@@ -195,7 +232,6 @@
|
|||||||
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public RenderFragment B1Content { get; set; }
|
|
||||||
public Common.Dtos.CurrentUserInfo CurrentUser { get; set; }
|
public Common.Dtos.CurrentUserInfo CurrentUser { get; set; }
|
||||||
List<Read_GroupDto> _Group = new List<Read_GroupDto>();
|
List<Read_GroupDto> _Group = new List<Read_GroupDto>();
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
@@ -210,6 +246,8 @@
|
|||||||
public string MsgInput { get; set; }
|
public string MsgInput { get; set; }
|
||||||
bool chatloading = false;
|
bool chatloading = false;
|
||||||
string SelectedChatUserName = "مهدی ربیع نژاد";
|
string SelectedChatUserName = "مهدی ربیع نژاد";
|
||||||
|
private bool _shouldObserveVisibility = false;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@functions {
|
@functions {
|
||||||
@@ -220,8 +258,19 @@
|
|||||||
Inbox1Items = await chatService.ChatAwaitingOurResponse();
|
Inbox1Items = await chatService.ChatAwaitingOurResponse();
|
||||||
Inbox2Items = await chatService.MyChatsIsInProgress();
|
Inbox2Items = await chatService.MyChatsIsInProgress();
|
||||||
Inbox3Items = await chatService.MyChatsIsFinished();
|
Inbox3Items = await chatService.MyChatsIsFinished();
|
||||||
|
|
||||||
await base.OnInitializedAsync();
|
await base.OnInitializedAsync();
|
||||||
}
|
}
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (_shouldObserveVisibility)
|
||||||
|
{
|
||||||
|
_shouldObserveVisibility = false;
|
||||||
|
await JS.InvokeVoidAsync("observeVisibility", DotNetObjectReference.Create(this));
|
||||||
|
await JS.InvokeVoidAsync("scrollToTarget");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async Task OnclickInbox(int ID)
|
async Task OnclickInbox(int ID)
|
||||||
{
|
{
|
||||||
switch (ID)
|
switch (ID)
|
||||||
@@ -262,37 +311,29 @@
|
|||||||
}
|
}
|
||||||
async Task onClickSelectedChat(int InboxID, ChatItemDto chatItem)
|
async Task onClickSelectedChat(int InboxID, ChatItemDto chatItem)
|
||||||
{
|
{
|
||||||
|
|
||||||
chatloading = true;
|
chatloading = true;
|
||||||
SelectedChatUserName = "در حال گفتگو با " + chatItem.UserFullName;
|
SelectedChatUserName = "در حال گفتگو با " + chatItem.UserFullName;
|
||||||
ChatCurrent = chatItem;
|
ChatCurrent = chatItem;
|
||||||
|
|
||||||
bool target = false;
|
_shouldObserveVisibility = true; // فعال کن تا در OnAfterRenderAsync صدا زده بشه
|
||||||
B1Content =@<div class="chat-container p-3">
|
|
||||||
@foreach (var msg in ChatCurrent.Responses)
|
|
||||||
{
|
|
||||||
@if (!target && ((!msg.IsRead && msg.Type == Common.Enums.ConversationType.UE) || ChatCurrent.Responses.Last() == msg))
|
|
||||||
{
|
|
||||||
target = true;
|
|
||||||
<div id="target" style="text-align: center;">
|
|
||||||
@if (!msg.IsRead && msg.Type == Common.Enums.ConversationType.UE) { <p>ـــــــــــــــــــــــــ</p>}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="d-flex mb-2 @(msg.Type==Common.Enums.ConversationType.UE ? "justify-content-end" : "justify-content-start")">
|
StateHasChanged(); // مجبور کن Blazor رندر کنه
|
||||||
<div class="chat-bubble @(msg.Type==Common.Enums.ConversationType.UE ? "chat-mine": "chat-other")" data-id="@msg.ID"> @msg.text </div>
|
|
||||||
@if (msg.Type == Common.Enums.ConversationType.EU)
|
|
||||||
{
|
|
||||||
if (msg.IsRead) { <Icon Style="align-self: self-end;" Name="IconName.CheckAll" Size="IconSize.x5" Color="IconColor.Success" /> }
|
|
||||||
else { <Icon Style="align-self: self-end;" Name="IconName.CheckLg" Size="IconSize.x5" /> }
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>;
|
|
||||||
await JS.InvokeVoidAsync("observeVisibility", DotNetObjectReference.Create(this));
|
|
||||||
await JS.InvokeVoidAsync("scrollToTarget");
|
|
||||||
chatloading = false;
|
chatloading = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
[JSInvokable]
|
||||||
|
public async Task MarkAsRead(int id)
|
||||||
|
{
|
||||||
|
var msg = ChatCurrent.Responses.FirstOrDefault(m => m.ID == id);
|
||||||
|
if (msg != null && !msg.IsRead && msg.Type == Common.Enums.ConversationType.UE)
|
||||||
|
{
|
||||||
|
msg.IsRead = true;
|
||||||
|
await chatService.MarkAsReadChatItemAsync(id);
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
|
await Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -321,6 +362,7 @@
|
|||||||
color: #353;
|
color: #353;
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-group-text-chat {
|
.input-group-text-chat {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@@ -9,6 +9,11 @@ namespace HushianWebApp.Service
|
|||||||
private readonly BaseController _baseController;
|
private readonly BaseController _baseController;
|
||||||
const string BaseRoute = "v1/Chat/";
|
const string BaseRoute = "v1/Chat/";
|
||||||
|
|
||||||
|
public ChatService(BaseController baseController)
|
||||||
|
{
|
||||||
|
_baseController = baseController;
|
||||||
|
}
|
||||||
|
|
||||||
//Inbox1
|
//Inbox1
|
||||||
public async Task<List<ChatItemDto>> ChatAwaitingOurResponse()
|
public async Task<List<ChatItemDto>> ChatAwaitingOurResponse()
|
||||||
{
|
{
|
||||||
@@ -62,6 +67,12 @@ namespace HushianWebApp.Service
|
|||||||
var response = await _baseController.Put($"{BaseRoute}ChatIsFinish/{ChatID}");
|
var response = await _baseController.Put($"{BaseRoute}ChatIsFinish/{ChatID}");
|
||||||
return response.IsSuccessStatusCode;
|
return response.IsSuccessStatusCode;
|
||||||
}
|
}
|
||||||
|
public async Task<bool> MarkAsReadChatItemAsync(int ID)
|
||||||
|
{
|
||||||
|
var response = await _baseController.Put($"{BaseRoute}MarkAsReadChatItem/{ID}");
|
||||||
|
return response.IsSuccessStatusCode;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user