@fayz-ai/admin 0.43.2 → 0.44.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.
Files changed (51) hide show
  1. package/dist/ScheduleEditor-MNHZCQIG.js +6 -0
  2. package/dist/{ScheduleEditor-ZEG6PG3Z.js.map → ScheduleEditor-MNHZCQIG.js.map} +1 -1
  3. package/dist/SubscriptionPage-JWWS44SE.js +9 -0
  4. package/dist/{SubscriptionPage-VXZ37WZZ.js.map → SubscriptionPage-JWWS44SE.js.map} +1 -1
  5. package/dist/{chunk-A5UZL52H.js → chunk-OINP2UYL.js} +3 -3
  6. package/dist/{chunk-A5UZL52H.js.map → chunk-OINP2UYL.js.map} +1 -1
  7. package/dist/{chunk-KP3LNCNP.js → chunk-V2IBAF4O.js} +954 -23
  8. package/dist/chunk-V2IBAF4O.js.map +1 -0
  9. package/dist/{chunk-HOMD2MAG.js → chunk-VH4LLIMH.js} +3 -3
  10. package/dist/{chunk-HOMD2MAG.js.map → chunk-VH4LLIMH.js.map} +1 -1
  11. package/dist/components/connect/useConnectors.d.ts.map +1 -1
  12. package/dist/components/settings/ConnectedCompanySettings.d.ts.map +1 -1
  13. package/dist/crud/archetypes/OrderDeliveryBlock.d.ts +32 -0
  14. package/dist/crud/archetypes/OrderDeliveryBlock.d.ts.map +1 -0
  15. package/dist/crud/archetypes/OrderDetailPage.d.ts +4 -2
  16. package/dist/crud/archetypes/OrderDetailPage.d.ts.map +1 -1
  17. package/dist/crud/archetypes/OrderDetailRail.d.ts +2 -0
  18. package/dist/crud/archetypes/OrderDetailRail.d.ts.map +1 -1
  19. package/dist/crud/archetypes/OrderDetailView.d.ts +11 -1
  20. package/dist/crud/archetypes/OrderDetailView.d.ts.map +1 -1
  21. package/dist/crud/archetypes/OrderFormView.d.ts +10 -2
  22. package/dist/crud/archetypes/OrderFormView.d.ts.map +1 -1
  23. package/dist/crud/archetypes/OrderListView.d.ts +20 -1
  24. package/dist/crud/archetypes/OrderListView.d.ts.map +1 -1
  25. package/dist/crud/archetypes/orderStage.d.ts +16 -0
  26. package/dist/crud/archetypes/orderStage.d.ts.map +1 -0
  27. package/dist/crud/archetypes/orderVocabulary.d.ts.map +1 -1
  28. package/dist/crud/archetypes/useOrderKindTransitions.d.ts +10 -0
  29. package/dist/crud/archetypes/useOrderKindTransitions.d.ts.map +1 -0
  30. package/dist/crud/relation-field.d.ts.map +1 -1
  31. package/dist/index.d.ts +9 -3
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +740 -918
  34. package/dist/index.js.map +1 -1
  35. package/dist/lib/currency.d.ts +33 -5
  36. package/dist/lib/currency.d.ts.map +1 -1
  37. package/dist/lib/format.d.ts.map +1 -1
  38. package/dist/org/context.d.ts.map +1 -1
  39. package/dist/org/index.js +1 -2
  40. package/dist/plugins/createPluginContext.d.ts.map +1 -1
  41. package/dist/theme/utils.d.ts +9 -0
  42. package/dist/theme/utils.d.ts.map +1 -1
  43. package/dist/units/useHouseCurrencySync.d.ts +9 -0
  44. package/dist/units/useHouseCurrencySync.d.ts.map +1 -0
  45. package/dist/units/useUnitBootstrap.d.ts.map +1 -1
  46. package/package.json +6 -6
  47. package/dist/ScheduleEditor-ZEG6PG3Z.js +0 -7
  48. package/dist/SubscriptionPage-VXZ37WZZ.js +0 -9
  49. package/dist/chunk-3C5Q4OGJ.js +0 -375
  50. package/dist/chunk-3C5Q4OGJ.js.map +0 -1
  51. package/dist/chunk-KP3LNCNP.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { PersonTimeline, TimelineList, TimelineSkeleton, getTimelineSources, registerTimelineSource, unregisterTimelineSource, usePersonTimeline } from './chunk-WXNTUCX3.js';
2
- import { useLimitGuard, invalidateLimit, useAccessOptional, useUpgradeModalStore, guardLimit, useLimit, checkAccess, featureDisplayName, PlanFeatureItem, AccessProvider, CORE_LIMIT_DECLARATIONS, entityDerivedLimitDeclarations, getPlanEntitlements, resolvePlanCurrency } from './chunk-HOMD2MAG.js';
3
- export { AccessProvider, UPGRADE_URL, agentDenial, checkAccess, getAccessSnapshot, guardLimit, invalidateLimit, isEntitledByPlan, resolveAccess, useAccess, useAccessOptional, useLimit, useLimitGuard, useModuleNavAccess, useUpgradeModalStore } from './chunk-HOMD2MAG.js';
2
+ import { useLimitGuard, invalidateLimit, useAccessOptional, useUpgradeModalStore, guardLimit, useLimit, checkAccess, featureDisplayName, PlanFeatureItem, AccessProvider, CORE_LIMIT_DECLARATIONS, entityDerivedLimitDeclarations, getPlanEntitlements, resolvePlanCurrency } from './chunk-VH4LLIMH.js';
3
+ export { AccessProvider, UPGRADE_URL, agentDenial, checkAccess, getAccessSnapshot, guardLimit, invalidateLimit, isEntitledByPlan, resolveAccess, useAccess, useAccessOptional, useLimit, useLimitGuard, useModuleNavAccess, useUpgradeModalStore } from './chunk-VH4LLIMH.js';
4
4
  export { clearRecentRecords, listRecentRecords, rememberVisit, subscribeRecentRecords, useOpenRecent, useRecentRecords, useRecordVisit } from './chunk-OD7P4L3D.js';
5
5
  import { useTranslation as useTranslation$1 } from './chunk-YUHCC7JY.js';
6
6
  import { useBillingStore, resolvePlanBadge, TrialWidget } from './chunk-IUCDHAAB.js';
