@fayz-ai/plugin-conversations 0.23.15 → 0.24.0
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/{chunk-LJKLHGFX.js → ConversationsPage-BTRYZPM7.js} +129 -123
- package/dist/ConversationsPage-BTRYZPM7.js.map +1 -0
- package/dist/{ConversationsSettings-7UQYM26R.js → ConversationsSettings-Q3PGQMB3.js} +3 -3
- package/dist/{ConversationsSettings-7UQYM26R.js.map → ConversationsSettings-Q3PGQMB3.js.map} +1 -1
- package/dist/{chunk-3FZX3ZQ3.js → chunk-2JV6B366.js} +77 -76
- package/dist/chunk-2JV6B366.js.map +1 -0
- package/dist/chunk-X7BP2JH6.js +74 -0
- package/dist/chunk-X7BP2JH6.js.map +1 -0
- package/dist/components/InboxWatcher.d.ts +6 -15
- package/dist/components/InboxWatcher.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +122 -143
- package/dist/index.js.map +1 -1
- package/dist/integrations/evolution/connectorDef.d.ts +4 -0
- package/dist/integrations/evolution/connectorDef.d.ts.map +1 -0
- package/dist/views/ConversationList.d.ts.map +1 -1
- package/dist/views/WhatsAppConnectionFooter.d.ts +8 -0
- package/dist/views/WhatsAppConnectionFooter.d.ts.map +1 -0
- package/package.json +4 -4
- package/dist/ConversationsPage-4V4VLM4D.js +0 -47
- package/dist/ConversationsPage-4V4VLM4D.js.map +0 -1
- package/dist/chunk-3FZX3ZQ3.js.map +0 -1
- package/dist/chunk-LJKLHGFX.js.map +0 -1
- package/dist/components/ConversationsRailPanel.d.ts +0 -15
- package/dist/components/ConversationsRailPanel.d.ts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/channel.ts","../src/views/shared.tsx","../src/data/channel-connections.ts","../src/views/WhatsAppConnectionFooter.tsx","../src/views/ConversationList.tsx","../src/views/SendWindow.tsx","../src/views/MessageInspector.tsx","../src/views/MediaBubble.tsx","../src/views/MessageThread.tsx","../src/views/LeadCard.tsx","../src/views/ContactPanel.tsx","../src/views/NewConversationPanel.tsx","../src/views/useCaixaAoVivo.ts","../src/views/InboxView.tsx","../src/views/ConversationsPage.tsx"],"names":["React","React2","jsx","jsxs","cn","Button","InboxIcon","CheckCheck","getSupabaseClientOptional","getActiveTenantId","React6","Check","useTranslation","MessageSquare","X","User","Textarea","React10","Fragment","CHANNELS","appHref"],"mappings":"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","file":"ConversationsPage-BTRYZPM7.js","sourcesContent":["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 '../lib/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 * as React from 'react'\nimport { useConnectors } from '@fayz-ai/admin'\nimport { providersApi } from './providers'\nimport type { Channel } from '../types'\n\nlet whatsappCache: Promise<boolean> | null = null\nconst whatsappConnected = () => {\n whatsappCache ??= providersApi.list()\n .then((rows) => rows.some((r) => r.isActive || r.hasCredential))\n .catch(() => { whatsappCache = null; return false })\n return whatsappCache\n}\n\n/**\n * Which channels this house has an account connected for. WhatsApp reads its\n * providers; the others read the inbox's hub connectors. `undefined` while\n * WhatsApp is still being read, so nothing flashes as \"not connected\".\n */\nexport function useChannelConnections(): Partial<Record<Channel, boolean>> | undefined {\n const [whatsapp, setWhatsapp] = React.useState<boolean | undefined>(undefined)\n const { connectors } = useConnectors({ hostPluginId: 'conversations', includeGrants: false })\n React.useEffect(() => {\n let cancelled = false\n void whatsappConnected().then((v) => { if (!cancelled) setWhatsapp(v) })\n return () => { cancelled = true }\n }, [])\n return React.useMemo(() => {\n if (whatsapp === undefined) return undefined\n const live = (needle: string) => (connectors ?? []).some((c) => c.state === 'connected' && c.slug.toLowerCase().includes(needle))\n return { whatsapp: whatsapp || live('whatsapp'), email: live('mail'), instagram: live('instagram') }\n }, [whatsapp, connectors])\n}\n","import { CheckCircle2 } from 'lucide-react'\nimport { tl } from '@fayz-ai/core'\nimport { adminNavigateTo } from '@fayz-ai/admin'\nimport { Button } from '@fayz-ai/ui'\nimport { useChannelConnections } from '../data/channel-connections'\n\nconst CONNECTORS_ROUTE = '/settings/conversations/connectors'\n\n/**\n * The foot of the inbox list: a green «Conectar WhatsApp» when no number is\n * connected, otherwise «WhatsApp conectado · Gerenciar». The connector lives\n * in Configurações → Conversas → Conectores, two levels away from where the\n * person notices the inbox is empty; this is the short way there.\n */\nexport function WhatsAppConnectionFooter() {\n const connected = useChannelConnections()\n return (\n <div className=\"shrink-0 border-t border-border p-3\">\n {connected === undefined ? (\n <div className=\"h-10\" aria-hidden />\n ) : connected.whatsapp ? (\n <Button variant=\"bare\" size=\"bare\" type=\"button\" onClick={() => adminNavigateTo(CONNECTORS_ROUTE)}\n className=\"font-normal whitespace-normal justify-start fz-tap flex h-10 w-full items-center gap-2 rounded-button px-2 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-foreground\">\n <CheckCircle2 className=\"h-4 w-4 text-[#25D366]\" aria-hidden />\n <span className=\"min-w-0 flex-1 truncate text-left\">{tl('WhatsApp connected', 'WhatsApp conectado')}</span>\n <span className=\"text-xs text-primary\">{tl('Manage', 'Gerenciar')}</span>\n </Button>\n ) : (\n <Button variant=\"bare\" size=\"bare\" type=\"button\" onClick={() => adminNavigateTo(CONNECTORS_ROUTE)} data-testid=\"inbox-connect-whatsapp\"\n className=\"font-normal whitespace-normal fz-tap flex h-11 w-full items-center justify-center gap-2 rounded-button bg-[#25D366] text-sm font-semibold text-white shadow-sm transition-colors hover:bg-[#1EBE5A] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#25D366] focus-visible:ring-offset-2\">\n <WhatsAppMark className=\"h-[18px] w-[18px]\" />\n {tl('Connect WhatsApp', 'Conectar WhatsApp')}\n </Button>\n )}\n </div>\n )\n}\n\n/** The WhatsApp glyph — lucide has none, and a generic bubble on a green\n * button reads as \"chat\", not as the channel being connected. */\nfunction WhatsAppMark({ className }: { className?: string }) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} aria-hidden>\n <path d=\"M17.47 14.38c-.3-.15-1.76-.87-2.03-.97-.27-.1-.47-.15-.67.15-.2.3-.77.96-.94 1.16-.17.2-.35.22-.65.07-.3-.15-1.26-.46-2.4-1.48-.89-.79-1.49-1.77-1.66-2.07-.17-.3-.02-.46.13-.61.13-.13.3-.35.45-.52.15-.17.2-.3.3-.5.1-.2.05-.37-.02-.52-.08-.15-.67-1.61-.92-2.2-.24-.58-.49-.5-.67-.51h-.57c-.2 0-.52.07-.79.37-.27.3-1.04 1.02-1.04 2.48s1.07 2.88 1.21 3.08c.15.2 2.1 3.2 5.08 4.49.71.31 1.26.49 1.69.63.71.22 1.36.19 1.87.12.57-.09 1.76-.72 2.01-1.41.25-.7.25-1.29.17-1.41-.07-.13-.27-.2-.57-.35zM12.05 21.5h-.01a9.4 9.4 0 0 1-4.8-1.32l-.34-.2-3.56.93.95-3.47-.22-.36a9.4 9.4 0 0 1-1.44-5.02c0-5.2 4.23-9.43 9.43-9.43 2.52 0 4.89.98 6.67 2.77a9.37 9.37 0 0 1 2.76 6.67c0 5.2-4.23 9.43-9.44 9.43zm8.03-17.46A11.3 11.3 0 0 0 12.05.72C5.79.72.7 5.81.7 12.07c0 2 .52 3.95 1.52 5.67L.6 23.6l6-1.57a11.32 11.32 0 0 0 5.44 1.39h.01c6.26 0 11.35-5.1 11.35-11.35 0-3.03-1.18-5.88-3.32-8.03z\" />\n </svg>\n )\n}\n","import React from 'react'\nimport { Search, Inbox as InboxIcon, User, CheckCheck } from 'lucide-react'\nimport { Button, FilterChip, Input, Skeleton, cn } from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport { useConversationsStore } from '../context'\nimport { isWaitingOnUs, type Channel } from '../types'\nimport { Avatar, ChannelBadge, relativeTime } from './shared'\nimport { useChannelConnections } from '../data/channel-connections'\nimport { WhatsAppConnectionFooter } from './WhatsAppConnectionFooter'\n\n// SMS and web chat are not sold as channels; their old threads still show under \"Todas\".\nconst FILTERS: Array<Channel | 'all'> = ['all', 'whatsapp', 'instagram', 'email']\n\nexport function ConversationList({ className }: { className?: string }) {\n const t = useTranslation()\n const connected = useChannelConnections()\n const {\n conversations, selectedId, channelFilter, leadOwnerFilter, search, loading,\n select, markRead, setChannelFilter, setLeadOwnerFilter, setSearch,\n } = useConversationsStore((s) => s)\n\n // Os donos que a CAIXA conhece — não a equipe inteira. Um recorte que\n // oferece gente sem nenhuma conversa devolve lista vazia e parece defeito.\n // Enquanto um filtro está ativo a lista encolhe, então a opção escolhida\n // entra na marra: sem isso ela some do seletor e não há como desmarcá-la.\n const donos = React.useMemo(() => {\n const vistos = new Map<string, string>()\n for (const c of conversations) {\n if (c.leadOwnerId) vistos.set(c.leadOwnerId, c.leadOwnerName ?? c.leadOwnerId)\n }\n return [...vistos].map(([value, label]) => ({ value, label }))\n }, [conversations])\n\n return (\n <aside className={cn('w-full shrink-0 flex-col border-r border-border bg-card lg:w-[320px]', className)}>\n {/* No title: the shell header already names the page 24px away. Starting\n a conversation moved there too — it is the PAGE's action, not the list's. */}\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={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 // Dashed: no account connected for this channel yet.\n const off = id !== 'all' && connected !== undefined && !connected[id]\n return (\n <Button variant=\"bare\" size=\"bare\"\n key={id}\n onClick={() => setChannelFilter(id)}\n title={off ? t('conversations.filter.notConnected') : undefined}\n className={cn(\n 'rounded-full border px-2.5 py-1 text-xs font-medium transition-colors',\n channelFilter === id\n ? 'border-transparent bg-primary text-primary-foreground'\n : off\n ? 'border-dashed border-muted-foreground/40 bg-transparent text-muted-foreground hover:bg-muted/50'\n : 'border-transparent bg-muted text-muted-foreground hover:bg-muted/70',\n )}\n >\n {t(`conversations.filter.${id}`)}\n </Button>\n )\n })}\n </div>\n {/* O recorte por dono do lead. Some quando a caixa não tem nenhum —\n numa casa sem funil ele seria um seletor com uma opção só. */}\n {donos.length > 0 && (\n <div className=\"mt-2\">\n <FilterChip\n label={t('conversations.contact.leadOwner')}\n icon={User}\n allLabel={t('conversations.filter.anyOwner')}\n options={[{ value: 'none', label: t('conversations.filter.noOwner') }, ...donos]}\n value={leadOwnerFilter}\n onChange={(v) => { void setLeadOwnerFilter(v) }}\n />\n </div>\n )}\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 // `isWaitingOnUs` e não `unreadCount > 0`: a conta é uma das duas\n // evidências, e a outra — a última mensagem ser de entrada — é a que\n // sobrevive quando a conta se perde. Ela existe exatamente para isto,\n // e a lista era o único lugar que a ignorava.\n const unread = isWaitingOnUs(c)\n return (\n // `div` em volta e não um botão dentro de outro: HTML não permite\n // aninhar, e o navegador resolve isso silenciosamente movendo o\n // interno para fora — a linha inteira deixa de ser clicável e\n // ninguém entende por quê.\n <div key={c.id} className=\"group relative\">\n <Button variant=\"bare\" size=\"bare\"\n onClick={() => select(c.id)}\n className={cn(\n 'flex w-full items-start justify-start gap-3 rounded-none border-b border-border/50 px-3 py-3 text-left font-normal transition-colors',\n // Um TOM da cor de marca, e não `bg-accent`.\n //\n // `bg-accent` resolve para quase preto neste tema, e a linha da\n // conversa aberta ficava escura sobre escura. Trocar junto o\n // `text-accent-foreground` deixava legível, mas pintava de\n // preto a única linha que se está a ler — chamava mais atenção\n // que a conversa.\n //\n // `bg-primary/10` é um véu: o texto continua com as cores dele,\n // a seleção se lê como seleção e não como bloco, e funciona nos\n // dois temas porque não presume nada sobre o fundo.\n active ? 'bg-primary/10' : '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 {/* O dono do lead NA LINHA, que é o jeito rápido: saber de\n quem é a conversa sem abrir cada uma. Só o primeiro nome —\n \"Carolina Dias\" ao lado do canal empurra a prévia da\n mensagem para fora, e o sobrenome não distingue ninguém\n num time de dois. */}\n {c.leadOwnerName && (\n <span className=\"inline-flex shrink-0 items-center gap-0.5 rounded-full bg-muted px-1.5 text-[10px] text-muted-foreground\">\n <User className=\"h-2.5 w-2.5\" />\n {c.leadOwnerName.split(' ')[0]}\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-destructive px-1.5 text-[10px] font-semibold text-destructive-foreground\">\n {/* Um PONTO quando a conta é zero mas a conversa espera:\n escrever \"0\" ao lado de uma linha destacada diz duas\n coisas contrárias na mesma linha. */}\n {c.unreadCount > 0 ? c.unreadCount : '\\u00b7'}\n </span>\n )}\n </div>\n </div>\n </Button>\n {/* DAR POR VISTA sem abrir.\n O caso é o \"ok, obrigado\" que não pede resposta: ler já tira da\n fila, mas obrigar a abrir trinta conversas para limpar trinta\n bolinhas é trabalho que a lista pode poupar.\n Só aparece quando há o que tirar, e no hover — um botão fixo em\n cada linha competiria com o nome do contato pelo mesmo espaço. */}\n {unread && (\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n title={t('conversations.markRead')}\n aria-label={t('conversations.markRead')}\n onClick={(e) => { e.stopPropagation(); void markRead(c.id) }}\n className=\"absolute right-2 top-2 hidden rounded-full p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground group-hover:block\"\n >\n <CheckCheck className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n </div>\n )\n })}\n </div>\n <WhatsAppConnectionFooter />\n </aside>\n )\n}\n","import React from 'react'\nimport { getSupabaseClientOptional, getActiveTenantId } from '@fayz-ai/core'\nimport { providersApi, type ProviderRow } from '../data/providers'\n\n/**\n * Se dá para falar com esta pessoa AGORA, e por qual caminho.\n *\n * ── o defeito que isto existe para matar ────────────────────────────────\n *\n * Na API oficial do WhatsApp, texto livre só sai dentro de 24h contadas da\n * última mensagem DO CLIENTE. Fora dela a Meta recusa — e a recusa chega num\n * log, não na tela. O atendente digita, aperta enviar, vê a mensagem aparecer\n * na conversa, e ela nunca chega ao destinatário.\n *\n * Uma tela que aceita o que não vai entregar é pior que uma tela que recusa.\n *\n * ── e por que isso muda com o provedor ──────────────────────────────────\n *\n * No Evolution não existe janela nenhuma: manda sempre. Então o MESMO campo de\n * texto é seguro num provedor e mentiroso no outro, e qual está valendo é uma\n * configuração que muda numa tela distante daqui. Por isso este gancho lê as\n * duas coisas juntas — a janela da conversa E a capacidade do provedor ativo —\n * e devolve uma resposta só: pode escrever, ou não pode e por quê.\n */\n\nexport type SendMode =\n | { kind: 'free'; until: string | null; minutesLeft: number | null }\n | { kind: 'template'; reason: 'window_closed' | 'never_replied' }\n | { kind: 'blocked'; reason: 'no_provider' }\n\nexport interface WindowState {\n loading: boolean\n mode: SendMode\n provider: ProviderRow | undefined\n}\n\ninterface WindowRow {\n window_open: boolean\n window_expires_at: string | null\n minutes_left: number | null\n last_inbound_at: string | null\n}\n\nexport function useSendWindow(conversationId: string | undefined): WindowState {\n const [row, setRow] = React.useState<WindowRow | null>(null)\n const [providers, setProviders] = React.useState<ProviderRow[] | null>(null)\n\n React.useEffect(() => {\n let alive = true\n providersApi.list().then((p) => { if (alive) setProviders(p) }).catch(() => { if (alive) setProviders([]) })\n return () => { alive = false }\n }, [])\n\n React.useEffect(() => {\n let alive = true\n if (!conversationId) { setRow(null); return }\n const sb = getSupabaseClientOptional() as any\n if (!sb) { setRow(null); return }\n sb.from('v_conversations_window')\n .select('window_open, window_expires_at, minutes_left, last_inbound_at')\n .eq('conversation_id', conversationId).eq('tenant_id', getActiveTenantId())\n .maybeSingle()\n .then(({ data }: { data: WindowRow | null }) => { if (alive) setRow(data ?? null) })\n .catch(() => { if (alive) setRow(null) })\n return () => { alive = false }\n }, [conversationId])\n\n const provider = (providers ?? []).find((p) => p.isActive)\n\n const mode = React.useMemo<SendMode>(() => {\n if (!provider) return { kind: 'blocked', reason: 'no_provider' }\n // O provedor que não exige template não tem janela: manda sempre. Dizer\n // \"janela aberta\" aqui seria inventar um conceito que ele não tem.\n if (!provider.capabilities?.requires_template) {\n return { kind: 'free', until: null, minutesLeft: null }\n }\n if (row?.window_open) {\n return { kind: 'free', until: row.window_expires_at, minutesLeft: row.minutes_left }\n }\n return { kind: 'template', reason: row?.last_inbound_at ? 'window_closed' : 'never_replied' }\n }, [row, provider])\n\n return { loading: providers === null, mode, provider }\n}\n\n/** Quanto falta, em português de gente: \"faltam 3h\" e não um carimbo ISO. */\nexport function humanLeft(minutes: number | null | undefined): string {\n if (minutes == null) return ''\n if (minutes < 60) return `${minutes} min`\n const h = Math.floor(minutes / 60)\n return h < 24 ? `${h}h` : `${Math.floor(h / 24)}d`\n}\n\nexport function SendWindowBanner({ state }: { state: WindowState }) {\n const { mode, provider } = state\n if (mode.kind === 'free' && mode.minutesLeft == null) return null\n\n if (mode.kind === 'free') {\n // Aberta, mas fechando. O relógio importa: quem responde quer saber se dá\n // tempo de resolver agora ou se precisa de template.\n const urgent = (mode.minutesLeft ?? 0) < 120\n return (\n <div className={`flex items-center gap-2 px-4 py-1.5 text-[11px] ${urgent ? 'bg-warning-soft text-warning-soft-foreground' : 'text-muted-foreground'}`}>\n <span className=\"h-1.5 w-1.5 rounded-full bg-success\" />\n Janela aberta — texto livre por mais {humanLeft(mode.minutesLeft)}\n </div>\n )\n }\n\n if (mode.kind === 'blocked') {\n return (\n <div className=\"flex items-center gap-2 bg-destructive-soft px-4 py-2 text-[11px] text-destructive-soft-foreground\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-destructive\" />\n Nenhum provedor de WhatsApp ativo — configure em Ajustes › Conversas.\n </div>\n )\n }\n\n return (\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1 bg-warning-soft px-4 py-2 text-[11px] text-warning-soft-foreground\">\n <span className=\"h-1.5 w-1.5 shrink-0 rounded-full bg-warning\" />\n <span className=\"font-medium\">\n {mode.reason === 'never_replied'\n ? 'Esta pessoa nunca respondeu.'\n : 'A janela de 24 horas fechou.'}\n </span>\n <span>\n No {provider?.provider ?? 'provedor'}, texto livre só sai dentro de 24h da\n resposta do cliente. Para falar agora é preciso um template aprovado.\n </span>\n </div>\n )\n}\n","import React from 'react'\nimport { AlertTriangle, Check, CheckCheck, Clock, Loader2, MoreVertical, X } from 'lucide-react'\nimport { getSupabaseClientOptional, getActiveTenantId } from '@fayz-ai/core'\nimport { Button } from '@fayz-ai/ui'\nimport type { Message } from '../types'\n\n/**\n * O que aconteceu com esta mensagem, e o JSON cru de quem devia tê-la entregue.\n *\n * ── por que isto existe ─────────────────────────────────────────────────\n *\n * Duas mensagens ficaram um dia inteiro na caixa com a mesma cara de qualquer\n * outra — balão verde, horário, tudo igual — e nunca chegaram a ninguém. Não\n * havia como saber olhando. A tela dizia \"enviada\" porque a linha existia no\n * banco, e existir no banco não é ter saído.\n *\n * Uma mensagem que falhou precisa parecer que falhou. E quando alguém\n * perguntar \"por quê?\", a resposta não pode ser \"olha o log do servidor\".\n *\n * ── o JSON vem AO VIVO, e não de uma cópia ──────────────────────────────\n *\n * O status de uma mensagem de WhatsApp muda DEPOIS do envio: aceita, enviada,\n * entregue, lida — às vezes horas depois. Uma cópia gravada no momento do envio\n * envelhece na primeira mudança e passa a mentir com precisão de carimbo.\n * Então o detalhe é buscado no provedor na hora em que alguém abre.\n */\n\nconst STATUS: Record<string, { icon: typeof Check; label: string; cls: string }> = {\n queued: { icon: Clock, label: 'na fila', cls: 'text-white/60' },\n sent: { icon: Check, label: 'enviada', cls: 'text-white/70' },\n delivered: { icon: CheckCheck, label: 'entregue', cls: 'text-white/80' },\n read: { icon: CheckCheck, label: 'lida', cls: 'text-sky-200' },\n failed: { icon: AlertTriangle, label: 'NÃO ENVIADA', cls: 'text-white' },\n expired: { icon: AlertTriangle, label: 'expirou', cls: 'text-white' },\n delivery_timeout: { icon: AlertTriangle, label: 'sem confirmação', cls: 'text-white' },\n cancelled: { icon: X, label: 'cancelada', cls: 'text-white' },\n opted_out: { icon: X, label: 'recusada', cls: 'text-white' },\n}\n\nconst BAD = new Set(['failed', 'expired', 'cancelled', 'opted_out', 'delivery_timeout'])\n\nexport function isFailed(m: Message): boolean {\n if (m.direction !== 'outbound') return false\n // O STATUS MANDA. Ele vem do provedor e é a resposta de quem entregou.\n if (m.deliveryStatus) return BAD.has(m.deliveryStatus)\n\n // Sem status, a ausência de id do provedor é o único sinal que resta — mas\n // ela também é o estado normal nos primeiros segundos, enquanto o envio\n // acontece. Pintar de vermelho nesse intervalo faz a tela acusar de falha\n // uma mensagem que está saindo, e foi exatamente o que aconteceu com uma\n // que já tinha sido entregue.\n //\n // Dois minutos: mais que qualquer envio e menos que a paciência de quem\n // está olhando.\n if (m.providerMessageId) return false\n const age = Date.now() - new Date(m.at).getTime()\n // Uma mensagem em fila para o disparador local pode esperar mais que dois\n // minutos sem que nada esteja errado — ele confere a cada volta e a sessão\n // do WhatsApp pode estar religando.\n return Number.isFinite(age) && age > 120_000\n}\n\n/** O carimbo ao lado da hora. Some nas de entrada: elas chegaram. */\nexport function DeliveryMark({ m }: { m: Message }) {\n if (m.direction !== 'outbound') return null\n const key = isFailed(m) ? 'failed' : (m.deliveryStatus ?? 'sent')\n const cfg = STATUS[key] ?? STATUS.sent\n const Icon = cfg.icon\n return (\n <span className={`inline-flex items-center gap-0.5 ${cfg.cls}`} title={cfg.label}>\n <Icon className=\"h-3 w-3\" />\n {BAD.has(key) && <span className=\"text-[9px] font-semibold uppercase\">{cfg.label}</span>}\n </span>\n )\n}\n\nexport function MessageMenu({ m }: { m: Message }) {\n const [open, setOpen] = React.useState(false)\n const [detail, setDetail] = React.useState<unknown>(null)\n const [loading, setLoading] = React.useState(false)\n const [err, setErr] = React.useState<string | null>(null)\n\n async function load() {\n setOpen(true)\n if (!m.providerMessageId) return\n setLoading(true); setErr(null)\n try {\n const sb = getSupabaseClientOptional() as any\n const { data, error } = await sb.functions.invoke('conversations-provider', {\n body: { tenantId: getActiveTenantId(), action: 'message_detail', providerMessageId: m.providerMessageId },\n })\n if (error) {\n const d = (await error.context?.json?.().catch(() => null)) as { message?: string } | null\n throw new Error(d?.message ?? error.message)\n }\n if ((data as any)?.error) throw new Error((data as any).message ?? (data as any).error)\n setDetail((data as any).detail)\n } catch (e: any) {\n setErr(e?.message ?? 'Não consegui buscar')\n } finally {\n setLoading(false)\n }\n }\n\n return (\n <>\n <Button variant=\"bare\" size=\"bare\"\n onClick={() => void load()}\n aria-label=\"Detalhes da mensagem\"\n className=\"opacity-0 transition-opacity group-hover:opacity-60 hover:!opacity-100\"\n >\n <MoreVertical className=\"h-3.5 w-3.5\" />\n </Button>\n\n {open && (\n <div className=\"fixed inset-0 z-[120] flex items-center justify-center bg-black/50 p-4\" onClick={() => setOpen(false)}>\n <div className=\"max-h-[80vh] w-full max-w-2xl overflow-hidden rounded-card bg-card shadow-2xl\" onClick={(e) => e.stopPropagation()}>\n <div className=\"flex items-center justify-between border-b px-4 py-3\">\n <div>\n <p className=\"text-sm font-semibold\">Detalhes da mensagem</p>\n <p className=\"text-[11px] text-muted-foreground\">\n {new Date(m.at).toLocaleString()} · {m.direction === 'outbound' ? 'saída' : 'entrada'}\n {m.deliveryStatus ? ` · ${m.deliveryStatus}` : ''}\n </p>\n </div>\n <Button variant=\"bare\" size=\"bare\" onClick={() => setOpen(false)} aria-label=\"Fechar\"><X className=\"h-4 w-4\" /></Button>\n </div>\n\n <div className=\"max-h-[60vh] overflow-auto p-4 text-xs\">\n <p className=\"mb-1 font-medium text-muted-foreground\">Nesta base</p>\n <pre className=\"mb-4 overflow-auto rounded bg-muted/40 p-3 text-[11px] leading-relaxed\">\n{JSON.stringify({ id: m.id, direction: m.direction, body: m.body, at: m.at,\n author: m.author, deliveryStatus: m.deliveryStatus,\n providerMessageId: m.providerMessageId }, null, 2)}\n </pre>\n\n <p className=\"mb-1 font-medium text-muted-foreground\">No provedor</p>\n {!m.providerMessageId && (\n // A ausência é a informação: sem id, ninguém do outro lado\n // chegou a aceitar esta mensagem. Ela não atrasou — ela não saiu.\n <p className=\"rounded bg-destructive-soft p-3 text-[11px] text-destructive-soft-foreground\">\n Esta mensagem não tem id no provedor — ela nunca chegou a ser aceita para envio.\n Não há o que buscar do outro lado.\n </p>\n )}\n {loading && <p className=\"flex items-center gap-2 p-3 text-muted-foreground\"><Loader2 className=\"h-3 w-3 animate-spin\" /> buscando…</p>}\n {err && <p className=\"rounded bg-destructive-soft p-3 text-[11px] text-destructive-soft-foreground\">{err}</p>}\n {detail != null && (\n <pre className=\"overflow-auto rounded bg-muted/40 p-3 text-[11px] leading-relaxed\">\n{JSON.stringify(detail, null, 2)}\n </pre>\n )}\n </div>\n </div>\n </div>\n )}\n </>\n )\n}\n","// A mídia que chegou, mostrada — imagem, áudio, vídeo e documento.\n//\n// ── o que faltava, e não era o parser ───────────────────────────────────────\n//\n// A 012 fez a mensagem que não é texto parar de chegar vazia: um áudio entrou\n// classificado como `audio`, `ptt: true`, 23 segundos, `audio/ogg; codecs=opus`,\n// 55.825 bytes. Tudo certo, e a tela mostrava `[áudio]` escrito por extenso,\n// porque saber QUE existe um arquivo não é ter o arquivo.\n//\n// A 013 passou a guardar os bytes no balde `attachments`. Este componente é o\n// outro lado: o que transforma `media_path` em algo que toca.\n//\n// ── por que uma URL assinada por bolha, e não um link no payload ────────────\n//\n// O balde é privado de propósito — uma foto que um lead mandou no WhatsApp não\n// é para o mundo. Privado significa que o navegador não busca sozinho; cada\n// visualização precisa de uma assinatura temporária. Guardar uma URL pronta na\n// linha daria um link que vaza num print e vale para sempre.\n//\n// Quem assina é `conversations-provider`, e ele assina contra a LINHA (o id da\n// mensagem), nunca contra um caminho que o cliente mande — `media_path` começa\n// por `whatsapp/<inquilino>/…` e adivinhar o caminho de outra casa seria\n// trivial.\n//\n// ── por que só ao aparecer ──────────────────────────────────────────────────\n//\n// Uma conversa de vendas tem dezenas de mensagens e a maioria é texto. Assinar\n// tudo ao abrir seria uma chamada por bolha para depois descobrir que só três\n// têm arquivo. `IntersectionObserver` pede quando a bolha entra na tela, que é\n// também quando a assinatura de dez minutos começa a valer a pena.\nimport * as React from 'react'\nimport { Download, FileText } from 'lucide-react'\nimport { getSupabaseClientOptional, getActiveTenantId } from '@fayz-ai/core'\nimport type { Message } from '../types'\n\n/** Os tipos que têm arquivo. Os outros são inteiramente o que `body` e\n * `payload` já dizem, e não têm o que buscar. */\nconst COM_ARQUIVO = new Set(['image', 'video', 'audio', 'document', 'sticker'])\n\nexport function temArquivo(m: Message): boolean {\n return !!m.mediaPath && COM_ARQUIVO.has(String(m.messageType))\n}\n\n/** A URL assinada desta mensagem, pedida quando a bolha aparece.\n *\n * O estado `erro` existe separado de `url === null` porque os dois têm cara\n * diferente na tela: um arquivo que não carregou merece dizer que não\n * carregou, e uma bolha ainda não pedida não deve parecer defeito. */\nfunction useUrlAssinada(m: Message, visivel: boolean) {\n const [url, setUrl] = React.useState<string | null>(null)\n const [erro, setErro] = React.useState(false)\n\n React.useEffect(() => {\n if (!visivel || url || erro || !temArquivo(m)) return\n let vivo = true\n ;(async () => {\n try {\n const sb = getSupabaseClientOptional() as any\n const { data, error } = await sb.functions.invoke('conversations-provider', {\n body: { tenantId: getActiveTenantId(), action: 'media_url', messageId: m.id },\n })\n if (error || (data as any)?.error) throw new Error('falhou')\n if (vivo && (data as any)?.url) setUrl((data as any).url as string)\n else if (vivo) setErro(true)\n } catch {\n if (vivo) setErro(true)\n }\n })()\n return () => { vivo = false }\n }, [visivel, m.id, url, erro])\n\n return { url, erro }\n}\n\n/** `55825` → `55 KB`. Um número de bytes cru não diz a ninguém se vale a pena\n * esperar o download. */\nfunction tamanho(bytes?: number | null): string {\n if (!bytes || bytes <= 0) return ''\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\n/** `23` → `0:23`. A duração é o que decide se dá para ouvir agora. */\nfunction duracao(seg?: number | null): string {\n if (!seg || seg <= 0) return ''\n const m = Math.floor(seg / 60)\n const s = Math.floor(seg % 60)\n return `${m}:${String(s).padStart(2, '0')}`\n}\n\nexport function MediaBubble({ m, outbound }: { m: Message; outbound: boolean }) {\n const ref = React.useRef<HTMLDivElement>(null)\n const [visivel, setVisivel] = React.useState(false)\n const { url, erro } = useUrlAssinada(m, visivel)\n\n React.useEffect(() => {\n const el = ref.current\n // Sem IntersectionObserver (jsdom, navegador antigo) a bolha pede logo:\n // melhor uma chamada a mais do que um anexo que nunca aparece.\n if (!el || typeof IntersectionObserver === 'undefined') { setVisivel(true); return }\n const obs = new IntersectionObserver((entradas) => {\n if (entradas.some((e) => e.isIntersecting)) { setVisivel(true); obs.disconnect() }\n }, { rootMargin: '200px' })\n obs.observe(el)\n return () => obs.disconnect()\n }, [])\n\n const tipo = String(m.messageType)\n const p = (m.payload ?? {}) as { mimetype?: string | null; fileName?: string | null; fileLength?: number | null; seconds?: number | null; ptt?: boolean | null; caption?: string | null }\n const legenda = p.caption ?? null\n\n // O texto que a bolha já mostrava. Continua sendo o que se lê enquanto o\n // arquivo não chegou, e o que se lê para sempre se ele não chegar.\n const rotulo = <p className=\"whitespace-pre-wrap break-words\">{m.body}</p>\n\n if (erro) {\n return (\n <div ref={ref} className=\"space-y-1\">\n {rotulo}\n <p className=\"text-xs opacity-60\">O arquivo não carregou.</p>\n </div>\n )\n }\n\n if (!url) {\n return (\n <div ref={ref} className=\"space-y-1\">\n {rotulo}\n <div className=\"h-1 w-24 animate-pulse rounded bg-current opacity-20\" />\n </div>\n )\n }\n\n if (tipo === 'image' || tipo === 'sticker') {\n return (\n <div ref={ref} className=\"space-y-1\">\n <a href={url} target=\"_blank\" rel=\"noreferrer\">\n <img\n src={url}\n alt={legenda ?? (tipo === 'sticker' ? 'Figurinha' : 'Imagem recebida')}\n className={tipo === 'sticker' ? 'max-h-32 w-auto' : 'max-h-80 w-auto rounded-lg'}\n loading=\"lazy\"\n />\n </a>\n {legenda ? <p className=\"whitespace-pre-wrap break-words\">{legenda}</p> : null}\n </div>\n )\n }\n\n if (tipo === 'video') {\n return (\n <div ref={ref} className=\"space-y-1\">\n <video src={url} controls preload=\"metadata\" className=\"max-h-80 w-auto rounded-lg\" />\n {legenda ? <p className=\"whitespace-pre-wrap break-words\">{legenda}</p> : null}\n </div>\n )\n }\n\n if (tipo === 'audio') {\n return (\n <div ref={ref} className=\"space-y-1\">\n {/* `controls` nativo: o player do sistema já sabe tocar opus, arrastar\n e mudar a velocidade, e um player próprio seria trabalho para\n reimplementar o que o navegador faz melhor. */}\n <audio src={url} controls preload=\"metadata\" className=\"h-9 w-64 max-w-full\" />\n <p className=\"text-xs opacity-60\">\n {p.ptt ? 'Mensagem de voz' : 'Áudio'}\n {duracao(p.seconds) ? ` · ${duracao(p.seconds)}` : ''}\n </p>\n </div>\n )\n }\n\n // Documento: não há o que mostrar no lugar, então mostra-se o que ele É —\n // nome, tamanho e como pegá-lo.\n const nome = p.fileName ?? 'Documento'\n return (\n <div ref={ref} className=\"space-y-1\">\n <a\n href={url}\n target=\"_blank\"\n rel=\"noreferrer\"\n download={nome}\n className={`flex items-center gap-2 rounded-lg border p-2 ${outbound ? 'border-white/30' : 'border-black/10'}`}\n >\n <FileText className=\"h-5 w-5 shrink-0 opacity-70\" />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm\">{nome}</span>\n {tamanho(p.fileLength) ? <span className=\"block text-xs opacity-60\">{tamanho(p.fileLength)}</span> : null}\n </span>\n <Download className=\"h-4 w-4 shrink-0 opacity-70\" />\n </a>\n {legenda ? <p className=\"whitespace-pre-wrap break-words\">{legenda}</p> : null}\n </div>\n )\n}\n","import React from 'react'\nimport { useSendWindow, SendWindowBanner } from './SendWindow'\nimport { DeliveryMark, MessageMenu, isFailed } from './MessageInspector'\nimport { Send, Clock, Archive, PanelRight, MessageSquare, ChevronLeft, UserRound, Copy, Check } from 'lucide-react'\nimport { Button, Textarea, cn } from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport { useConversationsStore } from '../context'\nimport { CHANNEL_ACCENT, CHANNEL_LABELS } from '../lib/channel'\nimport type { Conversation, Message, SharedContact } from '../types'\nimport { Avatar, ChannelBadge, dayLabel } from './shared'\nimport { MediaBubble, temArquivo } from './MediaBubble'\n\n/**\n * A contact card someone forwarded into the thread.\n *\n * This is the shape the whole 012 change exists for: on 2026-09-22 a lead sent\n * his finance director's card, it rendered as an empty bubble, the SDR asked\n * him to type the number instead, and the screenshot he sent back rendered\n * empty too. The number was in the payload the entire time.\n *\n * The copy button is the point, not decoration — what someone does with a\n * forwarded number within seconds of seeing it is put it somewhere else.\n */\nfunction ContactCard({ contacts, outbound }: { contacts: SharedContact[]; outbound: boolean }) {\n const [copied, setCopied] = React.useState<string | null>(null)\n const copy = (value: string) => {\n void navigator.clipboard?.writeText(value)\n setCopied(value)\n // Long enough to register, short enough that the row is ready again before\n // anyone reaches for a second number on the same card.\n window.setTimeout(() => setCopied((c) => (c === value ? null : c)), 1500)\n }\n return (\n <div className=\"flex flex-col gap-2\">\n {contacts.map((c, i) => (\n <div\n key={`${c.name}-${i}`}\n className={cn(\n 'flex items-start gap-2.5 rounded-xl px-2.5 py-2',\n outbound ? 'bg-white/15' : 'bg-muted',\n )}\n >\n <UserRound className={cn('mt-0.5 h-4 w-4 shrink-0', outbound ? 'text-white/80' : 'text-muted-foreground')} />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate font-medium\">{c.name}</p>\n {c.phones.map((p) => (\n <Button variant=\"bare\" size=\"bare\"\n key={p.digits}\n type=\"button\"\n onClick={() => copy(p.display)}\n className={cn(\n 'group/phone mt-0.5 flex items-center justify-start gap-1.5 text-left text-[13px] font-normal tabular-nums',\n outbound ? 'text-white/90 hover:text-white' : 'text-muted-foreground hover:text-foreground',\n )}\n >\n {p.display}\n {copied === p.display\n ? <Check className=\"h-3 w-3\" />\n : <Copy className=\"h-3 w-3 opacity-0 transition-opacity group-hover/phone:opacity-100\" />}\n </Button>\n ))}\n </div>\n </div>\n ))}\n </div>\n )\n}\n\n/** The bubble's content. Text is the common case and stays exactly as it was;\n * everything else renders from `messageType`, which is null for any row\n * written before 012 — those fall through to their body, which is what they\n * have. */\nfunction MessageBody({ m, outbound }: { m: Message; outbound: boolean }) {\n const contacts = m.messageType === 'contact' ? m.payload?.contacts ?? [] : []\n if (contacts.length > 0) return <ContactCard contacts={contacts} outbound={outbound} />\n // Desde a 013 os bytes ficam conosco, e a bolha pode ser o arquivo em vez do\n // nome dele. `temArquivo` exige `media_path`: sem ele — texto, linha anterior\n // à 013, ou upload que não aconteceu — cai no rótulo, que é o que existe.\n if (temArquivo(m)) return <MediaBubble m={m} outbound={outbound} />\n return <p className=\"whitespace-pre-wrap break-words\">{m.body}</p>\n}\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, backAlways, className }: {\n selected: Conversation\n onTogglePanel: () => void\n panelOpen: boolean\n onBack?: () => void\n /** Keep \"back\" on wide screens too: in the floating inbox the list and the\n * thread take turns whatever the viewport is. */\n backAlways?: boolean\n className?: string\n}) {\n const t = useTranslation()\n const { messages, sending, send, setStatus, refreshMessages } = useConversationsStore((s) => s)\n const [draft, setDraft] = React.useState('')\n // Se dá para falar com esta pessoa AGORA, e por qual caminho. Lê a janela de\n // 24h da conversa E a capacidade do provedor ativo: o mesmo campo de texto é\n // seguro num provedor e mentiroso no outro.\n const win = useSendWindow(selected.id)\n const canType = win.mode.kind === 'free'\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 // O tique duplo chega pelo webhook, no banco, sem passar por aqui. Dez\n // segundos é o intervalo que faz \"entregue\" e \"lida\" aparecerem enquanto a\n // pessoa ainda olha a conversa, e é barato: uma consulta por thread aberta.\n //\n // Para quando a aba sai de foco. Uma caixa esquecida aberta a noite toda não\n // deve consultar 8.640 vezes por nada.\n React.useEffect(() => {\n if (!selected.id) return\n let timer: ReturnType<typeof setInterval> | null = null\n const start = () => { if (!timer) timer = setInterval(() => { void refreshMessages() }, 10_000) }\n const stop = () => { if (timer) { clearInterval(timer); timer = null } }\n const onVis = () => (document.visibilityState === 'visible' ? start() : stop())\n onVis()\n document.addEventListener('visibilitychange', onVis)\n return () => { stop(); document.removeEventListener('visibilitychange', onVis) }\n }, [selected.id, refreshMessages])\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={cn('-ml-1 shrink-0', !backAlways && '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 {/* Com o painel de detalhes ABERTO, canal e telefone já estão nele,\n uma coluna ao lado — repetir aqui é a mesma ficha duas vezes na\n mesma linha de leitura. O cabeçalho compacta para avatar + nome. */}\n {!panelOpen && (\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 )}\n </div>\n </div>\n <div className=\"flex shrink-0 items-center gap-1.5\">\n {/* ABRIR O LEAD, no lugar de \"Adiar\" e \"Encerrar\".\n Aqueles dois são vocabulário de suporte — uma fila de chamados que\n se despacha. Aqui a conversa é uma VENDA em andamento: ninguém\n \"encerra\" um lead que respondeu, e adiar é o que a fila da rota já\n faz com data. O que faltava era o caminho da conversa para a\n ficha, e ele não existia em lugar nenhum da tela. */}\n <Button variant=\"outline\" size=\"sm\" onClick={() => setStatus('closed')} aria-label=\"Arquivar\">\n <Archive className=\"h-3.5 w-3.5 sm:mr-1\" /> <span className=\"hidden sm:inline\">Arquivar</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 const failed = isFailed(m)\n return (\n <div\n key={row.id}\n className={cn('group flex items-center gap-1', outbound ? 'justify-end' : 'justify-start', row.startsRun ? 'mt-2.5' : 'mt-0.5')}\n >\n {/* O menu fica FORA do balão e do lado de dentro da conversa, para\n não empurrar o texto nem cobrir a hora. Aparece no hover. */}\n {outbound && <MessageMenu m={m} />}\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 // UMA MENSAGEM QUE FALHOU PRECISA PARECER QUE FALHOU. Duas\n // ficaram um dia na caixa com a cara de qualquer outra e nunca\n // chegaram a ninguém — não havia como saber olhando.\n outbound && failed && 'ring-2 ring-destructive',\n )}\n style={outbound ? { backgroundColor: failed ? 'hsl(var(--destructive))' : accent.color } : undefined}\n >\n <MessageBody m={m} outbound={outbound} />\n <div className={cn('mt-0.5 flex items-center justify-end gap-1 text-[10px]', outbound ? 'text-white/70' : 'text-muted-foreground')}>\n {new Date(m.at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}\n <DeliveryMark m={m} />\n </div>\n </div>\n {!outbound && <MessageMenu m={m} />}\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\">\n <SendWindowBanner state={win} />\n <div className=\"flex items-end gap-2 px-4 py-3\">\n <div className=\"flex-1\">\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 disabled={!canType}\n placeholder={\n canType\n ? t('conversations.thread.reply', { channel: CHANNEL_LABELS[selected.channel] })\n : win.mode.kind === 'blocked'\n ? 'Envio bloqueado'\n : 'Fora da janela — envie um template'\n }\n className=\"max-h-32 min-h-[40px] resize-none rounded-md border-border bg-background shadow-none focus:border-primary focus-visible:ring-0 focus-visible:ring-offset-0 disabled:bg-muted/40 disabled:text-muted-foreground disabled:opacity-100\"\n />\n </div>\n <Button onClick={() => void handleSend()} disabled={!canType || 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 { ExternalLink, Flame, Snowflake, Sun, Building2 } from 'lucide-react'\nimport { getSupabaseClientOptional, getActiveTenantId, appHref } from '@fayz-ai/core'\n\n/**\n * O lead, dentro da conversa.\n *\n * ── por que estes campos e não a ficha inteira ──────────────────────────\n *\n * Quem está respondendo tem uma pergunta só: \"com quem eu estou falando, e isto\n * é importante?\". A ficha inteira responde isso e mais quarenta coisas, e o\n * custo de ler quarenta é não ler nenhuma.\n *\n * Então: nome, empresa, temperatura, e os motivos que a produziram. O resto\n * está a um clique — e o clique existe, que é o outro defeito que isto conserta:\n * dava para ver o telefone do lead na conversa e não dava para chegar nele.\n *\n * ── sem import entre plugins ────────────────────────────────────────────\n *\n * Isto vive no plugin de conversas e lê tabelas do CRM. Não importa nada de\n * `plugin-crm`: as tabelas são do schema público com RLS por inquilino, e um\n * import amarraria a caixa de entrada a um plugin que pode não estar montado.\n * Mesmo princípio do `TalkToPerson`, que faz o caminho inverso.\n */\n\ninterface LeadBrief {\n id: string\n name: string\n company: string | null\n status: string | null\n sourceName: string | null\n temperature: 'hot' | 'warm' | 'cold' | null\n fitScore: number | null\n interestScore: number | null\n reasons: string[]\n}\n\nconst TEMP: Record<string, { icon: typeof Flame; cls: string; label: string }> = {\n hot: { icon: Flame, cls: 'bg-destructive-soft text-destructive-soft-foreground', label: 'Quente' },\n warm: { icon: Sun, cls: 'bg-warning-soft text-warning-soft-foreground', label: 'Morno' },\n cold: { icon: Snowflake, cls: 'bg-info-soft text-info-soft-foreground', label: 'Frio' },\n}\n\nexport function LeadCard({ personId, handle }: { personId?: string | null; handle?: string | null }) {\n const [lead, setLead] = React.useState<LeadBrief | null | undefined>(undefined)\n\n React.useEffect(() => {\n let alive = true\n const sb = getSupabaseClientOptional() as any\n const tenantId = getActiveTenantId()\n if (!sb || !tenantId || (!personId && !handle)) { setLead(null); return }\n\n ;(async () => {\n try {\n let q = sb.from('people')\n .select('id, name, metadata, phone')\n .eq('tenant_id', tenantId).eq('kind', 'lead').limit(1)\n // Pelo id quando a conversa já está vinculada; pelo telefone quando\n // não — e por DÍGITOS, porque o mesmo número aparece em três grafias.\n q = personId\n ? q.eq('id', personId)\n : q.like('phone', `%${String(handle).replace(/\\D/g, '').slice(-8)}`)\n const { data } = await q.maybeSingle()\n if (!alive) return\n if (!data) { setLead(null); return }\n\n const meta = (data.metadata ?? {}) as any\n let score: any = null\n try {\n const { data: s } = await sb.from('v_crm_lead_score')\n .select('temperature, fit_score, interest_score, reasons')\n .eq('lead_id', data.id).maybeSingle()\n score = s\n } catch { /* sem nota, o cartão mostra o resto */ }\n\n setLead({\n id: data.id, name: data.name,\n company: meta.company ?? null,\n status: meta.status ?? null,\n sourceName: meta.sourceName ?? null,\n temperature: score?.temperature ?? null,\n fitScore: score?.fit_score ?? null,\n interestScore: score?.interest_score ?? null,\n reasons: Array.isArray(score?.reasons) ? score.reasons : [],\n })\n } catch { if (alive) setLead(null) }\n })()\n return () => { alive = false }\n }, [personId, handle])\n\n if (lead === undefined) return <div className=\"px-4 py-3 text-xs text-muted-foreground\">carregando…</div>\n if (!lead) {\n return (\n <div className=\"border-t border-border px-4 py-3\">\n <p className=\"text-xs text-muted-foreground\">\n Este contato ainda não é um lead cadastrado.\n </p>\n </div>\n )\n }\n\n const t = lead.temperature ? TEMP[lead.temperature] : null\n const Icon = t?.icon\n\n return (\n <div className=\"border-t border-border px-4 py-3\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-semibold\">{lead.name}</p>\n {lead.company && (\n <p className=\"flex items-center gap-1 truncate text-xs text-muted-foreground\">\n <Building2 className=\"h-3 w-3 shrink-0\" /> {lead.company}\n </p>\n )}\n </div>\n {/* O caminho que faltava: da conversa para a ficha. */}\n <a\n href={appHref(`/sales/leads/${lead.id}`)}\n className=\"inline-flex shrink-0 items-center gap-1 rounded-button border bg-card px-2 py-1 text-[11px] font-medium hover:bg-muted\"\n >\n Abrir lead <ExternalLink className=\"h-3 w-3\" />\n </a>\n </div>\n\n <div className=\"mt-2 flex flex-wrap items-center gap-1.5\">\n {t && Icon && (\n <span className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-medium ${t.cls}`}>\n <Icon className=\"h-3 w-3\" /> {t.label}\n {lead.interestScore != null && <span className=\"tabular-nums opacity-70\">{lead.interestScore}</span>}\n </span>\n )}\n {lead.status && (\n <span className=\"rounded-full bg-muted px-2 py-0.5 text-[10px] capitalize text-muted-foreground\">{lead.status}</span>\n )}\n {lead.sourceName && (\n <span className=\"rounded-full bg-muted px-2 py-0.5 text-[10px] text-muted-foreground\">{lead.sourceName}</span>\n )}\n </div>\n\n {/* O PORQUÊ da temperatura. Sem ele o chip é um número que ninguém\n confere, e quem está respondendo não sabe o que puxar na conversa. */}\n {lead.reasons.length > 0 && (\n <ul className=\"mt-2 space-y-0.5\">\n {lead.reasons.slice(0, 4).map((r, i) => (\n <li key={i} className=\"flex gap-1.5 text-[11px] text-muted-foreground\">\n <span className=\"text-muted-foreground/40\">•</span><span>{r}</span>\n </li>\n ))}\n </ul>\n )}\n </div>\n )\n}\n","import React from 'react'\nimport { LeadCard } from './LeadCard'\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 '../lib/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 {/* O LEAD PRIMEIRO. \"Canal / Status / Responsável\" descrevem a\n conversa; quem está respondendo precisa saber de QUEM ela é — e\n precisa do caminho para a ficha, que não existia. */}\n <LeadCard personId={contact.contactPersonId} handle={contact.contactHandle} />\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 {/* O dono do LEAD, que é outra pergunta: quem ATENDE esta conversa\n pode não ser quem faz o follow-up no funil. As duas linhas ficam\n lado a lado de propósito — quando divergem, é informação. */}\n {contact.leadOwnerName && (\n <div className=\"flex items-center justify-between gap-2\">\n <dt className=\"text-muted-foreground\">{t('conversations.contact.leadOwner')}</dt>\n <dd className=\"font-medium text-foreground\">{contact.leadOwnerName}</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 { errorMessage } from '@fayz-ai/core'\nimport React from 'react'\nimport {\n Button, Textarea, cn, toast,\n Modal, ModalContent, ModalHeader, ModalTitle, ModalBody, ModalFooter,\n} from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport {\n useLimitGuard, invalidateLimit, ContactPicker,\n type ContactPickerValue,\n} from '@fayz-ai/admin'\nimport { useConversationsStore, useConversationsConfig } from '../context'\nimport { CHANNEL_ACCENT, CHANNEL_ICON, CHANNEL_LABELS } from '../lib/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\n/**\n * Starting a conversation, in a modal.\n *\n * It lived in the right rail for a while, but the inbox is already three\n * columns — list, thread, contact — and a fourth squeezed all of them into\n * slivers. The picker searches existing people by name, which covers the\n * \"does this thread already exist\" check the visible list used to serve.\n */\nexport function NewConversationPanel({\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 = errorMessage(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 className=\"max-w-md\">\n <ModalHeader>\n <ModalTitle>{t('conversations.new.title')}</ModalTitle>\n </ModalHeader>\n <form onSubmit={handleSubmit} className=\"flex min-h-0 flex-1 flex-col overflow-hidden\">\n <ModalBody className=\"space-y-4\">\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 variant=\"bare\" size=\"bare\"\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/admin), 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 lookup={config.contactLookup}\n createEntityDef={config.contactEntityDef}\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] resize-none rounded-md border-border bg-background shadow-none focus:border-primary focus-visible:ring-0 focus-visible:ring-offset-0\"\n />\n </div>\n\n </ModalBody>\n {/* No Cancel: the modal header already holds the way out. */}\n <ModalFooter>\n <Button type=\"submit\" disabled={!canSubmit} className=\"w-full\">\n {submitting ? t('conversations.new.creating') : t('conversations.new.create')}\n </Button>\n </ModalFooter>\n </form>\n </ModalContent>\n </Modal>\n )\n}\n","import * as React from 'react'\nimport { useActiveTenantId } from '@fayz-ai/core'\n\nimport { useConversationsStore } from '../context'\nimport { assinarChegada } from '../lib/campainha'\n\n/**\n * A caixa aberta se atualiza sozinha quando chega mensagem.\n *\n * ── por que o mesmo tópico do vigia ─────────────────────────────────────\n *\n * O aviso global (som, contagem, notificação do sistema) já escuta\n * `conversas:<tenant>`. A tela aberta precisa exatamente do mesmo sinal, e\n * assinar a TABELA aqui reintroduziria o defeito que levou dois dias para\n * achar: o Realtime resolve a conta pelo JWT, a política resolve por cabeçalho,\n * e quem atende mais de uma casa nunca recebe evento — sem erro nenhum.\n *\n * Dois ouvintes no mesmo tópico não se atrapalham: o servidor entrega a ambos,\n * e cada um faz o que lhe cabe. O vigia avisa; esta tela redesenha.\n *\n * ── por que recarregar em vez de aplicar o payload ──────────────────────\n *\n * A campainha traz só o id da conversa, de propósito — o conteúdo não viaja\n * pelo broadcast. Então a tela vai buscar: `load()` para a lista (que precisa\n * reordenar, atualizar a prévia e a hora) e `refreshMessages()` para a thread,\n * que só escreve se algo mudou e por isso não rouba a seleção de quem lê.\n *\n * É mais uma ida ao servidor do que aplicar o payload à mão, e é o que mantém\n * a tela com a MESMA verdade que um F5 mostraria — sem uma segunda montagem de\n * estado que envelhece em silêncio.\n */\nexport function useCaixaAoVivo() {\n const tenantId = useActiveTenantId()\n const load = useConversationsStore((s) => s.load)\n const refreshMessages = useConversationsStore((s) => s.refreshMessages)\n const selectedId = useConversationsStore((s) => s.selectedId)\n\n // Em refs para que a troca de conversa não derrube e recrie a assinatura:\n // sair e entrar do canal a cada clique na lista perde eventos na janela de\n // reconexão, que é justamente quando se está olhando.\n const abertoRef = React.useRef(selectedId)\n abertoRef.current = selectedId\n\n React.useEffect(() => {\n if (!tenantId) return\n return assinarChegada(tenantId, ({ conversationId }) => {\n void load()\n // A thread só quando é a conversa que está na tela. Recarregar a de\n // outra seria trabalho jogado fora e trocaria o que a pessoa está lendo.\n if (conversationId && conversationId === abertoRef.current) {\n void refreshMessages()\n }\n })\n }, [tenantId, load, refreshMessages])\n}\n","import React from 'react'\nimport { MessageSquare, SquarePen } from 'lucide-react'\nimport { Button, PageHeaderActions, cn } from '@fayz-ai/ui'\nimport { PageActions, useRightRailStore, type PageAction } from '@fayz-ai/admin'\nimport { useTranslation } from '@fayz-ai/core'\nimport { useConversationsStore } from '../context'\nimport { ConversationList } from './ConversationList'\nimport { MessageThread } from './MessageThread'\nimport { ContactPanel } from './ContactPanel'\nimport { NewConversationPanel } from './NewConversationPanel'\nimport { useMediaQuery } from './shared'\nimport { useCaixaAoVivo } from './useCaixaAoVivo'\n\n/**\n * `page` follows the viewport. In the floating inbox the panel is narrower than\n * the screen, so the layout follows the panel: `dock` takes turns between list\n * and thread, `dock-wide` puts them side by side. The contact panel always\n * slides over in a dock.\n */\nexport type InboxLayout = 'page' | 'dock' | 'dock-wide'\n\nexport function InboxView({ layout = 'page', newSignal = 0 }: {\n layout?: InboxLayout\n /** In a dock the \"new conversation\" button lives in the dock's header (the\n * page header belongs to the screen behind); each bump opens the composer. */\n newSignal?: number\n} = {}) {\n const t = useTranslation()\n const dock = layout !== 'page'\n const { conversations, selectedId, deselect } = useConversationsStore((s) => s)\n // A tela se atualiza sozinha: mesma campainha que o aviso global escuta.\n useCaixaAoVivo()\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 isWideViewport = useMediaQuery('(min-width: 1280px)')\n const isWidePanel = isWideViewport && !dock\n // The app's right rail (assistant) takes a fourth column; with it open the\n // contact panel turns three panes into slivers, so it yields and comes back\n // when the rail closes. Toggling it by hand is still the last word.\n const railOpen = useRightRailStore((s) => s.open)\n const [panelOpen, setPanelOpen] = React.useState(false)\n const [newOpen, setNewOpen] = React.useState(false)\n const selected = conversations.find((c) => c.id === selectedId) ?? null\n React.useEffect(() => { if (newSignal > 0) setNewOpen(true) }, [newSignal])\n\n // Open the panel by default only when it fits inline; collapse it otherwise.\n React.useEffect(() => {\n setPanelOpen(isWidePanel && !railOpen)\n }, [isWidePanel, railOpen])\n\n // Declared, not drawn: PageActions applies the role gate, gives the button\n // the same size every other list's primary has, and on a phone moves it to\n // the FAB in the thumb's corner instead of shrinking it to an icon squeezed\n // into the top bar.\n const newActions: PageAction[] = React.useMemo(() => [{\n id: 'new-conversation',\n label: t('conversations.list.new'),\n icon: SquarePen,\n intent: 'primary',\n // Starting a conversation creates a thread — the FAB is a \"+\".\n creates: true,\n testId: 'conversations-new',\n permission: { feature: 'conversations', action: 'create' },\n onSelect: () => setNewOpen(true),\n }], [t])\n\n return (\n <>\n {/* Outside the inbox row: with a header slot this portals and takes no\n space; without one it falls in as a block above the screen, rather\n than a column wedged between the list and the thread. */}\n {!dock && (\n <PageHeaderActions>\n <PageActions actions={newActions} />\n </PageHeaderActions>\n )}\n\n <NewConversationPanel open={newOpen} onOpenChange={setNewOpen} />\n\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(\n layout === 'page' && (selected ? 'hidden lg:flex' : 'flex'),\n layout === 'dock' && (selected ? 'hidden' : 'flex lg:w-full border-r-0'),\n layout === 'dock-wide' && 'flex lg:w-[300px]',\n )} />\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 backAlways={layout === 'dock'}\n className=\"flex\"\n />\n ) : layout === 'dock' ? null : (\n <section className={cn('min-w-0 flex-1 flex-col items-center justify-center bg-muted/20 text-muted-foreground', dock ? 'flex' : 'hidden 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 variant=\"bare\" size=\"bare\"\n className={cn('absolute inset-0 z-10 rounded-none bg-black/40', !dock && 'xl:hidden')}\n aria-label=\"Close details\"\n onClick={() => setPanelOpen(false)}\n />\n <ContactPanel\n contact={selected}\n onClose={() => setPanelOpen(false)}\n className={cn('absolute inset-y-0 right-0 z-20 w-[340px] max-w-[88%] shadow-2xl', !dock && 'xl:static xl:z-auto xl:w-[300px] xl:max-w-none xl:shadow-none')}\n />\n </>\n )}\n </div>\n </>\n )\n}\n","import React from 'react'\nimport type { StoreApi } from 'zustand/vanilla'\nimport { ConversationsContextProvider, type ResolvedConversationsConfig } from '../context'\nimport type { ConversationsUIState } from '../store'\nimport type { Channel } from '../types'\nimport { InboxView } from './InboxView'\nimport { currentAppPath, appHref } from '@fayz-ai/core'\n\nconst CHANNELS: Channel[] = ['sms', 'whatsapp', 'instagram', 'email', 'webchat']\n\n/** Quem o link de entrada pediu para abrir.\n *\n * A rota da shell é por hash, então os parâmetros vêm depois do `?` DENTRO do\n * hash — `#/conversations?personId=…`. `window.location.search` está vazio\n * aqui, e foi o primeiro lugar onde procurei.\n */\nfunction requestedContact(): { personId?: string; name: string; handle: string; channel: Channel } | null {\n try {\n const hash = currentAppPath()\n const qs = hash.includes('?') ? hash.slice(hash.indexOf('?') + 1) : ''\n if (!qs) return null\n const p = new URLSearchParams(qs)\n const handle = (p.get('handle') ?? '').trim()\n const name = (p.get('name') ?? '').trim()\n const personId = (p.get('personId') ?? '').trim() || undefined\n // Sem por onde falar não há conversa para abrir. Criar uma thread sem\n // handle produziria um registro que nunca entrega nada.\n if (!handle) return null\n const raw = (p.get('channel') ?? 'whatsapp').toLowerCase()\n const channel = (CHANNELS as string[]).includes(raw) ? (raw as Channel) : 'whatsapp'\n return { personId, name: name || handle, handle, channel }\n } catch {\n return null\n }\n}\n\nexport function ConversationsPage({ store, config }: {\n store: StoreApi<ConversationsUIState>\n config?: ResolvedConversationsConfig\n}) {\n React.useEffect(() => {\n const wanted = requestedContact()\n if (!wanted) {\n void store.getState().load()\n return\n }\n\n // `openForPerson` carrega a caixa sozinho quando precisa, então não há\n // `load()` aqui: os dois juntos disputariam a mesma lista e a thread recém\n // aberta poderia ser substituída pela resposta mais lenta.\n void store.getState().openForPerson(wanted).catch(() => {\n void store.getState().load()\n })\n\n // O parâmetro é uma ORDEM, não um estado: cumprida uma vez, sai da barra de\n // endereços. Sem isto, um F5 meia hora depois reabriria — ou pior,\n // recriaria — a conversa daquela pessoa, e o link ficaria colado no\n // histórico do navegador.\n try {\n const hash = currentAppPath()\n const clean = hash.includes('?') ? hash.slice(0, hash.indexOf('?')) : hash\n window.history.replaceState(null, '', appHref(clean || '/conversations'))\n } catch { /* a barra fica como está; a conversa já abriu */ }\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"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { COPY, WhatsAppProviders, listMessagingChannels, isPendingChannelStatus } from './chunk-
|
|
1
|
+
import { COPY, WhatsAppProviders, listMessagingChannels, isPendingChannelStatus } from './chunk-2JV6B366.js';
|
|
2
2
|
import { providersApi } from './chunk-HMWUU5O7.js';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { useTranslation, tl } from '@fayz-ai/core';
|
|
@@ -154,5 +154,5 @@ function ConversationsSettingsTab() {
|
|
|
154
154
|
ConversationsSettingsTab.displayName = "ConversationsSettingsTab";
|
|
155
155
|
|
|
156
156
|
export { ConversationsSettingsTab };
|
|
157
|
-
//# sourceMappingURL=ConversationsSettings-
|
|
158
|
-
//# sourceMappingURL=ConversationsSettings-
|
|
157
|
+
//# sourceMappingURL=ConversationsSettings-Q3PGQMB3.js.map
|
|
158
|
+
//# sourceMappingURL=ConversationsSettings-Q3PGQMB3.js.map
|
package/dist/{ConversationsSettings-7UQYM26R.js.map → ConversationsSettings-Q3PGQMB3.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/settings/WhatsAppConnectorList.tsx","../src/settings/ConversationsSettings.tsx"],"names":["jsxs","jsx","Badge","React2","tl"],"mappings":"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","file":"ConversationsSettings-7UQYM26R.js","sourcesContent":["import * as React from 'react'\nimport { tl } from '@fayz-ai/core'\nimport {\n ConnectorMark, StateChip, ConnectorDetail, useConnectors, openConnectorsPanel, useConnectorsPanelAvailable,\n type UnifiedConnector,\n} from '@fayz-ai/admin'\nimport { Badge, Button, Sheet, SheetBody, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@fayz-ai/ui'\nimport { providersApi, type ProviderId, type ProviderRow } from '../data/providers'\nimport { WhatsAppProviders, WHATSAPP_PROVIDER_COPY } from './WhatsAppProviders'\n\n// Providers with no connector here yet: listed so the house sees its provider\n// is known, not missing.\nconst UPCOMING = ['Meta Cloud API', 'Z-API', 'Twilio']\nconst PROVIDERS: ProviderId[] = ['tyxter', 'evolution']\n\nfunction providerState(row: ProviderRow | undefined): { label: string; tone: 'default' | 'secondary' | 'outline' } {\n if (row?.isActive) return { label: tl('In use', 'Valendo agora'), tone: 'default' }\n if (row?.hasCredential) return { label: tl('Connected', 'Conectado'), tone: 'secondary' }\n return { label: tl('Not connected', 'Não conectado'), tone: 'outline' }\n}\n\n/**\n * Where WhatsApp goes out, as one list (the Maquininhas pattern): mark, name,\n * state, one line, and Conectar/Configurar. Each provider's credentials,\n * test, numbers and pairing live in its own detail, not on this screen.\n */\nexport function WhatsAppConnectorList() {\n const [rows, setRows] = React.useState<ProviderRow[] | null>(null)\n const [open, setOpen] = React.useState<ProviderId | null>(null)\n const [hubSelected, setHubSelected] = React.useState<UnifiedConnector | null>(null)\n const { connectors } = useConnectors({ hostPluginId: 'conversations', includeGrants: false })\n const panelAvailable = useConnectorsPanelAvailable()\n\n const load = React.useCallback(() => {\n providersApi.list().then(setRows).catch(() => setRows([]))\n }, [])\n React.useEffect(load, [load])\n\n // Hub connectors of this inbox that are not one of the two providers above.\n const others = (connectors ?? []).filter((c) => !PROVIDERS.includes(c.slug as ProviderId))\n const byId = Object.fromEntries((rows ?? []).map((r) => [r.provider, r])) as Record<string, ProviderRow | undefined>\n const tyxterHub = (connectors ?? []).find((c) => c.slug === 'tyxter')\n\n return (\n <div className=\"space-y-2\">\n <h3 className=\"px-1 text-sm font-semibold\">{tl('WhatsApp providers', 'Provedores de WhatsApp')}</h3>\n <ul className=\"divide-y rounded-card border bg-card shadow-sm\">\n {PROVIDERS.map((p) => {\n const row = byId[p]\n const state = providerState(row)\n const copy = WHATSAPP_PROVIDER_COPY[p]\n return (\n <li key={p} className=\"flex items-center gap-3 p-4\">\n {p === 'tyxter' && tyxterHub ? <ConnectorMark connector={tyxterHub} /> : (\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-muted text-xs font-semibold text-muted-foreground\">\n {copy.name.slice(0, 2)}\n </span>\n )}\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium\">{copy.name}</span>\n <Badge variant={state.tone} className=\"font-normal\">{state.label}</Badge>\n </span>\n <span className=\"mt-0.5 block text-xs text-muted-foreground\">{copy.what}</span>\n </span>\n <Button variant=\"outline\" className=\"h-9 shrink-0\" onClick={() => setOpen(p)}>\n {row?.hasCredential ? tl('Configure', 'Configurar') : tl('Connect', 'Conectar')}\n </Button>\n </li>\n )\n })}\n {others.map((c) => (\n <li key={c.id} className=\"flex items-center gap-3 p-4\">\n <ConnectorMark connector={c} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium\">{c.name}</span>\n <StateChip state={c.state} />\n </span>\n {c.description && <span className=\"mt-0.5 block text-xs text-muted-foreground\">{c.description}</span>}\n </span>\n <Button variant=\"outline\" className=\"h-9 shrink-0\"\n onClick={() => (panelAvailable ? openConnectorsPanel(c) : setHubSelected(c))}>\n {c.state === 'connected' ? tl('Configure', 'Configurar') : tl('Connect', 'Conectar')}\n </Button>\n </li>\n ))}\n {UPCOMING.map((name) => (\n <li key={name} className=\"flex items-center gap-3 p-4 opacity-70\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-muted text-xs font-semibold text-muted-foreground\">\n {name.slice(0, 2)}\n </span>\n <span className=\"min-w-0 flex-1 font-medium\">{name}</span>\n <Badge variant=\"secondary\">{tl('Coming soon', 'Em breve')}</Badge>\n </li>\n ))}\n </ul>\n\n <Sheet open={!!open} onOpenChange={(o) => { if (!o) setOpen(null) }}>\n <SheetContent width=\"max-w-xl\">\n <SheetHeader>\n <SheetTitle>{open ? WHATSAPP_PROVIDER_COPY[open].name : ''}</SheetTitle>\n <SheetDescription>\n {tl('One provider sends at a time; the other keeps its settings.', 'Um provedor envia por vez; o outro guarda a configuração.')}\n </SheetDescription>\n </SheetHeader>\n <SheetBody>{open && <WhatsAppProviders only={open} onChanged={load} />}</SheetBody>\n </SheetContent>\n </Sheet>\n <ConnectorDetail connector={hubSelected} open={!!hubSelected} onOpenChange={(o) => { if (!o) setHubSelected(null) }} />\n </div>\n )\n}\n","import * as React from 'react'\nimport { WhatsAppConnectorList } from './WhatsAppConnectorList'\nimport { tl, useTranslation } from '@fayz-ai/core'\nimport { PluginSettingsPanel, SettingsGroup } from '@fayz-ai/admin'\nimport { Badge } from '@fayz-ai/ui'\nimport {\n listMessagingChannels,\n isPendingChannelStatus,\n type MessagingChannelAccount,\n} from '../data/channels'\n\n// ---------------------------------------------------------------------------\n// The inbox's settings screen.\n//\n// It exists for one reason: without it the WhatsApp connector is UNREACHABLE.\n// Connectors are surfaced by PluginSettingsPanel's Integrations tab, and that\n// tab only exists inside a plugin settings panel — so a plugin that declares a\n// connector and no settings route has declared a connector nobody can open.\n// Every app that mounted the inbox alone was in exactly that state.\n//\n// The General tab is deliberately not a copy of the connector's panel. That one\n// manages the Tyxter account (claim a number, register with Meta). This one\n// answers the question somebody asks BEFORE they know a connector exists:\n// \"why isn't my WhatsApp showing up in here?\" — so it states, plainly, which\n// numbers this inbox can send and receive by, and sends you one tab over when\n// the answer is \"none\".\n// ---------------------------------------------------------------------------\n\nfunction channelLabel(\n account: MessagingChannelAccount,\n t: (key: string) => string,\n): string {\n const key = `conversations.filter.${account.channel}`\n const translated = t(key)\n return translated === key ? account.channel : translated\n}\n\nfunction ChannelRow({ account }: { account: MessagingChannelAccount }) {\n const t = useTranslation()\n const pending = isPendingChannelStatus(account.status)\n return (\n <div className=\"flex items-center justify-between gap-3 border-b py-2.5 last:border-b-0\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium\">\n {account.phoneE164 ?? account.displayName ?? channelLabel(account, t)}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {channelLabel(account, t)}\n {' · '}\n {t(\n account.kind === 'dedicated'\n ? 'conversations.settings.channelDedicated'\n : 'conversations.settings.channelShared',\n )}\n </p>\n </div>\n {/* The provider's own word for the state, translated where we have a\n translation and passed through where we do not — a status invented\n here would drift from what the connector panel says one tab over. */}\n <Badge variant={account.status === 'active' ? 'default' : pending ? 'secondary' : 'outline'}>\n {t(`conversations.settings.status.${account.status}`) === `conversations.settings.status.${account.status}`\n ? account.status\n : t(`conversations.settings.status.${account.status}`)}\n </Badge>\n </div>\n )\n}\n\nfunction ConversationsGeneralSettings() {\n const t = useTranslation()\n const [channels, setChannels] = React.useState<MessagingChannelAccount[] | null>(null)\n // `null` = still loading, `[]` = loaded and empty, `'error'` = could not ask.\n // Three states and not two, because \"nenhum número conectado\" and \"não\n // consegui perguntar\" send somebody to opposite places.\n const [failed, setFailed] = React.useState(false)\n\n React.useEffect(() => {\n let cancelled = false\n listMessagingChannels()\n .then((rows) => { if (!cancelled) setChannels(rows) })\n .catch(() => { if (!cancelled) { setFailed(true); setChannels([]) } })\n return () => { cancelled = true }\n }, [])\n\n return (\n <div className=\"space-y-6\">\n <SettingsGroup\n title={t('conversations.settings.channels')}\n description={t('conversations.settings.channelsHelp')}\n >\n {channels === null && (\n <p className=\"py-2 text-sm text-muted-foreground\">{t('conversations.list.loading')}</p>\n )}\n {channels !== null && failed && (\n <p className=\"py-2 text-sm text-muted-foreground\">\n {t('conversations.settings.channelsUnavailable')}\n </p>\n )}\n {channels !== null && !failed && channels.length === 0 && (\n <p className=\"py-2 text-sm text-muted-foreground\">\n {t('conversations.settings.channelsEmpty')}\n </p>\n )}\n {channels?.map((account) => <ChannelRow key={account.id} account={account} />)}\n </SettingsGroup>\n </div>\n )\n}\nConversationsGeneralSettings.displayName = 'ConversationsGeneralSettings'\n\nexport function ConversationsSettingsTab() {\n const t = useTranslation()\n return (\n <PluginSettingsPanel\n title={t('conversations.settings.title')}\n generalSettings={<ConversationsGeneralSettings />}\n customTabs={[{ id: 'connectors', label: tl('Connectors', 'Conectores'), icon: 'Plug', content: <WhatsAppConnectorList /> }]}\n routeBase=\"/settings/conversations\"\n />\n )\n}\nConversationsSettingsTab.displayName = 'ConversationsSettingsTab'\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/settings/WhatsAppConnectorList.tsx","../src/settings/ConversationsSettings.tsx"],"names":["jsxs","jsx","Badge","React2","tl"],"mappings":"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","file":"ConversationsSettings-Q3PGQMB3.js","sourcesContent":["import * as React from 'react'\nimport { tl } from '@fayz-ai/core'\nimport {\n ConnectorMark, StateChip, ConnectorDetail, useConnectors, openConnectorsPanel, useConnectorsPanelAvailable,\n type UnifiedConnector,\n} from '@fayz-ai/admin'\nimport { Badge, Button, Sheet, SheetBody, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@fayz-ai/ui'\nimport { providersApi, type ProviderId, type ProviderRow } from '../data/providers'\nimport { WhatsAppProviders, WHATSAPP_PROVIDER_COPY } from './WhatsAppProviders'\n\n// Providers with no connector here yet: listed so the house sees its provider\n// is known, not missing.\nconst UPCOMING = ['Meta Cloud API', 'Z-API', 'Twilio']\nconst PROVIDERS: ProviderId[] = ['tyxter', 'evolution']\n\nfunction providerState(row: ProviderRow | undefined): { label: string; tone: 'default' | 'secondary' | 'outline' } {\n if (row?.isActive) return { label: tl('In use', 'Valendo agora'), tone: 'default' }\n if (row?.hasCredential) return { label: tl('Connected', 'Conectado'), tone: 'secondary' }\n return { label: tl('Not connected', 'Não conectado'), tone: 'outline' }\n}\n\n/**\n * Where WhatsApp goes out, as one list (the Maquininhas pattern): mark, name,\n * state, one line, and Conectar/Configurar. Each provider's credentials,\n * test, numbers and pairing live in its own detail, not on this screen.\n */\nexport function WhatsAppConnectorList() {\n const [rows, setRows] = React.useState<ProviderRow[] | null>(null)\n const [open, setOpen] = React.useState<ProviderId | null>(null)\n const [hubSelected, setHubSelected] = React.useState<UnifiedConnector | null>(null)\n const { connectors } = useConnectors({ hostPluginId: 'conversations', includeGrants: false })\n const panelAvailable = useConnectorsPanelAvailable()\n\n const load = React.useCallback(() => {\n providersApi.list().then(setRows).catch(() => setRows([]))\n }, [])\n React.useEffect(load, [load])\n\n // Hub connectors of this inbox that are not one of the two providers above.\n const others = (connectors ?? []).filter((c) => !PROVIDERS.includes(c.slug as ProviderId))\n const byId = Object.fromEntries((rows ?? []).map((r) => [r.provider, r])) as Record<string, ProviderRow | undefined>\n const tyxterHub = (connectors ?? []).find((c) => c.slug === 'tyxter')\n\n return (\n <div className=\"space-y-2\">\n <h3 className=\"px-1 text-sm font-semibold\">{tl('WhatsApp providers', 'Provedores de WhatsApp')}</h3>\n <ul className=\"divide-y rounded-card border bg-card shadow-sm\">\n {PROVIDERS.map((p) => {\n const row = byId[p]\n const state = providerState(row)\n const copy = WHATSAPP_PROVIDER_COPY[p]\n return (\n <li key={p} className=\"flex items-center gap-3 p-4\">\n {p === 'tyxter' && tyxterHub ? <ConnectorMark connector={tyxterHub} /> : (\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-muted text-xs font-semibold text-muted-foreground\">\n {copy.name.slice(0, 2)}\n </span>\n )}\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium\">{copy.name}</span>\n <Badge variant={state.tone} className=\"font-normal\">{state.label}</Badge>\n </span>\n <span className=\"mt-0.5 block text-xs text-muted-foreground\">{copy.what}</span>\n </span>\n <Button variant=\"outline\" className=\"h-9 shrink-0\" onClick={() => setOpen(p)}>\n {row?.hasCredential ? tl('Configure', 'Configurar') : tl('Connect', 'Conectar')}\n </Button>\n </li>\n )\n })}\n {others.map((c) => (\n <li key={c.id} className=\"flex items-center gap-3 p-4\">\n <ConnectorMark connector={c} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium\">{c.name}</span>\n <StateChip state={c.state} />\n </span>\n {c.description && <span className=\"mt-0.5 block text-xs text-muted-foreground\">{c.description}</span>}\n </span>\n <Button variant=\"outline\" className=\"h-9 shrink-0\"\n onClick={() => (panelAvailable ? openConnectorsPanel(c) : setHubSelected(c))}>\n {c.state === 'connected' ? tl('Configure', 'Configurar') : tl('Connect', 'Conectar')}\n </Button>\n </li>\n ))}\n {UPCOMING.map((name) => (\n <li key={name} className=\"flex items-center gap-3 p-4 opacity-70\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-muted text-xs font-semibold text-muted-foreground\">\n {name.slice(0, 2)}\n </span>\n <span className=\"min-w-0 flex-1 font-medium\">{name}</span>\n <Badge variant=\"secondary\">{tl('Coming soon', 'Em breve')}</Badge>\n </li>\n ))}\n </ul>\n\n <Sheet open={!!open} onOpenChange={(o) => { if (!o) setOpen(null) }}>\n <SheetContent width=\"max-w-xl\">\n <SheetHeader>\n <SheetTitle>{open ? WHATSAPP_PROVIDER_COPY[open].name : ''}</SheetTitle>\n <SheetDescription>\n {tl('One provider sends at a time; the other keeps its settings.', 'Um provedor envia por vez; o outro guarda a configuração.')}\n </SheetDescription>\n </SheetHeader>\n <SheetBody>{open && <WhatsAppProviders only={open} onChanged={load} />}</SheetBody>\n </SheetContent>\n </Sheet>\n <ConnectorDetail connector={hubSelected} open={!!hubSelected} onOpenChange={(o) => { if (!o) setHubSelected(null) }} />\n </div>\n )\n}\n","import * as React from 'react'\nimport { WhatsAppConnectorList } from './WhatsAppConnectorList'\nimport { tl, useTranslation } from '@fayz-ai/core'\nimport { PluginSettingsPanel, SettingsGroup } from '@fayz-ai/admin'\nimport { Badge } from '@fayz-ai/ui'\nimport {\n listMessagingChannels,\n isPendingChannelStatus,\n type MessagingChannelAccount,\n} from '../data/channels'\n\n// ---------------------------------------------------------------------------\n// The inbox's settings screen.\n//\n// It exists for one reason: without it the WhatsApp connector is UNREACHABLE.\n// Connectors are surfaced by PluginSettingsPanel's Integrations tab, and that\n// tab only exists inside a plugin settings panel — so a plugin that declares a\n// connector and no settings route has declared a connector nobody can open.\n// Every app that mounted the inbox alone was in exactly that state.\n//\n// The General tab is deliberately not a copy of the connector's panel. That one\n// manages the Tyxter account (claim a number, register with Meta). This one\n// answers the question somebody asks BEFORE they know a connector exists:\n// \"why isn't my WhatsApp showing up in here?\" — so it states, plainly, which\n// numbers this inbox can send and receive by, and sends you one tab over when\n// the answer is \"none\".\n// ---------------------------------------------------------------------------\n\nfunction channelLabel(\n account: MessagingChannelAccount,\n t: (key: string) => string,\n): string {\n const key = `conversations.filter.${account.channel}`\n const translated = t(key)\n return translated === key ? account.channel : translated\n}\n\nfunction ChannelRow({ account }: { account: MessagingChannelAccount }) {\n const t = useTranslation()\n const pending = isPendingChannelStatus(account.status)\n return (\n <div className=\"flex items-center justify-between gap-3 border-b py-2.5 last:border-b-0\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium\">\n {account.phoneE164 ?? account.displayName ?? channelLabel(account, t)}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {channelLabel(account, t)}\n {' · '}\n {t(\n account.kind === 'dedicated'\n ? 'conversations.settings.channelDedicated'\n : 'conversations.settings.channelShared',\n )}\n </p>\n </div>\n {/* The provider's own word for the state, translated where we have a\n translation and passed through where we do not — a status invented\n here would drift from what the connector panel says one tab over. */}\n <Badge variant={account.status === 'active' ? 'default' : pending ? 'secondary' : 'outline'}>\n {t(`conversations.settings.status.${account.status}`) === `conversations.settings.status.${account.status}`\n ? account.status\n : t(`conversations.settings.status.${account.status}`)}\n </Badge>\n </div>\n )\n}\n\nfunction ConversationsGeneralSettings() {\n const t = useTranslation()\n const [channels, setChannels] = React.useState<MessagingChannelAccount[] | null>(null)\n // `null` = still loading, `[]` = loaded and empty, `'error'` = could not ask.\n // Three states and not two, because \"nenhum número conectado\" and \"não\n // consegui perguntar\" send somebody to opposite places.\n const [failed, setFailed] = React.useState(false)\n\n React.useEffect(() => {\n let cancelled = false\n listMessagingChannels()\n .then((rows) => { if (!cancelled) setChannels(rows) })\n .catch(() => { if (!cancelled) { setFailed(true); setChannels([]) } })\n return () => { cancelled = true }\n }, [])\n\n return (\n <div className=\"space-y-6\">\n <SettingsGroup\n title={t('conversations.settings.channels')}\n description={t('conversations.settings.channelsHelp')}\n >\n {channels === null && (\n <p className=\"py-2 text-sm text-muted-foreground\">{t('conversations.list.loading')}</p>\n )}\n {channels !== null && failed && (\n <p className=\"py-2 text-sm text-muted-foreground\">\n {t('conversations.settings.channelsUnavailable')}\n </p>\n )}\n {channels !== null && !failed && channels.length === 0 && (\n <p className=\"py-2 text-sm text-muted-foreground\">\n {t('conversations.settings.channelsEmpty')}\n </p>\n )}\n {channels?.map((account) => <ChannelRow key={account.id} account={account} />)}\n </SettingsGroup>\n </div>\n )\n}\nConversationsGeneralSettings.displayName = 'ConversationsGeneralSettings'\n\nexport function ConversationsSettingsTab() {\n const t = useTranslation()\n return (\n <PluginSettingsPanel\n title={t('conversations.settings.title')}\n generalSettings={<ConversationsGeneralSettings />}\n customTabs={[{ id: 'connectors', label: tl('Connectors', 'Conectores'), icon: 'Plug', content: <WhatsAppConnectorList /> }]}\n routeBase=\"/settings/conversations\"\n />\n )\n}\nConversationsSettingsTab.displayName = 'ConversationsSettingsTab'\n"]}
|