@fayz-ai/plugin-conversations 0.2.4 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ConversationsContext.d.ts +18 -1
- package/dist/ConversationsContext.d.ts.map +1 -1
- package/dist/ConversationsPage.d.ts +3 -1
- package/dist/ConversationsPage.d.ts.map +1 -1
- package/dist/data/accents.d.ts +3 -0
- package/dist/data/accents.d.ts.map +1 -0
- package/dist/data/mock.d.ts +7 -1
- package/dist/data/mock.d.ts.map +1 -1
- package/dist/data/mock.test.d.ts +2 -0
- package/dist/data/mock.test.d.ts.map +1 -0
- package/dist/data/supabase.d.ts.map +1 -1
- package/dist/data/tables.d.ts +5 -0
- package/dist/data/tables.d.ts.map +1 -0
- package/dist/data/types.d.ts +2 -1
- package/dist/data/types.d.ts.map +1 -1
- package/dist/index.cjs +664 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +16 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +667 -73
- package/dist/index.js.map +1 -1
- package/dist/locales/en.d.ts.map +1 -1
- package/dist/locales/index.d.ts.map +1 -1
- package/dist/locales/pt-BR.d.ts +2 -0
- package/dist/locales/pt-BR.d.ts.map +1 -0
- package/dist/migrations/index.d.ts +7 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/store.d.ts +2 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/views/ContactPanel.d.ts.map +1 -1
- package/dist/views/ConversationList.d.ts.map +1 -1
- package/dist/views/InboxView.d.ts.map +1 -1
- package/dist/views/MessageThread.d.ts.map +1 -1
- package/dist/views/NewConversationModal.d.ts +6 -0
- package/dist/views/NewConversationModal.d.ts.map +1 -0
- package/package.json +10 -5
- package/src/ConversationsContext.tsx +31 -1
- package/src/ConversationsPage.tsx +6 -3
- package/src/data/accents.ts +12 -0
- package/src/data/mock.test.ts +90 -0
- package/src/data/mock.ts +131 -12
- package/src/data/supabase.ts +69 -7
- package/src/data/tables.ts +7 -0
- package/src/data/types.ts +2 -0
- package/src/index.ts +69 -11
- package/src/locales/en.ts +64 -0
- package/src/locales/index.ts +2 -0
- package/src/locales/pt-BR.ts +68 -0
- package/src/migrations/001_conversations.sql +74 -0
- package/src/migrations/002_contact_person.sql +22 -0
- package/src/migrations/index.ts +108 -0
- package/src/store.ts +44 -1
- package/src/types.ts +19 -0
- package/src/views/ContactPanel.tsx +14 -12
- package/src/views/ConversationList.tsx +48 -21
- package/src/views/InboxView.tsx +3 -1
- package/src/views/MessageThread.tsx +14 -16
- package/src/views/NewConversationModal.tsx +204 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ConversationsContext.tsx","../src/types.ts","../src/channel.ts","../src/views/shared.tsx","../src/views/ConversationList.tsx","../src/views/MessageThread.tsx","../src/views/ContactPanel.tsx","../src/views/InboxView.tsx","../src/ConversationsPage.tsx","../src/data/mock.ts","../src/data/supabase.ts","../src/store.ts","../src/locales/en.ts","../src/locales/index.ts","../src/index.ts"],"names":["React","jsx","jsxs","cn","InboxIcon","MessageSquare","Button","getSupabaseClientOptional"],"mappings":"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","file":"index.js","sourcesContent":["import React from 'react'\nimport { useStore, type StoreApi } from 'zustand'\nimport type { ConversationsUIState } from './store'\n\nconst StoreContext = React.createContext<StoreApi<ConversationsUIState> | null>(null)\n\nexport function ConversationsContextProvider({\n store,\n children,\n}: {\n store: StoreApi<ConversationsUIState>\n children?: React.ReactNode\n}) {\n return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>\n}\n\nexport function useConversationsStore<T>(selector: (state: ConversationsUIState) => T): T {\n const store = React.useContext(StoreContext)\n if (!store) throw new Error('useConversationsStore must be used within ConversationsPage')\n return useStore(store, selector)\n}\n","// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-conversations — domain types for the unified omni-channel\n// inbox (the GoHighLevel \"Conversations\" equivalent). Provider-agnostic.\n// ---------------------------------------------------------------------------\n\nexport type Channel = 'sms' | 'whatsapp' | 'instagram' | 'email' | 'webchat'\n\nexport type ConversationStatus = 'open' | 'snoozed' | 'closed'\n\nexport type MessageDirection = 'inbound' | 'outbound'\n\nexport interface Conversation {\n id: string\n contactName: string\n /** Phone, @handle, or email depending on channel */\n contactHandle: string\n channel: Channel\n lastMessagePreview: string\n lastMessageAt: string\n unreadCount: number\n status: ConversationStatus\n assignedTo?: string\n /** Tailwind-ish accent for the avatar bubble */\n accent: string\n tags: string[]\n // Optional context shown in the contact panel.\n location?: string\n note?: string\n}\n\nexport interface Message {\n id: string\n conversationId: string\n channel: Channel\n direction: MessageDirection\n body: string\n at: string\n author: string\n}\n\nexport interface ListConversationsQuery {\n channel?: Channel | 'all'\n status?: ConversationStatus | 'all'\n search?: string\n}\n\nexport interface SendMessageInput {\n conversationId: string\n body: string\n}\n\nexport const CHANNEL_LABELS: Record<Channel, string> = {\n sms: 'SMS',\n whatsapp: 'WhatsApp',\n instagram: 'Instagram',\n email: 'Email',\n webchat: 'Web Chat',\n}\n","import React from 'react'\nimport { MessageSquare, Phone, Instagram, Mail, Globe } from 'lucide-react'\nimport { CHANNEL_LABELS, type Channel } from './types'\n\n// ---------------------------------------------------------------------------\n// Shared channel visuals — one source of truth for the icon + accent color of\n// each channel, reused by the conversation list, thread header and contact\n// panel. Keeps the omni-channel inbox visually consistent.\n// ---------------------------------------------------------------------------\n\nexport const CHANNEL_ICON: Record<Channel, React.ComponentType<{ className?: string }>> = {\n sms: Phone,\n whatsapp: MessageSquare,\n instagram: Instagram,\n email: Mail,\n webchat: Globe,\n}\n\nexport interface ChannelAccent {\n /** Solid brand color (hex) — bubbles, dots, header chips. */\n color: string\n /** Soft tinted background classes for badges. */\n badge: string\n}\n\nexport const CHANNEL_ACCENT: Record<Channel, ChannelAccent> = {\n whatsapp: { color: '#22c55e', badge: 'bg-[#22c55e]/12 text-[#15803d] dark:text-[#4ade80]' },\n sms: { color: '#6366f1', badge: 'bg-[#6366f1]/12 text-[#4338ca] dark:text-[#a5b4fc]' },\n instagram: { color: '#ec4899', badge: 'bg-[#ec4899]/12 text-[#be185d] dark:text-[#f9a8d4]' },\n email: { color: '#0ea5e9', badge: 'bg-[#0ea5e9]/12 text-[#0369a1] dark:text-[#7dd3fc]' },\n webchat: { color: '#f59e0b', badge: 'bg-[#f59e0b]/12 text-[#b45309] dark:text-[#fcd34d]' },\n}\n\nexport { CHANNEL_LABELS }\n","import React from 'react'\nimport { cn } from '@fayz-ai/ui'\nimport { CHANNEL_ACCENT, CHANNEL_ICON, CHANNEL_LABELS } from '../channel'\nimport type { Channel } from '../types'\n\n// ---------------------------------------------------------------------------\n// Small presentational helpers shared across the inbox panes.\n// ---------------------------------------------------------------------------\n\n/** Reactive media-query match — drives the responsive list/thread/panel layout. */\nexport function useMediaQuery(query: string): boolean {\n const [matches, setMatches] = React.useState(\n () => typeof window !== 'undefined' && window.matchMedia(query).matches,\n )\n React.useEffect(() => {\n if (typeof window === 'undefined') return\n const mql = window.matchMedia(query)\n const onChange = () => setMatches(mql.matches)\n onChange()\n mql.addEventListener('change', onChange)\n return () => mql.removeEventListener('change', onChange)\n }, [query])\n return matches\n}\n\nexport function initialsOf(name: string): string {\n return name.replace('@', '').split(/\\s+/).filter(Boolean).map((w) => w[0]).slice(0, 2).join('').toUpperCase()\n}\n\nexport function Avatar({ name, accent, size = 'md', channel }: {\n name: string\n accent: string\n size?: 'sm' | 'md' | 'lg'\n /** When set, renders a small channel glyph badge over the avatar. */\n channel?: Channel\n}) {\n const dims = size === 'lg' ? 'h-14 w-14 text-lg' : size === 'sm' ? 'h-9 w-9 text-xs' : 'h-10 w-10 text-sm'\n const Icon = channel ? CHANNEL_ICON[channel] : null\n return (\n <div className=\"relative shrink-0\">\n <div\n className={cn('flex items-center justify-center rounded-full font-semibold text-white', dims)}\n style={{ backgroundColor: accent }}\n >\n {initialsOf(name)}\n </div>\n {Icon && (\n <span\n className=\"absolute -bottom-0.5 -right-0.5 flex h-4 w-4 items-center justify-center rounded-full ring-2 ring-card\"\n style={{ backgroundColor: CHANNEL_ACCENT[channel!].color }}\n >\n <Icon className=\"h-2.5 w-2.5 text-white\" />\n </span>\n )}\n </div>\n )\n}\n\nexport function ChannelBadge({ channel, className }: { channel: Channel; className?: string }) {\n const Icon = CHANNEL_ICON[channel]\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-[10px] font-medium',\n CHANNEL_ACCENT[channel].badge,\n className,\n )}\n >\n <Icon className=\"h-2.5 w-2.5\" />\n {CHANNEL_LABELS[channel]}\n </span>\n )\n}\n\nexport function relativeTime(iso: string): string {\n const diff = Date.now() - new Date(iso).getTime()\n const mins = Math.round(diff / 60_000)\n if (mins < 1) return 'now'\n if (mins < 60) return `${mins}m`\n const hours = Math.round(mins / 60)\n if (hours < 24) return `${hours}h`\n const days = Math.round(hours / 24)\n if (days < 7) return `${days}d`\n return `${Math.round(days / 7)}w`\n}\n\n/** Day label for the thread date separators. */\nexport function dayLabel(iso: string): string {\n const d = new Date(iso)\n const now = new Date()\n const startOf = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime()\n const dayDiff = Math.round((startOf(now) - startOf(d)) / 86_400_000)\n if (dayDiff <= 0) return 'Today'\n if (dayDiff === 1) return 'Yesterday'\n if (dayDiff < 7) return d.toLocaleDateString([], { weekday: 'long' })\n return d.toLocaleDateString([], { month: 'short', day: 'numeric', year: now.getFullYear() === d.getFullYear() ? undefined : 'numeric' })\n}\n","import React from 'react'\nimport { Search, Inbox as InboxIcon } from 'lucide-react'\nimport { Input, cn } from '@fayz-ai/ui'\nimport { useConversationsStore } from '../ConversationsContext'\nimport type { Channel } from '../types'\nimport { Avatar, ChannelBadge, relativeTime } from './shared'\n\nconst FILTERS: Array<{ id: Channel | 'all'; label: string }> = [\n { id: 'all', label: 'All' },\n { id: 'whatsapp', label: 'WhatsApp' },\n { id: 'sms', label: 'SMS' },\n { id: 'instagram', label: 'Instagram' },\n { id: 'email', label: 'Email' },\n { id: 'webchat', label: 'Web' },\n]\n\nexport function ConversationList({ className }: { className?: string }) {\n const {\n conversations, selectedId, channelFilter, search, loading,\n select, setChannelFilter, setSearch,\n } = useConversationsStore((s) => s)\n\n return (\n <aside className={cn('w-full shrink-0 flex-col border-r border-border bg-card lg:w-[320px]', className)}>\n <div className=\"border-b border-border px-3 py-3\">\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\" />\n <Input\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search conversations\"\n className=\"pl-8\"\n />\n </div>\n <div className=\"mt-2 flex flex-wrap gap-1\">\n {FILTERS.map((f) => (\n <button\n key={f.id}\n onClick={() => setChannelFilter(f.id)}\n className={cn(\n 'rounded-full px-2.5 py-1 text-xs font-medium transition-colors',\n channelFilter === f.id\n ? 'bg-primary text-primary-foreground'\n : 'bg-muted text-muted-foreground hover:bg-muted/70',\n )}\n >\n {f.label}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto\">\n {loading && conversations.length === 0 && (\n <p className=\"p-4 text-sm text-muted-foreground\">Loading…</p>\n )}\n {!loading && conversations.length === 0 && (\n <div className=\"flex flex-col items-center gap-2 p-8 text-center text-muted-foreground\">\n <InboxIcon className=\"h-6 w-6\" />\n <p className=\"text-sm\">No conversations</p>\n </div>\n )}\n {conversations.map((c) => {\n const active = c.id === selectedId\n const unread = c.unreadCount > 0\n return (\n <button\n key={c.id}\n onClick={() => select(c.id)}\n className={cn(\n 'flex w-full items-start gap-3 border-b border-border/50 px-3 py-3 text-left transition-colors',\n active ? 'bg-accent' : 'hover:bg-muted/50',\n )}\n >\n <Avatar name={c.contactName} accent={c.accent} channel={c.channel} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className={cn('truncate text-sm text-foreground', unread ? 'font-semibold' : 'font-medium')}>\n {c.contactName}\n </span>\n <span className={cn('shrink-0 text-[11px]', unread ? 'font-semibold text-primary' : 'text-muted-foreground')}>\n {relativeTime(c.lastMessageAt)}\n </span>\n </div>\n <div className=\"mt-1 flex items-center gap-2\">\n <ChannelBadge channel={c.channel} />\n {c.status !== 'open' && (\n <span className=\"text-[10px] uppercase tracking-wide text-muted-foreground/70\">{c.status}</span>\n )}\n </div>\n <div className=\"mt-1 flex items-center justify-between gap-2\">\n <span className={cn('truncate text-xs', unread ? 'text-foreground' : 'text-muted-foreground')}>\n {c.lastMessagePreview}\n </span>\n {unread && (\n <span className=\"flex h-[18px] min-w-[18px] shrink-0 items-center justify-center rounded-full bg-primary px-1.5 text-[10px] font-semibold text-primary-foreground\">\n {c.unreadCount}\n </span>\n )}\n </div>\n </div>\n </button>\n )\n })}\n </div>\n </aside>\n )\n}\n","import React from 'react'\nimport { Send, Clock, Archive, PanelRight, MessageSquare, Smile, Paperclip, ChevronLeft } from 'lucide-react'\nimport { Button, cn } from '@fayz-ai/ui'\nimport { useConversationsStore } from '../ConversationsContext'\nimport { CHANNEL_ACCENT, CHANNEL_LABELS } from '../channel'\nimport type { Conversation, Message } from '../types'\nimport { Avatar, ChannelBadge, dayLabel } from './shared'\n\n// Build a flat render list: day-separator rows interleaved with messages, and\n// each message flagged as the start of a new sender-run (WhatsApp grouping).\ntype Row =\n | { kind: 'day'; id: string; label: string }\n | { kind: 'msg'; id: string; message: Message; startsRun: boolean; endsRun: boolean }\n\nfunction buildRows(messages: Message[]): Row[] {\n const rows: Row[] = []\n let lastDay = ''\n messages.forEach((m, i) => {\n const day = new Date(m.at).toDateString()\n if (day !== lastDay) {\n rows.push({ kind: 'day', id: `day-${day}`, label: dayLabel(m.at) })\n lastDay = day\n }\n const prev = messages[i - 1]\n const next = messages[i + 1]\n const samePrev = prev && prev.direction === m.direction && new Date(prev.at).toDateString() === day\n const sameNext = next && next.direction === m.direction && new Date(next.at).toDateString() === day\n rows.push({ kind: 'msg', id: m.id, message: m, startsRun: !samePrev, endsRun: !sameNext })\n })\n return rows\n}\n\nexport function MessageThread({ selected, onTogglePanel, panelOpen, onBack, className }: {\n selected: Conversation\n onTogglePanel: () => void\n panelOpen: boolean\n onBack?: () => void\n className?: string\n}) {\n const { messages, sending, send, setStatus } = useConversationsStore((s) => s)\n const [draft, setDraft] = React.useState('')\n const threadRef = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n threadRef.current?.scrollTo({ top: threadRef.current.scrollHeight, behavior: 'smooth' })\n }, [messages.length, selected.id])\n\n async function handleSend() {\n if (!draft.trim()) return\n const body = draft\n setDraft('')\n await send(body)\n }\n\n const accent = CHANNEL_ACCENT[selected.channel]\n const rows = React.useMemo(() => buildRows(messages), [messages])\n\n return (\n <section className={cn('flex min-w-0 flex-1 flex-col bg-muted/20', className)}>\n {/* Header */}\n <div className=\"flex items-center justify-between gap-2 border-b border-border bg-card px-3 py-2.5 md:px-5\">\n <div className=\"flex min-w-0 items-center gap-2 md:gap-3\">\n {onBack && (\n <Button variant=\"ghost\" size=\"icon\" className=\"-ml-1 shrink-0 lg:hidden\" onClick={onBack} aria-label=\"Back to conversations\">\n <ChevronLeft className=\"h-5 w-5\" />\n </Button>\n )}\n <Avatar name={selected.contactName} accent={selected.accent} size=\"sm\" channel={selected.channel} />\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-semibold text-foreground\">{selected.contactName}</p>\n <p className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <ChannelBadge channel={selected.channel} />\n <span className=\"truncate\">{selected.contactHandle}</span>\n </p>\n </div>\n </div>\n <div className=\"flex shrink-0 items-center gap-1.5\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => setStatus('snoozed')} aria-label=\"Snooze\">\n <Clock className=\"h-3.5 w-3.5 sm:mr-1\" /> <span className=\"hidden sm:inline\">Snooze</span>\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setStatus('closed')} aria-label=\"Close conversation\">\n <Archive className=\"h-3.5 w-3.5 sm:mr-1\" /> <span className=\"hidden sm:inline\">Close</span>\n </Button>\n <Button\n variant={panelOpen ? 'secondary' : 'ghost'}\n size=\"icon\"\n onClick={onTogglePanel}\n aria-label=\"Toggle contact details\"\n >\n <PanelRight className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n\n {/* Messages */}\n <div ref={threadRef} className=\"min-h-0 flex-1 overflow-y-auto px-5 py-4\">\n {rows.map((row) => {\n if (row.kind === 'day') {\n return (\n <div key={row.id} className=\"my-3 flex items-center justify-center\">\n <span className=\"rounded-full bg-muted px-3 py-0.5 text-[11px] font-medium text-muted-foreground\">\n {row.label}\n </span>\n </div>\n )\n }\n const m = row.message\n const outbound = m.direction === 'outbound'\n return (\n <div\n key={row.id}\n className={cn('flex', outbound ? 'justify-end' : 'justify-start', row.startsRun ? 'mt-2.5' : 'mt-0.5')}\n >\n <div\n className={cn(\n 'max-w-[68%] px-3.5 py-2 text-sm shadow-sm',\n outbound ? 'rounded-2xl text-white' : 'rounded-2xl bg-card text-foreground',\n // Tail only on the last bubble of a run, on the sender's side.\n outbound && row.endsRun && 'rounded-br-sm',\n !outbound && row.endsRun && 'rounded-bl-sm',\n )}\n style={outbound ? { backgroundColor: accent.color } : undefined}\n >\n <p className=\"whitespace-pre-wrap break-words\">{m.body}</p>\n <div className={cn('mt-0.5 text-right text-[10px]', outbound ? 'text-white/70' : 'text-muted-foreground')}>\n {new Date(m.at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}\n </div>\n </div>\n </div>\n )\n })}\n {rows.length === 0 && (\n <div className=\"flex h-full flex-col items-center justify-center text-muted-foreground\">\n <MessageSquare className=\"h-7 w-7\" />\n <p className=\"mt-2 text-sm\">No messages yet</p>\n </div>\n )}\n </div>\n\n {/* Composer */}\n <div className=\"border-t border-border bg-card px-4 py-3\">\n <div className=\"flex items-end gap-2\">\n <Button variant=\"ghost\" size=\"icon\" className=\"mb-0.5 text-muted-foreground\" aria-label=\"Add emoji\">\n <Smile className=\"h-4 w-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon\" className=\"mb-0.5 text-muted-foreground\" aria-label=\"Attach file\">\n <Paperclip className=\"h-4 w-4\" />\n </Button>\n <textarea\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n void handleSend()\n }\n }}\n rows={1}\n placeholder={`Reply via ${CHANNEL_LABELS[selected.channel]}…`}\n className=\"max-h-32 min-h-[40px] flex-1 resize-none rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground outline-none focus:border-primary\"\n />\n <Button onClick={() => void handleSend()} disabled={sending || !draft.trim()} aria-label=\"Send\">\n <Send className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n </section>\n )\n}\n","import React from 'react'\nimport { MapPin, User, Tag, Link2, StickyNote, X } from 'lucide-react'\nimport { Button, cn } from '@fayz-ai/ui'\nimport { CHANNEL_LABELS } from '../channel'\nimport type { Conversation } from '../types'\nimport { Avatar, ChannelBadge } from './shared'\n\nfunction Section({ icon: Icon, title, children }: {\n icon: React.ComponentType<{ className?: string }>\n title: string\n children: React.ReactNode\n}) {\n return (\n <div className=\"border-t border-border px-4 py-3\">\n <p className=\"mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n <Icon className=\"h-3 w-3\" /> {title}\n </p>\n {children}\n </div>\n )\n}\n\nexport function ContactPanel({ contact, onClose, className }: {\n contact: Conversation\n onClose?: () => void\n className?: string\n}) {\n return (\n <aside className={cn('flex shrink-0 flex-col overflow-y-auto border-l border-border bg-card', className)}>\n {onClose && (\n <div className=\"flex items-center justify-between border-b border-border px-3 py-2 xl:hidden\">\n <span className=\"text-sm font-semibold text-foreground\">Details</span>\n <Button variant=\"ghost\" size=\"icon\" onClick={onClose} aria-label=\"Close details\">\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n )}\n <div className=\"flex flex-col items-center gap-2 px-4 py-5 text-center\">\n <Avatar name={contact.contactName} accent={contact.accent} size=\"lg\" channel={contact.channel} />\n <div>\n <p className=\"text-sm font-semibold text-foreground\">{contact.contactName}</p>\n <p className=\"text-xs text-muted-foreground\">{contact.contactHandle}</p>\n </div>\n <ChannelBadge channel={contact.channel} />\n </div>\n\n <Section icon={User} title=\"Details\">\n <dl className=\"space-y-1.5 text-sm\">\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-muted-foreground\">Channel</dt>\n <dd className=\"text-foreground\">{CHANNEL_LABELS[contact.channel]}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-muted-foreground\">Status</dt>\n <dd className=\"capitalize text-foreground\">{contact.status}</dd>\n </div>\n {contact.assignedTo && (\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-muted-foreground\">Assigned to</dt>\n <dd className=\"text-foreground\">{contact.assignedTo}</dd>\n </div>\n )}\n {contact.location && (\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"flex items-center gap-1 text-muted-foreground\"><MapPin className=\"h-3 w-3\" /> Location</dt>\n <dd className=\"text-foreground\">{contact.location}</dd>\n </div>\n )}\n </dl>\n </Section>\n\n {contact.tags.length > 0 && (\n <Section icon={Tag} title=\"Tags\">\n <div className=\"flex flex-wrap gap-1.5\">\n {contact.tags.map((tag) => (\n <span key={tag} className=\"rounded-full bg-muted px-2 py-0.5 text-xs font-medium text-foreground\">\n {tag}\n </span>\n ))}\n </div>\n </Section>\n )}\n\n {contact.note && (\n <Section icon={StickyNote} title=\"Note\">\n <p className=\"text-sm text-foreground\">{contact.note}</p>\n </Section>\n )}\n\n <Section icon={Link2} title=\"Linked records\">\n <p className=\"text-xs text-muted-foreground\">No linked records yet.</p>\n </Section>\n </aside>\n )\n}\n","import React from 'react'\nimport { MessageSquare } from 'lucide-react'\nimport { cn } from '@fayz-ai/ui'\nimport { useConversationsStore } from '../ConversationsContext'\nimport { ConversationList } from './ConversationList'\nimport { MessageThread } from './MessageThread'\nimport { ContactPanel } from './ContactPanel'\nimport { useMediaQuery } from './shared'\n\nexport function InboxView() {\n const { conversations, selectedId, deselect } = useConversationsStore((s) => s)\n // xl+ shows the contact panel inline (three panes); below that it's an\n // on-demand slide-over so the list + thread keep room to breathe.\n const isWidePanel = useMediaQuery('(min-width: 1280px)')\n const [panelOpen, setPanelOpen] = React.useState(false)\n const selected = conversations.find((c) => c.id === selectedId) ?? null\n\n // Open the panel by default only when it fits inline; collapse it otherwise.\n React.useEffect(() => {\n setPanelOpen(isWidePanel)\n }, [isWidePanel])\n\n return (\n <div className=\"relative flex h-full min-h-0 overflow-hidden bg-background\">\n {/* Conversation list — single-pane below lg (full width), fixed rail at lg+.\n Below lg it yields to the thread once a conversation is open. */}\n <ConversationList className={cn(selected ? 'hidden lg:flex' : 'flex')} />\n\n {/* Thread — hidden below lg until a conversation is selected. */}\n {selected ? (\n <MessageThread\n selected={selected}\n panelOpen={panelOpen}\n onTogglePanel={() => setPanelOpen((v) => !v)}\n onBack={deselect}\n className=\"flex\"\n />\n ) : (\n <section className=\"hidden min-w-0 flex-1 flex-col items-center justify-center bg-muted/20 text-muted-foreground lg:flex\">\n <MessageSquare className=\"h-9 w-9\" />\n <p className=\"mt-2 text-sm\">Select a conversation to start chatting</p>\n </section>\n )}\n\n {/* Contact panel — inline column at xl, slide-over overlay below xl. */}\n {selected && panelOpen && (\n <>\n <button\n className=\"absolute inset-0 z-10 bg-black/40 xl:hidden\"\n aria-label=\"Close details\"\n onClick={() => setPanelOpen(false)}\n />\n <ContactPanel\n contact={selected}\n onClose={() => setPanelOpen(false)}\n className=\"absolute inset-y-0 right-0 z-20 w-[340px] max-w-[88%] shadow-2xl xl:static xl:z-auto xl:w-[300px] xl:max-w-none xl:shadow-none\"\n />\n </>\n )}\n </div>\n )\n}\n","import React from 'react'\nimport type { StoreApi } from 'zustand/vanilla'\nimport { ConversationsContextProvider } from './ConversationsContext'\nimport type { ConversationsUIState } from './store'\nimport { InboxView } from './views/InboxView'\n\nexport function ConversationsPage({ store }: { store: StoreApi<ConversationsUIState> }) {\n React.useEffect(() => {\n void store.getState().load()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n return (\n <ConversationsContextProvider store={store}>\n <InboxView />\n </ConversationsContextProvider>\n )\n}\n","import type { ConversationsProvider } from './types'\nimport type {\n Conversation,\n Message,\n ListConversationsQuery,\n SendMessageInput,\n ConversationStatus,\n} from '../types'\n\n// Deterministic relative timestamps (no Date.now at module init for stable seeds).\nfunction minutesAgo(base: number, mins: number): string {\n return new Date(base - mins * 60_000).toISOString()\n}\n\nfunction seed(): { conversations: Conversation[]; messages: Message[] } {\n const base = new Date('2026-06-16T14:00:00Z').getTime()\n\n const conversations: Conversation[] = [\n {\n id: 'c1', contactName: 'Marina Alves', contactHandle: '+55 11 99876-1020', channel: 'whatsapp',\n lastMessagePreview: 'Perfect, can we book for Friday at 3pm?', lastMessageAt: minutesAgo(base, 4),\n unreadCount: 2, status: 'open', assignedTo: 'You', accent: '#22c55e', tags: ['Hot lead'],\n location: 'São Paulo, BR', note: 'Referred by Instagram ad — interested in full color + cut.',\n },\n {\n id: 'c2', contactName: 'Jordan Pierce', contactHandle: '+1 (415) 555-0142', channel: 'sms',\n lastMessagePreview: 'Got it — sending the deposit now.', lastMessageAt: minutesAgo(base, 22),\n unreadCount: 0, status: 'open', assignedTo: 'You', accent: '#6366f1', tags: ['Customer'],\n location: 'San Francisco, US',\n },\n {\n id: 'c3', contactName: '@thehairloft', contactHandle: 'thehairloft', channel: 'instagram',\n lastMessagePreview: 'Do you offer balayage on weekends?', lastMessageAt: minutesAgo(base, 51),\n unreadCount: 1, status: 'open', accent: '#ec4899', tags: ['New'],\n },\n {\n id: 'c4', contactName: 'David Whitman', contactHandle: 'david@whitman.co', channel: 'email',\n lastMessagePreview: 'Re: Proposal — looks great, one question on pricing…', lastMessageAt: minutesAgo(base, 95),\n unreadCount: 0, status: 'open', assignedTo: 'Sofia', accent: '#0ea5e9', tags: ['Proposal'],\n location: 'Austin, US', note: 'Evaluating the retainer tier. Decision expected this week.',\n },\n {\n id: 'c5', contactName: 'Website visitor', contactHandle: 'live chat · acme.com', channel: 'webchat',\n lastMessagePreview: 'Is anyone available to chat?', lastMessageAt: minutesAgo(base, 140),\n unreadCount: 0, status: 'snoozed', accent: '#f59e0b', tags: [],\n },\n {\n id: 'c6', contactName: 'Priya Nair', contactHandle: '+44 7700 900123', channel: 'whatsapp',\n lastMessagePreview: 'Thank you! See you next week 🙌', lastMessageAt: minutesAgo(base, 1440),\n unreadCount: 0, status: 'closed', assignedTo: 'You', accent: '#14b8a6', tags: ['Customer'],\n location: 'London, UK',\n },\n ]\n\n const messages: Message[] = [\n msg('m1', 'c1', 'whatsapp', 'inbound', 'Hi! I saw your ad — do you have availability this week?', 'Marina Alves', minutesAgo(base, 18)),\n msg('m2', 'c1', 'whatsapp', 'outbound', 'Hi Marina! Yes, we do. What service are you interested in?', 'You', minutesAgo(base, 15)),\n msg('m3', 'c1', 'whatsapp', 'inbound', 'A full color + cut.', 'Marina Alves', minutesAgo(base, 9)),\n msg('m4', 'c1', 'whatsapp', 'inbound', 'Perfect, can we book for Friday at 3pm?', 'Marina Alves', minutesAgo(base, 4)),\n\n msg('m5', 'c2', 'sms', 'outbound', 'Your appointment is confirmed for tomorrow at 10am.', 'You', minutesAgo(base, 40)),\n msg('m6', 'c2', 'sms', 'inbound', 'Got it — sending the deposit now.', 'Jordan Pierce', minutesAgo(base, 22)),\n\n msg('m7', 'c3', 'instagram', 'inbound', 'Do you offer balayage on weekends?', '@thehairloft', minutesAgo(base, 51)),\n\n msg('m8', 'c4', 'email', 'inbound', 'Re: Proposal — looks great, one question on pricing for the retainer tier.', 'David Whitman', minutesAgo(base, 95)),\n msg('m9', 'c4', 'email', 'outbound', 'Happy to walk you through it — are you free for a quick call tomorrow?', 'Sofia', minutesAgo(base, 80)),\n\n msg('m10', 'c5', 'webchat', 'inbound', 'Is anyone available to chat?', 'Website visitor', minutesAgo(base, 140)),\n\n msg('m11', 'c6', 'whatsapp', 'outbound', 'You are all set for next Tuesday. Anything else?', 'You', minutesAgo(base, 1500)),\n msg('m12', 'c6', 'whatsapp', 'inbound', 'Thank you! See you next week 🙌', 'Priya Nair', minutesAgo(base, 1440)),\n ]\n\n return { conversations, messages }\n}\n\nfunction msg(\n id: string, conversationId: string, channel: Message['channel'],\n direction: Message['direction'], body: string, author: string, at: string,\n): Message {\n return { id, conversationId, channel, direction, body, author, at }\n}\n\nexport function createMockConversationsProvider(): ConversationsProvider {\n const { conversations, messages } = seed()\n let counter = 100\n\n return {\n async listConversations(query?: ListConversationsQuery): Promise<Conversation[]> {\n let list = [...conversations]\n if (query?.channel && query.channel !== 'all') list = list.filter((c) => c.channel === query.channel)\n if (query?.status && query.status !== 'all') list = list.filter((c) => c.status === query.status)\n if (query?.search) {\n const q = query.search.toLowerCase()\n list = list.filter(\n (c) => c.contactName.toLowerCase().includes(q) || c.lastMessagePreview.toLowerCase().includes(q),\n )\n }\n return list.sort((a, b) => b.lastMessageAt.localeCompare(a.lastMessageAt))\n },\n\n async getMessages(conversationId: string): Promise<Message[]> {\n return messages\n .filter((m) => m.conversationId === conversationId)\n .sort((a, b) => a.at.localeCompare(b.at))\n },\n\n async sendMessage(input: SendMessageInput): Promise<Message> {\n const conv = conversations.find((c) => c.id === input.conversationId)\n const created: Message = {\n id: `m${++counter}`,\n conversationId: input.conversationId,\n channel: conv?.channel ?? 'sms',\n direction: 'outbound',\n body: input.body,\n author: 'You',\n at: new Date().toISOString(),\n }\n messages.push(created)\n if (conv) {\n conv.lastMessagePreview = input.body\n conv.lastMessageAt = created.at\n conv.unreadCount = 0\n if (conv.status === 'closed') conv.status = 'open'\n }\n return created\n },\n\n async markRead(conversationId: string): Promise<void> {\n const conv = conversations.find((c) => c.id === conversationId)\n if (conv) conv.unreadCount = 0\n },\n\n async setStatus(conversationId: string, status: ConversationStatus): Promise<Conversation> {\n const conv = conversations.find((c) => c.id === conversationId)\n if (!conv) throw new Error('Conversation not found')\n conv.status = status\n return conv\n },\n }\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport type { ConversationsProvider } from './types'\nimport type {\n Conversation,\n Message,\n ListConversationsQuery,\n SendMessageInput,\n ConversationStatus,\n} from '../types'\n\n// ---------------------------------------------------------------------------\n// Supabase-backed conversations provider — reads/writes the project's\n// `conversations` + `conversation_messages` tables (tenant-scoped via RLS +\n// an explicit tenant filter from the active-org context). Mirrors the inline\n// client-casting style of @fayz-ai/core's createSupabaseProvider; the global\n// client is `unknown`-typed so each call narrows the shape it needs.\n//\n// Real channel connectors (Twilio, WhatsApp Cloud, Meta, IMAP) deliver inbound\n// rows into these tables out-of-band; this provider is the read/compose surface.\n// ---------------------------------------------------------------------------\n\nexport interface SupabaseConversationsConfig {\n /** Supabase client; defaults to the global one registered by createFayzApp. */\n supabaseClient?: unknown\n /** Active tenant id (value or getter) used to scope reads and stamp writes. */\n tenantId?: string | (() => string | undefined)\n /** Display name stamped as the author of outbound messages. */\n selfAuthor?: string\n}\n\ntype Row = Record<string, unknown>\n\nfunction mapConversation(r: Row): Conversation {\n return {\n id: String(r.id),\n contactName: (r.contact_name as string) ?? '',\n contactHandle: (r.contact_handle as string) ?? '',\n channel: (r.channel as Conversation['channel']) ?? 'sms',\n lastMessagePreview: (r.last_message_preview as string) ?? '',\n lastMessageAt: (r.last_message_at as string) ?? '',\n unreadCount: Number(r.unread_count ?? 0),\n status: (r.status as ConversationStatus) ?? 'open',\n assignedTo: (r.assigned_to as string | null) ?? undefined,\n accent: (r.accent as string) ?? '#6366f1',\n tags: (r.tags as string[] | null) ?? [],\n location: (r.location as string | null) ?? undefined,\n note: (r.note as string | null) ?? undefined,\n }\n}\n\nfunction mapMessage(r: Row): Message {\n return {\n id: String(r.id),\n conversationId: String(r.conversation_id),\n channel: (r.channel as Message['channel']) ?? 'sms',\n direction: (r.direction as Message['direction']) ?? 'inbound',\n body: (r.body as string) ?? '',\n at: (r.at as string) ?? '',\n author: (r.author as string) ?? '',\n }\n}\n\nexport function createSupabaseConversationsProvider(\n config?: SupabaseConversationsConfig,\n): ConversationsProvider {\n const selfAuthor = config?.selfAuthor ?? 'You'\n\n function resolveTenantId(): string | undefined {\n if (!config?.tenantId) return undefined\n return typeof config.tenantId === 'function' ? config.tenantId() : config.tenantId\n }\n\n function client(): { from: (t: string) => Row } {\n const supabase = (config?.supabaseClient ?? getSupabaseClientOptional()) as\n | { from: (t: string) => Row }\n | null\n if (!supabase) {\n throw new Error(\n '[plugin-conversations] Supabase client not available. Pass supabaseClient or register the global client via createFayzApp.',\n )\n }\n return supabase\n }\n\n return {\n async listConversations(query?: ListConversationsQuery): Promise<Conversation[]> {\n let q = (client().from('conversations') as { select: (s: string) => Row }).select('*')\n\n const tenantId = resolveTenantId()\n if (tenantId) q = (q as { eq: (c: string, v: string) => Row }).eq('tenant_id', tenantId)\n if (query?.channel && query.channel !== 'all') {\n q = (q as { eq: (c: string, v: string) => Row }).eq('channel', query.channel)\n }\n if (query?.status && query.status !== 'all') {\n q = (q as { eq: (c: string, v: string) => Row }).eq('status', query.status)\n }\n if (query?.search) {\n const term = `%${query.search}%`\n q = (q as { or: (c: string) => Row }).or(\n `contact_name.ilike.${term},last_message_preview.ilike.${term}`,\n )\n }\n q = (q as { order: (c: string, o: unknown) => Row }).order('last_message_at', {\n ascending: false,\n })\n\n const { data, error } = (await q) as { data: Row[] | null; error: unknown }\n if (error) throw error\n return (data ?? []).map(mapConversation)\n },\n\n async getMessages(conversationId: string): Promise<Message[]> {\n const selected = (\n client().from('conversation_messages') as { select: (s: string) => Row }\n ).select('*')\n const filtered = (selected as { eq: (c: string, v: string) => Row }).eq(\n 'conversation_id',\n conversationId,\n )\n const ordered = (filtered as { order: (c: string, o: unknown) => Row }).order('at', {\n ascending: true,\n })\n const { data, error } = (await ordered) as { data: Row[] | null; error: unknown }\n if (error) throw error\n return (data ?? []).map(mapMessage)\n },\n\n async sendMessage(input: SendMessageInput): Promise<Message> {\n const tenantId = resolveTenantId()\n\n // Resolve the channel from the parent conversation so the message matches.\n const convSelected = (client().from('conversations') as { select: (s: string) => Row }).select(\n 'channel',\n )\n const convFiltered = (convSelected as { eq: (c: string, v: string) => Row }).eq(\n 'id',\n input.conversationId,\n )\n const { data: conv } = (await (\n convFiltered as { maybeSingle: () => Promise<{ data: Row | null }> }\n ).maybeSingle()) as { data: Row | null }\n const channel = (conv?.channel as Message['channel']) ?? 'sms'\n\n const at = new Date().toISOString()\n const row: Row = {\n conversation_id: input.conversationId,\n channel,\n direction: 'outbound',\n body: input.body,\n author: selfAuthor,\n at,\n }\n if (tenantId) row.tenant_id = tenantId\n\n const { data: created, error } = (await (\n (client().from('conversation_messages') as { insert: (r: Row) => Row }).insert(row) as {\n select: () => { single: () => Promise<{ data: Row | null; error: unknown }> }\n }\n )\n .select()\n .single()) as { data: Row | null; error: unknown }\n if (error) throw error\n\n // Roll the parent conversation forward (preview / timestamp / unread / reopen).\n await (\n (client().from('conversations') as {\n update: (r: Row) => Row\n }).update({\n last_message_preview: input.body,\n last_message_at: at,\n unread_count: 0,\n status: 'open',\n }) as { eq: (c: string, v: string) => Promise<unknown> }\n ).eq('id', input.conversationId)\n\n return mapMessage(created ?? row)\n },\n\n async markRead(conversationId: string): Promise<void> {\n const { error } = (await (\n (client().from('conversations') as { update: (r: Row) => Row }).update({\n unread_count: 0,\n }) as { eq: (c: string, v: string) => Promise<{ error: unknown }> }\n ).eq('id', conversationId)) as { error: unknown }\n if (error) throw error\n },\n\n async setStatus(conversationId: string, status: ConversationStatus): Promise<Conversation> {\n const updated = (client().from('conversations') as { update: (r: Row) => Row }).update({\n status,\n })\n const filtered = (updated as { eq: (c: string, v: string) => Row }).eq('id', conversationId)\n const selected = (filtered as { select: () => Row }).select()\n const { data, error } = (await (\n selected as { single: () => Promise<{ data: Row | null; error: unknown }> }\n ).single()) as { data: Row | null; error: unknown }\n if (error) throw error\n if (!data) throw new Error('Conversation not found')\n return mapConversation(data)\n },\n }\n}\n","import { createStore, type StoreApi } from 'zustand/vanilla'\nimport type { ConversationsProvider } from './data/types'\nimport type { Conversation, Message, Channel, ConversationStatus } from './types'\n\nexport interface ConversationsUIState {\n conversations: Conversation[]\n messages: Message[]\n selectedId: string | null\n channelFilter: Channel | 'all'\n search: string\n loading: boolean\n sending: boolean\n\n load(): Promise<void>\n select(id: string): Promise<void>\n deselect(): void\n setChannelFilter(channel: Channel | 'all'): Promise<void>\n setSearch(search: string): Promise<void>\n send(body: string): Promise<void>\n setStatus(status: ConversationStatus): Promise<void>\n}\n\nexport function createConversationsStore(\n provider: ConversationsProvider,\n): StoreApi<ConversationsUIState> {\n return createStore<ConversationsUIState>((set, get) => ({\n conversations: [],\n messages: [],\n selectedId: null,\n channelFilter: 'all',\n search: '',\n loading: false,\n sending: false,\n\n async load() {\n set({ loading: true })\n const conversations = await provider.listConversations({\n channel: get().channelFilter,\n search: get().search || undefined,\n })\n const selectedId = get().selectedId ?? conversations[0]?.id ?? null\n set({ conversations, loading: false, selectedId })\n if (selectedId) await get().select(selectedId)\n },\n\n async select(id: string) {\n set({ selectedId: id })\n const messages = await provider.getMessages(id)\n set({ messages })\n await provider.markRead(id)\n set((s) => ({\n conversations: s.conversations.map((c) => (c.id === id ? { ...c, unreadCount: 0 } : c)),\n }))\n },\n\n deselect() {\n set({ selectedId: null, messages: [] })\n },\n\n async setChannelFilter(channel) {\n set({ channelFilter: channel })\n await get().load()\n },\n\n async setSearch(search) {\n set({ search })\n await get().load()\n },\n\n async send(body: string) {\n const id = get().selectedId\n if (!id || !body.trim()) return\n set({ sending: true })\n const created = await provider.sendMessage({ conversationId: id, body: body.trim() })\n set((s) => ({\n sending: false,\n messages: [...s.messages, created],\n conversations: s.conversations.map((c) =>\n c.id === id ? { ...c, lastMessagePreview: created.body, lastMessageAt: created.at } : c,\n ),\n }))\n },\n\n async setStatus(status) {\n const id = get().selectedId\n if (!id) return\n const updated = await provider.setStatus(id, status)\n set((s) => ({\n conversations: s.conversations.map((c) => (c.id === id ? updated : c)),\n }))\n },\n }))\n}\n","export const en: Record<string, string> = {\n 'conversations.title': 'Conversations',\n 'conversations.subtitle': 'Unified inbox across every channel',\n}\n","import { en } from './en'\n\nexport const conversationsLocales: Record<string, Record<string, string>> = {\n en,\n}\n","import React from 'react'\nimport type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'\nimport { getActiveTenantId, getSupabaseClientOptional, registerTranslations } from '@fayz-ai/core'\nimport { ConversationsPage } from './ConversationsPage'\nimport type { ConversationsProvider } from './data/types'\nimport { createMockConversationsProvider } from './data/mock'\nimport { createSupabaseConversationsProvider } from './data/supabase'\nimport { createConversationsStore } from './store'\nimport { conversationsLocales } from './locales'\n\n// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-conversations — the GoHighLevel \"Conversations\" equivalent:\n// one omni-channel inbox (SMS / WhatsApp / Instagram / Email / Web chat).\n// Universal plugin — reusable by any vertical (beauty, resto, agency…).\n//\n// M1 ships a full mock inbox. Real channel connectors (Twilio, WhatsApp Cloud,\n// Meta, IMAP) + Supabase-backed threads land in a later milestone.\n// ---------------------------------------------------------------------------\n\nexport interface ConversationsPluginOptions {\n navPosition?: number\n navSection?: 'main' | 'secondary' | 'settings'\n navLabel?: string\n scope?: PluginScope\n verticalId?: VerticalId\n dataProvider?: ConversationsProvider\n}\n\nfunction createSafeProvider(): ConversationsProvider {\n // Real data when a Supabase client is registered (reads/writes the\n // `conversations` + `conversation_messages` tables, tenant-scoped via the\n // active-org context); falls back to the mock inbox when no backend is wired.\n if (getSupabaseClientOptional()) {\n return createSupabaseConversationsProvider({ tenantId: () => getActiveTenantId() })\n }\n return createMockConversationsProvider()\n}\n\nexport function createConversationsPlugin(options?: ConversationsPluginOptions): PluginManifest {\n registerTranslations(conversationsLocales)\n const provider = options?.dataProvider ?? createSafeProvider()\n const store = createConversationsStore(provider)\n\n const PageComponent: React.ComponentType<unknown> = () =>\n React.createElement(ConversationsPage, { store })\n PageComponent.displayName = 'ConversationsPage'\n\n return {\n id: 'conversations',\n name: options?.navLabel ?? 'Conversations',\n icon: 'MessageCircle',\n version: '1.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [{ id: 'conversations', label: 'Conversations', group: 'Engage' }],\n navigation: [\n {\n section: options?.navSection ?? 'main',\n position: options?.navPosition ?? 1,\n label: options?.navLabel ?? 'Conversations',\n route: '/conversations',\n icon: 'MessageCircle',\n permission: { feature: 'conversations', action: 'read' as const },\n },\n ],\n routes: [\n {\n path: '/conversations',\n component: PageComponent,\n fullBleed: true,\n permission: { feature: 'conversations', action: 'read' as const },\n },\n ],\n widgets: [],\n events: [\n { name: 'conversations.message.received', description: 'An inbound message arrived on any channel' },\n { name: 'conversations.message.sent', description: 'An outbound message was sent' },\n ],\n aiTools: [\n {\n id: 'conversations.list-threads',\n name: 'listConversations',\n description: 'Lists open conversations across all channels, optionally filtered by channel.',\n icon: 'MessageCircle',\n mode: 'read' as const,\n category: 'Conversations',\n parameters: {\n type: 'object' as const,\n properties: {\n channel: {\n type: 'string' as const,\n enum: ['all', 'sms', 'whatsapp', 'instagram', 'email', 'webchat'],\n },\n },\n },\n suggestions: [\n { label: 'Show unread conversations' },\n { label: 'Any new WhatsApp messages?' },\n ],\n permission: { feature: 'conversations', action: 'read' as const },\n },\n {\n id: 'conversations.send-message',\n name: 'sendMessage',\n description: 'Sends a reply in a conversation thread.',\n icon: 'Send',\n mode: 'persist' as const,\n category: 'Conversations',\n parameters: {\n type: 'object' as const,\n properties: {\n conversationId: { type: 'string' as const, description: 'Conversation id' },\n body: { type: 'string' as const, description: 'Message body' },\n },\n required: ['conversationId', 'body'],\n },\n permission: { feature: 'conversations', action: 'create' as const },\n },\n ],\n locales: conversationsLocales,\n }\n}\n\nexport type { ConversationsProvider } from './data/types'\nexport type { Conversation, Message, Channel } from './types'\nexport { createMockConversationsProvider } from './data/mock'\nexport {\n createSupabaseConversationsProvider,\n type SupabaseConversationsConfig,\n} from './data/supabase'\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/ConversationsContext.tsx","../src/types.ts","../src/channel.ts","../src/views/shared.tsx","../src/views/NewConversationModal.tsx","../src/views/ConversationList.tsx","../src/views/MessageThread.tsx","../src/views/ContactPanel.tsx","../src/views/InboxView.tsx","../src/ConversationsPage.tsx","../src/data/accents.ts","../src/data/mock.ts","../src/data/tables.ts","../src/data/supabase.ts","../src/store.ts","../src/locales/en.ts","../src/locales/pt-BR.ts","../src/locales/index.ts","../src/migrations/index.ts","../src/index.ts"],"names":["React","jsx","jsxs","cn","useTranslation","Button","InboxIcon","MessageSquare","getSupabaseClientOptional"],"mappings":"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","file":"index.js","sourcesContent":["import React from 'react'\nimport { useStore, type StoreApi } from 'zustand'\nimport type { EntityLookup } from '@fayz-ai/saas'\nimport type { ConversationsUIState } from './store'\n\n/**\n * App-tunable knobs the inbox UI reads. Kept tiny on purpose: everything here\n * describes the APP's data shape (which people are \"contacts\" in this vertical),\n * never product policy.\n */\nexport interface ResolvedConversationsConfig {\n /** `people.kind` used when the compose modal creates a contact. */\n contactKind: string\n /** Per-vertical extension table linked by `person_id` (skipped when absent). */\n contactExtensionTable?: string\n /** Search source for the contact picker. Defaults to the person archetype. */\n contactLookup?: EntityLookup\n}\n\nexport const DEFAULT_CONVERSATIONS_CONFIG: ResolvedConversationsConfig = {\n contactKind: 'contact',\n}\n\nconst StoreContext = React.createContext<StoreApi<ConversationsUIState> | null>(null)\nconst ConfigContext = React.createContext<ResolvedConversationsConfig>(DEFAULT_CONVERSATIONS_CONFIG)\n\nexport function ConversationsContextProvider({\n store,\n config = DEFAULT_CONVERSATIONS_CONFIG,\n children,\n}: {\n store: StoreApi<ConversationsUIState>\n config?: ResolvedConversationsConfig\n children?: React.ReactNode\n}) {\n return (\n <StoreContext.Provider value={store}>\n <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>\n </StoreContext.Provider>\n )\n}\n\nexport function useConversationsStore<T>(selector: (state: ConversationsUIState) => T): T {\n const store = React.useContext(StoreContext)\n if (!store) throw new Error('useConversationsStore must be used within ConversationsPage')\n return useStore(store, selector)\n}\n\nexport function useConversationsConfig(): ResolvedConversationsConfig {\n return React.useContext(ConfigContext)\n}\n","// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-conversations — domain types for the unified omni-channel\n// inbox (the GoHighLevel \"Conversations\" equivalent). Provider-agnostic.\n// ---------------------------------------------------------------------------\n\nexport type Channel = 'sms' | 'whatsapp' | 'instagram' | 'email' | 'webchat'\n\nexport type ConversationStatus = 'open' | 'snoozed' | 'closed'\n\nexport type MessageDirection = 'inbound' | 'outbound'\n\nexport interface Conversation {\n id: string\n contactName: string\n /**\n * `public.people` id when the thread is tied to a real contact record (the\n * compose modal resolves one via the shared ContactPicker). Absent for legacy\n * threads and for inbound messages from an unknown handle.\n */\n contactPersonId?: string\n /** Phone, @handle, or email depending on channel */\n contactHandle: string\n channel: Channel\n lastMessagePreview: string\n lastMessageAt: string\n unreadCount: number\n status: ConversationStatus\n assignedTo?: string\n /** Tailwind-ish accent for the avatar bubble */\n accent: string\n tags: string[]\n // Optional context shown in the contact panel.\n location?: string\n note?: string\n}\n\nexport interface Message {\n id: string\n conversationId: string\n channel: Channel\n direction: MessageDirection\n body: string\n at: string\n author: string\n}\n\nexport interface ListConversationsQuery {\n channel?: Channel | 'all'\n status?: ConversationStatus | 'all'\n search?: string\n}\n\nexport interface SendMessageInput {\n conversationId: string\n body: string\n}\n\nexport interface CreateConversationInput {\n contactName: string\n /** `public.people` id, when the contact was resolved/created by the picker. */\n contactPersonId?: string\n /** Phone, @handle, or email depending on channel. */\n contactHandle?: string\n channel: Channel\n /** Optional first outbound message; stamps preview + last_message_at. */\n firstMessage?: string\n /** Optional free-text note surfaced in the contact panel. */\n note?: string\n}\n\nexport const CHANNEL_LABELS: Record<Channel, string> = {\n sms: 'SMS',\n whatsapp: 'WhatsApp',\n instagram: 'Instagram',\n email: 'Email',\n webchat: 'Web Chat',\n}\n","import React from 'react'\nimport { MessageSquare, Phone, Instagram, Mail, Globe } from 'lucide-react'\nimport { CHANNEL_LABELS, type Channel } from './types'\n\n// ---------------------------------------------------------------------------\n// Shared channel visuals — one source of truth for the icon + accent color of\n// each channel, reused by the conversation list, thread header and contact\n// panel. Keeps the omni-channel inbox visually consistent.\n// ---------------------------------------------------------------------------\n\nexport const CHANNEL_ICON: Record<Channel, React.ComponentType<{ className?: string }>> = {\n sms: Phone,\n whatsapp: MessageSquare,\n instagram: Instagram,\n email: Mail,\n webchat: Globe,\n}\n\nexport interface ChannelAccent {\n /** Solid brand color (hex) — bubbles, dots, header chips. */\n color: string\n /** Soft tinted background classes for badges. */\n badge: string\n}\n\nexport const CHANNEL_ACCENT: Record<Channel, ChannelAccent> = {\n whatsapp: { color: '#22c55e', badge: 'bg-[#22c55e]/12 text-[#15803d] dark:text-[#4ade80]' },\n sms: { color: '#6366f1', badge: 'bg-[#6366f1]/12 text-[#4338ca] dark:text-[#a5b4fc]' },\n instagram: { color: '#ec4899', badge: 'bg-[#ec4899]/12 text-[#be185d] dark:text-[#f9a8d4]' },\n email: { color: '#0ea5e9', badge: 'bg-[#0ea5e9]/12 text-[#0369a1] dark:text-[#7dd3fc]' },\n webchat: { color: '#f59e0b', badge: 'bg-[#f59e0b]/12 text-[#b45309] dark:text-[#fcd34d]' },\n}\n\nexport { CHANNEL_LABELS }\n","import React from 'react'\nimport { cn } from '@fayz-ai/ui'\nimport { CHANNEL_ACCENT, CHANNEL_ICON, CHANNEL_LABELS } from '../channel'\nimport type { Channel } from '../types'\n\n// ---------------------------------------------------------------------------\n// Small presentational helpers shared across the inbox panes.\n// ---------------------------------------------------------------------------\n\n/** Reactive media-query match — drives the responsive list/thread/panel layout. */\nexport function useMediaQuery(query: string): boolean {\n const [matches, setMatches] = React.useState(\n () => typeof window !== 'undefined' && window.matchMedia(query).matches,\n )\n React.useEffect(() => {\n if (typeof window === 'undefined') return\n const mql = window.matchMedia(query)\n const onChange = () => setMatches(mql.matches)\n onChange()\n mql.addEventListener('change', onChange)\n return () => mql.removeEventListener('change', onChange)\n }, [query])\n return matches\n}\n\nexport function initialsOf(name: string): string {\n return name.replace('@', '').split(/\\s+/).filter(Boolean).map((w) => w[0]).slice(0, 2).join('').toUpperCase()\n}\n\nexport function Avatar({ name, accent, size = 'md', channel }: {\n name: string\n accent: string\n size?: 'sm' | 'md' | 'lg'\n /** When set, renders a small channel glyph badge over the avatar. */\n channel?: Channel\n}) {\n const dims = size === 'lg' ? 'h-14 w-14 text-lg' : size === 'sm' ? 'h-9 w-9 text-xs' : 'h-10 w-10 text-sm'\n const Icon = channel ? CHANNEL_ICON[channel] : null\n return (\n <div className=\"relative shrink-0\">\n <div\n className={cn('flex items-center justify-center rounded-full font-semibold text-white', dims)}\n style={{ backgroundColor: accent }}\n >\n {initialsOf(name)}\n </div>\n {Icon && (\n <span\n className=\"absolute -bottom-0.5 -right-0.5 flex h-4 w-4 items-center justify-center rounded-full ring-2 ring-card\"\n style={{ backgroundColor: CHANNEL_ACCENT[channel!].color }}\n >\n <Icon className=\"h-2.5 w-2.5 text-white\" />\n </span>\n )}\n </div>\n )\n}\n\nexport function ChannelBadge({ channel, className }: { channel: Channel; className?: string }) {\n const Icon = CHANNEL_ICON[channel]\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-[10px] font-medium',\n CHANNEL_ACCENT[channel].badge,\n className,\n )}\n >\n <Icon className=\"h-2.5 w-2.5\" />\n {CHANNEL_LABELS[channel]}\n </span>\n )\n}\n\nexport function relativeTime(iso: string): string {\n const diff = Date.now() - new Date(iso).getTime()\n const mins = Math.round(diff / 60_000)\n if (mins < 1) return 'now'\n if (mins < 60) return `${mins}m`\n const hours = Math.round(mins / 60)\n if (hours < 24) return `${hours}h`\n const days = Math.round(hours / 24)\n if (days < 7) return `${days}d`\n return `${Math.round(days / 7)}w`\n}\n\n/** Day label for the thread date separators. */\nexport function dayLabel(iso: string): string {\n const d = new Date(iso)\n const now = new Date()\n const startOf = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime()\n const dayDiff = Math.round((startOf(now) - startOf(d)) / 86_400_000)\n if (dayDiff <= 0) return 'Today'\n if (dayDiff === 1) return 'Yesterday'\n if (dayDiff < 7) return d.toLocaleDateString([], { weekday: 'long' })\n return d.toLocaleDateString([], { month: 'short', day: 'numeric', year: now.getFullYear() === d.getFullYear() ? undefined : 'numeric' })\n}\n","import React from 'react'\nimport { Button, Modal, ModalContent, cn, toast } from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport { useLimitGuard, invalidateLimit, ContactPicker, type ContactPickerValue } from '@fayz-ai/saas'\nimport { useConversationsStore, useConversationsConfig } from '../ConversationsContext'\nimport { CHANNEL_ACCENT, CHANNEL_ICON, CHANNEL_LABELS } from '../channel'\nimport type { Channel } from '../types'\n\nconst CHANNELS: Channel[] = ['whatsapp', 'sms', 'instagram', 'email', 'webchat']\n\n/**\n * Which field of a person IS the handle on a given channel. Phone channels read\n * the phone, email reads the email; Instagram and web chat have no counterpart\n * on a person record, so they always have to be typed. Deliberately NOT\n * cross-filling (an email in a WhatsApp handle looked plausible on screen and\n * was simply wrong).\n */\nfunction personHandleFor(channel: Channel, contact: ContactPickerValue | null): string {\n if (!contact) return ''\n if (channel === 'email') return contact.email ?? ''\n if (channel === 'sms' || channel === 'whatsapp') return contact.phone ?? ''\n return ''\n}\n\nconst HANDLE_LABEL_KEY: Record<Channel, string> = {\n whatsapp: 'conversations.new.handleLabel.phone',\n sms: 'conversations.new.handleLabel.phone',\n email: 'conversations.new.handleLabel.email',\n instagram: 'conversations.new.handleLabel.instagram',\n webchat: 'conversations.new.handleLabel.webchat',\n}\n\nexport function NewConversationModal({\n open,\n onOpenChange,\n}: {\n open: boolean\n onOpenChange: (open: boolean) => void\n}) {\n const t = useTranslation()\n const create = useConversationsStore((s) => s.create)\n const config = useConversationsConfig()\n const guardConversations = useLimitGuard('conversations_month')\n\n const [channel, setChannel] = React.useState<Channel>('whatsapp')\n const [contact, setContact] = React.useState<ContactPickerValue | null>(null)\n // Handle the user typed themselves. The one taken FROM the contact is derived\n // (see personHandleFor) and shown on the picker's chip — same as the agenda,\n // which never had a second phone field.\n const [typedHandle, setTypedHandle] = React.useState('')\n // While the picker's inline create form is open it already asks for phone and\n // email, so showing our own handle field would ask for the phone twice.\n const [creatingContact, setCreatingContact] = React.useState(false)\n const [firstMessage, setFirstMessage] = React.useState('')\n const [submitting, setSubmitting] = React.useState(false)\n\n // Reset the form each time the modal opens. `pickerKey` remounts the picker so\n // its internal search text resets too.\n const [pickerKey, setPickerKey] = React.useState(0)\n React.useEffect(() => {\n if (open) {\n setChannel('whatsapp')\n setContact(null)\n setTypedHandle('')\n setCreatingContact(false)\n setFirstMessage('')\n setSubmitting(false)\n setPickerKey((k) => k + 1)\n }\n }, [open])\n\n // What we'd message on this channel: the contact's own datum when they have\n // one, otherwise whatever the user typed. Recomputed on every channel switch,\n // so flipping WhatsApp → Email swaps phone for email with no stale state.\n const derivedHandle = personHandleFor(channel, contact)\n const effectiveHandle = derivedHandle || typedHandle\n const handleLabel = t(HANDLE_LABEL_KEY[channel])\n\n const canSubmit = (contact?.name.trim().length ?? 0) > 0 && !submitting\n\n async function handleSubmit(e: React.FormEvent) {\n e.preventDefault()\n if (!canSubmit) return\n setSubmitting(true)\n try {\n // Plan quantity guard (client-side, before the store call): opens the\n // global UpgradeModal and aborts when the monthly cap is reached. Inside\n // the try on purpose — it hits the network to count usage, and a rejection\n // out here used to escape unhandled, leaving the modal open with no\n // feedback at all (indistinguishable from a dead button).\n if ((await guardConversations()) === 'blocked') return\n await create({\n channel,\n contactName: contact!.name.trim(),\n contactPersonId: contact?.id,\n contactHandle: effectiveHandle.trim() || undefined,\n firstMessage: firstMessage.trim() || undefined,\n })\n invalidateLimit('conversations_month')\n onOpenChange(false)\n } catch (err) {\n // A failed insert (unresolved tenant, RLS rejection, offline…) previously\n // threw past the `finally` — `onOpenChange(false)` never ran, so the modal\n // stayed open with no feedback and the thread silently vanished. Surface\n // the failure and keep the form open so the user can retry.\n const message = err instanceof Error ? err.message : String(err)\n toast.error(t('conversations.new.createFailed'), { description: message })\n } finally {\n setSubmitting(false)\n }\n }\n\n return (\n <Modal open={open} onOpenChange={onOpenChange}>\n <ModalContent size=\"md\">\n <form onSubmit={handleSubmit} className=\"flex flex-col gap-4\">\n <h2 className=\"text-base font-semibold text-foreground\">{t('conversations.new.title')}</h2>\n\n {/* Channel picker */}\n <div>\n <label className=\"mb-1.5 block text-xs font-medium text-muted-foreground\">\n {t('conversations.new.channel')}\n </label>\n <div className=\"flex flex-wrap gap-1.5\">\n {CHANNELS.map((ch) => {\n const Icon = CHANNEL_ICON[ch]\n const active = channel === ch\n return (\n <button\n key={ch}\n type=\"button\"\n onClick={() => setChannel(ch)}\n aria-pressed={active}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-xs font-medium transition-colors',\n active\n ? 'text-white'\n : 'bg-muted text-muted-foreground hover:bg-muted/70',\n )}\n style={active ? { backgroundColor: CHANNEL_ACCENT[ch].color } : undefined}\n >\n <Icon className=\"h-3 w-3\" />\n {CHANNEL_LABELS[ch]}\n </button>\n )\n })}\n </div>\n </div>\n\n {/* Contact — shared find-or-create flow (@fayz-ai/saas), the same one\n the agenda uses to pick a client. The picker owns its label, the\n search field, the chip and the channel handle, so this composer and\n the appointment modal render the SAME thing from the same code. */}\n <ContactPicker\n key={pickerKey}\n value={contact}\n onChange={setContact}\n kind={config.contactKind}\n extensionTable={config.contactExtensionTable}\n lookup={config.contactLookup}\n allowFreeText\n onCreatingChange={setCreatingContact}\n autoFocus\n label={t('conversations.new.contactName')}\n placeholder={t('conversations.new.contactNamePlaceholder')}\n secondaryText={derivedHandle || undefined}\n handleField={{\n label: handleLabel,\n derived: derivedHandle || undefined,\n value: typedHandle,\n onChange: setTypedHandle,\n fieldLabel: t('conversations.new.handle'),\n placeholder: t('conversations.new.handlePlaceholder'),\n }}\n />\n\n {/* First message */}\n <div>\n <label htmlFor=\"conv-first-message\" className=\"mb-1.5 block text-xs font-medium text-muted-foreground\">\n {t('conversations.new.firstMessage')}\n </label>\n <textarea\n id=\"conv-first-message\"\n value={firstMessage}\n onChange={(e) => setFirstMessage(e.target.value)}\n rows={3}\n placeholder={t('conversations.new.firstMessagePlaceholder')}\n className=\"max-h-40 min-h-[64px] w-full resize-none rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground outline-none focus:border-primary\"\n />\n </div>\n\n <div className=\"mt-1 flex justify-end gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)}>\n {t('conversations.new.cancel')}\n </Button>\n <Button type=\"submit\" disabled={!canSubmit}>\n {submitting ? t('conversations.new.creating') : t('conversations.new.create')}\n </Button>\n </div>\n </form>\n </ModalContent>\n </Modal>\n )\n}\n","import React from 'react'\nimport { Search, Inbox as InboxIcon, Plus } from 'lucide-react'\nimport { Button, Input, Skeleton, cn } from '@fayz-ai/ui'\nimport { PermissionGate } from '@fayz-ai/saas'\nimport { useTranslation } from '@fayz-ai/core'\nimport { useConversationsStore } from '../ConversationsContext'\nimport type { Channel } from '../types'\nimport { Avatar, ChannelBadge, relativeTime } from './shared'\nimport { NewConversationModal } from './NewConversationModal'\n\nconst FILTERS: Array<Channel | 'all'> = ['all', 'whatsapp', 'sms', 'instagram', 'email', 'webchat']\n\nexport function ConversationList({ className }: { className?: string }) {\n const t = useTranslation()\n const {\n conversations, selectedId, channelFilter, search, loading,\n select, setChannelFilter, setSearch,\n } = useConversationsStore((s) => s)\n const [newOpen, setNewOpen] = React.useState(false)\n\n return (\n <aside className={cn('w-full shrink-0 flex-col border-r border-border bg-card lg:w-[320px]', className)}>\n <div className=\"border-b border-border px-3 py-3\">\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <span className=\"text-sm font-semibold text-foreground\">{t('conversations.title')}</span>\n <PermissionGate feature=\"conversations\" action=\"create\">\n <Button\n size=\"sm\"\n onClick={() => setNewOpen(true)}\n aria-label={t('conversations.list.new')}\n data-testid=\"conversations-new\"\n >\n <Plus className=\"h-3.5 w-3.5 sm:mr-1\" />\n <span className=\"hidden sm:inline\">{t('conversations.list.new')}</span>\n </Button>\n </PermissionGate>\n </div>\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\" />\n <Input\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder={t('conversations.list.search')}\n className=\"pl-8\"\n />\n </div>\n <div className=\"mt-2 flex flex-wrap gap-1\">\n {FILTERS.map((id) => (\n <button\n key={id}\n onClick={() => setChannelFilter(id)}\n className={cn(\n 'rounded-full px-2.5 py-1 text-xs font-medium transition-colors',\n channelFilter === id\n ? 'bg-primary text-primary-foreground'\n : 'bg-muted text-muted-foreground hover:bg-muted/70',\n )}\n >\n {t(`conversations.filter.${id}`)}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto\">\n {loading && conversations.length === 0 &&\n Array.from({ length: 6 }, (_, i) => (\n <div key={i} className=\"flex w-full items-start gap-3 border-b border-border/50 px-3 py-3\">\n <Skeleton className=\"h-10 w-10 shrink-0 rounded-full\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <Skeleton className=\"h-4 w-28\" />\n <Skeleton className=\"h-3 w-8\" />\n </div>\n <Skeleton className=\"mt-1.5 h-4 w-16 rounded-full\" />\n <Skeleton className=\"mt-1.5 h-3 w-3/4\" />\n </div>\n </div>\n ))}\n {!loading && conversations.length === 0 && (\n <div className=\"flex flex-col items-center gap-2 p-8 text-center text-muted-foreground\">\n <InboxIcon className=\"h-6 w-6\" />\n <p className=\"text-sm\">{t('conversations.list.empty')}</p>\n </div>\n )}\n {conversations.map((c) => {\n const active = c.id === selectedId\n const unread = c.unreadCount > 0\n return (\n <button\n key={c.id}\n onClick={() => select(c.id)}\n className={cn(\n 'flex w-full items-start gap-3 border-b border-border/50 px-3 py-3 text-left transition-colors',\n active ? 'bg-accent' : 'hover:bg-muted/50',\n )}\n >\n <Avatar name={c.contactName} accent={c.accent} channel={c.channel} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className={cn('truncate text-sm text-foreground', unread ? 'font-semibold' : 'font-medium')}>\n {c.contactName}\n </span>\n <span className={cn('shrink-0 text-[11px]', unread ? 'font-semibold text-primary' : 'text-muted-foreground')}>\n {relativeTime(c.lastMessageAt)}\n </span>\n </div>\n <div className=\"mt-1 flex items-center gap-2\">\n <ChannelBadge channel={c.channel} />\n {c.status !== 'open' && (\n <span className=\"text-[10px] uppercase tracking-wide text-muted-foreground/70\">\n {t(`conversations.status.${c.status}`)}\n </span>\n )}\n </div>\n <div className=\"mt-1 flex items-center justify-between gap-2\">\n <span className={cn('truncate text-xs', unread ? 'text-foreground' : 'text-muted-foreground')}>\n {c.lastMessagePreview}\n </span>\n {unread && (\n <span className=\"flex h-[18px] min-w-[18px] shrink-0 items-center justify-center rounded-full bg-primary px-1.5 text-[10px] font-semibold text-primary-foreground\">\n {c.unreadCount}\n </span>\n )}\n </div>\n </div>\n </button>\n )\n })}\n </div>\n\n <NewConversationModal open={newOpen} onOpenChange={setNewOpen} />\n </aside>\n )\n}\n","import React from 'react'\nimport { Send, Clock, Archive, PanelRight, MessageSquare, ChevronLeft } from 'lucide-react'\nimport { Button, cn } from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport { useConversationsStore } from '../ConversationsContext'\nimport { CHANNEL_ACCENT, CHANNEL_LABELS } from '../channel'\nimport type { Conversation, Message } from '../types'\nimport { Avatar, ChannelBadge, dayLabel } from './shared'\n\n// Build a flat render list: day-separator rows interleaved with messages, and\n// each message flagged as the start of a new sender-run (WhatsApp grouping).\ntype Row =\n | { kind: 'day'; id: string; label: string }\n | { kind: 'msg'; id: string; message: Message; startsRun: boolean; endsRun: boolean }\n\nfunction buildRows(messages: Message[]): Row[] {\n const rows: Row[] = []\n let lastDay = ''\n messages.forEach((m, i) => {\n const day = new Date(m.at).toDateString()\n if (day !== lastDay) {\n rows.push({ kind: 'day', id: `day-${day}`, label: dayLabel(m.at) })\n lastDay = day\n }\n const prev = messages[i - 1]\n const next = messages[i + 1]\n const samePrev = prev && prev.direction === m.direction && new Date(prev.at).toDateString() === day\n const sameNext = next && next.direction === m.direction && new Date(next.at).toDateString() === day\n rows.push({ kind: 'msg', id: m.id, message: m, startsRun: !samePrev, endsRun: !sameNext })\n })\n return rows\n}\n\nexport function MessageThread({ selected, onTogglePanel, panelOpen, onBack, className }: {\n selected: Conversation\n onTogglePanel: () => void\n panelOpen: boolean\n onBack?: () => void\n className?: string\n}) {\n const t = useTranslation()\n const { messages, sending, send, setStatus } = useConversationsStore((s) => s)\n const [draft, setDraft] = React.useState('')\n const threadRef = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n threadRef.current?.scrollTo({ top: threadRef.current.scrollHeight, behavior: 'smooth' })\n }, [messages.length, selected.id])\n\n async function handleSend() {\n if (!draft.trim()) return\n const body = draft\n setDraft('')\n await send(body)\n }\n\n const accent = CHANNEL_ACCENT[selected.channel]\n const rows = React.useMemo(() => buildRows(messages), [messages])\n\n return (\n <section className={cn('flex min-w-0 flex-1 flex-col bg-muted/20', className)}>\n {/* Header */}\n <div className=\"flex items-center justify-between gap-2 border-b border-border bg-card px-3 py-2.5 md:px-5\">\n <div className=\"flex min-w-0 items-center gap-2 md:gap-3\">\n {onBack && (\n <Button variant=\"ghost\" size=\"icon\" className=\"-ml-1 shrink-0 lg:hidden\" onClick={onBack} aria-label={t('conversations.thread.back')}>\n <ChevronLeft className=\"h-5 w-5\" />\n </Button>\n )}\n <Avatar name={selected.contactName} accent={selected.accent} size=\"sm\" channel={selected.channel} />\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-semibold text-foreground\">{selected.contactName}</p>\n <p className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <ChannelBadge channel={selected.channel} />\n <span className=\"truncate\">{selected.contactHandle}</span>\n </p>\n </div>\n </div>\n <div className=\"flex shrink-0 items-center gap-1.5\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => setStatus('snoozed')} aria-label={t('conversations.thread.snooze')}>\n <Clock className=\"h-3.5 w-3.5 sm:mr-1\" /> <span className=\"hidden sm:inline\">{t('conversations.thread.snooze')}</span>\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setStatus('closed')} aria-label={t('conversations.thread.close')}>\n <Archive className=\"h-3.5 w-3.5 sm:mr-1\" /> <span className=\"hidden sm:inline\">{t('conversations.thread.close')}</span>\n </Button>\n <Button\n variant={panelOpen ? 'secondary' : 'ghost'}\n size=\"icon\"\n onClick={onTogglePanel}\n aria-label={t('conversations.thread.details')}\n >\n <PanelRight className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n\n {/* Messages */}\n <div ref={threadRef} className=\"min-h-0 flex-1 overflow-y-auto px-5 py-4\">\n {rows.map((row) => {\n if (row.kind === 'day') {\n return (\n <div key={row.id} className=\"my-3 flex items-center justify-center\">\n <span className=\"rounded-full bg-muted px-3 py-0.5 text-[11px] font-medium text-muted-foreground\">\n {row.label}\n </span>\n </div>\n )\n }\n const m = row.message\n const outbound = m.direction === 'outbound'\n return (\n <div\n key={row.id}\n className={cn('flex', outbound ? 'justify-end' : 'justify-start', row.startsRun ? 'mt-2.5' : 'mt-0.5')}\n >\n <div\n className={cn(\n 'max-w-[68%] px-3.5 py-2 text-sm shadow-sm',\n outbound ? 'rounded-2xl text-white' : 'rounded-2xl bg-card text-foreground',\n // Tail only on the last bubble of a run, on the sender's side.\n outbound && row.endsRun && 'rounded-br-sm',\n !outbound && row.endsRun && 'rounded-bl-sm',\n )}\n style={outbound ? { backgroundColor: accent.color } : undefined}\n >\n <p className=\"whitespace-pre-wrap break-words\">{m.body}</p>\n <div className={cn('mt-0.5 text-right text-[10px]', outbound ? 'text-white/70' : 'text-muted-foreground')}>\n {new Date(m.at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}\n </div>\n </div>\n </div>\n )\n })}\n {rows.length === 0 && (\n <div className=\"flex h-full flex-col items-center justify-center text-muted-foreground\">\n <MessageSquare className=\"h-7 w-7\" />\n <p className=\"mt-2 text-sm\">{t('conversations.thread.empty')}</p>\n </div>\n )}\n </div>\n\n {/* Composer */}\n {/* TODO(follow-up): wire real emoji picker + attachment upload (removed the\n dead placeholder buttons rather than shipping non-functional UI). */}\n <div className=\"border-t border-border bg-card px-4 py-3\">\n <div className=\"flex items-end gap-2\">\n <textarea\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n void handleSend()\n }\n }}\n rows={1}\n placeholder={t('conversations.thread.reply', { channel: CHANNEL_LABELS[selected.channel] })}\n className=\"max-h-32 min-h-[40px] flex-1 resize-none rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground outline-none focus:border-primary\"\n />\n <Button onClick={() => void handleSend()} disabled={sending || !draft.trim()} aria-label={t('conversations.thread.send')}>\n <Send className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n </section>\n )\n}\n","import React from 'react'\nimport { MapPin, User, Tag, Link2, StickyNote, X } from 'lucide-react'\nimport { Button, cn } from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport { CHANNEL_LABELS } from '../channel'\nimport type { Conversation } from '../types'\nimport { Avatar, ChannelBadge } from './shared'\n\nfunction Section({ icon: Icon, title, children }: {\n icon: React.ComponentType<{ className?: string }>\n title: string\n children: React.ReactNode\n}) {\n return (\n <div className=\"border-t border-border px-4 py-3\">\n <p className=\"mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n <Icon className=\"h-3 w-3\" /> {title}\n </p>\n {children}\n </div>\n )\n}\n\nexport function ContactPanel({ contact, onClose, className }: {\n contact: Conversation\n onClose?: () => void\n className?: string\n}) {\n const t = useTranslation()\n return (\n <aside className={cn('flex shrink-0 flex-col overflow-y-auto border-l border-border bg-card', className)}>\n {onClose && (\n <div className=\"flex items-center justify-between border-b border-border px-3 py-2 xl:hidden\">\n <span className=\"text-sm font-semibold text-foreground\">{t('conversations.contact.details')}</span>\n <Button variant=\"ghost\" size=\"icon\" onClick={onClose} aria-label={t('conversations.contact.closeDetails')}>\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n )}\n <div className=\"flex flex-col items-center gap-2 px-4 py-5 text-center\">\n <Avatar name={contact.contactName} accent={contact.accent} size=\"lg\" channel={contact.channel} />\n <div>\n <p className=\"text-sm font-semibold text-foreground\">{contact.contactName}</p>\n <p className=\"text-xs text-muted-foreground\">{contact.contactHandle}</p>\n </div>\n <ChannelBadge channel={contact.channel} />\n </div>\n\n <Section icon={User} title={t('conversations.contact.details')}>\n <dl className=\"space-y-1.5 text-sm\">\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-muted-foreground\">{t('conversations.contact.channel')}</dt>\n <dd className=\"text-foreground\">{CHANNEL_LABELS[contact.channel]}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-muted-foreground\">{t('conversations.contact.status')}</dt>\n <dd className=\"text-foreground\">{t(`conversations.status.${contact.status}`)}</dd>\n </div>\n {contact.assignedTo && (\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-muted-foreground\">{t('conversations.contact.assignedTo')}</dt>\n <dd className=\"text-foreground\">{contact.assignedTo}</dd>\n </div>\n )}\n {contact.location && (\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"flex items-center gap-1 text-muted-foreground\"><MapPin className=\"h-3 w-3\" /> {t('conversations.contact.location')}</dt>\n <dd className=\"text-foreground\">{contact.location}</dd>\n </div>\n )}\n </dl>\n </Section>\n\n {contact.tags.length > 0 && (\n <Section icon={Tag} title={t('conversations.contact.tags')}>\n <div className=\"flex flex-wrap gap-1.5\">\n {contact.tags.map((tag) => (\n <span key={tag} className=\"rounded-full bg-muted px-2 py-0.5 text-xs font-medium text-foreground\">\n {tag}\n </span>\n ))}\n </div>\n </Section>\n )}\n\n {contact.note && (\n <Section icon={StickyNote} title={t('conversations.contact.note')}>\n <p className=\"text-sm text-foreground\">{contact.note}</p>\n </Section>\n )}\n\n <Section icon={Link2} title={t('conversations.contact.linkedRecords')}>\n <p className=\"text-xs text-muted-foreground\">{t('conversations.contact.noLinkedRecords')}</p>\n </Section>\n </aside>\n )\n}\n","import React from 'react'\nimport { MessageSquare } from 'lucide-react'\nimport { cn } from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport { useConversationsStore } from '../ConversationsContext'\nimport { ConversationList } from './ConversationList'\nimport { MessageThread } from './MessageThread'\nimport { ContactPanel } from './ContactPanel'\nimport { useMediaQuery } from './shared'\n\nexport function InboxView() {\n const t = useTranslation()\n const { conversations, selectedId, deselect } = useConversationsStore((s) => s)\n // xl+ shows the contact panel inline (three panes); below that it's an\n // on-demand slide-over so the list + thread keep room to breathe.\n const isWidePanel = useMediaQuery('(min-width: 1280px)')\n const [panelOpen, setPanelOpen] = React.useState(false)\n const selected = conversations.find((c) => c.id === selectedId) ?? null\n\n // Open the panel by default only when it fits inline; collapse it otherwise.\n React.useEffect(() => {\n setPanelOpen(isWidePanel)\n }, [isWidePanel])\n\n return (\n <div className=\"relative flex h-full min-h-0 overflow-hidden bg-background\">\n {/* Conversation list — single-pane below lg (full width), fixed rail at lg+.\n Below lg it yields to the thread once a conversation is open. */}\n <ConversationList className={cn(selected ? 'hidden lg:flex' : 'flex')} />\n\n {/* Thread — hidden below lg until a conversation is selected. */}\n {selected ? (\n <MessageThread\n selected={selected}\n panelOpen={panelOpen}\n onTogglePanel={() => setPanelOpen((v) => !v)}\n onBack={deselect}\n className=\"flex\"\n />\n ) : (\n <section className=\"hidden min-w-0 flex-1 flex-col items-center justify-center bg-muted/20 text-muted-foreground lg:flex\">\n <MessageSquare className=\"h-9 w-9\" />\n <p className=\"mt-2 text-sm\">{t('conversations.empty.select')}</p>\n </section>\n )}\n\n {/* Contact panel — inline column at xl, slide-over overlay below xl. */}\n {selected && panelOpen && (\n <>\n <button\n className=\"absolute inset-0 z-10 bg-black/40 xl:hidden\"\n aria-label=\"Close details\"\n onClick={() => setPanelOpen(false)}\n />\n <ContactPanel\n contact={selected}\n onClose={() => setPanelOpen(false)}\n className=\"absolute inset-y-0 right-0 z-20 w-[340px] max-w-[88%] shadow-2xl xl:static xl:z-auto xl:w-[300px] xl:max-w-none xl:shadow-none\"\n />\n </>\n )}\n </div>\n )\n}\n","import React from 'react'\nimport type { StoreApi } from 'zustand/vanilla'\nimport { ConversationsContextProvider, type ResolvedConversationsConfig } from './ConversationsContext'\nimport type { ConversationsUIState } from './store'\nimport { InboxView } from './views/InboxView'\n\nexport function ConversationsPage({ store, config }: {\n store: StoreApi<ConversationsUIState>\n config?: ResolvedConversationsConfig\n}) {\n React.useEffect(() => {\n void store.getState().load()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n return (\n <ConversationsContextProvider store={store} config={config}>\n <InboxView />\n </ConversationsContextProvider>\n )\n}\n","import type { Channel } from '../types'\n\n// Solid brand hex per channel — mirrors CHANNEL_ACCENT in ../channel.ts but\n// React-free so the data providers can stamp a sensible avatar accent on new\n// conversations without importing the icon layer.\nexport const CHANNEL_ACCENT_HEX: Record<Channel, string> = {\n whatsapp: '#22c55e',\n sms: '#6366f1',\n instagram: '#ec4899',\n email: '#0ea5e9',\n webchat: '#f59e0b',\n}\n","import type { ConversationsProvider } from './types'\nimport { CHANNEL_ACCENT_HEX } from './accents'\nimport type {\n Conversation,\n Message,\n ListConversationsQuery,\n SendMessageInput,\n CreateConversationInput,\n ConversationStatus,\n} from '../types'\n\n// Deterministic relative timestamps (no Date.now at module init for stable seeds).\nfunction minutesAgo(base: number, mins: number): string {\n return new Date(base - mins * 60_000).toISOString()\n}\n\nfunction seed(): { conversations: Conversation[]; messages: Message[] } {\n const base = new Date('2026-06-16T14:00:00Z').getTime()\n\n const conversations: Conversation[] = [\n {\n id: 'c1', contactName: 'Marina Alves', contactHandle: '+55 11 99876-1020', channel: 'whatsapp',\n lastMessagePreview: 'Perfect, can we book for Friday at 3pm?', lastMessageAt: minutesAgo(base, 4),\n unreadCount: 2, status: 'open', assignedTo: 'You', accent: '#22c55e', tags: ['Hot lead'],\n location: 'São Paulo, BR', note: 'Referred by Instagram ad — interested in full color + cut.',\n },\n {\n id: 'c2', contactName: 'Jordan Pierce', contactHandle: '+1 (415) 555-0142', channel: 'sms',\n lastMessagePreview: 'Got it — sending the deposit now.', lastMessageAt: minutesAgo(base, 22),\n unreadCount: 0, status: 'open', assignedTo: 'You', accent: '#6366f1', tags: ['Customer'],\n location: 'San Francisco, US',\n },\n {\n id: 'c3', contactName: '@thehairloft', contactHandle: 'thehairloft', channel: 'instagram',\n lastMessagePreview: 'Do you offer balayage on weekends?', lastMessageAt: minutesAgo(base, 51),\n unreadCount: 1, status: 'open', accent: '#ec4899', tags: ['New'],\n },\n {\n id: 'c4', contactName: 'David Whitman', contactHandle: 'david@whitman.co', channel: 'email',\n lastMessagePreview: 'Re: Proposal — looks great, one question on pricing…', lastMessageAt: minutesAgo(base, 95),\n unreadCount: 0, status: 'open', assignedTo: 'Sofia', accent: '#0ea5e9', tags: ['Proposal'],\n location: 'Austin, US', note: 'Evaluating the retainer tier. Decision expected this week.',\n },\n {\n id: 'c5', contactName: 'Website visitor', contactHandle: 'live chat · acme.com', channel: 'webchat',\n lastMessagePreview: 'Is anyone available to chat?', lastMessageAt: minutesAgo(base, 140),\n unreadCount: 0, status: 'snoozed', accent: '#f59e0b', tags: [],\n },\n {\n id: 'c6', contactName: 'Priya Nair', contactHandle: '+44 7700 900123', channel: 'whatsapp',\n lastMessagePreview: 'Thank you! See you next week 🙌', lastMessageAt: minutesAgo(base, 1440),\n unreadCount: 0, status: 'closed', assignedTo: 'You', accent: '#14b8a6', tags: ['Customer'],\n location: 'London, UK',\n },\n ]\n\n const messages: Message[] = [\n msg('m1', 'c1', 'whatsapp', 'inbound', 'Hi! I saw your ad — do you have availability this week?', 'Marina Alves', minutesAgo(base, 18)),\n msg('m2', 'c1', 'whatsapp', 'outbound', 'Hi Marina! Yes, we do. What service are you interested in?', 'You', minutesAgo(base, 15)),\n msg('m3', 'c1', 'whatsapp', 'inbound', 'A full color + cut.', 'Marina Alves', minutesAgo(base, 9)),\n msg('m4', 'c1', 'whatsapp', 'inbound', 'Perfect, can we book for Friday at 3pm?', 'Marina Alves', minutesAgo(base, 4)),\n\n msg('m5', 'c2', 'sms', 'outbound', 'Your appointment is confirmed for tomorrow at 10am.', 'You', minutesAgo(base, 40)),\n msg('m6', 'c2', 'sms', 'inbound', 'Got it — sending the deposit now.', 'Jordan Pierce', minutesAgo(base, 22)),\n\n msg('m7', 'c3', 'instagram', 'inbound', 'Do you offer balayage on weekends?', '@thehairloft', minutesAgo(base, 51)),\n\n msg('m8', 'c4', 'email', 'inbound', 'Re: Proposal — looks great, one question on pricing for the retainer tier.', 'David Whitman', minutesAgo(base, 95)),\n msg('m9', 'c4', 'email', 'outbound', 'Happy to walk you through it — are you free for a quick call tomorrow?', 'Sofia', minutesAgo(base, 80)),\n\n msg('m10', 'c5', 'webchat', 'inbound', 'Is anyone available to chat?', 'Website visitor', minutesAgo(base, 140)),\n\n msg('m11', 'c6', 'whatsapp', 'outbound', 'You are all set for next Tuesday. Anything else?', 'You', minutesAgo(base, 1500)),\n msg('m12', 'c6', 'whatsapp', 'inbound', 'Thank you! See you next week 🙌', 'Priya Nair', minutesAgo(base, 1440)),\n ]\n\n return { conversations, messages }\n}\n\nfunction msg(\n id: string, conversationId: string, channel: Message['channel'],\n direction: Message['direction'], body: string, author: string, at: string,\n): Message {\n return { id, conversationId, channel, direction, body, author, at }\n}\n\nexport interface MockConversationsConfig {\n /** Tenant id (value or getter) used to namespace the localStorage snapshot. */\n tenantId?: string | (() => string | undefined)\n /** Display name stamped as the author of outbound messages. */\n selfAuthor?: string\n}\n\ninterface Snapshot {\n conversations: Conversation[]\n messages: Message[]\n counter: number\n}\n\n// ---------------------------------------------------------------------------\n// In-memory mock inbox with best-effort localStorage persistence, so a browser\n// reload keeps whatever the demo created/sent within the session. The store is\n// namespaced per tenant; SSR / no-window environments degrade to pure memory.\n// ---------------------------------------------------------------------------\nexport function createMockConversationsProvider(\n config?: MockConversationsConfig,\n): ConversationsProvider {\n const selfAuthor = config?.selfAuthor ?? 'You'\n\n function resolveTenant(): string {\n const raw = typeof config?.tenantId === 'function' ? config.tenantId() : config?.tenantId\n return raw || 'default'\n }\n\n const storageKey = () => `saas:mock:conversations:${resolveTenant()}`\n\n function hasStorage(): boolean {\n try {\n return typeof window !== 'undefined' && !!window.localStorage\n } catch {\n return false\n }\n }\n\n function load(): Snapshot {\n if (hasStorage()) {\n try {\n const raw = window.localStorage.getItem(storageKey())\n if (raw) {\n const parsed = JSON.parse(raw) as Snapshot\n if (Array.isArray(parsed.conversations) && Array.isArray(parsed.messages)) {\n return {\n conversations: parsed.conversations,\n messages: parsed.messages,\n counter: parsed.counter ?? 100,\n }\n }\n }\n } catch {\n // Corrupt snapshot — fall through to a fresh seed.\n }\n }\n const seeded = seed()\n return { conversations: seeded.conversations, messages: seeded.messages, counter: 100 }\n }\n\n const state = load()\n\n function persist(): void {\n if (!hasStorage()) return\n try {\n window.localStorage.setItem(\n storageKey(),\n JSON.stringify({\n conversations: state.conversations,\n messages: state.messages,\n counter: state.counter,\n } satisfies Snapshot),\n )\n } catch {\n // Quota / privacy mode — keep working in memory only.\n }\n }\n\n // Persist the initial seed so a first reload is already stable.\n persist()\n\n return {\n async listConversations(query?: ListConversationsQuery): Promise<Conversation[]> {\n let list = [...state.conversations]\n if (query?.channel && query.channel !== 'all') list = list.filter((c) => c.channel === query.channel)\n if (query?.status && query.status !== 'all') list = list.filter((c) => c.status === query.status)\n if (query?.search) {\n const q = query.search.toLowerCase()\n list = list.filter(\n (c) => c.contactName.toLowerCase().includes(q) || c.lastMessagePreview.toLowerCase().includes(q),\n )\n }\n return list.sort((a, b) => b.lastMessageAt.localeCompare(a.lastMessageAt))\n },\n\n async getMessages(conversationId: string): Promise<Message[]> {\n return state.messages\n .filter((m) => m.conversationId === conversationId)\n .sort((a, b) => a.at.localeCompare(b.at))\n },\n\n async createConversation(input: CreateConversationInput): Promise<Conversation> {\n const now = new Date().toISOString()\n const firstMessage = input.firstMessage?.trim()\n const id = `c${++state.counter}`\n const conversation: Conversation = {\n id,\n contactName: input.contactName.trim(),\n contactPersonId: input.contactPersonId,\n contactHandle: input.contactHandle?.trim() ?? '',\n channel: input.channel,\n lastMessagePreview: firstMessage ?? '',\n lastMessageAt: now,\n unreadCount: 0,\n status: 'open',\n assignedTo: selfAuthor,\n accent: CHANNEL_ACCENT_HEX[input.channel],\n tags: [],\n note: input.note?.trim() || undefined,\n }\n state.conversations.unshift(conversation)\n if (firstMessage) {\n state.messages.push({\n id: `m${++state.counter}`,\n conversationId: id,\n channel: input.channel,\n direction: 'outbound',\n body: firstMessage,\n author: selfAuthor,\n at: now,\n })\n }\n persist()\n return conversation\n },\n\n async sendMessage(input: SendMessageInput): Promise<Message> {\n const conv = state.conversations.find((c) => c.id === input.conversationId)\n const created: Message = {\n id: `m${++state.counter}`,\n conversationId: input.conversationId,\n channel: conv?.channel ?? 'sms',\n direction: 'outbound',\n body: input.body,\n author: selfAuthor,\n at: new Date().toISOString(),\n }\n state.messages.push(created)\n if (conv) {\n conv.lastMessagePreview = input.body\n conv.lastMessageAt = created.at\n conv.unreadCount = 0\n if (conv.status === 'closed') conv.status = 'open'\n }\n persist()\n return created\n },\n\n async markRead(conversationId: string): Promise<void> {\n const conv = state.conversations.find((c) => c.id === conversationId)\n if (conv && conv.unreadCount !== 0) {\n conv.unreadCount = 0\n persist()\n }\n },\n\n async setStatus(conversationId: string, status: ConversationStatus): Promise<Conversation> {\n const conv = state.conversations.find((c) => c.id === conversationId)\n if (!conv) throw new Error('Conversation not found')\n conv.status = status\n persist()\n return conv\n },\n }\n}\n","// Physical table names for the conversations plugin (plg_conversations* prefix).\n// Import T and reference T.<key> in the data provider so a rename lands in\n// exactly one place.\nexport const T = {\n conversations: 'plg_conversations',\n messages: 'plg_conversation_messages',\n} as const\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport type { ConversationsProvider } from './types'\nimport { T } from './tables'\nimport { CHANNEL_ACCENT_HEX } from './accents'\nimport type {\n Conversation,\n Message,\n ListConversationsQuery,\n SendMessageInput,\n CreateConversationInput,\n ConversationStatus,\n} from '../types'\n\n// ---------------------------------------------------------------------------\n// Supabase-backed conversations provider — reads/writes the project's\n// `conversations` + `conversation_messages` tables (tenant-scoped via RLS +\n// an explicit tenant filter from the active-org context). Mirrors the inline\n// client-casting style of @fayz-ai/core's createSupabaseProvider; the global\n// client is `unknown`-typed so each call narrows the shape it needs.\n//\n// Real channel connectors (Twilio, WhatsApp Cloud, Meta, IMAP) deliver inbound\n// rows into these tables out-of-band; this provider is the read/compose surface.\n// ---------------------------------------------------------------------------\n\nexport interface SupabaseConversationsConfig {\n /** Supabase client; defaults to the global one registered by createFayzApp. */\n supabaseClient?: unknown\n /** Active tenant id (value or getter) used to scope reads and stamp writes. */\n tenantId?: string | (() => string | undefined)\n /** Display name stamped as the author of outbound messages. */\n selfAuthor?: string\n}\n\ntype Row = Record<string, unknown>\n\nfunction mapConversation(r: Row): Conversation {\n return {\n id: String(r.id),\n contactName: (r.contact_name as string) ?? '',\n contactPersonId: (r.contact_person_id as string | null) ?? undefined,\n contactHandle: (r.contact_handle as string) ?? '',\n channel: (r.channel as Conversation['channel']) ?? 'sms',\n lastMessagePreview: (r.last_message_preview as string) ?? '',\n lastMessageAt: (r.last_message_at as string) ?? '',\n unreadCount: Number(r.unread_count ?? 0),\n status: (r.status as ConversationStatus) ?? 'open',\n assignedTo: (r.assigned_to as string | null) ?? undefined,\n accent: (r.accent as string) ?? '#6366f1',\n tags: (r.tags as string[] | null) ?? [],\n location: (r.location as string | null) ?? undefined,\n note: (r.note as string | null) ?? undefined,\n }\n}\n\nfunction mapMessage(r: Row): Message {\n return {\n id: String(r.id),\n conversationId: String(r.conversation_id),\n channel: (r.channel as Message['channel']) ?? 'sms',\n direction: (r.direction as Message['direction']) ?? 'inbound',\n body: (r.body as string) ?? '',\n at: (r.at as string) ?? '',\n author: (r.author as string) ?? '',\n }\n}\n\nexport function createSupabaseConversationsProvider(\n config?: SupabaseConversationsConfig,\n): ConversationsProvider {\n const selfAuthor = config?.selfAuthor ?? 'You'\n\n function resolveTenantId(): string | undefined {\n if (!config?.tenantId) return undefined\n return typeof config.tenantId === 'function' ? config.tenantId() : config.tenantId\n }\n\n function client(): { from: (t: string) => Row } {\n const supabase = (config?.supabaseClient ?? getSupabaseClientOptional()) as\n | { from: (t: string) => Row }\n | null\n if (!supabase) {\n throw new Error(\n '[plugin-conversations] Supabase client not available. Pass supabaseClient or register the global client via createFayzApp.',\n )\n }\n return supabase\n }\n\n return {\n async listConversations(query?: ListConversationsQuery): Promise<Conversation[]> {\n let q = (client().from(T.conversations) as { select: (s: string) => Row }).select('*')\n\n const tenantId = resolveTenantId()\n if (tenantId) q = (q as { eq: (c: string, v: string) => Row }).eq('tenant_id', tenantId)\n if (query?.channel && query.channel !== 'all') {\n q = (q as { eq: (c: string, v: string) => Row }).eq('channel', query.channel)\n }\n if (query?.status && query.status !== 'all') {\n q = (q as { eq: (c: string, v: string) => Row }).eq('status', query.status)\n }\n if (query?.search) {\n const term = `%${query.search}%`\n q = (q as { or: (c: string) => Row }).or(\n `contact_name.ilike.${term},last_message_preview.ilike.${term}`,\n )\n }\n q = (q as { order: (c: string, o: unknown) => Row }).order('last_message_at', {\n ascending: false,\n })\n\n const { data, error } = (await q) as { data: Row[] | null; error: unknown }\n if (error) throw error\n return (data ?? []).map(mapConversation)\n },\n\n async getMessages(conversationId: string): Promise<Message[]> {\n const selected = (\n client().from(T.messages) as { select: (s: string) => Row }\n ).select('*')\n const filtered = (selected as { eq: (c: string, v: string) => Row }).eq(\n 'conversation_id',\n conversationId,\n )\n const ordered = (filtered as { order: (c: string, o: unknown) => Row }).order('at', {\n ascending: true,\n })\n const { data, error } = (await ordered) as { data: Row[] | null; error: unknown }\n if (error) throw error\n return (data ?? []).map(mapMessage)\n },\n\n async createConversation(input: CreateConversationInput): Promise<Conversation> {\n const tenantId = resolveTenantId()\n // Insert with a null tenant_id fails the plg_conversations RLS WITH CHECK\n // (tenant_id ∈ user_tenant_ids()) with an opaque Postgres error. When the\n // active tenant hasn't resolved yet (bootstrap race), fail fast with an\n // actionable message the compose modal can surface via toast.\n if (!tenantId) {\n throw new Error('[plugin-conversations] Active tenant not resolved — cannot create conversation. Try again in a moment.')\n }\n const now = new Date().toISOString()\n const firstMessage = input.firstMessage?.trim()\n\n const convRow: Row = {\n contact_name: input.contactName.trim(),\n // Only written when the picker resolved a real person — an app that\n // hasn't run migration 002 yet would reject an unknown column, and\n // omitting it keeps the free-text path working there.\n ...(input.contactPersonId ? { contact_person_id: input.contactPersonId } : {}),\n contact_handle: input.contactHandle?.trim() || null,\n channel: input.channel,\n last_message_preview: firstMessage || null,\n last_message_at: now,\n unread_count: 0,\n status: 'open',\n assigned_to: selfAuthor,\n accent: CHANNEL_ACCENT_HEX[input.channel],\n tags: [],\n note: input.note?.trim() || null,\n }\n if (tenantId) convRow.tenant_id = tenantId\n\n const { data: created, error } = (await (\n (client().from(T.conversations) as { insert: (r: Row) => Row }).insert(convRow) as {\n select: () => { single: () => Promise<{ data: Row | null; error: unknown }> }\n }\n )\n .select()\n .single()) as { data: Row | null; error: unknown }\n if (error) throw error\n if (!created) throw new Error('Conversation not created')\n\n // Seed the thread with the first outbound message when provided.\n if (firstMessage) {\n const msgRow: Row = {\n conversation_id: String(created.id),\n channel: input.channel,\n direction: 'outbound',\n body: firstMessage,\n author: selfAuthor,\n at: now,\n }\n if (tenantId) msgRow.tenant_id = tenantId\n await (client().from(T.messages) as { insert: (r: Row) => Promise<unknown> }).insert(msgRow)\n }\n\n return mapConversation(created)\n },\n\n async sendMessage(input: SendMessageInput): Promise<Message> {\n const tenantId = resolveTenantId()\n\n // Resolve the channel from the parent conversation so the message matches.\n const convSelected = (client().from(T.conversations) as { select: (s: string) => Row }).select(\n 'channel',\n )\n const convFiltered = (convSelected as { eq: (c: string, v: string) => Row }).eq(\n 'id',\n input.conversationId,\n )\n const { data: conv } = (await (\n convFiltered as { maybeSingle: () => Promise<{ data: Row | null }> }\n ).maybeSingle()) as { data: Row | null }\n const channel = (conv?.channel as Message['channel']) ?? 'sms'\n\n const at = new Date().toISOString()\n const row: Row = {\n conversation_id: input.conversationId,\n channel,\n direction: 'outbound',\n body: input.body,\n author: selfAuthor,\n at,\n }\n if (tenantId) row.tenant_id = tenantId\n\n const { data: created, error } = (await (\n (client().from(T.messages) as { insert: (r: Row) => Row }).insert(row) as {\n select: () => { single: () => Promise<{ data: Row | null; error: unknown }> }\n }\n )\n .select()\n .single()) as { data: Row | null; error: unknown }\n if (error) throw error\n\n // Roll the parent conversation forward (preview / timestamp / unread / reopen).\n await (\n (client().from(T.conversations) as {\n update: (r: Row) => Row\n }).update({\n last_message_preview: input.body,\n last_message_at: at,\n unread_count: 0,\n status: 'open',\n }) as { eq: (c: string, v: string) => Promise<unknown> }\n ).eq('id', input.conversationId)\n\n return mapMessage(created ?? row)\n },\n\n async markRead(conversationId: string): Promise<void> {\n const { error } = (await (\n (client().from(T.conversations) as { update: (r: Row) => Row }).update({\n unread_count: 0,\n }) as { eq: (c: string, v: string) => Promise<{ error: unknown }> }\n ).eq('id', conversationId)) as { error: unknown }\n if (error) throw error\n },\n\n async setStatus(conversationId: string, status: ConversationStatus): Promise<Conversation> {\n const updated = (client().from(T.conversations) as { update: (r: Row) => Row }).update({\n status,\n })\n const filtered = (updated as { eq: (c: string, v: string) => Row }).eq('id', conversationId)\n const selected = (filtered as { select: () => Row }).select()\n const { data, error } = (await (\n selected as { single: () => Promise<{ data: Row | null; error: unknown }> }\n ).single()) as { data: Row | null; error: unknown }\n if (error) throw error\n if (!data) throw new Error('Conversation not found')\n return mapConversation(data)\n },\n }\n}\n","import { createStore, type StoreApi } from 'zustand/vanilla'\nimport type { ConversationsProvider } from './data/types'\nimport type {\n Conversation,\n Message,\n Channel,\n ConversationStatus,\n CreateConversationInput,\n} from './types'\n\nexport interface ConversationsUIState {\n conversations: Conversation[]\n messages: Message[]\n selectedId: string | null\n channelFilter: Channel | 'all'\n search: string\n loading: boolean\n sending: boolean\n\n load(): Promise<void>\n select(id: string): Promise<void>\n deselect(): void\n setChannelFilter(channel: Channel | 'all'): Promise<void>\n setSearch(search: string): Promise<void>\n create(input: CreateConversationInput): Promise<Conversation>\n send(body: string): Promise<void>\n setStatus(status: ConversationStatus): Promise<void>\n}\n\nexport function createConversationsStore(\n provider: ConversationsProvider,\n): StoreApi<ConversationsUIState> {\n return createStore<ConversationsUIState>((set, get) => ({\n conversations: [],\n messages: [],\n selectedId: null,\n channelFilter: 'all',\n search: '',\n loading: false,\n sending: false,\n\n async load() {\n set({ loading: true })\n const conversations = await provider.listConversations({\n channel: get().channelFilter,\n search: get().search || undefined,\n })\n const selectedId = get().selectedId ?? conversations[0]?.id ?? null\n set({ conversations, loading: false, selectedId })\n if (selectedId) await get().select(selectedId)\n },\n\n async select(id: string) {\n set({ selectedId: id })\n const messages = await provider.getMessages(id)\n set({ messages })\n await provider.markRead(id)\n set((s) => ({\n conversations: s.conversations.map((c) => (c.id === id ? { ...c, unreadCount: 0 } : c)),\n }))\n },\n\n deselect() {\n set({ selectedId: null, messages: [] })\n },\n\n async setChannelFilter(channel) {\n set({ channelFilter: channel })\n await get().load()\n },\n\n async setSearch(search) {\n set({ search })\n await get().load()\n },\n\n async create(input) {\n const created = await provider.createConversation(input)\n // The thread EXISTS the moment the insert returns, so resolve on that and\n // show it optimistically. Clear filters that would hide it, prepend it,\n // select it — all local.\n set((s) => ({\n channelFilter: 'all',\n search: '',\n conversations: [created, ...s.conversations.filter((c) => c.id !== created.id)],\n selectedId: created.id,\n }))\n\n // Reconciliation (authoritative list + the thread's messages) runs in the\n // BACKGROUND. It used to be awaited here, which made the caller — the\n // compose modal — hostage to two extra round-trips: on a slow pool the\n // conversation was already in the database while the modal sat open\n // looking broken, inviting a second click and a duplicate thread.\n // Failures are non-fatal: the optimistic row above already renders.\n void (async () => {\n try {\n const conversations = await provider.listConversations({})\n // Read-after-write guard: a refetch that races the insert may not\n // return the new row yet — keep the local one rather than dropping it.\n const merged = conversations.some((c) => c.id === created.id)\n ? conversations\n : [created, ...conversations]\n set({ conversations: merged })\n await get().select(created.id)\n } catch {\n /* optimistic state stands; the next load() reconciles */\n }\n })()\n\n return created\n },\n\n async send(body: string) {\n const id = get().selectedId\n if (!id || !body.trim()) return\n set({ sending: true })\n const created = await provider.sendMessage({ conversationId: id, body: body.trim() })\n set((s) => ({\n sending: false,\n messages: [...s.messages, created],\n conversations: s.conversations.map((c) =>\n c.id === id ? { ...c, lastMessagePreview: created.body, lastMessageAt: created.at } : c,\n ),\n }))\n },\n\n async setStatus(status) {\n const id = get().selectedId\n if (!id) return\n const updated = await provider.setStatus(id, status)\n set((s) => ({\n conversations: s.conversations.map((c) => (c.id === id ? updated : c)),\n }))\n },\n }))\n}\n","export const en: Record<string, string> = {\n 'conversations.title': 'Conversations',\n 'conversations.subtitle': 'Unified inbox across every channel',\n\n // Conversation list\n 'conversations.list.search': 'Search conversations',\n 'conversations.list.loading': 'Loading…',\n 'conversations.list.empty': 'No conversations',\n 'conversations.list.new': 'New conversation',\n\n // Channel filters\n 'conversations.filter.all': 'All',\n 'conversations.filter.whatsapp': 'WhatsApp',\n 'conversations.filter.sms': 'SMS',\n 'conversations.filter.instagram': 'Instagram',\n 'conversations.filter.email': 'Email',\n 'conversations.filter.webchat': 'Web',\n\n // Status labels\n 'conversations.status.open': 'Open',\n 'conversations.status.snoozed': 'Snoozed',\n 'conversations.status.closed': 'Closed',\n\n // Empty state\n 'conversations.empty.select': 'Select a conversation to start chatting',\n\n // Thread\n 'conversations.thread.back': 'Back to conversations',\n 'conversations.thread.snooze': 'Snooze',\n 'conversations.thread.close': 'Close',\n 'conversations.thread.details': 'Toggle contact details',\n 'conversations.thread.empty': 'No messages yet',\n 'conversations.thread.reply': 'Reply via {{channel}}…',\n 'conversations.thread.send': 'Send',\n\n // Contact panel\n 'conversations.contact.details': 'Details',\n 'conversations.contact.closeDetails': 'Close details',\n 'conversations.contact.channel': 'Channel',\n 'conversations.contact.status': 'Status',\n 'conversations.contact.assignedTo': 'Assigned to',\n 'conversations.contact.location': 'Location',\n 'conversations.contact.tags': 'Tags',\n 'conversations.contact.note': 'Note',\n 'conversations.contact.linkedRecords': 'Linked records',\n 'conversations.contact.noLinkedRecords': 'No linked records yet.',\n\n // New-conversation modal\n 'conversations.new.title': 'New conversation',\n 'conversations.new.channel': 'Channel',\n 'conversations.new.contactName': 'Contact name',\n 'conversations.new.contactNamePlaceholder': 'e.g. Jane Doe',\n 'conversations.new.handle': 'Phone / handle / email',\n 'conversations.new.handlePlaceholder': '+1 555 000 0000',\n // The handle field only surfaces when the picked contact has nothing usable\n // for the active channel — otherwise it is derived and shown on the chip.\n 'conversations.new.addHandle': 'Add {label}',\n 'conversations.new.handleLabel.phone': 'phone',\n 'conversations.new.handleLabel.email': 'email',\n 'conversations.new.handleLabel.instagram': 'Instagram handle',\n 'conversations.new.handleLabel.webchat': 'web chat id',\n 'conversations.new.firstMessage': 'First message',\n 'conversations.new.firstMessagePlaceholder': 'Write the first message (optional)…',\n 'conversations.new.cancel': 'Cancel',\n 'conversations.new.create': 'Start conversation',\n 'conversations.new.creating': 'Starting…',\n 'conversations.new.createFailed': 'Could not create the conversation',\n}\n","export const ptBR: Record<string, string> = {\n 'conversations.title': 'Conversas',\n 'conversations.subtitle': 'Caixa de entrada unificada de todos os canais',\n\n // Lista de conversas\n 'conversations.list.search': 'Buscar conversas',\n 'conversations.list.loading': 'Carregando…',\n 'conversations.list.empty': 'Nenhuma conversa',\n 'conversations.list.new': 'Nova conversa',\n\n // Filtros de canal\n 'conversations.filter.all': 'Todas',\n 'conversations.filter.whatsapp': 'WhatsApp',\n 'conversations.filter.sms': 'SMS',\n 'conversations.filter.instagram': 'Instagram',\n 'conversations.filter.email': 'E-mail',\n 'conversations.filter.webchat': 'Web',\n\n // Rótulos de status\n 'conversations.status.open': 'Aberta',\n 'conversations.status.snoozed': 'Adiada',\n 'conversations.status.closed': 'Encerrada',\n\n // Estado vazio\n 'conversations.empty.select': 'Selecione uma conversa para começar a conversar',\n\n // Thread\n 'conversations.thread.back': 'Voltar às conversas',\n 'conversations.thread.snooze': 'Adiar',\n 'conversations.thread.close': 'Encerrar',\n 'conversations.thread.details': 'Alternar detalhes do contato',\n 'conversations.thread.empty': 'Nenhuma mensagem ainda',\n 'conversations.thread.reply': 'Responder via {{channel}}…',\n 'conversations.thread.send': 'Enviar',\n\n // Painel do contato\n 'conversations.contact.details': 'Detalhes',\n 'conversations.contact.closeDetails': 'Fechar detalhes',\n 'conversations.contact.channel': 'Canal',\n 'conversations.contact.status': 'Status',\n 'conversations.contact.assignedTo': 'Responsável',\n 'conversations.contact.location': 'Localização',\n 'conversations.contact.tags': 'Etiquetas',\n 'conversations.contact.note': 'Nota',\n 'conversations.contact.linkedRecords': 'Registros vinculados',\n 'conversations.contact.noLinkedRecords': 'Nenhum registro vinculado ainda.',\n\n // Modal de nova conversa\n 'conversations.new.title': 'Nova conversa',\n 'conversations.new.channel': 'Canal',\n 'conversations.new.contactName': 'Nome do contato',\n 'conversations.new.contactNamePlaceholder': 'ex.: Maria Silva',\n 'conversations.new.handle': 'Telefone / usuário / e-mail',\n 'conversations.new.handlePlaceholder': '+55 11 99999-0000',\n // O campo de handle só aparece quando o contato escolhido não tem o dado do\n // canal ativo — caso contrário ele é derivado e mostrado no chip.\n 'conversations.new.addHandle': 'Adicionar {label}',\n 'conversations.new.handleLabel.phone': 'telefone',\n 'conversations.new.handleLabel.email': 'e-mail',\n 'conversations.new.handleLabel.instagram': '@ do Instagram',\n 'conversations.new.handleLabel.webchat': 'id do chat',\n 'conversations.new.firstMessage': 'Primeira mensagem',\n 'conversations.new.firstMessagePlaceholder': 'Escreva a primeira mensagem (opcional)…',\n 'conversations.new.cancel': 'Cancelar',\n 'conversations.new.create': 'Iniciar conversa',\n 'conversations.new.creating': 'Iniciando…',\n 'conversations.new.createFailed': 'Não foi possível criar a conversa',\n}\n","import { en } from './en'\nimport { ptBR } from './pt-BR'\n\nexport const conversationsLocales: Record<string, Record<string, string>> = {\n en,\n 'pt-BR': ptBR,\n}\n","// AUTO-GENERATED from 001_conversations.sql, 002_contact_person.sql — regenerate with scripts/embed-migrations.mjs\n// SQL files are the source of truth; this inline copy lets the manifest declare\n// migrations as data. Do not edit by hand — run the embed script instead.\n\nexport const MIGRATION_001_CONVERSATIONS = `-- ============================================================================\n-- plugin-conversations 001: omni-channel inbox model (SMS / WhatsApp /\n-- Instagram / Email / Web chat). Prefix: plg_conversations / plg_conversation_messages.\n-- §1 plg_conversations — one thread per contact+channel\n-- §2 plg_conversation_messages — inbound/outbound messages within a thread\n-- §3 RLS: authenticated tenant-scoped CRUD on both tables + GRANTs\n--\n-- Column names mirror exactly what supabase.ts's mapConversation / mapMessage\n-- read. Real channel connectors (Twilio, WhatsApp Cloud, Meta, IMAP) deliver\n-- inbound rows here out-of-band; the provider is the read/compose surface.\n-- Idempotent + safe to re-run.\n-- ============================================================================\n\n-- §1 — conversations (threads)\nCREATE TABLE IF NOT EXISTS public.plg_conversations (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n contact_name text NOT NULL,\n contact_handle text,\n channel text NOT NULL\n CHECK (channel IN ('sms', 'whatsapp', 'instagram', 'email', 'webchat')),\n last_message_preview text,\n last_message_at timestamptz DEFAULT now(),\n unread_count int DEFAULT 0,\n status text DEFAULT 'open'\n CHECK (status IN ('open', 'snoozed', 'closed')),\n assigned_to text,\n accent text,\n tags text[],\n location text,\n note text,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n);\nALTER TABLE public.plg_conversations ENABLE ROW LEVEL SECURITY;\nCREATE INDEX IF NOT EXISTS idx_plg_conversations_tenant ON public.plg_conversations(tenant_id);\nCREATE INDEX IF NOT EXISTS idx_plg_conversations_tenant_recent ON public.plg_conversations(tenant_id, last_message_at DESC);\n\n-- §2 — messages\nCREATE TABLE IF NOT EXISTS public.plg_conversation_messages (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n conversation_id uuid NOT NULL REFERENCES public.plg_conversations(id) ON DELETE CASCADE,\n channel text\n CHECK (channel IS NULL OR channel IN ('sms', 'whatsapp', 'instagram', 'email', 'webchat')),\n direction text\n CHECK (direction IN ('inbound', 'outbound')),\n body text NOT NULL,\n author text,\n at timestamptz DEFAULT now()\n);\nALTER TABLE public.plg_conversation_messages ENABLE ROW LEVEL SECURITY;\nCREATE INDEX IF NOT EXISTS idx_plg_conversation_messages_thread ON public.plg_conversation_messages(conversation_id, at);\n\n-- §3 — RLS: authenticated tenant CRUD (the inbox reads/writes here)\nDROP POLICY IF EXISTS plg_conversations_select ON public.plg_conversations;\nDROP POLICY IF EXISTS plg_conversations_insert ON public.plg_conversations;\nDROP POLICY IF EXISTS plg_conversations_update ON public.plg_conversations;\nDROP POLICY IF EXISTS plg_conversations_delete ON public.plg_conversations;\nCREATE POLICY plg_conversations_select ON public.plg_conversations FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_conversations_insert ON public.plg_conversations FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_conversations_update ON public.plg_conversations FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_conversations_delete ON public.plg_conversations FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\nGRANT SELECT, INSERT, UPDATE, DELETE ON public.plg_conversations TO authenticated;\n\nDROP POLICY IF EXISTS plg_conversation_messages_select ON public.plg_conversation_messages;\nDROP POLICY IF EXISTS plg_conversation_messages_insert ON public.plg_conversation_messages;\nDROP POLICY IF EXISTS plg_conversation_messages_update ON public.plg_conversation_messages;\nDROP POLICY IF EXISTS plg_conversation_messages_delete ON public.plg_conversation_messages;\nCREATE POLICY plg_conversation_messages_select ON public.plg_conversation_messages FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_conversation_messages_insert ON public.plg_conversation_messages FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_conversation_messages_update ON public.plg_conversation_messages FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_conversation_messages_delete ON public.plg_conversation_messages FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\nGRANT SELECT, INSERT, UPDATE, DELETE ON public.plg_conversation_messages TO authenticated;\n`\n\nexport const MIGRATION_002_CONTACT_PERSON = `-- ============================================================================\n-- plugin-conversations 002: link a thread to a REAL person record.\n--\n-- The compose modal used to take a free-text name + handle, so a conversation\n-- with \"Maria\" had nothing to do with the Maria in the agenda, the CRM or the\n-- financial module. The shared ContactPicker (find-or-create over\n-- public.people) now resolves a person, and this column stores that link.\n--\n-- Nullable on purpose, in both directions of time:\n-- • rows created before this migration keep working (name/handle only);\n-- • an inbound message from an unknown number still opens a thread with no\n-- person attached — the contact panel can offer \"create contact\" later.\n-- ON DELETE SET NULL: deleting a person must never take their history with it.\n-- Idempotent + safe to re-run.\n-- ============================================================================\n\nALTER TABLE public.plg_conversations\n ADD COLUMN IF NOT EXISTS contact_person_id uuid REFERENCES public.people(id) ON DELETE SET NULL;\n\nCREATE INDEX IF NOT EXISTS idx_plg_conversations_person\n ON public.plg_conversations(tenant_id, contact_person_id)\n WHERE contact_person_id IS NOT NULL;\n`\n\nexport const MIGRATIONS: Array<{ id: string; sql: string }> = [\n { id: \"001_conversations\", sql: MIGRATION_001_CONVERSATIONS },\n { id: \"002_contact_person\", sql: MIGRATION_002_CONTACT_PERSON },\n]\n","import React from 'react'\nimport type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'\nimport { getActiveTenantId, getSupabaseClientOptional, registerTranslations } from '@fayz-ai/core'\nimport type { EntityLookup } from '@fayz-ai/saas'\nimport { ConversationsPage } from './ConversationsPage'\nimport type { ResolvedConversationsConfig } from './ConversationsContext'\nimport type { ConversationsProvider } from './data/types'\nimport { createMockConversationsProvider } from './data/mock'\nimport { createSupabaseConversationsProvider } from './data/supabase'\nimport { createConversationsStore } from './store'\nimport { conversationsLocales } from './locales'\nimport { MIGRATION_001_CONVERSATIONS, MIGRATION_002_CONTACT_PERSON } from './migrations'\n\n// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-conversations — the GoHighLevel \"Conversations\" equivalent:\n// one omni-channel inbox (SMS / WhatsApp / Instagram / Email / Web chat).\n// Universal plugin — reusable by any vertical (beauty, resto, agency…).\n//\n// Supabase-backed (plg_conversations / plg_conversation_messages, tenant-scoped\n// via RLS) when a client is registered; a persisted mock inbox otherwise. Real\n// channel connectors (Twilio, WhatsApp Cloud, Meta, IMAP) deliver inbound rows\n// out-of-band; this plugin is the read/compose surface.\n// ---------------------------------------------------------------------------\n\nexport interface ConversationsPluginOptions {\n navPosition?: number\n navSection?: 'main' | 'secondary' | 'settings'\n navLabel?: string\n scope?: PluginScope\n verticalId?: VerticalId\n dataProvider?: ConversationsProvider\n\n /**\n * `people.kind` for contacts created from the compose modal's picker. Each\n * vertical names its people differently (beauty 'client', agency 'lead'),\n * hence a knob rather than a hardcoded value. Default: 'contact'.\n */\n contactKind?: string\n /**\n * Per-vertical extension table linked by `person_id` (e.g. 'clients'). Pools\n * without it live off `public.people` alone — absent is not an error.\n */\n contactExtensionTable?: string\n /** Custom search source for the picker. Defaults to the person archetype lookup. */\n contactLookup?: EntityLookup\n}\n\nfunction createSafeProvider(): ConversationsProvider {\n // Real data when a Supabase client is registered; mock inbox otherwise.\n // Resolution is LAZY (per call): createConversationsPlugin runs at module\n // scope in the app config, BEFORE the Supabase client is registered — an\n // eager check here would capture the mock forever even on live backends.\n let real: ConversationsProvider | null = null\n let mock: ConversationsProvider | null = null\n const resolve = (): ConversationsProvider => {\n if (getSupabaseClientOptional()) {\n real ??= createSupabaseConversationsProvider({ tenantId: () => getActiveTenantId() })\n return real\n }\n mock ??= createMockConversationsProvider({ tenantId: () => getActiveTenantId() })\n return mock\n }\n return {\n listConversations: (...a) => resolve().listConversations(...a),\n getMessages: (...a) => resolve().getMessages(...a),\n sendMessage: (...a) => resolve().sendMessage(...a),\n markRead: (...a) => resolve().markRead(...a),\n setStatus: (...a) => resolve().setStatus(...a),\n createConversation: (...a) => resolve().createConversation(...a),\n }\n}\n\nexport function createConversationsPlugin(options?: ConversationsPluginOptions): PluginManifest {\n registerTranslations(conversationsLocales)\n const provider = options?.dataProvider ?? createSafeProvider()\n const store = createConversationsStore(provider)\n\n const config: ResolvedConversationsConfig = {\n contactKind: options?.contactKind ?? 'contact',\n contactExtensionTable: options?.contactExtensionTable,\n contactLookup: options?.contactLookup,\n }\n\n const PageComponent: React.ComponentType<unknown> = () =>\n React.createElement(ConversationsPage, { store, config })\n PageComponent.displayName = 'ConversationsPage'\n\n return {\n id: 'conversations',\n name: options?.navLabel ?? 'Conversations',\n icon: 'MessageCircle',\n version: '1.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [{ id: 'conversations', label: 'Conversations', group: 'Engage' }],\n // Recurring monthly quota — counts conversation threads created this month.\n declaredLimits: [\n { key: 'conversations_month', label: 'Conversations this month', table: 'plg_conversations', period: 'month' },\n ],\n navigation: [\n {\n section: options?.navSection ?? 'main',\n position: options?.navPosition ?? 1,\n label: options?.navLabel ?? 'Conversations',\n route: '/conversations',\n icon: 'MessageCircle',\n permission: { feature: 'conversations', action: 'read' as const },\n },\n ],\n routes: [\n {\n path: '/conversations',\n component: PageComponent,\n fullBleed: true,\n permission: { feature: 'conversations', action: 'read' as const },\n },\n ],\n widgets: [],\n events: [\n { name: 'conversations.message.received', description: 'An inbound message arrived on any channel' },\n { name: 'conversations.message.sent', description: 'An outbound message was sent' },\n ],\n aiTools: [\n {\n id: 'conversations.list-threads',\n name: 'listConversations',\n description: 'Lists open conversations across all channels, optionally filtered by channel.',\n icon: 'MessageCircle',\n mode: 'read' as const,\n category: 'Conversations',\n parameters: {\n type: 'object' as const,\n properties: {\n channel: {\n type: 'string' as const,\n enum: ['all', 'sms', 'whatsapp', 'instagram', 'email', 'webchat'],\n },\n },\n },\n suggestions: [\n { label: 'Show unread conversations' },\n { label: 'Any new WhatsApp messages?' },\n ],\n permission: { feature: 'conversations', action: 'read' as const },\n },\n {\n id: 'conversations.send-message',\n name: 'sendMessage',\n description: 'Sends a reply in a conversation thread.',\n icon: 'Send',\n mode: 'persist' as const,\n category: 'Conversations',\n parameters: {\n type: 'object' as const,\n properties: {\n conversationId: { type: 'string' as const, description: 'Conversation id' },\n body: { type: 'string' as const, description: 'Message body' },\n },\n required: ['conversationId', 'body'],\n },\n permission: { feature: 'conversations', action: 'create' as const },\n },\n ],\n migrations: [\n {\n id: 'conversations-001-base-tables',\n version: '1.0.0',\n sql: MIGRATION_001_CONVERSATIONS,\n description: 'Create plg_conversations and plg_conversation_messages (tenant-scoped RLS)',\n },\n {\n id: 'conversations-002-contact-person',\n version: '1.1.0',\n sql: MIGRATION_002_CONTACT_PERSON,\n description: 'Link threads to public.people via contact_person_id (nullable, ON DELETE SET NULL)',\n },\n ],\n locales: conversationsLocales,\n }\n}\n\nexport type { ConversationsProvider } from './data/types'\nexport type { Conversation, Message, Channel, CreateConversationInput } from './types'\nexport { createMockConversationsProvider, type MockConversationsConfig } from './data/mock'\nexport {\n createSupabaseConversationsProvider,\n type SupabaseConversationsConfig,\n} from './data/supabase'\n"]}
|
package/dist/locales/en.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/locales/en.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/locales/en.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmErC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/locales/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/locales/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGvE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pt-BR.d.ts","sourceRoot":"","sources":["../../src/locales/pt-BR.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmEvC,CAAA"}
|