Select or compose a message
+${escapeHtml(text)}
` }); + onSent(); + }, [sdk, onSent]); + const sendExternal = useCallback(async (target: string, subject: string, text: string, mirrorToUserId?: string) => { + await sdk.command("crm.mail.send", { target, subject, text, html: `${escapeHtml(text)}
`, ...(mirrorToUserId ? { mirrorToUserId } : {}) }); + onSent(); + }, [sdk, onSent]); + return { directory, sendInternal, sendExternal }; + } + return { directory: MOCK_PEOPLE, sendInternal: async () => onSent(), sendExternal: async () => onSent() }; +} + +function escapeHtml(s: string): string { + return s.replace(/&/g, "&").replace(//g, ">"); +} + +/* ============================ Mock (demo mode) ============================ */ + +const now = () => new Date().toISOString(); +const MOCK_PEOPLE: MailPerson[] = [ + { id: "pp_sofia", name: "Sofia Ramirez", kind: "staff" }, + { id: "cust_acme", name: "Acme Roofing (Client)", kind: "customer" }, +]; +const MOCK_THREADS: MailThread[] = [ + { threadId: "mt_1", subject: "Welcome to the Founders Club", participants: ["you", "system"], unread: 1, lastMessage: "Thanks for joining…", lastAt: now() }, + { threadId: "mt_2", subject: "Storm response — East side", participants: ["you", "pp_sofia"], unread: 0, lastMessage: "Crew rolling out at 7", lastAt: now() }, +]; +function useMockThread(threadId: string | null): MailThreadData { + const [extra, setExtra] = useStateThanks for joining the Founders Club. Set up your account to get started.
", text: "Thanks for joining the Founders Club." }] + : threadId === "mt_2" + ? [{ interactionId: "m2", actorId: "pp_sofia", kind: "EMAIL", occurredAt: now(), html: "Crew is rolling out at 7. Confirm the Henderson scope?
", text: "Crew rolling out at 7." }] + : []; + const reply = useCallback(async (content: string) => { + setExtra((l) => [...l, { interactionId: `r_${l.length}`, actorId: "you", kind: "MESSAGE", occurredAt: now(), html: null, text: content }]); + }, []); + return { loading: false, error: null, messages: threadId ? [...base, ...extra] : [], reply, refetch: () => {} }; +}