@fayz-ai/admin 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ScheduleEditor-A3SX6AYD.js → ScheduleEditor-63TVSCJC.js} +5 -4
- package/dist/ScheduleEditor-63TVSCJC.js.map +1 -0
- package/dist/SubscriptionPage-5PJ25YAD.js +8 -0
- package/dist/{SubscriptionPage-FE2B5ZXF.js.map → SubscriptionPage-5PJ25YAD.js.map} +1 -1
- package/dist/access/context.d.ts +3 -1
- package/dist/access/context.d.ts.map +1 -1
- package/dist/app/AdminShell.d.ts +6 -0
- package/dist/app/AdminShell.d.ts.map +1 -1
- package/dist/app/admin-app.d.ts.map +1 -1
- package/dist/app/config.d.ts +16 -0
- package/dist/app/config.d.ts.map +1 -1
- package/dist/app/scaffold.d.ts.map +1 -1
- package/dist/billing/TrialWidget.d.ts +25 -0
- package/dist/billing/TrialWidget.d.ts.map +1 -0
- package/dist/billing/index.d.ts +2 -0
- package/dist/billing/index.d.ts.map +1 -1
- package/dist/billing/index.js +2 -1
- package/dist/billing/trial.d.ts +48 -0
- package/dist/billing/trial.d.ts.map +1 -0
- package/dist/chunk-7DFJEXCR.js +48 -0
- package/dist/chunk-7DFJEXCR.js.map +1 -0
- package/dist/chunk-ERDS4OJS.js +194 -0
- package/dist/chunk-ERDS4OJS.js.map +1 -0
- package/dist/{chunk-IPWXA46H.js → chunk-G5PBC5OB.js} +10 -9
- package/dist/chunk-G5PBC5OB.js.map +1 -0
- package/dist/{chunk-OOWP6W2I.js → chunk-LZRLWKJ2.js} +3 -2
- package/dist/chunk-LZRLWKJ2.js.map +1 -0
- package/dist/{chunk-OB7ZSTQD.js → chunk-WN6PGQSG.js} +9 -51
- package/dist/chunk-WN6PGQSG.js.map +1 -0
- package/dist/components/billing/SoftLimitBanner.d.ts.map +1 -1
- package/dist/components/chat/ChatFab.d.ts.map +1 -1
- package/dist/crud/CrudAgentSurface.d.ts +7 -0
- package/dist/crud/CrudAgentSurface.d.ts.map +1 -1
- package/dist/crud/CrudPage.d.ts.map +1 -1
- package/dist/handbook/HandbookAgentSurface.d.ts +2 -0
- package/dist/handbook/HandbookAgentSurface.d.ts.map +1 -0
- package/dist/handbook/HandbookProvider.d.ts +7 -0
- package/dist/handbook/HandbookProvider.d.ts.map +1 -0
- package/dist/handbook/NotebookPanel.d.ts +5 -0
- package/dist/handbook/NotebookPanel.d.ts.map +1 -0
- package/dist/handbook/backend.d.ts +42 -0
- package/dist/handbook/backend.d.ts.map +1 -0
- package/dist/handbook/index.d.ts +10 -0
- package/dist/handbook/index.d.ts.map +1 -0
- package/dist/handbook/store.d.ts +36 -0
- package/dist/handbook/store.d.ts.map +1 -0
- package/dist/handbook/types.d.ts +124 -0
- package/dist/handbook/types.d.ts.map +1 -0
- package/dist/hooks/useChat.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5266 -3549
- package/dist/index.js.map +1 -1
- package/dist/lib/ai-tool-handlers.d.ts.map +1 -1
- package/dist/onboarding/ActivationAgentSurface.d.ts +6 -0
- package/dist/onboarding/ActivationAgentSurface.d.ts.map +1 -0
- package/dist/onboarding/ActivationChecklistCard.d.ts +23 -0
- package/dist/onboarding/ActivationChecklistCard.d.ts.map +1 -0
- package/dist/onboarding/ActivationProvider.d.ts +17 -0
- package/dist/onboarding/ActivationProvider.d.ts.map +1 -0
- package/dist/onboarding/GettingStartedWidget.d.ts +5 -5
- package/dist/onboarding/activation.store.d.ts +53 -0
- package/dist/onboarding/activation.store.d.ts.map +1 -0
- package/dist/onboarding/backend.d.ts +14 -0
- package/dist/onboarding/backend.d.ts.map +1 -1
- package/dist/onboarding/checklist.d.ts +23 -0
- package/dist/onboarding/checklist.d.ts.map +1 -1
- package/dist/onboarding/guided-runner.d.ts +87 -0
- package/dist/onboarding/guided-runner.d.ts.map +1 -0
- package/dist/onboarding/guided.d.ts +27 -0
- package/dist/onboarding/guided.d.ts.map +1 -0
- package/dist/onboarding/handbook-seed.d.ts +70 -0
- package/dist/onboarding/handbook-seed.d.ts.map +1 -0
- package/dist/onboarding/index.d.ts +12 -3
- package/dist/onboarding/index.d.ts.map +1 -1
- package/dist/onboarding/programs.d.ts +78 -0
- package/dist/onboarding/programs.d.ts.map +1 -0
- package/dist/onboarding/submit.d.ts +7 -2
- package/dist/onboarding/submit.d.ts.map +1 -1
- package/dist/onboarding/tasks.d.ts +7 -0
- package/dist/onboarding/tasks.d.ts.map +1 -1
- package/dist/onboarding/useActivationWatch.d.ts +2 -0
- package/dist/onboarding/useActivationWatch.d.ts.map +1 -0
- package/dist/org/adapters/supabase.d.ts.map +1 -1
- package/dist/org/index.js +3 -2
- package/dist/tasks/components/TaskCard.d.ts.map +1 -1
- package/package.json +5 -5
- package/dist/ScheduleEditor-A3SX6AYD.js.map +0 -1
- package/dist/SubscriptionPage-FE2B5ZXF.js +0 -7
- package/dist/chunk-IPWXA46H.js.map +0 -1
- package/dist/chunk-OB7ZSTQD.js.map +0 -1
- package/dist/chunk-OOWP6W2I.js.map +0 -1
- package/dist/chunk-VN5NTK26.js +0 -36
- package/dist/chunk-VN5NTK26.js.map +0 -1
- package/dist/components/notes/NotesPanel.d.ts +0 -13
- package/dist/components/notes/NotesPanel.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../../src/org/adapters/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAQX,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAuC,WAAW,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../../src/org/adapters/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAQX,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAuC,WAAW,EAAE,MAAM,eAAe,CAAA;AAoGrF;iFACiF;AACjF,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;kFAC8E;IAC9E,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAoID,MAAM,WAAW,wBAAwB;IACvC,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;uDACmD;IACnD,KAAK,CAAC,EAAE,YAAY,EAAE,CAAA;IACtB;;gEAE4D;IAC5D,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB;;;;;;4DAMwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,wBAAwB,GAAG,UAAU,CAgdtF"}
|
package/dist/org/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { createMockOrgAdapter, createSupabaseOrgAdapter } from '../chunk-
|
|
2
|
-
export { ORG_CACHE_TTL_MS, OrgProvider, clearOrgSnapshot,
|
|
1
|
+
export { createMockOrgAdapter, createSupabaseOrgAdapter } from '../chunk-LZRLWKJ2.js';
|
|
2
|
+
export { ORG_CACHE_TTL_MS, OrgProvider, clearOrgSnapshot, readOrgSnapshot, useOrgAdapter, useOrgAdapterOptional, useTenant, useTenantOptional } from '../chunk-WN6PGQSG.js';
|
|
3
3
|
import '../chunk-VTEP2AQX.js';
|
|
4
|
+
export { getPersistedOrgId, useOrganizationStore } from '../chunk-7DFJEXCR.js';
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskCard.d.ts","sourceRoot":"","sources":["../../../src/tasks/components/TaskCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"TaskCard.d.ts","sourceRoot":"","sources":["../../../src/tasks/components/TaskCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AA6BpC,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,YAAY,EAGZ,UAAiB,GAClB,EAAE;IACD,IAAI,EAAE,IAAI,CAAA;IACV,YAAY,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9C,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,qBA0FA"}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"fayz": {
|
|
4
4
|
"status": "beta"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.17.0",
|
|
7
7
|
"description": "Fayz SDK admin layer — the admin shell, CRUD engine, multi-tenancy, billing, permissions and org management",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"sideEffects": [
|
|
@@ -59,12 +59,12 @@
|
|
|
59
59
|
"@radix-ui/react-dialog": "^1.1.0",
|
|
60
60
|
"@tanstack/react-table": "^8.20.0",
|
|
61
61
|
"cmdk": "^1.0.0",
|
|
62
|
-
"@fayz-ai/auth": "^0.
|
|
63
|
-
"@fayz-ai/core": "^0.
|
|
62
|
+
"@fayz-ai/auth": "^0.17.0",
|
|
63
|
+
"@fayz-ai/core": "^0.17.0",
|
|
64
64
|
"@fayz-ai/db": "^0.13.0",
|
|
65
|
-
"@fayz-ai/plugin-auth": "^0.
|
|
65
|
+
"@fayz-ai/plugin-auth": "^0.12.0",
|
|
66
66
|
"@fayz-ai/sdk": "^0.15.0",
|
|
67
|
-
"@fayz-ai/ui": "^0.
|
|
67
|
+
"@fayz-ai/ui": "^0.17.0"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@supabase/supabase-js": "^2.45.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/schedule-service.ts","../src/crud/archetypes/BlockSettingsPopover.tsx","../src/crud/archetypes/ScheduleEditor.tsx"],"names":["useTranslation","useRef","jsx","jsxs","X","useState","useEffect"],"mappings":"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","file":"ScheduleEditor-A3SX6AYD.js","sourcesContent":["// ---------------------------------------------------------------------------\n// Standalone Schedule CRUD Service\n// Works outside the agenda plugin context — uses Supabase directly.\n// ---------------------------------------------------------------------------\n\n// Core tables now live in the public schema — use the plain client directly.\nimport { getFayzSupabaseClient as getCoreClient } from '../data/client'\nimport { useOrganizationStore } from '../org'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ScheduleRecord {\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\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 kind?: string\n}\n\n/** Advanced settings stored per schedule block in the metadata jsonb column. */\nexport interface BlockSettings {\n bufferMinutes?: number\n allowedServiceIds?: string[]\n maxConcurrent?: number\n minAdvanceHours?: number\n maxAdvanceDays?: number\n label?: string\n locationId?: string\n}\n\n/** Extract BlockSettings from a schedule record's metadata. */\nexport function parseBlockSettings(metadata: Record<string, unknown>): BlockSettings {\n return {\n bufferMinutes: typeof metadata.bufferMinutes === 'number' ? metadata.bufferMinutes : undefined,\n allowedServiceIds: Array.isArray(metadata.allowedServiceIds) ? metadata.allowedServiceIds : undefined,\n maxConcurrent: typeof metadata.maxConcurrent === 'number' ? metadata.maxConcurrent : undefined,\n minAdvanceHours: typeof metadata.minAdvanceHours === 'number' ? metadata.minAdvanceHours : undefined,\n maxAdvanceDays: typeof metadata.maxAdvanceDays === 'number' ? metadata.maxAdvanceDays : undefined,\n label: typeof metadata.label === 'string' ? metadata.label : undefined,\n locationId: typeof metadata.locationId === 'string' ? metadata.locationId : undefined,\n }\n}\n\n/** Merge BlockSettings into existing metadata object. */\nexport function mergeBlockSettings(metadata: Record<string, unknown>, settings: BlockSettings): Record<string, unknown> {\n const merged = { ...metadata }\n // Only set defined values, remove undefined ones to keep metadata clean\n for (const [key, value] of Object.entries(settings)) {\n if (value !== undefined && value !== null && !(Array.isArray(value) && value.length === 0)) {\n merged[key] = value\n } else {\n delete merged[key]\n }\n }\n return merged\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getTenantId(): string {\n const id = useOrganizationStore.getState().currentOrg?.id\n if (!id) throw new Error('No active tenant')\n return id\n}\n\nfunction mapRow(row: Record<string, unknown>): ScheduleRecord {\n const r: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(row)) {\n r[key.replace(/_([a-z])/g, (_, c) => c.toUpperCase())] = value\n }\n return r as unknown as ScheduleRecord\n}\n\n// ---------------------------------------------------------------------------\n// Service functions\n// ---------------------------------------------------------------------------\n\nexport async function getSchedules(\n assigneeId: string,\n kind = 'working_hours',\n): Promise<ScheduleRecord[]> {\n const core = getCoreClient()\n const { data, error } = await core\n .from('schedules')\n .select('*')\n .eq('kind', kind)\n .eq('assignee_id', assigneeId)\n .order('day_of_week')\n .order('starts_at')\n\n if (error) throw error\n return (data ?? []).map(mapRow)\n}\n\nexport async function saveSchedule(input: SaveScheduleInput): Promise<ScheduleRecord> {\n const core = getCoreClient()\n const tenantId = getTenantId()\n\n const { data, error } = await core\n .from('schedules')\n .insert({\n tenant_id: tenantId,\n kind: input.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 ?? true,\n })\n .select('*')\n .single()\n\n if (error) throw error\n return mapRow(data as Record<string, unknown>)\n}\n\nexport async function deleteSchedule(id: string): Promise<void> {\n const core = getCoreClient()\n const { error } = await core.from('schedules').delete().eq('id', id)\n if (error) throw error\n}\n\n/**\n * Replace all weekly schedules (day_of_week based) for an assignee.\n * Deletes existing weekly entries and creates new ones in a single flow.\n */\nexport async function replaceWeeklySchedules(\n assigneeId: string,\n week: Record<number, { enabled: boolean; periods: { startsAt: string; endsAt: string; settings?: BlockSettings }[] }>,\n kind = 'working_hours',\n): Promise<void> {\n const core = getCoreClient()\n const tenantId = getTenantId()\n\n // Delete existing weekly schedules (day_of_week NOT NULL, specific_date IS NULL)\n const { error: delErr } = await core\n .from('schedules')\n .delete()\n .eq('assignee_id', assigneeId)\n .eq('kind', kind)\n .not('day_of_week', 'is', null)\n .is('specific_date', null)\n\n if (delErr) throw delErr\n\n // Build insert rows\n const rows: Record<string, unknown>[] = []\n for (const [dayStr, day] of Object.entries(week)) {\n if (!day.enabled) continue\n for (const period of day.periods) {\n const metadata = period.settings ? mergeBlockSettings({}, period.settings) : {}\n rows.push({\n tenant_id: tenantId,\n kind,\n assignee_id: assigneeId,\n day_of_week: Number(dayStr),\n specific_date: null,\n starts_at: period.startsAt,\n ends_at: period.endsAt,\n is_active: true,\n metadata,\n })\n }\n }\n\n if (rows.length > 0) {\n const { error: insErr } = await core.from('schedules').insert(rows)\n if (insErr) throw insErr\n }\n}\n\n/**\n * Enumerate all dates in a range (inclusive).\n */\nfunction eachDate(startDate: string, endDate: string): string[] {\n const dates: string[] = []\n const current = new Date(startDate + 'T00:00:00Z')\n const end = new Date(endDate + 'T00:00:00Z')\n while (current <= end) {\n dates.push(current.toISOString().slice(0, 10))\n current.setUTCDate(current.getUTCDate() + 1)\n }\n return dates\n}\n\n/**\n * Save a date-range exception.\n * type: 'unavailable' marks days off, 'available' sets custom hours.\n * Stores notes and range info in metadata for retrieval.\n */\nexport async function saveException(input: {\n assigneeId: string\n startDate: string\n endDate: string\n type: 'available' | 'unavailable'\n periods: { startsAt: string; endsAt: string }[]\n notes?: string\n settings?: BlockSettings\n kind?: string\n}): Promise<void> {\n const core = getCoreClient()\n const tenantId = getTenantId()\n const kind = input.kind ?? 'working_hours'\n const dates = eachDate(input.startDate, input.endDate)\n const isRange = dates.length > 1\n const meta = mergeBlockSettings(\n {\n ...(input.notes ? { notes: input.notes } : {}),\n ...(isRange ? { rangeStart: input.startDate, rangeEnd: input.endDate } : {}),\n exceptionType: input.type,\n },\n input.settings ?? {},\n )\n\n // Delete existing exceptions for all dates in range (single query)\n const { error: delErr } = await core\n .from('schedules')\n .delete()\n .eq('assignee_id', input.assigneeId)\n .eq('kind', kind)\n .in('specific_date', dates)\n if (delErr) throw delErr\n\n const rows: Record<string, unknown>[] = []\n\n if (input.type === 'unavailable') {\n // One sentinel row per date with is_active: false\n for (const date of dates) {\n rows.push({\n tenant_id: tenantId,\n kind,\n assignee_id: input.assigneeId,\n day_of_week: null,\n specific_date: date,\n starts_at: '00:00',\n ends_at: '00:00',\n is_active: false,\n metadata: meta,\n })\n }\n } else {\n // Custom available hours for each date\n for (const date of dates) {\n for (const p of input.periods) {\n rows.push({\n tenant_id: tenantId,\n kind,\n assignee_id: input.assigneeId,\n day_of_week: null,\n specific_date: date,\n starts_at: p.startsAt,\n ends_at: p.endsAt,\n is_active: true,\n metadata: meta,\n })\n }\n }\n }\n\n if (rows.length > 0) {\n const { error } = await core.from('schedules').insert(rows)\n if (error) throw error\n }\n}\n\n/**\n * Delete an exception by its start date.\n * If it was part of a range, deletes all dates in that range.\n */\nexport async function deleteException(\n assigneeId: string,\n startDate: string,\n endDate?: string,\n kind = 'working_hours',\n): Promise<void> {\n const core = getCoreClient()\n const dates = eachDate(startDate, endDate ?? startDate)\n const { error } = await core\n .from('schedules')\n .delete()\n .eq('assignee_id', assigneeId)\n .eq('kind', kind)\n .in('specific_date', dates)\n if (error) throw error\n}\n","import React, { useRef, useEffect, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { X, ChevronDown } from 'lucide-react'\nimport type { BlockSettings } from '../../lib/schedule-service'\nimport type { ScheduleBlockConfig } from '../../lib/schedule-config'\nimport { useTranslation } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\ninterface BlockSettingsPopoverProps {\n settings: BlockSettings\n onChange: (settings: BlockSettings) => void\n config: ScheduleBlockConfig\n /** Ref to the trigger element for positioning */\n triggerRef: React.RefObject<HTMLElement | null>\n open: boolean\n onClose: () => void\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function BlockSettingsPopover({\n settings,\n onChange,\n config,\n triggerRef,\n open,\n onClose,\n}: BlockSettingsPopoverProps) {\n const t = useTranslation()\n const popoverRef = useRef<HTMLDivElement>(null)\n const [pos, setPos] = useState({ top: 0, left: 0 })\n\n useEffect(() => {\n if (!open || !triggerRef.current) return\n const rect = triggerRef.current.getBoundingClientRect()\n const popW = 280\n let left = rect.left + rect.width / 2 - popW / 2\n if (left + popW > window.innerWidth - 12) left = window.innerWidth - popW - 12\n if (left < 8) left = 8\n setPos({ top: rect.bottom + 6, left })\n }, [open, triggerRef])\n\n useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => {\n if (popoverRef.current?.contains(e.target as Node)) return\n if (triggerRef.current?.contains(e.target as Node)) return\n onClose()\n }\n document.addEventListener('mousedown', handler)\n return () => document.removeEventListener('mousedown', handler)\n }, [open, onClose, triggerRef])\n\n if (!open) return null\n\n const showServices = config.showServices !== false && config.services && config.services.length > 0\n const showConcurrent = config.showConcurrent !== false\n const showBookingWindow = config.showBookingWindow !== false\n const showLocations = config.showLocations === true && config.locations && config.locations.length > 0\n\n function update(patch: Partial<BlockSettings>) {\n onChange({ ...settings, ...patch })\n }\n\n return createPortal(\n <div\n ref={popoverRef}\n style={{ position: 'fixed', top: pos.top, left: pos.left, zIndex: 9999 }}\n className=\"fayz-glass-surface w-[280px] rounded-xl border bg-popover shadow-xl\"\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-3 py-2.5 border-b\">\n <span className=\"text-xs font-semibold\">{t('schedule.blockSettings.title')}</span>\n <button type=\"button\" onClick={onClose} className=\"p-0.5 rounded text-muted-foreground hover:text-foreground\">\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n\n <div className=\"p-3 space-y-3\">\n {/* Location select */}\n {showLocations && (\n <LocationSelect\n locations={config.locations!}\n value={settings.locationId}\n onChange={(id) => update({ locationId: id || undefined })}\n />\n )}\n\n {/* Services multi-select */}\n {showServices && (\n <ServiceSelect\n services={config.services!}\n selected={settings.allowedServiceIds ?? []}\n onChange={(ids) => update({ allowedServiceIds: ids.length > 0 ? ids : undefined })}\n />\n )}\n\n {/* Max concurrent */}\n {showConcurrent && (\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('schedule.blockSettings.maxConcurrent')}</label>\n <div className=\"flex items-center gap-2 mt-1\">\n <button\n type=\"button\"\n onClick={() => update({ maxConcurrent: Math.max(1, (settings.maxConcurrent ?? config.defaults.maxConcurrent) - 1) })}\n className=\"flex h-7 w-7 items-center justify-center rounded-md border text-sm hover:bg-muted bg-card shadow-button active:shadow-button-inset transition-colors\"\n >\n -\n </button>\n <span className=\"text-sm font-medium w-6 text-center\">\n {settings.maxConcurrent ?? config.defaults.maxConcurrent}\n </span>\n <button\n type=\"button\"\n onClick={() => update({ maxConcurrent: (settings.maxConcurrent ?? config.defaults.maxConcurrent) + 1 })}\n className=\"flex h-7 w-7 items-center justify-center rounded-md border text-sm hover:bg-muted bg-card shadow-button active:shadow-button-inset transition-colors\"\n >\n +\n </button>\n </div>\n </div>\n )}\n\n {/* Booking window */}\n {showBookingWindow && (\n <div className=\"grid grid-cols-2 gap-2\">\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('schedule.blockSettings.minAdvance')}</label>\n <div className=\"flex items-center gap-1 mt-1\">\n <input\n type=\"number\"\n min={0}\n value={settings.minAdvanceHours ?? config.defaults.minAdvanceHours}\n onChange={(e) => update({ minAdvanceHours: Number(e.target.value) || 0 })}\n className=\"w-full rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2 py-1 text-xs tabular-nums\"\n />\n <span className=\"text-[10px] text-muted-foreground shrink-0\">{t('schedule.blockSettings.hrs')}</span>\n </div>\n </div>\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('schedule.blockSettings.maxAdvance')}</label>\n <div className=\"flex items-center gap-1 mt-1\">\n <input\n type=\"number\"\n min={1}\n value={settings.maxAdvanceDays ?? config.defaults.maxAdvanceDays}\n onChange={(e) => update({ maxAdvanceDays: Number(e.target.value) || 30 })}\n className=\"w-full rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2 py-1 text-xs tabular-nums\"\n />\n <span className=\"text-[10px] text-muted-foreground shrink-0\">{t('schedule.blockSettings.days')}</span>\n </div>\n </div>\n </div>\n )}\n\n {/* Label */}\n <div>\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('schedule.blockSettings.label')}</label>\n <input\n type=\"text\"\n value={settings.label ?? ''}\n onChange={(e) => update({ label: e.target.value || undefined })}\n placeholder={t('schedule.blockSettings.labelPlaceholder')}\n className=\"mt-1 w-full rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2 py-1 text-xs placeholder:text-muted-foreground/40\"\n />\n </div>\n </div>\n </div>,\n document.body,\n )\n}\n\n// ---------------------------------------------------------------------------\n// Service multi-select (simple dropdown with checkboxes)\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Location select (custom dropdown)\n// ---------------------------------------------------------------------------\n\nfunction LocationSelect({\n locations,\n value,\n onChange,\n}: {\n locations: { id: string; name: string }[]\n value: string | undefined\n onChange: (id: string) => void\n}) {\n const t = useTranslation()\n const [open, setOpen] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\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 const current = value ? locations.find((l) => l.id === value) : null\n const label = current ? current.name : t('schedule.blockSettings.noLocation')\n\n return (\n <div ref={ref} className=\"relative\">\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('schedule.blockSettings.location')}</label>\n <button\n type=\"button\"\n onClick={() => setOpen((p) => !p)}\n className=\"mt-1 flex items-center justify-between w-full rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2 py-1.5 text-xs hover:bg-muted/30 transition-colors\"\n >\n <span className={current ? '' : 'text-muted-foreground'}>{label}</span>\n <ChevronDown className=\"h-3 w-3 text-muted-foreground\" />\n </button>\n {open && (\n <div className=\"fayz-glass-surface absolute top-full left-0 z-10 mt-1 w-full max-h-40 overflow-y-auto rounded-lg border bg-popover shadow-lg py-1\">\n <button\n type=\"button\"\n onClick={() => { onChange(''); setOpen(false) }}\n className={`block w-full px-2.5 py-1.5 text-xs text-left transition-colors ${!value ? 'bg-primary/10 text-primary font-medium' : 'hover:bg-muted/50'}`}\n >\n {t('schedule.blockSettings.noLocation')}\n </button>\n {locations.map((l) => (\n <button\n key={l.id}\n type=\"button\"\n onClick={() => { onChange(l.id); setOpen(false) }}\n className={`block w-full px-2.5 py-1.5 text-xs text-left transition-colors ${l.id === value ? 'bg-primary/10 text-primary font-medium' : 'hover:bg-muted/50'}`}\n >\n {l.name}\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Service multi-select (simple dropdown with checkboxes)\n// ---------------------------------------------------------------------------\n\nfunction ServiceSelect({\n services,\n selected,\n onChange,\n}: {\n services: { id: string; name: string }[]\n selected: string[]\n onChange: (ids: string[]) => void\n}) {\n const t = useTranslation()\n const [open, setOpen] = useState(false)\n const ref = useRef<HTMLDivElement>(null)\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 const allSelected = selected.length === 0\n const label = allSelected\n ? t('schedule.blockSettings.allServices')\n : selected.length === 1\n ? services.find((s) => s.id === selected[0])?.name ?? t('schedule.blockSettings.oneService')\n : t('schedule.blockSettings.nServices', { count: selected.length })\n\n function toggle(id: string) {\n onChange(selected.includes(id) ? selected.filter((s) => s !== id) : [...selected, id])\n }\n\n return (\n <div ref={ref} className=\"relative\">\n <label className=\"text-[11px] font-medium text-muted-foreground\">{t('schedule.blockSettings.allowedServices')}</label>\n <button\n type=\"button\"\n onClick={() => setOpen((p) => !p)}\n className=\"mt-1 flex items-center justify-between w-full rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-2 py-1.5 text-xs hover:bg-muted/30 transition-colors\"\n >\n <span className={allSelected ? 'text-muted-foreground' : ''}>{label}</span>\n <ChevronDown className=\"h-3 w-3 text-muted-foreground\" />\n </button>\n {open && (\n <div className=\"fayz-glass-surface absolute top-full left-0 z-10 mt-1 w-full max-h-40 overflow-y-auto rounded-lg border bg-popover shadow-lg py-1\">\n <button\n type=\"button\"\n onClick={() => onChange([])}\n className={`block w-full px-2.5 py-1.5 text-xs text-left transition-colors ${allSelected ? 'bg-primary/10 text-primary font-medium' : 'hover:bg-muted/50'}`}\n >\n {t('schedule.blockSettings.allServices')}\n </button>\n {services.map((s) => {\n const checked = selected.includes(s.id)\n return (\n <button\n key={s.id}\n type=\"button\"\n onClick={() => toggle(s.id)}\n className={`flex items-center gap-2 w-full px-2.5 py-1.5 text-xs text-left transition-colors ${checked ? 'bg-primary/5' : 'hover:bg-muted/50'}`}\n >\n <span className={`flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-sm border ${\n checked ? 'border-primary bg-primary text-primary-foreground' : 'border-muted-foreground/30'\n }`}>\n {checked && <svg className=\"h-2.5 w-2.5\" 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=\"truncate\">{s.name}</span>\n </button>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n","import React, { useEffect, useState, useCallback, useRef, useSyncExternalStore } from 'react'\nimport { Clock, Plus, Trash2, Copy, Save, CalendarOff, CalendarPlus, Check, Settings, X } from 'lucide-react'\nimport { toast } from '@fayz-ai/ui'\nimport {\n getSchedules,\n replaceWeeklySchedules,\n saveException,\n deleteException,\n parseBlockSettings,\n} from '../../lib/schedule-service'\nimport type { ScheduleRecord, BlockSettings } from '../../lib/schedule-service'\nimport { getScheduleBlockConfig, subscribeScheduleBlockConfig } from '../../lib/schedule-config'\nimport type { ScheduleBlockConfig } from '../../lib/schedule-config'\nimport { useTranslation } from '@fayz-ai/core'\nimport { BlockSettingsPopover } from './BlockSettingsPopover'\nimport { Card, CardContent } from '@fayz-ai/ui'\nimport { Button } from '@fayz-ai/ui'\nimport { Badge } from '@fayz-ai/ui'\nimport { Skeleton } from '@fayz-ai/ui'\nimport { DatePicker } from '@fayz-ai/ui'\nimport { TimePicker } from '@fayz-ai/ui'\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from '@fayz-ai/ui'\nimport { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, ModalTitle, ModalDescription } from '@fayz-ai/ui'\nimport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@fayz-ai/ui'\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DAY_KEYS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']\nconst WEEK_ORDER = [1, 2, 3, 4, 5, 6, 0] // Mon–Sun display order\n\ninterface Period {\n id?: string\n startsAt: string\n endsAt: string\n settings?: BlockSettings\n}\n\ninterface DaySchedule {\n enabled: boolean\n periods: Period[]\n}\n\ntype WeekSchedule = Record<number, DaySchedule>\n\ninterface ExceptionEntry {\n startDate: string\n endDate: string\n type: 'available' | 'unavailable'\n periods: { startsAt: string; endsAt: string }[]\n notes: string\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction schedulesToWeek(schedules: ScheduleRecord[]): WeekSchedule {\n const week: WeekSchedule = {}\n for (let i = 0; i < 7; i++) {\n week[i] = { enabled: false, periods: [] }\n }\n for (const s of schedules) {\n if (s.dayOfWeek == null || s.specificDate != null) continue\n const day = week[s.dayOfWeek]\n if (s.isActive) {\n day.enabled = true\n const settings = parseBlockSettings(s.metadata ?? {})\n const hasSettings = Object.values(settings).some((v) => v !== undefined)\n day.periods.push({\n id: s.id,\n startsAt: s.startsAt,\n endsAt: s.endsAt,\n settings: hasSettings ? settings : undefined,\n })\n }\n }\n for (const day of Object.values(week)) {\n day.periods.sort((a, b) => a.startsAt.localeCompare(b.startsAt))\n }\n return week\n}\n\nfunction schedulesToExceptions(schedules: ScheduleRecord[]): ExceptionEntry[] {\n // Group by range key (rangeStart–rangeEnd or single date)\n const map = new Map<string, ExceptionEntry>()\n for (const s of schedules) {\n if (!s.specificDate) continue\n const meta = (s.metadata ?? {}) as Record<string, unknown>\n const rangeStart = (meta.rangeStart as string) ?? s.specificDate\n const rangeEnd = (meta.rangeEnd as string) ?? s.specificDate\n const key = `${rangeStart}__${rangeEnd}`\n const exType = (meta.exceptionType as string) === 'available' ? 'available' : 'unavailable'\n const notes = (meta.notes as string) ?? ''\n\n const existing = map.get(key)\n if (!existing) {\n map.set(key, {\n startDate: rangeStart,\n endDate: rangeEnd,\n type: exType,\n periods: s.isActive ? [{ startsAt: s.startsAt, endsAt: s.endsAt }] : [],\n notes,\n })\n } else if (s.isActive && s.specificDate === rangeStart) {\n existing.periods.push({ startsAt: s.startsAt, endsAt: s.endsAt })\n }\n }\n return Array.from(map.values()).sort((a, b) => a.startDate.localeCompare(b.startDate))\n}\n\nfunction formatDate(dateStr: string): string {\n const d = new Date(dateStr + 'T00:00:00')\n return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' })\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// PeriodRow — single time block as a horizontal row\n// ---------------------------------------------------------------------------\n\ninterface PeriodRowProps {\n period: Period\n dayOfWeek: number\n blockConfig: ScheduleBlockConfig | null\n settingsOpen: boolean\n onUpdateTime: (field: 'startsAt' | 'endsAt', value: string) => void\n onUpdateBuffer: (value: number) => void\n onUpdateSettings: (settings: BlockSettings) => void\n onRemove: () => void\n onAddBlock: () => void\n onCopyToAll: () => void\n onToggleSettings: () => void\n onCloseSettings: () => void\n}\n\nfunction PeriodRow({\n period, blockConfig, dayOfWeek,\n settingsOpen, onUpdateTime, onUpdateBuffer, onUpdateSettings,\n onRemove, onCopyToAll, onToggleSettings, onCloseSettings,\n onAddBlock,\n}: PeriodRowProps) {\n const t = useTranslation()\n const gearRef = useRef<HTMLButtonElement>(null)\n const bufferValue = period.settings?.bufferMinutes ?? blockConfig?.defaults.bufferMinutes ?? 0\n const hasCustomSettings = period.settings && Object.entries(period.settings).some(\n ([k, v]) => k !== 'bufferMinutes' && v !== undefined,\n )\n const dayName = t(`schedule.days.${DAY_KEYS[dayOfWeek]}`)\n\n return (\n <TooltipProvider delayDuration={300}>\n <div className=\"flex items-center gap-1.5 group\">\n {/* Label */}\n {period.settings?.label && (\n <span className=\"text-[10px] font-medium text-primary bg-primary/10 rounded-full px-2 py-0.5 shrink-0\">\n {period.settings.label}\n </span>\n )}\n\n {/* Time range */}\n <TimePicker value={period.startsAt} onChange={(v) => onUpdateTime('startsAt', v)} interval={30} className=\"w-[90px]\" />\n <span className=\"text-xs text-muted-foreground/50\">-</span>\n <TimePicker value={period.endsAt} onChange={(v) => onUpdateTime('endsAt', v)} interval={30} min={period.startsAt} className=\"w-[90px]\" />\n\n {/* Buffer pill */}\n <Tooltip>\n <TooltipTrigger asChild>\n <div className=\"flex items-center gap-1 rounded-full border bg-muted/30 px-2 py-1 shrink-0\">\n <input\n type=\"number\"\n min={0}\n max={120}\n value={bufferValue}\n onChange={(e) => onUpdateBuffer(Number(e.target.value) || 0)}\n className=\"w-8 bg-transparent text-xs text-center tabular-nums outline-none\"\n />\n <span className=\"text-[10px] text-muted-foreground\">{t('schedule.editor.min')}</span>\n </div>\n </TooltipTrigger>\n <TooltipContent>{t('schedule.editor.bufferTooltip')}</TooltipContent>\n </Tooltip>\n\n {/* Actions */}\n <div className=\"flex items-center gap-0.5 shrink-0 ml-auto\">\n <Tooltip>\n <TooltipTrigger asChild>\n <button type=\"button\" onClick={onRemove}\n className=\"p-1.5 rounded-md text-muted-foreground/30 hover:text-destructive hover:bg-destructive/5 transition-colors\">\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>{t('schedule.editor.removeInterval')}</TooltipContent>\n </Tooltip>\n\n <Tooltip>\n <TooltipTrigger asChild>\n <button type=\"button\" onClick={onAddBlock}\n className=\"p-1.5 rounded-md text-muted-foreground/30 hover:text-foreground hover:bg-muted transition-colors\">\n <Plus className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>{t('schedule.editor.newInterval', { day: dayName })}</TooltipContent>\n </Tooltip>\n\n <Tooltip>\n <TooltipTrigger asChild>\n <button type=\"button\" onClick={onCopyToAll}\n className=\"p-1.5 rounded-md text-muted-foreground/30 hover:text-foreground hover:bg-muted transition-colors\">\n <Copy className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>{t('schedule.editor.copyToAll')}</TooltipContent>\n </Tooltip>\n\n {blockConfig && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button ref={gearRef} type=\"button\" onClick={onToggleSettings}\n className={`p-1.5 rounded-md transition-colors ${\n hasCustomSettings\n ? 'text-primary bg-primary/5'\n : 'text-muted-foreground/30 hover:text-foreground hover:bg-muted'\n }`}>\n <Settings className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>{t('schedule.blockSettings.title')}</TooltipContent>\n </Tooltip>\n )}\n </div>\n\n {/* Settings popover */}\n {blockConfig && (\n <BlockSettingsPopover\n settings={period.settings ?? {}}\n onChange={onUpdateSettings}\n config={blockConfig}\n triggerRef={gearRef}\n open={settingsOpen}\n onClose={onCloseSettings}\n />\n )}\n </div>\n </TooltipProvider>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Main Component\n// ---------------------------------------------------------------------------\n\ninterface ScheduleEditorProps {\n assigneeId: string\n}\n\nexport function ScheduleEditor({ assigneeId }: ScheduleEditorProps) {\n const t = useTranslation()\n const [week, setWeek] = useState<WeekSchedule>({})\n const [exceptions, setExceptions] = useState<ExceptionEntry[]>([])\n const [loading, setLoading] = useState(true)\n const [saving, setSaving] = useState(false)\n const [showAddException, setShowAddException] = useState(false)\n const blockConfig = useSyncExternalStore(subscribeScheduleBlockConfig, getScheduleBlockConfig)\n const [settingsPopover, setSettingsPopover] = useState<{ dayOfWeek: number; idx: number } | null>(null)\n const [weekDirty, setWeekDirty] = useState(false)\n\n // Lazy-fetch locations when showLocations is enabled but locations aren't loaded yet\n useEffect(() => {\n if (blockConfig?.showLocations && (!blockConfig.locations || blockConfig.locations.length === 0) && blockConfig.fetchLocations) {\n blockConfig.fetchLocations().catch(() => {})\n }\n }, [blockConfig?.showLocations, blockConfig?.locations?.length])\n\n // New exception form state\n const [newExStartDate, setNewExStartDate] = useState('')\n const [newExEndDate, setNewExEndDate] = useState('')\n const [newExType, setNewExType] = useState<'unavailable' | 'available'>('unavailable')\n const [newExPeriods, setNewExPeriods] = useState([{ startsAt: '09:00', endsAt: '17:00' }])\n const [newExNotes, setNewExNotes] = useState('')\n const [savingException, setSavingException] = useState(false)\n\n const loadData = useCallback(async () => {\n setLoading(true)\n try {\n const data = await getSchedules(assigneeId)\n setWeek(schedulesToWeek(data))\n setExceptions(schedulesToExceptions(data))\n setWeekDirty(false)\n } catch {\n toast.error(t('schedule.editor.failedToLoad'))\n }\n setLoading(false)\n }, [assigneeId])\n\n useEffect(() => {\n loadData()\n }, [loadData])\n\n // --- Weekly hours handlers ---\n\n function markDirty() { setWeekDirty(true) }\n\n function toggleDay(dayOfWeek: number) {\n markDirty()\n setWeek((prev) => ({\n ...prev,\n [dayOfWeek]: {\n ...prev[dayOfWeek],\n enabled: !prev[dayOfWeek]?.enabled,\n periods: prev[dayOfWeek]?.enabled ? [] : [{ startsAt: '09:00', endsAt: '18:00' }],\n },\n }))\n }\n\n function updatePeriod(dayOfWeek: number, idx: number, field: 'startsAt' | 'endsAt', value: string) {\n markDirty()\n setWeek((prev) => {\n const day = { ...prev[dayOfWeek] }\n const periods = [...day.periods]\n periods[idx] = { ...periods[idx], [field]: value }\n return { ...prev, [dayOfWeek]: { ...day, periods } }\n })\n }\n\n function addPeriod(dayOfWeek: number) {\n markDirty()\n setWeek((prev) => {\n const day = { ...prev[dayOfWeek] }\n const last = day.periods[day.periods.length - 1]\n day.periods = [...day.periods, { startsAt: last?.endsAt ?? '13:00', endsAt: '18:00' }]\n return { ...prev, [dayOfWeek]: day }\n })\n }\n\n function removePeriod(dayOfWeek: number, idx: number) {\n markDirty()\n setWeek((prev) => {\n const day = { ...prev[dayOfWeek] }\n day.periods = day.periods.filter((_, i) => i !== idx)\n if (day.periods.length === 0) day.enabled = false\n return { ...prev, [dayOfWeek]: day }\n })\n }\n\n function updatePeriodSettings(dayOfWeek: number, idx: number, settings: BlockSettings) {\n markDirty()\n setWeek((prev) => {\n const day = { ...prev[dayOfWeek] }\n const periods = [...day.periods]\n periods[idx] = { ...periods[idx], settings }\n return { ...prev, [dayOfWeek]: { ...day, periods } }\n })\n }\n\n function updateBufferMinutes(dayOfWeek: number, idx: number, value: number) {\n markDirty()\n setWeek((prev) => {\n const day = { ...prev[dayOfWeek] }\n const periods = [...day.periods]\n const existing = periods[idx].settings ?? {}\n periods[idx] = { ...periods[idx], settings: { ...existing, bufferMinutes: value || undefined } }\n return { ...prev, [dayOfWeek]: { ...day, periods } }\n })\n }\n\n function copyToAll(sourceDayOfWeek: number) {\n markDirty()\n const source = week[sourceDayOfWeek]\n if (!source) return\n setWeek((prev) => {\n const next = { ...prev }\n for (let i = 0; i < 7; i++) {\n if (i === sourceDayOfWeek) continue\n next[i] = {\n enabled: source.enabled,\n periods: source.periods.map((p) => ({ startsAt: p.startsAt, endsAt: p.endsAt, settings: p.settings ? { ...p.settings } : undefined })),\n }\n }\n return next\n })\n }\n\n async function handleSaveWeekly() {\n setSaving(true)\n try {\n await replaceWeeklySchedules(assigneeId, week)\n toast.success(t('schedule.editor.saved'))\n loadData()\n } catch (err: any) {\n toast.error(t('schedule.editor.failedToSave'), { description: err?.message })\n }\n setSaving(false)\n }\n\n // --- Exception handlers ---\n\n async function handleAddException() {\n if (!newExStartDate) {\n toast.error(t('schedule.editor.selectStartDate'))\n return\n }\n const endDate = newExEndDate || newExStartDate\n if (endDate < newExStartDate) {\n toast.error(t('schedule.editor.endDateAfterStart'))\n return\n }\n setSavingException(true)\n try {\n await saveException({\n assigneeId,\n startDate: newExStartDate,\n endDate,\n type: newExType,\n periods: newExType === 'unavailable' ? [] : newExPeriods,\n notes: newExNotes || undefined,\n })\n toast.success(t('schedule.editor.exceptionAdded'))\n setShowAddException(false)\n setNewExStartDate('')\n setNewExEndDate('')\n setNewExType('unavailable')\n setNewExPeriods([{ startsAt: '09:00', endsAt: '17:00' }])\n setNewExNotes('')\n loadData()\n } catch (err: any) {\n toast.error(t('schedule.editor.failedToSaveException'), { description: err?.message })\n }\n setSavingException(false)\n }\n\n async function handleDeleteException(startDate: string, endDate: string) {\n try {\n await deleteException(assigneeId, startDate, endDate)\n toast.success(t('schedule.editor.exceptionRemoved'))\n loadData()\n } catch (err: any) {\n toast.error(t('schedule.editor.failedToDelete'), { description: err?.message })\n }\n }\n\n // --- Render ---\n\n if (loading) {\n return (\n <div className=\"fz-fields fz-fields-2 gap-6\">\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"h-9 w-9 rounded-lg\" />\n <div className=\"space-y-1.5\"><Skeleton className=\"h-4 w-36\" /><Skeleton className=\"h-3 w-48\" /></div>\n </div>\n <Skeleton className=\"h-8 w-20 rounded-md\" />\n </div>\n <Card>\n <CardContent className=\"p-0 divide-y\">\n {Array.from({ length: 7 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 px-4 py-3\">\n <Skeleton className=\"h-5 w-5 rounded-full\" />\n <Skeleton className=\"h-4 w-8\" />\n {i < 5 ? (\n <>\n <Skeleton className=\"h-8 w-24 rounded-lg\" />\n <Skeleton className=\"h-3 w-3\" />\n <Skeleton className=\"h-8 w-24 rounded-lg\" />\n </>\n ) : (\n <Skeleton className=\"h-4 w-20\" />\n )}\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"h-9 w-9 rounded-lg\" />\n <div className=\"space-y-1.5\"><Skeleton className=\"h-4 w-32\" /><Skeleton className=\"h-3 w-44\" /></div>\n </div>\n <Skeleton className=\"h-8 w-32 rounded-md\" />\n </div>\n <Card><CardContent className=\"flex items-center justify-center py-8\"><Skeleton className=\"h-3 w-48\" /></CardContent></Card>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"fz-fields fz-fields-2 gap-6\">\n {/* ---- Weekly Working Hours ---- */}\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-primary/10\">\n <Clock className=\"h-4 w-4 text-primary\" />\n </div>\n <div>\n <h3 className=\"text-sm font-semibold\">{t('schedule.editor.weeklyTitle')}</h3>\n <p className=\"text-xs text-muted-foreground\">{t('schedule.editor.weeklyDescription')}</p>\n </div>\n </div>\n {weekDirty && (\n <Button size=\"sm\" onClick={handleSaveWeekly} disabled={saving}>\n <Save className=\"h-4 w-4 mr-1.5\" />\n {saving ? t('common.saving') : t('common.save')}\n </Button>\n )}\n </div>\n\n {/* Day rows */}\n <Card>\n <CardContent className=\"p-0 divide-y\">\n {WEEK_ORDER.map((dayOfWeek) => {\n const day = week[dayOfWeek] ?? { enabled: false, periods: [] }\n return (\n <div\n key={dayOfWeek}\n className={`flex items-start gap-4 px-4 py-3 transition-colors ${day.enabled ? '' : 'bg-muted/20'}`}\n >\n {/* Day toggle checkbox + label */}\n <button\n type=\"button\"\n onClick={() => toggleDay(dayOfWeek)}\n className=\"flex items-center gap-2.5 w-20 shrink-0 pt-1.5\"\n >\n <span className={`flex h-5 w-5 shrink-0 items-center justify-center rounded-full transition-all ${\n day.enabled\n ? 'bg-primary text-primary-foreground shadow-sm'\n : 'border-2 border-muted-foreground/25 hover:border-muted-foreground/40'\n }`}>\n {day.enabled && <Check className=\"h-3 w-3\" strokeWidth={3} />}\n </span>\n <span className={`text-sm font-medium ${day.enabled ? '' : 'text-muted-foreground/40'}`}>\n {t(`schedule.days.${DAY_KEYS[dayOfWeek]}`)}\n </span>\n </button>\n\n {/* Content */}\n {day.enabled ? (\n <div className=\"flex-1 space-y-2\">\n {day.periods.map((period, idx) => (\n <PeriodRow\n key={idx}\n period={period}\n dayOfWeek={dayOfWeek}\n blockConfig={blockConfig}\n settingsOpen={settingsPopover?.dayOfWeek === dayOfWeek && settingsPopover?.idx === idx}\n onUpdateTime={(field, v) => updatePeriod(dayOfWeek, idx, field, v)}\n onUpdateBuffer={(v) => updateBufferMinutes(dayOfWeek, idx, v)}\n onUpdateSettings={(s) => updatePeriodSettings(dayOfWeek, idx, s)}\n onRemove={() => removePeriod(dayOfWeek, idx)}\n onAddBlock={() => addPeriod(dayOfWeek)}\n onCopyToAll={() => copyToAll(dayOfWeek)}\n onToggleSettings={() => setSettingsPopover(\n settingsPopover?.dayOfWeek === dayOfWeek && settingsPopover?.idx === idx ? null : { dayOfWeek, idx }\n )}\n onCloseSettings={() => setSettingsPopover(null)}\n />\n ))}\n </div>\n ) : (\n <TooltipProvider delayDuration={300}>\n <div className=\"flex items-center gap-2 pt-1.5\">\n <span className=\"text-sm text-muted-foreground/40\">{t('schedule.editor.unavailable')}</span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => toggleDay(dayOfWeek)}\n className=\"flex h-6 w-6 items-center justify-center rounded-full border border-muted-foreground/25 text-muted-foreground/40 hover:border-foreground/40 hover:text-foreground hover:bg-muted transition-colors\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>{t('schedule.editor.addHoursFor', { day: t(`schedule.days.${DAY_KEYS[dayOfWeek]}`) })}</TooltipContent>\n </Tooltip>\n </div>\n </TooltipProvider>\n )}\n </div>\n )\n })}\n </CardContent>\n </Card>\n </div>\n\n {/* ---- Date Exceptions ---- */}\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-orange-500/10\">\n <CalendarOff className=\"h-4 w-4 text-orange-600\" />\n </div>\n <div>\n <h3 className=\"text-sm font-semibold\">{t('schedule.editor.exceptionsTitle')}</h3>\n <p className=\"text-xs text-muted-foreground\">{t('schedule.editor.exceptionsDescription')}</p>\n </div>\n </div>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setShowAddException(true)}\n >\n <CalendarPlus className=\"h-4 w-4 mr-1.5\" />\n {t('schedule.editor.addException')}\n </Button>\n </div>\n\n {/* Add exception modal */}\n <Modal open={showAddException} onOpenChange={setShowAddException}>\n <ModalContent size=\"md\">\n <ModalHeader>\n <ModalTitle>{t('schedule.editor.addException')}</ModalTitle>\n <ModalDescription>{t('schedule.editor.exceptionsDescription')}</ModalDescription>\n </ModalHeader>\n\n <ModalBody className=\"space-y-5\">\n {/* Date range */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"text-xs font-medium text-muted-foreground mb-1.5 block\">{t('schedule.editor.startDate')}</label>\n <DatePicker\n value={newExStartDate}\n onChange={(v) => {\n setNewExStartDate(v)\n if (!newExEndDate || v > newExEndDate) setNewExEndDate(v)\n }}\n />\n </div>\n <div>\n <label className=\"text-xs font-medium text-muted-foreground mb-1.5 block\">{t('schedule.editor.endDate')}</label>\n <DatePicker\n value={newExEndDate || newExStartDate}\n onChange={setNewExEndDate}\n />\n </div>\n </div>\n\n {/* Type — segmented tabs */}\n <div>\n <label className=\"text-xs font-medium text-muted-foreground mb-1.5 block\">{t('schedule.editor.type')}</label>\n <Tabs value={newExType} onValueChange={(v) => setNewExType(v as 'unavailable' | 'available')}>\n <TabsList className=\"h-9 w-full\">\n <TabsTrigger value=\"unavailable\" className=\"text-xs gap-1.5 flex-1\">\n <CalendarOff className=\"h-3.5 w-3.5\" />\n {t('schedule.editor.unavailable')}\n </TabsTrigger>\n <TabsTrigger value=\"available\" className=\"text-xs gap-1.5 flex-1\">\n <Clock className=\"h-3.5 w-3.5\" />\n {t('schedule.editor.customHours')}\n </TabsTrigger>\n </TabsList>\n </Tabs>\n </div>\n\n {/* Custom hours — only when type=available */}\n {newExType === 'available' && (\n <div className=\"space-y-3\">\n <label className=\"text-xs font-medium text-muted-foreground\">{t('schedule.editor.workingHours')}</label>\n {newExPeriods.map((period, idx) => (\n <div key={idx} className=\"flex items-center gap-3\">\n <TimePicker\n value={period.startsAt}\n onChange={(v) => {\n const updated = [...newExPeriods]\n updated[idx] = { ...updated[idx], startsAt: v }\n setNewExPeriods(updated)\n }}\n interval={30}\n className=\"flex-1\"\n />\n <span className=\"text-xs text-muted-foreground shrink-0\">{t('schedule.editor.to')}</span>\n <TimePicker\n value={period.endsAt}\n onChange={(v) => {\n const updated = [...newExPeriods]\n updated[idx] = { ...updated[idx], endsAt: v }\n setNewExPeriods(updated)\n }}\n interval={30}\n min={period.startsAt}\n className=\"flex-1\"\n />\n {newExPeriods.length > 1 && (\n <button\n type=\"button\"\n onClick={() => setNewExPeriods(newExPeriods.filter((_, i) => i !== idx))}\n className=\"p-1.5 rounded-md text-muted-foreground hover:text-destructive hover:bg-destructive/5 transition-colors shrink-0\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n ))}\n <button\n type=\"button\"\n onClick={() => {\n const last = newExPeriods[newExPeriods.length - 1]\n setNewExPeriods([...newExPeriods, { startsAt: last?.endsAt ?? '13:00', endsAt: '18:00' }])\n }}\n className=\"flex items-center gap-1 text-xs text-primary hover:underline\"\n >\n <Plus className=\"h-3 w-3\" /> {t('schedule.editor.addTimeBlock')}\n </button>\n </div>\n )}\n\n {/* Notes */}\n <div>\n <label className=\"text-xs font-medium text-muted-foreground mb-1.5 block\">{t('schedule.editor.notes')}</label>\n <input\n type=\"text\"\n value={newExNotes}\n onChange={(e) => setNewExNotes(e.target.value)}\n placeholder={t('schedule.editor.notesPlaceholder')}\n className=\"block w-full rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-3 py-2 text-sm placeholder:text-muted-foreground/40 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1\"\n />\n </div>\n </ModalBody>\n\n <ModalFooter>\n <Button variant=\"ghost\" onClick={() => setShowAddException(false)}>\n {t('common.cancel')}\n </Button>\n <Button onClick={handleAddException} disabled={savingException}>\n <Save className=\"h-3.5 w-3.5 mr-1.5\" />\n {savingException ? t('common.saving') : t('schedule.editor.saveException')}\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n\n {/* Exception list */}\n {exceptions.length > 0 ? (\n <Card>\n <CardContent className=\"p-0 divide-y\">\n {exceptions.map((ex) => {\n const isRange = ex.startDate !== ex.endDate\n const dateLabel = isRange\n ? `${formatDate(ex.startDate)} — ${formatDate(ex.endDate)}`\n : formatDate(ex.startDate)\n return (\n <div key={ex.startDate + ex.endDate} className=\"flex items-center justify-between px-4 py-3 group\">\n <div className=\"flex items-center gap-3 min-w-0\">\n {/* Type indicator dot */}\n <span className={`h-2.5 w-2.5 shrink-0 rounded-full ${\n ex.type === 'unavailable' ? 'bg-destructive' : 'bg-success'\n }`} />\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-sm font-medium\">{dateLabel}</span>\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n {ex.type === 'unavailable' ? t('schedule.editor.unavailable') : t('schedule.editor.customHours')}\n </Badge>\n {ex.type === 'available' && ex.periods.length > 0 && (\n <span className=\"text-xs text-muted-foreground\">\n {ex.periods.map((p) => `${p.startsAt} — ${p.endsAt}`).join(', ')}\n </span>\n )}\n </div>\n {ex.notes && (\n <p className=\"text-xs text-muted-foreground mt-0.5 truncate\">{ex.notes}</p>\n )}\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => handleDeleteException(ex.startDate, ex.endDate)}\n className=\"p-1.5 rounded-md text-muted-foreground hover:text-destructive hover:bg-destructive/5 transition-colors shrink-0 ml-2\"\n title={t('schedule.editor.removeException')}\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n )\n })}\n </CardContent>\n </Card>\n ) : (\n !showAddException && (\n <Card>\n <CardContent className=\"flex items-center justify-center py-8 text-sm text-muted-foreground\">\n {t('schedule.editor.noExceptions')}\n </CardContent>\n </Card>\n )\n )}\n </div>\n </div>\n )\n}\n"]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { SubscriptionPage } from './chunk-IPWXA46H.js';
|
|
2
|
-
import './chunk-YUHCC7JY.js';
|
|
3
|
-
import './chunk-VN5NTK26.js';
|
|
4
|
-
import './chunk-OB7ZSTQD.js';
|
|
5
|
-
import './chunk-VTEP2AQX.js';
|
|
6
|
-
//# sourceMappingURL=SubscriptionPage-FE2B5ZXF.js.map
|
|
7
|
-
//# sourceMappingURL=SubscriptionPage-FE2B5ZXF.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/billing/plan-feature.tsx","../src/access/limits-registry.ts","../src/access/upgrade-modal-store.ts","../src/access/context.tsx","../src/access/headless.ts","../src/access/module-nav.ts","../src/components/billing/access-contract.ts","../src/components/billing/SubscriptionPage.tsx"],"names":["jsx","useAuthStore","resolveAccess","countByTenant","React2","React3","jsxs","Sparkles","Check"],"mappings":"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","file":"chunk-IPWXA46H.js","sourcesContent":["import * as React from 'react'\nimport { Check, Sparkles } from 'lucide-react'\nimport { cn } from '../../lib/cn'\n\n// A plan feature string prefixed with `*` renders highlighted (Sparkles +\n// primary, medium weight) — the config-side seam for \"hero\" features like the\n// AI assistant. Shared by UpgradePrompt, PlanSelector and SubscriptionPage.\n\nexport function parsePlanFeature(feature: string): { label: string; highlighted: boolean } {\n return feature.startsWith('*')\n ? { label: feature.slice(1).trim(), highlighted: true }\n : { label: feature, highlighted: false }\n}\n\nexport function PlanFeatureItem({ feature, className, iconClassName }: {\n feature: string\n className?: string\n iconClassName?: string\n}) {\n const { label, highlighted } = parsePlanFeature(feature)\n return (\n <li className={cn('flex items-start gap-2', className, highlighted && 'font-medium text-primary')}>\n {highlighted ? (\n <Sparkles className={cn('mt-0.5 shrink-0 text-primary', iconClassName)} aria-hidden=\"true\" />\n ) : (\n <Check className={cn('mt-0.5 shrink-0 text-primary', iconClassName)} aria-hidden=\"true\" />\n )}\n <span>{label}</span>\n </li>\n )\n}\n","import type { LimitDeclaration, RegisteredEntity } from '@fayz-ai/core'\nimport { invalidateCount } from '@fayz-ai/core'\n\n/**\n * Module-level registry bridging React (the provider that knows the declarations)\n * and the plain `invalidateLimit(key)` function that create handlers call outside\n * any component. The AccessProvider publishes the merged declarations here on\n * mount; `useLimit`/`useLimitGuard` and `invalidateLimit` read from it.\n */\n\n/**\n * Shell built-in limit declarations. Unlike plugin/app limits (contributed via\n * `PluginManifest.declaredLimits` / `billing.limitDeclarations`), these count\n * core tenant tables that have no owning plugin: seats (`tenant_members`) and\n * `locations`. Merged as the LOWEST-priority layer by the AccessProvider, so a\n * plugin or app may still override a key (e.g. add a `kindFilter`).\n */\nexport const CORE_LIMIT_DECLARATIONS: LimitDeclaration[] = [\n { key: 'users', label: 'Users', table: 'tenant_members' },\n { key: 'locations', label: 'Locations', table: 'locations' },\n]\n\n/**\n * Entity-derived layer of the limit merge: any registered CRUD entity carrying\n * `limitKey` yields a declaration for free from its own data mapping (table +\n * archetype kind) — a cap without a countable binding is a dead cap. Shared by\n * the AccessProvider (live registry) and the manifest derivation (agent\n * contract), so both resolve the identical layer.\n */\nexport function entityDerivedLimitDeclarations(entities: RegisteredEntity[]): LimitDeclaration[] {\n const out: LimitDeclaration[] = []\n for (const e of entities) {\n const def = e.entityDef\n if (def?.limitKey && def.data?.table) {\n out.push({\n key: def.limitKey,\n label: e.labelPlural,\n table: def.data.table,\n kindFilter: def.data.archetypeKind,\n })\n }\n }\n return out\n}\n\nlet registry = new Map<string, LimitDeclaration>()\n\n/** Called by AccessProvider whenever the merged limit declarations change. */\nexport function setLimitRegistry(declarations: LimitDeclaration[]): void {\n const next = new Map<string, LimitDeclaration>()\n for (const decl of declarations) next.set(decl.key, decl)\n registry = next\n}\n\nexport function getLimitDeclaration(key: string): LimitDeclaration | undefined {\n return registry.get(key)\n}\n\n// --- Invalidation pub/sub -------------------------------------------------\n// useLimit subscribes per key; invalidateLimit(key) drops the cached count for\n// the declaration's table and notifies subscribers to re-fetch.\n\nconst listeners = new Map<string, Set<() => void>>()\n\nexport function subscribeLimit(key: string, cb: () => void): () => void {\n let set = listeners.get(key)\n if (!set) {\n set = new Set()\n listeners.set(key, set)\n }\n set.add(cb)\n return () => {\n set?.delete(cb)\n if (set && set.size === 0) listeners.delete(key)\n }\n}\n\n/**\n * Invalidate a limit after a create/delete so its next read is fresh, then wake\n * any mounted `useLimit(key)`. Safe to call from plain handlers (no React).\n */\nexport function invalidateLimit(key: string): void {\n const decl = registry.get(key)\n if (decl) invalidateCount(decl.table)\n listeners.get(key)?.forEach((cb) => cb())\n}\n","import { create } from 'zustand'\n\n/**\n * Payload describing WHY the upgrade modal opened, so the visual component (owned\n * by the shell/gates layer) can tailor its copy — a hit quantity cap\n * (`limitKey`) or a plan-gated feature (`feature`).\n */\nexport interface UpgradeModalPayload {\n limitKey?: string\n feature?: string\n}\n\nexport interface UpgradeModalStore {\n /** The active payload, or null when closed. */\n current: UpgradeModalPayload | null\n open(payload: UpgradeModalPayload): void\n close(): void\n}\n\n/**\n * Global, lightweight store for the single app-wide UpgradeModal. `useLimitGuard`\n * and imperative create handlers call `open(...)` when a limit blocks; the visual\n * modal (rendered once near the shell root by the gates layer) subscribes to\n * `current`. Kept as a zustand singleton so store + component share one instance.\n */\nexport const useUpgradeModalStore = create<UpgradeModalStore>((set) => ({\n current: null,\n open: (payload) => set({ current: payload }),\n close: () => set({ current: null }),\n}))\n","import * as React from 'react'\nimport type { LimitDeclaration, PermissionAction, Plan } from '@fayz-ai/core'\nimport { countByTenant, usePluginRuntimeOptional, getAllEntities } from '@fayz-ai/core'\nimport { useAuthStore } from '@fayz-ai/auth'\nimport { useOrganizationStore } from '../org/store'\nimport { usePermissionsStore } from '../permissions/store'\nimport { useBillingStore } from '../billing/store'\nimport { mergeLimitDeclarations } from '@fayz-ai/core/access'\nimport { resolveAccess, isEntitledByPlan, resolveLimit } from './resolver'\nimport { entityDerivedLimitDeclarations } from './limits-registry'\nimport { setLimitRegistry, getLimitDeclaration, subscribeLimit, CORE_LIMIT_DECLARATIONS } from './limits-registry'\nimport { useUpgradeModalStore } from './upgrade-modal-store'\nimport type { AccessApi, AccessDecision, AccessSession, LimitState } from './types'\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface AccessContextValue extends AccessApi {\n session: AccessSession\n}\n\nconst AccessContext = React.createContext<AccessContextValue | null>(null)\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport interface AccessProviderProps {\n children: React.ReactNode\n /**\n * App-level limit declarations layered ON TOP of the plugins' `declaredLimits`\n * (app wins on key collision). Sourced from `config.billing.limitDeclarations`.\n */\n limitDeclarations?: LimitDeclaration[]\n}\n\n/**\n * Assembles the reactive {@link AccessSession} from the singleton stores and\n * exposes the composed access API (role × plan). Thin by design — mounts just\n * inside PermissionsProvider so it can reuse the live permission profile and the\n * plugin runtime. Also publishes the merged limit declarations to the module\n * registry so `invalidateLimit` works from non-React create handlers.\n */\nexport function AccessProvider({ children, limitDeclarations }: AccessProviderProps) {\n const user = useAuthStore((s) => s.user)\n const org = useOrganizationStore((s) => s.currentOrg)\n const profile = usePermissionsStore((s) => s.currentProfile)\n const plans = useBillingStore((s) => s.plans)\n\n const runtime = usePluginRuntimeOptional()\n const pluginLimits = runtime?.pluginLimits\n\n // Merge limit declarations by priority (later wins by key): shell built-ins\n // (users/locations) < entity-derived < plugin `declaredLimits` < app\n // overrides. Then publish to the module registry consumed by\n // invalidateLimit / the limit hooks.\n //\n // Entity-derived: any registered CRUD entity carrying `limitKey` yields a\n // declaration for free from its own data mapping (table + archetype kind) —\n // this is what makes an app's `EntityDef.limitKey: 'clients'` enforceable\n // with ZERO extra wiring (a cap without a countable binding is a dead cap).\n React.useEffect(() => {\n setLimitRegistry(\n mergeLimitDeclarations(\n CORE_LIMIT_DECLARATIONS,\n entityDerivedLimitDeclarations(getAllEntities()),\n pluginLimits,\n limitDeclarations,\n ),\n )\n }, [pluginLimits, limitDeclarations])\n\n const plan: Plan | null = React.useMemo(\n () => (org?.plan ? plans.find((p) => p.id === org.plan) ?? null : null),\n [plans, org?.plan],\n )\n\n const session: AccessSession = React.useMemo(\n () => ({ user, org, profile, plan }),\n [user, org, profile, plan],\n )\n\n const value = React.useMemo<AccessContextValue>(\n () => ({\n session,\n can: (feature, action) => resolveAccess(session, feature, action),\n entitled: (feature) => isEntitledByPlan(session.plan, feature),\n }),\n [session],\n )\n\n return <AccessContext.Provider value={value}>{children}</AccessContext.Provider>\n}\nAccessProvider.displayName = 'AccessProvider'\n\n// ---------------------------------------------------------------------------\n// Hooks\n// ---------------------------------------------------------------------------\n\nconst ALLOW_ALL: AccessApi = {\n can: () => ({ allowed: true }),\n entitled: () => true,\n}\n\n/**\n * The composed access API. Throws outside <AccessProvider> — use\n * {@link useAccessOptional} for SDK components that must degrade gracefully.\n */\nexport function useAccess(): AccessApi {\n const ctx = React.useContext(AccessContext)\n if (!ctx) throw new Error('useAccess must be used inside <AccessProvider>')\n return { can: ctx.can, entitled: ctx.entitled }\n}\n\n/**\n * Like {@link useAccess} but degrades to allow-all when no provider is mounted,\n * so components stay usable under a bare host shell (gating is an enhancement).\n */\nexport function useAccessOptional(): AccessApi {\n const ctx = React.useContext(AccessContext)\n return ctx ? { can: ctx.can, entitled: ctx.entitled } : ALLOW_ALL\n}\n\n/** Internal: the live session (for hooks that need tenant/plan directly). */\nfunction useAccessSession(): AccessSession | null {\n return React.useContext(AccessContext)?.session ?? null\n}\n\n// ---------------------------------------------------------------------------\n// Limits\n// ---------------------------------------------------------------------------\n\nfunction resolveCap(plan: Plan | null, key: string): number | undefined {\n return plan?.entitlements?.limits?.[key]\n}\n\n/**\n * Live usage of a quantity limit for the active tenant. Resolves the limit's\n * declaration (plugin manifest or app override) → a tenant-scoped `count(*)`,\n * capped by the current plan. No declaration or no cap (or `-1`) ⇒ unlimited.\n * Re-fetches when the tenant, plan cap, or an `invalidateLimit(key)` fires.\n */\nexport function useLimit(key: string): LimitState {\n const session = useAccessSession()\n const tenantId = session?.org?.id\n const cap = resolveCap(session?.plan ?? null, key)\n const declaration = getLimitDeclaration(key)\n\n const unlimited = !declaration || cap === undefined || cap === -1\n\n const [used, setUsed] = React.useState(0)\n const [loading, setLoading] = React.useState(!unlimited)\n const [version, setVersion] = React.useState(0)\n\n const refresh = React.useCallback(() => setVersion((v) => v + 1), [])\n\n // Wake on external invalidation (a create/delete elsewhere).\n React.useEffect(() => subscribeLimit(key, refresh), [key, refresh])\n\n React.useEffect(() => {\n if (unlimited || !declaration || !tenantId) {\n setUsed(0)\n setLoading(false)\n return\n }\n let active = true\n setLoading(true)\n countByTenant(declaration.table, {\n kind: declaration.kindFilter,\n period: declaration.period,\n tenantId,\n fresh: version > 0,\n })\n .then((n) => {\n if (active) {\n setUsed(n)\n setLoading(false)\n }\n })\n .catch(() => {\n if (active) setLoading(false)\n })\n return () => {\n active = false\n }\n }, [unlimited, declaration, tenantId, version])\n\n const bounds = resolveLimit({ cap, hasDeclaration: Boolean(declaration), used })\n\n return { key, ...bounds, loading, refresh }\n}\n\n/**\n * Imperative guard for create handlers: `await guard(n)` returns `'ok'` when\n * adding `n` more rows stays within the cap, or `'blocked'` (and opens the global\n * UpgradeModal) when it would exceed it. Always checks a FRESH count so it never\n * relies on stale hook state.\n */\nexport function useLimitGuard(key: string): (n?: number) => Promise<'ok' | 'blocked'> {\n const session = useAccessSession()\n const tenantId = session?.org?.id\n const plan = session?.plan ?? null\n const openModal = useUpgradeModalStore((s) => s.open)\n\n return React.useCallback(\n async (n = 1) => {\n const cap = resolveCap(plan, key)\n const declaration = getLimitDeclaration(key)\n // Unlimited / no declaration / no tenant ⇒ never block.\n if (!declaration || cap === undefined || cap === -1 || !tenantId) return 'ok'\n\n const used = await countByTenant(declaration.table, {\n kind: declaration.kindFilter,\n period: declaration.period,\n tenantId,\n fresh: true,\n })\n\n if (used + n > cap) {\n openModal({ limitKey: key })\n return 'blocked'\n }\n return 'ok'\n },\n [key, plan, tenantId, openModal],\n )\n}\n","import type { PermissionAction, Plan } from '@fayz-ai/core'\nimport { countByTenant } from '@fayz-ai/core'\nimport { resolveAccess, agentDenial, type AgentGuardResult } from '@fayz-ai/core/access'\nimport { useAuthStore } from '@fayz-ai/auth'\nimport { useOrganizationStore } from '../org/store'\nimport { usePermissionsStore } from '../permissions/store'\nimport { useBillingStore } from '../billing/store'\nimport { getLimitDeclaration } from './limits-registry'\nimport type { AccessSession } from './types'\n\n// ---------------------------------------------------------------------------\n// Headless access — the imperative counterpart of useAccess()/useLimitGuard()\n// for runtimes without React: the agent's client-plane tool executor, command\n// handlers, background sync. Reads the SAME singleton stores the providers\n// hydrate, and decides with the SAME engine (@fayz-ai/core/access), so a\n// decision here never diverges from what the UI shows.\n//\n// Denials come back as the structured AgentDenial (never a silent failure) so\n// an agent can explain the denial and offer the upgrade conversationally.\n// ---------------------------------------------------------------------------\n\n/**\n * Snapshot of the live session assembled from the singleton stores — the same\n * assembly AccessProvider does reactively. Values are as-hydrated: before\n * AuthProvider/OrgProvider finish, fields are null (and decisions fail-open on\n * profile, closed on nothing — same semantics as the providers).\n */\nexport function getAccessSnapshot(): AccessSession {\n const user = useAuthStore.getState().user\n const org = useOrganizationStore.getState().currentOrg\n const profile = usePermissionsStore.getState().currentProfile\n const plans = useBillingStore.getState().plans\n const plan: Plan | null = org?.plan ? plans.find((p) => p.id === org.plan) ?? null : null\n return { user, org, profile, plan }\n}\n\n/** Imperative role × plan check over the live snapshot. */\nexport function checkAccess(feature: string, action?: PermissionAction): AgentGuardResult {\n const session = getAccessSnapshot()\n const decision = resolveAccess(session, feature, action)\n if (decision.allowed) return { allowed: true }\n return agentDenial(decision.reason ?? 'role')\n}\n\n/**\n * Imperative plan-limit guard: would adding `n` rows exceed the cap for\n * `key`? Counts FRESH (never trusts stale hook state), mirrors useLimitGuard.\n * No declaration / no cap / `-1` / no tenant ⇒ allowed. Does NOT open the\n * UpgradeModal — the caller decides how to surface the denial (an agent turns\n * it into a conversational upgrade prompt).\n */\nexport async function guardLimit(key: string, n = 1): Promise<AgentGuardResult> {\n const session = getAccessSnapshot()\n const tenantId = session.org?.id\n const cap = session.plan?.entitlements?.limits?.[key]\n const declaration = getLimitDeclaration(key)\n\n if (!declaration || cap === undefined || cap === -1 || !tenantId) return { allowed: true }\n\n const used = await countByTenant(declaration.table, {\n kind: declaration.kindFilter,\n period: declaration.period,\n tenantId,\n fresh: true,\n })\n\n if (used + n > cap) {\n return agentDenial('limit', { key, max: cap, used })\n }\n return { allowed: true }\n}\n","import * as React from 'react'\nimport type { ModuleNavItem } from '@fayz-ai/ui'\nimport { usePermissionsStore } from '../permissions/store'\nimport { useAccessOptional } from './context'\nimport type { AccessApi } from './types'\n\n// ---------------------------------------------------------------------------\n// useModuleNavAccess — the LINK-side counterpart of EntitlementGate for a\n// plugin's INTERNAL navigation (ModulePage sub-nav). Mirrors the top-level\n// Sidebar/AdminShell rule so a premium sub-module link reads identically:\n//\n// • role denies (can(feature,'read').reason === 'role') → REMOVE the link\n// • plan denies (entitled(feature) === false) → keep, premium:true\n// (the click still navigates; the gated CONTENT shows the\n// UpgradePrompt via EntitlementGate)\n// • otherwise → keep as-is\n//\n// A feature id ABSENT from the RBAC catalog is treated as \"default allow\": the\n// role axis is skipped entirely for it (an undeclared feature can't be a role\n// denial), so apps that wire the plugin without declaring the sub-feature don't\n// lose the link. The plan axis is naturally safe already — `entitled` returns\n// true for any feature a plan never disables.\n//\n// Recursive over `children`. Degrades to allow-all when no <AccessProvider> is\n// mounted (bare host shell), exactly like `useAccessOptional`.\n// ---------------------------------------------------------------------------\n\n/**\n * Pure decoration used by {@link useModuleNavAccess}. Kept store-free so it is\n * directly unit-testable: pass the composed {@link AccessApi} and the set of\n * feature ids known to the RBAC catalog.\n */\nexport function applyNavAccess(\n items: ModuleNavItem[],\n access: AccessApi,\n knownFeatures: Set<string>,\n): ModuleNavItem[] {\n const decorate = (item: ModuleNavItem): ModuleNavItem | null => {\n const children = item.children\n ? item.children\n .map(decorate)\n .filter((c): c is ModuleNavItem => c !== null)\n : undefined\n\n if (!item.feature) {\n return children ? { ...item, children } : item\n }\n\n // Role axis — only meaningful for a feature the RBAC catalog actually\n // declares. An undeclared feature defaults to allow (never removed).\n if (knownFeatures.has(item.feature)) {\n const decision = access.can(item.feature, 'read')\n if (!decision.allowed && decision.reason === 'role') return null\n }\n\n // Plan axis — `entitled` is `false` only on an explicit plan denial; absent\n // features stay entitled, so no Crown appears for them.\n const premium = access.entitled(item.feature) === false\n\n return children ? { ...item, premium, children } : { ...item, premium }\n }\n\n return items.map(decorate).filter((i): i is ModuleNavItem => i !== null)\n}\n\n/**\n * Resolve a plugin's internal nav against role × plan: hides role-denied links,\n * badges plan-denied ones with a Crown (`premium`), and passes everything else\n * through unchanged. Recursive over children.\n */\nexport function useModuleNavAccess(items: ModuleNavItem[]): ModuleNavItem[] {\n const access = useAccessOptional()\n const features = usePermissionsStore((s) => s.features)\n const knownFeatures = React.useMemo(\n () => new Set(features.map((f) => f.id)),\n [features],\n )\n return React.useMemo(\n () => applyNavAccess(items, access, knownFeatures),\n [items, access, knownFeatures],\n )\n}\n","// ---------------------------------------------------------------------------\n// access-contract — the single import seam the billing UI uses for the\n// entitlements engine (UpgradePrompt, UpgradeModal, EntitlementGate, LimitGate,\n// SoftLimitBanner, the AdminShell route guard / nav badge, SubscriptionPage\n// matrix). Re-exports the core access engine (packages/saas/src/access) so the\n// billing layer has ONE stable path and the wiring (AccessProvider) stays in the\n// núcleo. `getPlanEntitlements` is a thin local reader — core's Plan carries the\n// entitlements, so this just narrows the access.\n//\n// (History: this file shipped as a temporary stub while the access engine landed\n// in parallel; now repointed to the real module. The public names/types below\n// match the fixed contract, so no billing-wave consumer changed.)\n// ---------------------------------------------------------------------------\nimport type { Plan, PlanEntitlements } from '@fayz-ai/core'\n\nexport {\n useAccessOptional,\n useLimit,\n useLimitGuard,\n invalidateLimit,\n useUpgradeModalStore,\n} from '../../access'\n\nexport type { AccessApi, AccessDecision } from '../../access'\n// The billing layer refers to the limit shape as `LimitInfo`; the engine calls\n// it `LimitState`. Same structure — alias to keep call sites stable.\nexport type { LimitState as LimitInfo } from '../../access'\nexport type { PlanEntitlements } from '@fayz-ai/core'\n\n/** Narrow a plan to its entitlements (undefined when the plan declares none). */\nexport function getPlanEntitlements(plan: Plan | undefined | null): PlanEntitlements | undefined {\n return plan?.entitlements\n}\n\n/**\n * Clean a feature's raw permission label into a display name for the upgrade\n * surfaces. Feature labels in an app's permissions config carry an access-scope\n * suffix — e.g. \"Marketing (acesso)\" / \"Reports (access)\" — which reads as noise\n * when interpolated into a headline (\"Unlock Marketing (acesso)\"). Strip a single\n * trailing parenthetical group and collapse surrounding whitespace. Shared by\n * UpgradePrompt AND UpgradeModal so the two surfaces stay in lockstep.\n */\nexport function featureDisplayName(label: string | null | undefined): string {\n if (!label) return ''\n return label.replace(/\\s*\\([^)]*\\)\\s*$/, '').trim() || label.trim()\n}\n\n/**\n * Which ISO-4217 code to price a plan in. `Plan.currency` is the source of\n * truth, but apps DO ship billing configs that omit it — and silently printing\n * \"$79\" to a tenant billed in reais is worse than any other failure mode here.\n * So the fallback follows the ACTIVE LOCALE's region rather than a hardcoded\n * 'USD'; only a locale we can't place at all lands on USD.\n */\nconst CURRENCY_BY_REGION: Record<string, string> = {\n BR: 'BRL', PT: 'EUR', ES: 'EUR', FR: 'EUR', DE: 'EUR', IT: 'EUR', NL: 'EUR', IE: 'EUR',\n GB: 'GBP', US: 'USD', CA: 'CAD', AU: 'AUD', MX: 'MXN', AR: 'ARS', CL: 'CLP', CO: 'COP',\n}\n\nexport function resolvePlanCurrency(planCurrency: string | undefined, locale: string | undefined): string {\n if (planCurrency) return planCurrency\n const region = locale?.split(/[-_]/)[1]?.toUpperCase()\n return (region && CURRENCY_BY_REGION[region]) || 'USD'\n}\n","import * as React from 'react'\nimport { Crown, Check, Minus, Sparkles } from 'lucide-react'\nimport { PlanFeatureItem, parsePlanFeature } from './plan-feature'\nimport { Button, Badge, Card, CardContent, CardHeader, ConfirmDialog, toast } from '@fayz-ai/ui'\nimport type { Plan } from '@fayz-ai/core'\nimport { cn } from '../../lib/cn'\nimport { useTranslation } from '../../hooks/useTranslation'\nimport { useBillingStore } from '../../stores/billing.store'\nimport { resolvePlanBadge } from '../../billing/plan-badge'\nimport { useTenantOptional, useOrgAdapterOptional } from '../../org/context'\nimport { useOrganizationStore } from '../../org/store'\nimport { usePermissionsStore } from '../../permissions'\nimport { getPlanEntitlements } from './access-contract'\n\n// ---------------------------------------------------------------------------\n// SubscriptionPage — the shell's self-serve subscription surface. Present as the\n// /settings/subscription tab whenever `config.billing` is configured. Reads the\n// plans seeded into the billing store from config, resolves the current plan\n// from `currentOrg.plan`, and changes plan via the checkout seam (Stripe/Pix) or,\n// when no seam is configured, an optimistic `adapter.updateOrg(orgId, { plan })`.\n// ---------------------------------------------------------------------------\n\nfunction formatPrice(plan: Plan, tr: (k: string, f: string) => string): string {\n if (plan.price <= 0) return tr('billing.free', 'Free')\n try {\n const isInteger = Number.isInteger(plan.price)\n return new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency: plan.currency || 'USD',\n minimumFractionDigits: isInteger ? 0 : 2,\n }).format(plan.price)\n } catch {\n return `${plan.currency || ''} ${plan.price}`.trim()\n }\n}\n\nfunction intervalSuffix(plan: Plan, tr: (k: string, f: string) => string): string {\n if (plan.price <= 0) return ''\n return plan.interval === 'year'\n ? tr('billing.perYear', '/yr')\n : tr('billing.perMonth', '/mo')\n}\n\nexport function SubscriptionPage({ className }: { className?: string }) {\n const { t } = useTranslation()\n const tr = (key: string, fallback: string) => {\n const v = t(key)\n return !v || v === key ? fallback : v\n }\n\n const plans = useBillingStore((s) => s.plans)\n const checkout = useBillingStore((s) => s.checkout)\n const tenant = useTenantOptional()\n const adapter = useOrgAdapterOptional()\n const setCurrentOrg = useOrganizationStore((s) => s.setCurrentOrg)\n const currentOrg = useOrganizationStore((s) => s.currentOrg)\n\n const currentPlanId = currentOrg?.plan || 'free'\n const currentBadge = resolvePlanBadge(currentPlanId, plans)\n const currentPlan = plans.find((p) => p.id === currentPlanId)\n\n const [pending, setPending] = React.useState<Plan | null>(null)\n const [busy, setBusy] = React.useState(false)\n\n // Feature matrix — union of every plan's features, order-preserved.\n const allFeatures = React.useMemo(() => {\n const seen = new Set<string>()\n const out: string[] = []\n for (const plan of plans) {\n for (const f of plan.features) {\n if (!seen.has(f)) {\n seen.add(f)\n out.push(f)\n }\n }\n }\n return out\n }, [plans])\n\n // Real entitlements matrix — derived from plan.entitlements when any plan\n // declares them. Feature rows show ✓/— per plan; limit rows show \"Up to N\" /\n // \"Unlimited\". Falls back to the marketing-bullet matrix (allFeatures) below\n // when no plan carries entitlements.\n const featureCatalog = usePermissionsStore((s) => s.features)\n const entitlementsMatrix = React.useMemo(() => {\n const hasAny = plans.some((p) => getPlanEntitlements(p))\n if (!hasAny) return null\n\n const featureIds: string[] = []\n const featureSeen = new Set<string>()\n const limitKeys: string[] = []\n const limitSeen = new Set<string>()\n for (const plan of plans) {\n const ent = getPlanEntitlements(plan)\n for (const id of Object.keys(ent?.features ?? {})) {\n if (!featureSeen.has(id)) { featureSeen.add(id); featureIds.push(id) }\n }\n for (const key of Object.keys(ent?.limits ?? {})) {\n if (!limitSeen.has(key)) { limitSeen.add(key); limitKeys.push(key) }\n }\n }\n if (featureIds.length === 0 && limitKeys.length === 0) return null\n\n const labelForFeature = (id: string) => featureCatalog.find((f) => f.id === id)?.label ?? id\n const labelForLimit = (key: string) => {\n const v = t(`limit.label.${key}`)\n return !v || v === `limit.label.${key}` ? key : v\n }\n return { featureIds, limitKeys, labelForFeature, labelForLimit }\n }, [plans, featureCatalog, t])\n\n async function applyChange(plan: Plan) {\n setBusy(true)\n try {\n // Seam: a configured gateway (Stripe/Pix) owns the transition; the webhook\n // is the source of truth for the persisted plan, so we don't mutate here.\n if (checkout) {\n await checkout(plan.id)\n setPending(null)\n return\n }\n // No gateway: optimistic org update. Persist + swap the store so the plan\n // badge and CTAs re-render immediately.\n if (adapter && currentOrg) {\n const updated = await adapter.updateOrg(currentOrg.id, { plan: plan.id })\n setCurrentOrg(updated)\n } else if (currentOrg) {\n setCurrentOrg({ ...currentOrg, plan: plan.id })\n }\n toast.success(\n tr('billing.planChanged', 'Plan updated').replace('{{plan}}', plan.name),\n )\n setPending(null)\n } catch {\n toast.error(tr('billing.planChangeFailed', \"Couldn't change your plan. Please try again.\"))\n } finally {\n setBusy(false)\n }\n }\n\n if (plans.length === 0) {\n return (\n <div className={className ?? 'mx-auto max-w-5xl'}>\n <p className=\"text-sm text-muted-foreground\">\n {tr('billing.noPlans', 'No plans are configured.')}\n </p>\n </div>\n )\n }\n\n return (\n <div className={className ?? 'mx-auto max-w-5xl space-y-8'}>\n {/* Sem título nem descrição: a barra já escreve \"Assinatura\", e a frase\n embaixo custava uma linha para repetir o que os planos mostram. */}\n\n {/* Current plan highlight */}\n <Card\n className={cn(\n 'relative overflow-hidden',\n currentBadge.paid && 'border-amber-400/60 bg-gradient-to-br from-amber-50/60 to-transparent dark:from-amber-950/20',\n )}\n >\n <CardContent className=\"flex flex-wrap items-center justify-between gap-4 p-6\">\n <div className=\"flex items-center gap-4\">\n <div\n className={cn(\n 'flex h-12 w-12 shrink-0 items-center justify-center rounded-xl',\n currentBadge.paid ? 'bg-amber-400/20 text-amber-600 dark:text-amber-400' : 'bg-muted text-muted-foreground',\n )}\n >\n {currentBadge.paid ? <Crown className=\"h-6 w-6\" /> : <Sparkles className=\"h-6 w-6\" />}\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {tr('billing.currentPlan', 'Current Plan')}\n </p>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xl font-bold\">{currentBadge.label}</span>\n {currentBadge.paid && (\n // Paid marker only — a literal \"Pro\" here was misleading next\n // to non-Pro paid tiers (\"Starter / Pro\", QA finding).\n <Badge\n aria-label={tr('billing.paidPlan', 'Paid plan')}\n className=\"border-amber-400/40 bg-amber-400/15 text-amber-700 dark:text-amber-300\"\n >\n <Crown className=\"h-3 w-3\" />\n </Badge>\n )}\n </div>\n </div>\n </div>\n {currentPlan && (\n <div className=\"text-right\">\n <span className=\"text-2xl font-bold\">{formatPrice(currentPlan, tr)}</span>\n <span className=\"text-sm text-muted-foreground\">{intervalSuffix(currentPlan, tr)}</span>\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Plan cards */}\n <div className=\"grid gap-6 md:grid-cols-2 lg:grid-cols-3\">\n {plans.map((plan) => {\n const isCurrent = plan.id === currentPlanId\n const paid = plan.price > 0\n return (\n <Card\n key={plan.id}\n className={cn(\n 'relative flex flex-col',\n plan.highlighted && 'border-primary shadow-md',\n isCurrent && 'ring-2 ring-primary/40',\n )}\n >\n {plan.highlighted && (\n <div className=\"absolute -top-3 left-1/2 -translate-x-1/2\">\n <Badge>\n <Crown className=\"mr-1 h-3 w-3\" />\n {tr('billing.mostPopular', 'Most Popular')}\n </Badge>\n </div>\n )}\n <CardHeader className=\"pb-0\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-xl font-semibold\">{plan.name}</h3>\n {paid && <Crown className=\"h-4 w-4 text-amber-500\" />}\n </div>\n {plan.description && (\n <p className=\"text-sm text-muted-foreground\">{plan.description}</p>\n )}\n </CardHeader>\n <CardContent className=\"flex flex-1 flex-col pt-4\">\n <div className=\"mb-6\">\n <span className=\"text-4xl font-bold\">{formatPrice(plan, tr)}</span>\n <span className=\"text-muted-foreground\">{intervalSuffix(plan, tr)}</span>\n </div>\n <ul className=\"mb-6 flex-1 space-y-3\">\n {plan.features.map((feature) => (\n <PlanFeatureItem key={feature} feature={feature} className=\"text-sm\" iconClassName=\"h-4 w-4\" />\n ))}\n </ul>\n {isCurrent ? (\n <Button variant=\"outline\" className=\"w-full\" disabled>\n {tr('billing.currentPlan', 'Current Plan')}\n </Button>\n ) : (\n <Button\n className=\"w-full\"\n variant={plan.highlighted ? 'default' : 'outline'}\n onClick={() => setPending(plan)}\n >\n {tr('billing.changeToPlan', 'Switch to this plan')}\n </Button>\n )}\n </CardContent>\n </Card>\n )\n })}\n </div>\n\n {/* Feature matrix */}\n {(entitlementsMatrix || allFeatures.length > 0) && (\n <div className=\"space-y-3\">\n <h2 className=\"text-lg font-semibold\">\n {tr('billing.featureMatrix', 'Feature comparison')}\n </h2>\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full border-collapse text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/40\">\n <th className=\"px-4 py-3 text-left font-medium\">\n {tr('billing.features', 'Features')}\n </th>\n {plans.map((plan) => (\n <th key={plan.id} className=\"px-4 py-3 text-center font-medium\">\n <span className=\"inline-flex items-center gap-1\">\n {plan.price > 0 && <Crown className=\"h-3.5 w-3.5 text-amber-500\" />}\n {plan.name}\n </span>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {entitlementsMatrix ? (\n <>\n {entitlementsMatrix.featureIds.map((id, i) => (\n <tr key={`f:${id}`} className={cn(i % 2 === 1 && 'bg-muted/20')}>\n <td className=\"px-4 py-2.5 text-left\">{entitlementsMatrix.labelForFeature(id)}</td>\n {plans.map((plan) => {\n const entitled = getPlanEntitlements(plan)?.features?.[id] !== false\n return (\n <td key={plan.id} className=\"px-4 py-2.5 text-center\">\n {entitled ? (\n <Check className=\"mx-auto h-4 w-4 text-primary\" />\n ) : (\n <Minus className=\"mx-auto h-4 w-4 text-muted-foreground/40\" />\n )}\n </td>\n )\n })}\n </tr>\n ))}\n {entitlementsMatrix.limitKeys.map((key, i) => (\n <tr key={`l:${key}`} className={cn((entitlementsMatrix.featureIds.length + i) % 2 === 1 && 'bg-muted/20')}>\n <td className=\"px-4 py-2.5 text-left\">{entitlementsMatrix.labelForLimit(key)}</td>\n {plans.map((plan) => {\n const cap = getPlanEntitlements(plan)?.limits?.[key]\n const cell =\n cap === undefined\n ? '—'\n : cap < 0\n ? tr('billing.unlimited', 'Unlimited')\n : tr('billing.upTo', 'Up to {count}').replace('{count}', String(cap)).replace('{{count}}', String(cap))\n return (\n <td key={plan.id} className=\"px-4 py-2.5 text-center text-muted-foreground\">\n {cell}\n </td>\n )\n })}\n </tr>\n ))}\n </>\n ) : (\n allFeatures.map((feature, i) => (\n <tr key={feature} className={cn(i % 2 === 1 && 'bg-muted/20')}>\n <td className=\"px-4 py-2.5 text-left\">{parsePlanFeature(feature).label}</td>\n {plans.map((plan) => (\n <td key={plan.id} className=\"px-4 py-2.5 text-center\">\n {plan.features.includes(feature) ? (\n <Check className=\"mx-auto h-4 w-4 text-primary\" />\n ) : (\n <Minus className=\"mx-auto h-4 w-4 text-muted-foreground/40\" />\n )}\n </td>\n ))}\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n </div>\n )}\n\n {/* Change-plan confirm */}\n <ConfirmDialog\n open={pending !== null}\n onConfirm={() => pending && void applyChange(pending)}\n onCancel={() => setPending(null)}\n title={tr('billing.changePlanConfirmTitle', 'Change plan?')}\n description={\n pending\n ? tr('billing.changePlanConfirmBody', \"You're switching to the {{plan}} plan.\").replace('{{plan}}', pending.name)\n : undefined\n }\n confirmLabel={tr('billing.changePlanConfirm', 'Switch plan')}\n cancelLabel={tr('common.cancel', 'Cancel')}\n loading={busy}\n />\n </div>\n )\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/org/store.ts","../src/org/cache.ts","../src/org/context.tsx"],"names":["STORAGE_KEY"],"mappings":"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","file":"chunk-OB7ZSTQD.js","sourcesContent":["import { create } from 'zustand'\nimport { setActiveTenantId, type Organization, type OrgMember, type OrgMembership } from '@fayz-ai/core'\n\nconst STORAGE_KEY = 'fayz:current-org'\n\n// ---------------------------------------------------------------------------\n// Persistence helpers\n// ---------------------------------------------------------------------------\n\nfunction getPersistedOrgId(): string | null {\n try {\n if (typeof localStorage === 'undefined') return null\n return localStorage.getItem(STORAGE_KEY)\n } catch {\n return null\n }\n}\n\nfunction persistOrgId(orgId: string | null): void {\n try {\n if (typeof localStorage === 'undefined') return\n if (orgId) {\n localStorage.setItem(STORAGE_KEY, orgId)\n } else {\n localStorage.removeItem(STORAGE_KEY)\n }\n } catch {\n // ignore\n }\n}\n\n// ---------------------------------------------------------------------------\n// Store interface\n// ---------------------------------------------------------------------------\n\nexport interface OrgStore {\n currentOrg: Organization | null\n userOrgs: OrgMembership[]\n members: OrgMember[]\n /** Person `kind`s that make up the team (from config.team.personKinds). Drives\n * the Person-first Team screen; empty = legacy membership-only mode. */\n teamPersonKinds: string[]\n loading: boolean\n\n setCurrentOrg: (org: Organization | null) => void\n setUserOrgs: (orgs: OrgMembership[]) => void\n setMembers: (members: OrgMember[]) => void\n setTeamPersonKinds: (kinds: string[]) => void\n setLoading: (loading: boolean) => void\n reset: () => void\n}\n\nexport const useOrganizationStore = create<OrgStore>((set) => ({\n currentOrg: null,\n userOrgs: [],\n members: [],\n teamPersonKinds: [],\n loading: false,\n\n setCurrentOrg: (org) => {\n setActiveTenantId(org?.id)\n persistOrgId(org?.id ?? null)\n set({ currentOrg: org })\n },\n setUserOrgs: (orgs) => set({ userOrgs: orgs }),\n setMembers: (members) => set({ members }),\n setTeamPersonKinds: (kinds) => set({ teamPersonKinds: kinds }),\n setLoading: (loading) => set({ loading }),\n reset: () => {\n setActiveTenantId(undefined)\n // NOTE: do NOT clear the persisted org id here. The org providers call\n // reset() whenever the auth store transiently reports `user === null` —\n // which happens on every fresh load while the Supabase session hydrates\n // asynchronously. Wiping 'fayz:current-org' at that moment drops a\n // multi-org user's workspace selection BEFORE loadOrgs can read it back,\n // so the app always falls to memberships[0] on reload (single-org users\n // never noticed). The pin is a last-selected hint that's re-validated\n // against the fresh membership list on load, so it's safe to keep across\n // sign-out too (a mismatching pin just falls back to memberships[0]).\n set({ currentOrg: null, userOrgs: [], members: [], loading: false })\n },\n}))\n\nexport { getPersistedOrgId }\n","import type { Organization, OrgMember, OrgMembership, PermissionProfile } from '@fayz-ai/core'\n\n/**\n * Snapshot of the org bootstrap (org + memberships + members + permission\n * profiles) so a page reload doesn't wait on the whole chain again.\n *\n * Every mount used to pay `acceptPendingInvites → listUserOrgs → getOrg →\n * listMembers + listProfiles` before `org.id` existed, and every screen keyed\n * off the tenant (Conectores, plugin tabs, permission gates) sat idle until\n * then. The snapshot paints that state synchronously and the network is only\n * touched again once it goes stale.\n */\n\nconst STORAGE_KEY = 'fayz:org-snapshot'\nconst VERSION = 1\n\n/** Served without touching the network. */\nexport const ORG_CACHE_TTL_MS = 5 * 60 * 1000\n/** Older than this and the snapshot is dropped instead of painted. */\nconst MAX_AGE_MS = 24 * 60 * 60 * 1000\n/** Bigger than this (huge member lists) and we skip persisting rather than blow the quota. */\nconst MAX_BYTES = 512 * 1024\n\nexport interface OrgSnapshot {\n version: number\n /** Who the snapshot belongs to — a different user gets a cold load. */\n userId: string\n /** When the data last came from the server (store patches don't move it). */\n savedAt: number\n org: Organization\n userOrgs: OrgMembership[]\n members: OrgMember[]\n profiles: PermissionProfile[]\n currentProfileId: string | null\n}\n\nexport type OrgSnapshotInput = Omit<OrgSnapshot, 'version' | 'savedAt'>\n\nfunction storage(): Storage | null {\n try {\n if (typeof localStorage === 'undefined') return null\n return localStorage\n } catch {\n return null\n }\n}\n\nexport function readOrgSnapshot(): OrgSnapshot | null {\n const store = storage()\n if (!store) return null\n try {\n const raw = store.getItem(STORAGE_KEY)\n if (!raw) return null\n const snapshot = JSON.parse(raw) as OrgSnapshot\n if (snapshot?.version !== VERSION || !snapshot.org?.id || !snapshot.userId) return null\n if (snapshotAge(snapshot) > MAX_AGE_MS) {\n store.removeItem(STORAGE_KEY)\n return null\n }\n return snapshot\n } catch {\n return null\n }\n}\n\nexport function snapshotAge(snapshot: OrgSnapshot): number {\n const age = Date.now() - snapshot.savedAt\n // A clock that moved backwards shouldn't hand out an eternally fresh cache.\n return age < 0 ? Number.POSITIVE_INFINITY : age\n}\n\nexport function isSnapshotFresh(snapshot: OrgSnapshot, ttlMs: number): boolean {\n return snapshotAge(snapshot) < ttlMs\n}\n\n/** Record a fresh server read — restarts the TTL window. */\nexport function saveOrgSnapshot(input: OrgSnapshotInput): void {\n write({ ...input, version: VERSION, savedAt: Date.now() })\n}\n\n/**\n * Keep the snapshot in step with store writes made outside the provider\n * (renaming the org in Settings, editing a role) WITHOUT restarting the TTL —\n * otherwise a UI-only change would push the next revalidation out forever.\n */\nexport function patchOrgSnapshot(input: OrgSnapshotInput): void {\n const current = readOrgSnapshot()\n if (!current || current.userId !== input.userId) return\n write({ ...input, version: VERSION, savedAt: current.savedAt })\n}\n\nexport function clearOrgSnapshot(): void {\n try {\n storage()?.removeItem(STORAGE_KEY)\n } catch {\n // ignore\n }\n}\n\nfunction write(snapshot: OrgSnapshot): void {\n const store = storage()\n if (!store) return\n try {\n const raw = JSON.stringify(snapshot)\n if (raw.length > MAX_BYTES) return\n store.setItem(STORAGE_KEY, raw)\n } catch {\n // Quota or serialization failure — the cache is an optimization, not state.\n }\n}\n","import * as React from 'react'\nimport type { OrgAdapter, Organization, OrgMembership } from '@fayz-ai/core'\nimport { useAuthStore } from '@fayz-ai/auth'\nimport { useOrganizationStore, getPersistedOrgId } from './store'\nimport { usePermissionsStore } from '../permissions'\nimport {\n ORG_CACHE_TTL_MS,\n clearOrgSnapshot,\n isSnapshotFresh,\n patchOrgSnapshot,\n readOrgSnapshot,\n saveOrgSnapshot,\n type OrgSnapshot,\n} from './cache'\n\n// ---------------------------------------------------------------------------\n// Adapter context\n// ---------------------------------------------------------------------------\n\nconst OrgAdapterContext = React.createContext<OrgAdapter | null>(null)\n\nexport function useOrgAdapter(): OrgAdapter {\n const adapter = React.useContext(OrgAdapterContext)\n if (!adapter) {\n throw new Error('useOrgAdapter must be used within an <OrgProvider>')\n }\n return adapter\n}\n\nexport function useOrgAdapterOptional(): OrgAdapter | null {\n return React.useContext(OrgAdapterContext)\n}\n\n// ---------------------------------------------------------------------------\n// Tenant / org hook\n// ---------------------------------------------------------------------------\n\nexport interface TenantContext {\n /** The currently active organization */\n org: Organization | null\n /** All orgs the current user belongs to */\n userOrgs: OrgMembership[]\n loading: boolean\n /**\n * The bootstrap has finished at least once, so `org === null` now MEANS\n * \"belongs to no workspace\" instead of \"we have not looked yet\".\n *\n * `loading` cannot answer that: it starts `false`, before the effect that\n * loads anything has run. Anything deciding what to render from an empty org\n * — the setup gate — reads this, or it decides during the gap and flips its\n * mind a frame later.\n */\n settled: boolean\n /** Switch the active org */\n switchOrg: (orgId: string) => Promise<void>\n /** Refresh the current org from the adapter */\n refreshOrg: () => Promise<void>\n}\n\nconst TenantContext = React.createContext<TenantContext | null>(null)\n\n/**\n * Access the current tenant / organization.\n * Must be used inside <OrgProvider>.\n */\nexport function useTenant(): TenantContext {\n const ctx = React.useContext(TenantContext)\n if (!ctx) {\n throw new Error('useTenant must be used inside <OrgProvider>')\n }\n return ctx\n}\n\nexport function useTenantOptional(): TenantContext | null {\n return React.useContext(TenantContext)\n}\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport interface OrgProviderProps {\n adapter: OrgAdapter\n /** When true, automatically creates an org if the user has none */\n autoCreate?: boolean\n /**\n * How long the cached org bootstrap is served before the provider goes back\n * to the network (default 5 min). A cached load paints synchronously, so\n * screens that key off `org.id` don't wait a round trip on every reload.\n * `0` disables the cache and restores the always-fetch behaviour.\n */\n cacheTtlMs?: number\n children: React.ReactNode\n}\n\nconst useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect\n\nexport function OrgProvider({\n adapter,\n autoCreate = false,\n cacheTtlMs = ORG_CACHE_TTL_MS,\n children,\n}: OrgProviderProps) {\n const { user, isLoading: authLoading } = useAuthStore()\n const { currentOrg, userOrgs, loading, setCurrentOrg, setUserOrgs, setMembers, setLoading, reset } =\n useOrganizationStore()\n const setProfiles = usePermissionsStore((s) => s.setProfiles)\n const setCurrentProfile = usePermissionsStore((s) => s.setCurrentProfile)\n\n const adapterRef = React.useRef(adapter)\n adapterRef.current = adapter\n\n const [snapshot] = React.useState<OrgSnapshot | null>(() =>\n cacheTtlMs > 0 ? readOrgSnapshot() : null,\n )\n // One load per signed-in user per mount — auth reports `isLoading` and `user`\n // in two separate store writes, so the effect would otherwise fire twice.\n const loadedForRef = React.useRef<string | null>(null)\n\n // WHOSE bootstrap has finished, not whether one has. A boolean could not tell\n // the difference between \"we know this account has no workspace\" and \"we knew\n // that about the account that just signed out\" — which is what flashed the\n // setup flow over every login: sign-out settled it, and sign-in kept the\n // stale `true` for the whole round trip.\n //\n // A painted snapshot is already an answer for its own user: that account HAS a\n // workspace, and revalidation will not turn that into \"has none\".\n const [settledFor, setSettledFor] = React.useState<string | null>(() =>\n snapshot?.org ? snapshot.userId : null,\n )\n // Signed out there is nothing to wait for; signed in, only this user's answer counts.\n const settled = user ? settledFor === user.id : !authLoading\n\n // Paint the last known org before the first child renders. The stores are\n // filled in a layout effect, so nothing gets a frame with `org === null`.\n useIsomorphicLayoutEffect(() => {\n if (!snapshot) return\n setUserOrgs(snapshot.userOrgs)\n setCurrentOrg(snapshot.org)\n setMembers(snapshot.members)\n setProfiles(snapshot.profiles)\n setCurrentProfile(snapshot.profiles.find((p) => p.id === snapshot.currentProfileId) ?? null)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // Keep the snapshot in step with store writes made outside this provider —\n // renaming the org in Settings, editing a role — so the cache never serves a\n // value the user already changed on screen. Patching leaves `savedAt` alone:\n // a UI-only edit must not push the next revalidation further out.\n React.useEffect(() => {\n if (cacheTtlMs <= 0 || !user) return\n const uid = user.id\n const sync = () => {\n const org = useOrganizationStore.getState()\n if (!org.currentOrg) return\n const perms = usePermissionsStore.getState()\n patchOrgSnapshot({\n userId: uid,\n org: org.currentOrg,\n userOrgs: org.userOrgs,\n members: org.members,\n profiles: perms.profiles,\n // realProfile, not currentProfile: an impersonation preview is not\n // something to cache back as the user's own role.\n currentProfileId: perms.realProfile?.id ?? null,\n })\n }\n const unsubscribeOrg = useOrganizationStore.subscribe(sync)\n const unsubscribePerms = usePermissionsStore.subscribe(sync)\n return () => {\n unsubscribeOrg()\n unsubscribePerms()\n }\n }, [user?.id, cacheTtlMs])\n\n // Load the org's members + permission profiles into the shared stores whenever\n // an org resolves. This is what makes the role list, the invite dialog's role\n // dropdown, and permission checks work — previously nothing loaded them here,\n // so those surfaces came up empty. Also resolves the signed-in user's own role.\n const hydrateOrg = React.useCallback(\n async (org: Organization, memberships: OrgMembership[], uid: string | undefined) => {\n try {\n const [members, profiles] = await Promise.all([\n adapterRef.current.listMembers(org.id),\n adapterRef.current.listProfiles(org.id),\n ])\n setMembers(members)\n setProfiles(profiles)\n const myMembership = uid ? members.find((m) => m.userId === uid) : undefined\n const profile = profiles.find((p) => p.id === myMembership?.profileId) ?? null\n setCurrentProfile(profile)\n // Everything the next reload needs, stamped now — this is the only\n // place the TTL window restarts.\n if (cacheTtlMs > 0 && uid) {\n saveOrgSnapshot({\n userId: uid,\n org,\n userOrgs: memberships,\n members,\n profiles,\n currentProfileId: profile?.id ?? null,\n })\n }\n } catch {\n // Non-fatal — leave stores as-is if the load fails.\n }\n },\n [setMembers, setProfiles, setCurrentProfile, cacheTtlMs],\n )\n\n // Load orgs when user is authenticated\n React.useEffect(() => {\n if (!user) {\n // A cold load reports `user === null` while the session hydrates — that's\n // not a sign-out, so the painted snapshot stands until auth settles.\n if (authLoading) return\n loadedForRef.current = null\n reset()\n clearOrgSnapshot()\n setSettledFor(null)\n return\n }\n\n const cached = snapshot?.userId === user.id ? snapshot : null\n\n // Already painted and still inside its window: skip the whole bootstrap.\n if (cached && isSnapshotFresh(cached, cacheTtlMs)) { setSettledFor(user.id); return }\n\n // A snapshot from another account was painted — drop it before loading.\n if (snapshot && snapshot.userId !== user.id && loadedForRef.current === null) {\n reset()\n clearOrgSnapshot()\n }\n\n if (loadedForRef.current === user.id) return\n loadedForRef.current = user.id\n\n // Stale but painted: revalidate quietly, so screens keep the data they're\n // showing instead of flipping back to a skeleton.\n const silent = !!cached\n\n let cancelled = false\n\n async function loadOrgs() {\n if (!silent) setLoading(true)\n try {\n // Redeem invites first — an invitee has no membership until this runs,\n // and without it autoCreate below would hand them a personal org\n // instead of the one that invited them.\n let accepted = 0\n try {\n accepted = (await adapterRef.current.acceptPendingInvites?.()) ?? 0\n } catch {\n // Non-fatal: fall through and load whatever memberships exist.\n }\n\n if (cancelled) return\n\n let memberships = await adapterRef.current.listUserOrgs(user!.id)\n\n // An empty list right after accepting means the read was deduped onto a\n // request that started before the invite landed. Ask once more.\n if (memberships.length === 0 && accepted > 0) {\n memberships = await adapterRef.current.listUserOrgs(user!.id)\n }\n\n if (cancelled) return\n\n setUserOrgs(memberships)\n\n // Auto-create org if user has none\n if (memberships.length === 0 && accepted === 0 && autoCreate) {\n const newOrg = await adapterRef.current.createOrg(\n user!.fullName ? `${user!.fullName}'s Organization` : 'My Organization',\n user!.id,\n )\n if (!cancelled) {\n const ownMembership: OrgMembership[] = [\n {\n orgId: newOrg.id,\n orgName: newOrg.name,\n orgSlug: newOrg.slug,\n profileId: 'owner',\n profileName: 'Owner',\n },\n ]\n setUserOrgs(ownMembership)\n setCurrentOrg(newOrg)\n await hydrateOrg(newOrg, ownMembership, user!.id)\n }\n return\n }\n\n // Restore previously selected org or default to first\n const persistedId = getPersistedOrgId()\n const target =\n memberships.find((m) => m.orgId === persistedId) ?? memberships[0]\n\n if (target && !cancelled) {\n const org = await adapterRef.current.getOrg(target.orgId)\n if (!cancelled) {\n setCurrentOrg(org)\n await hydrateOrg(org, memberships, user!.id)\n }\n }\n } finally {\n if (!cancelled && !silent) setLoading(false)\n // Settled even when the load threw: the answer is then \"we asked and\n // could not tell\", and holding the screen forever is worse than showing\n // the app. It is about the wait being over, not about success.\n if (!cancelled) setSettledFor(user!.id)\n }\n }\n\n void loadOrgs()\n\n return () => {\n cancelled = true\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [user?.id, authLoading])\n\n async function switchOrg(orgId: string): Promise<void> {\n setLoading(true)\n try {\n const org = await adapterRef.current.getOrg(orgId)\n setCurrentOrg(org)\n await hydrateOrg(org, useOrganizationStore.getState().userOrgs, user?.id)\n } finally {\n setLoading(false)\n }\n }\n\n // Explicit refresh always goes to the network and restarts the cache window.\n async function refreshOrg(): Promise<void> {\n if (!currentOrg) return\n setLoading(true)\n try {\n const org = await adapterRef.current.getOrg(currentOrg.id)\n setCurrentOrg(org)\n await hydrateOrg(org, useOrganizationStore.getState().userOrgs, user?.id)\n } finally {\n setLoading(false)\n }\n }\n\n const tenantValue: TenantContext = {\n org: currentOrg,\n userOrgs,\n loading,\n settled,\n switchOrg,\n refreshOrg,\n }\n\n return (\n <OrgAdapterContext.Provider value={adapter}>\n <TenantContext.Provider value={tenantValue}>\n {children}\n </TenantContext.Provider>\n </OrgAdapterContext.Provider>\n )\n}\n"]}
|