@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
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/AgendaContext.tsx","../src/calendar-styles.ts","../src/hooks/useAgendaSettings.ts","../src/components/MiniCalendar.tsx","../src/components/BookingPaymentPanel.tsx","../src/types.ts","../src/components/AppointmentModal.tsx","../src/components/FloatingPanel.tsx","../src/components/AppointmentPopover.tsx","../src/components/EventContextMenu.tsx","../src/components/AgendaMobileList.tsx","../src/views/CalendarView.tsx","../src/lib/tenant.ts","../src/AgendaPage.tsx","../src/data/supabase.ts","../src/store.ts","../src/registries.ts","../src/components/AgendaGeneralSettings.tsx","../src/locales/en.ts","../src/locales/pt-BR.ts","../src/locales/index.ts","../src/migrations/index.ts","../src/bridges/create-financial-bridge.ts","../src/integrations/google-calendar/mapping.ts","../src/integrations/google-calendar/data/tables.ts","../src/integrations/google-calendar/data/supabase.ts","../src/integrations/google-calendar/components/CalendarColorDot.tsx","../src/integrations/google-calendar/components/useAgendaLookups.ts","../src/integrations/google-calendar/components/ChannelMappingList.tsx","../src/integrations/google-calendar/components/ImportEventsWizard.tsx","../src/integrations/google-calendar/connectorDef.tsx","../src/integrations/google-calendar/connector.ts","../src/integrations/google-calendar/index.ts","../src/index.ts"],"names":["React","formatCurrency","t","jsxs","jsx","useState","useEffect","Fragment","createPortal","useTranslation","getCurrentLocale","provider","useMemo","getSupabaseClientOptional","X","Check","STYLE_ID","useRef","fmtCurrency","Clock","User","MapPin","FileText","HandCoins","DollarSign","AlertTriangle","Tooltip","Pencil","Trash2","usePluginPrefs","useCallback","booking","t2","PersonLink","Plus","ChevronLeft","ChevronRight","Button","bookingToEvent","getActiveTenantId","toast","Loader2","AlertCircle","RefreshCw","Checkbox","Badge","CalendarPlus","CheckCircle2","setScheduleBlockConfig","getScheduleBlockConfig"],"mappings":"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","file":"index.js","sourcesContent":["import type { PluginRegistryDef, PluginScope, VerticalId } from '@fayz-ai/core'\nimport type { EntityLookup } from '@fayz-ai/saas'\nimport type { AgendaDataProvider } from './data/types'\nimport type { StatusConfig, BookingTypeConfig } from './types'\nimport type { AgendaFinancialBridge } from './financial-bridge'\nimport type { EntityDef } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Public options interface\n// ---------------------------------------------------------------------------\n\nexport interface AgendaPluginLabels {\n pageTitle: string\n pageSubtitle: string\n calendar: string\n dayView: string\n weekView: string\n monthView: string\n listView: string\n workingHours: string\n confirmations: string\n newAppointment: string\n filters: string\n}\n\nexport interface ConfirmationChannelOption {\n id: string\n label: string\n icon: string\n}\n\nexport interface CancellationReasonOption {\n id: string\n label: string\n requiresNotes?: boolean\n}\n\nexport interface CancellationDetailsProvider {\n listReasons(): Promise<CancellationReasonOption[]>\n saveCancellationDetails(input: {\n bookingId: string\n reasonId: string\n notes?: string\n cancelledAt?: string\n }): Promise<void>\n}\n\nexport interface ExternalBookingSource {\n type: string\n id?: string\n [key: string]: unknown\n}\n\nexport interface LocationOption {\n id: string\n name: string\n isHQ?: boolean\n}\n\nexport interface AgendaPluginOptions {\n modules?: {\n workingHours?: boolean\n confirmations?: boolean\n conflictDetection?: boolean\n dragAndDrop?: boolean\n locationSelection?: boolean\n /** Enable financial integration (auto-enabled when financialBridge is provided) */\n financial?: boolean\n }\n labels?: Partial<AgendaPluginLabels>\n currency?: { code?: string; locale?: string; symbol?: string }\n\n /** Booking kind used in public.appointments.kind (default: 'appointment') */\n bookingKind?: string\n\n /** Order kind for financial records (default: 'service_order') */\n orderKind?: string\n\n /** Schedule kind in public.schedules.kind (default: 'working_hours') */\n scheduleKind?: string\n\n /** Booking type tabs shown in the appointment modal */\n bookingTypes?: BookingTypeConfig[]\n\n /**\n * Simplifies the agenda to Google-Calendar-style events (no client /\n * professional / service). When set to 'simple', the plugin exposes a single\n * \"Evento\" booking type whose modal shows only title / date-time / notes.\n * Ignored when an explicit `bookingTypes` override is provided.\n */\n eventMode?: 'simple'\n\n /** Booking status options */\n statuses?: StatusConfig[]\n\n /** Default calendar view (default: 'resourceTimeGridWeek'). Options: 'dayGridMonth', 'timeGridWeek', 'resourceTimeGridWeek', 'listWeek' */\n defaultCalendarView?: string\n\n /** Calendar visible time range (default: '07:00'-'21:00') */\n businessHours?: { startTime: string; endTime: string }\n\n /** Slot duration in minutes (default: 30) */\n slotDuration?: number\n\n /** Person kind for professionals (default: 'staff') */\n professionalKind?: string\n\n /** Person kind for clients (default: 'customer') */\n clientKind?: string\n\n /** Auto-create an order when creating a booking (default: true) */\n autoCreateOrder?: boolean\n\n /** Contact/client lookup */\n contactLookup?: EntityLookup\n\n /** Client entity definition for the Client tab in booking modal */\n clientEntityDef?: EntityDef\n\n /** Service lookup */\n serviceLookup?: EntityLookup\n\n /** Professional/staff lookup */\n professionalLookup?: EntityLookup\n\n /** Location lookup */\n locationLookup?: EntityLookup\n\n /** Called when user clicks a selected entity link (e.g. view client profile) */\n onEntityClick?: (type: 'client' | 'service' | 'professional', id: string) => void\n\n /** Business locations for unit filtering */\n locations?: LocationOption[]\n\n /** Confirmation channel options */\n confirmationChannels?: ConfirmationChannelOption[]\n\n /** Optional app/plugin bridge for cancel-time reason capture. */\n cancellationDetails?: CancellationDetailsProvider\n\n /** Called after a booking is created from an external operational source. */\n onBookingCreated?: (input: { bookingId: string; source?: ExternalBookingSource }) => void | Promise<void>\n\n /** App-owned registries shown under /settings/agenda Properties. */\n settingsRegistries?: PluginRegistryDef[]\n\n /** Financial bridge for agenda × financial cross-plugin integration */\n financialBridge?: AgendaFinancialBridge\n\n /** Data provider — defaults to Supabase, falls back to mock */\n dataProvider?: AgendaDataProvider\n\n /** Default values for schedule block advanced settings */\n scheduleBlockDefaults?: {\n bufferMinutes?: number\n maxConcurrent?: number\n minAdvanceHours?: number\n maxAdvanceDays?: number\n }\n\n navPosition?: number\n navSection?: 'main' | 'secondary'\n scope?: PluginScope\n verticalId?: VerticalId\n}\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_LABELS: AgendaPluginLabels = {\n pageTitle: 'Agenda',\n pageSubtitle: 'Calendar and appointment management',\n calendar: 'Calendar',\n dayView: 'Day',\n weekView: 'Week',\n monthView: 'Month',\n listView: 'Agenda',\n workingHours: 'Working Hours',\n confirmations: 'Confirmations',\n newAppointment: 'New Appointment',\n filters: 'Filters',\n}\n\nconst DEFAULT_CURRENCY = { code: 'BRL', locale: 'pt-BR', symbol: 'R$' }\n\nconst DEFAULT_STATUSES: StatusConfig[] = [\n { value: 'scheduled', label: 'Scheduled', color: '#6366f1' },\n { value: 'confirmed', label: 'Confirmed', color: '#3b82f6' },\n { value: 'in_progress', label: 'In Progress', color: '#f59e0b', availableWhen: 'today_only' },\n { value: 'completed', label: 'Completed', color: '#10b981', availableWhen: 'today_or_past' },\n { value: 'cancelled', label: 'Cancelled', color: '#ef4444' },\n { value: 'no_show', label: 'No Show', color: '#6b7280', availableWhen: 'today_or_past' },\n]\n\nconst DEFAULT_BOOKING_TYPES: BookingTypeConfig[] = [\n {\n id: 'appointment', label: 'Appointment', icon: 'Calendar', color: '#6366f1',\n fields: { client: true, professional: true, services: true, location: true, status: true },\n requiresServices: true, requiresClient: true,\n },\n {\n id: 'task', label: 'Task', icon: 'CheckSquare', color: '#f59e0b',\n fields: { client: false, professional: true, services: false, location: false, status: true },\n requiresServices: false, requiresClient: false,\n },\n {\n id: 'block', label: 'Block', icon: 'Ban', color: '#6b7280',\n fields: { client: false, professional: true, services: false, location: false, status: false },\n requiresServices: false, requiresClient: false,\n },\n]\n\n// Simple / Google-Calendar-style event — a single \"Evento\" type with just a\n// free-text title, date-time and notes. No client / professional / service.\n// Used by personal-finance-style agendas (see eventMode: 'simple').\nconst SIMPLE_EVENT_BOOKING_TYPES: BookingTypeConfig[] = [\n {\n id: 'event', label: 'Event', icon: 'Calendar', color: '#6366f1',\n fields: { title: true, client: false, professional: false, services: false, location: false, status: false },\n requiresServices: false, requiresClient: false,\n },\n]\n\n// ---------------------------------------------------------------------------\n// Resolved config — fully merged, no optionals\n// ---------------------------------------------------------------------------\n\nexport interface AgendaModules {\n workingHours: boolean\n confirmations: boolean\n conflictDetection: boolean\n dragAndDrop: boolean\n locationSelection: boolean\n financial: boolean\n}\n\n/**\n * Derived UI capabilities — computed ONCE in resolveConfig from the resolved\n * bookingTypes so no component ever re-derives \"is this a simple event agenda?\"\n * ad-hoc. A capability is enabled when ANY booking type uses that field. In\n * eventMode:'simple' the single \"Evento\" type disables\n * client/professional/services/location/status, so every consumer (popover,\n * filter rail, modal) hides the professional/service/status machinery in one\n * place instead of scattering `eventMode === 'simple'` checks.\n */\nexport interface AgendaCapabilities {\n title: boolean\n client: boolean\n professional: boolean\n services: boolean\n location: boolean\n status: boolean\n}\n\nexport interface AgendaCurrency {\n code: string\n locale: string\n symbol: string\n}\n\nexport interface ResolvedAgendaConfig {\n modules: AgendaModules\n /** Whether this is a simple Google-Calendar-style event agenda (eventMode:'simple'). */\n simpleMode: boolean\n /** Derived once from bookingTypes — see AgendaCapabilities. */\n capabilities: AgendaCapabilities\n labels: AgendaPluginLabels\n currency: AgendaCurrency\n bookingKind: string\n orderKind: string\n scheduleKind: string\n statuses: StatusConfig[]\n bookingTypes: BookingTypeConfig[]\n businessHours: { startTime: string; endTime: string }\n slotDuration: number\n professionalKind: string\n clientKind: string\n autoCreateOrder: boolean\n locations: LocationOption[]\n confirmationChannels: ConfirmationChannelOption[]\n cancellationDetails?: CancellationDetailsProvider\n onBookingCreated?: (input: { bookingId: string; source?: ExternalBookingSource }) => void | Promise<void>\n contactLookup?: EntityLookup\n clientEntityDef?: EntityDef\n serviceLookup?: EntityLookup\n professionalLookup?: EntityLookup\n locationLookup?: EntityLookup\n onEntityClick?: (type: 'client' | 'service' | 'professional', id: string) => void\n financialBridge?: AgendaFinancialBridge\n scheduleBlockDefaults: {\n bufferMinutes: number\n maxConcurrent: number\n minAdvanceHours: number\n maxAdvanceDays: number\n }\n defaultCalendarView: string\n}\n\n// ---------------------------------------------------------------------------\n// Config resolver\n// ---------------------------------------------------------------------------\n\nexport function resolveConfig(options?: AgendaPluginOptions): ResolvedAgendaConfig {\n // ── eventMode:'simple' derives ALL module + capability defaults ONCE, here. ──\n // Simple = Google-Calendar-style events (title/description + timestamp). It\n // flips professional/service machinery OFF by default: no working-hours /\n // schedule checks, no confirmations outreach, no conflict (double-booking)\n // detection, no location. Explicit `modules.*` re-enable individually. Full\n // mode (beauty) is unchanged — every default below matches the old behavior\n // when `simple` is false. Field-level machinery (client/professional/\n // services/location/status/title) is derived into `capabilities` from the\n // resolved bookingTypes, so components never test eventMode themselves.\n const simple = options?.eventMode === 'simple'\n const bookingTypes = options?.bookingTypes\n ?? (simple ? SIMPLE_EVENT_BOOKING_TYPES : DEFAULT_BOOKING_TYPES)\n const capabilities: AgendaCapabilities = {\n title: bookingTypes.some((bt) => bt.fields.title === true),\n client: bookingTypes.some((bt) => bt.fields.client),\n professional: bookingTypes.some((bt) => bt.fields.professional),\n services: bookingTypes.some((bt) => bt.fields.services),\n location: bookingTypes.some((bt) => bt.fields.location),\n status: bookingTypes.some((bt) => bt.fields.status),\n }\n return {\n modules: {\n // Off-unless-explicit in simple mode (`?? !simple`); default-on in full.\n workingHours: options?.modules?.workingHours ?? !simple,\n confirmations: options?.modules?.confirmations ?? !simple,\n conflictDetection: options?.modules?.conflictDetection ?? !simple,\n dragAndDrop: options?.modules?.dragAndDrop !== false,\n locationSelection: options?.modules?.locationSelection === true,\n financial: options?.modules?.financial ?? !!options?.financialBridge,\n },\n simpleMode: simple,\n capabilities,\n labels: { ...DEFAULT_LABELS, ...options?.labels },\n currency: { ...DEFAULT_CURRENCY, ...options?.currency },\n bookingKind: options?.bookingKind ?? 'appointment',\n orderKind: options?.orderKind ?? 'service_order',\n scheduleKind: options?.scheduleKind ?? 'working_hours',\n statuses: options?.statuses ?? DEFAULT_STATUSES,\n bookingTypes,\n businessHours: options?.businessHours ?? { startTime: '07:00', endTime: '21:00' },\n slotDuration: options?.slotDuration ?? 30,\n professionalKind: options?.professionalKind ?? 'staff',\n clientKind: options?.clientKind ?? 'customer',\n autoCreateOrder: options?.autoCreateOrder !== false,\n locations: options?.locations ?? [],\n confirmationChannels: options?.confirmationChannels ?? [],\n cancellationDetails: options?.cancellationDetails,\n onBookingCreated: options?.onBookingCreated,\n contactLookup: options?.contactLookup,\n clientEntityDef: options?.clientEntityDef,\n serviceLookup: options?.serviceLookup,\n professionalLookup: options?.professionalLookup,\n locationLookup: options?.locationLookup,\n onEntityClick: options?.onEntityClick,\n financialBridge: options?.financialBridge,\n scheduleBlockDefaults: {\n bufferMinutes: options?.scheduleBlockDefaults?.bufferMinutes ?? 0,\n maxConcurrent: options?.scheduleBlockDefaults?.maxConcurrent ?? 1,\n minAdvanceHours: options?.scheduleBlockDefaults?.minAdvanceHours ?? 0,\n maxAdvanceDays: options?.scheduleBlockDefaults?.maxAdvanceDays ?? 60,\n },\n defaultCalendarView: options?.defaultCalendarView ?? 'resourceTimeGridWeek',\n }\n}\n","import { createPluginContext } from '@fayz-ai/saas'\nimport type { ResolvedAgendaConfig } from './config'\nimport type { AgendaDataProvider } from './data/types'\nimport type { AgendaUIState } from './store'\n\nconst ctx = createPluginContext<ResolvedAgendaConfig, AgendaDataProvider, AgendaUIState>('AgendaPage')\n\nexport const AgendaContextProvider = ctx.ContextProvider\nexport const useAgendaConfig = ctx.useConfig\nexport const useAgendaProvider = ctx.useProvider\nexport const useAgendaStore = ctx.useStore\n","/**\n * Injects agenda calendar CSS at runtime.\n * This ensures styles work both in symlinked dev mode and when consumed\n * as a built package (where CSS side-effect imports are extracted by tsup\n * and not automatically loaded).\n */\n\nconst STYLE_ID = 'saas-agenda-calendar-styles'\n\nconst css = /* css */ `\n/* Dark mode content background — uses the content token */\n.dark .agenda-calendar,\n.dark .agenda-calendar .fc,\n.dark .agenda-calendar .fc-view-harness,\n.dark .agenda-calendar .fc-timegrid,\n.dark .agenda-calendar .fc-scrollgrid,\n.dark .agenda-calendar .fc-timegrid-col,\n.dark .agenda-calendar .fc-daygrid-body,\n.dark .agenda-calendar .fc-timegrid-slot-lane {\n background-color: hsl(var(--content));\n}\n\n/* FullCalendar — Google Calendar inspired theme */\n\n.agenda-calendar {\n --fc-border-color: hsl(var(--border));\n --fc-today-bg-color: transparent;\n --fc-now-indicator-color: hsl(var(--destructive));\n --fc-highlight-color: hsl(var(--primary) / 0.06);\n --fc-non-business-color: hsl(var(--muted) / 0.15);\n --fc-neutral-bg-color: transparent;\n --fc-page-bg-color: transparent;\n --fc-event-border-color: transparent;\n}\n\n.agenda-calendar .fc {\n font-family: inherit;\n background: transparent;\n}\n\n.agenda-calendar .fc .fc-view-harness {\n background: transparent;\n}\n\n/* ── Column headers ── */\n.agenda-calendar .fc-col-header-cell {\n background: transparent;\n border-bottom: 1px solid var(--fc-border-color);\n border-left: none;\n border-right: none;\n border-top: none;\n}\n\n.agenda-calendar .fc-col-header-cell-cushion {\n padding: 8px 4px;\n font-weight: 400;\n font-size: 0.7rem;\n color: hsl(var(--muted-foreground));\n text-decoration: none;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n/* Today's column header */\n.agenda-calendar .fc-day-today .fc-col-header-cell-cushion {\n color: hsl(var(--primary));\n font-weight: 600;\n}\n\n/* Resource header (professional columns) */\n.agenda-calendar .fc .fc-resource-header {\n background: transparent;\n border-bottom: 1px solid var(--fc-border-color);\n}\n\n/* ── Time slots — compact ── */\n.agenda-calendar .fc-timegrid-slot {\n height: 1.5rem;\n border-bottom: 1px solid hsl(var(--border) / 0.4);\n}\n\n.agenda-calendar .fc-timegrid-slot-label {\n vertical-align: top;\n border: none;\n}\n\n.agenda-calendar .fc-timegrid-slot-label-cushion {\n font-size: 0.65rem;\n color: hsl(var(--muted-foreground) / 0.7);\n padding: 1px 8px 0 0;\n}\n\n/* Half-hour lines lighter */\n.agenda-calendar .fc-timegrid-slot-minor {\n border-bottom-style: none;\n}\n\n/* Column dividers */\n.agenda-calendar .fc-timegrid-col {\n border-right: 1px solid hsl(var(--border) / 0.5);\n}\n\n/* ── Events ── */\n.agenda-calendar .fc-event {\n border-radius: 6px;\n border-width: 0;\n border-left: 4px solid;\n cursor: pointer;\n transition: opacity 0.15s, box-shadow 0.15s, backdrop-filter 0.15s;\n font-size: 0.7rem;\n line-height: 1.3;\n margin: 0 2px;\n overflow: hidden;\n backdrop-filter: blur(8px) saturate(140%);\n -webkit-backdrop-filter: blur(8px) saturate(140%);\n}\n\n.agenda-calendar .fc-event .fc-event-main {\n background: inherit;\n border-radius: inherit;\n overflow: hidden;\n}\n\n.agenda-calendar .fc-event:not(.fc-bg-event):hover {\n opacity: 0.92;\n box-shadow: 0 2px 8px rgba(0,0,0,0.12);\n backdrop-filter: blur(12px) saturate(160%);\n -webkit-backdrop-filter: blur(12px) saturate(160%);\n}\n\n.agenda-calendar .fc-bg-event {\n pointer-events: none;\n}\n\n/* ── Now indicator ── */\n.agenda-calendar .fc-timegrid-now-indicator-line {\n border-color: hsl(var(--destructive));\n border-width: 2px;\n}\n\n.agenda-calendar .fc-timegrid-now-indicator-arrow {\n border-top-color: hsl(var(--destructive));\n}\n\n/* ── Month view ── */\n.agenda-calendar .fc-daygrid-day-number {\n font-size: 0.8rem;\n padding: 4px 8px;\n text-decoration: none;\n color: hsl(var(--foreground));\n}\n\n.agenda-calendar .fc-daygrid-day.fc-day-today .fc-daygrid-day-number {\n background-color: hsl(var(--primary));\n color: hsl(var(--primary-foreground));\n border-radius: 50%;\n width: 1.5rem;\n height: 1.5rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.75rem;\n}\n\n/* ── Selection ── */\n.agenda-calendar .fc-highlight {\n background: hsl(var(--primary) / 0.08);\n}\n\n/* ── Links ── */\n.agenda-calendar .fc a {\n text-decoration: none;\n color: inherit;\n}\n\n/* ── Scrollbar ── */\n.agenda-calendar .fc-scroller {\n scrollbar-width: thin;\n scrollbar-color: hsl(var(--muted-foreground) / 0.12) transparent;\n}\n\n.agenda-calendar .fc-scroller::-webkit-scrollbar {\n width: 6px;\n}\n\n.agenda-calendar .fc-scroller::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.agenda-calendar .fc-scroller::-webkit-scrollbar-thumb {\n background: hsl(var(--muted-foreground) / 0.12);\n border-radius: 3px;\n}\n\n/* ── Clean up borders ── */\n.agenda-calendar .fc .fc-timegrid {\n border: none;\n}\n\n.agenda-calendar .fc-scrollgrid {\n border: none !important;\n}\n\n.agenda-calendar .fc-scrollgrid td:last-child {\n border-right: none;\n}\n\n/* ── Unavailable time background — opaque/disabled feel ── */\n.agenda-calendar .fc-unavailable-bg {\n background: hsl(var(--muted-foreground) / 0.08) !important;\n background-image: repeating-linear-gradient(\n 45deg,\n transparent,\n transparent 4px,\n hsl(var(--muted-foreground) / 0.04) 4px,\n hsl(var(--muted-foreground) / 0.04) 8px\n ) !important;\n border-radius: 0;\n border-left: none !important;\n}\n\n/* ── Location label on schedule blocks ── */\n.agenda-calendar .fc-location-label {\n background: transparent !important;\n border: none !important;\n border-left-width: 0 !important;\n cursor: default !important;\n pointer-events: none;\n box-shadow: none !important;\n z-index: 1 !important;\n margin: 0 4px !important;\n font-weight: 500 !important;\n}\n\n.agenda-calendar .fc-location-label .fc-event-main {\n padding: 0 !important;\n}\n\n/* Week view day header with date */\n.agenda-calendar .fc-timegrid .fc-col-header-cell {\n padding: 4px 0;\n}\n\n/* ── Alternating resource column backgrounds ── */\n.agenda-calendar .fc-resource-alt {\n background-color: hsl(var(--muted) / 0.4) !important;\n}\n\n.dark .agenda-calendar .fc-resource-alt {\n background-color: hsl(var(--muted-foreground) / 0.08) !important;\n}\n\n/* Resource group header separator — stronger border between professionals */\n.agenda-calendar .fc-resource-group {\n border-left: 2px solid hsl(var(--border));\n}\n\n/* Also stripe the resource header label for the alt group */\n.agenda-calendar th.fc-resource-alt {\n background-color: hsl(var(--muted) / 0.4) !important;\n}\n\n.dark .agenda-calendar th.fc-resource-alt {\n background-color: hsl(var(--muted-foreground) / 0.06) !important;\n}\n`\n\nlet injected = false\n\nexport function injectCalendarStyles(): void {\n if (injected) return\n if (typeof document === 'undefined') return\n\n // Check if already present (e.g. from CSS import in dev mode)\n if (document.getElementById(STYLE_ID)) {\n injected = true\n return\n }\n\n const style = document.createElement('style')\n style.id = STYLE_ID\n style.textContent = css\n document.head.appendChild(style)\n injected = true\n}\n","import { usePluginPrefs } from '@fayz-ai/saas'\n\nconst DEFAULTS = {\n startTime: '07:00',\n endTime: '21:00',\n}\n\nexport function useAgendaSettings() {\n const prefs = usePluginPrefs('agenda', DEFAULTS)\n\n return {\n startTime: prefs.get('startTime'),\n endTime: prefs.get('endTime'),\n setStartTime: (v: string) => prefs.set('startTime', v),\n setEndTime: (v: string) => prefs.set('endTime', v),\n }\n}\n","import React, { useMemo } from 'react'\nimport { ChevronLeft, ChevronRight } from 'lucide-react'\nimport { getCurrentLocale } from '@fayz-ai/core'\n\ninterface MiniCalendarProps {\n selectedDate: Date\n onDateSelect: (date: Date) => void\n onMonthChange?: (date: Date) => void\n}\n\nconst DAY_LABELS: Record<string, string[]> = {\n en: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],\n 'pt-BR': ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],\n}\n\nfunction isSameDay(a: Date, b: Date) {\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()\n}\n\nfunction isToday(d: Date) {\n return isSameDay(d, new Date())\n}\n\nfunction toDateLocale(locale: string): string {\n if (locale === 'pt-BR') return 'pt-BR'\n return 'en-US'\n}\n\nexport function MiniCalendar({ selectedDate, onDateSelect, onMonthChange }: MiniCalendarProps) {\n const locale = getCurrentLocale()\n const [viewMonth, setViewMonth] = React.useState(() => new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 1))\n\n const monthLabel = viewMonth.toLocaleDateString(toDateLocale(locale), { month: 'long', year: 'numeric' })\n const dayLabels = DAY_LABELS[locale] ?? DAY_LABELS.en\n\n const weeks = useMemo(() => {\n const year = viewMonth.getFullYear()\n const month = viewMonth.getMonth()\n const firstDay = new Date(year, month, 1)\n const startOffset = firstDay.getDay()\n const daysInMonth = new Date(year, month + 1, 0).getDate()\n\n const cells: (Date | null)[] = []\n for (let i = 0; i < startOffset; i++) cells.push(null)\n for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(year, month, d))\n while (cells.length % 7 !== 0) cells.push(null)\n\n const rows: (Date | null)[][] = []\n for (let i = 0; i < cells.length; i += 7) rows.push(cells.slice(i, i + 7))\n return rows\n }, [viewMonth])\n\n function prevMonth() {\n const d = new Date(viewMonth.getFullYear(), viewMonth.getMonth() - 1, 1)\n setViewMonth(d)\n onMonthChange?.(d)\n }\n\n function nextMonth() {\n const d = new Date(viewMonth.getFullYear(), viewMonth.getMonth() + 1, 1)\n setViewMonth(d)\n onMonthChange?.(d)\n }\n\n function handleClick(date: Date) {\n onDateSelect(date)\n }\n\n return (\n <div className=\"select-none\">\n {/* Month header */}\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm font-medium capitalize\">{monthLabel}</span>\n <div className=\"flex items-center gap-0.5\">\n <button onClick={prevMonth} className=\"flex h-6 w-6 items-center justify-center rounded-full hover:bg-muted transition-colors\">\n <ChevronLeft className=\"h-3.5 w-3.5\" />\n </button>\n <button onClick={nextMonth} className=\"flex h-6 w-6 items-center justify-center rounded-full hover:bg-muted transition-colors\">\n <ChevronRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n\n {/* Day labels */}\n <div className=\"grid grid-cols-7 mb-0.5\">\n {dayLabels.map((label, i) => (\n <div key={i} className=\"flex h-6 w-6 items-center justify-center text-[10px] font-medium text-muted-foreground mx-auto\">\n {label}\n </div>\n ))}\n </div>\n\n {/* Dates */}\n {weeks.map((week, wi) => (\n <div key={wi} className=\"grid grid-cols-7\">\n {week.map((date, di) => {\n if (!date) return <div key={di} className=\"h-6 w-6 mx-auto\" />\n const selected = isSameDay(date, selectedDate)\n const today = isToday(date)\n return (\n <button\n key={di}\n onClick={() => handleClick(date)}\n className={`flex h-6 w-6 items-center justify-center rounded-full text-[11px] mx-auto transition-colors ${\n selected\n ? 'bg-primary text-primary-foreground'\n : today\n ? 'bg-primary/10 text-primary font-semibold'\n : 'hover:bg-muted text-foreground'\n }`}\n >\n {date.getDate()}\n </button>\n )\n })}\n </div>\n ))}\n </div>\n )\n}\n","import React, { useState, useEffect } from 'react'\nimport { createPortal } from 'react-dom'\nimport { X, Check, Banknote, QrCode, CreditCard, ArrowRightLeft, FileCheck, ExternalLink } from 'lucide-react'\nimport { useAgendaConfig } from '../AgendaContext'\nimport { useTranslation } from '@fayz-ai/core'\nimport type { BookingPaymentDetail } from '../financial-bridge'\n\n// ---------------------------------------------------------------------------\n// Payment method type visuals (mirrors financial PaymentModal)\n// ---------------------------------------------------------------------------\n\nconst TYPE_ICONS: Record<string, React.ElementType> = {\n cash: Banknote, pix: QrCode, credit_card: CreditCard, debit_card: CreditCard,\n bank_transfer: ArrowRightLeft, check: FileCheck,\n}\n\nconst TYPE_COLORS: Record<string, string> = {\n cash: 'border-success/30 bg-success/5 hover:bg-success/10 data-[active=true]:border-success data-[active=true]:bg-success/15',\n pix: 'border-teal-500/30 bg-teal-500/5 hover:bg-teal-500/10 data-[active=true]:border-teal-500 data-[active=true]:bg-teal-500/15',\n credit_card: 'border-info/30 bg-info/5 hover:bg-info/10 data-[active=true]:border-info data-[active=true]:bg-info/15',\n debit_card: 'border-magic/30 bg-magic/5 hover:bg-magic/10 data-[active=true]:border-magic data-[active=true]:bg-magic/15',\n bank_transfer: 'border-warning/30 bg-warning/5 hover:bg-warning/10 data-[active=true]:border-warning data-[active=true]:bg-warning/15',\n check: 'border-input/30 bg-muted/5 hover:bg-muted/10 data-[active=true]:border-input data-[active=true]:bg-muted/15',\n}\n\nconst ICON_COLORS: Record<string, string> = {\n cash: 'text-success', pix: 'text-teal-500', credit_card: 'text-info',\n debit_card: 'text-magic', bank_transfer: 'text-warning', check: 'text-muted-foreground',\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\ninterface Props {\n orderId: string\n orderTotal: number\n services?: Array<{ name: string; price: number; durationMinutes: number }>\n onClose: () => void\n onPaymentChange?: () => void\n formatCurrency: (amount: number) => string\n /** Render inline (no portal overlay) — for embedding in tabs */\n inline?: boolean\n}\n\nexport function BookingPaymentPanel({ orderId, orderTotal, services, onClose, onPaymentChange, formatCurrency, inline }: Props) {\n const t = useTranslation()\n const config = useAgendaConfig()\n const bridge = config.financialBridge!\n\n const [visible, setVisible] = useState(false)\n const [loading, setLoading] = useState(true)\n const [detail, setDetail] = useState<BookingPaymentDetail | null>(null)\n\n // Payment form\n const [selectedTypeId, setSelectedTypeId] = useState('')\n const [paymentTypes, setPaymentTypes] = useState<Array<{ id: string; name: string; transactionType?: string }>>([])\n const [bankAccounts, setBankAccounts] = useState<Array<{ id: string; name: string; accountType: string }>>([])\n const [filteredMethods, setFilteredMethods] = useState<Array<{ id: string; name: string }>>([])\n const [selectedBankId, setSelectedBankId] = useState('')\n const [paymentMethodId, setPaymentMethodId] = useState('')\n const [cardBrand, setCardBrand] = useState('')\n const [cardInstallments, setCardInstallments] = useState(1)\n const [processing, setProcessing] = useState(false)\n const [justPaid, setJustPaid] = useState(false)\n\n useEffect(() => { requestAnimationFrame(() => setVisible(true)) }, [])\n\n // Single combined fetch for all initial data\n useEffect(() => {\n let cancelled = false\n setLoading(true)\n Promise.all([\n bridge.getPaymentDetail(orderId).catch(() => null),\n bridge.getPaymentMethodTypes().catch(() => [] as typeof paymentTypes),\n bridge.getBankAccounts().catch(() => [] as typeof bankAccounts),\n ]).then(([d, types, accounts]) => {\n if (cancelled) return\n setDetail(d)\n setPaymentTypes(types)\n setBankAccounts(accounts)\n setLoading(false)\n })\n return () => { cancelled = true }\n }, [orderId])\n\n function handleClose() {\n setVisible(false)\n setTimeout(onClose, 200)\n }\n\n const selectedType = paymentTypes.find((t) => t.id === selectedTypeId)\n const txType = selectedType?.transactionType ?? ''\n const needsBank = ['bank_transfer', 'pix', 'check'].includes(txType)\n const needsCard = txType === 'credit_card' || txType === 'debit_card'\n const needsCardInstallments = txType === 'credit_card'\n\n function handleSelectType(typeId: string) {\n setSelectedTypeId(typeId)\n setSelectedBankId('')\n setPaymentMethodId('')\n setCardBrand('')\n setCardInstallments(1)\n // Fetch specific payment methods for this type\n if (bridge.getPaymentMethods) {\n bridge.getPaymentMethods(typeId).then(setFilteredMethods).catch(() => setFilteredMethods([]))\n }\n }\n\n async function handleCheckout() {\n if (!selectedTypeId) return\n setProcessing(true)\n try {\n const result = await bridge.checkout(orderId, {\n paymentMethodTypeId: selectedTypeId,\n paymentMethodId: paymentMethodId || undefined,\n bankAccountId: needsBank ? selectedBankId || undefined : undefined,\n cardBrand: needsCard ? cardBrand || undefined : undefined,\n cardInstallments: needsCardInstallments ? cardInstallments : undefined,\n })\n setDetail(result)\n setJustPaid(true)\n onPaymentChange?.()\n // Show confirmation animation, then transition to summary\n setTimeout(() => setJustPaid(false), 2200)\n } catch { /* toast */ }\n setProcessing(false)\n }\n\n const isPaid = detail?.status === 'paid'\n\n const content = (\n <div className=\"px-5 py-4 space-y-4\">\n\n {/* Loading */}\n {loading && (\n <div className=\"space-y-3 py-2\">\n {[...Array(3)].map((_, i) => (\n <div key={i} className=\"h-8 rounded-lg bg-muted animate-pulse\" />\n ))}\n </div>\n )}\n\n {/* Just paid — confirmation animation */}\n {!loading && isPaid && justPaid && (\n <div className=\"text-center py-8 space-y-2 animate-in fade-in zoom-in-95 duration-300\">\n <div className=\"flex h-14 w-14 mx-auto items-center justify-center rounded-full bg-success/10 animate-bounce\" style={{ animationDuration: '600ms', animationIterationCount: '2' }}>\n <Check className=\"h-7 w-7 text-success\" />\n </div>\n <p className=\"text-sm font-semibold text-success\">{t('agenda.payment.checkoutComplete')}</p>\n <p className=\"text-xs text-muted-foreground\">{formatCurrency(detail!.totalAmount)}</p>\n </div>\n )}\n\n {/* Invoice summary — shown after animation or when returning to an already-paid/pending booking */}\n {!loading && detail && detail.status !== 'none' && !justPaid && (\n <div className=\"space-y-3 animate-in fade-in duration-300\">\n {/* Movement rows with inline status badge */}\n {detail.movements.length > 0 ? (\n <div className=\"space-y-1.5\">\n {detail.movements.map((mov) => {\n const methodName = mov.paymentMethodTypeName\n const txKey = (methodName ?? '').toLowerCase().replace(/\\s+/g, '_')\n const Icon = TYPE_ICONS[txKey] ?? Banknote\n const iconColor = ICON_COLORS[txKey] ?? 'text-muted-foreground'\n const isMovPaid = mov.status === 'paid'\n const isPartial = mov.status === 'partial'\n const isOverdue = mov.status === 'overdue'\n\n return (\n <div key={mov.id} className=\"flex items-center gap-3 rounded-lg border px-3 py-2.5\">\n <Icon className={`h-4 w-4 shrink-0 ${isMovPaid ? iconColor : 'text-muted-foreground'}`} />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">\n {methodName ?? '—'}\n {mov.cardBrand ? ` · ${mov.cardBrand}` : ''}\n {mov.cardInstallments && mov.cardInstallments > 1 ? ` ${mov.cardInstallments}x` : ''}\n </p>\n <p className=\"text-[10px] text-muted-foreground\">\n {mov.paymentDate ?? mov.dueDate}\n {detail.movements.length > 1 && mov.installmentNumber ? ` · ${t('agenda.payment.installment')} ${mov.installmentNumber}` : ''}\n </p>\n </div>\n <div className=\"flex items-center gap-2 shrink-0\">\n {isMovPaid && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-success/10 px-2 py-0.5 text-[10px] font-medium text-success\">\n <Check className=\"h-2.5 w-2.5\" /> {t('agenda.payment.paid')}\n </span>\n )}\n {isPartial && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-warning/10 px-2 py-0.5 text-[10px] font-medium text-warning\">\n ! {formatCurrency(mov.paidAmount)}/{formatCurrency(mov.amount)}\n </span>\n )}\n {isOverdue && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-destructive/10 px-2 py-0.5 text-[10px] font-medium text-destructive\">\n ! {t('agenda.payment.overdue')}\n </span>\n )}\n {mov.status === 'pending' && (\n <span className=\"inline-flex items-center rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground\">\n {t('agenda.payment.pending')}\n </span>\n )}\n <span className=\"text-sm font-semibold\">{formatCurrency(mov.paidAmount || mov.amount)}</span>\n </div>\n </div>\n )\n })}\n </div>\n ) : (\n <div className=\"flex items-center justify-between text-sm px-1\">\n <span className=\"text-muted-foreground\">{t('agenda.payment.total')}</span>\n <span className=\"font-semibold\">{formatCurrency(detail.totalAmount)}</span>\n </div>\n )}\n\n {/* Invoice ref + link */}\n <div className=\"flex items-center justify-between\">\n {detail.referenceNumber && (\n <span className=\"text-[10px] font-mono text-muted-foreground\">#{detail.referenceNumber}</span>\n )}\n <a\n href={`#/financial/receivables/detail/${detail.invoiceId}`}\n className=\"inline-flex items-center gap-1.5 text-xs font-medium text-primary hover:underline ml-auto\"\n >\n {t('agenda.payment.viewInvoice')}\n <ExternalLink className=\"h-3 w-3\" />\n </a>\n </div>\n </div>\n )}\n\n {/* Checkout view — only when no invoice exists yet */}\n {!loading && (!detail || detail.movements.length === 0) && (\n <>\n {/* Service summary */}\n {services && services.length > 0 && (\n <div>\n <p className=\"text-[11px] font-medium text-muted-foreground mb-2\">{t('agenda.payment.serviceSummary')}</p>\n <div className=\"space-y-0.5\">\n {services.map((svc, i) => (\n <div key={i} className=\"flex items-center justify-between text-sm py-1\">\n <span className=\"truncate\">{svc.name}</span>\n <span className=\"shrink-0 text-muted-foreground\">{formatCurrency(svc.price)}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Total */}\n <div className=\"flex items-center justify-between text-sm font-semibold pt-2 border-t\">\n <span>{t('agenda.payment.total')}</span>\n <span>{formatCurrency(orderTotal)}</span>\n </div>\n\n {/* Payment method grid */}\n <div>\n <p className=\"text-[11px] font-medium text-muted-foreground mb-2\">{t('agenda.payment.paymentMethod')}</p>\n {paymentTypes.length === 0 ? (\n <div className=\"rounded-lg border border-dashed border-input bg-muted/30 px-3 py-3 text-center\">\n <p className=\"text-xs text-muted-foreground\">{t('agenda.payment.noMethods')}</p>\n <a href=\"#/financial/settings\" className=\"mt-1.5 inline-block text-xs font-medium text-primary hover:underline\">\n {t('agenda.payment.configureMethods')} →\n </a>\n </div>\n ) : (\n <div className=\"grid grid-cols-3 gap-1.5\">\n {paymentTypes.map((pt) => {\n const ptTx = pt.transactionType ?? pt.name.toLowerCase().replace(/\\s+/g, '_')\n const Icon = TYPE_ICONS[ptTx] ?? Banknote\n const colorClass = TYPE_COLORS[ptTx] ?? TYPE_COLORS.cash\n const iconColor = ICON_COLORS[ptTx] ?? ICON_COLORS.cash\n const isActive = selectedTypeId === pt.id\n return (\n <button\n key={pt.id}\n type=\"button\"\n data-active={isActive}\n onClick={() => handleSelectType(pt.id)}\n className={`flex flex-col items-center gap-1 rounded-lg border p-2.5 text-[10px] font-medium transition-all ${colorClass}`}\n >\n <Icon className={`h-4 w-4 ${iconColor}`} />\n <span className=\"truncate w-full text-center\">{pt.name}</span>\n </button>\n )\n })}\n </div>\n )}\n </div>\n\n {/* Extra fields based on payment type */}\n {selectedTypeId && (\n <div className=\"space-y-3\">\n {/* Specific payment method (filtered by type) */}\n {filteredMethods.length > 0 && (\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">\n {needsCard ? t('agenda.payment.card') : t('agenda.payment.method')}\n </label>\n <select value={paymentMethodId} onChange={(e) => setPaymentMethodId(e.target.value)}\n className=\"w-full mt-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring\">\n <option value=\"\">{t('agenda.payment.select')}</option>\n {filteredMethods.map((m) => <option key={m.id} value={m.id}>{m.name}</option>)}\n </select>\n </div>\n )}\n\n {/* Card brand + installments */}\n {needsCard && (\n <div className={`grid gap-2.5 ${needsCardInstallments ? 'grid-cols-2' : 'grid-cols-1'}`}>\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('agenda.payment.cardBrand')}</label>\n <select value={cardBrand} onChange={(e) => setCardBrand(e.target.value)}\n className=\"w-full mt-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring\">\n <option value=\"\">{t('agenda.payment.selectBrand')}</option>\n {['Visa', 'Mastercard', 'American Express', 'Elo', 'Hipercard', 'Diners Club'].map((b) => (\n <option key={b} value={b}>{b}</option>\n ))}\n </select>\n </div>\n {needsCardInstallments && (\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('agenda.payment.cardInstallments')}</label>\n <select value={cardInstallments} onChange={(e) => setCardInstallments(Number(e.target.value))}\n className=\"w-full mt-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring\">\n {Array.from({ length: 12 }, (_, i) => i + 1).map((n) => (\n <option key={n} value={n}>{n}x {n > 1 ? formatCurrency(orderTotal / n) : ''}</option>\n ))}\n </select>\n </div>\n )}\n </div>\n )}\n\n {/* Bank account */}\n {needsBank && bankAccounts.length > 0 && (\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('agenda.payment.bankAccount')}</label>\n <select value={selectedBankId} onChange={(e) => setSelectedBankId(e.target.value)}\n className=\"w-full mt-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring\">\n <option value=\"\">{t('agenda.payment.selectAccount')}</option>\n {bankAccounts.map((a) => (\n <option key={a.id} value={a.id}>{a.name}</option>\n ))}\n </select>\n </div>\n )}\n </div>\n )}\n\n {/* Confirm button */}\n <button\n type=\"button\"\n onClick={handleCheckout}\n disabled={processing || !selectedTypeId}\n className=\"w-full rounded-lg bg-primary border border-primary py-2.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 shadow-button-primary active:shadow-button-inset disabled:opacity-40 transition-colors\"\n >\n {processing\n ? t('agenda.payment.checkingOut')\n : `${t('agenda.payment.checkout')} ${formatCurrency(orderTotal)}`\n }\n </button>\n </>\n )}\n </div>\n )\n\n if (inline) return content\n\n return createPortal(\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center transition-colors duration-200\"\n style={{ backgroundColor: visible ? 'rgba(0,0,0,0.5)' : 'rgba(0,0,0,0)' }}\n onClick={handleClose}\n >\n <div\n className=\"w-full max-w-md rounded-xl border bg-card shadow-2xl mx-4 transition-all duration-200 max-h-[90vh] overflow-y-auto\"\n style={{ opacity: visible ? 1 : 0, transform: visible ? 'scale(1) translateY(0)' : 'scale(0.95) translateY(8px)' }}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between px-5 py-4 border-b sticky top-0 bg-card z-10\">\n <h3 className=\"text-base font-semibold\">{t('agenda.payment.title')}</h3>\n <button onClick={handleClose} className=\"p-1 text-muted-foreground hover:text-foreground transition-colors\">\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n {content}\n </div>\n </div>,\n document.body,\n )\n}\n","// ---------------------------------------------------------------------------\n// Agenda Plugin — Pure TypeScript types\n// Zero dependencies. Maps to public archetype tables.\n// ---------------------------------------------------------------------------\n\n// ============================================================\n// ENUMS / LITERALS\n// ============================================================\n\n/** Booking status lifecycle */\nexport type BookingStatus =\n | 'scheduled'\n | 'confirmed'\n | 'in_progress'\n | 'completed'\n | 'cancelled'\n | 'no_show'\n\n/** Confirmation outreach status */\nexport type ConfirmationStatus = 'pending' | 'sent' | 'confirmed' | 'declined'\n\n/** Booking type identifier — extensible via string literal union */\nexport type BookingTypeId = 'appointment' | 'task' | 'out_of_office' | 'block' | (string & {})\n\n/** Configuration for a booking type (event type) */\nexport interface BookingTypeConfig {\n id: BookingTypeId\n label: string\n icon: string\n color: string\n fields: {\n /** Free-text event title (maps to the booking's display name). Used by\n * simple / Google-Calendar-style events that have no client party. */\n title?: boolean\n client: boolean\n professional: boolean\n services: boolean\n location: boolean\n status: boolean\n }\n requiresServices: boolean\n requiresClient: boolean\n}\n\n// ============================================================\n// CORE ENTITIES\n// ============================================================\n\n/** A booking service line item (from public.appointment_items) */\nexport interface BookingService {\n id: string\n serviceId: string | null\n name: string\n durationMinutes: number\n price: number\n assigneeId: string | null\n}\n\n/** Calendar booking — the main entity rendered on the calendar (from v_appointments view on orders) */\nexport interface CalendarBooking {\n id: string\n tenantId: string\n kind: string\n /** Lifecycle stage: booked, invoiced, paid, etc. */\n stage?: string\n /** Financial direction: credit, debit, null */\n direction?: string | null\n startsAt: string\n endsAt: string | null\n status: BookingStatus\n notes: string | null\n /** In unified model, orderId === id (the booking IS the order) */\n orderId: string | null\n locationId: string | null\n metadata: Record<string, unknown>\n\n // Client (party)\n clientId: string | null\n clientName: string | null\n clientPhone: string | null\n clientEmail: string | null\n clientAvatarUrl: string | null\n\n // Professional (assignee)\n professionalId: string | null\n professionalName: string | null\n professionalAvatarUrl: string | null\n\n // Location\n locationName: string | null\n\n // Order totals\n orderTotal: number | null\n orderStatus: string | null\n /** Payment status from financial bridge (enriched at runtime) */\n paymentStatus?: import('./financial-bridge').BookingPaymentStatus\n\n // Aggregated services\n services: BookingService[] | null\n totalDurationMinutes: number | null\n\n createdAt: string\n updatedAt: string\n}\n\n/** Professional / staff resource for the calendar */\nexport interface Professional {\n id: string\n name: string\n avatarUrl: string | null\n locationId: string | null\n locationName: string | null\n isActive: boolean\n}\n\n/** Working hours schedule (from public.schedules) */\nexport interface Schedule {\n id: string\n tenantId: string\n kind: string\n assigneeId: string | null\n locationId: string | null\n dayOfWeek: number | null\n specificDate: string | null\n startsAt: string\n endsAt: string\n isActive: boolean\n metadata: Record<string, unknown>\n}\n\n/** Available time slot */\nexport interface TimeSlot {\n start: string\n end: string\n}\n\n/** Confirmation record stored in booking metadata */\nexport interface ConfirmationRecord {\n channel: string\n sentAt: string\n status: ConfirmationStatus\n confirmedAt?: string\n}\n\n// ============================================================\n// STATUS CONFIGURATION\n// ============================================================\n\n/**\n * When a status is available for selection relative to the booking date.\n * - 'always' — any date (e.g. scheduled, confirmed, cancelled)\n * - 'today_or_past' — booking is today or earlier (e.g. completed, no_show)\n * - 'today_only' — booking is today (e.g. in_progress)\n */\nexport type StatusAvailability = 'always' | 'today_or_past' | 'today_only'\n\nexport interface StatusConfig {\n value: string\n label: string\n color: string\n /** When this status can be selected (default: 'always') */\n availableWhen?: StatusAvailability\n}\n\n/** Check if a status is available for a given booking date */\nexport function isStatusAvailable(status: StatusConfig, bookingStartsAt: string): boolean {\n const when = status.availableWhen ?? 'always'\n if (when === 'always') return true\n const bookingDate = bookingStartsAt.slice(0, 10)\n const today = new Date().toISOString().slice(0, 10)\n if (when === 'today_or_past') return bookingDate <= today\n if (when === 'today_only') return bookingDate === today\n return true\n}\n\n// ============================================================\n// MODAL TAB EXTENSION\n// ============================================================\n\n/** Props passed to every booking modal tab component */\nexport interface BookingModalTabProps {\n bookingId?: string\n clientId: string\n orderId: string | null\n services: Array<{ name: string; price: number; durationMinutes: number }>\n formatCurrency: (amount: number) => string\n onDataChange?: () => void\n}\n\n/** A tab registered in the booking edit modal */\nexport interface BookingModalTab {\n id: string\n label: string\n icon: string\n order: number\n component: React.ComponentType<BookingModalTabProps>\n visible?: (ctx: { mode: 'create' | 'edit'; clientId?: string; orderId?: string }) => boolean\n}\n\n// ============================================================\n// INPUT TYPES (create / mutate)\n// ============================================================\n\nexport interface CreateBookingInput {\n kind?: BookingTypeId\n clientId: string\n professionalId: string\n locationId?: string\n startsAt: string\n notes?: string\n /** Free-text event title for simple events (no client party). Maps to the\n * booking's display name (clientName in the read model). */\n title?: string\n services: CreateBookingServiceInput[]\n}\n\nexport interface CreateBookingServiceInput {\n serviceId: string\n name: string\n durationMinutes: number\n price: number\n assigneeId?: string\n}\n\nexport interface UpdateBookingInput {\n clientId?: string\n professionalId?: string\n locationId?: string\n startsAt?: string\n endsAt?: string\n status?: BookingStatus\n notes?: string\n /** Free-text event title for simple events (no client party). */\n title?: string\n services?: CreateBookingServiceInput[]\n}\n\nexport interface SaveScheduleInput {\n assigneeId: string\n locationId?: string\n dayOfWeek?: number\n specificDate?: string\n startsAt: string\n endsAt: string\n isActive?: boolean\n metadata?: Record<string, unknown>\n}\n\n// ============================================================\n// QUERY / FILTER TYPES\n// ============================================================\n\nexport interface BookingQuery {\n dateRange: { start: string; end: string }\n professionalIds?: string[]\n locationId?: string\n statuses?: string[]\n kind?: string\n}\n\nexport interface ConflictCheckParams {\n assigneeId: string\n startsAt: string\n endsAt: string\n excludeBookingId?: string\n}\n\nexport interface AvailableSlotsParams {\n assigneeId: string\n date: string\n durationMinutes: number\n slotInterval?: number\n}\n","import React, { useState, useEffect, useMemo, useRef } from 'react'\nimport { createPortal } from 'react-dom'\nimport { Clock, AlertTriangle, X, User, Briefcase, FileText, CircleDot, Plus, MapPin, Calendar, DollarSign, CheckSquare, Ban, Check, HandCoins } from 'lucide-react'\n\nconst BOOKING_TYPE_ICONS: Record<string, React.ElementType> = {\n Calendar, CheckSquare, Ban,\n}\nimport {\n Modal, ModalContent, ModalTitle,\n} from '@fayz-ai/ui'\nimport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@fayz-ai/ui'\nimport { cn } from '@fayz-ai/ui'\nimport { SearchCombobox, type ComboboxOption } from '@fayz-ai/ui'\nimport { ContactPicker, type ContactPickerValue } from '@fayz-ai/saas'\nimport { BookingPaymentPanel } from './BookingPaymentPanel'\nimport { CrudDetailPage } from '@fayz-ai/saas'\nimport { CrudFormPage } from '@fayz-ai/saas'\nimport { useLimitGuard, invalidateLimit } from '@fayz-ai/saas'\nimport { Button } from '@fayz-ai/ui'\nimport { useAgendaConfig, useAgendaProvider, useAgendaStore } from '../AgendaContext'\nimport { useTranslation } from '@fayz-ai/core'\nimport { getCurrentLocale } from '@fayz-ai/core'\nimport { isStatusAvailable } from '../types'\nimport type { CreateBookingInput, BookingTypeId } from '../types'\nimport type { ExternalBookingSource } from '../config'\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction fmtCurrency(amount: number, locale: string, code: string): string {\n return new Intl.NumberFormat(locale, { style: 'currency', currency: code }).format(amount)\n}\n\nfunction formatCompactDate(dateStr: string, locale: string): string {\n const d = new Date(dateStr + 'T00:00:00')\n return d.toLocaleDateString(locale === 'pt-BR' ? 'pt-BR' : 'en-US', {\n weekday: 'short', month: 'short', day: 'numeric',\n })\n}\n\ninterface ServiceItem { serviceId: string; name: string; durationMinutes: number; price: number }\ninterface CancellationReasonItem { id: string; label: string; requiresNotes?: boolean }\n\n// ---------------------------------------------------------------------------\n// Inline editable number — allows clearing, commits on blur/enter\n// ---------------------------------------------------------------------------\n\nfunction InlineNumber({ value, onChange, min = 0, step = 1, className, disabled, tooltip }: {\n value: number; onChange: (v: number) => void; min?: number; step?: number\n className?: string; disabled?: boolean; tooltip?: string\n}) {\n const [draft, setDraft] = useState(String(value))\n const [focused, setFocused] = useState(false)\n\n useEffect(() => { if (!focused) setDraft(String(value)) }, [value, focused])\n\n function commit() {\n setFocused(false)\n const v = parseFloat(draft)\n if (!isNaN(v) && v >= min) {\n onChange(v)\n } else {\n setDraft(String(value))\n }\n }\n\n const input = (\n <input\n type=\"text\"\n inputMode=\"decimal\"\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onFocus={(e) => { setFocused(true); e.target.select() }}\n onBlur={commit}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); commit() } }}\n disabled={disabled}\n className={cn(\n 'text-right text-[11px] text-muted-foreground bg-transparent border-b border-transparent hover:border-muted-foreground/40 focus:border-foreground focus:outline-none tabular-nums',\n className,\n )}\n />\n )\n\n if (!tooltip) return input\n\n return (\n <TooltipProvider delayDuration={400}>\n <Tooltip>\n <TooltipTrigger asChild>{input}</TooltipTrigger>\n <TooltipContent side=\"top\" className=\"text-xs\">{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Custom Status Select\n// ---------------------------------------------------------------------------\n\nfunction StatusSelect({ value, onChange, statuses, bookingDate }: {\n value: string; onChange: (v: string) => void\n statuses: Array<{ value: string; label: string; color: string; availableWhen?: string }>\n bookingDate?: string\n}) {\n const [open, setOpen] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\n const dropdownRef = useRef<HTMLDivElement>(null)\n const current = statuses.find((s) => s.value === value)\n\n useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => {\n const target = e.target as Node\n if (ref.current?.contains(target)) return\n if (dropdownRef.current?.contains(target)) return\n setOpen(false)\n }\n document.addEventListener('mousedown', handler)\n return () => document.removeEventListener('mousedown', handler)\n }, [open])\n\n const btnRef = useRef<HTMLButtonElement>(null)\n const [dropRect, setDropRect] = useState<DOMRect | null>(null)\n\n function handleOpen() {\n if (btnRef.current) setDropRect(btnRef.current.getBoundingClientRect())\n setOpen((p) => !p)\n }\n\n return (\n <div ref={ref} className=\"relative flex-1\">\n <button ref={btnRef} type=\"button\" onClick={handleOpen}\n className=\"flex items-center gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-muted/30 transition-colors text-left w-full\">\n {current && <>\n <span className=\"h-2 w-2 rounded-full shrink-0\" style={{ backgroundColor: current.color }} />\n <span>{current.label}</span>\n </>}\n <svg className=\"ml-auto h-3 w-3 text-muted-foreground shrink-0\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n </svg>\n </button>\n {open && dropRect && createPortal(\n <div ref={dropdownRef} data-modal-passthrough style={{ position: 'fixed', left: dropRect.left, top: dropRect.bottom + 4, width: dropRect.width, zIndex: 9999, pointerEvents: 'auto' }}\n className=\"fayz-glass-surface rounded-lg border bg-popover shadow-lg py-1 animate-in fade-in zoom-in-95 duration-100\">\n {statuses.map((s: any) => {\n const available = !bookingDate || isStatusAvailable(s as any, bookingDate)\n return (\n <button key={s.value} type=\"button\" disabled={!available}\n onClick={() => { if (available) { onChange(s.value); setOpen(false) } }}\n className={`flex w-full items-center gap-2.5 px-3 py-1.5 text-sm transition-colors ${\n !available ? 'opacity-30 cursor-not-allowed' : s.value === value ? 'bg-muted/30' : 'hover:bg-muted/50'\n }`}>\n <span className=\"h-2 w-2 rounded-full shrink-0\" style={{ backgroundColor: s.color }} />\n <span>{s.label}</span>\n </button>\n )\n })}\n </div>,\n document.body,\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Professional Select — compact inline dropdown with initials\n// ---------------------------------------------------------------------------\n\nfunction ProfessionalSelect({ value, onChange, professionals }: {\n value: string; onChange: (v: string) => void\n professionals: Array<{ id: string; name: string }>\n}) {\n const t = useTranslation()\n const [open, setOpen] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\n const current = professionals.find((p) => p.id === value)\n\n useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false) }\n document.addEventListener('mousedown', handler)\n return () => document.removeEventListener('mousedown', handler)\n }, [open])\n\n return (\n <div ref={ref} className=\"relative flex-1\">\n <button type=\"button\" onClick={() => setOpen((p) => !p)}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-muted/30 transition-colors text-left\">\n {current ? (\n <span>{current.name}</span>\n ) : (\n <span className=\"text-muted-foreground\">{t('agenda.appointment.selectProfessional')}</span>\n )}\n <svg className=\"ml-auto h-3 w-3 text-muted-foreground shrink-0\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n </svg>\n </button>\n {open && (\n <div className=\"fayz-glass-surface absolute top-full left-0 right-0 z-50 mt-1 rounded-lg border bg-popover shadow-lg py-1 animate-in fade-in zoom-in-95 duration-100\">\n {professionals.map((p: any) => (\n <button key={p.id} type=\"button\"\n onClick={() => { onChange(p.id); setOpen(false) }}\n className={`flex w-full items-center gap-2 px-3 py-1.5 text-sm hover:bg-muted/50 transition-colors ${p.id === value ? 'bg-muted/30' : ''}`}>\n <span>{p.name}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Location Select — compact inline dropdown\n// ---------------------------------------------------------------------------\n\nfunction LocationSelect({ value, onChange, locations }: {\n value: string; onChange: (v: string) => void\n locations: Array<{ id: string; name: string }>\n}) {\n const t = useTranslation()\n const [open, setOpen] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\n const current = locations.find((l) => l.id === value)\n\n useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false) }\n document.addEventListener('mousedown', handler)\n return () => document.removeEventListener('mousedown', handler)\n }, [open])\n\n return (\n <div ref={ref} className=\"relative flex-1\">\n <button type=\"button\" onClick={() => setOpen((p) => !p)}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-muted/30 transition-colors text-left\">\n {current ? (\n <span>{current.name}</span>\n ) : (\n <span className=\"text-muted-foreground\">{t('agenda.appointment.selectLocation')}</span>\n )}\n <svg className=\"ml-auto h-3 w-3 text-muted-foreground shrink-0\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n </svg>\n </button>\n {open && (\n <div className=\"fayz-glass-surface absolute top-full left-0 right-0 z-50 mt-1 rounded-lg border bg-popover shadow-lg py-1 animate-in fade-in zoom-in-95 duration-100 max-h-48 overflow-y-auto\">\n {locations.map((l: any) => (\n <button key={l.id} type=\"button\"\n onClick={() => { onChange(l.id); setOpen(false) }}\n className={`flex w-full items-center gap-2 px-3 py-1.5 text-sm hover:bg-muted/50 transition-colors ${l.id === value ? 'bg-muted/30' : ''}`}>\n <span>{l.name}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Appointment Modal — Google Calendar-inspired compact layout\n// ---------------------------------------------------------------------------\n\ninterface Props {\n open: boolean\n mode: 'create' | 'edit'\n bookingId?: string\n prefill?: Partial<CreateBookingInput> & { endsAt?: string }\n initialTab?: string\n externalSource?: ExternalBookingSource\n onClose: () => void\n onCreated?: (bookingId: string, source?: ExternalBookingSource) => void\n}\n\nexport function AppointmentModal({ open, mode, bookingId, prefill, initialTab, externalSource, onClose, onCreated }: Props) {\n const t = useTranslation()\n const locale = getCurrentLocale()\n const config = useAgendaConfig()\n const provider = useAgendaProvider()\n const initialSnapshot = useRef<string>('')\n const createBooking = useAgendaStore((s) => s.createBooking)\n const guardBookings = useLimitGuard('bookings_month')\n const updateBooking = useAgendaStore((s) => s.updateBooking)\n const deleteBooking = useAgendaStore((s) => s.deleteBooking)\n const fetchBookings = useAgendaStore((s) => s.fetchBookings)\n const agendaDateRange = useAgendaStore((s) => s.dateRange)\n const professionals = useAgendaStore((s) => s.professionals)\n const storeLocations = useAgendaStore((s) => s.locations)\n\n // --- State ---\n // Default to the first configured booking type (e.g. 'event' in simple mode,\n // 'appointment' otherwise) so single-type agendas resolve their type cleanly.\n const defaultBookingType = (config.bookingTypes[0]?.id ?? 'appointment') as BookingTypeId\n const [loading, setLoading] = useState(mode === 'edit')\n const [bookingType, setBookingType] = useState<BookingTypeId>(prefill?.kind ?? defaultBookingType)\n const [title, setTitle] = useState('')\n const [clientId, setClientId] = useState(prefill?.clientId ?? '')\n const [clientSearch, setClientSearch] = useState('')\n const [clientPhone, setClientPhone] = useState('')\n const [professionalId, setProfessionalId] = useState(prefill?.professionalId ?? '')\n const [locationId, setLocationId] = useState(prefill?.locationId ?? '')\n const [services, setServices] = useState<ServiceItem[]>([])\n const [serviceSearch, setServiceSearch] = useState('')\n const [date, setDate] = useState(() => {\n if (prefill?.startsAt) return prefill.startsAt.slice(0, 10)\n return new Date().toISOString().slice(0, 10)\n })\n const [startTime, setStartTime] = useState(() => {\n if (prefill?.startsAt) {\n const d = new Date(prefill.startsAt)\n return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`\n }\n return '09:00'\n })\n const [status, setStatus] = useState('scheduled')\n const [notes, setNotes] = useState('')\n const [showNotes, setShowNotes] = useState(false)\n const [saving, setSaving] = useState(false)\n const [conflict, setConflict] = useState(false)\n // Client search/quick-create state now lives inside <ContactPicker>.\n const [serviceOptions, setServiceOptions] = useState<ComboboxOption[]>([])\n const [initialServiceOptions, setInitialServiceOptions] = useState<ComboboxOption[]>([])\n const [editingDate, setEditingDate] = useState(false)\n const [editingTime, setEditingTime] = useState(false)\n const [confirmingDelete, setConfirmingDelete] = useState(false)\n const [deleting, setDeleting] = useState(false)\n const [editOrderId, setEditOrderId] = useState<string | null>(null)\n const [editOrderTotal, setEditOrderTotal] = useState(0)\n const [editPaymentStatus, setEditPaymentStatus] = useState<import('../financial-bridge').BookingPaymentStatus>('none')\n const [paymentStatusLoading, setPaymentStatusLoading] = useState(false)\n const [modalTab, setModalTab] = useState<'appointment' | 'client' | 'financial'>('appointment')\n const [clientData, setClientData] = useState<Record<string, any> | null>(null)\n const [clientDataLoading, setClientDataLoading] = useState(false)\n const [clientEditing, setClientEditing] = useState(false)\n const [cancellationReasons, setCancellationReasons] = useState<CancellationReasonItem[]>([])\n const [cancellationReasonId, setCancellationReasonId] = useState('')\n const [cancellationNotes, setCancellationNotes] = useState('')\n const [cancellationReasonsLoading, setCancellationReasonsLoading] = useState(false)\n\n // Active booking type config\n const activeType = config.bookingTypes.find((bt) => bt.id === bookingType) ?? config.bookingTypes[0]\n\n // Reset form when modal opens\n useEffect(() => {\n if (!open) return\n setClientId(prefill?.clientId ?? ''); setClientSearch(''); setClientPhone('')\n setProfessionalId(prefill?.professionalId ?? ''); setLocationId(prefill?.locationId ?? ''); setServices([])\n setServiceSearch(''); setNotes(''); setStatus('scheduled'); setShowNotes(false)\n setConflict(false); setLoading(mode === 'edit')\n setBookingType(prefill?.kind ?? defaultBookingType); setTitle('')\n setEditingDate(false); setEditingTime(false); setConfirmingDelete(false); setDeleting(false)\n setEditOrderId(null); setEditOrderTotal(0); setEditPaymentStatus('none'); setPaymentStatusLoading(false)\n setClientData(null); setClientDataLoading(false); setClientEditing(false)\n setCancellationReasonId(''); setCancellationNotes(''); setCancellationReasonsLoading(false)\n setModalTab((initialTab as 'appointment' | 'client' | 'financial') || 'appointment')\n if (!prefill?.professionalId && professionals.length === 1) setProfessionalId(professionals[0].id)\n setDate(() => {\n if (prefill?.startsAt) return prefill.startsAt.slice(0, 10)\n return new Date().toISOString().slice(0, 10)\n })\n setStartTime(() => {\n if (prefill?.startsAt) {\n const d = new Date(prefill.startsAt)\n return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`\n }\n return '09:00'\n })\n }, [open])\n\n // Edit: load existing\n useEffect(() => {\n if (!open || mode !== 'edit' || !bookingId) return\n setLoading(true)\n provider.getBookingById(bookingId).then((b) => {\n if (!b) { setLoading(false); return }\n setBookingType((b.kind as BookingTypeId) ?? defaultBookingType)\n setTitle(b.clientName ?? '')\n setClientId(b.clientId ?? ''); setClientSearch(b.clientName ?? '')\n setProfessionalId(b.professionalId ?? ''); setLocationId(b.locationId ?? '')\n setDate(b.startsAt.slice(0, 10))\n const d = new Date(b.startsAt)\n setStartTime(`${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`)\n setStatus(b.status); setNotes(b.notes ?? '')\n if (b.notes) setShowNotes(true)\n if (b.services) setServices(b.services.map((s: any) => ({\n serviceId: s.serviceId ?? '', name: s.name, durationMinutes: s.durationMinutes, price: s.price,\n })))\n setEditOrderId(b.orderId ?? null)\n setEditOrderTotal(b.orderTotal ?? 0)\n setEditPaymentStatus(b.paymentStatus ?? 'none')\n // Save initial snapshot for dirty check\n const svcSnap = b.services ? b.services.map((s: any) => ({ id: s.serviceId ?? '', dur: s.durationMinutes, price: s.price })) : []\n initialSnapshot.current = JSON.stringify({\n title: b.clientName ?? '',\n clientId: b.clientId ?? '', professionalId: b.professionalId ?? '', locationId: b.locationId ?? '',\n date: b.startsAt.slice(0, 10),\n startTime: `${String(new Date(b.startsAt).getHours()).padStart(2, '0')}:${String(new Date(b.startsAt).getMinutes()).padStart(2, '0')}`,\n status: b.status, notes: b.notes ?? '', cancellationReasonId: '', cancellationNotes: '', services: svcSnap,\n })\n setLoading(false)\n // Resolve payment status from bridge if available\n if (b.orderId && config.financialBridge) {\n setPaymentStatusLoading(true)\n config.financialBridge.resolvePaymentStatuses([b.orderId]).then((map) => {\n const summary = map.get(b.orderId!)\n if (summary) {\n setEditPaymentStatus(summary.status)\n setEditOrderTotal(summary.totalAmount)\n }\n }).catch(() => {}).finally(() => setPaymentStatusLoading(false))\n }\n }).catch(() => setLoading(false))\n }, [open, mode, bookingId])\n\n // Fetch client data when client tab is opened\n useEffect(() => {\n if (modalTab !== 'client' || !clientId || !config.contactLookup || clientData) return\n setClientDataLoading(true)\n config.contactLookup.getById(clientId).then((result) => {\n setClientData(result?.data ?? null)\n setClientDataLoading(false)\n }).catch(() => setClientDataLoading(false))\n }, [modalTab, clientId])\n\n useEffect(() => {\n if (!open || status !== 'cancelled' || !config.cancellationDetails || cancellationReasons.length > 0) return\n setCancellationReasonsLoading(true)\n config.cancellationDetails.listReasons()\n .then((reasons) => setCancellationReasons(reasons))\n .catch(() => setCancellationReasons([]))\n .finally(() => setCancellationReasonsLoading(false))\n }, [open, status, config.cancellationDetails, cancellationReasons.length])\n\n // Fetch initial service list when modal opens\n useEffect(() => {\n if (!open || !config.serviceLookup) return\n const lookup = config.serviceLookup\n const fetch = lookup.list ? () => lookup.list!() : () => lookup.search('')\n fetch().then((results) => {\n const opts = results.map((r: any) => ({ id: r.id, label: r.label, subtitle: r.subtitle, price: r.price, data: r.data }))\n setInitialServiceOptions(opts)\n }).catch(() => setInitialServiceOptions([]))\n }, [open])\n\n // Search effects (client search now lives inside <ContactPicker>)\n useEffect(() => {\n if (!config.serviceLookup || serviceSearch.length < 1) { setServiceOptions([]); return }\n const timer = setTimeout(async () => {\n try {\n const results = await config.serviceLookup!.search(serviceSearch)\n setServiceOptions(results.map((r: any) => ({ id: r.id, label: r.label, subtitle: r.subtitle, price: r.price, data: r.data })))\n } catch { setServiceOptions([]) }\n }, 250)\n return () => clearTimeout(timer)\n }, [serviceSearch])\n\n // Computed\n const serviceDuration = services.reduce((sum, s) => sum + s.durationMinutes, 0)\n const selectionDuration = useMemo(() => {\n if (!prefill?.startsAt || !prefill?.endsAt) return 0\n return Math.round((new Date(prefill.endsAt).getTime() - new Date(prefill.startsAt).getTime()) / 60000)\n }, [prefill?.startsAt, prefill?.endsAt])\n const totalDuration = serviceDuration > 0 ? serviceDuration : selectionDuration\n const totalPrice = services.reduce((sum, s) => sum + s.price, 0)\n const { currency } = config\n\n const endTime = useMemo(() => {\n const [h, m] = startTime.split(':').map(Number)\n const total = h * 60 + m + totalDuration\n return `${String(Math.floor(total / 60) % 24).padStart(2, '0')}:${String(total % 60).padStart(2, '0')}`\n }, [startTime, totalDuration])\n\n // Conflict check\n useEffect(() => {\n if (!professionalId || totalDuration === 0) { setConflict(false); return }\n const timer = setTimeout(() => {\n provider.checkConflict({\n assigneeId: professionalId, startsAt: `${date}T${startTime}:00`, endsAt: `${date}T${endTime}:00`, excludeBookingId: bookingId,\n }).then(setConflict).catch(() => setConflict(false))\n }, 300)\n return () => clearTimeout(timer)\n }, [professionalId, date, startTime, endTime, bookingId])\n\n function addService(opt: ComboboxOption) {\n const duration = (opt.data?.duration_minutes as number) || 60\n setServices((p) => [...p, { serviceId: opt.id, name: opt.label, durationMinutes: duration, price: opt.price ?? 0 }])\n setServiceSearch(''); setServiceOptions([])\n }\n function removeService(idx: number) { setServices((p) => p.filter((_, i) => i !== idx)) }\n\n async function handleSubmit(e: React.FormEvent) {\n e.preventDefault()\n if (!canSubmit) return\n // Plan quantity guard (client-side, before the store call): opens the global\n // UpgradeModal and aborts when the monthly booking cap is reached. CREATE only.\n if (mode === 'create' && (await guardBookings()) === 'blocked') return\n setSaving(true)\n try {\n const startsAt = new Date(`${date}T${startTime}:00`).toISOString()\n if (mode === 'create') {\n const newBooking = await createBooking({ kind: bookingType, clientId, professionalId, locationId: locationId || undefined, startsAt, notes: notes || undefined,\n title: activeType.fields.title ? title.trim() : undefined,\n services: services.map((s: any) => ({ serviceId: s.serviceId, name: s.name, durationMinutes: s.durationMinutes, price: s.price })) })\n invalidateLimit('bookings_month')\n onClose()\n onCreated?.(newBooking.id, externalSource)\n } else if (bookingId) {\n await updateBooking(bookingId, {\n clientId, professionalId, locationId: locationId || undefined, startsAt, notes: notes || undefined, status: status as any,\n title: activeType.fields.title ? title.trim() : undefined,\n services: services.map((s: any) => ({ serviceId: s.serviceId, name: s.name, durationMinutes: s.durationMinutes, price: s.price })),\n })\n if (status === 'cancelled' && config.cancellationDetails && cancellationReasonId) {\n await config.cancellationDetails.saveCancellationDetails({\n bookingId,\n reasonId: cancellationReasonId,\n notes: cancellationNotes.trim() || undefined,\n cancelledAt: new Date().toISOString(),\n })\n }\n onClose()\n }\n } catch { /* toast */ }\n setSaving(false)\n }\n\n async function handleDelete() {\n if (!bookingId) return\n setDeleting(true)\n try {\n await deleteBooking(bookingId)\n onClose()\n } catch {\n // deleteBooking surfaces its own toast. Return the footer to its normal\n // state (out of the confirm step) so a failure is clear feedback rather\n // than a modal that silently stays stuck on \"Confirm delete\".\n setConfirmingDelete(false)\n } finally {\n setDeleting(false)\n }\n }\n\n const isPaidBooking = editPaymentStatus === 'paid'\n const selectedCancellationReason = cancellationReasons.find((reason) => reason.id === cancellationReasonId)\n const needsCancellationReason = mode === 'edit' && status === 'cancelled' && !!config.cancellationDetails\n const needsCancellationNotes = needsCancellationReason && !!selectedCancellationReason?.requiresNotes\n\n // Dirty check — only enable Update when something changed\n const formSnapshot = useMemo(() =>\n JSON.stringify({ title, clientId, professionalId, locationId, date, startTime, status, notes, cancellationReasonId, cancellationNotes, services: services.map((s: any) => ({ id: s.serviceId, dur: s.durationMinutes, price: s.price })) }),\n [title, clientId, professionalId, locationId, date, startTime, status, notes, cancellationReasonId, cancellationNotes, services]\n )\n const isDirty = mode === 'create' || formSnapshot !== initialSnapshot.current\n\n const canSubmit = (\n (!activeType.fields.title || title.trim()) &&\n (!activeType.requiresClient || clientId) &&\n (!activeType.fields.professional || professionalId) &&\n (!activeType.requiresServices || services.length > 0) &&\n (!needsCancellationReason || !!cancellationReasonId) &&\n (!needsCancellationNotes || !!cancellationNotes.trim()) &&\n !conflict && !saving\n )\n\n const showTabs = config.bookingTypes.length > 1\n\n return (\n <Modal open={open} onOpenChange={(v) => { if (!v) onClose() }}>\n <ModalContent size=\"lg\" noPadding>\n\n {/* ═══ TOP — type tabs + date/time ═══ */}\n <div className=\"px-5 pt-4 pb-3 shrink-0 space-y-3\">\n <ModalTitle className=\"sr-only\">\n {mode === 'create' ? t('agenda.appointment.new') : t('agenda.appointment.edit')}\n </ModalTitle>\n\n {/* Booking type tabs (create) or section tabs (edit) */}\n {showTabs && mode === 'create' ? (\n <div className=\"flex gap-1 border-b fayz-glass-divider\">\n {config.bookingTypes.map((bt) => {\n const label = t(`agenda.bookingType.${bt.id}`) || bt.label\n const isActive = bookingType === bt.id\n const BtIcon = BOOKING_TYPE_ICONS[bt.icon] ?? Calendar\n return (\n <button key={bt.id} type=\"button\" onClick={() => setBookingType(bt.id)}\n className={`relative flex items-center gap-1.5 pb-2 px-2 text-xs font-medium transition-colors ${\n isActive ? 'text-foreground' : 'text-muted-foreground hover:text-foreground'\n }`}>\n <BtIcon className=\"h-3.5 w-3.5\" />\n {label}\n {isActive && (\n <span className=\"absolute bottom-0 left-0 right-0 h-0.5 rounded-full bg-foreground\" />\n )}\n </button>\n )\n })}\n </div>\n ) : mode === 'edit' && (\n (config.clientEntityDef && clientId) || (config.modules.financial && editOrderId) ? (\n <div className=\"flex gap-1 border-b fayz-glass-divider\">\n {([\n { id: 'appointment' as const, label: t(`agenda.bookingType.${bookingType}`) || activeType.label, icon: Calendar, show: true },\n { id: 'client' as const, label: t('agenda.appointment.clientTab'), icon: User, show: !!config.clientEntityDef && !!clientId },\n { id: 'financial' as const, label: t('agenda.payment.title'), icon: DollarSign, show: config.modules.financial && !!editOrderId },\n ]).filter((tab) => tab.show).map((tab) => {\n const isActive = modalTab === tab.id\n return (\n <button key={tab.id} type=\"button\" onClick={() => setModalTab(tab.id)}\n className={`relative flex items-center gap-1.5 pb-2 px-2 text-xs font-medium transition-colors ${\n isActive ? 'text-foreground' : 'text-muted-foreground hover:text-foreground'\n }`}>\n <tab.icon className=\"h-3.5 w-3.5\" />\n {tab.label}\n {tab.id === 'financial' && editPaymentStatus === 'paid' && (\n <span className=\"h-1.5 w-1.5 rounded-full bg-success\" />\n )}\n {tab.id === 'financial' && editPaymentStatus !== 'paid' && (\n (editPaymentStatus !== 'none' || (totalPrice > 0 && date <= new Date().toISOString().slice(0, 10)))\n ) && (\n <span className=\"h-1.5 w-1.5 rounded-full bg-warning\" />\n )}\n {isActive && (\n <span className=\"absolute bottom-0 left-0 right-0 h-0.5 rounded-full bg-foreground\" />\n )}\n </button>\n )\n })}\n </div>\n ) : (\n <h2 className=\"text-sm font-semibold\">\n {t(`agenda.bookingType.${bookingType}`) || activeType.label}\n </h2>\n )\n )}\n\n {/* Date/time + professional row — hidden on financial tab */}\n {modalTab === 'appointment' && (\n <>\n <div className=\"flex items-center gap-3\">\n <Clock className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <div className=\"flex items-center gap-1.5 text-sm flex-1 min-w-0\">\n {editingDate ? (\n <input type=\"date\" value={date} autoFocus\n onChange={(e) => { setDate(e.target.value); setEditingDate(false) }}\n onBlur={() => setEditingDate(false)}\n className=\"bg-transparent text-sm font-medium focus:outline-none border-b border-foreground w-auto shrink-0\" />\n ) : (\n <button type=\"button\" onClick={() => setEditingDate(true)}\n className=\"px-0.5 py-0.5 font-medium border-b border-transparent hover:border-foreground transition-colors shrink-0\">\n {formatCompactDate(date, locale)}\n </button>\n )}\n {editingTime ? (\n <input type=\"time\" value={startTime} autoFocus\n onChange={(e) => { if (e.target.value) { setStartTime(e.target.value); setEditingTime(false) } }}\n onBlur={() => setEditingTime(false)}\n className=\"bg-transparent text-xs text-muted-foreground focus:outline-none border-b border-foreground w-auto shrink-0\" />\n ) : (\n <button type=\"button\" onClick={() => setEditingTime(true)}\n className=\"px-0.5 py-0.5 text-xs text-muted-foreground border-b border-transparent hover:border-foreground transition-colors shrink-0\">\n {startTime}\n </button>\n )}\n <span className=\"text-[11px] text-muted-foreground/60\">—</span>\n <span className=\"text-[11px] text-muted-foreground/60\">{endTime}</span>\n\n {/* Professional — right-aligned on the same row */}\n {activeType.fields.professional && (\n <div className=\"ml-auto shrink-0\">\n <ProfessionalSelect value={professionalId} onChange={setProfessionalId} professionals={professionals} />\n </div>\n )}\n </div>\n </div>\n\n {conflict && (\n <div className=\"flex items-center gap-2 rounded-lg bg-destructive/10 px-3 py-1.5 text-xs text-destructive\">\n <AlertTriangle className=\"h-3.5 w-3.5 shrink-0\" />\n {t('agenda.appointment.conflict')}\n </div>\n )}\n </>\n )}\n </div>\n\n {/* ═══ BODY ═══ */}\n <div className=\"flex flex-col flex-1 min-h-0 overflow-hidden\">\n\n {/* Client tab content — reuses the same CrudDetailPage as /clients/:id */}\n {modalTab === 'client' && clientId && config.clientEntityDef && (\n <div className=\"flex-1 overflow-y-auto px-5 py-4\">\n {clientDataLoading ? (\n <div className=\"space-y-3 py-2\">\n {[...Array(4)].map((_, i) => (\n <div key={i} className=\"h-8 rounded-lg bg-muted animate-pulse\" />\n ))}\n </div>\n ) : clientData ? (\n clientEditing ? (\n <CrudFormPage\n embedded\n entityDef={config.clientEntityDef}\n mode=\"edit\"\n initialData={clientData}\n namePlural=\"\"\n onCancel={() => setClientEditing(false)}\n onSubmit={async (data) => {\n try {\n const { getSupabaseClientOptional } = await import('@fayz-ai/core')\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) return\n const dbData: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(data)) {\n dbData[k.replace(/[A-Z]/g, (m) => '_' + m.toLowerCase())] = v\n }\n await supabase.from('people').update(dbData).eq('id', clientId)\n setClientData({ ...clientData, ...data })\n setClientEditing(false)\n } catch { /* toast */ }\n }}\n />\n ) : (\n <CrudDetailPage\n embedded\n entityDef={config.clientEntityDef}\n item={clientData}\n namePlural=\"\"\n basePath=\"\"\n onBack={() => setModalTab('appointment')}\n onEdit={() => setClientEditing(true)}\n />\n )\n ) : (\n <p className=\"text-sm text-muted-foreground py-4 text-center\">{t('agenda.appointment.noClientData')}</p>\n )}\n </div>\n )}\n\n {/* Financial tab content */}\n {modalTab === 'financial' && editOrderId && config.financialBridge && (\n <div className=\"flex-1 overflow-y-auto\">\n <BookingPaymentPanel\n orderId={editOrderId}\n orderTotal={editOrderTotal}\n services={services.map((s: any) => ({ name: s.name, price: s.price, durationMinutes: s.durationMinutes }))}\n formatCurrency={(v) => fmtCurrency(v, currency.locale, currency.code)}\n inline\n onClose={() => setModalTab('appointment')}\n onPaymentChange={() => {\n config.financialBridge!.getPaymentDetail(editOrderId).then((d) => {\n if (d) { setEditPaymentStatus(d.status); setEditOrderTotal(d.totalAmount) }\n }).catch(() => {})\n // Propagate to the calendar card + popover badge (booking.paymentStatus\n // is ledger-derived) so they update without a page refresh.\n if (agendaDateRange.start) fetchBookings(agendaDateRange)\n }}\n />\n </div>\n )}\n\n {/* Appointment tab content */}\n <form onSubmit={handleSubmit} className=\"flex flex-col flex-1 min-h-0 overflow-hidden\" style={{ display: modalTab === 'appointment' ? undefined : 'none' }}>\n <div className=\"border-t fayz-glass-divider px-5 py-3 space-y-1 flex-1 overflow-y-auto\">\n\n {/* Loading skeleton */}\n {loading && (\n <div className=\"space-y-2 py-2\">\n {[...Array(4)].map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 py-1.5\">\n <div className=\"h-4 w-4 rounded bg-muted animate-pulse shrink-0\" />\n <div className=\"h-8 flex-1 rounded-lg bg-muted animate-pulse\" />\n </div>\n ))}\n </div>\n )}\n\n {!loading && <>\n\n {/* Title — free-text event name (simple / Google-Calendar-style events) */}\n {activeType.fields.title && (\n <div className=\"flex items-center gap-3 py-1\">\n <Calendar className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <input type=\"text\" value={title} onChange={(e) => setTitle(e.target.value)}\n placeholder={t('agenda.appointment.addTitle')} autoFocus={mode === 'create'}\n className=\"w-full flex-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-ring\" />\n </div>\n )}\n\n {/* Client */}\n {activeType.fields.client && (\n <div className=\"flex items-center gap-3 py-1\">\n <User className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <div className=\"flex-1\">\n {/* Shared find-or-create contact flow (@fayz-ai/saas). The\n quick-create that used to live inline here now writes the\n SAME people(+clients) rows for every plugin — see\n `createPerson`. `clientKind`/`clientExtensionTable` keep the\n vertical's discriminator and extension table.\n `variant=\"inline\"` keeps this modal's grammar: an icon\n column and borderless controls (like Scheduled / Add\n notes). Same component and same flow as the conversations\n composer — only the input's chrome differs. */}\n <ContactPicker\n value={clientId || clientSearch ? { id: clientId || undefined, name: clientSearch, phone: clientPhone } : null}\n onChange={(contact) => {\n setClientId(contact?.id ?? '')\n setClientSearch(contact?.name ?? '')\n setClientPhone(contact?.phone ?? '')\n }}\n kind={config.clientKind}\n extensionTable=\"clients\"\n lookup={config.contactLookup}\n clearable={!isPaidBooking}\n variant=\"inline\"\n placeholder={t('agenda.appointment.searchClient')}\n createLabel={t('agenda.appointment.newClient')}\n hint={\n <p className=\"text-[11px] text-warning\">\n {t('agenda.appointment.selectClientHint')}\n </p>\n }\n />\n </div>\n </div>\n )}\n\n {/* Location */}\n {activeType.fields.location && config.modules.locationSelection && (storeLocations.length > 0 || config.locations.length > 0) && (\n <div className=\"flex items-center gap-3 py-1\">\n <MapPin className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <LocationSelect\n value={locationId}\n onChange={setLocationId}\n locations={storeLocations.length > 0 ? storeLocations : config.locations}\n />\n </div>\n )}\n\n {/* Services */}\n {activeType.fields.services && (\n <div className=\"flex items-start gap-3 py-1\">\n <Briefcase className=\"h-4 w-4 mt-1.5 text-muted-foreground shrink-0\" />\n <div className=\"flex-1\">\n {services.length > 0 && (\n <div className=\"space-y-0.5 mb-1\">\n {services.map((svc, idx) => (\n <div key={idx} className=\"flex items-center rounded-md bg-muted/30 px-2.5 py-1.5 text-sm\">\n <span className=\"flex-1 truncate min-w-0\">{svc.name}</span>\n <div className=\"flex items-center gap-0.5 shrink-0 ml-3\">\n <InlineNumber\n value={svc.durationMinutes}\n onChange={(v) => setServices((p) => p.map((s, i) => i === idx ? { ...s, durationMinutes: Math.round(v) } : s))}\n min={5}\n step={5}\n className=\"w-10 shrink-0\"\n disabled={isPaidBooking}\n tooltip={t('agenda.appointment.duration')}\n />\n <span className=\"text-[11px] text-muted-foreground\">min</span>\n </div>\n <div className=\"flex items-center gap-0.5 shrink-0 ml-3\">\n <span className=\"text-[11px] text-muted-foreground\">{currency.symbol}</span>\n <InlineNumber\n value={svc.price}\n onChange={(v) => setServices((p) => p.map((s, i) => i === idx ? { ...s, price: v } : s))}\n min={0}\n step={0.01}\n className=\"w-14 shrink-0\"\n disabled={isPaidBooking}\n tooltip={t('agenda.appointment.price')}\n />\n </div>\n {!isPaidBooking && (\n <button type=\"button\" onClick={() => removeService(idx)} className=\"p-0.5 ml-2 text-muted-foreground hover:text-destructive shrink-0\">\n <X className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n ))}\n </div>\n )}\n\n {!isPaidBooking && <SearchCombobox\n value={serviceSearch}\n onChange={setServiceSearch}\n onSelect={addService}\n options={serviceOptions}\n placeholder={t('agenda.appointment.searchService')}\n onBlurEmpty={() => {}}\n onFocus={() => { if (!serviceSearch && serviceOptions.length === 0) setServiceOptions(initialServiceOptions) }}\n renderRight={(opt) => {\n const dur = (opt.data?.duration_minutes as number) || 0\n const hasPrice = opt.price != null\n if (!hasPrice && !dur) return null\n return (\n <span className=\"text-muted-foreground text-xs whitespace-nowrap\">\n {hasPrice && fmtCurrency(opt.price!, currency.locale, currency.code)}\n {hasPrice && dur > 0 && ' · '}\n {dur > 0 && `${dur}min`}\n </span>\n )\n }}\n minimal\n inlineLabel={services.length > 0 ? t('agenda.appointment.addService') : t('agenda.appointment.addServiceFirst')}\n inlineIcon={services.length > 0 ? 'plus' : 'search'}\n />}\n </div>\n </div>\n )}\n\n {/* Status */}\n {activeType.fields.status && (\n <div className=\"flex items-center gap-3 py-1\">\n <CircleDot className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <StatusSelect value={status} onChange={setStatus} statuses={config.statuses} bookingDate={date} />\n </div>\n )}\n\n {needsCancellationReason && (\n <div className=\"flex items-start gap-3 py-1\">\n <Ban className=\"h-4 w-4 mt-2 text-muted-foreground shrink-0\" />\n <div className=\"flex-1 space-y-2\">\n <select\n value={cancellationReasonId}\n onChange={(event) => setCancellationReasonId(event.target.value)}\n disabled={cancellationReasonsLoading}\n className=\"w-full rounded-input border border-input bg-card px-2.5 py-1.5 text-sm shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] focus:outline-none focus:ring-2 focus:ring-ring\"\n >\n <option value=\"\">{cancellationReasonsLoading ? t('agenda.cancellation.loadingReasons') : t('agenda.cancellation.selectReason')}</option>\n {cancellationReasons.map((reason) => (\n <option key={reason.id} value={reason.id}>\n {reason.label}{reason.requiresNotes ? ' *' : ''}\n </option>\n ))}\n </select>\n <textarea\n value={cancellationNotes}\n onChange={(event) => setCancellationNotes(event.target.value)}\n placeholder={needsCancellationNotes ? t('agenda.cancellation.notesRequired') : t('agenda.cancellation.notesOptional')}\n rows={2}\n className=\"w-full rounded-input border border-input bg-card px-2.5 py-1.5 text-sm resize-none shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n </div>\n )}\n\n {/* Notes — progressive disclosure */}\n {!showNotes ? (\n <div className=\"flex items-center gap-3 py-1\">\n <FileText className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <button type=\"button\" onClick={() => setShowNotes(true)}\n className=\"text-sm text-muted-foreground hover:text-foreground transition-colors text-left py-1.5 pl-2\">\n {t('agenda.appointment.addNotes')}\n </button>\n </div>\n ) : (\n <div className=\"flex items-start gap-3 py-1\">\n <FileText className=\"h-4 w-4 mt-2 text-muted-foreground shrink-0\" />\n <textarea value={notes} onChange={(e) => setNotes(e.target.value)}\n placeholder={t('agenda.appointment.addDescription')} rows={2} autoFocus\n className=\"w-full flex-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm resize-none focus:outline-none focus:ring-2 focus:ring-ring\" />\n </div>\n )}\n\n </>}\n </div>\n\n {/* Appointment footer — inside form for submit */}\n {modalTab === 'appointment' && !clientEditing && (\n <div className=\"px-5 py-2.5 border-t fayz-glass-divider bg-transparent shrink-0 sm:rounded-b-2xl\">\n {confirmingDelete ? (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-destructive font-medium\">{t('agenda.appointment.deleteConfirm')}</span>\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setConfirmingDelete(false)}>\n {t('agenda.appointment.cancel')}\n </Button>\n <Button type=\"button\" variant=\"destructive\" size=\"sm\" onClick={handleDelete} disabled={deleting}>\n {deleting ? t('agenda.appointment.deleting') : t('agenda.appointment.confirmDelete')}\n </Button>\n </div>\n </div>\n ) : (\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n {mode === 'edit' && (\n <button type=\"button\" onClick={() => setConfirmingDelete(true)} className=\"text-xs text-destructive font-medium hover:underline\">{t('agenda.appointment.delete')}</button>\n )}\n {services.length > 0 && (\n <span className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <Clock className=\"h-3 w-3\" />\n {totalDuration}min\n {config.modules.financial && totalPrice > 0 && mode === 'edit' ? (\n paymentStatusLoading ? (\n <span className=\"h-4 w-16 rounded-full bg-muted animate-pulse\" />\n ) : isPaidBooking ? (\n <button type=\"button\" onClick={(e) => { e.stopPropagation(); setModalTab('financial') }}\n className=\"inline-flex items-center gap-1 rounded-full bg-success/10 px-2 py-0.5 text-[10px] font-medium text-success hover:bg-success/20 transition-colors\">\n <Check className=\"h-2.5 w-2.5\" />\n {fmtCurrency(totalPrice, currency.locale, currency.code)} &middot; {t('agenda.payment.paid')}\n </button>\n ) : date <= new Date().toISOString().slice(0, 10) ? (\n <button type=\"button\" onClick={(e) => { e.stopPropagation(); setModalTab('financial') }}\n className=\"inline-flex items-center gap-1 rounded-full bg-warning/10 px-2 py-0.5 text-[10px] font-medium text-warning hover:bg-warning/20 transition-colors\">\n <HandCoins className=\"h-3 w-3\" />\n {fmtCurrency(totalPrice, currency.locale, currency.code)} &middot; {t('agenda.payment.collect')}\n </button>\n ) : (\n <span>&middot; {fmtCurrency(totalPrice, currency.locale, currency.code)}</span>\n )\n ) : (\n <span>&middot; {fmtCurrency(totalPrice, currency.locale, currency.code)}</span>\n )}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={onClose} className=\"hidden sm:inline-flex\">\n {t('agenda.appointment.cancel')}\n </Button>\n <Button type=\"submit\" variant=\"default\" size=\"sm\" disabled={!canSubmit || !isDirty}>\n {saving ? t('agenda.appointment.saving') : mode === 'create' ? t('agenda.appointment.save') : t('agenda.appointment.update')}\n </Button>\n </div>\n </div>\n )}\n </div>\n )}\n </form>\n\n {/* Non-appointment tab footer — outside form */}\n {modalTab !== 'appointment' && !clientEditing && (\n <div className=\"px-5 py-2.5 border-t fayz-glass-divider bg-transparent shrink-0 sm:rounded-b-2xl\">\n <div className=\"flex items-center\">\n <button type=\"button\" onClick={() => { setModalTab('appointment'); setClientEditing(false) }}\n className=\"inline-flex items-center gap-1 text-xs font-medium text-muted-foreground hover:text-foreground transition-colors\">\n <svg className=\"h-3 w-3\" viewBox=\"0 0 16 16\" fill=\"none\"><path d=\"M10 12L6 8l4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/></svg>\n {t('agenda.payment.backToAppointment')}\n </button>\n </div>\n </div>\n )}\n </div>\n </ModalContent>\n\n </Modal>\n )\n}\n","import React, { useEffect, useRef, useState, useCallback } from 'react'\nimport { createPortal } from 'react-dom'\n\n// ---------------------------------------------------------------------------\n// Inject animations once\n// ---------------------------------------------------------------------------\n\nconst STYLE_ID = 'saas-floating-panel'\nif (typeof document !== 'undefined' && !document.getElementById(STYLE_ID)) {\n const s = document.createElement('style')\n s.id = STYLE_ID\n s.textContent = `\n @keyframes _fp-dismiss { from { opacity:1; transform:scale(1) } to { opacity:0; transform:scale(.96) } }\n @keyframes _fp-expand { from { opacity:1; transform:scale(1) } to { opacity:0; transform:scale(1.08) } }\n .saas-fp-dismissing { animation: _fp-dismiss 150ms ease-in forwards; pointer-events: none }\n .saas-fp-expanding { animation: _fp-expand 200ms ease-in forwards; pointer-events: none }\n `\n document.head.appendChild(s)\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Phase = 'visible' | 'dismissing' | 'expanding'\n\nexport interface FloatingPanelRef {\n /** Dismiss with fade-out, then call onClose */\n dismiss: () => void\n /** Expand-out animation (e.g. popover → modal), then call callback */\n expandThen: (callback: () => void) => void\n}\n\ninterface FloatingPanelProps {\n position: { x: number; y: number }\n width: number\n height: number\n /** Offset from cursor (default: { x: 0, y: 0 }) */\n offset?: { x: number; y: number }\n onClose: () => void\n className?: string\n children: (ref: FloatingPanelRef) => React.ReactNode\n zIndex?: number\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function FloatingPanel({\n position, width, height, offset, onClose, className, children, zIndex = 100,\n}: FloatingPanelProps) {\n const ref = useRef<HTMLDivElement>(null)\n const [phase, setPhase] = useState<Phase>('visible')\n const phaseRef = useRef<Phase>('visible')\n phaseRef.current = phase\n const onCloseRef = useRef(onClose)\n onCloseRef.current = onClose\n const expandCallbackRef = useRef<(() => void) | null>(null)\n\n const dismiss = useCallback(() => {\n if (phaseRef.current !== 'visible') return\n setPhase('dismissing')\n setTimeout(() => onCloseRef.current(), 150)\n }, [])\n\n const expandThen = useCallback((callback: () => void) => {\n if (phaseRef.current !== 'visible') return\n expandCallbackRef.current = callback\n setPhase('expanding')\n setTimeout(() => {\n callback()\n onCloseRef.current()\n }, 220)\n }, [])\n\n // Outside click + Escape\n useEffect(() => {\n function handleClick(e: MouseEvent) {\n if (phaseRef.current !== 'visible') return\n if (ref.current && !ref.current.contains(e.target as Node)) {\n // Don't dismiss if clicking another calendar event — let eventClick handle it\n const target = e.target as HTMLElement\n if (target.closest('.fc-event')) return\n dismiss()\n }\n }\n function handleKey(e: KeyboardEvent) {\n if (e.key === 'Escape') dismiss()\n }\n document.addEventListener('mousedown', handleClick)\n document.addEventListener('keydown', handleKey)\n return () => {\n document.removeEventListener('mousedown', handleClick)\n document.removeEventListener('keydown', handleKey)\n }\n }, [dismiss])\n\n // Clamp position to viewport\n const ox = offset?.x ?? 0\n const oy = offset?.y ?? 0\n let x = position.x + ox\n let y = position.y + oy\n if (x + width > window.innerWidth - 12) x = x - width - ox * 2\n if (y + height > window.innerHeight - 12) y = y - height - oy * 2\n if (x < 12) x = 12\n if (y < 12) y = 12\n\n const panelRef: FloatingPanelRef = { dismiss, expandThen }\n\n return createPortal(\n <div ref={ref}\n style={{ position: 'fixed', left: x, top: y, zIndex, transition: phase === 'visible' ? 'left 200ms ease-out, top 200ms ease-out' : undefined }}\n className={`fayz-glass-surface rounded-modal border bg-popover shadow-lg overflow-hidden ${\n phase === 'expanding' ? 'saas-fp-expanding'\n : phase === 'dismissing' ? 'saas-fp-dismissing'\n : 'animate-in fade-in zoom-in-95 duration-150'\n } ${className ?? ''}`}>\n {children(panelRef)}\n </div>,\n document.body,\n )\n}\n","import React, { useState, useRef, useEffect } from 'react'\nimport { X, Pencil, Trash2, Clock, MapPin, User, FileText, DollarSign, Check, AlertTriangle, HandCoins } from 'lucide-react'\nimport { PersonLink } from '@fayz-ai/saas'\nimport { FloatingPanel, type FloatingPanelRef } from './FloatingPanel'\nimport { useAgendaConfig, useAgendaStore } from '../AgendaContext'\nimport { useTranslation } from '@fayz-ai/core'\nimport { isStatusAvailable } from '../types'\nimport type { CalendarBooking } from '../types'\n\ninterface Props {\n booking: CalendarBooking\n position: { x: number; y: number }\n onClose: () => void\n onEdit: (id: string) => void\n}\n\nfunction fmtTime(iso: string) {\n return new Date(iso).toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })\n}\nfunction fmtDate(iso: string) {\n return new Date(iso).toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric' })\n}\nfunction fmtCurrency(amount: number, locale: string, code: string) {\n return new Intl.NumberFormat(locale, { style: 'currency', currency: code }).format(amount)\n}\n\n// Inline status select for the popover\nfunction PopoverStatusSelect({ value, statuses, bookingStartsAt, onChange }: {\n value: string; statuses: Array<{ value: string; label: string; color: string; availableWhen?: string }>\n bookingStartsAt: string; onChange: (v: string) => void\n}) {\n const [open, setOpen] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\n const current = statuses.find((s) => s.value === value)\n\n useEffect(() => {\n if (!open) return\n const h = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false) }\n document.addEventListener('mousedown', h)\n return () => document.removeEventListener('mousedown', h)\n }, [open])\n\n return (\n <div ref={ref} className=\"relative inline-block\">\n <button type=\"button\" onClick={() => setOpen((p) => !p)}\n className=\"inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-[11px] font-medium transition-colors hover:opacity-80\"\n style={{ backgroundColor: (current?.color ?? '#6b7280') + '18', color: current?.color ?? '#6b7280' }}>\n <span className=\"h-2 w-2 rounded-full\" style={{ backgroundColor: current?.color }} />\n {current?.label ?? value}\n <svg className=\"h-3 w-3 opacity-50\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n </svg>\n </button>\n {open && (\n <div className=\"fayz-glass-surface absolute bottom-full left-0 z-50 mb-1 rounded-lg border bg-popover shadow-lg py-1 animate-in fade-in zoom-in-95 duration-100 min-w-[140px]\">\n {statuses.map((s) => {\n const available = isStatusAvailable(s as any, bookingStartsAt)\n return (\n <button key={s.value} type=\"button\" disabled={!available}\n onClick={() => { if (available) { onChange(s.value); setOpen(false) } }}\n className={`flex w-full items-center gap-2 px-3 py-1.5 text-xs transition-colors ${\n !available ? 'opacity-30 cursor-not-allowed' : s.value === value ? 'bg-muted/30' : 'hover:bg-muted/50'\n }`}>\n <span className=\"h-2 w-2 rounded-full shrink-0\" style={{ backgroundColor: s.color }} />\n <span>{s.label}</span>\n </button>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n\nexport function AppointmentPopover({ booking, position, onClose, onEdit }: Props) {\n const t = useTranslation()\n const config = useAgendaConfig()\n const deleteBooking = useAgendaStore((s) => s.deleteBooking)\n const updateStatus = useAgendaStore((s) => s.updateBookingStatus)\n const openModal = useAgendaStore((s) => s.openAppointmentModal)\n const [confirmingDelete, setConfirmingDelete] = useState(false)\n const [deleting, setDeleting] = useState(false)\n const statusConfig = config.statuses.find((s) => s.value === booking.status)\n const color = statusConfig?.color ?? '#6b7280'\n const timeRange = `${fmtTime(booking.startsAt)}${booking.endsAt ? ' – ' + fmtTime(booking.endsAt) : ''}`\n\n async function handleDelete() {\n setDeleting(true)\n try { await deleteBooking(booking.id); onClose() } catch { setDeleting(false) }\n }\n\n return (\n <>\n <FloatingPanel position={position} width={320} height={340} onClose={onClose}>\n {(panel) => (\n <>\n {/* Action bar */}\n <div className=\"flex items-center justify-end gap-0.5 px-3 pt-3 pb-1\">\n {confirmingDelete ? (\n <>\n <span className=\"text-xs text-destructive font-medium mr-auto pl-1\">{t('agenda.appointment.deleteConfirm')}</span>\n <button onClick={() => setConfirmingDelete(false)}\n className=\"rounded px-2 py-0.5 text-[11px] font-medium hover:bg-muted/50 transition-colors\">{t('agenda.appointment.cancel')}</button>\n <button onClick={handleDelete} disabled={deleting}\n className=\"rounded bg-destructive border border-destructive px-2 py-0.5 text-[11px] font-medium text-destructive-foreground hover:bg-destructive/90 shadow-button-primary active:shadow-button-inset disabled:opacity-40 transition-colors\">{deleting ? t('agenda.appointment.deleting') : t('agenda.appointment.confirmDelete')}</button>\n </>\n ) : (\n <>\n <button onClick={() => panel.expandThen(() => onEdit(booking.id))}\n className=\"p-1.5 rounded-full hover:bg-muted transition-colors\" title={t('common.edit')}>\n <Pencil className=\"h-4 w-4 text-muted-foreground\" />\n </button>\n <button onClick={() => setConfirmingDelete(true)}\n className=\"p-1.5 rounded-full hover:bg-destructive/10 transition-colors\" title={t('common.delete')}>\n <Trash2 className=\"h-4 w-4 text-muted-foreground hover:text-destructive\" />\n </button>\n <button onClick={panel.dismiss} className=\"p-1.5 rounded-full hover:bg-muted transition-colors\">\n <X className=\"h-4 w-4 text-muted-foreground\" />\n </button>\n </>\n )}\n </div>\n\n {/* Content */}\n <div className=\"px-5 pb-5 space-y-3\">\n <div className=\"flex items-start gap-3\">\n <span className=\"mt-1.5 h-3 w-3 rounded shrink-0\" style={{ backgroundColor: color }} />\n <div className=\"min-w-0\">\n {/* Client agendas link to the person; simple events (no client\n capability) render the free-text title as a plain heading —\n booking.clientName carries the event title in that model. */}\n {config.capabilities.client ? (\n <PersonLink personId={booking.clientId} name={booking.clientName ?? 'Unknown'} className=\"text-base\" />\n ) : (\n <p className=\"text-base font-medium truncate\">{booking.clientName || t('agenda.appointment.untitled')}</p>\n )}\n <p className=\"text-sm text-muted-foreground mt-0.5\">{fmtDate(booking.startsAt)} &middot; {timeRange}</p>\n </div>\n </div>\n\n {booking.services && booking.services.length > 0 && (\n <div className=\"flex items-start gap-3\">\n <Clock className=\"h-4 w-4 mt-0.5 text-muted-foreground shrink-0\" />\n <div className=\"text-sm space-y-0.5\">\n {booking.services.map((svc) => (\n <p key={svc.id}>{svc.name} <span className=\"text-muted-foreground\">({svc.durationMinutes}min)</span></p>\n ))}\n </div>\n </div>\n )}\n\n {config.capabilities.professional && booking.professionalName && (\n <div className=\"flex items-center gap-3\">\n <User className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <span className=\"text-sm\">{booking.professionalName}</span>\n </div>\n )}\n\n {booking.locationName && (\n <div className=\"flex items-center gap-3\">\n <MapPin className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <span className=\"text-sm\">{booking.locationName}</span>\n </div>\n )}\n\n {booking.notes && (\n <div className=\"flex items-start gap-3\">\n <FileText className=\"h-4 w-4 mt-0.5 text-muted-foreground shrink-0\" />\n <p className=\"text-sm text-muted-foreground\">{booking.notes}</p>\n </div>\n )}\n\n {booking.orderTotal != null && booking.orderTotal > 0 && (() => {\n const total = fmtCurrency(booking.orderTotal, config.currency.locale, config.currency.code)\n const ps = booking.paymentStatus ?? 'none'\n const hasFinancial = config.modules.financial && booking.orderId\n\n // No financial module — just show total\n if (!hasFinancial) {\n return (\n <div className=\"pt-2 border-t fayz-glass-divider flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground\">{t('agenda.appointment.total')}</span>\n <span className=\"font-medium\">{total}</span>\n </div>\n )\n }\n\n const badgeConfig: Record<string, { icon: React.ElementType; bg: string; text: string; label: string }> = {\n none: { icon: HandCoins, bg: 'bg-warning/10 hover:bg-warning/15', text: 'text-warning', label: `${total} · ${t('agenda.payment.collect')}` },\n pending: { icon: Clock, bg: 'bg-warning/10 hover:bg-warning/15', text: 'text-warning', label: `${total} · ${t('agenda.payment.pending')}` },\n partial: { icon: DollarSign, bg: 'bg-warning/10 hover:bg-warning/15', text: 'text-warning', label: `${total} · ${t('agenda.payment.partial')}` },\n paid: { icon: Check, bg: 'bg-success/10 hover:bg-success/15', text: 'text-success', label: `${total} · ${t('agenda.payment.paid')}` },\n overdue: { icon: AlertTriangle, bg: 'bg-destructive/10 hover:bg-destructive/15', text: 'text-destructive', label: `${total} · ${t('agenda.payment.overdue')}` },\n cancelled: { icon: X, bg: 'bg-muted hover:bg-muted/80', text: 'text-muted-foreground', label: `${total} · ${t('agenda.payment.cancelled')}` },\n }\n const cfg = badgeConfig[ps] ?? badgeConfig.none\n const StatusIcon = cfg.icon\n\n return (\n <div className=\"pt-2 border-t fayz-glass-divider flex items-center justify-between\">\n <span className=\"text-xs text-muted-foreground\">{t('agenda.appointment.total')}</span>\n <button\n type=\"button\"\n onClick={() => { onClose(); openModal('edit', { bookingId: booking.id, initialTab: 'financial' }) }}\n className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium transition-colors ${cfg.bg} ${cfg.text}`}\n >\n <StatusIcon className=\"h-3 w-3\" />\n {cfg.label}\n </button>\n </div>\n )\n })()}\n\n {/* Status workflow — hidden for simple events (no status capability). */}\n {config.capabilities.status && (\n <div className=\"pt-2 border-t fayz-glass-divider\">\n <PopoverStatusSelect\n value={booking.status}\n statuses={config.statuses}\n bookingStartsAt={booking.startsAt}\n onChange={(v) => { updateStatus(booking.id, v); onClose() }}\n />\n </div>\n )}\n </div>\n </>\n )}\n </FloatingPanel>\n </>\n )\n}\n","import React, { useRef, useState, useMemo } from 'react'\nimport { createPortal } from 'react-dom'\nimport { Pencil, Trash2, Check } from 'lucide-react'\nimport { FloatingPanel } from './FloatingPanel'\nimport { useAgendaConfig, useAgendaStore } from '../AgendaContext'\nimport { useTranslation } from '@fayz-ai/core'\nimport { isStatusAvailable } from '../types'\nimport type { CalendarBooking } from '../types'\n\n// ---------------------------------------------------------------------------\n// Tooltip — portaled to body\n// ---------------------------------------------------------------------------\n\nfunction Tooltip({ anchor, label }: { anchor: DOMRect; label: string }) {\n return createPortal(\n <div style={{ position: 'fixed', left: anchor.left + anchor.width / 2, top: anchor.bottom + 6, transform: 'translateX(-50%)', zIndex: 120 }}\n className=\"pointer-events-none\">\n <div className=\"rounded-md bg-foreground text-background px-2 py-0.5 text-[11px] font-medium whitespace-nowrap shadow-lg\">\n {label}\n </div>\n </div>,\n document.body,\n )\n}\n\n// ---------------------------------------------------------------------------\n// Status dot with portaled tooltip\n// ---------------------------------------------------------------------------\n\nfunction StatusDot({ color, label, isActive, disabled, onClick }: {\n color: string; label: string; isActive: boolean; disabled?: boolean; onClick: () => void\n}) {\n const [hover, setHover] = useState(false)\n const btnRef = useRef<HTMLButtonElement>(null)\n const [rect, setRect] = useState<DOMRect | null>(null)\n\n return (\n <>\n <button ref={btnRef} type=\"button\" onClick={disabled ? undefined : onClick} disabled={disabled}\n onMouseEnter={() => { setHover(true); if (btnRef.current) setRect(btnRef.current.getBoundingClientRect()) }}\n onMouseLeave={() => setHover(false)}\n className={`flex h-7 w-7 items-center justify-center rounded-full transition-all ${\n disabled ? 'opacity-25 cursor-not-allowed' : isActive ? 'ring-2 ring-offset-2 ring-offset-popover' : 'hover:scale-110'\n }`}\n style={{ backgroundColor: color, ['--tw-ring-color' as any]: isActive ? color : undefined }}>\n {isActive && <Check className=\"h-3.5 w-3.5 text-white\" strokeWidth={2.5} />}\n </button>\n {hover && rect && <Tooltip anchor={rect} label={label} />}\n </>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Context Menu\n// ---------------------------------------------------------------------------\n\ninterface Props {\n booking: CalendarBooking\n position: { x: number; y: number }\n onClose: () => void\n onEdit: (id: string) => void\n}\n\nexport function EventContextMenu({ booking, position, onClose, onEdit }: Props) {\n const t = useTranslation()\n const config = useAgendaConfig()\n const updateStatus = useAgendaStore((s) => s.updateBookingStatus)\n const deleteBooking = useAgendaStore((s) => s.deleteBooking)\n const [confirming, setConfirming] = useState(false)\n const [deleting, setDeleting] = useState(false)\n\n async function handleDelete() {\n setDeleting(true)\n try { await deleteBooking(booking.id); onClose() } catch { setDeleting(false) }\n }\n\n return (\n <FloatingPanel position={position} width={230} height={180} offset={{ x: 4, y: 4 }} onClose={onClose} zIndex={110}>\n {(panel) => (\n <>\n <div className=\"py-1\">\n <button onClick={() => panel.expandThen(() => onEdit(booking.id))}\n className=\"flex w-full items-center gap-3 px-4 py-2 text-sm hover:bg-muted/50 transition-colors\">\n <Pencil className=\"h-4 w-4 text-muted-foreground\" /> {t('agenda.contextMenu.edit')}\n </button>\n {confirming ? (\n <div className=\"flex items-center justify-between px-4 py-2\">\n <span className=\"text-xs text-destructive font-medium\">{t('agenda.appointment.deleteConfirm')}</span>\n <div className=\"flex items-center gap-1.5\">\n <button onClick={() => setConfirming(false)}\n className=\"rounded px-2 py-0.5 text-[11px] font-medium hover:bg-muted/50 transition-colors\">{t('agenda.appointment.cancel')}</button>\n <button onClick={handleDelete} disabled={deleting}\n className=\"rounded bg-destructive border border-destructive px-2 py-0.5 text-[11px] font-medium text-destructive-foreground hover:bg-destructive/90 shadow-button-primary active:shadow-button-inset disabled:opacity-40 transition-colors\">{deleting ? t('agenda.appointment.deleting') : t('agenda.appointment.confirmDelete')}</button>\n </div>\n </div>\n ) : (\n <button onClick={() => setConfirming(true)}\n className=\"flex w-full items-center gap-3 px-4 py-2 text-sm hover:bg-muted/50 transition-colors text-destructive\">\n <Trash2 className=\"h-4 w-4\" /> {t('agenda.contextMenu.delete')}\n </button>\n )}\n </div>\n\n {/* Status workflow — hidden for simple events (no status capability). */}\n {config.capabilities.status && (\n <div className=\"border-t px-4 py-3\">\n <p className=\"text-[11px] font-medium text-muted-foreground mb-2\">{t('agenda.contextMenu.changeStatus')}</p>\n <div className=\"flex items-center gap-1.5\">\n {config.statuses.map((s) => {\n const available = isStatusAvailable(s, booking.startsAt)\n return (\n <StatusDot key={s.value} color={s.color} label={available ? s.label : `${s.label} ${t('agenda.contextMenu.notAvailable')}`}\n isActive={booking.status === s.value}\n disabled={!available}\n onClick={() => { if (available) { updateStatus(booking.id, s.value); panel.dismiss() } }} />\n )\n })}\n </div>\n </div>\n )}\n </>\n )}\n </FloatingPanel>\n )\n}\n","import React, { useMemo } from 'react'\nimport { formatCurrency, useTranslation, getCurrentLocale } from '@fayz-ai/core'\nimport type { CalendarBooking } from '../types'\n\n// ---------------------------------------------------------------------------\n// Mobile agenda list — a thumb-friendly, date-grouped list of upcoming items.\n// Rendered on <md viewports instead of the FullCalendar grid. Each row shows a\n// category/status dot, the title, the time, and (for finance-style events) the\n// amount. Fed straight from the store bookings so it works for any seeded app.\n// ---------------------------------------------------------------------------\n\nfunction startOfDay(d: Date): Date {\n const x = new Date(d)\n x.setHours(0, 0, 0, 0)\n return x\n}\n\nfunction timeLabel(iso: string): string {\n const d = new Date(iso)\n return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`\n}\n\nexport interface AgendaMobileListProps {\n bookings: CalendarBooking[]\n statusColors: Record<string, string>\n currencyCode: string\n onSelect: (booking: CalendarBooking) => void\n}\n\nexport function AgendaMobileList({ bookings, statusColors, currencyCode, onSelect }: AgendaMobileListProps) {\n const t = useTranslation()\n const locale = getCurrentLocale() === 'pt-BR' ? 'pt-BR' : 'en'\n\n const groups = useMemo(() => {\n const todayStart = startOfDay(new Date()).getTime()\n const sorted = bookings\n .filter((b) => !!b.startsAt)\n .slice()\n .sort((a, b) => (a.startsAt < b.startsAt ? -1 : a.startsAt > b.startsAt ? 1 : 0))\n const map = new Map<string, CalendarBooking[]>()\n for (const b of sorted) {\n const day = startOfDay(new Date(b.startsAt))\n if (day.getTime() < todayStart) continue // upcoming only\n const key = day.toISOString().slice(0, 10)\n const list = map.get(key) ?? []\n list.push(b)\n map.set(key, list)\n }\n return Array.from(map.entries()).map(([key, items]) => ({ key, date: new Date(key + 'T00:00:00'), items }))\n }, [bookings])\n\n function dayLabel(date: Date): string {\n const today = startOfDay(new Date())\n const diff = Math.round((startOfDay(date).getTime() - today.getTime()) / 86400000)\n if (diff === 0) return t('agenda.list.today')\n if (diff === 1) return t('agenda.list.tomorrow')\n return date.toLocaleDateString(locale, { weekday: 'long', day: 'numeric', month: 'long' })\n }\n\n if (groups.length === 0) {\n return (\n <div className=\"flex-1 flex flex-col items-center justify-center px-6 py-16 text-center text-muted-foreground\">\n <p className=\"text-sm\">{t('agenda.list.empty')}</p>\n </div>\n )\n }\n\n return (\n <div className=\"flex-1 overflow-y-auto px-3 py-3 space-y-5\">\n {groups.map((g) => (\n <div key={g.key}>\n <h3 className=\"px-1 pb-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n {dayLabel(g.date)}\n </h3>\n <div className=\"space-y-1.5\">\n {g.items.map((b) => {\n const color = statusColors[b.status] ?? '#6b7280'\n const hasAmount = typeof b.orderTotal === 'number' && b.orderTotal > 0\n return (\n <button\n key={b.id}\n onClick={() => onSelect(b)}\n className=\"flex w-full items-center gap-3 rounded-lg border bg-card px-3 py-2.5 text-left shadow-sm transition-colors active:bg-muted/50\"\n >\n <span className=\"h-2.5 w-2.5 shrink-0 rounded-full\" style={{ backgroundColor: color }} />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-foreground\">{b.clientName ?? '—'}</p>\n <p className=\"text-xs text-muted-foreground\">{timeLabel(b.startsAt)}</p>\n </div>\n {hasAmount && (\n <span className=\"shrink-0 text-sm font-semibold tabular-nums text-foreground\">\n {formatCurrency(b.orderTotal, currencyCode)}\n </span>\n )}\n </button>\n )\n })}\n </div>\n </div>\n ))}\n </div>\n )\n}\n","import React, { useRef, useEffect, useCallback, useMemo, useState } from 'react'\nimport { injectCalendarStyles } from '../calendar-styles'\nimport FullCalendar from '@fullcalendar/react'\nimport dayGridPlugin from '@fullcalendar/daygrid'\nimport timeGridPlugin from '@fullcalendar/timegrid'\nimport resourceTimeGridPlugin from '@fullcalendar/resource-timegrid'\nimport interactionPlugin from '@fullcalendar/interaction'\nimport listPlugin from '@fullcalendar/list'\nimport ptBrLocale from '@fullcalendar/core/locales/pt-br'\nimport type { EventInput, EventClickArg, DateSelectArg, EventDropArg } from '@fullcalendar/core'\nimport { ChevronLeft, ChevronRight, Plus, ChevronDown, Settings } from 'lucide-react'\nimport { usePluginPrefs } from '@fayz-ai/saas'\nimport { getCurrentLocale } from '@fayz-ai/core'\nimport { useTranslation, useDataChanged } from '@fayz-ai/core'\nimport { useAgendaConfig, useAgendaStore } from '../AgendaContext'\nimport { useAgendaSettings } from '../hooks/useAgendaSettings'\nimport { MiniCalendar } from '../components/MiniCalendar'\nimport { AppointmentModal } from '../components/AppointmentModal'\nimport { AppointmentPopover } from '../components/AppointmentPopover'\nimport { PersonLink } from '@fayz-ai/saas'\nimport { EventContextMenu } from '../components/EventContextMenu'\nimport { AgendaMobileList } from '../components/AgendaMobileList'\nimport { ConfirmDialog } from '@fayz-ai/ui'\nimport { Button } from '@fayz-ai/ui'\nimport type { CalendarBooking, Schedule } from '../types'\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction bookingToEvent(booking: CalendarBooking, statusColors: Record<string, string>): EventInput {\n const color = statusColors[booking.status] ?? '#6b7280'\n const serviceNames = booking.services?.map((s) => s.name).join(', ') ?? ''\n return {\n id: booking.id,\n resourceId: booking.professionalId ?? undefined,\n title: booking.clientName ?? 'Unknown',\n start: booking.startsAt,\n end: booking.endsAt ?? undefined,\n backgroundColor: color + '30',\n borderColor: color,\n textColor: color,\n extendedProps: { booking, serviceNames },\n }\n}\n\n/**\n * Generate FullCalendar background events showing unavailable time.\n * For each day, creates background blocks for the gaps OUTSIDE working hours\n * within the visible business hours window. This grays out non-working time.\n */\nfunction generateAvailabilityEvents(\n schedules: Schedule[],\n professionals: { id: string }[],\n dateRange: { start: string; end: string } | null,\n businessHours?: { startTime: string; endTime: string },\n locationMap?: Map<string, string>,\n): EventInput[] {\n if (!dateRange || schedules.length === 0) return []\n\n const bgEvents: EventInput[] = []\n const startDate = new Date(dateRange.start)\n const endDate = new Date(dateRange.end)\n const bizStart = businessHours?.startTime ?? '08:00'\n const bizEnd = businessHours?.endTime ?? '20:00'\n\n // Group schedules by assignee\n const byAssignee = new Map<string, Schedule[]>()\n for (const s of schedules) {\n const aid = s.assigneeId\n if (!aid) continue\n const list = byAssignee.get(aid) ?? []\n list.push(s)\n byAssignee.set(aid, list)\n }\n\n function timeToMinutes(t: string): number {\n const [h, m] = t.split(':').map(Number)\n return h * 60 + m\n }\n\n function minutesToTime(m: number): string {\n return `${String(Math.floor(m / 60)).padStart(2, '0')}:${String(m % 60).padStart(2, '0')}`\n }\n\n const bizStartMin = timeToMinutes(bizStart)\n const bizEndMin = timeToMinutes(bizEnd)\n\n for (const prof of professionals) {\n const profSchedules = byAssignee.get(prof.id) ?? []\n\n // Separate weekly and date-specific schedules\n const weekly = profSchedules.filter((s) => s.dayOfWeek != null && !s.specificDate)\n const exceptions = profSchedules.filter((s) => s.specificDate != null)\n const exceptionDates = new Set(exceptions.map((s) => s.specificDate!))\n\n const current = new Date(startDate)\n while (current < endDate) {\n const dateStr = current.toISOString().slice(0, 10)\n const dayOfWeek = current.getDay()\n\n // Get working periods for this day\n let daySchedules: Schedule[]\n if (exceptionDates.has(dateStr)) {\n daySchedules = exceptions.filter((s) => s.specificDate === dateStr && s.isActive)\n } else {\n daySchedules = weekly.filter((s) => s.dayOfWeek === dayOfWeek && s.isActive)\n }\n\n // Convert working periods to sorted minute ranges, preserving locationId\n const workRanges = daySchedules\n .map((s) => {\n const locId = s.locationId ?? (s.metadata?.locationId as string | undefined)\n return {\n start: timeToMinutes(s.startsAt),\n end: timeToMinutes(s.endsAt),\n locationName: locId && locationMap ? locationMap.get(locId) : undefined,\n }\n })\n .sort((a, b) => a.start - b.start)\n\n // Compute unavailable gaps within business hours\n let cursor = bizStartMin\n for (const range of workRanges) {\n const availStart = Math.max(range.start, bizStartMin)\n const availEnd = Math.min(range.end, bizEndMin)\n\n // Gap before this working range = unavailable\n if (cursor < availStart) {\n bgEvents.push({\n resourceId: prof.id,\n start: dateStr + 'T' + minutesToTime(cursor) + ':00',\n end: dateStr + 'T' + minutesToTime(availStart) + ':00',\n display: 'background',\n classNames: ['fc-unavailable-bg'],\n })\n }\n\n // Location label on available range\n if (availStart < availEnd && range.locationName) {\n bgEvents.push({\n id: `loc-${prof.id}-${dateStr}-${minutesToTime(availStart)}`,\n resourceId: prof.id,\n start: dateStr + 'T' + minutesToTime(availStart) + ':00',\n end: dateStr + 'T' + minutesToTime(availStart + 20) + ':00',\n title: range.locationName,\n display: 'auto',\n editable: false,\n backgroundColor: 'transparent',\n borderColor: 'transparent',\n textColor: '#a3a3a3',\n classNames: ['fc-location-label'],\n extendedProps: { isLocationLabel: true },\n })\n }\n\n cursor = Math.max(cursor, availEnd)\n }\n\n // Gap after last working range = unavailable\n if (cursor < bizEndMin) {\n bgEvents.push({\n resourceId: prof.id,\n start: dateStr + 'T' + minutesToTime(cursor) + ':00',\n end: dateStr + 'T' + minutesToTime(bizEndMin) + ':00',\n display: 'background',\n classNames: ['fc-unavailable-bg'],\n })\n }\n\n\n current.setDate(current.getDate() + 1)\n }\n }\n\n return bgEvents\n}\n\n// ---------------------------------------------------------------------------\n// Loading skeleton — mimics the resource-timegrid-week layout\n// ---------------------------------------------------------------------------\n\nfunction CalendarSkeleton({ profCount = 2 }: { profCount?: number }) {\n const days = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']\n const hours = ['07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00']\n\n return (\n <div className=\"flex-1 overflow-hidden animate-pulse\">\n <div className=\"flex border-b\" style={{ paddingLeft: 56 }}>\n {Array.from({ length: profCount }).map((_, pi) => (\n <div key={pi} className=\"flex-1 border-r last:border-r-0 py-2 px-3\">\n <div className=\"flex items-center justify-center gap-2\">\n <div className=\"h-6 w-6 rounded-full bg-muted\" />\n <div className=\"h-3 w-20 rounded bg-muted\" />\n </div>\n </div>\n ))}\n </div>\n <div className=\"flex border-b\" style={{ paddingLeft: 56 }}>\n {Array.from({ length: profCount }).map((_, pi) => (\n <div key={pi} className=\"flex-1 flex border-r last:border-r-0\">\n {days.map((d) => (\n <div key={d} className=\"flex-1 py-1.5 text-center\">\n <span className=\"text-[10px] text-muted-foreground/40\">{d}</span>\n </div>\n ))}\n </div>\n ))}\n </div>\n <div className=\"relative\">\n {hours.map((h) => (\n <div key={h} className=\"flex border-b border-border/30\" style={{ height: 50 }}>\n <div className=\"w-14 shrink-0 pr-2 text-right\">\n <span className=\"text-[10px] text-muted-foreground/30\">{h}</span>\n </div>\n <div className=\"flex-1 flex\">\n {Array.from({ length: profCount * 7 }).map((_, ci) => (\n <div key={ci} className={`flex-1 border-r border-border/20 ${Math.floor(ci / 7) % 2 === 1 ? 'bg-muted/20' : ''}`} />\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n )\n}\n\n// Resource views — one column per professional. Used when the app has staff.\nconst RESOURCE_VIEW_OPTIONS = [\n { key: 'resourceTimeGridDay', labelKey: 'agenda.calendar.viewDay' },\n { key: 'resourceTimeGridWeek', labelKey: 'agenda.calendar.viewWeek' },\n { key: 'dayGridMonth', labelKey: 'agenda.calendar.viewMonth' },\n] as const\n\n// Non-resource variants — used when there are no professionals/resources (e.g. a\n// personal-finance agenda). A resource timegrid renders an EMPTY grid with zero\n// resource columns and drops events that have no resourceId, so those apps fall\n// back to a plain month/day/week calendar.\nconst PLAIN_VIEW_OPTIONS = [\n { key: 'timeGridDay', labelKey: 'agenda.calendar.viewDay' },\n { key: 'timeGridWeek', labelKey: 'agenda.calendar.viewWeek' },\n { key: 'dayGridMonth', labelKey: 'agenda.calendar.viewMonth' },\n { key: 'listMonth', labelKey: 'agenda.calendar.viewList' },\n] as const\n\n// Sentinel view key for the thumb-friendly mobile agenda list (AgendaMobileList),\n// which is NOT a FullCalendar view. Selected by default on <md so B2C opens on the\n// list; picking any grid option (Dia/Semana/Mês) mounts the real calendar instead.\nconst MOBILE_LIST_VIEW = '__mobileList__'\n\n/** Collapse a resource view to a plain month calendar when there are no resources. */\nfunction viewForNoResources(view: string): string {\n return view.startsWith('resource') ? 'dayGridMonth' : view\n}\n\n/** Promote a plain timegrid to its resource variant when the app has resources. */\nfunction viewForResources(view: string): string {\n if (view === 'timeGridWeek') return 'resourceTimeGridWeek'\n if (view === 'timeGridDay') return 'resourceTimeGridDay'\n return view\n}\n\n/** Small viewport (<md) → render the thumb-friendly agenda list instead of the grid. */\nfunction useIsMobile(): boolean {\n const [isMobile, setIsMobile] = useState(() =>\n typeof window !== 'undefined' && window.matchMedia('(max-width: 767px)').matches)\n useEffect(() => {\n if (typeof window === 'undefined') return\n const mq = window.matchMedia('(max-width: 767px)')\n const onChange = () => setIsMobile(mq.matches)\n mq.addEventListener('change', onChange)\n return () => mq.removeEventListener('change', onChange)\n }, [])\n return isMobile\n}\n\n// ---------------------------------------------------------------------------\n// Calendar View\n// ---------------------------------------------------------------------------\n\nexport function CalendarView() {\n injectCalendarStyles()\n const config = useAgendaConfig()\n const t = useTranslation()\n const currentLocale = getCurrentLocale()\n const fcLocale = currentLocale === 'pt-BR' ? ptBrLocale : undefined\n const calendarRef = useRef<FullCalendar>(null)\n const prefs = usePluginPrefs('agenda', { calendarView: config.defaultCalendarView ?? 'resourceTimeGridWeek' })\n const agendaSettings = useAgendaSettings()\n const effectiveBusinessHours = {\n startTime: agendaSettings.startTime,\n endTime: agendaSettings.endTime,\n }\n\n const bookings = useAgendaStore((s) => s.bookings)\n const bookingsLoading = useAgendaStore((s) => s.bookingsLoading)\n const professionals = useAgendaStore((s) => s.professionals)\n const professionalsLoading = useAgendaStore((s) => s.professionalsLoading)\n const currentView = useAgendaStore((s) => s.currentView)\n const selectedProfIds = useAgendaStore((s) => s.selectedProfessionalIds)\n const selectedStatuses = useAgendaStore((s) => s.selectedStatuses)\n const schedules = useAgendaStore((s) => s.schedules)\n const fetchBookings = useAgendaStore((s) => s.fetchBookings)\n const fetchProfessionals = useAgendaStore((s) => s.fetchProfessionals)\n const fetchLocations = useAgendaStore((s) => s.fetchLocations)\n const storeLocations = useAgendaStore((s) => s.locations)\n const fetchSchedules = useAgendaStore((s) => s.fetchSchedules)\n const rescheduleBooking = useAgendaStore((s) => s.rescheduleBooking)\n const setView = useAgendaStore((s) => s.setView)\n const setFilters = useAgendaStore((s) => s.setFilters)\n const _openModal = useAgendaStore((s) => s.openAppointmentModal)\n const closeModal = useAgendaStore((s) => s.closeAppointmentModal)\n const modalState = useAgendaStore((s) => s.appointmentModal)\n\n // Resource-capable = the app has professionals/staff. When it doesn't (e.g. a\n // personal-finance agenda), resource views render empty, so we force plain\n // (non-resource) views and default to a month calendar.\n const isMobile = useIsMobile()\n const resourceCapable = professionals.length > 0\n const viewOptions = resourceCapable ? RESOURCE_VIEW_OPTIONS : PLAIN_VIEW_OPTIONS\n\n // Mobile (<md) has its own view selection, independent of the desktop pref: it\n // defaults to the thumb-friendly list and lets the user switch to any grid view\n // (Dia/Semana/Mês) without changing the desktop's stored calendarView. The list\n // sentinel replaces FullCalendar's own listMonth so mobile always gets the rich\n // AgendaMobileList, and a list option is offered even for resource apps.\n const [mobileView, setMobileView] = useState<string>(MOBILE_LIST_VIEW)\n const mobileViewOptions = useMemo(\n () => [\n ...viewOptions.filter((o) => o.key !== 'listMonth'),\n { key: MOBILE_LIST_VIEW, labelKey: 'agenda.calendar.viewList' },\n ],\n [viewOptions],\n )\n const mobileGridActive = isMobile && mobileView !== MOBILE_LIST_VIEW\n\n const [selectedBooking, setSelectedBooking] = useState<CalendarBooking | null>(null)\n const [popoverAnchor, setPopoverAnchor] = useState<{ x: number; y: number } | null>(null)\n const [popoverVisible, _setPopoverVisible] = useState(false)\n const popoverVisibleRef = useRef(false)\n const setPopoverVisible = useCallback((v: boolean) => { popoverVisibleRef.current = v; _setPopoverVisible(v) }, [])\n const [contextMenu, setContextMenu] = useState<{ booking: CalendarBooking; x: number; y: number } | null>(null)\n const [contextMenuVisible, _setContextMenuVisible] = useState(false)\n const contextMenuVisibleRef = useRef(false)\n const setContextMenuVisible = useCallback((v: boolean) => { contextMenuVisibleRef.current = v; _setContextMenuVisible(v) }, [])\n const [scheduleConfirm, setScheduleConfirm] = useState<{ onConfirm: () => void } | null>(null)\n const [calendarTitle, setCalendarTitle] = useState('')\n const [selectedDate, setSelectedDate] = useState(new Date())\n const [profSectionOpen, setProfSectionOpen] = useState(true)\n const [statusSectionOpen, setStatusSectionOpen] = useState(false)\n const [visibleRange, setVisibleRange] = useState<{ start: string; end: string } | null>(null)\n\n // Wrap openModal to always dismiss popover/context menu first\n const openModal: typeof _openModal = useCallback((...args) => {\n setPopoverVisible(false); setSelectedBooking(null); setPopoverAnchor(null)\n setContextMenuVisible(false); setContextMenu(null)\n _openModal(...args)\n }, [_openModal])\n\n const statusColors = useMemo(() => {\n const map: Record<string, string> = {}\n for (const s of config.statuses) map[s.value] = s.color\n return map\n }, [config.statuses])\n\n useEffect(() => {\n fetchProfessionals(); fetchSchedules()\n if (config.modules.locationSelection) fetchLocations()\n }, [])\n\n // Keep the view consistent with resource-capability, in case a stale/shared\n // pref selected the wrong variant. No resources → a resource view is an empty\n // grid that drops the seeded events; resources → a plain timegrid loses the\n // per-professional columns.\n useEffect(() => {\n const api = calendarRef.current?.getApi()\n if (!api) return\n if (!resourceCapable && currentView.startsWith('resource')) {\n api.changeView('dayGridMonth')\n } else if (resourceCapable && (currentView === 'timeGridWeek' || currentView === 'timeGridDay')) {\n api.changeView(viewForResources(currentView))\n }\n }, [resourceCapable, currentView])\n\n // Mobile renders the agenda list (no FullCalendar), so the grid's datesSet —\n // which normally drives fetchBookings — never fires. Fetch a wide upcoming\n // window directly so the list has data.\n useEffect(() => {\n if (!isMobile) return\n const start = new Date(); start.setHours(0, 0, 0, 0); start.setDate(start.getDate() - 1)\n const end = new Date(start); end.setDate(end.getDate() + 91)\n fetchBookings({ start: start.toISOString(), end: end.toISOString() })\n }, [isMobile, fetchBookings])\n\n // A booking created outside the grid — the assistant, the public page,\n // another device — repaints the calendar it belongs to. Without this the\n // manager who just said \"agenda a Maria amanhã às 10\" still sees yesterday's\n // grid and reloads the tab by hand.\n useDataChanged({}, () => {\n if (visibleRange) {\n fetchBookings(visibleRange)\n return\n }\n const start = new Date(); start.setHours(0, 0, 0, 0); start.setDate(start.getDate() - 1)\n const end = new Date(start); end.setDate(end.getDate() + 91)\n fetchBookings({ start: start.toISOString(), end: end.toISOString() })\n }, [visibleRange, fetchBookings])\n\n const resources = useMemo(() => {\n const filtered = selectedProfIds.length > 0\n ? professionals.filter((p) => selectedProfIds.includes(p.id))\n : professionals\n return filtered.map((p) => ({\n id: p.id, title: p.name,\n extendedProps: { avatarUrl: p.avatarUrl, locationName: p.locationName },\n }))\n }, [professionals, selectedProfIds])\n\n const bookingEvents = useMemo(() =>\n bookings.map((b) => bookingToEvent(b, statusColors)), [bookings, statusColors])\n\n // Merge static config locations with dynamically fetched locations\n const allLocations = useMemo(() => {\n const map = new Map<string, string>()\n for (const loc of config.locations) map.set(loc.id, loc.name)\n for (const loc of storeLocations) map.set(loc.id, loc.name)\n return map\n }, [config.locations, storeLocations])\n\n const locationMap = useMemo(() => {\n if (!config.modules.locationSelection || allLocations.size === 0) return undefined\n return allLocations\n }, [config.modules.locationSelection, allLocations])\n\n const availabilityEvents = useMemo(() =>\n generateAvailabilityEvents(schedules, professionals, visibleRange, effectiveBusinessHours, locationMap),\n [schedules, professionals, visibleRange, effectiveBusinessHours, locationMap])\n\n const events = useMemo(() =>\n [...bookingEvents, ...availabilityEvents], [bookingEvents, availabilityEvents])\n\n const storedView = prefs.get('calendarView')\n const effectiveInitialView = resourceCapable ? viewForResources(storedView) : viewForNoResources(storedView)\n\n // ── Calendar handlers ──\n const handleDatesSet = useCallback((arg: { startStr: string; endStr: string; view: { title: string; type: string } }) => {\n setCalendarTitle(arg.view.title)\n setView(arg.view.type)\n setVisibleRange({ start: arg.startStr, end: arg.endStr })\n fetchBookings({ start: arg.startStr, end: arg.endStr })\n }, [fetchBookings, setView])\n\n // Double-click → open edit directly\n // Right-click → context menu\n const handleEventDidMount = useCallback((arg: { event: any; el: HTMLElement }) => {\n const booking = arg.event.extendedProps?.booking as CalendarBooking | undefined\n if (booking) arg.el.setAttribute('data-booking-id', booking.id)\n arg.el.addEventListener('dblclick', (e) => {\n e.preventDefault()\n e.stopPropagation()\n skipClickRef.current = true\n const booking = arg.event.extendedProps.booking as CalendarBooking\n setSelectedBooking(null)\n setPopoverAnchor(null)\n setContextMenu(null)\n openModal('edit', { bookingId: booking.id })\n })\n arg.el.addEventListener('contextmenu', (e) => {\n e.preventDefault()\n const booking = arg.event.extendedProps.booking as CalendarBooking\n const menuW = 210, menuH = 200\n let x = e.clientX + 4\n let y = e.clientY + 4\n if (x + menuW > window.innerWidth - 12) x = x - menuW\n if (y + menuH > window.innerHeight - 12) y = y - menuH\n setContextMenu({ booking, x, y })\n setContextMenuVisible(true)\n setSelectedBooking(null)\n setPopoverAnchor(null)\n })\n }, [])\n\n // Flag to suppress single-click after a double-click\n const skipClickRef = useRef(false)\n\n // Hover timer — show popover after 4s hover on a booking event\n const hoverTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const handleEventMouseEnter = useCallback((arg: { event: any; el: HTMLElement }) => {\n if (arg.event.display === 'background') return\n if (arg.event.extendedProps?.isLocationLabel) return\n const booking = arg.event.extendedProps.booking as CalendarBooking\n if (!booking) return\n\n hoverTimerRef.current = setTimeout(() => {\n const rect = arg.el.getBoundingClientRect()\n const popW = 320, popH = 340\n let x = rect.right + 8\n let y = rect.top + rect.height / 2 - popH / 2\n if (x + popW > window.innerWidth - 16) x = rect.left - popW - 8\n if (x < 16) x = Math.max(16, rect.left + rect.width / 2 - popW / 2)\n if (y + popH > window.innerHeight - 16) y = window.innerHeight - popH - 16\n if (y < 16) y = 16\n setSelectedBooking(booking)\n setPopoverAnchor({ x, y })\n setPopoverVisible(true)\n }, 3000)\n }, [])\n\n const handleEventMouseLeave = useCallback(() => {\n if (hoverTimerRef.current) {\n clearTimeout(hoverTimerRef.current)\n hoverTimerRef.current = null\n }\n }, [])\n\n // Single click — open popover instantly, or slide to new position if already open\n const handleEventClick = useCallback((arg: EventClickArg) => {\n if (skipClickRef.current) { skipClickRef.current = false; return }\n // Ignore clicks on background availability events and location labels\n if (arg.event.display === 'background') return\n if (arg.event.extendedProps?.isLocationLabel) return\n setContextMenu(null); setContextMenuVisible(false)\n const booking = arg.event.extendedProps.booking as CalendarBooking\n if (!booking) return\n const rect = arg.el.getBoundingClientRect()\n const popW = 320, popH = 340\n let x = rect.right + 8\n let y = rect.top + rect.height / 2 - popH / 2\n if (x + popW > window.innerWidth - 16) x = rect.left - popW - 8\n if (x < 16) x = Math.max(16, rect.left + rect.width / 2 - popW / 2)\n if (y + popH > window.innerHeight - 16) y = window.innerHeight - popH - 16\n if (y < 16) y = 16\n // Always update — if popover is already open it slides to the new position\n setSelectedBooking(booking)\n setPopoverAnchor({ x, y })\n setPopoverVisible(true)\n }, [])\n\n // Find the schedule block covering a given time slot for a professional\n const findScheduleForSlot = useCallback((professionalId: string | undefined, dateTimeStr: string): Schedule | null => {\n if (!professionalId) return null\n const dt = new Date(dateTimeStr)\n const dateStr = dt.toISOString().slice(0, 10)\n const dayOfWeek = dt.getDay()\n const timeMin = dt.getHours() * 60 + dt.getMinutes()\n\n const profSchedules = schedules.filter((s) => s.assigneeId === professionalId)\n const exceptions = profSchedules.filter((s) => s.specificDate === dateStr && s.isActive)\n const weekly = profSchedules.filter((s) => s.dayOfWeek === dayOfWeek && s.isActive && !s.specificDate)\n const daySchedules = exceptions.length > 0 ? exceptions : weekly\n\n for (const s of daySchedules) {\n const [sh, sm] = s.startsAt.split(':').map(Number)\n const [eh, em] = s.endsAt.split(':').map(Number)\n if (timeMin >= sh * 60 + sm && timeMin < eh * 60 + em) return s\n }\n return null\n }, [schedules])\n\n const handleSelect = useCallback((arg: DateSelectArg) => {\n calendarRef.current?.getApi().unselect()\n\n // Don't open create if popover/context menu is showing — dismiss them instead\n if (popoverVisibleRef.current || contextMenuVisibleRef.current) {\n setPopoverVisible(false); setSelectedBooking(null); setPopoverAnchor(null)\n setContextMenuVisible(false); setContextMenu(null)\n return\n }\n\n const professionalId = arg.resource?.id\n const schedule = findScheduleForSlot(professionalId, arg.startStr)\n\n const proceed = () => {\n const locId = schedule?.locationId ?? (schedule?.metadata?.locationId as string | undefined)\n openModal('create', { prefill: { startsAt: arg.startStr, endsAt: arg.endStr, professionalId, locationId: locId || undefined } })\n }\n\n // Warn if no schedule covers this slot — only when the working-hours module\n // is on (off by default in eventMode:'simple', so simple/Google-Calendar\n // events never surface the \"no open schedule for this professional\" dialog).\n if (config.modules.workingHours && !schedule) {\n setScheduleConfirm({ onConfirm: proceed })\n return\n }\n\n proceed()\n }, [openModal, findScheduleForSlot, config.modules.workingHours])\n\n const handleEventDrop = useCallback(async (arg: EventDropArg) => {\n const booking = arg.event.extendedProps.booking as CalendarBooking\n try { await rescheduleBooking(booking.id, arg.event.startStr, arg.event.endStr, arg.newResource?.id ?? undefined) }\n catch { arg.revert() }\n }, [rescheduleBooking])\n\n const handleViewChange = useCallback((v: string) => {\n calendarRef.current?.getApi().changeView(v)\n prefs.set('calendarView', v)\n }, [prefs])\n // Mobile switcher: swap between the list sentinel and a real grid view. When a\n // grid is picked we also sync the store's currentView so the resource-collapse\n // effect doesn't fight the freshly-mounted mobile calendar; if it's already\n // mounted (grid → grid), changeView animates in place.\n const handleMobileViewChange = useCallback((v: string) => {\n setMobileView(v)\n if (v === MOBILE_LIST_VIEW) return\n setView(v)\n calendarRef.current?.getApi()?.changeView(v)\n }, [setView])\n const handlePrev = useCallback(() => calendarRef.current?.getApi().prev(), [])\n const handleNext = useCallback(() => calendarRef.current?.getApi().next(), [])\n const handleToday = useCallback(() => { calendarRef.current?.getApi().today(); setSelectedDate(new Date()) }, [])\n\n function handleMiniDateSelect(date: Date) {\n setSelectedDate(date)\n calendarRef.current?.getApi().gotoDate(date)\n }\n\n function toggleProfessional(id: string) {\n const next = selectedProfIds.includes(id)\n ? selectedProfIds.filter((p) => p !== id)\n : [...selectedProfIds, id]\n setFilters({ professionalIds: next })\n }\n\n function toggleStatus(value: string) {\n const next = selectedStatuses.includes(value)\n ? selectedStatuses.filter((s) => s !== value)\n : [...selectedStatuses, value]\n setFilters({ statuses: next })\n }\n\n // Alternating resource backgrounds — apply via DOM after render\n const wrapperRef = useRef<HTMLDivElement>(null)\n\n // FullCalendar measures its columns once and only re-measures on a WINDOW\n // resize. Opening/closing the assistant rail (or the sidebar) resizes the\n // container without one, so the grid stayed locked at the narrow width until\n // a real window resize came along. Watch the container and hand FC the new box.\n useEffect(() => {\n const container = wrapperRef.current\n if (!container) return\n let frame = 0\n let lastWidth = container.clientWidth\n let lastHeight = container.clientHeight\n const ro = new ResizeObserver(() => {\n const width = container.clientWidth\n const height = container.clientHeight\n if (width === lastWidth && height === lastHeight) return\n lastWidth = width\n lastHeight = height\n // Next frame, not inline: measuring inside the observer callback reads a\n // mid-layout box (and trips the RO loop warning). The rail animates, so\n // this fires on each frame and the last one settles on the final width.\n cancelAnimationFrame(frame)\n frame = requestAnimationFrame(() => calendarRef.current?.getApi()?.updateSize())\n })\n ro.observe(container)\n return () => { cancelAnimationFrame(frame); ro.disconnect() }\n // Re-attach whenever the calendar branch remounts (skeleton → grid, mobile\n // list → grid), since the observed node is gone on the other branches.\n }, [isMobile, mobileGridActive, professionalsLoading, professionals.length])\n\n // Responsive day headers — collapse weekday names to a single initial (S M T\n // W T F S, Google-Calendar style) when day columns get too narrow. Measured\n // from the actual rendered column width so it adapts to resource count + view.\n const [dayHeaderCompact, setDayHeaderCompact] = useState(false)\n useEffect(() => {\n const container = wrapperRef.current\n if (!container) return\n let frame = 0\n const measure = () => {\n // Measure an actual DAY column ([data-date]) — in resource views the first\n // .fc-col-header-cell is the wide resource header, not a day column.\n const cell = container.querySelector('.fc-col-header-cell[data-date]') as HTMLElement | null\n if (!cell) return\n const colWidth = cell.getBoundingClientRect().width\n // Collapse to single-letter ONLY when the full weekday label can't fit.\n // Measure the widest full line (\"WED\" / \"12/14\") in the header's font so\n // the breakpoint adapts to font + locale instead of a magic number.\n const cushion = (cell.querySelector('.fc-col-header-cell-cushion') as HTMLElement | null) ?? cell\n const cs = getComputedStyle(cushion)\n const probe = document.createElement('span')\n probe.style.cssText = 'position:absolute;visibility:hidden;white-space:nowrap;top:-9999px'\n probe.style.fontSize = cs.fontSize\n probe.style.fontWeight = cs.fontWeight\n probe.style.fontFamily = cs.fontFamily\n probe.style.letterSpacing = cs.letterSpacing\n probe.style.textTransform = cs.textTransform\n document.body.appendChild(probe)\n probe.textContent = 'Wed'\n const weekdayWidth = probe.getBoundingClientRect().width\n probe.textContent = '12/14'\n const dateWidth = probe.getBoundingClientRect().width\n probe.remove()\n const needed = Math.max(weekdayWidth, dateWidth) + 12 // text + cushion padding\n setDayHeaderCompact(colWidth < needed)\n }\n // FullCalendar reflows its inner day columns on a later tick than the\n // container resize, so re-measure across a few frames to read settled widths.\n const timers: ReturnType<typeof setTimeout>[] = []\n const schedule = () => {\n cancelAnimationFrame(frame)\n frame = requestAnimationFrame(measure)\n timers.forEach(clearTimeout)\n timers.length = 0\n timers.push(setTimeout(measure, 130), setTimeout(measure, 330))\n }\n schedule()\n const ro = new ResizeObserver(schedule)\n ro.observe(container)\n return () => { cancelAnimationFrame(frame); timers.forEach(clearTimeout); ro.disconnect() }\n }, [resources, currentView, visibleRange])\n\n const applyResourceStriping = useCallback(() => {\n const container = wrapperRef.current\n if (!container) return\n const resourceIds = resources.map((r: { id: string }) => r.id)\n if (resourceIds.length < 2) return\n container.querySelectorAll('[data-resource-id]').forEach((el: Element) => {\n const rid = el.getAttribute('data-resource-id')\n const idx = rid ? resourceIds.indexOf(rid) : -1\n el.classList.toggle('fc-resource-alt', idx % 2 === 1)\n })\n }, [resources])\n\n useEffect(() => {\n applyResourceStriping()\n const t1 = setTimeout(applyResourceStriping, 100)\n const t2 = setTimeout(applyResourceStriping, 300)\n return () => { clearTimeout(t1); clearTimeout(t2) }\n }, [applyResourceStriping, currentView, visibleRange, bookings])\n\n // Listen for cross-plugin booking open requests (e.g., from financial invoice detail)\n useEffect(() => {\n function handleOpenBooking(e: Event) {\n const detail = (e as CustomEvent).detail ?? {}\n const externalSource = detail.source\n ? { type: String(detail.source), id: detail.waitlistId, waitlistId: detail.waitlistId }\n : undefined\n if (detail.bookingId) {\n openModal('edit', { bookingId: detail.bookingId, externalSource })\n return\n }\n openModal('create', {\n prefill: detail.prefill ?? {\n clientId: detail.clientId,\n professionalId: detail.professionalId,\n locationId: detail.locationId,\n startsAt: detail.startsAt,\n },\n externalSource,\n })\n }\n window.addEventListener('agenda:open-booking', handleOpenBooking)\n return () => window.removeEventListener('agenda:open-booking', handleOpenBooking)\n }, [openModal])\n\n // Custom day header: weekday + date stacked. When columns get narrow it\n // collapses the weekday to a single initial (S / 16, Google-Calendar style).\n // Always returns explicit content — returning undefined renders an EMPTY\n // header in the React adapter rather than falling back to the default.\n const dayHeaderContent = useCallback((arg: any) => {\n const date: Date = arg.date\n const dateLocale = currentLocale === 'pt-BR' ? 'pt-BR' : 'en'\n // Inline styles (not CSS classes) so stacking is guaranteed regardless of\n // the runtime style-injection state.\n const wrapStyle: React.CSSProperties = { display: 'flex', flexDirection: 'column', alignItems: 'center', lineHeight: 1.15 }\n const dateStyle: React.CSSProperties = { fontSize: '0.65rem', opacity: 0.75 }\n if (dayHeaderCompact) {\n const letter = date.toLocaleDateString(dateLocale, { weekday: 'narrow' })\n return (\n <div style={wrapStyle}>\n <span style={{ fontWeight: 600 }}>{letter}</span>\n <span style={dateStyle}>{date.getDate()}</span>\n </div>\n )\n }\n const weekday = date.toLocaleDateString(dateLocale, { weekday: 'short' })\n return (\n <div style={wrapStyle}>\n <span>{weekday}</span>\n <span style={dateStyle}>{`${date.getMonth() + 1}/${date.getDate()}`}</span>\n </div>\n )\n }, [dayHeaderCompact, currentLocale])\n\n const resourceLabelContent = useCallback((arg: any) => {\n const { id, title, extendedProps } = arg.resource\n const initials = title.split(' ').map((n: string) => n[0]).join('').slice(0, 2)\n return (\n <div className=\"flex items-center gap-2 px-2 py-1.5\">\n <div className=\"flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary/10 text-[10px] font-bold text-primary\">{initials}</div>\n <div className=\"min-w-0\">\n <PersonLink\n personId={id}\n name={title}\n size=\"sm\"\n tab=\"schedule\"\n profileHref={`#/registry/staff/${id}/schedule`}\n />\n {extendedProps?.locationName && <p className=\"text-[10px] text-muted-foreground truncate\">{extendedProps.locationName}</p>}\n </div>\n </div>\n )\n }, [])\n\n const eventContent = useCallback((arg: any) => {\n // Location label events — render as a small tag\n if (arg.event.extendedProps?.isLocationLabel) {\n return (\n <div className=\"px-1.5 py-0.5 overflow-hidden\">\n <p className=\"text-[10px] font-medium truncate\">{arg.event.title}</p>\n </div>\n )\n }\n const serviceNames = arg.event.extendedProps?.serviceNames\n const start = arg.event.start\n const end = arg.event.end\n const fmt = (d: Date) => `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`\n const timeRange = start && end ? `${fmt(start)} – ${fmt(end)}` : start ? fmt(start) : ''\n return (\n <div className=\"px-1.5 py-0.5 overflow-hidden leading-tight h-full\">\n <div className=\"flex items-start justify-between gap-1\">\n <p className=\"text-[11px] font-semibold truncate\">{arg.event.title}</p>\n {serviceNames && <p className=\"text-[10px] opacity-60 truncate shrink-0 max-w-[45%] text-right\">{serviceNames}</p>}\n </div>\n {timeRange && <p className=\"text-[9px] opacity-50\">{timeRange}</p>}\n </div>\n )\n }, [])\n\n return (\n <div className=\"flex h-[calc(100vh-7.5rem)]\">\n {/* ═══ LEFT SIDEBAR — hidden on mobile ═══ */}\n <div className=\"hidden md:flex w-[220px] shrink-0 flex-col overflow-y-auto py-4 px-3 mr-4\">\n {/* + Create button */}\n <button\n onClick={() => openModal('create')}\n className=\"flex items-center gap-2 rounded-button bg-primary text-primary-foreground border border-primary pl-3 pr-4 py-1.5 text-sm font-semibold hover:bg-primary/90 shadow-button-primary active:shadow-button-inset transition-all mb-6 w-fit\"\n >\n <Plus className=\"h-4 w-4\" />\n {t('agenda.sidebar.create')}\n </button>\n\n {/* Mini month calendar */}\n <MiniCalendar selectedDate={selectedDate} onDateSelect={handleMiniDateSelect} />\n\n {/* Agendas (professional filter) — hidden when no booking type uses a\n professional (e.g. eventMode:'simple'). */}\n {config.capabilities.professional && (<>\n <div className=\"h-px bg-border my-4\" />\n\n <button onClick={() => setProfSectionOpen((p) => !p)}\n className=\"flex items-center justify-between w-full text-xs font-medium text-muted-foreground hover:text-foreground py-1 transition-colors\">\n <span>Agendas</span>\n <ChevronDown className={`h-3.5 w-3.5 transition-transform ${profSectionOpen ? '' : '-rotate-90'}`} />\n </button>\n {profSectionOpen && (\n <div className=\"mt-1.5 space-y-0.5\">\n {professionals.map((prof) => {\n const active = selectedProfIds.length === 0 || selectedProfIds.includes(prof.id)\n return (\n <label key={prof.id} className=\"flex items-center gap-2.5 rounded px-1 py-1 cursor-pointer hover:bg-muted/50 transition-colors\">\n <span className={`flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border-2 transition-colors ${\n active ? 'border-primary bg-primary' : 'border-muted-foreground/30'\n }`}>\n {active && <svg className=\"h-2.5 w-2.5 text-primary-foreground\" viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/></svg>}\n </span>\n <span className={`text-xs truncate ${active ? 'text-foreground' : 'text-muted-foreground'}`}>{prof.name}</span>\n <input type=\"checkbox\" className=\"sr-only\" checked={active} onChange={() => toggleProfessional(prof.id)} />\n </label>\n )\n })}\n </div>\n )}\n </>)}\n\n {/* Status filter — hidden when no booking type uses a status workflow\n (e.g. eventMode:'simple'). */}\n {config.capabilities.status && (<>\n <div className=\"h-px bg-border my-4\" />\n\n <button onClick={() => setStatusSectionOpen((p) => !p)}\n className=\"flex items-center justify-between w-full text-xs font-medium text-muted-foreground hover:text-foreground py-1 transition-colors\">\n <span>Status</span>\n <ChevronDown className={`h-3.5 w-3.5 transition-transform ${statusSectionOpen ? '' : '-rotate-90'}`} />\n </button>\n {statusSectionOpen && (\n <div className=\"mt-1.5 space-y-0.5\">\n {config.statuses.map((st) => {\n const active = selectedStatuses.length === 0 || selectedStatuses.includes(st.value)\n return (\n <label key={st.value} className=\"flex items-center gap-2.5 rounded px-1 py-1 cursor-pointer hover:bg-muted/50 transition-colors\">\n <span className=\"flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border-2 transition-colors\"\n style={{ borderColor: active ? st.color : st.color + '40', backgroundColor: active ? st.color : 'transparent' }}>\n {active && <svg className=\"h-2.5 w-2.5 text-white\" viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/></svg>}\n </span>\n <span className={`text-xs ${active ? 'text-foreground' : 'text-muted-foreground'}`}>{st.label}</span>\n <input type=\"checkbox\" className=\"sr-only\" checked={active} onChange={() => toggleStatus(st.value)} />\n </label>\n )\n })}\n </div>\n )}\n </>)}\n </div>\n\n {/* ═══ MAIN AREA ═══ */}\n <div className=\"flex-1 flex flex-col min-w-0 overflow-hidden\">\n {/* Toolbar */}\n <div className=\"shrink-0 border-b\">\n {/* Row 1 — create + date nav + title (left), desktop switcher + settings\n (right). Extra right padding on mobile clears the transparent header's\n floating profile avatar, which otherwise overlaps the settings gear. */}\n <div className=\"flex items-center justify-between pl-4 pr-14 md:px-4 h-12\">\n <div className=\"flex items-center gap-3 min-w-0\">\n {/* Mobile create button */}\n <button onClick={() => openModal('create')}\n className=\"md:hidden flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground\">\n <Plus className=\"h-4 w-4\" />\n </button>\n\n {/* Date navigation drives the FullCalendar api — shown on desktop and,\n on mobile, only when a grid view is active (the list paginates\n itself, so it has no grid to page through). */}\n <div className={`${mobileGridActive ? 'flex' : 'hidden'} md:flex items-center gap-3`}>\n <button onClick={handleToday}\n className=\"rounded-md border px-3 py-1 text-sm font-medium hover:bg-muted bg-card shadow-button active:shadow-button-inset transition-colors\">\n {t('agenda.toolbar.today')}\n </button>\n <div className=\"flex items-center gap-0.5\">\n <button onClick={handlePrev} className=\"flex h-7 w-7 items-center justify-center rounded-full hover:bg-muted transition-colors\">\n <ChevronLeft className=\"h-4 w-4\" />\n </button>\n <button onClick={handleNext} className=\"flex h-7 w-7 items-center justify-center rounded-full hover:bg-muted transition-colors\">\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n <h1 className=\"text-base sm:text-lg font-normal truncate\">{isMobile && !mobileGridActive ? t('agenda.calendar.viewAgenda') : calendarTitle}</h1>\n </div>\n\n <div className=\"flex items-center gap-1 shrink-0\">\n <div className=\"hidden md:flex items-center gap-1\">\n {viewOptions.map((opt) => (\n <button key={opt.key} onClick={() => handleViewChange(opt.key)}\n className={`rounded-md px-3 py-1 text-sm transition-colors ${\n currentView === opt.key\n ? 'bg-primary/10 text-primary font-medium'\n : 'text-muted-foreground hover:bg-muted/50'\n }`}>\n {t(opt.labelKey)}\n </button>\n ))}\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => window.location.hash = '/settings/agenda'}\n title=\"Agenda Settings\"\n className=\"ml-1\"\n >\n <Settings className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n\n {/* Row 2 (mobile only) — compact segmented view switcher on its own row so\n it never collides with the floating avatar. Dia/Semana/Mês mount the\n calendar; Lista returns to the thumb-friendly agenda list. */}\n <div className=\"flex md:hidden items-center gap-1 overflow-x-auto px-3 pb-2\">\n {mobileViewOptions.map((opt) => (\n <button key={opt.key} onClick={() => handleMobileViewChange(opt.key)}\n className={`shrink-0 rounded-md px-3 py-1 text-sm transition-colors ${\n mobileView === opt.key\n ? 'bg-primary/10 text-primary font-medium'\n : 'text-muted-foreground hover:bg-muted/50'\n }`}>\n {t(opt.labelKey)}\n </button>\n ))}\n </div>\n </div>\n\n {/* Mobile list view → thumb-friendly agenda list; otherwise (desktop, or a\n mobile grid view the user switched to) → FullCalendar grid. */}\n {isMobile && !mobileGridActive ? (\n <AgendaMobileList\n bookings={bookings}\n statusColors={statusColors}\n currencyCode={config.currency.code}\n onSelect={(b) => openModal('edit', { bookingId: b.id })}\n />\n ) : professionalsLoading && professionals.length === 0 ? (\n <CalendarSkeleton profCount={2} />\n ) : (\n <div ref={wrapperRef} className=\"flex-1 overflow-hidden agenda-calendar\">\n <FullCalendar\n ref={calendarRef}\n plugins={[dayGridPlugin, timeGridPlugin, resourceTimeGridPlugin, interactionPlugin, listPlugin]}\n initialView={mobileGridActive ? mobileView : effectiveInitialView}\n schedulerLicenseKey=\"CC-Attribution-NonCommercial-NoDerivatives\"\n resources={resourceCapable ? resources : undefined}\n events={events}\n headerToolbar={false}\n locale={fcLocale}\n height=\"100%\"\n slotMinTime={effectiveBusinessHours.startTime + ':00'}\n slotMaxTime={effectiveBusinessHours.endTime + ':00'}\n slotDuration={{ minutes: config.slotDuration }}\n allDaySlot={false}\n nowIndicator={true}\n editable={config.modules.dragAndDrop}\n selectable={true}\n selectMirror={true}\n eventOverlap={false}\n datesSet={handleDatesSet}\n eventDidMount={handleEventDidMount}\n eventClick={handleEventClick}\n eventMouseEnter={handleEventMouseEnter}\n eventMouseLeave={handleEventMouseLeave}\n select={handleSelect}\n eventDrop={handleEventDrop}\n resourceLabelContent={resourceLabelContent}\n dayHeaderContent={dayHeaderContent}\n eventContent={eventContent}\n resourceOrder=\"title\"\n stickyHeaderDates={true}\n expandRows={false}\n eventTimeFormat={{ hour: '2-digit', minute: '2-digit', hour12: false }}\n slotLabelFormat={{ hour: '2-digit', minute: '2-digit', hour12: false }}\n />\n </div>\n )}\n </div>\n\n {/* Popover — stays mounted until animation finishes */}\n {selectedBooking && popoverAnchor && popoverVisible && (\n <AppointmentPopover booking={selectedBooking} position={popoverAnchor}\n onClose={() => {\n // Called AFTER the popover's exit animation finishes\n setPopoverVisible(false)\n setSelectedBooking(null)\n setPopoverAnchor(null)\n }}\n onEdit={(id) => {\n setPopoverVisible(false)\n setSelectedBooking(null)\n setPopoverAnchor(null)\n openModal('edit', { bookingId: id })\n }} />\n )}\n\n {/* Context Menu */}\n {contextMenu && (\n <EventContextMenu\n booking={contextMenu.booking}\n position={{ x: contextMenu.x, y: contextMenu.y }}\n onClose={() => { setContextMenuVisible(false); setContextMenu(null) }}\n onEdit={(id) => { setContextMenuVisible(false); setContextMenu(null); openModal('edit', { bookingId: id }) }}\n />\n )}\n\n {/* No-schedule confirm */}\n <ConfirmDialog\n open={!!scheduleConfirm}\n variant=\"warning\"\n title={t('agenda.calendar.noScheduleConfirm')}\n confirmLabel={t('common.confirm')}\n cancelLabel={t('common.cancel')}\n onConfirm={() => { const cb = scheduleConfirm?.onConfirm; setScheduleConfirm(null); cb?.() }}\n onCancel={() => setScheduleConfirm(null)}\n />\n\n {/* Modal — always mounted, Radix controls open/close animation */}\n <AppointmentModal\n open={modalState.open}\n mode={modalState.mode}\n bookingId={modalState.bookingId}\n prefill={modalState.prefill}\n initialTab={modalState.initialTab}\n externalSource={modalState.externalSource}\n onClose={closeModal}\n onCreated={(newId, source) => {\n if (config.onBookingCreated) {\n void Promise.resolve(config.onBookingCreated({ bookingId: newId, source })).catch((error: unknown) => {\n console.error('Failed to run agenda booking-created bridge', error)\n })\n }\n // After a short delay (let calendar re-render), find the event and show popover\n setTimeout(() => {\n const booking = bookings.find((b: CalendarBooking) => b.id === newId)\n if (!booking) return\n const el = document.querySelector(`[data-booking-id=\"${newId}\"]`) as HTMLElement | null\n if (el) {\n const rect = el.getBoundingClientRect()\n const popW = 320, popH = 340\n let x = rect.right + 8\n let y = rect.top + rect.height / 2 - popH / 2\n if (x + popW > window.innerWidth - 16) x = rect.left - popW - 8\n if (y + popH > window.innerHeight - 16) y = window.innerHeight - popH - 16\n if (y < 16) y = 16\n setSelectedBooking(booking)\n setPopoverAnchor({ x, y })\n setPopoverVisible(true)\n }\n }, 400)\n }} />\n </div>\n )\n}\n","let t: string | undefined\nexport function setAgendaTenantId(id: string | undefined){ t = id }\nexport function getAgendaTenantId(): string | undefined { return t }\n","import React from 'react'\nimport { usePluginRuntimeOptional } from '@fayz-ai/core'\nimport type { StoreApi } from 'zustand/vanilla'\nimport { AgendaContextProvider } from './AgendaContext'\nimport type { ResolvedAgendaConfig } from './config'\nimport type { AgendaDataProvider } from './data/types'\nimport type { AgendaUIState } from './store'\nimport { CalendarView } from './views/CalendarView'\nimport { setAgendaTenantId } from './lib/tenant'\n\n// ---------------------------------------------------------------------------\n// Main page — clean single-page calendar, no module nav wrapper\n// ---------------------------------------------------------------------------\n\nexport function AgendaPage({ config, provider, store }: {\n config: ResolvedAgendaConfig\n provider: AgendaDataProvider\n store: StoreApi<AgendaUIState>\n}) {\n const runtime = usePluginRuntimeOptional()\n const tenantId = runtime?.context.tenant?.id\n\n React.useEffect(() => {\n setAgendaTenantId(tenantId)\n return () => setAgendaTenantId(undefined)\n }, [tenantId])\n\n return (\n <AgendaContextProvider config={config} provider={provider} store={store}>\n <CalendarView />\n </AgendaContextProvider>\n )\n}\n","import type { AgendaDataProvider } from './types'\nimport type {\n CalendarBooking, Professional, Schedule, TimeSlot,\n CreateBookingInput, UpdateBookingInput, SaveScheduleInput,\n BookingQuery, ConflictCheckParams, AvailableSlotsParams, BookingStatus,\n} from '../types'\nimport { getSupabaseClientOptional, getActiveTenantId } from '@fayz-ai/core'\nimport { getAgendaTenantId } from '../lib/tenant'\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getTenantId(): string | undefined {\n // Plugin-local override wins; else fall back to the app's active tenant so\n // writes stamp the right tenant_id and pass orders/bookings RLS.\n return getAgendaTenantId() ?? getActiveTenantId()\n}\n\nfunction snakeToCamel(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj)) {\n result[key.replace(/_([a-z])/g, (_, c) => c.toUpperCase())] = value\n }\n return result\n}\n\nfunction getClients() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase not initialized')\n // Core v1 lives in PUBLIC — a single client serves both core and view reads.\n return { core: supabase, pub: supabase }\n}\n\nfunction mapBooking(row: Record<string, unknown>): CalendarBooking {\n return snakeToCamel(row) as unknown as CalendarBooking\n}\n\nfunction mapSchedule(row: Record<string, unknown>): Schedule {\n return snakeToCamel(row) as unknown as Schedule\n}\n\nfunction addMinutes(iso: string, minutes: number): string {\n const d = new Date(iso)\n d.setMinutes(d.getMinutes() + minutes)\n return d.toISOString()\n}\n\nfunction unique(values: Array<string | null | undefined>): string[] {\n return Array.from(new Set(values.filter((value): value is string => !!value)))\n}\n\nfunction indexById(rows: any[] | null | undefined): Map<string, any> {\n return new Map((rows ?? []).filter((row) => row?.id).map((row) => [row.id, row]))\n}\n\nfunction groupBy<T>(rows: T[], getKey: (row: T) => string | null | undefined): Map<string, T[]> {\n const grouped = new Map<string, T[]>()\n for (const row of rows) {\n const key = getKey(row)\n if (!key) continue\n grouped.set(key, [...(grouped.get(key) ?? []), row])\n }\n return grouped\n}\n\nfunction getDurationMinutes(startsAt: string, endsAt: string | null | undefined): number | null {\n if (!endsAt) return null\n return Math.round((new Date(endsAt).getTime() - new Date(startsAt).getTime()) / 60000)\n}\n\nfunction mergeBookings(viewBookings: CalendarBooking[], canonicalBookings: CalendarBooking[]): CalendarBooking[] {\n const canonicalIds = new Set(canonicalBookings.map((booking) => booking.id))\n const canonicalOrderIds = new Set(canonicalBookings.map((booking) => booking.orderId).filter(Boolean))\n const merged = [\n ...canonicalBookings,\n ...viewBookings.filter((booking) => {\n if (canonicalIds.has(booking.id)) return false\n if (booking.orderId && canonicalOrderIds.has(booking.orderId)) return false\n if (canonicalOrderIds.has(booking.id)) return false\n return true\n }),\n ]\n\n return merged.sort((a, b) => new Date(a.startsAt).getTime() - new Date(b.startsAt).getTime())\n}\n\nasync function hydrateCanonicalBookings(core: any, bookings: any[]): Promise<CalendarBooking[]> {\n const personIds = unique(bookings.flatMap((booking) => [booking.party_id, booking.assignee_id]))\n const locationIds = unique(bookings.map((booking) => booking.location_id))\n const orderIds = unique(bookings.map((booking) => booking.order_id))\n const bookingIds = unique(bookings.map((booking) => booking.id))\n\n const [\n { data: persons, error: personsError },\n { data: locations, error: locationsError },\n { data: orders, error: ordersError },\n { data: items, error: itemsError },\n ] = await Promise.all([\n personIds.length\n ? core.from('people').select('id, name, phone, email, avatar_url').in('id', personIds)\n : Promise.resolve({ data: [], error: null }),\n locationIds.length\n ? core.from('locations').select('id, name').in('id', locationIds)\n : Promise.resolve({ data: [], error: null }),\n orderIds.length\n ? core.from('orders').select('id, total, status').in('id', orderIds)\n : Promise.resolve({ data: [], error: null }),\n orderIds.length\n ? core.from('order_items').select('id, order_id, service_id, name, duration_minutes, unit_price, assignee_id, sort_order').in('order_id', orderIds)\n : Promise.resolve({ data: [], error: null }),\n ])\n\n if (personsError) throw personsError\n if (locationsError) throw locationsError\n if (ordersError) throw ordersError\n if (itemsError) throw itemsError\n\n const personsById = indexById(persons)\n const locationsById = indexById(locations)\n const ordersById = indexById(orders)\n // S4: line items come from order_items (single source), keyed by order_id.\n const itemsByOrderId = groupBy(items ?? [], (item: any) => item.order_id)\n\n return bookings.map((booking) => {\n const client = booking.party_id ? personsById.get(booking.party_id) : null\n const professional = booking.assignee_id ? personsById.get(booking.assignee_id) : null\n const location = booking.location_id ? locationsById.get(booking.location_id) : null\n const order = booking.order_id ? ordersById.get(booking.order_id) : null\n const bookingItems = ((booking.order_id ? itemsByOrderId.get(booking.order_id) : null) ?? [])\n .sort((a: any, b: any) => (a.sort_order ?? 0) - (b.sort_order ?? 0))\n .map((item: any) => ({\n id: item.id,\n serviceId: item.service_id,\n name: item.name,\n durationMinutes: item.duration_minutes,\n price: item.unit_price,\n assigneeId: item.assignee_id,\n }))\n const itemDuration = bookingItems.reduce((sum: number, item: any) => sum + (item.durationMinutes ?? 0), 0)\n\n return {\n id: booking.id,\n tenantId: booking.tenant_id,\n kind: booking.kind,\n startsAt: booking.starts_at,\n endsAt: booking.ends_at,\n status: booking.status,\n notes: booking.notes,\n orderId: booking.order_id,\n locationId: booking.location_id,\n metadata: booking.metadata ?? {},\n clientId: booking.party_id,\n // Simple events (no party) fall back to the title stored in metadata;\n // partyless blocks/tasks (e.g. imported Google events) get their notes or\n // a kind label so the calendar never renders an unnamed chip.\n clientName: client?.name\n ?? (booking.metadata?.title as string | undefined)\n ?? (booking.kind === 'appointment'\n ? null\n : booking.notes || (booking.kind === 'task' ? 'Tarefa' : 'Bloqueio')),\n clientPhone: client?.phone ?? null,\n clientEmail: client?.email ?? null,\n clientAvatarUrl: client?.avatar_url ?? null,\n professionalId: booking.assignee_id,\n professionalName: professional?.name ?? null,\n professionalAvatarUrl: professional?.avatar_url ?? null,\n locationName: location?.name ?? null,\n orderTotal: order?.total ?? null,\n orderStatus: order?.status ?? null,\n services: bookingItems.length ? bookingItems : null,\n totalDurationMinutes: itemDuration || getDurationMinutes(booking.starts_at, booking.ends_at),\n createdAt: booking.created_at,\n updatedAt: booking.updated_at,\n } satisfies CalendarBooking\n })\n}\n\nasync function getCanonicalBookings(core: any, query: BookingQuery): Promise<CalendarBooking[]> {\n let q = core.from('appointments')\n .select('id, tenant_id, kind, starts_at, ends_at, status, notes, order_id, location_id, metadata, party_id, assignee_id, created_at, updated_at')\n .gte('starts_at', query.dateRange.start)\n .lte('starts_at', query.dateRange.end)\n\n if (query.kind) q = q.eq('kind', query.kind)\n if (query.statuses?.length) q = q.in('status', query.statuses)\n if (query.professionalIds?.length) q = q.in('assignee_id', query.professionalIds)\n if (query.locationId) q = q.eq('location_id', query.locationId)\n\n const { data, error } = await q.order('starts_at', { ascending: true })\n if (error) throw error\n return hydrateCanonicalBookings(core, data ?? [])\n}\n\nasync function getCanonicalBookingById(core: any, id: string): Promise<CalendarBooking | null> {\n const columns = 'id, tenant_id, kind, starts_at, ends_at, status, notes, order_id, location_id, metadata, party_id, assignee_id, created_at, updated_at'\n let { data, error } = await core.from('appointments').select(columns).eq('id', id).maybeSingle()\n if (error) throw error\n\n if (!data) {\n const fallback = await core.from('appointments').select(columns).eq('order_id', id).maybeSingle()\n if (fallback.error) throw fallback.error\n data = fallback.data\n }\n\n if (!data) return null\n const [booking] = await hydrateCanonicalBookings(core, [data])\n return booking ?? null\n}\n\n// ---------------------------------------------------------------------------\n// Supabase Agenda Provider\n// ---------------------------------------------------------------------------\n\nexport interface SupabaseAgendaProviderOptions {\n /** people.kind used for calendar resources/professionals (default 'staff' — schools use 'teacher'). */\n professionalKind?: string\n}\n\nexport function createSupabaseAgendaProvider(providerOptions?: SupabaseAgendaProviderOptions): AgendaDataProvider {\n const professionalKind = providerOptions?.professionalKind ?? 'staff'\n return {\n // v_appointments is in public schema (PostgREST default)\n async getBookings(query: BookingQuery): Promise<CalendarBooking[]> {\n const { core, pub } = getClients()\n let q = pub.from('v_appointments').select('*')\n .gte('starts_at', query.dateRange.start)\n .lte('starts_at', query.dateRange.end)\n\n if (query.kind) q = q.eq('kind', query.kind)\n if (query.statuses?.length) q = q.in('status', query.statuses)\n if (query.professionalIds?.length) q = q.in('professional_id', query.professionalIds)\n if (query.locationId) q = q.eq('location_id', query.locationId)\n\n q = q.order('starts_at', { ascending: true })\n\n const { data, error } = await q\n if (error) throw error\n const viewBookings = (data ?? []).map(mapBooking)\n const canonicalBookings = await getCanonicalBookings(core, query)\n return mergeBookings(viewBookings, canonicalBookings)\n },\n\n async getBookingById(id: string): Promise<CalendarBooking | null> {\n const { core, pub } = getClients()\n const { data, error } = await pub.from('v_appointments').select('*').eq('id', id).maybeSingle()\n if (error) throw error\n if (data) {\n const booking = mapBooking(data as Record<string, unknown>)\n // v_appointments is a FLAT read model — it exposes no line items. The\n // calendar list path merges in the canonical hydration (which carries\n // `services` from order_items), but this single-record lookup used by the\n // edit modal previously returned the bare view row. That dropped\n // `services`, so a booking whose type has `requiresServices` reopened with\n // an empty service list and kept the \"Update\" button permanently disabled\n // (canSubmit stayed false). Hydrate the line items here to stay consistent\n // with getBookings.\n if (booking.orderId) {\n const { data: items } = await core.from('order_items')\n .select('id, service_id, name, duration_minutes, unit_price, assignee_id, sort_order')\n .eq('order_id', booking.orderId)\n .order('sort_order', { ascending: true })\n if (items && items.length) {\n const services = items.map((item: any) => ({\n id: item.id,\n serviceId: item.service_id,\n name: item.name,\n durationMinutes: item.duration_minutes,\n price: item.unit_price,\n assigneeId: item.assignee_id,\n }))\n booking.services = services\n const itemDuration = services.reduce((sum: number, s: any) => sum + (s.durationMinutes ?? 0), 0)\n if (itemDuration) booking.totalDurationMinutes = itemDuration\n }\n }\n return booking\n }\n return getCanonicalBookingById(core, id)\n },\n\n async createBooking(input: CreateBookingInput): Promise<CalendarBooking> {\n const { core } = getClients()\n const tenantId = getTenantId()\n if (!tenantId) throw new Error('No active tenant')\n\n const hasServices = input.services.length > 0\n const totalDuration = input.services.reduce((sum, s) => sum + s.durationMinutes, 0)\n const totalPrice = input.services.reduce((sum, s) => sum + s.price, 0)\n const endsAt = addMinutes(input.startsAt, totalDuration || 30)\n const serviceNames = input.services.map((s: any) => s.name).join(', ')\n\n // Resolve client name for metadata (used by financial detail view)\n let contactName: string | undefined\n if (input.clientId) {\n const { data: person } = await core.from('people').select('name').eq('id', input.clientId).single()\n contactName = person?.name as string | undefined\n }\n\n // Simple / Google-Calendar-style events have no client party — persist the\n // free-text title in metadata so the read model can surface it as the name.\n const eventTitle = input.title?.trim() || undefined\n\n const { data: order, error: orderErr } = await core.from('orders').insert({\n tenant_id: tenantId,\n kind: input.kind ?? 'appointment',\n status: 'scheduled',\n party_id: input.clientId || null,\n assignee_id: input.professionalId || null,\n location_id: input.locationId ?? null,\n subtotal: totalPrice,\n total: totalPrice,\n notes: input.notes ?? null,\n metadata: {\n source: 'agenda',\n ...(serviceNames ? { serviceNames, itemsSummary: serviceNames } : {}),\n ...(contactName ? { contactName } : {}),\n ...(eventTitle ? { title: eventTitle } : {}),\n },\n }).select('id').single()\n if (orderErr) throw orderErr\n\n const { data: booking, error: bookingErr } = await core.from('appointments').insert({\n tenant_id: tenantId,\n kind: input.kind ?? 'appointment',\n party_id: input.clientId || null,\n assignee_id: input.professionalId || null,\n location_id: input.locationId ?? null,\n order_id: order.id,\n starts_at: input.startsAt,\n ends_at: endsAt,\n status: 'scheduled',\n notes: input.notes ?? null,\n metadata: {\n source: 'agenda',\n ...(serviceNames ? { serviceNames, itemsSummary: serviceNames } : {}),\n ...(contactName ? { contactName } : {}),\n ...(eventTitle ? { title: eventTitle } : {}),\n },\n }).select('id').single()\n if (bookingErr) throw bookingErr\n\n if (hasServices) {\n // S4: line items live ONLY in order_items now (booking_items deprecated).\n const orderItems = input.services.map((s, i) => ({\n order_id: order.id,\n service_id: s.serviceId,\n name: s.name,\n quantity: 1,\n unit_price: s.price,\n total: s.price,\n sort_order: i,\n duration_minutes: s.durationMinutes,\n assignee_id: s.assigneeId || input.professionalId || null,\n }))\n const { error: oiErr } = await core.from('order_items').insert(orderItems)\n if (oiErr) throw oiErr\n }\n\n const createdBooking = await this.getBookingById(booking.id)\n if (!createdBooking) throw new Error('Created booking did not resolve from agenda read model')\n return createdBooking\n },\n\n async updateBooking(id: string, data: UpdateBookingInput): Promise<CalendarBooking> {\n const { core } = getClients()\n const { data: existing, error: existingErr } = await core.from('appointments')\n .select('id, order_id, starts_at, assignee_id, metadata')\n .eq('id', id)\n .single()\n if (existingErr) throw existingErr\n\n const updates: Record<string, unknown> = {}\n if (data.startsAt) updates.starts_at = data.startsAt\n if (data.endsAt) updates.ends_at = data.endsAt\n // Simple-event title lives in metadata (no client party) — merge, don't clobber.\n if (data.title !== undefined) {\n updates.metadata = { ...(existing?.metadata as Record<string, unknown> ?? {}), title: data.title }\n }\n if (data.status) {\n // Only update the agenda status — never touch the financial stage\n updates.status = data.status\n }\n if (data.notes !== undefined) updates.notes = data.notes\n if (data.professionalId) updates.assignee_id = data.professionalId\n if (data.clientId) updates.party_id = data.clientId\n if (data.locationId) updates.location_id = data.locationId\n\n // Recalculate totals when services are updated\n if (data.services) {\n const totalDuration = data.services.reduce((s, svc) => s + svc.durationMinutes, 0)\n const totalPrice = data.services.reduce((s, svc) => s + svc.price, 0)\n // Recalculate ends_at from startsAt + total duration\n const startsAt = data.startsAt ?? (existing?.starts_at as string | undefined)\n if (startsAt) {\n const ends = new Date(new Date(startsAt).getTime() + totalDuration * 60000)\n updates.ends_at = ends.toISOString()\n }\n }\n\n const effectiveAssigneeId = data.professionalId ?? (existing?.assignee_id as string | null | undefined) ?? null\n\n const { error } = await core.from('appointments').update(updates).eq('id', id)\n if (error) throw error\n\n // S4: services are updated only in order_items below (booking_items deprecated).\n const orderId = existing?.order_id as string | null | undefined\n if (orderId) {\n const orderUpdates: Record<string, unknown> = {}\n if (data.notes !== undefined) orderUpdates.notes = data.notes\n if (data.professionalId) orderUpdates.assignee_id = data.professionalId\n if (data.clientId) orderUpdates.party_id = data.clientId\n if (data.locationId) orderUpdates.location_id = data.locationId\n\n if (data.services) {\n const totalPrice = data.services.reduce((s, svc) => s + svc.price, 0)\n orderUpdates.subtotal = totalPrice\n orderUpdates.total = totalPrice\n }\n\n if (Object.keys(orderUpdates).length > 0) {\n const { error: orderErr } = await core.from('orders').update(orderUpdates).eq('id', orderId)\n if (orderErr) throw orderErr\n }\n\n if (data.services) {\n await core.from('order_items').delete().eq('order_id', orderId)\n if (data.services.length > 0) {\n const items = data.services.map((svc, idx) => ({\n order_id: orderId,\n service_id: svc.serviceId || null,\n name: svc.name,\n quantity: 1,\n unit_price: svc.price,\n total: svc.price,\n sort_order: idx,\n duration_minutes: svc.durationMinutes,\n assignee_id: svc.assigneeId ?? effectiveAssigneeId,\n }))\n const { error: itemErr } = await core.from('order_items').insert(items)\n if (itemErr) throw itemErr\n }\n }\n }\n\n return (await this.getBookingById(id))!\n },\n\n async deleteBooking(id: string): Promise<void> {\n const { core, pub } = getClients()\n const { data: booking, error: bookingErr } = await core.from('appointments')\n .select('order_id')\n .eq('id', id)\n .single()\n if (bookingErr) throw bookingErr\n\n const orderId = booking?.order_id as string | null | undefined\n // Financial movements live in the financial plugin's tables. Pools that\n // don't provision that plugin (e.g. school/event agendas) have no\n // plg_financial_movements table, and the probe below returns a PostgREST\n // \"relation does not exist\" error. Previously that error was rethrown,\n // which aborted the ENTIRE delete — the modal caught it and left the\n // booking in place, so \"Delete\" looked like a silent no-op (works in\n // beauty, which has the table; fails in school, which doesn't). Treat any\n // probe failure as \"no linked movements\" and fall through to a plain delete.\n let movementCount = 0\n if (orderId) {\n const { count, error: movementErr } = await pub\n .from('plg_financial_movements')\n .select('id', { count: 'exact', head: true })\n .eq('invoice_id', orderId)\n if (!movementErr) movementCount = count ?? 0\n }\n\n if (orderId && movementCount > 0) {\n // Cancel movements + order (don't delete financial records)\n await pub.from('plg_financial_movements').update({ status: 'cancelled' }).eq('invoice_id', orderId)\n await core.from('orders').update({ status: 'cancelled' }).eq('id', orderId)\n const { error } = await core.from('appointments').update({ status: 'cancelled' }).eq('id', id)\n if (error) throw error\n } else {\n // Safe to delete — remove any movements first (FK constraint)\n if (orderId) {\n await pub.from('plg_financial_movements').delete().eq('invoice_id', orderId)\n }\n const { error } = await core.from('appointments').delete().eq('id', id)\n if (error) throw error\n if (orderId) {\n const { error: orderErr } = await core.from('orders').delete().eq('id', orderId)\n if (orderErr) throw orderErr\n }\n }\n },\n\n async updateBookingStatus(id: string, status: string): Promise<CalendarBooking> {\n return this.updateBooking(id, { status: status as BookingStatus })\n },\n\n async checkConflict(params: ConflictCheckParams): Promise<boolean> {\n const { core } = getClients()\n let q = core.from('appointments').select('id', { count: 'exact', head: true })\n .eq('assignee_id', params.assigneeId)\n .eq('kind', 'appointment')\n .not('status', 'in', '(\"cancelled\",\"no_show\")')\n .not('starts_at', 'is', null)\n .lt('starts_at', params.endsAt)\n .gt('ends_at', params.startsAt)\n\n if (params.excludeBookingId) {\n q = q.neq('id', params.excludeBookingId)\n }\n\n const { count, error } = await q\n if (error) throw error\n return (count ?? 0) > 0\n },\n\n async getAvailableSlots(params: AvailableSlotsParams): Promise<TimeSlot[]> {\n const { pub } = getClients()\n const { data, error } = await pub.rpc('get_available_slots', {\n p_tenant_id: getTenantId(),\n p_assignee_id: params.assigneeId,\n p_date: params.date,\n p_duration_minutes: params.durationMinutes,\n p_slot_interval: params.slotInterval ?? 30,\n })\n if (error) throw error\n return (data ?? []).map((row: any) => ({ start: row.slot_start, end: row.slot_end }))\n },\n\n async getSchedules(professionalId?: string): Promise<Schedule[]> {\n const { core } = getClients()\n let q = core.from('schedules').select('*').eq('kind', 'working_hours')\n if (professionalId) q = q.eq('assignee_id', professionalId)\n q = q.order('day_of_week').order('starts_at')\n\n const { data, error } = await q\n if (error) throw error\n return (data ?? []).map(mapSchedule)\n },\n\n async saveSchedule(input: SaveScheduleInput): Promise<Schedule> {\n const { core } = getClients()\n const tenantId = getTenantId()\n if (!tenantId) throw new Error('No active tenant')\n\n const { data, error } = await core.from('schedules').insert({\n tenant_id: tenantId,\n kind: 'working_hours',\n assignee_id: input.assigneeId,\n location_id: input.locationId ?? null,\n day_of_week: input.dayOfWeek ?? null,\n specific_date: input.specificDate ?? null,\n starts_at: input.startsAt,\n ends_at: input.endsAt,\n is_active: input.isActive !== false,\n metadata: input.metadata ?? {},\n }).select('*').single()\n if (error) throw error\n return mapSchedule(data as Record<string, unknown>)\n },\n\n async deleteSchedule(id: string): Promise<void> {\n const { core } = getClients()\n const { error } = await core.from('schedules').delete().eq('id', id)\n if (error) throw error\n },\n\n async getProfessionals(): Promise<Professional[]> {\n const { core } = getClients()\n const { data, error } = await core.from('people')\n .select('id, name, avatar_url, is_active')\n .eq('kind', professionalKind)\n .eq('is_active', true)\n .order('name')\n if (error) throw error\n return (data ?? []).map((p: any) => ({\n id: p.id, name: p.name, avatarUrl: p.avatar_url,\n locationId: null, locationName: null, isActive: p.is_active,\n }))\n },\n\n async getLocations(): Promise<Array<{ id: string; name: string }>> {\n const { core } = getClients()\n const { data, error } = await core.from('locations')\n .select('id, name')\n .eq('is_active', true)\n .order('name')\n if (error) throw error\n return (data ?? []).map((l: any) => ({ id: l.id, name: l.name }))\n },\n\n async getConfirmationsPending(daysAhead = 2): Promise<CalendarBooking[]> {\n const { pub } = getClients()\n const now = new Date().toISOString()\n const cutoff = new Date()\n cutoff.setDate(cutoff.getDate() + daysAhead)\n\n const { data, error } = await pub.from('v_appointments').select('*')\n .eq('status', 'scheduled')\n .gte('starts_at', now)\n .lte('starts_at', cutoff.toISOString())\n .order('starts_at')\n if (error) throw error\n return (data ?? []).map(mapBooking)\n },\n\n async sendConfirmation(bookingId: string, channel: string): Promise<void> {\n const { core } = getClients()\n const { data: booking } = await core.from('appointments').select('metadata').eq('id', bookingId).single()\n const metadata = (booking?.metadata ?? {}) as Record<string, unknown>\n const confirmations = (metadata.confirmations as any[] ?? [])\n confirmations.push({ channel, sentAt: new Date().toISOString(), status: 'sent' })\n await core.from('appointments').update({ metadata: { ...metadata, confirmations } }).eq('id', bookingId)\n },\n\n async completeBooking(bookingId: string): Promise<{ booking: CalendarBooking; orderId: string }> {\n const { core } = getClients()\n const { data: existing, error: existingErr } = await core.from('appointments')\n .select('order_id')\n .eq('id', bookingId)\n .single()\n if (existingErr) throw existingErr\n\n const { error } = await core.from('appointments')\n .update({ status: 'completed' })\n .eq('id', bookingId)\n if (error) throw error\n\n const orderId = existing?.order_id as string | null | undefined\n const booking = await this.getBookingById(bookingId)\n if (!booking) throw new Error('Booking not found')\n return { booking, orderId: orderId ?? bookingId }\n },\n }\n}\n","import { createStore, type StoreApi } from 'zustand/vanilla'\nimport { emitDataChanged } from '@fayz-ai/core'\nimport { dedup } from '@fayz-ai/saas'\nimport { toast } from '@fayz-ai/ui'\nimport { getScheduleBlockConfig, setScheduleBlockConfig } from '@fayz-ai/saas'\nimport type { AgendaDataProvider } from './data/types'\nimport type { AgendaFinancialBridge } from './financial-bridge'\nimport type { ExternalBookingSource } from './config'\nimport type {\n CalendarBooking, Professional, Schedule,\n CreateBookingInput, UpdateBookingInput, BookingQuery,\n} from './types'\n\n// ---------------------------------------------------------------------------\n// Store state\n// ---------------------------------------------------------------------------\n\nexport interface AgendaUIState {\n // Calendar data\n bookings: CalendarBooking[]\n bookingsLoading: boolean\n dateRange: { start: string; end: string }\n currentView: string\n selectedDate: string\n\n // Resources\n professionals: Professional[]\n professionalsLoading: boolean\n\n // Filters\n selectedProfessionalIds: string[]\n selectedLocationId: string | null\n selectedStatuses: string[]\n\n // Locations\n locations: Array<{ id: string; name: string }>\n\n // Schedules\n schedules: Schedule[]\n schedulesLoading: boolean\n\n // Confirmations\n pendingConfirmations: CalendarBooking[]\n confirmationsLoading: boolean\n\n // Modal state\n appointmentModal: {\n open: boolean\n mode: 'create' | 'edit'\n bookingId?: string\n prefill?: Partial<CreateBookingInput> & { endsAt?: string }\n initialTab?: string\n externalSource?: ExternalBookingSource\n }\n\n // Actions\n fetchBookings(range: { start: string; end: string }): Promise<void>\n fetchProfessionals(): Promise<void>\n fetchLocations(): Promise<void>\n fetchSchedules(professionalId?: string): Promise<void>\n fetchConfirmations(): Promise<void>\n createBooking(input: CreateBookingInput): Promise<CalendarBooking>\n updateBooking(id: string, data: UpdateBookingInput): Promise<CalendarBooking>\n deleteBooking(id: string): Promise<void>\n updateBookingStatus(id: string, status: string): Promise<void>\n rescheduleBooking(id: string, newStart: string, newEnd: string, newProfessionalId?: string): Promise<void>\n setFilters(filters: Partial<{ professionalIds: string[]; locationId: string | null; statuses: string[] }>): void\n setView(view: string): void\n setSelectedDate(date: string): void\n openAppointmentModal(mode: 'create' | 'edit', options?: { bookingId?: string; prefill?: Partial<CreateBookingInput> & { endsAt?: string }; initialTab?: string; externalSource?: ExternalBookingSource }): void\n closeAppointmentModal(): void\n}\n\n// ---------------------------------------------------------------------------\n// Store factory\n// ---------------------------------------------------------------------------\n\nfunction getCurrentBookingQuery(state: AgendaUIState, dateRange = state.dateRange): BookingQuery {\n return {\n dateRange,\n professionalIds: state.selectedProfessionalIds.length ? state.selectedProfessionalIds : undefined,\n locationId: state.selectedLocationId ?? undefined,\n statuses: state.selectedStatuses.length ? state.selectedStatuses : undefined,\n }\n}\n\nexport function createAgendaStore(provider: AgendaDataProvider, financialBridge?: AgendaFinancialBridge): StoreApi<AgendaUIState> {\n return createStore<AgendaUIState>((set, get) => ({\n bookings: [],\n bookingsLoading: false,\n dateRange: { start: '', end: '' },\n currentView: 'resourceTimeGridDay',\n selectedDate: new Date().toISOString().slice(0, 10),\n\n professionals: [],\n professionalsLoading: false,\n\n selectedProfessionalIds: [],\n selectedLocationId: null,\n selectedStatuses: ['scheduled', 'confirmed', 'in_progress', 'completed'],\n\n locations: [],\n\n schedules: [],\n schedulesLoading: false,\n\n pendingConfirmations: [],\n confirmationsLoading: false,\n\n appointmentModal: { open: false, mode: 'create' },\n\n async fetchBookings(range) {\n const key = `agenda:bookings:${range.start}:${range.end}`\n return dedup(key, async () => {\n set({ bookingsLoading: true, dateRange: range })\n const state = get()\n const query = getCurrentBookingQuery(state, range)\n let bookings = await provider.getBookings(query)\n\n // Enrich with payment status if financial bridge is available\n if (financialBridge) {\n const orderIds = bookings.map((b) => b.orderId).filter((id): id is string => !!id)\n if (orderIds.length > 0) {\n try {\n const statuses = await financialBridge.resolvePaymentStatuses(orderIds)\n bookings = bookings.map((b) => {\n if (!b.orderId) return b\n const summary = statuses.get(b.orderId)\n return summary ? { ...b, paymentStatus: summary.status } : b\n })\n } catch { /* non-blocking */ }\n }\n }\n\n set({ bookings, bookingsLoading: false })\n })\n },\n\n async fetchProfessionals() {\n return dedup('agenda:professionals', async () => {\n set({ professionalsLoading: true })\n const professionals = await provider.getProfessionals()\n set({ professionals, professionalsLoading: false })\n })\n },\n\n async fetchLocations() {\n return dedup('agenda:locations', async () => {\n if (!provider.getLocations) return\n const locations = await provider.getLocations()\n set({ locations })\n // Update global schedule block config so ScheduleEditor picks up locations\n const current = getScheduleBlockConfig()\n if (current) {\n setScheduleBlockConfig({ ...current, locations })\n }\n })\n },\n\n async fetchSchedules(professionalId) {\n return dedup('agenda:schedules:' + (professionalId ?? 'all'), async () => {\n set({ schedulesLoading: true })\n const schedules = await provider.getSchedules(professionalId)\n set({ schedules, schedulesLoading: false })\n })\n },\n\n async fetchConfirmations() {\n return dedup('agenda:confirmations', async () => {\n set({ confirmationsLoading: true })\n const pendingConfirmations = await provider.getConfirmationsPending()\n set({ pendingConfirmations, confirmationsLoading: false })\n })\n },\n\n async createBooking(input) {\n try {\n const booking = await provider.createBooking(input)\n // Refresh bookings for current range\n const state = get()\n if (state.dateRange.start && state.dateRange.end) {\n const bookings = await provider.getBookings(getCurrentBookingQuery(state))\n set({ bookings })\n }\n emitDataChanged({ table: 'appointments', op: 'create', id: booking.id, source: 'ui' })\n toast.success('Appointment created')\n return booking\n } catch (err: any) {\n toast.error('Failed to create appointment', { description: err?.message })\n throw err\n }\n },\n\n async updateBooking(id, data) {\n try {\n const booking = await provider.updateBooking(id, data)\n const state = get()\n if (state.dateRange.start && state.dateRange.end) {\n const bookings = await provider.getBookings(getCurrentBookingQuery(state))\n set({ bookings })\n }\n emitDataChanged({ table: 'appointments', op: 'update', id, source: 'ui' })\n toast.success('Appointment updated')\n return booking\n } catch (err: any) {\n toast.error('Failed to update appointment', { description: err?.message })\n throw err\n }\n },\n\n async deleteBooking(id) {\n try {\n await provider.deleteBooking(id)\n const state = get()\n if (state.dateRange.start && state.dateRange.end) {\n const bookings = await provider.getBookings(getCurrentBookingQuery(state))\n set({ bookings })\n }\n emitDataChanged({ table: 'appointments', op: 'delete', id, source: 'ui' })\n toast.success('Appointment deleted')\n } catch (err: any) {\n toast.error('Failed to delete appointment', { description: err?.message })\n throw err\n }\n },\n\n async updateBookingStatus(id, status) {\n // Optimistic update — change color immediately\n const prev = get().bookings\n set({ bookings: prev.map((b) => b.id === id ? { ...b, status: status as any } : b) })\n try {\n await provider.updateBookingStatus(id, status)\n // Refresh from server to get full data\n const state = get()\n if (state.dateRange.start && state.dateRange.end) {\n const bookings = await provider.getBookings(getCurrentBookingQuery(state))\n set({ bookings })\n }\n emitDataChanged({ table: 'appointments', op: 'update', id, source: 'ui' })\n toast.success('Status updated')\n } catch (err: any) {\n // Rollback on failure\n set({ bookings: prev })\n toast.error('Failed to update status', { description: err?.message })\n throw err\n }\n },\n\n async rescheduleBooking(id, newStart, newEnd, newProfessionalId) {\n try {\n // Check for conflicts\n const existing = get().bookings.find((b) => b.id === id)\n const assigneeId = newProfessionalId ?? existing?.professionalId\n if (assigneeId) {\n const hasConflict = await provider.checkConflict({\n assigneeId,\n startsAt: newStart,\n endsAt: newEnd,\n excludeBookingId: id,\n })\n if (hasConflict) {\n toast.error('Time conflict detected', { description: 'This professional already has an appointment at this time.' })\n throw new Error('Time conflict')\n }\n }\n await provider.updateBooking(id, {\n startsAt: newStart,\n endsAt: newEnd,\n ...(newProfessionalId && { professionalId: newProfessionalId }),\n })\n const state = get()\n if (state.dateRange.start && state.dateRange.end) {\n const bookings = await provider.getBookings(getCurrentBookingQuery(state))\n set({ bookings })\n }\n toast.success('Appointment rescheduled')\n } catch (err: any) {\n if (err?.message !== 'Time conflict') {\n toast.error('Failed to reschedule', { description: err?.message })\n }\n throw err\n }\n },\n\n setFilters(filters) {\n set({\n ...(filters.professionalIds !== undefined && { selectedProfessionalIds: filters.professionalIds }),\n ...(filters.locationId !== undefined && { selectedLocationId: filters.locationId }),\n ...(filters.statuses !== undefined && { selectedStatuses: filters.statuses }),\n })\n // Re-fetch with new filters\n const { dateRange } = get()\n if (dateRange.start && dateRange.end) {\n get().fetchBookings(dateRange)\n }\n },\n\n setView(view) { set({ currentView: view }) },\n setSelectedDate(date) { set({ selectedDate: date }) },\n\n openAppointmentModal(mode, options) {\n set({ appointmentModal: { open: true, mode, bookingId: options?.bookingId, prefill: options?.prefill, initialTab: options?.initialTab, externalSource: options?.externalSource } })\n },\n\n closeAppointmentModal() {\n // Only toggle open — keep mode/bookingId/prefill intact so layout\n // doesn't shift during the close animation\n set((state) => ({ appointmentModal: { ...state.appointmentModal, open: false } }))\n },\n }))\n}\n","import type { PluginRegistryDef } from '@fayz-ai/core'\nimport type { EntityDef } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Holidays (public.holidays — tenant-scoped)\n// ---------------------------------------------------------------------------\n\nconst holidayEntity: EntityDef = {\n name: 'Holiday',\n namePlural: 'Holidays',\n icon: 'TreePalm',\n displayField: 'name',\n defaultSort: 'date',\n defaultSortDir: 'asc',\n fields: [\n { key: 'name', label: 'Name', type: 'text', required: true, showInTable: true },\n { key: 'date', label: 'Date', type: 'date', required: true, showInTable: true, sortable: true },\n { key: 'recurring', label: 'Recurring Annually', type: 'boolean', showInTable: true, defaultValue: false },\n { key: 'description', label: 'Description', type: 'text', showInTable: false },\n { key: 'isActive', label: 'Active', type: 'boolean', showInTable: true, defaultValue: true },\n ],\n data: {\n table: 'holidays',\n tenantScoped: true,\n },\n}\n\nexport const agendaRegistries: PluginRegistryDef[] = [\n {\n id: 'holidays',\n entity: holidayEntity,\n icon: 'TreePalm',\n description: 'Non-working days and recurring holidays',\n },\n]\n","import React from 'react'\nimport { SettingsGroup, ToggleRow, SelectRow, useTenantPluginSettings } from '@fayz-ai/saas'\nimport { useTranslation } from '@fayz-ai/core'\nimport { useAgendaSettings } from '../hooks/useAgendaSettings'\n\nconst HOUR_OPTIONS = Array.from({ length: 18 }, (_, i) => {\n const h = (5 + i).toString().padStart(2, '0')\n return { value: `${h}:00`, label: `${h}:00` }\n})\n\n// Per-tenant toggle defaults = the values that used to be hardcoded here.\n// NOTE: these are persisted + re-hydrated per tenant; actually consuming them to\n// change agenda behaviour is a follow-up (see useTenantPluginSettings docs).\nconst AGENDA_TOGGLE_DEFAULTS = {\n conflictDetection: true,\n dragDrop: true,\n autoCreateOrder: true,\n enableLocation: false,\n enableWorkingHours: true,\n blockOutside: false,\n enableConfirmations: true,\n autoConfirm: false,\n reminder: true,\n showCancelled: false,\n showNoShow: true,\n compact: false,\n newBookingNotif: true,\n cancelAlerts: true,\n noShowTracking: false,\n}\n\nexport function AgendaGeneralSettings() {\n const t = useTranslation()\n const { startTime, endTime, setStartTime, setEndTime } = useAgendaSettings()\n const s = useTenantPluginSettings('agenda', AGENDA_TOGGLE_DEFAULTS)\n return (\n <div className=\"space-y-4\">\n <SettingsGroup title={t('agenda.settings.scheduling')} description={t('agenda.settings.schedulingDesc')}>\n <ToggleRow label={t('agenda.settings.conflictDetection')} description={t('agenda.settings.conflictDetectionDesc')} checked={s.get('conflictDetection')} onChange={(v) => s.set('conflictDetection', v)} />\n <ToggleRow label={t('agenda.settings.dragDrop')} description={t('agenda.settings.dragDropDesc')} checked={s.get('dragDrop')} onChange={(v) => s.set('dragDrop', v)} />\n <ToggleRow label={t('agenda.settings.autoCreateOrder')} description={t('agenda.settings.autoCreateOrderDesc')} checked={s.get('autoCreateOrder')} onChange={(v) => s.set('autoCreateOrder', v)} />\n </SettingsGroup>\n\n <SettingsGroup title={t('agenda.settings.locations')} description={t('agenda.settings.locationsDesc')}>\n <ToggleRow label={t('agenda.settings.enableLocation')} description={t('agenda.settings.enableLocationDesc')} checked={s.get('enableLocation')} onChange={(v) => s.set('enableLocation', v)} />\n </SettingsGroup>\n\n <SettingsGroup title={t('agenda.settings.workingHours')} description={t('agenda.settings.workingHoursDesc')}>\n <ToggleRow label={t('agenda.settings.enableWorkingHours')} description={t('agenda.settings.enableWorkingHoursDesc')} checked={s.get('enableWorkingHours')} onChange={(v) => s.set('enableWorkingHours', v)} />\n <ToggleRow label={t('agenda.settings.blockOutside')} description={t('agenda.settings.blockOutsideDesc')} checked={s.get('blockOutside')} onChange={(v) => s.set('blockOutside', v)} />\n </SettingsGroup>\n\n <SettingsGroup title={t('agenda.settings.confirmations')} description={t('agenda.settings.confirmationsDesc')}>\n <ToggleRow label={t('agenda.settings.enableConfirmations')} description={t('agenda.settings.enableConfirmationsDesc')} checked={s.get('enableConfirmations')} onChange={(v) => s.set('enableConfirmations', v)} />\n <ToggleRow label={t('agenda.settings.autoConfirm')} description={t('agenda.settings.autoConfirmDesc')} checked={s.get('autoConfirm')} onChange={(v) => s.set('autoConfirm', v)} />\n <ToggleRow label={t('agenda.settings.reminder')} description={t('agenda.settings.reminderDesc')} checked={s.get('reminder')} onChange={(v) => s.set('reminder', v)} />\n </SettingsGroup>\n\n <SettingsGroup title={t('agenda.settings.calendarDisplay')} description={t('agenda.settings.calendarDisplayDesc')}>\n <SelectRow\n label={t('agenda.settings.dayStartTime')}\n description={t('agenda.settings.dayStartTimeDesc')}\n value={startTime}\n options={HOUR_OPTIONS}\n onChange={setStartTime}\n />\n <SelectRow\n label={t('agenda.settings.dayEndTime')}\n description={t('agenda.settings.dayEndTimeDesc')}\n value={endTime}\n options={HOUR_OPTIONS}\n onChange={setEndTime}\n />\n <ToggleRow label={t('agenda.settings.showCancelled')} description={t('agenda.settings.showCancelledDesc')} checked={s.get('showCancelled')} onChange={(v) => s.set('showCancelled', v)} />\n <ToggleRow label={t('agenda.settings.showNoShow')} description={t('agenda.settings.showNoShowDesc')} checked={s.get('showNoShow')} onChange={(v) => s.set('showNoShow', v)} />\n <ToggleRow label={t('agenda.settings.compact')} description={t('agenda.settings.compactDesc')} checked={s.get('compact')} onChange={(v) => s.set('compact', v)} />\n </SettingsGroup>\n\n <SettingsGroup title={t('agenda.settings.notifications')} description={t('agenda.settings.notificationsDesc')}>\n <ToggleRow label={t('agenda.settings.newBookingNotif')} description={t('agenda.settings.newBookingNotifDesc')} checked={s.get('newBookingNotif')} onChange={(v) => s.set('newBookingNotif', v)} />\n <ToggleRow label={t('agenda.settings.cancelAlerts')} description={t('agenda.settings.cancelAlertsDesc')} checked={s.get('cancelAlerts')} onChange={(v) => s.set('cancelAlerts', v)} />\n <ToggleRow label={t('agenda.settings.noShowTracking')} description={t('agenda.settings.noShowTrackingDesc')} checked={s.get('noShowTracking')} onChange={(v) => s.set('noShowTracking', v)} />\n </SettingsGroup>\n </div>\n )\n}\n","// agenda.* — merged plugin-own + saas-core central i18n\nexport const en: Record<string, string> = {\n \"agenda.appointment.addDescription\": \"Add description...\",\n \"agenda.appointment.addService\": \"Add service\",\n \"agenda.appointment.cancel\": \"Cancel\",\n \"agenda.appointment.clientTab\": \"Client\",\n \"agenda.appointment.noClientData\": \"No client data available\",\n \"agenda.appointment.client\": \"Client\",\n \"agenda.appointment.conflict\": \"Time conflict — this professional is already booked at this time.\",\n \"agenda.appointment.create\": \"Create\",\n \"agenda.appointment.createClientFailed\": \"Failed to create client\",\n \"agenda.appointment.creating\": \"Creating...\",\n \"agenda.appointment.delete\": \"Delete\",\n \"agenda.appointment.deleteConfirm\": \"Delete this appointment?\",\n \"agenda.appointment.confirmDelete\": \"Delete\",\n \"agenda.appointment.deleting\": \"Deleting…\",\n \"agenda.appointment.edit\": \"Edit Appointment\",\n \"agenda.appointment.emailOptional\": \"Email (optional)\",\n \"agenda.appointment.location\": \"Location\",\n \"agenda.appointment.name\": \"Name\",\n \"agenda.appointment.new\": \"New Appointment\",\n \"agenda.appointment.newClient\": \"New client\",\n \"agenda.appointment.notes\": \"Notes\",\n \"agenda.appointment.phone\": \"Phone\",\n \"agenda.appointment.professional\": \"Professional\",\n \"agenda.appointment.save\": \"Save\",\n \"agenda.appointment.saving\": \"Saving...\",\n \"agenda.appointment.searchClient\": \"Search client...\",\n \"agenda.appointment.searchService\": \"Search service to add...\",\n \"agenda.appointment.selectLocation\": \"Select location...\",\n \"agenda.appointment.selectProfessional\": \"Select professional...\",\n \"agenda.appointment.selectClientHint\": \"Select the client from the list or use New client to enable saving.\",\n \"agenda.appointment.services\": \"Services\",\n \"agenda.appointment.status\": \"Status\",\n \"agenda.appointment.to\": \"to\",\n \"agenda.appointment.total\": \"Total\",\n \"agenda.appointment.update\": \"Update\",\n \"agenda.payment.title\": \"Payment\",\n \"agenda.payment.generateInvoice\": \"Generate invoice\",\n \"agenda.payment.generating\": \"Generating…\",\n \"agenda.payment.pending\": \"Pending\",\n \"agenda.payment.partial\": \"Partial\",\n \"agenda.payment.paid\": \"Paid\",\n \"agenda.payment.collect\": \"Collect\",\n \"agenda.payment.overdue\": \"Overdue\",\n \"agenda.payment.cancelled\": \"Cancelled\",\n \"agenda.payment.none\": \"Payment\",\n \"agenda.payment.pay\": \"Pay\",\n \"agenda.payment.paying\": \"Paying…\",\n \"agenda.payment.remaining\": \"Remaining\",\n \"agenda.payment.installment\": \"Installment\",\n \"agenda.payment.total\": \"Total\",\n \"agenda.payment.noInvoice\": \"No invoice generated\",\n \"agenda.payment.selectAccount\": \"Select account\",\n \"agenda.payment.registerPayment\": \"Register payment\",\n \"agenda.payment.registerPaymentHint\": \"Record a payment for this appointment\",\n \"agenda.payment.pendingHint\": \"Invoice generated, awaiting payment\",\n \"agenda.payment.partialHint\": \"Partially paid, tap to complete\",\n \"agenda.payment.paidHint\": \"Payment completed\",\n \"agenda.payment.overdueHint\": \"Payment overdue\",\n \"agenda.payment.backToAppointment\": \"Back to appointment\",\n \"agenda.payment.checkout\": \"Confirm\",\n \"agenda.payment.checkingOut\": \"Processing…\",\n \"agenda.payment.serviceSummary\": \"Service summary\",\n \"agenda.payment.paymentMethod\": \"Payment method\",\n \"agenda.payment.noMethods\": \"No payment methods configured.\",\n \"agenda.payment.configureMethods\": \"Set up payment methods\",\n \"agenda.payment.checkoutComplete\": \"Payment confirmed\",\n \"agenda.payment.card\": \"Card\",\n \"agenda.payment.method\": \"Method\",\n \"agenda.payment.select\": \"Select…\",\n \"agenda.payment.cardBrand\": \"Brand\",\n \"agenda.payment.selectBrand\": \"Select brand…\",\n \"agenda.payment.cardInstallments\": \"Installments\",\n \"agenda.payment.bankAccount\": \"Account\",\n \"agenda.payment.viewInvoice\": \"View invoice details\",\n \"agenda.calendar.agendas\": \"Agendas\",\n \"agenda.calendar.create\": \"Create\",\n \"agenda.calendar.next\": \"Next\",\n \"agenda.calendar.previous\": \"Previous\",\n \"agenda.calendar.status\": \"Status\",\n \"agenda.calendar.today\": \"Today\",\n \"agenda.calendar.viewAgenda\": \"Agenda\",\n \"agenda.calendar.viewDay\": \"Day\",\n \"agenda.calendar.viewList\": \"List\",\n \"agenda.calendar.viewMonth\": \"Month\",\n \"agenda.calendar.viewWeek\": \"Week\",\n \"agenda.list.today\": \"Today\",\n \"agenda.list.tomorrow\": \"Tomorrow\",\n \"agenda.list.empty\": \"No upcoming items\",\n \"agenda.confirmations.confirmed\": \"Confirmed:\",\n \"agenda.confirmations.empty\": \"No pending confirmations\",\n \"agenda.confirmations.emptySubtitle\": \"All upcoming appointments have been confirmed\",\n \"agenda.confirmations.loading\": \"Loading...\",\n \"agenda.confirmations.subtitle\": \"Upcoming appointments pending confirmation\",\n \"agenda.confirmations.unknownClient\": \"Unknown client\",\n \"agenda.confirmations.sendWhatsApp\": \"Send WhatsApp\",\n \"agenda.confirmations.call\": \"Call\",\n \"agenda.confirmations.markConfirmed\": \"Mark Confirmed\",\n \"agenda.confirmations.markCancelled\": \"Mark Cancelled\",\n \"agenda.cancellation.loadingReasons\": \"Loading reasons...\",\n \"agenda.cancellation.notesOptional\": \"Cancellation notes (optional)\",\n \"agenda.cancellation.notesRequired\": \"Cancellation notes required\",\n \"agenda.cancellation.selectReason\": \"Select cancellation reason\",\n \"agenda.contextMenu.changeStatus\": \"Change status\",\n \"agenda.contextMenu.delete\": \"Delete\",\n \"agenda.contextMenu.edit\": \"Edit\",\n \"agenda.contextMenu.notAvailable\": \"(not available)\",\n \"agenda.index.settingsSubtitle\": \"Working hours, scheduling preferences, and confirmations\",\n \"agenda.index.settingsTitle\": \"Agenda Settings\",\n \"settings.plugin.agenda-working-hours\": \"Working Hours\",\n \"agenda.popover.unknown\": \"Unknown\",\n \"agenda.settings.autoConfirm\": \"Auto-confirm\",\n \"agenda.settings.autoConfirmDesc\": \"Automatically confirm new bookings\",\n \"agenda.settings.autoCreateOrder\": \"Auto-create Order\",\n \"agenda.settings.autoCreateOrderDesc\": \"Automatically create a financial order for new bookings\",\n \"agenda.settings.blockOutside\": \"Block Outside Hours\",\n \"agenda.settings.blockOutsideDesc\": \"Prevent bookings outside working hours\",\n \"agenda.settings.calendarDisplay\": \"Calendar Display\",\n \"agenda.settings.calendarDisplayDesc\": \"Visual settings for the calendar\",\n \"agenda.settings.cancelAlerts\": \"Cancellation Alerts\",\n \"agenda.settings.cancelAlertsDesc\": \"Notify when a booking is cancelled\",\n \"agenda.settings.compact\": \"Compact Mode\",\n \"agenda.settings.compactDesc\": \"Use smaller event blocks\",\n \"agenda.settings.confirmations\": \"Confirmations\",\n \"agenda.settings.confirmationsDesc\": \"Booking confirmation settings\",\n \"agenda.settings.conflictDetection\": \"Conflict Detection\",\n \"agenda.settings.conflictDetectionDesc\": \"Warn when bookings overlap\",\n \"agenda.settings.dragDrop\": \"Drag & Drop\",\n \"agenda.settings.dragDropDesc\": \"Allow rescheduling by dragging events\",\n \"agenda.settings.enableConfirmations\": \"Enable Confirmations\",\n \"agenda.settings.enableConfirmationsDesc\": \"Require confirmation for new bookings\",\n \"agenda.settings.enableLocation\": \"Enable Location Selection\",\n \"agenda.settings.enableLocationDesc\": \"Show location picker in booking modal\",\n \"agenda.settings.enableWorkingHours\": \"Enable Working Hours\",\n \"agenda.settings.enableWorkingHoursDesc\": \"Show working hours overlay on calendar\",\n \"agenda.settings.locations\": \"Locations\",\n \"agenda.settings.locationsDesc\": \"Multi-location settings\",\n \"agenda.settings.newBookingNotif\": \"New Booking Alerts\",\n \"agenda.settings.newBookingNotifDesc\": \"Notify when a new booking is created\",\n \"agenda.settings.noShowTracking\": \"No-show Tracking\",\n \"agenda.settings.noShowTrackingDesc\": \"Track and alert on no-shows\",\n \"agenda.settings.notifications\": \"Notifications\",\n \"agenda.settings.notificationsDesc\": \"Notification preferences\",\n \"agenda.settings.reminder\": \"Reminders\",\n \"agenda.settings.reminderDesc\": \"Send reminders before appointments\",\n \"agenda.settings.scheduling\": \"Scheduling\",\n \"agenda.settings.schedulingDesc\": \"Configure scheduling behavior\",\n \"agenda.settings.showCancelled\": \"Show Cancelled\",\n \"agenda.settings.showCancelledDesc\": \"Display cancelled bookings on calendar\",\n \"agenda.settings.showNoShow\": \"Show No-shows\",\n \"agenda.settings.showNoShowDesc\": \"Display no-show bookings on calendar\",\n \"agenda.settings.workingHours\": \"Working Hours\",\n \"agenda.settings.workingHoursDesc\": \"Working hours and availability\",\n \"agenda.sidebar.agendas\": \"Agendas\",\n \"agenda.sidebar.allLocations\": \"All locations\",\n \"agenda.sidebar.create\": \"Create\",\n \"agenda.sidebar.location\": \"Location\",\n \"agenda.sidebar.status\": \"Status\",\n \"agenda.toolbar.next\": \"Next\",\n \"agenda.toolbar.previous\": \"Previous\",\n \"agenda.toolbar.today\": \"Today\",\n \"agenda.workingHours.addBreak\": \"Add break\",\n \"agenda.workingHours.copyToAll\": \"Copy to all\",\n \"agenda.workingHours.dayOff\": \"Day off\",\n \"agenda.workingHours.removePeriod\": \"Remove period\",\n \"agenda.workingHours.professional\": \"Professional\",\n \"agenda.workingHours.save\": \"Save\",\n \"agenda.workingHours.saveFailed\": \"Failed to save\",\n \"agenda.workingHours.saved\": \"Working hours saved\",\n \"agenda.workingHours.saving\": \"Saving...\",\n \"agenda.workingHours.subtitle\": \"Manage working hours per professional\",\n \"agenda.workingHours.to\": \"to\",\n \"agenda.title\": \"Agenda\",\n \"agenda.calendar.title\": \"Calendar\",\n \"agenda.calendar.noScheduleConfirm\": \"This time slot has no open schedule for this professional. Do you want to book anyway?\",\n \"agenda.calendar.newAppointment\": \"New Appointment\",\n \"agenda.booking.create\": \"New Appointment\",\n \"agenda.booking.edit\": \"Edit Appointment\",\n \"agenda.booking.delete\": \"Delete Appointment\",\n \"agenda.booking.deleteConfirm\": \"Are you sure you want to delete this appointment?\",\n \"agenda.booking.client\": \"Client\",\n \"agenda.booking.professional\": \"Professional\",\n \"agenda.booking.services\": \"Services\",\n \"agenda.booking.date\": \"Date\",\n \"agenda.booking.time\": \"Time\",\n \"agenda.booking.duration\": \"Duration\",\n \"agenda.booking.notes\": \"Notes\",\n \"agenda.booking.status\": \"Status\",\n \"agenda.booking.save\": \"Save Appointment\",\n \"agenda.booking.saving\": \"Saving...\",\n \"agenda.confirmations.title\": \"Confirmations\",\n \"agenda.confirmations.pending\": \"Pending Confirmations\",\n \"agenda.confirmations.emptyDescription\": \"All upcoming appointments have been confirmed\",\n \"agenda.confirmations.confirm\": \"Confirm\",\n \"agenda.confirmations.cancel\": \"Cancel\",\n \"agenda.workingHours.title\": \"Working Hours\",\n \"agenda.workingHours.addPeriod\": \"Add period\",\n \"agenda.workingHours.loading\": \"Loading...\",\n \"agenda.appointment.addClient\": \"Add client\",\n \"agenda.appointment.addServiceFirst\": \"Add service\",\n \"agenda.appointment.addNotes\": \"Add notes\",\n \"agenda.appointment.duration\": \"Duration (minutes)\",\n \"agenda.appointment.price\": \"Price\",\n \"agenda.appointment.title\": \"Title\",\n \"agenda.appointment.addTitle\": \"Add a title\",\n \"agenda.appointment.untitled\": \"(no title)\",\n \"agenda.bookingType.appointment\": \"Appointment\",\n \"agenda.bookingType.event\": \"Event\",\n \"agenda.bookingType.task\": \"Task\",\n \"agenda.bookingType.out_of_office\": \"Out of Office\",\n \"agenda.bookingType.block\": \"Block\",\n \"agenda.settings.title\": \"Agenda Settings\",\n \"agenda.settings.slotDuration\": \"Slot Duration\",\n \"agenda.settings.bookingKind\": \"Booking Kind\",\n \"agenda.settings.dayStartTime\": \"Day Start Time\",\n \"agenda.settings.dayStartTimeDesc\": \"First hour shown on the calendar\",\n \"agenda.settings.dayEndTime\": \"Day End Time\",\n \"agenda.settings.dayEndTimeDesc\": \"Last hour shown on the calendar\",\n}\n","// agenda.* — merged plugin-own + saas-core central i18n\nexport const ptBR: Record<string, string> = {\n \"agenda.appointment.addDescription\": \"Adicionar descrição...\",\n \"agenda.appointment.addService\": \"Adicionar serviço\",\n \"agenda.appointment.cancel\": \"Cancelar\",\n \"agenda.appointment.clientTab\": \"Cliente\",\n \"agenda.appointment.noClientData\": \"Dados do cliente não disponíveis\",\n \"agenda.appointment.client\": \"Cliente\",\n \"agenda.appointment.conflict\": \"Conflito de horário — este profissional já está reservado neste horário.\",\n \"agenda.appointment.create\": \"Criar\",\n \"agenda.appointment.createClientFailed\": \"Falha ao criar cliente\",\n \"agenda.appointment.creating\": \"Criando...\",\n \"agenda.appointment.delete\": \"Excluir\",\n \"agenda.appointment.deleteConfirm\": \"Excluir este agendamento?\",\n \"agenda.appointment.confirmDelete\": \"Excluir\",\n \"agenda.appointment.deleting\": \"Excluindo…\",\n \"agenda.appointment.edit\": \"Editar Agendamento\",\n \"agenda.appointment.emailOptional\": \"E-mail (opcional)\",\n \"agenda.appointment.location\": \"Local\",\n \"agenda.appointment.name\": \"Nome\",\n \"agenda.appointment.new\": \"Novo Agendamento\",\n \"agenda.appointment.newClient\": \"Novo cliente\",\n \"agenda.appointment.notes\": \"Observações\",\n \"agenda.appointment.phone\": \"Telefone\",\n \"agenda.appointment.professional\": \"Profissional\",\n \"agenda.appointment.save\": \"Salvar\",\n \"agenda.appointment.saving\": \"Salvando...\",\n \"agenda.appointment.searchClient\": \"Buscar cliente...\",\n \"agenda.appointment.searchService\": \"Buscar serviço para adicionar...\",\n \"agenda.appointment.selectLocation\": \"Selecionar local...\",\n \"agenda.appointment.selectProfessional\": \"Selecionar profissional...\",\n \"agenda.appointment.selectClientHint\": \"Selecione o cliente na lista ou use Novo cliente para habilitar o salvamento.\",\n \"agenda.appointment.services\": \"Serviços\",\n \"agenda.appointment.status\": \"Status\",\n \"agenda.appointment.to\": \"até\",\n \"agenda.appointment.total\": \"Total\",\n \"agenda.appointment.update\": \"Atualizar\",\n \"agenda.payment.title\": \"Recebimento\",\n \"agenda.payment.generateInvoice\": \"Gerar recebimento\",\n \"agenda.payment.generating\": \"Gerando…\",\n \"agenda.payment.pending\": \"Pendente\",\n \"agenda.payment.partial\": \"Parcial\",\n \"agenda.payment.paid\": \"Pago\",\n \"agenda.payment.collect\": \"Receber\",\n \"agenda.payment.overdue\": \"Vencido\",\n \"agenda.payment.cancelled\": \"Cancelado\",\n \"agenda.payment.none\": \"Recebimento\",\n \"agenda.payment.pay\": \"Pagar\",\n \"agenda.payment.paying\": \"Pagando…\",\n \"agenda.payment.remaining\": \"Restante\",\n \"agenda.payment.installment\": \"Parcela\",\n \"agenda.payment.total\": \"Total\",\n \"agenda.payment.noInvoice\": \"Sem recebimento gerado\",\n \"agenda.payment.selectAccount\": \"Selecionar conta\",\n \"agenda.payment.registerPayment\": \"Registrar recebimento\",\n \"agenda.payment.registerPaymentHint\": \"Registrar pagamento deste agendamento\",\n \"agenda.payment.pendingHint\": \"Fatura gerada, aguardando pagamento\",\n \"agenda.payment.partialHint\": \"Parcialmente pago, toque para completar\",\n \"agenda.payment.paidHint\": \"Pagamento realizado\",\n \"agenda.payment.overdueHint\": \"Pagamento vencido\",\n \"agenda.payment.backToAppointment\": \"Voltar ao agendamento\",\n \"agenda.payment.checkout\": \"Confirmar\",\n \"agenda.payment.checkingOut\": \"Processando…\",\n \"agenda.payment.serviceSummary\": \"Resumo do atendimento\",\n \"agenda.payment.paymentMethod\": \"Forma de pagamento\",\n \"agenda.payment.noMethods\": \"Nenhuma forma de pagamento configurada.\",\n \"agenda.payment.configureMethods\": \"Configurar formas de pagamento\",\n \"agenda.payment.checkoutComplete\": \"Pagamento confirmado\",\n \"agenda.payment.card\": \"Cartão\",\n \"agenda.payment.method\": \"Método\",\n \"agenda.payment.select\": \"Selecionar…\",\n \"agenda.payment.cardBrand\": \"Bandeira\",\n \"agenda.payment.selectBrand\": \"Selecionar bandeira…\",\n \"agenda.payment.cardInstallments\": \"Parcelas\",\n \"agenda.payment.bankAccount\": \"Conta\",\n \"agenda.payment.viewInvoice\": \"Ver detalhes da fatura\",\n \"agenda.calendar.agendas\": \"Agendas\",\n \"agenda.calendar.create\": \"Criar\",\n \"agenda.calendar.next\": \"Próximo\",\n \"agenda.calendar.previous\": \"Anterior\",\n \"agenda.calendar.status\": \"Status\",\n \"agenda.calendar.today\": \"Hoje\",\n \"agenda.calendar.viewAgenda\": \"Agenda\",\n \"agenda.calendar.viewDay\": \"Dia\",\n \"agenda.calendar.viewList\": \"Lista\",\n \"agenda.calendar.viewMonth\": \"Mês\",\n \"agenda.calendar.viewWeek\": \"Semana\",\n \"agenda.list.today\": \"Hoje\",\n \"agenda.list.tomorrow\": \"Amanhã\",\n \"agenda.list.empty\": \"Nenhum item próximo\",\n \"agenda.confirmations.confirmed\": \"Confirmado:\",\n \"agenda.confirmations.empty\": \"Nenhuma confirmação pendente\",\n \"agenda.confirmations.emptySubtitle\": \"Todos os agendamentos futuros foram confirmados\",\n \"agenda.confirmations.loading\": \"Carregando...\",\n \"agenda.confirmations.subtitle\": \"Agendamentos futuros pendentes de confirmação\",\n \"agenda.confirmations.unknownClient\": \"Cliente desconhecido\",\n \"agenda.confirmations.sendWhatsApp\": \"Enviar WhatsApp\",\n \"agenda.confirmations.call\": \"Ligar\",\n \"agenda.confirmations.markConfirmed\": \"Marcar Confirmado\",\n \"agenda.confirmations.markCancelled\": \"Marcar Cancelado\",\n \"agenda.cancellation.loadingReasons\": \"Carregando motivos...\",\n \"agenda.cancellation.notesOptional\": \"Observações do cancelamento (opcional)\",\n \"agenda.cancellation.notesRequired\": \"Observações do cancelamento obrigatórias\",\n \"agenda.cancellation.selectReason\": \"Selecionar motivo do cancelamento\",\n \"agenda.contextMenu.changeStatus\": \"Alterar status\",\n \"agenda.contextMenu.delete\": \"Excluir\",\n \"agenda.contextMenu.edit\": \"Editar\",\n \"agenda.contextMenu.notAvailable\": \"(indisponível)\",\n \"agenda.index.settingsSubtitle\": \"Horários de funcionamento, preferências de agendamento e confirmações\",\n \"agenda.index.settingsTitle\": \"Configurações da Agenda\",\n \"settings.plugin.agenda-working-hours\": \"Horário de Funcionamento\",\n \"agenda.popover.unknown\": \"Desconhecido\",\n \"agenda.settings.autoConfirm\": \"Confirmar Automaticamente\",\n \"agenda.settings.autoConfirmDesc\": \"Confirmar automaticamente novos agendamentos\",\n \"agenda.settings.autoCreateOrder\": \"Criar Pedido Automaticamente\",\n \"agenda.settings.autoCreateOrderDesc\": \"Criar automaticamente um pedido financeiro para novos agendamentos\",\n \"agenda.settings.blockOutside\": \"Bloquear Fora do Horário\",\n \"agenda.settings.blockOutsideDesc\": \"Impedir agendamentos fora do horário de funcionamento\",\n \"agenda.settings.calendarDisplay\": \"Exibição do Calendário\",\n \"agenda.settings.calendarDisplayDesc\": \"Configurações visuais do calendário\",\n \"agenda.settings.cancelAlerts\": \"Alertas de Cancelamento\",\n \"agenda.settings.cancelAlertsDesc\": \"Notificar quando um agendamento é cancelado\",\n \"agenda.settings.compact\": \"Modo Compacto\",\n \"agenda.settings.compactDesc\": \"Usar blocos de eventos menores\",\n \"agenda.settings.confirmations\": \"Confirmações\",\n \"agenda.settings.confirmationsDesc\": \"Configurações de confirmação de agendamento\",\n \"agenda.settings.conflictDetection\": \"Detecção de Conflitos\",\n \"agenda.settings.conflictDetectionDesc\": \"Alertar quando agendamentos se sobrepõem\",\n \"agenda.settings.dragDrop\": \"Arrastar e Soltar\",\n \"agenda.settings.dragDropDesc\": \"Permitir reagendamento arrastando eventos\",\n \"agenda.settings.enableConfirmations\": \"Habilitar Confirmações\",\n \"agenda.settings.enableConfirmationsDesc\": \"Exigir confirmação para novos agendamentos\",\n \"agenda.settings.enableLocation\": \"Habilitar Seleção de Local\",\n \"agenda.settings.enableLocationDesc\": \"Mostrar seletor de local no modal de agendamento\",\n \"agenda.settings.enableWorkingHours\": \"Habilitar Horário de Funcionamento\",\n \"agenda.settings.enableWorkingHoursDesc\": \"Mostrar sobreposição de horário de funcionamento no calendário\",\n \"agenda.settings.locations\": \"Locais\",\n \"agenda.settings.locationsDesc\": \"Configurações de múltiplos locais\",\n \"agenda.settings.newBookingNotif\": \"Alertas de Novo Agendamento\",\n \"agenda.settings.newBookingNotifDesc\": \"Notificar quando um novo agendamento é criado\",\n \"agenda.settings.noShowTracking\": \"Rastreamento de Ausências\",\n \"agenda.settings.noShowTrackingDesc\": \"Rastrear e alertar sobre ausências\",\n \"agenda.settings.notifications\": \"Notificações\",\n \"agenda.settings.notificationsDesc\": \"Preferências de notificação\",\n \"agenda.settings.reminder\": \"Lembretes\",\n \"agenda.settings.reminderDesc\": \"Enviar lembretes antes dos compromissos\",\n \"agenda.settings.scheduling\": \"Agendamento\",\n \"agenda.settings.schedulingDesc\": \"Configurar comportamento do agendamento\",\n \"agenda.settings.showCancelled\": \"Mostrar Cancelados\",\n \"agenda.settings.showCancelledDesc\": \"Exibir agendamentos cancelados no calendário\",\n \"agenda.settings.showNoShow\": \"Mostrar Ausências\",\n \"agenda.settings.showNoShowDesc\": \"Exibir ausências no calendário\",\n \"agenda.settings.workingHours\": \"Horário de Funcionamento\",\n \"agenda.settings.workingHoursDesc\": \"Horários e disponibilidade\",\n \"agenda.sidebar.agendas\": \"Agendas\",\n \"agenda.sidebar.allLocations\": \"Todos os locais\",\n \"agenda.sidebar.create\": \"Criar\",\n \"agenda.sidebar.location\": \"Local\",\n \"agenda.sidebar.status\": \"Status\",\n \"agenda.toolbar.next\": \"Próximo\",\n \"agenda.toolbar.previous\": \"Anterior\",\n \"agenda.toolbar.today\": \"Hoje\",\n \"agenda.workingHours.addBreak\": \"Adicionar intervalo\",\n \"agenda.workingHours.copyToAll\": \"Copiar para todos\",\n \"agenda.workingHours.dayOff\": \"Folga\",\n \"agenda.workingHours.removePeriod\": \"Remover período\",\n \"agenda.workingHours.professional\": \"Profissional\",\n \"agenda.workingHours.save\": \"Salvar\",\n \"agenda.workingHours.saveFailed\": \"Falha ao salvar\",\n \"agenda.workingHours.saved\": \"Horários de trabalho salvos\",\n \"agenda.workingHours.saving\": \"Salvando...\",\n \"agenda.workingHours.subtitle\": \"Gerenciar horários de trabalho por profissional\",\n \"agenda.workingHours.to\": \"até\",\n \"agenda.title\": \"Agenda\",\n \"agenda.calendar.title\": \"Calendário\",\n \"agenda.calendar.noScheduleConfirm\": \"Este horário não possui agenda aberta para este profissional. Deseja agendar mesmo assim?\",\n \"agenda.calendar.newAppointment\": \"Novo Agendamento\",\n \"agenda.booking.create\": \"Novo Agendamento\",\n \"agenda.booking.edit\": \"Editar Agendamento\",\n \"agenda.booking.delete\": \"Excluir Agendamento\",\n \"agenda.booking.deleteConfirm\": \"Tem certeza que deseja excluir este agendamento?\",\n \"agenda.booking.client\": \"Cliente\",\n \"agenda.booking.professional\": \"Profissional\",\n \"agenda.booking.services\": \"Serviços\",\n \"agenda.booking.date\": \"Data\",\n \"agenda.booking.time\": \"Horário\",\n \"agenda.booking.duration\": \"Duração\",\n \"agenda.booking.notes\": \"Observações\",\n \"agenda.booking.status\": \"Status\",\n \"agenda.booking.save\": \"Salvar Agendamento\",\n \"agenda.booking.saving\": \"Salvando...\",\n \"agenda.confirmations.title\": \"Confirmações\",\n \"agenda.confirmations.pending\": \"Confirmações Pendentes\",\n \"agenda.confirmations.emptyDescription\": \"Todos os agendamentos futuros foram confirmados\",\n \"agenda.confirmations.confirm\": \"Confirmar\",\n \"agenda.confirmations.cancel\": \"Cancelar\",\n \"agenda.workingHours.title\": \"Horário de Trabalho\",\n \"agenda.workingHours.addPeriod\": \"Adicionar período\",\n \"agenda.workingHours.loading\": \"Carregando...\",\n \"agenda.appointment.addClient\": \"Adicionar cliente\",\n \"agenda.appointment.addServiceFirst\": \"Adicionar serviço\",\n \"agenda.appointment.addNotes\": \"Adicionar observações\",\n \"agenda.appointment.duration\": \"Duração (minutos)\",\n \"agenda.appointment.price\": \"Preço\",\n \"agenda.appointment.title\": \"Título\",\n \"agenda.appointment.addTitle\": \"Adicionar um título\",\n \"agenda.appointment.untitled\": \"(sem título)\",\n \"agenda.bookingType.appointment\": \"Agendamento\",\n \"agenda.bookingType.event\": \"Evento\",\n \"agenda.bookingType.task\": \"Tarefa\",\n \"agenda.bookingType.out_of_office\": \"Ausência\",\n \"agenda.bookingType.block\": \"Bloqueio\",\n \"agenda.settings.title\": \"Configurações da Agenda\",\n \"agenda.settings.slotDuration\": \"Duração do Intervalo\",\n \"agenda.settings.bookingKind\": \"Tipo de Agendamento\",\n \"agenda.settings.dayStartTime\": \"Horário de Início\",\n \"agenda.settings.dayStartTimeDesc\": \"Primeiro horário exibido no calendário\",\n \"agenda.settings.dayEndTime\": \"Horário de Término\",\n \"agenda.settings.dayEndTimeDesc\": \"Último horário exibido no calendário\",\n}\n","import { en } from './en'\nimport { ptBR } from './pt-BR'\n\nexport const agendaLocales: Record<string, Record<string, string>> = {\n en,\n 'pt-BR': ptBR,\n}\n","// AUTO-GENERATED from 000b_v_bookings_rename.sql, 000c_dedupe_customer_phones.sql, 001_public_booking.sql, 002_v_bookings_compat.sql, 003_public_client_kind.sql, 004_public_booking_assignee.sql, 005_agent_rpcs.sql, 006_agent_rpc_localtime.sql, 007_schedule_exception_precedence.sql, 008_agent_rpc_exception_precedence.sql, 009_public_booking_location.sql, 010_public_service_curation.sql, 011_default_assignee.sql, 012_drop_legacy_booking_overload.sql, 013_normalize_v_appointments.sql, 014_agent_rpc_update_appointment.sql — regenerate with scripts/embed-migrations.mjs\n// SQL files are the source of truth; this inline copy lets the manifest declare\n// migrations as data. Do not edit by hand — run the embed script instead.\n\nexport const MIGRATION_000B_V_BOOKINGS_RENAME = `-- Salon-only unblock: the pre-pools beauty deployment built rep_* report\n-- views on top of its (wider) v_bookings view, so 001's cleanup DROP cannot\n-- run there. Renaming keeps the dependents attached (they track the OID) and\n-- frees the name for 001; 002_v_bookings_compat re-creates v_bookings as a\n-- thin alias for live pre-M5 clients. No-op on fresh pools and on pools whose\n-- v_bookings has no dependents (001's DROP handles those).\n\nDO $rename$\nBEGIN\n IF to_regclass('public.v_bookings') IS NOT NULL\n AND to_regclass('public.v_bookings_legacy_beauty') IS NULL\n AND EXISTS (\n SELECT 1 FROM pg_depend d\n JOIN pg_rewrite rw ON rw.oid = d.objid\n JOIN pg_class dep ON dep.oid = rw.ev_class\n JOIN pg_class ref ON ref.oid = d.refobjid\n WHERE ref.relname = 'v_bookings' AND dep.relname <> 'v_bookings'\n ) THEN\n EXECUTE 'ALTER VIEW public.v_bookings RENAME TO v_bookings_legacy_beauty';\n END IF;\nEND $rename$;\n`\n\nexport const MIGRATION_000C_DEDUPE_CUSTOMER_PHONES = `-- 001 needs the customer-phone upsert key UNIQUE(tenant_id, phone). Converted\n-- pools can carry duplicates (found live on salon: 9 dogfood test records all\n-- sharing the founder's phone). Non-destructive dedupe: per (tenant_id, phone)\n-- customer group keep the row with most appointments (tie: oldest), NULL the\n-- phone on the rest and stash the original in metadata->'dedupedPhone'.\n-- Idempotent: reruns find no groups > 1.\n\nDO $dedupe$\nDECLARE\n r record;\nBEGIN\n IF to_regclass('public.people') IS NULL THEN\n RETURN;\n END IF;\n\n FOR r IN\n SELECT p.id, p.phone\n FROM public.people p\n JOIN LATERAL (\n SELECT count(*) AS appts\n FROM public.appointments a WHERE a.party_id = p.id\n ) ac ON true\n WHERE p.kind = 'customer' AND p.phone IS NOT NULL\n AND p.id NOT IN (\n SELECT DISTINCT ON (p2.tenant_id, p2.phone) p2.id\n FROM public.people p2\n WHERE p2.kind = 'customer' AND p2.phone IS NOT NULL\n ORDER BY p2.tenant_id, p2.phone,\n (SELECT count(*) FROM public.appointments a2 WHERE a2.party_id = p2.id) DESC,\n p2.created_at ASC\n )\n AND (p.tenant_id, p.phone) IN (\n SELECT tenant_id, phone FROM public.people\n WHERE kind = 'customer' AND phone IS NOT NULL\n GROUP BY tenant_id, phone HAVING count(*) > 1\n )\n LOOP\n UPDATE public.people\n SET metadata = COALESCE(metadata, '{}'::jsonb) || jsonb_build_object('dedupedPhone', r.phone),\n phone = NULL\n WHERE id = r.id;\n END LOOP;\nEND $dedupe$;\n`\n\nexport const MIGRATION_001_PUBLIC_BOOKING = `-- ============================================================================\n-- plugin-agenda 001: booking read model + public (anon) booking surface\n--\n-- Ships the objects the agenda providers reference but the spine (packages/db\n-- migrations 001–010) does not define:\n-- §0 converted-pool cleanup — drop the pre-rename v_bookings view / indexes\n-- §1 order_items columns the admin provider writes (duration/assignee)\n-- §2 public.v_appointments — admin read model (authenticated, RLS applies)\n-- §3 public.v_public_services — anon-readable service catalog\n-- §4 public.get_available_slots — anon RPC (mirrors the mock algorithm)\n-- §5 public.create_public_booking — anon RPC (validated, race-safe write)\n--\n-- Core v1 lives directly in PUBLIC (no separate core schema): people (was\n-- persons), appointments (was bookings). This migration is written against public\n-- names and is idempotent + safe on both fresh and converted pools.\n--\n-- Anon-access design: public booking pages run with the publishable key and no\n-- session, so the canonical tenant RLS yields nothing. Anon access is granted\n-- ONLY via the column-whitelisted view (§3) and SECURITY DEFINER RPCs (§4, §5)\n-- with tight input validation and hardcoded statuses.\n-- ============================================================================\n\n-- §0 — converted-pool cleanup. The pre-industry-pool shape shipped a v_bookings\n-- view and persons_/bookings_-named indexes; drop them so this file re-emits the\n-- canonical v_appointments view + people_/appointments_ indexes without leaving\n-- duplicates. All guarded with IF EXISTS → no-ops on a fresh pool.\nDROP VIEW IF EXISTS public.v_bookings;\nDROP INDEX IF EXISTS public.persons_tenant_customer_phone;\nDROP INDEX IF EXISTS public.bookings_assignee_time;\n\n-- §1 — columns the agenda provider writes but 004_archetypes lacks\nALTER TABLE public.order_items\n ADD COLUMN IF NOT EXISTS duration_minutes integer,\n ADD COLUMN IF NOT EXISTS assignee_id uuid REFERENCES public.people(id) ON DELETE SET NULL;\n\n-- Upsert key for public customers (per tenant, by normalized phone)\nCREATE UNIQUE INDEX IF NOT EXISTS people_tenant_customer_phone\n ON public.people(tenant_id, phone)\n WHERE kind = 'customer' AND phone IS NOT NULL;\n\n-- Slot-conflict scan\nCREATE INDEX IF NOT EXISTS appointments_assignee_time\n ON public.appointments(assignee_id, starts_at, ends_at)\n WHERE status NOT IN ('cancelled', 'no_show');\n\n-- §2 — admin read model (security_invoker → underlying RLS applies; anon sees 0 rows)\n-- DROP first: 013 widens this view and CREATE OR REPLACE cannot narrow a live\n-- view on replay (\"cannot drop columns from view\"). 013 replays right after.\nDROP VIEW IF EXISTS public.v_appointments;\nCREATE VIEW public.v_appointments\nWITH (security_invoker = true) AS\nSELECT\n b.id, b.tenant_id, b.kind, b.starts_at, b.ends_at, b.status, b.notes,\n b.order_id, b.location_id, b.metadata, b.created_at, b.updated_at,\n b.party_id AS client_id,\n COALESCE(pc.name, b.metadata->>'title') AS client_name,\n pc.phone AS client_phone,\n pc.email AS client_email,\n pc.avatar_url AS client_avatar_url,\n b.assignee_id AS professional_id,\n ps.name AS professional_name,\n ps.avatar_url AS professional_avatar_url,\n l.name AS location_name,\n o.total AS order_total,\n o.status AS order_status,\n (EXTRACT(EPOCH FROM (COALESCE(b.ends_at, b.starts_at) - b.starts_at))::int / 60)\n AS total_duration_minutes\nFROM public.appointments b\nLEFT JOIN public.people pc ON pc.id = b.party_id\nLEFT JOIN public.people ps ON ps.id = b.assignee_id\nLEFT JOIN public.locations l ON l.id = b.location_id\nLEFT JOIN public.orders o ON o.id = b.order_id;\n\nGRANT SELECT ON public.v_appointments TO authenticated, service_role;\nREVOKE SELECT ON public.v_appointments FROM anon;\n\n-- §3 — anon-readable public catalog (owner-rights view = deliberate, whitelisted)\n-- DROP first: 010 widens this view (curation columns) — same replay rule as §2.\nDROP VIEW IF EXISTS public.v_public_services;\nCREATE VIEW public.v_public_services AS\nSELECT\n s.id, s.tenant_id, s.name, s.description, s.price, s.currency,\n COALESCE(s.duration_minutes, 30) AS duration_minutes,\n s.image_url,\n COALESCE((s.metadata->>'sort_order')::int, 0) AS sort_order\nFROM public.services s\nWHERE s.is_active AND s.status = 'active';\n\nGRANT SELECT ON public.v_public_services TO anon, authenticated, service_role;\n\n-- §4 — availability RPC (mirrors plugin-agenda/src/data/mock.ts getAvailableSlots)\nCREATE OR REPLACE FUNCTION public.get_available_slots(\n p_tenant_id uuid,\n p_date date,\n p_duration_minutes integer,\n p_assignee_id uuid DEFAULT NULL,\n p_slot_interval integer DEFAULT 30\n) RETURNS TABLE (slot_start timestamptz, slot_end timestamptz)\nLANGUAGE plpgsql STABLE SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_tz text;\nBEGIN\n -- tight validation: this function is anon-callable\n IF p_duration_minutes IS NULL OR p_duration_minutes NOT BETWEEN 5 AND 480 THEN\n RAISE EXCEPTION 'invalid duration';\n END IF;\n IF p_slot_interval IS NULL OR p_slot_interval NOT BETWEEN 5 AND 240 THEN\n RAISE EXCEPTION 'invalid interval';\n END IF;\n IF p_date IS NULL OR p_date < current_date OR p_date > current_date + 90 THEN\n RETURN;\n END IF;\n\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RETURN; END IF; -- unknown tenant → empty, not an error\n\n RETURN QUERY\n WITH day_schedules AS (\n SELECT sc.assignee_id, sc.starts_at AS win_start, sc.ends_at AS win_end\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (p_assignee_id IS NULL OR sc.assignee_id = p_assignee_id)\n AND (\n sc.specific_date = p_date\n OR (sc.specific_date IS NULL AND sc.day_of_week = EXTRACT(dow FROM p_date)::smallint)\n )\n ),\n candidate AS (\n SELECT\n ds.assignee_id,\n gs AS s_start,\n gs + make_interval(mins => p_duration_minutes) AS s_end\n FROM day_schedules ds\n CROSS JOIN LATERAL generate_series(\n (p_date + ds.win_start) AT TIME ZONE v_tz,\n ((p_date + ds.win_end) AT TIME ZONE v_tz) - make_interval(mins => p_duration_minutes),\n make_interval(mins => p_slot_interval)\n ) AS gs\n )\n SELECT DISTINCT c.s_start, c.s_end\n FROM candidate c\n WHERE NOT EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = c.assignee_id\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < c.s_end\n AND COALESCE(b.ends_at, b.starts_at) > c.s_start\n )\n ORDER BY 1;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.get_available_slots(uuid, date, integer, uuid, integer) FROM public;\nGRANT EXECUTE ON FUNCTION public.get_available_slots(uuid, date, integer, uuid, integer)\n TO anon, authenticated, service_role;\n\n-- §5 — public booking write RPC (validated, race-safe, hardcoded statuses)\nCREATE OR REPLACE FUNCTION public.create_public_booking(\n p_tenant_id uuid,\n p_service_id uuid,\n p_starts_at timestamptz,\n p_name text,\n p_phone text,\n p_email text DEFAULT NULL,\n p_notes text DEFAULT NULL\n) RETURNS TABLE (booking_id uuid, starts_at timestamptz, ends_at timestamptz)\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n\n -- pick the assignee whose working hours cover the slot\n SELECT sc.assignee_id INTO v_assignee\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (\n sc.specific_date = (p_starts_at AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM p_starts_at AT TIME ZONE v_tz)::smallint)\n )\n AND (p_starts_at AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the customer by (tenant, phone) — matches people_tenant_customer_phone\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, 'customer', trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n ON CONFLICT (tenant_id, phone) WHERE kind = 'customer' AND phone IS NOT NULL\n DO UPDATE SET\n name = EXCLUDED.name,\n email = COALESCE(EXCLUDED.email, people.email),\n updated_at = now()\n RETURNING id INTO v_person_id;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text) FROM public;\nGRANT EXECUTE ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text)\n TO anon, authenticated, service_role;\n`\n\nexport const MIGRATION_002_V_BOOKINGS_COMPAT = `-- Where 000b preserved the legacy beauty view, re-create v_bookings as a\n-- thin alias over it so live pre-M5 clients that SELECT v_bookings by name\n-- keep their full legacy column set. Dropped for good once the beauty app\n-- ships on v_appointments (M5 follow-up).\n\nDO $compat$\nBEGIN\n IF to_regclass('public.v_bookings_legacy_beauty') IS NOT NULL\n AND to_regclass('public.v_bookings') IS NULL THEN\n EXECUTE 'CREATE VIEW public.v_bookings WITH (security_invoker = true) AS SELECT * FROM public.v_bookings_legacy_beauty';\n EXECUTE 'GRANT SELECT ON public.v_bookings TO authenticated, service_role';\n EXECUTE 'REVOKE SELECT ON public.v_bookings FROM anon';\n END IF;\nEND $compat$;\n`\n\nexport const MIGRATION_003_PUBLIC_CLIENT_KIND = `-- ---------------------------------------------------------------------------\n-- Public booking — tenant-configurable client kind\n-- ---------------------------------------------------------------------------\n-- 001 hardcoded kind='customer' for people created by create_public_booking.\n-- Verticals whose client archetype uses another kind (school → 'student',\n-- clinic → whatever the app registers) ended up with people invisible to the\n-- app's own pages/lookups and with entity links resolving to unregistered\n-- routes (#/customers/:id → not found).\n--\n-- The client kind now comes from TENANT SETTINGS (admin-controlled — never\n-- from the anon caller): tenants.settings.booking.client_kind\n-- Default remains 'customer', so existing pools/tenants are unaffected until\n-- they opt in:\n-- UPDATE tenants SET settings = jsonb_set(COALESCE(settings,'{}'::jsonb),\n-- '{booking,client_kind}', '\"student\"') WHERE id = '<tenant>';\n--\n-- The upsert no longer relies on the kind-specific partial unique index\n-- (people_tenant_customer_phone) — a per-(tenant, phone) advisory lock\n-- serializes concurrent first-bookings for any kind. The 001 index stays in\n-- place (harmless, still guards direct customer writes).\n--\n-- Idempotent: CREATE OR REPLACE, same signature as 001.\n-- ---------------------------------------------------------------------------\nCREATE OR REPLACE FUNCTION public.create_public_booking(\n p_tenant_id uuid,\n p_service_id uuid,\n p_starts_at timestamptz,\n p_name text,\n p_phone text,\n p_email text DEFAULT NULL,\n p_notes text DEFAULT NULL\n) RETURNS TABLE (booking_id uuid, starts_at timestamptz, ends_at timestamptz)\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\n v_client_kind text;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n\n -- tenant config: timezone + client kind (admin-set; sanitized, never caller input)\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo'),\n COALESCE(NULLIF(trim(t.settings->'booking'->>'client_kind'), ''), 'customer')\n INTO v_tz, v_client_kind\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n IF v_client_kind !~ '^[a-z_]{2,32}$' THEN v_client_kind := 'customer'; END IF;\n\n -- pick the assignee whose working hours cover the slot\n SELECT sc.assignee_id INTO v_assignee\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (\n sc.specific_date = (p_starts_at AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM p_starts_at AT TIME ZONE v_tz)::smallint)\n )\n AND (p_starts_at AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the client by (tenant, kind, phone). Kind is tenant-configured, so\n -- the 001 customer-only partial index can't arbitrate — a per-(tenant,\n -- phone) advisory lock serializes concurrent first-bookings instead.\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || ':' || v_phone, 1));\n\n SELECT p.id INTO v_person_id\n FROM people p\n WHERE p.tenant_id = p_tenant_id AND p.kind = v_client_kind AND p.phone = v_phone\n ORDER BY p.created_at\n LIMIT 1;\n\n IF v_person_id IS NOT NULL THEN\n UPDATE people SET\n name = trim(p_name),\n email = COALESCE(p_email, people.email),\n updated_at = now()\n WHERE id = v_person_id;\n ELSE\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, v_client_kind, trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n RETURNING id INTO v_person_id;\n END IF;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text) FROM public;\nGRANT EXECUTE ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text)\n TO anon, authenticated, service_role;\n`\n\nexport const MIGRATION_004_PUBLIC_BOOKING_ASSIGNEE = `-- ---------------------------------------------------------------------------\n-- Public booking — respect the professional the visitor saw\n-- ---------------------------------------------------------------------------\n-- Until now create_public_booking IGNORED which professional the site showed\n-- availability for and re-picked by working hours (ORDER BY assignee_id\n-- LIMIT 1). With several professionals covering the same slot the booking\n-- landed on someone else than displayed (\"Equipe Great DJs\" on the site,\n-- \"Rafa Groove\" in the agenda). New optional p_assignee_id:\n-- * provided → validate THAT professional's working hours cover the slot and\n-- book them — never silently reassign (mismatch becomes an explicit error);\n-- * NULL → auto-pick as before (sites that don't pin a professional).\n-- Conflict check + advisory lock already run against the resolved assignee, so\n-- the double-book guard follows whichever path resolves.\n--\n-- Signature change (8th arg): the old 7-arg function is DROPPED first —\n-- CREATE OR REPLACE with a different signature would create an ambiguous\n-- PostgREST overload instead of replacing.\n-- Includes 003's tenant-configurable client kind. Idempotent.\n-- ---------------------------------------------------------------------------\nDROP FUNCTION IF EXISTS public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text);\n\nCREATE OR REPLACE FUNCTION public.create_public_booking(\n p_tenant_id uuid,\n p_service_id uuid,\n p_starts_at timestamptz,\n p_name text,\n p_phone text,\n p_email text DEFAULT NULL,\n p_notes text DEFAULT NULL,\n p_assignee_id uuid DEFAULT NULL\n) RETURNS TABLE (booking_id uuid, starts_at timestamptz, ends_at timestamptz)\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\n v_client_kind text;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n\n -- tenant config: timezone + client kind (admin-set; sanitized, never caller input)\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo'),\n COALESCE(NULLIF(trim(t.settings->'booking'->>'client_kind'), ''), 'customer')\n INTO v_tz, v_client_kind\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n IF v_client_kind !~ '^[a-z_]{2,32}$' THEN v_client_kind := 'customer'; END IF;\n\n -- resolve the professional: the one the visitor saw (validated), else the\n -- first whose working hours cover the slot\n SELECT sc.assignee_id INTO v_assignee\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (p_assignee_id IS NULL OR sc.assignee_id = p_assignee_id)\n AND (\n sc.specific_date = (p_starts_at AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM p_starts_at AT TIME ZONE v_tz)::smallint)\n )\n AND (p_starts_at AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the client by (tenant, kind, phone), serialized by advisory lock\n -- (kind is tenant-configured, so the customer-only partial index can't\n -- arbitrate)\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || ':' || v_phone, 1));\n\n SELECT p.id INTO v_person_id\n FROM people p\n WHERE p.tenant_id = p_tenant_id AND p.kind = v_client_kind AND p.phone = v_phone\n ORDER BY p.created_at\n LIMIT 1;\n\n IF v_person_id IS NOT NULL THEN\n UPDATE people SET\n name = trim(p_name),\n email = COALESCE(p_email, people.email),\n updated_at = now()\n WHERE id = v_person_id;\n ELSE\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, v_client_kind, trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n RETURNING id INTO v_person_id;\n END IF;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text, uuid) FROM public;\nGRANT EXECUTE ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text, uuid)\n TO anon, authenticated, service_role;\n`\n\nexport const MIGRATION_005_AGENT_RPCS = `-- ============================================================================\n-- plugin-agenda 005: server-plane agent write RPC.\n--\n-- public.agent_agenda_create_appointment — the INTERNAL (operator-actor)\n-- counterpart of create_public_booking (001 §5): same invariants (working\n-- hours, advisory-lock race safety, hardcoded statuses), but:\n-- * actor-authorized: public.agent_guard (spine 015) runs role→plan→limit\n-- BEFORE anything — denial comes back as a structured jsonb the agent can\n-- explain conversationally, never a raised exception;\n-- * the client is an EXISTING person id (the agent resolves names→ids via\n-- reads first — ambiguity is a conversation problem, not a SQL one);\n-- * a requested professional is honored (working hours permitting);\n-- * audited: audit_logs row with the acting user.\n--\n-- Contract (all agent_* RPCs): (p_tenant_id, p_actor_user_id, p_payload jsonb)\n-- → jsonb {ok:true, id, record:{...}} | {ok:false, denial:{...}} | {ok:false,\n-- error text}. GRANT authenticated+service_role — NEVER anon (the Fayz broker\n-- calls with the pool service key and injects tenant/actor server-side).\n-- ============================================================================\n\nCREATE OR REPLACE FUNCTION public.agent_agenda_create_appointment(\n p_tenant_id uuid,\n p_actor_user_id uuid,\n p_payload jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_denial jsonb;\n v_used int;\n v_client_id uuid;\n v_service_id uuid;\n v_professional uuid;\n v_starts timestamptz;\n v_notes text;\n v_service record;\n v_client record;\n v_ends timestamptz;\n v_tz text;\n v_order uuid;\n v_booking uuid;\nBEGIN\n -- ── payload ──────────────────────────────────────────────────────────────\n BEGIN\n v_client_id := (p_payload->>'client_id')::uuid;\n v_service_id := (p_payload->>'service_id')::uuid;\n v_professional := (p_payload->>'professional_id')::uuid;\n v_starts := (p_payload->>'starts_at')::timestamptz;\n EXCEPTION WHEN OTHERS THEN\n RETURN jsonb_build_object('ok', false, 'error', 'invalid payload: ' || SQLERRM);\n END;\n v_notes := left(p_payload->>'notes', 500);\n IF v_client_id IS NULL OR v_service_id IS NULL OR v_starts IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'client_id, service_id and starts_at are required');\n END IF;\n IF v_starts <= now() OR v_starts > now() + interval '365 days' THEN\n RETURN jsonb_build_object('ok', false, 'error', 'starts_at must be in the future (max 1 year)');\n END IF;\n\n -- ── authorization: role → plan → bookings_month cap ──────────────────────\n SELECT count(*) INTO v_used FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.created_at >= date_trunc('month', now());\n v_denial := agent_guard(p_tenant_id, p_actor_user_id,\n 'appointments', 'create', 'bookings_month', v_used, 1);\n IF v_denial IS NOT NULL THEN\n RETURN jsonb_build_object('ok', false, 'denial', v_denial);\n END IF;\n\n -- ── invariants ───────────────────────────────────────────────────────────\n SELECT p.id, p.name INTO v_client\n FROM people p\n WHERE p.id = v_client_id AND p.tenant_id = p_tenant_id;\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown client for this tenant');\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = v_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown or inactive service');\n END IF;\n\n v_ends := v_starts + make_interval(mins => v_service.duration_minutes);\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n\n -- requested professional honored; otherwise pick one whose hours cover the slot\n SELECT sc.assignee_id INTO v_professional\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (v_professional IS NULL OR sc.assignee_id = v_professional)\n AND (\n sc.specific_date = (v_starts AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM v_starts AT TIME ZONE v_tz)::smallint)\n )\n AND (v_starts AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_professional IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'slot outside working hours for the requested professional');\n END IF;\n\n -- race safety: serialize per (tenant, professional), then conflict-check\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_professional::text, 0));\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_professional\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n ) THEN\n RETURN jsonb_build_object('ok', false, 'error', 'slot no longer available');\n END IF;\n\n -- ── write (statuses hardcoded) + audit ───────────────────────────────────\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_client_id, v_professional,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_client_id, v_professional, v_order,\n v_starts, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_professional);\n\n INSERT INTO audit_logs (tenant_id, user_id, action, entity_type, entity_id, metadata)\n VALUES (p_tenant_id, p_actor_user_id, 'agent.createAppointment', 'appointment', v_booking::text,\n jsonb_build_object('payload', p_payload, 'order_id', v_order));\n\n RETURN jsonb_build_object(\n 'ok', true,\n 'id', v_booking,\n 'record', jsonb_build_object(\n 'ref', jsonb_build_object('id', v_booking, 'resource', 'appointments',\n 'archetype', 'schedule:appointment'),\n 'starts_at', v_starts,\n 'ends_at', v_ends,\n 'client_name', v_client.name,\n 'service_name', v_service.name,\n 'price', v_service.price,\n 'status', 'scheduled'\n )\n );\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM public;\nREVOKE EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM anon;\nGRANT EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb)\n TO authenticated, service_role;\n`\n\nexport const MIGRATION_006_AGENT_RPC_LOCALTIME = `-- ============================================================================\n-- plugin-agenda 006: agent_agenda_create_appointment speaks LOCAL time.\n--\n-- Models reliably mangle UTC↔local offsets (\"10h\" became 13:00 BRT via a\n-- wrong sign). The RPC knows the tenant's timezone — so stop asking the model\n-- to convert: \\`starts_at\\` WITHOUT an offset (2026-07-27T10:00) is interpreted\n-- in the tenant tz; an explicit offset still works. The result now carries\n-- starts_at_local/ends_at_local strings so the reply echoes the truth in the\n-- user's own clock. Supersedes 005's function body (new file — applied\n-- migrations are never edited).\n-- ============================================================================\n\nCREATE OR REPLACE FUNCTION public.agent_agenda_create_appointment(\n p_tenant_id uuid,\n p_actor_user_id uuid,\n p_payload jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_denial jsonb;\n v_used int;\n v_client_id uuid;\n v_service_id uuid;\n v_professional uuid;\n v_starts timestamptz;\n v_starts_raw text;\n v_notes text;\n v_service record;\n v_client record;\n v_ends timestamptz;\n v_tz text;\n v_order uuid;\n v_booking uuid;\nBEGIN\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown tenant');\n END IF;\n\n -- ── payload ──────────────────────────────────────────────────────────────\n BEGIN\n v_client_id := (p_payload->>'client_id')::uuid;\n v_service_id := (p_payload->>'service_id')::uuid;\n v_professional := (p_payload->>'professional_id')::uuid;\n v_starts_raw := p_payload->>'starts_at';\n IF v_starts_raw ~ '(Z|[+-][0-9]{2}:?[0-9]{2})$' THEN\n v_starts := v_starts_raw::timestamptz; -- explicit offset\n ELSE\n v_starts := (v_starts_raw::timestamp) AT TIME ZONE v_tz; -- tenant-local\n END IF;\n EXCEPTION WHEN OTHERS THEN\n RETURN jsonb_build_object('ok', false, 'error', 'invalid payload: ' || SQLERRM);\n END;\n v_notes := left(p_payload->>'notes', 500);\n IF v_client_id IS NULL OR v_service_id IS NULL OR v_starts IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'client_id, service_id and starts_at are required');\n END IF;\n IF v_starts <= now() OR v_starts > now() + interval '365 days' THEN\n RETURN jsonb_build_object('ok', false, 'error', 'starts_at must be in the future (max 1 year)');\n END IF;\n\n -- ── authorization: role → plan → bookings_month cap ──────────────────────\n SELECT count(*) INTO v_used FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.created_at >= date_trunc('month', now());\n v_denial := agent_guard(p_tenant_id, p_actor_user_id,\n 'appointments', 'create', 'bookings_month', v_used, 1);\n IF v_denial IS NOT NULL THEN\n RETURN jsonb_build_object('ok', false, 'denial', v_denial);\n END IF;\n\n -- ── invariants ───────────────────────────────────────────────────────────\n SELECT p.id, p.name INTO v_client\n FROM people p\n WHERE p.id = v_client_id AND p.tenant_id = p_tenant_id;\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown client for this tenant');\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = v_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown or inactive service');\n END IF;\n\n v_ends := v_starts + make_interval(mins => v_service.duration_minutes);\n\n SELECT sc.assignee_id INTO v_professional\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (v_professional IS NULL OR sc.assignee_id = v_professional)\n AND (\n sc.specific_date = (v_starts AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM v_starts AT TIME ZONE v_tz)::smallint)\n )\n AND (v_starts AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n -- prefer a professional who is actually FREE at the slot (when the user\n -- did not name one, the first busy professional must not block the booking)\n AND NOT EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = sc.assignee_id\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n )\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_professional IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'no professional is available at that slot (outside working hours or already booked). Suggest a different time. Times are tenant-local, tz ' || v_tz);\n END IF;\n\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_professional::text, 0));\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_professional\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n ) THEN\n RETURN jsonb_build_object('ok', false, 'error', 'slot no longer available');\n END IF;\n\n -- ── write + audit ────────────────────────────────────────────────────────\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_client_id, v_professional,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_client_id, v_professional, v_order,\n v_starts, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_professional);\n\n INSERT INTO audit_logs (tenant_id, user_id, action, entity_type, entity_id, metadata)\n VALUES (p_tenant_id, p_actor_user_id, 'agent.createAppointment', 'appointment', v_booking::text,\n jsonb_build_object('payload', p_payload, 'order_id', v_order));\n\n RETURN jsonb_build_object(\n 'ok', true,\n 'id', v_booking,\n 'record', jsonb_build_object(\n 'ref', jsonb_build_object('id', v_booking, 'resource', 'appointments',\n 'archetype', 'schedule:appointment'),\n 'starts_at', v_starts,\n 'ends_at', v_ends,\n 'starts_at_local', to_char(v_starts AT TIME ZONE v_tz, 'YYYY-MM-DD (Dy) HH24:MI') || ' ' || v_tz,\n 'ends_at_local', to_char(v_ends AT TIME ZONE v_tz, 'HH24:MI'),\n 'client_name', v_client.name,\n 'service_name', v_service.name,\n 'price', v_service.price,\n 'status', 'scheduled'\n )\n );\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM public;\nREVOKE EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM anon;\nGRANT EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb)\n TO authenticated, service_role;\n`\n\nexport const MIGRATION_007_SCHEDULE_EXCEPTION_PRECEDENCE = `-- ============================================================================\n-- plugin-agenda 007: specific-date exceptions take PRECEDENCE over weekly hours.\n--\n-- The admin ScheduleEditor (saveException) writes two kinds of specific-date\n-- rows: 'available' = active rows with custom windows for the date; day off\n-- ('unavailable') = ONE inactive 00:00–00:00 sentinel. Until now every reader\n-- treated schedules as a flat union filtered by is_active, so:\n-- • a day off was INVISIBLE (inactive sentinel filtered out, weekly rows\n-- still matched) — the public site kept selling a day the admin closed;\n-- • an 'available' exception ADDED to the weekly hours instead of replacing\n-- them (\"horário especial\" should define the date's hours).\n--\n-- Fix: one helper — agenda_working_windows(tenant, date, assignee) — is now the\n-- single source of a day's windows: if ANY specific-date row exists for an\n-- assignee (active or sentinel), only the ACTIVE specific-date rows count for\n-- that assignee; otherwise the weekly (day_of_week) rows apply. Both readers\n-- are redefined on top of it:\n-- • get_available_slots — body otherwise identical to the latest version\n-- (google-calendar/002_smart_sync §5, tenant-wide 'block' clause KEPT);\n-- • create_public_booking — body otherwise identical to 004.\n--\n-- ORDERING: on pools with the Google Calendar connector this file must run\n-- AFTER integrations/google-calendar/migrations/002_smart_sync.sql (both\n-- redefine get_available_slots; 007 is the superset and must win). Re-running\n-- 007 last is always safe — it preserves 002's block semantics.\n-- ============================================================================\n\n-- ----------------------------------------------------------------------------\n-- §1 agenda_working_windows — the day's working windows, exception-aware.\n-- ----------------------------------------------------------------------------\nCREATE OR REPLACE FUNCTION public.agenda_working_windows(\n p_tenant_id uuid,\n p_date date,\n p_assignee_id uuid DEFAULT NULL\n) RETURNS TABLE (assignee_id uuid, win_start time, win_end time)\nLANGUAGE sql STABLE\nSET search_path = public\nAS $$\n WITH exc AS (\n -- Every specific-date row for the date, ACTIVE OR NOT: the inactive day-off\n -- sentinel must still suppress the weekly rows below.\n SELECT sc.assignee_id, sc.starts_at, sc.ends_at, sc.is_active\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.specific_date = p_date\n AND (p_assignee_id IS NULL OR sc.assignee_id = p_assignee_id)\n )\n SELECT e.assignee_id, e.starts_at, e.ends_at\n FROM exc e\n WHERE e.is_active\n UNION ALL\n SELECT sc.assignee_id, sc.starts_at, sc.ends_at\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM p_date)::smallint\n AND (p_assignee_id IS NULL OR sc.assignee_id = p_assignee_id)\n AND NOT EXISTS (SELECT 1 FROM exc e WHERE e.assignee_id = sc.assignee_id)\n$$;\n\nREVOKE ALL ON FUNCTION public.agenda_working_windows(uuid, date, uuid) FROM public;\nREVOKE EXECUTE ON FUNCTION public.agenda_working_windows(uuid, date, uuid) FROM anon;\nGRANT EXECUTE ON FUNCTION public.agenda_working_windows(uuid, date, uuid)\n TO authenticated, service_role;\n\n-- ----------------------------------------------------------------------------\n-- §2 get_available_slots — day_schedules now comes from the helper.\n-- Everything else is byte-identical to google-calendar/002_smart_sync §5.\n-- ----------------------------------------------------------------------------\nCREATE OR REPLACE FUNCTION public.get_available_slots(\n p_tenant_id uuid,\n p_date date,\n p_duration_minutes integer,\n p_assignee_id uuid DEFAULT NULL,\n p_slot_interval integer DEFAULT 30\n) RETURNS TABLE (slot_start timestamptz, slot_end timestamptz)\nLANGUAGE plpgsql STABLE SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_tz text;\nBEGIN\n -- tight validation: this function is anon-callable\n IF p_duration_minutes IS NULL OR p_duration_minutes NOT BETWEEN 5 AND 480 THEN\n RAISE EXCEPTION 'invalid duration';\n END IF;\n IF p_slot_interval IS NULL OR p_slot_interval NOT BETWEEN 5 AND 240 THEN\n RAISE EXCEPTION 'invalid interval';\n END IF;\n IF p_date IS NULL OR p_date < current_date OR p_date > current_date + 90 THEN\n RETURN;\n END IF;\n\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RETURN; END IF; -- unknown tenant → empty, not an error\n\n RETURN QUERY\n WITH day_schedules AS (\n SELECT w.assignee_id, w.win_start, w.win_end\n FROM agenda_working_windows(p_tenant_id, p_date, p_assignee_id) w\n ),\n candidate AS (\n SELECT\n ds.assignee_id,\n gs AS s_start,\n gs + make_interval(mins => p_duration_minutes) AS s_end\n FROM day_schedules ds\n CROSS JOIN LATERAL generate_series(\n (p_date + ds.win_start) AT TIME ZONE v_tz,\n ((p_date + ds.win_end) AT TIME ZONE v_tz) - make_interval(mins => p_duration_minutes),\n make_interval(mins => p_slot_interval)\n ) AS gs\n )\n SELECT DISTINCT c.s_start, c.s_end\n FROM candidate c\n WHERE NOT EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n -- SMART SYNC (gcal 002): this professional's own bookings OR any\n -- tenant-wide BLOCK (assignee_id IS NULL AND kind='block') busy the slot.\n AND (b.assignee_id = c.assignee_id\n OR (b.assignee_id IS NULL AND b.kind = 'block'))\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < c.s_end\n AND COALESCE(b.ends_at, b.starts_at) > c.s_start\n )\n ORDER BY 1;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.get_available_slots(uuid, date, integer, uuid, integer) FROM public;\nGRANT EXECUTE ON FUNCTION public.get_available_slots(uuid, date, integer, uuid, integer)\n TO anon, authenticated, service_role;\n\n-- ----------------------------------------------------------------------------\n-- §3 create_public_booking — professional resolution goes through the helper\n-- (a booking on a closed date now fails 'slot outside working hours').\n-- Everything else is byte-identical to 004.\n-- ----------------------------------------------------------------------------\nCREATE OR REPLACE FUNCTION public.create_public_booking(\n p_tenant_id uuid,\n p_service_id uuid,\n p_starts_at timestamptz,\n p_name text,\n p_phone text,\n p_email text DEFAULT NULL,\n p_notes text DEFAULT NULL,\n p_assignee_id uuid DEFAULT NULL\n) RETURNS TABLE (booking_id uuid, starts_at timestamptz, ends_at timestamptz)\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\n v_client_kind text;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n\n -- tenant config: timezone + client kind (admin-set; sanitized, never caller input)\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo'),\n COALESCE(NULLIF(trim(t.settings->'booking'->>'client_kind'), ''), 'customer')\n INTO v_tz, v_client_kind\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n IF v_client_kind !~ '^[a-z_]{2,32}$' THEN v_client_kind := 'customer'; END IF;\n\n -- resolve the professional: the one the visitor saw (validated), else the\n -- first whose EXCEPTION-AWARE working hours cover the slot (007)\n SELECT w.assignee_id INTO v_assignee\n FROM agenda_working_windows(\n p_tenant_id, (p_starts_at AT TIME ZONE v_tz)::date, p_assignee_id) w\n WHERE (p_starts_at AT TIME ZONE v_tz)::time >= w.win_start\n AND (v_ends AT TIME ZONE v_tz)::time <= w.win_end\n ORDER BY w.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the client by (tenant, kind, phone), serialized by advisory lock\n -- (kind is tenant-configured, so the customer-only partial index can't\n -- arbitrate)\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || ':' || v_phone, 1));\n\n SELECT p.id INTO v_person_id\n FROM people p\n WHERE p.tenant_id = p_tenant_id AND p.kind = v_client_kind AND p.phone = v_phone\n ORDER BY p.created_at\n LIMIT 1;\n\n IF v_person_id IS NOT NULL THEN\n UPDATE people SET\n name = trim(p_name),\n email = COALESCE(p_email, people.email),\n updated_at = now()\n WHERE id = v_person_id;\n ELSE\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, v_client_kind, trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n RETURNING id INTO v_person_id;\n END IF;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text, uuid) FROM public;\nGRANT EXECUTE ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text, uuid)\n TO anon, authenticated, service_role;\n`\n\nexport const MIGRATION_008_AGENT_RPC_EXCEPTION_PRECEDENCE = `-- ============================================================================\n-- plugin-agenda 008: agent_agenda_create_appointment honors schedule exceptions.\n--\n-- Same precedence fix as 007, applied to the agent write path: professional\n-- resolution now goes through agenda_working_windows (007 §1), so a date the\n-- admin closed (day-off sentinel) or re-opened with custom hours (\"horário\n-- especial\") binds the agent exactly like it binds the public site. Everything\n-- else is byte-identical to 006 (LOCAL-time input, free-professional pick,\n-- advisory lock, audit). Requires 007. Supersedes 006's function body.\n-- ============================================================================\n\nCREATE OR REPLACE FUNCTION public.agent_agenda_create_appointment(\n p_tenant_id uuid,\n p_actor_user_id uuid,\n p_payload jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_denial jsonb;\n v_used int;\n v_client_id uuid;\n v_service_id uuid;\n v_professional uuid;\n v_starts timestamptz;\n v_starts_raw text;\n v_notes text;\n v_service record;\n v_client record;\n v_ends timestamptz;\n v_tz text;\n v_order uuid;\n v_booking uuid;\nBEGIN\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown tenant');\n END IF;\n\n -- ── payload ──────────────────────────────────────────────────────────────\n BEGIN\n v_client_id := (p_payload->>'client_id')::uuid;\n v_service_id := (p_payload->>'service_id')::uuid;\n v_professional := (p_payload->>'professional_id')::uuid;\n v_starts_raw := p_payload->>'starts_at';\n IF v_starts_raw ~ '(Z|[+-][0-9]{2}:?[0-9]{2})$' THEN\n v_starts := v_starts_raw::timestamptz; -- explicit offset\n ELSE\n v_starts := (v_starts_raw::timestamp) AT TIME ZONE v_tz; -- tenant-local\n END IF;\n EXCEPTION WHEN OTHERS THEN\n RETURN jsonb_build_object('ok', false, 'error', 'invalid payload: ' || SQLERRM);\n END;\n v_notes := left(p_payload->>'notes', 500);\n IF v_client_id IS NULL OR v_service_id IS NULL OR v_starts IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'client_id, service_id and starts_at are required');\n END IF;\n IF v_starts <= now() OR v_starts > now() + interval '365 days' THEN\n RETURN jsonb_build_object('ok', false, 'error', 'starts_at must be in the future (max 1 year)');\n END IF;\n\n -- ── authorization: role → plan → bookings_month cap ──────────────────────\n SELECT count(*) INTO v_used FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.created_at >= date_trunc('month', now());\n v_denial := agent_guard(p_tenant_id, p_actor_user_id,\n 'appointments', 'create', 'bookings_month', v_used, 1);\n IF v_denial IS NOT NULL THEN\n RETURN jsonb_build_object('ok', false, 'denial', v_denial);\n END IF;\n\n -- ── invariants ───────────────────────────────────────────────────────────\n SELECT p.id, p.name INTO v_client\n FROM people p\n WHERE p.id = v_client_id AND p.tenant_id = p_tenant_id;\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown client for this tenant');\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = v_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown or inactive service');\n END IF;\n\n v_ends := v_starts + make_interval(mins => v_service.duration_minutes);\n\n -- exception-aware windows (007); still prefer a professional who is FREE at\n -- the slot when the user did not name one\n SELECT w.assignee_id INTO v_professional\n FROM agenda_working_windows(\n p_tenant_id, (v_starts AT TIME ZONE v_tz)::date, v_professional) w\n WHERE (v_starts AT TIME ZONE v_tz)::time >= w.win_start\n AND (v_ends AT TIME ZONE v_tz)::time <= w.win_end\n AND NOT EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = w.assignee_id\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n )\n ORDER BY w.assignee_id\n LIMIT 1;\n IF v_professional IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'no professional is available at that slot (outside working hours or already booked). Suggest a different time. Times are tenant-local, tz ' || v_tz);\n END IF;\n\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_professional::text, 0));\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_professional\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n ) THEN\n RETURN jsonb_build_object('ok', false, 'error', 'slot no longer available');\n END IF;\n\n -- ── write + audit ────────────────────────────────────────────────────────\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_client_id, v_professional,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_client_id, v_professional, v_order,\n v_starts, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_professional);\n\n INSERT INTO audit_logs (tenant_id, user_id, action, entity_type, entity_id, metadata)\n VALUES (p_tenant_id, p_actor_user_id, 'agent.createAppointment', 'appointment', v_booking::text,\n jsonb_build_object('payload', p_payload, 'order_id', v_order));\n\n RETURN jsonb_build_object(\n 'ok', true,\n 'id', v_booking,\n 'record', jsonb_build_object(\n 'ref', jsonb_build_object('id', v_booking, 'resource', 'appointments',\n 'archetype', 'schedule:appointment'),\n 'starts_at', v_starts,\n 'ends_at', v_ends,\n 'starts_at_local', to_char(v_starts AT TIME ZONE v_tz, 'YYYY-MM-DD (Dy) HH24:MI') || ' ' || v_tz,\n 'ends_at_local', to_char(v_ends AT TIME ZONE v_tz, 'HH24:MI'),\n 'client_name', v_client.name,\n 'service_name', v_service.name,\n 'price', v_service.price,\n 'status', 'scheduled'\n )\n );\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM public;\nREVOKE EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM anon;\nGRANT EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb)\n TO authenticated, service_role;\n`\n\nexport const MIGRATION_009_PUBLIC_BOOKING_LOCATION = `-- Public bookings were written with location_id = NULL. The agenda's location\n-- filter is optional (default \"all\"), so they still rendered — but the moment\n-- an operator filtered by their unit, every booking taken from the website\n-- disappeared from the calendar. Single-location tenants are the common case\n-- and have an unambiguous answer, so default to it; multi-location tenants\n-- stay NULL (there is no correct guess) until the public flow asks.\n--\n-- Only the assignment is new; the rest of the body is unchanged from 004.\n\nCREATE OR REPLACE FUNCTION public.create_public_booking(\n p_tenant_id uuid,\n p_service_id uuid,\n p_starts_at timestamptz,\n p_name text,\n p_phone text,\n p_email text DEFAULT NULL,\n p_notes text DEFAULT NULL\n)\nRETURNS TABLE(booking_id uuid, starts_at timestamptz, ends_at timestamptz)\nLANGUAGE plpgsql\nSECURITY DEFINER\nSET search_path TO 'public'\nAS $function$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\n v_location uuid;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n\n -- pick the assignee whose working hours cover the slot\n SELECT sc.assignee_id INTO v_assignee\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (\n sc.specific_date = (p_starts_at AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM p_starts_at AT TIME ZONE v_tz)::smallint)\n )\n AND (p_starts_at AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- NEW: stamp the unit so the calendar's location filter keeps these visible.\n -- Prefer the schedule's own location; else the tenant's only location.\n SELECT sc.location_id INTO v_location\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND sc.assignee_id = v_assignee\n AND sc.location_id IS NOT NULL\n LIMIT 1;\n\n IF v_location IS NULL THEN\n SELECT l.id INTO v_location\n FROM locations l\n WHERE l.tenant_id = p_tenant_id\n HAVING count(*) = 1; -- unambiguous only\n END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the customer by (tenant, phone) — matches people_tenant_customer_phone\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, 'customer', trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n ON CONFLICT (tenant_id, phone) WHERE kind = 'customer' AND phone IS NOT NULL\n DO UPDATE SET\n name = EXCLUDED.name,\n email = COALESCE(EXCLUDED.email, people.email),\n updated_at = now()\n RETURNING id INTO v_person_id;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, location_id,\n subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee, v_location,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id, location_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order, v_location,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$function$;\n\nGRANT EXECUTE ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text) TO anon, authenticated;\n`\n\nexport const MIGRATION_010_PUBLIC_SERVICE_CURATION = `-- plugin-agenda 010: curate what the PUBLIC booking page sells.\n--\n-- v_public_services published every active service, so the website catalog was\n-- \"whatever exists in the system\". That conflates two different questions:\n--\n-- • is this service usable at all? → services.is_active / status\n-- • should a stranger be able to book it? → this flag\n--\n-- Without the split, hiding something from the site means deactivating it —\n-- which also removes it from the internal agenda and orphans its history. The\n-- case that forced this: a school whose public page listed 7 services when it\n-- sells 3, and one of the 4 extras already had real bookings attached.\n--\n-- OPT-OUT on purpose: a service is public unless explicitly marked otherwise.\n-- Opt-in would silently empty every live catalog the moment this ships.\n\nCREATE OR REPLACE VIEW public.v_public_services AS\nSELECT id,\n tenant_id,\n name,\n description,\n price,\n currency,\n COALESCE(duration_minutes, 30) AS duration_minutes,\n image_url,\n COALESCE(((metadata ->> 'sort_order'::text))::integer, 0) AS sort_order\n FROM services s\n WHERE is_active\n AND status = 'active'::text\n -- absent → public (back-compat). Only an explicit false hides it.\n AND COALESCE((metadata ->> 'bookableOnline'::text)::boolean, true);\n`\n\nexport const MIGRATION_011_DEFAULT_ASSIGNEE = `-- plugin-agenda 011: honour a tenant's default professional.\n--\n-- create_public_booking picks the assignee from whoever's working hours cover\n-- the slot, ordered by assignee_id — i.e. the lowest UUID wins. That is fine\n-- when the caller names the professional, and wrong when it does not: the\n-- public page confirms \"Equipe Great DJs\" while the booking silently lands on\n-- an unrelated instructor whose UUID happened to sort first.\n--\n-- Clients shipped before p_assignee_id existed still call this with 7 named\n-- args, so the parameter defaults to NULL and every live booking on those sites\n-- is mis-assigned today. Republishing the SDK fixes the caller, but the sites\n-- already deployed cannot be fixed that way — this can, from the database.\n--\n-- Precedence: explicit arg > tenant default > first covering schedule.\n-- Tenants without the setting keep exactly the previous behaviour.\n\nCREATE OR REPLACE FUNCTION public.create_public_booking(p_tenant_id uuid, p_service_id uuid, p_starts_at timestamp with time zone, p_name text, p_phone text, p_email text DEFAULT NULL::text, p_notes text DEFAULT NULL::text, p_assignee_id uuid DEFAULT NULL::uuid)\n RETURNS TABLE(booking_id uuid, starts_at timestamp with time zone, ends_at timestamp with time zone)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_requested uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\n v_client_kind text;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n\n -- tenant config: timezone + client kind (admin-set; sanitized, never caller input)\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo'),\n COALESCE(NULLIF(trim(t.settings->'booking'->>'client_kind'), ''), 'customer')\n INTO v_tz, v_client_kind\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n IF v_client_kind !~ '^[a-z_]{2,32}$' THEN v_client_kind := 'customer'; END IF;\n\n -- resolve the professional, in order of trust:\n -- 1. the id the caller sent (the one the visitor actually saw)\n -- 2. the tenant's configured default (settings->>'defaultAssigneeId')\n -- 3. whoever's working hours cover the slot\n --\n -- Step 2 is why this migration exists. Older published clients call this with\n -- 7 named args, leaving p_assignee_id NULL, and step 3 then resolved to\n -- \"lowest assignee UUID\" — an arbitrary instructor who had nothing to do with\n -- the name the site displayed on the confirmation screen. The default gives\n -- those clients a correct answer without waiting for a redeploy.\n v_requested := COALESCE(\n p_assignee_id,\n (SELECT NULLIF(t.settings ->> 'defaultAssigneeId', '')::uuid\n FROM tenants t WHERE t.id = p_tenant_id)\n );\n\n SELECT w.assignee_id INTO v_assignee\n FROM agenda_working_windows(\n p_tenant_id, (p_starts_at AT TIME ZONE v_tz)::date, v_requested) w\n WHERE (p_starts_at AT TIME ZONE v_tz)::time >= w.win_start\n AND (v_ends AT TIME ZONE v_tz)::time <= w.win_end\n ORDER BY w.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the client by (tenant, kind, phone), serialized by advisory lock\n -- (kind is tenant-configured, so the customer-only partial index can't\n -- arbitrate)\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || ':' || v_phone, 1));\n\n SELECT p.id INTO v_person_id\n FROM people p\n WHERE p.tenant_id = p_tenant_id AND p.kind = v_client_kind AND p.phone = v_phone\n ORDER BY p.created_at\n LIMIT 1;\n\n IF v_person_id IS NOT NULL THEN\n UPDATE people SET\n name = trim(p_name),\n email = COALESCE(p_email, people.email),\n updated_at = now()\n WHERE id = v_person_id;\n ELSE\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, v_client_kind, trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n RETURNING id INTO v_person_id;\n END IF;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$function$;\n`\n\nexport const MIGRATION_012_DROP_LEGACY_BOOKING_OVERLOAD = `-- plugin-agenda 012: retire the pre-assignee create_public_booking overload.\n--\n-- ⚠️ DO NOT APPLY UNTIL @fayz-ai/plugin-agenda IS REPUBLISHED *AND* EVERY LIVE\n-- SITE HAS BEEN REDEPLOYED. Applying early breaks public booking on any\n-- site still serving a bundle that calls the 7-argument signature — the\n-- call stops resolving and every submission fails.\n--\n-- Some pools carry two overloads side by side:\n-- create_public_booking(uuid,uuid,timestamptz,text,text,text,text)\n-- create_public_booking(uuid,uuid,timestamptz,text,text,text,text,uuid)\n--\n-- Nothing errors when both exist, which is exactly the problem: a stale client\n-- silently resolves to the 7-arg one, which cannot know which professional the\n-- visitor was shown and falls back to \"lowest assignee UUID\". The site confirms\n-- one name, the agenda records another, and no one finds out until someone\n-- compares the two screens.\n--\n-- 011 makes that fallback survivable (tenant default). This makes it\n-- impossible — but only once no caller needs the old signature.\n--\n-- Verify before running:\n-- 1. npm view @fayz-ai/plugin-agenda version → the republished version\n-- 2. every deployed bundle greps for p_assignee_id:\n-- curl -s https://<site>/assets/index-*.js | grep -c p_assignee_id\n-- Each must be ≥ 2 (slots + booking). Zero means that site still needs it.\n\nDROP FUNCTION IF EXISTS public.create_public_booking(\n uuid, uuid, timestamptz, text, text, text, text\n);\n`\n\nexport const MIGRATION_013_NORMALIZE_V_APPOINTMENTS = `-- plugin-agenda 013: one booking read model — v_appointments.\n--\n-- Three views described the same 34 rows:\n--\n-- v_bookings → thin alias over the legacy view (002 compat shim)\n-- v_bookings_legacy_beauty → the pre-pools shape, still feeding 5 rep_* views\n-- v_appointments → the canonical name, and the only one the SDK reads\n--\n-- The school pool already had only v_appointments; the salon pool carried all\n-- three. Same data, three names, and reports quietly wired to the oldest one.\n--\n-- v_appointments was a strict SUBSET, so it could not simply absorb them. It\n-- gains the 7 columns it lacked — most importantly \\`services\\`, the order_items\n-- aggregate that 4 of the 5 reports depend on. That also retires a documented\n-- N+1: getBookingById fetches order_items in a second round-trip precisely\n-- because this view had no line items (see plugin-agenda/src/data/supabase.ts).\n--\n-- Deliberately NOT copied from the legacy view:\n-- • total_duration_minutes — legacy sums order_items durations, the canonical\n-- measures the slot. They disagree, no report reads it, and the SDK relies\n-- on the canonical meaning. Kept as-is.\n-- • client_name — the canonical COALESCEs with metadata->>'title' so blocks\n-- and personal events show a label instead of NULL. Kept as-is (an\n-- improvement the legacy shape never had).\n\n-- 1. v_appointments becomes the superset. Columns are APPENDED: CREATE OR\n-- REPLACE VIEW cannot reorder or drop, and the SDK selects '*'.\nCREATE OR REPLACE VIEW public.v_appointments\nWITH (security_invoker = true) AS\n SELECT b.id,\n b.tenant_id,\n b.kind,\n b.starts_at,\n b.ends_at,\n b.status,\n b.notes,\n b.order_id,\n b.location_id,\n b.metadata,\n b.created_at,\n b.updated_at,\n b.party_id AS client_id,\n COALESCE(pc.name, (b.metadata ->> 'title'::text)) AS client_name,\n pc.phone AS client_phone,\n pc.email AS client_email,\n pc.avatar_url AS client_avatar_url,\n b.assignee_id AS professional_id,\n ps.name AS professional_name,\n ps.avatar_url AS professional_avatar_url,\n l.name AS location_name,\n o.total AS order_total,\n o.status AS order_status,\n ((EXTRACT(epoch FROM (COALESCE(b.ends_at, b.starts_at) - b.starts_at)))::integer / 60) AS total_duration_minutes,\n -- appended:\n o.reference_number,\n o.status AS stage,\n (o.metadata ->> 'direction'::text) AS direction,\n ( SELECT json_agg(json_build_object('id', oi.id, 'serviceId', oi.service_id,\n 'name', oi.name, 'durationMinutes', oi.duration_minutes,\n 'price', oi.unit_price, 'assigneeId', oi.assignee_id)\n ORDER BY oi.sort_order)\n FROM order_items oi\n WHERE (oi.order_id = b.order_id)) AS services,\n inv.status AS payment_status,\n inv.paid AS order_paid,\n inv.balance AS order_balance\n FROM (((((appointments b\n LEFT JOIN people pc ON ((pc.id = b.party_id)))\n LEFT JOIN people ps ON ((ps.id = b.assignee_id)))\n LEFT JOIN locations l ON ((l.id = b.location_id)))\n LEFT JOIN orders o ON ((o.id = b.order_id)))\n LEFT JOIN v_invoice_balances inv ON ((inv.invoice_id = b.order_id)));\n\n-- 2. Repoint the reports off the legacy view. Bodies are unchanged\n-- except for the source relation.\n\nCREATE OR REPLACE VIEW public.rep_appointments_by_period AS\nSELECT tenant_id,\n id AS booking_id,\n (starts_at)::date AS date,\n starts_at,\n client_id,\n client_name,\n professional_id,\n professional_name,\n COALESCE(((services -> 0) ->> 'name'::text), ((services -> 0) ->> 'serviceName'::text)) AS service_name,\n status,\n order_total AS revenue,\n created_at,\n updated_at\n FROM v_appointments b;\n\n-- legacy_pre_pools only exists on pools migrated from the pre-pool era; fresh\n-- pools get the same shape with confirmation columns defaulting to pending/NULL.\nDO $$\nBEGIN\n IF to_regclass('legacy_pre_pools.appointments') IS NOT NULL THEN\n EXECUTE $v$\n CREATE OR REPLACE VIEW public.rep_confirmation_queue AS\n SELECT b.tenant_id,\n b.id AS booking_id,\n (b.starts_at)::date AS date,\n b.starts_at,\n b.client_id,\n b.client_name,\n b.professional_id,\n b.professional_name,\n COALESCE(((b.services -> 0) ->> 'name'::text), ((b.services -> 0) ->> 'serviceName'::text)) AS service_name,\n COALESCE(a.confirmation_status, 'pending'::text) AS confirmation_status,\n a.confirmation_channel,\n a.confirmation_sent_at,\n a.confirmed_at,\n b.created_at,\n b.updated_at\n FROM (v_appointments b\n LEFT JOIN legacy_pre_pools.appointments a ON ((a.booking_id = b.id)))\n WHERE ((b.status <> ALL (ARRAY['cancelled'::text, 'no_show'::text])) AND (b.starts_at >= (now() - '1 day'::interval)))\n $v$;\n ELSE\n EXECUTE $v$\n CREATE OR REPLACE VIEW public.rep_confirmation_queue AS\n SELECT b.tenant_id,\n b.id AS booking_id,\n (b.starts_at)::date AS date,\n b.starts_at,\n b.client_id,\n b.client_name,\n b.professional_id,\n b.professional_name,\n COALESCE(((b.services -> 0) ->> 'name'::text), ((b.services -> 0) ->> 'serviceName'::text)) AS service_name,\n 'pending'::text AS confirmation_status,\n NULL::text AS confirmation_channel,\n NULL::timestamptz AS confirmation_sent_at,\n NULL::timestamptz AS confirmed_at,\n b.created_at,\n b.updated_at\n FROM v_appointments b\n WHERE ((b.status <> ALL (ARRAY['cancelled'::text, 'no_show'::text])) AND (b.starts_at >= (now() - '1 day'::interval)))\n $v$;\n END IF;\nEND $$;\n\n-- v_clients (beauty Ring-2 extension) may not exist on non-salon pools — the\n-- report only makes sense where it does.\nDO $$\nBEGIN\n IF to_regclass('public.v_clients') IS NULL THEN RETURN; END IF;\n EXECUTE $v$\n CREATE OR REPLACE VIEW public.rep_new_clients AS\n SELECT c.tenant_id,\n c.id AS client_id,\n (c.created_at)::date AS date,\n c.name AS client_name,\n c.origin,\n first_booking.service_name AS first_service,\n c.created_at,\n c.updated_at\n FROM (v_clients c\n LEFT JOIN LATERAL ( SELECT COALESCE(((b.services -> 0) ->> 'name'::text), ((b.services -> 0) ->> 'serviceName'::text)) AS service_name\n FROM v_appointments b\n WHERE (b.client_id = c.id)\n ORDER BY b.starts_at\n LIMIT 1) first_booking ON (true))\n $v$;\nEND $$;\n\nCREATE OR REPLACE VIEW public.rep_revenue_by_professional AS\nSELECT tenant_id,\n (starts_at)::date AS date,\n professional_id,\n COALESCE(professional_name, 'Sem profissional'::text) AS professional_name,\n (count(*))::integer AS appointment_count,\n (COALESCE(sum(NULLIF(order_total, (0)::numeric)), (0)::numeric))::numeric(14,2) AS total_revenue,\n (COALESCE(avg(NULLIF(order_total, (0)::numeric)), (0)::numeric))::numeric(14,2) AS avg_ticket,\n (0)::numeric(14,2) AS commission,\n max(updated_at) AS updated_at\n FROM v_appointments b\n WHERE (status <> ALL (ARRAY['cancelled'::text, 'no_show'::text]))\n GROUP BY tenant_id, ((starts_at)::date), professional_id, COALESCE(professional_name, 'Sem profissional'::text);\n\nCREATE OR REPLACE VIEW public.rep_revenue_by_service AS\nSELECT b.tenant_id,\n (b.starts_at)::date AS date,\n NULLIF((service_item.value ->> 'serviceId'::text), ''::text) AS service_id,\n COALESCE((service_item.value ->> 'name'::text), (service_item.value ->> 'serviceName'::text), 'Sem servico'::text) AS service_name,\n (count(DISTINCT b.id))::integer AS quantity,\n (COALESCE(sum((NULLIF((service_item.value ->> 'price'::text), ''::text))::numeric), (0)::numeric))::numeric(14,2) AS total_revenue,\n (COALESCE(avg((NULLIF((service_item.value ->> 'price'::text), ''::text))::numeric), (0)::numeric))::numeric(14,2) AS avg_ticket,\n max(b.updated_at) AS updated_at\n FROM (v_appointments b\n CROSS JOIN LATERAL jsonb_array_elements(COALESCE((b.services)::jsonb, '[]'::jsonb)) service_item(value))\n WHERE (b.status <> ALL (ARRAY['cancelled'::text, 'no_show'::text]))\n GROUP BY b.tenant_id, ((b.starts_at)::date), NULLIF((service_item.value ->> 'serviceId'::text), ''::text), COALESCE((service_item.value ->> 'name'::text), (service_item.value ->> 'serviceName'::text), 'Sem servico'::text);\n\n-- 3. Retire the duplicates. v_bookings goes first: it reads the legacy view.\n-- Nothing in the SDK references either name (checked: only migrations and a\n-- README mention v_bookings).\nDROP VIEW IF EXISTS public.v_bookings;\nDROP VIEW IF EXISTS public.v_bookings_legacy_beauty;\n`\n\nexport const MIGRATION_014_AGENT_RPC_UPDATE_APPOINTMENT = `-- ============================================================================\n-- plugin-agenda 014: agent_agenda_update_appointment — remarcar / reatribuir /\n-- cancelar um agendamento existente.\n--\n-- Lacuna que isso fecha: o agente sabia CRIAR e não sabia MEXER. Pedido real\n-- (\"remarca esse paciente pra 16:30\") caía no updateRecord genérico, que bate\n-- em v_appointments — uma view — e devolve read_only; o modelo então \"resolvia\"\n-- abrindo um agendamento NOVO, deixando o antigo de pé. Duplicar a agenda de um\n-- salão é pior do que não fazer nada.\n--\n-- Mesma cadeia de guardas do 008 (agent_guard → janela de trabalho com exceções\n-- → lock advisory → checagem de conflito → auditoria), com três diferenças:\n-- • ação 'edit', sem cota (remarcar não consome bookings_month);\n-- • o próprio agendamento é excluído da checagem de conflito consigo mesmo;\n-- • cancelar não precisa de horário livre — só o guard.\n-- Requer 007 (agenda_working_windows). Idempotente.\n-- ============================================================================\n\nCREATE OR REPLACE FUNCTION public.agent_agenda_update_appointment(\n p_tenant_id uuid,\n p_actor_user_id uuid,\n p_payload jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_denial jsonb;\n v_id uuid;\n v_tz text;\n v_row record;\n v_starts_raw text;\n v_starts timestamptz;\n v_ends timestamptz;\n v_duration int;\n v_professional uuid;\n v_status text;\n v_notes text;\n v_wants_move boolean;\n v_wants_status boolean;\nBEGIN\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown tenant');\n END IF;\n\n -- ── payload ──────────────────────────────────────────────────────────────\n BEGIN\n v_id := (p_payload->>'appointment_id')::uuid;\n v_professional := (p_payload->>'professional_id')::uuid;\n v_starts_raw := p_payload->>'starts_at';\n EXCEPTION WHEN OTHERS THEN\n RETURN jsonb_build_object('ok', false, 'error', 'invalid payload: ' || SQLERRM);\n END;\n v_status := nullif(trim(lower(p_payload->>'status')), '');\n v_notes := left(p_payload->>'notes', 500);\n v_wants_move := v_starts_raw IS NOT NULL OR v_professional IS NOT NULL;\n v_wants_status := v_status IS NOT NULL;\n\n IF v_id IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'appointment_id is required — search the agenda first and reuse the id of the appointment to change');\n END IF;\n IF NOT v_wants_move AND NOT v_wants_status AND v_notes IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'nothing to change: send starts_at, professional_id, status or notes');\n END IF;\n IF v_status IS NOT NULL\n AND v_status NOT IN ('scheduled', 'confirmed', 'in_progress', 'completed', 'cancelled', 'no_show') THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'status must be one of scheduled, confirmed, in_progress, completed, cancelled, no_show');\n END IF;\n\n -- ── the appointment must exist, in THIS tenant ───────────────────────────\n SELECT b.id, b.starts_at, b.ends_at, b.assignee_id, b.status, b.party_id, b.order_id\n INTO v_row\n FROM appointments b\n WHERE b.id = v_id AND b.tenant_id = p_tenant_id;\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown appointment for this tenant');\n END IF;\n\n -- ── authorization: role → plan. No cap: editing frees nothing and buys\n -- nothing, so charging bookings_month for a reschedule would be wrong.\n v_denial := agent_guard(p_tenant_id, p_actor_user_id, 'appointments', 'edit');\n IF v_denial IS NOT NULL THEN\n RETURN jsonb_build_object('ok', false, 'denial', v_denial);\n END IF;\n\n -- Duration is preserved across a move — a 60-minute appointment stays 60.\n v_duration := GREATEST(\n COALESCE(EXTRACT(EPOCH FROM (v_row.ends_at - v_row.starts_at)) / 60, 30)::int, 5);\n v_professional := COALESCE(v_professional, v_row.assignee_id);\n\n IF v_wants_move THEN\n IF v_starts_raw IS NOT NULL THEN\n BEGIN\n IF v_starts_raw ~ '(Z|[+-][0-9]{2}:?[0-9]{2})$' THEN\n v_starts := v_starts_raw::timestamptz; -- explicit offset\n ELSE\n v_starts := (v_starts_raw::timestamp) AT TIME ZONE v_tz; -- tenant-local\n END IF;\n EXCEPTION WHEN OTHERS THEN\n RETURN jsonb_build_object('ok', false, 'error', 'invalid starts_at: ' || SQLERRM);\n END;\n ELSE\n v_starts := v_row.starts_at;\n END IF;\n v_ends := v_starts + make_interval(mins => v_duration);\n\n IF v_starts > now() + interval '365 days' THEN\n RETURN jsonb_build_object('ok', false, 'error', 'starts_at must be within the next year');\n END IF;\n\n -- Working window (exception-aware, 007) for the target professional.\n IF NOT EXISTS (\n SELECT 1\n FROM agenda_working_windows(\n p_tenant_id, (v_starts AT TIME ZONE v_tz)::date, v_professional) w\n WHERE w.assignee_id = v_professional\n AND (v_starts AT TIME ZONE v_tz)::time >= w.win_start\n AND (v_ends AT TIME ZONE v_tz)::time <= w.win_end\n ) THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'that slot is outside the professional''s working hours. Suggest a different time. Times are tenant-local, tz ' || v_tz);\n END IF;\n\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_professional::text, 0));\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_professional\n AND b.id <> v_id -- never conflicts with itself\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n ) THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'that slot is already taken. Suggest a different time.');\n END IF;\n END IF;\n\n -- ── write + audit ────────────────────────────────────────────────────────\n UPDATE appointments b SET\n starts_at = COALESCE(v_starts, b.starts_at),\n ends_at = COALESCE(v_ends, b.ends_at),\n assignee_id = v_professional,\n status = COALESCE(v_status, b.status),\n notes = COALESCE(v_notes, b.notes),\n metadata = COALESCE(b.metadata, '{}'::jsonb) || jsonb_build_object('lastAgentEdit', now()),\n updated_at = now()\n WHERE b.id = v_id AND b.tenant_id = p_tenant_id;\n\n -- The order mirrors the appointment's assignee/status so the financial side\n -- does not drift from the calendar.\n IF v_row.order_id IS NOT NULL THEN\n UPDATE orders o SET\n assignee_id = v_professional,\n status = CASE WHEN v_status = 'cancelled' THEN 'cancelled' ELSE o.status END,\n updated_at = now()\n WHERE o.id = v_row.order_id AND o.tenant_id = p_tenant_id;\n END IF;\n\n INSERT INTO audit_logs (tenant_id, user_id, action, entity_type, entity_id, metadata)\n VALUES (p_tenant_id, p_actor_user_id, 'agent.updateAppointment', 'appointment', v_id::text,\n jsonb_build_object('payload', p_payload,\n 'previous', jsonb_build_object(\n 'starts_at', v_row.starts_at,\n 'ends_at', v_row.ends_at,\n 'assignee_id', v_row.assignee_id,\n 'status', v_row.status)));\n\n SELECT a.id, a.starts_at, a.ends_at, a.status, a.client_name, a.professional_name\n INTO v_row\n FROM v_appointments a WHERE a.id = v_id;\n\n RETURN jsonb_build_object(\n 'ok', true,\n 'id', v_id,\n 'record', jsonb_build_object(\n 'ref', jsonb_build_object('id', v_id, 'resource', 'appointments',\n 'archetype', 'schedule:appointment'),\n 'starts_at', v_row.starts_at,\n 'ends_at', v_row.ends_at,\n 'starts_at_local', to_char(v_row.starts_at AT TIME ZONE v_tz, 'YYYY-MM-DD (Dy) HH24:MI') || ' ' || v_tz,\n 'ends_at_local', to_char(v_row.ends_at AT TIME ZONE v_tz, 'HH24:MI'),\n 'client_name', v_row.client_name,\n 'professional_name', v_row.professional_name,\n 'status', v_row.status\n )\n );\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.agent_agenda_update_appointment(uuid, uuid, jsonb) FROM public;\nREVOKE EXECUTE ON FUNCTION public.agent_agenda_update_appointment(uuid, uuid, jsonb) FROM anon;\nGRANT EXECUTE ON FUNCTION public.agent_agenda_update_appointment(uuid, uuid, jsonb)\n TO authenticated, service_role;\n`\n\nexport const MIGRATIONS: Array<{ id: string; sql: string }> = [\n { id: \"000b_v_bookings_rename\", sql: MIGRATION_000B_V_BOOKINGS_RENAME },\n { id: \"000c_dedupe_customer_phones\", sql: MIGRATION_000C_DEDUPE_CUSTOMER_PHONES },\n { id: \"001_public_booking\", sql: MIGRATION_001_PUBLIC_BOOKING },\n { id: \"002_v_bookings_compat\", sql: MIGRATION_002_V_BOOKINGS_COMPAT },\n { id: \"003_public_client_kind\", sql: MIGRATION_003_PUBLIC_CLIENT_KIND },\n { id: \"004_public_booking_assignee\", sql: MIGRATION_004_PUBLIC_BOOKING_ASSIGNEE },\n { id: \"005_agent_rpcs\", sql: MIGRATION_005_AGENT_RPCS },\n { id: \"006_agent_rpc_localtime\", sql: MIGRATION_006_AGENT_RPC_LOCALTIME },\n { id: \"007_schedule_exception_precedence\", sql: MIGRATION_007_SCHEDULE_EXCEPTION_PRECEDENCE },\n { id: \"008_agent_rpc_exception_precedence\", sql: MIGRATION_008_AGENT_RPC_EXCEPTION_PRECEDENCE },\n { id: \"009_public_booking_location\", sql: MIGRATION_009_PUBLIC_BOOKING_LOCATION },\n { id: \"010_public_service_curation\", sql: MIGRATION_010_PUBLIC_SERVICE_CURATION },\n { id: \"011_default_assignee\", sql: MIGRATION_011_DEFAULT_ASSIGNEE },\n { id: \"012_drop_legacy_booking_overload\", sql: MIGRATION_012_DROP_LEGACY_BOOKING_OVERLOAD },\n { id: \"013_normalize_v_appointments\", sql: MIGRATION_013_NORMALIZE_V_APPOINTMENTS },\n { id: \"014_agent_rpc_update_appointment\", sql: MIGRATION_014_AGENT_RPC_UPDATE_APPOINTMENT },\n]\n","// ---------------------------------------------------------------------------\n// Bridge factory: adapts FinancialDataProvider → AgendaFinancialBridge\n// Consumer apps call this at plugin wiring time.\n// ---------------------------------------------------------------------------\n\nimport type { FinancialDataProvider } from '@fayz-ai/plugin-financial'\nimport type { AgendaFinancialBridge, BookingPaymentSummary, BookingPaymentDetail, BookingPaymentStatus } from '../financial-bridge'\nimport { getSupabaseClientOptional } from '@fayz-ai/core'\n\n/**\n * Pure commission math: percentage of a realized order total, rounded to cents.\n * Exported for unit-testing and reuse; the bridge method below wraps the I/O.\n * Returns 0 for a non-positive base or rate so callers can skip empty accruals.\n */\nexport function computeCommissionAmount(total: number, ratePercent: number): number {\n const base = Number(total) || 0\n const rate = Number(ratePercent) || 0\n if (base <= 0 || rate <= 0) return 0\n return Math.round(base * (rate / 100) * 100) / 100\n}\n\nfunction computeStatus(movements: Array<{ status: string }>): BookingPaymentStatus {\n if (movements.length === 0) return 'none'\n const allPaid = movements.every((m) => m.status === 'paid')\n if (allPaid) return 'paid'\n const allCancelled = movements.every((m) => m.status === 'cancelled')\n if (allCancelled) return 'cancelled'\n const anyOverdue = movements.some((m) => m.status === 'overdue')\n if (anyOverdue) return 'overdue'\n const anyPaid = movements.some((m) => m.status === 'paid' || m.status === 'partial')\n if (anyPaid) return 'partial'\n return 'pending'\n}\n\n/**\n * Create an AgendaFinancialBridge backed by the financial plugin's data provider.\n *\n * @example\n * const financialProvider = createSupabaseFinancialProvider()\n * const agenda = createAgendaPlugin({\n * financialBridge: createFinancialBridge(financialProvider),\n * })\n */\nexport function createFinancialBridge(provider: FinancialDataProvider): AgendaFinancialBridge {\n return {\n async resolvePaymentStatuses(orderIds: string[]): Promise<Map<string, BookingPaymentSummary>> {\n const result = new Map<string, BookingPaymentSummary>()\n if (orderIds.length === 0) return result\n\n // Single batch query instead of N individual getInvoiceById calls\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) return result\n\n try {\n const [{ data: orders }, { data: movements }] = await Promise.all([\n supabase\n .from('orders')\n .select('id, kind, status, total, reference_number, metadata')\n .in('id', orderIds),\n supabase\n .from('plg_financial_movements')\n .select('invoice_id, status, paid_amount')\n .in('invoice_id', orderIds),\n ])\n\n const movementsByOrderId = new Map<string, Array<{ status: string; paid_amount: number }>>()\n for (const movement of movements ?? []) {\n const invoiceId = movement.invoice_id as string | undefined\n if (!invoiceId) continue\n movementsByOrderId.set(invoiceId, [...(movementsByOrderId.get(invoiceId) ?? []), movement])\n }\n\n for (const order of orders ?? []) {\n const orderMovements = movementsByOrderId.get(order.id) ?? []\n const meta = (order.metadata ?? {}) as Record<string, unknown>\n const paidAmount = orderMovements.length > 0\n ? orderMovements.reduce((sum, movement) => sum + (Number(movement.paid_amount) || 0), 0)\n : Number(meta.paidAmount) || 0\n\n result.set(order.id, {\n invoiceId: order.id,\n referenceNumber: order.reference_number as string | undefined,\n status: orderMovements.length > 0 ? computeStatus(orderMovements) : mapInvoiceStatus(order.status as string),\n totalAmount: Number(order.total) || 0,\n paidAmount,\n })\n }\n } catch { /* non-blocking */ }\n\n return result\n },\n\n async getPaymentDetail(orderId: string): Promise<BookingPaymentDetail | null> {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) return null\n\n // Single query: get order + movements in parallel\n const [orderRes, movRes] = await Promise.all([\n supabase.from('orders').select('id, status, total, reference_number, metadata').eq('id', orderId).single(),\n supabase.from('plg_financial_movements').select('*').eq('invoice_id', orderId).order('due_date'),\n ])\n\n const order = orderRes.data\n if (!order) return null\n const meta = (order.metadata ?? {}) as Record<string, unknown>\n\n // Collect unique payment_method_type_ids to resolve names in one query\n const typeIds = [...new Set((movRes.data ?? []).map((m: any) => m.payment_method_type_id).filter(Boolean))]\n let typeNames: Record<string, string> = {}\n if (typeIds.length > 0) {\n const { data: types } = await supabase.from('plg_financial_payment_method_types').select('id, name').in('id', typeIds)\n typeNames = Object.fromEntries((types ?? []).map((t: any) => [t.id, t.name]))\n }\n\n const movements = (movRes.data ?? []).map((m: Record<string, unknown>) => ({\n id: String(m.id),\n amount: Number(m.amount) || 0,\n paidAmount: Number(m.paid_amount) || 0,\n status: String(m.status ?? 'pending'),\n dueDate: String(m.due_date ?? ''),\n installmentNumber: m.installment_number != null ? Number(m.installment_number) : undefined,\n paymentDate: m.payment_date ? String(m.payment_date) : undefined,\n paymentMethodTypeName: m.payment_method_type_id ? typeNames[String(m.payment_method_type_id)] : undefined,\n cardBrand: m.card_brand ? String(m.card_brand) : undefined,\n cardInstallments: m.card_installments ? Number(m.card_installments) : undefined,\n }))\n\n return {\n invoiceId: order.id,\n referenceNumber: order.reference_number as string | undefined,\n status: movements.length > 0 ? computeStatus(movements) : mapInvoiceStatus(order.status as string),\n totalAmount: Number(order.total) || 0,\n paidAmount: Number(meta.paidAmount) || 0,\n movements,\n }\n },\n\n async createInvoiceFromOrder(orderId: string, options?: {\n installments?: number\n dueDate?: string\n paymentMethodTypeId?: string\n }): Promise<string> {\n // Promote the existing order to an invoice_receivable atomically via the\n // shared DB function (ref + stage/direction + N installments, idempotent).\n // status='invoiced' is valid for appointment/service_order (CHECK).\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase not available')\n const { error } = await supabase.rpc('fn_invoice_from_order', {\n p_order_id: orderId,\n p_due_date: options?.dueDate ?? null,\n p_status: 'invoiced',\n p_installments: options?.installments ?? 1,\n p_direction: 'credit',\n })\n if (error) throw new Error(error.message)\n return orderId\n },\n\n async payMovement(input) {\n await provider.payMovement({\n movementId: input.movementId,\n amount: input.amount,\n paymentDate: input.paymentDate,\n paymentMethodTypeId: input.paymentMethodTypeId,\n paymentMethodId: input.paymentMethodId,\n bankAccountId: input.bankAccountId,\n cardBrand: input.cardBrand,\n cardInstallments: input.cardInstallments,\n })\n },\n\n async createCommissionMovement(orderId, options) {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) return null\n\n // Order carries the assigned professional (assignee_id) and realized total.\n const { data: order } = await supabase\n .from('orders')\n .select('id, tenant_id, assignee_id, total')\n .eq('id', orderId)\n .single()\n if (!order || !order.assignee_id) return null // no professional → no commission\n\n // Per-professional rate lives on staff_members, surfaced via v_staff (id = person id).\n const { data: staff } = await supabase\n .from('v_staff')\n .select('commission_rate')\n .eq('id', order.assignee_id)\n .single()\n\n const rate = Number(staff?.commission_rate) || 0\n const base = Number(order.total) || 0\n const amount = computeCommissionAmount(base, rate)\n if (amount <= 0) return null // nothing configured/realized to accrue\n\n // Idempotent: one commission accrual per order. Reuse if already present.\n const { data: existing } = await supabase\n .from('plg_financial_movements')\n .select('id')\n .eq('invoice_id', orderId)\n .eq('movement_kind', 'commission')\n .limit(1)\n if (existing && existing.length > 0) return existing[0].id as string\n\n const dueDate = options?.dueDate ?? new Date().toISOString().slice(0, 10)\n\n const { data: inserted } = await supabase\n .from('plg_financial_movements')\n .insert({\n tenant_id: order.tenant_id,\n invoice_id: orderId,\n direction: 'debit', // payable to the professional\n movement_kind: 'commission',\n amount,\n paid_amount: 0,\n status: 'pending',\n due_date: dueDate,\n metadata: {\n source: 'agenda',\n kind: 'commission',\n professionalId: order.assignee_id,\n commissionRate: rate,\n baseAmount: base,\n },\n })\n .select('id')\n .single()\n\n return (inserted?.id as string | undefined) ?? null\n },\n\n async checkout(orderId, input) {\n // 1. Create invoice (single installment, due today)\n const today = new Date().toISOString().slice(0, 10)\n const invoiceId = await this.createInvoiceFromOrder(orderId, { installments: 1, dueDate: today })\n\n // 2. Get the created movement\n const detail = await this.getPaymentDetail(invoiceId)\n if (!detail || detail.movements.length === 0) throw new Error('No movement created')\n\n const movement = detail.movements[0]\n\n // 3. Pay it in full\n await this.payMovement({\n movementId: movement.id,\n amount: movement.amount,\n paymentDate: today,\n paymentMethodTypeId: input.paymentMethodTypeId,\n paymentMethodId: input.paymentMethodId,\n bankAccountId: input.bankAccountId,\n cardBrand: input.cardBrand,\n cardInstallments: input.cardInstallments,\n })\n\n // 4. Return updated detail\n return (await this.getPaymentDetail(invoiceId))!\n },\n\n async getPaymentMethodTypes() {\n const types = await provider.getPaymentMethodTypes()\n return types.map((t: any) => ({ id: t.id, name: t.name, transactionType: t.transactionType }))\n },\n\n async getBankAccounts() {\n const accounts = await provider.getBankAccounts()\n return accounts\n .filter((a: any) => a.isActive)\n .map((a: any) => ({ id: a.id, name: a.name, accountType: a.accountType }))\n },\n\n async getPaymentMethods(paymentMethodTypeId: string) {\n const methods = await provider.getPaymentMethods()\n return methods\n .filter((m: any) => m.paymentMethodTypeId === paymentMethodTypeId && m.isActive)\n .map((m: any) => ({ id: m.id, name: m.name }))\n },\n }\n}\n\nfunction mapInvoiceStatus(status: string): BookingPaymentStatus {\n switch (status) {\n case 'paid': return 'paid'\n case 'partial': return 'partial'\n case 'overdue': return 'overdue'\n case 'cancelled': return 'cancelled'\n case 'invoiced': return 'pending'\n case 'pending': return 'pending'\n case 'scheduled': return 'none'\n case 'confirmed': return 'none'\n case 'in_progress': return 'none'\n case 'completed': return 'none'\n case 'no_show': return 'none'\n case 'booked': return 'none'\n default: return 'pending'\n }\n}\n","// Booking ↔ Google Calendar event mapping — the SINGLE SOURCE OF TRUTH.\n//\n// These helpers are pure and Deno-friendly (only `import type`, no runtime\n// node/react/https imports), so the Supabase edge function imports this exact\n// file via a relative path (`../../src/integrations/google-calendar/mapping.ts`)\n// instead of keeping a divergent mirror. `import type` is elided by the Deno /\n// esbuild bundler, so the plugin `types.ts`/`CalendarBooking` type imports never\n// become runtime dependencies of the function bundle.\n//\n// Two callers, two input shapes:\n// • the SDK/UI works with the rich `CalendarBooking` (camelCase, joined) — see\n// bookingToEvent / eventToBookingPatch;\n// • the edge function + RPCs work with the raw `AppointmentRow` (snake_case DB\n// columns) — see appointmentRowToEvent / eventToAppointmentPatch.\n// Field decisions (title, all-day, cancel) are made once, here.\nimport type { CalendarBooking } from '../../types'\nimport type { GCalEvent, AppointmentRow, CalendarChannel, CalendarChannelRow } from './types'\n\nexport interface GCalEventInput {\n summary: string\n description?: string\n // Timed events use dateTime; all-day events use date (YYYY-MM-DD).\n start: { dateTime?: string; date?: string; timeZone?: string }\n end: { dateTime?: string; date?: string; timeZone?: string }\n}\n\n/** Normalized time window read off a Google event, all-day aware. */\nexport interface EventTimes {\n startsAt: string\n endsAt: string\n allDay: boolean\n}\n\n// --- Booking (rich SDK shape) → event -------------------------------------\n\n/** Build the event title from the booking's services + client. */\nexport function bookingSummary(b: Pick<CalendarBooking, 'services' | 'clientName'>): string {\n const services = (b.services ?? []).map((s) => s.name).filter(Boolean).join(', ')\n const who = b.clientName ?? ''\n if (services && who) return `${services} — ${who}`\n return services || who || 'Appointment'\n}\n\n/** Map a Fayz booking to a Google Calendar event input. Returns null when the booking has no end. */\nexport function bookingToEvent(b: CalendarBooking, timeZone?: string): GCalEventInput | null {\n if (!b.startsAt || !b.endsAt) return null\n const notes = [b.notes, b.professionalName ? `Pro: ${b.professionalName}` : '', b.locationName ?? '']\n .filter(Boolean).join('\\n')\n return {\n summary: bookingSummary(b),\n description: notes || undefined,\n start: { dateTime: b.startsAt, timeZone },\n end: { dateTime: b.endsAt, timeZone },\n }\n}\n\n/** Map an inbound Google event change to a partial booking update (reschedule/cancel), all-day aware. */\nexport function eventToBookingPatch(ev: GCalEvent): { startsAt?: string; endsAt?: string; status?: 'cancelled' } {\n if (ev.status === 'cancelled') return { status: 'cancelled' }\n const t = eventTimes(ev)\n return { startsAt: t.startsAt, endsAt: t.endsAt }\n}\n\n// --- Appointment row (raw DB shape) → event -------------------------------\n\n/**\n * Build the event title from an appointments row's denormalized metadata.\n * The raw row has no joined services/client, so we read the names the app\n * stamps onto metadata (serviceNames, contactName/clientName).\n */\nexport function appointmentRowSummary(row: AppointmentRow): string {\n const m = row.metadata ?? {}\n const services = (m.serviceNames as string) ?? ''\n const who = (m.contactName as string) ?? (m.clientName as string) ?? ''\n if (services && who) return `${services} — ${who}`\n return services || who || 'Appointment'\n}\n\n/** Map a raw appointments row to a Google event input (outbound push from the edge function). */\nexport function appointmentRowToEvent(row: AppointmentRow): GCalEventInput {\n return {\n summary: appointmentRowSummary(row),\n description: row.notes ?? undefined,\n start: { dateTime: row.starts_at },\n end: { dateTime: row.ends_at ?? row.starts_at },\n }\n}\n\n/**\n * Map an inbound Google event to a DB-friendly appointment patch (snake_case\n * times), all-day aware, cancellation included. Consumed by the edge function\n * when calling gcal_apply_event_patch.\n */\nexport function eventToAppointmentPatch(ev: GCalEvent): {\n starts_at?: string\n ends_at?: string\n summary?: string\n allDay?: boolean\n cancelled: boolean\n} {\n if (ev.status === 'cancelled') return { cancelled: true }\n const t = eventTimes(ev)\n return { starts_at: t.startsAt, ends_at: t.endsAt, summary: ev.summary, allDay: t.allDay, cancelled: false }\n}\n\n// --- Shared time normalization (all-day aware) ----------------------------\n\n/**\n * Read a normalized {startsAt, endsAt, allDay} window off a Google event.\n * All-day events carry `start.date`/`end.date` (YYYY-MM-DD, end exclusive) and\n * no dateTime; timed events carry dateTime. Falls back start→end when one side\n * is missing so callers always get a usable pair.\n */\nexport function eventTimes(ev: GCalEvent): EventTimes {\n const allDay = !ev.start?.dateTime && !!ev.start?.date\n const startsAt = ev.start?.dateTime ?? ev.start?.date ?? ''\n const endsAt = ev.end?.dateTime ?? ev.end?.date ?? startsAt\n return { startsAt, endsAt, allDay }\n}\n\n// --- Channel resolution (outbound destination priority) -------------------\n\n/** Convert a raw plg_calendar_channels row (snake_case) to the camelCase CalendarChannel. */\nexport function channelRowToChannel(r: CalendarChannelRow): CalendarChannel {\n return {\n id: r.id,\n integrationId: r.integration_id,\n tenantId: r.tenant_id,\n googleCalendarId: r.google_calendar_id,\n summary: r.summary ?? null,\n color: r.color ?? null,\n direction: r.direction,\n targetKind: r.target_kind ?? null,\n targetId: r.target_id ?? null,\n importMode: r.import_mode ?? 'appointment',\n syncToken: r.sync_token ?? null,\n channelId: r.channel_id ?? null,\n resourceId: r.resource_id ?? null,\n channelExpiresAt: r.channel_expires_at ?? null,\n isActive: r.is_active ?? true,\n createdAt: r.created_at ?? '',\n updatedAt: r.updated_at ?? '',\n }\n}\n\nexport interface ChannelMatchInput {\n assigneeId?: string | null\n serviceIds?: string[]\n locationId?: string | null\n}\n\n/**\n * Pick the outbound destination channel for a booking, by priority:\n * 1. a channel targeting the booking's assignee,\n * 2. else a channel targeting one of the booking's services,\n * 3. else a channel targeting the booking's location,\n * 4. else the whole-agenda channel (targetKind === null).\n * Only active outbound/bidirectional channels are eligible. Returns null when\n * nothing matches (caller falls back to the integration's default calendar).\n */\nexport function resolveTargetChannel(\n channels: CalendarChannel[],\n booking: ChannelMatchInput,\n): CalendarChannel | null {\n const eligible = channels.filter(\n (c) => c.isActive && (c.direction === 'outbound' || c.direction === 'bidirectional'),\n )\n const serviceIds = booking.serviceIds ?? []\n\n if (booking.assigneeId) {\n const byAssignee = eligible.find((c) => c.targetKind === 'assignee' && c.targetId === booking.assigneeId)\n if (byAssignee) return byAssignee\n }\n if (serviceIds.length) {\n const byService = eligible.find((c) => c.targetKind === 'service' && !!c.targetId && serviceIds.includes(c.targetId))\n if (byService) return byService\n }\n if (booking.locationId) {\n const byLocation = eligible.find((c) => c.targetKind === 'location' && c.targetId === booking.locationId)\n if (byLocation) return byLocation\n }\n return eligible.find((c) => c.targetKind === null) ?? null\n}\n","// Canonical DB object names for the Google Calendar connector.\n//\n// Plugin-owned tables carry the platform `plg_<plugin>_` prefix (DATA-MODEL.md\n// Ring 1). Single source of truth so the connector data layer (supabase.ts) and\n// the google-calendar-sync edge function never drift on a table name. The SQL\n// side is owned by ./migrations/001_google_calendar.sql + 002_smart_sync.sql\n// (fresh installs) and 003_plg_rename.sql (legacy-pool rename).\nexport const GCAL_TABLES = {\n integrations: 'plg_calendar_integrations',\n channels: 'plg_calendar_channels',\n syncLog: 'plg_calendar_sync_log',\n} as const\n","// Google Calendar integration (control plane) — Supabase client.\n//\n// Thin client. Split of responsibilities:\n// • anything that needs the OAuth client secret or a Google API call goes\n// through the google-calendar-sync edge function (invoke);\n// • plain tenant-scoped reads/writes (integration row, channels, log) hit the\n// tables directly under RLS.\nimport { getSupabaseClientOptional, getActiveTenantId } from '@fayz-ai/core'\nimport { channelRowToChannel } from '../mapping'\nimport { GCAL_TABLES } from './tables'\nimport type {\n CalendarIntegration,\n CalendarSyncLogEntry,\n CalendarChannel,\n ExternalEventPreview,\n GoogleCalendarListEntry,\n ImportEventsResult,\n} from '../types'\n\nconst FUNCTION = 'google-calendar-sync'\n\nfunction sb() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase not initialized')\n return supabase\n}\n\n/** Snake_case patch for plg_calendar_channels writes (RLS-scoped). */\nexport interface CalendarChannelInput {\n id?: string\n integrationId?: string\n googleCalendarId: string\n summary?: string | null\n color?: string | null\n direction?: CalendarChannel['direction']\n targetKind?: CalendarChannel['targetKind']\n targetId?: string | null\n importMode?: CalendarChannel['importMode']\n isActive?: boolean\n}\n\nexport interface GoogleCalendarProvider {\n getIntegration(): Promise<CalendarIntegration | null>\n /** Start the OAuth connect flow — returns the Google consent URL to redirect to. */\n getConnectUrl(redirectTo?: string): Promise<string>\n setCalendar(calendarId: string): Promise<void>\n disconnect(): Promise<void>\n /** Manually pull external changes now (inbound). */\n syncNow(): Promise<{ fetched: number; written: number; discovered?: number }>\n getSyncLog(): Promise<CalendarSyncLogEntry[]>\n // --- smart sync: multi-calendar channels + import wizard ---\n /** List the user's Google calendars for the de-para picker (needs the API → function). */\n listGoogleCalendars(): Promise<GoogleCalendarListEntry[]>\n /** Read this tenant's channels (RLS). */\n listChannels(): Promise<CalendarChannel[]>\n /** Create/update a channel (RLS upsert on integration_id + google_calendar_id). */\n saveChannel(input: CalendarChannelInput): Promise<void>\n /** Delete a channel by id (RLS). */\n deleteChannel(id: string): Promise<void>\n /** Preview future events not yet linked to an appointment (import wizard). */\n listExternalEvents(params?: { channelId?: string; timeMin?: string }): Promise<ExternalEventPreview[]>\n /** Import selected external events as appointments. */\n importEvents(items: { channelId: string; eventId: string }[]): Promise<ImportEventsResult>\n}\n\nexport function createGoogleCalendarProvider(): GoogleCalendarProvider {\n return {\n async getIntegration() {\n const { data } = await sb().from(GCAL_TABLES.integrations).select('*').eq('provider', 'google').limit(1).maybeSingle()\n if (!data) return null\n return {\n id: data.id,\n provider: data.provider,\n calendarId: data.calendar_id ?? 'primary',\n active: data.active ?? true,\n connected: !!data.oauth_refresh_token,\n lastSyncAt: data.last_sync_at ?? undefined,\n }\n },\n\n async getConnectUrl(redirectTo) {\n const { data, error } = await sb().functions.invoke(FUNCTION, {\n body: { action: 'oauth_start', tenantId: getActiveTenantId(), redirectTo: redirectTo ?? window.location.href },\n })\n if (error) throw new Error(error.message)\n return (data as { url: string }).url\n },\n\n async setCalendar(calendarId) {\n await sb().from(GCAL_TABLES.integrations).update({ calendar_id: calendarId, updated_at: new Date().toISOString() }).eq('provider', 'google')\n },\n\n async disconnect() {\n await sb().from(GCAL_TABLES.integrations).update({ active: false, oauth_refresh_token: null, oauth_access_token: null }).eq('provider', 'google')\n },\n\n async syncNow() {\n const { data, error } = await sb().functions.invoke(FUNCTION, { body: { action: 'pull_events', tenantId: getActiveTenantId(), trigger: 'manual' } })\n if (error) throw new Error(error.message)\n return data as { fetched: number; written: number; discovered?: number }\n },\n\n async getSyncLog() {\n const { data } = await sb().from(GCAL_TABLES.syncLog).select('*').order('created_at', { ascending: false }).limit(20)\n return (data ?? []).map((r: any) => ({\n id: r.id, direction: r.direction, trigger: r.trigger ?? undefined,\n status: r.status, fetched: r.fetched ?? 0, written: r.written ?? 0,\n error: r.error ?? undefined, createdAt: r.created_at,\n }))\n },\n\n async listGoogleCalendars() {\n const { data, error } = await sb().functions.invoke(FUNCTION, { body: { action: 'list_calendars', tenantId: getActiveTenantId() } })\n if (error) throw new Error(error.message)\n return (data as { calendars: GoogleCalendarListEntry[] }).calendars ?? []\n },\n\n async listChannels() {\n const { data } = await sb().from(GCAL_TABLES.channels).select('*').order('created_at', { ascending: true })\n return (data ?? []).map(channelRowToChannel)\n },\n\n async saveChannel(input) {\n const tenantId = getActiveTenantId()\n // Resolve the integration id when the caller didn't pass one.\n let integrationId = input.integrationId\n if (!integrationId) {\n const { data } = await sb().from(GCAL_TABLES.integrations).select('id').eq('provider', 'google').limit(1).maybeSingle()\n integrationId = data?.id\n }\n const row: Record<string, unknown> = {\n integration_id: integrationId,\n tenant_id: tenantId,\n google_calendar_id: input.googleCalendarId,\n updated_at: new Date().toISOString(),\n }\n if (input.id !== undefined) row.id = input.id\n if (input.summary !== undefined) row.summary = input.summary\n if (input.color !== undefined) row.color = input.color\n if (input.direction !== undefined) row.direction = input.direction\n if (input.targetKind !== undefined) row.target_kind = input.targetKind\n if (input.targetId !== undefined) row.target_id = input.targetId\n if (input.importMode !== undefined) row.import_mode = input.importMode\n if (input.isActive !== undefined) row.is_active = input.isActive\n const { error } = await sb().from(GCAL_TABLES.channels).upsert(row, { onConflict: 'integration_id,google_calendar_id' })\n if (error) throw new Error(error.message)\n },\n\n async deleteChannel(id) {\n const { error } = await sb().from(GCAL_TABLES.channels).delete().eq('id', id)\n if (error) throw new Error(error.message)\n },\n\n async listExternalEvents(params) {\n const { data, error } = await sb().functions.invoke(FUNCTION, {\n body: { action: 'list_external_events', tenantId: getActiveTenantId(), channelId: params?.channelId, timeMin: params?.timeMin },\n })\n if (error) throw new Error(error.message)\n return (data as { events: ExternalEventPreview[] }).events ?? []\n },\n\n async importEvents(items) {\n const { data, error } = await sb().functions.invoke(FUNCTION, {\n body: { action: 'import_events', tenantId: getActiveTenantId(), items },\n })\n if (error) throw new Error(error.message)\n return data as ImportEventsResult\n },\n }\n}\n","// A small round swatch tinted with a Google calendar's backgroundColor.\n//\n// Google's calendarList entries carry a `backgroundColor` hex; we render it as a\n// dot next to the calendar summary in the de-para list and as the leading dot of\n// the origin badge in the import wizard. Falls back to the muted border when a\n// calendar has no color (rare, e.g. some shared calendars).\nimport React from 'react'\n\nexport function CalendarColorDot({\n color,\n className = '',\n}: {\n color?: string | null\n className?: string\n}) {\n return (\n <span\n className={`inline-block h-2.5 w-2.5 shrink-0 rounded-full border border-black/10 ${className}`}\n style={{ backgroundColor: color || 'hsl(var(--muted-foreground))' }}\n aria-hidden\n />\n )\n}\n","// Host-plugin lookups for the smart-sync de-para target picker.\n//\n// A channel can target one professional (assignee), one service, or one location\n// instead of the whole agenda. To offer real pickers (not raw uuid inputs) the\n// connector reuses plugin-agenda's own data providers — it lives inside the same\n// package, so these are in-process reads under the same RLS:\n// • professionals + locations → createSupabaseAgendaProvider()\n// • services → createSupabasePublicBookingProvider() (v_public_services)\n// Everything is loaded once, lazily, and degrades to an empty list (the row then\n// falls back to a plain uuid input) if a lookup is unavailable for the tenant.\nimport { useEffect, useState } from 'react'\nimport { getActiveTenantId } from '@fayz-ai/core'\nimport { createSupabaseAgendaProvider } from '../../../data'\nimport { createSupabasePublicBookingProvider } from '../../../public/data.supabase'\nimport type { ChannelTargetKind } from '../types'\n\n/** A pickable target option (assignee/service/location) — id + display name. */\nexport interface LookupOption {\n id: string\n name: string\n}\n\nexport interface AgendaLookups {\n assignee: LookupOption[]\n service: LookupOption[]\n location: LookupOption[]\n}\n\nconst EMPTY: AgendaLookups = { assignee: [], service: [], location: [] }\n\nexport interface UseAgendaLookupsResult {\n lookups: AgendaLookups\n loading: boolean\n /** True when at least one of the three lookups returned rows. */\n hasAny: boolean\n}\n\n/**\n * Load professionals / services / locations for the target picker. Failures are\n * swallowed per-lookup (each falls back to an empty list) so a missing table or\n * a vertical without services never breaks the whole de-para screen.\n */\nexport function useAgendaLookups(enabled: boolean): UseAgendaLookupsResult {\n const [lookups, setLookups] = useState<AgendaLookups>(EMPTY)\n const [loading, setLoading] = useState(false)\n\n useEffect(() => {\n if (!enabled) return\n let cancelled = false\n setLoading(true)\n void (async () => {\n const agenda = createSupabaseAgendaProvider()\n const tenantId = getActiveTenantId()\n const publicProvider = tenantId\n ? createSupabasePublicBookingProvider({ tenantId })\n : null\n\n const [assignee, location, service] = await Promise.all([\n agenda.getProfessionals().then(\n (rows) => rows.map((p) => ({ id: p.id, name: p.name })),\n () => [] as LookupOption[],\n ),\n (agenda.getLocations?.() ?? Promise.resolve([])).then(\n (rows) => rows.map((l) => ({ id: l.id, name: l.name })),\n () => [] as LookupOption[],\n ),\n (publicProvider?.getServices() ?? Promise.resolve([])).then(\n (rows) => rows.map((s) => ({ id: s.id, name: s.name })),\n () => [] as LookupOption[],\n ),\n ])\n\n if (cancelled) return\n setLookups({ assignee, service, location })\n setLoading(false)\n })()\n\n return () => {\n cancelled = true\n }\n }, [enabled])\n\n const hasAny =\n lookups.assignee.length > 0 ||\n lookups.service.length > 0 ||\n lookups.location.length > 0\n\n return { lookups, loading, hasAny }\n}\n\n/** Options available for a given target kind (empty for whole-agenda / null). */\nexport function optionsForKind(\n lookups: AgendaLookups,\n kind: ChannelTargetKind,\n): LookupOption[] {\n if (kind === 'assignee') return lookups.assignee\n if (kind === 'service') return lookups.service\n if (kind === 'location') return lookups.location\n return []\n}\n","// De-para (mapping) list — one row per Google calendar.\n//\n// Reads the user's Google calendars (listGoogleCalendars) and this tenant's\n// existing channels (listChannels), joins them by google_calendar_id, and lets\n// the user, per calendar:\n// • toggle sync on/off → creates/updates the channel (is_active)\n// • pick a direction → Two-way / Import only / Export only / Off\n// • pick a target → Whole agenda / Professional / Service / Location\n// • pick an import mode → Block / Appointment\n// Every change is persisted immediately via saveChannel (RLS upsert on\n// integration_id + google_calendar_id), snapshotting the calendar summary+color\n// onto the channel. Target ids come from real host lookups (useAgendaLookups);\n// if a lookup is empty for the tenant the row degrades to a raw uuid input.\nimport React, { useCallback, useEffect, useState } from 'react'\nimport { Loader2, AlertCircle, RefreshCw } from 'lucide-react'\nimport {\n Button,\n Checkbox,\n Badge,\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n toast,\n} from '@fayz-ai/ui'\nimport type { GoogleCalendarProvider } from '../data/supabase'\nimport type {\n CalendarChannel,\n ChannelDirection,\n ChannelTargetKind,\n ChannelImportMode,\n GoogleCalendarListEntry,\n} from '../types'\nimport { CalendarColorDot } from './CalendarColorDot'\nimport { useAgendaLookups, optionsForKind } from './useAgendaLookups'\n\nconst DIRECTION_LABELS: Record<ChannelDirection, string> = {\n bidirectional: 'Two-way',\n inbound: 'Import only',\n outbound: 'Export only',\n off: 'Off',\n}\nconst IMPORT_MODE_LABELS: Record<ChannelImportMode, string> = {\n block: 'Block',\n appointment: 'Appointment',\n}\n// 'agenda' is the UI sentinel for the whole-agenda target (target_kind = null).\nconst TARGET_KIND_LABELS: Record<'agenda' | 'assignee' | 'service' | 'location', string> = {\n agenda: 'Whole agenda',\n assignee: 'Professional',\n service: 'Service',\n location: 'Location',\n}\nconst NO_TARGET = '__none__'\n\n/** Defaults for a freshly-enabled calendar (mirror the migration defaults). */\nfunction defaultChannel(): {\n direction: ChannelDirection\n targetKind: ChannelTargetKind\n targetId: string | null\n importMode: ChannelImportMode\n} {\n return { direction: 'bidirectional', targetKind: null, targetId: null, importMode: 'block' }\n}\n\nexport function ChannelMappingList({\n provider,\n onChannelsChange,\n}: {\n provider: GoogleCalendarProvider\n /** Bubble the current channels up so the parent can gate the import wizard. */\n onChannelsChange?: (channels: CalendarChannel[]) => void\n}) {\n const [calendars, setCalendars] = useState<GoogleCalendarListEntry[]>([])\n const [byGcalId, setByGcalId] = useState<Record<string, CalendarChannel>>({})\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [savingId, setSavingId] = useState<string | null>(null)\n\n const { lookups, hasAny: hasLookups } = useAgendaLookups(true)\n\n const load = useCallback(async () => {\n setLoading(true)\n setError(null)\n try {\n const [cals, channels] = await Promise.all([\n provider.listGoogleCalendars(),\n provider.listChannels(),\n ])\n setCalendars(cals)\n const map: Record<string, CalendarChannel> = {}\n for (const ch of channels) map[ch.googleCalendarId] = ch\n setByGcalId(map)\n onChannelsChange?.(channels)\n } catch (e: any) {\n setError(e?.message ?? 'Could not load Google calendars')\n } finally {\n setLoading(false)\n }\n }, [provider, onChannelsChange])\n\n useEffect(() => {\n void load()\n }, [load])\n\n /** Persist a patch for one calendar, then refresh channels (keeps ids correct). */\n const persist = useCallback(\n async (\n cal: GoogleCalendarListEntry,\n patch: {\n direction?: ChannelDirection\n targetKind?: ChannelTargetKind\n targetId?: string | null\n importMode?: ChannelImportMode\n isActive?: boolean\n },\n ) => {\n const existing = byGcalId[cal.id]\n const base = existing ?? { ...defaultChannel(), isActive: true }\n setSavingId(cal.id)\n try {\n await provider.saveChannel({\n id: existing?.id,\n googleCalendarId: cal.id,\n summary: cal.summary,\n color: cal.backgroundColor ?? null,\n direction: patch.direction ?? base.direction,\n targetKind: patch.targetKind !== undefined ? patch.targetKind : base.targetKind,\n targetId: patch.targetId !== undefined ? patch.targetId : base.targetId ?? null,\n importMode: patch.importMode ?? base.importMode,\n isActive: patch.isActive !== undefined ? patch.isActive : base.isActive,\n })\n const channels = await provider.listChannels()\n const map: Record<string, CalendarChannel> = {}\n for (const ch of channels) map[ch.googleCalendarId] = ch\n setByGcalId(map)\n onChannelsChange?.(channels)\n } catch (e: any) {\n toast.error(e?.message ?? 'Could not save calendar mapping')\n } finally {\n setSavingId(null)\n }\n },\n [byGcalId, provider, onChannelsChange],\n )\n\n if (loading) {\n return (\n <div className=\"py-6 text-center text-sm text-muted-foreground\">\n <Loader2 className=\"h-4 w-4 animate-spin inline\" />\n </div>\n )\n }\n\n if (error) {\n return (\n <div className=\"rounded-md border border-warning/40 bg-warning-soft/40 px-3 py-3 text-sm\">\n <div className=\"flex items-center gap-2 text-warning-soft-foreground\">\n <AlertCircle className=\"h-4 w-4\" /> {error}\n </div>\n <Button variant=\"outline\" size=\"sm\" className=\"mt-2\" onClick={() => void load()}>\n <RefreshCw className=\"h-3.5 w-3.5\" /> Retry\n </Button>\n </div>\n )\n }\n\n if (calendars.length === 0) {\n return (\n <p className=\"py-6 text-center text-sm text-muted-foreground\">\n No Google calendars found on this account.\n </p>\n )\n }\n\n return (\n <div className=\"rounded-md border divide-y\">\n {calendars.map((cal) => {\n const ch = byGcalId[cal.id]\n const active = !!ch?.isActive\n const saving = savingId === cal.id\n const direction: ChannelDirection = ch?.direction ?? 'bidirectional'\n const targetKind: ChannelTargetKind = ch?.targetKind ?? null\n const importMode: ChannelImportMode = ch?.importMode ?? 'block'\n // Import mode only matters when Google can write into the agenda.\n const canImport = direction === 'inbound' || direction === 'bidirectional'\n const kindOptions = optionsForKind(lookups, targetKind)\n\n return (\n <div key={cal.id} className=\"px-3 py-3 space-y-3\">\n <div className=\"flex items-center gap-2.5\">\n <Checkbox\n checked={active}\n disabled={saving}\n onChange={(next) => void persist(cal, { isActive: next })}\n />\n <CalendarColorDot color={cal.backgroundColor} />\n <span className=\"text-sm font-medium truncate\">{cal.summary}</span>\n {cal.primary && (\n <Badge variant=\"outline\" className=\"shrink-0\">\n Primary\n </Badge>\n )}\n {saving && <Loader2 className=\"ml-auto h-3.5 w-3.5 animate-spin text-muted-foreground\" />}\n </div>\n\n {active && (\n <div className=\"grid gap-2 pl-[26px] sm:grid-cols-2 lg:grid-cols-4\">\n {/* Direction */}\n <label className=\"block\">\n <span className=\"text-[11px] font-medium text-muted-foreground\">Direction</span>\n <Select\n value={direction}\n onValueChange={(v) => void persist(cal, { direction: v as ChannelDirection })}\n >\n <SelectTrigger className=\"mt-1 h-8 text-sm\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {(Object.keys(DIRECTION_LABELS) as ChannelDirection[]).map((d) => (\n <SelectItem key={d} value={d}>\n {DIRECTION_LABELS[d]}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n\n {/* Target kind */}\n <label className=\"block\">\n <span className=\"text-[11px] font-medium text-muted-foreground\">Target</span>\n <Select\n value={targetKind ?? 'agenda'}\n onValueChange={(v) =>\n void persist(cal, {\n targetKind: v === 'agenda' ? null : (v as ChannelTargetKind),\n // Reset the id whenever the kind changes.\n targetId: null,\n })\n }\n >\n <SelectTrigger className=\"mt-1 h-8 text-sm\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {(Object.keys(TARGET_KIND_LABELS) as Array<keyof typeof TARGET_KIND_LABELS>).map(\n (k) => (\n <SelectItem key={k} value={k}>\n {TARGET_KIND_LABELS[k]}\n </SelectItem>\n ),\n )}\n </SelectContent>\n </Select>\n </label>\n\n {/* Target id — real picker when we have lookups, uuid input otherwise */}\n {targetKind && (\n <label className=\"block\">\n <span className=\"text-[11px] font-medium text-muted-foreground\">\n {TARGET_KIND_LABELS[targetKind]}\n </span>\n {kindOptions.length > 0 ? (\n <Select\n value={ch?.targetId ?? NO_TARGET}\n onValueChange={(v) =>\n void persist(cal, { targetId: v === NO_TARGET ? null : v })\n }\n >\n <SelectTrigger className=\"mt-1 h-8 text-sm\">\n <SelectValue placeholder=\"Select…\" />\n </SelectTrigger>\n <SelectContent>\n {kindOptions.map((o) => (\n <SelectItem key={o.id} value={o.id}>\n {o.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : (\n <input\n defaultValue={ch?.targetId ?? ''}\n placeholder=\"uuid\"\n onBlur={(e) =>\n void persist(cal, { targetId: e.target.value.trim() || null })\n }\n className=\"w-full mt-1 h-8 rounded-input border border-input bg-card px-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n )}\n </label>\n )}\n\n {/* Import mode — only when inbound */}\n {canImport && (\n <label className=\"block\">\n <span className=\"text-[11px] font-medium text-muted-foreground\">Import as</span>\n <Select\n value={importMode}\n onValueChange={(v) => void persist(cal, { importMode: v as ChannelImportMode })}\n >\n <SelectTrigger className=\"mt-1 h-8 text-sm\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {(Object.keys(IMPORT_MODE_LABELS) as ChannelImportMode[]).map((m) => (\n <SelectItem key={m} value={m}>\n {IMPORT_MODE_LABELS[m]}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n )}\n </div>\n )}\n </div>\n )\n })}\n {!hasLookups && (\n <p className=\"px-3 py-2 text-[11px] text-muted-foreground\">\n No professional/service/location lookups available — target ids fall back to manual uuid\n entry.\n </p>\n )}\n </div>\n )\n}\n","// Import wizard — pull FUTURE Google events into the agenda as blocks/appointments.\n//\n// listExternalEvents() returns events on the active inbound channels that are not\n// yet linked to an appointment. The user ticks the ones to bring in and confirms;\n// importEvents() runs them through gcal_import_event (honouring each channel's\n// import_mode + target) and returns a per-item tally {imported, skipped, errors}.\n// Events show their source calendar as a colored badge and an \"All-day\" badge\n// when applicable; times are formatted pt-BR.\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { Loader2, CalendarPlus, CheckCircle2, AlertCircle, RefreshCw, X } from 'lucide-react'\nimport { Button, Checkbox, Badge, toast } from '@fayz-ai/ui'\nimport type { GoogleCalendarProvider } from '../data/supabase'\nimport type { CalendarChannel, ExternalEventPreview, ImportEventsResult } from '../types'\nimport { CalendarColorDot } from './CalendarColorDot'\n\n/** pt-BR datetime label, all-day aware (date only for all-day events). */\nfunction formatWhen(ev: ExternalEventPreview): string {\n const start = new Date(ev.startsAt)\n if (ev.allDay) {\n return start.toLocaleDateString('pt-BR', { day: '2-digit', month: 'short', year: 'numeric' })\n }\n return start.toLocaleString('pt-BR', {\n day: '2-digit',\n month: 'short',\n hour: '2-digit',\n minute: '2-digit',\n })\n}\n\nexport function ImportEventsWizard({\n provider,\n channels,\n onClose,\n onImported,\n}: {\n provider: GoogleCalendarProvider\n /** Active channels — used to label each event with its source calendar + color. */\n channels: CalendarChannel[]\n onClose: () => void\n /** Fired after a successful import so the parent can refresh status/history. */\n onImported?: (result: ImportEventsResult) => void\n}) {\n const [events, setEvents] = useState<ExternalEventPreview[]>([])\n const [selected, setSelected] = useState<Set<string>>(new Set())\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [importing, setImporting] = useState(false)\n const [result, setResult] = useState<ImportEventsResult | null>(null)\n\n const channelById = useMemo(() => {\n const m: Record<string, CalendarChannel> = {}\n for (const c of channels) m[c.id] = c\n return m\n }, [channels])\n\n const load = useCallback(async () => {\n setLoading(true)\n setError(null)\n setResult(null)\n try {\n const rows = await provider.listExternalEvents()\n setEvents(rows)\n setSelected(new Set(rows.map((r) => r.eventId)))\n } catch (e: any) {\n setError(e?.message ?? 'Could not load upcoming events')\n } finally {\n setLoading(false)\n }\n }, [provider])\n\n useEffect(() => {\n void load()\n }, [load])\n\n const toggle = (eventId: string) =>\n setSelected((prev) => {\n const next = new Set(prev)\n if (next.has(eventId)) next.delete(eventId)\n else next.add(eventId)\n return next\n })\n\n const allSelected = events.length > 0 && selected.size === events.length\n const toggleAll = () =>\n setSelected(allSelected ? new Set() : new Set(events.map((e) => e.eventId)))\n\n async function handleImport() {\n const items = events\n .filter((e) => selected.has(e.eventId))\n .map((e) => ({ channelId: e.channelId, eventId: e.eventId }))\n if (items.length === 0) return\n setImporting(true)\n try {\n const res = await provider.importEvents(items)\n setResult(res)\n onImported?.(res)\n toast.success(`Imported ${res.imported} · skipped ${res.skipped}`)\n // Drop imported events from the list so the wizard reflects the new state.\n await load()\n } catch (e: any) {\n toast.error(e?.message ?? 'Import failed')\n } finally {\n setImporting(false)\n }\n }\n\n return (\n <div className=\"rounded-md border bg-card\">\n <div className=\"flex items-center gap-2 border-b px-3 py-2\">\n <CalendarPlus className=\"h-4 w-4 text-muted-foreground\" />\n <h4 className=\"text-sm font-semibold\">Import future events</h4>\n <button\n onClick={onClose}\n className=\"ml-auto rounded p-1 text-muted-foreground hover:bg-muted/50\"\n aria-label=\"Close\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n\n {loading ? (\n <div className=\"py-8 text-center text-sm text-muted-foreground\">\n <Loader2 className=\"h-4 w-4 animate-spin inline\" />\n </div>\n ) : error ? (\n <div className=\"p-3\">\n <div className=\"flex items-center gap-2 text-sm text-warning-soft-foreground\">\n <AlertCircle className=\"h-4 w-4\" /> {error}\n </div>\n <Button variant=\"outline\" size=\"sm\" className=\"mt-2\" onClick={() => void load()}>\n <RefreshCw className=\"h-3.5 w-3.5\" /> Retry\n </Button>\n </div>\n ) : events.length === 0 ? (\n <div className=\"py-8 px-4 text-center space-y-1\">\n <p className=\"text-sm font-medium\">You're all caught up</p>\n <p className=\"text-xs text-muted-foreground\">\n No upcoming Google events left to import on your active calendars.\n </p>\n {result && (\n <p className=\"text-xs text-success\">\n Imported {result.imported} · skipped {result.skipped}\n {result.errors.length > 0 ? ` · ${result.errors.length} errors` : ''}\n </p>\n )}\n </div>\n ) : (\n <>\n <div className=\"flex items-center gap-2.5 border-b px-3 py-2\">\n <Checkbox checked={allSelected} onChange={toggleAll} />\n <span className=\"text-xs text-muted-foreground\">\n {selected.size} of {events.length} selected\n </span>\n </div>\n <div className=\"max-h-[320px] overflow-y-auto divide-y\">\n {events.map((ev) => {\n const ch = channelById[ev.channelId]\n return (\n <label\n key={ev.eventId}\n className=\"flex items-start gap-2.5 px-3 py-2.5 cursor-pointer hover:bg-muted/30\"\n >\n <Checkbox\n checked={selected.has(ev.eventId)}\n onChange={() => toggle(ev.eventId)}\n />\n <div className=\"min-w-0 flex-1 space-y-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium truncate\">\n {ev.summary || '(no title)'}\n </span>\n {ev.allDay && (\n <Badge variant=\"secondary\" className=\"shrink-0\">\n All-day\n </Badge>\n )}\n </div>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span>{formatWhen(ev)}</span>\n <span className=\"inline-flex items-center gap-1\">\n <CalendarColorDot color={ch?.color} />\n {ch?.summary ?? ev.calendarId}\n </span>\n </div>\n </div>\n </label>\n )\n })}\n </div>\n <div className=\"flex items-center gap-2 border-t px-3 py-2\">\n {result && (\n <span className=\"text-xs text-muted-foreground\">\n Last run: {result.imported} imported\n {result.errors.length > 0 ? `, ${result.errors.length} errors` : ''}\n </span>\n )}\n <Button\n size=\"sm\"\n className=\"ml-auto\"\n disabled={importing || selected.size === 0}\n onClick={handleImport}\n >\n {importing ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n )}\n Import {selected.size > 0 ? selected.size : ''}\n </Button>\n </div>\n </>\n )}\n </div>\n )\n}\n","// Google Calendar as a unified ConnectorDefinition.\n//\n// Surfaces inside plugin-agenda's settings → Integrations tab (the host),\n// rendered by the shared ConnectorsHub. The hub handles the OAuth connect/\n// disconnect; the ExtraPanel below adds the calendar picker, manual sync and\n// run history (only meaningful once connected).\nimport React, { useEffect, useState } from 'react'\nimport { RefreshCw, History, CheckCircle2, AlertCircle, Loader2, CalendarCog, CalendarPlus } from 'lucide-react'\nimport { Button, toast } from '@fayz-ai/ui'\nimport type { ConnectorDefinition } from '@fayz-ai/core'\nimport { createGoogleCalendarProvider } from './data/supabase'\nimport type { CalendarChannel, CalendarSyncLogEntry } from './types'\nimport { ChannelMappingList } from './components/ChannelMappingList'\nimport { ImportEventsWizard } from './components/ImportEventsWizard'\n\nconst provider = createGoogleCalendarProvider()\n\n/** Channels Google is allowed to write INTO the agenda from (gate the import wizard). */\nfunction inboundChannels(channels: CalendarChannel[]): CalendarChannel[] {\n return channels.filter(\n (c) => c.isActive && (c.direction === 'inbound' || c.direction === 'bidirectional'),\n )\n}\n\nfunction GoogleCalendarExtraPanel() {\n const [connected, setConnected] = useState(false)\n const [lastSyncAt, setLastSyncAt] = useState<string | undefined>()\n const [syncing, setSyncing] = useState(false)\n const [log, setLog] = useState<CalendarSyncLogEntry[]>([])\n const [loaded, setLoaded] = useState(false)\n const [channels, setChannels] = useState<CalendarChannel[]>([])\n // Progressive disclosure: once connected the de-para is opened either on the\n // \"Configure calendars\" CTA or automatically when channels already exist.\n const [showMapping, setShowMapping] = useState(false)\n const [showWizard, setShowWizard] = useState(false)\n\n async function load() {\n const integ = await provider.getIntegration()\n setConnected(!!integ?.connected)\n if (integ) {\n setLastSyncAt(integ.lastSyncAt)\n void provider.getSyncLog().then(setLog)\n void provider.listChannels().then((ch) => {\n setChannels(ch)\n if (ch.length > 0) setShowMapping(true)\n })\n }\n setLoaded(true)\n }\n useEffect(() => { void load() }, [])\n\n // Before connecting there's nothing to configure here — a short hint only.\n if (!loaded) return null\n if (!connected) {\n return (\n <p className=\"text-xs text-muted-foreground border-t pt-4\">\n Connect a Google account above to map your calendars and import events.\n </p>\n )\n }\n\n async function handleSyncNow() {\n setSyncing(true)\n try {\n const r = await provider.syncNow()\n toast.success(`Synced — ${r.written} updated`)\n void provider.getSyncLog().then(setLog)\n void provider.getIntegration().then((i) => setLastSyncAt(i?.lastSyncAt))\n } catch (e: any) { toast.error(e?.message ?? 'Sync failed') }\n finally { setSyncing(false) }\n }\n\n const canImport = inboundChannels(channels).length > 0\n\n return (\n <div className=\"space-y-5 border-t pt-4\">\n {/* 1 — De-para (mapping). CTA first when nothing is configured yet. */}\n <section className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <CalendarCog className=\"h-4 w-4 text-muted-foreground\" />\n <h4 className=\"text-sm font-semibold\">Calendars</h4>\n </div>\n {showMapping ? (\n <ChannelMappingList provider={provider} onChannelsChange={setChannels} />\n ) : (\n <div className=\"rounded-md border border-dashed px-4 py-5 text-center space-y-2\">\n <p className=\"text-sm text-muted-foreground\">\n Map each Google calendar to what it syncs — a professional, service, location, or your\n whole agenda.\n </p>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setShowMapping(true)}>\n <CalendarCog className=\"h-3.5 w-3.5\" /> Configure calendars\n </Button>\n </div>\n )}\n </section>\n\n {/* 2 — Import future events (only meaningful once an inbound channel exists). */}\n {showMapping && (\n <section className=\"space-y-2\">\n {showWizard ? (\n <ImportEventsWizard\n provider={provider}\n channels={inboundChannels(channels)}\n onClose={() => setShowWizard(false)}\n onImported={() => {\n void provider.getSyncLog().then(setLog)\n void provider.getIntegration().then((i) => setLastSyncAt(i?.lastSyncAt))\n }}\n />\n ) : (\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={!canImport}\n title={canImport ? undefined : 'Enable an importing calendar first'}\n onClick={() => setShowWizard(true)}\n >\n <CalendarPlus className=\"h-3.5 w-3.5\" /> Import future events\n </Button>\n )}\n </section>\n )}\n\n {/* 3 — Status: last sync + manual pull + run history. */}\n <section className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button variant=\"outline\" size=\"sm\" onClick={handleSyncNow} disabled={syncing}>\n <RefreshCw className={`h-3.5 w-3.5 ${syncing ? 'animate-spin' : ''}`} /> Sync now\n </Button>\n {lastSyncAt && (\n <span className=\"text-[11px] text-muted-foreground\">\n Last sync: {new Date(lastSyncAt).toLocaleString()}\n </span>\n )}\n </div>\n\n {log.length > 0 && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <History className=\"h-4 w-4 text-muted-foreground\" />\n <h4 className=\"text-sm font-semibold\">History</h4>\n </div>\n <div className=\"rounded-md border divide-y text-sm\">\n {log.map((r) => (\n <div key={r.id} className=\"flex items-center gap-3 px-3 py-2\">\n <span className=\"text-muted-foreground text-xs\">{new Date(r.createdAt).toLocaleString()}</span>\n <span className=\"text-[10px] uppercase tracking-wide px-1 py-px rounded bg-muted text-muted-foreground\">{r.direction}</span>\n <span className=\"ml-auto text-xs\">{r.written} written / {r.fetched} fetched</span>\n {r.status === 'success'\n ? <CheckCircle2 className=\"h-3.5 w-3.5 text-success\" />\n : <AlertCircle className=\"h-3.5 w-3.5 text-warning\" />}\n </div>\n ))}\n </div>\n </div>\n )}\n </section>\n </div>\n )\n}\n\nexport const googleCalendarConnectorDef: ConnectorDefinition = {\n id: 'google-calendar',\n hostPluginId: 'agenda',\n name: 'Google Calendar',\n description: 'Two-way sync between your bookings and Google Calendar.',\n icon: 'Calendar',\n authKind: 'oauth',\n category: 'scheduling',\n direction: 'outbound',\n // Sync only, and deliberately: the agenda has to exist inside the app — to be\n // listed, filtered, reported on, and read when Google is unreachable. An\n // agentic plane would answer questions but leave the calendar screen empty.\n planes: ['sync'],\n entities: ['booking'],\n docsUrl: 'https://support.google.com/calendar',\n async getStatus() {\n const integ = await provider.getIntegration()\n return { connected: !!integ?.connected }\n },\n startOAuth: (redirectTo) => provider.getConnectUrl(redirectTo),\n disconnect: () => provider.disconnect(),\n ExtraPanel: GoogleCalendarExtraPanel,\n}\n","// Google Calendar connector descriptor (control-plane metadata).\n//\n// Declares the connector against the SDK integration spine so the platform can\n// reason about what it syncs. The actual data-plane verbs run in the\n// google-calendar-sync edge function; this is the typed contract + capabilities.\nimport type { Connector } from '@fayz-ai/core'\n\nexport const googleCalendarConnector: Connector = {\n id: 'google-calendar',\n provider: 'google',\n pluginId: 'agenda',\n authKind: 'oauth',\n capabilities: [\n {\n entity: 'booking',\n direction: 'bidirectional',\n triggers: ['on-write', 'scheduled', 'webhook'],\n },\n ],\n}\n","// Google Calendar integration — official (in-SDK) addon for plugin-agenda.\n//\n// Settings-only PluginManifest: contributes a \"Google Calendar\" tab to /settings\n// for connecting an account and running a manual sync. Outbound (booking →\n// Google) is automatic via a DB trigger; inbound (Google → booking) via pg_cron\n// or a Google watch webhook. The data plane is the google-calendar-sync edge\n// function (see ./functions/google-calendar-sync). The booking↔event link lives\n// on public.appointments.metadata.googleCalendarEventId.\n//\n// Graduation path: extract to its own `@fayz-ai/plugin-google-calendar` package.\nimport type { PluginManifest } from '@fayz-ai/core'\nimport { googleCalendarConnectorDef } from './connectorDef'\n\nexport { createGoogleCalendarProvider } from './data/supabase'\nexport { googleCalendarConnector } from './connector'\nexport { googleCalendarConnectorDef } from './connectorDef'\nexport {\n bookingToEvent,\n eventToBookingPatch,\n bookingSummary,\n appointmentRowToEvent,\n eventToAppointmentPatch,\n eventTimes,\n resolveTargetChannel,\n channelRowToChannel,\n} from './mapping'\nexport * from './types'\n\n// Addon plugin: contributes the Google Calendar connector into its host\n// (plugin-agenda). It appears in Agenda settings → Integrations — no top-level\n// settings tab of its own. See packages/saas ConnectorsHub.\nexport function createGoogleCalendarPlugin(): PluginManifest {\n return {\n id: 'google-calendar',\n name: 'Google Calendar',\n icon: 'Calendar',\n version: '0.1.0',\n scope: 'addon',\n defaultEnabled: true,\n dependencies: ['agenda'],\n navigation: [],\n routes: [],\n connectors: [googleCalendarConnectorDef],\n }\n}\n","import React from 'react'\nimport type { PluginManifest } from '@fayz-ai/core'\nimport { createSafeDataProvider, registerTranslations } from '@fayz-ai/core'\nimport type { AgendaPluginOptions } from './config'\nimport { resolveConfig } from './config'\nimport { AgendaPage } from './AgendaPage'\nimport { createSupabaseAgendaProvider } from './data/supabase'\nimport { createMockAgendaProvider } from './data/mock'\nimport { setAgendaTenantId } from './lib/tenant'\nimport { createAgendaStore } from './store'\nimport { agendaRegistries } from './registries'\nimport { AgendaGeneralSettings } from './components/AgendaGeneralSettings'\nimport { agendaLocales } from './locales'\nimport { MIGRATION_001_PUBLIC_BOOKING } from './migrations'\nimport { setScheduleBlockConfig, getScheduleBlockConfig, PluginSettingsPanel } from '@fayz-ai/saas'\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createAgendaPlugin(options?: AgendaPluginOptions): PluginManifest {\n const config = resolveConfig(options)\n registerTranslations(agendaLocales)\n const provider = options?.dataProvider ?? createSafeDataProvider(\n () => createSupabaseAgendaProvider({ professionalKind: config.professionalKind }),\n () => createMockAgendaProvider(),\n )\n const store = createAgendaStore(provider, options?.financialBridge)\n const registries = [...agendaRegistries, ...(options?.settingsRegistries ?? [])]\n\n // Register schedule block config globally so ScheduleEditor can read it\n setScheduleBlockConfig({\n defaults: config.scheduleBlockDefaults,\n showServices: !!config.serviceLookup,\n showConcurrent: true,\n showBookingWindow: true,\n showLocations: config.modules.locationSelection,\n locations: config.locations.map((l) => ({ id: l.id, name: l.name })),\n // Lazy fetcher — called by ScheduleEditor when locations are needed but empty\n fetchLocations: config.modules.locationSelection && provider.getLocations\n ? async () => {\n const locations = await provider.getLocations!()\n const current = getScheduleBlockConfig()\n if (current) setScheduleBlockConfig({ ...current, locations })\n return locations\n }\n : undefined,\n })\n\n const PageComponent: React.FC<any> = () =>\n React.createElement(AgendaPage, { config, provider, store })\n\n return {\n id: 'agenda',\n name: config.labels.pageTitle,\n icon: 'Calendar',\n version: '1.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n // Booking/scheduling is business-ops (clinic, salon, services) — targets\n // the saas/admin Panel world, not the ecommerce storefront.\n scaffolds: ['saas'],\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [\n { id: 'appointments', label: config.labels.pageTitle, group: config.labels.pageTitle },\n { id: 'agenda.schedules', label: 'Schedule Management', group: config.labels.pageTitle },\n ],\n // Recurring monthly quota — counts appointment rows created this month.\n // (Clients/patients are the app's CRUD entity, so their cap is declared by\n // the app's EntityDef.limitKey, not here.)\n declaredLimits: [\n { key: 'bookings_month', label: 'Appointments this month', table: 'appointments', period: 'month' },\n ],\n queryEntities: [\n {\n key: 'agenda:appointments',\n entity: {\n name: 'Appointment',\n namePlural: 'Appointments',\n icon: 'Calendar',\n permission: { feature: 'appointments', action: 'read' },\n // Keys are the PROVIDER's output shape (camelCase) — what filters/\n // dateField/groupBy match against, not the raw DB columns.\n fields: [\n { key: 'startsAt', label: 'Starts at', type: 'text' },\n { key: 'endsAt', label: 'Ends at', type: 'text' },\n { key: 'status', label: 'Status', type: 'text' },\n { key: 'clientName', label: 'Client', type: 'text', searchable: true },\n { key: 'professionalName', label: 'Professional', type: 'text', searchable: true },\n { key: 'orderTotal', label: 'Order total', type: 'number' },\n { key: 'totalDurationMinutes', label: 'Duration (min)', type: 'number' },\n { key: 'createdAt', label: 'Created at', type: 'text' },\n ],\n data: {\n table: 'v_appointments',\n tenantScoped: true,\n searchColumns: ['client_name', 'professional_name'],\n },\n },\n },\n ],\n declaredRpcs: [\n {\n name: 'agent_agenda_create_appointment',\n kind: 'write' as const,\n description:\n 'Guarded appointment create: agent_guard (role→plan→bookings_month cap), working hours, race-safe conflict check, audited.',\n audits: true,\n },\n {\n name: 'agent_agenda_update_appointment',\n kind: 'write' as const,\n description:\n 'Guarded appointment reschedule/reassign/cancel: agent_guard (role→plan, no cap), working hours, race-safe conflict check that skips the appointment itself, audited.',\n audits: true,\n },\n ],\n\n navigation: [\n {\n section: options?.navSection ?? 'main',\n position: options?.navPosition ?? 2,\n label: config.labels.pageTitle,\n route: '/agenda',\n icon: 'Calendar',\n permission: { feature: 'appointments', action: 'read' as const },\n },\n ],\n\n routes: [\n {\n path: '/agenda',\n component: PageComponent,\n permission: { feature: 'appointments', action: 'read' as const },\n // Matches the ref agent_agenda_create_appointment returns.\n entityRoutes: ['schedule:appointment'],\n },\n ],\n\n widgets: [],\n\n aiTools: [\n {\n id: 'agenda.list-appointments',\n name: 'listAppointments',\n description: 'Lists upcoming appointments for a given date or date range, optionally filtered by professional.',\n icon: 'Calendar',\n mode: 'read' as const,\n category: 'Scheduling',\n parameters: {\n type: 'object' as const,\n properties: {\n date: { type: 'string' as const, description: 'Date (YYYY-MM-DD) or \"today\", \"tomorrow\", \"this week\"' },\n professional: { type: 'string' as const, description: 'Professional name to filter by' },\n },\n },\n suggestions: [\n { label: \"What's on the agenda today?\" },\n { label: 'Show me tomorrow\\'s appointments' },\n { label: 'Who has the most bookings this week?' },\n ],\n permission: { feature: 'appointments', action: 'read' as const },\n },\n {\n id: 'agenda.create-appointment',\n name: 'createAppointment',\n description:\n 'Creates a new appointment. Takes IDS, not names: resolve the client/service/professional ids first via findAnything/searchRecords, then call this with an ISO start time in the tenant timezone. The user confirms before booking.',\n icon: 'CalendarPlus',\n mode: 'persist' as const,\n limitKey: 'bookings_month',\n execution: { plane: 'server' as const, kind: 'rpc' as const, rpc: 'agent_agenda_create_appointment' },\n category: 'Scheduling',\n parameters: {\n type: 'object' as const,\n properties: {\n client_id: { type: 'string' as const, description: 'Client id (from a search)' },\n service_id: { type: 'string' as const, description: 'Service id (from a search)' },\n professional_id: { type: 'string' as const, description: 'Professional id (optional — auto-assigned when omitted)' },\n starts_at: { type: 'string' as const, description: \"LOCAL date-time of the business, NO timezone suffix — e.g. '2026-07-27T10:00' for 10h. The system applies the tenant timezone.\" },\n notes: { type: 'string' as const, description: 'Optional notes' },\n },\n required: ['client_id', 'service_id', 'starts_at'],\n },\n suggestions: [\n { label: 'Book a haircut for Sarah tomorrow at 10am' },\n ],\n permission: { feature: 'appointments', action: 'create' as const },\n },\n {\n id: 'agenda.update-appointment',\n name: 'updateAppointment',\n description:\n 'Changes an appointment that ALREADY EXISTS: reschedule (starts_at), reassign (professional_id), cancel or confirm (status), or annotate (notes). ' +\n 'This is the ONLY way to change an appointment — the appointments entity is a read-only view, so updateRecord cannot touch it. ' +\n 'NEVER answer a reschedule or a cancellation by creating a new appointment: that leaves the original standing and double-books the professional. ' +\n 'Takes the appointment id from a previous search. The duration is preserved automatically. The user confirms before anything changes.',\n icon: 'CalendarClock',\n mode: 'persist' as const,\n execution: { plane: 'server' as const, kind: 'rpc' as const, rpc: 'agent_agenda_update_appointment' },\n category: 'Scheduling',\n parameters: {\n type: 'object' as const,\n properties: {\n appointment_id: { type: 'string' as const, description: 'Id of the appointment to change (from a search)' },\n starts_at: { type: 'string' as const, description: \"New LOCAL date-time of the business, NO timezone suffix — e.g. '2026-07-27T16:30'. Omit to keep the current time.\" },\n professional_id: { type: 'string' as const, description: 'Move to another professional (optional)' },\n status: {\n type: 'string' as const,\n description: 'New status — use \"cancelled\" to cancel',\n enum: ['scheduled', 'confirmed', 'in_progress', 'completed', 'cancelled', 'no_show'],\n },\n notes: { type: 'string' as const, description: 'Optional notes' },\n },\n required: ['appointment_id'],\n },\n suggestions: [\n { label: 'Remarca o Gustavo para 16:30' },\n { label: 'Cancela o atendimento das 10h' },\n ],\n permission: { feature: 'appointments', action: 'edit' as const },\n },\n {\n id: 'agenda.check-availability',\n name: 'checkAvailability',\n description: 'Checks available time slots for a professional on a given date.',\n icon: 'Clock',\n mode: 'read' as const,\n category: 'Scheduling',\n parameters: {\n type: 'object' as const,\n properties: {\n professional: { type: 'string' as const, description: 'Professional name' },\n date: { type: 'string' as const, description: 'Date (YYYY-MM-DD) or \"today\", \"tomorrow\"' },\n duration: { type: 'number' as const, description: 'Required duration in minutes' },\n },\n required: ['professional', 'date'],\n },\n suggestions: [\n { label: 'When is Ana available tomorrow?' },\n { label: 'Find a 90-minute slot for Carlos this week' },\n ],\n permission: { feature: 'appointments', action: 'read' as const },\n },\n ],\n\n registries,\n\n settings: [\n {\n id: 'agenda',\n label: 'Agenda',\n icon: 'Calendar',\n // Standard layout: General | Integrations (Google Calendar addon) | Properties.\n component: (() => {\n const AgendaSettingsTab: React.FC = () => React.createElement(PluginSettingsPanel, {\n title: 'Agenda',\n generalSettings: React.createElement(AgendaGeneralSettings),\n registries,\n hostPluginId: 'agenda',\n routeBase: '/settings/agenda',\n })\n AgendaSettingsTab.displayName = 'AgendaSettingsTab'\n return AgendaSettingsTab as unknown as React.ComponentType<unknown>\n })(),\n order: 5,\n permission: { feature: 'appointments', action: 'read' as const },\n },\n ],\n migrations: [\n {\n id: 'agenda-001-public-booking',\n version: '0.3.0',\n sql: MIGRATION_001_PUBLIC_BOOKING,\n description:\n 'Booking read model (v_appointments) + anon public booking surface (v_public_services, get_available_slots, create_public_booking) + order_items duration/assignee columns',\n },\n ],\n\n locales: agendaLocales,\n }\n}\n\n// Re-export types for consumers\nexport type { AgendaPluginOptions } from './config'\nexport type { ResolvedAgendaConfig } from './config'\nexport type { AgendaDataProvider } from './data/types'\n// Seedable in-memory provider — apps pass a seed to render the calendar with\n// app-specific events instead of the built-in salon sample.\nexport { createMockAgendaProvider } from './data/mock'\nexport type { MockAgendaSeed, MockAgendaProviderOptions } from './data/mock'\nexport type { AgendaFinancialBridge, BookingPaymentStatus, BookingPaymentSummary, BookingPaymentDetail } from './financial-bridge'\nexport { createFinancialBridge, computeCommissionAmount } from './bridges/create-financial-bridge'\n\n// Google Calendar integration (official addon) — settings-only plugin + helpers\nexport { createGoogleCalendarPlugin, createGoogleCalendarProvider, googleCalendarConnector, bookingToEvent, eventToBookingPatch } from './integrations/google-calendar'\n"]}
1
+ {"version":3,"sources":["../src/lib/message-events.ts","../src/config.ts","../src/context.tsx","../src/styles/calendar-styles.ts","../src/hooks/useAgendaSettings.ts","../src/components/MiniCalendar.tsx","../src/components/BookingPaymentPanel.tsx","../src/types.ts","../src/components/AppointmentModal.tsx","../src/components/FloatingPanel.tsx","../src/components/AppointmentPopover.tsx","../src/components/EventContextMenu.tsx","../src/components/AgendaMobileList.tsx","../src/views/CalendarView.tsx","../src/lib/tenant.ts","../src/views/AgendaPage.tsx","../src/data/supabase.ts","../src/store.ts","../src/data/registries.ts","../src/components/AgendaGeneralSettings.tsx","../src/locales/en.ts","../src/locales/pt-BR.ts","../src/locales/index.ts","../src/migrations/index.ts","../src/bridges/create-financial-bridge.ts","../src/integrations/google-calendar/mapping.ts","../src/integrations/google-calendar/data/tables.ts","../src/integrations/google-calendar/data/supabase.ts","../src/integrations/google-calendar/components/CalendarColorDot.tsx","../src/integrations/google-calendar/components/useAgendaLookups.ts","../src/integrations/google-calendar/components/ChannelMappingList.tsx","../src/integrations/google-calendar/components/ImportEventsWizard.tsx","../src/integrations/google-calendar/connectorDef.tsx","../src/integrations/google-calendar/connector.ts","../src/integrations/google-calendar/index.ts","../src/index.ts"],"names":["React","formatCurrency","t","jsxs","jsx","useState","useEffect","Fragment","createPortal","useTranslation","getCurrentLocale","provider","useMemo","getSupabaseClientOptional","X","Check","STYLE_ID","useRef","fmtCurrency","Clock","User","MapPin","FileText","HandCoins","DollarSign","AlertTriangle","Tooltip","Pencil","Trash2","usePluginPrefs","useCallback","booking","t2","PersonLink","Plus","ChevronLeft","ChevronRight","Button","bookingToEvent","getActiveTenantId","toast","Loader2","AlertCircle","RefreshCw","Checkbox","Badge","CalendarPlus","CheckCircle2","setScheduleBlockConfig","getScheduleBlockConfig"],"mappings":"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","file":"index.js","sourcesContent":["import type { PluginEventDefinition, MessageDefaultsDef, EventField } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Os FATOS da agenda, e — separadamente — o texto sugerido para cada um.\n//\n// buildAgendaDomainEvents() o contrato do fato: o que houve, que dados\n// vêm junto, se entra na auditoria. Webhook,\n// Google Agenda e auditoria leem isto.\n// buildAgendaMessageDefaults() uma REAÇÃO: canal + texto. Só as automações.\n//\n// É aqui que mora a automação que todo salão e toda clínica esperam ter no\n// primeiro dia: o lembrete de véspera. Cliente que não aparece é prejuízo\n// direto, e o lembrete é a mensagem que se paga sozinha.\n// ---------------------------------------------------------------------------\n\nconst BOOKING_FIELDS: EventField[] = [\n { name: 'customer_name', label: 'Cliente', type: 'string', example: 'Maria Silva' },\n { name: 'service_name', label: 'Serviço', type: 'string', example: 'Corte + Escova' },\n { name: 'professional_name', label: 'Profissional', type: 'string', example: 'Camila Duarte' },\n { name: 'booking_date', label: 'Data', type: 'date', example: '12/08/2026' },\n { name: 'booking_time', label: 'Horário', type: 'string', example: '14:30' },\n { name: 'location_name', label: 'Local', type: 'string', example: 'Unidade Centro' },\n { name: 'business_name', label: 'Seu negócio', type: 'string', example: 'Seu Negócio' },\n]\n\n/**\n * Os FATOS da agenda.\n *\n * `audit: true` em todos: marcar, remarcar e cancelar um horário são ATOS de\n * alguém — e \"quem cancelou este atendimento?\" é exatamente a pergunta que a\n * trilha de auditoria existe para responder. Nenhum evento aqui é a ausência\n * de um ato: até 'no_show' é registrado por alguém da recepção.\n */\nexport function buildAgendaDomainEvents(): PluginEventDefinition[] {\n return [\n { name: 'agenda.booking_created', title: 'Agendamento criado', icon: 'CalendarPlus', audit: true,\n description: 'Um horário foi marcado',\n trigger: 'Quando o agendamento é criado (recepção, site ou app)',\n fields: BOOKING_FIELDS },\n { name: 'agenda.booking_reminder', title: 'Lembrete de horário', icon: 'BellRing', audit: false,\n description: 'Véspera do atendimento',\n trigger: 'No dia anterior ao horário marcado',\n fields: BOOKING_FIELDS },\n { name: 'agenda.booking_rescheduled', title: 'Horário remarcado', icon: 'CalendarClock', audit: true,\n description: 'O atendimento mudou de dia ou de hora',\n trigger: 'Quando a data ou o horário do agendamento muda',\n fields: BOOKING_FIELDS },\n { name: 'agenda.booking_cancelled', title: 'Agendamento cancelado', icon: 'CalendarX', audit: true,\n description: 'O horário foi desmarcado',\n trigger: 'Quando o agendamento é cancelado',\n fields: BOOKING_FIELDS },\n { name: 'agenda.booking_completed', title: 'Atendimento concluído', icon: 'CalendarCheck', audit: true,\n description: 'O atendimento aconteceu',\n trigger: 'Quando o agendamento é marcado como concluído',\n fields: BOOKING_FIELDS },\n { name: 'agenda.booking_no_show', title: 'Cliente não compareceu', icon: 'UserX', audit: true,\n description: 'O horário foi perdido',\n trigger: 'Quando o agendamento é marcado como falta',\n fields: BOOKING_FIELDS },\n ]\n}\n\nexport function buildAgendaMessageDefaults(): MessageDefaultsDef[] {\n return [\n {\n eventKey: 'agenda.booking_created',\n kind: 'transactional',\n // WhatsApp na frente em toda a agenda: confirmação de horário é lida no\n // celular, e no Brasil é lá que a cliente responde.\n channels: ['whatsapp', 'email'],\n defaults: {\n whatsapp: {\n body: 'Oi {{customer_name}}! Seu horário está marcado ✅\\n\\n*{{service_name}}*\\n{{booking_date}} às {{booking_time}}\\ncom {{professional_name}}\\n\\nQualquer coisa é só chamar aqui. — {{business_name}}',\n },\n email: {\n subject: 'Horário confirmado — {{booking_date}} às {{booking_time}}',\n body: 'Olá {{customer_name}},\\n\\nSeu horário está confirmado:\\n\\n{{service_name}}\\n{{booking_date}} às {{booking_time}}\\ncom {{professional_name}}\\n{{location_name}}\\n\\nAté lá!\\n{{business_name}}',\n },\n },\n // Confirmar por e-mail é o mínimo que se espera de quem acabou de marcar\n // um horário — nasce ligado. O WhatsApp custa por mensagem e exige número\n // aprovado; ligá-lo sozinho gastaria o dinheiro de alguém sem ser pedido.\n defaultEnabled: { email: true },\n },\n {\n eventKey: 'agenda.booking_reminder',\n kind: 'transactional',\n channels: ['whatsapp', 'email'],\n defaults: {\n whatsapp: {\n body: 'Oi {{customer_name}}! Passando para lembrar do seu horário amanhã 💇\\n\\n*{{service_name}}*\\n{{booking_date}} às {{booking_time}}\\ncom {{professional_name}}\\n\\nConsegue vir? Se precisar remarcar, me avisa por aqui. — {{business_name}}',\n },\n email: {\n subject: 'Lembrete: seu horário é amanhã, {{booking_time}}',\n body: 'Olá {{customer_name}},\\n\\nSeu horário é amanhã:\\n\\n{{service_name}}\\n{{booking_date}} às {{booking_time}}\\ncom {{professional_name}}\\n{{location_name}}\\n\\nSe precisar remarcar, é só responder este e-mail.\\n\\n{{business_name}}',\n },\n },\n defaultEnabled: { email: true },\n },\n {\n eventKey: 'agenda.booking_rescheduled',\n kind: 'transactional',\n channels: ['whatsapp', 'email'],\n defaults: {\n whatsapp: {\n body: 'Oi {{customer_name}}! Seu horário foi remarcado 🗓\\n\\n*{{service_name}}*\\nAgora: {{booking_date}} às {{booking_time}}\\ncom {{professional_name}}\\n\\n— {{business_name}}',\n },\n email: {\n subject: 'Seu horário mudou para {{booking_date}}, {{booking_time}}',\n body: 'Olá {{customer_name}},\\n\\nSeu horário foi remarcado:\\n\\n{{service_name}}\\n{{booking_date}} às {{booking_time}}\\ncom {{professional_name}}\\n\\n{{business_name}}',\n },\n },\n defaultEnabled: { email: true },\n },\n {\n eventKey: 'agenda.booking_cancelled',\n kind: 'transactional',\n channels: ['whatsapp', 'email'],\n defaults: {\n whatsapp: {\n body: 'Oi {{customer_name}}, seu horário de {{booking_date}} às {{booking_time}} foi cancelado.\\n\\nQuer que eu veja outra data para você? — {{business_name}}',\n },\n email: {\n subject: 'Horário de {{booking_date}} cancelado',\n body: 'Olá {{customer_name}},\\n\\nSeu horário de {{booking_date}} às {{booking_time}} foi cancelado.\\n\\nSe quiser remarcar, é só responder este e-mail.\\n\\n{{business_name}}',\n },\n },\n defaultEnabled: { email: true },\n },\n {\n eventKey: 'agenda.booking_completed',\n kind: 'marketing',\n // Pedir opinião é iniciativa do negócio, não resposta a um ato da\n // pessoa — e é por isso que nasce desligado.\n channels: ['whatsapp'],\n defaults: {\n whatsapp: {\n body: 'Oi {{customer_name}}! Foi ótimo te atender hoje 💛\\n\\nComo foi a experiência com {{professional_name}}? Sua opinião ajuda demais.\\n\\n— {{business_name}}',\n },\n },\n },\n {\n eventKey: 'agenda.booking_no_show',\n kind: 'transactional',\n channels: ['whatsapp'],\n defaults: {\n whatsapp: {\n body: 'Oi {{customer_name}}, senti sua falta no horário de {{booking_date}} 😔\\n\\nAconteceu alguma coisa? Se quiser, já deixo outro horário separado para você. — {{business_name}}',\n },\n },\n },\n ]\n}\n","import type { PluginRegistryDef, PluginScope, VerticalId } from '@fayz-ai/core'\nimport type { EntityLookup } from '@fayz-ai/admin'\nimport type { AgendaDataProvider } from './data/types'\nimport type { StatusConfig, BookingTypeConfig } from './types'\nimport type { AgendaFinancialBridge } from './bridges/financial-bridge'\nimport type { EntityDef } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Public options interface\n// ---------------------------------------------------------------------------\n\nexport interface AgendaPluginLabels {\n pageTitle: string\n pageSubtitle: string\n calendar: string\n dayView: string\n weekView: string\n monthView: string\n listView: string\n workingHours: string\n confirmations: string\n newAppointment: string\n filters: string\n}\n\nexport interface ConfirmationChannelOption {\n id: string\n label: string\n icon: string\n}\n\nexport interface CancellationReasonOption {\n id: string\n label: string\n requiresNotes?: boolean\n}\n\nexport interface CancellationDetailsProvider {\n listReasons(): Promise<CancellationReasonOption[]>\n saveCancellationDetails(input: {\n bookingId: string\n reasonId: string\n notes?: string\n cancelledAt?: string\n }): Promise<void>\n}\n\nexport interface ExternalBookingSource {\n type: string\n id?: string\n [key: string]: unknown\n}\n\nexport interface LocationOption {\n id: string\n name: string\n isHQ?: boolean\n}\n\nexport interface AgendaPluginOptions {\n modules?: {\n workingHours?: boolean\n confirmations?: boolean\n conflictDetection?: boolean\n dragAndDrop?: boolean\n locationSelection?: boolean\n /** Enable financial integration (auto-enabled when financialBridge is provided) */\n financial?: boolean\n }\n labels?: Partial<AgendaPluginLabels>\n currency?: { code?: string; locale?: string; symbol?: string }\n\n /** Booking kind used in public.appointments.kind (default: 'appointment') */\n bookingKind?: string\n\n /** Order kind for financial records (default: 'service_order') */\n orderKind?: string\n\n /** Schedule kind in public.schedules.kind (default: 'working_hours') */\n scheduleKind?: string\n\n /** Booking type tabs shown in the appointment modal */\n bookingTypes?: BookingTypeConfig[]\n\n /**\n * Simplifies the agenda to Google-Calendar-style events (no client /\n * professional / service). When set to 'simple', the plugin exposes a single\n * \"Evento\" booking type whose modal shows only title / date-time / notes.\n * Ignored when an explicit `bookingTypes` override is provided.\n */\n eventMode?: 'simple'\n\n /** Booking status options */\n statuses?: StatusConfig[]\n\n /** Default calendar view (default: 'resourceTimeGridWeek'). Options: 'dayGridMonth', 'timeGridWeek', 'resourceTimeGridWeek', 'listWeek' */\n defaultCalendarView?: string\n\n /** Calendar visible time range (default: '07:00'-'21:00') */\n businessHours?: { startTime: string; endTime: string }\n\n /** Slot duration in minutes (default: 30) */\n slotDuration?: number\n\n /** Person kind for professionals (default: 'staff') */\n professionalKind?: string\n\n /** Person kind for clients (default: 'customer') */\n clientKind?: string\n\n /** Auto-create an order when creating a booking (default: true) */\n autoCreateOrder?: boolean\n\n /** Contact/client lookup */\n contactLookup?: EntityLookup\n\n /** Client entity definition for the Client tab in booking modal */\n clientEntityDef?: EntityDef\n\n /** Service lookup */\n serviceLookup?: EntityLookup\n\n /** Professional/staff lookup */\n professionalLookup?: EntityLookup\n\n /** Location lookup */\n locationLookup?: EntityLookup\n\n /** Called when user clicks a selected entity link (e.g. view client profile) */\n onEntityClick?: (type: 'client' | 'service' | 'professional', id: string) => void\n\n /** Business locations for unit filtering */\n locations?: LocationOption[]\n\n /** Confirmation channel options */\n confirmationChannels?: ConfirmationChannelOption[]\n\n /** Optional app/plugin bridge for cancel-time reason capture. */\n cancellationDetails?: CancellationDetailsProvider\n\n /** Called after a booking is created from an external operational source. */\n onBookingCreated?: (input: { bookingId: string; source?: ExternalBookingSource }) => void | Promise<void>\n\n /** App-owned registries shown under /settings/agenda Properties. */\n settingsRegistries?: PluginRegistryDef[]\n\n /** Financial bridge for agenda × financial cross-plugin integration */\n financialBridge?: AgendaFinancialBridge\n\n /** Data provider — defaults to Supabase, falls back to mock */\n dataProvider?: AgendaDataProvider\n\n /** Default values for schedule block advanced settings */\n scheduleBlockDefaults?: {\n bufferMinutes?: number\n maxConcurrent?: number\n minAdvanceHours?: number\n maxAdvanceDays?: number\n }\n\n navPosition?: number\n navSection?: 'main' | 'secondary'\n scope?: PluginScope\n verticalId?: VerticalId\n}\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_LABELS: AgendaPluginLabels = {\n pageTitle: 'Agenda',\n pageSubtitle: 'Calendar and appointment management',\n calendar: 'Calendar',\n dayView: 'Day',\n weekView: 'Week',\n monthView: 'Month',\n listView: 'Agenda',\n workingHours: 'Working Hours',\n confirmations: 'Confirmations',\n newAppointment: 'New Appointment',\n filters: 'Filters',\n}\n\nconst DEFAULT_CURRENCY = { code: 'BRL', locale: 'pt-BR', symbol: 'R$' }\n\nconst DEFAULT_STATUSES: StatusConfig[] = [\n { value: 'scheduled', label: 'Scheduled', color: '#6366f1' },\n { value: 'confirmed', label: 'Confirmed', color: '#3b82f6' },\n { value: 'in_progress', label: 'In Progress', color: '#f59e0b', availableWhen: 'today_only' },\n { value: 'completed', label: 'Completed', color: '#10b981', availableWhen: 'today_or_past' },\n { value: 'cancelled', label: 'Cancelled', color: '#ef4444' },\n { value: 'no_show', label: 'No Show', color: '#6b7280', availableWhen: 'today_or_past' },\n]\n\nconst DEFAULT_BOOKING_TYPES: BookingTypeConfig[] = [\n {\n id: 'appointment', label: 'Appointment', icon: 'Calendar', color: '#6366f1',\n fields: { client: true, professional: true, services: true, location: true, status: true },\n requiresServices: true, requiresClient: true,\n },\n {\n id: 'task', label: 'Task', icon: 'CheckSquare', color: '#f59e0b',\n fields: { client: false, professional: true, services: false, location: false, status: true },\n requiresServices: false, requiresClient: false,\n },\n {\n id: 'block', label: 'Block', icon: 'Ban', color: '#6b7280',\n fields: { client: false, professional: true, services: false, location: false, status: false },\n requiresServices: false, requiresClient: false,\n },\n]\n\n// Simple / Google-Calendar-style event — a single \"Evento\" type with just a\n// free-text title, date-time and notes. No client / professional / service.\n// Used by personal-finance-style agendas (see eventMode: 'simple').\nconst SIMPLE_EVENT_BOOKING_TYPES: BookingTypeConfig[] = [\n {\n id: 'event', label: 'Event', icon: 'Calendar', color: '#6366f1',\n fields: { title: true, client: false, professional: false, services: false, location: false, status: false },\n requiresServices: false, requiresClient: false,\n },\n]\n\n// ---------------------------------------------------------------------------\n// Resolved config — fully merged, no optionals\n// ---------------------------------------------------------------------------\n\nexport interface AgendaModules {\n workingHours: boolean\n confirmations: boolean\n conflictDetection: boolean\n dragAndDrop: boolean\n locationSelection: boolean\n financial: boolean\n}\n\n/**\n * Derived UI capabilities — computed ONCE in resolveConfig from the resolved\n * bookingTypes so no component ever re-derives \"is this a simple event agenda?\"\n * ad-hoc. A capability is enabled when ANY booking type uses that field. In\n * eventMode:'simple' the single \"Evento\" type disables\n * client/professional/services/location/status, so every consumer (popover,\n * filter rail, modal) hides the professional/service/status machinery in one\n * place instead of scattering `eventMode === 'simple'` checks.\n */\nexport interface AgendaCapabilities {\n title: boolean\n client: boolean\n professional: boolean\n services: boolean\n location: boolean\n status: boolean\n}\n\nexport interface AgendaCurrency {\n code: string\n locale: string\n symbol: string\n}\n\nexport interface ResolvedAgendaConfig {\n modules: AgendaModules\n /** Whether this is a simple Google-Calendar-style event agenda (eventMode:'simple'). */\n simpleMode: boolean\n /** Derived once from bookingTypes — see AgendaCapabilities. */\n capabilities: AgendaCapabilities\n labels: AgendaPluginLabels\n currency: AgendaCurrency\n bookingKind: string\n orderKind: string\n scheduleKind: string\n statuses: StatusConfig[]\n bookingTypes: BookingTypeConfig[]\n businessHours: { startTime: string; endTime: string }\n slotDuration: number\n professionalKind: string\n clientKind: string\n autoCreateOrder: boolean\n locations: LocationOption[]\n confirmationChannels: ConfirmationChannelOption[]\n cancellationDetails?: CancellationDetailsProvider\n onBookingCreated?: (input: { bookingId: string; source?: ExternalBookingSource }) => void | Promise<void>\n contactLookup?: EntityLookup\n clientEntityDef?: EntityDef\n serviceLookup?: EntityLookup\n professionalLookup?: EntityLookup\n locationLookup?: EntityLookup\n onEntityClick?: (type: 'client' | 'service' | 'professional', id: string) => void\n financialBridge?: AgendaFinancialBridge\n scheduleBlockDefaults: {\n bufferMinutes: number\n maxConcurrent: number\n minAdvanceHours: number\n maxAdvanceDays: number\n }\n defaultCalendarView: string\n}\n\n// ---------------------------------------------------------------------------\n// Config resolver\n// ---------------------------------------------------------------------------\n\nexport function resolveConfig(options?: AgendaPluginOptions): ResolvedAgendaConfig {\n // ── eventMode:'simple' derives ALL module + capability defaults ONCE, here. ──\n // Simple = Google-Calendar-style events (title/description + timestamp). It\n // flips professional/service machinery OFF by default: no working-hours /\n // schedule checks, no confirmations outreach, no conflict (double-booking)\n // detection, no location. Explicit `modules.*` re-enable individually. Full\n // mode (beauty) is unchanged — every default below matches the old behavior\n // when `simple` is false. Field-level machinery (client/professional/\n // services/location/status/title) is derived into `capabilities` from the\n // resolved bookingTypes, so components never test eventMode themselves.\n const simple = options?.eventMode === 'simple'\n const bookingTypes = options?.bookingTypes\n ?? (simple ? SIMPLE_EVENT_BOOKING_TYPES : DEFAULT_BOOKING_TYPES)\n const capabilities: AgendaCapabilities = {\n title: bookingTypes.some((bt) => bt.fields.title === true),\n client: bookingTypes.some((bt) => bt.fields.client),\n professional: bookingTypes.some((bt) => bt.fields.professional),\n services: bookingTypes.some((bt) => bt.fields.services),\n location: bookingTypes.some((bt) => bt.fields.location),\n status: bookingTypes.some((bt) => bt.fields.status),\n }\n return {\n modules: {\n // Off-unless-explicit in simple mode (`?? !simple`); default-on in full.\n workingHours: options?.modules?.workingHours ?? !simple,\n confirmations: options?.modules?.confirmations ?? !simple,\n conflictDetection: options?.modules?.conflictDetection ?? !simple,\n dragAndDrop: options?.modules?.dragAndDrop !== false,\n locationSelection: options?.modules?.locationSelection === true,\n financial: options?.modules?.financial ?? !!options?.financialBridge,\n },\n simpleMode: simple,\n capabilities,\n labels: { ...DEFAULT_LABELS, ...options?.labels },\n currency: { ...DEFAULT_CURRENCY, ...options?.currency },\n bookingKind: options?.bookingKind ?? 'appointment',\n orderKind: options?.orderKind ?? 'service_order',\n scheduleKind: options?.scheduleKind ?? 'working_hours',\n statuses: options?.statuses ?? DEFAULT_STATUSES,\n bookingTypes,\n businessHours: options?.businessHours ?? { startTime: '07:00', endTime: '21:00' },\n slotDuration: options?.slotDuration ?? 30,\n professionalKind: options?.professionalKind ?? 'staff',\n clientKind: options?.clientKind ?? 'customer',\n autoCreateOrder: options?.autoCreateOrder !== false,\n locations: options?.locations ?? [],\n confirmationChannels: options?.confirmationChannels ?? [],\n cancellationDetails: options?.cancellationDetails,\n onBookingCreated: options?.onBookingCreated,\n contactLookup: options?.contactLookup,\n clientEntityDef: options?.clientEntityDef,\n serviceLookup: options?.serviceLookup,\n professionalLookup: options?.professionalLookup,\n locationLookup: options?.locationLookup,\n onEntityClick: options?.onEntityClick,\n financialBridge: options?.financialBridge,\n scheduleBlockDefaults: {\n bufferMinutes: options?.scheduleBlockDefaults?.bufferMinutes ?? 0,\n maxConcurrent: options?.scheduleBlockDefaults?.maxConcurrent ?? 1,\n minAdvanceHours: options?.scheduleBlockDefaults?.minAdvanceHours ?? 0,\n maxAdvanceDays: options?.scheduleBlockDefaults?.maxAdvanceDays ?? 60,\n },\n defaultCalendarView: options?.defaultCalendarView ?? 'resourceTimeGridWeek',\n }\n}\n","import { createPluginContext } from '@fayz-ai/admin'\nimport type { ResolvedAgendaConfig } from './config'\nimport type { AgendaDataProvider } from './data/types'\nimport type { AgendaUIState } from './store'\n\nconst ctx = createPluginContext<ResolvedAgendaConfig, AgendaDataProvider, AgendaUIState>('AgendaPage')\n\nexport const AgendaContextProvider = ctx.ContextProvider\nexport const useAgendaConfig = ctx.useConfig\nexport const useAgendaProvider = ctx.useProvider\nexport const useAgendaStore = ctx.useStore\n","/**\n * Injects agenda calendar CSS at runtime.\n * This ensures styles work both in symlinked dev mode and when consumed\n * as a built package (where CSS side-effect imports are extracted by tsup\n * and not automatically loaded).\n */\n\nconst STYLE_ID = 'saas-agenda-calendar-styles'\n\nconst css = /* css */ `\n/* Dark mode content background — uses the content token */\n.dark .agenda-calendar,\n.dark .agenda-calendar .fc,\n.dark .agenda-calendar .fc-view-harness,\n.dark .agenda-calendar .fc-timegrid,\n.dark .agenda-calendar .fc-scrollgrid,\n.dark .agenda-calendar .fc-timegrid-col,\n.dark .agenda-calendar .fc-daygrid-body,\n.dark .agenda-calendar .fc-timegrid-slot-lane {\n background-color: hsl(var(--content));\n}\n\n/* FullCalendar — Google Calendar inspired theme */\n\n.agenda-calendar {\n --fc-border-color: hsl(var(--border));\n --fc-today-bg-color: transparent;\n --fc-now-indicator-color: hsl(var(--destructive));\n --fc-highlight-color: hsl(var(--primary) / 0.06);\n --fc-non-business-color: hsl(var(--muted) / 0.15);\n --fc-neutral-bg-color: transparent;\n --fc-page-bg-color: transparent;\n --fc-event-border-color: transparent;\n}\n\n.agenda-calendar .fc {\n font-family: inherit;\n background: transparent;\n}\n\n.agenda-calendar .fc .fc-view-harness {\n background: transparent;\n}\n\n/* ── Column headers ── */\n.agenda-calendar .fc-col-header-cell {\n background: transparent;\n border-bottom: 1px solid var(--fc-border-color);\n border-left: none;\n border-right: none;\n border-top: none;\n}\n\n.agenda-calendar .fc-col-header-cell-cushion {\n padding: 8px 4px;\n font-weight: 400;\n font-size: 0.7rem;\n color: hsl(var(--muted-foreground));\n text-decoration: none;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n/* Today's column header */\n.agenda-calendar .fc-day-today .fc-col-header-cell-cushion {\n color: hsl(var(--primary));\n font-weight: 600;\n}\n\n/* Resource header (professional columns) */\n.agenda-calendar .fc .fc-resource-header {\n background: transparent;\n border-bottom: 1px solid var(--fc-border-color);\n}\n\n/* ── Time slots — compact ── */\n.agenda-calendar .fc-timegrid-slot {\n height: 1.5rem;\n border-bottom: 1px solid hsl(var(--border) / 0.4);\n}\n\n.agenda-calendar .fc-timegrid-slot-label {\n vertical-align: top;\n border: none;\n}\n\n.agenda-calendar .fc-timegrid-slot-label-cushion {\n font-size: 0.65rem;\n color: hsl(var(--muted-foreground) / 0.7);\n padding: 1px 8px 0 0;\n}\n\n/* Half-hour lines lighter */\n.agenda-calendar .fc-timegrid-slot-minor {\n border-bottom-style: none;\n}\n\n/* Column dividers */\n.agenda-calendar .fc-timegrid-col {\n border-right: 1px solid hsl(var(--border) / 0.5);\n}\n\n/* ── Events ── */\n.agenda-calendar .fc-event {\n border-radius: 6px;\n border-width: 0;\n border-left: 4px solid;\n cursor: pointer;\n transition: opacity 0.15s, box-shadow 0.15s, backdrop-filter 0.15s;\n font-size: 0.7rem;\n line-height: 1.3;\n margin: 0 2px;\n overflow: hidden;\n backdrop-filter: blur(8px) saturate(140%);\n -webkit-backdrop-filter: blur(8px) saturate(140%);\n}\n\n.agenda-calendar .fc-event .fc-event-main {\n background: inherit;\n border-radius: inherit;\n overflow: hidden;\n}\n\n.agenda-calendar .fc-event:not(.fc-bg-event):hover {\n opacity: 0.92;\n box-shadow: 0 2px 8px rgba(0,0,0,0.12);\n backdrop-filter: blur(12px) saturate(160%);\n -webkit-backdrop-filter: blur(12px) saturate(160%);\n}\n\n.agenda-calendar .fc-bg-event {\n pointer-events: none;\n}\n\n/* ── Now indicator ── */\n.agenda-calendar .fc-timegrid-now-indicator-line {\n border-color: hsl(var(--destructive));\n border-width: 2px;\n}\n\n.agenda-calendar .fc-timegrid-now-indicator-arrow {\n border-top-color: hsl(var(--destructive));\n}\n\n/* ── Month view ── */\n.agenda-calendar .fc-daygrid-day-number {\n font-size: 0.8rem;\n padding: 4px 8px;\n text-decoration: none;\n color: hsl(var(--foreground));\n}\n\n.agenda-calendar .fc-daygrid-day.fc-day-today .fc-daygrid-day-number {\n background-color: hsl(var(--primary));\n color: hsl(var(--primary-foreground));\n border-radius: 50%;\n width: 1.5rem;\n height: 1.5rem;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.75rem;\n}\n\n/* ── Selection ── */\n.agenda-calendar .fc-highlight {\n background: hsl(var(--primary) / 0.08);\n}\n\n/* ── Links ── */\n.agenda-calendar .fc a {\n text-decoration: none;\n color: inherit;\n}\n\n/* ── Scrollbar ── */\n.agenda-calendar .fc-scroller {\n scrollbar-width: thin;\n scrollbar-color: hsl(var(--muted-foreground) / 0.12) transparent;\n}\n\n.agenda-calendar .fc-scroller::-webkit-scrollbar {\n width: 6px;\n}\n\n.agenda-calendar .fc-scroller::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.agenda-calendar .fc-scroller::-webkit-scrollbar-thumb {\n background: hsl(var(--muted-foreground) / 0.12);\n border-radius: 3px;\n}\n\n/* ── Clean up borders ── */\n.agenda-calendar .fc .fc-timegrid {\n border: none;\n}\n\n.agenda-calendar .fc-scrollgrid {\n border: none !important;\n}\n\n.agenda-calendar .fc-scrollgrid td:last-child {\n border-right: none;\n}\n\n/* ── Unavailable time background — opaque/disabled feel ── */\n.agenda-calendar .fc-unavailable-bg {\n background: hsl(var(--muted-foreground) / 0.08) !important;\n background-image: repeating-linear-gradient(\n 45deg,\n transparent,\n transparent 4px,\n hsl(var(--muted-foreground) / 0.04) 4px,\n hsl(var(--muted-foreground) / 0.04) 8px\n ) !important;\n border-radius: 0;\n border-left: none !important;\n}\n\n/* ── Location label on schedule blocks ── */\n.agenda-calendar .fc-location-label {\n background: transparent !important;\n border: none !important;\n border-left-width: 0 !important;\n cursor: default !important;\n pointer-events: none;\n box-shadow: none !important;\n z-index: 1 !important;\n margin: 0 4px !important;\n font-weight: 500 !important;\n}\n\n.agenda-calendar .fc-location-label .fc-event-main {\n padding: 0 !important;\n}\n\n/* Week view day header with date */\n.agenda-calendar .fc-timegrid .fc-col-header-cell {\n padding: 4px 0;\n}\n\n/* ── Alternating resource column backgrounds ── */\n.agenda-calendar .fc-resource-alt {\n background-color: hsl(var(--muted) / 0.4) !important;\n}\n\n.dark .agenda-calendar .fc-resource-alt {\n background-color: hsl(var(--muted-foreground) / 0.08) !important;\n}\n\n/* Resource group header separator — stronger border between professionals */\n.agenda-calendar .fc-resource-group {\n border-left: 2px solid hsl(var(--border));\n}\n\n/* Also stripe the resource header label for the alt group */\n.agenda-calendar th.fc-resource-alt {\n background-color: hsl(var(--muted) / 0.4) !important;\n}\n\n.dark .agenda-calendar th.fc-resource-alt {\n background-color: hsl(var(--muted-foreground) / 0.06) !important;\n}\n`\n\nlet injected = false\n\nexport function injectCalendarStyles(): void {\n if (injected) return\n if (typeof document === 'undefined') return\n\n // Check if already present (e.g. from CSS import in dev mode)\n if (document.getElementById(STYLE_ID)) {\n injected = true\n return\n }\n\n const style = document.createElement('style')\n style.id = STYLE_ID\n style.textContent = css\n document.head.appendChild(style)\n injected = true\n}\n","import { usePluginPrefs } from '@fayz-ai/admin'\n\nconst DEFAULTS = {\n startTime: '07:00',\n endTime: '21:00',\n}\n\nexport function useAgendaSettings() {\n const prefs = usePluginPrefs('agenda', DEFAULTS)\n\n return {\n startTime: prefs.get('startTime'),\n endTime: prefs.get('endTime'),\n setStartTime: (v: string) => prefs.set('startTime', v),\n setEndTime: (v: string) => prefs.set('endTime', v),\n }\n}\n","import React, { useMemo } from 'react'\nimport { ChevronLeft, ChevronRight } from 'lucide-react'\nimport { getCurrentLocale } from '@fayz-ai/core'\n\ninterface MiniCalendarProps {\n selectedDate: Date\n onDateSelect: (date: Date) => void\n onMonthChange?: (date: Date) => void\n}\n\nconst DAY_LABELS: Record<string, string[]> = {\n en: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],\n 'pt-BR': ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],\n}\n\nfunction isSameDay(a: Date, b: Date) {\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()\n}\n\nfunction isToday(d: Date) {\n return isSameDay(d, new Date())\n}\n\nfunction toDateLocale(locale: string): string {\n if (locale === 'pt-BR') return 'pt-BR'\n return 'en-US'\n}\n\nexport function MiniCalendar({ selectedDate, onDateSelect, onMonthChange }: MiniCalendarProps) {\n const locale = getCurrentLocale()\n const [viewMonth, setViewMonth] = React.useState(() => new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 1))\n\n const monthLabel = viewMonth.toLocaleDateString(toDateLocale(locale), { month: 'long', year: 'numeric' })\n const dayLabels = DAY_LABELS[locale] ?? DAY_LABELS.en\n\n const weeks = useMemo(() => {\n const year = viewMonth.getFullYear()\n const month = viewMonth.getMonth()\n const firstDay = new Date(year, month, 1)\n const startOffset = firstDay.getDay()\n const daysInMonth = new Date(year, month + 1, 0).getDate()\n\n const cells: (Date | null)[] = []\n for (let i = 0; i < startOffset; i++) cells.push(null)\n for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(year, month, d))\n while (cells.length % 7 !== 0) cells.push(null)\n\n const rows: (Date | null)[][] = []\n for (let i = 0; i < cells.length; i += 7) rows.push(cells.slice(i, i + 7))\n return rows\n }, [viewMonth])\n\n function prevMonth() {\n const d = new Date(viewMonth.getFullYear(), viewMonth.getMonth() - 1, 1)\n setViewMonth(d)\n onMonthChange?.(d)\n }\n\n function nextMonth() {\n const d = new Date(viewMonth.getFullYear(), viewMonth.getMonth() + 1, 1)\n setViewMonth(d)\n onMonthChange?.(d)\n }\n\n function handleClick(date: Date) {\n onDateSelect(date)\n }\n\n return (\n <div className=\"select-none\">\n {/* Month header */}\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm font-medium capitalize\">{monthLabel}</span>\n <div className=\"flex items-center gap-0.5\">\n <button onClick={prevMonth} className=\"flex h-6 w-6 items-center justify-center rounded-full hover:bg-muted transition-colors\">\n <ChevronLeft className=\"h-3.5 w-3.5\" />\n </button>\n <button onClick={nextMonth} className=\"flex h-6 w-6 items-center justify-center rounded-full hover:bg-muted transition-colors\">\n <ChevronRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n\n {/* Day labels */}\n <div className=\"grid grid-cols-7 mb-0.5\">\n {dayLabels.map((label, i) => (\n <div key={i} className=\"flex h-6 w-6 items-center justify-center text-[10px] font-medium text-muted-foreground mx-auto\">\n {label}\n </div>\n ))}\n </div>\n\n {/* Dates */}\n {weeks.map((week, wi) => (\n <div key={wi} className=\"grid grid-cols-7\">\n {week.map((date, di) => {\n if (!date) return <div key={di} className=\"h-6 w-6 mx-auto\" />\n const selected = isSameDay(date, selectedDate)\n const today = isToday(date)\n return (\n <button\n key={di}\n onClick={() => handleClick(date)}\n className={`flex h-6 w-6 items-center justify-center rounded-full text-[11px] mx-auto transition-colors ${\n selected\n ? 'bg-primary text-primary-foreground'\n : today\n ? 'bg-primary/10 text-primary font-semibold'\n : 'hover:bg-muted text-foreground'\n }`}\n >\n {date.getDate()}\n </button>\n )\n })}\n </div>\n ))}\n </div>\n )\n}\n","import React, { useState, useEffect } from 'react'\nimport { createPortal } from 'react-dom'\nimport { X, Check, Banknote, QrCode, CreditCard, ArrowRightLeft, FileCheck, ExternalLink } from 'lucide-react'\nimport { useAgendaConfig } from '../context'\nimport { useTranslation } from '@fayz-ai/core'\nimport type { BookingPaymentDetail } from '../bridges/financial-bridge'\n\n// ---------------------------------------------------------------------------\n// Payment method type visuals (mirrors financial PaymentModal)\n// ---------------------------------------------------------------------------\n\nconst TYPE_ICONS: Record<string, React.ElementType> = {\n cash: Banknote, pix: QrCode, credit_card: CreditCard, debit_card: CreditCard,\n bank_transfer: ArrowRightLeft, check: FileCheck,\n}\n\nconst TYPE_COLORS: Record<string, string> = {\n cash: 'border-success/30 bg-success/5 hover:bg-success/10 data-[active=true]:border-success data-[active=true]:bg-success/15',\n pix: 'border-teal-500/30 bg-teal-500/5 hover:bg-teal-500/10 data-[active=true]:border-teal-500 data-[active=true]:bg-teal-500/15',\n credit_card: 'border-info/30 bg-info/5 hover:bg-info/10 data-[active=true]:border-info data-[active=true]:bg-info/15',\n debit_card: 'border-magic/30 bg-magic/5 hover:bg-magic/10 data-[active=true]:border-magic data-[active=true]:bg-magic/15',\n bank_transfer: 'border-warning/30 bg-warning/5 hover:bg-warning/10 data-[active=true]:border-warning data-[active=true]:bg-warning/15',\n check: 'border-input/30 bg-muted/5 hover:bg-muted/10 data-[active=true]:border-input data-[active=true]:bg-muted/15',\n}\n\nconst ICON_COLORS: Record<string, string> = {\n cash: 'text-success', pix: 'text-teal-500', credit_card: 'text-info',\n debit_card: 'text-magic', bank_transfer: 'text-warning', check: 'text-muted-foreground',\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\ninterface Props {\n orderId: string\n orderTotal: number\n services?: Array<{ name: string; price: number; durationMinutes: number }>\n onClose: () => void\n onPaymentChange?: () => void\n formatCurrency: (amount: number) => string\n /** Render inline (no portal overlay) — for embedding in tabs */\n inline?: boolean\n}\n\nexport function BookingPaymentPanel({ orderId, orderTotal, services, onClose, onPaymentChange, formatCurrency, inline }: Props) {\n const t = useTranslation()\n const config = useAgendaConfig()\n const bridge = config.financialBridge!\n\n const [visible, setVisible] = useState(false)\n const [loading, setLoading] = useState(true)\n const [detail, setDetail] = useState<BookingPaymentDetail | null>(null)\n\n // Payment form\n const [selectedTypeId, setSelectedTypeId] = useState('')\n const [paymentTypes, setPaymentTypes] = useState<Array<{ id: string; name: string; transactionType?: string }>>([])\n const [bankAccounts, setBankAccounts] = useState<Array<{ id: string; name: string; accountType: string }>>([])\n const [filteredMethods, setFilteredMethods] = useState<Array<{ id: string; name: string }>>([])\n const [selectedBankId, setSelectedBankId] = useState('')\n const [paymentMethodId, setPaymentMethodId] = useState('')\n const [cardBrand, setCardBrand] = useState('')\n const [cardInstallments, setCardInstallments] = useState(1)\n const [processing, setProcessing] = useState(false)\n const [justPaid, setJustPaid] = useState(false)\n\n useEffect(() => { requestAnimationFrame(() => setVisible(true)) }, [])\n\n // Single combined fetch for all initial data\n useEffect(() => {\n let cancelled = false\n setLoading(true)\n Promise.all([\n bridge.getPaymentDetail(orderId).catch(() => null),\n bridge.getPaymentMethodTypes().catch(() => [] as typeof paymentTypes),\n bridge.getBankAccounts().catch(() => [] as typeof bankAccounts),\n ]).then(([d, types, accounts]) => {\n if (cancelled) return\n setDetail(d)\n setPaymentTypes(types)\n setBankAccounts(accounts)\n setLoading(false)\n })\n return () => { cancelled = true }\n }, [orderId])\n\n function handleClose() {\n setVisible(false)\n setTimeout(onClose, 200)\n }\n\n const selectedType = paymentTypes.find((t) => t.id === selectedTypeId)\n const txType = selectedType?.transactionType ?? ''\n const needsBank = ['bank_transfer', 'pix', 'check'].includes(txType)\n const needsCard = txType === 'credit_card' || txType === 'debit_card'\n const needsCardInstallments = txType === 'credit_card'\n\n function handleSelectType(typeId: string) {\n setSelectedTypeId(typeId)\n setSelectedBankId('')\n setPaymentMethodId('')\n setCardBrand('')\n setCardInstallments(1)\n // Fetch specific payment methods for this type\n if (bridge.getPaymentMethods) {\n bridge.getPaymentMethods(typeId).then(setFilteredMethods).catch(() => setFilteredMethods([]))\n }\n }\n\n async function handleCheckout() {\n if (!selectedTypeId) return\n setProcessing(true)\n try {\n const result = await bridge.checkout(orderId, {\n paymentMethodTypeId: selectedTypeId,\n paymentMethodId: paymentMethodId || undefined,\n bankAccountId: needsBank ? selectedBankId || undefined : undefined,\n cardBrand: needsCard ? cardBrand || undefined : undefined,\n cardInstallments: needsCardInstallments ? cardInstallments : undefined,\n })\n setDetail(result)\n setJustPaid(true)\n onPaymentChange?.()\n // Show confirmation animation, then transition to summary\n setTimeout(() => setJustPaid(false), 2200)\n } catch { /* toast */ }\n setProcessing(false)\n }\n\n const isPaid = detail?.status === 'paid'\n\n const content = (\n <div className=\"px-5 py-4 space-y-4\">\n\n {/* Loading */}\n {loading && (\n <div className=\"space-y-3 py-2\">\n {[...Array(3)].map((_, i) => (\n <div key={i} className=\"h-8 rounded-lg bg-muted animate-pulse\" />\n ))}\n </div>\n )}\n\n {/* Just paid — confirmation animation */}\n {!loading && isPaid && justPaid && (\n <div className=\"text-center py-8 space-y-2 animate-in fade-in zoom-in-95 duration-300\">\n <div className=\"flex h-14 w-14 mx-auto items-center justify-center rounded-full bg-success/10 animate-bounce\" style={{ animationDuration: '600ms', animationIterationCount: '2' }}>\n <Check className=\"h-7 w-7 text-success\" />\n </div>\n <p className=\"text-sm font-semibold text-success\">{t('agenda.payment.checkoutComplete')}</p>\n <p className=\"text-xs text-muted-foreground\">{formatCurrency(detail!.totalAmount)}</p>\n </div>\n )}\n\n {/* Invoice summary — shown after animation or when returning to an already-paid/pending booking */}\n {!loading && detail && detail.status !== 'none' && !justPaid && (\n <div className=\"space-y-3 animate-in fade-in duration-300\">\n {/* Movement rows with inline status badge */}\n {detail.movements.length > 0 ? (\n <div className=\"space-y-1.5\">\n {detail.movements.map((mov) => {\n const methodName = mov.paymentMethodTypeName\n const txKey = (methodName ?? '').toLowerCase().replace(/\\s+/g, '_')\n const Icon = TYPE_ICONS[txKey] ?? Banknote\n const iconColor = ICON_COLORS[txKey] ?? 'text-muted-foreground'\n const isMovPaid = mov.status === 'paid'\n const isPartial = mov.status === 'partial'\n const isOverdue = mov.status === 'overdue'\n\n return (\n <div key={mov.id} className=\"flex items-center gap-3 rounded-lg border px-3 py-2.5\">\n <Icon className={`h-4 w-4 shrink-0 ${isMovPaid ? iconColor : 'text-muted-foreground'}`} />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">\n {methodName ?? '—'}\n {mov.cardBrand ? ` · ${mov.cardBrand}` : ''}\n {mov.cardInstallments && mov.cardInstallments > 1 ? ` ${mov.cardInstallments}x` : ''}\n </p>\n <p className=\"text-[10px] text-muted-foreground\">\n {mov.paymentDate ?? mov.dueDate}\n {detail.movements.length > 1 && mov.installmentNumber ? ` · ${t('agenda.payment.installment')} ${mov.installmentNumber}` : ''}\n </p>\n </div>\n <div className=\"flex items-center gap-2 shrink-0\">\n {isMovPaid && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-success/10 px-2 py-0.5 text-[10px] font-medium text-success\">\n <Check className=\"h-2.5 w-2.5\" /> {t('agenda.payment.paid')}\n </span>\n )}\n {isPartial && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-warning/10 px-2 py-0.5 text-[10px] font-medium text-warning\">\n ! {formatCurrency(mov.paidAmount)}/{formatCurrency(mov.amount)}\n </span>\n )}\n {isOverdue && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-destructive/10 px-2 py-0.5 text-[10px] font-medium text-destructive\">\n ! {t('agenda.payment.overdue')}\n </span>\n )}\n {mov.status === 'pending' && (\n <span className=\"inline-flex items-center rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground\">\n {t('agenda.payment.pending')}\n </span>\n )}\n <span className=\"text-sm font-semibold\">{formatCurrency(mov.paidAmount || mov.amount)}</span>\n </div>\n </div>\n )\n })}\n </div>\n ) : (\n <div className=\"flex items-center justify-between text-sm px-1\">\n <span className=\"text-muted-foreground\">{t('agenda.payment.total')}</span>\n <span className=\"font-semibold\">{formatCurrency(detail.totalAmount)}</span>\n </div>\n )}\n\n {/* Invoice ref + link */}\n <div className=\"flex items-center justify-between\">\n {detail.referenceNumber && (\n <span className=\"text-[10px] font-mono text-muted-foreground\">#{detail.referenceNumber}</span>\n )}\n <a\n href={`#/financial/receivables/detail/${detail.invoiceId}`}\n className=\"inline-flex items-center gap-1.5 text-xs font-medium text-primary hover:underline ml-auto\"\n >\n {t('agenda.payment.viewInvoice')}\n <ExternalLink className=\"h-3 w-3\" />\n </a>\n </div>\n </div>\n )}\n\n {/* Checkout view — only when no invoice exists yet */}\n {!loading && (!detail || detail.movements.length === 0) && (\n <>\n {/* Service summary */}\n {services && services.length > 0 && (\n <div>\n <p className=\"text-[11px] font-medium text-muted-foreground mb-2\">{t('agenda.payment.serviceSummary')}</p>\n <div className=\"space-y-0.5\">\n {services.map((svc, i) => (\n <div key={i} className=\"flex items-center justify-between text-sm py-1\">\n <span className=\"truncate\">{svc.name}</span>\n <span className=\"shrink-0 text-muted-foreground\">{formatCurrency(svc.price)}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Total */}\n <div className=\"flex items-center justify-between text-sm font-semibold pt-2 border-t\">\n <span>{t('agenda.payment.total')}</span>\n <span>{formatCurrency(orderTotal)}</span>\n </div>\n\n {/* Payment method grid */}\n <div>\n <p className=\"text-[11px] font-medium text-muted-foreground mb-2\">{t('agenda.payment.paymentMethod')}</p>\n {paymentTypes.length === 0 ? (\n <div className=\"rounded-lg border border-dashed border-input bg-muted/30 px-3 py-3 text-center\">\n <p className=\"text-xs text-muted-foreground\">{t('agenda.payment.noMethods')}</p>\n <a href=\"#/financial/settings\" className=\"mt-1.5 inline-block text-xs font-medium text-primary hover:underline\">\n {t('agenda.payment.configureMethods')} →\n </a>\n </div>\n ) : (\n <div className=\"grid grid-cols-3 gap-1.5\">\n {paymentTypes.map((pt) => {\n const ptTx = pt.transactionType ?? pt.name.toLowerCase().replace(/\\s+/g, '_')\n const Icon = TYPE_ICONS[ptTx] ?? Banknote\n const colorClass = TYPE_COLORS[ptTx] ?? TYPE_COLORS.cash\n const iconColor = ICON_COLORS[ptTx] ?? ICON_COLORS.cash\n const isActive = selectedTypeId === pt.id\n return (\n <button\n key={pt.id}\n type=\"button\"\n data-active={isActive}\n onClick={() => handleSelectType(pt.id)}\n className={`flex flex-col items-center gap-1 rounded-lg border p-2.5 text-[10px] font-medium transition-all ${colorClass}`}\n >\n <Icon className={`h-4 w-4 ${iconColor}`} />\n <span className=\"truncate w-full text-center\">{pt.name}</span>\n </button>\n )\n })}\n </div>\n )}\n </div>\n\n {/* Extra fields based on payment type */}\n {selectedTypeId && (\n <div className=\"space-y-3\">\n {/* Specific payment method (filtered by type) */}\n {filteredMethods.length > 0 && (\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">\n {needsCard ? t('agenda.payment.card') : t('agenda.payment.method')}\n </label>\n <select value={paymentMethodId} onChange={(e) => setPaymentMethodId(e.target.value)}\n className=\"w-full mt-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring\">\n <option value=\"\">{t('agenda.payment.select')}</option>\n {filteredMethods.map((m) => <option key={m.id} value={m.id}>{m.name}</option>)}\n </select>\n </div>\n )}\n\n {/* Card brand + installments */}\n {needsCard && (\n <div className={`grid gap-2.5 ${needsCardInstallments ? 'grid-cols-2' : 'grid-cols-1'}`}>\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('agenda.payment.cardBrand')}</label>\n <select value={cardBrand} onChange={(e) => setCardBrand(e.target.value)}\n className=\"w-full mt-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring\">\n <option value=\"\">{t('agenda.payment.selectBrand')}</option>\n {['Visa', 'Mastercard', 'American Express', 'Elo', 'Hipercard', 'Diners Club'].map((b) => (\n <option key={b} value={b}>{b}</option>\n ))}\n </select>\n </div>\n {needsCardInstallments && (\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('agenda.payment.cardInstallments')}</label>\n <select value={cardInstallments} onChange={(e) => setCardInstallments(Number(e.target.value))}\n className=\"w-full mt-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring\">\n {Array.from({ length: 12 }, (_, i) => i + 1).map((n) => (\n <option key={n} value={n}>{n}x {n > 1 ? formatCurrency(orderTotal / n) : ''}</option>\n ))}\n </select>\n </div>\n )}\n </div>\n )}\n\n {/* Bank account */}\n {needsBank && bankAccounts.length > 0 && (\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('agenda.payment.bankAccount')}</label>\n <select value={selectedBankId} onChange={(e) => setSelectedBankId(e.target.value)}\n className=\"w-full mt-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring\">\n <option value=\"\">{t('agenda.payment.selectAccount')}</option>\n {bankAccounts.map((a) => (\n <option key={a.id} value={a.id}>{a.name}</option>\n ))}\n </select>\n </div>\n )}\n </div>\n )}\n\n {/* Confirm button */}\n <button\n type=\"button\"\n onClick={handleCheckout}\n disabled={processing || !selectedTypeId}\n className=\"w-full rounded-lg bg-primary border border-primary py-2.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 shadow-button-primary active:shadow-button-inset disabled:opacity-40 transition-colors\"\n >\n {processing\n ? t('agenda.payment.checkingOut')\n : `${t('agenda.payment.checkout')} ${formatCurrency(orderTotal)}`\n }\n </button>\n </>\n )}\n </div>\n )\n\n if (inline) return content\n\n return createPortal(\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center transition-colors duration-200\"\n style={{ backgroundColor: visible ? 'rgba(0,0,0,0.5)' : 'rgba(0,0,0,0)' }}\n onClick={handleClose}\n >\n <div\n className=\"w-full max-w-md rounded-xl border bg-card shadow-2xl mx-4 transition-all duration-200 max-h-[90vh] overflow-y-auto\"\n style={{ opacity: visible ? 1 : 0, transform: visible ? 'scale(1) translateY(0)' : 'scale(0.95) translateY(8px)' }}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between px-5 py-4 border-b sticky top-0 bg-card z-10\">\n <h3 className=\"text-base font-semibold\">{t('agenda.payment.title')}</h3>\n <button onClick={handleClose} className=\"p-1 text-muted-foreground hover:text-foreground transition-colors\">\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n {content}\n </div>\n </div>,\n document.body,\n )\n}\n","// ---------------------------------------------------------------------------\n// Agenda Plugin — Pure TypeScript types\n// Zero dependencies. Maps to public archetype tables.\n// ---------------------------------------------------------------------------\n\n// ============================================================\n// ENUMS / LITERALS\n// ============================================================\n\n/** Booking status lifecycle */\nexport type BookingStatus =\n | 'scheduled'\n | 'confirmed'\n | 'in_progress'\n | 'completed'\n | 'cancelled'\n | 'no_show'\n\n/** Confirmation outreach status */\nexport type ConfirmationStatus = 'pending' | 'sent' | 'confirmed' | 'declined'\n\n/** Booking type identifier — extensible via string literal union */\nexport type BookingTypeId = 'appointment' | 'task' | 'out_of_office' | 'block' | (string & {})\n\n/** Configuration for a booking type (event type) */\nexport interface BookingTypeConfig {\n id: BookingTypeId\n label: string\n icon: string\n color: string\n fields: {\n /** Free-text event title (maps to the booking's display name). Used by\n * simple / Google-Calendar-style events that have no client party. */\n title?: boolean\n client: boolean\n professional: boolean\n services: boolean\n location: boolean\n status: boolean\n }\n requiresServices: boolean\n requiresClient: boolean\n}\n\n// ============================================================\n// CORE ENTITIES\n// ============================================================\n\n/** A booking service line item (from public.appointment_items) */\nexport interface BookingService {\n id: string\n serviceId: string | null\n name: string\n durationMinutes: number\n price: number\n assigneeId: string | null\n}\n\n/** Calendar booking — the main entity rendered on the calendar (from v_appointments view on orders) */\nexport interface CalendarBooking {\n id: string\n tenantId: string\n kind: string\n /** Lifecycle stage: booked, invoiced, paid, etc. */\n stage?: string\n /** Financial direction: credit, debit, null */\n direction?: string | null\n startsAt: string\n endsAt: string | null\n status: BookingStatus\n notes: string | null\n /** In unified model, orderId === id (the booking IS the order) */\n orderId: string | null\n locationId: string | null\n metadata: Record<string, unknown>\n\n // Client (party)\n clientId: string | null\n clientName: string | null\n clientPhone: string | null\n clientEmail: string | null\n clientAvatarUrl: string | null\n\n // Professional (assignee)\n professionalId: string | null\n professionalName: string | null\n professionalAvatarUrl: string | null\n\n // Location\n locationName: string | null\n\n // Order totals\n orderTotal: number | null\n orderStatus: string | null\n /** Payment status from financial bridge (enriched at runtime) */\n paymentStatus?: import('./bridges/financial-bridge').BookingPaymentStatus\n\n // Aggregated services\n services: BookingService[] | null\n totalDurationMinutes: number | null\n\n createdAt: string\n updatedAt: string\n}\n\n/** Professional / staff resource for the calendar */\nexport interface Professional {\n id: string\n name: string\n avatarUrl: string | null\n locationId: string | null\n locationName: string | null\n isActive: boolean\n}\n\n/** Working hours schedule (from public.schedules) */\nexport interface Schedule {\n id: string\n tenantId: string\n kind: string\n assigneeId: string | null\n locationId: string | null\n dayOfWeek: number | null\n specificDate: string | null\n startsAt: string\n endsAt: string\n isActive: boolean\n metadata: Record<string, unknown>\n}\n\n/** Available time slot */\nexport interface TimeSlot {\n start: string\n end: string\n}\n\n/** Confirmation record stored in booking metadata */\nexport interface ConfirmationRecord {\n channel: string\n sentAt: string\n status: ConfirmationStatus\n confirmedAt?: string\n}\n\n// ============================================================\n// STATUS CONFIGURATION\n// ============================================================\n\n/**\n * When a status is available for selection relative to the booking date.\n * - 'always' — any date (e.g. scheduled, confirmed, cancelled)\n * - 'today_or_past' — booking is today or earlier (e.g. completed, no_show)\n * - 'today_only' — booking is today (e.g. in_progress)\n */\nexport type StatusAvailability = 'always' | 'today_or_past' | 'today_only'\n\nexport interface StatusConfig {\n value: string\n label: string\n color: string\n /** When this status can be selected (default: 'always') */\n availableWhen?: StatusAvailability\n}\n\n/** Check if a status is available for a given booking date */\nexport function isStatusAvailable(status: StatusConfig, bookingStartsAt: string): boolean {\n const when = status.availableWhen ?? 'always'\n if (when === 'always') return true\n const bookingDate = bookingStartsAt.slice(0, 10)\n const today = new Date().toISOString().slice(0, 10)\n if (when === 'today_or_past') return bookingDate <= today\n if (when === 'today_only') return bookingDate === today\n return true\n}\n\n// ============================================================\n// MODAL TAB EXTENSION\n// ============================================================\n\n/** Props passed to every booking modal tab component */\nexport interface BookingModalTabProps {\n bookingId?: string\n clientId: string\n orderId: string | null\n services: Array<{ name: string; price: number; durationMinutes: number }>\n formatCurrency: (amount: number) => string\n onDataChange?: () => void\n}\n\n/** A tab registered in the booking edit modal */\nexport interface BookingModalTab {\n id: string\n label: string\n icon: string\n order: number\n component: React.ComponentType<BookingModalTabProps>\n visible?: (ctx: { mode: 'create' | 'edit'; clientId?: string; orderId?: string }) => boolean\n}\n\n// ============================================================\n// INPUT TYPES (create / mutate)\n// ============================================================\n\nexport interface CreateBookingInput {\n kind?: BookingTypeId\n clientId: string\n professionalId: string\n locationId?: string\n startsAt: string\n notes?: string\n /** Free-text event title for simple events (no client party). Maps to the\n * booking's display name (clientName in the read model). */\n title?: string\n services: CreateBookingServiceInput[]\n}\n\nexport interface CreateBookingServiceInput {\n serviceId: string\n name: string\n durationMinutes: number\n price: number\n assigneeId?: string\n}\n\nexport interface UpdateBookingInput {\n clientId?: string\n professionalId?: string\n locationId?: string\n startsAt?: string\n endsAt?: string\n status?: BookingStatus\n notes?: string\n /** Free-text event title for simple events (no client party). */\n title?: string\n services?: CreateBookingServiceInput[]\n}\n\nexport interface SaveScheduleInput {\n assigneeId: string\n locationId?: string\n dayOfWeek?: number\n specificDate?: string\n startsAt: string\n endsAt: string\n isActive?: boolean\n metadata?: Record<string, unknown>\n}\n\n// ============================================================\n// QUERY / FILTER TYPES\n// ============================================================\n\nexport interface BookingQuery {\n dateRange: { start: string; end: string }\n professionalIds?: string[]\n locationId?: string\n statuses?: string[]\n kind?: string\n}\n\nexport interface ConflictCheckParams {\n assigneeId: string\n startsAt: string\n endsAt: string\n excludeBookingId?: string\n}\n\nexport interface AvailableSlotsParams {\n assigneeId: string\n date: string\n durationMinutes: number\n slotInterval?: number\n}\n","import React, { useState, useEffect, useMemo, useRef } from 'react'\nimport { createPortal } from 'react-dom'\nimport { Clock, AlertTriangle, X, User, Briefcase, FileText, CircleDot, Plus, MapPin, Calendar, DollarSign, CheckSquare, Ban, Check, HandCoins } from 'lucide-react'\n\nconst BOOKING_TYPE_ICONS: Record<string, React.ElementType> = {\n Calendar, CheckSquare, Ban,\n}\nimport {\n Modal, ModalContent, ModalTitle,\n} from '@fayz-ai/ui'\nimport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@fayz-ai/ui'\nimport { cn } from '@fayz-ai/ui'\nimport { SearchCombobox, type ComboboxOption } from '@fayz-ai/ui'\nimport { ContactPicker, type ContactPickerValue } from '@fayz-ai/admin'\nimport { BookingPaymentPanel } from './BookingPaymentPanel'\nimport { CrudDetailPage } from '@fayz-ai/admin'\nimport { CrudFormPage } from '@fayz-ai/admin'\nimport { useLimitGuard, invalidateLimit } from '@fayz-ai/admin'\nimport { Button } from '@fayz-ai/ui'\nimport { useAgendaConfig, useAgendaProvider, useAgendaStore } from '../context'\nimport { useTranslation } from '@fayz-ai/core'\nimport { getCurrentLocale } from '@fayz-ai/core'\nimport { isStatusAvailable } from '../types'\nimport type { CreateBookingInput, BookingTypeId } from '../types'\nimport type { ExternalBookingSource } from '../config'\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction fmtCurrency(amount: number, locale: string, code: string): string {\n return new Intl.NumberFormat(locale, { style: 'currency', currency: code }).format(amount)\n}\n\nfunction formatCompactDate(dateStr: string, locale: string): string {\n const d = new Date(dateStr + 'T00:00:00')\n return d.toLocaleDateString(locale === 'pt-BR' ? 'pt-BR' : 'en-US', {\n weekday: 'short', month: 'short', day: 'numeric',\n })\n}\n\ninterface ServiceItem { serviceId: string; name: string; durationMinutes: number; price: number }\ninterface CancellationReasonItem { id: string; label: string; requiresNotes?: boolean }\n\n// ---------------------------------------------------------------------------\n// Inline editable number — allows clearing, commits on blur/enter\n// ---------------------------------------------------------------------------\n\nfunction InlineNumber({ value, onChange, min = 0, step = 1, className, disabled, tooltip }: {\n value: number; onChange: (v: number) => void; min?: number; step?: number\n className?: string; disabled?: boolean; tooltip?: string\n}) {\n const [draft, setDraft] = useState(String(value))\n const [focused, setFocused] = useState(false)\n\n useEffect(() => { if (!focused) setDraft(String(value)) }, [value, focused])\n\n function commit() {\n setFocused(false)\n const v = parseFloat(draft)\n if (!isNaN(v) && v >= min) {\n onChange(v)\n } else {\n setDraft(String(value))\n }\n }\n\n const input = (\n <input\n type=\"text\"\n inputMode=\"decimal\"\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onFocus={(e) => { setFocused(true); e.target.select() }}\n onBlur={commit}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); commit() } }}\n disabled={disabled}\n className={cn(\n 'text-right text-[11px] text-muted-foreground bg-transparent border-b border-transparent hover:border-muted-foreground/40 focus:border-foreground focus:outline-none tabular-nums',\n className,\n )}\n />\n )\n\n if (!tooltip) return input\n\n return (\n <TooltipProvider delayDuration={400}>\n <Tooltip>\n <TooltipTrigger asChild>{input}</TooltipTrigger>\n <TooltipContent side=\"top\" className=\"text-xs\">{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Custom Status Select\n// ---------------------------------------------------------------------------\n\nfunction StatusSelect({ value, onChange, statuses, bookingDate }: {\n value: string; onChange: (v: string) => void\n statuses: Array<{ value: string; label: string; color: string; availableWhen?: string }>\n bookingDate?: string\n}) {\n const [open, setOpen] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\n const dropdownRef = useRef<HTMLDivElement>(null)\n const current = statuses.find((s) => s.value === value)\n\n useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => {\n const target = e.target as Node\n if (ref.current?.contains(target)) return\n if (dropdownRef.current?.contains(target)) return\n setOpen(false)\n }\n document.addEventListener('mousedown', handler)\n return () => document.removeEventListener('mousedown', handler)\n }, [open])\n\n const btnRef = useRef<HTMLButtonElement>(null)\n const [dropRect, setDropRect] = useState<DOMRect | null>(null)\n\n function handleOpen() {\n if (btnRef.current) setDropRect(btnRef.current.getBoundingClientRect())\n setOpen((p) => !p)\n }\n\n return (\n <div ref={ref} className=\"relative flex-1\">\n <button ref={btnRef} type=\"button\" onClick={handleOpen}\n className=\"flex items-center gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-muted/30 transition-colors text-left w-full\">\n {current && <>\n <span className=\"h-2 w-2 rounded-full shrink-0\" style={{ backgroundColor: current.color }} />\n <span>{current.label}</span>\n </>}\n <svg className=\"ml-auto h-3 w-3 text-muted-foreground shrink-0\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n </svg>\n </button>\n {open && dropRect && createPortal(\n <div ref={dropdownRef} data-modal-passthrough style={{ position: 'fixed', left: dropRect.left, top: dropRect.bottom + 4, width: dropRect.width, zIndex: 9999, pointerEvents: 'auto' }}\n className=\"fayz-glass-surface rounded-lg border bg-popover shadow-lg py-1 animate-in fade-in zoom-in-95 duration-100\">\n {statuses.map((s: any) => {\n const available = !bookingDate || isStatusAvailable(s as any, bookingDate)\n return (\n <button key={s.value} type=\"button\" disabled={!available}\n onClick={() => { if (available) { onChange(s.value); setOpen(false) } }}\n className={`flex w-full items-center gap-2.5 px-3 py-1.5 text-sm transition-colors ${\n !available ? 'opacity-30 cursor-not-allowed' : s.value === value ? 'bg-muted/30' : 'hover:bg-muted/50'\n }`}>\n <span className=\"h-2 w-2 rounded-full shrink-0\" style={{ backgroundColor: s.color }} />\n <span>{s.label}</span>\n </button>\n )\n })}\n </div>,\n document.body,\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Professional Select — compact inline dropdown with initials\n// ---------------------------------------------------------------------------\n\nfunction ProfessionalSelect({ value, onChange, professionals }: {\n value: string; onChange: (v: string) => void\n professionals: Array<{ id: string; name: string }>\n}) {\n const t = useTranslation()\n const [open, setOpen] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\n const current = professionals.find((p) => p.id === value)\n\n useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false) }\n document.addEventListener('mousedown', handler)\n return () => document.removeEventListener('mousedown', handler)\n }, [open])\n\n return (\n <div ref={ref} className=\"relative flex-1\">\n <button type=\"button\" onClick={() => setOpen((p) => !p)}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-muted/30 transition-colors text-left\">\n {current ? (\n <span>{current.name}</span>\n ) : (\n <span className=\"text-muted-foreground\">{t('agenda.appointment.selectProfessional')}</span>\n )}\n <svg className=\"ml-auto h-3 w-3 text-muted-foreground shrink-0\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n </svg>\n </button>\n {open && (\n <div className=\"fayz-glass-surface absolute top-full left-0 right-0 z-50 mt-1 rounded-lg border bg-popover shadow-lg py-1 animate-in fade-in zoom-in-95 duration-100\">\n {professionals.map((p: any) => (\n <button key={p.id} type=\"button\"\n onClick={() => { onChange(p.id); setOpen(false) }}\n className={`flex w-full items-center gap-2 px-3 py-1.5 text-sm hover:bg-muted/50 transition-colors ${p.id === value ? 'bg-muted/30' : ''}`}>\n <span>{p.name}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Location Select — compact inline dropdown\n// ---------------------------------------------------------------------------\n\nfunction LocationSelect({ value, onChange, locations }: {\n value: string; onChange: (v: string) => void\n locations: Array<{ id: string; name: string }>\n}) {\n const t = useTranslation()\n const [open, setOpen] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\n const current = locations.find((l) => l.id === value)\n\n useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false) }\n document.addEventListener('mousedown', handler)\n return () => document.removeEventListener('mousedown', handler)\n }, [open])\n\n return (\n <div ref={ref} className=\"relative flex-1\">\n <button type=\"button\" onClick={() => setOpen((p) => !p)}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-muted/30 transition-colors text-left\">\n {current ? (\n <span>{current.name}</span>\n ) : (\n <span className=\"text-muted-foreground\">{t('agenda.appointment.selectLocation')}</span>\n )}\n <svg className=\"ml-auto h-3 w-3 text-muted-foreground shrink-0\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n </svg>\n </button>\n {open && (\n <div className=\"fayz-glass-surface absolute top-full left-0 right-0 z-50 mt-1 rounded-lg border bg-popover shadow-lg py-1 animate-in fade-in zoom-in-95 duration-100 max-h-48 overflow-y-auto\">\n {locations.map((l: any) => (\n <button key={l.id} type=\"button\"\n onClick={() => { onChange(l.id); setOpen(false) }}\n className={`flex w-full items-center gap-2 px-3 py-1.5 text-sm hover:bg-muted/50 transition-colors ${l.id === value ? 'bg-muted/30' : ''}`}>\n <span>{l.name}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Appointment Modal — Google Calendar-inspired compact layout\n// ---------------------------------------------------------------------------\n\ninterface Props {\n open: boolean\n mode: 'create' | 'edit'\n bookingId?: string\n prefill?: Partial<CreateBookingInput> & { endsAt?: string }\n initialTab?: string\n externalSource?: ExternalBookingSource\n onClose: () => void\n onCreated?: (bookingId: string, source?: ExternalBookingSource) => void\n}\n\nexport function AppointmentModal({ open, mode, bookingId, prefill, initialTab, externalSource, onClose, onCreated }: Props) {\n const t = useTranslation()\n const locale = getCurrentLocale()\n const config = useAgendaConfig()\n const provider = useAgendaProvider()\n const initialSnapshot = useRef<string>('')\n const createBooking = useAgendaStore((s) => s.createBooking)\n const guardBookings = useLimitGuard('bookings_month')\n const updateBooking = useAgendaStore((s) => s.updateBooking)\n const deleteBooking = useAgendaStore((s) => s.deleteBooking)\n const fetchBookings = useAgendaStore((s) => s.fetchBookings)\n const agendaDateRange = useAgendaStore((s) => s.dateRange)\n const professionals = useAgendaStore((s) => s.professionals)\n const storeLocations = useAgendaStore((s) => s.locations)\n\n // --- State ---\n // Default to the first configured booking type (e.g. 'event' in simple mode,\n // 'appointment' otherwise) so single-type agendas resolve their type cleanly.\n const defaultBookingType = (config.bookingTypes[0]?.id ?? 'appointment') as BookingTypeId\n const [loading, setLoading] = useState(mode === 'edit')\n const [bookingType, setBookingType] = useState<BookingTypeId>(prefill?.kind ?? defaultBookingType)\n const [title, setTitle] = useState('')\n const [clientId, setClientId] = useState(prefill?.clientId ?? '')\n const [clientSearch, setClientSearch] = useState('')\n const [clientPhone, setClientPhone] = useState('')\n const [professionalId, setProfessionalId] = useState(prefill?.professionalId ?? '')\n const [locationId, setLocationId] = useState(prefill?.locationId ?? '')\n const [services, setServices] = useState<ServiceItem[]>([])\n const [serviceSearch, setServiceSearch] = useState('')\n const [date, setDate] = useState(() => {\n if (prefill?.startsAt) return prefill.startsAt.slice(0, 10)\n return new Date().toISOString().slice(0, 10)\n })\n const [startTime, setStartTime] = useState(() => {\n if (prefill?.startsAt) {\n const d = new Date(prefill.startsAt)\n return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`\n }\n return '09:00'\n })\n const [status, setStatus] = useState('scheduled')\n const [notes, setNotes] = useState('')\n const [showNotes, setShowNotes] = useState(false)\n const [saving, setSaving] = useState(false)\n const [conflict, setConflict] = useState(false)\n // Client search/quick-create state now lives inside <ContactPicker>.\n const [serviceOptions, setServiceOptions] = useState<ComboboxOption[]>([])\n const [initialServiceOptions, setInitialServiceOptions] = useState<ComboboxOption[]>([])\n const [editingDate, setEditingDate] = useState(false)\n const [editingTime, setEditingTime] = useState(false)\n const [confirmingDelete, setConfirmingDelete] = useState(false)\n const [deleting, setDeleting] = useState(false)\n const [editOrderId, setEditOrderId] = useState<string | null>(null)\n const [editOrderTotal, setEditOrderTotal] = useState(0)\n const [editPaymentStatus, setEditPaymentStatus] = useState<import('../bridges/financial-bridge').BookingPaymentStatus>('none')\n const [paymentStatusLoading, setPaymentStatusLoading] = useState(false)\n const [modalTab, setModalTab] = useState<'appointment' | 'client' | 'financial'>('appointment')\n const [clientData, setClientData] = useState<Record<string, any> | null>(null)\n const [clientDataLoading, setClientDataLoading] = useState(false)\n const [clientEditing, setClientEditing] = useState(false)\n const [cancellationReasons, setCancellationReasons] = useState<CancellationReasonItem[]>([])\n const [cancellationReasonId, setCancellationReasonId] = useState('')\n const [cancellationNotes, setCancellationNotes] = useState('')\n const [cancellationReasonsLoading, setCancellationReasonsLoading] = useState(false)\n\n // Active booking type config\n const activeType = config.bookingTypes.find((bt) => bt.id === bookingType) ?? config.bookingTypes[0]\n\n // Reset form when modal opens\n useEffect(() => {\n if (!open) return\n setClientId(prefill?.clientId ?? ''); setClientSearch(''); setClientPhone('')\n setProfessionalId(prefill?.professionalId ?? ''); setLocationId(prefill?.locationId ?? ''); setServices([])\n setServiceSearch(''); setNotes(''); setStatus('scheduled'); setShowNotes(false)\n setConflict(false); setLoading(mode === 'edit')\n setBookingType(prefill?.kind ?? defaultBookingType); setTitle('')\n setEditingDate(false); setEditingTime(false); setConfirmingDelete(false); setDeleting(false)\n setEditOrderId(null); setEditOrderTotal(0); setEditPaymentStatus('none'); setPaymentStatusLoading(false)\n setClientData(null); setClientDataLoading(false); setClientEditing(false)\n setCancellationReasonId(''); setCancellationNotes(''); setCancellationReasonsLoading(false)\n setModalTab((initialTab as 'appointment' | 'client' | 'financial') || 'appointment')\n if (!prefill?.professionalId && professionals.length === 1) setProfessionalId(professionals[0].id)\n setDate(() => {\n if (prefill?.startsAt) return prefill.startsAt.slice(0, 10)\n return new Date().toISOString().slice(0, 10)\n })\n setStartTime(() => {\n if (prefill?.startsAt) {\n const d = new Date(prefill.startsAt)\n return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`\n }\n return '09:00'\n })\n }, [open])\n\n // Edit: load existing\n useEffect(() => {\n if (!open || mode !== 'edit' || !bookingId) return\n setLoading(true)\n provider.getBookingById(bookingId).then((b) => {\n if (!b) { setLoading(false); return }\n setBookingType((b.kind as BookingTypeId) ?? defaultBookingType)\n setTitle(b.clientName ?? '')\n setClientId(b.clientId ?? ''); setClientSearch(b.clientName ?? '')\n setProfessionalId(b.professionalId ?? ''); setLocationId(b.locationId ?? '')\n setDate(b.startsAt.slice(0, 10))\n const d = new Date(b.startsAt)\n setStartTime(`${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`)\n setStatus(b.status); setNotes(b.notes ?? '')\n if (b.notes) setShowNotes(true)\n if (b.services) setServices(b.services.map((s: any) => ({\n serviceId: s.serviceId ?? '', name: s.name, durationMinutes: s.durationMinutes, price: s.price,\n })))\n setEditOrderId(b.orderId ?? null)\n setEditOrderTotal(b.orderTotal ?? 0)\n setEditPaymentStatus(b.paymentStatus ?? 'none')\n // Save initial snapshot for dirty check\n const svcSnap = b.services ? b.services.map((s: any) => ({ id: s.serviceId ?? '', dur: s.durationMinutes, price: s.price })) : []\n initialSnapshot.current = JSON.stringify({\n title: b.clientName ?? '',\n clientId: b.clientId ?? '', professionalId: b.professionalId ?? '', locationId: b.locationId ?? '',\n date: b.startsAt.slice(0, 10),\n startTime: `${String(new Date(b.startsAt).getHours()).padStart(2, '0')}:${String(new Date(b.startsAt).getMinutes()).padStart(2, '0')}`,\n status: b.status, notes: b.notes ?? '', cancellationReasonId: '', cancellationNotes: '', services: svcSnap,\n })\n setLoading(false)\n // Resolve payment status from bridge if available\n if (b.orderId && config.financialBridge) {\n setPaymentStatusLoading(true)\n config.financialBridge.resolvePaymentStatuses([b.orderId]).then((map) => {\n const summary = map.get(b.orderId!)\n if (summary) {\n setEditPaymentStatus(summary.status)\n setEditOrderTotal(summary.totalAmount)\n }\n }).catch(() => {}).finally(() => setPaymentStatusLoading(false))\n }\n }).catch(() => setLoading(false))\n }, [open, mode, bookingId])\n\n // Fetch client data when client tab is opened\n useEffect(() => {\n if (modalTab !== 'client' || !clientId || !config.contactLookup || clientData) return\n setClientDataLoading(true)\n config.contactLookup.getById(clientId).then((result) => {\n setClientData(result?.data ?? null)\n setClientDataLoading(false)\n }).catch(() => setClientDataLoading(false))\n }, [modalTab, clientId])\n\n useEffect(() => {\n if (!open || status !== 'cancelled' || !config.cancellationDetails || cancellationReasons.length > 0) return\n setCancellationReasonsLoading(true)\n config.cancellationDetails.listReasons()\n .then((reasons) => setCancellationReasons(reasons))\n .catch(() => setCancellationReasons([]))\n .finally(() => setCancellationReasonsLoading(false))\n }, [open, status, config.cancellationDetails, cancellationReasons.length])\n\n // Fetch initial service list when modal opens\n useEffect(() => {\n if (!open || !config.serviceLookup) return\n const lookup = config.serviceLookup\n const fetch = lookup.list ? () => lookup.list!() : () => lookup.search('')\n fetch().then((results) => {\n const opts = results.map((r: any) => ({ id: r.id, label: r.label, subtitle: r.subtitle, price: r.price, data: r.data }))\n setInitialServiceOptions(opts)\n }).catch(() => setInitialServiceOptions([]))\n }, [open])\n\n // Search effects (client search now lives inside <ContactPicker>)\n useEffect(() => {\n if (!config.serviceLookup || serviceSearch.length < 1) { setServiceOptions([]); return }\n const timer = setTimeout(async () => {\n try {\n const results = await config.serviceLookup!.search(serviceSearch)\n setServiceOptions(results.map((r: any) => ({ id: r.id, label: r.label, subtitle: r.subtitle, price: r.price, data: r.data })))\n } catch { setServiceOptions([]) }\n }, 250)\n return () => clearTimeout(timer)\n }, [serviceSearch])\n\n // Computed\n const serviceDuration = services.reduce((sum, s) => sum + s.durationMinutes, 0)\n const selectionDuration = useMemo(() => {\n if (!prefill?.startsAt || !prefill?.endsAt) return 0\n return Math.round((new Date(prefill.endsAt).getTime() - new Date(prefill.startsAt).getTime()) / 60000)\n }, [prefill?.startsAt, prefill?.endsAt])\n const totalDuration = serviceDuration > 0 ? serviceDuration : selectionDuration\n const totalPrice = services.reduce((sum, s) => sum + s.price, 0)\n const { currency } = config\n\n const endTime = useMemo(() => {\n const [h, m] = startTime.split(':').map(Number)\n const total = h * 60 + m + totalDuration\n return `${String(Math.floor(total / 60) % 24).padStart(2, '0')}:${String(total % 60).padStart(2, '0')}`\n }, [startTime, totalDuration])\n\n // Conflict check\n useEffect(() => {\n if (!professionalId || totalDuration === 0) { setConflict(false); return }\n const timer = setTimeout(() => {\n provider.checkConflict({\n assigneeId: professionalId, startsAt: `${date}T${startTime}:00`, endsAt: `${date}T${endTime}:00`, excludeBookingId: bookingId,\n }).then(setConflict).catch(() => setConflict(false))\n }, 300)\n return () => clearTimeout(timer)\n }, [professionalId, date, startTime, endTime, bookingId])\n\n function addService(opt: ComboboxOption) {\n const duration = (opt.data?.duration_minutes as number) || 60\n setServices((p) => [...p, { serviceId: opt.id, name: opt.label, durationMinutes: duration, price: opt.price ?? 0 }])\n setServiceSearch(''); setServiceOptions([])\n }\n function removeService(idx: number) { setServices((p) => p.filter((_, i) => i !== idx)) }\n\n async function handleSubmit(e: React.FormEvent) {\n e.preventDefault()\n if (!canSubmit) return\n // Plan quantity guard (client-side, before the store call): opens the global\n // UpgradeModal and aborts when the monthly booking cap is reached. CREATE only.\n if (mode === 'create' && (await guardBookings()) === 'blocked') return\n setSaving(true)\n try {\n const startsAt = new Date(`${date}T${startTime}:00`).toISOString()\n if (mode === 'create') {\n const newBooking = await createBooking({ kind: bookingType, clientId, professionalId, locationId: locationId || undefined, startsAt, notes: notes || undefined,\n title: activeType.fields.title ? title.trim() : undefined,\n services: services.map((s: any) => ({ serviceId: s.serviceId, name: s.name, durationMinutes: s.durationMinutes, price: s.price })) })\n invalidateLimit('bookings_month')\n onClose()\n onCreated?.(newBooking.id, externalSource)\n } else if (bookingId) {\n await updateBooking(bookingId, {\n clientId, professionalId, locationId: locationId || undefined, startsAt, notes: notes || undefined, status: status as any,\n title: activeType.fields.title ? title.trim() : undefined,\n services: services.map((s: any) => ({ serviceId: s.serviceId, name: s.name, durationMinutes: s.durationMinutes, price: s.price })),\n })\n if (status === 'cancelled' && config.cancellationDetails && cancellationReasonId) {\n await config.cancellationDetails.saveCancellationDetails({\n bookingId,\n reasonId: cancellationReasonId,\n notes: cancellationNotes.trim() || undefined,\n cancelledAt: new Date().toISOString(),\n })\n }\n onClose()\n }\n } catch { /* toast */ }\n setSaving(false)\n }\n\n async function handleDelete() {\n if (!bookingId) return\n setDeleting(true)\n try {\n await deleteBooking(bookingId)\n onClose()\n } catch {\n // deleteBooking surfaces its own toast. Return the footer to its normal\n // state (out of the confirm step) so a failure is clear feedback rather\n // than a modal that silently stays stuck on \"Confirm delete\".\n setConfirmingDelete(false)\n } finally {\n setDeleting(false)\n }\n }\n\n const isPaidBooking = editPaymentStatus === 'paid'\n const selectedCancellationReason = cancellationReasons.find((reason) => reason.id === cancellationReasonId)\n const needsCancellationReason = mode === 'edit' && status === 'cancelled' && !!config.cancellationDetails\n const needsCancellationNotes = needsCancellationReason && !!selectedCancellationReason?.requiresNotes\n\n // Dirty check — only enable Update when something changed\n const formSnapshot = useMemo(() =>\n JSON.stringify({ title, clientId, professionalId, locationId, date, startTime, status, notes, cancellationReasonId, cancellationNotes, services: services.map((s: any) => ({ id: s.serviceId, dur: s.durationMinutes, price: s.price })) }),\n [title, clientId, professionalId, locationId, date, startTime, status, notes, cancellationReasonId, cancellationNotes, services]\n )\n const isDirty = mode === 'create' || formSnapshot !== initialSnapshot.current\n\n const canSubmit = (\n (!activeType.fields.title || title.trim()) &&\n (!activeType.requiresClient || clientId) &&\n (!activeType.fields.professional || professionalId) &&\n (!activeType.requiresServices || services.length > 0) &&\n (!needsCancellationReason || !!cancellationReasonId) &&\n (!needsCancellationNotes || !!cancellationNotes.trim()) &&\n !conflict && !saving\n )\n\n const showTabs = config.bookingTypes.length > 1\n\n return (\n <Modal open={open} onOpenChange={(v) => { if (!v) onClose() }}>\n <ModalContent size=\"lg\" noPadding>\n\n {/* ═══ TOP — type tabs + date/time ═══ */}\n <div className=\"px-5 pt-4 pb-3 shrink-0 space-y-3\">\n <ModalTitle className=\"sr-only\">\n {mode === 'create' ? t('agenda.appointment.new') : t('agenda.appointment.edit')}\n </ModalTitle>\n\n {/* Booking type tabs (create) or section tabs (edit) */}\n {showTabs && mode === 'create' ? (\n <div className=\"flex gap-1 border-b fayz-glass-divider\">\n {config.bookingTypes.map((bt) => {\n const label = t(`agenda.bookingType.${bt.id}`) || bt.label\n const isActive = bookingType === bt.id\n const BtIcon = BOOKING_TYPE_ICONS[bt.icon] ?? Calendar\n return (\n <button key={bt.id} type=\"button\" onClick={() => setBookingType(bt.id)}\n className={`relative flex items-center gap-1.5 pb-2 px-2 text-xs font-medium transition-colors ${\n isActive ? 'text-foreground' : 'text-muted-foreground hover:text-foreground'\n }`}>\n <BtIcon className=\"h-3.5 w-3.5\" />\n {label}\n {isActive && (\n <span className=\"absolute bottom-0 left-0 right-0 h-0.5 rounded-full bg-foreground\" />\n )}\n </button>\n )\n })}\n </div>\n ) : mode === 'edit' && (\n (config.clientEntityDef && clientId) || (config.modules.financial && editOrderId) ? (\n <div className=\"flex gap-1 border-b fayz-glass-divider\">\n {([\n { id: 'appointment' as const, label: t(`agenda.bookingType.${bookingType}`) || activeType.label, icon: Calendar, show: true },\n { id: 'client' as const, label: t('agenda.appointment.clientTab'), icon: User, show: !!config.clientEntityDef && !!clientId },\n { id: 'financial' as const, label: t('agenda.payment.title'), icon: DollarSign, show: config.modules.financial && !!editOrderId },\n ]).filter((tab) => tab.show).map((tab) => {\n const isActive = modalTab === tab.id\n return (\n <button key={tab.id} type=\"button\" onClick={() => setModalTab(tab.id)}\n className={`relative flex items-center gap-1.5 pb-2 px-2 text-xs font-medium transition-colors ${\n isActive ? 'text-foreground' : 'text-muted-foreground hover:text-foreground'\n }`}>\n <tab.icon className=\"h-3.5 w-3.5\" />\n {tab.label}\n {tab.id === 'financial' && editPaymentStatus === 'paid' && (\n <span className=\"h-1.5 w-1.5 rounded-full bg-success\" />\n )}\n {tab.id === 'financial' && editPaymentStatus !== 'paid' && (\n (editPaymentStatus !== 'none' || (totalPrice > 0 && date <= new Date().toISOString().slice(0, 10)))\n ) && (\n <span className=\"h-1.5 w-1.5 rounded-full bg-warning\" />\n )}\n {isActive && (\n <span className=\"absolute bottom-0 left-0 right-0 h-0.5 rounded-full bg-foreground\" />\n )}\n </button>\n )\n })}\n </div>\n ) : (\n <h2 className=\"text-sm font-semibold\">\n {t(`agenda.bookingType.${bookingType}`) || activeType.label}\n </h2>\n )\n )}\n\n {/* Date/time + professional row — hidden on financial tab */}\n {modalTab === 'appointment' && (\n <>\n <div className=\"flex items-center gap-3\">\n <Clock className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <div className=\"flex items-center gap-1.5 text-sm flex-1 min-w-0\">\n {editingDate ? (\n <input type=\"date\" value={date} autoFocus\n onChange={(e) => { setDate(e.target.value); setEditingDate(false) }}\n onBlur={() => setEditingDate(false)}\n className=\"bg-transparent text-sm font-medium focus:outline-none border-b border-foreground w-auto shrink-0\" />\n ) : (\n <button type=\"button\" onClick={() => setEditingDate(true)}\n className=\"px-0.5 py-0.5 font-medium border-b border-transparent hover:border-foreground transition-colors shrink-0\">\n {formatCompactDate(date, locale)}\n </button>\n )}\n {editingTime ? (\n <input type=\"time\" value={startTime} autoFocus\n onChange={(e) => { if (e.target.value) { setStartTime(e.target.value); setEditingTime(false) } }}\n onBlur={() => setEditingTime(false)}\n className=\"bg-transparent text-xs text-muted-foreground focus:outline-none border-b border-foreground w-auto shrink-0\" />\n ) : (\n <button type=\"button\" onClick={() => setEditingTime(true)}\n className=\"px-0.5 py-0.5 text-xs text-muted-foreground border-b border-transparent hover:border-foreground transition-colors shrink-0\">\n {startTime}\n </button>\n )}\n <span className=\"text-[11px] text-muted-foreground/60\">—</span>\n <span className=\"text-[11px] text-muted-foreground/60\">{endTime}</span>\n\n {/* Professional — right-aligned on the same row */}\n {activeType.fields.professional && (\n <div className=\"ml-auto shrink-0\">\n <ProfessionalSelect value={professionalId} onChange={setProfessionalId} professionals={professionals} />\n </div>\n )}\n </div>\n </div>\n\n {conflict && (\n <div className=\"flex items-center gap-2 rounded-lg bg-destructive/10 px-3 py-1.5 text-xs text-destructive\">\n <AlertTriangle className=\"h-3.5 w-3.5 shrink-0\" />\n {t('agenda.appointment.conflict')}\n </div>\n )}\n </>\n )}\n </div>\n\n {/* ═══ BODY ═══ */}\n <div className=\"flex flex-col flex-1 min-h-0 overflow-hidden\">\n\n {/* Client tab content — reuses the same CrudDetailPage as /clients/:id */}\n {modalTab === 'client' && clientId && config.clientEntityDef && (\n <div className=\"flex-1 overflow-y-auto px-5 py-4\">\n {clientDataLoading ? (\n <div className=\"space-y-3 py-2\">\n {[...Array(4)].map((_, i) => (\n <div key={i} className=\"h-8 rounded-lg bg-muted animate-pulse\" />\n ))}\n </div>\n ) : clientData ? (\n clientEditing ? (\n <CrudFormPage\n embedded\n entityDef={config.clientEntityDef}\n mode=\"edit\"\n initialData={clientData}\n namePlural=\"\"\n onCancel={() => setClientEditing(false)}\n onSubmit={async (data) => {\n try {\n const { getSupabaseClientOptional } = await import('@fayz-ai/core')\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) return\n const dbData: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(data)) {\n dbData[k.replace(/[A-Z]/g, (m) => '_' + m.toLowerCase())] = v\n }\n await supabase.from('people').update(dbData).eq('id', clientId)\n setClientData({ ...clientData, ...data })\n setClientEditing(false)\n } catch { /* toast */ }\n }}\n />\n ) : (\n <CrudDetailPage\n embedded\n entityDef={config.clientEntityDef}\n item={clientData}\n namePlural=\"\"\n basePath=\"\"\n onBack={() => setModalTab('appointment')}\n onEdit={() => setClientEditing(true)}\n />\n )\n ) : (\n <p className=\"text-sm text-muted-foreground py-4 text-center\">{t('agenda.appointment.noClientData')}</p>\n )}\n </div>\n )}\n\n {/* Financial tab content */}\n {modalTab === 'financial' && editOrderId && config.financialBridge && (\n <div className=\"flex-1 overflow-y-auto\">\n <BookingPaymentPanel\n orderId={editOrderId}\n orderTotal={editOrderTotal}\n services={services.map((s: any) => ({ name: s.name, price: s.price, durationMinutes: s.durationMinutes }))}\n formatCurrency={(v) => fmtCurrency(v, currency.locale, currency.code)}\n inline\n onClose={() => setModalTab('appointment')}\n onPaymentChange={() => {\n config.financialBridge!.getPaymentDetail(editOrderId).then((d) => {\n if (d) { setEditPaymentStatus(d.status); setEditOrderTotal(d.totalAmount) }\n }).catch(() => {})\n // Propagate to the calendar card + popover badge (booking.paymentStatus\n // is ledger-derived) so they update without a page refresh.\n if (agendaDateRange.start) fetchBookings(agendaDateRange)\n }}\n />\n </div>\n )}\n\n {/* Appointment tab content */}\n <form onSubmit={handleSubmit} className=\"flex flex-col flex-1 min-h-0 overflow-hidden\" style={{ display: modalTab === 'appointment' ? undefined : 'none' }}>\n <div className=\"border-t fayz-glass-divider px-5 py-3 space-y-1 flex-1 overflow-y-auto\">\n\n {/* Loading skeleton */}\n {loading && (\n <div className=\"space-y-2 py-2\">\n {[...Array(4)].map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 py-1.5\">\n <div className=\"h-4 w-4 rounded bg-muted animate-pulse shrink-0\" />\n <div className=\"h-8 flex-1 rounded-lg bg-muted animate-pulse\" />\n </div>\n ))}\n </div>\n )}\n\n {!loading && <>\n\n {/* Title — free-text event name (simple / Google-Calendar-style events) */}\n {activeType.fields.title && (\n <div className=\"flex items-center gap-3 py-1\">\n <Calendar className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <input type=\"text\" value={title} onChange={(e) => setTitle(e.target.value)}\n placeholder={t('agenda.appointment.addTitle')} autoFocus={mode === 'create'}\n className=\"w-full flex-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-ring\" />\n </div>\n )}\n\n {/* Client */}\n {activeType.fields.client && (\n <div className=\"flex items-center gap-3 py-1\">\n <User className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <div className=\"flex-1\">\n {/* Shared find-or-create contact flow (@fayz-ai/admin). The\n quick-create that used to live inline here now writes the\n SAME people(+clients) rows for every plugin — see\n `createPerson`. `clientKind`/`clientExtensionTable` keep the\n vertical's discriminator and extension table.\n `variant=\"inline\"` keeps this modal's grammar: an icon\n column and borderless controls (like Scheduled / Add\n notes). Same component and same flow as the conversations\n composer — only the input's chrome differs. */}\n <ContactPicker\n value={clientId || clientSearch ? { id: clientId || undefined, name: clientSearch, phone: clientPhone } : null}\n onChange={(contact) => {\n setClientId(contact?.id ?? '')\n setClientSearch(contact?.name ?? '')\n setClientPhone(contact?.phone ?? '')\n }}\n kind={config.clientKind}\n extensionTable=\"clients\"\n lookup={config.contactLookup}\n clearable={!isPaidBooking}\n variant=\"inline\"\n placeholder={t('agenda.appointment.searchClient')}\n createLabel={t('agenda.appointment.newClient')}\n hint={\n <p className=\"text-[11px] text-warning\">\n {t('agenda.appointment.selectClientHint')}\n </p>\n }\n />\n </div>\n </div>\n )}\n\n {/* Location */}\n {activeType.fields.location && config.modules.locationSelection && (storeLocations.length > 0 || config.locations.length > 0) && (\n <div className=\"flex items-center gap-3 py-1\">\n <MapPin className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <LocationSelect\n value={locationId}\n onChange={setLocationId}\n locations={storeLocations.length > 0 ? storeLocations : config.locations}\n />\n </div>\n )}\n\n {/* Services */}\n {activeType.fields.services && (\n <div className=\"flex items-start gap-3 py-1\">\n <Briefcase className=\"h-4 w-4 mt-1.5 text-muted-foreground shrink-0\" />\n <div className=\"flex-1\">\n {services.length > 0 && (\n <div className=\"space-y-0.5 mb-1\">\n {services.map((svc, idx) => (\n <div key={idx} className=\"flex items-center rounded-md bg-muted/30 px-2.5 py-1.5 text-sm\">\n <span className=\"flex-1 truncate min-w-0\">{svc.name}</span>\n <div className=\"flex items-center gap-0.5 shrink-0 ml-3\">\n <InlineNumber\n value={svc.durationMinutes}\n onChange={(v) => setServices((p) => p.map((s, i) => i === idx ? { ...s, durationMinutes: Math.round(v) } : s))}\n min={5}\n step={5}\n className=\"w-10 shrink-0\"\n disabled={isPaidBooking}\n tooltip={t('agenda.appointment.duration')}\n />\n <span className=\"text-[11px] text-muted-foreground\">min</span>\n </div>\n <div className=\"flex items-center gap-0.5 shrink-0 ml-3\">\n <span className=\"text-[11px] text-muted-foreground\">{currency.symbol}</span>\n <InlineNumber\n value={svc.price}\n onChange={(v) => setServices((p) => p.map((s, i) => i === idx ? { ...s, price: v } : s))}\n min={0}\n step={0.01}\n className=\"w-14 shrink-0\"\n disabled={isPaidBooking}\n tooltip={t('agenda.appointment.price')}\n />\n </div>\n {!isPaidBooking && (\n <button type=\"button\" onClick={() => removeService(idx)} className=\"p-0.5 ml-2 text-muted-foreground hover:text-destructive shrink-0\">\n <X className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n ))}\n </div>\n )}\n\n {!isPaidBooking && <SearchCombobox\n value={serviceSearch}\n onChange={setServiceSearch}\n onSelect={addService}\n options={serviceOptions}\n placeholder={t('agenda.appointment.searchService')}\n onBlurEmpty={() => {}}\n onFocus={() => { if (!serviceSearch && serviceOptions.length === 0) setServiceOptions(initialServiceOptions) }}\n renderRight={(opt) => {\n const dur = (opt.data?.duration_minutes as number) || 0\n const hasPrice = opt.price != null\n if (!hasPrice && !dur) return null\n return (\n <span className=\"text-muted-foreground text-xs whitespace-nowrap\">\n {hasPrice && fmtCurrency(opt.price!, currency.locale, currency.code)}\n {hasPrice && dur > 0 && ' · '}\n {dur > 0 && `${dur}min`}\n </span>\n )\n }}\n minimal\n inlineLabel={services.length > 0 ? t('agenda.appointment.addService') : t('agenda.appointment.addServiceFirst')}\n inlineIcon={services.length > 0 ? 'plus' : 'search'}\n />}\n </div>\n </div>\n )}\n\n {/* Status */}\n {activeType.fields.status && (\n <div className=\"flex items-center gap-3 py-1\">\n <CircleDot className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <StatusSelect value={status} onChange={setStatus} statuses={config.statuses} bookingDate={date} />\n </div>\n )}\n\n {needsCancellationReason && (\n <div className=\"flex items-start gap-3 py-1\">\n <Ban className=\"h-4 w-4 mt-2 text-muted-foreground shrink-0\" />\n <div className=\"flex-1 space-y-2\">\n <select\n value={cancellationReasonId}\n onChange={(event) => setCancellationReasonId(event.target.value)}\n disabled={cancellationReasonsLoading}\n className=\"w-full rounded-input border border-input bg-card px-2.5 py-1.5 text-sm shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] focus:outline-none focus:ring-2 focus:ring-ring\"\n >\n <option value=\"\">{cancellationReasonsLoading ? t('agenda.cancellation.loadingReasons') : t('agenda.cancellation.selectReason')}</option>\n {cancellationReasons.map((reason) => (\n <option key={reason.id} value={reason.id}>\n {reason.label}{reason.requiresNotes ? ' *' : ''}\n </option>\n ))}\n </select>\n <textarea\n value={cancellationNotes}\n onChange={(event) => setCancellationNotes(event.target.value)}\n placeholder={needsCancellationNotes ? t('agenda.cancellation.notesRequired') : t('agenda.cancellation.notesOptional')}\n rows={2}\n className=\"w-full rounded-input border border-input bg-card px-2.5 py-1.5 text-sm resize-none shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n </div>\n )}\n\n {/* Notes — progressive disclosure */}\n {!showNotes ? (\n <div className=\"flex items-center gap-3 py-1\">\n <FileText className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <button type=\"button\" onClick={() => setShowNotes(true)}\n className=\"text-sm text-muted-foreground hover:text-foreground transition-colors text-left py-1.5 pl-2\">\n {t('agenda.appointment.addNotes')}\n </button>\n </div>\n ) : (\n <div className=\"flex items-start gap-3 py-1\">\n <FileText className=\"h-4 w-4 mt-2 text-muted-foreground shrink-0\" />\n <textarea value={notes} onChange={(e) => setNotes(e.target.value)}\n placeholder={t('agenda.appointment.addDescription')} rows={2} autoFocus\n className=\"w-full flex-1 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2.5 py-1.5 text-sm resize-none focus:outline-none focus:ring-2 focus:ring-ring\" />\n </div>\n )}\n\n </>}\n </div>\n\n {/* Appointment footer — inside form for submit */}\n {modalTab === 'appointment' && !clientEditing && (\n <div className=\"px-5 py-2.5 border-t fayz-glass-divider bg-transparent shrink-0 sm:rounded-b-2xl\">\n {confirmingDelete ? (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-destructive font-medium\">{t('agenda.appointment.deleteConfirm')}</span>\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setConfirmingDelete(false)}>\n {t('agenda.appointment.cancel')}\n </Button>\n <Button type=\"button\" variant=\"destructive\" size=\"sm\" onClick={handleDelete} disabled={deleting}>\n {deleting ? t('agenda.appointment.deleting') : t('agenda.appointment.confirmDelete')}\n </Button>\n </div>\n </div>\n ) : (\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n {mode === 'edit' && (\n <button type=\"button\" onClick={() => setConfirmingDelete(true)} className=\"text-xs text-destructive font-medium hover:underline\">{t('agenda.appointment.delete')}</button>\n )}\n {services.length > 0 && (\n <span className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <Clock className=\"h-3 w-3\" />\n {totalDuration}min\n {config.modules.financial && totalPrice > 0 && mode === 'edit' ? (\n paymentStatusLoading ? (\n <span className=\"h-4 w-16 rounded-full bg-muted animate-pulse\" />\n ) : isPaidBooking ? (\n <button type=\"button\" onClick={(e) => { e.stopPropagation(); setModalTab('financial') }}\n className=\"inline-flex items-center gap-1 rounded-full bg-success/10 px-2 py-0.5 text-[10px] font-medium text-success hover:bg-success/20 transition-colors\">\n <Check className=\"h-2.5 w-2.5\" />\n {fmtCurrency(totalPrice, currency.locale, currency.code)} &middot; {t('agenda.payment.paid')}\n </button>\n ) : date <= new Date().toISOString().slice(0, 10) ? (\n <button type=\"button\" onClick={(e) => { e.stopPropagation(); setModalTab('financial') }}\n className=\"inline-flex items-center gap-1 rounded-full bg-warning/10 px-2 py-0.5 text-[10px] font-medium text-warning hover:bg-warning/20 transition-colors\">\n <HandCoins className=\"h-3 w-3\" />\n {fmtCurrency(totalPrice, currency.locale, currency.code)} &middot; {t('agenda.payment.collect')}\n </button>\n ) : (\n <span>&middot; {fmtCurrency(totalPrice, currency.locale, currency.code)}</span>\n )\n ) : (\n <span>&middot; {fmtCurrency(totalPrice, currency.locale, currency.code)}</span>\n )}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={onClose} className=\"hidden sm:inline-flex\">\n {t('agenda.appointment.cancel')}\n </Button>\n <Button type=\"submit\" variant=\"default\" size=\"sm\" disabled={!canSubmit || !isDirty}>\n {saving ? t('agenda.appointment.saving') : mode === 'create' ? t('agenda.appointment.save') : t('agenda.appointment.update')}\n </Button>\n </div>\n </div>\n )}\n </div>\n )}\n </form>\n\n {/* Non-appointment tab footer — outside form */}\n {modalTab !== 'appointment' && !clientEditing && (\n <div className=\"px-5 py-2.5 border-t fayz-glass-divider bg-transparent shrink-0 sm:rounded-b-2xl\">\n <div className=\"flex items-center\">\n <button type=\"button\" onClick={() => { setModalTab('appointment'); setClientEditing(false) }}\n className=\"inline-flex items-center gap-1 text-xs font-medium text-muted-foreground hover:text-foreground transition-colors\">\n <svg className=\"h-3 w-3\" viewBox=\"0 0 16 16\" fill=\"none\"><path d=\"M10 12L6 8l4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/></svg>\n {t('agenda.payment.backToAppointment')}\n </button>\n </div>\n </div>\n )}\n </div>\n </ModalContent>\n\n </Modal>\n )\n}\n","import React, { useEffect, useRef, useState, useCallback } from 'react'\nimport { createPortal } from 'react-dom'\n\n// ---------------------------------------------------------------------------\n// Inject animations once\n// ---------------------------------------------------------------------------\n\nconst STYLE_ID = 'saas-floating-panel'\nif (typeof document !== 'undefined' && !document.getElementById(STYLE_ID)) {\n const s = document.createElement('style')\n s.id = STYLE_ID\n s.textContent = `\n @keyframes _fp-dismiss { from { opacity:1; transform:scale(1) } to { opacity:0; transform:scale(.96) } }\n @keyframes _fp-expand { from { opacity:1; transform:scale(1) } to { opacity:0; transform:scale(1.08) } }\n .saas-fp-dismissing { animation: _fp-dismiss 150ms ease-in forwards; pointer-events: none }\n .saas-fp-expanding { animation: _fp-expand 200ms ease-in forwards; pointer-events: none }\n `\n document.head.appendChild(s)\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Phase = 'visible' | 'dismissing' | 'expanding'\n\nexport interface FloatingPanelRef {\n /** Dismiss with fade-out, then call onClose */\n dismiss: () => void\n /** Expand-out animation (e.g. popover → modal), then call callback */\n expandThen: (callback: () => void) => void\n}\n\ninterface FloatingPanelProps {\n position: { x: number; y: number }\n width: number\n height: number\n /** Offset from cursor (default: { x: 0, y: 0 }) */\n offset?: { x: number; y: number }\n onClose: () => void\n className?: string\n children: (ref: FloatingPanelRef) => React.ReactNode\n zIndex?: number\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function FloatingPanel({\n position, width, height, offset, onClose, className, children, zIndex = 100,\n}: FloatingPanelProps) {\n const ref = useRef<HTMLDivElement>(null)\n const [phase, setPhase] = useState<Phase>('visible')\n const phaseRef = useRef<Phase>('visible')\n phaseRef.current = phase\n const onCloseRef = useRef(onClose)\n onCloseRef.current = onClose\n const expandCallbackRef = useRef<(() => void) | null>(null)\n\n const dismiss = useCallback(() => {\n if (phaseRef.current !== 'visible') return\n setPhase('dismissing')\n setTimeout(() => onCloseRef.current(), 150)\n }, [])\n\n const expandThen = useCallback((callback: () => void) => {\n if (phaseRef.current !== 'visible') return\n expandCallbackRef.current = callback\n setPhase('expanding')\n setTimeout(() => {\n callback()\n onCloseRef.current()\n }, 220)\n }, [])\n\n // Outside click + Escape\n useEffect(() => {\n function handleClick(e: MouseEvent) {\n if (phaseRef.current !== 'visible') return\n if (ref.current && !ref.current.contains(e.target as Node)) {\n // Don't dismiss if clicking another calendar event — let eventClick handle it\n const target = e.target as HTMLElement\n if (target.closest('.fc-event')) return\n dismiss()\n }\n }\n function handleKey(e: KeyboardEvent) {\n if (e.key === 'Escape') dismiss()\n }\n document.addEventListener('mousedown', handleClick)\n document.addEventListener('keydown', handleKey)\n return () => {\n document.removeEventListener('mousedown', handleClick)\n document.removeEventListener('keydown', handleKey)\n }\n }, [dismiss])\n\n // Clamp position to viewport\n const ox = offset?.x ?? 0\n const oy = offset?.y ?? 0\n let x = position.x + ox\n let y = position.y + oy\n if (x + width > window.innerWidth - 12) x = x - width - ox * 2\n if (y + height > window.innerHeight - 12) y = y - height - oy * 2\n if (x < 12) x = 12\n if (y < 12) y = 12\n\n const panelRef: FloatingPanelRef = { dismiss, expandThen }\n\n return createPortal(\n <div ref={ref}\n style={{ position: 'fixed', left: x, top: y, zIndex, transition: phase === 'visible' ? 'left 200ms ease-out, top 200ms ease-out' : undefined }}\n className={`fayz-glass-surface rounded-modal border bg-popover shadow-lg overflow-hidden ${\n phase === 'expanding' ? 'saas-fp-expanding'\n : phase === 'dismissing' ? 'saas-fp-dismissing'\n : 'animate-in fade-in zoom-in-95 duration-150'\n } ${className ?? ''}`}>\n {children(panelRef)}\n </div>,\n document.body,\n )\n}\n","import React, { useState, useRef, useEffect } from 'react'\nimport { X, Pencil, Trash2, Clock, MapPin, User, FileText, DollarSign, Check, AlertTriangle, HandCoins } from 'lucide-react'\nimport { PersonLink } from '@fayz-ai/admin'\nimport { FloatingPanel, type FloatingPanelRef } from './FloatingPanel'\nimport { useAgendaConfig, useAgendaStore } from '../context'\nimport { useTranslation } from '@fayz-ai/core'\nimport { isStatusAvailable } from '../types'\nimport type { CalendarBooking } from '../types'\n\ninterface Props {\n booking: CalendarBooking\n position: { x: number; y: number }\n onClose: () => void\n onEdit: (id: string) => void\n}\n\nfunction fmtTime(iso: string) {\n return new Date(iso).toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })\n}\nfunction fmtDate(iso: string) {\n return new Date(iso).toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric' })\n}\nfunction fmtCurrency(amount: number, locale: string, code: string) {\n return new Intl.NumberFormat(locale, { style: 'currency', currency: code }).format(amount)\n}\n\n// Inline status select for the popover\nfunction PopoverStatusSelect({ value, statuses, bookingStartsAt, onChange }: {\n value: string; statuses: Array<{ value: string; label: string; color: string; availableWhen?: string }>\n bookingStartsAt: string; onChange: (v: string) => void\n}) {\n const [open, setOpen] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\n const current = statuses.find((s) => s.value === value)\n\n useEffect(() => {\n if (!open) return\n const h = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false) }\n document.addEventListener('mousedown', h)\n return () => document.removeEventListener('mousedown', h)\n }, [open])\n\n return (\n <div ref={ref} className=\"relative inline-block\">\n <button type=\"button\" onClick={() => setOpen((p) => !p)}\n className=\"inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-[11px] font-medium transition-colors hover:opacity-80\"\n style={{ backgroundColor: (current?.color ?? '#6b7280') + '18', color: current?.color ?? '#6b7280' }}>\n <span className=\"h-2 w-2 rounded-full\" style={{ backgroundColor: current?.color }} />\n {current?.label ?? value}\n <svg className=\"h-3 w-3 opacity-50\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n </svg>\n </button>\n {open && (\n <div className=\"fayz-glass-surface absolute bottom-full left-0 z-50 mb-1 rounded-lg border bg-popover shadow-lg py-1 animate-in fade-in zoom-in-95 duration-100 min-w-[140px]\">\n {statuses.map((s) => {\n const available = isStatusAvailable(s as any, bookingStartsAt)\n return (\n <button key={s.value} type=\"button\" disabled={!available}\n onClick={() => { if (available) { onChange(s.value); setOpen(false) } }}\n className={`flex w-full items-center gap-2 px-3 py-1.5 text-xs transition-colors ${\n !available ? 'opacity-30 cursor-not-allowed' : s.value === value ? 'bg-muted/30' : 'hover:bg-muted/50'\n }`}>\n <span className=\"h-2 w-2 rounded-full shrink-0\" style={{ backgroundColor: s.color }} />\n <span>{s.label}</span>\n </button>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n\nexport function AppointmentPopover({ booking, position, onClose, onEdit }: Props) {\n const t = useTranslation()\n const config = useAgendaConfig()\n const deleteBooking = useAgendaStore((s) => s.deleteBooking)\n const updateStatus = useAgendaStore((s) => s.updateBookingStatus)\n const openModal = useAgendaStore((s) => s.openAppointmentModal)\n const [confirmingDelete, setConfirmingDelete] = useState(false)\n const [deleting, setDeleting] = useState(false)\n const statusConfig = config.statuses.find((s) => s.value === booking.status)\n const color = statusConfig?.color ?? '#6b7280'\n const timeRange = `${fmtTime(booking.startsAt)}${booking.endsAt ? ' – ' + fmtTime(booking.endsAt) : ''}`\n\n async function handleDelete() {\n setDeleting(true)\n try { await deleteBooking(booking.id); onClose() } catch { setDeleting(false) }\n }\n\n return (\n <>\n <FloatingPanel position={position} width={320} height={340} onClose={onClose}>\n {(panel) => (\n <>\n {/* Action bar */}\n <div className=\"flex items-center justify-end gap-0.5 px-3 pt-3 pb-1\">\n {confirmingDelete ? (\n <>\n <span className=\"text-xs text-destructive font-medium mr-auto pl-1\">{t('agenda.appointment.deleteConfirm')}</span>\n <button onClick={() => setConfirmingDelete(false)}\n className=\"rounded px-2 py-0.5 text-[11px] font-medium hover:bg-muted/50 transition-colors\">{t('agenda.appointment.cancel')}</button>\n <button onClick={handleDelete} disabled={deleting}\n className=\"rounded bg-destructive border border-destructive px-2 py-0.5 text-[11px] font-medium text-destructive-foreground hover:bg-destructive/90 shadow-button-primary active:shadow-button-inset disabled:opacity-40 transition-colors\">{deleting ? t('agenda.appointment.deleting') : t('agenda.appointment.confirmDelete')}</button>\n </>\n ) : (\n <>\n <button onClick={() => panel.expandThen(() => onEdit(booking.id))}\n className=\"p-1.5 rounded-full hover:bg-muted transition-colors\" title={t('common.edit')}>\n <Pencil className=\"h-4 w-4 text-muted-foreground\" />\n </button>\n <button onClick={() => setConfirmingDelete(true)}\n className=\"p-1.5 rounded-full hover:bg-destructive/10 transition-colors\" title={t('common.delete')}>\n <Trash2 className=\"h-4 w-4 text-muted-foreground hover:text-destructive\" />\n </button>\n <button onClick={panel.dismiss} className=\"p-1.5 rounded-full hover:bg-muted transition-colors\">\n <X className=\"h-4 w-4 text-muted-foreground\" />\n </button>\n </>\n )}\n </div>\n\n {/* Content */}\n <div className=\"px-5 pb-5 space-y-3\">\n <div className=\"flex items-start gap-3\">\n <span className=\"mt-1.5 h-3 w-3 rounded shrink-0\" style={{ backgroundColor: color }} />\n <div className=\"min-w-0\">\n {/* Client agendas link to the person; simple events (no client\n capability) render the free-text title as a plain heading —\n booking.clientName carries the event title in that model. */}\n {config.capabilities.client ? (\n <PersonLink personId={booking.clientId} name={booking.clientName ?? 'Unknown'} className=\"text-base\" />\n ) : (\n <p className=\"text-base font-medium truncate\">{booking.clientName || t('agenda.appointment.untitled')}</p>\n )}\n <p className=\"text-sm text-muted-foreground mt-0.5\">{fmtDate(booking.startsAt)} &middot; {timeRange}</p>\n </div>\n </div>\n\n {booking.services && booking.services.length > 0 && (\n <div className=\"flex items-start gap-3\">\n <Clock className=\"h-4 w-4 mt-0.5 text-muted-foreground shrink-0\" />\n <div className=\"text-sm space-y-0.5\">\n {booking.services.map((svc) => (\n <p key={svc.id}>{svc.name} <span className=\"text-muted-foreground\">({svc.durationMinutes}min)</span></p>\n ))}\n </div>\n </div>\n )}\n\n {config.capabilities.professional && booking.professionalName && (\n <div className=\"flex items-center gap-3\">\n <User className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <span className=\"text-sm\">{booking.professionalName}</span>\n </div>\n )}\n\n {booking.locationName && (\n <div className=\"flex items-center gap-3\">\n <MapPin className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n <span className=\"text-sm\">{booking.locationName}</span>\n </div>\n )}\n\n {booking.notes && (\n <div className=\"flex items-start gap-3\">\n <FileText className=\"h-4 w-4 mt-0.5 text-muted-foreground shrink-0\" />\n <p className=\"text-sm text-muted-foreground\">{booking.notes}</p>\n </div>\n )}\n\n {booking.orderTotal != null && booking.orderTotal > 0 && (() => {\n const total = fmtCurrency(booking.orderTotal, config.currency.locale, config.currency.code)\n const ps = booking.paymentStatus ?? 'none'\n const hasFinancial = config.modules.financial && booking.orderId\n\n // No financial module — just show total\n if (!hasFinancial) {\n return (\n <div className=\"pt-2 border-t fayz-glass-divider flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground\">{t('agenda.appointment.total')}</span>\n <span className=\"font-medium\">{total}</span>\n </div>\n )\n }\n\n const badgeConfig: Record<string, { icon: React.ElementType; bg: string; text: string; label: string }> = {\n none: { icon: HandCoins, bg: 'bg-warning/10 hover:bg-warning/15', text: 'text-warning', label: `${total} · ${t('agenda.payment.collect')}` },\n pending: { icon: Clock, bg: 'bg-warning/10 hover:bg-warning/15', text: 'text-warning', label: `${total} · ${t('agenda.payment.pending')}` },\n partial: { icon: DollarSign, bg: 'bg-warning/10 hover:bg-warning/15', text: 'text-warning', label: `${total} · ${t('agenda.payment.partial')}` },\n paid: { icon: Check, bg: 'bg-success/10 hover:bg-success/15', text: 'text-success', label: `${total} · ${t('agenda.payment.paid')}` },\n overdue: { icon: AlertTriangle, bg: 'bg-destructive/10 hover:bg-destructive/15', text: 'text-destructive', label: `${total} · ${t('agenda.payment.overdue')}` },\n cancelled: { icon: X, bg: 'bg-muted hover:bg-muted/80', text: 'text-muted-foreground', label: `${total} · ${t('agenda.payment.cancelled')}` },\n }\n const cfg = badgeConfig[ps] ?? badgeConfig.none\n const StatusIcon = cfg.icon\n\n return (\n <div className=\"pt-2 border-t fayz-glass-divider flex items-center justify-between\">\n <span className=\"text-xs text-muted-foreground\">{t('agenda.appointment.total')}</span>\n <button\n type=\"button\"\n onClick={() => { onClose(); openModal('edit', { bookingId: booking.id, initialTab: 'financial' }) }}\n className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium transition-colors ${cfg.bg} ${cfg.text}`}\n >\n <StatusIcon className=\"h-3 w-3\" />\n {cfg.label}\n </button>\n </div>\n )\n })()}\n\n {/* Status workflow — hidden for simple events (no status capability). */}\n {config.capabilities.status && (\n <div className=\"pt-2 border-t fayz-glass-divider\">\n <PopoverStatusSelect\n value={booking.status}\n statuses={config.statuses}\n bookingStartsAt={booking.startsAt}\n onChange={(v) => { updateStatus(booking.id, v); onClose() }}\n />\n </div>\n )}\n </div>\n </>\n )}\n </FloatingPanel>\n </>\n )\n}\n","import React, { useRef, useState, useMemo } from 'react'\nimport { createPortal } from 'react-dom'\nimport { Pencil, Trash2, Check } from 'lucide-react'\nimport { FloatingPanel } from './FloatingPanel'\nimport { useAgendaConfig, useAgendaStore } from '../context'\nimport { useTranslation } from '@fayz-ai/core'\nimport { isStatusAvailable } from '../types'\nimport type { CalendarBooking } from '../types'\n\n// ---------------------------------------------------------------------------\n// Tooltip — portaled to body\n// ---------------------------------------------------------------------------\n\nfunction Tooltip({ anchor, label }: { anchor: DOMRect; label: string }) {\n return createPortal(\n <div style={{ position: 'fixed', left: anchor.left + anchor.width / 2, top: anchor.bottom + 6, transform: 'translateX(-50%)', zIndex: 120 }}\n className=\"pointer-events-none\">\n <div className=\"rounded-md bg-foreground text-background px-2 py-0.5 text-[11px] font-medium whitespace-nowrap shadow-lg\">\n {label}\n </div>\n </div>,\n document.body,\n )\n}\n\n// ---------------------------------------------------------------------------\n// Status dot with portaled tooltip\n// ---------------------------------------------------------------------------\n\nfunction StatusDot({ color, label, isActive, disabled, onClick }: {\n color: string; label: string; isActive: boolean; disabled?: boolean; onClick: () => void\n}) {\n const [hover, setHover] = useState(false)\n const btnRef = useRef<HTMLButtonElement>(null)\n const [rect, setRect] = useState<DOMRect | null>(null)\n\n return (\n <>\n <button ref={btnRef} type=\"button\" onClick={disabled ? undefined : onClick} disabled={disabled}\n onMouseEnter={() => { setHover(true); if (btnRef.current) setRect(btnRef.current.getBoundingClientRect()) }}\n onMouseLeave={() => setHover(false)}\n className={`flex h-7 w-7 items-center justify-center rounded-full transition-all ${\n disabled ? 'opacity-25 cursor-not-allowed' : isActive ? 'ring-2 ring-offset-2 ring-offset-popover' : 'hover:scale-110'\n }`}\n style={{ backgroundColor: color, ['--tw-ring-color' as any]: isActive ? color : undefined }}>\n {isActive && <Check className=\"h-3.5 w-3.5 text-white\" strokeWidth={2.5} />}\n </button>\n {hover && rect && <Tooltip anchor={rect} label={label} />}\n </>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Context Menu\n// ---------------------------------------------------------------------------\n\ninterface Props {\n booking: CalendarBooking\n position: { x: number; y: number }\n onClose: () => void\n onEdit: (id: string) => void\n}\n\nexport function EventContextMenu({ booking, position, onClose, onEdit }: Props) {\n const t = useTranslation()\n const config = useAgendaConfig()\n const updateStatus = useAgendaStore((s) => s.updateBookingStatus)\n const deleteBooking = useAgendaStore((s) => s.deleteBooking)\n const [confirming, setConfirming] = useState(false)\n const [deleting, setDeleting] = useState(false)\n\n async function handleDelete() {\n setDeleting(true)\n try { await deleteBooking(booking.id); onClose() } catch { setDeleting(false) }\n }\n\n return (\n <FloatingPanel position={position} width={230} height={180} offset={{ x: 4, y: 4 }} onClose={onClose} zIndex={110}>\n {(panel) => (\n <>\n <div className=\"py-1\">\n <button onClick={() => panel.expandThen(() => onEdit(booking.id))}\n className=\"flex w-full items-center gap-3 px-4 py-2 text-sm hover:bg-muted/50 transition-colors\">\n <Pencil className=\"h-4 w-4 text-muted-foreground\" /> {t('agenda.contextMenu.edit')}\n </button>\n {confirming ? (\n <div className=\"flex items-center justify-between px-4 py-2\">\n <span className=\"text-xs text-destructive font-medium\">{t('agenda.appointment.deleteConfirm')}</span>\n <div className=\"flex items-center gap-1.5\">\n <button onClick={() => setConfirming(false)}\n className=\"rounded px-2 py-0.5 text-[11px] font-medium hover:bg-muted/50 transition-colors\">{t('agenda.appointment.cancel')}</button>\n <button onClick={handleDelete} disabled={deleting}\n className=\"rounded bg-destructive border border-destructive px-2 py-0.5 text-[11px] font-medium text-destructive-foreground hover:bg-destructive/90 shadow-button-primary active:shadow-button-inset disabled:opacity-40 transition-colors\">{deleting ? t('agenda.appointment.deleting') : t('agenda.appointment.confirmDelete')}</button>\n </div>\n </div>\n ) : (\n <button onClick={() => setConfirming(true)}\n className=\"flex w-full items-center gap-3 px-4 py-2 text-sm hover:bg-muted/50 transition-colors text-destructive\">\n <Trash2 className=\"h-4 w-4\" /> {t('agenda.contextMenu.delete')}\n </button>\n )}\n </div>\n\n {/* Status workflow — hidden for simple events (no status capability). */}\n {config.capabilities.status && (\n <div className=\"border-t px-4 py-3\">\n <p className=\"text-[11px] font-medium text-muted-foreground mb-2\">{t('agenda.contextMenu.changeStatus')}</p>\n <div className=\"flex items-center gap-1.5\">\n {config.statuses.map((s) => {\n const available = isStatusAvailable(s, booking.startsAt)\n return (\n <StatusDot key={s.value} color={s.color} label={available ? s.label : `${s.label} ${t('agenda.contextMenu.notAvailable')}`}\n isActive={booking.status === s.value}\n disabled={!available}\n onClick={() => { if (available) { updateStatus(booking.id, s.value); panel.dismiss() } }} />\n )\n })}\n </div>\n </div>\n )}\n </>\n )}\n </FloatingPanel>\n )\n}\n","import React, { useMemo } from 'react'\nimport { formatCurrency, useTranslation, getCurrentLocale } from '@fayz-ai/core'\nimport type { CalendarBooking } from '../types'\n\n// ---------------------------------------------------------------------------\n// Mobile agenda list — a thumb-friendly, date-grouped list of upcoming items.\n// Rendered on <md viewports instead of the FullCalendar grid. Each row shows a\n// category/status dot, the title, the time, and (for finance-style events) the\n// amount. Fed straight from the store bookings so it works for any seeded app.\n// ---------------------------------------------------------------------------\n\nfunction startOfDay(d: Date): Date {\n const x = new Date(d)\n x.setHours(0, 0, 0, 0)\n return x\n}\n\nfunction timeLabel(iso: string): string {\n const d = new Date(iso)\n return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`\n}\n\nexport interface AgendaMobileListProps {\n bookings: CalendarBooking[]\n statusColors: Record<string, string>\n currencyCode: string\n onSelect: (booking: CalendarBooking) => void\n}\n\nexport function AgendaMobileList({ bookings, statusColors, currencyCode, onSelect }: AgendaMobileListProps) {\n const t = useTranslation()\n const locale = getCurrentLocale() === 'pt-BR' ? 'pt-BR' : 'en'\n\n const groups = useMemo(() => {\n const todayStart = startOfDay(new Date()).getTime()\n const sorted = bookings\n .filter((b) => !!b.startsAt)\n .slice()\n .sort((a, b) => (a.startsAt < b.startsAt ? -1 : a.startsAt > b.startsAt ? 1 : 0))\n const map = new Map<string, CalendarBooking[]>()\n for (const b of sorted) {\n const day = startOfDay(new Date(b.startsAt))\n if (day.getTime() < todayStart) continue // upcoming only\n const key = day.toISOString().slice(0, 10)\n const list = map.get(key) ?? []\n list.push(b)\n map.set(key, list)\n }\n return Array.from(map.entries()).map(([key, items]) => ({ key, date: new Date(key + 'T00:00:00'), items }))\n }, [bookings])\n\n function dayLabel(date: Date): string {\n const today = startOfDay(new Date())\n const diff = Math.round((startOfDay(date).getTime() - today.getTime()) / 86400000)\n if (diff === 0) return t('agenda.list.today')\n if (diff === 1) return t('agenda.list.tomorrow')\n return date.toLocaleDateString(locale, { weekday: 'long', day: 'numeric', month: 'long' })\n }\n\n if (groups.length === 0) {\n return (\n <div className=\"flex-1 flex flex-col items-center justify-center px-6 py-16 text-center text-muted-foreground\">\n <p className=\"text-sm\">{t('agenda.list.empty')}</p>\n </div>\n )\n }\n\n return (\n <div className=\"flex-1 overflow-y-auto px-3 py-3 space-y-5\">\n {groups.map((g) => (\n <div key={g.key}>\n <h3 className=\"px-1 pb-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n {dayLabel(g.date)}\n </h3>\n <div className=\"space-y-1.5\">\n {g.items.map((b) => {\n const color = statusColors[b.status] ?? '#6b7280'\n const hasAmount = typeof b.orderTotal === 'number' && b.orderTotal > 0\n return (\n <button\n key={b.id}\n onClick={() => onSelect(b)}\n className=\"flex w-full items-center gap-3 rounded-lg border bg-card px-3 py-2.5 text-left shadow-sm transition-colors active:bg-muted/50\"\n >\n <span className=\"h-2.5 w-2.5 shrink-0 rounded-full\" style={{ backgroundColor: color }} />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-foreground\">{b.clientName ?? '—'}</p>\n <p className=\"text-xs text-muted-foreground\">{timeLabel(b.startsAt)}</p>\n </div>\n {hasAmount && (\n <span className=\"shrink-0 text-sm font-semibold tabular-nums text-foreground\">\n {formatCurrency(b.orderTotal, currencyCode)}\n </span>\n )}\n </button>\n )\n })}\n </div>\n </div>\n ))}\n </div>\n )\n}\n","import React, { useRef, useEffect, useCallback, useMemo, useState } from 'react'\nimport { injectCalendarStyles } from '../styles/calendar-styles'\nimport FullCalendar from '@fullcalendar/react'\nimport dayGridPlugin from '@fullcalendar/daygrid'\nimport timeGridPlugin from '@fullcalendar/timegrid'\nimport resourceTimeGridPlugin from '@fullcalendar/resource-timegrid'\nimport interactionPlugin from '@fullcalendar/interaction'\nimport listPlugin from '@fullcalendar/list'\nimport ptBrLocale from '@fullcalendar/core/locales/pt-br'\nimport type { EventInput, EventClickArg, DateSelectArg, EventDropArg } from '@fullcalendar/core'\nimport { ChevronLeft, ChevronRight, Plus, ChevronDown, Settings } from 'lucide-react'\nimport { usePluginPrefs } from '@fayz-ai/admin'\nimport { getCurrentLocale } from '@fayz-ai/core'\nimport { useTranslation, useDataChanged } from '@fayz-ai/core'\nimport { useAgendaConfig, useAgendaStore } from '../context'\nimport { useAgendaSettings } from '../hooks/useAgendaSettings'\nimport { MiniCalendar } from '../components/MiniCalendar'\nimport { AppointmentModal } from '../components/AppointmentModal'\nimport { AppointmentPopover } from '../components/AppointmentPopover'\nimport { PersonLink } from '@fayz-ai/admin'\nimport { EventContextMenu } from '../components/EventContextMenu'\nimport { AgendaMobileList } from '../components/AgendaMobileList'\nimport { ConfirmDialog } from '@fayz-ai/ui'\nimport { Button } from '@fayz-ai/ui'\nimport type { CalendarBooking, Schedule } from '../types'\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction bookingToEvent(booking: CalendarBooking, statusColors: Record<string, string>): EventInput {\n const color = statusColors[booking.status] ?? '#6b7280'\n const serviceNames = booking.services?.map((s) => s.name).join(', ') ?? ''\n return {\n id: booking.id,\n resourceId: booking.professionalId ?? undefined,\n title: booking.clientName ?? 'Unknown',\n start: booking.startsAt,\n end: booking.endsAt ?? undefined,\n backgroundColor: color + '30',\n borderColor: color,\n textColor: color,\n extendedProps: { booking, serviceNames },\n }\n}\n\n/**\n * Generate FullCalendar background events showing unavailable time.\n * For each day, creates background blocks for the gaps OUTSIDE working hours\n * within the visible business hours window. This grays out non-working time.\n */\nfunction generateAvailabilityEvents(\n schedules: Schedule[],\n professionals: { id: string }[],\n dateRange: { start: string; end: string } | null,\n businessHours?: { startTime: string; endTime: string },\n locationMap?: Map<string, string>,\n): EventInput[] {\n if (!dateRange || schedules.length === 0) return []\n\n const bgEvents: EventInput[] = []\n const startDate = new Date(dateRange.start)\n const endDate = new Date(dateRange.end)\n const bizStart = businessHours?.startTime ?? '08:00'\n const bizEnd = businessHours?.endTime ?? '20:00'\n\n // Group schedules by assignee\n const byAssignee = new Map<string, Schedule[]>()\n for (const s of schedules) {\n const aid = s.assigneeId\n if (!aid) continue\n const list = byAssignee.get(aid) ?? []\n list.push(s)\n byAssignee.set(aid, list)\n }\n\n function timeToMinutes(t: string): number {\n const [h, m] = t.split(':').map(Number)\n return h * 60 + m\n }\n\n function minutesToTime(m: number): string {\n return `${String(Math.floor(m / 60)).padStart(2, '0')}:${String(m % 60).padStart(2, '0')}`\n }\n\n const bizStartMin = timeToMinutes(bizStart)\n const bizEndMin = timeToMinutes(bizEnd)\n\n for (const prof of professionals) {\n const profSchedules = byAssignee.get(prof.id) ?? []\n\n // Separate weekly and date-specific schedules\n const weekly = profSchedules.filter((s) => s.dayOfWeek != null && !s.specificDate)\n const exceptions = profSchedules.filter((s) => s.specificDate != null)\n const exceptionDates = new Set(exceptions.map((s) => s.specificDate!))\n\n const current = new Date(startDate)\n while (current < endDate) {\n const dateStr = current.toISOString().slice(0, 10)\n const dayOfWeek = current.getDay()\n\n // Get working periods for this day\n let daySchedules: Schedule[]\n if (exceptionDates.has(dateStr)) {\n daySchedules = exceptions.filter((s) => s.specificDate === dateStr && s.isActive)\n } else {\n daySchedules = weekly.filter((s) => s.dayOfWeek === dayOfWeek && s.isActive)\n }\n\n // Convert working periods to sorted minute ranges, preserving locationId\n const workRanges = daySchedules\n .map((s) => {\n const locId = s.locationId ?? (s.metadata?.locationId as string | undefined)\n return {\n start: timeToMinutes(s.startsAt),\n end: timeToMinutes(s.endsAt),\n locationName: locId && locationMap ? locationMap.get(locId) : undefined,\n }\n })\n .sort((a, b) => a.start - b.start)\n\n // Compute unavailable gaps within business hours\n let cursor = bizStartMin\n for (const range of workRanges) {\n const availStart = Math.max(range.start, bizStartMin)\n const availEnd = Math.min(range.end, bizEndMin)\n\n // Gap before this working range = unavailable\n if (cursor < availStart) {\n bgEvents.push({\n resourceId: prof.id,\n start: dateStr + 'T' + minutesToTime(cursor) + ':00',\n end: dateStr + 'T' + minutesToTime(availStart) + ':00',\n display: 'background',\n classNames: ['fc-unavailable-bg'],\n })\n }\n\n // Location label on available range\n if (availStart < availEnd && range.locationName) {\n bgEvents.push({\n id: `loc-${prof.id}-${dateStr}-${minutesToTime(availStart)}`,\n resourceId: prof.id,\n start: dateStr + 'T' + minutesToTime(availStart) + ':00',\n end: dateStr + 'T' + minutesToTime(availStart + 20) + ':00',\n title: range.locationName,\n display: 'auto',\n editable: false,\n backgroundColor: 'transparent',\n borderColor: 'transparent',\n textColor: '#a3a3a3',\n classNames: ['fc-location-label'],\n extendedProps: { isLocationLabel: true },\n })\n }\n\n cursor = Math.max(cursor, availEnd)\n }\n\n // Gap after last working range = unavailable\n if (cursor < bizEndMin) {\n bgEvents.push({\n resourceId: prof.id,\n start: dateStr + 'T' + minutesToTime(cursor) + ':00',\n end: dateStr + 'T' + minutesToTime(bizEndMin) + ':00',\n display: 'background',\n classNames: ['fc-unavailable-bg'],\n })\n }\n\n\n current.setDate(current.getDate() + 1)\n }\n }\n\n return bgEvents\n}\n\n// ---------------------------------------------------------------------------\n// Loading skeleton — mimics the resource-timegrid-week layout\n// ---------------------------------------------------------------------------\n\nfunction CalendarSkeleton({ profCount = 2 }: { profCount?: number }) {\n const days = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']\n const hours = ['07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00']\n\n return (\n <div className=\"flex-1 overflow-hidden animate-pulse\">\n <div className=\"flex border-b\" style={{ paddingLeft: 56 }}>\n {Array.from({ length: profCount }).map((_, pi) => (\n <div key={pi} className=\"flex-1 border-r last:border-r-0 py-2 px-3\">\n <div className=\"flex items-center justify-center gap-2\">\n <div className=\"h-6 w-6 rounded-full bg-muted\" />\n <div className=\"h-3 w-20 rounded bg-muted\" />\n </div>\n </div>\n ))}\n </div>\n <div className=\"flex border-b\" style={{ paddingLeft: 56 }}>\n {Array.from({ length: profCount }).map((_, pi) => (\n <div key={pi} className=\"flex-1 flex border-r last:border-r-0\">\n {days.map((d) => (\n <div key={d} className=\"flex-1 py-1.5 text-center\">\n <span className=\"text-[10px] text-muted-foreground/40\">{d}</span>\n </div>\n ))}\n </div>\n ))}\n </div>\n <div className=\"relative\">\n {hours.map((h) => (\n <div key={h} className=\"flex border-b border-border/30\" style={{ height: 50 }}>\n <div className=\"w-14 shrink-0 pr-2 text-right\">\n <span className=\"text-[10px] text-muted-foreground/30\">{h}</span>\n </div>\n <div className=\"flex-1 flex\">\n {Array.from({ length: profCount * 7 }).map((_, ci) => (\n <div key={ci} className={`flex-1 border-r border-border/20 ${Math.floor(ci / 7) % 2 === 1 ? 'bg-muted/20' : ''}`} />\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n )\n}\n\n// Resource views — one column per professional. Used when the app has staff.\nconst RESOURCE_VIEW_OPTIONS = [\n { key: 'resourceTimeGridDay', labelKey: 'agenda.calendar.viewDay' },\n { key: 'resourceTimeGridWeek', labelKey: 'agenda.calendar.viewWeek' },\n { key: 'dayGridMonth', labelKey: 'agenda.calendar.viewMonth' },\n] as const\n\n// Non-resource variants — used when there are no professionals/resources (e.g. a\n// personal-finance agenda). A resource timegrid renders an EMPTY grid with zero\n// resource columns and drops events that have no resourceId, so those apps fall\n// back to a plain month/day/week calendar.\nconst PLAIN_VIEW_OPTIONS = [\n { key: 'timeGridDay', labelKey: 'agenda.calendar.viewDay' },\n { key: 'timeGridWeek', labelKey: 'agenda.calendar.viewWeek' },\n { key: 'dayGridMonth', labelKey: 'agenda.calendar.viewMonth' },\n { key: 'listMonth', labelKey: 'agenda.calendar.viewList' },\n] as const\n\n// Sentinel view key for the thumb-friendly mobile agenda list (AgendaMobileList),\n// which is NOT a FullCalendar view. Selected by default on <md so B2C opens on the\n// list; picking any grid option (Dia/Semana/Mês) mounts the real calendar instead.\nconst MOBILE_LIST_VIEW = '__mobileList__'\n\n/** Collapse a resource view to a plain month calendar when there are no resources. */\nfunction viewForNoResources(view: string): string {\n return view.startsWith('resource') ? 'dayGridMonth' : view\n}\n\n/** Promote a plain timegrid to its resource variant when the app has resources. */\nfunction viewForResources(view: string): string {\n if (view === 'timeGridWeek') return 'resourceTimeGridWeek'\n if (view === 'timeGridDay') return 'resourceTimeGridDay'\n return view\n}\n\n/** Small viewport (<md) → render the thumb-friendly agenda list instead of the grid. */\nfunction useIsMobile(): boolean {\n const [isMobile, setIsMobile] = useState(() =>\n typeof window !== 'undefined' && window.matchMedia('(max-width: 767px)').matches)\n useEffect(() => {\n if (typeof window === 'undefined') return\n const mq = window.matchMedia('(max-width: 767px)')\n const onChange = () => setIsMobile(mq.matches)\n mq.addEventListener('change', onChange)\n return () => mq.removeEventListener('change', onChange)\n }, [])\n return isMobile\n}\n\n// ---------------------------------------------------------------------------\n// Calendar View\n// ---------------------------------------------------------------------------\n\nexport function CalendarView() {\n injectCalendarStyles()\n const config = useAgendaConfig()\n const t = useTranslation()\n const currentLocale = getCurrentLocale()\n const fcLocale = currentLocale === 'pt-BR' ? ptBrLocale : undefined\n const calendarRef = useRef<FullCalendar>(null)\n const prefs = usePluginPrefs('agenda', { calendarView: config.defaultCalendarView ?? 'resourceTimeGridWeek' })\n const agendaSettings = useAgendaSettings()\n const effectiveBusinessHours = {\n startTime: agendaSettings.startTime,\n endTime: agendaSettings.endTime,\n }\n\n const bookings = useAgendaStore((s) => s.bookings)\n const bookingsLoading = useAgendaStore((s) => s.bookingsLoading)\n const professionals = useAgendaStore((s) => s.professionals)\n const professionalsLoading = useAgendaStore((s) => s.professionalsLoading)\n const currentView = useAgendaStore((s) => s.currentView)\n const selectedProfIds = useAgendaStore((s) => s.selectedProfessionalIds)\n const selectedStatuses = useAgendaStore((s) => s.selectedStatuses)\n const schedules = useAgendaStore((s) => s.schedules)\n const fetchBookings = useAgendaStore((s) => s.fetchBookings)\n const fetchProfessionals = useAgendaStore((s) => s.fetchProfessionals)\n const fetchLocations = useAgendaStore((s) => s.fetchLocations)\n const storeLocations = useAgendaStore((s) => s.locations)\n const fetchSchedules = useAgendaStore((s) => s.fetchSchedules)\n const rescheduleBooking = useAgendaStore((s) => s.rescheduleBooking)\n const setView = useAgendaStore((s) => s.setView)\n const setFilters = useAgendaStore((s) => s.setFilters)\n const _openModal = useAgendaStore((s) => s.openAppointmentModal)\n const closeModal = useAgendaStore((s) => s.closeAppointmentModal)\n const modalState = useAgendaStore((s) => s.appointmentModal)\n\n // Resource-capable = the app has professionals/staff. When it doesn't (e.g. a\n // personal-finance agenda), resource views render empty, so we force plain\n // (non-resource) views and default to a month calendar.\n const isMobile = useIsMobile()\n const resourceCapable = professionals.length > 0\n const viewOptions = resourceCapable ? RESOURCE_VIEW_OPTIONS : PLAIN_VIEW_OPTIONS\n\n // Mobile (<md) has its own view selection, independent of the desktop pref: it\n // defaults to the thumb-friendly list and lets the user switch to any grid view\n // (Dia/Semana/Mês) without changing the desktop's stored calendarView. The list\n // sentinel replaces FullCalendar's own listMonth so mobile always gets the rich\n // AgendaMobileList, and a list option is offered even for resource apps.\n const [mobileView, setMobileView] = useState<string>(MOBILE_LIST_VIEW)\n const mobileViewOptions = useMemo(\n () => [\n ...viewOptions.filter((o) => o.key !== 'listMonth'),\n { key: MOBILE_LIST_VIEW, labelKey: 'agenda.calendar.viewList' },\n ],\n [viewOptions],\n )\n const mobileGridActive = isMobile && mobileView !== MOBILE_LIST_VIEW\n\n const [selectedBooking, setSelectedBooking] = useState<CalendarBooking | null>(null)\n const [popoverAnchor, setPopoverAnchor] = useState<{ x: number; y: number } | null>(null)\n const [popoverVisible, _setPopoverVisible] = useState(false)\n const popoverVisibleRef = useRef(false)\n const setPopoverVisible = useCallback((v: boolean) => { popoverVisibleRef.current = v; _setPopoverVisible(v) }, [])\n const [contextMenu, setContextMenu] = useState<{ booking: CalendarBooking; x: number; y: number } | null>(null)\n const [contextMenuVisible, _setContextMenuVisible] = useState(false)\n const contextMenuVisibleRef = useRef(false)\n const setContextMenuVisible = useCallback((v: boolean) => { contextMenuVisibleRef.current = v; _setContextMenuVisible(v) }, [])\n const [scheduleConfirm, setScheduleConfirm] = useState<{ onConfirm: () => void } | null>(null)\n const [calendarTitle, setCalendarTitle] = useState('')\n const [selectedDate, setSelectedDate] = useState(new Date())\n const [profSectionOpen, setProfSectionOpen] = useState(true)\n const [statusSectionOpen, setStatusSectionOpen] = useState(false)\n const [visibleRange, setVisibleRange] = useState<{ start: string; end: string } | null>(null)\n\n // Wrap openModal to always dismiss popover/context menu first\n const openModal: typeof _openModal = useCallback((...args) => {\n setPopoverVisible(false); setSelectedBooking(null); setPopoverAnchor(null)\n setContextMenuVisible(false); setContextMenu(null)\n _openModal(...args)\n }, [_openModal])\n\n const statusColors = useMemo(() => {\n const map: Record<string, string> = {}\n for (const s of config.statuses) map[s.value] = s.color\n return map\n }, [config.statuses])\n\n useEffect(() => {\n fetchProfessionals(); fetchSchedules()\n if (config.modules.locationSelection) fetchLocations()\n }, [])\n\n // Keep the view consistent with resource-capability, in case a stale/shared\n // pref selected the wrong variant. No resources → a resource view is an empty\n // grid that drops the seeded events; resources → a plain timegrid loses the\n // per-professional columns.\n useEffect(() => {\n const api = calendarRef.current?.getApi()\n if (!api) return\n if (!resourceCapable && currentView.startsWith('resource')) {\n api.changeView('dayGridMonth')\n } else if (resourceCapable && (currentView === 'timeGridWeek' || currentView === 'timeGridDay')) {\n api.changeView(viewForResources(currentView))\n }\n }, [resourceCapable, currentView])\n\n // Mobile renders the agenda list (no FullCalendar), so the grid's datesSet —\n // which normally drives fetchBookings — never fires. Fetch a wide upcoming\n // window directly so the list has data.\n useEffect(() => {\n if (!isMobile) return\n const start = new Date(); start.setHours(0, 0, 0, 0); start.setDate(start.getDate() - 1)\n const end = new Date(start); end.setDate(end.getDate() + 91)\n fetchBookings({ start: start.toISOString(), end: end.toISOString() })\n }, [isMobile, fetchBookings])\n\n // A booking created outside the grid — the assistant, the public page,\n // another device — repaints the calendar it belongs to. Without this the\n // manager who just said \"agenda a Maria amanhã às 10\" still sees yesterday's\n // grid and reloads the tab by hand.\n useDataChanged({}, () => {\n if (visibleRange) {\n fetchBookings(visibleRange)\n return\n }\n const start = new Date(); start.setHours(0, 0, 0, 0); start.setDate(start.getDate() - 1)\n const end = new Date(start); end.setDate(end.getDate() + 91)\n fetchBookings({ start: start.toISOString(), end: end.toISOString() })\n }, [visibleRange, fetchBookings])\n\n const resources = useMemo(() => {\n const filtered = selectedProfIds.length > 0\n ? professionals.filter((p) => selectedProfIds.includes(p.id))\n : professionals\n return filtered.map((p) => ({\n id: p.id, title: p.name,\n extendedProps: { avatarUrl: p.avatarUrl, locationName: p.locationName },\n }))\n }, [professionals, selectedProfIds])\n\n const bookingEvents = useMemo(() =>\n bookings.map((b) => bookingToEvent(b, statusColors)), [bookings, statusColors])\n\n // Merge static config locations with dynamically fetched locations\n const allLocations = useMemo(() => {\n const map = new Map<string, string>()\n for (const loc of config.locations) map.set(loc.id, loc.name)\n for (const loc of storeLocations) map.set(loc.id, loc.name)\n return map\n }, [config.locations, storeLocations])\n\n const locationMap = useMemo(() => {\n if (!config.modules.locationSelection || allLocations.size === 0) return undefined\n return allLocations\n }, [config.modules.locationSelection, allLocations])\n\n const availabilityEvents = useMemo(() =>\n generateAvailabilityEvents(schedules, professionals, visibleRange, effectiveBusinessHours, locationMap),\n [schedules, professionals, visibleRange, effectiveBusinessHours, locationMap])\n\n const events = useMemo(() =>\n [...bookingEvents, ...availabilityEvents], [bookingEvents, availabilityEvents])\n\n const storedView = prefs.get('calendarView')\n const effectiveInitialView = resourceCapable ? viewForResources(storedView) : viewForNoResources(storedView)\n\n // ── Calendar handlers ──\n const handleDatesSet = useCallback((arg: { startStr: string; endStr: string; view: { title: string; type: string } }) => {\n setCalendarTitle(arg.view.title)\n setView(arg.view.type)\n setVisibleRange({ start: arg.startStr, end: arg.endStr })\n fetchBookings({ start: arg.startStr, end: arg.endStr })\n }, [fetchBookings, setView])\n\n // Double-click → open edit directly\n // Right-click → context menu\n const handleEventDidMount = useCallback((arg: { event: any; el: HTMLElement }) => {\n const booking = arg.event.extendedProps?.booking as CalendarBooking | undefined\n if (booking) arg.el.setAttribute('data-booking-id', booking.id)\n arg.el.addEventListener('dblclick', (e) => {\n e.preventDefault()\n e.stopPropagation()\n skipClickRef.current = true\n const booking = arg.event.extendedProps.booking as CalendarBooking\n setSelectedBooking(null)\n setPopoverAnchor(null)\n setContextMenu(null)\n openModal('edit', { bookingId: booking.id })\n })\n arg.el.addEventListener('contextmenu', (e) => {\n e.preventDefault()\n const booking = arg.event.extendedProps.booking as CalendarBooking\n const menuW = 210, menuH = 200\n let x = e.clientX + 4\n let y = e.clientY + 4\n if (x + menuW > window.innerWidth - 12) x = x - menuW\n if (y + menuH > window.innerHeight - 12) y = y - menuH\n setContextMenu({ booking, x, y })\n setContextMenuVisible(true)\n setSelectedBooking(null)\n setPopoverAnchor(null)\n })\n }, [])\n\n // Flag to suppress single-click after a double-click\n const skipClickRef = useRef(false)\n\n // Hover timer — show popover after 4s hover on a booking event\n const hoverTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const handleEventMouseEnter = useCallback((arg: { event: any; el: HTMLElement }) => {\n if (arg.event.display === 'background') return\n if (arg.event.extendedProps?.isLocationLabel) return\n const booking = arg.event.extendedProps.booking as CalendarBooking\n if (!booking) return\n\n hoverTimerRef.current = setTimeout(() => {\n const rect = arg.el.getBoundingClientRect()\n const popW = 320, popH = 340\n let x = rect.right + 8\n let y = rect.top + rect.height / 2 - popH / 2\n if (x + popW > window.innerWidth - 16) x = rect.left - popW - 8\n if (x < 16) x = Math.max(16, rect.left + rect.width / 2 - popW / 2)\n if (y + popH > window.innerHeight - 16) y = window.innerHeight - popH - 16\n if (y < 16) y = 16\n setSelectedBooking(booking)\n setPopoverAnchor({ x, y })\n setPopoverVisible(true)\n }, 3000)\n }, [])\n\n const handleEventMouseLeave = useCallback(() => {\n if (hoverTimerRef.current) {\n clearTimeout(hoverTimerRef.current)\n hoverTimerRef.current = null\n }\n }, [])\n\n // Single click — open popover instantly, or slide to new position if already open\n const handleEventClick = useCallback((arg: EventClickArg) => {\n if (skipClickRef.current) { skipClickRef.current = false; return }\n // Ignore clicks on background availability events and location labels\n if (arg.event.display === 'background') return\n if (arg.event.extendedProps?.isLocationLabel) return\n setContextMenu(null); setContextMenuVisible(false)\n const booking = arg.event.extendedProps.booking as CalendarBooking\n if (!booking) return\n const rect = arg.el.getBoundingClientRect()\n const popW = 320, popH = 340\n let x = rect.right + 8\n let y = rect.top + rect.height / 2 - popH / 2\n if (x + popW > window.innerWidth - 16) x = rect.left - popW - 8\n if (x < 16) x = Math.max(16, rect.left + rect.width / 2 - popW / 2)\n if (y + popH > window.innerHeight - 16) y = window.innerHeight - popH - 16\n if (y < 16) y = 16\n // Always update — if popover is already open it slides to the new position\n setSelectedBooking(booking)\n setPopoverAnchor({ x, y })\n setPopoverVisible(true)\n }, [])\n\n // Find the schedule block covering a given time slot for a professional\n const findScheduleForSlot = useCallback((professionalId: string | undefined, dateTimeStr: string): Schedule | null => {\n if (!professionalId) return null\n const dt = new Date(dateTimeStr)\n const dateStr = dt.toISOString().slice(0, 10)\n const dayOfWeek = dt.getDay()\n const timeMin = dt.getHours() * 60 + dt.getMinutes()\n\n const profSchedules = schedules.filter((s) => s.assigneeId === professionalId)\n const exceptions = profSchedules.filter((s) => s.specificDate === dateStr && s.isActive)\n const weekly = profSchedules.filter((s) => s.dayOfWeek === dayOfWeek && s.isActive && !s.specificDate)\n const daySchedules = exceptions.length > 0 ? exceptions : weekly\n\n for (const s of daySchedules) {\n const [sh, sm] = s.startsAt.split(':').map(Number)\n const [eh, em] = s.endsAt.split(':').map(Number)\n if (timeMin >= sh * 60 + sm && timeMin < eh * 60 + em) return s\n }\n return null\n }, [schedules])\n\n const handleSelect = useCallback((arg: DateSelectArg) => {\n calendarRef.current?.getApi().unselect()\n\n // Don't open create if popover/context menu is showing — dismiss them instead\n if (popoverVisibleRef.current || contextMenuVisibleRef.current) {\n setPopoverVisible(false); setSelectedBooking(null); setPopoverAnchor(null)\n setContextMenuVisible(false); setContextMenu(null)\n return\n }\n\n const professionalId = arg.resource?.id\n const schedule = findScheduleForSlot(professionalId, arg.startStr)\n\n const proceed = () => {\n const locId = schedule?.locationId ?? (schedule?.metadata?.locationId as string | undefined)\n openModal('create', { prefill: { startsAt: arg.startStr, endsAt: arg.endStr, professionalId, locationId: locId || undefined } })\n }\n\n // Warn if no schedule covers this slot — only when the working-hours module\n // is on (off by default in eventMode:'simple', so simple/Google-Calendar\n // events never surface the \"no open schedule for this professional\" dialog).\n if (config.modules.workingHours && !schedule) {\n setScheduleConfirm({ onConfirm: proceed })\n return\n }\n\n proceed()\n }, [openModal, findScheduleForSlot, config.modules.workingHours])\n\n const handleEventDrop = useCallback(async (arg: EventDropArg) => {\n const booking = arg.event.extendedProps.booking as CalendarBooking\n try { await rescheduleBooking(booking.id, arg.event.startStr, arg.event.endStr, arg.newResource?.id ?? undefined) }\n catch { arg.revert() }\n }, [rescheduleBooking])\n\n const handleViewChange = useCallback((v: string) => {\n calendarRef.current?.getApi().changeView(v)\n prefs.set('calendarView', v)\n }, [prefs])\n // Mobile switcher: swap between the list sentinel and a real grid view. When a\n // grid is picked we also sync the store's currentView so the resource-collapse\n // effect doesn't fight the freshly-mounted mobile calendar; if it's already\n // mounted (grid → grid), changeView animates in place.\n const handleMobileViewChange = useCallback((v: string) => {\n setMobileView(v)\n if (v === MOBILE_LIST_VIEW) return\n setView(v)\n calendarRef.current?.getApi()?.changeView(v)\n }, [setView])\n const handlePrev = useCallback(() => calendarRef.current?.getApi().prev(), [])\n const handleNext = useCallback(() => calendarRef.current?.getApi().next(), [])\n const handleToday = useCallback(() => { calendarRef.current?.getApi().today(); setSelectedDate(new Date()) }, [])\n\n function handleMiniDateSelect(date: Date) {\n setSelectedDate(date)\n calendarRef.current?.getApi().gotoDate(date)\n }\n\n function toggleProfessional(id: string) {\n const next = selectedProfIds.includes(id)\n ? selectedProfIds.filter((p) => p !== id)\n : [...selectedProfIds, id]\n setFilters({ professionalIds: next })\n }\n\n function toggleStatus(value: string) {\n const next = selectedStatuses.includes(value)\n ? selectedStatuses.filter((s) => s !== value)\n : [...selectedStatuses, value]\n setFilters({ statuses: next })\n }\n\n // Alternating resource backgrounds — apply via DOM after render\n const wrapperRef = useRef<HTMLDivElement>(null)\n\n // FullCalendar measures its columns once and only re-measures on a WINDOW\n // resize. Opening/closing the assistant rail (or the sidebar) resizes the\n // container without one, so the grid stayed locked at the narrow width until\n // a real window resize came along. Watch the container and hand FC the new box.\n useEffect(() => {\n const container = wrapperRef.current\n if (!container) return\n let frame = 0\n let lastWidth = container.clientWidth\n let lastHeight = container.clientHeight\n const ro = new ResizeObserver(() => {\n const width = container.clientWidth\n const height = container.clientHeight\n if (width === lastWidth && height === lastHeight) return\n lastWidth = width\n lastHeight = height\n // Next frame, not inline: measuring inside the observer callback reads a\n // mid-layout box (and trips the RO loop warning). The rail animates, so\n // this fires on each frame and the last one settles on the final width.\n cancelAnimationFrame(frame)\n frame = requestAnimationFrame(() => calendarRef.current?.getApi()?.updateSize())\n })\n ro.observe(container)\n return () => { cancelAnimationFrame(frame); ro.disconnect() }\n // Re-attach whenever the calendar branch remounts (skeleton → grid, mobile\n // list → grid), since the observed node is gone on the other branches.\n }, [isMobile, mobileGridActive, professionalsLoading, professionals.length])\n\n // Responsive day headers — collapse weekday names to a single initial (S M T\n // W T F S, Google-Calendar style) when day columns get too narrow. Measured\n // from the actual rendered column width so it adapts to resource count + view.\n const [dayHeaderCompact, setDayHeaderCompact] = useState(false)\n useEffect(() => {\n const container = wrapperRef.current\n if (!container) return\n let frame = 0\n const measure = () => {\n // Measure an actual DAY column ([data-date]) — in resource views the first\n // .fc-col-header-cell is the wide resource header, not a day column.\n const cell = container.querySelector('.fc-col-header-cell[data-date]') as HTMLElement | null\n if (!cell) return\n const colWidth = cell.getBoundingClientRect().width\n // Collapse to single-letter ONLY when the full weekday label can't fit.\n // Measure the widest full line (\"WED\" / \"12/14\") in the header's font so\n // the breakpoint adapts to font + locale instead of a magic number.\n const cushion = (cell.querySelector('.fc-col-header-cell-cushion') as HTMLElement | null) ?? cell\n const cs = getComputedStyle(cushion)\n const probe = document.createElement('span')\n probe.style.cssText = 'position:absolute;visibility:hidden;white-space:nowrap;top:-9999px'\n probe.style.fontSize = cs.fontSize\n probe.style.fontWeight = cs.fontWeight\n probe.style.fontFamily = cs.fontFamily\n probe.style.letterSpacing = cs.letterSpacing\n probe.style.textTransform = cs.textTransform\n document.body.appendChild(probe)\n probe.textContent = 'Wed'\n const weekdayWidth = probe.getBoundingClientRect().width\n probe.textContent = '12/14'\n const dateWidth = probe.getBoundingClientRect().width\n probe.remove()\n const needed = Math.max(weekdayWidth, dateWidth) + 12 // text + cushion padding\n setDayHeaderCompact(colWidth < needed)\n }\n // FullCalendar reflows its inner day columns on a later tick than the\n // container resize, so re-measure across a few frames to read settled widths.\n const timers: ReturnType<typeof setTimeout>[] = []\n const schedule = () => {\n cancelAnimationFrame(frame)\n frame = requestAnimationFrame(measure)\n timers.forEach(clearTimeout)\n timers.length = 0\n timers.push(setTimeout(measure, 130), setTimeout(measure, 330))\n }\n schedule()\n const ro = new ResizeObserver(schedule)\n ro.observe(container)\n return () => { cancelAnimationFrame(frame); timers.forEach(clearTimeout); ro.disconnect() }\n }, [resources, currentView, visibleRange])\n\n const applyResourceStriping = useCallback(() => {\n const container = wrapperRef.current\n if (!container) return\n const resourceIds = resources.map((r: { id: string }) => r.id)\n if (resourceIds.length < 2) return\n container.querySelectorAll('[data-resource-id]').forEach((el: Element) => {\n const rid = el.getAttribute('data-resource-id')\n const idx = rid ? resourceIds.indexOf(rid) : -1\n el.classList.toggle('fc-resource-alt', idx % 2 === 1)\n })\n }, [resources])\n\n useEffect(() => {\n applyResourceStriping()\n const t1 = setTimeout(applyResourceStriping, 100)\n const t2 = setTimeout(applyResourceStriping, 300)\n return () => { clearTimeout(t1); clearTimeout(t2) }\n }, [applyResourceStriping, currentView, visibleRange, bookings])\n\n // Listen for cross-plugin booking open requests (e.g., from financial invoice detail)\n useEffect(() => {\n function handleOpenBooking(e: Event) {\n const detail = (e as CustomEvent).detail ?? {}\n const externalSource = detail.source\n ? { type: String(detail.source), id: detail.waitlistId, waitlistId: detail.waitlistId }\n : undefined\n if (detail.bookingId) {\n openModal('edit', { bookingId: detail.bookingId, externalSource })\n return\n }\n openModal('create', {\n prefill: detail.prefill ?? {\n clientId: detail.clientId,\n professionalId: detail.professionalId,\n locationId: detail.locationId,\n startsAt: detail.startsAt,\n },\n externalSource,\n })\n }\n window.addEventListener('agenda:open-booking', handleOpenBooking)\n return () => window.removeEventListener('agenda:open-booking', handleOpenBooking)\n }, [openModal])\n\n // Custom day header: weekday + date stacked. When columns get narrow it\n // collapses the weekday to a single initial (S / 16, Google-Calendar style).\n // Always returns explicit content — returning undefined renders an EMPTY\n // header in the React adapter rather than falling back to the default.\n const dayHeaderContent = useCallback((arg: any) => {\n const date: Date = arg.date\n const dateLocale = currentLocale === 'pt-BR' ? 'pt-BR' : 'en'\n // Inline styles (not CSS classes) so stacking is guaranteed regardless of\n // the runtime style-injection state.\n const wrapStyle: React.CSSProperties = { display: 'flex', flexDirection: 'column', alignItems: 'center', lineHeight: 1.15 }\n const dateStyle: React.CSSProperties = { fontSize: '0.65rem', opacity: 0.75 }\n if (dayHeaderCompact) {\n const letter = date.toLocaleDateString(dateLocale, { weekday: 'narrow' })\n return (\n <div style={wrapStyle}>\n <span style={{ fontWeight: 600 }}>{letter}</span>\n <span style={dateStyle}>{date.getDate()}</span>\n </div>\n )\n }\n const weekday = date.toLocaleDateString(dateLocale, { weekday: 'short' })\n return (\n <div style={wrapStyle}>\n <span>{weekday}</span>\n <span style={dateStyle}>{`${date.getMonth() + 1}/${date.getDate()}`}</span>\n </div>\n )\n }, [dayHeaderCompact, currentLocale])\n\n const resourceLabelContent = useCallback((arg: any) => {\n const { id, title, extendedProps } = arg.resource\n const initials = title.split(' ').map((n: string) => n[0]).join('').slice(0, 2)\n return (\n <div className=\"flex items-center gap-2 px-2 py-1.5\">\n <div className=\"flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary/10 text-[10px] font-bold text-primary\">{initials}</div>\n <div className=\"min-w-0\">\n <PersonLink\n personId={id}\n name={title}\n size=\"sm\"\n tab=\"schedule\"\n profileHref={`#/registry/staff/${id}/schedule`}\n />\n {extendedProps?.locationName && <p className=\"text-[10px] text-muted-foreground truncate\">{extendedProps.locationName}</p>}\n </div>\n </div>\n )\n }, [])\n\n const eventContent = useCallback((arg: any) => {\n // Location label events — render as a small tag\n if (arg.event.extendedProps?.isLocationLabel) {\n return (\n <div className=\"px-1.5 py-0.5 overflow-hidden\">\n <p className=\"text-[10px] font-medium truncate\">{arg.event.title}</p>\n </div>\n )\n }\n const serviceNames = arg.event.extendedProps?.serviceNames\n const start = arg.event.start\n const end = arg.event.end\n const fmt = (d: Date) => `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`\n const timeRange = start && end ? `${fmt(start)} – ${fmt(end)}` : start ? fmt(start) : ''\n return (\n <div className=\"px-1.5 py-0.5 overflow-hidden leading-tight h-full\">\n <div className=\"flex items-start justify-between gap-1\">\n <p className=\"text-[11px] font-semibold truncate\">{arg.event.title}</p>\n {serviceNames && <p className=\"text-[10px] opacity-60 truncate shrink-0 max-w-[45%] text-right\">{serviceNames}</p>}\n </div>\n {timeRange && <p className=\"text-[9px] opacity-50\">{timeRange}</p>}\n </div>\n )\n }, [])\n\n return (\n <div className=\"flex h-[calc(100vh-7.5rem)]\">\n {/* ═══ LEFT SIDEBAR — hidden on mobile ═══ */}\n <div className=\"hidden md:flex w-[220px] shrink-0 flex-col overflow-y-auto py-4 px-3 mr-4\">\n {/* + Create button */}\n <button\n onClick={() => openModal('create')}\n className=\"flex items-center gap-2 rounded-button bg-primary text-primary-foreground border border-primary pl-3 pr-4 py-1.5 text-sm font-semibold hover:bg-primary/90 shadow-button-primary active:shadow-button-inset transition-all mb-6 w-fit\"\n >\n <Plus className=\"h-4 w-4\" />\n {t('agenda.sidebar.create')}\n </button>\n\n {/* Mini month calendar */}\n <MiniCalendar selectedDate={selectedDate} onDateSelect={handleMiniDateSelect} />\n\n {/* Agendas (professional filter) — hidden when no booking type uses a\n professional (e.g. eventMode:'simple'). */}\n {config.capabilities.professional && (<>\n <div className=\"h-px bg-border my-4\" />\n\n <button onClick={() => setProfSectionOpen((p) => !p)}\n className=\"flex items-center justify-between w-full text-xs font-medium text-muted-foreground hover:text-foreground py-1 transition-colors\">\n <span>Agendas</span>\n <ChevronDown className={`h-3.5 w-3.5 transition-transform ${profSectionOpen ? '' : '-rotate-90'}`} />\n </button>\n {profSectionOpen && (\n <div className=\"mt-1.5 space-y-0.5\">\n {professionals.map((prof) => {\n const active = selectedProfIds.length === 0 || selectedProfIds.includes(prof.id)\n return (\n <label key={prof.id} className=\"flex items-center gap-2.5 rounded px-1 py-1 cursor-pointer hover:bg-muted/50 transition-colors\">\n <span className={`flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border-2 transition-colors ${\n active ? 'border-primary bg-primary' : 'border-muted-foreground/30'\n }`}>\n {active && <svg className=\"h-2.5 w-2.5 text-primary-foreground\" viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/></svg>}\n </span>\n <span className={`text-xs truncate ${active ? 'text-foreground' : 'text-muted-foreground'}`}>{prof.name}</span>\n <input type=\"checkbox\" className=\"sr-only\" checked={active} onChange={() => toggleProfessional(prof.id)} />\n </label>\n )\n })}\n </div>\n )}\n </>)}\n\n {/* Status filter — hidden when no booking type uses a status workflow\n (e.g. eventMode:'simple'). */}\n {config.capabilities.status && (<>\n <div className=\"h-px bg-border my-4\" />\n\n <button onClick={() => setStatusSectionOpen((p) => !p)}\n className=\"flex items-center justify-between w-full text-xs font-medium text-muted-foreground hover:text-foreground py-1 transition-colors\">\n <span>Status</span>\n <ChevronDown className={`h-3.5 w-3.5 transition-transform ${statusSectionOpen ? '' : '-rotate-90'}`} />\n </button>\n {statusSectionOpen && (\n <div className=\"mt-1.5 space-y-0.5\">\n {config.statuses.map((st) => {\n const active = selectedStatuses.length === 0 || selectedStatuses.includes(st.value)\n return (\n <label key={st.value} className=\"flex items-center gap-2.5 rounded px-1 py-1 cursor-pointer hover:bg-muted/50 transition-colors\">\n <span className=\"flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border-2 transition-colors\"\n style={{ borderColor: active ? st.color : st.color + '40', backgroundColor: active ? st.color : 'transparent' }}>\n {active && <svg className=\"h-2.5 w-2.5 text-white\" viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/></svg>}\n </span>\n <span className={`text-xs ${active ? 'text-foreground' : 'text-muted-foreground'}`}>{st.label}</span>\n <input type=\"checkbox\" className=\"sr-only\" checked={active} onChange={() => toggleStatus(st.value)} />\n </label>\n )\n })}\n </div>\n )}\n </>)}\n </div>\n\n {/* ═══ MAIN AREA ═══ */}\n <div className=\"flex-1 flex flex-col min-w-0 overflow-hidden\">\n {/* Toolbar */}\n <div className=\"shrink-0 border-b\">\n {/* Row 1 — create + date nav + title (left), desktop switcher + settings\n (right). Extra right padding on mobile clears the transparent header's\n floating profile avatar, which otherwise overlaps the settings gear. */}\n <div className=\"flex items-center justify-between pl-4 pr-14 md:px-4 h-12\">\n <div className=\"flex items-center gap-3 min-w-0\">\n {/* Mobile create button */}\n <button onClick={() => openModal('create')}\n className=\"md:hidden flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground\">\n <Plus className=\"h-4 w-4\" />\n </button>\n\n {/* Date navigation drives the FullCalendar api — shown on desktop and,\n on mobile, only when a grid view is active (the list paginates\n itself, so it has no grid to page through). */}\n <div className={`${mobileGridActive ? 'flex' : 'hidden'} md:flex items-center gap-3`}>\n <button onClick={handleToday}\n className=\"rounded-md border px-3 py-1 text-sm font-medium hover:bg-muted bg-card shadow-button active:shadow-button-inset transition-colors\">\n {t('agenda.toolbar.today')}\n </button>\n <div className=\"flex items-center gap-0.5\">\n <button onClick={handlePrev} className=\"flex h-7 w-7 items-center justify-center rounded-full hover:bg-muted transition-colors\">\n <ChevronLeft className=\"h-4 w-4\" />\n </button>\n <button onClick={handleNext} className=\"flex h-7 w-7 items-center justify-center rounded-full hover:bg-muted transition-colors\">\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n <h1 className=\"text-base sm:text-lg font-normal truncate\">{isMobile && !mobileGridActive ? t('agenda.calendar.viewAgenda') : calendarTitle}</h1>\n </div>\n\n <div className=\"flex items-center gap-1 shrink-0\">\n <div className=\"hidden md:flex items-center gap-1\">\n {viewOptions.map((opt) => (\n <button key={opt.key} onClick={() => handleViewChange(opt.key)}\n className={`rounded-md px-3 py-1 text-sm transition-colors ${\n currentView === opt.key\n ? 'bg-primary/10 text-primary font-medium'\n : 'text-muted-foreground hover:bg-muted/50'\n }`}>\n {t(opt.labelKey)}\n </button>\n ))}\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => window.location.hash = '/settings/agenda'}\n title=\"Agenda Settings\"\n className=\"ml-1\"\n >\n <Settings className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n\n {/* Row 2 (mobile only) — compact segmented view switcher on its own row so\n it never collides with the floating avatar. Dia/Semana/Mês mount the\n calendar; Lista returns to the thumb-friendly agenda list. */}\n <div className=\"flex md:hidden items-center gap-1 overflow-x-auto px-3 pb-2\">\n {mobileViewOptions.map((opt) => (\n <button key={opt.key} onClick={() => handleMobileViewChange(opt.key)}\n className={`shrink-0 rounded-md px-3 py-1 text-sm transition-colors ${\n mobileView === opt.key\n ? 'bg-primary/10 text-primary font-medium'\n : 'text-muted-foreground hover:bg-muted/50'\n }`}>\n {t(opt.labelKey)}\n </button>\n ))}\n </div>\n </div>\n\n {/* Mobile list view → thumb-friendly agenda list; otherwise (desktop, or a\n mobile grid view the user switched to) → FullCalendar grid. */}\n {isMobile && !mobileGridActive ? (\n <AgendaMobileList\n bookings={bookings}\n statusColors={statusColors}\n currencyCode={config.currency.code}\n onSelect={(b) => openModal('edit', { bookingId: b.id })}\n />\n ) : professionalsLoading && professionals.length === 0 ? (\n <CalendarSkeleton profCount={2} />\n ) : (\n <div ref={wrapperRef} className=\"flex-1 overflow-hidden agenda-calendar\">\n <FullCalendar\n ref={calendarRef}\n plugins={[dayGridPlugin, timeGridPlugin, resourceTimeGridPlugin, interactionPlugin, listPlugin]}\n initialView={mobileGridActive ? mobileView : effectiveInitialView}\n schedulerLicenseKey=\"CC-Attribution-NonCommercial-NoDerivatives\"\n resources={resourceCapable ? resources : undefined}\n events={events}\n headerToolbar={false}\n locale={fcLocale}\n height=\"100%\"\n slotMinTime={effectiveBusinessHours.startTime + ':00'}\n slotMaxTime={effectiveBusinessHours.endTime + ':00'}\n slotDuration={{ minutes: config.slotDuration }}\n allDaySlot={false}\n nowIndicator={true}\n editable={config.modules.dragAndDrop}\n selectable={true}\n selectMirror={true}\n eventOverlap={false}\n datesSet={handleDatesSet}\n eventDidMount={handleEventDidMount}\n eventClick={handleEventClick}\n eventMouseEnter={handleEventMouseEnter}\n eventMouseLeave={handleEventMouseLeave}\n select={handleSelect}\n eventDrop={handleEventDrop}\n resourceLabelContent={resourceLabelContent}\n dayHeaderContent={dayHeaderContent}\n eventContent={eventContent}\n resourceOrder=\"title\"\n stickyHeaderDates={true}\n expandRows={false}\n eventTimeFormat={{ hour: '2-digit', minute: '2-digit', hour12: false }}\n slotLabelFormat={{ hour: '2-digit', minute: '2-digit', hour12: false }}\n />\n </div>\n )}\n </div>\n\n {/* Popover — stays mounted until animation finishes */}\n {selectedBooking && popoverAnchor && popoverVisible && (\n <AppointmentPopover booking={selectedBooking} position={popoverAnchor}\n onClose={() => {\n // Called AFTER the popover's exit animation finishes\n setPopoverVisible(false)\n setSelectedBooking(null)\n setPopoverAnchor(null)\n }}\n onEdit={(id) => {\n setPopoverVisible(false)\n setSelectedBooking(null)\n setPopoverAnchor(null)\n openModal('edit', { bookingId: id })\n }} />\n )}\n\n {/* Context Menu */}\n {contextMenu && (\n <EventContextMenu\n booking={contextMenu.booking}\n position={{ x: contextMenu.x, y: contextMenu.y }}\n onClose={() => { setContextMenuVisible(false); setContextMenu(null) }}\n onEdit={(id) => { setContextMenuVisible(false); setContextMenu(null); openModal('edit', { bookingId: id }) }}\n />\n )}\n\n {/* No-schedule confirm */}\n <ConfirmDialog\n open={!!scheduleConfirm}\n variant=\"warning\"\n title={t('agenda.calendar.noScheduleConfirm')}\n confirmLabel={t('common.confirm')}\n cancelLabel={t('common.cancel')}\n onConfirm={() => { const cb = scheduleConfirm?.onConfirm; setScheduleConfirm(null); cb?.() }}\n onCancel={() => setScheduleConfirm(null)}\n />\n\n {/* Modal — always mounted, Radix controls open/close animation */}\n <AppointmentModal\n open={modalState.open}\n mode={modalState.mode}\n bookingId={modalState.bookingId}\n prefill={modalState.prefill}\n initialTab={modalState.initialTab}\n externalSource={modalState.externalSource}\n onClose={closeModal}\n onCreated={(newId, source) => {\n if (config.onBookingCreated) {\n void Promise.resolve(config.onBookingCreated({ bookingId: newId, source })).catch((error: unknown) => {\n console.error('Failed to run agenda booking-created bridge', error)\n })\n }\n // After a short delay (let calendar re-render), find the event and show popover\n setTimeout(() => {\n const booking = bookings.find((b: CalendarBooking) => b.id === newId)\n if (!booking) return\n const el = document.querySelector(`[data-booking-id=\"${newId}\"]`) as HTMLElement | null\n if (el) {\n const rect = el.getBoundingClientRect()\n const popW = 320, popH = 340\n let x = rect.right + 8\n let y = rect.top + rect.height / 2 - popH / 2\n if (x + popW > window.innerWidth - 16) x = rect.left - popW - 8\n if (y + popH > window.innerHeight - 16) y = window.innerHeight - popH - 16\n if (y < 16) y = 16\n setSelectedBooking(booking)\n setPopoverAnchor({ x, y })\n setPopoverVisible(true)\n }\n }, 400)\n }} />\n </div>\n )\n}\n","let t: string | undefined\nexport function setAgendaTenantId(id: string | undefined){ t = id }\nexport function getAgendaTenantId(): string | undefined { return t }\n","import React from 'react'\nimport { usePluginRuntimeOptional } from '@fayz-ai/core'\nimport type { StoreApi } from 'zustand/vanilla'\nimport { AgendaContextProvider } from '../context'\nimport type { ResolvedAgendaConfig } from '../config'\nimport type { AgendaDataProvider } from '../data/types'\nimport type { AgendaUIState } from '../store'\nimport { CalendarView } from './CalendarView'\nimport { setAgendaTenantId } from '../lib/tenant'\n\n// ---------------------------------------------------------------------------\n// Main page — clean single-page calendar, no module nav wrapper\n// ---------------------------------------------------------------------------\n\nexport function AgendaPage({ config, provider, store }: {\n config: ResolvedAgendaConfig\n provider: AgendaDataProvider\n store: StoreApi<AgendaUIState>\n}) {\n const runtime = usePluginRuntimeOptional()\n const tenantId = runtime?.context.tenant?.id\n\n React.useEffect(() => {\n setAgendaTenantId(tenantId)\n return () => setAgendaTenantId(undefined)\n }, [tenantId])\n\n return (\n <AgendaContextProvider config={config} provider={provider} store={store}>\n <CalendarView />\n </AgendaContextProvider>\n )\n}\n","import type { AgendaDataProvider } from './types'\nimport type {\n CalendarBooking, Professional, Schedule, TimeSlot,\n CreateBookingInput, UpdateBookingInput, SaveScheduleInput,\n BookingQuery, ConflictCheckParams, AvailableSlotsParams, BookingStatus,\n} from '../types'\nimport { getSupabaseClientOptional, getActiveTenantId } from '@fayz-ai/core'\nimport { getAgendaTenantId } from '../lib/tenant'\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getTenantId(): string | undefined {\n // Plugin-local override wins; else fall back to the app's active tenant so\n // writes stamp the right tenant_id and pass orders/bookings RLS.\n return getAgendaTenantId() ?? getActiveTenantId()\n}\n\nfunction snakeToCamel(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj)) {\n result[key.replace(/_([a-z])/g, (_, c) => c.toUpperCase())] = value\n }\n return result\n}\n\nfunction getClients() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase not initialized')\n // Core v1 lives in PUBLIC — a single client serves both core and view reads.\n return { core: supabase, pub: supabase }\n}\n\nfunction mapBooking(row: Record<string, unknown>): CalendarBooking {\n return snakeToCamel(row) as unknown as CalendarBooking\n}\n\nfunction mapSchedule(row: Record<string, unknown>): Schedule {\n return snakeToCamel(row) as unknown as Schedule\n}\n\nfunction addMinutes(iso: string, minutes: number): string {\n const d = new Date(iso)\n d.setMinutes(d.getMinutes() + minutes)\n return d.toISOString()\n}\n\nfunction unique(values: Array<string | null | undefined>): string[] {\n return Array.from(new Set(values.filter((value): value is string => !!value)))\n}\n\nfunction indexById(rows: any[] | null | undefined): Map<string, any> {\n return new Map((rows ?? []).filter((row) => row?.id).map((row) => [row.id, row]))\n}\n\nfunction groupBy<T>(rows: T[], getKey: (row: T) => string | null | undefined): Map<string, T[]> {\n const grouped = new Map<string, T[]>()\n for (const row of rows) {\n const key = getKey(row)\n if (!key) continue\n grouped.set(key, [...(grouped.get(key) ?? []), row])\n }\n return grouped\n}\n\nfunction getDurationMinutes(startsAt: string, endsAt: string | null | undefined): number | null {\n if (!endsAt) return null\n return Math.round((new Date(endsAt).getTime() - new Date(startsAt).getTime()) / 60000)\n}\n\nfunction mergeBookings(viewBookings: CalendarBooking[], canonicalBookings: CalendarBooking[]): CalendarBooking[] {\n const canonicalIds = new Set(canonicalBookings.map((booking) => booking.id))\n const canonicalOrderIds = new Set(canonicalBookings.map((booking) => booking.orderId).filter(Boolean))\n const merged = [\n ...canonicalBookings,\n ...viewBookings.filter((booking) => {\n if (canonicalIds.has(booking.id)) return false\n if (booking.orderId && canonicalOrderIds.has(booking.orderId)) return false\n if (canonicalOrderIds.has(booking.id)) return false\n return true\n }),\n ]\n\n return merged.sort((a, b) => new Date(a.startsAt).getTime() - new Date(b.startsAt).getTime())\n}\n\nasync function hydrateCanonicalBookings(core: any, bookings: any[]): Promise<CalendarBooking[]> {\n const personIds = unique(bookings.flatMap((booking) => [booking.party_id, booking.assignee_id]))\n const locationIds = unique(bookings.map((booking) => booking.location_id))\n const orderIds = unique(bookings.map((booking) => booking.order_id))\n const bookingIds = unique(bookings.map((booking) => booking.id))\n\n const [\n { data: persons, error: personsError },\n { data: locations, error: locationsError },\n { data: orders, error: ordersError },\n { data: items, error: itemsError },\n ] = await Promise.all([\n personIds.length\n ? core.from('people').select('id, name, phone, email, avatar_url').in('id', personIds)\n : Promise.resolve({ data: [], error: null }),\n locationIds.length\n ? core.from('locations').select('id, name').in('id', locationIds)\n : Promise.resolve({ data: [], error: null }),\n orderIds.length\n ? core.from('orders').select('id, total, status').in('id', orderIds)\n : Promise.resolve({ data: [], error: null }),\n orderIds.length\n ? core.from('order_items').select('id, order_id, service_id, name, duration_minutes, unit_price, assignee_id, sort_order').in('order_id', orderIds)\n : Promise.resolve({ data: [], error: null }),\n ])\n\n if (personsError) throw personsError\n if (locationsError) throw locationsError\n if (ordersError) throw ordersError\n if (itemsError) throw itemsError\n\n const personsById = indexById(persons)\n const locationsById = indexById(locations)\n const ordersById = indexById(orders)\n // S4: line items come from order_items (single source), keyed by order_id.\n const itemsByOrderId = groupBy(items ?? [], (item: any) => item.order_id)\n\n return bookings.map((booking) => {\n const client = booking.party_id ? personsById.get(booking.party_id) : null\n const professional = booking.assignee_id ? personsById.get(booking.assignee_id) : null\n const location = booking.location_id ? locationsById.get(booking.location_id) : null\n const order = booking.order_id ? ordersById.get(booking.order_id) : null\n const bookingItems = ((booking.order_id ? itemsByOrderId.get(booking.order_id) : null) ?? [])\n .sort((a: any, b: any) => (a.sort_order ?? 0) - (b.sort_order ?? 0))\n .map((item: any) => ({\n id: item.id,\n serviceId: item.service_id,\n name: item.name,\n durationMinutes: item.duration_minutes,\n price: item.unit_price,\n assigneeId: item.assignee_id,\n }))\n const itemDuration = bookingItems.reduce((sum: number, item: any) => sum + (item.durationMinutes ?? 0), 0)\n\n return {\n id: booking.id,\n tenantId: booking.tenant_id,\n kind: booking.kind,\n startsAt: booking.starts_at,\n endsAt: booking.ends_at,\n status: booking.status,\n notes: booking.notes,\n orderId: booking.order_id,\n locationId: booking.location_id,\n metadata: booking.metadata ?? {},\n clientId: booking.party_id,\n // Simple events (no party) fall back to the title stored in metadata;\n // partyless blocks/tasks (e.g. imported Google events) get their notes or\n // a kind label so the calendar never renders an unnamed chip.\n clientName: client?.name\n ?? (booking.metadata?.title as string | undefined)\n ?? (booking.kind === 'appointment'\n ? null\n : booking.notes || (booking.kind === 'task' ? 'Tarefa' : 'Bloqueio')),\n clientPhone: client?.phone ?? null,\n clientEmail: client?.email ?? null,\n clientAvatarUrl: client?.avatar_url ?? null,\n professionalId: booking.assignee_id,\n professionalName: professional?.name ?? null,\n professionalAvatarUrl: professional?.avatar_url ?? null,\n locationName: location?.name ?? null,\n orderTotal: order?.total ?? null,\n orderStatus: order?.status ?? null,\n services: bookingItems.length ? bookingItems : null,\n totalDurationMinutes: itemDuration || getDurationMinutes(booking.starts_at, booking.ends_at),\n createdAt: booking.created_at,\n updatedAt: booking.updated_at,\n } satisfies CalendarBooking\n })\n}\n\nasync function getCanonicalBookings(core: any, query: BookingQuery): Promise<CalendarBooking[]> {\n let q = core.from('appointments')\n .select('id, tenant_id, kind, starts_at, ends_at, status, notes, order_id, location_id, metadata, party_id, assignee_id, created_at, updated_at')\n .gte('starts_at', query.dateRange.start)\n .lte('starts_at', query.dateRange.end)\n\n if (query.kind) q = q.eq('kind', query.kind)\n if (query.statuses?.length) q = q.in('status', query.statuses)\n if (query.professionalIds?.length) q = q.in('assignee_id', query.professionalIds)\n if (query.locationId) q = q.eq('location_id', query.locationId)\n\n const { data, error } = await q.order('starts_at', { ascending: true })\n if (error) throw error\n return hydrateCanonicalBookings(core, data ?? [])\n}\n\nasync function getCanonicalBookingById(core: any, id: string): Promise<CalendarBooking | null> {\n const columns = 'id, tenant_id, kind, starts_at, ends_at, status, notes, order_id, location_id, metadata, party_id, assignee_id, created_at, updated_at'\n let { data, error } = await core.from('appointments').select(columns).eq('id', id).maybeSingle()\n if (error) throw error\n\n if (!data) {\n const fallback = await core.from('appointments').select(columns).eq('order_id', id).maybeSingle()\n if (fallback.error) throw fallback.error\n data = fallback.data\n }\n\n if (!data) return null\n const [booking] = await hydrateCanonicalBookings(core, [data])\n return booking ?? null\n}\n\n// ---------------------------------------------------------------------------\n// Supabase Agenda Provider\n// ---------------------------------------------------------------------------\n\nexport interface SupabaseAgendaProviderOptions {\n /** people.kind used for calendar resources/professionals (default 'staff' — schools use 'teacher'). */\n professionalKind?: string\n}\n\nexport function createSupabaseAgendaProvider(providerOptions?: SupabaseAgendaProviderOptions): AgendaDataProvider {\n const professionalKind = providerOptions?.professionalKind ?? 'staff'\n return {\n // v_appointments is in public schema (PostgREST default)\n async getBookings(query: BookingQuery): Promise<CalendarBooking[]> {\n const { core, pub } = getClients()\n let q = pub.from('v_appointments').select('*')\n .gte('starts_at', query.dateRange.start)\n .lte('starts_at', query.dateRange.end)\n\n if (query.kind) q = q.eq('kind', query.kind)\n if (query.statuses?.length) q = q.in('status', query.statuses)\n if (query.professionalIds?.length) q = q.in('professional_id', query.professionalIds)\n if (query.locationId) q = q.eq('location_id', query.locationId)\n\n q = q.order('starts_at', { ascending: true })\n\n const { data, error } = await q\n if (error) throw error\n const viewBookings = (data ?? []).map(mapBooking)\n const canonicalBookings = await getCanonicalBookings(core, query)\n return mergeBookings(viewBookings, canonicalBookings)\n },\n\n async getBookingById(id: string): Promise<CalendarBooking | null> {\n const { core, pub } = getClients()\n const { data, error } = await pub.from('v_appointments').select('*').eq('id', id).maybeSingle()\n if (error) throw error\n if (data) {\n const booking = mapBooking(data as Record<string, unknown>)\n // v_appointments is a FLAT read model — it exposes no line items. The\n // calendar list path merges in the canonical hydration (which carries\n // `services` from order_items), but this single-record lookup used by the\n // edit modal previously returned the bare view row. That dropped\n // `services`, so a booking whose type has `requiresServices` reopened with\n // an empty service list and kept the \"Update\" button permanently disabled\n // (canSubmit stayed false). Hydrate the line items here to stay consistent\n // with getBookings.\n if (booking.orderId) {\n const { data: items } = await core.from('order_items')\n .select('id, service_id, name, duration_minutes, unit_price, assignee_id, sort_order')\n .eq('order_id', booking.orderId)\n .order('sort_order', { ascending: true })\n if (items && items.length) {\n const services = items.map((item: any) => ({\n id: item.id,\n serviceId: item.service_id,\n name: item.name,\n durationMinutes: item.duration_minutes,\n price: item.unit_price,\n assigneeId: item.assignee_id,\n }))\n booking.services = services\n const itemDuration = services.reduce((sum: number, s: any) => sum + (s.durationMinutes ?? 0), 0)\n if (itemDuration) booking.totalDurationMinutes = itemDuration\n }\n }\n return booking\n }\n return getCanonicalBookingById(core, id)\n },\n\n async createBooking(input: CreateBookingInput): Promise<CalendarBooking> {\n const { core } = getClients()\n const tenantId = getTenantId()\n if (!tenantId) throw new Error('No active tenant')\n\n const hasServices = input.services.length > 0\n const totalDuration = input.services.reduce((sum, s) => sum + s.durationMinutes, 0)\n const totalPrice = input.services.reduce((sum, s) => sum + s.price, 0)\n const endsAt = addMinutes(input.startsAt, totalDuration || 30)\n const serviceNames = input.services.map((s: any) => s.name).join(', ')\n\n // Resolve client name for metadata (used by financial detail view)\n let contactName: string | undefined\n if (input.clientId) {\n const { data: person } = await core.from('people').select('name').eq('id', input.clientId).single()\n contactName = person?.name as string | undefined\n }\n\n // Simple / Google-Calendar-style events have no client party — persist the\n // free-text title in metadata so the read model can surface it as the name.\n const eventTitle = input.title?.trim() || undefined\n\n const { data: order, error: orderErr } = await core.from('orders').insert({\n tenant_id: tenantId,\n kind: input.kind ?? 'appointment',\n status: 'scheduled',\n party_id: input.clientId || null,\n assignee_id: input.professionalId || null,\n location_id: input.locationId ?? null,\n subtotal: totalPrice,\n total: totalPrice,\n notes: input.notes ?? null,\n metadata: {\n source: 'agenda',\n ...(serviceNames ? { serviceNames, itemsSummary: serviceNames } : {}),\n ...(contactName ? { contactName } : {}),\n ...(eventTitle ? { title: eventTitle } : {}),\n },\n }).select('id').single()\n if (orderErr) throw orderErr\n\n const { data: booking, error: bookingErr } = await core.from('appointments').insert({\n tenant_id: tenantId,\n kind: input.kind ?? 'appointment',\n party_id: input.clientId || null,\n assignee_id: input.professionalId || null,\n location_id: input.locationId ?? null,\n order_id: order.id,\n starts_at: input.startsAt,\n ends_at: endsAt,\n status: 'scheduled',\n notes: input.notes ?? null,\n metadata: {\n source: 'agenda',\n ...(serviceNames ? { serviceNames, itemsSummary: serviceNames } : {}),\n ...(contactName ? { contactName } : {}),\n ...(eventTitle ? { title: eventTitle } : {}),\n },\n }).select('id').single()\n if (bookingErr) throw bookingErr\n\n if (hasServices) {\n // S4: line items live ONLY in order_items now (booking_items deprecated).\n const orderItems = input.services.map((s, i) => ({\n order_id: order.id,\n service_id: s.serviceId,\n name: s.name,\n quantity: 1,\n unit_price: s.price,\n total: s.price,\n sort_order: i,\n duration_minutes: s.durationMinutes,\n assignee_id: s.assigneeId || input.professionalId || null,\n }))\n const { error: oiErr } = await core.from('order_items').insert(orderItems)\n if (oiErr) throw oiErr\n }\n\n const createdBooking = await this.getBookingById(booking.id)\n if (!createdBooking) throw new Error('Created booking did not resolve from agenda read model')\n return createdBooking\n },\n\n async updateBooking(id: string, data: UpdateBookingInput): Promise<CalendarBooking> {\n const { core } = getClients()\n const { data: existing, error: existingErr } = await core.from('appointments')\n .select('id, order_id, starts_at, assignee_id, metadata')\n .eq('id', id)\n .single()\n if (existingErr) throw existingErr\n\n const updates: Record<string, unknown> = {}\n if (data.startsAt) updates.starts_at = data.startsAt\n if (data.endsAt) updates.ends_at = data.endsAt\n // Simple-event title lives in metadata (no client party) — merge, don't clobber.\n if (data.title !== undefined) {\n updates.metadata = { ...(existing?.metadata as Record<string, unknown> ?? {}), title: data.title }\n }\n if (data.status) {\n // Only update the agenda status — never touch the financial stage\n updates.status = data.status\n }\n if (data.notes !== undefined) updates.notes = data.notes\n if (data.professionalId) updates.assignee_id = data.professionalId\n if (data.clientId) updates.party_id = data.clientId\n if (data.locationId) updates.location_id = data.locationId\n\n // Recalculate totals when services are updated\n if (data.services) {\n const totalDuration = data.services.reduce((s, svc) => s + svc.durationMinutes, 0)\n const totalPrice = data.services.reduce((s, svc) => s + svc.price, 0)\n // Recalculate ends_at from startsAt + total duration\n const startsAt = data.startsAt ?? (existing?.starts_at as string | undefined)\n if (startsAt) {\n const ends = new Date(new Date(startsAt).getTime() + totalDuration * 60000)\n updates.ends_at = ends.toISOString()\n }\n }\n\n const effectiveAssigneeId = data.professionalId ?? (existing?.assignee_id as string | null | undefined) ?? null\n\n const { error } = await core.from('appointments').update(updates).eq('id', id)\n if (error) throw error\n\n // S4: services are updated only in order_items below (booking_items deprecated).\n const orderId = existing?.order_id as string | null | undefined\n if (orderId) {\n const orderUpdates: Record<string, unknown> = {}\n if (data.notes !== undefined) orderUpdates.notes = data.notes\n if (data.professionalId) orderUpdates.assignee_id = data.professionalId\n if (data.clientId) orderUpdates.party_id = data.clientId\n if (data.locationId) orderUpdates.location_id = data.locationId\n\n if (data.services) {\n const totalPrice = data.services.reduce((s, svc) => s + svc.price, 0)\n orderUpdates.subtotal = totalPrice\n orderUpdates.total = totalPrice\n }\n\n if (Object.keys(orderUpdates).length > 0) {\n const { error: orderErr } = await core.from('orders').update(orderUpdates).eq('id', orderId)\n if (orderErr) throw orderErr\n }\n\n if (data.services) {\n await core.from('order_items').delete().eq('order_id', orderId)\n if (data.services.length > 0) {\n const items = data.services.map((svc, idx) => ({\n order_id: orderId,\n service_id: svc.serviceId || null,\n name: svc.name,\n quantity: 1,\n unit_price: svc.price,\n total: svc.price,\n sort_order: idx,\n duration_minutes: svc.durationMinutes,\n assignee_id: svc.assigneeId ?? effectiveAssigneeId,\n }))\n const { error: itemErr } = await core.from('order_items').insert(items)\n if (itemErr) throw itemErr\n }\n }\n }\n\n return (await this.getBookingById(id))!\n },\n\n async deleteBooking(id: string): Promise<void> {\n const { core, pub } = getClients()\n const { data: booking, error: bookingErr } = await core.from('appointments')\n .select('order_id')\n .eq('id', id)\n .single()\n if (bookingErr) throw bookingErr\n\n const orderId = booking?.order_id as string | null | undefined\n // Financial movements live in the financial plugin's tables. Pools that\n // don't provision that plugin (e.g. school/event agendas) have no\n // plg_financial_movements table, and the probe below returns a PostgREST\n // \"relation does not exist\" error. Previously that error was rethrown,\n // which aborted the ENTIRE delete — the modal caught it and left the\n // booking in place, so \"Delete\" looked like a silent no-op (works in\n // beauty, which has the table; fails in school, which doesn't). Treat any\n // probe failure as \"no linked movements\" and fall through to a plain delete.\n let movementCount = 0\n if (orderId) {\n const { count, error: movementErr } = await pub\n .from('plg_financial_movements')\n .select('id', { count: 'exact', head: true })\n .eq('invoice_id', orderId)\n if (!movementErr) movementCount = count ?? 0\n }\n\n if (orderId && movementCount > 0) {\n // Cancel movements + order (don't delete financial records)\n await pub.from('plg_financial_movements').update({ status: 'cancelled' }).eq('invoice_id', orderId)\n await core.from('orders').update({ status: 'cancelled' }).eq('id', orderId)\n const { error } = await core.from('appointments').update({ status: 'cancelled' }).eq('id', id)\n if (error) throw error\n } else {\n // Safe to delete — remove any movements first (FK constraint)\n if (orderId) {\n await pub.from('plg_financial_movements').delete().eq('invoice_id', orderId)\n }\n const { error } = await core.from('appointments').delete().eq('id', id)\n if (error) throw error\n if (orderId) {\n const { error: orderErr } = await core.from('orders').delete().eq('id', orderId)\n if (orderErr) throw orderErr\n }\n }\n },\n\n async updateBookingStatus(id: string, status: string): Promise<CalendarBooking> {\n return this.updateBooking(id, { status: status as BookingStatus })\n },\n\n async checkConflict(params: ConflictCheckParams): Promise<boolean> {\n const { core } = getClients()\n let q = core.from('appointments').select('id', { count: 'exact', head: true })\n .eq('assignee_id', params.assigneeId)\n .eq('kind', 'appointment')\n .not('status', 'in', '(\"cancelled\",\"no_show\")')\n .not('starts_at', 'is', null)\n .lt('starts_at', params.endsAt)\n .gt('ends_at', params.startsAt)\n\n if (params.excludeBookingId) {\n q = q.neq('id', params.excludeBookingId)\n }\n\n const { count, error } = await q\n if (error) throw error\n return (count ?? 0) > 0\n },\n\n async getAvailableSlots(params: AvailableSlotsParams): Promise<TimeSlot[]> {\n const { pub } = getClients()\n const { data, error } = await pub.rpc('get_available_slots', {\n p_tenant_id: getTenantId(),\n p_assignee_id: params.assigneeId,\n p_date: params.date,\n p_duration_minutes: params.durationMinutes,\n p_slot_interval: params.slotInterval ?? 30,\n })\n if (error) throw error\n return (data ?? []).map((row: any) => ({ start: row.slot_start, end: row.slot_end }))\n },\n\n async getSchedules(professionalId?: string): Promise<Schedule[]> {\n const { core } = getClients()\n let q = core.from('schedules').select('*').eq('kind', 'working_hours')\n if (professionalId) q = q.eq('assignee_id', professionalId)\n q = q.order('day_of_week').order('starts_at')\n\n const { data, error } = await q\n if (error) throw error\n return (data ?? []).map(mapSchedule)\n },\n\n async saveSchedule(input: SaveScheduleInput): Promise<Schedule> {\n const { core } = getClients()\n const tenantId = getTenantId()\n if (!tenantId) throw new Error('No active tenant')\n\n const { data, error } = await core.from('schedules').insert({\n tenant_id: tenantId,\n kind: 'working_hours',\n assignee_id: input.assigneeId,\n location_id: input.locationId ?? null,\n day_of_week: input.dayOfWeek ?? null,\n specific_date: input.specificDate ?? null,\n starts_at: input.startsAt,\n ends_at: input.endsAt,\n is_active: input.isActive !== false,\n metadata: input.metadata ?? {},\n }).select('*').single()\n if (error) throw error\n return mapSchedule(data as Record<string, unknown>)\n },\n\n async deleteSchedule(id: string): Promise<void> {\n const { core } = getClients()\n const { error } = await core.from('schedules').delete().eq('id', id)\n if (error) throw error\n },\n\n async getProfessionals(): Promise<Professional[]> {\n const { core } = getClients()\n const { data, error } = await core.from('people')\n .select('id, name, avatar_url, is_active')\n .eq('kind', professionalKind)\n .eq('is_active', true)\n .order('name')\n if (error) throw error\n return (data ?? []).map((p: any) => ({\n id: p.id, name: p.name, avatarUrl: p.avatar_url,\n locationId: null, locationName: null, isActive: p.is_active,\n }))\n },\n\n async getLocations(): Promise<Array<{ id: string; name: string }>> {\n const { core } = getClients()\n const { data, error } = await core.from('locations')\n .select('id, name')\n .eq('is_active', true)\n .order('name')\n if (error) throw error\n return (data ?? []).map((l: any) => ({ id: l.id, name: l.name }))\n },\n\n async getConfirmationsPending(daysAhead = 2): Promise<CalendarBooking[]> {\n const { pub } = getClients()\n const now = new Date().toISOString()\n const cutoff = new Date()\n cutoff.setDate(cutoff.getDate() + daysAhead)\n\n const { data, error } = await pub.from('v_appointments').select('*')\n .eq('status', 'scheduled')\n .gte('starts_at', now)\n .lte('starts_at', cutoff.toISOString())\n .order('starts_at')\n if (error) throw error\n return (data ?? []).map(mapBooking)\n },\n\n async sendConfirmation(bookingId: string, channel: string): Promise<void> {\n const { core } = getClients()\n const { data: booking } = await core.from('appointments').select('metadata').eq('id', bookingId).single()\n const metadata = (booking?.metadata ?? {}) as Record<string, unknown>\n const confirmations = (metadata.confirmations as any[] ?? [])\n confirmations.push({ channel, sentAt: new Date().toISOString(), status: 'sent' })\n await core.from('appointments').update({ metadata: { ...metadata, confirmations } }).eq('id', bookingId)\n },\n\n async completeBooking(bookingId: string): Promise<{ booking: CalendarBooking; orderId: string }> {\n const { core } = getClients()\n const { data: existing, error: existingErr } = await core.from('appointments')\n .select('order_id')\n .eq('id', bookingId)\n .single()\n if (existingErr) throw existingErr\n\n const { error } = await core.from('appointments')\n .update({ status: 'completed' })\n .eq('id', bookingId)\n if (error) throw error\n\n const orderId = existing?.order_id as string | null | undefined\n const booking = await this.getBookingById(bookingId)\n if (!booking) throw new Error('Booking not found')\n return { booking, orderId: orderId ?? bookingId }\n },\n }\n}\n","import { createStore, type StoreApi } from 'zustand/vanilla'\nimport { emitDataChanged } from '@fayz-ai/core'\nimport { dedup } from '@fayz-ai/admin'\nimport { toast } from '@fayz-ai/ui'\nimport { getScheduleBlockConfig, setScheduleBlockConfig } from '@fayz-ai/admin'\nimport type { AgendaDataProvider } from './data/types'\nimport type { AgendaFinancialBridge } from './bridges/financial-bridge'\nimport type { ExternalBookingSource } from './config'\nimport type {\n CalendarBooking, Professional, Schedule,\n CreateBookingInput, UpdateBookingInput, BookingQuery,\n} from './types'\n\n// ---------------------------------------------------------------------------\n// Store state\n// ---------------------------------------------------------------------------\n\nexport interface AgendaUIState {\n // Calendar data\n bookings: CalendarBooking[]\n bookingsLoading: boolean\n dateRange: { start: string; end: string }\n currentView: string\n selectedDate: string\n\n // Resources\n professionals: Professional[]\n professionalsLoading: boolean\n\n // Filters\n selectedProfessionalIds: string[]\n selectedLocationId: string | null\n selectedStatuses: string[]\n\n // Locations\n locations: Array<{ id: string; name: string }>\n\n // Schedules\n schedules: Schedule[]\n schedulesLoading: boolean\n\n // Confirmations\n pendingConfirmations: CalendarBooking[]\n confirmationsLoading: boolean\n\n // Modal state\n appointmentModal: {\n open: boolean\n mode: 'create' | 'edit'\n bookingId?: string\n prefill?: Partial<CreateBookingInput> & { endsAt?: string }\n initialTab?: string\n externalSource?: ExternalBookingSource\n }\n\n // Actions\n fetchBookings(range: { start: string; end: string }): Promise<void>\n fetchProfessionals(): Promise<void>\n fetchLocations(): Promise<void>\n fetchSchedules(professionalId?: string): Promise<void>\n fetchConfirmations(): Promise<void>\n createBooking(input: CreateBookingInput): Promise<CalendarBooking>\n updateBooking(id: string, data: UpdateBookingInput): Promise<CalendarBooking>\n deleteBooking(id: string): Promise<void>\n updateBookingStatus(id: string, status: string): Promise<void>\n rescheduleBooking(id: string, newStart: string, newEnd: string, newProfessionalId?: string): Promise<void>\n setFilters(filters: Partial<{ professionalIds: string[]; locationId: string | null; statuses: string[] }>): void\n setView(view: string): void\n setSelectedDate(date: string): void\n openAppointmentModal(mode: 'create' | 'edit', options?: { bookingId?: string; prefill?: Partial<CreateBookingInput> & { endsAt?: string }; initialTab?: string; externalSource?: ExternalBookingSource }): void\n closeAppointmentModal(): void\n}\n\n// ---------------------------------------------------------------------------\n// Store factory\n// ---------------------------------------------------------------------------\n\nfunction getCurrentBookingQuery(state: AgendaUIState, dateRange = state.dateRange): BookingQuery {\n return {\n dateRange,\n professionalIds: state.selectedProfessionalIds.length ? state.selectedProfessionalIds : undefined,\n locationId: state.selectedLocationId ?? undefined,\n statuses: state.selectedStatuses.length ? state.selectedStatuses : undefined,\n }\n}\n\nexport function createAgendaStore(provider: AgendaDataProvider, financialBridge?: AgendaFinancialBridge): StoreApi<AgendaUIState> {\n return createStore<AgendaUIState>((set, get) => ({\n bookings: [],\n bookingsLoading: false,\n dateRange: { start: '', end: '' },\n currentView: 'resourceTimeGridDay',\n selectedDate: new Date().toISOString().slice(0, 10),\n\n professionals: [],\n professionalsLoading: false,\n\n selectedProfessionalIds: [],\n selectedLocationId: null,\n selectedStatuses: ['scheduled', 'confirmed', 'in_progress', 'completed'],\n\n locations: [],\n\n schedules: [],\n schedulesLoading: false,\n\n pendingConfirmations: [],\n confirmationsLoading: false,\n\n appointmentModal: { open: false, mode: 'create' },\n\n async fetchBookings(range) {\n const key = `agenda:bookings:${range.start}:${range.end}`\n return dedup(key, async () => {\n set({ bookingsLoading: true, dateRange: range })\n const state = get()\n const query = getCurrentBookingQuery(state, range)\n let bookings = await provider.getBookings(query)\n\n // Enrich with payment status if financial bridge is available\n if (financialBridge) {\n const orderIds = bookings.map((b) => b.orderId).filter((id): id is string => !!id)\n if (orderIds.length > 0) {\n try {\n const statuses = await financialBridge.resolvePaymentStatuses(orderIds)\n bookings = bookings.map((b) => {\n if (!b.orderId) return b\n const summary = statuses.get(b.orderId)\n return summary ? { ...b, paymentStatus: summary.status } : b\n })\n } catch { /* non-blocking */ }\n }\n }\n\n set({ bookings, bookingsLoading: false })\n })\n },\n\n async fetchProfessionals() {\n return dedup('agenda:professionals', async () => {\n set({ professionalsLoading: true })\n const professionals = await provider.getProfessionals()\n set({ professionals, professionalsLoading: false })\n })\n },\n\n async fetchLocations() {\n return dedup('agenda:locations', async () => {\n if (!provider.getLocations) return\n const locations = await provider.getLocations()\n set({ locations })\n // Update global schedule block config so ScheduleEditor picks up locations\n const current = getScheduleBlockConfig()\n if (current) {\n setScheduleBlockConfig({ ...current, locations })\n }\n })\n },\n\n async fetchSchedules(professionalId) {\n return dedup('agenda:schedules:' + (professionalId ?? 'all'), async () => {\n set({ schedulesLoading: true })\n const schedules = await provider.getSchedules(professionalId)\n set({ schedules, schedulesLoading: false })\n })\n },\n\n async fetchConfirmations() {\n return dedup('agenda:confirmations', async () => {\n set({ confirmationsLoading: true })\n const pendingConfirmations = await provider.getConfirmationsPending()\n set({ pendingConfirmations, confirmationsLoading: false })\n })\n },\n\n async createBooking(input) {\n try {\n const booking = await provider.createBooking(input)\n // Refresh bookings for current range\n const state = get()\n if (state.dateRange.start && state.dateRange.end) {\n const bookings = await provider.getBookings(getCurrentBookingQuery(state))\n set({ bookings })\n }\n emitDataChanged({ table: 'appointments', op: 'create', id: booking.id, source: 'ui' })\n toast.success('Appointment created')\n return booking\n } catch (err: any) {\n toast.error('Failed to create appointment', { description: err?.message })\n throw err\n }\n },\n\n async updateBooking(id, data) {\n try {\n const booking = await provider.updateBooking(id, data)\n const state = get()\n if (state.dateRange.start && state.dateRange.end) {\n const bookings = await provider.getBookings(getCurrentBookingQuery(state))\n set({ bookings })\n }\n emitDataChanged({ table: 'appointments', op: 'update', id, source: 'ui' })\n toast.success('Appointment updated')\n return booking\n } catch (err: any) {\n toast.error('Failed to update appointment', { description: err?.message })\n throw err\n }\n },\n\n async deleteBooking(id) {\n try {\n await provider.deleteBooking(id)\n const state = get()\n if (state.dateRange.start && state.dateRange.end) {\n const bookings = await provider.getBookings(getCurrentBookingQuery(state))\n set({ bookings })\n }\n emitDataChanged({ table: 'appointments', op: 'delete', id, source: 'ui' })\n toast.success('Appointment deleted')\n } catch (err: any) {\n toast.error('Failed to delete appointment', { description: err?.message })\n throw err\n }\n },\n\n async updateBookingStatus(id, status) {\n // Optimistic update — change color immediately\n const prev = get().bookings\n set({ bookings: prev.map((b) => b.id === id ? { ...b, status: status as any } : b) })\n try {\n await provider.updateBookingStatus(id, status)\n // Refresh from server to get full data\n const state = get()\n if (state.dateRange.start && state.dateRange.end) {\n const bookings = await provider.getBookings(getCurrentBookingQuery(state))\n set({ bookings })\n }\n emitDataChanged({ table: 'appointments', op: 'update', id, source: 'ui' })\n toast.success('Status updated')\n } catch (err: any) {\n // Rollback on failure\n set({ bookings: prev })\n toast.error('Failed to update status', { description: err?.message })\n throw err\n }\n },\n\n async rescheduleBooking(id, newStart, newEnd, newProfessionalId) {\n try {\n // Check for conflicts\n const existing = get().bookings.find((b) => b.id === id)\n const assigneeId = newProfessionalId ?? existing?.professionalId\n if (assigneeId) {\n const hasConflict = await provider.checkConflict({\n assigneeId,\n startsAt: newStart,\n endsAt: newEnd,\n excludeBookingId: id,\n })\n if (hasConflict) {\n toast.error('Time conflict detected', { description: 'This professional already has an appointment at this time.' })\n throw new Error('Time conflict')\n }\n }\n await provider.updateBooking(id, {\n startsAt: newStart,\n endsAt: newEnd,\n ...(newProfessionalId && { professionalId: newProfessionalId }),\n })\n const state = get()\n if (state.dateRange.start && state.dateRange.end) {\n const bookings = await provider.getBookings(getCurrentBookingQuery(state))\n set({ bookings })\n }\n toast.success('Appointment rescheduled')\n } catch (err: any) {\n if (err?.message !== 'Time conflict') {\n toast.error('Failed to reschedule', { description: err?.message })\n }\n throw err\n }\n },\n\n setFilters(filters) {\n set({\n ...(filters.professionalIds !== undefined && { selectedProfessionalIds: filters.professionalIds }),\n ...(filters.locationId !== undefined && { selectedLocationId: filters.locationId }),\n ...(filters.statuses !== undefined && { selectedStatuses: filters.statuses }),\n })\n // Re-fetch with new filters\n const { dateRange } = get()\n if (dateRange.start && dateRange.end) {\n get().fetchBookings(dateRange)\n }\n },\n\n setView(view) { set({ currentView: view }) },\n setSelectedDate(date) { set({ selectedDate: date }) },\n\n openAppointmentModal(mode, options) {\n set({ appointmentModal: { open: true, mode, bookingId: options?.bookingId, prefill: options?.prefill, initialTab: options?.initialTab, externalSource: options?.externalSource } })\n },\n\n closeAppointmentModal() {\n // Only toggle open — keep mode/bookingId/prefill intact so layout\n // doesn't shift during the close animation\n set((state) => ({ appointmentModal: { ...state.appointmentModal, open: false } }))\n },\n }))\n}\n","import type { PluginRegistryDef } from '@fayz-ai/core'\nimport type { EntityDef } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Holidays (public.holidays — tenant-scoped)\n// ---------------------------------------------------------------------------\n\nconst holidayEntity: EntityDef = {\n name: 'Holiday',\n namePlural: 'Holidays',\n icon: 'TreePalm',\n displayField: 'name',\n defaultSort: 'date',\n defaultSortDir: 'asc',\n fields: [\n { key: 'name', label: 'Name', type: 'text', required: true, showInTable: true },\n { key: 'date', label: 'Date', type: 'date', required: true, showInTable: true, sortable: true },\n { key: 'recurring', label: 'Recurring Annually', type: 'boolean', showInTable: true, defaultValue: false },\n { key: 'description', label: 'Description', type: 'text', showInTable: false },\n { key: 'isActive', label: 'Active', type: 'boolean', showInTable: true, defaultValue: true },\n ],\n data: {\n table: 'holidays',\n tenantScoped: true,\n },\n}\n\nexport const agendaRegistries: PluginRegistryDef[] = [\n {\n id: 'holidays',\n entity: holidayEntity,\n icon: 'TreePalm',\n description: 'Non-working days and recurring holidays',\n },\n]\n","import React from 'react'\nimport { SettingsGroup, ToggleRow, SelectRow, useTenantPluginSettings } from '@fayz-ai/admin'\nimport { useTranslation } from '@fayz-ai/core'\nimport { useAgendaSettings } from '../hooks/useAgendaSettings'\n\nconst HOUR_OPTIONS = Array.from({ length: 18 }, (_, i) => {\n const h = (5 + i).toString().padStart(2, '0')\n return { value: `${h}:00`, label: `${h}:00` }\n})\n\n// Per-tenant toggle defaults = the values that used to be hardcoded here.\n// NOTE: these are persisted + re-hydrated per tenant; actually consuming them to\n// change agenda behaviour is a follow-up (see useTenantPluginSettings docs).\nconst AGENDA_TOGGLE_DEFAULTS = {\n conflictDetection: true,\n dragDrop: true,\n autoCreateOrder: true,\n enableLocation: false,\n enableWorkingHours: true,\n blockOutside: false,\n enableConfirmations: true,\n autoConfirm: false,\n reminder: true,\n showCancelled: false,\n showNoShow: true,\n compact: false,\n newBookingNotif: true,\n cancelAlerts: true,\n noShowTracking: false,\n}\n\nexport function AgendaGeneralSettings() {\n const t = useTranslation()\n const { startTime, endTime, setStartTime, setEndTime } = useAgendaSettings()\n const s = useTenantPluginSettings('agenda', AGENDA_TOGGLE_DEFAULTS)\n return (\n <div className=\"space-y-4\">\n <SettingsGroup title={t('agenda.settings.scheduling')} description={t('agenda.settings.schedulingDesc')}>\n <ToggleRow label={t('agenda.settings.conflictDetection')} description={t('agenda.settings.conflictDetectionDesc')} checked={s.get('conflictDetection')} onChange={(v) => s.set('conflictDetection', v)} />\n <ToggleRow label={t('agenda.settings.dragDrop')} description={t('agenda.settings.dragDropDesc')} checked={s.get('dragDrop')} onChange={(v) => s.set('dragDrop', v)} />\n <ToggleRow label={t('agenda.settings.autoCreateOrder')} description={t('agenda.settings.autoCreateOrderDesc')} checked={s.get('autoCreateOrder')} onChange={(v) => s.set('autoCreateOrder', v)} />\n </SettingsGroup>\n\n <SettingsGroup title={t('agenda.settings.locations')} description={t('agenda.settings.locationsDesc')}>\n <ToggleRow label={t('agenda.settings.enableLocation')} description={t('agenda.settings.enableLocationDesc')} checked={s.get('enableLocation')} onChange={(v) => s.set('enableLocation', v)} />\n </SettingsGroup>\n\n <SettingsGroup title={t('agenda.settings.workingHours')} description={t('agenda.settings.workingHoursDesc')}>\n <ToggleRow label={t('agenda.settings.enableWorkingHours')} description={t('agenda.settings.enableWorkingHoursDesc')} checked={s.get('enableWorkingHours')} onChange={(v) => s.set('enableWorkingHours', v)} />\n <ToggleRow label={t('agenda.settings.blockOutside')} description={t('agenda.settings.blockOutsideDesc')} checked={s.get('blockOutside')} onChange={(v) => s.set('blockOutside', v)} />\n </SettingsGroup>\n\n <SettingsGroup title={t('agenda.settings.confirmations')} description={t('agenda.settings.confirmationsDesc')}>\n <ToggleRow label={t('agenda.settings.enableConfirmations')} description={t('agenda.settings.enableConfirmationsDesc')} checked={s.get('enableConfirmations')} onChange={(v) => s.set('enableConfirmations', v)} />\n <ToggleRow label={t('agenda.settings.autoConfirm')} description={t('agenda.settings.autoConfirmDesc')} checked={s.get('autoConfirm')} onChange={(v) => s.set('autoConfirm', v)} />\n <ToggleRow label={t('agenda.settings.reminder')} description={t('agenda.settings.reminderDesc')} checked={s.get('reminder')} onChange={(v) => s.set('reminder', v)} />\n </SettingsGroup>\n\n <SettingsGroup title={t('agenda.settings.calendarDisplay')} description={t('agenda.settings.calendarDisplayDesc')}>\n <SelectRow\n label={t('agenda.settings.dayStartTime')}\n description={t('agenda.settings.dayStartTimeDesc')}\n value={startTime}\n options={HOUR_OPTIONS}\n onChange={setStartTime}\n />\n <SelectRow\n label={t('agenda.settings.dayEndTime')}\n description={t('agenda.settings.dayEndTimeDesc')}\n value={endTime}\n options={HOUR_OPTIONS}\n onChange={setEndTime}\n />\n <ToggleRow label={t('agenda.settings.showCancelled')} description={t('agenda.settings.showCancelledDesc')} checked={s.get('showCancelled')} onChange={(v) => s.set('showCancelled', v)} />\n <ToggleRow label={t('agenda.settings.showNoShow')} description={t('agenda.settings.showNoShowDesc')} checked={s.get('showNoShow')} onChange={(v) => s.set('showNoShow', v)} />\n <ToggleRow label={t('agenda.settings.compact')} description={t('agenda.settings.compactDesc')} checked={s.get('compact')} onChange={(v) => s.set('compact', v)} />\n </SettingsGroup>\n\n <SettingsGroup title={t('agenda.settings.notifications')} description={t('agenda.settings.notificationsDesc')}>\n <ToggleRow label={t('agenda.settings.newBookingNotif')} description={t('agenda.settings.newBookingNotifDesc')} checked={s.get('newBookingNotif')} onChange={(v) => s.set('newBookingNotif', v)} />\n <ToggleRow label={t('agenda.settings.cancelAlerts')} description={t('agenda.settings.cancelAlertsDesc')} checked={s.get('cancelAlerts')} onChange={(v) => s.set('cancelAlerts', v)} />\n <ToggleRow label={t('agenda.settings.noShowTracking')} description={t('agenda.settings.noShowTrackingDesc')} checked={s.get('noShowTracking')} onChange={(v) => s.set('noShowTracking', v)} />\n </SettingsGroup>\n </div>\n )\n}\n","// agenda.* — merged plugin-own + saas-core central i18n\nexport const en: Record<string, string> = {\n \"agenda.appointment.addDescription\": \"Add description...\",\n \"agenda.appointment.addService\": \"Add service\",\n \"agenda.appointment.cancel\": \"Cancel\",\n \"agenda.appointment.clientTab\": \"Client\",\n \"agenda.appointment.noClientData\": \"No client data available\",\n \"agenda.appointment.client\": \"Client\",\n \"agenda.appointment.conflict\": \"Time conflict — this professional is already booked at this time.\",\n \"agenda.appointment.create\": \"Create\",\n \"agenda.appointment.createClientFailed\": \"Failed to create client\",\n \"agenda.appointment.creating\": \"Creating...\",\n \"agenda.appointment.delete\": \"Delete\",\n \"agenda.appointment.deleteConfirm\": \"Delete this appointment?\",\n \"agenda.appointment.confirmDelete\": \"Delete\",\n \"agenda.appointment.deleting\": \"Deleting…\",\n \"agenda.appointment.edit\": \"Edit Appointment\",\n \"agenda.appointment.emailOptional\": \"Email (optional)\",\n \"agenda.appointment.location\": \"Location\",\n \"agenda.appointment.name\": \"Name\",\n \"agenda.appointment.new\": \"New Appointment\",\n \"agenda.appointment.newClient\": \"New client\",\n \"agenda.appointment.notes\": \"Notes\",\n \"agenda.appointment.phone\": \"Phone\",\n \"agenda.appointment.professional\": \"Professional\",\n \"agenda.appointment.save\": \"Save\",\n \"agenda.appointment.saving\": \"Saving...\",\n \"agenda.appointment.searchClient\": \"Search client...\",\n \"agenda.appointment.searchService\": \"Search service to add...\",\n \"agenda.appointment.selectLocation\": \"Select location...\",\n \"agenda.appointment.selectProfessional\": \"Select professional...\",\n \"agenda.appointment.selectClientHint\": \"Select the client from the list or use New client to enable saving.\",\n \"agenda.appointment.services\": \"Services\",\n \"agenda.appointment.status\": \"Status\",\n \"agenda.appointment.to\": \"to\",\n \"agenda.appointment.total\": \"Total\",\n \"agenda.appointment.update\": \"Update\",\n \"agenda.payment.title\": \"Payment\",\n \"agenda.payment.generateInvoice\": \"Generate invoice\",\n \"agenda.payment.generating\": \"Generating…\",\n \"agenda.payment.pending\": \"Pending\",\n \"agenda.payment.partial\": \"Partial\",\n \"agenda.payment.paid\": \"Paid\",\n \"agenda.payment.collect\": \"Collect\",\n \"agenda.payment.overdue\": \"Overdue\",\n \"agenda.payment.cancelled\": \"Cancelled\",\n \"agenda.payment.none\": \"Payment\",\n \"agenda.payment.pay\": \"Pay\",\n \"agenda.payment.paying\": \"Paying…\",\n \"agenda.payment.remaining\": \"Remaining\",\n \"agenda.payment.installment\": \"Installment\",\n \"agenda.payment.total\": \"Total\",\n \"agenda.payment.noInvoice\": \"No invoice generated\",\n \"agenda.payment.selectAccount\": \"Select account\",\n \"agenda.payment.registerPayment\": \"Register payment\",\n \"agenda.payment.registerPaymentHint\": \"Record a payment for this appointment\",\n \"agenda.payment.pendingHint\": \"Invoice generated, awaiting payment\",\n \"agenda.payment.partialHint\": \"Partially paid, tap to complete\",\n \"agenda.payment.paidHint\": \"Payment completed\",\n \"agenda.payment.overdueHint\": \"Payment overdue\",\n \"agenda.payment.backToAppointment\": \"Back to appointment\",\n \"agenda.payment.checkout\": \"Confirm\",\n \"agenda.payment.checkingOut\": \"Processing…\",\n \"agenda.payment.serviceSummary\": \"Service summary\",\n \"agenda.payment.paymentMethod\": \"Payment method\",\n \"agenda.payment.noMethods\": \"No payment methods configured.\",\n \"agenda.payment.configureMethods\": \"Set up payment methods\",\n \"agenda.payment.checkoutComplete\": \"Payment confirmed\",\n \"agenda.payment.card\": \"Card\",\n \"agenda.payment.method\": \"Method\",\n \"agenda.payment.select\": \"Select…\",\n \"agenda.payment.cardBrand\": \"Brand\",\n \"agenda.payment.selectBrand\": \"Select brand…\",\n \"agenda.payment.cardInstallments\": \"Installments\",\n \"agenda.payment.bankAccount\": \"Account\",\n \"agenda.payment.viewInvoice\": \"View invoice details\",\n \"agenda.calendar.agendas\": \"Agendas\",\n \"agenda.calendar.create\": \"Create\",\n \"agenda.calendar.next\": \"Next\",\n \"agenda.calendar.previous\": \"Previous\",\n \"agenda.calendar.status\": \"Status\",\n \"agenda.calendar.today\": \"Today\",\n \"agenda.calendar.viewAgenda\": \"Agenda\",\n \"agenda.calendar.viewDay\": \"Day\",\n \"agenda.calendar.viewList\": \"List\",\n \"agenda.calendar.viewMonth\": \"Month\",\n \"agenda.calendar.viewWeek\": \"Week\",\n \"agenda.list.today\": \"Today\",\n \"agenda.list.tomorrow\": \"Tomorrow\",\n \"agenda.list.empty\": \"No upcoming items\",\n \"agenda.confirmations.confirmed\": \"Confirmed:\",\n \"agenda.confirmations.empty\": \"No pending confirmations\",\n \"agenda.confirmations.emptySubtitle\": \"All upcoming appointments have been confirmed\",\n \"agenda.confirmations.loading\": \"Loading...\",\n \"agenda.confirmations.subtitle\": \"Upcoming appointments pending confirmation\",\n \"agenda.confirmations.unknownClient\": \"Unknown client\",\n \"agenda.confirmations.sendWhatsApp\": \"Send WhatsApp\",\n \"agenda.confirmations.call\": \"Call\",\n \"agenda.confirmations.markConfirmed\": \"Mark Confirmed\",\n \"agenda.confirmations.markCancelled\": \"Mark Cancelled\",\n \"agenda.cancellation.loadingReasons\": \"Loading reasons...\",\n \"agenda.cancellation.notesOptional\": \"Cancellation notes (optional)\",\n \"agenda.cancellation.notesRequired\": \"Cancellation notes required\",\n \"agenda.cancellation.selectReason\": \"Select cancellation reason\",\n \"agenda.contextMenu.changeStatus\": \"Change status\",\n \"agenda.contextMenu.delete\": \"Delete\",\n \"agenda.contextMenu.edit\": \"Edit\",\n \"agenda.contextMenu.notAvailable\": \"(not available)\",\n \"agenda.index.settingsSubtitle\": \"Working hours, scheduling preferences, and confirmations\",\n \"agenda.index.settingsTitle\": \"Agenda Settings\",\n \"settings.plugin.agenda-working-hours\": \"Working Hours\",\n \"agenda.popover.unknown\": \"Unknown\",\n \"agenda.settings.autoConfirm\": \"Auto-confirm\",\n \"agenda.settings.autoConfirmDesc\": \"Automatically confirm new bookings\",\n \"agenda.settings.autoCreateOrder\": \"Auto-create Order\",\n \"agenda.settings.autoCreateOrderDesc\": \"Automatically create a financial order for new bookings\",\n \"agenda.settings.blockOutside\": \"Block Outside Hours\",\n \"agenda.settings.blockOutsideDesc\": \"Prevent bookings outside working hours\",\n \"agenda.settings.calendarDisplay\": \"Calendar Display\",\n \"agenda.settings.calendarDisplayDesc\": \"Visual settings for the calendar\",\n \"agenda.settings.cancelAlerts\": \"Cancellation Alerts\",\n \"agenda.settings.cancelAlertsDesc\": \"Notify when a booking is cancelled\",\n \"agenda.settings.compact\": \"Compact Mode\",\n \"agenda.settings.compactDesc\": \"Use smaller event blocks\",\n \"agenda.settings.confirmations\": \"Confirmations\",\n \"agenda.settings.confirmationsDesc\": \"Booking confirmation settings\",\n \"agenda.settings.conflictDetection\": \"Conflict Detection\",\n \"agenda.settings.conflictDetectionDesc\": \"Warn when bookings overlap\",\n \"agenda.settings.dragDrop\": \"Drag & Drop\",\n \"agenda.settings.dragDropDesc\": \"Allow rescheduling by dragging events\",\n \"agenda.settings.enableConfirmations\": \"Enable Confirmations\",\n \"agenda.settings.enableConfirmationsDesc\": \"Require confirmation for new bookings\",\n \"agenda.settings.enableLocation\": \"Enable Location Selection\",\n \"agenda.settings.enableLocationDesc\": \"Show location picker in booking modal\",\n \"agenda.settings.enableWorkingHours\": \"Enable Working Hours\",\n \"agenda.settings.enableWorkingHoursDesc\": \"Show working hours overlay on calendar\",\n \"agenda.settings.locations\": \"Locations\",\n \"agenda.settings.locationsDesc\": \"Multi-location settings\",\n \"agenda.settings.newBookingNotif\": \"New Booking Alerts\",\n \"agenda.settings.newBookingNotifDesc\": \"Notify when a new booking is created\",\n \"agenda.settings.noShowTracking\": \"No-show Tracking\",\n \"agenda.settings.noShowTrackingDesc\": \"Track and alert on no-shows\",\n \"agenda.settings.notifications\": \"Notifications\",\n \"agenda.settings.notificationsDesc\": \"Notification preferences\",\n \"agenda.settings.reminder\": \"Reminders\",\n \"agenda.settings.reminderDesc\": \"Send reminders before appointments\",\n \"agenda.settings.scheduling\": \"Scheduling\",\n \"agenda.settings.schedulingDesc\": \"Configure scheduling behavior\",\n \"agenda.settings.showCancelled\": \"Show Cancelled\",\n \"agenda.settings.showCancelledDesc\": \"Display cancelled bookings on calendar\",\n \"agenda.settings.showNoShow\": \"Show No-shows\",\n \"agenda.settings.showNoShowDesc\": \"Display no-show bookings on calendar\",\n \"agenda.settings.workingHours\": \"Working Hours\",\n \"agenda.settings.workingHoursDesc\": \"Working hours and availability\",\n \"agenda.sidebar.agendas\": \"Agendas\",\n \"agenda.sidebar.allLocations\": \"All locations\",\n \"agenda.sidebar.create\": \"Create\",\n \"agenda.sidebar.location\": \"Location\",\n \"agenda.sidebar.status\": \"Status\",\n \"agenda.toolbar.next\": \"Next\",\n \"agenda.toolbar.previous\": \"Previous\",\n \"agenda.toolbar.today\": \"Today\",\n \"agenda.workingHours.addBreak\": \"Add break\",\n \"agenda.workingHours.copyToAll\": \"Copy to all\",\n \"agenda.workingHours.dayOff\": \"Day off\",\n \"agenda.workingHours.removePeriod\": \"Remove period\",\n \"agenda.workingHours.professional\": \"Professional\",\n \"agenda.workingHours.save\": \"Save\",\n \"agenda.workingHours.saveFailed\": \"Failed to save\",\n \"agenda.workingHours.saved\": \"Working hours saved\",\n \"agenda.workingHours.saving\": \"Saving...\",\n \"agenda.workingHours.subtitle\": \"Manage working hours per professional\",\n \"agenda.workingHours.to\": \"to\",\n \"agenda.title\": \"Agenda\",\n \"agenda.calendar.title\": \"Calendar\",\n \"agenda.calendar.noScheduleConfirm\": \"This time slot has no open schedule for this professional. Do you want to book anyway?\",\n \"agenda.calendar.newAppointment\": \"New Appointment\",\n \"agenda.booking.create\": \"New Appointment\",\n \"agenda.booking.edit\": \"Edit Appointment\",\n \"agenda.booking.delete\": \"Delete Appointment\",\n \"agenda.booking.deleteConfirm\": \"Are you sure you want to delete this appointment?\",\n \"agenda.booking.client\": \"Client\",\n \"agenda.booking.professional\": \"Professional\",\n \"agenda.booking.services\": \"Services\",\n \"agenda.booking.date\": \"Date\",\n \"agenda.booking.time\": \"Time\",\n \"agenda.booking.duration\": \"Duration\",\n \"agenda.booking.notes\": \"Notes\",\n \"agenda.booking.status\": \"Status\",\n \"agenda.booking.save\": \"Save Appointment\",\n \"agenda.booking.saving\": \"Saving...\",\n \"agenda.confirmations.title\": \"Confirmations\",\n \"agenda.confirmations.pending\": \"Pending Confirmations\",\n \"agenda.confirmations.emptyDescription\": \"All upcoming appointments have been confirmed\",\n \"agenda.confirmations.confirm\": \"Confirm\",\n \"agenda.confirmations.cancel\": \"Cancel\",\n \"agenda.workingHours.title\": \"Working Hours\",\n \"agenda.workingHours.addPeriod\": \"Add period\",\n \"agenda.workingHours.loading\": \"Loading...\",\n \"agenda.appointment.addClient\": \"Add client\",\n \"agenda.appointment.addServiceFirst\": \"Add service\",\n \"agenda.appointment.addNotes\": \"Add notes\",\n \"agenda.appointment.duration\": \"Duration (minutes)\",\n \"agenda.appointment.price\": \"Price\",\n \"agenda.appointment.title\": \"Title\",\n \"agenda.appointment.addTitle\": \"Add a title\",\n \"agenda.appointment.untitled\": \"(no title)\",\n \"agenda.bookingType.appointment\": \"Appointment\",\n \"agenda.bookingType.event\": \"Event\",\n \"agenda.bookingType.task\": \"Task\",\n \"agenda.bookingType.out_of_office\": \"Out of Office\",\n \"agenda.bookingType.block\": \"Block\",\n \"agenda.settings.title\": \"Agenda Settings\",\n \"agenda.settings.slotDuration\": \"Slot Duration\",\n \"agenda.settings.bookingKind\": \"Booking Kind\",\n \"agenda.settings.dayStartTime\": \"Day Start Time\",\n \"agenda.settings.dayStartTimeDesc\": \"First hour shown on the calendar\",\n \"agenda.settings.dayEndTime\": \"Day End Time\",\n \"agenda.settings.dayEndTimeDesc\": \"Last hour shown on the calendar\",\n}\n","// agenda.* — merged plugin-own + saas-core central i18n\nexport const ptBR: Record<string, string> = {\n \"agenda.appointment.addDescription\": \"Adicionar descrição...\",\n \"agenda.appointment.addService\": \"Adicionar serviço\",\n \"agenda.appointment.cancel\": \"Cancelar\",\n \"agenda.appointment.clientTab\": \"Cliente\",\n \"agenda.appointment.noClientData\": \"Dados do cliente não disponíveis\",\n \"agenda.appointment.client\": \"Cliente\",\n \"agenda.appointment.conflict\": \"Conflito de horário — este profissional já está reservado neste horário.\",\n \"agenda.appointment.create\": \"Criar\",\n \"agenda.appointment.createClientFailed\": \"Falha ao criar cliente\",\n \"agenda.appointment.creating\": \"Criando...\",\n \"agenda.appointment.delete\": \"Excluir\",\n \"agenda.appointment.deleteConfirm\": \"Excluir este agendamento?\",\n \"agenda.appointment.confirmDelete\": \"Excluir\",\n \"agenda.appointment.deleting\": \"Excluindo…\",\n \"agenda.appointment.edit\": \"Editar Agendamento\",\n \"agenda.appointment.emailOptional\": \"E-mail (opcional)\",\n \"agenda.appointment.location\": \"Local\",\n \"agenda.appointment.name\": \"Nome\",\n \"agenda.appointment.new\": \"Novo Agendamento\",\n \"agenda.appointment.newClient\": \"Novo cliente\",\n \"agenda.appointment.notes\": \"Observações\",\n \"agenda.appointment.phone\": \"Telefone\",\n \"agenda.appointment.professional\": \"Profissional\",\n \"agenda.appointment.save\": \"Salvar\",\n \"agenda.appointment.saving\": \"Salvando...\",\n \"agenda.appointment.searchClient\": \"Buscar cliente...\",\n \"agenda.appointment.searchService\": \"Buscar serviço para adicionar...\",\n \"agenda.appointment.selectLocation\": \"Selecionar local...\",\n \"agenda.appointment.selectProfessional\": \"Selecionar profissional...\",\n \"agenda.appointment.selectClientHint\": \"Selecione o cliente na lista ou use Novo cliente para habilitar o salvamento.\",\n \"agenda.appointment.services\": \"Serviços\",\n \"agenda.appointment.status\": \"Status\",\n \"agenda.appointment.to\": \"até\",\n \"agenda.appointment.total\": \"Total\",\n \"agenda.appointment.update\": \"Atualizar\",\n \"agenda.payment.title\": \"Recebimento\",\n \"agenda.payment.generateInvoice\": \"Gerar recebimento\",\n \"agenda.payment.generating\": \"Gerando…\",\n \"agenda.payment.pending\": \"Pendente\",\n \"agenda.payment.partial\": \"Parcial\",\n \"agenda.payment.paid\": \"Pago\",\n \"agenda.payment.collect\": \"Receber\",\n \"agenda.payment.overdue\": \"Vencido\",\n \"agenda.payment.cancelled\": \"Cancelado\",\n \"agenda.payment.none\": \"Recebimento\",\n \"agenda.payment.pay\": \"Pagar\",\n \"agenda.payment.paying\": \"Pagando…\",\n \"agenda.payment.remaining\": \"Restante\",\n \"agenda.payment.installment\": \"Parcela\",\n \"agenda.payment.total\": \"Total\",\n \"agenda.payment.noInvoice\": \"Sem recebimento gerado\",\n \"agenda.payment.selectAccount\": \"Selecionar conta\",\n \"agenda.payment.registerPayment\": \"Registrar recebimento\",\n \"agenda.payment.registerPaymentHint\": \"Registrar pagamento deste agendamento\",\n \"agenda.payment.pendingHint\": \"Fatura gerada, aguardando pagamento\",\n \"agenda.payment.partialHint\": \"Parcialmente pago, toque para completar\",\n \"agenda.payment.paidHint\": \"Pagamento realizado\",\n \"agenda.payment.overdueHint\": \"Pagamento vencido\",\n \"agenda.payment.backToAppointment\": \"Voltar ao agendamento\",\n \"agenda.payment.checkout\": \"Confirmar\",\n \"agenda.payment.checkingOut\": \"Processando…\",\n \"agenda.payment.serviceSummary\": \"Resumo do atendimento\",\n \"agenda.payment.paymentMethod\": \"Forma de pagamento\",\n \"agenda.payment.noMethods\": \"Nenhuma forma de pagamento configurada.\",\n \"agenda.payment.configureMethods\": \"Configurar formas de pagamento\",\n \"agenda.payment.checkoutComplete\": \"Pagamento confirmado\",\n \"agenda.payment.card\": \"Cartão\",\n \"agenda.payment.method\": \"Método\",\n \"agenda.payment.select\": \"Selecionar…\",\n \"agenda.payment.cardBrand\": \"Bandeira\",\n \"agenda.payment.selectBrand\": \"Selecionar bandeira…\",\n \"agenda.payment.cardInstallments\": \"Parcelas\",\n \"agenda.payment.bankAccount\": \"Conta\",\n \"agenda.payment.viewInvoice\": \"Ver detalhes da fatura\",\n \"agenda.calendar.agendas\": \"Agendas\",\n \"agenda.calendar.create\": \"Criar\",\n \"agenda.calendar.next\": \"Próximo\",\n \"agenda.calendar.previous\": \"Anterior\",\n \"agenda.calendar.status\": \"Status\",\n \"agenda.calendar.today\": \"Hoje\",\n \"agenda.calendar.viewAgenda\": \"Agenda\",\n \"agenda.calendar.viewDay\": \"Dia\",\n \"agenda.calendar.viewList\": \"Lista\",\n \"agenda.calendar.viewMonth\": \"Mês\",\n \"agenda.calendar.viewWeek\": \"Semana\",\n \"agenda.list.today\": \"Hoje\",\n \"agenda.list.tomorrow\": \"Amanhã\",\n \"agenda.list.empty\": \"Nenhum item próximo\",\n \"agenda.confirmations.confirmed\": \"Confirmado:\",\n \"agenda.confirmations.empty\": \"Nenhuma confirmação pendente\",\n \"agenda.confirmations.emptySubtitle\": \"Todos os agendamentos futuros foram confirmados\",\n \"agenda.confirmations.loading\": \"Carregando...\",\n \"agenda.confirmations.subtitle\": \"Agendamentos futuros pendentes de confirmação\",\n \"agenda.confirmations.unknownClient\": \"Cliente desconhecido\",\n \"agenda.confirmations.sendWhatsApp\": \"Enviar WhatsApp\",\n \"agenda.confirmations.call\": \"Ligar\",\n \"agenda.confirmations.markConfirmed\": \"Marcar Confirmado\",\n \"agenda.confirmations.markCancelled\": \"Marcar Cancelado\",\n \"agenda.cancellation.loadingReasons\": \"Carregando motivos...\",\n \"agenda.cancellation.notesOptional\": \"Observações do cancelamento (opcional)\",\n \"agenda.cancellation.notesRequired\": \"Observações do cancelamento obrigatórias\",\n \"agenda.cancellation.selectReason\": \"Selecionar motivo do cancelamento\",\n \"agenda.contextMenu.changeStatus\": \"Alterar status\",\n \"agenda.contextMenu.delete\": \"Excluir\",\n \"agenda.contextMenu.edit\": \"Editar\",\n \"agenda.contextMenu.notAvailable\": \"(indisponível)\",\n \"agenda.index.settingsSubtitle\": \"Horários de funcionamento, preferências de agendamento e confirmações\",\n \"agenda.index.settingsTitle\": \"Configurações da Agenda\",\n \"settings.plugin.agenda-working-hours\": \"Horário de Funcionamento\",\n \"agenda.popover.unknown\": \"Desconhecido\",\n \"agenda.settings.autoConfirm\": \"Confirmar Automaticamente\",\n \"agenda.settings.autoConfirmDesc\": \"Confirmar automaticamente novos agendamentos\",\n \"agenda.settings.autoCreateOrder\": \"Criar Pedido Automaticamente\",\n \"agenda.settings.autoCreateOrderDesc\": \"Criar automaticamente um pedido financeiro para novos agendamentos\",\n \"agenda.settings.blockOutside\": \"Bloquear Fora do Horário\",\n \"agenda.settings.blockOutsideDesc\": \"Impedir agendamentos fora do horário de funcionamento\",\n \"agenda.settings.calendarDisplay\": \"Exibição do Calendário\",\n \"agenda.settings.calendarDisplayDesc\": \"Configurações visuais do calendário\",\n \"agenda.settings.cancelAlerts\": \"Alertas de Cancelamento\",\n \"agenda.settings.cancelAlertsDesc\": \"Notificar quando um agendamento é cancelado\",\n \"agenda.settings.compact\": \"Modo Compacto\",\n \"agenda.settings.compactDesc\": \"Usar blocos de eventos menores\",\n \"agenda.settings.confirmations\": \"Confirmações\",\n \"agenda.settings.confirmationsDesc\": \"Configurações de confirmação de agendamento\",\n \"agenda.settings.conflictDetection\": \"Detecção de Conflitos\",\n \"agenda.settings.conflictDetectionDesc\": \"Alertar quando agendamentos se sobrepõem\",\n \"agenda.settings.dragDrop\": \"Arrastar e Soltar\",\n \"agenda.settings.dragDropDesc\": \"Permitir reagendamento arrastando eventos\",\n \"agenda.settings.enableConfirmations\": \"Habilitar Confirmações\",\n \"agenda.settings.enableConfirmationsDesc\": \"Exigir confirmação para novos agendamentos\",\n \"agenda.settings.enableLocation\": \"Habilitar Seleção de Local\",\n \"agenda.settings.enableLocationDesc\": \"Mostrar seletor de local no modal de agendamento\",\n \"agenda.settings.enableWorkingHours\": \"Habilitar Horário de Funcionamento\",\n \"agenda.settings.enableWorkingHoursDesc\": \"Mostrar sobreposição de horário de funcionamento no calendário\",\n \"agenda.settings.locations\": \"Locais\",\n \"agenda.settings.locationsDesc\": \"Configurações de múltiplos locais\",\n \"agenda.settings.newBookingNotif\": \"Alertas de Novo Agendamento\",\n \"agenda.settings.newBookingNotifDesc\": \"Notificar quando um novo agendamento é criado\",\n \"agenda.settings.noShowTracking\": \"Rastreamento de Ausências\",\n \"agenda.settings.noShowTrackingDesc\": \"Rastrear e alertar sobre ausências\",\n \"agenda.settings.notifications\": \"Notificações\",\n \"agenda.settings.notificationsDesc\": \"Preferências de notificação\",\n \"agenda.settings.reminder\": \"Lembretes\",\n \"agenda.settings.reminderDesc\": \"Enviar lembretes antes dos compromissos\",\n \"agenda.settings.scheduling\": \"Agendamento\",\n \"agenda.settings.schedulingDesc\": \"Configurar comportamento do agendamento\",\n \"agenda.settings.showCancelled\": \"Mostrar Cancelados\",\n \"agenda.settings.showCancelledDesc\": \"Exibir agendamentos cancelados no calendário\",\n \"agenda.settings.showNoShow\": \"Mostrar Ausências\",\n \"agenda.settings.showNoShowDesc\": \"Exibir ausências no calendário\",\n \"agenda.settings.workingHours\": \"Horário de Funcionamento\",\n \"agenda.settings.workingHoursDesc\": \"Horários e disponibilidade\",\n \"agenda.sidebar.agendas\": \"Agendas\",\n \"agenda.sidebar.allLocations\": \"Todos os locais\",\n \"agenda.sidebar.create\": \"Criar\",\n \"agenda.sidebar.location\": \"Local\",\n \"agenda.sidebar.status\": \"Status\",\n \"agenda.toolbar.next\": \"Próximo\",\n \"agenda.toolbar.previous\": \"Anterior\",\n \"agenda.toolbar.today\": \"Hoje\",\n \"agenda.workingHours.addBreak\": \"Adicionar intervalo\",\n \"agenda.workingHours.copyToAll\": \"Copiar para todos\",\n \"agenda.workingHours.dayOff\": \"Folga\",\n \"agenda.workingHours.removePeriod\": \"Remover período\",\n \"agenda.workingHours.professional\": \"Profissional\",\n \"agenda.workingHours.save\": \"Salvar\",\n \"agenda.workingHours.saveFailed\": \"Falha ao salvar\",\n \"agenda.workingHours.saved\": \"Horários de trabalho salvos\",\n \"agenda.workingHours.saving\": \"Salvando...\",\n \"agenda.workingHours.subtitle\": \"Gerenciar horários de trabalho por profissional\",\n \"agenda.workingHours.to\": \"até\",\n \"agenda.title\": \"Agenda\",\n \"agenda.calendar.title\": \"Calendário\",\n \"agenda.calendar.noScheduleConfirm\": \"Este horário não possui agenda aberta para este profissional. Deseja agendar mesmo assim?\",\n \"agenda.calendar.newAppointment\": \"Novo Agendamento\",\n \"agenda.booking.create\": \"Novo Agendamento\",\n \"agenda.booking.edit\": \"Editar Agendamento\",\n \"agenda.booking.delete\": \"Excluir Agendamento\",\n \"agenda.booking.deleteConfirm\": \"Tem certeza que deseja excluir este agendamento?\",\n \"agenda.booking.client\": \"Cliente\",\n \"agenda.booking.professional\": \"Profissional\",\n \"agenda.booking.services\": \"Serviços\",\n \"agenda.booking.date\": \"Data\",\n \"agenda.booking.time\": \"Horário\",\n \"agenda.booking.duration\": \"Duração\",\n \"agenda.booking.notes\": \"Observações\",\n \"agenda.booking.status\": \"Status\",\n \"agenda.booking.save\": \"Salvar Agendamento\",\n \"agenda.booking.saving\": \"Salvando...\",\n \"agenda.confirmations.title\": \"Confirmações\",\n \"agenda.confirmations.pending\": \"Confirmações Pendentes\",\n \"agenda.confirmations.emptyDescription\": \"Todos os agendamentos futuros foram confirmados\",\n \"agenda.confirmations.confirm\": \"Confirmar\",\n \"agenda.confirmations.cancel\": \"Cancelar\",\n \"agenda.workingHours.title\": \"Horário de Trabalho\",\n \"agenda.workingHours.addPeriod\": \"Adicionar período\",\n \"agenda.workingHours.loading\": \"Carregando...\",\n \"agenda.appointment.addClient\": \"Adicionar cliente\",\n \"agenda.appointment.addServiceFirst\": \"Adicionar serviço\",\n \"agenda.appointment.addNotes\": \"Adicionar observações\",\n \"agenda.appointment.duration\": \"Duração (minutos)\",\n \"agenda.appointment.price\": \"Preço\",\n \"agenda.appointment.title\": \"Título\",\n \"agenda.appointment.addTitle\": \"Adicionar um título\",\n \"agenda.appointment.untitled\": \"(sem título)\",\n \"agenda.bookingType.appointment\": \"Agendamento\",\n \"agenda.bookingType.event\": \"Evento\",\n \"agenda.bookingType.task\": \"Tarefa\",\n \"agenda.bookingType.out_of_office\": \"Ausência\",\n \"agenda.bookingType.block\": \"Bloqueio\",\n \"agenda.settings.title\": \"Configurações da Agenda\",\n \"agenda.settings.slotDuration\": \"Duração do Intervalo\",\n \"agenda.settings.bookingKind\": \"Tipo de Agendamento\",\n \"agenda.settings.dayStartTime\": \"Horário de Início\",\n \"agenda.settings.dayStartTimeDesc\": \"Primeiro horário exibido no calendário\",\n \"agenda.settings.dayEndTime\": \"Horário de Término\",\n \"agenda.settings.dayEndTimeDesc\": \"Último horário exibido no calendário\",\n}\n","import { en } from './en'\nimport { ptBR } from './pt-BR'\n\nexport const agendaLocales: Record<string, Record<string, string>> = {\n en,\n 'pt-BR': ptBR,\n}\n","// AUTO-GENERATED from 000b_v_bookings_rename.sql, 000c_dedupe_customer_phones.sql, 001_public_booking.sql, 002_v_bookings_compat.sql, 003_public_client_kind.sql, 004_public_booking_assignee.sql, 005_agent_rpcs.sql, 006_agent_rpc_localtime.sql, 007_schedule_exception_precedence.sql, 008_agent_rpc_exception_precedence.sql, 009_public_booking_location.sql, 010_public_service_curation.sql, 011_default_assignee.sql, 012_drop_legacy_booking_overload.sql, 013_normalize_v_appointments.sql, 014_agent_rpc_update_appointment.sql — regenerate with scripts/embed-migrations.mjs\n// SQL files are the source of truth; this inline copy lets the manifest declare\n// migrations as data. Do not edit by hand — run the embed script instead.\n\nexport const MIGRATION_000B_V_BOOKINGS_RENAME = `-- Salon-only unblock: the pre-pools beauty deployment built rep_* report\n-- views on top of its (wider) v_bookings view, so 001's cleanup DROP cannot\n-- run there. Renaming keeps the dependents attached (they track the OID) and\n-- frees the name for 001; 002_v_bookings_compat re-creates v_bookings as a\n-- thin alias for live pre-M5 clients. No-op on fresh pools and on pools whose\n-- v_bookings has no dependents (001's DROP handles those).\n\nDO $rename$\nBEGIN\n IF to_regclass('public.v_bookings') IS NOT NULL\n AND to_regclass('public.v_bookings_legacy_beauty') IS NULL\n AND EXISTS (\n SELECT 1 FROM pg_depend d\n JOIN pg_rewrite rw ON rw.oid = d.objid\n JOIN pg_class dep ON dep.oid = rw.ev_class\n JOIN pg_class ref ON ref.oid = d.refobjid\n WHERE ref.relname = 'v_bookings' AND dep.relname <> 'v_bookings'\n ) THEN\n EXECUTE 'ALTER VIEW public.v_bookings RENAME TO v_bookings_legacy_beauty';\n END IF;\nEND $rename$;\n`\n\nexport const MIGRATION_000C_DEDUPE_CUSTOMER_PHONES = `-- 001 needs the customer-phone upsert key UNIQUE(tenant_id, phone). Converted\n-- pools can carry duplicates (found live on salon: 9 dogfood test records all\n-- sharing the founder's phone). Non-destructive dedupe: per (tenant_id, phone)\n-- customer group keep the row with most appointments (tie: oldest), NULL the\n-- phone on the rest and stash the original in metadata->'dedupedPhone'.\n-- Idempotent: reruns find no groups > 1.\n\nDO $dedupe$\nDECLARE\n r record;\nBEGIN\n IF to_regclass('public.people') IS NULL THEN\n RETURN;\n END IF;\n\n FOR r IN\n SELECT p.id, p.phone\n FROM public.people p\n JOIN LATERAL (\n SELECT count(*) AS appts\n FROM public.appointments a WHERE a.party_id = p.id\n ) ac ON true\n WHERE p.kind = 'customer' AND p.phone IS NOT NULL\n AND p.id NOT IN (\n SELECT DISTINCT ON (p2.tenant_id, p2.phone) p2.id\n FROM public.people p2\n WHERE p2.kind = 'customer' AND p2.phone IS NOT NULL\n ORDER BY p2.tenant_id, p2.phone,\n (SELECT count(*) FROM public.appointments a2 WHERE a2.party_id = p2.id) DESC,\n p2.created_at ASC\n )\n AND (p.tenant_id, p.phone) IN (\n SELECT tenant_id, phone FROM public.people\n WHERE kind = 'customer' AND phone IS NOT NULL\n GROUP BY tenant_id, phone HAVING count(*) > 1\n )\n LOOP\n UPDATE public.people\n SET metadata = COALESCE(metadata, '{}'::jsonb) || jsonb_build_object('dedupedPhone', r.phone),\n phone = NULL\n WHERE id = r.id;\n END LOOP;\nEND $dedupe$;\n`\n\nexport const MIGRATION_001_PUBLIC_BOOKING = `-- ============================================================================\n-- plugin-agenda 001: booking read model + public (anon) booking surface\n--\n-- Ships the objects the agenda providers reference but the spine (packages/db\n-- migrations 001–010) does not define:\n-- §0 converted-pool cleanup — drop the pre-rename v_bookings view / indexes\n-- §1 order_items columns the admin provider writes (duration/assignee)\n-- §2 public.v_appointments — admin read model (authenticated, RLS applies)\n-- §3 public.v_public_services — anon-readable service catalog\n-- §4 public.get_available_slots — anon RPC (mirrors the mock algorithm)\n-- §5 public.create_public_booking — anon RPC (validated, race-safe write)\n--\n-- Core v1 lives directly in PUBLIC (no separate core schema): people (was\n-- persons), appointments (was bookings). This migration is written against public\n-- names and is idempotent + safe on both fresh and converted pools.\n--\n-- Anon-access design: public booking pages run with the publishable key and no\n-- session, so the canonical tenant RLS yields nothing. Anon access is granted\n-- ONLY via the column-whitelisted view (§3) and SECURITY DEFINER RPCs (§4, §5)\n-- with tight input validation and hardcoded statuses.\n-- ============================================================================\n\n-- §0 — converted-pool cleanup. The pre-industry-pool shape shipped a v_bookings\n-- view and persons_/bookings_-named indexes; drop them so this file re-emits the\n-- canonical v_appointments view + people_/appointments_ indexes without leaving\n-- duplicates. All guarded with IF EXISTS → no-ops on a fresh pool.\nDROP VIEW IF EXISTS public.v_bookings;\nDROP INDEX IF EXISTS public.persons_tenant_customer_phone;\nDROP INDEX IF EXISTS public.bookings_assignee_time;\n\n-- §1 — columns the agenda provider writes but 004_archetypes lacks\nALTER TABLE public.order_items\n ADD COLUMN IF NOT EXISTS duration_minutes integer,\n ADD COLUMN IF NOT EXISTS assignee_id uuid REFERENCES public.people(id) ON DELETE SET NULL;\n\n-- Upsert key for public customers (per tenant, by normalized phone)\nCREATE UNIQUE INDEX IF NOT EXISTS people_tenant_customer_phone\n ON public.people(tenant_id, phone)\n WHERE kind = 'customer' AND phone IS NOT NULL;\n\n-- Slot-conflict scan\nCREATE INDEX IF NOT EXISTS appointments_assignee_time\n ON public.appointments(assignee_id, starts_at, ends_at)\n WHERE status NOT IN ('cancelled', 'no_show');\n\n-- §2 — admin read model (security_invoker → underlying RLS applies; anon sees 0 rows)\n-- DROP first: 013 widens this view and CREATE OR REPLACE cannot narrow a live\n-- view on replay (\"cannot drop columns from view\"). 013 replays right after.\nDROP VIEW IF EXISTS public.v_appointments;\nCREATE VIEW public.v_appointments\nWITH (security_invoker = true) AS\nSELECT\n b.id, b.tenant_id, b.kind, b.starts_at, b.ends_at, b.status, b.notes,\n b.order_id, b.location_id, b.metadata, b.created_at, b.updated_at,\n b.party_id AS client_id,\n COALESCE(pc.name, b.metadata->>'title') AS client_name,\n pc.phone AS client_phone,\n pc.email AS client_email,\n pc.avatar_url AS client_avatar_url,\n b.assignee_id AS professional_id,\n ps.name AS professional_name,\n ps.avatar_url AS professional_avatar_url,\n l.name AS location_name,\n o.total AS order_total,\n o.status AS order_status,\n (EXTRACT(EPOCH FROM (COALESCE(b.ends_at, b.starts_at) - b.starts_at))::int / 60)\n AS total_duration_minutes\nFROM public.appointments b\nLEFT JOIN public.people pc ON pc.id = b.party_id\nLEFT JOIN public.people ps ON ps.id = b.assignee_id\nLEFT JOIN public.locations l ON l.id = b.location_id\nLEFT JOIN public.orders o ON o.id = b.order_id;\n\nGRANT SELECT ON public.v_appointments TO authenticated, service_role;\nREVOKE SELECT ON public.v_appointments FROM anon;\n\n-- §3 — anon-readable public catalog (owner-rights view = deliberate, whitelisted)\n-- DROP first: 010 widens this view (curation columns) — same replay rule as §2.\nDROP VIEW IF EXISTS public.v_public_services;\nCREATE VIEW public.v_public_services AS\nSELECT\n s.id, s.tenant_id, s.name, s.description, s.price, s.currency,\n COALESCE(s.duration_minutes, 30) AS duration_minutes,\n s.image_url,\n COALESCE((s.metadata->>'sort_order')::int, 0) AS sort_order\nFROM public.services s\nWHERE s.is_active AND s.status = 'active';\n\nGRANT SELECT ON public.v_public_services TO anon, authenticated, service_role;\n\n-- §4 — availability RPC (mirrors plugin-agenda/src/data/mock.ts getAvailableSlots)\nCREATE OR REPLACE FUNCTION public.get_available_slots(\n p_tenant_id uuid,\n p_date date,\n p_duration_minutes integer,\n p_assignee_id uuid DEFAULT NULL,\n p_slot_interval integer DEFAULT 30\n) RETURNS TABLE (slot_start timestamptz, slot_end timestamptz)\nLANGUAGE plpgsql STABLE SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_tz text;\nBEGIN\n -- tight validation: this function is anon-callable\n IF p_duration_minutes IS NULL OR p_duration_minutes NOT BETWEEN 5 AND 480 THEN\n RAISE EXCEPTION 'invalid duration';\n END IF;\n IF p_slot_interval IS NULL OR p_slot_interval NOT BETWEEN 5 AND 240 THEN\n RAISE EXCEPTION 'invalid interval';\n END IF;\n IF p_date IS NULL OR p_date < current_date OR p_date > current_date + 90 THEN\n RETURN;\n END IF;\n\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RETURN; END IF; -- unknown tenant → empty, not an error\n\n RETURN QUERY\n WITH day_schedules AS (\n SELECT sc.assignee_id, sc.starts_at AS win_start, sc.ends_at AS win_end\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (p_assignee_id IS NULL OR sc.assignee_id = p_assignee_id)\n AND (\n sc.specific_date = p_date\n OR (sc.specific_date IS NULL AND sc.day_of_week = EXTRACT(dow FROM p_date)::smallint)\n )\n ),\n candidate AS (\n SELECT\n ds.assignee_id,\n gs AS s_start,\n gs + make_interval(mins => p_duration_minutes) AS s_end\n FROM day_schedules ds\n CROSS JOIN LATERAL generate_series(\n (p_date + ds.win_start) AT TIME ZONE v_tz,\n ((p_date + ds.win_end) AT TIME ZONE v_tz) - make_interval(mins => p_duration_minutes),\n make_interval(mins => p_slot_interval)\n ) AS gs\n )\n SELECT DISTINCT c.s_start, c.s_end\n FROM candidate c\n WHERE NOT EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = c.assignee_id\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < c.s_end\n AND COALESCE(b.ends_at, b.starts_at) > c.s_start\n )\n ORDER BY 1;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.get_available_slots(uuid, date, integer, uuid, integer) FROM public;\nGRANT EXECUTE ON FUNCTION public.get_available_slots(uuid, date, integer, uuid, integer)\n TO anon, authenticated, service_role;\n\n-- §5 — public booking write RPC (validated, race-safe, hardcoded statuses)\nCREATE OR REPLACE FUNCTION public.create_public_booking(\n p_tenant_id uuid,\n p_service_id uuid,\n p_starts_at timestamptz,\n p_name text,\n p_phone text,\n p_email text DEFAULT NULL,\n p_notes text DEFAULT NULL\n) RETURNS TABLE (booking_id uuid, starts_at timestamptz, ends_at timestamptz)\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n\n -- pick the assignee whose working hours cover the slot\n SELECT sc.assignee_id INTO v_assignee\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (\n sc.specific_date = (p_starts_at AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM p_starts_at AT TIME ZONE v_tz)::smallint)\n )\n AND (p_starts_at AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the customer by (tenant, phone) — matches people_tenant_customer_phone\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, 'customer', trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n ON CONFLICT (tenant_id, phone) WHERE kind = 'customer' AND phone IS NOT NULL\n DO UPDATE SET\n name = EXCLUDED.name,\n email = COALESCE(EXCLUDED.email, people.email),\n updated_at = now()\n RETURNING id INTO v_person_id;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text) FROM public;\nGRANT EXECUTE ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text)\n TO anon, authenticated, service_role;\n`\n\nexport const MIGRATION_002_V_BOOKINGS_COMPAT = `-- Where 000b preserved the legacy beauty view, re-create v_bookings as a\n-- thin alias over it so live pre-M5 clients that SELECT v_bookings by name\n-- keep their full legacy column set. Dropped for good once the beauty app\n-- ships on v_appointments (M5 follow-up).\n\nDO $compat$\nBEGIN\n IF to_regclass('public.v_bookings_legacy_beauty') IS NOT NULL\n AND to_regclass('public.v_bookings') IS NULL THEN\n EXECUTE 'CREATE VIEW public.v_bookings WITH (security_invoker = true) AS SELECT * FROM public.v_bookings_legacy_beauty';\n EXECUTE 'GRANT SELECT ON public.v_bookings TO authenticated, service_role';\n EXECUTE 'REVOKE SELECT ON public.v_bookings FROM anon';\n END IF;\nEND $compat$;\n`\n\nexport const MIGRATION_003_PUBLIC_CLIENT_KIND = `-- ---------------------------------------------------------------------------\n-- Public booking — tenant-configurable client kind\n-- ---------------------------------------------------------------------------\n-- 001 hardcoded kind='customer' for people created by create_public_booking.\n-- Verticals whose client archetype uses another kind (school → 'student',\n-- clinic → whatever the app registers) ended up with people invisible to the\n-- app's own pages/lookups and with entity links resolving to unregistered\n-- routes (#/customers/:id → not found).\n--\n-- The client kind now comes from TENANT SETTINGS (admin-controlled — never\n-- from the anon caller): tenants.settings.booking.client_kind\n-- Default remains 'customer', so existing pools/tenants are unaffected until\n-- they opt in:\n-- UPDATE tenants SET settings = jsonb_set(COALESCE(settings,'{}'::jsonb),\n-- '{booking,client_kind}', '\"student\"') WHERE id = '<tenant>';\n--\n-- The upsert no longer relies on the kind-specific partial unique index\n-- (people_tenant_customer_phone) — a per-(tenant, phone) advisory lock\n-- serializes concurrent first-bookings for any kind. The 001 index stays in\n-- place (harmless, still guards direct customer writes).\n--\n-- Idempotent: CREATE OR REPLACE, same signature as 001.\n-- ---------------------------------------------------------------------------\nCREATE OR REPLACE FUNCTION public.create_public_booking(\n p_tenant_id uuid,\n p_service_id uuid,\n p_starts_at timestamptz,\n p_name text,\n p_phone text,\n p_email text DEFAULT NULL,\n p_notes text DEFAULT NULL\n) RETURNS TABLE (booking_id uuid, starts_at timestamptz, ends_at timestamptz)\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\n v_client_kind text;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n\n -- tenant config: timezone + client kind (admin-set; sanitized, never caller input)\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo'),\n COALESCE(NULLIF(trim(t.settings->'booking'->>'client_kind'), ''), 'customer')\n INTO v_tz, v_client_kind\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n IF v_client_kind !~ '^[a-z_]{2,32}$' THEN v_client_kind := 'customer'; END IF;\n\n -- pick the assignee whose working hours cover the slot\n SELECT sc.assignee_id INTO v_assignee\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (\n sc.specific_date = (p_starts_at AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM p_starts_at AT TIME ZONE v_tz)::smallint)\n )\n AND (p_starts_at AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the client by (tenant, kind, phone). Kind is tenant-configured, so\n -- the 001 customer-only partial index can't arbitrate — a per-(tenant,\n -- phone) advisory lock serializes concurrent first-bookings instead.\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || ':' || v_phone, 1));\n\n SELECT p.id INTO v_person_id\n FROM people p\n WHERE p.tenant_id = p_tenant_id AND p.kind = v_client_kind AND p.phone = v_phone\n ORDER BY p.created_at\n LIMIT 1;\n\n IF v_person_id IS NOT NULL THEN\n UPDATE people SET\n name = trim(p_name),\n email = COALESCE(p_email, people.email),\n updated_at = now()\n WHERE id = v_person_id;\n ELSE\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, v_client_kind, trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n RETURNING id INTO v_person_id;\n END IF;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text) FROM public;\nGRANT EXECUTE ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text)\n TO anon, authenticated, service_role;\n`\n\nexport const MIGRATION_004_PUBLIC_BOOKING_ASSIGNEE = `-- ---------------------------------------------------------------------------\n-- Public booking — respect the professional the visitor saw\n-- ---------------------------------------------------------------------------\n-- Until now create_public_booking IGNORED which professional the site showed\n-- availability for and re-picked by working hours (ORDER BY assignee_id\n-- LIMIT 1). With several professionals covering the same slot the booking\n-- landed on someone else than displayed (\"Equipe Great DJs\" on the site,\n-- \"Rafa Groove\" in the agenda). New optional p_assignee_id:\n-- * provided → validate THAT professional's working hours cover the slot and\n-- book them — never silently reassign (mismatch becomes an explicit error);\n-- * NULL → auto-pick as before (sites that don't pin a professional).\n-- Conflict check + advisory lock already run against the resolved assignee, so\n-- the double-book guard follows whichever path resolves.\n--\n-- Signature change (8th arg): the old 7-arg function is DROPPED first —\n-- CREATE OR REPLACE with a different signature would create an ambiguous\n-- PostgREST overload instead of replacing.\n-- Includes 003's tenant-configurable client kind. Idempotent.\n-- ---------------------------------------------------------------------------\nDROP FUNCTION IF EXISTS public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text);\n\nCREATE OR REPLACE FUNCTION public.create_public_booking(\n p_tenant_id uuid,\n p_service_id uuid,\n p_starts_at timestamptz,\n p_name text,\n p_phone text,\n p_email text DEFAULT NULL,\n p_notes text DEFAULT NULL,\n p_assignee_id uuid DEFAULT NULL\n) RETURNS TABLE (booking_id uuid, starts_at timestamptz, ends_at timestamptz)\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\n v_client_kind text;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n\n -- tenant config: timezone + client kind (admin-set; sanitized, never caller input)\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo'),\n COALESCE(NULLIF(trim(t.settings->'booking'->>'client_kind'), ''), 'customer')\n INTO v_tz, v_client_kind\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n IF v_client_kind !~ '^[a-z_]{2,32}$' THEN v_client_kind := 'customer'; END IF;\n\n -- resolve the professional: the one the visitor saw (validated), else the\n -- first whose working hours cover the slot\n SELECT sc.assignee_id INTO v_assignee\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (p_assignee_id IS NULL OR sc.assignee_id = p_assignee_id)\n AND (\n sc.specific_date = (p_starts_at AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM p_starts_at AT TIME ZONE v_tz)::smallint)\n )\n AND (p_starts_at AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the client by (tenant, kind, phone), serialized by advisory lock\n -- (kind is tenant-configured, so the customer-only partial index can't\n -- arbitrate)\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || ':' || v_phone, 1));\n\n SELECT p.id INTO v_person_id\n FROM people p\n WHERE p.tenant_id = p_tenant_id AND p.kind = v_client_kind AND p.phone = v_phone\n ORDER BY p.created_at\n LIMIT 1;\n\n IF v_person_id IS NOT NULL THEN\n UPDATE people SET\n name = trim(p_name),\n email = COALESCE(p_email, people.email),\n updated_at = now()\n WHERE id = v_person_id;\n ELSE\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, v_client_kind, trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n RETURNING id INTO v_person_id;\n END IF;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text, uuid) FROM public;\nGRANT EXECUTE ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text, uuid)\n TO anon, authenticated, service_role;\n`\n\nexport const MIGRATION_005_AGENT_RPCS = `-- ============================================================================\n-- plugin-agenda 005: server-plane agent write RPC.\n--\n-- public.agent_agenda_create_appointment — the INTERNAL (operator-actor)\n-- counterpart of create_public_booking (001 §5): same invariants (working\n-- hours, advisory-lock race safety, hardcoded statuses), but:\n-- * actor-authorized: public.agent_guard (spine 015) runs role→plan→limit\n-- BEFORE anything — denial comes back as a structured jsonb the agent can\n-- explain conversationally, never a raised exception;\n-- * the client is an EXISTING person id (the agent resolves names→ids via\n-- reads first — ambiguity is a conversation problem, not a SQL one);\n-- * a requested professional is honored (working hours permitting);\n-- * audited: audit_logs row with the acting user.\n--\n-- Contract (all agent_* RPCs): (p_tenant_id, p_actor_user_id, p_payload jsonb)\n-- → jsonb {ok:true, id, record:{...}} | {ok:false, denial:{...}} | {ok:false,\n-- error text}. GRANT authenticated+service_role — NEVER anon (the Fayz broker\n-- calls with the pool service key and injects tenant/actor server-side).\n-- ============================================================================\n\nCREATE OR REPLACE FUNCTION public.agent_agenda_create_appointment(\n p_tenant_id uuid,\n p_actor_user_id uuid,\n p_payload jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_denial jsonb;\n v_used int;\n v_client_id uuid;\n v_service_id uuid;\n v_professional uuid;\n v_starts timestamptz;\n v_notes text;\n v_service record;\n v_client record;\n v_ends timestamptz;\n v_tz text;\n v_order uuid;\n v_booking uuid;\nBEGIN\n -- ── payload ──────────────────────────────────────────────────────────────\n BEGIN\n v_client_id := (p_payload->>'client_id')::uuid;\n v_service_id := (p_payload->>'service_id')::uuid;\n v_professional := (p_payload->>'professional_id')::uuid;\n v_starts := (p_payload->>'starts_at')::timestamptz;\n EXCEPTION WHEN OTHERS THEN\n RETURN jsonb_build_object('ok', false, 'error', 'invalid payload: ' || SQLERRM);\n END;\n v_notes := left(p_payload->>'notes', 500);\n IF v_client_id IS NULL OR v_service_id IS NULL OR v_starts IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'client_id, service_id and starts_at are required');\n END IF;\n IF v_starts <= now() OR v_starts > now() + interval '365 days' THEN\n RETURN jsonb_build_object('ok', false, 'error', 'starts_at must be in the future (max 1 year)');\n END IF;\n\n -- ── authorization: role → plan → bookings_month cap ──────────────────────\n SELECT count(*) INTO v_used FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.created_at >= date_trunc('month', now());\n v_denial := agent_guard(p_tenant_id, p_actor_user_id,\n 'appointments', 'create', 'bookings_month', v_used, 1);\n IF v_denial IS NOT NULL THEN\n RETURN jsonb_build_object('ok', false, 'denial', v_denial);\n END IF;\n\n -- ── invariants ───────────────────────────────────────────────────────────\n SELECT p.id, p.name INTO v_client\n FROM people p\n WHERE p.id = v_client_id AND p.tenant_id = p_tenant_id;\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown client for this tenant');\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = v_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown or inactive service');\n END IF;\n\n v_ends := v_starts + make_interval(mins => v_service.duration_minutes);\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n\n -- requested professional honored; otherwise pick one whose hours cover the slot\n SELECT sc.assignee_id INTO v_professional\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (v_professional IS NULL OR sc.assignee_id = v_professional)\n AND (\n sc.specific_date = (v_starts AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM v_starts AT TIME ZONE v_tz)::smallint)\n )\n AND (v_starts AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_professional IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'slot outside working hours for the requested professional');\n END IF;\n\n -- race safety: serialize per (tenant, professional), then conflict-check\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_professional::text, 0));\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_professional\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n ) THEN\n RETURN jsonb_build_object('ok', false, 'error', 'slot no longer available');\n END IF;\n\n -- ── write (statuses hardcoded) + audit ───────────────────────────────────\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_client_id, v_professional,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_client_id, v_professional, v_order,\n v_starts, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_professional);\n\n INSERT INTO audit_logs (tenant_id, user_id, action, entity_type, entity_id, metadata)\n VALUES (p_tenant_id, p_actor_user_id, 'agent.createAppointment', 'appointment', v_booking::text,\n jsonb_build_object('payload', p_payload, 'order_id', v_order));\n\n RETURN jsonb_build_object(\n 'ok', true,\n 'id', v_booking,\n 'record', jsonb_build_object(\n 'ref', jsonb_build_object('id', v_booking, 'resource', 'appointments',\n 'archetype', 'schedule:appointment'),\n 'starts_at', v_starts,\n 'ends_at', v_ends,\n 'client_name', v_client.name,\n 'service_name', v_service.name,\n 'price', v_service.price,\n 'status', 'scheduled'\n )\n );\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM public;\nREVOKE EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM anon;\nGRANT EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb)\n TO authenticated, service_role;\n`\n\nexport const MIGRATION_006_AGENT_RPC_LOCALTIME = `-- ============================================================================\n-- plugin-agenda 006: agent_agenda_create_appointment speaks LOCAL time.\n--\n-- Models reliably mangle UTC↔local offsets (\"10h\" became 13:00 BRT via a\n-- wrong sign). The RPC knows the tenant's timezone — so stop asking the model\n-- to convert: \\`starts_at\\` WITHOUT an offset (2026-07-27T10:00) is interpreted\n-- in the tenant tz; an explicit offset still works. The result now carries\n-- starts_at_local/ends_at_local strings so the reply echoes the truth in the\n-- user's own clock. Supersedes 005's function body (new file — applied\n-- migrations are never edited).\n-- ============================================================================\n\nCREATE OR REPLACE FUNCTION public.agent_agenda_create_appointment(\n p_tenant_id uuid,\n p_actor_user_id uuid,\n p_payload jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_denial jsonb;\n v_used int;\n v_client_id uuid;\n v_service_id uuid;\n v_professional uuid;\n v_starts timestamptz;\n v_starts_raw text;\n v_notes text;\n v_service record;\n v_client record;\n v_ends timestamptz;\n v_tz text;\n v_order uuid;\n v_booking uuid;\nBEGIN\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown tenant');\n END IF;\n\n -- ── payload ──────────────────────────────────────────────────────────────\n BEGIN\n v_client_id := (p_payload->>'client_id')::uuid;\n v_service_id := (p_payload->>'service_id')::uuid;\n v_professional := (p_payload->>'professional_id')::uuid;\n v_starts_raw := p_payload->>'starts_at';\n IF v_starts_raw ~ '(Z|[+-][0-9]{2}:?[0-9]{2})$' THEN\n v_starts := v_starts_raw::timestamptz; -- explicit offset\n ELSE\n v_starts := (v_starts_raw::timestamp) AT TIME ZONE v_tz; -- tenant-local\n END IF;\n EXCEPTION WHEN OTHERS THEN\n RETURN jsonb_build_object('ok', false, 'error', 'invalid payload: ' || SQLERRM);\n END;\n v_notes := left(p_payload->>'notes', 500);\n IF v_client_id IS NULL OR v_service_id IS NULL OR v_starts IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'client_id, service_id and starts_at are required');\n END IF;\n IF v_starts <= now() OR v_starts > now() + interval '365 days' THEN\n RETURN jsonb_build_object('ok', false, 'error', 'starts_at must be in the future (max 1 year)');\n END IF;\n\n -- ── authorization: role → plan → bookings_month cap ──────────────────────\n SELECT count(*) INTO v_used FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.created_at >= date_trunc('month', now());\n v_denial := agent_guard(p_tenant_id, p_actor_user_id,\n 'appointments', 'create', 'bookings_month', v_used, 1);\n IF v_denial IS NOT NULL THEN\n RETURN jsonb_build_object('ok', false, 'denial', v_denial);\n END IF;\n\n -- ── invariants ───────────────────────────────────────────────────────────\n SELECT p.id, p.name INTO v_client\n FROM people p\n WHERE p.id = v_client_id AND p.tenant_id = p_tenant_id;\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown client for this tenant');\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = v_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown or inactive service');\n END IF;\n\n v_ends := v_starts + make_interval(mins => v_service.duration_minutes);\n\n SELECT sc.assignee_id INTO v_professional\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (v_professional IS NULL OR sc.assignee_id = v_professional)\n AND (\n sc.specific_date = (v_starts AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM v_starts AT TIME ZONE v_tz)::smallint)\n )\n AND (v_starts AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n -- prefer a professional who is actually FREE at the slot (when the user\n -- did not name one, the first busy professional must not block the booking)\n AND NOT EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = sc.assignee_id\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n )\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_professional IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'no professional is available at that slot (outside working hours or already booked). Suggest a different time. Times are tenant-local, tz ' || v_tz);\n END IF;\n\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_professional::text, 0));\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_professional\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n ) THEN\n RETURN jsonb_build_object('ok', false, 'error', 'slot no longer available');\n END IF;\n\n -- ── write + audit ────────────────────────────────────────────────────────\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_client_id, v_professional,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_client_id, v_professional, v_order,\n v_starts, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_professional);\n\n INSERT INTO audit_logs (tenant_id, user_id, action, entity_type, entity_id, metadata)\n VALUES (p_tenant_id, p_actor_user_id, 'agent.createAppointment', 'appointment', v_booking::text,\n jsonb_build_object('payload', p_payload, 'order_id', v_order));\n\n RETURN jsonb_build_object(\n 'ok', true,\n 'id', v_booking,\n 'record', jsonb_build_object(\n 'ref', jsonb_build_object('id', v_booking, 'resource', 'appointments',\n 'archetype', 'schedule:appointment'),\n 'starts_at', v_starts,\n 'ends_at', v_ends,\n 'starts_at_local', to_char(v_starts AT TIME ZONE v_tz, 'YYYY-MM-DD (Dy) HH24:MI') || ' ' || v_tz,\n 'ends_at_local', to_char(v_ends AT TIME ZONE v_tz, 'HH24:MI'),\n 'client_name', v_client.name,\n 'service_name', v_service.name,\n 'price', v_service.price,\n 'status', 'scheduled'\n )\n );\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM public;\nREVOKE EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM anon;\nGRANT EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb)\n TO authenticated, service_role;\n`\n\nexport const MIGRATION_007_SCHEDULE_EXCEPTION_PRECEDENCE = `-- ============================================================================\n-- plugin-agenda 007: specific-date exceptions take PRECEDENCE over weekly hours.\n--\n-- The admin ScheduleEditor (saveException) writes two kinds of specific-date\n-- rows: 'available' = active rows with custom windows for the date; day off\n-- ('unavailable') = ONE inactive 00:00–00:00 sentinel. Until now every reader\n-- treated schedules as a flat union filtered by is_active, so:\n-- • a day off was INVISIBLE (inactive sentinel filtered out, weekly rows\n-- still matched) — the public site kept selling a day the admin closed;\n-- • an 'available' exception ADDED to the weekly hours instead of replacing\n-- them (\"horário especial\" should define the date's hours).\n--\n-- Fix: one helper — agenda_working_windows(tenant, date, assignee) — is now the\n-- single source of a day's windows: if ANY specific-date row exists for an\n-- assignee (active or sentinel), only the ACTIVE specific-date rows count for\n-- that assignee; otherwise the weekly (day_of_week) rows apply. Both readers\n-- are redefined on top of it:\n-- • get_available_slots — body otherwise identical to the latest version\n-- (google-calendar/002_smart_sync §5, tenant-wide 'block' clause KEPT);\n-- • create_public_booking — body otherwise identical to 004.\n--\n-- ORDERING: on pools with the Google Calendar connector this file must run\n-- AFTER integrations/google-calendar/migrations/002_smart_sync.sql (both\n-- redefine get_available_slots; 007 is the superset and must win). Re-running\n-- 007 last is always safe — it preserves 002's block semantics.\n-- ============================================================================\n\n-- ----------------------------------------------------------------------------\n-- §1 agenda_working_windows — the day's working windows, exception-aware.\n-- ----------------------------------------------------------------------------\nCREATE OR REPLACE FUNCTION public.agenda_working_windows(\n p_tenant_id uuid,\n p_date date,\n p_assignee_id uuid DEFAULT NULL\n) RETURNS TABLE (assignee_id uuid, win_start time, win_end time)\nLANGUAGE sql STABLE\nSET search_path = public\nAS $$\n WITH exc AS (\n -- Every specific-date row for the date, ACTIVE OR NOT: the inactive day-off\n -- sentinel must still suppress the weekly rows below.\n SELECT sc.assignee_id, sc.starts_at, sc.ends_at, sc.is_active\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.specific_date = p_date\n AND (p_assignee_id IS NULL OR sc.assignee_id = p_assignee_id)\n )\n SELECT e.assignee_id, e.starts_at, e.ends_at\n FROM exc e\n WHERE e.is_active\n UNION ALL\n SELECT sc.assignee_id, sc.starts_at, sc.ends_at\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM p_date)::smallint\n AND (p_assignee_id IS NULL OR sc.assignee_id = p_assignee_id)\n AND NOT EXISTS (SELECT 1 FROM exc e WHERE e.assignee_id = sc.assignee_id)\n$$;\n\nREVOKE ALL ON FUNCTION public.agenda_working_windows(uuid, date, uuid) FROM public;\nREVOKE EXECUTE ON FUNCTION public.agenda_working_windows(uuid, date, uuid) FROM anon;\nGRANT EXECUTE ON FUNCTION public.agenda_working_windows(uuid, date, uuid)\n TO authenticated, service_role;\n\n-- ----------------------------------------------------------------------------\n-- §2 get_available_slots — day_schedules now comes from the helper.\n-- Everything else is byte-identical to google-calendar/002_smart_sync §5.\n-- ----------------------------------------------------------------------------\nCREATE OR REPLACE FUNCTION public.get_available_slots(\n p_tenant_id uuid,\n p_date date,\n p_duration_minutes integer,\n p_assignee_id uuid DEFAULT NULL,\n p_slot_interval integer DEFAULT 30\n) RETURNS TABLE (slot_start timestamptz, slot_end timestamptz)\nLANGUAGE plpgsql STABLE SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_tz text;\nBEGIN\n -- tight validation: this function is anon-callable\n IF p_duration_minutes IS NULL OR p_duration_minutes NOT BETWEEN 5 AND 480 THEN\n RAISE EXCEPTION 'invalid duration';\n END IF;\n IF p_slot_interval IS NULL OR p_slot_interval NOT BETWEEN 5 AND 240 THEN\n RAISE EXCEPTION 'invalid interval';\n END IF;\n IF p_date IS NULL OR p_date < current_date OR p_date > current_date + 90 THEN\n RETURN;\n END IF;\n\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RETURN; END IF; -- unknown tenant → empty, not an error\n\n RETURN QUERY\n WITH day_schedules AS (\n SELECT w.assignee_id, w.win_start, w.win_end\n FROM agenda_working_windows(p_tenant_id, p_date, p_assignee_id) w\n ),\n candidate AS (\n SELECT\n ds.assignee_id,\n gs AS s_start,\n gs + make_interval(mins => p_duration_minutes) AS s_end\n FROM day_schedules ds\n CROSS JOIN LATERAL generate_series(\n (p_date + ds.win_start) AT TIME ZONE v_tz,\n ((p_date + ds.win_end) AT TIME ZONE v_tz) - make_interval(mins => p_duration_minutes),\n make_interval(mins => p_slot_interval)\n ) AS gs\n )\n SELECT DISTINCT c.s_start, c.s_end\n FROM candidate c\n WHERE NOT EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n -- SMART SYNC (gcal 002): this professional's own bookings OR any\n -- tenant-wide BLOCK (assignee_id IS NULL AND kind='block') busy the slot.\n AND (b.assignee_id = c.assignee_id\n OR (b.assignee_id IS NULL AND b.kind = 'block'))\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < c.s_end\n AND COALESCE(b.ends_at, b.starts_at) > c.s_start\n )\n ORDER BY 1;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.get_available_slots(uuid, date, integer, uuid, integer) FROM public;\nGRANT EXECUTE ON FUNCTION public.get_available_slots(uuid, date, integer, uuid, integer)\n TO anon, authenticated, service_role;\n\n-- ----------------------------------------------------------------------------\n-- §3 create_public_booking — professional resolution goes through the helper\n-- (a booking on a closed date now fails 'slot outside working hours').\n-- Everything else is byte-identical to 004.\n-- ----------------------------------------------------------------------------\nCREATE OR REPLACE FUNCTION public.create_public_booking(\n p_tenant_id uuid,\n p_service_id uuid,\n p_starts_at timestamptz,\n p_name text,\n p_phone text,\n p_email text DEFAULT NULL,\n p_notes text DEFAULT NULL,\n p_assignee_id uuid DEFAULT NULL\n) RETURNS TABLE (booking_id uuid, starts_at timestamptz, ends_at timestamptz)\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\n v_client_kind text;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n\n -- tenant config: timezone + client kind (admin-set; sanitized, never caller input)\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo'),\n COALESCE(NULLIF(trim(t.settings->'booking'->>'client_kind'), ''), 'customer')\n INTO v_tz, v_client_kind\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n IF v_client_kind !~ '^[a-z_]{2,32}$' THEN v_client_kind := 'customer'; END IF;\n\n -- resolve the professional: the one the visitor saw (validated), else the\n -- first whose EXCEPTION-AWARE working hours cover the slot (007)\n SELECT w.assignee_id INTO v_assignee\n FROM agenda_working_windows(\n p_tenant_id, (p_starts_at AT TIME ZONE v_tz)::date, p_assignee_id) w\n WHERE (p_starts_at AT TIME ZONE v_tz)::time >= w.win_start\n AND (v_ends AT TIME ZONE v_tz)::time <= w.win_end\n ORDER BY w.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the client by (tenant, kind, phone), serialized by advisory lock\n -- (kind is tenant-configured, so the customer-only partial index can't\n -- arbitrate)\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || ':' || v_phone, 1));\n\n SELECT p.id INTO v_person_id\n FROM people p\n WHERE p.tenant_id = p_tenant_id AND p.kind = v_client_kind AND p.phone = v_phone\n ORDER BY p.created_at\n LIMIT 1;\n\n IF v_person_id IS NOT NULL THEN\n UPDATE people SET\n name = trim(p_name),\n email = COALESCE(p_email, people.email),\n updated_at = now()\n WHERE id = v_person_id;\n ELSE\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, v_client_kind, trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n RETURNING id INTO v_person_id;\n END IF;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text, uuid) FROM public;\nGRANT EXECUTE ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text, uuid)\n TO anon, authenticated, service_role;\n`\n\nexport const MIGRATION_008_AGENT_RPC_EXCEPTION_PRECEDENCE = `-- ============================================================================\n-- plugin-agenda 008: agent_agenda_create_appointment honors schedule exceptions.\n--\n-- Same precedence fix as 007, applied to the agent write path: professional\n-- resolution now goes through agenda_working_windows (007 §1), so a date the\n-- admin closed (day-off sentinel) or re-opened with custom hours (\"horário\n-- especial\") binds the agent exactly like it binds the public site. Everything\n-- else is byte-identical to 006 (LOCAL-time input, free-professional pick,\n-- advisory lock, audit). Requires 007. Supersedes 006's function body.\n-- ============================================================================\n\nCREATE OR REPLACE FUNCTION public.agent_agenda_create_appointment(\n p_tenant_id uuid,\n p_actor_user_id uuid,\n p_payload jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_denial jsonb;\n v_used int;\n v_client_id uuid;\n v_service_id uuid;\n v_professional uuid;\n v_starts timestamptz;\n v_starts_raw text;\n v_notes text;\n v_service record;\n v_client record;\n v_ends timestamptz;\n v_tz text;\n v_order uuid;\n v_booking uuid;\nBEGIN\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown tenant');\n END IF;\n\n -- ── payload ──────────────────────────────────────────────────────────────\n BEGIN\n v_client_id := (p_payload->>'client_id')::uuid;\n v_service_id := (p_payload->>'service_id')::uuid;\n v_professional := (p_payload->>'professional_id')::uuid;\n v_starts_raw := p_payload->>'starts_at';\n IF v_starts_raw ~ '(Z|[+-][0-9]{2}:?[0-9]{2})$' THEN\n v_starts := v_starts_raw::timestamptz; -- explicit offset\n ELSE\n v_starts := (v_starts_raw::timestamp) AT TIME ZONE v_tz; -- tenant-local\n END IF;\n EXCEPTION WHEN OTHERS THEN\n RETURN jsonb_build_object('ok', false, 'error', 'invalid payload: ' || SQLERRM);\n END;\n v_notes := left(p_payload->>'notes', 500);\n IF v_client_id IS NULL OR v_service_id IS NULL OR v_starts IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'client_id, service_id and starts_at are required');\n END IF;\n IF v_starts <= now() OR v_starts > now() + interval '365 days' THEN\n RETURN jsonb_build_object('ok', false, 'error', 'starts_at must be in the future (max 1 year)');\n END IF;\n\n -- ── authorization: role → plan → bookings_month cap ──────────────────────\n SELECT count(*) INTO v_used FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.created_at >= date_trunc('month', now());\n v_denial := agent_guard(p_tenant_id, p_actor_user_id,\n 'appointments', 'create', 'bookings_month', v_used, 1);\n IF v_denial IS NOT NULL THEN\n RETURN jsonb_build_object('ok', false, 'denial', v_denial);\n END IF;\n\n -- ── invariants ───────────────────────────────────────────────────────────\n SELECT p.id, p.name INTO v_client\n FROM people p\n WHERE p.id = v_client_id AND p.tenant_id = p_tenant_id;\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown client for this tenant');\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = v_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown or inactive service');\n END IF;\n\n v_ends := v_starts + make_interval(mins => v_service.duration_minutes);\n\n -- exception-aware windows (007); still prefer a professional who is FREE at\n -- the slot when the user did not name one\n SELECT w.assignee_id INTO v_professional\n FROM agenda_working_windows(\n p_tenant_id, (v_starts AT TIME ZONE v_tz)::date, v_professional) w\n WHERE (v_starts AT TIME ZONE v_tz)::time >= w.win_start\n AND (v_ends AT TIME ZONE v_tz)::time <= w.win_end\n AND NOT EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = w.assignee_id\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n )\n ORDER BY w.assignee_id\n LIMIT 1;\n IF v_professional IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'no professional is available at that slot (outside working hours or already booked). Suggest a different time. Times are tenant-local, tz ' || v_tz);\n END IF;\n\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_professional::text, 0));\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_professional\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n ) THEN\n RETURN jsonb_build_object('ok', false, 'error', 'slot no longer available');\n END IF;\n\n -- ── write + audit ────────────────────────────────────────────────────────\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_client_id, v_professional,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_client_id, v_professional, v_order,\n v_starts, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'agent', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_professional);\n\n INSERT INTO audit_logs (tenant_id, user_id, action, entity_type, entity_id, metadata)\n VALUES (p_tenant_id, p_actor_user_id, 'agent.createAppointment', 'appointment', v_booking::text,\n jsonb_build_object('payload', p_payload, 'order_id', v_order));\n\n RETURN jsonb_build_object(\n 'ok', true,\n 'id', v_booking,\n 'record', jsonb_build_object(\n 'ref', jsonb_build_object('id', v_booking, 'resource', 'appointments',\n 'archetype', 'schedule:appointment'),\n 'starts_at', v_starts,\n 'ends_at', v_ends,\n 'starts_at_local', to_char(v_starts AT TIME ZONE v_tz, 'YYYY-MM-DD (Dy) HH24:MI') || ' ' || v_tz,\n 'ends_at_local', to_char(v_ends AT TIME ZONE v_tz, 'HH24:MI'),\n 'client_name', v_client.name,\n 'service_name', v_service.name,\n 'price', v_service.price,\n 'status', 'scheduled'\n )\n );\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM public;\nREVOKE EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb) FROM anon;\nGRANT EXECUTE ON FUNCTION public.agent_agenda_create_appointment(uuid, uuid, jsonb)\n TO authenticated, service_role;\n`\n\nexport const MIGRATION_009_PUBLIC_BOOKING_LOCATION = `-- Public bookings were written with location_id = NULL. The agenda's location\n-- filter is optional (default \"all\"), so they still rendered — but the moment\n-- an operator filtered by their unit, every booking taken from the website\n-- disappeared from the calendar. Single-location tenants are the common case\n-- and have an unambiguous answer, so default to it; multi-location tenants\n-- stay NULL (there is no correct guess) until the public flow asks.\n--\n-- Only the assignment is new; the rest of the body is unchanged from 004.\n\nCREATE OR REPLACE FUNCTION public.create_public_booking(\n p_tenant_id uuid,\n p_service_id uuid,\n p_starts_at timestamptz,\n p_name text,\n p_phone text,\n p_email text DEFAULT NULL,\n p_notes text DEFAULT NULL\n)\nRETURNS TABLE(booking_id uuid, starts_at timestamptz, ends_at timestamptz)\nLANGUAGE plpgsql\nSECURITY DEFINER\nSET search_path TO 'public'\nAS $function$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\n v_location uuid;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n\n -- pick the assignee whose working hours cover the slot\n SELECT sc.assignee_id INTO v_assignee\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND (\n sc.specific_date = (p_starts_at AT TIME ZONE v_tz)::date\n OR (sc.specific_date IS NULL\n AND sc.day_of_week = EXTRACT(dow FROM p_starts_at AT TIME ZONE v_tz)::smallint)\n )\n AND (p_starts_at AT TIME ZONE v_tz)::time >= sc.starts_at\n AND (v_ends AT TIME ZONE v_tz)::time <= sc.ends_at\n ORDER BY sc.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- NEW: stamp the unit so the calendar's location filter keeps these visible.\n -- Prefer the schedule's own location; else the tenant's only location.\n SELECT sc.location_id INTO v_location\n FROM schedules sc\n WHERE sc.tenant_id = p_tenant_id\n AND sc.kind = 'working_hours'\n AND sc.is_active\n AND sc.assignee_id = v_assignee\n AND sc.location_id IS NOT NULL\n LIMIT 1;\n\n IF v_location IS NULL THEN\n SELECT l.id INTO v_location\n FROM locations l\n WHERE l.tenant_id = p_tenant_id\n HAVING count(*) = 1; -- unambiguous only\n END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the customer by (tenant, phone) — matches people_tenant_customer_phone\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, 'customer', trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n ON CONFLICT (tenant_id, phone) WHERE kind = 'customer' AND phone IS NOT NULL\n DO UPDATE SET\n name = EXCLUDED.name,\n email = COALESCE(EXCLUDED.email, people.email),\n updated_at = now()\n RETURNING id INTO v_person_id;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, location_id,\n subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee, v_location,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id, location_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order, v_location,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$function$;\n\nGRANT EXECUTE ON FUNCTION public.create_public_booking(uuid, uuid, timestamptz, text, text, text, text) TO anon, authenticated;\n`\n\nexport const MIGRATION_010_PUBLIC_SERVICE_CURATION = `-- plugin-agenda 010: curate what the PUBLIC booking page sells.\n--\n-- v_public_services published every active service, so the website catalog was\n-- \"whatever exists in the system\". That conflates two different questions:\n--\n-- • is this service usable at all? → services.is_active / status\n-- • should a stranger be able to book it? → this flag\n--\n-- Without the split, hiding something from the site means deactivating it —\n-- which also removes it from the internal agenda and orphans its history. The\n-- case that forced this: a school whose public page listed 7 services when it\n-- sells 3, and one of the 4 extras already had real bookings attached.\n--\n-- OPT-OUT on purpose: a service is public unless explicitly marked otherwise.\n-- Opt-in would silently empty every live catalog the moment this ships.\n\nCREATE OR REPLACE VIEW public.v_public_services AS\nSELECT id,\n tenant_id,\n name,\n description,\n price,\n currency,\n COALESCE(duration_minutes, 30) AS duration_minutes,\n image_url,\n COALESCE(((metadata ->> 'sort_order'::text))::integer, 0) AS sort_order\n FROM services s\n WHERE is_active\n AND status = 'active'::text\n -- absent → public (back-compat). Only an explicit false hides it.\n AND COALESCE((metadata ->> 'bookableOnline'::text)::boolean, true);\n`\n\nexport const MIGRATION_011_DEFAULT_ASSIGNEE = `-- plugin-agenda 011: honour a tenant's default professional.\n--\n-- create_public_booking picks the assignee from whoever's working hours cover\n-- the slot, ordered by assignee_id — i.e. the lowest UUID wins. That is fine\n-- when the caller names the professional, and wrong when it does not: the\n-- public page confirms \"Equipe Great DJs\" while the booking silently lands on\n-- an unrelated instructor whose UUID happened to sort first.\n--\n-- Clients shipped before p_assignee_id existed still call this with 7 named\n-- args, so the parameter defaults to NULL and every live booking on those sites\n-- is mis-assigned today. Republishing the SDK fixes the caller, but the sites\n-- already deployed cannot be fixed that way — this can, from the database.\n--\n-- Precedence: explicit arg > tenant default > first covering schedule.\n-- Tenants without the setting keep exactly the previous behaviour.\n\nCREATE OR REPLACE FUNCTION public.create_public_booking(p_tenant_id uuid, p_service_id uuid, p_starts_at timestamp with time zone, p_name text, p_phone text, p_email text DEFAULT NULL::text, p_notes text DEFAULT NULL::text, p_assignee_id uuid DEFAULT NULL::uuid)\n RETURNS TABLE(booking_id uuid, starts_at timestamp with time zone, ends_at timestamp with time zone)\n LANGUAGE plpgsql\n SECURITY DEFINER\n SET search_path TO 'public'\nAS $function$\nDECLARE\n v_service record;\n v_person_id uuid;\n v_assignee uuid;\n v_requested uuid;\n v_ends timestamptz;\n v_order uuid;\n v_booking uuid;\n v_phone text;\n v_tz text;\n v_notes text;\n v_client_kind text;\nBEGIN\n -- validation: anon-callable, everything tight\n IF p_name IS NULL OR length(trim(p_name)) NOT BETWEEN 2 AND 120 THEN\n RAISE EXCEPTION 'invalid name';\n END IF;\n v_phone := regexp_replace(COALESCE(p_phone, ''), '\\\\D', '', 'g');\n IF length(v_phone) NOT BETWEEN 8 AND 15 THEN\n RAISE EXCEPTION 'invalid phone';\n END IF;\n IF p_email IS NOT NULL AND (length(p_email) > 254 OR p_email !~ '^[^@\\\\s]+@[^@\\\\s]+\\\\.[^@\\\\s]+$') THEN\n RAISE EXCEPTION 'invalid email';\n END IF;\n v_notes := left(p_notes, 500);\n IF p_starts_at IS NULL OR p_starts_at <= now() OR p_starts_at > now() + interval '90 days' THEN\n RAISE EXCEPTION 'invalid start';\n END IF;\n\n SELECT s.id, s.name, s.price, COALESCE(s.duration_minutes, 30) AS duration_minutes\n INTO v_service\n FROM services s\n WHERE s.id = p_service_id AND s.tenant_id = p_tenant_id\n AND s.is_active AND s.status = 'active';\n IF NOT FOUND THEN RAISE EXCEPTION 'unknown service'; END IF;\n\n v_ends := p_starts_at + make_interval(mins => v_service.duration_minutes);\n\n -- tenant config: timezone + client kind (admin-set; sanitized, never caller input)\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo'),\n COALESCE(NULLIF(trim(t.settings->'booking'->>'client_kind'), ''), 'customer')\n INTO v_tz, v_client_kind\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN RAISE EXCEPTION 'unknown tenant'; END IF;\n IF v_client_kind !~ '^[a-z_]{2,32}$' THEN v_client_kind := 'customer'; END IF;\n\n -- resolve the professional, in order of trust:\n -- 1. the id the caller sent (the one the visitor actually saw)\n -- 2. the tenant's configured default (settings->>'defaultAssigneeId')\n -- 3. whoever's working hours cover the slot\n --\n -- Step 2 is why this migration exists. Older published clients call this with\n -- 7 named args, leaving p_assignee_id NULL, and step 3 then resolved to\n -- \"lowest assignee UUID\" — an arbitrary instructor who had nothing to do with\n -- the name the site displayed on the confirmation screen. The default gives\n -- those clients a correct answer without waiting for a redeploy.\n v_requested := COALESCE(\n p_assignee_id,\n (SELECT NULLIF(t.settings ->> 'defaultAssigneeId', '')::uuid\n FROM tenants t WHERE t.id = p_tenant_id)\n );\n\n SELECT w.assignee_id INTO v_assignee\n FROM agenda_working_windows(\n p_tenant_id, (p_starts_at AT TIME ZONE v_tz)::date, v_requested) w\n WHERE (p_starts_at AT TIME ZONE v_tz)::time >= w.win_start\n AND (v_ends AT TIME ZONE v_tz)::time <= w.win_end\n ORDER BY w.assignee_id\n LIMIT 1;\n IF v_assignee IS NULL THEN RAISE EXCEPTION 'slot outside working hours'; END IF;\n\n -- serialize per (tenant, assignee) to kill the double-book race\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_assignee::text, 0));\n\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_assignee\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > p_starts_at\n ) THEN\n RAISE EXCEPTION 'slot no longer available';\n END IF;\n\n -- anti-spam: cap open future public bookings per phone per tenant\n IF (\n SELECT count(*) FROM appointments b\n JOIN people p ON p.id = b.party_id\n WHERE b.tenant_id = p_tenant_id\n AND p.phone = v_phone\n AND b.starts_at > now()\n AND b.status = 'scheduled'\n ) >= 3 THEN\n RAISE EXCEPTION 'too many open bookings for this phone';\n END IF;\n\n -- upsert the client by (tenant, kind, phone), serialized by advisory lock\n -- (kind is tenant-configured, so the customer-only partial index can't\n -- arbitrate)\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || ':' || v_phone, 1));\n\n SELECT p.id INTO v_person_id\n FROM people p\n WHERE p.tenant_id = p_tenant_id AND p.kind = v_client_kind AND p.phone = v_phone\n ORDER BY p.created_at\n LIMIT 1;\n\n IF v_person_id IS NOT NULL THEN\n UPDATE people SET\n name = trim(p_name),\n email = COALESCE(p_email, people.email),\n updated_at = now()\n WHERE id = v_person_id;\n ELSE\n INSERT INTO people (tenant_id, kind, name, phone, email, metadata)\n VALUES (p_tenant_id, v_client_kind, trim(p_name), v_phone, p_email,\n jsonb_build_object('source', 'public_booking'))\n RETURNING id INTO v_person_id;\n END IF;\n\n -- order + booking + order_item (statuses hardcoded — caller cannot set)\n INSERT INTO orders (tenant_id, kind, status, party_id, assignee_id, subtotal, total, notes, metadata)\n VALUES (p_tenant_id, 'appointment', 'scheduled', v_person_id, v_assignee,\n v_service.price, v_service.price, v_notes,\n jsonb_build_object('source', 'public_booking',\n 'serviceNames', v_service.name,\n 'contactName', trim(p_name)))\n RETURNING id INTO v_order;\n\n INSERT INTO appointments (tenant_id, kind, party_id, assignee_id, order_id,\n starts_at, ends_at, status, notes, metadata)\n VALUES (p_tenant_id, 'appointment', v_person_id, v_assignee, v_order,\n p_starts_at, v_ends, 'scheduled', v_notes,\n jsonb_build_object('source', 'public_booking', 'serviceNames', v_service.name))\n RETURNING id INTO v_booking;\n\n INSERT INTO order_items (order_id, service_id, name, quantity, unit_price, total,\n sort_order, duration_minutes, assignee_id)\n VALUES (v_order, v_service.id, v_service.name, 1, v_service.price, v_service.price,\n 0, v_service.duration_minutes, v_assignee);\n\n RETURN QUERY SELECT v_booking, p_starts_at, v_ends;\nEND;\n$function$;\n`\n\nexport const MIGRATION_012_DROP_LEGACY_BOOKING_OVERLOAD = `-- plugin-agenda 012: retire the pre-assignee create_public_booking overload.\n--\n-- ⚠️ DO NOT APPLY UNTIL @fayz-ai/plugin-agenda IS REPUBLISHED *AND* EVERY LIVE\n-- SITE HAS BEEN REDEPLOYED. Applying early breaks public booking on any\n-- site still serving a bundle that calls the 7-argument signature — the\n-- call stops resolving and every submission fails.\n--\n-- Some pools carry two overloads side by side:\n-- create_public_booking(uuid,uuid,timestamptz,text,text,text,text)\n-- create_public_booking(uuid,uuid,timestamptz,text,text,text,text,uuid)\n--\n-- Nothing errors when both exist, which is exactly the problem: a stale client\n-- silently resolves to the 7-arg one, which cannot know which professional the\n-- visitor was shown and falls back to \"lowest assignee UUID\". The site confirms\n-- one name, the agenda records another, and no one finds out until someone\n-- compares the two screens.\n--\n-- 011 makes that fallback survivable (tenant default). This makes it\n-- impossible — but only once no caller needs the old signature.\n--\n-- Verify before running:\n-- 1. npm view @fayz-ai/plugin-agenda version → the republished version\n-- 2. every deployed bundle greps for p_assignee_id:\n-- curl -s https://<site>/assets/index-*.js | grep -c p_assignee_id\n-- Each must be ≥ 2 (slots + booking). Zero means that site still needs it.\n\nDROP FUNCTION IF EXISTS public.create_public_booking(\n uuid, uuid, timestamptz, text, text, text, text\n);\n`\n\nexport const MIGRATION_013_NORMALIZE_V_APPOINTMENTS = `-- plugin-agenda 013: one booking read model — v_appointments.\n--\n-- Three views described the same 34 rows:\n--\n-- v_bookings → thin alias over the legacy view (002 compat shim)\n-- v_bookings_legacy_beauty → the pre-pools shape, still feeding 5 rep_* views\n-- v_appointments → the canonical name, and the only one the SDK reads\n--\n-- The school pool already had only v_appointments; the salon pool carried all\n-- three. Same data, three names, and reports quietly wired to the oldest one.\n--\n-- v_appointments was a strict SUBSET, so it could not simply absorb them. It\n-- gains the 7 columns it lacked — most importantly \\`services\\`, the order_items\n-- aggregate that 4 of the 5 reports depend on. That also retires a documented\n-- N+1: getBookingById fetches order_items in a second round-trip precisely\n-- because this view had no line items (see plugin-agenda/src/data/supabase.ts).\n--\n-- Deliberately NOT copied from the legacy view:\n-- • total_duration_minutes — legacy sums order_items durations, the canonical\n-- measures the slot. They disagree, no report reads it, and the SDK relies\n-- on the canonical meaning. Kept as-is.\n-- • client_name — the canonical COALESCEs with metadata->>'title' so blocks\n-- and personal events show a label instead of NULL. Kept as-is (an\n-- improvement the legacy shape never had).\n\n-- 1. v_appointments becomes the superset. Columns are APPENDED: CREATE OR\n-- REPLACE VIEW cannot reorder or drop, and the SDK selects '*'.\nCREATE OR REPLACE VIEW public.v_appointments\nWITH (security_invoker = true) AS\n SELECT b.id,\n b.tenant_id,\n b.kind,\n b.starts_at,\n b.ends_at,\n b.status,\n b.notes,\n b.order_id,\n b.location_id,\n b.metadata,\n b.created_at,\n b.updated_at,\n b.party_id AS client_id,\n COALESCE(pc.name, (b.metadata ->> 'title'::text)) AS client_name,\n pc.phone AS client_phone,\n pc.email AS client_email,\n pc.avatar_url AS client_avatar_url,\n b.assignee_id AS professional_id,\n ps.name AS professional_name,\n ps.avatar_url AS professional_avatar_url,\n l.name AS location_name,\n o.total AS order_total,\n o.status AS order_status,\n ((EXTRACT(epoch FROM (COALESCE(b.ends_at, b.starts_at) - b.starts_at)))::integer / 60) AS total_duration_minutes,\n -- appended:\n o.reference_number,\n o.status AS stage,\n (o.metadata ->> 'direction'::text) AS direction,\n ( SELECT json_agg(json_build_object('id', oi.id, 'serviceId', oi.service_id,\n 'name', oi.name, 'durationMinutes', oi.duration_minutes,\n 'price', oi.unit_price, 'assigneeId', oi.assignee_id)\n ORDER BY oi.sort_order)\n FROM order_items oi\n WHERE (oi.order_id = b.order_id)) AS services,\n inv.status AS payment_status,\n inv.paid AS order_paid,\n inv.balance AS order_balance\n FROM (((((appointments b\n LEFT JOIN people pc ON ((pc.id = b.party_id)))\n LEFT JOIN people ps ON ((ps.id = b.assignee_id)))\n LEFT JOIN locations l ON ((l.id = b.location_id)))\n LEFT JOIN orders o ON ((o.id = b.order_id)))\n LEFT JOIN v_invoice_balances inv ON ((inv.invoice_id = b.order_id)));\n\n-- 2. Repoint the reports off the legacy view. Bodies are unchanged\n-- except for the source relation.\n\nCREATE OR REPLACE VIEW public.rep_appointments_by_period AS\nSELECT tenant_id,\n id AS booking_id,\n (starts_at)::date AS date,\n starts_at,\n client_id,\n client_name,\n professional_id,\n professional_name,\n COALESCE(((services -> 0) ->> 'name'::text), ((services -> 0) ->> 'serviceName'::text)) AS service_name,\n status,\n order_total AS revenue,\n created_at,\n updated_at\n FROM v_appointments b;\n\n-- legacy_pre_pools only exists on pools migrated from the pre-pool era; fresh\n-- pools get the same shape with confirmation columns defaulting to pending/NULL.\nDO $$\nBEGIN\n IF to_regclass('legacy_pre_pools.appointments') IS NOT NULL THEN\n EXECUTE $v$\n CREATE OR REPLACE VIEW public.rep_confirmation_queue AS\n SELECT b.tenant_id,\n b.id AS booking_id,\n (b.starts_at)::date AS date,\n b.starts_at,\n b.client_id,\n b.client_name,\n b.professional_id,\n b.professional_name,\n COALESCE(((b.services -> 0) ->> 'name'::text), ((b.services -> 0) ->> 'serviceName'::text)) AS service_name,\n COALESCE(a.confirmation_status, 'pending'::text) AS confirmation_status,\n a.confirmation_channel,\n a.confirmation_sent_at,\n a.confirmed_at,\n b.created_at,\n b.updated_at\n FROM (v_appointments b\n LEFT JOIN legacy_pre_pools.appointments a ON ((a.booking_id = b.id)))\n WHERE ((b.status <> ALL (ARRAY['cancelled'::text, 'no_show'::text])) AND (b.starts_at >= (now() - '1 day'::interval)))\n $v$;\n ELSE\n EXECUTE $v$\n CREATE OR REPLACE VIEW public.rep_confirmation_queue AS\n SELECT b.tenant_id,\n b.id AS booking_id,\n (b.starts_at)::date AS date,\n b.starts_at,\n b.client_id,\n b.client_name,\n b.professional_id,\n b.professional_name,\n COALESCE(((b.services -> 0) ->> 'name'::text), ((b.services -> 0) ->> 'serviceName'::text)) AS service_name,\n 'pending'::text AS confirmation_status,\n NULL::text AS confirmation_channel,\n NULL::timestamptz AS confirmation_sent_at,\n NULL::timestamptz AS confirmed_at,\n b.created_at,\n b.updated_at\n FROM v_appointments b\n WHERE ((b.status <> ALL (ARRAY['cancelled'::text, 'no_show'::text])) AND (b.starts_at >= (now() - '1 day'::interval)))\n $v$;\n END IF;\nEND $$;\n\n-- v_clients (beauty Ring-2 extension) may not exist on non-salon pools — the\n-- report only makes sense where it does.\nDO $$\nBEGIN\n IF to_regclass('public.v_clients') IS NULL THEN RETURN; END IF;\n EXECUTE $v$\n CREATE OR REPLACE VIEW public.rep_new_clients AS\n SELECT c.tenant_id,\n c.id AS client_id,\n (c.created_at)::date AS date,\n c.name AS client_name,\n c.origin,\n first_booking.service_name AS first_service,\n c.created_at,\n c.updated_at\n FROM (v_clients c\n LEFT JOIN LATERAL ( SELECT COALESCE(((b.services -> 0) ->> 'name'::text), ((b.services -> 0) ->> 'serviceName'::text)) AS service_name\n FROM v_appointments b\n WHERE (b.client_id = c.id)\n ORDER BY b.starts_at\n LIMIT 1) first_booking ON (true))\n $v$;\nEND $$;\n\nCREATE OR REPLACE VIEW public.rep_revenue_by_professional AS\nSELECT tenant_id,\n (starts_at)::date AS date,\n professional_id,\n COALESCE(professional_name, 'Sem profissional'::text) AS professional_name,\n (count(*))::integer AS appointment_count,\n (COALESCE(sum(NULLIF(order_total, (0)::numeric)), (0)::numeric))::numeric(14,2) AS total_revenue,\n (COALESCE(avg(NULLIF(order_total, (0)::numeric)), (0)::numeric))::numeric(14,2) AS avg_ticket,\n (0)::numeric(14,2) AS commission,\n max(updated_at) AS updated_at\n FROM v_appointments b\n WHERE (status <> ALL (ARRAY['cancelled'::text, 'no_show'::text]))\n GROUP BY tenant_id, ((starts_at)::date), professional_id, COALESCE(professional_name, 'Sem profissional'::text);\n\nCREATE OR REPLACE VIEW public.rep_revenue_by_service AS\nSELECT b.tenant_id,\n (b.starts_at)::date AS date,\n NULLIF((service_item.value ->> 'serviceId'::text), ''::text) AS service_id,\n COALESCE((service_item.value ->> 'name'::text), (service_item.value ->> 'serviceName'::text), 'Sem servico'::text) AS service_name,\n (count(DISTINCT b.id))::integer AS quantity,\n (COALESCE(sum((NULLIF((service_item.value ->> 'price'::text), ''::text))::numeric), (0)::numeric))::numeric(14,2) AS total_revenue,\n (COALESCE(avg((NULLIF((service_item.value ->> 'price'::text), ''::text))::numeric), (0)::numeric))::numeric(14,2) AS avg_ticket,\n max(b.updated_at) AS updated_at\n FROM (v_appointments b\n CROSS JOIN LATERAL jsonb_array_elements(COALESCE((b.services)::jsonb, '[]'::jsonb)) service_item(value))\n WHERE (b.status <> ALL (ARRAY['cancelled'::text, 'no_show'::text]))\n GROUP BY b.tenant_id, ((b.starts_at)::date), NULLIF((service_item.value ->> 'serviceId'::text), ''::text), COALESCE((service_item.value ->> 'name'::text), (service_item.value ->> 'serviceName'::text), 'Sem servico'::text);\n\n-- 3. Retire the duplicates. v_bookings goes first: it reads the legacy view.\n-- Nothing in the SDK references either name (checked: only migrations and a\n-- README mention v_bookings).\nDROP VIEW IF EXISTS public.v_bookings;\nDROP VIEW IF EXISTS public.v_bookings_legacy_beauty;\n`\n\nexport const MIGRATION_014_AGENT_RPC_UPDATE_APPOINTMENT = `-- ============================================================================\n-- plugin-agenda 014: agent_agenda_update_appointment — remarcar / reatribuir /\n-- cancelar um agendamento existente.\n--\n-- Lacuna que isso fecha: o agente sabia CRIAR e não sabia MEXER. Pedido real\n-- (\"remarca esse paciente pra 16:30\") caía no updateRecord genérico, que bate\n-- em v_appointments — uma view — e devolve read_only; o modelo então \"resolvia\"\n-- abrindo um agendamento NOVO, deixando o antigo de pé. Duplicar a agenda de um\n-- salão é pior do que não fazer nada.\n--\n-- Mesma cadeia de guardas do 008 (agent_guard → janela de trabalho com exceções\n-- → lock advisory → checagem de conflito → auditoria), com três diferenças:\n-- • ação 'edit', sem cota (remarcar não consome bookings_month);\n-- • o próprio agendamento é excluído da checagem de conflito consigo mesmo;\n-- • cancelar não precisa de horário livre — só o guard.\n-- Requer 007 (agenda_working_windows). Idempotente.\n-- ============================================================================\n\nCREATE OR REPLACE FUNCTION public.agent_agenda_update_appointment(\n p_tenant_id uuid,\n p_actor_user_id uuid,\n p_payload jsonb\n) RETURNS jsonb\nLANGUAGE plpgsql SECURITY DEFINER\nSET search_path = public\nAS $$\nDECLARE\n v_denial jsonb;\n v_id uuid;\n v_tz text;\n v_row record;\n v_starts_raw text;\n v_starts timestamptz;\n v_ends timestamptz;\n v_duration int;\n v_professional uuid;\n v_status text;\n v_notes text;\n v_wants_move boolean;\n v_wants_status boolean;\nBEGIN\n SELECT COALESCE(t.settings->>'timezone', 'America/Sao_Paulo') INTO v_tz\n FROM tenants t WHERE t.id = p_tenant_id;\n IF v_tz IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown tenant');\n END IF;\n\n -- ── payload ──────────────────────────────────────────────────────────────\n BEGIN\n v_id := (p_payload->>'appointment_id')::uuid;\n v_professional := (p_payload->>'professional_id')::uuid;\n v_starts_raw := p_payload->>'starts_at';\n EXCEPTION WHEN OTHERS THEN\n RETURN jsonb_build_object('ok', false, 'error', 'invalid payload: ' || SQLERRM);\n END;\n v_status := nullif(trim(lower(p_payload->>'status')), '');\n v_notes := left(p_payload->>'notes', 500);\n v_wants_move := v_starts_raw IS NOT NULL OR v_professional IS NOT NULL;\n v_wants_status := v_status IS NOT NULL;\n\n IF v_id IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'appointment_id is required — search the agenda first and reuse the id of the appointment to change');\n END IF;\n IF NOT v_wants_move AND NOT v_wants_status AND v_notes IS NULL THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'nothing to change: send starts_at, professional_id, status or notes');\n END IF;\n IF v_status IS NOT NULL\n AND v_status NOT IN ('scheduled', 'confirmed', 'in_progress', 'completed', 'cancelled', 'no_show') THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'status must be one of scheduled, confirmed, in_progress, completed, cancelled, no_show');\n END IF;\n\n -- ── the appointment must exist, in THIS tenant ───────────────────────────\n SELECT b.id, b.starts_at, b.ends_at, b.assignee_id, b.status, b.party_id, b.order_id\n INTO v_row\n FROM appointments b\n WHERE b.id = v_id AND b.tenant_id = p_tenant_id;\n IF NOT FOUND THEN\n RETURN jsonb_build_object('ok', false, 'error', 'unknown appointment for this tenant');\n END IF;\n\n -- ── authorization: role → plan. No cap: editing frees nothing and buys\n -- nothing, so charging bookings_month for a reschedule would be wrong.\n v_denial := agent_guard(p_tenant_id, p_actor_user_id, 'appointments', 'edit');\n IF v_denial IS NOT NULL THEN\n RETURN jsonb_build_object('ok', false, 'denial', v_denial);\n END IF;\n\n -- Duration is preserved across a move — a 60-minute appointment stays 60.\n v_duration := GREATEST(\n COALESCE(EXTRACT(EPOCH FROM (v_row.ends_at - v_row.starts_at)) / 60, 30)::int, 5);\n v_professional := COALESCE(v_professional, v_row.assignee_id);\n\n IF v_wants_move THEN\n IF v_starts_raw IS NOT NULL THEN\n BEGIN\n IF v_starts_raw ~ '(Z|[+-][0-9]{2}:?[0-9]{2})$' THEN\n v_starts := v_starts_raw::timestamptz; -- explicit offset\n ELSE\n v_starts := (v_starts_raw::timestamp) AT TIME ZONE v_tz; -- tenant-local\n END IF;\n EXCEPTION WHEN OTHERS THEN\n RETURN jsonb_build_object('ok', false, 'error', 'invalid starts_at: ' || SQLERRM);\n END;\n ELSE\n v_starts := v_row.starts_at;\n END IF;\n v_ends := v_starts + make_interval(mins => v_duration);\n\n IF v_starts > now() + interval '365 days' THEN\n RETURN jsonb_build_object('ok', false, 'error', 'starts_at must be within the next year');\n END IF;\n\n -- Working window (exception-aware, 007) for the target professional.\n IF NOT EXISTS (\n SELECT 1\n FROM agenda_working_windows(\n p_tenant_id, (v_starts AT TIME ZONE v_tz)::date, v_professional) w\n WHERE w.assignee_id = v_professional\n AND (v_starts AT TIME ZONE v_tz)::time >= w.win_start\n AND (v_ends AT TIME ZONE v_tz)::time <= w.win_end\n ) THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'that slot is outside the professional''s working hours. Suggest a different time. Times are tenant-local, tz ' || v_tz);\n END IF;\n\n PERFORM pg_advisory_xact_lock(hashtextextended(p_tenant_id::text || v_professional::text, 0));\n IF EXISTS (\n SELECT 1 FROM appointments b\n WHERE b.tenant_id = p_tenant_id\n AND b.assignee_id = v_professional\n AND b.id <> v_id -- never conflicts with itself\n AND b.status NOT IN ('cancelled', 'no_show')\n AND b.starts_at < v_ends\n AND COALESCE(b.ends_at, b.starts_at) > v_starts\n ) THEN\n RETURN jsonb_build_object('ok', false, 'error',\n 'that slot is already taken. Suggest a different time.');\n END IF;\n END IF;\n\n -- ── write + audit ────────────────────────────────────────────────────────\n UPDATE appointments b SET\n starts_at = COALESCE(v_starts, b.starts_at),\n ends_at = COALESCE(v_ends, b.ends_at),\n assignee_id = v_professional,\n status = COALESCE(v_status, b.status),\n notes = COALESCE(v_notes, b.notes),\n metadata = COALESCE(b.metadata, '{}'::jsonb) || jsonb_build_object('lastAgentEdit', now()),\n updated_at = now()\n WHERE b.id = v_id AND b.tenant_id = p_tenant_id;\n\n -- The order mirrors the appointment's assignee/status so the financial side\n -- does not drift from the calendar.\n IF v_row.order_id IS NOT NULL THEN\n UPDATE orders o SET\n assignee_id = v_professional,\n status = CASE WHEN v_status = 'cancelled' THEN 'cancelled' ELSE o.status END,\n updated_at = now()\n WHERE o.id = v_row.order_id AND o.tenant_id = p_tenant_id;\n END IF;\n\n INSERT INTO audit_logs (tenant_id, user_id, action, entity_type, entity_id, metadata)\n VALUES (p_tenant_id, p_actor_user_id, 'agent.updateAppointment', 'appointment', v_id::text,\n jsonb_build_object('payload', p_payload,\n 'previous', jsonb_build_object(\n 'starts_at', v_row.starts_at,\n 'ends_at', v_row.ends_at,\n 'assignee_id', v_row.assignee_id,\n 'status', v_row.status)));\n\n SELECT a.id, a.starts_at, a.ends_at, a.status, a.client_name, a.professional_name\n INTO v_row\n FROM v_appointments a WHERE a.id = v_id;\n\n RETURN jsonb_build_object(\n 'ok', true,\n 'id', v_id,\n 'record', jsonb_build_object(\n 'ref', jsonb_build_object('id', v_id, 'resource', 'appointments',\n 'archetype', 'schedule:appointment'),\n 'starts_at', v_row.starts_at,\n 'ends_at', v_row.ends_at,\n 'starts_at_local', to_char(v_row.starts_at AT TIME ZONE v_tz, 'YYYY-MM-DD (Dy) HH24:MI') || ' ' || v_tz,\n 'ends_at_local', to_char(v_row.ends_at AT TIME ZONE v_tz, 'HH24:MI'),\n 'client_name', v_row.client_name,\n 'professional_name', v_row.professional_name,\n 'status', v_row.status\n )\n );\nEND;\n$$;\n\nREVOKE ALL ON FUNCTION public.agent_agenda_update_appointment(uuid, uuid, jsonb) FROM public;\nREVOKE EXECUTE ON FUNCTION public.agent_agenda_update_appointment(uuid, uuid, jsonb) FROM anon;\nGRANT EXECUTE ON FUNCTION public.agent_agenda_update_appointment(uuid, uuid, jsonb)\n TO authenticated, service_role;\n`\n\nexport const MIGRATIONS: Array<{ id: string; sql: string }> = [\n { id: \"000b_v_bookings_rename\", sql: MIGRATION_000B_V_BOOKINGS_RENAME },\n { id: \"000c_dedupe_customer_phones\", sql: MIGRATION_000C_DEDUPE_CUSTOMER_PHONES },\n { id: \"001_public_booking\", sql: MIGRATION_001_PUBLIC_BOOKING },\n { id: \"002_v_bookings_compat\", sql: MIGRATION_002_V_BOOKINGS_COMPAT },\n { id: \"003_public_client_kind\", sql: MIGRATION_003_PUBLIC_CLIENT_KIND },\n { id: \"004_public_booking_assignee\", sql: MIGRATION_004_PUBLIC_BOOKING_ASSIGNEE },\n { id: \"005_agent_rpcs\", sql: MIGRATION_005_AGENT_RPCS },\n { id: \"006_agent_rpc_localtime\", sql: MIGRATION_006_AGENT_RPC_LOCALTIME },\n { id: \"007_schedule_exception_precedence\", sql: MIGRATION_007_SCHEDULE_EXCEPTION_PRECEDENCE },\n { id: \"008_agent_rpc_exception_precedence\", sql: MIGRATION_008_AGENT_RPC_EXCEPTION_PRECEDENCE },\n { id: \"009_public_booking_location\", sql: MIGRATION_009_PUBLIC_BOOKING_LOCATION },\n { id: \"010_public_service_curation\", sql: MIGRATION_010_PUBLIC_SERVICE_CURATION },\n { id: \"011_default_assignee\", sql: MIGRATION_011_DEFAULT_ASSIGNEE },\n { id: \"012_drop_legacy_booking_overload\", sql: MIGRATION_012_DROP_LEGACY_BOOKING_OVERLOAD },\n { id: \"013_normalize_v_appointments\", sql: MIGRATION_013_NORMALIZE_V_APPOINTMENTS },\n { id: \"014_agent_rpc_update_appointment\", sql: MIGRATION_014_AGENT_RPC_UPDATE_APPOINTMENT },\n]\n","// ---------------------------------------------------------------------------\n// Bridge factory: adapts FinancialDataProvider → AgendaFinancialBridge\n// Consumer apps call this at plugin wiring time.\n// ---------------------------------------------------------------------------\n\nimport type { FinancialDataProvider } from '@fayz-ai/plugin-financial'\nimport type { AgendaFinancialBridge, BookingPaymentSummary, BookingPaymentDetail, BookingPaymentStatus } from './financial-bridge'\nimport { getSupabaseClientOptional } from '@fayz-ai/core'\n\n/**\n * Pure commission math: percentage of a realized order total, rounded to cents.\n * Exported for unit-testing and reuse; the bridge method below wraps the I/O.\n * Returns 0 for a non-positive base or rate so callers can skip empty accruals.\n */\nexport function computeCommissionAmount(total: number, ratePercent: number): number {\n const base = Number(total) || 0\n const rate = Number(ratePercent) || 0\n if (base <= 0 || rate <= 0) return 0\n return Math.round(base * (rate / 100) * 100) / 100\n}\n\nfunction computeStatus(movements: Array<{ status: string }>): BookingPaymentStatus {\n if (movements.length === 0) return 'none'\n const allPaid = movements.every((m) => m.status === 'paid')\n if (allPaid) return 'paid'\n const allCancelled = movements.every((m) => m.status === 'cancelled')\n if (allCancelled) return 'cancelled'\n const anyOverdue = movements.some((m) => m.status === 'overdue')\n if (anyOverdue) return 'overdue'\n const anyPaid = movements.some((m) => m.status === 'paid' || m.status === 'partial')\n if (anyPaid) return 'partial'\n return 'pending'\n}\n\n/**\n * Create an AgendaFinancialBridge backed by the financial plugin's data provider.\n *\n * @example\n * const financialProvider = createSupabaseFinancialProvider()\n * const agenda = createAgendaPlugin({\n * financialBridge: createFinancialBridge(financialProvider),\n * })\n */\nexport function createFinancialBridge(provider: FinancialDataProvider): AgendaFinancialBridge {\n return {\n async resolvePaymentStatuses(orderIds: string[]): Promise<Map<string, BookingPaymentSummary>> {\n const result = new Map<string, BookingPaymentSummary>()\n if (orderIds.length === 0) return result\n\n // Single batch query instead of N individual getInvoiceById calls\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) return result\n\n try {\n const [{ data: orders }, { data: movements }] = await Promise.all([\n supabase\n .from('orders')\n .select('id, kind, status, total, reference_number, metadata')\n .in('id', orderIds),\n supabase\n .from('plg_financial_movements')\n .select('invoice_id, status, paid_amount')\n .in('invoice_id', orderIds),\n ])\n\n const movementsByOrderId = new Map<string, Array<{ status: string; paid_amount: number }>>()\n for (const movement of movements ?? []) {\n const invoiceId = movement.invoice_id as string | undefined\n if (!invoiceId) continue\n movementsByOrderId.set(invoiceId, [...(movementsByOrderId.get(invoiceId) ?? []), movement])\n }\n\n for (const order of orders ?? []) {\n const orderMovements = movementsByOrderId.get(order.id) ?? []\n const meta = (order.metadata ?? {}) as Record<string, unknown>\n const paidAmount = orderMovements.length > 0\n ? orderMovements.reduce((sum, movement) => sum + (Number(movement.paid_amount) || 0), 0)\n : Number(meta.paidAmount) || 0\n\n result.set(order.id, {\n invoiceId: order.id,\n referenceNumber: order.reference_number as string | undefined,\n status: orderMovements.length > 0 ? computeStatus(orderMovements) : mapInvoiceStatus(order.status as string),\n totalAmount: Number(order.total) || 0,\n paidAmount,\n })\n }\n } catch { /* non-blocking */ }\n\n return result\n },\n\n async getPaymentDetail(orderId: string): Promise<BookingPaymentDetail | null> {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) return null\n\n // Single query: get order + movements in parallel\n const [orderRes, movRes] = await Promise.all([\n supabase.from('orders').select('id, status, total, reference_number, metadata').eq('id', orderId).single(),\n supabase.from('plg_financial_movements').select('*').eq('invoice_id', orderId).order('due_date'),\n ])\n\n const order = orderRes.data\n if (!order) return null\n const meta = (order.metadata ?? {}) as Record<string, unknown>\n\n // Collect unique payment_method_type_ids to resolve names in one query\n const typeIds = [...new Set((movRes.data ?? []).map((m: any) => m.payment_method_type_id).filter(Boolean))]\n let typeNames: Record<string, string> = {}\n if (typeIds.length > 0) {\n const { data: types } = await supabase.from('plg_financial_payment_method_types').select('id, name').in('id', typeIds)\n typeNames = Object.fromEntries((types ?? []).map((t: any) => [t.id, t.name]))\n }\n\n const movements = (movRes.data ?? []).map((m: Record<string, unknown>) => ({\n id: String(m.id),\n amount: Number(m.amount) || 0,\n paidAmount: Number(m.paid_amount) || 0,\n status: String(m.status ?? 'pending'),\n dueDate: String(m.due_date ?? ''),\n installmentNumber: m.installment_number != null ? Number(m.installment_number) : undefined,\n paymentDate: m.payment_date ? String(m.payment_date) : undefined,\n paymentMethodTypeName: m.payment_method_type_id ? typeNames[String(m.payment_method_type_id)] : undefined,\n cardBrand: m.card_brand ? String(m.card_brand) : undefined,\n cardInstallments: m.card_installments ? Number(m.card_installments) : undefined,\n }))\n\n return {\n invoiceId: order.id,\n referenceNumber: order.reference_number as string | undefined,\n status: movements.length > 0 ? computeStatus(movements) : mapInvoiceStatus(order.status as string),\n totalAmount: Number(order.total) || 0,\n paidAmount: Number(meta.paidAmount) || 0,\n movements,\n }\n },\n\n async createInvoiceFromOrder(orderId: string, options?: {\n installments?: number\n dueDate?: string\n paymentMethodTypeId?: string\n }): Promise<string> {\n // Promote the existing order to an invoice_receivable atomically via the\n // shared DB function (ref + stage/direction + N installments, idempotent).\n // status='invoiced' is valid for appointment/service_order (CHECK).\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase not available')\n const { error } = await supabase.rpc('fn_invoice_from_order', {\n p_order_id: orderId,\n p_due_date: options?.dueDate ?? null,\n p_status: 'invoiced',\n p_installments: options?.installments ?? 1,\n p_direction: 'credit',\n })\n if (error) throw new Error(error.message)\n return orderId\n },\n\n async payMovement(input) {\n await provider.payMovement({\n movementId: input.movementId,\n amount: input.amount,\n paymentDate: input.paymentDate,\n paymentMethodTypeId: input.paymentMethodTypeId,\n paymentMethodId: input.paymentMethodId,\n bankAccountId: input.bankAccountId,\n cardBrand: input.cardBrand,\n cardInstallments: input.cardInstallments,\n })\n },\n\n async createCommissionMovement(orderId, options) {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) return null\n\n // Order carries the assigned professional (assignee_id) and realized total.\n const { data: order } = await supabase\n .from('orders')\n .select('id, tenant_id, assignee_id, total')\n .eq('id', orderId)\n .single()\n if (!order || !order.assignee_id) return null // no professional → no commission\n\n // Per-professional rate lives on staff_members, surfaced via v_staff (id = person id).\n const { data: staff } = await supabase\n .from('v_staff')\n .select('commission_rate')\n .eq('id', order.assignee_id)\n .single()\n\n const rate = Number(staff?.commission_rate) || 0\n const base = Number(order.total) || 0\n const amount = computeCommissionAmount(base, rate)\n if (amount <= 0) return null // nothing configured/realized to accrue\n\n // Idempotent: one commission accrual per order. Reuse if already present.\n const { data: existing } = await supabase\n .from('plg_financial_movements')\n .select('id')\n .eq('invoice_id', orderId)\n .eq('movement_kind', 'commission')\n .limit(1)\n if (existing && existing.length > 0) return existing[0].id as string\n\n const dueDate = options?.dueDate ?? new Date().toISOString().slice(0, 10)\n\n const { data: inserted } = await supabase\n .from('plg_financial_movements')\n .insert({\n tenant_id: order.tenant_id,\n invoice_id: orderId,\n direction: 'debit', // payable to the professional\n movement_kind: 'commission',\n amount,\n paid_amount: 0,\n status: 'pending',\n due_date: dueDate,\n metadata: {\n source: 'agenda',\n kind: 'commission',\n professionalId: order.assignee_id,\n commissionRate: rate,\n baseAmount: base,\n },\n })\n .select('id')\n .single()\n\n return (inserted?.id as string | undefined) ?? null\n },\n\n async checkout(orderId, input) {\n // 1. Create invoice (single installment, due today)\n const today = new Date().toISOString().slice(0, 10)\n const invoiceId = await this.createInvoiceFromOrder(orderId, { installments: 1, dueDate: today })\n\n // 2. Get the created movement\n const detail = await this.getPaymentDetail(invoiceId)\n if (!detail || detail.movements.length === 0) throw new Error('No movement created')\n\n const movement = detail.movements[0]\n\n // 3. Pay it in full\n await this.payMovement({\n movementId: movement.id,\n amount: movement.amount,\n paymentDate: today,\n paymentMethodTypeId: input.paymentMethodTypeId,\n paymentMethodId: input.paymentMethodId,\n bankAccountId: input.bankAccountId,\n cardBrand: input.cardBrand,\n cardInstallments: input.cardInstallments,\n })\n\n // 4. Return updated detail\n return (await this.getPaymentDetail(invoiceId))!\n },\n\n async getPaymentMethodTypes() {\n const types = await provider.getPaymentMethodTypes()\n return types.map((t: any) => ({ id: t.id, name: t.name, transactionType: t.transactionType }))\n },\n\n async getBankAccounts() {\n const accounts = await provider.getBankAccounts()\n return accounts\n .filter((a: any) => a.isActive)\n .map((a: any) => ({ id: a.id, name: a.name, accountType: a.accountType }))\n },\n\n async getPaymentMethods(paymentMethodTypeId: string) {\n const methods = await provider.getPaymentMethods()\n return methods\n .filter((m: any) => m.paymentMethodTypeId === paymentMethodTypeId && m.isActive)\n .map((m: any) => ({ id: m.id, name: m.name }))\n },\n }\n}\n\nfunction mapInvoiceStatus(status: string): BookingPaymentStatus {\n switch (status) {\n case 'paid': return 'paid'\n case 'partial': return 'partial'\n case 'overdue': return 'overdue'\n case 'cancelled': return 'cancelled'\n case 'invoiced': return 'pending'\n case 'pending': return 'pending'\n case 'scheduled': return 'none'\n case 'confirmed': return 'none'\n case 'in_progress': return 'none'\n case 'completed': return 'none'\n case 'no_show': return 'none'\n case 'booked': return 'none'\n default: return 'pending'\n }\n}\n","// Booking ↔ Google Calendar event mapping — the SINGLE SOURCE OF TRUTH.\n//\n// These helpers are pure and Deno-friendly (only `import type`, no runtime\n// node/react/https imports), so the Supabase edge function imports this exact\n// file via a relative path (`../../src/integrations/google-calendar/mapping.ts`)\n// instead of keeping a divergent mirror. `import type` is elided by the Deno /\n// esbuild bundler, so the plugin `types.ts`/`CalendarBooking` type imports never\n// become runtime dependencies of the function bundle.\n//\n// Two callers, two input shapes:\n// • the SDK/UI works with the rich `CalendarBooking` (camelCase, joined) — see\n// bookingToEvent / eventToBookingPatch;\n// • the edge function + RPCs work with the raw `AppointmentRow` (snake_case DB\n// columns) — see appointmentRowToEvent / eventToAppointmentPatch.\n// Field decisions (title, all-day, cancel) are made once, here.\nimport type { CalendarBooking } from '../../types'\nimport type { GCalEvent, AppointmentRow, CalendarChannel, CalendarChannelRow } from './types'\n\nexport interface GCalEventInput {\n summary: string\n description?: string\n // Timed events use dateTime; all-day events use date (YYYY-MM-DD).\n start: { dateTime?: string; date?: string; timeZone?: string }\n end: { dateTime?: string; date?: string; timeZone?: string }\n}\n\n/** Normalized time window read off a Google event, all-day aware. */\nexport interface EventTimes {\n startsAt: string\n endsAt: string\n allDay: boolean\n}\n\n// --- Booking (rich SDK shape) → event -------------------------------------\n\n/** Build the event title from the booking's services + client. */\nexport function bookingSummary(b: Pick<CalendarBooking, 'services' | 'clientName'>): string {\n const services = (b.services ?? []).map((s) => s.name).filter(Boolean).join(', ')\n const who = b.clientName ?? ''\n if (services && who) return `${services} — ${who}`\n return services || who || 'Appointment'\n}\n\n/** Map a Fayz booking to a Google Calendar event input. Returns null when the booking has no end. */\nexport function bookingToEvent(b: CalendarBooking, timeZone?: string): GCalEventInput | null {\n if (!b.startsAt || !b.endsAt) return null\n const notes = [b.notes, b.professionalName ? `Pro: ${b.professionalName}` : '', b.locationName ?? '']\n .filter(Boolean).join('\\n')\n return {\n summary: bookingSummary(b),\n description: notes || undefined,\n start: { dateTime: b.startsAt, timeZone },\n end: { dateTime: b.endsAt, timeZone },\n }\n}\n\n/** Map an inbound Google event change to a partial booking update (reschedule/cancel), all-day aware. */\nexport function eventToBookingPatch(ev: GCalEvent): { startsAt?: string; endsAt?: string; status?: 'cancelled' } {\n if (ev.status === 'cancelled') return { status: 'cancelled' }\n const t = eventTimes(ev)\n return { startsAt: t.startsAt, endsAt: t.endsAt }\n}\n\n// --- Appointment row (raw DB shape) → event -------------------------------\n\n/**\n * Build the event title from an appointments row's denormalized metadata.\n * The raw row has no joined services/client, so we read the names the app\n * stamps onto metadata (serviceNames, contactName/clientName).\n */\nexport function appointmentRowSummary(row: AppointmentRow): string {\n const m = row.metadata ?? {}\n const services = (m.serviceNames as string) ?? ''\n const who = (m.contactName as string) ?? (m.clientName as string) ?? ''\n if (services && who) return `${services} — ${who}`\n return services || who || 'Appointment'\n}\n\n/** Map a raw appointments row to a Google event input (outbound push from the edge function). */\nexport function appointmentRowToEvent(row: AppointmentRow): GCalEventInput {\n return {\n summary: appointmentRowSummary(row),\n description: row.notes ?? undefined,\n start: { dateTime: row.starts_at },\n end: { dateTime: row.ends_at ?? row.starts_at },\n }\n}\n\n/**\n * Map an inbound Google event to a DB-friendly appointment patch (snake_case\n * times), all-day aware, cancellation included. Consumed by the edge function\n * when calling gcal_apply_event_patch.\n */\nexport function eventToAppointmentPatch(ev: GCalEvent): {\n starts_at?: string\n ends_at?: string\n summary?: string\n allDay?: boolean\n cancelled: boolean\n} {\n if (ev.status === 'cancelled') return { cancelled: true }\n const t = eventTimes(ev)\n return { starts_at: t.startsAt, ends_at: t.endsAt, summary: ev.summary, allDay: t.allDay, cancelled: false }\n}\n\n// --- Shared time normalization (all-day aware) ----------------------------\n\n/**\n * Read a normalized {startsAt, endsAt, allDay} window off a Google event.\n * All-day events carry `start.date`/`end.date` (YYYY-MM-DD, end exclusive) and\n * no dateTime; timed events carry dateTime. Falls back start→end when one side\n * is missing so callers always get a usable pair.\n */\nexport function eventTimes(ev: GCalEvent): EventTimes {\n const allDay = !ev.start?.dateTime && !!ev.start?.date\n const startsAt = ev.start?.dateTime ?? ev.start?.date ?? ''\n const endsAt = ev.end?.dateTime ?? ev.end?.date ?? startsAt\n return { startsAt, endsAt, allDay }\n}\n\n// --- Channel resolution (outbound destination priority) -------------------\n\n/** Convert a raw plg_calendar_channels row (snake_case) to the camelCase CalendarChannel. */\nexport function channelRowToChannel(r: CalendarChannelRow): CalendarChannel {\n return {\n id: r.id,\n integrationId: r.integration_id,\n tenantId: r.tenant_id,\n googleCalendarId: r.google_calendar_id,\n summary: r.summary ?? null,\n color: r.color ?? null,\n direction: r.direction,\n targetKind: r.target_kind ?? null,\n targetId: r.target_id ?? null,\n importMode: r.import_mode ?? 'appointment',\n syncToken: r.sync_token ?? null,\n channelId: r.channel_id ?? null,\n resourceId: r.resource_id ?? null,\n channelExpiresAt: r.channel_expires_at ?? null,\n isActive: r.is_active ?? true,\n createdAt: r.created_at ?? '',\n updatedAt: r.updated_at ?? '',\n }\n}\n\nexport interface ChannelMatchInput {\n assigneeId?: string | null\n serviceIds?: string[]\n locationId?: string | null\n}\n\n/**\n * Pick the outbound destination channel for a booking, by priority:\n * 1. a channel targeting the booking's assignee,\n * 2. else a channel targeting one of the booking's services,\n * 3. else a channel targeting the booking's location,\n * 4. else the whole-agenda channel (targetKind === null).\n * Only active outbound/bidirectional channels are eligible. Returns null when\n * nothing matches (caller falls back to the integration's default calendar).\n */\nexport function resolveTargetChannel(\n channels: CalendarChannel[],\n booking: ChannelMatchInput,\n): CalendarChannel | null {\n const eligible = channels.filter(\n (c) => c.isActive && (c.direction === 'outbound' || c.direction === 'bidirectional'),\n )\n const serviceIds = booking.serviceIds ?? []\n\n if (booking.assigneeId) {\n const byAssignee = eligible.find((c) => c.targetKind === 'assignee' && c.targetId === booking.assigneeId)\n if (byAssignee) return byAssignee\n }\n if (serviceIds.length) {\n const byService = eligible.find((c) => c.targetKind === 'service' && !!c.targetId && serviceIds.includes(c.targetId))\n if (byService) return byService\n }\n if (booking.locationId) {\n const byLocation = eligible.find((c) => c.targetKind === 'location' && c.targetId === booking.locationId)\n if (byLocation) return byLocation\n }\n return eligible.find((c) => c.targetKind === null) ?? null\n}\n","// Canonical DB object names for the Google Calendar connector.\n//\n// Plugin-owned tables carry the platform `plg_<plugin>_` prefix (DATA-MODEL.md\n// Ring 1). Single source of truth so the connector data layer (supabase.ts) and\n// the google-calendar-sync edge function never drift on a table name. The SQL\n// side is owned by ./migrations/001_google_calendar.sql + 002_smart_sync.sql\n// (fresh installs) and 003_plg_rename.sql (legacy-pool rename).\nexport const GCAL_TABLES = {\n integrations: 'plg_calendar_integrations',\n channels: 'plg_calendar_channels',\n syncLog: 'plg_calendar_sync_log',\n} as const\n","// Google Calendar integration (control plane) — Supabase client.\n//\n// Thin client. Split of responsibilities:\n// • anything that needs the OAuth client secret or a Google API call goes\n// through the google-calendar-sync edge function (invoke);\n// • plain tenant-scoped reads/writes (integration row, channels, log) hit the\n// tables directly under RLS.\nimport { getSupabaseClientOptional, getActiveTenantId } from '@fayz-ai/core'\nimport { channelRowToChannel } from '../mapping'\nimport { GCAL_TABLES } from './tables'\nimport type {\n CalendarIntegration,\n CalendarSyncLogEntry,\n CalendarChannel,\n ExternalEventPreview,\n GoogleCalendarListEntry,\n ImportEventsResult,\n} from '../types'\n\nconst FUNCTION = 'google-calendar-sync'\n\nfunction sb() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase not initialized')\n return supabase\n}\n\n/** Snake_case patch for plg_calendar_channels writes (RLS-scoped). */\nexport interface CalendarChannelInput {\n id?: string\n integrationId?: string\n googleCalendarId: string\n summary?: string | null\n color?: string | null\n direction?: CalendarChannel['direction']\n targetKind?: CalendarChannel['targetKind']\n targetId?: string | null\n importMode?: CalendarChannel['importMode']\n isActive?: boolean\n}\n\nexport interface GoogleCalendarProvider {\n getIntegration(): Promise<CalendarIntegration | null>\n /** Start the OAuth connect flow — returns the Google consent URL to redirect to. */\n getConnectUrl(redirectTo?: string): Promise<string>\n setCalendar(calendarId: string): Promise<void>\n disconnect(): Promise<void>\n /** Manually pull external changes now (inbound). */\n syncNow(): Promise<{ fetched: number; written: number; discovered?: number }>\n getSyncLog(): Promise<CalendarSyncLogEntry[]>\n // --- smart sync: multi-calendar channels + import wizard ---\n /** List the user's Google calendars for the de-para picker (needs the API → function). */\n listGoogleCalendars(): Promise<GoogleCalendarListEntry[]>\n /** Read this tenant's channels (RLS). */\n listChannels(): Promise<CalendarChannel[]>\n /** Create/update a channel (RLS upsert on integration_id + google_calendar_id). */\n saveChannel(input: CalendarChannelInput): Promise<void>\n /** Delete a channel by id (RLS). */\n deleteChannel(id: string): Promise<void>\n /** Preview future events not yet linked to an appointment (import wizard). */\n listExternalEvents(params?: { channelId?: string; timeMin?: string }): Promise<ExternalEventPreview[]>\n /** Import selected external events as appointments. */\n importEvents(items: { channelId: string; eventId: string }[]): Promise<ImportEventsResult>\n}\n\nexport function createGoogleCalendarProvider(): GoogleCalendarProvider {\n return {\n async getIntegration() {\n const { data } = await sb().from(GCAL_TABLES.integrations).select('*').eq('provider', 'google').limit(1).maybeSingle()\n if (!data) return null\n return {\n id: data.id,\n provider: data.provider,\n calendarId: data.calendar_id ?? 'primary',\n active: data.active ?? true,\n connected: !!data.oauth_refresh_token,\n lastSyncAt: data.last_sync_at ?? undefined,\n }\n },\n\n async getConnectUrl(redirectTo) {\n const { data, error } = await sb().functions.invoke(FUNCTION, {\n body: { action: 'oauth_start', tenantId: getActiveTenantId(), redirectTo: redirectTo ?? window.location.href },\n })\n if (error) throw new Error(error.message)\n return (data as { url: string }).url\n },\n\n async setCalendar(calendarId) {\n await sb().from(GCAL_TABLES.integrations).update({ calendar_id: calendarId, updated_at: new Date().toISOString() }).eq('provider', 'google')\n },\n\n async disconnect() {\n await sb().from(GCAL_TABLES.integrations).update({ active: false, oauth_refresh_token: null, oauth_access_token: null }).eq('provider', 'google')\n },\n\n async syncNow() {\n const { data, error } = await sb().functions.invoke(FUNCTION, { body: { action: 'pull_events', tenantId: getActiveTenantId(), trigger: 'manual' } })\n if (error) throw new Error(error.message)\n return data as { fetched: number; written: number; discovered?: number }\n },\n\n async getSyncLog() {\n const { data } = await sb().from(GCAL_TABLES.syncLog).select('*').order('created_at', { ascending: false }).limit(20)\n return (data ?? []).map((r: any) => ({\n id: r.id, direction: r.direction, trigger: r.trigger ?? undefined,\n status: r.status, fetched: r.fetched ?? 0, written: r.written ?? 0,\n error: r.error ?? undefined, createdAt: r.created_at,\n }))\n },\n\n async listGoogleCalendars() {\n const { data, error } = await sb().functions.invoke(FUNCTION, { body: { action: 'list_calendars', tenantId: getActiveTenantId() } })\n if (error) throw new Error(error.message)\n return (data as { calendars: GoogleCalendarListEntry[] }).calendars ?? []\n },\n\n async listChannels() {\n const { data } = await sb().from(GCAL_TABLES.channels).select('*').order('created_at', { ascending: true })\n return (data ?? []).map(channelRowToChannel)\n },\n\n async saveChannel(input) {\n const tenantId = getActiveTenantId()\n // Resolve the integration id when the caller didn't pass one.\n let integrationId = input.integrationId\n if (!integrationId) {\n const { data } = await sb().from(GCAL_TABLES.integrations).select('id').eq('provider', 'google').limit(1).maybeSingle()\n integrationId = data?.id\n }\n const row: Record<string, unknown> = {\n integration_id: integrationId,\n tenant_id: tenantId,\n google_calendar_id: input.googleCalendarId,\n updated_at: new Date().toISOString(),\n }\n if (input.id !== undefined) row.id = input.id\n if (input.summary !== undefined) row.summary = input.summary\n if (input.color !== undefined) row.color = input.color\n if (input.direction !== undefined) row.direction = input.direction\n if (input.targetKind !== undefined) row.target_kind = input.targetKind\n if (input.targetId !== undefined) row.target_id = input.targetId\n if (input.importMode !== undefined) row.import_mode = input.importMode\n if (input.isActive !== undefined) row.is_active = input.isActive\n const { error } = await sb().from(GCAL_TABLES.channels).upsert(row, { onConflict: 'integration_id,google_calendar_id' })\n if (error) throw new Error(error.message)\n },\n\n async deleteChannel(id) {\n const { error } = await sb().from(GCAL_TABLES.channels).delete().eq('id', id)\n if (error) throw new Error(error.message)\n },\n\n async listExternalEvents(params) {\n const { data, error } = await sb().functions.invoke(FUNCTION, {\n body: { action: 'list_external_events', tenantId: getActiveTenantId(), channelId: params?.channelId, timeMin: params?.timeMin },\n })\n if (error) throw new Error(error.message)\n return (data as { events: ExternalEventPreview[] }).events ?? []\n },\n\n async importEvents(items) {\n const { data, error } = await sb().functions.invoke(FUNCTION, {\n body: { action: 'import_events', tenantId: getActiveTenantId(), items },\n })\n if (error) throw new Error(error.message)\n return data as ImportEventsResult\n },\n }\n}\n","// A small round swatch tinted with a Google calendar's backgroundColor.\n//\n// Google's calendarList entries carry a `backgroundColor` hex; we render it as a\n// dot next to the calendar summary in the de-para list and as the leading dot of\n// the origin badge in the import wizard. Falls back to the muted border when a\n// calendar has no color (rare, e.g. some shared calendars).\nimport React from 'react'\n\nexport function CalendarColorDot({\n color,\n className = '',\n}: {\n color?: string | null\n className?: string\n}) {\n return (\n <span\n className={`inline-block h-2.5 w-2.5 shrink-0 rounded-full border border-black/10 ${className}`}\n style={{ backgroundColor: color || 'hsl(var(--muted-foreground))' }}\n aria-hidden\n />\n )\n}\n","// Host-plugin lookups for the smart-sync de-para target picker.\n//\n// A channel can target one professional (assignee), one service, or one location\n// instead of the whole agenda. To offer real pickers (not raw uuid inputs) the\n// connector reuses plugin-agenda's own data providers — it lives inside the same\n// package, so these are in-process reads under the same RLS:\n// • professionals + locations → createSupabaseAgendaProvider()\n// • services → createSupabasePublicBookingProvider() (v_public_services)\n// Everything is loaded once, lazily, and degrades to an empty list (the row then\n// falls back to a plain uuid input) if a lookup is unavailable for the tenant.\nimport { useEffect, useState } from 'react'\nimport { getActiveTenantId } from '@fayz-ai/core'\nimport { createSupabaseAgendaProvider } from '../../../data'\nimport { createSupabasePublicBookingProvider } from '../../../public/data/supabase'\nimport type { ChannelTargetKind } from '../types'\n\n/** A pickable target option (assignee/service/location) — id + display name. */\nexport interface LookupOption {\n id: string\n name: string\n}\n\nexport interface AgendaLookups {\n assignee: LookupOption[]\n service: LookupOption[]\n location: LookupOption[]\n}\n\nconst EMPTY: AgendaLookups = { assignee: [], service: [], location: [] }\n\nexport interface UseAgendaLookupsResult {\n lookups: AgendaLookups\n loading: boolean\n /** True when at least one of the three lookups returned rows. */\n hasAny: boolean\n}\n\n/**\n * Load professionals / services / locations for the target picker. Failures are\n * swallowed per-lookup (each falls back to an empty list) so a missing table or\n * a vertical without services never breaks the whole de-para screen.\n */\nexport function useAgendaLookups(enabled: boolean): UseAgendaLookupsResult {\n const [lookups, setLookups] = useState<AgendaLookups>(EMPTY)\n const [loading, setLoading] = useState(false)\n\n useEffect(() => {\n if (!enabled) return\n let cancelled = false\n setLoading(true)\n void (async () => {\n const agenda = createSupabaseAgendaProvider()\n const tenantId = getActiveTenantId()\n const publicProvider = tenantId\n ? createSupabasePublicBookingProvider({ tenantId })\n : null\n\n const [assignee, location, service] = await Promise.all([\n agenda.getProfessionals().then(\n (rows) => rows.map((p) => ({ id: p.id, name: p.name })),\n () => [] as LookupOption[],\n ),\n (agenda.getLocations?.() ?? Promise.resolve([])).then(\n (rows) => rows.map((l) => ({ id: l.id, name: l.name })),\n () => [] as LookupOption[],\n ),\n (publicProvider?.getServices() ?? Promise.resolve([])).then(\n (rows) => rows.map((s) => ({ id: s.id, name: s.name })),\n () => [] as LookupOption[],\n ),\n ])\n\n if (cancelled) return\n setLookups({ assignee, service, location })\n setLoading(false)\n })()\n\n return () => {\n cancelled = true\n }\n }, [enabled])\n\n const hasAny =\n lookups.assignee.length > 0 ||\n lookups.service.length > 0 ||\n lookups.location.length > 0\n\n return { lookups, loading, hasAny }\n}\n\n/** Options available for a given target kind (empty for whole-agenda / null). */\nexport function optionsForKind(\n lookups: AgendaLookups,\n kind: ChannelTargetKind,\n): LookupOption[] {\n if (kind === 'assignee') return lookups.assignee\n if (kind === 'service') return lookups.service\n if (kind === 'location') return lookups.location\n return []\n}\n","// De-para (mapping) list — one row per Google calendar.\n//\n// Reads the user's Google calendars (listGoogleCalendars) and this tenant's\n// existing channels (listChannels), joins them by google_calendar_id, and lets\n// the user, per calendar:\n// • toggle sync on/off → creates/updates the channel (is_active)\n// • pick a direction → Two-way / Import only / Export only / Off\n// • pick a target → Whole agenda / Professional / Service / Location\n// • pick an import mode → Block / Appointment\n// Every change is persisted immediately via saveChannel (RLS upsert on\n// integration_id + google_calendar_id), snapshotting the calendar summary+color\n// onto the channel. Target ids come from real host lookups (useAgendaLookups);\n// if a lookup is empty for the tenant the row degrades to a raw uuid input.\nimport React, { useCallback, useEffect, useState } from 'react'\nimport { Loader2, AlertCircle, RefreshCw } from 'lucide-react'\nimport {\n Button,\n Checkbox,\n Badge,\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n toast,\n} from '@fayz-ai/ui'\nimport type { GoogleCalendarProvider } from '../data/supabase'\nimport type {\n CalendarChannel,\n ChannelDirection,\n ChannelTargetKind,\n ChannelImportMode,\n GoogleCalendarListEntry,\n} from '../types'\nimport { CalendarColorDot } from './CalendarColorDot'\nimport { useAgendaLookups, optionsForKind } from './useAgendaLookups'\n\nconst DIRECTION_LABELS: Record<ChannelDirection, string> = {\n bidirectional: 'Two-way',\n inbound: 'Import only',\n outbound: 'Export only',\n off: 'Off',\n}\nconst IMPORT_MODE_LABELS: Record<ChannelImportMode, string> = {\n block: 'Block',\n appointment: 'Appointment',\n}\n// 'agenda' is the UI sentinel for the whole-agenda target (target_kind = null).\nconst TARGET_KIND_LABELS: Record<'agenda' | 'assignee' | 'service' | 'location', string> = {\n agenda: 'Whole agenda',\n assignee: 'Professional',\n service: 'Service',\n location: 'Location',\n}\nconst NO_TARGET = '__none__'\n\n/** Defaults for a freshly-enabled calendar (mirror the migration defaults). */\nfunction defaultChannel(): {\n direction: ChannelDirection\n targetKind: ChannelTargetKind\n targetId: string | null\n importMode: ChannelImportMode\n} {\n return { direction: 'bidirectional', targetKind: null, targetId: null, importMode: 'block' }\n}\n\nexport function ChannelMappingList({\n provider,\n onChannelsChange,\n}: {\n provider: GoogleCalendarProvider\n /** Bubble the current channels up so the parent can gate the import wizard. */\n onChannelsChange?: (channels: CalendarChannel[]) => void\n}) {\n const [calendars, setCalendars] = useState<GoogleCalendarListEntry[]>([])\n const [byGcalId, setByGcalId] = useState<Record<string, CalendarChannel>>({})\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [savingId, setSavingId] = useState<string | null>(null)\n\n const { lookups, hasAny: hasLookups } = useAgendaLookups(true)\n\n const load = useCallback(async () => {\n setLoading(true)\n setError(null)\n try {\n const [cals, channels] = await Promise.all([\n provider.listGoogleCalendars(),\n provider.listChannels(),\n ])\n setCalendars(cals)\n const map: Record<string, CalendarChannel> = {}\n for (const ch of channels) map[ch.googleCalendarId] = ch\n setByGcalId(map)\n onChannelsChange?.(channels)\n } catch (e: any) {\n setError(e?.message ?? 'Could not load Google calendars')\n } finally {\n setLoading(false)\n }\n }, [provider, onChannelsChange])\n\n useEffect(() => {\n void load()\n }, [load])\n\n /** Persist a patch for one calendar, then refresh channels (keeps ids correct). */\n const persist = useCallback(\n async (\n cal: GoogleCalendarListEntry,\n patch: {\n direction?: ChannelDirection\n targetKind?: ChannelTargetKind\n targetId?: string | null\n importMode?: ChannelImportMode\n isActive?: boolean\n },\n ) => {\n const existing = byGcalId[cal.id]\n const base = existing ?? { ...defaultChannel(), isActive: true }\n setSavingId(cal.id)\n try {\n await provider.saveChannel({\n id: existing?.id,\n googleCalendarId: cal.id,\n summary: cal.summary,\n color: cal.backgroundColor ?? null,\n direction: patch.direction ?? base.direction,\n targetKind: patch.targetKind !== undefined ? patch.targetKind : base.targetKind,\n targetId: patch.targetId !== undefined ? patch.targetId : base.targetId ?? null,\n importMode: patch.importMode ?? base.importMode,\n isActive: patch.isActive !== undefined ? patch.isActive : base.isActive,\n })\n const channels = await provider.listChannels()\n const map: Record<string, CalendarChannel> = {}\n for (const ch of channels) map[ch.googleCalendarId] = ch\n setByGcalId(map)\n onChannelsChange?.(channels)\n } catch (e: any) {\n toast.error(e?.message ?? 'Could not save calendar mapping')\n } finally {\n setSavingId(null)\n }\n },\n [byGcalId, provider, onChannelsChange],\n )\n\n if (loading) {\n return (\n <div className=\"py-6 text-center text-sm text-muted-foreground\">\n <Loader2 className=\"h-4 w-4 animate-spin inline\" />\n </div>\n )\n }\n\n if (error) {\n return (\n <div className=\"rounded-md border border-warning/40 bg-warning-soft/40 px-3 py-3 text-sm\">\n <div className=\"flex items-center gap-2 text-warning-soft-foreground\">\n <AlertCircle className=\"h-4 w-4\" /> {error}\n </div>\n <Button variant=\"outline\" size=\"sm\" className=\"mt-2\" onClick={() => void load()}>\n <RefreshCw className=\"h-3.5 w-3.5\" /> Retry\n </Button>\n </div>\n )\n }\n\n if (calendars.length === 0) {\n return (\n <p className=\"py-6 text-center text-sm text-muted-foreground\">\n No Google calendars found on this account.\n </p>\n )\n }\n\n return (\n <div className=\"rounded-md border divide-y\">\n {calendars.map((cal) => {\n const ch = byGcalId[cal.id]\n const active = !!ch?.isActive\n const saving = savingId === cal.id\n const direction: ChannelDirection = ch?.direction ?? 'bidirectional'\n const targetKind: ChannelTargetKind = ch?.targetKind ?? null\n const importMode: ChannelImportMode = ch?.importMode ?? 'block'\n // Import mode only matters when Google can write into the agenda.\n const canImport = direction === 'inbound' || direction === 'bidirectional'\n const kindOptions = optionsForKind(lookups, targetKind)\n\n return (\n <div key={cal.id} className=\"px-3 py-3 space-y-3\">\n <div className=\"flex items-center gap-2.5\">\n <Checkbox\n checked={active}\n disabled={saving}\n onChange={(next) => void persist(cal, { isActive: next })}\n />\n <CalendarColorDot color={cal.backgroundColor} />\n <span className=\"text-sm font-medium truncate\">{cal.summary}</span>\n {cal.primary && (\n <Badge variant=\"outline\" className=\"shrink-0\">\n Primary\n </Badge>\n )}\n {saving && <Loader2 className=\"ml-auto h-3.5 w-3.5 animate-spin text-muted-foreground\" />}\n </div>\n\n {active && (\n <div className=\"grid gap-2 pl-[26px] sm:grid-cols-2 lg:grid-cols-4\">\n {/* Direction */}\n <label className=\"block\">\n <span className=\"text-[11px] font-medium text-muted-foreground\">Direction</span>\n <Select\n value={direction}\n onValueChange={(v) => void persist(cal, { direction: v as ChannelDirection })}\n >\n <SelectTrigger className=\"mt-1 h-8 text-sm\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {(Object.keys(DIRECTION_LABELS) as ChannelDirection[]).map((d) => (\n <SelectItem key={d} value={d}>\n {DIRECTION_LABELS[d]}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n\n {/* Target kind */}\n <label className=\"block\">\n <span className=\"text-[11px] font-medium text-muted-foreground\">Target</span>\n <Select\n value={targetKind ?? 'agenda'}\n onValueChange={(v) =>\n void persist(cal, {\n targetKind: v === 'agenda' ? null : (v as ChannelTargetKind),\n // Reset the id whenever the kind changes.\n targetId: null,\n })\n }\n >\n <SelectTrigger className=\"mt-1 h-8 text-sm\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {(Object.keys(TARGET_KIND_LABELS) as Array<keyof typeof TARGET_KIND_LABELS>).map(\n (k) => (\n <SelectItem key={k} value={k}>\n {TARGET_KIND_LABELS[k]}\n </SelectItem>\n ),\n )}\n </SelectContent>\n </Select>\n </label>\n\n {/* Target id — real picker when we have lookups, uuid input otherwise */}\n {targetKind && (\n <label className=\"block\">\n <span className=\"text-[11px] font-medium text-muted-foreground\">\n {TARGET_KIND_LABELS[targetKind]}\n </span>\n {kindOptions.length > 0 ? (\n <Select\n value={ch?.targetId ?? NO_TARGET}\n onValueChange={(v) =>\n void persist(cal, { targetId: v === NO_TARGET ? null : v })\n }\n >\n <SelectTrigger className=\"mt-1 h-8 text-sm\">\n <SelectValue placeholder=\"Select…\" />\n </SelectTrigger>\n <SelectContent>\n {kindOptions.map((o) => (\n <SelectItem key={o.id} value={o.id}>\n {o.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : (\n <input\n defaultValue={ch?.targetId ?? ''}\n placeholder=\"uuid\"\n onBlur={(e) =>\n void persist(cal, { targetId: e.target.value.trim() || null })\n }\n className=\"w-full mt-1 h-8 rounded-input border border-input bg-card px-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n )}\n </label>\n )}\n\n {/* Import mode — only when inbound */}\n {canImport && (\n <label className=\"block\">\n <span className=\"text-[11px] font-medium text-muted-foreground\">Import as</span>\n <Select\n value={importMode}\n onValueChange={(v) => void persist(cal, { importMode: v as ChannelImportMode })}\n >\n <SelectTrigger className=\"mt-1 h-8 text-sm\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {(Object.keys(IMPORT_MODE_LABELS) as ChannelImportMode[]).map((m) => (\n <SelectItem key={m} value={m}>\n {IMPORT_MODE_LABELS[m]}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n )}\n </div>\n )}\n </div>\n )\n })}\n {!hasLookups && (\n <p className=\"px-3 py-2 text-[11px] text-muted-foreground\">\n No professional/service/location lookups available — target ids fall back to manual uuid\n entry.\n </p>\n )}\n </div>\n )\n}\n","// Import wizard — pull FUTURE Google events into the agenda as blocks/appointments.\n//\n// listExternalEvents() returns events on the active inbound channels that are not\n// yet linked to an appointment. The user ticks the ones to bring in and confirms;\n// importEvents() runs them through gcal_import_event (honouring each channel's\n// import_mode + target) and returns a per-item tally {imported, skipped, errors}.\n// Events show their source calendar as a colored badge and an \"All-day\" badge\n// when applicable; times are formatted pt-BR.\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { Loader2, CalendarPlus, CheckCircle2, AlertCircle, RefreshCw, X } from 'lucide-react'\nimport { Button, Checkbox, Badge, toast } from '@fayz-ai/ui'\nimport type { GoogleCalendarProvider } from '../data/supabase'\nimport type { CalendarChannel, ExternalEventPreview, ImportEventsResult } from '../types'\nimport { CalendarColorDot } from './CalendarColorDot'\n\n/** pt-BR datetime label, all-day aware (date only for all-day events). */\nfunction formatWhen(ev: ExternalEventPreview): string {\n const start = new Date(ev.startsAt)\n if (ev.allDay) {\n return start.toLocaleDateString('pt-BR', { day: '2-digit', month: 'short', year: 'numeric' })\n }\n return start.toLocaleString('pt-BR', {\n day: '2-digit',\n month: 'short',\n hour: '2-digit',\n minute: '2-digit',\n })\n}\n\nexport function ImportEventsWizard({\n provider,\n channels,\n onClose,\n onImported,\n}: {\n provider: GoogleCalendarProvider\n /** Active channels — used to label each event with its source calendar + color. */\n channels: CalendarChannel[]\n onClose: () => void\n /** Fired after a successful import so the parent can refresh status/history. */\n onImported?: (result: ImportEventsResult) => void\n}) {\n const [events, setEvents] = useState<ExternalEventPreview[]>([])\n const [selected, setSelected] = useState<Set<string>>(new Set())\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [importing, setImporting] = useState(false)\n const [result, setResult] = useState<ImportEventsResult | null>(null)\n\n const channelById = useMemo(() => {\n const m: Record<string, CalendarChannel> = {}\n for (const c of channels) m[c.id] = c\n return m\n }, [channels])\n\n const load = useCallback(async () => {\n setLoading(true)\n setError(null)\n setResult(null)\n try {\n const rows = await provider.listExternalEvents()\n setEvents(rows)\n setSelected(new Set(rows.map((r) => r.eventId)))\n } catch (e: any) {\n setError(e?.message ?? 'Could not load upcoming events')\n } finally {\n setLoading(false)\n }\n }, [provider])\n\n useEffect(() => {\n void load()\n }, [load])\n\n const toggle = (eventId: string) =>\n setSelected((prev) => {\n const next = new Set(prev)\n if (next.has(eventId)) next.delete(eventId)\n else next.add(eventId)\n return next\n })\n\n const allSelected = events.length > 0 && selected.size === events.length\n const toggleAll = () =>\n setSelected(allSelected ? new Set() : new Set(events.map((e) => e.eventId)))\n\n async function handleImport() {\n const items = events\n .filter((e) => selected.has(e.eventId))\n .map((e) => ({ channelId: e.channelId, eventId: e.eventId }))\n if (items.length === 0) return\n setImporting(true)\n try {\n const res = await provider.importEvents(items)\n setResult(res)\n onImported?.(res)\n toast.success(`Imported ${res.imported} · skipped ${res.skipped}`)\n // Drop imported events from the list so the wizard reflects the new state.\n await load()\n } catch (e: any) {\n toast.error(e?.message ?? 'Import failed')\n } finally {\n setImporting(false)\n }\n }\n\n return (\n <div className=\"rounded-md border bg-card\">\n <div className=\"flex items-center gap-2 border-b px-3 py-2\">\n <CalendarPlus className=\"h-4 w-4 text-muted-foreground\" />\n <h4 className=\"text-sm font-semibold\">Import future events</h4>\n <button\n onClick={onClose}\n className=\"ml-auto rounded p-1 text-muted-foreground hover:bg-muted/50\"\n aria-label=\"Close\"\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n\n {loading ? (\n <div className=\"py-8 text-center text-sm text-muted-foreground\">\n <Loader2 className=\"h-4 w-4 animate-spin inline\" />\n </div>\n ) : error ? (\n <div className=\"p-3\">\n <div className=\"flex items-center gap-2 text-sm text-warning-soft-foreground\">\n <AlertCircle className=\"h-4 w-4\" /> {error}\n </div>\n <Button variant=\"outline\" size=\"sm\" className=\"mt-2\" onClick={() => void load()}>\n <RefreshCw className=\"h-3.5 w-3.5\" /> Retry\n </Button>\n </div>\n ) : events.length === 0 ? (\n <div className=\"py-8 px-4 text-center space-y-1\">\n <p className=\"text-sm font-medium\">You're all caught up</p>\n <p className=\"text-xs text-muted-foreground\">\n No upcoming Google events left to import on your active calendars.\n </p>\n {result && (\n <p className=\"text-xs text-success\">\n Imported {result.imported} · skipped {result.skipped}\n {result.errors.length > 0 ? ` · ${result.errors.length} errors` : ''}\n </p>\n )}\n </div>\n ) : (\n <>\n <div className=\"flex items-center gap-2.5 border-b px-3 py-2\">\n <Checkbox checked={allSelected} onChange={toggleAll} />\n <span className=\"text-xs text-muted-foreground\">\n {selected.size} of {events.length} selected\n </span>\n </div>\n <div className=\"max-h-[320px] overflow-y-auto divide-y\">\n {events.map((ev) => {\n const ch = channelById[ev.channelId]\n return (\n <label\n key={ev.eventId}\n className=\"flex items-start gap-2.5 px-3 py-2.5 cursor-pointer hover:bg-muted/30\"\n >\n <Checkbox\n checked={selected.has(ev.eventId)}\n onChange={() => toggle(ev.eventId)}\n />\n <div className=\"min-w-0 flex-1 space-y-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium truncate\">\n {ev.summary || '(no title)'}\n </span>\n {ev.allDay && (\n <Badge variant=\"secondary\" className=\"shrink-0\">\n All-day\n </Badge>\n )}\n </div>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span>{formatWhen(ev)}</span>\n <span className=\"inline-flex items-center gap-1\">\n <CalendarColorDot color={ch?.color} />\n {ch?.summary ?? ev.calendarId}\n </span>\n </div>\n </div>\n </label>\n )\n })}\n </div>\n <div className=\"flex items-center gap-2 border-t px-3 py-2\">\n {result && (\n <span className=\"text-xs text-muted-foreground\">\n Last run: {result.imported} imported\n {result.errors.length > 0 ? `, ${result.errors.length} errors` : ''}\n </span>\n )}\n <Button\n size=\"sm\"\n className=\"ml-auto\"\n disabled={importing || selected.size === 0}\n onClick={handleImport}\n >\n {importing ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n )}\n Import {selected.size > 0 ? selected.size : ''}\n </Button>\n </div>\n </>\n )}\n </div>\n )\n}\n","// Google Calendar as a unified ConnectorDefinition.\n//\n// Surfaces inside plugin-agenda's settings → Integrations tab (the host),\n// rendered by the shared ConnectorsHub. The hub handles the OAuth connect/\n// disconnect; the ExtraPanel below adds the calendar picker, manual sync and\n// run history (only meaningful once connected).\nimport React, { useEffect, useState } from 'react'\nimport { RefreshCw, History, CheckCircle2, AlertCircle, Loader2, CalendarCog, CalendarPlus } from 'lucide-react'\nimport { Button, toast } from '@fayz-ai/ui'\nimport type { ConnectorDefinition } from '@fayz-ai/core'\nimport { createGoogleCalendarProvider } from './data/supabase'\nimport type { CalendarChannel, CalendarSyncLogEntry } from './types'\nimport { ChannelMappingList } from './components/ChannelMappingList'\nimport { ImportEventsWizard } from './components/ImportEventsWizard'\n\nconst provider = createGoogleCalendarProvider()\n\n/** Channels Google is allowed to write INTO the agenda from (gate the import wizard). */\nfunction inboundChannels(channels: CalendarChannel[]): CalendarChannel[] {\n return channels.filter(\n (c) => c.isActive && (c.direction === 'inbound' || c.direction === 'bidirectional'),\n )\n}\n\nfunction GoogleCalendarExtraPanel() {\n const [connected, setConnected] = useState(false)\n const [lastSyncAt, setLastSyncAt] = useState<string | undefined>()\n const [syncing, setSyncing] = useState(false)\n const [log, setLog] = useState<CalendarSyncLogEntry[]>([])\n const [loaded, setLoaded] = useState(false)\n const [channels, setChannels] = useState<CalendarChannel[]>([])\n // Progressive disclosure: once connected the de-para is opened either on the\n // \"Configure calendars\" CTA or automatically when channels already exist.\n const [showMapping, setShowMapping] = useState(false)\n const [showWizard, setShowWizard] = useState(false)\n\n async function load() {\n const integ = await provider.getIntegration()\n setConnected(!!integ?.connected)\n if (integ) {\n setLastSyncAt(integ.lastSyncAt)\n void provider.getSyncLog().then(setLog)\n void provider.listChannels().then((ch) => {\n setChannels(ch)\n if (ch.length > 0) setShowMapping(true)\n })\n }\n setLoaded(true)\n }\n useEffect(() => { void load() }, [])\n\n // Before connecting there's nothing to configure here — a short hint only.\n if (!loaded) return null\n if (!connected) {\n return (\n <p className=\"text-xs text-muted-foreground border-t pt-4\">\n Connect a Google account above to map your calendars and import events.\n </p>\n )\n }\n\n async function handleSyncNow() {\n setSyncing(true)\n try {\n const r = await provider.syncNow()\n toast.success(`Synced — ${r.written} updated`)\n void provider.getSyncLog().then(setLog)\n void provider.getIntegration().then((i) => setLastSyncAt(i?.lastSyncAt))\n } catch (e: any) { toast.error(e?.message ?? 'Sync failed') }\n finally { setSyncing(false) }\n }\n\n const canImport = inboundChannels(channels).length > 0\n\n return (\n <div className=\"space-y-5 border-t pt-4\">\n {/* 1 — De-para (mapping). CTA first when nothing is configured yet. */}\n <section className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <CalendarCog className=\"h-4 w-4 text-muted-foreground\" />\n <h4 className=\"text-sm font-semibold\">Calendars</h4>\n </div>\n {showMapping ? (\n <ChannelMappingList provider={provider} onChannelsChange={setChannels} />\n ) : (\n <div className=\"rounded-md border border-dashed px-4 py-5 text-center space-y-2\">\n <p className=\"text-sm text-muted-foreground\">\n Map each Google calendar to what it syncs — a professional, service, location, or your\n whole agenda.\n </p>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setShowMapping(true)}>\n <CalendarCog className=\"h-3.5 w-3.5\" /> Configure calendars\n </Button>\n </div>\n )}\n </section>\n\n {/* 2 — Import future events (only meaningful once an inbound channel exists). */}\n {showMapping && (\n <section className=\"space-y-2\">\n {showWizard ? (\n <ImportEventsWizard\n provider={provider}\n channels={inboundChannels(channels)}\n onClose={() => setShowWizard(false)}\n onImported={() => {\n void provider.getSyncLog().then(setLog)\n void provider.getIntegration().then((i) => setLastSyncAt(i?.lastSyncAt))\n }}\n />\n ) : (\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={!canImport}\n title={canImport ? undefined : 'Enable an importing calendar first'}\n onClick={() => setShowWizard(true)}\n >\n <CalendarPlus className=\"h-3.5 w-3.5\" /> Import future events\n </Button>\n )}\n </section>\n )}\n\n {/* 3 — Status: last sync + manual pull + run history. */}\n <section className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button variant=\"outline\" size=\"sm\" onClick={handleSyncNow} disabled={syncing}>\n <RefreshCw className={`h-3.5 w-3.5 ${syncing ? 'animate-spin' : ''}`} /> Sync now\n </Button>\n {lastSyncAt && (\n <span className=\"text-[11px] text-muted-foreground\">\n Last sync: {new Date(lastSyncAt).toLocaleString()}\n </span>\n )}\n </div>\n\n {log.length > 0 && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <History className=\"h-4 w-4 text-muted-foreground\" />\n <h4 className=\"text-sm font-semibold\">History</h4>\n </div>\n <div className=\"rounded-md border divide-y text-sm\">\n {log.map((r) => (\n <div key={r.id} className=\"flex items-center gap-3 px-3 py-2\">\n <span className=\"text-muted-foreground text-xs\">{new Date(r.createdAt).toLocaleString()}</span>\n <span className=\"text-[10px] uppercase tracking-wide px-1 py-px rounded bg-muted text-muted-foreground\">{r.direction}</span>\n <span className=\"ml-auto text-xs\">{r.written} written / {r.fetched} fetched</span>\n {r.status === 'success'\n ? <CheckCircle2 className=\"h-3.5 w-3.5 text-success\" />\n : <AlertCircle className=\"h-3.5 w-3.5 text-warning\" />}\n </div>\n ))}\n </div>\n </div>\n )}\n </section>\n </div>\n )\n}\n\nexport const googleCalendarConnectorDef: ConnectorDefinition = {\n id: 'google-calendar',\n hostPluginId: 'agenda',\n name: 'Google Calendar',\n description: 'Two-way sync between your bookings and Google Calendar.',\n icon: 'Calendar',\n authKind: 'oauth',\n category: 'scheduling',\n direction: 'outbound',\n // Sync only, and deliberately: the agenda has to exist inside the app — to be\n // listed, filtered, reported on, and read when Google is unreachable. An\n // agentic plane would answer questions but leave the calendar screen empty.\n planes: ['sync'],\n entities: ['booking'],\n docsUrl: 'https://support.google.com/calendar',\n async getStatus() {\n const integ = await provider.getIntegration()\n return { connected: !!integ?.connected }\n },\n startOAuth: (redirectTo) => provider.getConnectUrl(redirectTo),\n disconnect: () => provider.disconnect(),\n ExtraPanel: GoogleCalendarExtraPanel,\n}\n","// Google Calendar connector descriptor (control-plane metadata).\n//\n// Declares the connector against the SDK integration spine so the platform can\n// reason about what it syncs. The actual data-plane verbs run in the\n// google-calendar-sync edge function; this is the typed contract + capabilities.\nimport type { Connector } from '@fayz-ai/core'\n\nexport const googleCalendarConnector: Connector = {\n id: 'google-calendar',\n provider: 'google',\n pluginId: 'agenda',\n authKind: 'oauth',\n capabilities: [\n {\n entity: 'booking',\n direction: 'bidirectional',\n triggers: ['on-write', 'scheduled', 'webhook'],\n },\n ],\n}\n","// Google Calendar integration — official (in-SDK) addon for plugin-agenda.\n//\n// Settings-only PluginManifest: contributes a \"Google Calendar\" tab to /settings\n// for connecting an account and running a manual sync. Outbound (booking →\n// Google) is automatic via a DB trigger; inbound (Google → booking) via pg_cron\n// or a Google watch webhook. The data plane is the google-calendar-sync edge\n// function (see ./functions/google-calendar-sync). The booking↔event link lives\n// on public.appointments.metadata.googleCalendarEventId.\n//\n// Graduation path: extract to its own `@fayz-ai/plugin-google-calendar` package.\nimport type { PluginManifest } from '@fayz-ai/core'\nimport { googleCalendarConnectorDef } from './connectorDef'\n\nexport { createGoogleCalendarProvider } from './data/supabase'\nexport { googleCalendarConnector } from './connector'\nexport { googleCalendarConnectorDef } from './connectorDef'\nexport {\n bookingToEvent,\n eventToBookingPatch,\n bookingSummary,\n appointmentRowToEvent,\n eventToAppointmentPatch,\n eventTimes,\n resolveTargetChannel,\n channelRowToChannel,\n} from './mapping'\nexport * from './types'\n\n// Addon plugin: contributes the Google Calendar connector into its host\n// (plugin-agenda). It appears in Agenda settings → Integrations — no top-level\n// settings tab of its own. See packages/saas ConnectorsHub.\nexport function createGoogleCalendarPlugin(): PluginManifest {\n return {\n id: 'google-calendar',\n name: 'Google Calendar',\n icon: 'Calendar',\n version: '0.1.0',\n scope: 'addon',\n defaultEnabled: true,\n dependencies: ['agenda'],\n navigation: [],\n routes: [],\n connectors: [googleCalendarConnectorDef],\n }\n}\n","import React from 'react'\nimport type { PluginManifest } from '@fayz-ai/core'\nimport { createSafeDataProvider, registerTranslations, registerMessageDefaults } from '@fayz-ai/core'\nimport { buildAgendaDomainEvents, buildAgendaMessageDefaults } from './lib/message-events'\nimport type { AgendaPluginOptions } from './config'\nimport { resolveConfig } from './config'\nimport { AgendaPage } from './views/AgendaPage'\nimport { createSupabaseAgendaProvider } from './data/supabase'\nimport { createMockAgendaProvider } from './data/mock'\nimport { setAgendaTenantId } from './lib/tenant'\nimport { createAgendaStore } from './store'\nimport { agendaRegistries } from './data/registries'\nimport { AgendaGeneralSettings } from './components/AgendaGeneralSettings'\nimport { agendaLocales } from './locales'\nimport { MIGRATION_001_PUBLIC_BOOKING } from './migrations'\nimport { setScheduleBlockConfig, getScheduleBlockConfig, PluginSettingsPanel } from '@fayz-ai/admin'\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createAgendaPlugin(options?: AgendaPluginOptions): PluginManifest {\n const config = resolveConfig(options)\n registerTranslations(agendaLocales)\n // O texto sugerido para cada fato da agenda. Os FATOS vão no manifesto\n // (`events`), de onde automações, integrações e auditoria leem o mesmo\n // contrato.\n registerMessageDefaults(buildAgendaMessageDefaults())\n const provider = options?.dataProvider ?? createSafeDataProvider(\n () => createSupabaseAgendaProvider({ professionalKind: config.professionalKind }),\n () => createMockAgendaProvider(),\n )\n const store = createAgendaStore(provider, options?.financialBridge)\n const registries = [...agendaRegistries, ...(options?.settingsRegistries ?? [])]\n\n // Register schedule block config globally so ScheduleEditor can read it\n setScheduleBlockConfig({\n defaults: config.scheduleBlockDefaults,\n showServices: !!config.serviceLookup,\n showConcurrent: true,\n showBookingWindow: true,\n showLocations: config.modules.locationSelection,\n locations: config.locations.map((l) => ({ id: l.id, name: l.name })),\n // Lazy fetcher — called by ScheduleEditor when locations are needed but empty\n fetchLocations: config.modules.locationSelection && provider.getLocations\n ? async () => {\n const locations = await provider.getLocations!()\n const current = getScheduleBlockConfig()\n if (current) setScheduleBlockConfig({ ...current, locations })\n return locations\n }\n : undefined,\n })\n\n const PageComponent: React.FC<any> = () =>\n React.createElement(AgendaPage, { config, provider, store })\n\n return {\n id: 'agenda',\n name: config.labels.pageTitle,\n icon: 'Calendar',\n version: '1.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n // Booking/scheduling is business-ops (clinic, salon, services) — targets\n // the saas/admin Panel world, not the ecommerce storefront.\n scaffolds: ['saas'],\n defaultEnabled: true,\n dependencies: [],\n // Os FATOS da agenda — só expostos enquanto o módulo está ATIVO.\n events: buildAgendaDomainEvents(),\n declaredFeatures: [\n { id: 'appointments', label: config.labels.pageTitle, group: config.labels.pageTitle },\n { id: 'agenda.schedules', label: 'Schedule Management', group: config.labels.pageTitle },\n ],\n // Recurring monthly quota — counts appointment rows created this month.\n // (Clients/patients are the app's CRUD entity, so their cap is declared by\n // the app's EntityDef.limitKey, not here.)\n declaredLimits: [\n { key: 'bookings_month', label: 'Appointments this month', table: 'appointments', period: 'month' },\n ],\n queryEntities: [\n {\n key: 'agenda:appointments',\n entity: {\n name: 'Appointment',\n namePlural: 'Appointments',\n icon: 'Calendar',\n permission: { feature: 'appointments', action: 'read' },\n // Keys are the PROVIDER's output shape (camelCase) — what filters/\n // dateField/groupBy match against, not the raw DB columns.\n fields: [\n { key: 'startsAt', label: 'Starts at', type: 'text' },\n { key: 'endsAt', label: 'Ends at', type: 'text' },\n { key: 'status', label: 'Status', type: 'text' },\n { key: 'clientName', label: 'Client', type: 'text', searchable: true },\n { key: 'professionalName', label: 'Professional', type: 'text', searchable: true },\n { key: 'orderTotal', label: 'Order total', type: 'number' },\n { key: 'totalDurationMinutes', label: 'Duration (min)', type: 'number' },\n { key: 'createdAt', label: 'Created at', type: 'text' },\n ],\n data: {\n table: 'v_appointments',\n tenantScoped: true,\n searchColumns: ['client_name', 'professional_name'],\n },\n },\n },\n ],\n declaredRpcs: [\n {\n name: 'agent_agenda_create_appointment',\n kind: 'write' as const,\n description:\n 'Guarded appointment create: agent_guard (role→plan→bookings_month cap), working hours, race-safe conflict check, audited.',\n audits: true,\n },\n {\n name: 'agent_agenda_update_appointment',\n kind: 'write' as const,\n description:\n 'Guarded appointment reschedule/reassign/cancel: agent_guard (role→plan, no cap), working hours, race-safe conflict check that skips the appointment itself, audited.',\n audits: true,\n },\n ],\n\n navigation: [\n {\n section: options?.navSection ?? 'main',\n position: options?.navPosition ?? 2,\n label: config.labels.pageTitle,\n route: '/agenda',\n icon: 'Calendar',\n permission: { feature: 'appointments', action: 'read' as const },\n },\n ],\n\n routes: [\n {\n path: '/agenda',\n component: PageComponent,\n permission: { feature: 'appointments', action: 'read' as const },\n // Matches the ref agent_agenda_create_appointment returns.\n entityRoutes: ['schedule:appointment'],\n },\n ],\n\n widgets: [],\n\n aiTools: [\n {\n id: 'agenda.list-appointments',\n name: 'listAppointments',\n description: 'Lists upcoming appointments for a given date or date range, optionally filtered by professional.',\n icon: 'Calendar',\n mode: 'read' as const,\n category: 'Scheduling',\n parameters: {\n type: 'object' as const,\n properties: {\n date: { type: 'string' as const, description: 'Date (YYYY-MM-DD) or \"today\", \"tomorrow\", \"this week\"' },\n professional: { type: 'string' as const, description: 'Professional name to filter by' },\n },\n },\n suggestions: [\n { label: \"What's on the agenda today?\" },\n { label: 'Show me tomorrow\\'s appointments' },\n { label: 'Who has the most bookings this week?' },\n ],\n permission: { feature: 'appointments', action: 'read' as const },\n },\n {\n id: 'agenda.create-appointment',\n name: 'createAppointment',\n description:\n 'Creates a new appointment. Takes IDS, not names: resolve the client/service/professional ids first via findAnything/searchRecords, then call this with an ISO start time in the tenant timezone. The user confirms before booking.',\n icon: 'CalendarPlus',\n mode: 'persist' as const,\n limitKey: 'bookings_month',\n execution: { plane: 'server' as const, kind: 'rpc' as const, rpc: 'agent_agenda_create_appointment' },\n category: 'Scheduling',\n parameters: {\n type: 'object' as const,\n properties: {\n client_id: { type: 'string' as const, description: 'Client id (from a search)' },\n service_id: { type: 'string' as const, description: 'Service id (from a search)' },\n professional_id: { type: 'string' as const, description: 'Professional id (optional — auto-assigned when omitted)' },\n starts_at: { type: 'string' as const, description: \"LOCAL date-time of the business, NO timezone suffix — e.g. '2026-07-27T10:00' for 10h. The system applies the tenant timezone.\" },\n notes: { type: 'string' as const, description: 'Optional notes' },\n },\n required: ['client_id', 'service_id', 'starts_at'],\n },\n suggestions: [\n { label: 'Book a haircut for Sarah tomorrow at 10am' },\n ],\n permission: { feature: 'appointments', action: 'create' as const },\n },\n {\n id: 'agenda.update-appointment',\n name: 'updateAppointment',\n description:\n 'Changes an appointment that ALREADY EXISTS: reschedule (starts_at), reassign (professional_id), cancel or confirm (status), or annotate (notes). ' +\n 'This is the ONLY way to change an appointment — the appointments entity is a read-only view, so updateRecord cannot touch it. ' +\n 'NEVER answer a reschedule or a cancellation by creating a new appointment: that leaves the original standing and double-books the professional. ' +\n 'Takes the appointment id from a previous search. The duration is preserved automatically. The user confirms before anything changes.',\n icon: 'CalendarClock',\n mode: 'persist' as const,\n execution: { plane: 'server' as const, kind: 'rpc' as const, rpc: 'agent_agenda_update_appointment' },\n category: 'Scheduling',\n parameters: {\n type: 'object' as const,\n properties: {\n appointment_id: { type: 'string' as const, description: 'Id of the appointment to change (from a search)' },\n starts_at: { type: 'string' as const, description: \"New LOCAL date-time of the business, NO timezone suffix — e.g. '2026-07-27T16:30'. Omit to keep the current time.\" },\n professional_id: { type: 'string' as const, description: 'Move to another professional (optional)' },\n status: {\n type: 'string' as const,\n description: 'New status — use \"cancelled\" to cancel',\n enum: ['scheduled', 'confirmed', 'in_progress', 'completed', 'cancelled', 'no_show'],\n },\n notes: { type: 'string' as const, description: 'Optional notes' },\n },\n required: ['appointment_id'],\n },\n suggestions: [\n { label: 'Remarca o Gustavo para 16:30' },\n { label: 'Cancela o atendimento das 10h' },\n ],\n permission: { feature: 'appointments', action: 'edit' as const },\n },\n {\n id: 'agenda.check-availability',\n name: 'checkAvailability',\n description: 'Checks available time slots for a professional on a given date.',\n icon: 'Clock',\n mode: 'read' as const,\n category: 'Scheduling',\n parameters: {\n type: 'object' as const,\n properties: {\n professional: { type: 'string' as const, description: 'Professional name' },\n date: { type: 'string' as const, description: 'Date (YYYY-MM-DD) or \"today\", \"tomorrow\"' },\n duration: { type: 'number' as const, description: 'Required duration in minutes' },\n },\n required: ['professional', 'date'],\n },\n suggestions: [\n { label: 'When is Ana available tomorrow?' },\n { label: 'Find a 90-minute slot for Carlos this week' },\n ],\n permission: { feature: 'appointments', action: 'read' as const },\n },\n ],\n\n registries,\n\n settings: [\n {\n id: 'agenda',\n label: 'Agenda',\n icon: 'Calendar',\n // Standard layout: General | Integrations (Google Calendar addon) | Properties.\n component: (() => {\n const AgendaSettingsTab: React.FC = () => React.createElement(PluginSettingsPanel, {\n title: 'Agenda',\n generalSettings: React.createElement(AgendaGeneralSettings),\n registries,\n hostPluginId: 'agenda',\n routeBase: '/settings/agenda',\n })\n AgendaSettingsTab.displayName = 'AgendaSettingsTab'\n return AgendaSettingsTab as unknown as React.ComponentType<unknown>\n })(),\n order: 5,\n permission: { feature: 'appointments', action: 'read' as const },\n },\n ],\n migrations: [\n {\n id: 'agenda-001-public-booking',\n version: '0.3.0',\n sql: MIGRATION_001_PUBLIC_BOOKING,\n description:\n 'Booking read model (v_appointments) + anon public booking surface (v_public_services, get_available_slots, create_public_booking) + order_items duration/assignee columns',\n },\n ],\n\n locales: agendaLocales,\n }\n}\n\n// Re-export types for consumers\nexport type { AgendaPluginOptions } from './config'\nexport type { ResolvedAgendaConfig } from './config'\nexport type { AgendaDataProvider } from './data/types'\n// Seedable in-memory provider — apps pass a seed to render the calendar with\n// app-specific events instead of the built-in salon sample.\nexport { createMockAgendaProvider } from './data/mock'\nexport type { MockAgendaSeed, MockAgendaProviderOptions } from './data/mock'\nexport type { AgendaFinancialBridge, BookingPaymentStatus, BookingPaymentSummary, BookingPaymentDetail } from './bridges/financial-bridge'\nexport { createFinancialBridge, computeCommissionAmount } from './bridges/create-financial-bridge'\n\n// Google Calendar integration (official addon) — settings-only plugin + helpers\nexport { createGoogleCalendarPlugin, createGoogleCalendarProvider, googleCalendarConnector, bookingToEvent, eventToBookingPatch } from './integrations/google-calendar'\n\n// O catálogo de fatos da agenda — exposto para quem quiser ler o contrato sem\n// instalar o módulo (documentação, testes, um consumidor de webhook).\nexport { buildAgendaDomainEvents, buildAgendaMessageDefaults } from './lib/message-events'\n"]}