@fayz-ai/plugin-agenda 0.9.0 → 0.9.1

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 (153) hide show
  1. package/README.md +3 -3
  2. package/dist/bridges/create-financial-bridge.d.ts +1 -1
  3. package/dist/bridges/create-financial-bridge.d.ts.map +1 -1
  4. package/dist/bridges/financial-bridge.d.ts.map +1 -0
  5. package/dist/{chunk-Q2PAWBPR.js → chunk-76ZOHRBM.js} +2 -2
  6. package/dist/{chunk-Q2PAWBPR.js.map → chunk-76ZOHRBM.js.map} +1 -1
  7. package/dist/components/PaymentStatusBadge.d.ts +1 -1
  8. package/dist/components/PaymentStatusBadge.d.ts.map +1 -1
  9. package/dist/config.d.ts +2 -2
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/{AgendaContext.d.ts → context.d.ts} +1 -1
  12. package/dist/context.d.ts.map +1 -0
  13. package/dist/data/registries.d.ts.map +1 -0
  14. package/dist/index.d.ts +2 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +170 -7
  17. package/dist/index.js.map +1 -1
  18. package/dist/lib/message-events.d.ts +12 -0
  19. package/dist/lib/message-events.d.ts.map +1 -0
  20. package/dist/public/{data.d.ts → data/index.d.ts} +4 -4
  21. package/dist/public/data/index.d.ts.map +1 -0
  22. package/dist/public/{data.supabase.d.ts → data/supabase.d.ts} +2 -2
  23. package/dist/public/data/supabase.d.ts.map +1 -0
  24. package/dist/public/{hooks.d.ts → hooks/index.d.ts} +4 -4
  25. package/dist/public/hooks/index.d.ts.map +1 -0
  26. package/dist/public/index.d.ts +4 -4
  27. package/dist/public/index.d.ts.map +1 -1
  28. package/dist/public/index.js +3 -3
  29. package/dist/public/index.js.map +1 -1
  30. package/dist/public/{format.d.ts → lib/format.d.ts} +1 -1
  31. package/dist/public/lib/format.d.ts.map +1 -0
  32. package/dist/public/views/BookingWidget.d.ts.map +1 -0
  33. package/dist/public/{steps → views/steps}/ContactStep.d.ts +1 -1
  34. package/dist/public/views/steps/ContactStep.d.ts.map +1 -0
  35. package/dist/public/{steps → views/steps}/DateTimeStep.d.ts +3 -3
  36. package/dist/public/views/steps/DateTimeStep.d.ts.map +1 -0
  37. package/dist/public/{steps → views/steps}/OverviewStep.d.ts +1 -1
  38. package/dist/public/views/steps/OverviewStep.d.ts.map +1 -0
  39. package/dist/public/{steps → views/steps}/PaymentStep.d.ts +1 -1
  40. package/dist/public/views/steps/PaymentStep.d.ts.map +1 -0
  41. package/dist/store.d.ts +1 -1
  42. package/dist/store.d.ts.map +1 -1
  43. package/dist/styles/calendar-styles.d.ts.map +1 -0
  44. package/dist/types.d.ts +1 -1
  45. package/dist/types.d.ts.map +1 -1
  46. package/dist/{AgendaPage.d.ts → views/AgendaPage.d.ts} +3 -3
  47. package/dist/views/AgendaPage.d.ts.map +1 -0
  48. package/package.json +6 -9
  49. package/dist/AgendaContext.d.ts.map +0 -1
  50. package/dist/AgendaPage.d.ts.map +0 -1
  51. package/dist/calendar-styles.d.ts.map +0 -1
  52. package/dist/financial-bridge.d.ts.map +0 -1
  53. package/dist/public/BookingWidget.d.ts.map +0 -1
  54. package/dist/public/data.d.ts.map +0 -1
  55. package/dist/public/data.supabase.d.ts.map +0 -1
  56. package/dist/public/format.d.ts.map +0 -1
  57. package/dist/public/hooks.d.ts.map +0 -1
  58. package/dist/public/steps/ContactStep.d.ts.map +0 -1
  59. package/dist/public/steps/DateTimeStep.d.ts.map +0 -1
  60. package/dist/public/steps/OverviewStep.d.ts.map +0 -1
  61. package/dist/public/steps/PaymentStep.d.ts.map +0 -1
  62. package/dist/registries.d.ts.map +0 -1
  63. package/src/AgendaContext.tsx +0 -11
  64. package/src/AgendaPage.tsx +0 -33
  65. package/src/bridges/create-financial-bridge.ts +0 -296
  66. package/src/calendar-styles.css +0 -245
  67. package/src/calendar-styles.ts +0 -285
  68. package/src/components/AgendaGeneralSettings.tsx +0 -86
  69. package/src/components/AgendaMobileList.tsx +0 -103
  70. package/src/components/AppointmentModal.tsx +0 -1050
  71. package/src/components/AppointmentPopover.tsx +0 -231
  72. package/src/components/BookingPaymentPanel.tsx +0 -394
  73. package/src/components/CalendarSidebar.tsx +0 -119
  74. package/src/components/CalendarToolbar.tsx +0 -86
  75. package/src/components/EventContextMenu.tsx +0 -125
  76. package/src/components/FloatingPanel.tsx +0 -123
  77. package/src/components/MiniCalendar.tsx +0 -120
  78. package/src/components/PaymentStatusBadge.tsx +0 -62
  79. package/src/components/StatusBadge.tsx +0 -23
  80. package/src/config.ts +0 -368
  81. package/src/data/index.ts +0 -4
  82. package/src/data/mock.ts +0 -344
  83. package/src/data/supabase.ts +0 -636
  84. package/src/data/types.ts +0 -37
  85. package/src/financial-bridge.ts +0 -96
  86. package/src/hooks/useAgendaSettings.ts +0 -17
  87. package/src/index.ts +0 -297
  88. package/src/integrations/google-calendar/GoogleCalendarSettings.tsx +0 -136
  89. package/src/integrations/google-calendar/components/CalendarColorDot.tsx +0 -23
  90. package/src/integrations/google-calendar/components/ChannelMappingList.tsx +0 -329
  91. package/src/integrations/google-calendar/components/ImportEventsWizard.tsx +0 -215
  92. package/src/integrations/google-calendar/components/useAgendaLookups.ts +0 -100
  93. package/src/integrations/google-calendar/connector.ts +0 -20
  94. package/src/integrations/google-calendar/connectorDef.tsx +0 -185
  95. package/src/integrations/google-calendar/data/supabase.ts +0 -170
  96. package/src/integrations/google-calendar/data/tables.ts +0 -12
  97. package/src/integrations/google-calendar/index.ts +0 -45
  98. package/src/integrations/google-calendar/integration.test.ts +0 -199
  99. package/src/integrations/google-calendar/mapping.ts +0 -183
  100. package/src/integrations/google-calendar/migrations/001_google_calendar.sql +0 -97
  101. package/src/integrations/google-calendar/migrations/002_smart_sync.sql +0 -517
  102. package/src/integrations/google-calendar/migrations/003_plg_rename.sql +0 -273
  103. package/src/integrations/google-calendar/types.ts +0 -142
  104. package/src/lib/tenant.ts +0 -3
  105. package/src/locales/en.ts +0 -220
  106. package/src/locales/index.ts +0 -7
  107. package/src/locales/pt-BR.ts +0 -220
  108. package/src/migrations/000b_v_bookings_rename.sql +0 -21
  109. package/src/migrations/000c_dedupe_customer_phones.sql +0 -43
  110. package/src/migrations/001_public_booking.sql +0 -296
  111. package/src/migrations/002_v_bookings_compat.sql +0 -14
  112. package/src/migrations/003_public_client_kind.sql +0 -175
  113. package/src/migrations/004_public_booking_assignee.sql +0 -176
  114. package/src/migrations/005_agent_rpcs.sql +0 -168
  115. package/src/migrations/006_agent_rpc_localtime.sql +0 -181
  116. package/src/migrations/007_schedule_exception_precedence.sql +0 -290
  117. package/src/migrations/008_agent_rpc_exception_precedence.sql +0 -172
  118. package/src/migrations/009_public_booking_location.sql +0 -162
  119. package/src/migrations/010_public_service_curation.sql +0 -31
  120. package/src/migrations/011_default_assignee.sql +0 -167
  121. package/src/migrations/012_drop_legacy_booking_overload.sql +0 -29
  122. package/src/migrations/013_normalize_v_appointments.sql +0 -199
  123. package/src/migrations/014_agent_rpc_update_appointment.sql +0 -199
  124. package/src/migrations/index.ts +0 -2377
  125. package/src/public/BookingWidget.tsx +0 -324
  126. package/src/public/components/BrandHeader.tsx +0 -27
  127. package/src/public/components/ServiceCard.tsx +0 -39
  128. package/src/public/components/SidebarExtras.tsx +0 -30
  129. package/src/public/components/StepRailItem.tsx +0 -27
  130. package/src/public/components/SuccessPanel.tsx +0 -27
  131. package/src/public/components/SummaryRail.tsx +0 -90
  132. package/src/public/components/defaults.ts +0 -14
  133. package/src/public/context.tsx +0 -103
  134. package/src/public/createPublicBookingPlugin.ts +0 -281
  135. package/src/public/data.supabase.ts +0 -97
  136. package/src/public/data.ts +0 -105
  137. package/src/public/format.ts +0 -96
  138. package/src/public/hooks.ts +0 -110
  139. package/src/public/index.ts +0 -69
  140. package/src/public/steps/ContactStep.tsx +0 -184
  141. package/src/public/steps/DateTimeStep.tsx +0 -138
  142. package/src/public/steps/OverviewStep.tsx +0 -81
  143. package/src/public/steps/PaymentStep.tsx +0 -180
  144. package/src/public/types.ts +0 -250
  145. package/src/registries.ts +0 -35
  146. package/src/store.ts +0 -311
  147. package/src/types.ts +0 -273
  148. package/src/views/CalendarView.tsx +0 -1112
  149. package/src/views/ConfirmationsView.tsx +0 -155
  150. /package/dist/{financial-bridge.d.ts → bridges/financial-bridge.d.ts} +0 -0
  151. /package/dist/{registries.d.ts → data/registries.d.ts} +0 -0
  152. /package/dist/public/{BookingWidget.d.ts → views/BookingWidget.d.ts} +0 -0
  153. /package/dist/{calendar-styles.d.ts → styles/calendar-styles.d.ts} +0 -0
