@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,169 @@
1
+ import { FilterRail, RailWorkspace, Dropdown, DropdownTrigger, Button, DropdownContent, DropdownItem, normalizePhone } from '@fayz-ai/ui';
2
+ export { AdaptiveFilter, INLINE_FILTER_MAX } from '@fayz-ai/ui';
3
+ import { useRightRailStore, PersonLink } from '@fayz-ai/admin';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+ import { MessageCircle, ChevronDown, Phone, CalendarDays, Clock, User, MapPin, DoorOpen, Briefcase } from 'lucide-react';
6
+ import { useTranslation, formatCurrency } from '@fayz-ai/core';
7
+
8
+ // src/components/AgendaFilterRail.tsx
9
+ var AgendaFilterRail = FilterRail;
10
+ function AgendaRailColumn({ children }) {
11
+ const collapsed = useRightRailStore((s) => s.open);
12
+ return /* @__PURE__ */ jsx(RailWorkspaceColumn, { collapsed, children });
13
+ }
14
+ function RailWorkspaceColumn({ collapsed, children }) {
15
+ return /* @__PURE__ */ jsx(RailWorkspace, { collapsed, rail: children, children: null });
16
+ }
17
+ function AgendaWorkspace({ rail, children, className }) {
18
+ const collapsed = useRightRailStore((s) => s.open);
19
+ return /* @__PURE__ */ jsx(RailWorkspace, { rail, className, collapsed, children });
20
+ }
21
+ function whatsappNumber(raw) {
22
+ const digits = raw.replace(/\D/g, "");
23
+ return digits.length <= 11 ? `55${digits}` : digits;
24
+ }
25
+ function phoneDisplay(raw) {
26
+ const display = normalizePhone(raw).display || (raw ?? "");
27
+ return display.replace(/^\+\d{1,3}\s*/, "");
28
+ }
29
+ var two = (n) => String(n).padStart(2, "0");
30
+ var formatCardTime = (iso) => {
31
+ const d = new Date(iso);
32
+ return `${two(d.getHours())}:${two(d.getMinutes())}`;
33
+ };
34
+ var formatCardDate = (iso) => {
35
+ const d = new Date(iso);
36
+ return `${two(d.getDate())}/${two(d.getMonth() + 1)}`;
37
+ };
38
+ function ClientContactButton({ phone, compact }) {
39
+ const t = useTranslation();
40
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-stretch overflow-hidden rounded-button shadow-button", children: [
41
+ /* @__PURE__ */ jsxs(
42
+ "a",
43
+ {
44
+ href: `https://wa.me/${whatsappNumber(phone)}`,
45
+ target: "_blank",
46
+ rel: "noreferrer",
47
+ "aria-label": `${t("agenda.confirmations.sendWhatsApp")} ${phoneDisplay(phone)}`,
48
+ className: "flex h-8 items-center gap-1.5 bg-[#25D366] px-2.5 text-xs font-medium text-white transition-all hover:brightness-105 active:scale-95",
49
+ children: [
50
+ /* @__PURE__ */ jsx(MessageCircle, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
51
+ /* @__PURE__ */ jsx("span", { className: compact ? "fz-tight-hide tabular-nums" : "tabular-nums", children: phoneDisplay(phone) })
52
+ ]
53
+ }
54
+ ),
55
+ /* @__PURE__ */ jsxs(Dropdown, { children: [
56
+ /* @__PURE__ */ jsx(DropdownTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
57
+ Button,
58
+ {
59
+ variant: "bare",
60
+ size: "bare",
61
+ type: "button",
62
+ "aria-label": t("agenda.confirmations.otherChannels"),
63
+ className: "rounded-none flex h-8 w-6 items-center justify-center border-l border-black/10 bg-[#25D366] text-white transition-all hover:brightness-105 active:scale-95",
64
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5" })
65
+ }
66
+ ) }),
67
+ /* @__PURE__ */ jsx(DropdownContent, { align: "end", children: /* @__PURE__ */ jsxs(DropdownItem, { onSelect: () => {
68
+ window.location.href = `tel:${whatsappNumber(phone)}`;
69
+ }, children: [
70
+ /* @__PURE__ */ jsx(Phone, { className: "mr-2 h-3.5 w-3.5" }),
71
+ t("agenda.confirmations.call")
72
+ ] }) })
73
+ ] })
74
+ ] });
75
+ }
76
+ function BookingCard({
77
+ booking,
78
+ clientKind,
79
+ flagClass,
80
+ badge,
81
+ actions,
82
+ showDate,
83
+ late,
84
+ aside,
85
+ busy,
86
+ selected,
87
+ className,
88
+ style,
89
+ hideClient,
90
+ showMoney = true,
91
+ formatCurrency: formatCurrency$1
92
+ }) {
93
+ const t = useTranslation();
94
+ const services = (booking.services ?? []).map((s) => s.name).join(", ");
95
+ const fmt = formatCurrency$1 ?? ((v) => formatCurrency(v, "BRL"));
96
+ const money = showMoney && booking.orderTotal != null ? fmt(booking.orderTotal) : null;
97
+ const nome = booking.clientName ?? t("agenda.confirmations.unknownClient");
98
+ return /* @__PURE__ */ jsxs(
99
+ "div",
100
+ {
101
+ className: `fz-container flex items-start gap-3 rounded-2xl border border-border bg-card px-3 py-2.5 transition-all ${// `outline`, não `border`/`ring`: temas de superfície (glass) sobem
102
+ // `body .border { border-color: transparent }` por cima de qualquer
103
+ // utility de cor de borda, e anulam o ring junto. O outline ninguém
104
+ // reescreve.
105
+ selected ? "outline outline-2 -outline-offset-1 outline-foreground shadow-sm" : ""} ${className ?? ""}`,
106
+ style,
107
+ "data-state": selected ? "active" : void 0,
108
+ "aria-busy": busy,
109
+ children: [
110
+ flagClass && /* @__PURE__ */ jsx("div", { className: `w-1 shrink-0 self-stretch rounded-full ${flagClass}`, "aria-hidden": true }),
111
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
112
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-0.5", children: [
113
+ showDate && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs font-medium text-muted-foreground", children: [
114
+ /* @__PURE__ */ jsx(CalendarDays, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
115
+ formatCardDate(booking.startsAt)
116
+ ] }),
117
+ /* @__PURE__ */ jsxs("span", { className: `inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-xs font-medium tabular-nums ${late ? "text-destructive" : "text-muted-foreground"}`, children: [
118
+ /* @__PURE__ */ jsx(Clock, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
119
+ formatCardTime(booking.startsAt),
120
+ late && /* @__PURE__ */ jsx("span", { className: "font-semibold", children: "\xB7 atrasado" })
121
+ ] }),
122
+ !hideClient && /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-sm font-semibold text-foreground", children: booking.clientId ? /* @__PURE__ */ jsx(PersonLink, { personId: booking.clientId, name: nome, kind: Array.isArray(clientKind) ? clientKind[0] : clientKind }) : nome })
123
+ ] }),
124
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-muted-foreground", children: [
125
+ booking.professionalName ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 truncate", children: [
126
+ /* @__PURE__ */ jsx(User, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
127
+ booking.professionalName
128
+ ] }) : !booking.professionalId ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 truncate", children: [
129
+ /* @__PURE__ */ jsx(User, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
130
+ t("agenda.card.noProfessional")
131
+ ] }) : null,
132
+ booking.locationName && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 truncate", children: [
133
+ /* @__PURE__ */ jsx(MapPin, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
134
+ booking.locationName
135
+ ] }),
136
+ booking.resourceName && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 truncate", children: [
137
+ /* @__PURE__ */ jsx(DoorOpen, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
138
+ booking.resourceName
139
+ ] }),
140
+ services && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 truncate", children: [
141
+ /* @__PURE__ */ jsx(Briefcase, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
142
+ services
143
+ ] }),
144
+ booking.totalDurationMinutes ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 tabular-nums", children: [
145
+ /* @__PURE__ */ jsx(Clock, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
146
+ booking.totalDurationMinutes,
147
+ "min"
148
+ ] }) : null,
149
+ money && /* @__PURE__ */ jsx("span", { className: "inline-flex items-center gap-1.5 tabular-nums font-medium text-foreground", children: money })
150
+ ] }),
151
+ booking.notes && /* @__PURE__ */ jsxs("p", { className: "truncate text-xs italic text-muted-foreground/80", children: [
152
+ t("agenda.confirmations.notesPrefix"),
153
+ " ",
154
+ booking.notes
155
+ ] })
156
+ ] }),
157
+ aside,
158
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col items-end gap-1.5", children: [
159
+ badge,
160
+ actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children: actions })
161
+ ] })
162
+ ]
163
+ }
164
+ );
165
+ }
166
+
167
+ export { AgendaFilterRail, AgendaRailColumn, AgendaWorkspace, BookingCard, ClientContactButton };
168
+ //# sourceMappingURL=chunk-HGJI2JR6.js.map
169
+ //# sourceMappingURL=chunk-HGJI2JR6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/AgendaFilterRail.tsx","../src/lib/phone.ts","../src/components/BookingCard.tsx"],"names":["jsx","formatCurrency","formatMoney"],"mappings":"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","file":"chunk-HGJI2JR6.js","sourcesContent":["import React from 'react'\nimport { FilterRail, RailWorkspace, AdaptiveFilter, FILTER_RAIL_WIDTH, INLINE_FILTER_MAX } from '@fayz-ai/ui'\nimport type { FilterRailProps, FilterRailSection, AdaptiveFilterOption } from '@fayz-ai/ui'\nimport { useRightRailStore } from '@fayz-ai/admin'\n\n// ---------------------------------------------------------------------------\n// A coluna da agenda — que agora é A coluna, e mora no design system.\n//\n// O componente nasceu aqui, com Agenda, Check-in, Confirmações e Comunicação\n// brigando por quatro versões da mesma coisa. A pergunta, porém, nunca foi da\n// agenda: escala, ponto e encargos recortam listas do mesmo jeito, e o\n// workforce estava a caminho de desenhar a quinta. Subiu para\n// `@fayz-ai/ui` (primitives/filter-rail) com o nome do que faz.\n//\n// O que ficou aqui é a única coisa que é mesmo deste aplicativo: a coluna CEDE\n// quando o rail de detalhe abre à direita. Quem sabe que existe um rail de\n// detalhe é a casca do admin, e uma primitiva não pode importá-la.\n// ---------------------------------------------------------------------------\n\nexport { AdaptiveFilter, INLINE_FILTER_MAX }\nexport type { AdaptiveFilterOption }\nexport const AGENDA_RAIL_WIDTH = FILTER_RAIL_WIDTH\nexport const AgendaFilterRail = FilterRail\nexport type AgendaFilterRailProps = FilterRailProps\nexport type AgendaFilterSection = FilterRailSection\n\nexport function AgendaRailColumn({ children }: { children: React.ReactNode }) {\n const collapsed = useRightRailStore((s) => s.open)\n return <RailWorkspaceColumn collapsed={collapsed}>{children}</RailWorkspaceColumn>\n}\n\nfunction RailWorkspaceColumn({ collapsed, children }: { collapsed: boolean; children: React.ReactNode }) {\n return <RailWorkspace collapsed={collapsed} rail={children}>{null}</RailWorkspace>\n}\n\nexport function AgendaWorkspace({ rail, children, className }: {\n rail: React.ReactNode\n children: React.ReactNode\n className?: string\n}) {\n const collapsed = useRightRailStore((s) => s.open)\n return (\n <RailWorkspace rail={rail} className={className} collapsed={collapsed}>\n {children}\n </RailWorkspace>\n )\n}\n","import { normalizePhone } from '@fayz-ai/ui'\n\n// ---------------------------------------------------------------------------\n// O telefone do cliente, nas duas formas em que a agenda precisa dele.\n//\n// Estava escrito dentro de Confirmações e ia ser escrito de novo no Check-in.\n// Duas cópias da mesma regra de formatação divergem na primeira vez que alguém\n// conserta uma delas — e telefone errado num botão de WhatsApp é a recepção\n// mandando mensagem para outra pessoa.\n// ---------------------------------------------------------------------------\n\n/** Só dígitos, com o país na frente — o formato que o `wa.me` e o `tel:` pedem. */\nexport function whatsappNumber(raw: string): string {\n const digits = raw.replace(/\\D/g, '')\n // Onze dígitos é um celular brasileiro sem o país; dez, um fixo. O DDI só\n // entra quando falta, senão \"5521…\" viraria \"555521…\".\n return digits.length <= 11 ? `55${digits}` : digits\n}\n\n/**\n * O número como se lê em voz alta, SEM o país.\n *\n * \"+55 (21) 99788-1675\" num botão de 180px empurra o DDD para fora e gasta\n * quatro caracteres dizendo o que toda linha desta tela tem em comum. Quem\n * confere um telefone confere o DDD e o final; o +55 é do `tel:`, não do olho.\n */\nexport function phoneDisplay(raw: string | null | undefined): string {\n const display = normalizePhone(raw).display || (raw ?? '')\n return display.replace(/^\\+\\d{1,3}\\s*/, '')\n}\n","import React from 'react'\nimport {\n Briefcase, CalendarDays, ChevronDown, Clock, DoorOpen, MapPin, MessageCircle, Phone, User,\n} from 'lucide-react'\nimport { Button, Dropdown, DropdownContent, DropdownItem, DropdownTrigger } from '@fayz-ai/ui'\nimport { PersonLink } from '@fayz-ai/admin'\nimport { useTranslation, formatCurrency as formatMoney } from '@fayz-ai/core'\nimport { phoneDisplay, whatsappNumber } from '../lib/phone'\nimport type { CalendarBooking } from '../types'\n\n// ---------------------------------------------------------------------------\n// O CARTÃO DE UM COMPROMISSO — um só, para as telas que listam compromissos.\n//\n// Check-in e Confirmações são a MESMA leitura: quando, quem, com quem, para\n// quê, e um canal para falar. O que muda entre elas é o que se FAZ no fim da\n// linha — \"Check-in\" numa, \"Confirmar/Cancelar\" na outra. Por um tempo cada\n// tela desenhou o seu, e as duas divergiram onde ninguém queria: o serviço\n// aparecia numa e não na outra, o telefone virava botão numa e texto na outra,\n// a data existia numa e sumia na outra.\n//\n// Aqui o cartão é o mesmo e as AÇÕES são um slot. A tela diz o que oferece; o\n// cartão diz o que a pessoa precisa saber para escolher.\n//\n// ── O que é slot e o que é regra ──────────────────────────────────────────\n//\n// Slot: as ações, o selo de estado e a cor da faixa — são da tela.\n// Regra: a ordem das linhas, o que entra em cada uma, e o fato de o nome abrir\n// a ficha. Se cada tela pudesse reordenar, voltaríamos a ter dois cartões com\n// um arquivo só.\n// ---------------------------------------------------------------------------\n\nconst two = (n: number) => String(n).padStart(2, '0')\n\nexport const formatCardTime = (iso: string) => {\n const d = new Date(iso)\n return `${two(d.getHours())}:${two(d.getMinutes())}`\n}\n\nexport const formatCardDate = (iso: string) => {\n const d = new Date(iso)\n return `${two(d.getDate())}/${two(d.getMonth() + 1)}`\n}\n\n/**\n * Falar com a cliente: WhatsApp na frente, ligar na setinha.\n *\n * O número some quando o CARTÃO aperta, não quando a janela aperta. Era\n * `lg:inline` — um breakpoint de viewport — e o rail de detalhes abre sobre uma\n * janela larga: a janela continuava \"grande\", o número continuava escrito, e o\n * cartão de 390px cortava o resto no meio da palavra (\"Vinici\", \"Treina\",\n * \"Avalia\"). `fz-tight-hide` mede o contêiner, que é quem realmente encolheu.\n *\n * WhatsApp é como se fala com cliente no Brasil; ligar é a alternativa de quem\n * não respondeu, não um igual. O número é o RÓTULO do botão — quem vai falar lê\n * o telefone antes de clicar — e por isso não se repete no \"Ligar\": é o mesmo\n * número, do mesmo cartão, a dois centímetros de distância.\n *\n * O verde é o do WhatsApp e não o `success` do tema: o botão é reconhecido pela\n * cor do aplicativo que ele abre, antes de qualquer leitura.\n */\nexport function ClientContactButton({ phone, compact }: { phone: string; compact?: boolean }) {\n const t = useTranslation()\n return (\n <div className=\"flex items-stretch overflow-hidden rounded-button shadow-button\">\n <a\n href={`https://wa.me/${whatsappNumber(phone)}`}\n target=\"_blank\"\n rel=\"noreferrer\"\n aria-label={`${t('agenda.confirmations.sendWhatsApp')} ${phoneDisplay(phone)}`}\n className=\"flex h-8 items-center gap-1.5 bg-[#25D366] px-2.5 text-xs font-medium text-white transition-all hover:brightness-105 active:scale-95\"\n >\n <MessageCircle className=\"h-3.5 w-3.5 shrink-0\" aria-hidden />\n <span className={compact ? 'fz-tight-hide tabular-nums' : 'tabular-nums'}>{phoneDisplay(phone)}</span>\n </a>\n <Dropdown>\n <DropdownTrigger asChild>\n <Button variant=\"bare\" size=\"bare\"\n type=\"button\"\n aria-label={t('agenda.confirmations.otherChannels')}\n className=\"rounded-none flex h-8 w-6 items-center justify-center border-l border-black/10 bg-[#25D366] text-white transition-all hover:brightness-105 active:scale-95\"\n >\n <ChevronDown className=\"h-3.5 w-3.5\" />\n </Button>\n </DropdownTrigger>\n <DropdownContent align=\"end\">\n <DropdownItem onSelect={() => { window.location.href = `tel:${whatsappNumber(phone)}` }}>\n <Phone className=\"mr-2 h-3.5 w-3.5\" />\n {t('agenda.confirmations.call')}\n </DropdownItem>\n </DropdownContent>\n </Dropdown>\n </div>\n )\n}\n\nexport interface BookingCardProps {\n booking: CalendarBooking\n /** O ofício de quem é atendido — um cliente de salão não mora onde o de loja.\n * Aceita lista porque a configuração da agenda aceita: uma casa pode atender\n * mais de um ofício. O LINK usa o primeiro — ele abre a ficha de UMA pessoa,\n * e o `kind` ali só escolhe por qual porta procurá-la. */\n clientKind?: string | string[]\n /** A faixa de cor à esquerda. Vazio = sem faixa. */\n flagClass?: string\n /** O selo de estado, no alto à direita. */\n badge?: React.ReactNode\n /** O que ESTA tela oferece fazer. É a única coisa que muda entre elas. */\n actions?: React.ReactNode\n /** Mostrar a data além da hora. Check-in é só hoje; Confirmações olha adiante. */\n showDate?: boolean\n /**\n * Passou da hora e a pessoa não chegou. Pinta o RELÓGIO de vermelho — é o\n * dado que muda o que a recepção faz, e ele mora na hora, não num selo à\n * parte: quem varre a coluna da esquerda vendo horários vê o atraso no\n * mesmo lugar em que lê a hora.\n */\n late?: boolean\n /** Algo à esquerda das ações — o selo de pagamento da fila, por exemplo. */\n aside?: React.ReactNode\n /**\n * Esconde o nome do cliente. Para o HISTÓRICO, que já está dentro da ficha\n * dele: repetir \"Matheus Teste 2\" em cada linha da lista dele é ruído.\n */\n hideClient?: boolean\n /**\n * Mostrar o valor na linha. A fila o esconde porque já tem o selo de\n * pagamento ao lado, que diz o valor E o estado dele.\n */\n showMoney?: boolean\n /** Como esta casa escreve dinheiro. */\n formatCurrency?: (value: number) => string\n busy?: boolean\n /**\n * Este cartão é o que está aberto no painel ao lado. Com o rail ocupando a\n * direita, a fila continua visível — e sem a borda o olho perde de quem é a\n * conferência que está lendo.\n */\n selected?: boolean\n className?: string\n style?: React.CSSProperties\n}\n\nexport function BookingCard({\n booking, clientKind, flagClass, badge, actions, showDate, late, aside, busy, selected, className, style,\n hideClient, showMoney = true, formatCurrency,\n}: BookingCardProps) {\n const t = useTranslation()\n const services = (booking.services ?? []).map((s) => s.name).join(', ')\n // Zero é valor VÁLIDO: uma avaliação de cortesia custa R$ 0,00 e continua\n // sendo um compromisso. O que não há é `null` — aí não existe fatura, e\n // escrever \"R$ 0,00\" seria afirmar um preço que ninguém definiu.\n const fmt = formatCurrency ?? ((v: number) => formatMoney(v, 'BRL'))\n const money = showMoney && booking.orderTotal != null ? fmt(booking.orderTotal) : null\n const nome = booking.clientName ?? t('agenda.confirmations.unknownClient')\n\n return (\n <div\n // `fz-container` é o ponto de medição: as partes que cedem primeiro\n // (o número do telefone) respondem à largura DESTE cartão.\n className={`fz-container flex items-start gap-3 rounded-2xl border border-border bg-card px-3 py-2.5 transition-all ${\n // `outline`, não `border`/`ring`: temas de superfície (glass) sobem\n // `body .border { border-color: transparent }` por cima de qualquer\n // utility de cor de borda, e anulam o ring junto. O outline ninguém\n // reescreve.\n selected ? 'outline outline-2 -outline-offset-1 outline-foreground shadow-sm' : ''\n } ${className ?? ''}`}\n style={style}\n data-state={selected ? 'active' : undefined}\n aria-busy={busy}\n >\n {flagClass && <div className={`w-1 shrink-0 self-stretch rounded-full ${flagClass}`} aria-hidden />}\n\n <div className=\"min-w-0 flex-1 space-y-1\">\n {/* Linha 1: QUANDO e QUEM — é por onde se liga. */}\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-0.5\">\n {showDate && (\n <span className=\"inline-flex items-center gap-1.5 text-xs font-medium text-muted-foreground\">\n <CalendarDays className=\"h-3.5 w-3.5 shrink-0\" aria-hidden />\n {formatCardDate(booking.startsAt)}\n </span>\n )}\n {/* HORA E ATRASO NÃO SE SEPARAM.\n No celular a linha quebrava entre o \"·\" e a palavra, e sobrava um\n ponto órfão no fim de uma linha e \"atrasado\" sozinho na seguinte.\n São uma informação só: a hora e o fato de ela já ter passado. */}\n <span className={`inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-xs font-medium tabular-nums ${\n late ? 'text-destructive' : 'text-muted-foreground'\n }`}>\n <Clock className=\"h-3.5 w-3.5 shrink-0\" aria-hidden />\n {formatCardTime(booking.startsAt)}\n {late && <span className=\"font-semibold\">· atrasado</span>}\n </span>\n {/* A MESMA ficha que a grade e a fila abrem: quem vai falar com a\n cliente quer ver o histórico antes — quantas vezes faltou, o que\n costuma marcar. */}\n {/* `min-w-0` junto do `truncate`: um item de flex nasce com\n `min-width: auto` e se recusa a encolher abaixo do conteúdo — o\n nome longo transbordava a borda do cartão em vez de virar\n reticências. */}\n {!hideClient && (\n <span className=\"min-w-0 truncate text-sm font-semibold text-foreground\">\n {booking.clientId\n ? <PersonLink personId={booking.clientId} name={nome} kind={Array.isArray(clientKind) ? clientKind[0] : clientKind} />\n : nome}\n </span>\n )}\n </div>\n\n {/* Linha 2: o ATENDIMENTO — com quem, onde, para quê, quanto. */}\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-muted-foreground\">\n {/* \"Sem profissional\" é uma AFIRMAÇÃO: diz que ninguém foi designado.\n Quando o agendamento TEM `professionalId` e o nome não veio, o que\n houve foi outra coisa — a RLS de pessoa é por alcance de unidade, e\n um profissional de outra unidade não volta na consulta nem pela\n view (`security_invoker`). Aí a linha simplesmente não aparece:\n ausência não afirma nada, e afirmar o contrário faria a recepção\n procurar um responsável que existe. */}\n {booking.professionalName ? (\n <span className=\"inline-flex items-center gap-1.5 truncate\">\n <User className=\"h-3.5 w-3.5 shrink-0\" aria-hidden />\n {booking.professionalName}\n </span>\n ) : !booking.professionalId ? (\n <span className=\"inline-flex items-center gap-1.5 truncate\">\n <User className=\"h-3.5 w-3.5 shrink-0\" aria-hidden />\n {t('agenda.card.noProfessional')}\n </span>\n ) : null}\n {booking.locationName && (\n <span className=\"inline-flex items-center gap-1.5 truncate\">\n <MapPin className=\"h-3.5 w-3.5 shrink-0\" aria-hidden />\n {booking.locationName}\n </span>\n )}\n {/* A SALA, quando há. Escolher a sala e não vê-la em lugar nenhum é\n uma decisão que some: quem separou a maca não consegue conferir\n depois. Ícone próprio porque ela NÃO é a unidade — o alfinete do\n mapa já é dela. */}\n {booking.resourceName && (\n <span className=\"inline-flex items-center gap-1.5 truncate\">\n <DoorOpen className=\"h-3.5 w-3.5 shrink-0\" aria-hidden />\n {booking.resourceName}\n </span>\n )}\n {services && (\n <span className=\"inline-flex items-center gap-1.5 truncate\">\n <Briefcase className=\"h-3.5 w-3.5 shrink-0\" aria-hidden />\n {services}\n </span>\n )}\n {/* Zero é valor válido — uma avaliação de cortesia custa R$ 0,00 e\n continua sendo um compromisso —, mas sem fatura não há o que\n dizer, e um \"R$ 0,00\" ali seria uma afirmação errada. */}\n {/* Quanto tempo a sala fica ocupada — o V1 mostra no histórico, e\n vale nas três listas: é o que separa uma avaliação de 30min de um\n procedimento que toma a tarde. */}\n {booking.totalDurationMinutes ? (\n <span className=\"inline-flex items-center gap-1.5 tabular-nums\">\n <Clock className=\"h-3.5 w-3.5 shrink-0\" aria-hidden />\n {booking.totalDurationMinutes}min\n </span>\n ) : null}\n {/* SEM `ml-auto`. Empurrar o valor para a direita alinha uma coluna\n bonita enquanto tudo cabe numa linha; quando a linha quebra — e\n ela quebra assim que a tela estreita — o valor vai sozinho para a\n linha de baixo, encostado na borda, longe do serviço que ele\n precifica. Inline ele fica ao lado do que cobra, que é como o V1\n escreve a linha: os serviços, e o valor. */}\n {money && (\n <span className=\"inline-flex items-center gap-1.5 tabular-nums font-medium text-foreground\">\n {money}\n </span>\n )}\n </div>\n\n {booking.notes && (\n <p className=\"truncate text-xs italic text-muted-foreground/80\">\n {t('agenda.confirmations.notesPrefix')} {booking.notes}\n </p>\n )}\n </div>\n\n {aside}\n\n {/* O selo diz ONDE está; as ações dizem o que fazer a seguir. */}\n <div className=\"flex shrink-0 flex-col items-end gap-1.5\">\n {badge}\n {actions && <div className=\"flex items-center gap-1.5\">{actions}</div>}\n </div>\n </div>\n )\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import { usePluginRuntimeOptional, getWidgetsForZone } from '@fayz-ai/core';
2
+
3
+ // src/hooks/useZoneFilled.ts
4
+ function useZoneFilled(zone) {
5
+ const runtime = usePluginRuntimeOptional();
6
+ return runtime ? getWidgetsForZone(runtime, zone).length > 0 : false;
7
+ }
8
+
9
+ export { useZoneFilled };
10
+ //# sourceMappingURL=chunk-VFQPXKXP.js.map
11
+ //# sourceMappingURL=chunk-VFQPXKXP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useZoneFilled.ts"],"names":[],"mappings":";;;AAGO,SAAS,cAAc,IAAA,EAAuB;AACnD,EAAA,MAAM,UAAU,wBAAA,EAAyB;AACzC,EAAA,OAAO,UAAU,iBAAA,CAAkB,OAAA,EAAS,IAAI,CAAA,CAAE,SAAS,CAAA,GAAI,KAAA;AACjE","file":"chunk-VFQPXKXP.js","sourcesContent":["import { getWidgetsForZone, usePluginRuntimeOptional } from '@fayz-ai/core'\n\n/** Whether a mounted plugin fills this zone, so a host can hide the action that would open it. */\nexport function useZoneFilled(zone: string): boolean {\n const runtime = usePluginRuntimeOptional()\n return runtime ? getWidgetsForZone(runtime, zone).length > 0 : false\n}\n"]}