...
This commit is contained in:
@@ -63,6 +63,7 @@ namespace Hushian.Application
|
|||||||
services.AddScoped(typeof(AuthService));
|
services.AddScoped(typeof(AuthService));
|
||||||
services.AddScoped(typeof(CompanyService));
|
services.AddScoped(typeof(CompanyService));
|
||||||
services.AddScoped(typeof(ConversationService));
|
services.AddScoped(typeof(ConversationService));
|
||||||
|
services.AddScoped(typeof(ChatService));
|
||||||
services.AddScoped(typeof(ExperService));
|
services.AddScoped(typeof(ExperService));
|
||||||
services.AddScoped(typeof(GroupService));
|
services.AddScoped(typeof(GroupService));
|
||||||
services.AddScoped(typeof(UserService));
|
services.AddScoped(typeof(UserService));
|
||||||
|
@@ -54,7 +54,7 @@ namespace Hushian.Application.Services
|
|||||||
IsRead = ss.IsRead,
|
IsRead = ss.IsRead,
|
||||||
text = ss.Text,
|
text = ss.Text,
|
||||||
Type = ss.Type
|
Type = ss.Type
|
||||||
})
|
}).ToList()
|
||||||
|
|
||||||
}).ToListAsync();
|
}).ToListAsync();
|
||||||
public async Task<List<ChatItemDto>> GetChatsByCompanyID(int CompanyID, ConversationStatus status)
|
public async Task<List<ChatItemDto>> GetChatsByCompanyID(int CompanyID, ConversationStatus status)
|
||||||
@@ -88,7 +88,7 @@ namespace Hushian.Application.Services
|
|||||||
IsRead = ss.IsRead,
|
IsRead = ss.IsRead,
|
||||||
text = ss.Text,
|
text = ss.Text,
|
||||||
Type = ss.Type
|
Type = ss.Type
|
||||||
})
|
}).ToList()
|
||||||
|
|
||||||
}).ToListAsync();
|
}).ToListAsync();
|
||||||
public async Task<List<ChatItemDto>> ChatsAwaitingOurResponse(int CompanyID)
|
public async Task<List<ChatItemDto>> ChatsAwaitingOurResponse(int CompanyID)
|
||||||
@@ -122,7 +122,7 @@ namespace Hushian.Application.Services
|
|||||||
IsRead = ss.IsRead,
|
IsRead = ss.IsRead,
|
||||||
text = ss.Text,
|
text = ss.Text,
|
||||||
Type = ss.Type
|
Type = ss.Type
|
||||||
})
|
}).ToList()
|
||||||
|
|
||||||
}).ToListAsync();
|
}).ToListAsync();
|
||||||
//------------------------
|
//------------------------
|
||||||
@@ -242,5 +242,20 @@ namespace Hushian.Application.Services
|
|||||||
|
|
||||||
return Response;
|
return Response;
|
||||||
}
|
}
|
||||||
|
public async Task<bool> FinishChat(int ChatID)
|
||||||
|
{
|
||||||
|
var convModel = await _ConversationRepository.Get()
|
||||||
|
.Include(inc => inc.ConversationResponses)
|
||||||
|
.FirstOrDefaultAsync(w => w.ID == ChatID);
|
||||||
|
|
||||||
|
if (convModel != null && convModel.Status != ConversationStatus.Finished)
|
||||||
|
{
|
||||||
|
convModel.Status = ConversationStatus.Finished;
|
||||||
|
convModel.FinishedDateTime = DateTime.Now;
|
||||||
|
return await _ConversationRepository.UPDATEBool(convModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -93,5 +93,12 @@ namespace Hushian.WebApi.Controllers.v1
|
|||||||
return Response.Success ? Ok(Response.Value)
|
return Response.Success ? Ok(Response.Value)
|
||||||
: BadRequest(Response.Errors);
|
: BadRequest(Response.Errors);
|
||||||
}
|
}
|
||||||
|
[HttpGet("ChatIsFinish/{ChatID}")]
|
||||||
|
[Authorize(Roles = "Company,Exper")]
|
||||||
|
public async Task<ActionResult> ChatIsFinish(int ChatID)
|
||||||
|
{
|
||||||
|
return await _chatService.FinishChat(ChatID) ? NoContent()
|
||||||
|
: BadRequest(new List<string> { "خطا در بروزرسانی وضعیت" });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,201 @@
|
|||||||
@page "/Chant"
|
@page "/Chant"
|
||||||
@using Common.Dtos.Conversation
|
@using Common.Dtos.Conversation
|
||||||
@using Common.Dtos.Group
|
@using Common.Dtos.Group
|
||||||
|
@using Common.Enums
|
||||||
@using HushianWebApp.Service
|
@using HushianWebApp.Service
|
||||||
@inject ChatService chatService
|
@inject ChatService chatService
|
||||||
@inject GroupService groupService
|
@inject GroupService groupService
|
||||||
@inject UserService userService
|
@inject UserService userService
|
||||||
@inject IJSRuntime JS
|
@inject IJSRuntime JS
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row" style="height:85vh">
|
||||||
|
<!-- Sidebar (A) -->
|
||||||
|
<div class="col-md-3 bg-light d-flex flex-column p-2 rounded-end" id="A">
|
||||||
|
<!-- A1: Header -->
|
||||||
|
<div class="border mb-2 p-2" id="A1">
|
||||||
|
گفتگو های اخیر
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- A2: Buttons -->
|
||||||
|
<div class="d-flex justify-content-between mb-2" id="A2">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Inbox1 -->
|
||||||
|
<Button Outline="@isSelectedInbox1" Type="ButtonType.Link" @onclick="async()=>{await OnclickInbox(1);}" Size=ButtonSize.ExtraSmall Color="ButtonColor.Secondary">
|
||||||
|
پیام های آمده <Badge Color="BadgeColor.Warning">@Inbox1Items.Count()</Badge>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Inbox2 -->
|
||||||
|
<Button Outline="@isSelectedInbox2" Type="ButtonType.Link" @onclick="async()=>{await OnclickInbox(2);}" Size=ButtonSize.ExtraSmall Color="ButtonColor.Secondary">
|
||||||
|
پیام های من <Badge Color="BadgeColor.Warning">@Inbox2Items.Count()</Badge>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Inbox3 -->
|
||||||
|
<Button Outline="@isSelectedInbox3" Type="ButtonType.Link" @onclick="async()=>{await OnclickInbox(3);}" Size=ButtonSize.ExtraSmall Color="ButtonColor.Secondary">
|
||||||
|
پیام های بسته
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- A3: Chat list -->
|
||||||
|
<div class="flex-fill border p-2 overflow-auto" id="A3" style="height: 300px; overflow-y: auto;">
|
||||||
|
<Spinner Class="me-3" Type="SpinnerType.Dots" Color="SpinnerColor.Primary" Visible="@chatloading" Size="SpinnerSize.Small" />
|
||||||
|
@if (isSelectedInbox1)
|
||||||
|
{
|
||||||
|
@foreach (var item in Inbox1Items)
|
||||||
|
{
|
||||||
|
<div class="d-flex align-items-center p-3 border-bottom message-item hover-bg"
|
||||||
|
style="cursor: pointer; margin-top: -10px;margin-bottom: -10px;" @onclick="async()=>await onClickSelectedChat(1,item)">
|
||||||
|
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<strong>@item.UserFullName</strong>
|
||||||
|
<small class="text-muted">@item.LastMsgdate</small>
|
||||||
|
<small class="text-muted">@item.LastMsgtime</small>
|
||||||
|
</div>
|
||||||
|
<div class="text-muted small text-truncate">@item.LastText</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Badge Style="margin-top:25px" Color="BadgeColor.Danger">@item.Responses.Count()</Badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (isSelectedInbox2)
|
||||||
|
{
|
||||||
|
@foreach (var item in Inbox2Items)
|
||||||
|
{
|
||||||
|
<div class="d-flex align-items-center p-3 border-bottom message-item hover-bg"
|
||||||
|
style="cursor: pointer; margin-top: -10px;margin-bottom: -10px;" @onclick="async()=>await onClickSelectedChat(2,item)">
|
||||||
|
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<strong>@item.UserFullName</strong>
|
||||||
|
<small class="text-muted">@item.LastMsgdate</small>
|
||||||
|
<small class="text-muted">@item.LastMsgtime</small>
|
||||||
|
</div>
|
||||||
|
<div class="text-muted small text-truncate">@item.LastText</div>
|
||||||
|
</div>
|
||||||
|
@if (item.Responses.Count(c => !c.IsRead && c.Type == ConversationType.UE) > 0)
|
||||||
|
{
|
||||||
|
<Badge Style="margin-top:25px" Color="BadgeColor.Danger">@item.Responses.Count(c => !c.IsRead && c.Type == ConversationType.UE)</Badge>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (isSelectedInbox3)
|
||||||
|
{
|
||||||
|
@foreach (var item in Inbox3Items)
|
||||||
|
{
|
||||||
|
<div class="d-flex align-items-center p-3 border-bottom message-item hover-bg"
|
||||||
|
style="cursor: pointer; margin-top: -10px;margin-bottom: -10px;" @onclick="async()=>await onClickSelectedChat(3,item)">
|
||||||
|
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<strong>@item.UserFullName</strong>
|
||||||
|
<small class="text-muted">@item.LastMsgdate</small>
|
||||||
|
<small class="text-muted">@item.LastMsgtime</small>
|
||||||
|
</div>
|
||||||
|
<div class="text-muted small text-truncate">@item.LastText</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Main Chat Section (B) -->
|
||||||
|
<div class="col-md-9 d-flex flex-column" id="B">
|
||||||
|
<div class="input-group">
|
||||||
|
@if (ChatCurrent != null)
|
||||||
|
{
|
||||||
|
<p type="text" class="form-control fw-bold text-primary" style="border:none;align-self: center;" aria-describedby="basic-addon1">@SelectedChatUserName</p>
|
||||||
|
<span class="input-group-text-chat" id="basic-addon1">
|
||||||
|
@if (ChatCurrent.status == Common.Enums.ConversationStatus.InProgress)
|
||||||
|
{
|
||||||
|
<Button Color="ButtonColor.Danger" Size=ButtonSize.ExtraSmall Outline="true"
|
||||||
|
@onclick="async()=>
|
||||||
|
{
|
||||||
|
if(await chatService.ChatIsFinish(ChatCurrent.ID))
|
||||||
|
ChatCurrent.status=Common.Enums.ConversationStatus.Finished;
|
||||||
|
}">
|
||||||
|
<Icon Name="IconName.Escape" /> اتمام گفتگو
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button Color="ButtonColor.Secondary" Size=ButtonSize.ExtraSmall Outline="true"
|
||||||
|
Class="m-3">
|
||||||
|
<Icon Name="IconName.EnvelopeArrowUp" /> ارجاع به...
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
else if (ChatCurrent.status == Common.Enums.ConversationStatus.Finished
|
||||||
|
&& (CurrentUser.Role == "Company" || ChatCurrent.ExperID == CurrentUser.ExperID))
|
||||||
|
{
|
||||||
|
<Button Color="ButtonColor.Success" Size=ButtonSize.ExtraSmall Outline="true">
|
||||||
|
|
||||||
|
<Icon Name="IconName.Escape" /> باز کردن گفتگو
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- B1: Chat area -->
|
||||||
|
<div class="flex-fill border p-2 overflow-auto" id="B1" style="height: 300px; overflow-y: auto;">
|
||||||
|
@if (ChatCurrent != null && ChatCurrent.Responses != null)
|
||||||
|
{ @B1Content }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-center align-items-center flex-column" style="height: 80%;">
|
||||||
|
|
||||||
|
<Spinner Type="SpinnerType.Dots" Color="SpinnerColor.Primary" Visible="@chatloading" />
|
||||||
|
<p style="margin-top: 15px; font-size: 1.5rem; color: #0d6efd; font-weight: bold; text-shadow: 1px 1px 2px rgba(0,0,0,0.2);">
|
||||||
|
هوشیان
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (ChatCurrent != null && ChatCurrent.status != Common.Enums.ConversationStatus.Finished && ChatCurrent.Responses != null)
|
||||||
|
{
|
||||||
|
<!-- B2: Message input -->
|
||||||
|
<div class="border m-2 p-2 rounded d-flex align-items-center" id="B2">
|
||||||
|
<input type="text" @bind-value="MsgInput" class="form-control" style="margin-left:10px" placeholder="پیام خود را بنویسید..." />
|
||||||
|
|
||||||
|
<Button Color="ButtonColor.Dark" Outline="true" @onclick="OnClickSendMsg"><Icon Name="IconName.AppIndicator" /> </Button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@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>();
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
@@ -19,11 +208,14 @@
|
|||||||
/////////////
|
/////////////
|
||||||
public ChatItemDto? ChatCurrent { get; set; } = null;
|
public ChatItemDto? ChatCurrent { get; set; } = null;
|
||||||
public string MsgInput { get; set; }
|
public string MsgInput { get; set; }
|
||||||
|
bool chatloading = false;
|
||||||
|
string SelectedChatUserName = "مهدی ربیع نژاد";
|
||||||
|
|
||||||
}
|
}
|
||||||
@functions {
|
@functions {
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
CurrentUser =await userService.GetCurrentUserInfo();
|
CurrentUser = await userService.GetCurrentUserInfo();
|
||||||
_Group = await groupService.GetGroups();
|
_Group = await groupService.GetGroups();
|
||||||
Inbox1Items = await chatService.ChatAwaitingOurResponse();
|
Inbox1Items = await chatService.ChatAwaitingOurResponse();
|
||||||
Inbox2Items = await chatService.MyChatsIsInProgress();
|
Inbox2Items = await chatService.MyChatsIsInProgress();
|
||||||
@@ -37,7 +229,7 @@
|
|||||||
case 1:
|
case 1:
|
||||||
isSelectedInbox1 = true;
|
isSelectedInbox1 = true;
|
||||||
isSelectedInbox2 = false;
|
isSelectedInbox2 = false;
|
||||||
isSelectedInbox3 = false;
|
isSelectedInbox3 = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
@@ -55,7 +247,7 @@
|
|||||||
ChatCurrent = null;
|
ChatCurrent = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
async Task SendMsg()
|
async Task OnClickSendMsg()
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(MsgInput) && ChatCurrent != null)
|
if (!string.IsNullOrEmpty(MsgInput) && ChatCurrent != null)
|
||||||
{
|
{
|
||||||
@@ -68,15 +260,67 @@
|
|||||||
MsgInput = string.Empty;
|
MsgInput = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async Task onClickSelectedCon(int InboxID, Read_ConversationDto conversationDto)
|
async Task onClickSelectedChat(int InboxID, ChatItemDto chatItem)
|
||||||
{
|
{
|
||||||
|
chatloading = true;
|
||||||
|
SelectedChatUserName = "در حال گفتگو با " + chatItem.UserFullName;
|
||||||
|
ChatCurrent = chatItem;
|
||||||
|
|
||||||
|
bool target = false;
|
||||||
|
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")">
|
||||||
|
<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;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.chat-bubble {
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
max-width: 75%;
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-mine {
|
||||||
|
background: linear-gradient(to right, #005eff, #267fff);
|
||||||
|
color: white;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-other {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
color: #333;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-ai {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
color: #353;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
.input-group-text-chat {
|
.input-group-text-chat {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@@ -17,5 +17,6 @@ builder.Services.AddScoped<UserService>();
|
|||||||
builder.Services.AddScoped<CompanyService>();
|
builder.Services.AddScoped<CompanyService>();
|
||||||
builder.Services.AddScoped<GroupService>();
|
builder.Services.AddScoped<GroupService>();
|
||||||
builder.Services.AddScoped<ConversationService>();
|
builder.Services.AddScoped<ConversationService>();
|
||||||
|
builder.Services.AddScoped<ChatService>();
|
||||||
builder.Services.AddBlazorBootstrap();
|
builder.Services.AddBlazorBootstrap();
|
||||||
await builder.Build().RunAsync();
|
await builder.Build().RunAsync();
|
||||||
|
@@ -57,6 +57,11 @@ namespace HushianWebApp.Service
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
public async Task<bool> ChatIsFinish(int ChatID)
|
||||||
|
{
|
||||||
|
var response = await _baseController.Put($"{BaseRoute}ChatIsFinish/{ChatID}");
|
||||||
|
return response.IsSuccessStatusCode;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user