'use client'; import { useEffect } from 'react'; import { toast } from 'sonner'; import { useSocket } from '@/providers/socket-provider'; import { stageLabel } from '@/lib/constants'; /** * App-wide subscriber that surfaces high-signal sales events as sonner * toasts. Mounted once inside SocketProvider so reps see "EOI signed", * "Deposit recorded", "Stage advanced" without having to refresh. * * Render-only — no children. Intentionally narrow in scope: only toast on * events that are noteworthy *to a user staring at any page*. Per-page * cache invalidations stay in `useRealtimeInvalidation`. */ export function RealtimeToasts() { const socket = useSocket(); useEffect(() => { if (!socket) return; function onStageChanged(payload: { newStage?: string; oldStage?: string | null; clientName?: string; }) { if (!payload?.newStage) return; const who = payload.clientName?.trim() || 'an interest'; toast.success(`${who} → ${stageLabel(payload.newStage)}`, { description: payload.oldStage ? `Advanced from ${stageLabel(payload.oldStage)}.` : 'Pipeline stage advanced.', }); } function onDocumentCompleted(payload: { type?: string }) { // Kick a generic "fully signed" — the type-specific message is // friendlier when we can identify it as an EOI. if (payload?.type === 'eoi') { toast.success('EOI fully signed', { description: 'All required signatures received.', }); } else { toast.success('Document fully signed'); } } function onSignerSigned(payload: { signerName?: string; documentTitle?: string }) { const who = payload?.signerName?.trim(); const title = payload?.documentTitle?.trim(); if (who && title) { toast.message(`${who} signed "${title}"`); } else if (who) { toast.message(`${who} signed a document`); } else { toast.message('Signer added a signature'); } } function onOutcomeSet(payload: { outcome?: string }) { if (!payload?.outcome) return; const isWon = payload.outcome === 'won'; const label = payload.outcome.replace(/_/g, ' '); const fn = isWon ? toast.success : toast.message; fn(`Interest closed — ${label}`); } socket.on('interest:stageChanged', onStageChanged); socket.on('document:completed', onDocumentCompleted); socket.on('document:signer:signed', onSignerSigned); socket.on('interest:outcomeSet', onOutcomeSet); return () => { socket.off('interest:stageChanged', onStageChanged); socket.off('document:completed', onDocumentCompleted); socket.off('document:signer:signed', onSignerSigned); socket.off('interest:outcomeSet', onOutcomeSet); }; }, [socket]); return null; }