@@ -1,180 +0,0 @@
1
- import { CalendarCheck, Check, Copy, CreditCard, Loader2, Plus, QrCode, ShieldCheck } from 'lucide-react'
2
- import type { PixCharge } from '@fayz-ai/core'
3
- import type { BookingFormatters, PublicService, ResolvedPayment } from '../types'
4
-
5
- // Static, realistic-looking Pix payload for the POC copia-e-cola fallback
6
- // (used only when no payment provider is injected).
7
- const PIX_PAYLOAD =
8
- '00020126840014br.gov.bcb.pix2562qrcode.fayz.ai/pix/v2/9d8f7a6b-agendamento5204000053039865802BR5904FAYZ6009SAO PAULO62070503***6304AB12'
9
-
10
- /** Deterministic QR-looking placeholder rendered from a payload (POC visual). */
11
- function QrPlaceholder({ data }: { data: string }) {
12
- const size = 25
13
- // Seed the data-cell pattern from the payload so different charges look different.
14
- let seed = 0
15
- for (let i = 0; i < data.length; i++) seed = (seed * 31 + data.charCodeAt(i)) % 100000
16
- const cells: { x: number; y: number }[] = []
17
- const isFinder = (x: number, y: number) => {
18
- const inBox = (bx: number, by: number) => x >= bx && x < bx + 7 && y >= by && y < by + 7
19
- return inBox(0, 0) || inBox(size - 7, 0) || inBox(0, size - 7)
20
- }
21
- for (let y = 0; y < size; y++) {
22
- for (let x = 0; x < size; x++) {
23
- if (isFinder(x, y)) {
24
- const corner = x < 7 && y < 7 ? { bx: 0, by: 0 } : x >= size - 7 && y < 7 ? { bx: size - 7, by: 0 } : { bx: 0, by: size - 7 }
25
- const lx = x - corner.bx
26
- const ly = y - corner.by
27
- const outer = lx === 0 || lx === 6 || ly === 0 || ly === 6
28
- const inner = lx >= 2 && lx <= 4 && ly >= 2 && ly <= 4
29
- if (outer || inner) cells.push({ x, y })
30
- } else if ((x * 31 + y * 17 + x * y + seed) % 3 === 0) {
31
- cells.push({ x, y })
32
- }
33
- }
34
- }
35
- return (
36
- <svg viewBox={`0 0 ${size} ${size}`} className="h-40 w-40" role="img" aria-label="QR Code Pix (demonstração)">
37
- <rect width={size} height={size} fill="white" />
38
- {cells.map((c, i) => (
39
- <rect key={i} x={c.x} y={c.y} width={1} height={1} fill="currentColor" className="text-foreground" />
40
- ))}
41
- </svg>
42
- )
43
- }
44
-
45
- interface PaymentStepProps {
46
- service: PublicService
47
- payment: ResolvedPayment
48
- paymentStep: 'choose' | 'pix'
49
- charge: PixCharge | null
50
- busy: boolean
51
- error: Error | null
52
- copied: boolean
53
- fmt: BookingFormatters
54
- onPayWithPix: (fee: number) => void
55
- onCopy: () => void
56
- onSimulatePaid: () => void
57
- }
58
-
59
- /** Payment step: order summary + Pix method → QR/copia-e-cola while polling. */
60
- export function PaymentStep({
61
- service, payment, paymentStep, charge, busy, error, copied, fmt, onPayWithPix, onCopy, onSimulatePaid,
62
- }: PaymentStepProps) {
63
- const feePct = payment.reservationFeePercent
64
- const fee = Math.round(service.price * feePct) / 100
65
- const remaining = Math.round((service.price - fee) * 100) / 100
66
-
67
- if (paymentStep === 'choose') {
68
- return (
69
- <div>
70
- {/* Order summary */}
71
- <div className="rounded-2xl border border-border p-4">
72
- <div className="flex items-center justify-between font-semibold text-foreground">
73
- <span>{service.name}</span>
74
- <span className="tabular-nums">{fmt.price.format(service.price)}</span>
75
- </div>
76
- <div className="mt-3 space-y-2 text-sm">
77
- <div className="flex items-center justify-between text-foreground">
78
- <span className="flex items-center gap-2">
79
- <span className="flex h-4 w-4 items-center justify-center rounded bg-primary text-primary-foreground"><Check className="h-3 w-3" /></span>
80
- Taxa de reserva <span className="rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground">{feePct}%</span>
81
- </span>
82
- <span className="tabular-nums">{fmt.price.format(fee)}</span>
83
- </div>
84
- <div className="flex items-center justify-between text-muted-foreground">
85
- <span className="flex items-center gap-2">
86
- <span className="h-4 w-4 rounded border border-border" /> Valor restante
87
- </span>
88
- <span className="tabular-nums">{remaining <= 0 ? 'Grátis' : fmt.price.format(remaining)}</span>
89
- </div>
90
- <button type="button" className="flex items-center gap-1 text-sm font-medium text-primary hover:underline">
91
- <Plus className="h-3.5 w-3.5" /> Adicionar cupom
92
- </button>
93
- </div>
94
- <div className="mt-3 flex items-center justify-between border-t border-dashed border-border pt-3 font-semibold text-foreground">
95
- <span>Valor total</span>
96
- <span className="tabular-nums">{fmt.price.format(service.price)}</span>
97
- </div>
98
- </div>
99
-
100
- {/* Method */}
101
- <div className="mt-6 flex items-center justify-between">
102
- <h3 className="font-heading text-lg font-bold text-foreground">Escolha como pagar</h3>
103
- <span className="flex items-center gap-1 text-xs text-muted-foreground"><ShieldCheck className="h-3.5 w-3.5 text-primary" /> Pagamento seguro</span>
104
- </div>
105
- <div className="mt-3 rounded-2xl border-2 border-primary bg-accent/20 p-4">
106
- <p className="flex items-center gap-2 font-semibold text-foreground">
107
- <span className="flex h-5 w-5 items-center justify-center rounded-full bg-primary text-primary-foreground"><Check className="h-3.5 w-3.5" /></span>
108
- Pix
109
- </p>
110
- <div className="mt-4 grid grid-cols-1 gap-4 sm:grid-cols-3">
111
- {[
112
- { icon: Check, t: 'Finalize o agendamento clicando em "Pagar com Pix".' },
113
- { icon: QrCode, t: 'Mostraremos um QR Code e o Pix copia-e-cola.' },
114
- { icon: CalendarCheck, t: 'Após o pagamento, seu agendamento é reservado.' },
115
- ].map((s, i) => (
116
- <div key={i} className="text-sm text-muted-foreground">
117
- <span className="mb-2 flex h-8 w-8 items-center justify-center rounded-lg bg-accent text-primary"><s.icon className="h-4 w-4" /></span>
118
- <span className="font-semibold text-foreground">{i + 1}.</span> {s.t}
119
- </div>
120
- ))}
121
- </div>
122
- </div>
123
-
124
- {error ? <p role="alert" className="mt-3 text-sm text-destructive">Não foi possível iniciar o pagamento. Tente novamente.</p> : null}
125
- <button
126
- type="button"
127
- disabled={busy}
128
- onClick={() => onPayWithPix(fee)}
129
- className="mt-6 flex w-full items-center justify-center gap-2 rounded-xl bg-primary py-3 font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
130
- >
131
- {busy ? <Loader2 className="h-4 w-4 animate-spin" /> : <CreditCard className="h-4 w-4" />}
132
- Pagar {fmt.price.format(fee)} com Pix
133
- </button>
134
- </div>
135
- )
136
- }
137
-
138
- // Pix QR — aguardando pagamento
139
- return (
140
- <div>
141
- <div className="rounded-xl border border-amber-300/60 bg-amber-50 p-4 dark:border-amber-400/30 dark:bg-amber-950/30">
142
- <p className="flex items-center gap-2 text-sm font-semibold text-foreground">
143
- <Loader2 className="h-4 w-4 animate-spin text-primary" /> Realize o pagamento para finalizar
144
- </p>
145
- <p className="mt-1 text-xs text-muted-foreground">
146
- Este código Pix é válido por somente 5 minutos. Não feche esta página até receber a confirmação do pagamento.
147
- </p>
148
- </div>
149
- <h3 className="mt-6 font-heading text-lg font-bold text-foreground">Escaneie ou copie este código para pagar</h3>
150
- <ol className="mt-2 space-y-1 text-sm text-muted-foreground">
151
- <li>1. Acesse o app do seu banco, pagamentos ou Internet Banking.</li>
152
- <li>2. Escolha pagar via Pix.</li>
153
- <li>3. Escaneie o QR Code ou use o Pix copia-e-cola:</li>
154
- </ol>
155
- <div className="mt-4 w-fit rounded-xl border border-border bg-white p-3">
156
- <QrPlaceholder data={charge?.pixQrCode ?? PIX_PAYLOAD} />
157
- </div>
158
- <div className="mt-4 flex max-w-md items-center gap-2">
159
- <code className="flex-1 truncate rounded-lg border border-border bg-muted px-3 py-2 text-xs text-muted-foreground">{charge?.pixCopyPaste ?? PIX_PAYLOAD}</code>
160
- <button
161
- type="button"
162
- onClick={onCopy}
163
- className="inline-flex shrink-0 items-center gap-1.5 rounded-lg bg-foreground px-3 py-2 text-xs font-medium text-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
164
- >
165
- {copied ? <Check className="h-3.5 w-3.5" /> : <Copy className="h-3.5 w-3.5" />} {copied ? 'Copiado' : 'Copiar'}
166
- </button>
167
- </div>
168
- {/* POC shortcut — the mock provider also auto-confirms via polling after a few seconds. */}
169
- <button
170
- type="button"
171
- onClick={onSimulatePaid}
172
- className="mt-6 w-full rounded-xl border border-primary py-3 font-semibold text-primary transition-colors hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
173
- >
174
- Já paguei — confirmar (simulação)
175
- </button>
176
- </div>
177
- )
178
- }
179
-
180
- export { PIX_PAYLOAD }
@@ -1,250 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Public (customer-facing) booking types. This surface is deliberately decoupled
3
- // from the admin calendar: it depends only on the narrow PublicBookingDataProvider
4
- // seam (see ./data), so mock slots today and real availability (Supabase RPC /
5
- // ERP / Google Calendar) later are a provider swap with no widget change.
6
- //
7
- // Customization model: hosts personalize via three levers, cheapest first —
8
- // 1. `labels` — every user-visible string (all defaulted, pt-BR)
9
- // 2. `brand` — name/logo/tagline/icons/badges/highlights (text + assets)
10
- // 3. `components` — swap whole subcomponents (BookingComponents) when the
11
- // structure itself must change. Defaults are exported for composition.
12
- // ---------------------------------------------------------------------------
13
-
14
- import type { ComponentType, ReactNode } from 'react'
15
-
16
- export interface PublicService {
17
- id: string
18
- name: string
19
- durationMinutes: number
20
- price: number
21
- description?: string
22
- }
23
-
24
- export interface ContactInfo {
25
- name: string
26
- email?: string
27
- phone?: string
28
- notes?: string
29
- }
30
-
31
- export interface WorkingHours {
32
- /** 0=Sun … 6=Sat. */
33
- daysOfWeek: number[]
34
- /** 'HH:MM' */
35
- start: string
36
- /** 'HH:MM' */
37
- end: string
38
- }
39
-
40
- export interface BookingWindow {
41
- /** Earliest lead time before a slot can be booked. */
42
- minAdvanceHours: number
43
- /** How many days ahead the date picker offers. */
44
- maxAdvanceDays: number
45
- /** Slot granularity in minutes. */
46
- slotInterval: number
47
- }
48
-
49
- export interface PaymentConfig {
50
- /** Show a Pagamento step as the final stage of the flow. */
51
- enabled?: boolean
52
- /** % of the service price charged up-front as a reservation fee (default 100). */
53
- reservationFeePercent?: number
54
- /** Payment method (POC ships 'pix'). */
55
- method?: 'pix'
56
- }
57
-
58
- export interface ResolvedPayment {
59
- reservationFeePercent: number
60
- method: 'pix'
61
- }
62
-
63
- // ---------------------------------------------------------------------------
64
- // Phone verification
65
- // ---------------------------------------------------------------------------
66
-
67
- /**
68
- * How the customer's phone number is verified before the details sub-step.
69
- *
70
- * • 'otp' — show the code modal (POC: the code is the literal '0000'; no
71
- * message is actually sent). Use only where a real sender exists.
72
- * • 'none' — trust the typed number: the flow goes straight to the details
73
- * sub-step and the identity is emitted as-is.
74
- *
75
- * Default is 'none': until a real WhatsApp sender is wired, an OTP nobody can
76
- * receive is a dead end for real customers.
77
- */
78
- export type PhoneVerificationMode = 'otp' | 'none'
79
-
80
- // ---------------------------------------------------------------------------
81
- // Brand
82
- // ---------------------------------------------------------------------------
83
-
84
- /** One icon+text bullet on the overview sidebar. */
85
- export interface BookingHighlight {
86
- icon?: ComponentType<{ className?: string }>
87
- text: string
88
- }
89
-
90
- /** Brand/text-level personalization — no components needed for these. */
91
- export interface BookingBrand {
92
- /** e.g. "HempDent · Consulta Canábica". */
93
- name?: string
94
- /** Avatar letter; defaults to name.charAt(0). Ignored when logoUrl is set. */
95
- initials?: string
96
- logoUrl?: string
97
- /** Subheader line under the name. `null` hides the row. */
98
- tagline?: string | null
99
- /** Icon on service rows. Default: lucide Video. */
100
- serviceIcon?: ComponentType<{ className?: string }>
101
- /** Chip after the duration ("Online", "Presencial"…). `null` hides. */
102
- serviceMeta?: string | null
103
- /** Badge on the first service. `null` disables. Default 'Mais procurado'. */
104
- featuredBadge?: string | null
105
- /** Overview sidebar bullets (replaces the default generic ones). */
106
- highlights?: BookingHighlight[]
107
- }
108
-
109
- export interface ResolvedBookingBrand {
110
- name: string
111
- initials: string
112
- logoUrl?: string
113
- tagline: string | null
114
- serviceIcon: ComponentType<{ className?: string }>
115
- serviceMeta: string | null
116
- featuredBadge: string | null
117
- highlights: BookingHighlight[]
118
- }
119
-
120
- // ---------------------------------------------------------------------------
121
- // Formatters (shared Intl instances, see ./format)
122
- // ---------------------------------------------------------------------------
123
-
124
- export interface BookingFormatters {
125
- price: Intl.NumberFormat
126
- time: Intl.DateTimeFormat
127
- weekday: Intl.DateTimeFormat
128
- dayNum: Intl.DateTimeFormat
129
- longDay: Intl.DateTimeFormat
130
- dateShort: Intl.DateTimeFormat
131
- month: Intl.DateTimeFormat
132
- }
133
-
134
- // ---------------------------------------------------------------------------
135
- // Component override seam
136
- // ---------------------------------------------------------------------------
137
-
138
- export type StepState = 'done' | 'active' | 'todo'
139
-
140
- export interface BrandHeaderProps {
141
- brand: ResolvedBookingBrand
142
- }
143
-
144
- export interface ServiceCardProps {
145
- service: PublicService
146
- featured: boolean
147
- onSelect: () => void
148
- fmt: BookingFormatters
149
- brand: ResolvedBookingBrand
150
- }
151
-
152
- export interface SidebarExtrasProps {
153
- professionalName: string
154
- brand: ResolvedBookingBrand
155
- /** Renders the primary CTA — replacements can call it from their own button. */
156
- onStartBooking: () => void
157
- labels: PublicBookingLabels
158
- }
159
-
160
- export interface SuccessPanelProps {
161
- service: PublicService | null
162
- /** ISO datetime of the booked slot. */
163
- slotStart: string | null
164
- professionalName: string
165
- labels: PublicBookingLabels
166
- fmt: BookingFormatters
167
- }
168
-
169
- export interface StepRailItemProps {
170
- n: number
171
- label: string
172
- state: StepState
173
- children?: ReactNode
174
- }
175
-
176
- /**
177
- * Host-overridable subcomponents. Flow-critical parts (week strip, slot grid,
178
- * contact forms, payment panel) stay internal — these are the brand-visible
179
- * seams. Defaults are exported so hosts can wrap instead of rewriting.
180
- */
181
- export interface BookingComponents {
182
- BrandHeader: ComponentType<BrandHeaderProps>
183
- ServiceCard: ComponentType<ServiceCardProps>
184
- SidebarExtras: ComponentType<SidebarExtrasProps>
185
- SuccessPanel: ComponentType<SuccessPanelProps>
186
- StepRailItem: ComponentType<StepRailItemProps>
187
- }
188
-
189
- // ---------------------------------------------------------------------------
190
- // Labels — every user-visible string in the flow (all defaulted, pt-BR)
191
- // ---------------------------------------------------------------------------
192
-
193
- export interface PublicBookingLabels {
194
- title: string
195
- serviceStep: string
196
- dateStep: string
197
- contactStep: string
198
- confirmCta: string
199
- successTitle: string
200
- successBody: string
201
- // overview
202
- servicesHeading: string
203
- aboutHeading: string
204
- openingHoursHeading: string
205
- closedLabel: string
206
- bookNowCta: string
207
- // datetime
208
- timezoneNote: string
209
- slotsHeading: string
210
- noSlots: string
211
- continueCta: string
212
- backToServices: string
213
- back: string
214
- prevWeek: string
215
- nextWeek: string
216
- // contact
217
- contactIntro: string
218
- phoneLabel: string
219
- phoneHint: string
220
- sendCodeCta: string
221
- /** Phone hint shown when phoneVerification is 'none' (no code is sent). */
222
- phoneHintNoVerification: string
223
- /** Phone CTA shown when phoneVerification is 'none'. */
224
- phoneContinueCta: string
225
- codeTitle: string
226
- codeBody: string
227
- codeInvalid: string
228
- codeConfirmCta: string
229
- codeResendHint: string
230
- phoneVerified: string
231
- changePhone: string
232
- nameLabel: string
233
- namePlaceholder: string
234
- emailLabel: string
235
- emailPlaceholder: string
236
- emailHint: string
237
- notesLabel: string
238
- notesPlaceholder: string
239
- saveAndContinueCta: string
240
- submitError: string
241
- noChargeNote: string
242
- // right rail
243
- railTitle: string
244
- railWaitingPayment: string
245
- railService: string
246
- railProfessional: string
247
- railDatetime: string
248
- railContact: string
249
- railPayment: string
250
- }
package/src/registries.ts DELETED
@@ -1,35 +0,0 @@
1
- import type { PluginRegistryDef } from '@fayz-ai/core'
2
- import type { EntityDef } from '@fayz-ai/core'
3
-
4
- // ---------------------------------------------------------------------------
5
- // Holidays (public.holidays — tenant-scoped)
6
- // ---------------------------------------------------------------------------
7
-
8
- const holidayEntity: EntityDef = {
9
- name: 'Holiday',
10
- namePlural: 'Holidays',
11
- icon: 'TreePalm',
12
- displayField: 'name',
13
- defaultSort: 'date',
14
- defaultSortDir: 'asc',
15
- fields: [
16
- { key: 'name', label: 'Name', type: 'text', required: true, showInTable: true },
17
- { key: 'date', label: 'Date', type: 'date', required: true, showInTable: true, sortable: true },
18
- { key: 'recurring', label: 'Recurring Annually', type: 'boolean', showInTable: true, defaultValue: false },
19
- { key: 'description', label: 'Description', type: 'text', showInTable: false },
20
- { key: 'isActive', label: 'Active', type: 'boolean', showInTable: true, defaultValue: true },
21
- ],
22
- data: {
23
- table: 'holidays',
24
- tenantScoped: true,
25
- },
26
- }
27
-
28
- export const agendaRegistries: PluginRegistryDef[] = [
29
- {
30
- id: 'holidays',
31
- entity: holidayEntity,
32
- icon: 'TreePalm',
33
- description: 'Non-working days and recurring holidays',
34
- },
35
- ]