@fayz-ai/plugin-agenda 0.27.10 → 0.27.12

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.
Files changed (45) hide show
  1. package/dist/AgendaGeneralSettings-YBI43RB6.js +96 -0
  2. package/dist/AgendaGeneralSettings-YBI43RB6.js.map +1 -0
  3. package/dist/AgendaMessageTemplates-46ZLTFLM.js +31 -0
  4. package/dist/AgendaMessageTemplates-46ZLTFLM.js.map +1 -0
  5. package/dist/AgendaPage-43OXQDZE.js +3174 -0
  6. package/dist/AgendaPage-43OXQDZE.js.map +1 -0
  7. package/dist/CheckinPage-SGWK2TQZ.js +904 -0
  8. package/dist/CheckinPage-SGWK2TQZ.js.map +1 -0
  9. package/dist/ConfirmationsView-DZJSYBXA.js +361 -0
  10. package/dist/ConfirmationsView-DZJSYBXA.js.map +1 -0
  11. package/dist/MyClientsTodayWidget-ZGTXJJKN.js +127 -0
  12. package/dist/MyClientsTodayWidget-ZGTXJJKN.js.map +1 -0
  13. package/dist/PersonAttendanceBlock-PHZVHFQ4.js +105 -0
  14. package/dist/PersonAttendanceBlock-PHZVHFQ4.js.map +1 -0
  15. package/dist/PersonAttendancesWidget-3NTWBGCU.js +1278 -0
  16. package/dist/PersonAttendancesWidget-3NTWBGCU.js.map +1 -0
  17. package/dist/PersonServicesWidget-4RJGKX3K.js +80 -0
  18. package/dist/PersonServicesWidget-4RJGKX3K.js.map +1 -0
  19. package/dist/chunk-37INOUNW.js +20 -0
  20. package/dist/chunk-37INOUNW.js.map +1 -0
  21. package/dist/chunk-A2VD5DVN.js +12 -0
  22. package/dist/chunk-A2VD5DVN.js.map +1 -0
  23. package/dist/chunk-HGJI2JR6.js +169 -0
  24. package/dist/chunk-HGJI2JR6.js.map +1 -0
  25. package/dist/chunk-VFQPXKXP.js +11 -0
  26. package/dist/chunk-VFQPXKXP.js.map +1 -0
  27. package/dist/chunk-WNANVT4F.js +2386 -0
  28. package/dist/chunk-WNANVT4F.js.map +1 -0
  29. package/dist/chunk-X7PKHXT6.js +18 -0
  30. package/dist/chunk-X7PKHXT6.js.map +1 -0
  31. package/dist/chunk-XTNSK4RJ.js +12 -0
  32. package/dist/chunk-XTNSK4RJ.js.map +1 -0
  33. package/dist/components/PersonAttendanceBlock.d.ts.map +1 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +2530 -19553
  36. package/dist/index.js.map +1 -1
  37. package/dist/migrations/integrations-google-calendar.browser.js +15 -0
  38. package/dist/migrations/integrations-google-calendar.browser.js.map +1 -0
  39. package/dist/migrations/integrations-google-calendar.js +1992 -0
  40. package/dist/migrations/integrations-google-calendar.js.map +1 -0
  41. package/dist/migrations/main.browser.js +29 -0
  42. package/dist/migrations/main.browser.js.map +1 -0
  43. package/dist/migrations/main.js +6440 -0
  44. package/dist/migrations/main.js.map +1 -0
  45. package/package.json +13 -7
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/views/ConfirmationsView.tsx"],"names":[],"mappings":"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","file":"ConfirmationsView-DZJSYBXA.js","sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from 'react'\nimport { CheckCircle, ChevronDown, XCircle, Clock, Loader2, Check, X } from 'lucide-react'\nimport { Button, Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@fayz-ai/ui'\nimport { FilterCheckRow } from '@fayz-ai/ui'\nimport { PersonLink } from '@fayz-ai/admin'\nimport { useTranslation, formatCurrency } from '@fayz-ai/core'\nimport { useAgendaConfig, useAgendaStore } from '../context'\nimport { usePluginPrefs } from '@fayz-ai/admin'\nimport { AgendaFilterRail, AgendaWorkspace, AdaptiveFilter } from '../components/AgendaFilterRail'\nimport { BookingCard, ClientContactButton } from '../components/BookingCard'\nimport type { CalendarBooking, ConfirmationRecord } from '../types'\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n\n\n/**\n * A COR DE CADA ESTADO, em três lugares: a faixa da esquerda, a moldura e o\n * selo.\n *\n * A faixa é o que se lê varrendo a coluna, sem ler palavra nenhuma; a moldura\n * tinge o cartão de leve para o estado alcançar a linha inteira; o selo é o\n * mesmo fato ESCRITO, porque cor sozinha não é informação para quem não a\n * distingue.\n */\n/**\n * As janelas que uma recepção de fato usa.\n *\n * Não é um seletor de datas: confirmar é sempre para FRENTE, e \"de 12 a 19 de\n * outubro\" é uma pergunta que ninguém faz ao telefone. Hoje, amanhã, a semana.\n */\nconst HORIZONS = [\n { days: 1, label: 'Só hoje', short: 'hoje' },\n { days: 2, label: 'Hoje e amanhã', short: '2 dias' },\n { days: 3, label: 'Próximos 3 dias', short: '3 dias' },\n { days: 7, label: 'Próximos 7 dias', short: '7 dias' },\n]\n\nconst STATE_TONE: Record<string, { flag: string; border: string; badge: string }> = {\n pending: {\n flag: 'bg-warning',\n border: 'border-warning/40',\n badge: 'bg-warning/15 text-warning-foreground',\n },\n sent: {\n flag: 'bg-info',\n border: 'border-info/40',\n badge: 'bg-info/15 text-info',\n },\n confirmed: {\n flag: 'bg-success',\n border: 'border-success/40',\n badge: 'bg-success/15 text-success',\n },\n declined: {\n flag: 'bg-destructive',\n border: 'border-destructive/40',\n badge: 'bg-destructive/15 text-destructive',\n },\n}\n\nconst STATE_LABEL = (t: (key: string) => string): Record<string, string> => ({\n pending: t('agenda.confirmations.statePending'),\n sent: t('agenda.confirmations.stateSent'),\n confirmed: t('agenda.confirmations.stateConfirmed'),\n declined: t('agenda.confirmations.stateDeclined'),\n})\n\nfunction getConfirmationStatus(booking: CalendarBooking): string {\n // O ESTADO DO AGENDAMENTO GANHA DO HISTÓRICO DE ENVIOS.\n //\n // `metadata.confirmations` guarda o que SAIU — a mensagem enviada, a\n // resposta registrada. Mas quem confirma no balcão, ou pelo telefone, muda\n // `status` e não passa por canal nenhum: o cartão ficava \"Pendente\" de\n // borda âmbar logo depois de alguém clicar em Confirmar, porque a única\n // coisa que ele olhava era o histórico de envios.\n if (booking.status === 'confirmed') return 'confirmed'\n if (booking.status === 'cancelled' || booking.status === 'no_show') return 'declined'\n const confirmations = booking.metadata?.confirmations as ConfirmationRecord[] | undefined\n if (!confirmations?.length) return 'pending'\n const last = confirmations[confirmations.length - 1]\n return last.status\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Um grupo que se dobra, com a conta no cabeçalho.\n *\n * O `FilterSection` da coluna da esquerda faz o mesmo gesto, mas ele é do\n * primitivo de FILTRO: usá-lo aqui amarraria a lista a um componente que um\n * dia vai ganhar comportamento de filtro. O gesto é curto o bastante para\n * viver aqui, e o cabeçalho é outro — ele conta linhas, não seleções.\n */\nfunction Group({\n title, count, defaultOpen, empty, pulse, children,\n}: {\n title: string\n count: number\n defaultOpen?: boolean\n /** O que dizer quando o grupo está aberto e vazio. */\n empty?: string\n /**\n * O contador acabou de subir.\n *\n * Um cartão que desce para um grupo FECHADO desaparece, e sem nada piscando\n * no destino a pessoa não sabe para onde ele foi. O número crescendo é a\n * outra ponta do movimento.\n */\n pulse?: boolean\n children: React.ReactNode\n}) {\n const [open, setOpen] = useState(defaultOpen ?? true)\n return (\n <section>\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n onClick={() => setOpen((p) => !p)}\n aria-expanded={open}\n className=\"justify-start whitespace-normal mb-2 flex w-full items-center gap-2 text-left text-xs font-medium text-muted-foreground transition-colors hover:text-foreground\"\n >\n <ChevronDown className={`h-3.5 w-3.5 shrink-0 transition-transform ${open ? '' : '-rotate-90'}`} />\n <span>{title}</span>\n <span className={`rounded-full px-1.5 py-px text-[10px] font-semibold tabular-nums transition-all duration-300 ${\n pulse\n ? 'scale-125 bg-success text-white'\n : 'scale-100 bg-muted text-muted-foreground'\n }`}>\n {count}\n </span>\n </Button>\n {open && (count > 0\n ? <ul className=\"space-y-2\">{children}</ul>\n : empty\n ? <p className=\"px-1 pb-1 text-xs text-muted-foreground\">{empty}</p>\n : null)}\n </section>\n )\n}\n\nexport function ConfirmationsView() {\n const t = useTranslation()\n const config = useAgendaConfig()\n const confirmations = useAgendaStore((s) => s.pendingConfirmations)\n const loading = useAgendaStore((s) => s.confirmationsLoading)\n const fetchConfirmations = useAgendaStore((s) => s.fetchConfirmations)\n const updateStatus = useAgendaStore((s) => s.updateBookingStatus)\n\n /**\n * ATÉ ONDE A LISTA OLHA — e a tela diz qual é.\n *\n * O alcance era 2 dias FIXOS dentro da consulta, e invisível: uma lista\n * vazia dizia \"não há ninguém para confirmar\" quando às vezes dizia \"o teu\n * alcance é curto\". A casa que confirma com três dias de antecedência não\n * tinha como pedir. O V1 resolve com DE e ATÉ; aqui é um horizonte, que é a\n * pergunta real — \"quem vem nos próximos N dias\" —, e ele fica GRAVADO: a\n * antecedência de confirmar é hábito da casa, não escolha de cada manhã.\n */\n const prefs = usePluginPrefs('agenda', { confirmationDays: 2 })\n const days = Number(prefs.get('confirmationDays') ?? 2) || 2\n\n useEffect(() => { void fetchConfirmations(days) }, [days, fetchConfirmations])\n\n // ── Os filtros ──────────────────────────────────────────────────────────\n // Esta era a ÚNICA das quatro telas do módulo sem coluna à esquerda, e a\n // lista dela é a que mais cresce: tudo que ainda não foi confirmado, de hoje\n // até onde o alcance for. Sem recorte, quem liga para confirmar procura na\n // rolagem a pessoa que já tentou ontem.\n //\n // Três eixos, e só três — todos MODELADOS aqui: quem vai atender, em que\n // estado está a confirmação, e o nome de quem se procura. Nada de período:\n // quem decide o alcance é `getConfirmationsPending`, e um filtro que\n // promete uma data que a consulta não trouxe mente.\n const [term, setTerm] = useState('')\n const [shownPros, setShownPros] = useState<string[]>([])\n const [shownStates, setShownStates] = useState<string[]>([])\n /**\n * A linha que está SENDO decidida.\n *\n * A troca é otimista — o selo e os botões já mudaram —, mas a escrita ainda\n * está no ar, e clicar duas vezes em \"Confirmar\" manda dois pedidos. O\n * spinner na própria linha diz onde a resposta está sendo esperada, sem\n * tirar a lista do lugar.\n */\n const [busyId, setBusyId] = useState<string | null>(null)\n\n /**\n * O CARTÃO DECIDIDO NÃO SALTA DE GRUPO.\n *\n * Sem isto ele desaparece do topo no mesmo quadro em que o estado muda, e o\n * que a pessoa vê é uma linha sumindo — não a linha DELA indo para onde as\n * decididas ficam. O movimento é o que explica o destino.\n *\n * `held` decidido, mas ainda no topo: mostra o novo selo por um\n * instante, no lugar onde o olho já está.\n * `leavingId` a descida: desliza e esmaece.\n * `pulse` o contador do grupo de baixo crescendo — a outra ponta do\n * movimento, e a única pista quando ele está fechado.\n */\n const [held, setHeld] = useState<string[]>([])\n const [leavingId, setLeavingId] = useState<string | null>(null)\n const [pulse, setPulse] = useState(false)\n const timers = useRef<number[]>([])\n useEffect(() => () => { timers.current.forEach(clearTimeout) }, [])\n\n const HOLD_MS = 650 // o tempo de ler o novo selo\n const SLIDE_MS = 480 // o tempo da descida\n\n const decide = async (id: string, next: string) => {\n setBusyId(id)\n // `updateBookingStatus` já pinta as duas listas na hora e desfaz sozinho\n // se a escrita falhar — aqui só se espera para soltar a linha.\n try {\n await updateStatus(id, next)\n setHeld((cur) => [...cur, id])\n timers.current.push(window.setTimeout(() => setLeavingId(id), HOLD_MS))\n timers.current.push(window.setTimeout(() => {\n setLeavingId(null)\n setHeld((cur) => cur.filter((x) => x !== id))\n setPulse(true)\n }, HOLD_MS + SLIDE_MS))\n timers.current.push(window.setTimeout(() => setPulse(false), HOLD_MS + SLIDE_MS + 420))\n } catch { /* o store já avisou */ }\n finally { setBusyId(null) }\n }\n\n const CONFIRMATION_STATES = useMemo(() => [\n { value: 'pending', label: t('agenda.confirmations.statePending'), color: 'hsl(var(--warning))' },\n { value: 'sent', label: t('agenda.confirmations.stateSent'), color: 'hsl(var(--info))' },\n { value: 'confirmed', label: t('agenda.confirmations.stateConfirmed'), color: 'hsl(var(--success))' },\n { value: 'declined', label: t('agenda.confirmations.stateDeclined'), color: 'hsl(var(--destructive))' },\n ], [t])\n\n const pros = useMemo(() => {\n const names = new Set<string>()\n for (const b of confirmations) if (b.professionalName) names.add(b.professionalName)\n return [...names].sort((a, b) => a.localeCompare(b))\n }, [confirmations])\n\n // Vazio quer dizer TODOS — a mesma regra das outras três telas.\n const shown = useMemo(() => {\n const needle = term.trim().toLowerCase()\n return confirmations.filter((b) => {\n if (shownPros.length && !(b.professionalName && shownPros.includes(b.professionalName))) return false\n if (shownStates.length && !shownStates.includes(getConfirmationStatus(b))) return false\n if (needle) {\n const hay = `${b.clientName ?? ''} ${b.professionalName ?? ''} ${b.clientPhone ?? ''}`.toLowerCase()\n if (!hay.includes(needle)) return false\n }\n return true\n })\n }, [confirmations, shownPros, shownStates, term])\n\n // Decidido é decidido: confirmado, cancelado ou não compareceu saem do topo.\n const isSettled = (b: CalendarBooking) => {\n const st = getConfirmationStatus(b)\n return st === 'confirmed' || st === 'declined'\n }\n const pending = shown.filter((b) => !isSettled(b) || held.includes(b.id))\n const settled = shown.filter((b) => isSettled(b) && !held.includes(b.id))\n\n const confirmedCount = confirmations.filter((b) => b.status === 'confirmed').length\n const pendingCount = confirmations.length - confirmedCount\n const totalCount = confirmations.length\n const confirmRate = totalCount > 0 ? Math.round((confirmedCount / totalCount) * 100) : 0\n const allDone = totalCount > 0 && pendingCount === 0\n\n const rail = (\n <AgendaFilterRail\n search={{ value: term, onChange: setTerm, placeholder: t('agenda.confirmations.searchPlaceholder') }}\n sections={[\n {\n id: 'professionals',\n title: t('agenda.sidebar.professionals'),\n count: shownPros.length,\n content: (\n <AdaptiveFilter\n options={pros.map((name) => ({ value: name, label: name, avatarUrl: null }))}\n value={shownPros}\n onChange={setShownPros}\n allLabel={t('agenda.sidebar.allProfessionals')}\n />\n ),\n },\n {\n id: 'horizon',\n // O VALOR VAI NO TÍTULO. Dobrar a seção guardaria o recorte junto\n // com a régua, e é justamente a seção fechada que faria a lista\n // vazia mentir — \"não há ninguém para confirmar\" quando o que há é\n // um alcance curto. No título ele sobrevive ao fechamento.\n title: `Período · ${HORIZONS.find((h) => h.days === days)?.short ?? ''}`,\n defaultOpen: true,\n content: (\n <div className=\"space-y-0.5\">\n {HORIZONS.map((h) => (\n <Button variant=\"bare\" size=\"bare\"\n key={h.days}\n type=\"button\"\n onClick={() => prefs.set('confirmationDays', h.days)}\n aria-pressed={h.days === days}\n className={'flex w-full items-center justify-start gap-2 rounded-md px-1.5 py-1.5 text-left text-xs transition-colors '\n + (h.days === days ? 'bg-muted font-medium text-foreground' : 'font-normal text-muted-foreground hover:bg-muted/50')}\n >\n {h.label}\n </Button>\n ))}\n </div>\n ),\n },\n {\n id: 'state',\n title: t('agenda.sidebar.status'),\n count: shownStates.length,\n content: (\n <>\n {CONFIRMATION_STATES.map((st) => (\n <FilterCheckRow\n key={st.value}\n option={{ value: st.value, label: st.label, color: st.color }}\n checked={shownStates.length === 0 || shownStates.includes(st.value)}\n onToggle={() => setShownStates((cur) =>\n cur.includes(st.value) ? cur.filter((x) => x !== st.value) : [...cur, st.value])}\n />\n ))}\n </>\n ),\n },\n ]}\n footer={<>{shown.length} de {confirmations.length}</>}\n />\n )\n\n const renderCard = (booking: CalendarBooking) => {\n const confStatus = getConfirmationStatus(booking)\n const tone = STATE_TONE[confStatus] ?? STATE_TONE.pending\n const busy = busyId === booking.id\n const leaving = leavingId === booking.id\n const services = booking.services?.map((sv) => sv.name).join(', ')\n const money = booking.orderTotal != null\n ? formatCurrency(booking.orderTotal, config.currency.code)\n : null\n\n return (\n <li key={booking.id}>\n <BookingCard\n booking={booking}\n /* `clientKind` aceita lista desde a agenda de leads; o link\n da ficha quer UMA espécie, e a primeira é a principal. */\n clientKind={Array.isArray(config.clientKind) ? config.clientKind[0] : config.clientKind}\n showDate\n busy={busy}\n flagClass={tone.flag}\n /* A BORDA CARREGA O ESTADO: a faixa da esquerda é grossa e a\n moldura é tingida de leve, então dá para varrer a coluna e\n saber o que falta sem ler uma palavra — e quem não\n distingue as cores ainda tem o selo escrito à direita.\n\n A descida: `translate-y` leva o cartão na direção do grupo\n de baixo e a opacidade o entrega. Transição de propriedade,\n não keyframe — começa sozinha quando a classe muda, e o\n `prefers-reduced-motion` do navegador a encurta. */\n className={`shadow-button hover:bg-muted/40 ${tone.border} ${\n busy ? 'pointer-events-none opacity-60' : ''\n } ${\n leaving\n ? 'pointer-events-none translate-y-8 scale-[0.98] opacity-0 duration-[480ms] ease-in'\n : 'translate-y-0 scale-100 duration-300'\n }`}\n badge={\n <span className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium ${tone.badge}`}>\n {busy && <Loader2 className=\"h-3 w-3 animate-spin\" aria-hidden />}\n {STATE_LABEL(t)[confStatus] ?? confStatus}\n </span>\n }\n actions={<>\n {/* FALAR à esquerda, DECIDIR à direita, separados por um\n fio. São dois gestos diferentes — um alcança a cliente,\n o outro encerra a linha — e misturá-los numa fileira de\n ícones iguais fazia a pessoa ler quatro botões para\n achar o que veio fazer. */}\n {booking.clientPhone && <ClientContactButton phone={booking.clientPhone} />}\n <span className=\"mx-0.5 h-5 w-px bg-border\" aria-hidden />\n {/* Confirmado não oferece \"confirmar\": um botão que repete\n o que já está feito convida o segundo telefonema. */}\n {booking.status !== 'confirmed' && (\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n onClick={() => decide(booking.id, 'confirmed')}\n disabled={busy}\n /* A COR DA CASA. Confirmar é a ação que a pessoa veio\n fazer, e a ação primária de toda tela deste app usa\n `primary` — pintá-la de verde aqui ensinava um\n segundo idioma de botão só nesta lista. */\n className=\"flex h-8 items-center gap-1.5 rounded-button bg-primary px-3 text-xs font-medium text-primary-foreground shadow-button transition-all hover:brightness-110 active:scale-95 disabled:opacity-60\"\n >\n <Check className=\"h-3.5 w-3.5\" />\n <span>{t('agenda.confirmations.confirmShort')}</span>\n </Button>\n )}\n {/* Cancelar NÃO é o par visual de confirmar. Fica discreto\n e só se acende no hover: é a ação que se toma poucas\n vezes, e dois botões de mesmo peso lado a lado fazem\n quem estava com pressa errar a metade das vezes. */}\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n onClick={() => decide(booking.id, 'cancelled')}\n disabled={busy}\n aria-label={t('agenda.confirmations.markCancelled')}\n className=\"flex h-8 w-8 items-center justify-center rounded-button border border-transparent text-muted-foreground transition-all hover:border-destructive/30 hover:bg-destructive/10 hover:text-destructive active:scale-95 disabled:opacity-60\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>{t('agenda.confirmations.markCancelled')}</TooltipContent>\n </Tooltip>\n </>}\n />\n </li>\n )\n }\n\n return (\n <AgendaWorkspace rail={rail}>\n <TooltipProvider delayDuration={300}>\n <div className=\"space-y-4\">\n {/* ── O PLACAR ───────────────────────────────────────────────────────\n Confirmar a agenda do dia é uma tarefa de RISCAR DA LISTA, e quem a\n faz não quer um relatório: quer ver o número subir. A barra enche com\n transição, a porcentagem conta, e o \"faltam N\" some sozinho quando\n chega a zero — o fim da fila é a recompensa.\n\n A cor acompanha: âmbar enquanto falta gente, verde quando fecha. */}\n <div className={`rounded-lg border p-3 transition-colors ${\n allDone ? 'border-success/40 bg-success/5' : 'border-border bg-card'\n }`}>\n <div className=\"mb-2 flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1\">\n <span className=\"flex items-baseline gap-2\">\n <span className={`text-2xl font-semibold tabular-nums transition-colors ${\n allDone ? 'text-success' : 'text-foreground'\n }`}>\n {confirmRate}%\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {confirmedCount} {t('agenda.confirmations.ofConfirmed', { total: String(totalCount) })}\n </span>\n </span>\n {allDone ? (\n <span className=\"inline-flex items-center gap-1.5 text-sm font-medium text-success\">\n <CheckCircle className=\"h-4 w-4\" aria-hidden />\n {t('agenda.confirmations.allDone')}\n </span>\n ) : (\n <span className=\"text-sm text-muted-foreground\">\n {t('agenda.confirmations.toConfirm')}{' '}\n <strong className=\"text-base font-semibold text-foreground tabular-nums\">{pendingCount}</strong>\n </span>\n )}\n </div>\n <div\n className=\"h-2 overflow-hidden rounded-full bg-muted\"\n role=\"progressbar\"\n aria-valuenow={confirmRate}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={t('agenda.confirmations.confirmed')}\n >\n <div\n className={`h-full rounded-full transition-[width,background-color] duration-700 ease-out ${\n allDone ? 'bg-success' : 'bg-warning'\n }`}\n style={{ width: `${confirmRate}%` }}\n />\n </div>\n </div>\n\n {/* ── A lista ────────────────────────────────────────────────────────\n Esqueleto com a FORMA do cartão: sem ele a tela salta quando os\n dados chegam, e quem já mirou num botão perde a linha. */}\n {loading && confirmations.length === 0 ? (\n <ul className=\"space-y-2\" aria-busy=\"true\" aria-label={t('agenda.confirmations.loading')}>\n {[0, 1, 2, 3].map((i) => (\n <li key={i} className=\"flex gap-3 rounded-lg border border-border bg-card p-3\">\n <div className=\"w-1 shrink-0 rounded-full bg-muted\" />\n <div className=\"flex-1 space-y-2\">\n <div className=\"flex items-center gap-3\">\n <div className=\"h-3.5 w-16 animate-pulse rounded bg-muted\" />\n <div className=\"h-4 w-44 animate-pulse rounded bg-muted/80\" />\n </div>\n <div className=\"h-3 w-72 animate-pulse rounded bg-muted/60\" />\n </div>\n <div className=\"h-8 w-40 shrink-0 animate-pulse rounded-button bg-muted/60\" />\n </li>\n ))}\n </ul>\n ) : shown.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <CheckCircle className=\"mb-3 h-12 w-12 text-muted-foreground/30\" />\n <p className=\"text-muted-foreground\">\n {confirmations.length === 0 ? t('agenda.confirmations.empty') : t('agenda.confirmations.noMatch')}\n </p>\n <p className=\"text-sm text-muted-foreground/70\">\n {confirmations.length === 0 ? t('agenda.confirmations.emptySubtitle') : t('agenda.confirmations.noMatchSubtitle')}\n </p>\n </div>\n ) : (\n <div className=\"space-y-4\">\n {/* DOIS GRUPOS, e o segundo fechado.\n Confirmar a agenda do dia é riscar da lista, e o que já foi\n riscado não pode continuar ocupando o topo — mas também não some:\n quem confirmou errado precisa achar a linha para desfazer. O\n contador no cabeçalho é o que diz que ela está ali dentro. */}\n <Group\n title={t('agenda.confirmations.groupPending')}\n count={pending.length}\n defaultOpen\n empty={t('agenda.confirmations.allDone')}\n >\n {pending.map(renderCard)}\n </Group>\n {/* O destino existe ENQUANTO o cartão desce, mesmo vazio: um grupo\n que aparece junto com a linha não é para onde ela foi, é uma\n segunda coisa acontecendo. */}\n {(settled.length > 0 || held.length > 0) && (\n <Group\n title={t('agenda.confirmations.groupSettled')}\n count={settled.length}\n defaultOpen={false}\n pulse={pulse}\n >\n {settled.map(renderCard)}\n </Group>\n )}\n </div>\n )}\n </div>\n </TooltipProvider>\n </AgendaWorkspace>\n )\n}\n"]}
@@ -0,0 +1,127 @@
1
+ import { useAgendaProvider, useAgendaConfig } from './chunk-XTNSK4RJ.js';
2
+ import React from 'react';
3
+ import { ArrowRight, Play } from 'lucide-react';
4
+ import { Card, CardHeader, CardTitle, CardContent, Skeleton, Button } from '@fayz-ai/ui';
5
+ import { PersonLink, openEntity } from '@fayz-ai/admin';
6
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
+
8
+ var OPEN = ["scheduled", "confirmed", "waiting", "in_progress"];
9
+ var REFUSAL = {
10
+ sem_ficha_de_profissional: "Este login n\xE3o tem ficha de profissional. S\xF3 quem atende inicia o atendimento.",
11
+ nao_e_seu_atendimento: "Este atendimento \xE9 de outro profissional.",
12
+ nao_e_de_hoje: "S\xF3 d\xE1 para iniciar um atendimento de hoje.",
13
+ ja_encerrado: "Este atendimento j\xE1 foi encerrado.",
14
+ not_found: "Este agendamento n\xE3o existe mais."
15
+ };
16
+ function todayRange() {
17
+ const start = /* @__PURE__ */ new Date();
18
+ start.setHours(0, 0, 0, 0);
19
+ const end = /* @__PURE__ */ new Date();
20
+ end.setHours(23, 59, 59, 999);
21
+ return { start: start.toISOString(), end: end.toISOString() };
22
+ }
23
+ var hhmm = (iso) => new Date(iso).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" });
24
+ function MyClientsTodayWidget() {
25
+ const provider = useAgendaProvider();
26
+ const config = useAgendaConfig();
27
+ const [me, setMe] = React.useState(void 0);
28
+ const [rows, setRows] = React.useState(null);
29
+ const [busy, setBusy] = React.useState(null);
30
+ const [refusal, setRefusal] = React.useState(null);
31
+ const load = React.useCallback(async (personId) => {
32
+ const r = await provider.getBookings({ dateRange: todayRange(), professionalIds: [personId], statuses: OPEN });
33
+ setRows(r.filter((b) => b.clientId).sort((a, b) => a.startsAt.localeCompare(b.startsAt)));
34
+ }, [provider]);
35
+ React.useEffect(() => {
36
+ let alive = true;
37
+ Promise.resolve(provider.getCurrentPersonId?.() ?? null).then((id) => {
38
+ if (alive) setMe(id ?? null);
39
+ }).catch(() => {
40
+ if (alive) setMe(null);
41
+ });
42
+ return () => {
43
+ alive = false;
44
+ };
45
+ }, [provider]);
46
+ const [isPro, setIsPro] = React.useState(void 0);
47
+ React.useEffect(() => {
48
+ if (!me) return;
49
+ let alive = true;
50
+ provider.getProfessionals().then((ps) => {
51
+ if (alive) setIsPro(ps.some((p) => p.id === me));
52
+ }).catch(() => {
53
+ if (alive) setIsPro(false);
54
+ });
55
+ return () => {
56
+ alive = false;
57
+ };
58
+ }, [me, provider]);
59
+ React.useEffect(() => {
60
+ if (!me || !isPro) return;
61
+ load(me).catch(() => setRows([]));
62
+ }, [me, isPro, load]);
63
+ if (me === null || isPro === false) return null;
64
+ const statusLabel = (v) => config.statuses.find((s) => s.value === v)?.label ?? "";
65
+ async function start(b) {
66
+ setRefusal(null);
67
+ if (b.status === "in_progress") {
68
+ openEntity(b.clientId, "person", "customer", "attendance");
69
+ return;
70
+ }
71
+ setBusy(b.id);
72
+ try {
73
+ const r = await provider.startAttendance?.(b.id);
74
+ if (!r?.ok) {
75
+ setRefusal(REFUSAL[r?.reason ?? ""] ?? "N\xE3o foi poss\xEDvel iniciar o atendimento.");
76
+ return;
77
+ }
78
+ openEntity(b.clientId, "person", "customer", "attendance");
79
+ } finally {
80
+ setBusy(null);
81
+ }
82
+ }
83
+ return /* @__PURE__ */ jsxs(Card, { children: [
84
+ /* @__PURE__ */ jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsx(CardTitle, { className: "text-sm", children: "Seus clientes de hoje" }) }),
85
+ /* @__PURE__ */ jsxs(CardContent, { className: "space-y-1.5", children: [
86
+ (me === void 0 || isPro === void 0 || rows === null) && /* @__PURE__ */ jsxs(Fragment, { children: [
87
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-11 w-full" }),
88
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-11 w-full" })
89
+ ] }),
90
+ rows && rows.length === 0 && /* @__PURE__ */ jsx("p", { className: "py-2 text-xs text-muted-foreground", children: "Nenhum cliente marcado com voc\xEA hoje." }),
91
+ refusal && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: refusal }),
92
+ rows?.map((b) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-lg border px-3 py-2", children: [
93
+ /* @__PURE__ */ jsx("span", { className: "w-11 shrink-0 text-sm font-medium tabular-nums", children: hhmm(b.startsAt) }),
94
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
95
+ /* @__PURE__ */ jsx(PersonLink, { personId: b.clientId, name: b.clientName ?? "", className: "block truncate text-sm font-medium" }),
96
+ /* @__PURE__ */ jsxs("p", { className: "truncate text-xs text-muted-foreground", children: [
97
+ (b.services ?? []).map((s) => s.name).join(", ") || "Servi\xE7o n\xE3o informado",
98
+ statusLabel(b.status) ? ` \xB7 ${statusLabel(b.status)}` : ""
99
+ ] })
100
+ ] }),
101
+ /* @__PURE__ */ jsx(
102
+ Button,
103
+ {
104
+ variant: "bare",
105
+ size: "bare",
106
+ type: "button",
107
+ disabled: busy === b.id,
108
+ onClick: () => start(b),
109
+ className: "inline-flex shrink-0 items-center gap-1.5 rounded-button bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50",
110
+ children: b.status === "in_progress" ? /* @__PURE__ */ jsxs(Fragment, { children: [
111
+ /* @__PURE__ */ jsx(ArrowRight, { className: "h-3.5 w-3.5" }),
112
+ " Continuar"
113
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
114
+ /* @__PURE__ */ jsx(Play, { className: "h-3.5 w-3.5" }),
115
+ " ",
116
+ busy === b.id ? "Iniciando\u2026" : "Iniciar"
117
+ ] })
118
+ }
119
+ )
120
+ ] }, b.id))
121
+ ] })
122
+ ] });
123
+ }
124
+
125
+ export { MyClientsTodayWidget };
126
+ //# sourceMappingURL=MyClientsTodayWidget-ZGTXJJKN.js.map
127
+ //# sourceMappingURL=MyClientsTodayWidget-ZGTXJJKN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/MyClientsTodayWidget.tsx"],"names":[],"mappings":";;;;;;;AAOA,IAAM,IAAA,GAAO,CAAC,WAAA,EAAa,WAAA,EAAa,WAAW,aAAa,CAAA;AAEhE,IAAM,OAAA,GAAkC;AAAA,EACtC,yBAAA,EAA2B,sFAAA;AAAA,EAC3B,qBAAA,EAAuB,8CAAA;AAAA,EACvB,aAAA,EAAe,kDAAA;AAAA,EACf,YAAA,EAAc,uCAAA;AAAA,EACd,SAAA,EAAW;AACb,CAAA;AAEA,SAAS,UAAA,GAAa;AACpB,EAAA,MAAM,KAAA,uBAAY,IAAA,EAAK;AAAG,EAAA,KAAA,CAAM,QAAA,CAAS,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA;AACnD,EAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AAAG,EAAA,GAAA,CAAI,QAAA,CAAS,EAAA,EAAI,EAAA,EAAI,EAAA,EAAI,GAAG,CAAA;AACpD,EAAA,OAAO,EAAE,OAAO,KAAA,CAAM,WAAA,IAAe,GAAA,EAAK,GAAA,CAAI,aAAY,EAAE;AAC9D;AAEA,IAAM,IAAA,GAAO,CAAC,GAAA,KAAgB,IAAI,KAAK,GAAG,CAAA,CAAE,kBAAA,CAAmB,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,WAAW,CAAA;AAMvG,SAAS,oBAAA,GAAuB;AACrC,EAAA,MAAM,WAAW,iBAAA,EAAkB;AACnC,EAAA,MAAM,SAAS,eAAA,EAAgB;AAC/B,EAAA,MAAM,CAAC,EAAA,EAAI,KAAK,CAAA,GAAI,KAAA,CAAM,SAAoC,MAAS,CAAA;AACvE,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,KAAA,CAAM,SAAmC,IAAI,CAAA;AACrE,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,KAAA,CAAM,SAAwB,IAAI,CAAA;AAC1D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,KAAA,CAAM,SAAwB,IAAI,CAAA;AAEhE,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,WAAA,CAAY,OAAO,QAAA,KAAqB;AACzD,IAAA,MAAM,CAAA,GAAI,MAAM,QAAA,CAAS,WAAA,CAAY,EAAE,SAAA,EAAW,UAAA,EAAW,EAAG,eAAA,EAAiB,CAAC,QAAQ,CAAA,EAAG,QAAA,EAAU,MAAM,CAAA;AAC7G,IAAA,OAAA,CAAQ,EAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,QAAA,CAAS,cAAc,CAAA,CAAE,QAAQ,CAAC,CAAC,CAAA;AAAA,EAC1F,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,IAAI,KAAA,GAAQ,IAAA;AACZ,IAAA,OAAA,CAAQ,OAAA,CAAQ,SAAS,kBAAA,IAAqB,IAAK,IAAI,CAAA,CACpD,IAAA,CAAK,CAAC,EAAA,KAAO;AAAE,MAAA,IAAI,KAAA,EAAO,KAAA,CAAM,EAAA,IAAM,IAAI,CAAA;AAAA,IAAE,CAAC,CAAA,CAC7C,KAAA,CAAM,MAAM;AAAE,MAAA,IAAI,KAAA,QAAa,IAAI,CAAA;AAAA,IAAE,CAAC,CAAA;AACzC,IAAA,OAAO,MAAM;AAAE,MAAA,KAAA,GAAQ,KAAA;AAAA,IAAM,CAAA;AAAA,EAC/B,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAGb,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,KAAA,CAAM,SAA8B,MAAS,CAAA;AACvE,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,IAAI,CAAC,EAAA,EAAI;AACT,IAAA,IAAI,KAAA,GAAQ,IAAA;AACZ,IAAA,QAAA,CAAS,gBAAA,EAAiB,CACvB,IAAA,CAAK,CAAC,EAAA,KAAO;AAAE,MAAA,IAAI,KAAA,WAAgB,EAAA,CAAG,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,EAAE,CAAC,CAAA;AAAA,IAAE,CAAC,CAAA,CACjE,KAAA,CAAM,MAAM;AAAE,MAAA,IAAI,KAAA,WAAgB,KAAK,CAAA;AAAA,IAAE,CAAC,CAAA;AAC7C,IAAA,OAAO,MAAM;AAAE,MAAA,KAAA,GAAQ,KAAA;AAAA,IAAM,CAAA;AAAA,EAC/B,CAAA,EAAG,CAAC,EAAA,EAAI,QAAQ,CAAC,CAAA;AAEjB,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,IAAI,CAAC,EAAA,IAAM,CAAC,KAAA,EAAO;AACnB,IAAA,IAAA,CAAK,EAAE,CAAA,CAAE,KAAA,CAAM,MAAM,OAAA,CAAQ,EAAE,CAAC,CAAA;AAAA,EAClC,CAAA,EAAG,CAAC,EAAA,EAAI,KAAA,EAAO,IAAI,CAAC,CAAA;AAEpB,EAAA,IAAI,EAAA,KAAO,IAAA,IAAQ,KAAA,KAAU,KAAA,EAAO,OAAO,IAAA;AAE3C,EAAA,MAAM,WAAA,GAAc,CAAC,CAAA,KAAc,MAAA,CAAO,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,KAAU,CAAC,CAAA,EAAG,KAAA,IAAS,EAAA;AAExF,EAAA,eAAe,MAAM,CAAA,EAAoB;AACvC,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,IAAI,CAAA,CAAE,WAAW,aAAA,EAAe;AAAE,MAAA,UAAA,CAAW,CAAA,CAAE,QAAA,EAAW,QAAA,EAAU,UAAA,EAAY,YAAY,CAAA;AAAG,MAAA;AAAA,IAAO;AACtG,IAAA,OAAA,CAAQ,EAAE,EAAE,CAAA;AACZ,IAAA,IAAI;AACF,MAAA,MAAM,CAAA,GAAI,MAAM,QAAA,CAAS,eAAA,GAAkB,EAAE,EAAE,CAAA;AAC/C,MAAA,IAAI,CAAC,GAAG,EAAA,EAAI;AAAE,QAAA,UAAA,CAAW,OAAA,CAAQ,CAAA,EAAG,MAAA,IAAU,EAAE,KAAK,+CAAyC,CAAA;AAAG,QAAA;AAAA,MAAO;AACxG,MAAA,UAAA,CAAW,CAAA,CAAE,QAAA,EAAW,QAAA,EAAU,UAAA,EAAY,YAAY,CAAA;AAAA,IAC5D,CAAA,SAAE;AAAU,MAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,IAAE;AAAA,EAC5B;AAEA,EAAA,4BACG,IAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,WAAU,MAAA,EACpB,QAAA,kBAAA,GAAA,CAAC,aAAU,SAAA,EAAU,SAAA,EAAU,mCAAqB,CAAA,EACtD,CAAA;AAAA,oBACA,IAAA,CAAC,WAAA,EAAA,EAAY,SAAA,EAAU,aAAA,EACnB,QAAA,EAAA;AAAA,MAAA,CAAA,EAAA,KAAO,MAAA,IAAa,KAAA,KAAU,MAAA,IAAa,IAAA,KAAS,yBACpD,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,QAAA,EAAA,EAAS,WAAU,aAAA,EAAc,CAAA;AAAA,wBAClC,GAAA,CAAC,QAAA,EAAA,EAAS,SAAA,EAAU,aAAA,EAAc;AAAA,OAAA,EACpC,CAAA;AAAA,MAED,IAAA,IAAQ,KAAK,MAAA,KAAW,CAAA,wBACtB,GAAA,EAAA,EAAE,SAAA,EAAU,sCAAqC,QAAA,EAAA,0CAAA,EAAqC,CAAA;AAAA,MAExF,OAAA,oBAAW,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,4BAA4B,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,MAC5D,MAAM,GAAA,CAAI,CAAC,sBACV,IAAA,CAAC,KAAA,EAAA,EAAe,WAAU,qDAAA,EACxB,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,UAAK,SAAA,EAAU,gDAAA,EAAkD,QAAA,EAAA,IAAA,CAAK,CAAA,CAAE,QAAQ,CAAA,EAAE,CAAA;AAAA,wBACnF,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,UAAA,EAAA,EAAW,UAAU,CAAA,CAAE,QAAA,EAAW,MAAM,CAAA,CAAE,UAAA,IAAc,EAAA,EAAI,SAAA,EAAU,oCAAA,EAAqC,CAAA;AAAA,0BAC5G,IAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,wCAAA,EACT,QAAA,EAAA;AAAA,YAAA,CAAA,CAAA,CAAE,QAAA,IAAY,EAAC,EAAG,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,IAAK,6BAAA;AAAA,YACpD,WAAA,CAAY,EAAE,MAAM,CAAA,GAAI,SAAM,WAAA,CAAY,CAAA,CAAE,MAAM,CAAC,CAAA,CAAA,GAAK;AAAA,WAAA,EAC3D;AAAA,SAAA,EACF,CAAA;AAAA,wBACA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YAAO,OAAA,EAAQ,MAAA;AAAA,YAAO,IAAA,EAAK,MAAA;AAAA,YAC1B,IAAA,EAAK,QAAA;AAAA,YACL,QAAA,EAAU,SAAS,CAAA,CAAE,EAAA;AAAA,YACrB,OAAA,EAAS,MAAM,KAAA,CAAM,CAAC,CAAA;AAAA,YACtB,SAAA,EAAU,qKAAA;AAAA,YAET,QAAA,EAAA,CAAA,CAAE,MAAA,KAAW,aAAA,mBACV,IAAA,CAAA,QAAA,EAAA,EAAE,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,UAAA,EAAA,EAAW,WAAU,aAAA,EAAc,CAAA;AAAA,cAAE;AAAA,aAAA,EAAU,oBAClD,IAAA,CAAA,QAAA,EAAA,EAAE,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,WAAU,aAAA,EAAc,CAAA;AAAA,cAAE,GAAA;AAAA,cAAE,IAAA,KAAS,CAAA,CAAE,EAAA,GAAK,iBAAA,GAAe;AAAA,aAAA,EAAU;AAAA;AAAA;AACnF,OAAA,EAAA,EAlBQ,CAAA,CAAE,EAmBZ,CACD;AAAA,KAAA,EACH;AAAA,GAAA,EACF,CAAA;AAEJ","file":"MyClientsTodayWidget-ZGTXJJKN.js","sourcesContent":["import React from 'react'\nimport { Play, ArrowRight } from 'lucide-react'\nimport { Button, Card, CardHeader, CardTitle, CardContent, Skeleton } from '@fayz-ai/ui'\nimport { openEntity, PersonLink } from '@fayz-ai/admin'\nimport { useAgendaConfig, useAgendaProvider } from '../context'\nimport type { CalendarBooking } from '../types'\n\nconst OPEN = ['scheduled', 'confirmed', 'waiting', 'in_progress']\n\nconst REFUSAL: Record<string, string> = {\n sem_ficha_de_profissional: 'Este login não tem ficha de profissional. Só quem atende inicia o atendimento.',\n nao_e_seu_atendimento: 'Este atendimento é de outro profissional.',\n nao_e_de_hoje: 'Só dá para iniciar um atendimento de hoje.',\n ja_encerrado: 'Este atendimento já foi encerrado.',\n not_found: 'Este agendamento não existe mais.',\n}\n\nfunction todayRange() {\n const start = new Date(); start.setHours(0, 0, 0, 0)\n const end = new Date(); end.setHours(23, 59, 59, 999)\n return { start: start.toISOString(), end: end.toISOString() }\n}\n\nconst hhmm = (iso: string) => new Date(iso).toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })\n\n/**\n * V1 home \"Seus clientes de hoje\" (FAY-1613): the professional's own day, with Iniciar. Renders\n * nothing for a login that is not a professional — V1 only shows it to whoever attends.\n */\nexport function MyClientsTodayWidget() {\n const provider = useAgendaProvider()\n const config = useAgendaConfig()\n const [me, setMe] = React.useState<string | null | undefined>(undefined)\n const [rows, setRows] = React.useState<CalendarBooking[] | null>(null)\n const [busy, setBusy] = React.useState<string | null>(null)\n const [refusal, setRefusal] = React.useState<string | null>(null)\n\n const load = React.useCallback(async (personId: string) => {\n const r = await provider.getBookings({ dateRange: todayRange(), professionalIds: [personId], statuses: OPEN })\n setRows(r.filter((b) => b.clientId).sort((a, b) => a.startsAt.localeCompare(b.startsAt)))\n }, [provider])\n\n React.useEffect(() => {\n let alive = true\n Promise.resolve(provider.getCurrentPersonId?.() ?? null)\n .then((id) => { if (alive) setMe(id ?? null) })\n .catch(() => { if (alive) setMe(null) })\n return () => { alive = false }\n }, [provider])\n\n // Only whoever is on the bookable roster: reception has a person record too.\n const [isPro, setIsPro] = React.useState<boolean | undefined>(undefined)\n React.useEffect(() => {\n if (!me) return\n let alive = true\n provider.getProfessionals()\n .then((ps) => { if (alive) setIsPro(ps.some((p) => p.id === me)) })\n .catch(() => { if (alive) setIsPro(false) })\n return () => { alive = false }\n }, [me, provider])\n\n React.useEffect(() => {\n if (!me || !isPro) return\n load(me).catch(() => setRows([]))\n }, [me, isPro, load])\n\n if (me === null || isPro === false) return null\n // Someone who attends but has nobody today still sees the card: an empty day is an answer.\n const statusLabel = (v: string) => config.statuses.find((s) => s.value === v)?.label ?? ''\n\n async function start(b: CalendarBooking) {\n setRefusal(null)\n if (b.status === 'in_progress') { openEntity(b.clientId!, 'person', 'customer', 'attendance'); return }\n setBusy(b.id)\n try {\n const r = await provider.startAttendance?.(b.id)\n if (!r?.ok) { setRefusal(REFUSAL[r?.reason ?? ''] ?? 'Não foi possível iniciar o atendimento.'); return }\n openEntity(b.clientId!, 'person', 'customer', 'attendance')\n } finally { setBusy(null) }\n }\n\n return (\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm\">Seus clientes de hoje</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-1.5\">\n {(me === undefined || isPro === undefined || rows === null) && (\n <>\n <Skeleton className=\"h-11 w-full\" />\n <Skeleton className=\"h-11 w-full\" />\n </>\n )}\n {rows && rows.length === 0 && (\n <p className=\"py-2 text-xs text-muted-foreground\">Nenhum cliente marcado com você hoje.</p>\n )}\n {refusal && <p className=\"text-xs text-destructive\">{refusal}</p>}\n {rows?.map((b) => (\n <div key={b.id} className=\"flex items-center gap-3 rounded-lg border px-3 py-2\">\n <span className=\"w-11 shrink-0 text-sm font-medium tabular-nums\">{hhmm(b.startsAt)}</span>\n <div className=\"min-w-0 flex-1\">\n <PersonLink personId={b.clientId!} name={b.clientName ?? ''} className=\"block truncate text-sm font-medium\" />\n <p className=\"truncate text-xs text-muted-foreground\">\n {(b.services ?? []).map((s) => s.name).join(', ') || 'Serviço não informado'}\n {statusLabel(b.status) ? ` · ${statusLabel(b.status)}` : ''}\n </p>\n </div>\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n disabled={busy === b.id}\n onClick={() => start(b)}\n className=\"inline-flex shrink-0 items-center gap-1.5 rounded-button bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\"\n >\n {b.status === 'in_progress'\n ? <><ArrowRight className=\"h-3.5 w-3.5\" /> Continuar</>\n : <><Play className=\"h-3.5 w-3.5\" /> {busy === b.id ? 'Iniciando…' : 'Iniciar'}</>}\n </Button>\n </div>\n ))}\n </CardContent>\n </Card>\n )\n}\n"]}
@@ -0,0 +1,105 @@
1
+ import { useAgendaProvider } from './chunk-XTNSK4RJ.js';
2
+ import React from 'react';
3
+ import { Stethoscope } from 'lucide-react';
4
+ import { Button } from '@fayz-ai/ui';
5
+ import { currentAppPath, navigateApp } from '@fayz-ai/core';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ function hoje() {
9
+ const d = /* @__PURE__ */ new Date();
10
+ const iso = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
11
+ return { start: `${iso}T00:00:00`, end: `${iso}T23:59:59` };
12
+ }
13
+ function PersonAttendanceBlock({ personId }) {
14
+ const provider = useAgendaProvider();
15
+ const [pessoa, setPessoa] = React.useState(void 0);
16
+ const [booking, setBooking] = React.useState(null);
17
+ const [indo, setIndo] = React.useState(false);
18
+ const [recusa, setRecusa] = React.useState(null);
19
+ React.useEffect(() => {
20
+ let vivo = true;
21
+ (async () => {
22
+ const eu = await provider.getCurrentPersonId?.() ?? null;
23
+ if (!vivo) return;
24
+ setPessoa(eu);
25
+ if (!eu || !personId) return;
26
+ try {
27
+ const bs = await provider.getBookings({
28
+ dateRange: hoje(),
29
+ professionalIds: [eu],
30
+ statuses: ["scheduled", "confirmed", "waiting", "in_progress"]
31
+ });
32
+ const meu = bs.find((b) => b.clientId === personId);
33
+ if (vivo) setBooking(meu ?? null);
34
+ } catch {
35
+ if (vivo) setBooking(null);
36
+ }
37
+ })();
38
+ return () => {
39
+ vivo = false;
40
+ };
41
+ }, [personId, provider]);
42
+ if (pessoa === void 0) return null;
43
+ if (pessoa === null) {
44
+ return /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 rounded-xl border border-dashed px-3 py-2 text-[11px] text-muted-foreground", children: [
45
+ /* @__PURE__ */ jsx(Stethoscope, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
46
+ "Atender exige um login ligado a uma ficha de profissional. O seu n\xE3o est\xE1."
47
+ ] });
48
+ }
49
+ if (!booking) return null;
50
+ const emCurso = booking.status === "in_progress";
51
+ function irParaAba() {
52
+ const h = currentAppPath();
53
+ if (personId && !h.includes(personId)) return;
54
+ const base = h.split("?")[0].replace(/\/(overview|attendance|documents|financial|activity|addresses)$/, "");
55
+ navigateApp(`#${base}/attendance`);
56
+ }
57
+ async function comecar() {
58
+ if (!booking) return;
59
+ if (emCurso) {
60
+ irParaAba();
61
+ return;
62
+ }
63
+ setIndo(true);
64
+ setRecusa(null);
65
+ try {
66
+ const r = await provider.startAttendance?.(booking.id);
67
+ if (!r?.ok) {
68
+ setRecusa(r?.reason === "nao_e_seu_atendimento" ? "Este atendimento \xE9 de outro profissional." : "N\xE3o foi poss\xEDvel iniciar o atendimento.");
69
+ return;
70
+ }
71
+ irParaAba();
72
+ } finally {
73
+ setIndo(false);
74
+ }
75
+ }
76
+ return /* @__PURE__ */ jsxs("section", { className: "rounded-xl border bg-card px-3 py-2.5", children: [
77
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
78
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
79
+ /* @__PURE__ */ jsx("p", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Etapas do atendimento" }),
80
+ /* @__PURE__ */ jsxs("p", { className: "truncate text-xs", children: [
81
+ new Date(booking.startsAt).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" }),
82
+ booking.services?.length ? ` \xB7 ${booking.services.map((s) => s.name).join(", ")}` : "",
83
+ emCurso ? " \xB7 em atendimento" : ""
84
+ ] })
85
+ ] }),
86
+ /* @__PURE__ */ jsx(
87
+ Button,
88
+ {
89
+ variant: "bare",
90
+ size: "bare",
91
+ type: "button",
92
+ disabled: indo,
93
+ onClick: comecar,
94
+ className: `shrink-0 rounded-button px-3 py-1.5 text-xs font-semibold disabled:opacity-40 ${emCurso ? "border border-input hover:bg-muted" : "bg-success text-success-foreground"}`,
95
+ children: indo ? "Abrindo\u2026" : emCurso ? "Continuar atendimento" : "Iniciar atendimento"
96
+ }
97
+ )
98
+ ] }),
99
+ recusa && /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-[11px] text-destructive", children: recusa })
100
+ ] });
101
+ }
102
+
103
+ export { PersonAttendanceBlock };
104
+ //# sourceMappingURL=PersonAttendanceBlock-PHZVHFQ4.js.map
105
+ //# sourceMappingURL=PersonAttendanceBlock-PHZVHFQ4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/PersonAttendanceBlock.tsx"],"names":[],"mappings":"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","file":"PersonAttendanceBlock-PHZVHFQ4.js","sourcesContent":["import React from 'react'\nimport { Stethoscope } from 'lucide-react'\nimport { useAgendaProvider } from '../context'\nimport type { CalendarBooking } from '../types'\nimport { Button } from '@fayz-ai/ui'\nimport { navigateApp, currentAppPath } from '@fayz-ai/core'\n\nfunction hoje(): { start: string; end: string } {\n const d = new Date()\n const iso = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`\n return { start: `${iso}T00:00:00`, end: `${iso}T23:59:59` }\n}\n\n/**\n * ETAPAS DO ATENDIMENTO NA FICHA — a porta que o V1 declara.\n *\n * *\"O bloco ETAPAS DO ATENDIMENTO aparece acima das abas\"*, e a busca dele é\n * estreita de propósito: `professional_id = <o meu> AND client_id = <este> AND\n * status = 'in_progress'`. **Um profissional só enxerga o atendimento DELE com\n * aquele cliente** — o do colega não aparece.\n *\n * O V1 também documenta o próprio buraco: quem entra sem ficha de profissional\n * — admin, recepção — vê a ficha *\"sem botão nenhum\"*, e *\"a tela não explica:\n * ela simplesmente não desenha nada\"*. O doc chama isso de \"a resposta para a\n * pergunta de suporte mais provável desta página\". Aqui ela explica.\n */\nexport function PersonAttendanceBlock({ personId }: { personId?: string }) {\n const provider = useAgendaProvider()\n const [pessoa, setPessoa] = React.useState<string | null | undefined>(undefined)\n const [booking, setBooking] = React.useState<CalendarBooking | null>(null)\n const [indo, setIndo] = React.useState(false)\n const [recusa, setRecusa] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n let vivo = true\n ;(async () => {\n const eu = (await provider.getCurrentPersonId?.()) ?? null\n if (!vivo) return\n setPessoa(eu)\n if (!eu || !personId) return\n try {\n const bs = await provider.getBookings({\n dateRange: hoje(),\n professionalIds: [eu],\n statuses: ['scheduled', 'confirmed', 'waiting', 'in_progress'],\n })\n const meu = bs.find((b) => b.clientId === personId)\n if (vivo) setBooking(meu ?? null)\n } catch { if (vivo) setBooking(null) }\n })()\n return () => { vivo = false }\n }, [personId, provider])\n\n if (pessoa === undefined) return null\n\n // Sem ficha de profissional não há régua — e agora se diz por quê, uma linha,\n // sem botão morto ao lado.\n if (pessoa === null) {\n return (\n <p className=\"flex items-center gap-2 rounded-xl border border-dashed px-3 py-2 text-[11px] text-muted-foreground\">\n <Stethoscope className=\"h-3.5 w-3.5 shrink-0\" aria-hidden />\n Atender exige um login ligado a uma ficha de profissional. O seu não está.\n </p>\n )\n }\n\n if (!booking) return null\n\n const emCurso = booking.status === 'in_progress'\n\n function irParaAba() {\n // A ficha já está aberta: é só trocar de aba. O V1 monta a régua DENTRO\n // dela, e não numa tela própria — abrir outra rota tirava do profissional\n // o resto da ficha, que é o que ele consulta enquanto atende.\n const h = currentAppPath()\n // Dentro de um MODAL (a ficha aberta do agendamento) a rota da página é a\n // agenda, não a ficha — reescrever o hash quebrava a URL e não trocava\n // aba nenhuma. Sem a ficha na rota, fica onde está: a aba Atendimentos da\n // própria moldura está a um clique.\n if (personId && !h.includes(personId)) return\n const base = h.split('?')[0].replace(/\\/(overview|attendance|documents|financial|activity|addresses)$/, '')\n navigateApp(`#${base}/attendance`)\n }\n\n async function comecar() {\n if (!booking) return\n if (emCurso) { irParaAba(); return }\n setIndo(true)\n setRecusa(null)\n try {\n const r = await provider.startAttendance?.(booking.id)\n if (!r?.ok) {\n setRecusa(r?.reason === 'nao_e_seu_atendimento'\n ? 'Este atendimento é de outro profissional.'\n : 'Não foi possível iniciar o atendimento.')\n return\n }\n irParaAba()\n } finally { setIndo(false) }\n }\n\n return (\n <section className=\"rounded-xl border bg-card px-3 py-2.5\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n Etapas do atendimento\n </p>\n <p className=\"truncate text-xs\">\n {new Date(booking.startsAt).toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })}\n {booking.services?.length ? ` · ${booking.services.map((s) => s.name).join(', ')}` : ''}\n {emCurso ? ' · em atendimento' : ''}\n </p>\n </div>\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n disabled={indo}\n onClick={comecar}\n className={`shrink-0 rounded-button px-3 py-1.5 text-xs font-semibold disabled:opacity-40 ${\n emCurso ? 'border border-input hover:bg-muted' : 'bg-success text-success-foreground'\n }`}\n >\n {indo ? 'Abrindo…' : emCurso ? 'Continuar atendimento' : 'Iniciar atendimento'}\n </Button>\n </div>\n {recusa && <p className=\"mt-1.5 text-[11px] text-destructive\">{recusa}</p>}\n </section>\n )\n}\n"]}