feat: real-time staff messaging over Socket.io

Add conversations/participants/messages tables, a participant-scoped REST
API (/api/conversations) and a Socket.io server (session-authenticated
handshake; per-user + per-conversation rooms) sharing the HTTP port. New
messages broadcast live and create per-recipient notifications. Also lands
the notifications table + service + routes (used by the message flow). The
Messages page is rewritten: live threads, unread state, and a compose
dialog to start a conversation with a clinic member.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Khalid Abdi
2026-06-07 21:26:28 +03:00
parent 48378ebc5e
commit 730e07fcfc
21 changed files with 4086 additions and 158 deletions
+25
View File
@@ -0,0 +1,25 @@
// Canonical messaging shapes returned by the API / emitted over Socket.io.
// Mirrors the frontend `lib/messages.ts`.
export type Participant = {
id: string;
name: string;
};
export type ConversationMessage = {
id: string;
conversationId: string;
senderId: string;
senderName: string;
body: string;
createdAt: string;
};
export type ConversationSummary = {
id: string;
name: string; // display name: group name, or the other participant for a DM
isGroup: boolean;
participants: Participant[];
lastMessage: ConversationMessage | null;
unread: boolean;
updatedAt: string;
};
+13
View File
@@ -0,0 +1,13 @@
// The canonical Notification shape returned by the API. Per-recipient, scoped to
// a clinic. Auto-created from events (new message, patient record change).
export type Notification = {
id: string;
type: string;
text: string;
read: boolean;
entityType: string | null;
entityId: string | null;
actorName: string | null;
actorInitials: string | null;
createdAt: string;
};