Skip to content

Commit

Permalink
Update Chat page in Manager
Browse files Browse the repository at this point in the history
- Create complete page and controller for Manager Chat page
- Apply filter by status of dentist
- Change UI of Chat detail page
  • Loading branch information
hoapooh committed Jul 21, 2024
1 parent e21739f commit 2c22d54
Show file tree
Hide file tree
Showing 6 changed files with 483 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using Dental_Clinic_System.Models.Data;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Dental_Clinic_System.Areas.Manager.Controllers
{
[Area("Manager")]
[Authorize(AuthenticationSchemes = "ManagerScheme", Roles = "Quản Lý")]
public class ChatController : Controller
{

private readonly DentalClinicDbContext _context;

public ChatController(DentalClinicDbContext context)
{
_context = context;
}

public async Task<IActionResult> Index(int patientID, string searchStatus)
{
var clinicId = HttpContext.Session.GetInt32("clinicId");
if (clinicId == null)
{ // Check if session has expired, log out
return RedirectToAction("Logout", "ManagerAccount", new { area = "Manager" });
}

var dentists = await _context.Dentists.Include(d => d.Account).Include(d => d.Clinic).Include(d => d.Degree).Where(d => d.ClinicID == clinicId).ToListAsync();

if (searchStatus != null)
{
ViewBag.SearchStatus = searchStatus;
dentists = dentists.Where(d => d.Account.AccountStatus == searchStatus).ToList();
}
else
{
ViewBag.SearchStatus = "Hoạt Động";
dentists = dentists.Where(d => d.Account.AccountStatus == "Hoạt Động").ToList();
}

return View(dentists);
}

public async Task<IActionResult> ChatList(int dentistID)
{
var chats = await _context.ChatHubMessages
.Where(m => m.SenderId == dentistID || m.ReceiverId == dentistID)
.Select(m => new
{
Id = m.ID,
Content = m.Content,
Timestamp = m.Timestamp,
SenderId = m.SenderId,
ReceiverId = m.ReceiverId,
SenderName = m.Sender.FirstName + " " + m.Sender.LastName ,
ReceiverName = m.Receiver.FirstName + " " + m.Receiver.LastName
})
.GroupBy(m => m.SenderId == dentistID ? m.ReceiverId : m.SenderId)
.Select(g => g.OrderByDescending(m => m.Timestamp).FirstOrDefault())
.ToListAsync();

var accounts = await _context.Accounts.ToDictionaryAsync(a => a.ID, a => a.Role);

ViewBag.Accounts = accounts;
ViewBag.ChatList = chats;
ViewBag.DentistID = dentistID;
return View();
}

public async Task<IActionResult> ChatDentistDetail(int patientID, int dentistID)
{
var messages = await _context.ChatHubMessages
.Where(m => (m.SenderId == dentistID && m.ReceiverId == patientID) || (m.SenderId == patientID && m.ReceiverId == dentistID))
.OrderBy(m => m.Timestamp)
.ToListAsync();

ViewBag.PatientID = patientID;
ViewBag.Messages = messages;

var patient = await _context.Accounts.FirstAsync(a => a.ID == patientID);

var patientName = $"{patient.FirstName} {patient.LastName}";

var accounts = await _context.Accounts.ToDictionaryAsync(a => a.ID, a => a.Role);

ViewBag.Accounts = accounts;
ViewBag.PatientName = patientName ?? "Ẩn Danh";
ViewBag.DentistID = dentistID;

return View("ChatDetail");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
@{
ViewData["Title"] = "Danh sách chat";
Layout = "_LayoutManager";
var userID = ViewBag.DentistID;
var patientID = ViewBag.PatientID;
var messages = ViewBag.Messages;
var patientName = ViewBag.PatientName;
var accounts = ViewBag.Accounts as Dictionary<int, string>; // Assuming this is a dictionary with user ID as key and role as value
}

<head>
<meta name="description" content="Đây là nơi nha sĩ dùng để trao đổi với bệnh nhân">
<link rel="stylesheet" href="~/assets/css/chat.css" />
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>
<div class="msger__container" style="background: none">
<div class="msger" style="background: #fff; box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.3)">
<header class="msger-header" style="background: #579ffb">
<div class="msger-header-title" style="font-size: 2rem">
<i class="fa-solid fa-comments"></i> Chat with Patients
</div>
<div class="msger-header-options">
<div class="btn-wrapper" style="font-size: 2rem;">
<a href="~/Manager/Chat/ChatList?dentistID=@userID" class="back-btn" style="color: #fff; font-weight: bold">
Quay lại <i class="fa-solid fa-arrow-rotate-left"></i>
</a>
</div>
</div>
</header>

<main class="msger-chat" id="messagesList" style="border-radius: 0 0 15px 15px; background: #fff">
@foreach (var message in messages)
{
var isSenderDentist = accounts?.ContainsKey(message.SenderId) && accounts?[message.SenderId] == "Nha Sĩ";
var isReceiverDentist = accounts?.ContainsKey(message.ReceiverId) && accounts?[message.ReceiverId] == "Nha Sĩ";

@if (isSenderDentist)
{
<div class="msg left-msg" style="display: block">
<div class="msg-bubble" style="background: none; padding: 0; max-width: 100%;">
<div class="msg-info" style="color: #000">
<div class="msg-info-name"><i class="fa-solid fa-user-doctor"></i> Nha sĩ &mdash;</div>
<div class="msg-info-time">@message.Timestamp</div>
</div>
<div class="msg-text" style="color: #fff; background: #fa806a; padding: 5px 12px; display: inline-block; border-radius: 50px; max-width: 80%;
word-wrap: break-word;">
@message.Content
</div>
</div>
</div>
}
else
{
<div class="msg left-msg" style="display: block">
<div class="msg-bubble" style="background: none; padding: 0; max-width: 100%;">
<div class="msg-info" style="color: #000">
<div class="msg-info-name"><i class="fa-solid fa-circle-user"></i> @patientName &mdash;</div>
<div class="msg-info-time">@message.Timestamp</div>
</div>
<div class="msg-text" style="color: #fff; background: #6e7df5; padding: 5px 12px; display: inline-block; border-radius: 50px; max-width: 80%;
word-wrap: break-word;">
@message.Content
</div>
</div>
</div>
}
}
</main>
</div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/5.0.12/signalr.min.js"></script>
<script>
const userID = '@userID';
const patientName = '@patientName';
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub?userID=" + encodeURIComponent(userID))
.configureLogging(signalR.LogLevel.Information)
.build();
connection.on("ReceiveMessage", (user, message) => {
console.log(`Message received from ${user}: ${message}`);
const msg = document.createElement("div");
const isUserDentist = user === userID;
const msgClass = isUserDentist ? "right-msg" : "left-msg";
const userName = isUserDentist ? "Bạn" : patientName;
const now = new Date();
const timeString = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
msg.classList.add("msg", msgClass);
msg.innerHTML = `
<div class="msg-img" style="background-image: url('${isUserDentist ? 'https://firebasestorage.googleapis.com/v0/b/dental-care-3388d.appspot.com/o/Profile%2FPatient%2Fuser.png?alt=media&token=9010a4a6-0220-4d29-bb85-1fe425100744' : 'https://firebasestorage.googleapis.com/v0/b/dental-care-3388d.appspot.com/o/Profile%2FPatient%2Fuser.png?alt=media&token=9010a4a6-0220-4d29-bb85-1fe425100744'}')"></div>
<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name">${userName}</div>
<div class="msg-info-time">${timeString}</div>
</div>
<div class="msg-text">${message}</div>
</div>
`;
document.getElementById("messagesList").appendChild(msg);
document.getElementById("messagesList").scrollTop = document.getElementById("messagesList").scrollHeight; // Ensure scrolls to bottom
});
connection.start()
.then(() => console.log("Connection established."))
.catch(err => console.error("Connection failed: ", err.toString()));
function sendMessage() {
const receiver = document.getElementById("receiverInput").value;
const message = document.getElementById("messageInput").value;
if (!message) return;
console.log(`Sending message to ${receiver}: ${message}`);
connection.invoke("SendMessageToUser", receiver, message)
.then(() => {
document.getElementById("messageInput").value = '';
console.log("Message sent successfully.");
})
.catch(err => console.error("Send message failed: ", err.toString()));
}
function scrollToBottom() {
const messagesList = document.getElementById("messagesList");
messagesList.scrollTop = messagesList.scrollHeight;
}
// Scroll to bottom when the page loads
window.onload = scrollToBottom;
</script>
</body>

Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
ViewData["Title"] = "Danh sách chat";
Layout = "_LayoutManager";
var chats = ViewBag.ChatList;
var accounts = ViewBag.Accounts as Dictionary<int, string>; // Assuming this is a dictionary with user ID as key and role as value
}

<head>
<meta name="description" content="Đây là nơi nha sĩ dùng để theo dõi tin nhắn đến từ phía của bệnh nhân">
<style>
a {
text-decoration: none !important;
}
sup {
font-size: 18px;
color: red;
}
.sidebar .nav-item a.Quan_ly_chat {
color: #fff;
background: #4880ff;
}
.chat-list {
display: flex;
flex-direction: column;
width: 50%;
margin: auto;
border: 1px solid #1376f8;
height: 80vh;
overflow-y: auto;
padding: 20px;
border-radius: 15px;
}
.chat-item {
padding: 10px 20px;
border: 1px solid #1376f8;
border-radius: 15px;
cursor: pointer;
margin-bottom: 10px;
}
.chat-item strong {
font-size: 1.8rem;
}
.chat-item p {
font-size: 1.6rem;
color: #333;
margin-bottom: 5px;
}
.chat-item:hover {
background-color: #f1f1f1;
border-radius: 15px;
}
.back-btn {
color: #1376f8;
font-size: 2rem;
font-weight: 600;
padding: 10px 20px;
display: inline-flex;
align-items: center;
margin-bottom: 10px;
gap: 5px;
}
.back-btn:hover {
border-radius: 15px;
background: #e8f1ff;
}
</style>
</head>

<body>
<div>
<div>
<div style="text-align: right; width: 50%; margin: auto; margin-top: 10px;">
<a asp-controller="Chat" asp-action="Index" class="back-btn">Trở về danh sách nha sĩ <i class="fa-solid fa-rotate-left" aria-hidden="true"></i></a>
</div>
</div>
<div class="chat-list" id="chatList">
@foreach (var chat in chats)
{
int patientID = chat.SenderId;
if (accounts?.ContainsKey(chat.SenderId) && accounts?[chat.SenderId] == "Nha Sĩ")
{
patientID = chat.ReceiverId;
}

if (accounts.ContainsKey(patientID) && accounts[patientID] == "Bệnh Nhân")
{
<a href="@Url.Action("ChatDentistDetail", "Chat", new { area = "Manager", patientID = patientID, dentistID = ViewBag.DentistID })">
<div class="chat-item">
<strong>@chat.ReceiverName</strong>
<p>@chat.Content</p>
<p>@chat.Timestamp</p>
</div>
</a>
}
}
</div>
</body>
Loading

0 comments on commit 2c22d54

Please sign in to comment.