@@ -10,12 +10,10 @@ export { openEntity, resolveEntityAnchor, resolveEntityHref, resolveEntityRoute
10
10
  import { useAdminPath, navigateTo, normalizeAdminPath, routeScore, matchRoute } from './chunk-VX3WJLKK.js';
11
11
  export { navigateTo as adminNavigateTo, useAdminPath } from './chunk-VX3WJLKK.js';
12
12
  export { ImportWizard } from './chunk-46UABOOC.js';
13
- import { createArchetypeLookup, getPersonLookup } from './chunk-A5UZL52H.js';
14
- export { ScheduleDateExceptions, ScheduleEditor, ScheduleGridPanel, createArchetypeLookup, deleteSchedule, getPersonBookable, getPersonLookup, getScheduleBlockConfig, getSchedules, mergeBlockSettings, parseBlockSettings, registerPersonLookup, replaceWeeklySchedules, saveSchedule, setPersonBookable, setScheduleBlockConfig, subscribeScheduleBlockConfig } from './chunk-A5UZL52H.js';
15
- import { getFayzSupabaseClientOptional, getSupabaseClientOptional as getSupabaseClientOptional$1, useAppConfigStore, activePluginIds, hasPlugin, useWorkspaceSwitchingStore, searchWorkspaces, OrgMark, WorkspaceChooserGate, WorkspaceSwitchingHost, createFayzSupabaseClient, resolveAppId, createSupabaseOrgAdapter, createMockOrgAdapter, getFayzSupabaseClient } from './chunk-KP3LNCNP.js';
16
- export { OrgMark, activePluginIds, createFayzSupabaseClient, createMockOrgAdapter, createSupabaseOrgAdapter, getFayzSupabaseClient, getFayzSupabaseClientOptional, hasPlugin, orgInitials, useAppConfigStore } from './chunk-KP3LNCNP.js';
17
- import { readOrgSnapshot, useTenantOptional, useOrgAdapter, useTenant, OrgProvider, useOrgAdapterOptional, markWorkspaceSwitch } from './chunk-3C5Q4OGJ.js';
18
- export { ORG_CACHE_TTL_MS, OrgProvider, clearOrgSnapshot, readOrgSnapshot, useOrgAdapter, useOrgAdapterOptional, useTenant, useTenantOptional } from './chunk-3C5Q4OGJ.js';
13
+ import { createArchetypeLookup, getPersonLookup } from './chunk-OINP2UYL.js';
14
+ export { ScheduleDateExceptions, ScheduleEditor, ScheduleGridPanel, createArchetypeLookup, deleteSchedule, getPersonBookable, getPersonLookup, getScheduleBlockConfig, getSchedules, mergeBlockSettings, parseBlockSettings, registerPersonLookup, replaceWeeklySchedules, saveSchedule, setPersonBookable, setScheduleBlockConfig, subscribeScheduleBlockConfig } from './chunk-OINP2UYL.js';
15
+ import { dedup, useUnitStore, getFayzSupabaseClientOptional, getSupabaseClientOptional as getSupabaseClientOptional$1, useTenantOptional, fetchMemberUnits, UNIT_ACCESS_CHANGED, useAppConfigStore, useOrgAdapter, useTenant, activePluginIds, hasPlugin, useWorkspaceSwitchingStore, searchWorkspaces, OrgMark, WorkspaceChooserGate, WorkspaceSwitchingHost, createFayzSupabaseClient, OrgProvider, useOrgAdapterOptional, bindUserToUnit, unbindUserFromUnit, resolveAppId, createSupabaseOrgAdapter, createMockOrgAdapter, fetchUnitMembers, fetchMemberActivity, getFayzSupabaseClient, markWorkspaceSwitch, countUnboundMembers, bindAllMembersTo, setUnitModeRemote, fetchUserIdForPerson } from './chunk-V2IBAF4O.js';
16
+ export { ORG_CACHE_TTL_MS, OrgMark, OrgProvider, activePluginIds, clearOrgSnapshot, createFayzSupabaseClient, createMockOrgAdapter, createSupabaseOrgAdapter, dedup, getFayzSupabaseClient, getFayzSupabaseClientOptional, hasPlugin, orgInitials, readOrgSnapshot, useAppConfigStore, useOrgAdapter, useOrgAdapterOptional, useTenant, useTenantOptional, useUnitStore } from './chunk-V2IBAF4O.js';
19
17
  import { usePermissionOptional, usePermissionsStore, PermissionsProvider } from './chunk-UQ2NTFQC.js';
20
18
  export { PermissionsProvider, useHasPermission, usePermission, usePermissionOptional, usePermissions, usePermissionsStore } from './chunk-UQ2NTFQC.js';
21
19
  import { cn, useOrganizationStore } from './chunk-QOS6UAQ4.js';
@@ -24,7 +22,7 @@ import * as React133 from 'react';
24
22
  import React133__default, { createContext, useMemo, useState, useRef, useCallback, useEffect, useLayoutEffect, useContext, createElement } from 'react';
25
23
  import * as LucideIcons from 'lucide-react';
26
24
  import { RotateCcw, WifiOff, Pencil, Copy, Trash2, Upload, Search, ArrowDown, ArrowUp, ArrowUpDown, Check, Download, ChevronLeft, ChevronRight, AlertTriangle, Building2, Inbox, Package, Sparkles, Plug, DollarSign, Clock, X, WandSparkles, Loader2, ArrowDownToLine, ArrowUpFromLine, CheckCircle2, Crown, ArrowRight, History, SquarePen, Settings2, Mic, User, Plus, Minus, ListChecks, ChevronDown, ArrowLeft, Calendar, ClipboardList, BookOpen, Lock, PinOff, Pin, Eye, Users, StickyNote, CheckSquare2, Square, Globe, LayoutTemplate, Store, ChevronsUpDown, ExternalLink, PenSquare, RefreshCw, XCircle, Camera, Edit, Star, Link2Off, Layers, ShoppingBag, MoreHorizontal, ChevronUp, List, LayoutGrid, CircleDollarSign, Receipt, Settings, Mail, MessageCircle, Cake, HelpCircle, Wrench, ShieldCheck, MessageSquare, Paperclip, Infinity, CheckCheck, PartyPopper, Compass, Play, MapPin, Landmark, LocateFixed, ArrowUpCircle, ArrowUpRight, Pause, CalendarDays, CircleCheckBig, UserX, Ban, CircleAlert, CircleEllipsis, FileText, CircleDashed, Power, ArrowRightLeft, File as File$1, FileImage, FileSpreadsheet, AlertCircle, CreditCard, SlidersHorizontal, Puzzle, Shield, Palette, Blocks, ShieldAlert, UserCog, LogOut, Bell, Database, Radio, Zap, Save, ImagePlus, UserPlus, Contact, UserMinus, Send, Sun, Moon, Monitor, Languages, Info, Link2, KeyRound, Ellipsis, Phone, Bug, Home, Heart, Briefcase, BarChart3, Tag, Truck, Globe2 } from 'lucide-react';
27
- import { reportAppError, toDataError, tl, createDebug, resetActiveUnit, setUnitMode, setActiveUnitId, setScopedResources, fetchAppConfig, getSupabaseClientOptional, payeeAccountFields, maskCpfCnpj, recordRailFields, RECORD_GROUP, activeFacet, createSafeDataProvider, isKnownMissing, rememberIfMissing, deriveEntityKey, registerEntity, getActiveTenantId, resolveDataProvider, bulkRemove, emitDomainEvent, entityEventKey, errorMessage, useTranslation, describeError, useDataChanged, emitDataChanged, exportCSV, getScopedResource, formatDateTime as formatDateTime$1, formatDate as formatDate$1, formatCurrency as formatCurrency$1, bulkCreate, matchesRange, isConnectorCategory, usePluginRuntimeOptional, useDataVersion, getWidgetsForZone, resolvePluginComponent, useUnitMode, invalidateAppConfig, toTenantPluginBindings, setCurrentLocale, resolveLocale, resolvePluginRuntime, PluginRuntimeProvider, I18nProvider, getAllEntities, resolveIntegrationSurface, defineApp, registerScaffold, useActiveTenantId, onDataChanged, useConnectorsForPlugin, renderApp as renderApp$1, parseRangeFilter, isFilterObject, connectionKey, useManifest, registerEventSink, formatPostalCode, isValidPostalCode, lookupPostalCode, usePluginRuntime, useConnectivity, RECONNECTED_EVENT, installGlobalErrorHandlers, registerErrorReporter, getConnectivity, applyNavComposition, mergeTranslations, coreTranslations, attachPersistentCache, getPersistentCache, createMockProvider, listConnections, connectorPlanes, connectorPermissions, connectorEntities, preferredPlane, connectorDirection, countByTenant, isAddressIncomplete, isBankIncomplete, payeeMethodOf, getCurrentLocale, searchEverything, readImpersonation, getComponent, getPluginFactory, connectorSettings, groupedPermissions, invocationPlane, missingRequiredSettings, isBankEmpty, isAddressEmpty, writeImpersonation, isSettingSet, getEntityByKey, connectorSubscribesTo, eventKeyMatches } from '@fayz-ai/core';
25
+ import { reportAppError, toDataError, tl, createDebug, fetchAppConfig, getSupabaseClientOptional, payeeAccountFields, maskCpfCnpj, recordRailFields, RECORD_GROUP, activeFacet, createSafeDataProvider, isKnownMissing, rememberIfMissing, deriveEntityKey, registerEntity, getActiveTenantId, resolveDataProvider, bulkRemove, emitDomainEvent, entityEventKey, errorMessage, useTranslation, describeError, useDataChanged, emitDataChanged, exportCSV, getScopedResource, formatDateTime as formatDateTime$1, formatDate as formatDate$1, formatCurrency as formatCurrency$1, bulkCreate, matchesRange, isConnectorCategory, usePluginRuntimeOptional, useDataVersion, getWidgetsForZone, resolvePluginComponent, useUnitMode, invalidateAppConfig, toTenantPluginBindings, setCurrentLocale, resolveLocale, resolvePluginRuntime, PluginRuntimeProvider, I18nProvider, getAllEntities, resolveIntegrationSurface, defineApp, registerScaffold, subscribeHouseCurrency, getHouseCurrency, resolveCurrency, useActiveTenantId, onDataChanged, useConnectorsForPlugin, renderApp as renderApp$1, parseRangeFilter, isFilterObject, connectionKey, useManifest, registerEventSink, formatPostalCode, isValidPostalCode, lookupPostalCode, usePluginRuntime, useConnectivity, RECONNECTED_EVENT, installGlobalErrorHandlers, registerErrorReporter, getConnectivity, applyNavComposition, mergeTranslations, coreTranslations, attachPersistentCache, getPersistentCache, createMockProvider, listConnections, connectorPlanes, connectorPermissions, connectorEntities, preferredPlane, connectorDirection, countByTenant, isAddressIncomplete, isBankIncomplete, payeeMethodOf, getCurrentLocale, searchEverything, readImpersonation, getComponent, getPluginFactory, connectorSettings, groupedPermissions, invocationPlane, missingRequiredSettings, isBankEmpty, isAddressEmpty, writeImpersonation, isSettingSet, getEntityByKey, connectorSubscribesTo, eventKeyMatches } from '@fayz-ai/core';
28
26
  export { ConnectorRuntimeTokenUnavailableError, createSafeDataProvider, formatDate, formatDateTime, getActiveLocale, getActiveTenantId, getConnectorRuntimeTokenSource, getCurrentLocale, getSupabaseClientOptional, preloadLocale, resolveBackendEnv, setConnectorRuntimeTokenSource, setCurrentLocale, tl, useActiveTenantId } from '@fayz-ai/core';
29
27
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
30
28
  import { usePasswordSetupGate, SetPasswordPage, AuthGate, AuthProvider, createAuthRuntime } from '@fayz-ai/plugin-auth';
@@ -1134,8 +1132,8 @@ ${buildToolIndex(searchable)}`,
1134
1132
  }
1135
1133
  ];
1136
1134
  }
1137
- function words(text2) {
1138
- return text2.replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length > 2);
1135
+ function words(text3) {
1136
+ return text3.replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length > 2);
1139
1137
  }
1140
1138
  function matches(tool, query) {
1141
1139
  const terms = words(query);
@@ -1256,9 +1254,9 @@ async function readAllRows(digest) {
1256
1254
  if (digest.kind !== "csv") {
1257
1255
  throw new Error("Only CSV files can be read in full here. Ask the user to save the sheet as CSV.");
1258
1256
  }
1259
- const text2 = await entry.file.text();
1260
- const delimiter = detectDelimiter(text2, /\.tsv$/i.test(entry.file.name) ? " " : void 0);
1261
- const { rows } = parseDelimited(text2, delimiter);
1257
+ const text3 = await entry.file.text();
1258
+ const delimiter = detectDelimiter(text3, /\.tsv$/i.test(entry.file.name) ? " " : void 0);
1259
+ const { rows } = parseDelimited(text3, delimiter);
1262
1260
  if (!rows.length) return [];
1263
1261
  const headers = rows[0].map((h) => h.trim());
1264
1262
  return rows.slice(1).filter((row) => row.some((cell) => cell.trim())).map((row) => {
@@ -1320,22 +1318,22 @@ async function readTextBounded(file) {
1320
1318
  return { text: await file.slice(0, HEAD_SLICE).text(), partial: true };
1321
1319
  }
1322
1320
  async function parseTextFile(file, base) {
1323
- const { text: text2 } = await readTextBounded(file);
1324
- const preview = text2.slice(0, PREVIEW_CHARS);
1321
+ const { text: text3 } = await readTextBounded(file);
1322
+ const preview = text3.slice(0, PREVIEW_CHARS);
1325
1323
  return {
1326
1324
  ...base,
1327
1325
  preview,
1328
- ...text2.length > PREVIEW_CHARS ? { warnings: [`preview truncated to ${PREVIEW_CHARS} characters`] } : {}
1326
+ ...text3.length > PREVIEW_CHARS ? { warnings: [`preview truncated to ${PREVIEW_CHARS} characters`] } : {}
1329
1327
  };
1330
1328
  }
1331
1329
  async function parseDelimitedFile(file, base) {
1332
- const { text: text2, partial } = await readTextBounded(file);
1330
+ const { text: text3, partial } = await readTextBounded(file);
1333
1331
  const warnings = [];
1334
1332
  if (partial) {
1335
1333
  warnings.push("file too large \u2014 only the first rows were read, row count unknown");
1336
1334
  }
1337
- const delimiter = detectDelimiter(text2, /\.tsv$/i.test(file.name) ? " " : void 0);
1338
- const sheet = buildSheet(file.name.replace(CSV_EXT, ""), parseDelimited(text2, delimiter), warnings);
1335
+ const delimiter = detectDelimiter(text3, /\.tsv$/i.test(file.name) ? " " : void 0);
1336
+ const sheet = buildSheet(file.name.replace(CSV_EXT, ""), parseDelimited(text3, delimiter), warnings);
1339
1337
  if (partial) delete sheet.rowCount;
1340
1338
  return {
1341
1339
  ...base,
@@ -1391,9 +1389,9 @@ async function parseSpreadsheetFile(file, base) {
1391
1389
  ...warnings.length ? { warnings } : {}
1392
1390
  };
1393
1391
  }
1394
- function detectDelimiter(text2, forced) {
1392
+ function detectDelimiter(text3, forced) {
1395
1393
  if (forced) return forced;
1396
- const firstLine = text2.slice(0, 4e3).split(/\r?\n/)[0] ?? "";
1394
+ const firstLine = text3.slice(0, 4e3).split(/\r?\n/)[0] ?? "";
1397
1395
  let best = ",";
1398
1396
  let bestCount = 0;
1399
1397
  for (const candidate of [",", ";", " ", "|"]) {
@@ -1415,7 +1413,7 @@ function countOutsideQuotes(line, char) {
1415
1413
  }
1416
1414
  return count;
1417
1415
  }
1418
- function parseDelimited(text2, delimiter) {
1416
+ function parseDelimited(text3, delimiter) {
1419
1417
  const rows = [];
1420
1418
  let count = 0;
1421
1419
  let row = [];
@@ -1431,7 +1429,7 @@ function parseDelimited(text2, delimiter) {
1431
1429
  if (rows.length < SCAN_ROWS) rows.push(row);
1432
1430
  row = [];
1433
1431
  };
1434
- const source = text2.charCodeAt(0) === 65279 ? text2.slice(1) : text2;
1432
+ const source = text3.charCodeAt(0) === 65279 ? text3.slice(1) : text3;
1435
1433
  for (let i = 0; i < source.length; i++) {
1436
1434
  const c = source[i];
1437
1435
  if (inQuotes) {
@@ -1465,8 +1463,8 @@ function buildSheet(name, parsed, warnings) {
1465
1463
  return { name, headers, rowCount: Math.max(0, parsed.count - 1), sample, columnTypes };
1466
1464
  }
1467
1465
  function truncateCell(value) {
1468
- const text2 = String(value ?? "");
1469
- return text2.length > MAX_CELL_CHARS ? `${text2.slice(0, MAX_CELL_CHARS)}\u2026` : text2;
1466
+ const text3 = String(value ?? "");
1467
+ return text3.length > MAX_CELL_CHARS ? `${text3.slice(0, MAX_CELL_CHARS)}\u2026` : text3;
1470
1468
  }
1471
1469
  var SLASH_DATE = /^(\d{1,2})[/.-](\d{1,2})[/.-](\d{2,4})$/;
1472
1470
  var ISO_DATE = /^\d{4}-\d{2}-\d{2}([T ]\d{2}:\d{2}(:\d{2})?)?/;
@@ -1629,16 +1627,16 @@ function formatBytes(bytes) {
1629
1627
  // src/lib/assistant-text.ts
1630
1628
  var TOOL_IN_BRACES = /\{\s*[a-z][A-Za-z0-9_]{2,}\s*(?:\([^()]*\))?\s*\}/g;
1631
1629
  var FAKE_BUTTON_LINE = /^[ \t]*\[[^\][\n]{2,60}\][ \t]*$(?!\()/gm;
1632
- function mapOutsideCode(text2, transform) {
1633
- return text2.split(/(```[\s\S]*?```|`[^`\n]*`)/g).map((chunk, index) => index % 2 === 1 ? chunk : transform(chunk)).join("");
1630
+ function mapOutsideCode(text3, transform) {
1631
+ return text3.split(/(```[\s\S]*?```|`[^`\n]*`)/g).map((chunk, index) => index % 2 === 1 ? chunk : transform(chunk)).join("");
1634
1632
  }
1635
- function sanitizeAssistantText(text2) {
1636
- if (!text2 || !text2.includes("{") && !text2.includes("[")) return text2;
1633
+ function sanitizeAssistantText(text3) {
1634
+ if (!text3 || !text3.includes("{") && !text3.includes("[")) return text3;
1637
1635
  const cleaned = mapOutsideCode(
1638
- text2,
1636
+ text3,
1639
1637
  (chunk) => chunk.replace(TOOL_IN_BRACES, "").replace(FAKE_BUTTON_LINE, "")
1640
1638
  );
1641
- if (cleaned === text2) return text2;
1639
+ if (cleaned === text3) return text3;
1642
1640
  return cleaned.replace(/[ \t]+$/gm, "").replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
1643
1641
  }
1644
1642
 
@@ -2567,8 +2565,8 @@ function useAsk() {
2567
2565
  const queuePrompt = useChatStore((s) => s.queuePrompt);
2568
2566
  const dismiss = useAssistantInviteStore((s) => s.dismiss);
2569
2567
  return React133.useCallback(
2570
- (text2) => {
2571
- const trimmed = text2.trim();
2568
+ (text3) => {
2569
+ const trimmed = text3.trim();
2572
2570
  if (!trimmed) return;
2573
2571
  dismiss();
2574
2572
  queuePrompt(trimmed);
@@ -4210,539 +4208,6 @@ registerAIToolHandler(
4210
4208
  "findTools",
4211
4209
  (args, ctx) => resolveToolSearch(args, ctx.searchableTools ?? [], new Set(ctx.carriedTools ?? []))
4212
4210
  );
4213
- var UNIT_BOOTSTRAP_OBJECT = "rpc:unit_bootstrap";
4214
- var UNIT_MODE_OBJECT = "tenants.unit_scoping_enabled";
4215
- var SCOPED_RESOURCES_OBJECT = "scoped_resources";
4216
- var UNIT_ACCESS_CHANGED = "core.unit-access.changed";
4217
- function emitUnitAccessChanged(userId, unitId) {
4218
- emitDomainEvent(
4219
- UNIT_ACCESS_CHANGED,
4220
- { user_id: userId, unit_id: unitId },
4221
- { tenantId: getActiveTenantId() ?? null, subject: { type: "location", id: unitId } }
4222
- );
4223
- }
4224
- function client() {
4225
- return getSupabaseClientOptional();
4226
- }
4227
- function mapUnit(row) {
4228
- return {
4229
- id: row.id,
4230
- tenantId: row.tenant_id,
4231
- kind: row.kind ?? "branch",
4232
- name: row.name,
4233
- email: row.email ?? void 0,
4234
- phone: row.phone ?? void 0,
4235
- address: row.address ?? void 0,
4236
- city: row.city ?? void 0,
4237
- state: row.state ?? void 0,
4238
- country: row.country ?? "BR",
4239
- postalCode: row.postal_code ?? void 0,
4240
- isHeadquarters: Boolean(row.is_headquarters),
4241
- isActive: row.is_active !== false,
4242
- tags: row.tags ?? [],
4243
- notes: row.notes ?? void 0,
4244
- metadata: row.metadata ?? {},
4245
- createdAt: row.created_at,
4246
- updatedAt: row.updated_at,
4247
- parentId: row.parent_id ?? null,
4248
- code: row.code ?? null,
4249
- // numeric do Postgres chega como string no PostgREST; a aritmética de
4250
- // distância precisa de número, e `Number(null)` é 0, que é uma coordenada
4251
- // real no golfo da Guiné.
4252
- latitude: row.latitude == null ? null : Number(row.latitude),
4253
- longitude: row.longitude == null ? null : Number(row.longitude)
4254
- };
4255
- }
4256
- async function fetchUnits(tenantId2) {
4257
- const db2 = client();
4258
- if (!db2) return [];
4259
- const { data, error } = await db2.from("v_units").select("*").eq("tenant_id", tenantId2).order("is_headquarters", { ascending: false }).order("name");
4260
- if (error) return [];
4261
- return (data ?? []).map(mapUnit);
4262
- }
4263
- async function fetchMyBindings(userId, tenantId2) {
4264
- const db2 = client();
4265
- if (!db2) return [];
4266
- const { data, error } = await db2.from("v_unit_members").select("location_id, role").eq("user_id", userId).eq("tenant_id", tenantId2);
4267
- if (error) return [];
4268
- return (data ?? []).map((r) => ({ locationId: r.location_id, role: r.role ?? null }));
4269
- }
4270
- async function fetchUnitBootstrap(tenantId2, deviceId) {
4271
- const db2 = client();
4272
- if (!db2) return null;
4273
- if (isKnownMissing(UNIT_BOOTSTRAP_OBJECT)) return null;
4274
- const { data, error } = await db2.rpc("unit_bootstrap", {
4275
- p_tenant_id: tenantId2,
4276
- p_device_id: deviceId ?? null
4277
- });
4278
- if (error) {
4279
- rememberIfMissing(UNIT_BOOTSTRAP_OBJECT, error);
4280
- return null;
4281
- }
4282
- if (!data) return null;
4283
- const raw = data;
4284
- return {
4285
- mode: Boolean(raw.mode),
4286
- units: (raw.units ?? []).map(mapUnit),
4287
- bindings: (raw.bindings ?? []).map((r) => ({
4288
- locationId: r.location_id,
4289
- role: r.role ?? null
4290
- })),
4291
- scoped: Object.fromEntries(
4292
- Object.entries(raw.scoped ?? {}).map(([table, v]) => [
4293
- table,
4294
- { unitColumn: v?.unit_column ?? "unit_id", shareable: v?.shareable !== false }
4295
- ])
4296
- ),
4297
- // user_unit_ids_in walks the tree with UNION over (id, depth): a branch
4298
- // reached directly AND through its HQ comes back twice.
4299
- reachable: Array.isArray(raw.reachable) ? [...new Set(raw.reachable)] : void 0,
4300
- devicePin: { set: Boolean(raw.device_pin_set), unitId: raw.device_pin ?? null },
4301
- accountPin: { set: Boolean(raw.account_pin_set), unitId: raw.account_pin ?? null }
4302
- };
4303
- }
4304
- async function saveEntryUnit(tenantId2, unitId, deviceId) {
4305
- const db2 = client();
4306
- if (!db2 || !deviceId) return;
4307
- await db2.rpc("set_entry_unit", {
4308
- p_tenant_id: tenantId2,
4309
- p_unit_id: unitId ?? null,
4310
- p_device_id: deviceId
4311
- });
4312
- }
4313
- async function fetchUnitMembers(unitId) {
4314
- const db2 = client();
4315
- if (!db2) return [];
4316
- const { data, error } = await db2.from("v_unit_members").select("id, user_id, role, created_at").eq("location_id", unitId).order("created_at");
4317
- if (error) return [];
4318
- return (data ?? []).map((r) => ({
4319
- id: r.id,
4320
- userId: r.user_id,
4321
- role: r.role ?? null,
4322
- since: r.created_at ?? null
4323
- }));
4324
- }
4325
- async function fetchMemberActivity(tenantId2) {
4326
- const db2 = client();
4327
- if (!db2) return {};
4328
- const { data, error } = await db2.rpc("tenant_member_activity", { p_tenant_id: tenantId2 });
4329
- if (error) return {};
4330
- const out = {};
4331
- for (const r of data ?? []) {
4332
- out[r.user_id] = {
4333
- lastSignInAt: r.last_sign_in_at ?? null,
4334
- signedUpAt: r.signed_up_at ?? null
4335
- };
4336
- }
4337
- return out;
4338
- }
4339
- async function fetchMemberUnits(userId, tenantId2) {
4340
- const tenant = getActiveTenantId();
4341
- if (!tenant) return [];
4342
- return fetchMyBindings(userId, tenant);
4343
- }
4344
- async function bindUserToUnit(unitId, userId, role) {
4345
- const db2 = client();
4346
- if (!db2) throw new Error("sem conex\xE3o");
4347
- const { error } = await db2.rpc("unit_member_set", { p_unit: unitId, p_user: userId, p_role: role });
4348
- if (error) throw error;
4349
- emitUnitAccessChanged(userId, unitId);
4350
- }
4351
- async function unbindUserFromUnit(unitId, userId) {
4352
- const db2 = client();
4353
- if (!db2) throw new Error("sem conex\xE3o");
4354
- const { error } = await db2.rpc("unit_member_remove", { p_unit: unitId, p_user: userId });
4355
- if (error) throw error;
4356
- emitUnitAccessChanged(userId, unitId);
4357
- }
4358
- async function fetchUserIdForPerson(personId) {
4359
- const db2 = client();
4360
- if (!db2) return null;
4361
- const { data, error } = await db2.from("v_team_members").select("user_id").eq("person_id", personId).maybeSingle();
4362
- if (error || !data) return null;
4363
- return data.user_id ?? null;
4364
- }
4365
- async function fetchScopedResources() {
4366
- const db2 = client();
4367
- if (!db2) return {};
4368
- if (isKnownMissing(SCOPED_RESOURCES_OBJECT)) return {};
4369
- const { data, error } = await db2.from("scoped_resources").select("resource_table, unit_column, shareable");
4370
- if (error) {
4371
- rememberIfMissing(SCOPED_RESOURCES_OBJECT, error);
4372
- return {};
4373
- }
4374
- const out = {};
4375
- for (const r of data ?? []) {
4376
- out[r.resource_table] = {
4377
- unitColumn: r.unit_column ?? "unit_id",
4378
- shareable: r.shareable !== false
4379
- };
4380
- }
4381
- return out;
4382
- }
4383
- async function fetchUnitMode(tenantId2) {
4384
- const db2 = client();
4385
- if (!db2) return { installed: false, on: false };
4386
- if (isKnownMissing(UNIT_MODE_OBJECT)) return { installed: false, on: false };
4387
- const { data, error } = await db2.from("tenants").select("unit_scoping_enabled").eq("id", tenantId2).maybeSingle();
4388
- if (error) {
4389
- rememberIfMissing(UNIT_MODE_OBJECT, error);
4390
- return { installed: false, on: false };
4391
- }
4392
- return { installed: true, on: Boolean(data?.unit_scoping_enabled) };
4393
- }
4394
- async function setUnitModeRemote(tenantId2, on) {
4395
- const db2 = client();
4396
- if (!db2) throw new Error("sem conex\xE3o");
4397
- const { error } = await db2.from("tenants").update({ unit_scoping_enabled: on }).eq("id", tenantId2);
4398
- if (error) throw error;
4399
- }
4400
- async function bindAllMembersTo(tenantId2, unitId) {
4401
- const db2 = client();
4402
- if (!db2) return 0;
4403
- const { data } = await db2.from("v_team_members").select("user_id").eq("tenant_id", tenantId2);
4404
- const userIds = (data ?? []).map((m) => m.user_id);
4405
- if (userIds.length === 0) return 0;
4406
- for (const userId of userIds) {
4407
- const { error } = await db2.rpc("unit_member_set", { p_unit: unitId, p_user: userId, p_role: null });
4408
- if (error) throw error;
4409
- }
4410
- emitUnitAccessChanged(null, unitId);
4411
- return userIds.length;
4412
- }
4413
- async function countUnboundMembers(tenantId2) {
4414
- const db2 = client();
4415
- if (!db2) return 0;
4416
- const { data: members } = await db2.from("v_team_members").select("user_id").eq("tenant_id", tenantId2);
4417
- const { data: units } = await db2.from("v_units").select("id").eq("tenant_id", tenantId2);
4418
- const unitIds = (units ?? []).map((u) => u.id);
4419
- if (unitIds.length === 0) return (members ?? []).length;
4420
- const { data: bound } = await db2.from("v_unit_members").select("user_id").in("location_id", unitIds);
4421
- const boundSet = new Set((bound ?? []).map((b) => b.user_id));
4422
- return (members ?? []).filter((m) => !boundSet.has(m.user_id)).length;
4423
- }
4424
-
4425
- // src/units/cache.ts
4426
- var STORAGE_KEY = "fayz:units-snapshot";
4427
- var VERSION = 1;
4428
- var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
4429
- var MAX_BYTES = 256 * 1024;
4430
- function storage() {
4431
- try {
4432
- if (typeof localStorage === "undefined") return null;
4433
- return localStorage;
4434
- } catch {
4435
- return null;
4436
- }
4437
- }
4438
- function readUnitSnapshot() {
4439
- const store = storage();
4440
- if (!store) return null;
4441
- try {
4442
- const raw = store.getItem(STORAGE_KEY);
4443
- if (!raw) return null;
4444
- const snapshot = JSON.parse(raw);
4445
- if (snapshot?.version !== VERSION || !snapshot.tenantId || !snapshot.userId) return null;
4446
- const age = Date.now() - snapshot.savedAt;
4447
- if (age < 0 || age > MAX_AGE_MS) {
4448
- store.removeItem(STORAGE_KEY);
4449
- return null;
4450
- }
4451
- return snapshot;
4452
- } catch {
4453
- return null;
4454
- }
4455
- }
4456
- function saveUnitSnapshot(input) {
4457
- const store = storage();
4458
- if (!store) return;
4459
- try {
4460
- const raw = JSON.stringify({ ...input, version: VERSION, savedAt: Date.now() });
4461
- if (raw.length > MAX_BYTES) return;
4462
- store.setItem(STORAGE_KEY, raw);
4463
- } catch {
4464
- }
4465
- }
4466
- function patchUnitSnapshotActive(activeUnitId) {
4467
- const store = storage();
4468
- const current2 = readUnitSnapshot();
4469
- if (!store || !current2) return;
4470
- try {
4471
- store.setItem(STORAGE_KEY, JSON.stringify({ ...current2, activeUnitId }));
4472
- } catch {
4473
- }
4474
- }
4475
- function clearUnitSnapshot() {
4476
- try {
4477
- storage()?.removeItem(STORAGE_KEY);
4478
- } catch {
4479
- }
4480
- }
4481
-
4482
- // src/units/device.ts
4483
- var STORAGE_KEY2 = "fayz:device-id";
4484
- var cached = null;
4485
- function randomId() {
4486
- try {
4487
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
4488
- return crypto.randomUUID();
4489
- }
4490
- } catch {
4491
- }
4492
- return `d-${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
4493
- }
4494
- function getDeviceId() {
4495
- if (cached) return cached;
4496
- try {
4497
- if (typeof localStorage === "undefined") return void 0;
4498
- const existing = localStorage.getItem(STORAGE_KEY2);
4499
- if (existing) {
4500
- cached = existing;
4501
- return existing;
4502
- }
4503
- const fresh = randomId();
4504
- localStorage.setItem(STORAGE_KEY2, fresh);
4505
- cached = fresh;
4506
- return fresh;
4507
- } catch {
4508
- return void 0;
4509
- }
4510
- }
4511
-
4512
- // src/lib/dedup.ts
4513
- var inflight = /* @__PURE__ */ new Map();
4514
- function dedup(key, fn) {
4515
- const existing = inflight.get(key);
4516
- if (existing) return existing;
4517
- const promise = fn().finally(() => {
4518
- inflight.delete(key);
4519
- });
4520
- inflight.set(key, promise);
4521
- return promise;
4522
- }
4523
-
4524
- // src/units/entry.ts
4525
- function resolveEntry(reachable, pins) {
4526
- const canStand = (id) => id != null && reachable.includes(id);
4527
- const ladder = [
4528
- [pins.device, "device"],
4529
- [pins.account, "account"]
4530
- ];
4531
- for (const [pin, reason] of ladder) {
4532
- if (!pin?.set) continue;
4533
- if (pin.unitId === null) return { unitId: void 0, reason: "all", needsChoice: false };
4534
- if (canStand(pin.unitId)) return { unitId: pin.unitId, reason, needsChoice: false };
4535
- }
4536
- if (canStand(pins.legacy)) return { unitId: pins.legacy, reason: "device", needsChoice: false };
4537
- if (reachable.length === 1) return { unitId: reachable[0], reason: "only", needsChoice: false };
4538
- return { unitId: void 0, reason: "all", needsChoice: reachable.length > 1 };
4539
- }
4540
-
4541
- // src/units/store.ts
4542
- var LEGACY_KEY = "saas-core:current-location";
4543
- function legacyPin() {
4544
- try {
4545
- return localStorage.getItem(LEGACY_KEY) ?? void 0;
4546
- } catch {
4547
- return void 0;
4548
- }
4549
- }
4550
- function buildTree(units) {
4551
- const nodes = /* @__PURE__ */ new Map();
4552
- for (const u of units) nodes.set(u.id, { ...u, children: [] });
4553
- const roots = [];
4554
- for (const node of nodes.values()) {
4555
- const parent = node.parentId ? nodes.get(node.parentId) : void 0;
4556
- if (parent && parent.id !== node.id) parent.children.push(node);
4557
- else roots.push(node);
4558
- }
4559
- return roots;
4560
- }
4561
- function expandDown(units, seeds) {
4562
- const childrenOf = /* @__PURE__ */ new Map();
4563
- for (const u of units) {
4564
- if (!u.parentId) continue;
4565
- const list = childrenOf.get(u.parentId) ?? [];
4566
- list.push(u.id);
4567
- childrenOf.set(u.parentId, list);
4568
- }
4569
- const out = /* @__PURE__ */ new Set();
4570
- const queue = [...seeds];
4571
- while (queue.length > 0) {
4572
- const id = queue.shift();
4573
- if (out.has(id)) continue;
4574
- out.add(id);
4575
- for (const child of childrenOf.get(id) ?? []) queue.push(child);
4576
- }
4577
- return [...out];
4578
- }
4579
- function branchesOnly(ids, byId) {
4580
- return ids.filter((id) => byId[id]?.kind !== "region");
4581
- }
4582
- var useUnitStore = create((set, get) => ({
4583
- units: [],
4584
- byId: {},
4585
- tree: [],
4586
- myUnitIds: [],
4587
- myBindings: [],
4588
- activeUnitId: void 0,
4589
- entryReason: "all",
4590
- unitMode: false,
4591
- loading: false,
4592
- resolved: false,
4593
- needsChoice: false,
4594
- loadedFor: null,
4595
- // Uma chamada por conta, por mais telas que peçam.
4596
- //
4597
- // Dez componentes chamam `useUnitBootstrap` — o seletor, a linha de
4598
- // identidade, o rodapé do registro, a aba de unidades de uma pessoa — e todos
4599
- // montam no mesmo quadro. A guarda anterior era `loadedFor === tenantId &&
4600
- // !loading`, que deixa passar exatamente enquanto a primeira chamada está no
4601
- // ar: o segundo componente via a conta já marcada, via `loading` ligado, e a
4602
- // condição inteira dava falso. Resultado: uma requisição por tela, todas
4603
- // idênticas. Juntar cinco viagens numa e depois disparar essa uma cinco vezes
4604
- // não economiza nada.
4605
- //
4606
- // `dedup` é o mesmo utilitário que a tela de equipe já usa: quem chegar
4607
- // enquanto a primeira está no ar recebe a MESMA promessa em vez de abrir
4608
- // outra.
4609
- async load(tenantId2, userId) {
4610
- if (!tenantId2) return;
4611
- if (get().loadedFor === tenantId2 && !get().loading) return;
4612
- return dedup(`units:${tenantId2}:${userId ?? ""}`, () => loadOnce(tenantId2, userId, set, get));
4613
- },
4614
- setActive(unitId, reason = "manual") {
4615
- setActiveUnitId(unitId);
4616
- set({ activeUnitId: unitId, entryReason: reason, needsChoice: false });
4617
- patchUnitSnapshotActive(unitId ?? null);
4618
- const tenantId2 = get().loadedFor;
4619
- if (tenantId2) void saveEntryUnit(tenantId2, unitId, getDeviceId());
4620
- },
4621
- setMode(on) {
4622
- setUnitMode(on);
4623
- set({ unitMode: on });
4624
- if (!on) {
4625
- setActiveUnitId(void 0);
4626
- set({ activeUnitId: void 0, entryReason: "all", needsChoice: false });
4627
- patchUnitSnapshotActive(null);
4628
- }
4629
- },
4630
- reset() {
4631
- clearUnitSnapshot();
4632
- resetActiveUnit();
4633
- set({
4634
- units: [],
4635
- byId: {},
4636
- tree: [],
4637
- myUnitIds: [],
4638
- myBindings: [],
4639
- activeUnitId: void 0,
4640
- entryReason: "all",
4641
- unitMode: false,
4642
- loading: false,
4643
- resolved: false,
4644
- needsChoice: false,
4645
- loadedFor: null
4646
- });
4647
- }
4648
- }));
4649
- async function loadOnce(tenantId2, userId, set, get) {
4650
- set({ loading: true, loadedFor: tenantId2 });
4651
- try {
4652
- const deviceId = getDeviceId();
4653
- const boot = await fetchUnitBootstrap(tenantId2, deviceId);
4654
- let mode;
4655
- let units;
4656
- let bindings;
4657
- let scoped;
4658
- let reachableFromServer;
4659
- if (boot) {
4660
- ;
4661
- [mode, units, bindings, scoped] = [boot.mode, boot.units, boot.bindings, boot.scoped];
4662
- reachableFromServer = boot.reachable;
4663
- } else {
4664
- const modeResult = await fetchUnitMode(tenantId2);
4665
- mode = modeResult.on;
4666
- if (!modeResult.installed) {
4667
- units = [];
4668
- bindings = [];
4669
- scoped = {};
4670
- } else {
4671
- ;
4672
- [units, bindings, scoped] = await Promise.all([
4673
- fetchUnits(tenantId2),
4674
- userId ? fetchMyBindings(userId, tenantId2) : Promise.resolve([]),
4675
- mode ? fetchScopedResources() : Promise.resolve({})
4676
- ]);
4677
- }
4678
- }
4679
- setScopedResources(scoped);
4680
- const byId = {};
4681
- for (const u of units) byId[u.id] = u;
4682
- const reachable = reachableFromServer ? branchesOnly(reachableFromServer.filter((id) => byId[id]), byId) : branchesOnly(expandDown(units, bindings.map((b) => b.locationId)), byId);
4683
- const entry = resolveEntry(reachable, {
4684
- device: boot?.devicePin,
4685
- account: boot?.accountPin,
4686
- legacy: legacyPin()
4687
- });
4688
- setUnitMode(mode);
4689
- setActiveUnitId(entry.unitId);
4690
- set({
4691
- units,
4692
- byId,
4693
- tree: buildTree(units),
4694
- myUnitIds: reachable,
4695
- myBindings: bindings,
4696
- unitMode: mode,
4697
- activeUnitId: entry.unitId,
4698
- entryReason: entry.reason,
4699
- needsChoice: entry.needsChoice,
4700
- loading: false,
4701
- resolved: true
4702
- });
4703
- if (userId) {
4704
- saveUnitSnapshot({
4705
- userId,
4706
- tenantId: tenantId2,
4707
- mode,
4708
- units,
4709
- bindings,
4710
- myUnitIds: reachable,
4711
- activeUnitId: entry.unitId ?? null,
4712
- scoped
4713
- });
4714
- }
4715
- } finally {
4716
- if (get().loading) set({ loading: false });
4717
- }
4718
- }
4719
- (function hydrate() {
4720
- const snapshot = readUnitSnapshot();
4721
- if (!snapshot) return;
4722
- const org = readOrgSnapshot();
4723
- if (!org || org.org?.id !== snapshot.tenantId || org.userId !== snapshot.userId) {
4724
- clearUnitSnapshot();
4725
- return;
4726
- }
4727
- const byId = {};
4728
- for (const u of snapshot.units) byId[u.id] = u;
4729
- const active2 = snapshot.activeUnitId ?? void 0;
4730
- const standable = active2 && snapshot.myUnitIds.includes(active2) ? active2 : void 0;
4731
- setScopedResources(snapshot.scoped);
4732
- setUnitMode(snapshot.mode);
4733
- setActiveUnitId(standable);
4734
- useUnitStore.setState({
4735
- units: snapshot.units,
4736
- byId,
4737
- tree: buildTree(snapshot.units),
4738
- myUnitIds: snapshot.myUnitIds,
4739
- myBindings: snapshot.bindings,
4740
- unitMode: snapshot.mode,
4741
- activeUnitId: standable,
4742
- entryReason: standable ? "device" : "all",
4743
- resolved: true
4744
- });
4745
- })();
4746
4211
  function useSystemPermission() {
4747
4212
  const currentProfile = usePermissionsStore((s) => s.currentProfile);
4748
4213
  return useCallback(
@@ -5702,10 +5167,10 @@ function toInstalled(definition, status) {
5702
5167
  }
5703
5168
  var connectionsFlight = null;
5704
5169
  var statusFlights = /* @__PURE__ */ new Map();
5705
- function loadConnections(tenantId2, ids, client3) {
5170
+ function loadConnections(tenantId2, ids, client2) {
5706
5171
  const flight = connectionsFlight;
5707
5172
  if (flight && flight.tenantId === tenantId2 && ids.every((id) => flight.ids.has(id))) return flight.promise;
5708
- const promise = listConnections(ids, { tenantId: tenantId2, client: client3 }).catch(() => /* @__PURE__ */ new Map());
5173
+ const promise = listConnections(ids, { tenantId: tenantId2, client: client2 }).catch(() => /* @__PURE__ */ new Map());
5709
5174
  const entry = { tenantId: tenantId2, ids: new Set(ids), promise };
5710
5175
  connectionsFlight = entry;
5711
5176
  void promise.finally(() => {
@@ -5769,17 +5234,17 @@ function describeFayzAgentGap(override) {
5769
5234
  if (!(override?.publishableKey ?? env("VITE_FAYZ_AGENT_KEY"))) missing.push("VITE_FAYZ_AGENT_KEY");
5770
5235
  return missing.length ? { missing } : null;
5771
5236
  }
5772
- var cached2 = null;
5237
+ var cached = null;
5773
5238
  function getFayzAgentClient(connection) {
5774
5239
  const key = `${connection.apiBaseUrl}|${connection.projectId}|${connection.publishableKey}`;
5775
- if (cached2?.key === key) return cached2.client;
5776
- const client3 = createFayzAgentClient({
5240
+ if (cached?.key === key) return cached.client;
5241
+ const client2 = createFayzAgentClient({
5777
5242
  baseUrl: connection.apiBaseUrl,
5778
5243
  projectId: connection.projectId,
5779
5244
  publishableKey: connection.publishableKey
5780
5245
  });
5781
- cached2 = { key, client: client3 };
5782
- return client3;
5246
+ cached = { key, client: client2 };
5247
+ return client2;
5783
5248
  }
5784
5249
 
5785
5250
  // src/components/connect/useConnectors.ts
@@ -5920,7 +5385,8 @@ function useConnectors(options = {}) {
5920
5385
  }, [call2, tenantId2, includeGrants, connection, nonce]);
5921
5386
  const revokeGrant = React133__default.useCallback(
5922
5387
  async (connector) => {
5923
- const response = await call2(`/${connector.id}`, { method: "DELETE" });
5388
+ if (!tenantId2) throw new Error("Nenhuma conta selecionada.");
5389
+ const response = await call2(`/${connector.id}?tenantId=${encodeURIComponent(tenantId2)}`, { method: "DELETE" });
5924
5390
  if (!response.ok) {
5925
5391
  const body = await response.json().catch(() => ({}));
5926
5392
  throw new Error(body.message ?? "N\xE3o foi poss\xEDvel desconectar.");
@@ -5928,7 +5394,7 @@ function useConnectors(options = {}) {
5928
5394
  invalidateGrants();
5929
5395
  setGrants((current2) => (current2 ?? []).filter((g) => g.id !== connector.id));
5930
5396
  },
5931
- [call2]
5397
+ [call2, tenantId2]
5932
5398
  );
5933
5399
  const waitingGrants = includeGrants && !!connection && !!tenantId2 && grants === null;
5934
5400
  const connectors = React133__default.useMemo(() => {
@@ -6748,8 +6214,8 @@ function summaryRows(values) {
6748
6214
  const rows = [];
6749
6215
  const push = (label3, raw) => {
6750
6216
  if (raw === void 0 || raw === null || raw === "") return;
6751
- const text2 = Array.isArray(raw) ? raw.join(", ") : String(raw);
6752
- if (text2.trim()) rows.push({ label: label3, value: text2 });
6217
+ const text3 = Array.isArray(raw) ? raw.join(", ") : String(raw);
6218
+ if (text3.trim()) rows.push({ label: label3, value: text3 });
6753
6219
  };
6754
6220
  push(tl("Workspace", "\xC1rea de trabalho"), values[NAME_FIELD]);
6755
6221
  push(tl("Contact", "Contato"), values["workspace.email"]);
@@ -7180,9 +6646,9 @@ function startNativeDictation(locale, cb) {
7180
6646
  let interim = "";
7181
6647
  for (let i = event.resultIndex; i < event.results.length; i++) {
7182
6648
  const result = event.results[i];
7183
- const text2 = result[0]?.transcript ?? "";
7184
- if (result.isFinal) finalText += text2;
7185
- else interim += text2;
6649
+ const text3 = result[0]?.transcript ?? "";
6650
+ if (result.isFinal) finalText += text3;
6651
+ else interim += text3;
7186
6652
  }
7187
6653
  cb.onInterim?.((finalText + interim).trim());
7188
6654
  };
@@ -7285,9 +6751,9 @@ function pickVoice(locale) {
7285
6751
  function stopSpeaking() {
7286
6752
  if (isSpeechOutputSupported()) window.speechSynthesis.cancel();
7287
6753
  }
7288
- function speak(text2, options = { locale: "pt-BR" }) {
6754
+ function speak(text3, options = { locale: "pt-BR" }) {
7289
6755
  if (!isSpeechOutputSupported()) return;
7290
- const content = text2.trim();
6756
+ const content = text3.trim();
7291
6757
  if (!content) return;
7292
6758
  window.speechSynthesis.cancel();
7293
6759
  const utterance = new SpeechSynthesisUtterance(content);
@@ -7417,7 +6883,7 @@ function useChat(options) {
7417
6883
  searchableTools: searchable,
7418
6884
  carriedTools: [...pinned]
7419
6885
  };
7420
- const client3 = getFayzAgentClient(activeConnection);
6886
+ const client2 = getFayzAgentClient(activeConnection);
7421
6887
  const upcoming = Array.from({ length: 7 }, (_, i) => {
7422
6888
  const d = new Date(Date.now() + (i + 1) * 864e5);
7423
6889
  return `${d.toLocaleDateString("pt-BR", { weekday: "long" })}=${d.toISOString().slice(0, 10)}`;
@@ -7448,7 +6914,7 @@ function useChat(options) {
7448
6914
  for (let round = 0; round <= MAX_TOOL_ROUNDS; round++) {
7449
6915
  toolset = buildToolset();
7450
6916
  toolContext.writeTools = toolset.map((t2) => toolByName.get(t2.name)).filter((d) => d?.mode === "persist").map((d) => ({ name: d.name, action: d.permission?.action }));
7451
- const response = await client3.chatStream({
6917
+ const response = await client2.chatStream({
7452
6918
  message,
7453
6919
  toolResults,
7454
6920
  confirmAction,
@@ -7660,8 +7126,8 @@ ${JSON.stringify(snapshot.length === 1 ? snapshot[0] : snapshot)}` : void 0
7660
7126
  return;
7661
7127
  }
7662
7128
  const data = await response.json();
7663
- const text2 = data.choices?.[0]?.message?.content ?? data.content ?? "No response.";
7664
- store.updateLastAssistant(text2);
7129
+ const text3 = data.choices?.[0]?.message?.content ?? data.content ?? "No response.";
7130
+ store.updateLastAssistant(text3);
7665
7131
  } catch {
7666
7132
  store.updateLastAssistant("Sorry, I could not connect. Please try again later.");
7667
7133
  } finally {
@@ -7812,12 +7278,12 @@ var AGENT_WAIT_MS = 2500;
7812
7278
  function prefersReducedMotion2() {
7813
7279
  return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
7814
7280
  }
7815
- function TypewriterText({ text: text2, speed = 26, onDone }) {
7281
+ function TypewriterText({ text: text3, speed = 26, onDone }) {
7816
7282
  const [displayed, setDisplayed] = React133.useState("");
7817
7283
  const indexRef = React133.useRef(0);
7818
7284
  React133.useEffect(() => {
7819
7285
  if (prefersReducedMotion2()) {
7820
- setDisplayed(text2);
7286
+ setDisplayed(text3);
7821
7287
  onDone?.();
7822
7288
  return;
7823
7289
  }
@@ -7825,18 +7291,18 @@ function TypewriterText({ text: text2, speed = 26, onDone }) {
7825
7291
  indexRef.current = 0;
7826
7292
  const interval = setInterval(() => {
7827
7293
  indexRef.current++;
7828
- if (indexRef.current > text2.length) {
7294
+ if (indexRef.current > text3.length) {
7829
7295
  clearInterval(interval);
7830
7296
  onDone?.();
7831
7297
  return;
7832
7298
  }
7833
- setDisplayed(text2.slice(0, indexRef.current));
7299
+ setDisplayed(text3.slice(0, indexRef.current));
7834
7300
  }, speed);
7835
7301
  return () => clearInterval(interval);
7836
- }, [text2, speed]);
7302
+ }, [text3, speed]);
7837
7303
  return /* @__PURE__ */ jsxs("span", { children: [
7838
7304
  displayed,
7839
- displayed.length < text2.length && /* @__PURE__ */ jsx("span", { className: "ml-0.5 -mb-px inline-block h-3 w-[2px] bg-current/60 motion-safe:animate-pulse" })
7305
+ displayed.length < text3.length && /* @__PURE__ */ jsx("span", { className: "ml-0.5 -mb-px inline-block h-3 w-[2px] bg-current/60 motion-safe:animate-pulse" })
7840
7306
  ] });
7841
7307
  }
7842
7308
  var STYLE_ID = "chat-fab-anims";
@@ -9815,14 +9281,14 @@ function SettingRow({
9815
9281
  }
9816
9282
  );
9817
9283
  default: {
9818
- const text2 = typeof value === "string" ? value : "";
9819
- const bad = !matchesPattern(setting, text2);
9284
+ const text3 = typeof value === "string" ? value : "";
9285
+ const bad = !matchesPattern(setting, text3);
9820
9286
  return /* @__PURE__ */ jsx(
9821
9287
  TextRow,
9822
9288
  {
9823
9289
  label: setting.label,
9824
9290
  description: description || void 0,
9825
- value: text2,
9291
+ value: text3,
9826
9292
  placeholder: setting.placeholder,
9827
9293
  hint: setting.patternHint,
9828
9294
  invalid: bad,
@@ -10565,10 +10031,10 @@ function useDictation({
10565
10031
  sessionRef.current = startDictation(
10566
10032
  { locale: resolvedLocale, transcribeEndpoint },
10567
10033
  {
10568
- onInterim: (text2) => callbacks.current.onInterim?.(text2),
10569
- onFinal: (text2) => {
10034
+ onInterim: (text3) => callbacks.current.onInterim?.(text3),
10035
+ onFinal: (text3) => {
10570
10036
  finish();
10571
- if (text2) callbacks.current.onTranscript(text2);
10037
+ if (text3) callbacks.current.onTranscript(text3);
10572
10038
  },
10573
10039
  onError: (code) => {
10574
10040
  sessionRef.current = null;
@@ -10891,8 +10357,8 @@ function ChatComposer({
10891
10357
  const parsing = attachments.some((a) => a.status === "parsing");
10892
10358
  const readyAttachments = attachments.filter((a) => a.status === "ready").length;
10893
10359
  const submit = React133.useCallback(
10894
- (text2) => {
10895
- const trimmed = text2.trim();
10360
+ (text3) => {
10361
+ const trimmed = text3.trim();
10896
10362
  const media = useChatStore.getState().composerMedia;
10897
10363
  if (!trimmed && !readyAttachments && !media || parsing || isStreaming || !isConfigured || blocked) return;
10898
10364
  setInput("");
@@ -10906,17 +10372,17 @@ function ChatComposer({
10906
10372
  const dictation = useDictation({
10907
10373
  locale: voice?.locale,
10908
10374
  transcribeEndpoint: voice?.transcribeEndpoint,
10909
- onInterim: (text2) => setInput(text2),
10910
- onTranscript: (text2) => {
10375
+ onInterim: (text3) => setInput(text3),
10376
+ onTranscript: (text3) => {
10911
10377
  if (autoSend) {
10912
- submit(text2);
10378
+ submit(text3);
10913
10379
  return;
10914
10380
  }
10915
- setInput(text2);
10381
+ setInput(text3);
10916
10382
  const el = textareaRef.current;
10917
10383
  if (el) {
10918
10384
  el.focus();
10919
- requestAnimationFrame(() => el.setSelectionRange(text2.length, text2.length));
10385
+ requestAnimationFrame(() => el.setSelectionRange(text3.length, text3.length));
10920
10386
  }
10921
10387
  }
10922
10388
  });
@@ -11069,8 +10535,8 @@ function ChatComposer({
11069
10535
  if (!canAttach) return;
11070
10536
  const files = Array.from(event.clipboardData?.files ?? []);
11071
10537
  if (!files.length) return;
11072
- const text2 = event.clipboardData?.getData("text/plain");
11073
- if (text2 && files.every((f) => f.type.startsWith("image/"))) return;
10538
+ const text3 = event.clipboardData?.getData("text/plain");
10539
+ if (text3 && files.every((f) => f.type.startsWith("image/"))) return;
11074
10540
  event.preventDefault();
11075
10541
  receiveFiles(files);
11076
10542
  },
@@ -11390,14 +10856,14 @@ function MdLink({ href, children }) {
11390
10856
  }
11391
10857
  );
11392
10858
  }
11393
- function renderInline(text2, keyBase) {
10859
+ function renderInline(text3, keyBase) {
11394
10860
  const out = [];
11395
10861
  const pattern = /(`[^`]+`)|(\*\*[^*]+\*\*)|(\*[^*]+\*)|(\[[^\]]+\]\([^)\s]+\))/g;
11396
10862
  let last = 0;
11397
10863
  let match;
11398
10864
  let i = 0;
11399
- while ((match = pattern.exec(text2)) !== null) {
11400
- if (match.index > last) out.push(text2.slice(last, match.index));
10865
+ while ((match = pattern.exec(text3)) !== null) {
10866
+ if (match.index > last) out.push(text3.slice(last, match.index));
11401
10867
  const token = match[0];
11402
10868
  const key = `${keyBase}-${i++}`;
11403
10869
  if (token.startsWith("`")) {
@@ -11420,7 +10886,7 @@ function renderInline(text2, keyBase) {
11420
10886
  }
11421
10887
  last = match.index + token.length;
11422
10888
  }
11423
- if (last < text2.length) out.push(text2.slice(last));
10889
+ if (last < text3.length) out.push(text3.slice(last));
11424
10890
  return out;
11425
10891
  }
11426
10892
  var LIST_RE = /^(\s*)([-*]|\d+[.)])\s+(.*)$/;
@@ -12201,13 +11667,13 @@ function formatValue(value) {
12201
11667
  if (typeof value === "boolean") return value ? "\u2713" : "\u2014";
12202
11668
  if (Array.isArray(value)) return value.map((v) => formatValue(v)).join(", ");
12203
11669
  if (value && typeof value === "object") return JSON.stringify(value);
12204
- const text2 = String(value);
12205
- const iso = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})/.exec(text2);
11670
+ const text3 = String(value);
11671
+ const iso = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})/.exec(text3);
12206
11672
  if (iso) {
12207
- const parsed = new Date(text2);
11673
+ const parsed = new Date(text3);
12208
11674
  if (!Number.isNaN(parsed.getTime())) return parsed.toLocaleString();
12209
11675
  }
12210
- return text2;
11676
+ return text3;
12211
11677
  }
12212
11678
  var PLAIN_DATE = /^\d{4}-\d{2}-\d{2}$/;
12213
11679
  function toInputDate(value, type) {
@@ -12322,7 +11788,7 @@ function usePrefersReducedMotion() {
12322
11788
  return reduced;
12323
11789
  }
12324
11790
  function TypedText({
12325
- text: text2,
11791
+ text: text3,
12326
11792
  className,
12327
11793
  as: Tag3 = "p",
12328
11794
  start = true,
@@ -12330,7 +11796,7 @@ function TypedText({
12330
11796
  onDone
12331
11797
  }) {
12332
11798
  const reduced = usePrefersReducedMotion();
12333
- const [count, setCount] = React133.useState(reduced ? text2.length : 0);
11799
+ const [count, setCount] = React133.useState(reduced ? text3.length : 0);
12334
11800
  const done = React133.useRef(onDone);
12335
11801
  done.current = onDone;
12336
11802
  React133.useEffect(() => {
@@ -12338,19 +11804,19 @@ function TypedText({
12338
11804
  setCount(0);
12339
11805
  return;
12340
11806
  }
12341
- if (reduced || !text2) {
12342
- setCount(text2.length);
11807
+ if (reduced || !text3) {
11808
+ setCount(text3.length);
12343
11809
  const id = setTimeout(() => done.current?.(), 0);
12344
11810
  return () => clearTimeout(id);
12345
11811
  }
12346
11812
  setCount(0);
12347
- const step = Math.min(MAX_CHAR_MS, Math.max(MIN_CHAR_MS, Math.round(TYPE_MS / text2.length)));
11813
+ const step = Math.min(MAX_CHAR_MS, Math.max(MIN_CHAR_MS, Math.round(TYPE_MS / text3.length)));
12348
11814
  let i = 0;
12349
11815
  let timer;
12350
11816
  const first = setTimeout(function tick() {
12351
11817
  i += 1;
12352
11818
  setCount(i);
12353
- if (i >= text2.length) {
11819
+ if (i >= text3.length) {
12354
11820
  done.current?.();
12355
11821
  return;
12356
11822
  }
@@ -12360,11 +11826,11 @@ function TypedText({
12360
11826
  clearTimeout(first);
12361
11827
  clearTimeout(timer);
12362
11828
  };
12363
- }, [text2, reduced, start, startDelay]);
11829
+ }, [text3, reduced, start, startDelay]);
12364
11830
  return /* @__PURE__ */ jsxs(Tag3, { className: cn("grid", className), children: [
12365
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "invisible", style: { gridArea: "1 / 1" }, children: text2 }),
12366
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: text2 }),
12367
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, style: { gridArea: "1 / 1" }, children: text2.slice(0, count) })
11831
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "invisible", style: { gridArea: "1 / 1" }, children: text3 }),
11832
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: text3 }),
11833
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, style: { gridArea: "1 / 1" }, children: text3.slice(0, count) })
12368
11834
  ] });
12369
11835
  }
12370
11836
  function RevealSequence({
@@ -12655,11 +12121,11 @@ function ChatConversation({
12655
12121
  const el = event.currentTarget;
12656
12122
  setAtBottom(el.scrollHeight - el.scrollTop - el.clientHeight < 48);
12657
12123
  };
12658
- const send = (text2) => {
12124
+ const send = (text3) => {
12659
12125
  setView("thread");
12660
12126
  setAtBottom(true);
12661
12127
  setSuggestionsOpen(false);
12662
- sendMessage(text2);
12128
+ sendMessage(text3);
12663
12129
  };
12664
12130
  const queuedPrompt = useChatStore((s) => s.queuedPrompt);
12665
12131
  const consumeQueuedPrompt = useChatStore((s) => s.consumeQueuedPrompt);
@@ -13032,7 +12498,7 @@ function AgentAvatar({
13032
12498
  className
13033
12499
  }) {
13034
12500
  const [failed, setFailed] = React133.useState(false);
13035
- const { box, text: text2, px } = SIZES[size];
12501
+ const { box, text: text3, px } = SIZES[size];
13036
12502
  if (Face) {
13037
12503
  return /* @__PURE__ */ jsx(
13038
12504
  "span",
@@ -13051,7 +12517,7 @@ function AgentAvatar({
13051
12517
  "relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-full",
13052
12518
  "bg-muted font-medium text-muted-foreground",
13053
12519
  box,
13054
- text2,
12520
+ text3,
13055
12521
  className
13056
12522
  ),
13057
12523
  children: [
@@ -13596,10 +13062,10 @@ function TaskQuickAdd({ parentId }) {
13596
13062
  )
13597
13063
  ] });
13598
13064
  }
13599
- var STORAGE_KEY3 = "saas-core:locale";
13065
+ var STORAGE_KEY = "saas-core:locale";
13600
13066
  function readPersistedLocale() {
13601
13067
  try {
13602
- return localStorage.getItem(STORAGE_KEY3) ?? void 0;
13068
+ return localStorage.getItem(STORAGE_KEY) ?? void 0;
13603
13069
  } catch {
13604
13070
  return void 0;
13605
13071
  }
@@ -13611,7 +13077,7 @@ var useLocaleStore = create((set) => ({
13611
13077
  locale: getPersistedLocale(),
13612
13078
  setLocale: (locale) => {
13613
13079
  try {
13614
- localStorage.setItem(STORAGE_KEY3, locale);
13080
+ localStorage.setItem(STORAGE_KEY, locale);
13615
13081
  } catch {
13616
13082
  }
13617
13083
  set({ locale });
@@ -14497,23 +13963,23 @@ var TYPING_LEAD_MS = 420;
14497
13963
  var TYPING_MS_PER_WORD = 55;
14498
13964
  var TYPING_CEILING_MS = 1200;
14499
13965
  var TYPING_FRAME_MS = 45;
14500
- function say(text2, cards) {
13966
+ function say(text3, cards) {
14501
13967
  const chat = useChatStore.getState();
14502
13968
  const id = `guided-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
14503
- const trimmed = text2.trim();
13969
+ const trimmed = text3.trim();
14504
13970
  chat.addMessage({
14505
13971
  id,
14506
13972
  role: "assistant",
14507
13973
  // Empty content is what renders the typing dots (see ChatMessages).
14508
- content: trimmed ? "" : text2,
13974
+ content: trimmed ? "" : text3,
14509
13975
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
14510
13976
  ...cards ? { cards } : {}
14511
13977
  });
14512
13978
  chat.setOpen(true);
14513
- if (trimmed) typeInto(id, text2);
13979
+ if (trimmed) typeInto(id, text3);
14514
13980
  }
14515
- function typeInto(id, text2) {
14516
- const words2 = text2.split(/(\s+)/);
13981
+ function typeInto(id, text3) {
13982
+ const words2 = text3.split(/(\s+)/);
14517
13983
  const wordCount = words2.filter((w) => w.trim()).length;
14518
13984
  const total = Math.min(TYPING_CEILING_MS, wordCount * TYPING_MS_PER_WORD);
14519
13985
  const frames = Math.max(1, Math.round(total / TYPING_FRAME_MS));
@@ -14523,7 +13989,7 @@ function typeInto(id, text2) {
14523
13989
  const finish = () => {
14524
13990
  if (timer) clearTimeout(timer);
14525
13991
  typers.delete(finish);
14526
- useChatStore.getState().setMessageContent(id, text2);
13992
+ useChatStore.getState().setMessageContent(id, text3);
14527
13993
  };
14528
13994
  const step = () => {
14529
13995
  cursor += perFrame;
@@ -14543,8 +14009,8 @@ function flushTyping() {
14543
14009
  var BEAT_FLOOR_MS = 1400;
14544
14010
  var MS_PER_WORD = 260;
14545
14011
  var BEAT_CEILING_MS = 6e3;
14546
- function readingTime(text2) {
14547
- const words2 = text2.trim().split(/\s+/).length;
14012
+ function readingTime(text3) {
14013
+ const words2 = text3.trim().split(/\s+/).length;
14548
14014
  return Math.min(BEAT_CEILING_MS, BEAT_FLOOR_MS + words2 * MS_PER_WORD);
14549
14015
  }
14550
14016
  var NAV_MS = 1e3;
@@ -16073,7 +15539,7 @@ function ActivationProvider() {
16073
15539
  const orgName = useOrganizationStore((s) => s.currentOrg?.name);
16074
15540
  const user = useAuthStore((s) => s.user);
16075
15541
  const setCatalog = useActivationStore((s) => s.setCatalog);
16076
- const load = useActivationStore((s) => s.load);
15542
+ const load2 = useActivationStore((s) => s.load);
16077
15543
  const programs = runtime?.onboardingPrograms ?? [];
16078
15544
  const settingsIds = useSettingsTabsStore((s) => s.ids);
16079
15545
  const routeKey = (runtime?.routes.length ?? 0) + ":" + settingsIds.join(",");
@@ -16096,7 +15562,7 @@ function ActivationProvider() {
16096
15562
  if (!tenantId2) return;
16097
15563
  let cancelled = false;
16098
15564
  void (async () => {
16099
- await load(tenantId2);
15565
+ await load2(tenantId2);
16100
15566
  if (cancelled || !user) return;
16101
15567
  const rows = useActivationStore.getState().rows ?? [];
16102
15568
  const stale = /* @__PURE__ */ new Set([
@@ -16118,12 +15584,12 @@ function ActivationProvider() {
16118
15584
  userName: user.fullName || user.email,
16119
15585
  items: missing
16120
15586
  });
16121
- if (ok && !cancelled) await load(tenantId2);
15587
+ if (ok && !cancelled) await load2(tenantId2);
16122
15588
  })();
16123
15589
  return () => {
16124
15590
  cancelled = true;
16125
15591
  };
16126
- }, [tenantId2, catalog, answers, hasRoute, settingsIds, user?.id, load]);
15592
+ }, [tenantId2, catalog, answers, hasRoute, settingsIds, user?.id, load2]);
16127
15593
  React133.useEffect(() => {
16128
15594
  if (!tenantId2) {
16129
15595
  useBusinessProfileStore.getState().clear();
@@ -16200,8 +15666,8 @@ var useHandbookStore = create((set, get) => ({
16200
15666
  open: async (path) => {
16201
15667
  const { tenantId: tenantId2, pages } = get();
16202
15668
  if (!tenantId2) return null;
16203
- const cached3 = (pages ?? []).find((p) => p.path === path);
16204
- if (cached3) return cached3;
15669
+ const cached2 = (pages ?? []).find((p) => p.path === path);
15670
+ if (cached2) return cached2;
16205
15671
  return readHandbookPage(tenantId2, path);
16206
15672
  },
16207
15673
  write: async (input) => {
@@ -17047,14 +16513,14 @@ function NotebookRailPanel() {
17047
16513
  function HandbookProvider() {
17048
16514
  const tenantId2 = useOrganizationStore((s) => s.currentOrg?.id);
17049
16515
  const userId = useAuthStore((s) => s.user?.id);
17050
- const load = useHandbookStore((s) => s.load);
16516
+ const load2 = useHandbookStore((s) => s.load);
17051
16517
  const setUser = useHandbookStore((s) => s.setUser);
17052
16518
  React133.useEffect(() => {
17053
16519
  setUser(userId);
17054
16520
  }, [userId, setUser]);
17055
16521
  React133.useEffect(() => {
17056
- if (tenantId2) void load(tenantId2);
17057
- }, [tenantId2, load]);
16522
+ if (tenantId2) void load2(tenantId2);
16523
+ }, [tenantId2, load2]);
17058
16524
  useLocalNotesImport(tenantId2, userId);
17059
16525
  return /* @__PURE__ */ jsxs(Fragment, { children: [
17060
16526
  /* @__PURE__ */ jsx(NotebookRailPanel, {}),
@@ -17112,9 +16578,9 @@ function useUnitBootstrap() {
17112
16578
  const orgId = tenant?.org?.id;
17113
16579
  React133.useEffect(() => {
17114
16580
  if (!orgId) return;
17115
- const { loadedFor, load, reset } = useUnitStore.getState();
16581
+ const { loadedFor, load: load2, reset } = useUnitStore.getState();
17116
16582
  if (loadedFor && loadedFor !== orgId) reset();
17117
- void load(orgId, userId);
16583
+ void load2(orgId, userId);
17118
16584
  }, [orgId, userId]);
17119
16585
  }
17120
16586
  var NO_EXTRA_ROLE = "__none__";
@@ -17500,14 +16966,14 @@ function startFayzEventBridge(override) {
17500
16966
  };
17501
16967
  }
17502
16968
  debug(`started \u2192 ${connection.apiBaseUrl} (project ${connection.projectId})`);
17503
- const client3 = createFayzEventsClient({
16969
+ const client2 = createFayzEventsClient({
17504
16970
  baseUrl: connection.apiBaseUrl,
17505
16971
  projectId: connection.projectId,
17506
16972
  publishableKey: connection.publishableKey
17507
16973
  });
17508
16974
  const off = registerEventSink((event) => {
17509
- debug(`enqueue ${event.key}`, { tenantId: event.tenantId, pending: client3.pending() + 1 });
17510
- client3.enqueue({
16975
+ debug(`enqueue ${event.key}`, { tenantId: event.tenantId, pending: client2.pending() + 1 });
16976
+ client2.enqueue({
17511
16977
  // The dedupe id is minted at the sink, once per emission — a transport
17512
16978
  // retry reuses it, so the server never runs the same fact twice.
17513
16979
  id: crypto.randomUUID(),
@@ -17519,7 +16985,7 @@ function startFayzEventBridge(override) {
17519
16985
  subject: event.subject
17520
16986
  });
17521
16987
  });
17522
- active = { client: client3, off };
16988
+ active = { client: client2, off };
17523
16989
  return stopFayzEventBridge;
17524
16990
  }
17525
16991
  function stopFayzEventBridge() {
@@ -17772,6 +17238,24 @@ function tripletLuminance(triplet) {
17772
17238
  });
17773
17239
  return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2];
17774
17240
  }
17241
+ function contrast(a, b) {
17242
+ return (Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05);
17243
+ }
17244
+ function readableInkOn(primary, surface) {
17245
+ const surfaceL = tripletLuminance(surface);
17246
+ const primaryL = tripletLuminance(primary);
17247
+ if (!primary || surfaceL == null || primaryL == null) return primary;
17248
+ if (contrast(primaryL, surfaceL) >= 3) return primary;
17249
+ const [h, sat, light] = primary.trim().split("/")[0].trim().split(/\s+/);
17250
+ const step = surfaceL > 0.5 ? -2 : 2;
17251
+ let l = parseFloat(light);
17252
+ for (let i = 0; i < 50; i++) {
17253
+ l = Math.min(100, Math.max(0, l + step));
17254
+ const candidate = `${h} ${sat} ${Math.round(l * 10) / 10}%`;
17255
+ if (contrast(tripletLuminance(candidate) ?? surfaceL, surfaceL) >= 4.5 || l === 0 || l === 100) return candidate;
17256
+ }
17257
+ return primary;
17258
+ }
17775
17259
  function inkOnTriplet(triplet) {
17776
17260
  const l = tripletLuminance(triplet);
17777
17261
  return l != null && l > 0.45 ? "0 0% 10%" : "0 0% 100%";
@@ -17959,6 +17443,9 @@ function applyTheme(theme, element) {
17959
17443
  target.style.setProperty(cssVar, value);
17960
17444
  }
17961
17445
  }
17446
+ const paper = tripletLuminance(theme.colors.content) != null ? theme.colors.content : theme.colors.background;
17447
+ const ink = readableInkOn(theme.colors.primary, paper);
17448
+ if (ink) target.style.setProperty("--primary-ink", ink);
17962
17449
  persistBootPalette(theme.colors);
17963
17450
  }
17964
17451
  function hexToHslTriplet(hex) {
@@ -17985,14 +17472,14 @@ function hexToHslTriplet(hex) {
17985
17472
  }
17986
17473
 
17987
17474
  // src/stores/theme.store.ts
17988
- var STORAGE_KEY4 = "saas-core:theme-mode";
17475
+ var STORAGE_KEY2 = "saas-core:theme-mode";
17989
17476
  function getSystemPreference() {
17990
17477
  if (typeof window === "undefined") return "light";
17991
17478
  return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
17992
17479
  }
17993
17480
  function getSavedMode() {
17994
17481
  if (typeof window === "undefined") return "light";
17995
- const saved = localStorage.getItem(STORAGE_KEY4);
17482
+ const saved = localStorage.getItem(STORAGE_KEY2);
17996
17483
  if (saved === "light" || saved === "dark" || saved === "system") return saved;
17997
17484
  return "light";
17998
17485
  }
@@ -18044,7 +17531,7 @@ function createThemeStore() {
18044
17531
  const resolved = resolveMode(mode);
18045
17532
  set({ mode, resolvedMode: resolved });
18046
17533
  if (typeof window !== "undefined") {
18047
- localStorage.setItem(STORAGE_KEY4, mode);
17534
+ localStorage.setItem(STORAGE_KEY2, mode);
18048
17535
  }
18049
17536
  const { overrides } = get();
18050
17537
  const baseTheme = resolved === "dark" ? darkTheme : lightTheme;
@@ -18374,12 +17861,12 @@ function PublicSurveyPage({ token, appName }) {
18374
17861
  const [failed, setFailed] = React133__default.useState(null);
18375
17862
  React133__default.useEffect(() => {
18376
17863
  let alive = true;
18377
- const client3 = getFayzSupabaseClientOptional();
18378
- if (!client3) {
17864
+ const client2 = getFayzSupabaseClientOptional();
17865
+ if (!client2) {
18379
17866
  setLoaded({ status: "not_found" });
18380
17867
  return;
18381
17868
  }
18382
- client3.rpc("crm_survey_invite_load", { p_token: token }).then(({ data, error }) => {
17869
+ client2.rpc("crm_survey_invite_load", { p_token: token }).then(({ data, error }) => {
18383
17870
  if (!alive) return;
18384
17871
  setLoaded(error ? { status: "not_found" } : data);
18385
17872
  });
@@ -18398,9 +17885,9 @@ function PublicSurveyPage({ token, appName }) {
18398
17885
  if (missing.length > 0 || sending) return;
18399
17886
  setSending(true);
18400
17887
  setFailed(null);
18401
- const client3 = getFayzSupabaseClientOptional();
17888
+ const client2 = getFayzSupabaseClientOptional();
18402
17889
  const answers = questions.map((q) => ({ question_id: q.id, rating: draft[q.id]?.rating ?? null, comment: draft[q.id]?.comment ?? null })).filter((a) => a.rating != null || (a.comment ?? "").trim() !== "");
18403
- const { data, error } = await client3.rpc("crm_survey_invite_submit", {
17890
+ const { data, error } = await client2.rpc("crm_survey_invite_submit", {
18404
17891
  p_token: token,
18405
17892
  p_answers: answers,
18406
17893
  p_respondent_name: name.trim() || null
@@ -19017,8 +18504,8 @@ function coerceField(field, value) {
19017
18504
  }
19018
18505
  const first = Array.isArray(value) ? value[0] : value;
19019
18506
  if (typeof first !== "string") return void 0;
19020
- const text2 = field.normalize ? field.normalize(first) : first.trim();
19021
- return text2 || void 0;
18507
+ const text3 = field.normalize ? field.normalize(first) : first.trim();
18508
+ return text3 || void 0;
19022
18509
  }
19023
18510
 
19024
18511
  // src/onboarding/analyze-site.ts
@@ -19439,14 +18926,14 @@ var useAppDirectoryStore = create((set, get) => ({
19439
18926
  load: async (tenantId2, currentAppId, deps) => {
19440
18927
  const state = get();
19441
18928
  if (state.status !== "idle" && state.tenantId === tenantId2) return;
19442
- const client3 = deps?.client === void 0 ? getFayzSupabaseClientOptional() : deps.client;
19443
- if (!client3) {
18929
+ const client2 = deps?.client === void 0 ? getFayzSupabaseClientOptional() : deps.client;
18930
+ if (!client2) {
19444
18931
  set({ status: "done", tenantId: tenantId2 });
19445
18932
  return;
19446
18933
  }
19447
18934
  set({ status: "loading", tenantId: tenantId2 });
19448
18935
  try {
19449
- const config = await fetchAppConfig(client3, { tenantId: tenantId2 });
18936
+ const config = await fetchAppConfig(client2, { tenantId: tenantId2 });
19450
18937
  set({ apps: normalize(config.apps, currentAppId), status: "done", tenantId: tenantId2 });
19451
18938
  } catch {
19452
18939
  set({ status: "done", tenantId: tenantId2 });
@@ -19462,10 +18949,10 @@ function resetAppDirectory() {
19462
18949
  function useAppDirectory() {
19463
18950
  const tenantId2 = useActiveTenantId();
19464
18951
  const apps = useAppDirectoryStore((s) => s.apps);
19465
- const load = useAppDirectoryStore((s) => s.load);
18952
+ const load2 = useAppDirectoryStore((s) => s.load);
19466
18953
  React133.useEffect(() => {
19467
- if (tenantId2) void load(tenantId2, resolveAppId());
19468
- }, [tenantId2, load]);
18954
+ if (tenantId2) void load2(tenantId2, resolveAppId());
18955
+ }, [tenantId2, load2]);
19469
18956
  return { apps };
19470
18957
  }
19471
18958
  var FAMILY_SUFFIX = "Control";
@@ -20291,9 +19778,9 @@ function WorkspaceUnitRow({ canCreate = true }) {
20291
19778
  }
20292
19779
  var TABLE2 = "published_sites";
20293
19780
  function db() {
20294
- const client3 = getSupabaseClientOptional();
20295
- if (!client3) throw new Error("[fayz-projects] Supabase not initialized");
20296
- return client3;
19781
+ const client2 = getSupabaseClientOptional();
19782
+ if (!client2) throw new Error("[fayz-projects] Supabase not initialized");
19783
+ return client2;
20297
19784
  }
20298
19785
  function tenantId() {
20299
19786
  return useOrganizationStore.getState().currentOrg?.id ?? getActiveTenantId();
@@ -20437,7 +19924,7 @@ function SeuSiteWidget({ fallback, onEdit }) {
20437
19924
  const t = useTranslation();
20438
19925
  const currentOrgId = useOrganizationStore((s) => s.currentOrg?.id);
20439
19926
  const projects = useFayzProjectsStore((s) => s.projects);
20440
- const load = useFayzProjectsStore((s) => s.load);
19927
+ const load2 = useFayzProjectsStore((s) => s.load);
20441
19928
  const loadedFor = useFayzProjectsStore((s) => s.loadedFor);
20442
19929
  const collapsed = useLayoutStore((s) => s.sidebarCollapsed);
20443
19930
  const [selectedId, setSelectedId] = React133.useState(null);
@@ -20461,8 +19948,8 @@ function SeuSiteWidget({ fallback, onEdit }) {
20461
19948
  };
20462
19949
  React133.useEffect(() => () => cancelClose(), []);
20463
19950
  React133.useEffect(() => {
20464
- if (loadedFor !== (currentOrgId ?? null)) void load(currentOrgId);
20465
- }, [currentOrgId, loadedFor, load]);
19951
+ if (loadedFor !== (currentOrgId ?? null)) void load2(currentOrgId);
19952
+ }, [currentOrgId, loadedFor, load2]);
20466
19953
  const active2 = projects.find((p) => p.id === selectedId) ?? defaultProjectOf(projects) ?? synthFromFallback(fallback);
20467
19954
  if (!active2) return null;
20468
19955
  const Icon = KIND_ICON2[active2.kind] ?? Globe;
@@ -21536,17 +21023,17 @@ function ConsentBody({
21536
21023
  busy
21537
21024
  }) {
21538
21025
  if (!payload) return /* @__PURE__ */ jsx(ConsentSkeleton, {});
21539
- const { client: client3, access, organizations } = payload;
21026
+ const { client: client2, access, organizations } = payload;
21540
21027
  const org = organizations.find((o) => o.tenantId === tenantId2);
21541
- const mark = client3.logoUri ?? knownClientMark(client3.website, client3.identityVerified === true, client3.name);
21028
+ const mark = client2.logoUri ?? knownClientMark(client2.website, client2.identityVerified === true, client2.name);
21542
21029
  return /* @__PURE__ */ jsxs(Fragment, { children: [
21543
21030
  /* @__PURE__ */ jsxs("div", { className: "mb-6 flex items-center justify-center gap-3", children: [
21544
- /* @__PURE__ */ jsx(MarkBadge, { fallback: client3.name, children: mark ? /* @__PURE__ */ jsx("img", { src: mark, alt: "", className: "h-full w-full object-cover" }) : null }),
21031
+ /* @__PURE__ */ jsx(MarkBadge, { fallback: client2.name, children: mark ? /* @__PURE__ */ jsx("img", { src: mark, alt: "", className: "h-full w-full object-cover" }) : null }),
21545
21032
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "\u21C4" }),
21546
21033
  /* @__PURE__ */ jsx(MarkBadge, { fallback: product, children: logo })
21547
21034
  ] }),
21548
21035
  /* @__PURE__ */ jsxs("h1", { className: "text-center text-xl font-semibold text-foreground", children: [
21549
- client3.name,
21036
+ client2.name,
21550
21037
  " quer acessar seus dados"
21551
21038
  ] }),
21552
21039
  /* @__PURE__ */ jsxs("dl", { className: "mt-6 divide-y divide-border overflow-hidden rounded-xl border border-border text-sm", children: [
@@ -21555,8 +21042,8 @@ function ConsentBody({
21555
21042
  {
21556
21043
  label: "Aplicativo",
21557
21044
  value: /* @__PURE__ */ jsxs("span", { children: [
21558
- client3.name,
21559
- client3.identityVerified !== true && // Not an alarm — most CLI clients register themselves and are
21045
+ client2.name,
21046
+ client2.identityVerified !== true && // Not an alarm — most CLI clients register themselves and are
21560
21047
  // perfectly legitimate. But the user is about to hand over an
21561
21048
  // organization's data, and "this name is self-declared" is a
21562
21049
  // fact they are entitled to before deciding.
@@ -21564,14 +21051,14 @@ function ConsentBody({
21564
21051
  ] })
21565
21052
  }
21566
21053
  ),
21567
- client3.website && /* @__PURE__ */ jsx(
21054
+ client2.website && /* @__PURE__ */ jsx(
21568
21055
  Row2,
21569
21056
  {
21570
21057
  label: "Site",
21571
- value: /* @__PURE__ */ jsx("a", { href: client3.website, target: "_blank", rel: "noreferrer noopener", className: "text-primary hover:underline", children: client3.website })
21058
+ value: /* @__PURE__ */ jsx("a", { href: client2.website, target: "_blank", rel: "noreferrer noopener", className: "text-primary hover:underline", children: client2.website })
21572
21059
  }
21573
21060
  ),
21574
- /* @__PURE__ */ jsx(Row2, { label: "Retorna para", value: /* @__PURE__ */ jsx("span", { className: "break-all font-mono text-xs", children: client3.redirectUri }) }),
21061
+ /* @__PURE__ */ jsx(Row2, { label: "Retorna para", value: /* @__PURE__ */ jsx("span", { className: "break-all font-mono text-xs", children: client2.redirectUri }) }),
21575
21062
  /* @__PURE__ */ jsx(
21576
21063
  Row2,
21577
21064
  {
@@ -21618,7 +21105,7 @@ function ConsentBody({
21618
21105
  ] }),
21619
21106
  /* @__PURE__ */ jsxs("p", { className: "mt-5 text-xs leading-relaxed text-muted-foreground", children: [
21620
21107
  "Ao aprovar, ",
21621
- client3.name,
21108
+ client2.name,
21622
21109
  " poder\xE1 ler os dados",
21623
21110
  org ? ` de ${org.name}` : " da organiza\xE7\xE3o escolhida",
21624
21111
  " at\xE9 voc\xEA desconectar. Voc\xEA pode desfazer isso a qualquer momento em ",
@@ -22116,7 +21603,7 @@ var ICON = {
22116
21603
  failed: { Icon: XCircle, className: "text-destructive", label: "N\xE3o foi" }
22117
21604
  };
22118
21605
  function ConnectorDeliveries({
22119
- load,
21606
+ load: load2,
22120
21607
  providerName,
22121
21608
  limit = 10
22122
21609
  }) {
@@ -22124,7 +21611,7 @@ function ConnectorDeliveries({
22124
21611
  const [rows, setRows] = React133__default.useState(null);
22125
21612
  React133__default.useEffect(() => {
22126
21613
  let cancelled = false;
22127
- void load({ limit }).then((r) => {
21614
+ void load2({ limit }).then((r) => {
22128
21615
  if (!cancelled) setRows(r);
22129
21616
  }).catch(() => {
22130
21617
  if (!cancelled) setRows([]);
@@ -22132,7 +21619,7 @@ function ConnectorDeliveries({
22132
21619
  return () => {
22133
21620
  cancelled = true;
22134
21621
  };
22135
- }, [load, limit]);
21622
+ }, [load2, limit]);
22136
21623
  if (rows === null) {
22137
21624
  return /* @__PURE__ */ jsx("p", { className: "flex justify-center py-4", children: /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) });
22138
21625
  }
@@ -22291,7 +21778,7 @@ function UnitModeCard() {
22291
21778
  const unitMode = useUnitStore((s) => s.unitMode);
22292
21779
  const units = useUnitStore((s) => s.units);
22293
21780
  const setMode = useUnitStore((s) => s.setMode);
22294
- const load = useUnitStore((s) => s.load);
21781
+ const load2 = useUnitStore((s) => s.load);
22295
21782
  const [unbound, setUnbound] = React133.useState(null);
22296
21783
  const [bindEveryone, setBindEveryone] = React133.useState(true);
22297
21784
  const [pending2, setPending] = React133.useState(null);
@@ -22321,7 +21808,7 @@ function UnitModeCard() {
22321
21808
  await setUnitModeRemote(org.id, on);
22322
21809
  setMode(on);
22323
21810
  emitDataChanged();
22324
- await load(org.id, user?.id);
21811
+ await load2(org.id, user?.id);
22325
21812
  toast.success(on ? "Gest\xE3o por unidades ligada" : "Gest\xE3o por unidades desligada");
22326
21813
  } catch (err) {
22327
21814
  toast.error("N\xE3o deu para mudar", { description: err?.message });
@@ -22439,11 +21926,11 @@ function ConnectedCompanySettings() {
22439
21926
  const handleSave = async (data) => {
22440
21927
  if (!adapter || !currentOrg) return;
22441
21928
  try {
22442
- const currentSettings = toTenantSettings(currentOrg.settings);
21929
+ const raw = currentOrg.settings && typeof currentOrg.settings === "object" ? currentOrg.settings : {};
22443
21930
  const updated = await adapter.updateOrg(currentOrg.id, {
22444
21931
  name: data.name,
22445
21932
  settings: {
22446
- ...currentSettings,
21933
+ ...raw,
22447
21934
  timezone: data.timezone,
22448
21935
  currency: data.currency
22449
21936
  }
@@ -22569,11 +22056,11 @@ function UserProfile({ user, onSave, onAvatarChange }) {
22569
22056
  ] }) })
22570
22057
  ] }) });
22571
22058
  }
22572
- function client2() {
22059
+ function client() {
22573
22060
  return getSupabaseClientOptional();
22574
22061
  }
22575
22062
  async function fetchMyPersonRecord(tenantId2, userId) {
22576
- const db2 = client2();
22063
+ const db2 = client();
22577
22064
  if (!db2) return null;
22578
22065
  const { data, error } = await db2.from("v_team_members").select("person_id").eq("tenant_id", tenantId2).eq("user_id", userId).maybeSingle();
22579
22066
  if (error || !data?.person_id) return null;
@@ -22582,7 +22069,7 @@ async function fetchMyPersonRecord(tenantId2, userId) {
22582
22069
  return { id: person.id, name: person.name ?? "", kind: person.kind ?? null };
22583
22070
  }
22584
22071
  async function findMyPersonCandidate(tenantId2, email, staffKinds) {
22585
- const db2 = client2();
22072
+ const db2 = client();
22586
22073
  if (!db2 || !email || staffKinds.length === 0) return null;
22587
22074
  const { data, error } = await db2.from("people").select("id, name, kind, email").eq("tenant_id", tenantId2).in("kind", staffKinds).ilike("email", email).limit(2);
22588
22075
  if (error || !data || data.length !== 1) return null;
@@ -22592,13 +22079,13 @@ async function findMyPersonCandidate(tenantId2, email, staffKinds) {
22592
22079
  return { id: candidate.id, name: candidate.name ?? "", kind: candidate.kind ?? null };
22593
22080
  }
22594
22081
  async function linkPersonToLogin(tenantId2, userId, personId) {
22595
- const db2 = client2();
22082
+ const db2 = client();
22596
22083
  if (!db2) throw new Error("sem conex\xE3o");
22597
22084
  const { error } = await db2.rpc("people_link_membership", { p_person: personId, p_user: userId });
22598
22085
  if (error) throw error;
22599
22086
  }
22600
22087
  async function fetchMyPersonId(tenantId2, userId) {
22601
- const db2 = client2();
22088
+ const db2 = client();
22602
22089
  if (!db2) return null;
22603
22090
  const { data, error } = await db2.from("v_team_members").select("person_id").eq("tenant_id", tenantId2).eq("user_id", userId).maybeSingle();
22604
22091
  if (error) return null;
@@ -22621,7 +22108,7 @@ function useMyPersonId(enabled = true) {
22621
22108
  return personId;
22622
22109
  }
22623
22110
  async function fetchPersonAccess(personId) {
22624
- const db2 = client2();
22111
+ const db2 = client();
22625
22112
  if (!db2) return null;
22626
22113
  const { data, error } = await db2.from("v_team_members").select("id, user_id, role, created_at").eq("person_id", personId).maybeSingle();
22627
22114
  if (error || !data) return null;
@@ -22636,7 +22123,7 @@ async function fetchPersonAccess(personId) {
22636
22123
  };
22637
22124
  }
22638
22125
  async function setPersonEmail(personId, email) {
22639
- const db2 = client2();
22126
+ const db2 = client();
22640
22127
  if (!db2) throw new Error("sem conex\xE3o");
22641
22128
  const { error } = await db2.from("people").update({ email }).eq("id", personId);
22642
22129
  if (error) throw error;
@@ -22673,15 +22160,15 @@ function MyWorkspaceCard() {
22673
22160
  const [linking, setLinking] = React133.useState(false);
22674
22161
  const orgId = currentOrg?.id;
22675
22162
  const userId = user?.id;
22676
- const load = React133.useCallback(async () => {
22163
+ const load2 = React133.useCallback(async () => {
22677
22164
  if (!orgId || !userId) return;
22678
22165
  const linked = await fetchMyPersonRecord(orgId, userId);
22679
22166
  setPerson(linked);
22680
22167
  setCandidate(linked ? null : await findMyPersonCandidate(orgId, user?.email, staffKinds));
22681
22168
  }, [orgId, userId, user?.email, staffKinds]);
22682
22169
  React133.useEffect(() => {
22683
- void load();
22684
- }, [load]);
22170
+ void load2();
22171
+ }, [load2]);
22685
22172
  if (!currentOrg) return null;
22686
22173
  const myRole = members.find((m) => m.userId === userId)?.profileName;
22687
22174
  async function link() {
@@ -22690,7 +22177,7 @@ function MyWorkspaceCard() {
22690
22177
  try {
22691
22178
  await linkPersonToLogin(orgId, userId, candidate.id);
22692
22179
  toast.success(`Login ligado ao cadastro de ${candidate.name}`);
22693
- await load();
22180
+ await load2();
22694
22181
  } catch (err) {
22695
22182
  toast.error("S\xF3 um administrador pode ligar um login a um cadastro", { description: err?.message });
22696
22183
  } finally {
@@ -22794,9 +22281,9 @@ function useUserLabel(userId) {
22794
22281
  const [resolved, setResolved] = useState(null);
22795
22282
  useEffect(() => {
22796
22283
  if (!userId || fromMembers) return;
22797
- const cached3 = userLabelCache.get(userId);
22798
- if (cached3 !== void 0) {
22799
- setResolved(cached3);
22284
+ const cached2 = userLabelCache.get(userId);
22285
+ if (cached2 !== void 0) {
22286
+ setResolved(cached2);
22800
22287
  return;
22801
22288
  }
22802
22289
  let alive = true;
@@ -22982,15 +22469,15 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
22982
22469
  const [deleting, setDeleting] = useState(null);
22983
22470
  const ownerId = record?.id;
22984
22471
  const db2 = () => getSupabaseClientOptional();
22985
- const load = useCallback(async () => {
22986
- const client3 = db2();
22987
- if (!client3 || !ownerId) {
22472
+ const load2 = useCallback(async () => {
22473
+ const client2 = db2();
22474
+ if (!client2 || !ownerId) {
22988
22475
  setLoading(false);
22989
22476
  return;
22990
22477
  }
22991
22478
  setLoading(true);
22992
22479
  setError(null);
22993
- let q = client3.from("addresses").select("*").eq("owner_id", ownerId);
22480
+ let q = client2.from("addresses").select("*").eq("owner_id", ownerId);
22994
22481
  if (ownerType !== "person") q = q.eq("owner_type", ownerType);
22995
22482
  const { data, error: err } = await q.order("is_default", { ascending: false });
22996
22483
  if (err) setError(err.message);
@@ -22998,8 +22485,8 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
22998
22485
  setLoading(false);
22999
22486
  }, [ownerId, ownerType]);
23000
22487
  useEffect(() => {
23001
- void load();
23002
- }, [load]);
22488
+ void load2();
22489
+ }, [load2]);
23003
22490
  const openCreate = () => {
23004
22491
  setEditing(null);
23005
22492
  setForm(single ? { ...EMPTY_FORM, kind: "main", is_default: true } : EMPTY_FORM);
@@ -23089,8 +22576,8 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
23089
22576
  }
23090
22577
  };
23091
22578
  const handleSave = async () => {
23092
- const client3 = db2();
23093
- if (!client3 || !ownerId || !canSave) return;
22579
+ const client2 = db2();
22580
+ if (!client2 || !ownerId || !canSave) return;
23094
22581
  const tenantId2 = getActiveTenantId();
23095
22582
  if (!tenantId2) {
23096
22583
  toast.error(t("crud.archetype.addresses.noTenant"));
@@ -23116,12 +22603,12 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
23116
22603
  longitude: coordPair(form).lng
23117
22604
  };
23118
22605
  if (form.is_default) {
23119
- let q = client3.from("addresses").update({ is_default: false }).eq("owner_id", ownerId).eq("owner_type", ownerType).eq("kind", form.kind).eq("is_default", true);
22606
+ let q = client2.from("addresses").update({ is_default: false }).eq("owner_id", ownerId).eq("owner_type", ownerType).eq("kind", form.kind).eq("is_default", true);
23120
22607
  if (editing) q = q.neq("id", editing.id);
23121
22608
  const { error: clearErr } = await q;
23122
22609
  if (clearErr) throw clearErr;
23123
22610
  }
23124
- const { error: err } = editing ? await client3.from("addresses").update(values).eq("id", editing.id) : await client3.from("addresses").insert({
22611
+ const { error: err } = editing ? await client2.from("addresses").update(values).eq("id", editing.id) : await client2.from("addresses").insert({
23125
22612
  ...values,
23126
22613
  tenant_id: tenantId2,
23127
22614
  owner_type: ownerType,
@@ -23129,7 +22616,7 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
23129
22616
  });
23130
22617
  if (err) throw err;
23131
22618
  setFormOpen(false);
23132
- await load();
22619
+ await load2();
23133
22620
  toast.success(editing ? t("crud.archetype.addresses.updated") : t("crud.archetype.addresses.created"));
23134
22621
  } catch (e) {
23135
22622
  toast.error(t("crud.archetype.addresses.saveFailed"), { description: e?.message });
@@ -23138,15 +22625,15 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
23138
22625
  }
23139
22626
  };
23140
22627
  const handleDelete = async () => {
23141
- const client3 = db2();
23142
- if (!client3 || !deleting) return;
23143
- const { error: err } = await client3.from("addresses").delete().eq("id", deleting.id);
22628
+ const client2 = db2();
22629
+ if (!client2 || !deleting) return;
22630
+ const { error: err } = await client2.from("addresses").delete().eq("id", deleting.id);
23144
22631
  setDeleting(null);
23145
22632
  if (err) {
23146
22633
  toast.error(t("crud.archetype.addresses.deleteFailed"), { description: err.message });
23147
22634
  return;
23148
22635
  }
23149
- await load();
22636
+ await load2();
23150
22637
  toast.success(t("crud.archetype.addresses.deleted"));
23151
22638
  };
23152
22639
  if (loading) {
@@ -23423,28 +22910,28 @@ function PayeeAccountsSection({
23423
22910
  const canEdit = can("financial", "edit");
23424
22911
  const canDelete = can("financial", "delete");
23425
22912
  const db2 = () => getSupabaseClientOptional();
23426
- const load = useCallback(async () => {
23427
- const client3 = db2();
23428
- if (!client3 || !ownerId) {
22913
+ const load2 = useCallback(async () => {
22914
+ const client2 = db2();
22915
+ if (!client2 || !ownerId) {
23429
22916
  setLoading(false);
23430
22917
  return;
23431
22918
  }
23432
22919
  setLoading(true);
23433
22920
  setError(null);
23434
- const { data, error: err } = await client3.from("payee_accounts").select("*").eq("owner_type", ownerType).eq("owner_id", ownerId).order("is_default", { ascending: false });
22921
+ const { data, error: err } = await client2.from("payee_accounts").select("*").eq("owner_type", ownerType).eq("owner_id", ownerId).order("is_default", { ascending: false });
23435
22922
  if (err) setError(err.message);
23436
22923
  else setRows(data ?? []);
23437
22924
  setLoading(false);
23438
22925
  }, [ownerId, ownerType]);
23439
22926
  useEffect(() => {
23440
- void load();
23441
- }, [load]);
22927
+ void load2();
22928
+ }, [load2]);
23442
22929
  const set = (key, value) => setForm((prev) => ({ ...prev, [key]: value }));
23443
22930
  const canSave = !!blank(form.accountNumber ?? null) || !!blank(form.pixKey ?? null);
23444
22931
  const handleSave = async () => {
23445
- const client3 = db2();
22932
+ const client2 = db2();
23446
22933
  const tenantId2 = getActiveTenantId();
23447
- if (!client3 || !ownerId || !tenantId2 || !canSave) return;
22934
+ if (!client2 || !ownerId || !tenantId2 || !canSave) return;
23448
22935
  setSaving(true);
23449
22936
  try {
23450
22937
  const pix = form.method === "pix";
@@ -23465,9 +22952,9 @@ function PayeeAccountsSection({
23465
22952
  holder_document: b("holderDocument")
23466
22953
  };
23467
22954
  if (form.is_default) {
23468
- await client3.from("payee_accounts").update({ is_default: false }).eq("owner_type", ownerType).eq("owner_id", ownerId);
22955
+ await client2.from("payee_accounts").update({ is_default: false }).eq("owner_type", ownerType).eq("owner_id", ownerId);
23469
22956
  }
23470
- const { error: err } = editing ? await client3.from("payee_accounts").update(values).eq("id", editing.id) : await client3.from("payee_accounts").insert({
22957
+ const { error: err } = editing ? await client2.from("payee_accounts").update(values).eq("id", editing.id) : await client2.from("payee_accounts").insert({
23471
22958
  ...values,
23472
22959
  tenant_id: tenantId2,
23473
22960
  owner_type: ownerType,
@@ -23475,7 +22962,7 @@ function PayeeAccountsSection({
23475
22962
  });
23476
22963
  if (err) throw err;
23477
22964
  setFormOpen(false);
23478
- await load();
22965
+ await load2();
23479
22966
  toast.success(t("crud.archetype.payeeAccounts.saved"));
23480
22967
  } catch (e) {
23481
22968
  toast.error(t("crud.archetype.payeeAccounts.saveFailed"), { description: e?.message });
@@ -23484,15 +22971,15 @@ function PayeeAccountsSection({
23484
22971
  }
23485
22972
  };
23486
22973
  const handleDelete = async () => {
23487
- const client3 = db2();
23488
- if (!client3 || !deleting) return;
23489
- const { error: err } = await client3.from("payee_accounts").delete().eq("id", deleting.id);
22974
+ const client2 = db2();
22975
+ if (!client2 || !deleting) return;
22976
+ const { error: err } = await client2.from("payee_accounts").delete().eq("id", deleting.id);
23490
22977
  setDeleting(null);
23491
22978
  if (err) {
23492
22979
  toast.error(t("crud.archetype.payeeAccounts.deleteFailed"), { description: err.message });
23493
22980
  return;
23494
22981
  }
23495
- await load();
22982
+ await load2();
23496
22983
  toast.success(t("crud.archetype.payeeAccounts.deleted"));
23497
22984
  };
23498
22985
  if (!canRead) return null;
@@ -23783,7 +23270,7 @@ function CrudRecordModal({
23783
23270
  onSaved,
23784
23271
  entityDef,
23785
23272
  mode = "edit",
23786
- load,
23273
+ load: load2,
23787
23274
  initialData,
23788
23275
  save,
23789
23276
  title,
@@ -23800,14 +23287,14 @@ function CrudRecordModal({
23800
23287
  React133.useEffect(() => {
23801
23288
  if (!open) return;
23802
23289
  setError(null);
23803
- if (mode === "create" || !load) {
23290
+ if (mode === "create" || !load2) {
23804
23291
  setRecord(initialData ?? {});
23805
23292
  setLoading(false);
23806
23293
  return;
23807
23294
  }
23808
23295
  let cancelled = false;
23809
23296
  setLoading(true);
23810
- load().then((found) => {
23297
+ load2().then((found) => {
23811
23298
  if (!cancelled) setRecord(found);
23812
23299
  }).catch((err) => {
23813
23300
  if (!cancelled) setError(errorMessage(err));
@@ -23938,6 +23425,57 @@ function useRelationOptions(r) {
23938
23425
  const labelFor2 = (value) => options.find((o) => o.value === String(value))?.label ?? "";
23939
23426
  return { options, loading, labelFor: labelFor2 };
23940
23427
  }
23428
+ async function createOption(r, label3) {
23429
+ const supabase = getSupabaseClientOptional();
23430
+ if (!supabase) throw new Error("no client");
23431
+ const valueField = r.valueField ?? "id";
23432
+ const row = {
23433
+ ...r.filter ?? {},
23434
+ ...r.create?.defaults ?? {},
23435
+ [(r.labelFields ?? [r.labelField ?? "name"])[0]]: label3
23436
+ };
23437
+ if (r.tenantScoped !== false) row.tenant_id = getActiveTenantId();
23438
+ const { data, error } = await (r.schema ? supabase.schema(r.schema) : supabase).from(r.table).insert(row).select(valueField).single();
23439
+ if (error) throw error;
23440
+ invalidateRelationOptions();
23441
+ return String(data[valueField]);
23442
+ }
23443
+ function CreatableRelationSelect({ relation, value, onChange, required, placeholder }) {
23444
+ const [created, setCreated] = useState([]);
23445
+ const { options } = useRelationOptions(relation);
23446
+ const all = [...options, ...created.filter((c) => !options.some((o) => o.value === c.value))];
23447
+ return /* @__PURE__ */ jsx(
23448
+ SearchSelect,
23449
+ {
23450
+ value: value ? String(value) : void 0,
23451
+ displayValue: all.find((o) => o.value === String(value))?.label,
23452
+ required,
23453
+ placeholder,
23454
+ minChars: 0,
23455
+ noResultsLabel: "Nada encontrado",
23456
+ searchingLabel: "Buscando\u2026",
23457
+ createLabel: "Cadastrar",
23458
+ clearLabel: "Limpar",
23459
+ allowCreate: true,
23460
+ onSearch: (query) => {
23461
+ const q = query.trim().toLowerCase();
23462
+ return all.filter((o) => !q || o.label.toLowerCase().includes(q)).map((o) => ({ id: o.value, label: o.label }));
23463
+ },
23464
+ onChange: (id) => onChange(id || null),
23465
+ onCreate: async (query) => {
23466
+ const label3 = query.trim();
23467
+ if (!label3) return;
23468
+ try {
23469
+ const id = await createOption(relation, label3);
23470
+ setCreated((prev) => [...prev, { value: id, label: label3 }]);
23471
+ onChange(id);
23472
+ } catch (err) {
23473
+ toast.error(describeError(err));
23474
+ }
23475
+ }
23476
+ }
23477
+ );
23478
+ }
23941
23479
  function RelationSelect({
23942
23480
  relation,
23943
23481
  value,
@@ -23947,6 +23485,11 @@ function RelationSelect({
23947
23485
  placeholder
23948
23486
  }) {
23949
23487
  const { options, loading } = useRelationOptions(relation);
23488
+ const can = usePermissionOptional();
23489
+ const mayCreate = !!relation?.create && (!relation.create.permission || can(relation.create.permission.feature, relation.create.permission.action ?? "edit"));
23490
+ if (relation && mayCreate) {
23491
+ return /* @__PURE__ */ jsx(CreatableRelationSelect, { relation, value, onChange, required, placeholder });
23492
+ }
23950
23493
  return /* @__PURE__ */ jsxs(
23951
23494
  Select,
23952
23495
  {
@@ -24052,7 +23595,7 @@ function RelatedSection({ parentId, related, compact }) {
24052
23595
  const [error, setError] = React133.useState(null);
24053
23596
  const [adding, setAdding] = React133.useState(false);
24054
23597
  const [draft, setDraft] = React133.useState(null);
24055
- const load = React133.useCallback(async () => {
23598
+ const load2 = React133.useCallback(async () => {
24056
23599
  if (orfa) {
24057
23600
  setLoading(false);
24058
23601
  return;
@@ -24069,8 +23612,8 @@ function RelatedSection({ parentId, related, compact }) {
24069
23612
  }
24070
23613
  }, [provider2, orfa]);
24071
23614
  React133.useEffect(() => {
24072
- void load();
24073
- }, [load]);
23615
+ void load2();
23616
+ }, [load2]);
24074
23617
  const guardadas = React133.useRef([]);
24075
23618
  guardadas.current = rows;
24076
23619
  React133.useEffect(() => {
@@ -24185,7 +23728,7 @@ function RelatedSection({ parentId, related, compact }) {
24185
23728
  try {
24186
23729
  await provider2.create(pronto);
24187
23730
  setDraft(null);
24188
- await load();
23731
+ await load2();
24189
23732
  } catch (e) {
24190
23733
  toast.error(errorMessage(e));
24191
23734
  } finally {
@@ -24202,7 +23745,7 @@ function RelatedSection({ parentId, related, compact }) {
24202
23745
  }
24203
23746
  try {
24204
23747
  await provider2.create(copia);
24205
- await load();
23748
+ await load2();
24206
23749
  } catch (e) {
24207
23750
  toast.error(errorMessage(e));
24208
23751
  }
@@ -24422,7 +23965,7 @@ function RelatedSection({ parentId, related, compact }) {
24422
23965
  mode: "create",
24423
23966
  save: async (data) => {
24424
23967
  await provider2.create(data);
24425
- await load();
23968
+ await load2();
24426
23969
  },
24427
23970
  onSaved: () => setAdding(false)
24428
23971
  }
@@ -25166,10 +24709,10 @@ function useSuggestions(table) {
25166
24709
  const [tags, setTags] = useState(() => table ? suggestionCache.get(table) ?? [] : []);
25167
24710
  useEffect(() => {
25168
24711
  if (!table || suggestionCache.has(table)) return;
25169
- const client3 = getSupabaseClientOptional();
25170
- if (!client3) return;
24712
+ const client2 = getSupabaseClientOptional();
24713
+ if (!client2) return;
25171
24714
  let alive = true;
25172
- void client3.from(table).select("tags").not("tags", "is", null).limit(500).then(({ data }) => {
24715
+ void client2.from(table).select("tags").not("tags", "is", null).limit(500).then(({ data }) => {
25173
24716
  const all = /* @__PURE__ */ new Set();
25174
24717
  for (const r of data ?? []) for (const t of r.tags ?? []) all.add(t);
25175
24718
  const list = [...all].sort();
@@ -28605,17 +28148,17 @@ function PersonAvailabilityTab({ item }) {
28605
28148
  const [busy, setBusy] = React133.useState(false);
28606
28149
  const [availabilityReady, setAvailabilityReady] = React133.useState(true);
28607
28150
  const db2 = () => getSupabaseClientOptional();
28608
- const load = React133.useCallback(async () => {
28609
- const client3 = db2();
28610
- if (!client3 || !personId) {
28151
+ const load2 = React133.useCallback(async () => {
28152
+ const client2 = db2();
28153
+ if (!client2 || !personId) {
28611
28154
  setLoading(false);
28612
28155
  return;
28613
28156
  }
28614
28157
  setLoading(true);
28615
28158
  try {
28616
28159
  const [{ data: unitRows, error: unitError }, { data: unitIds, error: grantError }] = await Promise.all([
28617
- client3.from("v_units").select("id,name,city").eq("is_active", true).order("name"),
28618
- client3.rpc("people_available_unit_ids", { p_person: personId })
28160
+ client2.from("v_units").select("id,name,city").eq("is_active", true).order("name"),
28161
+ client2.rpc("people_available_unit_ids", { p_person: personId })
28619
28162
  ]);
28620
28163
  if (unitError) throw unitError;
28621
28164
  setUnits(unitRows ?? []);
@@ -28635,14 +28178,14 @@ function PersonAvailabilityTab({ item }) {
28635
28178
  }
28636
28179
  }, [personId]);
28637
28180
  React133.useEffect(() => {
28638
- void load();
28639
- }, [load]);
28181
+ void load2();
28182
+ }, [load2]);
28640
28183
  async function makeOrganizationWide() {
28641
- const client3 = db2();
28642
- if (!client3 || !personId || busy) return;
28184
+ const client2 = db2();
28185
+ if (!client2 || !personId || busy) return;
28643
28186
  setBusy(true);
28644
28187
  try {
28645
- const { error } = await client3.rpc("people_set_available_units", {
28188
+ const { error } = await client2.rpc("people_set_available_units", {
28646
28189
  p_person: personId,
28647
28190
  p_unit_ids: []
28648
28191
  });
@@ -28656,19 +28199,19 @@ function PersonAvailabilityTab({ item }) {
28656
28199
  }
28657
28200
  }
28658
28201
  async function toggle(unitId, enabled) {
28659
- const client3 = db2();
28660
- if (!client3 || !personId || busy) return;
28202
+ const client2 = db2();
28203
+ if (!client2 || !personId || busy) return;
28661
28204
  setBusy(true);
28662
28205
  try {
28663
28206
  const next = new Set(selected);
28664
28207
  if (enabled) next.add(unitId);
28665
28208
  else next.delete(unitId);
28666
- const { error } = await client3.rpc("people_set_available_units", {
28209
+ const { error } = await client2.rpc("people_set_available_units", {
28667
28210
  p_person: personId,
28668
28211
  p_unit_ids: Array.from(next)
28669
28212
  });
28670
28213
  if (error) throw error;
28671
- await load();
28214
+ await load2();
28672
28215
  toast.success("Unidades atualizadas.");
28673
28216
  } catch (error) {
28674
28217
  toast.error("N\xE3o foi poss\xEDvel atualizar as unidades", { description: error?.message });
@@ -28713,7 +28256,7 @@ function PersonAvailabilityTab({ item }) {
28713
28256
  ] }) });
28714
28257
  }
28715
28258
  var ScheduleEditor2 = React133__default.lazy(
28716
- () => import('./ScheduleEditor-ZEG6PG3Z.js').then((m) => ({ default: m.ScheduleEditor }))
28259
+ () => import('./ScheduleEditor-MNHZCQIG.js').then((m) => ({ default: m.ScheduleEditor }))
28717
28260
  );
28718
28261
  var PersonTimeline2 = React133__default.lazy(
28719
28262
  () => import('./timeline-LECYQ4IA.js').then((m) => ({ default: m.PersonTimeline }))
@@ -30047,7 +29590,7 @@ function MyRecordPanel() {
30047
29590
  const members = useOrganizationStore((s) => s.members);
30048
29591
  const myRole = members.find((m) => m.userId === userId)?.profileName;
30049
29592
  const [state, setState] = React133.useState({ status: "loading" });
30050
- const load = React133.useCallback(async () => {
29593
+ const load2 = React133.useCallback(async () => {
30051
29594
  if (!orgId || !userId) return;
30052
29595
  const person = await dedup(`self:record:${orgId}:${userId}`, () => fetchMyPersonRecord(orgId, userId));
30053
29596
  if (!person) return setState({ status: "none" });
@@ -30065,8 +29608,8 @@ function MyRecordPanel() {
30065
29608
  }
30066
29609
  }, [orgId, userId]);
30067
29610
  React133.useEffect(() => {
30068
- void load();
30069
- }, [load]);
29611
+ void load2();
29612
+ }, [load2]);
30070
29613
  const changePhoto = React133.useCallback(async (file) => {
30071
29614
  if (state.status !== "ready") return;
30072
29615
  const supabase = getFayzSupabaseClientOptional();
@@ -31137,13 +30680,13 @@ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["READY", "ERROR", "ABANDONED",
31137
30680
  function ProjectsSettings() {
31138
30681
  const currentOrgId = useOrganizationStore((s) => s.currentOrg?.id);
31139
30682
  const projects = useFayzProjectsStore((s) => s.projects);
31140
- const load = useFayzProjectsStore((s) => s.load);
30683
+ const load2 = useFayzProjectsStore((s) => s.load);
31141
30684
  const refresh = useFayzProjectsStore((s) => s.refresh);
31142
30685
  const [linking, setLinking] = React133.useState(false);
31143
30686
  const connected = isPlatformConnected();
31144
30687
  React133.useEffect(() => {
31145
- void load(currentOrgId);
31146
- }, [currentOrgId, load]);
30688
+ void load2(currentOrgId);
30689
+ }, [currentOrgId, load2]);
31147
30690
  React133.useEffect(() => {
31148
30691
  if (!connected || projects.length === 0) return;
31149
30692
  let cancelled = false;
@@ -31892,29 +31435,29 @@ function ModulesSettings({ hidden = [], onToggle, permits, busy, catalog = [] })
31892
31435
  }
31893
31436
 
31894
31437
  // src/app/app-config-cache.ts
31895
- var STORAGE_KEY5 = "fayz:app-config";
31896
- var VERSION2 = 1;
31438
+ var STORAGE_KEY3 = "fayz:app-config";
31439
+ var VERSION = 1;
31897
31440
  var APP_CONFIG_TTL_MS = 5 * 60 * 1e3;
31898
- var MAX_AGE_MS2 = 24 * 60 * 60 * 1e3;
31899
- var MAX_BYTES2 = 256 * 1024;
31900
- function storage2() {
31441
+ var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
31442
+ var MAX_BYTES = 256 * 1024;
31443
+ function storage() {
31901
31444
  try {
31902
31445
  return globalThis.localStorage ?? null;
31903
31446
  } catch {
31904
31447
  return null;
31905
31448
  }
31906
31449
  }
31907
- var keyFor = (tenantId2) => `${STORAGE_KEY5}:${tenantId2}`;
31450
+ var keyFor = (tenantId2) => `${STORAGE_KEY3}:${tenantId2}`;
31908
31451
  function readAppConfigSnapshot(tenantId2) {
31909
- const store = storage2();
31452
+ const store = storage();
31910
31453
  if (!store) return null;
31911
31454
  try {
31912
31455
  const raw = store.getItem(keyFor(tenantId2));
31913
31456
  if (!raw) return null;
31914
31457
  const snap = JSON.parse(raw);
31915
- if (snap.version !== VERSION2 || snap.tenantId !== tenantId2) return null;
31458
+ if (snap.version !== VERSION || snap.tenantId !== tenantId2) return null;
31916
31459
  const age = Date.now() - snap.savedAt;
31917
- if (age > MAX_AGE_MS2) {
31460
+ if (age > MAX_AGE_MS) {
31918
31461
  store.removeItem(keyFor(tenantId2));
31919
31462
  return null;
31920
31463
  }
@@ -31924,17 +31467,17 @@ function readAppConfigSnapshot(tenantId2) {
31924
31467
  }
31925
31468
  }
31926
31469
  function writeAppConfigSnapshot(tenantId2, config) {
31927
- const store = storage2();
31470
+ const store = storage();
31928
31471
  if (!store) return;
31929
31472
  try {
31930
- const payload = JSON.stringify({ version: VERSION2, tenantId: tenantId2, savedAt: Date.now(), config });
31931
- if (payload.length > MAX_BYTES2) return;
31473
+ const payload = JSON.stringify({ version: VERSION, tenantId: tenantId2, savedAt: Date.now(), config });
31474
+ if (payload.length > MAX_BYTES) return;
31932
31475
  store.setItem(keyFor(tenantId2), payload);
31933
31476
  } catch {
31934
31477
  }
31935
31478
  }
31936
31479
  function clearAppConfigSnapshot(tenantId2) {
31937
- const store = storage2();
31480
+ const store = storage();
31938
31481
  if (!store) return;
31939
31482
  try {
31940
31483
  if (tenantId2) {
@@ -31943,7 +31486,7 @@ function clearAppConfigSnapshot(tenantId2) {
31943
31486
  }
31944
31487
  for (let i = store.length - 1; i >= 0; i -= 1) {
31945
31488
  const key = store.key(i);
31946
- if (key?.startsWith(`${STORAGE_KEY5}:`)) store.removeItem(key);
31489
+ if (key?.startsWith(`${STORAGE_KEY3}:`)) store.removeItem(key);
31947
31490
  }
31948
31491
  } catch {
31949
31492
  }
@@ -32590,19 +32133,19 @@ function UnitIndicator({
32590
32133
  const reachable = myUnitIds.length > 0 ? myUnitIds : units.filter((u) => u.kind !== "region").map((u) => u.id);
32591
32134
  if (reachable.length === 0) return null;
32592
32135
  const current2 = activeUnitId ? byId[activeUnitId] : void 0;
32593
- const text2 = current2?.name ?? (reachable.length > 1 ? "Todas as unidades" : byId[reachable[0]]?.name ?? "");
32594
- if (!text2) return null;
32136
+ const text3 = current2?.name ?? (reachable.length > 1 ? "Todas as unidades" : byId[reachable[0]]?.name ?? "");
32137
+ if (!text3) return null;
32595
32138
  if (collapsed) {
32596
- return /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-0.5", title: text2, children: /* @__PURE__ */ jsx(Building2, { className: "h-3 w-3 text-sidebar-muted" }) });
32139
+ return /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-0.5", title: text3, children: /* @__PURE__ */ jsx(Building2, { className: "h-3 w-3 text-sidebar-muted" }) });
32597
32140
  }
32598
32141
  const body = /* @__PURE__ */ jsxs(Fragment, { children: [
32599
32142
  /* @__PURE__ */ jsx(Building2, { className: "h-3 w-3 shrink-0 text-sidebar-muted/70" }),
32600
- /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-[11px] leading-none text-sidebar-muted/90", children: text2 })
32143
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-[11px] leading-none text-sidebar-muted/90", children: text3 })
32601
32144
  ] });
32602
32145
  if (inline) {
32603
- return /* @__PURE__ */ jsx("span", { className: "mt-0.5 flex min-w-0 items-center gap-1", title: text2, children: body });
32146
+ return /* @__PURE__ */ jsx("span", { className: "mt-0.5 flex min-w-0 items-center gap-1", title: text3, children: body });
32604
32147
  }
32605
- return /* @__PURE__ */ jsx("div", { className: "flex min-w-0 items-center gap-1.5 pl-12 pr-1.5 pb-1", title: text2, children: body });
32148
+ return /* @__PURE__ */ jsx("div", { className: "flex min-w-0 items-center gap-1.5 pl-12 pr-1.5 pb-1", title: text3, children: body });
32606
32149
  }
32607
32150
  var UNIT_DETAIL_ZONES = {
32608
32151
  rooms: "unit.detail.rooms",
@@ -34370,7 +33913,7 @@ var CommandPalette = React133.lazy(
34370
33913
  () => import('./CommandPalette-B5PMQFDG.js').then((m) => ({ default: m.CommandPalette }))
34371
33914
  );
34372
33915
  var SubscriptionPage = React133.lazy(
34373
- () => import('./SubscriptionPage-VXZ37WZZ.js').then((m) => ({ default: m.SubscriptionPage }))
33916
+ () => import('./SubscriptionPage-JWWS44SE.js').then((m) => ({ default: m.SubscriptionPage }))
34374
33917
  );
34375
33918
  function WorkspaceSwitcher({
34376
33919
  variant = "sidebar",
@@ -36720,11 +36263,14 @@ function Badge26({ badge, className = "" }) {
36720
36263
  /* @__PURE__ */ jsx("span", { className: `inline-flex shrink-0 items-center rounded-full px-2 py-0.5 text-xs font-medium ${TONE_CLASS[badge.tone ?? "muted"]} ${className}`, children: badge.label })
36721
36264
  );
36722
36265
  }
36723
- function OrderDetailBlock({ title, hint, children }) {
36266
+ function OrderDetailBlock({ title, hint, actions, children }) {
36724
36267
  return /* @__PURE__ */ jsxs("div", { className: "rounded-card border bg-card p-4", children: [
36725
- (title || hint) && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
36726
- title && /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: title }),
36727
- hint && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: hint })
36268
+ (title || hint || actions) && /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-start justify-between gap-2", children: [
36269
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
36270
+ title && /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: title }),
36271
+ hint && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: hint })
36272
+ ] }),
36273
+ actions && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: actions })
36728
36274
  ] }),
36729
36275
  children
36730
36276
  ] });
@@ -36783,7 +36329,8 @@ function OrderDetailView(props) {
36783
36329
  banner,
36784
36330
  embedded
36785
36331
  } = props;
36786
- const actionSlots = Math.max(0, ...items.map((it) => it.actions?.length ?? 0));
36332
+ const itemMenu = !!props.itemActionsMenu;
36333
+ const actionSlots = itemMenu ? items.some((it) => (it.actions?.length ?? 0) > 0) ? 1 : 0 : Math.max(0, ...items.map((it) => it.actions?.length ?? 0));
36787
36334
  const hasBadges = badges.length > 0 || !!props.badgesNode;
36788
36335
  const titleNode = hasBadges ? /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
36789
36336
  /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: title }),
@@ -36825,7 +36372,8 @@ function OrderDetailView(props) {
36825
36372
  /* @__PURE__ */ jsx(Thumbnail, { src: item.imageUrl, size: "sm", icon: item.icon }),
36826
36373
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
36827
36374
  /* @__PURE__ */ jsx("p", { className: cn$1("truncate text-sm font-medium", item.struck && "text-muted-foreground line-through"), children: item.name }),
36828
- item.description ? /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null
36375
+ item.description ? /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null,
36376
+ item.note ? /* @__PURE__ */ jsx("p", { className: "truncate text-xs", children: item.note }) : null
36829
36377
  ] }),
36830
36378
  item.account && /* @__PURE__ */ jsx(Badge, { variant: "secondary", title: item.account, className: "fz-tight-hide max-w-[12rem] shrink-0 truncate", children: item.account }),
36831
36379
  /* @__PURE__ */ jsxs("span", { className: cn$1("shrink-0 text-xs text-muted-foreground tabular-nums", item.struck && "line-through"), children: [
@@ -36841,26 +36389,42 @@ function OrderDetailView(props) {
36841
36389
  // ficam visíveis o tempo todo (`pointer: coarse`).
36842
36390
  // Every row reserves the widest row's slot, so a line with fewer
36843
36391
  // actions (a cancelled one has none) keeps its numbers in the column.
36844
- /* @__PURE__ */ jsx(
36392
+ /* @__PURE__ */ jsxs(
36845
36393
  "span",
36846
36394
  {
36847
- style: { width: actionSlots * 28 + (actionSlots - 1) * 2 },
36395
+ style: { width: itemMenu ? 36 : actionSlots * 28 + (actionSlots - 1) * 2 },
36848
36396
  className: "flex shrink-0 items-center justify-end gap-0.5 opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100 [@media(pointer:coarse)]:opacity-100",
36849
- children: (item.actions ?? []).map((a) => {
36850
- const Icon = a.icon;
36851
- return /* @__PURE__ */ jsx(Hint, { label: a.label, children: /* @__PURE__ */ jsx(
36852
- Button,
36397
+ children: [
36398
+ itemMenu && /* @__PURE__ */ jsx(
36399
+ RowActions,
36853
36400
  {
36854
- type: "button",
36855
- variant: "ghost",
36856
- size: "icon",
36857
- className: "h-7 w-7",
36858
- "aria-label": a.label,
36859
- onClick: () => a.onSelect(item),
36860
- children: Icon ? /* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-3.5 w-3.5" })
36401
+ inlineLimit: 0,
36402
+ actions: (item.actions ?? []).map((a) => ({
36403
+ id: a.id,
36404
+ label: a.label,
36405
+ icon: a.icon,
36406
+ intent: a.intent,
36407
+ disabled: a.disabled,
36408
+ onSelect: () => a.onSelect(item)
36409
+ }))
36861
36410
  }
36862
- ) }, a.id);
36863
- })
36411
+ ),
36412
+ !itemMenu && (item.actions ?? []).map((a) => {
36413
+ const Icon = a.icon;
36414
+ return /* @__PURE__ */ jsx(Hint, { label: a.label, children: /* @__PURE__ */ jsx(
36415
+ Button,
36416
+ {
36417
+ type: "button",
36418
+ variant: "ghost",
36419
+ size: "icon",
36420
+ className: "h-7 w-7",
36421
+ "aria-label": a.label,
36422
+ onClick: () => a.onSelect(item),
36423
+ children: Icon ? /* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-3.5 w-3.5" })
36424
+ }
36425
+ ) }, a.id);
36426
+ })
36427
+ ]
36864
36428
  }
36865
36429
  )
36866
36430
  ] }, item.id ?? i)) }) }),
@@ -37123,7 +36687,10 @@ function OrderFormItemRow({
37123
36687
  labels,
37124
36688
  extraFieldGroups,
37125
36689
  readOnly = false,
37126
- pickOnly = false
36690
+ pickOnly = false,
36691
+ note,
36692
+ imageUrl,
36693
+ icon
37127
36694
  }) {
37128
36695
  const l = { ...ITEM_LABELS, ...labels };
37129
36696
  const total = quantity * unitPrice - (discount ?? 0) + (surcharge ?? 0);
@@ -37166,8 +36733,14 @@ function OrderFormItemRow({
37166
36733
  index + 1,
37167
36734
  "."
37168
36735
  ] }),
37169
- kindLabel && /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0 items-center rounded bg-muted px-1.5 py-0.5 text-[9px] font-medium text-muted-foreground", children: kindLabel }),
37170
- /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm", children: description || /* @__PURE__ */ jsx("span", { className: "italic text-muted-foreground", children: l.noDescription }) }),
36736
+ (imageUrl || icon) && /* @__PURE__ */ jsx(Thumbnail, { src: imageUrl, size: "sm", icon }),
36737
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 text-sm", children: [
36738
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
36739
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: description || /* @__PURE__ */ jsx("span", { className: "italic text-muted-foreground", children: l.noDescription }) }),
36740
+ kindLabel && /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0 items-center rounded bg-muted px-1.5 py-0.5 text-[9px] font-medium text-muted-foreground", children: kindLabel })
36741
+ ] }),
36742
+ note && /* @__PURE__ */ jsx("span", { className: "mt-0.5 block truncate text-xs", children: note })
36743
+ ] }),
37171
36744
  (extraFieldGroups ?? []).filter((g) => g.summary).map((g) => /* @__PURE__ */ jsx(
37172
36745
  Badge,
37173
36746
  {
@@ -37507,26 +37080,30 @@ function OrderFormItemsCard({
37507
37080
  emptyLabel = "Nenhum item adicionado",
37508
37081
  emptyActionLabel = "Adicione o primeiro item",
37509
37082
  children,
37510
- "data-tour": dataTour
37083
+ "data-tour": dataTour,
37084
+ headerExtra
37511
37085
  }) {
37512
37086
  return /* @__PURE__ */ jsxs("div", { "data-tour": dataTour, className: "flex flex-col overflow-hidden rounded-card border bg-card", children: [
37513
37087
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b px-4 py-3", children: [
37514
37088
  /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: label3 }),
37515
- onAdd && /* @__PURE__ */ jsxs(
37516
- "button",
37517
- {
37518
- type: "button",
37519
- onClick: onAdd,
37520
- disabled: addDisabled,
37521
- title: addDisabled ? addDisabledHint : void 0,
37522
- className: "fz-tap inline-flex items-center gap-2 rounded-button border border-primary bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground shadow-button-primary transition-colors hover:bg-primary/90 active:shadow-button-inset disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-primary",
37523
- children: [
37524
- /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
37525
- " ",
37526
- addLabel
37527
- ]
37528
- }
37529
- )
37089
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
37090
+ headerExtra,
37091
+ onAdd && /* @__PURE__ */ jsxs(
37092
+ "button",
37093
+ {
37094
+ type: "button",
37095
+ onClick: onAdd,
37096
+ disabled: addDisabled,
37097
+ title: addDisabled ? addDisabledHint : void 0,
37098
+ className: "fz-tap inline-flex items-center gap-2 rounded-button border border-primary bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground shadow-button-primary transition-colors hover:bg-primary/90 active:shadow-button-inset disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-primary",
37099
+ children: [
37100
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
37101
+ " ",
37102
+ addLabel
37103
+ ]
37104
+ }
37105
+ )
37106
+ ] })
37530
37107
  ] }),
37531
37108
  /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
37532
37109
  header,
@@ -38522,6 +38099,13 @@ function OrderListView({
38522
38099
  searchText,
38523
38100
  searchPlaceholder,
38524
38101
  pageSize = 25,
38102
+ search: searchProp,
38103
+ onSearchChange,
38104
+ page: pageProp,
38105
+ total,
38106
+ onPageChange,
38107
+ filters,
38108
+ mobileLayout,
38525
38109
  bulkActions,
38526
38110
  rowId,
38527
38111
  selectedRowId,
@@ -38531,8 +38115,15 @@ function OrderListView({
38531
38115
  boards,
38532
38116
  viewKey
38533
38117
  }) {
38534
- const [search, setSearch] = React133.useState("");
38535
- const [page, setPage] = React133.useState(1);
38118
+ const [localSearch, setLocalSearch] = React133.useState("");
38119
+ const [localPage, setLocalPage] = React133.useState(1);
38120
+ const serverPaged = total != null;
38121
+ const search = onSearchChange ? searchProp ?? "" : localSearch;
38122
+ const setSearch = onSearchChange ?? setLocalSearch;
38123
+ const page = serverPaged ? pageProp ?? 1 : localPage;
38124
+ const setPage = serverPaged ? onPageChange ?? (() => {
38125
+ }) : setLocalPage;
38126
+ const searchable = !!searchText || !!onSearchChange;
38536
38127
  const [rawSelection, setRawSelection] = React133.useState([]);
38537
38128
  const offered = React133.useMemo(
38538
38129
  () => views && views.length > 0 ? views : ["list"],
@@ -38587,6 +38178,7 @@ function OrderListView({
38587
38178
  const cols = React133.useMemo(
38588
38179
  () => columns.map((c) => ({
38589
38180
  id: c.key,
38181
+ ...c.mobile ? { meta: { mobile: c.mobile } } : {},
38590
38182
  header: () => /* @__PURE__ */ jsx("div", { className: c.align === "right" ? "text-right" : "", children: c.header }),
38591
38183
  cell: ({ row }) => /* @__PURE__ */ jsx("div", { className: c.align === "right" ? "text-right" : "", children: c.render(row.original) })
38592
38184
  })),
@@ -38594,13 +38186,14 @@ function OrderListView({
38594
38186
  );
38595
38187
  const filtered = React133.useMemo(() => {
38596
38188
  const term = search.trim().toLowerCase();
38597
- if (!term || !searchText) return rows;
38189
+ if (!term || !searchText || onSearchChange) return rows;
38598
38190
  return rows.filter((row) => searchText(row).toLowerCase().includes(term));
38599
38191
  }, [rows, search, searchText]);
38600
38192
  React133.useEffect(() => {
38601
- setPage(1);
38602
- }, [search]);
38603
- const paged = pageSize > 0 ? filtered.slice((page - 1) * pageSize, page * pageSize) : filtered;
38193
+ setLocalPage(1);
38194
+ }, [localSearch]);
38195
+ const paged = serverPaged || pageSize <= 0 ? filtered : filtered.slice((page - 1) * pageSize, page * pageSize);
38196
+ const totalRows = serverPaged ? total : filtered.length;
38604
38197
  const getId = React133.useCallback(
38605
38198
  (row) => rowId ? rowId(row) : String(row.id ?? ""),
38606
38199
  [rowId]
@@ -38658,19 +38251,26 @@ function OrderListView({
38658
38251
  }
38659
38252
  ) : null,
38660
38253
  tiles.length > 0 && /* @__PURE__ */ jsx(StatTiles, { tiles, loading }),
38661
- activeCustom ? activeCustom() : showingBoard ? /* @__PURE__ */ jsx(
38662
- OrderBoardView,
38663
- {
38664
- board: activeBoard,
38665
- rows: filtered,
38666
- loading,
38667
- empty,
38668
- onRowClick,
38669
- rowId,
38670
- selectedRowId
38671
- }
38672
- ) : /* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
38673
- (searchText || hasSelection) && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-2", children: hasSelection ? /* @__PURE__ */ jsx(
38254
+ activeCustom ? activeCustom() : showingBoard ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
38255
+ (searchable || filters) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
38256
+ searchable && /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: /* @__PURE__ */ jsx(SearchField, { value: search, onChange: setSearch, placeholder: searchPlaceholder ?? "Buscar\u2026" }) }),
38257
+ filters
38258
+ ] }),
38259
+ /* @__PURE__ */ jsx(
38260
+ OrderBoardView,
38261
+ {
38262
+ board: activeBoard,
38263
+ rows: filtered,
38264
+ loading,
38265
+ empty,
38266
+ onRowClick,
38267
+ rowId,
38268
+ selectedRowId
38269
+ }
38270
+ ),
38271
+ serverPaged && !loading && totalRows > pageSize && pageSize > 0 && /* @__PURE__ */ jsx(ChevronPager, { page, pageSize, total: totalRows, onPageChange: setPage })
38272
+ ] }) : /* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
38273
+ (searchable || filters || hasSelection) && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-2", children: hasSelection ? /* @__PURE__ */ jsx(
38674
38274
  BulkActionBar,
38675
38275
  {
38676
38276
  variant: "inline",
@@ -38680,14 +38280,17 @@ function OrderListView({
38680
38280
  onClear: () => setRawSelection([]),
38681
38281
  actions: barActions
38682
38282
  }
38683
- ) : /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: /* @__PURE__ */ jsx(
38684
- SearchField,
38685
- {
38686
- value: search,
38687
- onChange: setSearch,
38688
- placeholder: searchPlaceholder ?? "Buscar\u2026"
38689
- }
38690
- ) }) }),
38283
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
38284
+ searchable && /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: /* @__PURE__ */ jsx(
38285
+ SearchField,
38286
+ {
38287
+ value: search,
38288
+ onChange: setSearch,
38289
+ placeholder: searchPlaceholder ?? "Buscar\u2026"
38290
+ }
38291
+ ) }),
38292
+ filters
38293
+ ] }) }),
38691
38294
  /* @__PURE__ */ jsx(
38692
38295
  DataTable,
38693
38296
  {
@@ -38700,15 +38303,16 @@ function OrderListView({
38700
38303
  data: loading ? [] : paged,
38701
38304
  emptyMessage: search.trim() ? "Nada encontrado para esta busca." : empty,
38702
38305
  loading,
38703
- onRowClick: onRowClick ? (row) => onRowClick(row) : void 0
38306
+ onRowClick: onRowClick ? (row) => onRowClick(row) : void 0,
38307
+ ...mobileLayout ? { mobileLayout } : {}
38704
38308
  }
38705
38309
  ),
38706
- !loading && filtered.length > 0 && pageSize > 0 && /* @__PURE__ */ jsx(
38310
+ !loading && totalRows > 0 && pageSize > 0 && /* @__PURE__ */ jsx(
38707
38311
  ChevronPager,
38708
38312
  {
38709
38313
  page,
38710
38314
  pageSize,
38711
- total: filtered.length,
38315
+ total: totalRows,
38712
38316
  onPageChange: setPage
38713
38317
  }
38714
38318
  )
@@ -38766,7 +38370,7 @@ function PaymentStatusBadge({
38766
38370
  React133__default.useEffect(() => {
38767
38371
  setLines(null);
38768
38372
  }, [status, paidAmount]);
38769
- const load = React133__default.useCallback(() => {
38373
+ const load2 = React133__default.useCallback(() => {
38770
38374
  if (lines || !onLoadDetails) return;
38771
38375
  void onLoadDetails().then(setLines).catch(() => setLines([]));
38772
38376
  }, [lines, onLoadDetails]);
@@ -38781,7 +38385,7 @@ function PaymentStatusBadge({
38781
38385
  onMouseEnter: onLoadDetails ? () => {
38782
38386
  timer.current = setTimeout(() => {
38783
38387
  setOpen(true);
38784
- load();
38388
+ load2();
38785
38389
  }, 500);
38786
38390
  } : void 0,
38787
38391
  onMouseLeave: onLoadDetails ? () => {
@@ -38802,7 +38406,7 @@ function PaymentStatusBadge({
38802
38406
  const remaining = totalAmount != null && paidAmount != null ? totalAmount - paidAmount : null;
38803
38407
  return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: (v) => {
38804
38408
  setOpen(v);
38805
- if (v) load();
38409
+ if (v) load2();
38806
38410
  }, children: [
38807
38411
  /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: trigger }),
38808
38412
  /* @__PURE__ */ jsxs(PopoverContent, { align: "end", sideOffset: 6, className: "w-60 p-3", children: [
@@ -38907,7 +38511,7 @@ function useOrdersPaymentStatus(orderIds) {
38907
38511
  );
38908
38512
  const [byOrder, setByOrder] = React133.useState(() => /* @__PURE__ */ new Map());
38909
38513
  const [loading, setLoading] = React133.useState(false);
38910
- const load = React133.useCallback(async (force = false) => {
38514
+ const load2 = React133.useCallback(async (force = false) => {
38911
38515
  const ids = key ? key.split(",") : [];
38912
38516
  if (ids.length === 0) {
38913
38517
  setByOrder(/* @__PURE__ */ new Map());
@@ -38939,9 +38543,9 @@ function useOrdersPaymentStatus(orderIds) {
38939
38543
  setByOrder(new Map(ids.map((id) => [id, cache2.get(id)]).filter(([, v]) => Boolean(v))));
38940
38544
  }, [key]);
38941
38545
  React133.useEffect(() => {
38942
- void load();
38943
- }, [load]);
38944
- return { byOrder, loading, reload: () => load(true) };
38546
+ void load2();
38547
+ }, [load2]);
38548
+ return { byOrder, loading, reload: () => load2(true) };
38945
38549
  }
38946
38550
  var ORDER_KIND_LABELS = {
38947
38551
  sale: "Venda",
@@ -38974,7 +38578,9 @@ var ORDER_CHANNEL_LABELS = {
38974
38578
  balcao: "Balc\xE3o",
38975
38579
  shop: "Loja",
38976
38580
  dine_in: "Sal\xE3o",
38977
- delivery: "Delivery"
38581
+ delivery: "Delivery",
38582
+ retirada: "Retirada",
38583
+ ticketing: "Bilheteria"
38978
38584
  };
38979
38585
  function Badge28({ children }) {
38980
38586
  return /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium", children });
@@ -39023,7 +38629,7 @@ function useOrderDetail(orderId) {
39023
38629
  try {
39024
38630
  const db2 = getSupabaseClientOptional();
39025
38631
  if (!db2) throw new Error("Supabase client is not configured");
39026
- const { data: row, error: rowError } = await db2.from("v_orders").select("id, reference_number, kind, channel, status, party_id, subtotal, discount, tax, total, currency, notes, created_at").eq("id", orderId).maybeSingle();
38632
+ const { data: row, error: rowError } = await db2.from("v_orders").select("id, reference_number, kind, channel, status, fulfillment_status, party_id, subtotal, discount, tax, total, currency, notes, created_at").eq("id", orderId).maybeSingle();
39027
38633
  if (rowError) throw new Error(rowError.message);
39028
38634
  if (!row) throw new Error("Pedido n\xE3o encontrado");
39029
38635
  const [{ data: items }, { data: party }] = await Promise.all([
@@ -39046,6 +38652,7 @@ function useOrderDetail(orderId) {
39046
38652
  kind: row.kind ?? void 0,
39047
38653
  channel: row.channel ?? void 0,
39048
38654
  status: row.status ?? void 0,
38655
+ fulfillmentStatus: row.fulfillment_status ?? void 0,
39049
38656
  partyName: party?.name ?? void 0,
39050
38657
  notes: row.notes ?? void 0,
39051
38658
  currency: row.currency ?? "BRL",
@@ -39342,6 +38949,155 @@ function toOrderDetailReceivable(receivable, money4, options = {}) {
39342
38949
  ...options.actions ? { actions: options.actions } : {}
39343
38950
  };
39344
38951
  }
38952
+
38953
+ // src/crud/archetypes/orderStage.ts
38954
+ var ORDER_STAGES = ["to_receive", "to_ship", "shipped", "done", "cancelled"];
38955
+ var ORDER_STAGE_LABELS = {
38956
+ to_receive: "A receber",
38957
+ to_ship: "A enviar",
38958
+ shipped: "Enviado",
38959
+ done: "Conclu\xEDdo",
38960
+ cancelled: "Cancelado"
38961
+ };
38962
+ var ORDER_STAGE_COLORS = {
38963
+ to_receive: "bg-amber-500",
38964
+ to_ship: "bg-blue-500",
38965
+ shipped: "bg-cyan-500",
38966
+ done: "bg-emerald-500",
38967
+ cancelled: "bg-gray-400"
38968
+ };
38969
+ var SHIPPING_CHANNELS = /* @__PURE__ */ new Set(["shop", "delivery"]);
38970
+ function orderStage(order) {
38971
+ if (order.status === "cancelled") return "cancelled";
38972
+ const owed = ["pending", "open", "partial", "overdue"].includes(order.paymentStatus ?? "");
38973
+ if (order.status === "completed") return owed ? "to_receive" : "done";
38974
+ if (order.paymentStatus !== "paid") return "to_receive";
38975
+ const shipments = (order.shipmentStatuses ?? []).filter((s) => s !== "cancelled");
38976
+ const delivered = shipments.length > 0 && shipments.every((s) => s === "delivered" || s === "completed");
38977
+ if (shipments.some((s) => s === "in_transit")) return "shipped";
38978
+ if (order.fulfillmentStatus === "fulfilled" || delivered) return "done";
38979
+ const ships = shipments.length > 0 || SHIPPING_CHANNELS.has(order.channel ?? "");
38980
+ return ships ? "to_ship" : "done";
38981
+ }
38982
+ var STATUS_LABEL = {
38983
+ pending: "Aguardando envio",
38984
+ in_progress: "Em preparo",
38985
+ in_transit: "Em tr\xE2nsito",
38986
+ delivered: "Entregue",
38987
+ completed: "Entregue",
38988
+ failed: "Falhou",
38989
+ returned: "Devolvido",
38990
+ cancelled: "Cancelado"
38991
+ };
38992
+ var KIND_LABEL = { shipment: "Envio", pickup: "Retirada" };
38993
+ function text2(value) {
38994
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
38995
+ }
38996
+ function useOrderFulfillments(orderId) {
38997
+ const [fulfillments, setFulfillments] = React133.useState([]);
38998
+ const [loading, setLoading] = React133.useState(false);
38999
+ const [error, setError] = React133.useState(null);
39000
+ const [nonce, setNonce] = React133.useState(0);
39001
+ const reload2 = React133.useCallback(() => setNonce((n) => n + 1), []);
39002
+ React133.useEffect(() => {
39003
+ if (!orderId) {
39004
+ setFulfillments([]);
39005
+ setError(null);
39006
+ return;
39007
+ }
39008
+ let cancelled = false;
39009
+ setLoading(true);
39010
+ setError(null);
39011
+ void (async () => {
39012
+ try {
39013
+ const db2 = getSupabaseClientOptional();
39014
+ if (!db2) return;
39015
+ const { data: rows, error: rowsError } = await db2.from("fulfillments").select("id, kind, status, carrier, tracking_code, tracking_url, shipped_at, delivered_at, estimated_delivery_at, address_id, metadata").eq("order_id", orderId).in("kind", ["shipment", "pickup"]).order("occurred_at", { ascending: true });
39016
+ if (rowsError) throw new Error(rowsError.message);
39017
+ const addressIds = [...new Set((rows ?? []).map((r) => r.address_id).filter(Boolean))];
39018
+ const { data: addresses, error: addressError } = addressIds.length ? await db2.from("addresses").select("id, recipient, phone, postal_code, street, number, complement, district, city, state").in("id", addressIds) : { data: [], error: null };
39019
+ if (addressError) throw new Error(addressError.message);
39020
+ if (cancelled) return;
39021
+ const addressById = new Map((addresses ?? []).map((a) => [a.id, a]));
39022
+ setFulfillments((rows ?? []).map((r) => {
39023
+ const meta = r.metadata ?? {};
39024
+ const a = r.address_id ? addressById.get(r.address_id) : void 0;
39025
+ return {
39026
+ id: r.id,
39027
+ kind: r.kind,
39028
+ status: r.status,
39029
+ // Older rows carry these in metadata; the columns win when set.
39030
+ carrier: text2(r.carrier) ?? text2(meta.carrier),
39031
+ trackingCode: text2(r.tracking_code) ?? text2(meta.tracking_code),
39032
+ trackingUrl: text2(r.tracking_url) ?? text2(meta.tracking_url),
39033
+ shippedAt: r.shipped_at ?? void 0,
39034
+ deliveredAt: r.delivered_at ?? void 0,
39035
+ estimatedDeliveryAt: r.estimated_delivery_at ?? void 0,
39036
+ address: a ? {
39037
+ recipient: text2(a.recipient),
39038
+ phone: text2(a.phone),
39039
+ line1: [a.street, a.number].filter(Boolean).join(", ") + (a.complement ? ` \u2014 ${a.complement}` : ""),
39040
+ line2: [a.district, [a.city, a.state].filter(Boolean).join("/"), a.postal_code].filter(Boolean).join(" \xB7 ")
39041
+ } : void 0
39042
+ };
39043
+ }));
39044
+ } catch (err) {
39045
+ if (!cancelled) {
39046
+ setFulfillments([]);
39047
+ setError(err instanceof Error ? err.message : String(err));
39048
+ }
39049
+ } finally {
39050
+ if (!cancelled) setLoading(false);
39051
+ }
39052
+ })();
39053
+ return () => {
39054
+ cancelled = true;
39055
+ };
39056
+ }, [orderId, nonce]);
39057
+ return { fulfillments, loading, error, reload: reload2 };
39058
+ }
39059
+ function day(value) {
39060
+ return value ? new Date(value).toLocaleDateString("pt-BR") : void 0;
39061
+ }
39062
+ function OrderDeliveryBlock({ fulfillments, error }) {
39063
+ if (error) {
39064
+ return /* @__PURE__ */ jsx(OrderDetailBlock, { title: "Entrega", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", role: "alert", "data-testid": "order-delivery-error", children: "N\xE3o foi poss\xEDvel carregar a entrega deste pedido." }) });
39065
+ }
39066
+ if (fulfillments.length === 0) {
39067
+ return /* @__PURE__ */ jsx(OrderDetailBlock, { title: "Entrega", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", "data-testid": "order-delivery-empty", children: "Nenhum endere\xE7o ou envio registrado neste pedido." }) });
39068
+ }
39069
+ return /* @__PURE__ */ jsx(OrderDetailBlock, { title: "Entrega", children: /* @__PURE__ */ jsx("ul", { className: "divide-y text-sm", children: fulfillments.map((f) => /* @__PURE__ */ jsxs("li", { className: "space-y-1 py-2 first:pt-0 last:pb-0", "data-testid": "order-fulfillment", children: [
39070
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
39071
+ /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
39072
+ KIND_LABEL[f.kind] ?? f.kind,
39073
+ f.carrier ? ` \xB7 ${f.carrier}` : ""
39074
+ ] }),
39075
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: STATUS_LABEL[f.status] ?? f.status })
39076
+ ] }),
39077
+ f.trackingCode && /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground", children: [
39078
+ "Rastreio:",
39079
+ " ",
39080
+ f.trackingUrl ? /* @__PURE__ */ jsx("a", { href: f.trackingUrl, target: "_blank", rel: "noreferrer", className: "text-primary underline-offset-2 hover:underline", children: f.trackingCode }) : /* @__PURE__ */ jsx("span", { className: "text-foreground", children: f.trackingCode })
39081
+ ] }),
39082
+ (f.shippedAt || f.deliveredAt || f.estimatedDeliveryAt) && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: [
39083
+ f.shippedAt && `Enviado em ${day(f.shippedAt)}`,
39084
+ f.deliveredAt ? `Entregue em ${day(f.deliveredAt)}` : f.estimatedDeliveryAt && `Previs\xE3o ${day(f.estimatedDeliveryAt)}`
39085
+ ].filter(Boolean).join(" \xB7 ") }),
39086
+ f.address && /* @__PURE__ */ jsxs("address", { className: "not-italic text-muted-foreground", children: [
39087
+ f.address.recipient && /* @__PURE__ */ jsx("span", { className: "block text-foreground", children: f.address.recipient }),
39088
+ /* @__PURE__ */ jsx("span", { className: "block", children: f.address.line1 }),
39089
+ /* @__PURE__ */ jsx("span", { className: "block", children: f.address.line2 }),
39090
+ f.address.phone && /* @__PURE__ */ jsx("span", { className: "block", children: f.address.phone })
39091
+ ] })
39092
+ ] }, f.id)) }) });
39093
+ }
39094
+ var STAGE_TONE = {
39095
+ to_receive: "warning",
39096
+ to_ship: "info",
39097
+ shipped: "info",
39098
+ done: "success",
39099
+ cancelled: "destructive"
39100
+ };
39345
39101
  function money3(value, currency) {
39346
39102
  return value.toLocaleString("pt-BR", { style: "currency", currency: currency || "BRL" });
39347
39103
  }
@@ -39354,9 +39110,10 @@ function OrderDetailPage({
39354
39110
  mapData,
39355
39111
  receivableActions
39356
39112
  }) {
39357
- const { order, loading, error } = useOrderDetail(orderId);
39113
+ const { order, loading, error, reload: reload2 } = useOrderDetail(orderId);
39114
+ const { fulfillments, error: fulfillmentsError } = useOrderFulfillments(orderId);
39358
39115
  const { receivable, reload: reloadReceivable } = useOrderReceivable(orderId);
39359
- if (loading) return /* @__PURE__ */ jsx(OrderDetailSkeleton, {});
39116
+ if (loading && !order) return /* @__PURE__ */ jsx(OrderDetailSkeleton, {});
39360
39117
  if (error || !order) {
39361
39118
  return /* @__PURE__ */ jsxs("div", { className: "p-6", children: [
39362
39119
  /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error ?? "Pedido n\xE3o encontrado" }),
@@ -39373,27 +39130,18 @@ function OrderDetailPage({
39373
39130
  }
39374
39131
  const currency = order.currency;
39375
39132
  const verbs = receivableActions?.(order, { receivable, reload: reloadReceivable });
39133
+ const stage = orderStage({
39134
+ status: order.status,
39135
+ channel: order.channel,
39136
+ paymentStatus: receivable?.balance.status ?? "none",
39137
+ fulfillmentStatus: order.fulfillmentStatus,
39138
+ shipmentStatuses: fulfillments.map((f) => f.status)
39139
+ });
39376
39140
  const base = {
39377
39141
  title: order.referenceNumber,
39378
- // Kind and channel are the two axes the archetype actually stores; status
39379
- // heads them because it is what changes.
39380
- // Through the shared vocabulary, not raw. The column holds `confirmed`,
39381
- // `dine_in`, `balcao` — machine words, and printing them is how a screen
39382
- // ends up saying "dine_in" to a waiter. Anything the vocabulary has not
39383
- // named falls through to the raw value rather than being guessed at.
39384
- badges: [
39385
- ...order.status ? [{ label: ORDER_STATUS_LABELS[order.status] ?? order.status, tone: orderStatusTone(order.status) }] : [],
39386
- ...order.kind ? [{ label: ORDER_KIND_LABELS[order.kind] ?? order.kind, tone: "muted" }] : [],
39387
- ...order.channel ? [{ label: ORDER_CHANNEL_LABELS[order.channel] ?? order.channel, tone: "muted" }] : [],
39388
- // O estado do DINHEIRO ao lado do estado do PEDIDO. Ate aqui a resposta
39389
- // existia so no bloco de baixo, e quem abre a ficha para saber se ja
39390
- // recebeu tinha de rolar a tela para descobrir. So aparece depois de
39391
- // faturado — sem fatura nao ha o que dizer, e o bloco de baixo ja diz.
39392
- ...receivable ? [{
39393
- label: RECEIVABLE_LABEL[receivable.balance.status] ?? receivable.balance.status,
39394
- tone: receivableTone(receivable.balance.status)
39395
- }] : []
39396
- ],
39142
+ // ONE badge, the same word the list and the board use for this order.
39143
+ // Status, kind, channel and money as four chips read as four states.
39144
+ badges: [{ label: ORDER_STAGE_LABELS[stage], tone: STAGE_TONE[stage] }],
39397
39145
  // The date belongs in the provenance footer, where every other ficha in the
39398
39146
  // app keeps "criado em" — beside the order number it competes with what the
39399
39147
  // person opened the screen to read. `meta` is what RecordMetaFooter reads.
@@ -39424,8 +39172,12 @@ function OrderDetailPage({
39424
39172
  // dois ramos: dois `createElement` distintos remontariam o componente na
39425
39173
  // troca de ramo, e com ele o modal aberto.
39426
39174
  receivable: toOrderDetailReceivable(receivable, (value) => money3(value, currency), { actions: verbs }) ?? { rows: [], installments: [], actions: verbs },
39427
- ...actions ? { actions: actions(order) } : {},
39428
- ...extraSections ? { extraSections: extraSections(order) } : {},
39175
+ ...actions ? { actions: actions(order, { reload: reload2 }) } : {},
39176
+ // Beside the customer, where the shop's own page keeps it.
39177
+ extraSections: /* @__PURE__ */ jsxs(Fragment, { children: [
39178
+ /* @__PURE__ */ jsx(OrderDeliveryBlock, { fulfillments, error: fulfillmentsError }),
39179
+ extraSections?.(order)
39180
+ ] }),
39429
39181
  backLabel,
39430
39182
  onBack: () => navigateTo(backTo)
39431
39183
  };
@@ -39543,6 +39295,43 @@ function useOrderEditor(orderId) {
39543
39295
  save
39544
39296
  };
39545
39297
  }
39298
+ var cache4 = null;
39299
+ function load() {
39300
+ cache4 ?? (cache4 = (async () => {
39301
+ const db2 = getSupabaseClientOptional();
39302
+ if (!db2) return /* @__PURE__ */ new Map();
39303
+ const { data, error } = await db2.from("order_kinds").select("kind, transitions");
39304
+ if (error) {
39305
+ cache4 = null;
39306
+ return /* @__PURE__ */ new Map();
39307
+ }
39308
+ return new Map((data ?? []).map((r) => [r.kind, r.transitions ?? {}]));
39309
+ })());
39310
+ return cache4;
39311
+ }
39312
+ var TERMINAL = /* @__PURE__ */ new Set(["completed", "cancelled"]);
39313
+ function nextOrderStatuses(transitions, status) {
39314
+ if (!transitions || !status) return [];
39315
+ const declared = transitions[status] ?? transitions["*"] ?? [];
39316
+ if (declared.includes("*")) return TERMINAL.has(status) ? [] : ["cancelled"];
39317
+ return declared;
39318
+ }
39319
+ function useOrderKindTransitions(kind, status) {
39320
+ const [byKind, setByKind] = React133.useState(null);
39321
+ React133.useEffect(() => {
39322
+ let live = true;
39323
+ void load().then((map) => {
39324
+ if (live) setByKind(map);
39325
+ });
39326
+ return () => {
39327
+ live = false;
39328
+ };
39329
+ }, []);
39330
+ return React133.useMemo(
39331
+ () => nextOrderStatuses(kind ? byKind?.get(kind) : void 0, status),
39332
+ [byKind, kind, status]
39333
+ );
39334
+ }
39546
39335
 
39547
39336
  // src/lib/create-client-orders-provider.ts
39548
39337
  var STAGE_FILTER_MAP = {
@@ -39763,6 +39552,39 @@ function ModuleActionBar({
39763
39552
  trailing
39764
39553
  ] });
39765
39554
  }
39555
+ function formatCurrency4(value, currency) {
39556
+ if (!currency) return formatCurrency$1(value);
39557
+ return new Intl.NumberFormat(currency.locale, {
39558
+ style: "currency",
39559
+ currency: currency.code,
39560
+ minimumFractionDigits: 2
39561
+ }).format(value);
39562
+ }
39563
+ function useHouseCurrency() {
39564
+ return React133.useSyncExternalStore(subscribeHouseCurrency, getHouseCurrency, getHouseCurrency);
39565
+ }
39566
+ var CurrencyScopeContext = React133.createContext(null);
39567
+ function CurrencyScope({ code, children }) {
39568
+ const outer = React133.useContext(CurrencyScopeContext);
39569
+ return React133.createElement(CurrencyScopeContext.Provider, { value: code || outer }, children);
39570
+ }
39571
+ function useCurrencyScope() {
39572
+ return React133.useContext(CurrencyScopeContext);
39573
+ }
39574
+ function useCurrency(declared, documentCode) {
39575
+ const house = useHouseCurrency();
39576
+ const scope = useCurrencyScope();
39577
+ const code = documentCode || scope;
39578
+ return React133.useMemo(
39579
+ () => resolveCurrency(declared, code),
39580
+ // `house` is read inside resolveCurrency; listed so a switch re-resolves.
39581
+ // eslint-disable-next-line react-hooks/exhaustive-deps
39582
+ [declared, code, house]
39583
+ );
39584
+ }
39585
+ function isCurrencyConfig(value) {
39586
+ return !!value && typeof value === "object" && typeof value.code === "string" && typeof value.locale === "string";
39587
+ }
39766
39588
  function createPluginContext(displayName) {
39767
39589
  const ConfigContext = React133__default.createContext(null);
39768
39590
  const ProviderContext = React133__default.createContext(null);
@@ -39776,8 +39598,16 @@ function createPluginContext(displayName) {
39776
39598
  ContextProvider.displayName = `${displayName}ContextProvider`;
39777
39599
  function useConfig() {
39778
39600
  const ctx = React133__default.useContext(ConfigContext);
39779
- if (!ctx) throw new Error(`useConfig must be used within ${displayName}`);
39780
- return ctx;
39601
+ const house = useHouseCurrency();
39602
+ const scope = useCurrencyScope();
39603
+ const resolved = React133__default.useMemo(() => {
39604
+ const declared = ctx?.currency;
39605
+ const code = scope || house;
39606
+ if (!ctx || !code || !isCurrencyConfig(declared) || declared.code === code) return ctx;
39607
+ return { ...ctx, currency: resolveCurrency(declared, scope) };
39608
+ }, [ctx, house, scope]);
39609
+ if (!resolved) throw new Error(`useConfig must be used within ${displayName}`);
39610
+ return resolved;
39781
39611
  }
39782
39612
  function useProvider() {
39783
39613
  const ctx = React133__default.useContext(ProviderContext);
@@ -39805,14 +39635,6 @@ function createViewRouter(routes, fallbackId) {
39805
39635
  return route ? route.render({ id }) : null;
39806
39636
  };
39807
39637
  }
39808
- function formatCurrency4(value, currency) {
39809
- if (!currency) return formatCurrency$1(value);
39810
- return new Intl.NumberFormat(currency.locale, {
39811
- style: "currency",
39812
- currency: currency.code,
39813
- minimumFractionDigits: 2
39814
- }).format(value);
39815
- }
39816
39638
  function RegistryCrudView({ registry: registry4, basePath }) {
39817
39639
  const useStore2 = useMemo(() => {
39818
39640
  const data = registry4.mockData ?? registry4.seedData ?? [];
@@ -40210,7 +40032,7 @@ function ContactPicker({
40210
40032
  () => lookup ?? createArchetypeLookup({ archetype: "person", kind }),
40211
40033
  [lookup, kind]
40212
40034
  );
40213
- const create32 = useMemo(() => {
40035
+ const create31 = useMemo(() => {
40214
40036
  if (createEntityDef?.data?.table) {
40215
40037
  const def2 = createEntityDef;
40216
40038
  return {
@@ -40246,8 +40068,8 @@ function ContactPicker({
40246
40068
  }
40247
40069
  };
40248
40070
  }, [createEntityDef, resolvedLookup]);
40249
- const createFeature = create32?.def.permission?.feature;
40250
- const canCreate = !!create32 && (!createFeature || can(createFeature, "create"));
40071
+ const createFeature = create31?.def.permission?.feature;
40072
+ const canCreate = !!create31 && (!createFeature || can(createFeature, "create"));
40251
40073
  const [search, setSearch] = useState(value?.id ? value.name : value?.name ?? "");
40252
40074
  const [options, setOptions] = useState([]);
40253
40075
  const [searching, setSearching] = useState(false);
@@ -40370,17 +40192,17 @@ function ContactPicker({
40370
40192
  ] })
40371
40193
  );
40372
40194
  }
40373
- if (creating && create32) {
40374
- const nameKey = create32.def.displayField ?? create32.def.fields[0]?.key ?? "name";
40195
+ if (creating && create31) {
40196
+ const nameKey = create31.def.displayField ?? create31.def.fields[0]?.key ?? "name";
40375
40197
  return frame(
40376
40198
  /* @__PURE__ */ jsx(
40377
40199
  LookupCreateInline,
40378
40200
  {
40379
- entityDef: create32.def,
40201
+ entityDef: create31.def,
40380
40202
  initialData: { [nameKey]: newName },
40381
40203
  onCancel: () => setCreating(false),
40382
40204
  save: async (data) => {
40383
- const person = await create32.write(data);
40205
+ const person = await create31.write(data);
40384
40206
  setSearch(person.name || newName);
40385
40207
  setCreating(false);
40386
40208
  onChange({ ...person, name: person.name || newName });
@@ -40698,9 +40520,9 @@ function clearDocumentOpeners() {
40698
40520
  function createOneShotAsk(override) {
40699
40521
  const connection = resolveFayzAgentConnection(override);
40700
40522
  if (!connection) return null;
40701
- const client3 = getFayzAgentClient(connection);
40523
+ const client2 = getFayzAgentClient(connection);
40702
40524
  return async ({ message, inlineFiles, signal }) => {
40703
- const reply = await client3.chat({
40525
+ const reply = await client2.chat({
40704
40526
  message,
40705
40527
  ...inlineFiles?.length ? { inlineFiles } : {},
40706
40528
  ...signal ? { signal } : {},
@@ -40926,7 +40748,7 @@ function useFeatureHelp(def) {
40926
40748
  }
40927
40749
  function HelpButton({
40928
40750
  icon: Icon,
40929
- text: text2,
40751
+ text: text3,
40930
40752
  hint,
40931
40753
  ariaLabel,
40932
40754
  className,
@@ -40944,7 +40766,7 @@ function HelpButton({
40944
40766
  onClick,
40945
40767
  children: [
40946
40768
  /* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }),
40947
- text2
40769
+ text3
40948
40770
  ]
40949
40771
  }
40950
40772
  ) }),
@@ -41309,6 +41131,6 @@ var renderApp = (...args) => {
41309
41131
  return renderApp$1(...args);
41310
41132
  };
41311
41133
 
41312
- export { ALWAYS_ON_TOOLS, ActivationChecklistCard, ActivationProvider, AddConnectorButton, AddConnectorPanel, AdminProviders, AdminScaffold, AdminShell, AskAIButton, AskAIMenuItem, AssistantInvite, BoardFrame, ChatConversation, ClientOrdersTab, ConnectConsentPage, ConnectorDeliveries, ConnectorDetail, ConnectorMark, ConnectorRow, ConnectorSyncActions, ConnectorsHub, ConnectorsTab, ContactPicker, CredentialSinkMissingError, CrudCardGrid, CrudDetailPage, CrudDetailSkeleton, CrudFormPage, CrudFormSkeleton, CrudListView, CrudPage, CrudRecordModal, DeleteConfirmDialog, DetailTabHeader, EntitlementGate, EntityLink, GetStarted, GettingStartedWidget, NotebookPanel as HandbookPanel, HandbookProvider, NotebookRailPanel as HandbookRailPanel, KanbanBoard, LimitGate, LookupCreateInline, MemberAccessRailPage, ModuleActionBar, MultiSelectRow, NOTE_LABEL_PREFIX, NotebookPanel, NotebookRailPanel, ONBOARDING_TASK_SOURCE, ORDER_CHANNEL_LABELS, ORDER_KIND_LABELS, OTHER_CONNECTOR, OrderAmount, OrderBoardView, OrderCreateScreen, OrderDetailBlock, OrderDetailPage, OrderDetailRail, OrderDetailRow, OrderDetailSkeleton, OrderDetailView, OrderFormAddItemStep, OrderDetailBlock as OrderFormBlock, OrderFormItemRow, OrderFormItemsCard, OrderFormSkeleton, OrderFormView, OrderListView, OrderPaymentChip, PAYMENT_STATUS_CONFIG, PAYMENT_STATUS_LABEL, PageActions, PaymentStatusBadge, PermissionGate, PersonLink2 as PersonLink, PlatformError, PluginOnboardingGateSkeleton, PluginRegistryManager, PluginSettingsPanel, ProjectsSettings, QUESTION_PACKS, QuickActionsButton, RECEIVABLE_LABEL, RecordPickerModal, RegistryCrudView2 as RegistryCrudView, RelatedListTab, RightRailActions, RightRailLeading, RightRailPage, RouteErrorBoundary, RouteErrorScreen, SelectRow, SettingsGroup, SettingsTabs, SetupAgentSurface, SetupMeLink, SeuSiteWidget, StateChip, TASK_PRIORITIES, TASK_STATUSES, TaskCard, TaskDetail, TaskGroup, TaskLabelBadge, TaskLabelBadges, TaskPriorityBadge, TaskQuickAdd, TaskSourceBadge, TaskStatusGroup, TasksFilterBar, TasksPanel, TasksRailPanel, TeachMeLink, TextRow, ToggleRow, UNIT_DETAIL_ZONES, UnitSwitcher, UnitsSettingsPage, UpgradePrompt, WORKSPACE_SETUP_FLOW_ID, WORKSPACE_SETUP_FLOW_VERSION, WORKSPACE_SETUP_ROUTE, WidgetSlot, WorkspaceSetupFlow, WorkspaceSetupGate, WorkspaceSwitcher, appendHandbookPage, applyFieldRules, askAI, beautyPack, brandMark, buildBusinessProfile, buildHandbookTree, buildWorkspaceSetupSteps, businessProfileBlock, categoryLabel, checkSlugAvailable, claimTasksSurface, clearDocumentOpeners, clearPersonActions, connectorOptions, connectorRoute, connectorRows, createClientOrdersProvider, createCrudPage, createFayzApp, createFayzProject, createLogoUploader, createMockTasksProvider, createCrudPage as createNativeCrudPage, createOneShotAsk, createPlaceholder, createPlatformProject, createPluginContext, createSupabaseTasksProvider, createViewRouter, currentBusinessProfileBlock, dedup, defaultProjectOf, defineSaas, deleteFayzProject, deriveAgentContract, deriveEntityKey5 as deriveEntityKey, describeAiError, describeAiGap, describeFayzAgentGap, duplicateWrite, ensureChecklist, exportToCSV, filterConnectors, foodPack, formatActivityElapsed, formatCurrency4 as formatCurrency, formatSetupGuide, getActiveAgent, getAgent, getCrudNavTabs, getDefaultFayzProject, getFayzAgentClient, getGenerationStatus, getHost, getPersonActions, getPersonPath, getPreview, getQuestionPack, getRailPage, getSetupGuide, getSetupGuideForStep, getTabCountProviders, getTasksProvider, helpWith, humanizeWriteError, inferVerticalId, invalidateOrderReceivable, invalidateOrdersPaymentStatus, invalidateRelationOptions, invalidateTabCounts, isPlatformConnected, listFayzProjects, listHandbook, listPlatformProjects, listSetupGuides, loadArea, loadTools, loadedToolNames, mergeLines, needsCredentialSink, normalizePath, openAssistant, openAssistantAs, openConnectorsPanel, orderChannelColumn, orderIsEditable, orderKindColumn, orientationTour, parseViewId, publishAssistantActivity, readAttachmentBytes, readHandbookPage, readSetupAnswers, receivableTone, recordOnboardingResponse, registerAdminScaffold, registerAssistantLauncher, registerCrudNavTabs, registerDocumentOpener, registerEntityPath, registerNotesTasksAdapter, registerPersonActions, registerRailPage, registerSetupGuides, registerTabCountProvider, renderApp, renderHandbookOutline, requestChatUpload, requestProjectChange, resetLoadedTools, resolveDocumentOpener, resolveDocumentOpenerFor, resolveFayzAgentConnection, resolveSetupMode, resolveVerticalId, retailPack, revealPage, runWelcome, searchHandbook, searchSetupGuides, setServedRoutes, setTasksProvider, setUpWithMe, shrinkForVision, slugify, soleAgent, splitConnectorValues, splitOnboardingTasks, startGuidedRun, startPreview, stopPreview, submitConnection, submitWorkspaceSetup, summariseSetupGuides, taskEntityDef, tasksSurfaceOwner, teachMe, toInlineFile, toOrderDetailReceivable, unregisterAssistantLauncher, unregisterTabCountProvider, updateFayzProject, useActivationStore, useActiveAgent, useAgent, useAgentStore, useAgentSurface, useAppConfig, useAssistantActivity, useAssistantInviteStore, useAssistantLaunchers, useBusinessProfileStore, useCatalogedItemTypes, useChatStore, useConnectors, useConnectorsPanelAvailable, useContextualNav, useContextualNavStore, useDelegateToAssistant, useFayzProjectsStore, useFeatureHelp, useFieldRules, useHandbookStore, useHasRightRail, useHeaderAction, useHeaderActions, useLaunchersForRole, useLookupCreate, useMemberAccessPanel, useModuleNavigation, useNavContribution, useNavContributionsStore, useNotesTasksBridge, useOrderDetail, useOrderEditor, useOrderReceivable, useOrdersPaymentStatus, usePersistedState, usePersonTabCounts, usePluginOnboardingGate, usePluginPrefs, usePresetLabel, usePublishAssistantActivity, useRegisterAssistantLauncher, useRememberedList, useRightRailDrill, useRightRailHosted, useRightRailMenu, useRightRailPanel, useRightRailStore, useScrollMemory, useSettingsTabsStore, useShellRailAvailable, useTasksStore, useTasksSummaryLine, useTeachMe, useTenantPluginSettings, useUnitBootstrap, useUnitFilter, useUnitStore, useWidgetSurface, useWorkspaceSetupBusy, useWorkspaceSetupGate, useWorkspaceSetupStore, validateSetupGuides, withdrawAssistantActivity, writeHandbookPage };
41134
+ export { ALWAYS_ON_TOOLS, ActivationChecklistCard, ActivationProvider, AddConnectorButton, AddConnectorPanel, AdminProviders, AdminScaffold, AdminShell, AskAIButton, AskAIMenuItem, AssistantInvite, BoardFrame, ChatConversation, ClientOrdersTab, ConnectConsentPage, ConnectorDeliveries, ConnectorDetail, ConnectorMark, ConnectorRow, ConnectorSyncActions, ConnectorsHub, ConnectorsTab, ContactPicker, CredentialSinkMissingError, CrudCardGrid, CrudDetailPage, CrudDetailSkeleton, CrudFormPage, CrudFormSkeleton, CrudListView, CrudPage, CrudRecordModal, CurrencyScope, DeleteConfirmDialog, DetailTabHeader, EntitlementGate, EntityLink, GetStarted, GettingStartedWidget, NotebookPanel as HandbookPanel, HandbookProvider, NotebookRailPanel as HandbookRailPanel, KanbanBoard, LimitGate, LookupCreateInline, MemberAccessRailPage, ModuleActionBar, MultiSelectRow, NOTE_LABEL_PREFIX, NotebookPanel, NotebookRailPanel, ONBOARDING_TASK_SOURCE, ORDER_CHANNEL_LABELS, ORDER_KIND_LABELS, ORDER_STAGES, ORDER_STAGE_COLORS, ORDER_STAGE_LABELS, ORDER_STATUS_LABELS, OTHER_CONNECTOR, OrderAmount, OrderBoardView, OrderCreateScreen, OrderDeliveryBlock, OrderDetailBlock, OrderDetailPage, OrderDetailRail, OrderDetailRow, OrderDetailSkeleton, OrderDetailView, OrderFormAddItemStep, OrderDetailBlock as OrderFormBlock, OrderFormItemRow, OrderFormItemsCard, OrderFormSkeleton, OrderFormView, OrderListView, OrderPaymentChip, PAYMENT_STATUS_CONFIG, PAYMENT_STATUS_LABEL, PageActions, PaymentStatusBadge, PermissionGate, PersonLink2 as PersonLink, PlatformError, PluginOnboardingGateSkeleton, PluginRegistryManager, PluginSettingsPanel, ProjectsSettings, QUESTION_PACKS, QuickActionsButton, RECEIVABLE_LABEL, RecordPickerModal, RegistryCrudView2 as RegistryCrudView, RelatedListTab, RightRailActions, RightRailLeading, RightRailPage, RouteErrorBoundary, RouteErrorScreen, SelectRow, SettingsGroup, SettingsTabs, SetupAgentSurface, SetupMeLink, SeuSiteWidget, StateChip, TASK_PRIORITIES, TASK_STATUSES, TagChip, TagsField, TaskCard, TaskDetail, TaskGroup, TaskLabelBadge, TaskLabelBadges, TaskPriorityBadge, TaskQuickAdd, TaskSourceBadge, TaskStatusGroup, TasksFilterBar, TasksPanel, TasksRailPanel, TeachMeLink, TextRow, ToggleRow, UNIT_DETAIL_ZONES, UnitSwitcher, UnitsSettingsPage, UpgradePrompt, WORKSPACE_SETUP_FLOW_ID, WORKSPACE_SETUP_FLOW_VERSION, WORKSPACE_SETUP_ROUTE, WidgetSlot, WorkspaceSetupFlow, WorkspaceSetupGate, WorkspaceSwitcher, appendHandbookPage, applyFieldRules, askAI, beautyPack, brandMark, buildBusinessProfile, buildHandbookTree, buildWorkspaceSetupSteps, businessProfileBlock, categoryLabel, checkSlugAvailable, claimTasksSurface, clearDocumentOpeners, clearPersonActions, connectorOptions, connectorRoute, connectorRows, createClientOrdersProvider, createCrudPage, createFayzApp, createFayzProject, createLogoUploader, createMockTasksProvider, createCrudPage as createNativeCrudPage, createOneShotAsk, createPlaceholder, createPlatformProject, createPluginContext, createSupabaseTasksProvider, createViewRouter, currentBusinessProfileBlock, defaultProjectOf, defineSaas, deleteFayzProject, deriveAgentContract, deriveEntityKey5 as deriveEntityKey, describeAiError, describeAiGap, describeFayzAgentGap, duplicateWrite, ensureChecklist, exportToCSV, filterConnectors, foodPack, formatActivityElapsed, formatCurrency4 as formatCurrency, formatSetupGuide, getActiveAgent, getAgent, getCrudNavTabs, getDefaultFayzProject, getFayzAgentClient, getGenerationStatus, getHost, getPersonActions, getPersonPath, getPreview, getQuestionPack, getRailPage, getSetupGuide, getSetupGuideForStep, getTabCountProviders, getTasksProvider, helpWith, humanizeWriteError, inferVerticalId, invalidateOrderReceivable, invalidateOrdersPaymentStatus, invalidateRelationOptions, invalidateTabCounts, isPlatformConnected, listFayzProjects, listHandbook, listPlatformProjects, listSetupGuides, loadArea, loadTools, loadedToolNames, mergeLines, needsCredentialSink, nextOrderStatuses, normalizePath, openAssistant, openAssistantAs, openConnectorsPanel, orderChannelColumn, orderIsEditable, orderKindColumn, orderStage, orderStatusTone, orientationTour, parseViewId, publishAssistantActivity, readAttachmentBytes, readHandbookPage, readSetupAnswers, receivableTone, recordOnboardingResponse, registerAdminScaffold, registerAssistantLauncher, registerCrudNavTabs, registerDocumentOpener, registerEntityPath, registerNotesTasksAdapter, registerPersonActions, registerRailPage, registerSetupGuides, registerTabCountProvider, renderApp, renderHandbookOutline, requestChatUpload, requestProjectChange, resetLoadedTools, resolveDocumentOpener, resolveDocumentOpenerFor, resolveFayzAgentConnection, resolveSetupMode, resolveVerticalId, retailPack, revealPage, runWelcome, searchHandbook, searchSetupGuides, setServedRoutes, setTasksProvider, setUpWithMe, shrinkForVision, slugify, soleAgent, splitConnectorValues, splitOnboardingTasks, startGuidedRun, startPreview, stopPreview, submitConnection, submitWorkspaceSetup, summariseSetupGuides, taskEntityDef, tasksSurfaceOwner, teachMe, toInlineFile, toOrderDetailReceivable, unregisterAssistantLauncher, unregisterTabCountProvider, updateFayzProject, useActivationStore, useActiveAgent, useAgent, useAgentStore, useAgentSurface, useAppConfig, useAssistantActivity, useAssistantInviteStore, useAssistantLaunchers, useBusinessProfileStore, useCatalogedItemTypes, useChatStore, useConnectors, useConnectorsPanelAvailable, useContextualNav, useContextualNavStore, useCurrency, useCurrencyScope, useDelegateToAssistant, useFayzProjectsStore, useFeatureHelp, useFieldRules, useHandbookStore, useHasRightRail, useHeaderAction, useHeaderActions, useHouseCurrency, useLaunchersForRole, useLookupCreate, useMemberAccessPanel, useModuleNavigation, useNavContribution, useNavContributionsStore, useNotesTasksBridge, useOfferedPlugins, useOrderDetail, useOrderEditor, useOrderFulfillments, useOrderKindTransitions, useOrderReceivable, useOrdersPaymentStatus, usePersistedState, usePersonTabCounts, usePluginOnboardingGate, usePluginPrefs, usePresetLabel, usePublishAssistantActivity, useRegisterAssistantLauncher, useRememberedList, useRightRailDrill, useRightRailHosted, useRightRailMenu, useRightRailPanel, useRightRailStore, useScrollMemory, useSettingsTabsStore, useShellRailAvailable, useTasksStore, useTasksSummaryLine, useTeachMe, useTenantPluginSettings, useUnitBootstrap, useUnitFilter, useWidgetSurface, useWorkspaceSetupBusy, useWorkspaceSetupGate, useWorkspaceSetupStore, validateSetupGuides, withdrawAssistantActivity, writeHandbookPage };
41313
41135
  //# sourceMappingURL=index.js.map
41314
41136
  //# sourceMappingURL=index.js.map