feat: granular WebSocket message.new events

- WebSocket now detects new ContactMessages and broadcasts
  message.new events with contactId, text, channel, direction
- Frontend handles message.new: refreshes timeline for open chat,
  refreshes contacts for sidebar preview update
- dashboard.changed still fires for non-message changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ruslan Bakiev
2026-02-24 20:04:55 +07:00
parent ac9c50b47d
commit 643d8d02ba
3 changed files with 69 additions and 1 deletions

View File

@@ -1,8 +1,18 @@
import { ref } from "vue";
export type RealtimeNewMessage = {
contactId: string;
contactName: string;
text: string;
channel: string;
direction: string;
at: string;
};
export function useCrmRealtime(opts: {
isAuthenticated: () => boolean;
onDashboardChanged: () => Promise<void>;
onNewMessage?: (msg: RealtimeNewMessage) => void;
}) {
const crmRealtimeState = ref<"idle" | "connecting" | "open" | "error">("idle");
let crmRealtimeSocket: WebSocket | null = null;
@@ -99,10 +109,13 @@ export function useCrmRealtime(opts: {
const raw = typeof event.data === "string" ? event.data : "";
if (!raw) return;
try {
const payload = JSON.parse(raw) as { type?: string };
const payload = JSON.parse(raw) as { type?: string; [key: string]: any };
if (payload.type === "dashboard.changed") {
scheduleCrmRealtimeRefresh();
}
if (payload.type === "message.new" && opts.onNewMessage) {
opts.onNewMessage(payload as unknown as RealtimeNewMessage);
}
} catch {
// ignore malformed realtime payloads
}