@fayz-ai/admin 0.43.4 → 0.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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/app/AdminShell.d.ts.map +1 -1
  6. package/dist/{chunk-A5UZL52H.js → chunk-OINP2UYL.js} +3 -3
  7. package/dist/{chunk-A5UZL52H.js.map → chunk-OINP2UYL.js.map} +1 -1
  8. package/dist/{chunk-KP3LNCNP.js → chunk-V2IBAF4O.js} +954 -23
  9. package/dist/chunk-V2IBAF4O.js.map +1 -0
  10. package/dist/{chunk-HOMD2MAG.js → chunk-VH4LLIMH.js} +3 -3
  11. package/dist/{chunk-HOMD2MAG.js.map → chunk-VH4LLIMH.js.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 +751 -927
  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
@@ -6749,8 +6214,8 @@ function summaryRows(values) {
6749
6214
  const rows = [];
6750
6215
  const push = (label3, raw) => {
6751
6216
  if (raw === void 0 || raw === null || raw === "") return;
6752
- const text2 = Array.isArray(raw) ? raw.join(", ") : String(raw);
6753
- 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 });
6754
6219
  };
6755
6220
  push(tl("Workspace", "\xC1rea de trabalho"), values[NAME_FIELD]);
6756
6221
  push(tl("Contact", "Contato"), values["workspace.email"]);
@@ -7181,9 +6646,9 @@ function startNativeDictation(locale, cb) {
7181
6646
  let interim = "";
7182
6647
  for (let i = event.resultIndex; i < event.results.length; i++) {
7183
6648
  const result = event.results[i];
7184
- const text2 = result[0]?.transcript ?? "";
7185
- if (result.isFinal) finalText += text2;
7186
- else interim += text2;
6649
+ const text3 = result[0]?.transcript ?? "";
6650
+ if (result.isFinal) finalText += text3;
6651
+ else interim += text3;
7187
6652
  }
7188
6653
  cb.onInterim?.((finalText + interim).trim());
7189
6654
  };
@@ -7286,9 +6751,9 @@ function pickVoice(locale) {
7286
6751
  function stopSpeaking() {
7287
6752
  if (isSpeechOutputSupported()) window.speechSynthesis.cancel();
7288
6753
  }
7289
- function speak(text2, options = { locale: "pt-BR" }) {
6754
+ function speak(text3, options = { locale: "pt-BR" }) {
7290
6755
  if (!isSpeechOutputSupported()) return;
7291
- const content = text2.trim();
6756
+ const content = text3.trim();
7292
6757
  if (!content) return;
7293
6758
  window.speechSynthesis.cancel();
7294
6759
  const utterance = new SpeechSynthesisUtterance(content);
@@ -7418,7 +6883,7 @@ function useChat(options) {
7418
6883
  searchableTools: searchable,
7419
6884
  carriedTools: [...pinned]
7420
6885
  };
7421
- const client3 = getFayzAgentClient(activeConnection);
6886
+ const client2 = getFayzAgentClient(activeConnection);
7422
6887
  const upcoming = Array.from({ length: 7 }, (_, i) => {
7423
6888
  const d = new Date(Date.now() + (i + 1) * 864e5);
7424
6889
  return `${d.toLocaleDateString("pt-BR", { weekday: "long" })}=${d.toISOString().slice(0, 10)}`;
@@ -7449,7 +6914,7 @@ function useChat(options) {
7449
6914
  for (let round = 0; round <= MAX_TOOL_ROUNDS; round++) {
7450
6915
  toolset = buildToolset();
7451
6916
  toolContext.writeTools = toolset.map((t2) => toolByName.get(t2.name)).filter((d) => d?.mode === "persist").map((d) => ({ name: d.name, action: d.permission?.action }));
7452
- const response = await client3.chatStream({
6917
+ const response = await client2.chatStream({
7453
6918
  message,
7454
6919
  toolResults,
7455
6920
  confirmAction,
@@ -7661,8 +7126,8 @@ ${JSON.stringify(snapshot.length === 1 ? snapshot[0] : snapshot)}` : void 0
7661
7126
  return;
7662
7127
  }
7663
7128
  const data = await response.json();
7664
- const text2 = data.choices?.[0]?.message?.content ?? data.content ?? "No response.";
7665
- store.updateLastAssistant(text2);
7129
+ const text3 = data.choices?.[0]?.message?.content ?? data.content ?? "No response.";
7130
+ store.updateLastAssistant(text3);
7666
7131
  } catch {
7667
7132
  store.updateLastAssistant("Sorry, I could not connect. Please try again later.");
7668
7133
  } finally {
@@ -7813,12 +7278,12 @@ var AGENT_WAIT_MS = 2500;
7813
7278
  function prefersReducedMotion2() {
7814
7279
  return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
7815
7280
  }
7816
- function TypewriterText({ text: text2, speed = 26, onDone }) {
7281
+ function TypewriterText({ text: text3, speed = 26, onDone }) {
7817
7282
  const [displayed, setDisplayed] = React133.useState("");
7818
7283
  const indexRef = React133.useRef(0);
7819
7284
  React133.useEffect(() => {
7820
7285
  if (prefersReducedMotion2()) {
7821
- setDisplayed(text2);
7286
+ setDisplayed(text3);
7822
7287
  onDone?.();
7823
7288
  return;
7824
7289
  }
@@ -7826,18 +7291,18 @@ function TypewriterText({ text: text2, speed = 26, onDone }) {
7826
7291
  indexRef.current = 0;
7827
7292
  const interval = setInterval(() => {
7828
7293
  indexRef.current++;
7829
- if (indexRef.current > text2.length) {
7294
+ if (indexRef.current > text3.length) {
7830
7295
  clearInterval(interval);
7831
7296
  onDone?.();
7832
7297
  return;
7833
7298
  }
7834
- setDisplayed(text2.slice(0, indexRef.current));
7299
+ setDisplayed(text3.slice(0, indexRef.current));
7835
7300
  }, speed);
7836
7301
  return () => clearInterval(interval);
7837
- }, [text2, speed]);
7302
+ }, [text3, speed]);
7838
7303
  return /* @__PURE__ */ jsxs("span", { children: [
7839
7304
  displayed,
7840
- 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" })
7841
7306
  ] });
7842
7307
  }
7843
7308
  var STYLE_ID = "chat-fab-anims";
@@ -9816,14 +9281,14 @@ function SettingRow({
9816
9281
  }
9817
9282
  );
9818
9283
  default: {
9819
- const text2 = typeof value === "string" ? value : "";
9820
- const bad = !matchesPattern(setting, text2);
9284
+ const text3 = typeof value === "string" ? value : "";
9285
+ const bad = !matchesPattern(setting, text3);
9821
9286
  return /* @__PURE__ */ jsx(
9822
9287
  TextRow,
9823
9288
  {
9824
9289
  label: setting.label,
9825
9290
  description: description || void 0,
9826
- value: text2,
9291
+ value: text3,
9827
9292
  placeholder: setting.placeholder,
9828
9293
  hint: setting.patternHint,
9829
9294
  invalid: bad,
@@ -10566,10 +10031,10 @@ function useDictation({
10566
10031
  sessionRef.current = startDictation(
10567
10032
  { locale: resolvedLocale, transcribeEndpoint },
10568
10033
  {
10569
- onInterim: (text2) => callbacks.current.onInterim?.(text2),
10570
- onFinal: (text2) => {
10034
+ onInterim: (text3) => callbacks.current.onInterim?.(text3),
10035
+ onFinal: (text3) => {
10571
10036
  finish();
10572
- if (text2) callbacks.current.onTranscript(text2);
10037
+ if (text3) callbacks.current.onTranscript(text3);
10573
10038
  },
10574
10039
  onError: (code) => {
10575
10040
  sessionRef.current = null;
@@ -10892,8 +10357,8 @@ function ChatComposer({
10892
10357
  const parsing = attachments.some((a) => a.status === "parsing");
10893
10358
  const readyAttachments = attachments.filter((a) => a.status === "ready").length;
10894
10359
  const submit = React133.useCallback(
10895
- (text2) => {
10896
- const trimmed = text2.trim();
10360
+ (text3) => {
10361
+ const trimmed = text3.trim();
10897
10362
  const media = useChatStore.getState().composerMedia;
10898
10363
  if (!trimmed && !readyAttachments && !media || parsing || isStreaming || !isConfigured || blocked) return;
10899
10364
  setInput("");
@@ -10907,17 +10372,17 @@ function ChatComposer({
10907
10372
  const dictation = useDictation({
10908
10373
  locale: voice?.locale,
10909
10374
  transcribeEndpoint: voice?.transcribeEndpoint,
10910
- onInterim: (text2) => setInput(text2),
10911
- onTranscript: (text2) => {
10375
+ onInterim: (text3) => setInput(text3),
10376
+ onTranscript: (text3) => {
10912
10377
  if (autoSend) {
10913
- submit(text2);
10378
+ submit(text3);
10914
10379
  return;
10915
10380
  }
10916
- setInput(text2);
10381
+ setInput(text3);
10917
10382
  const el = textareaRef.current;
10918
10383
  if (el) {
10919
10384
  el.focus();
10920
- requestAnimationFrame(() => el.setSelectionRange(text2.length, text2.length));
10385
+ requestAnimationFrame(() => el.setSelectionRange(text3.length, text3.length));
10921
10386
  }
10922
10387
  }
10923
10388
  });
@@ -11070,8 +10535,8 @@ function ChatComposer({
11070
10535
  if (!canAttach) return;
11071
10536
  const files = Array.from(event.clipboardData?.files ?? []);
11072
10537
  if (!files.length) return;
11073
- const text2 = event.clipboardData?.getData("text/plain");
11074
- 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;
11075
10540
  event.preventDefault();
11076
10541
  receiveFiles(files);
11077
10542
  },
@@ -11391,14 +10856,14 @@ function MdLink({ href, children }) {
11391
10856
  }
11392
10857
  );
11393
10858
  }
11394
- function renderInline(text2, keyBase) {
10859
+ function renderInline(text3, keyBase) {
11395
10860
  const out = [];
11396
10861
  const pattern = /(`[^`]+`)|(\*\*[^*]+\*\*)|(\*[^*]+\*)|(\[[^\]]+\]\([^)\s]+\))/g;
11397
10862
  let last = 0;
11398
10863
  let match;
11399
10864
  let i = 0;
11400
- while ((match = pattern.exec(text2)) !== null) {
11401
- 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));
11402
10867
  const token = match[0];
11403
10868
  const key = `${keyBase}-${i++}`;
11404
10869
  if (token.startsWith("`")) {
@@ -11421,7 +10886,7 @@ function renderInline(text2, keyBase) {
11421
10886
  }
11422
10887
  last = match.index + token.length;
11423
10888
  }
11424
- if (last < text2.length) out.push(text2.slice(last));
10889
+ if (last < text3.length) out.push(text3.slice(last));
11425
10890
  return out;
11426
10891
  }
11427
10892
  var LIST_RE = /^(\s*)([-*]|\d+[.)])\s+(.*)$/;
@@ -12202,13 +11667,13 @@ function formatValue(value) {
12202
11667
  if (typeof value === "boolean") return value ? "\u2713" : "\u2014";
12203
11668
  if (Array.isArray(value)) return value.map((v) => formatValue(v)).join(", ");
12204
11669
  if (value && typeof value === "object") return JSON.stringify(value);
12205
- const text2 = String(value);
12206
- 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);
12207
11672
  if (iso) {
12208
- const parsed = new Date(text2);
11673
+ const parsed = new Date(text3);
12209
11674
  if (!Number.isNaN(parsed.getTime())) return parsed.toLocaleString();
12210
11675
  }
12211
- return text2;
11676
+ return text3;
12212
11677
  }
12213
11678
  var PLAIN_DATE = /^\d{4}-\d{2}-\d{2}$/;
12214
11679
  function toInputDate(value, type) {
@@ -12323,7 +11788,7 @@ function usePrefersReducedMotion() {
12323
11788
  return reduced;
12324
11789
  }
12325
11790
  function TypedText({
12326
- text: text2,
11791
+ text: text3,
12327
11792
  className,
12328
11793
  as: Tag3 = "p",
12329
11794
  start = true,
@@ -12331,7 +11796,7 @@ function TypedText({
12331
11796
  onDone
12332
11797
  }) {
12333
11798
  const reduced = usePrefersReducedMotion();
12334
- const [count, setCount] = React133.useState(reduced ? text2.length : 0);
11799
+ const [count, setCount] = React133.useState(reduced ? text3.length : 0);
12335
11800
  const done = React133.useRef(onDone);
12336
11801
  done.current = onDone;
12337
11802
  React133.useEffect(() => {
@@ -12339,19 +11804,19 @@ function TypedText({
12339
11804
  setCount(0);
12340
11805
  return;
12341
11806
  }
12342
- if (reduced || !text2) {
12343
- setCount(text2.length);
11807
+ if (reduced || !text3) {
11808
+ setCount(text3.length);
12344
11809
  const id = setTimeout(() => done.current?.(), 0);
12345
11810
  return () => clearTimeout(id);
12346
11811
  }
12347
11812
  setCount(0);
12348
- 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)));
12349
11814
  let i = 0;
12350
11815
  let timer;
12351
11816
  const first = setTimeout(function tick() {
12352
11817
  i += 1;
12353
11818
  setCount(i);
12354
- if (i >= text2.length) {
11819
+ if (i >= text3.length) {
12355
11820
  done.current?.();
12356
11821
  return;
12357
11822
  }
@@ -12361,11 +11826,11 @@ function TypedText({
12361
11826
  clearTimeout(first);
12362
11827
  clearTimeout(timer);
12363
11828
  };
12364
- }, [text2, reduced, start, startDelay]);
11829
+ }, [text3, reduced, start, startDelay]);
12365
11830
  return /* @__PURE__ */ jsxs(Tag3, { className: cn("grid", className), children: [
12366
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "invisible", style: { gridArea: "1 / 1" }, children: text2 }),
12367
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: text2 }),
12368
- /* @__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) })
12369
11834
  ] });
12370
11835
  }
12371
11836
  function RevealSequence({
@@ -12656,11 +12121,11 @@ function ChatConversation({
12656
12121
  const el = event.currentTarget;
12657
12122
  setAtBottom(el.scrollHeight - el.scrollTop - el.clientHeight < 48);
12658
12123
  };
12659
- const send = (text2) => {
12124
+ const send = (text3) => {
12660
12125
  setView("thread");
12661
12126
  setAtBottom(true);
12662
12127
  setSuggestionsOpen(false);
12663
- sendMessage(text2);
12128
+ sendMessage(text3);
12664
12129
  };
12665
12130
  const queuedPrompt = useChatStore((s) => s.queuedPrompt);
12666
12131
  const consumeQueuedPrompt = useChatStore((s) => s.consumeQueuedPrompt);
@@ -13033,7 +12498,7 @@ function AgentAvatar({
13033
12498
  className
13034
12499
  }) {
13035
12500
  const [failed, setFailed] = React133.useState(false);
13036
- const { box, text: text2, px } = SIZES[size];
12501
+ const { box, text: text3, px } = SIZES[size];
13037
12502
  if (Face) {
13038
12503
  return /* @__PURE__ */ jsx(
13039
12504
  "span",
@@ -13052,7 +12517,7 @@ function AgentAvatar({
13052
12517
  "relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-full",
13053
12518
  "bg-muted font-medium text-muted-foreground",
13054
12519
  box,
13055
- text2,
12520
+ text3,
13056
12521
  className
13057
12522
  ),
13058
12523
  children: [
@@ -13597,10 +13062,10 @@ function TaskQuickAdd({ parentId }) {
13597
13062
  )
13598
13063
  ] });
13599
13064
  }
13600
- var STORAGE_KEY3 = "saas-core:locale";
13065
+ var STORAGE_KEY = "saas-core:locale";
13601
13066
  function readPersistedLocale() {
13602
13067
  try {
13603
- return localStorage.getItem(STORAGE_KEY3) ?? void 0;
13068
+ return localStorage.getItem(STORAGE_KEY) ?? void 0;
13604
13069
  } catch {
13605
13070
  return void 0;
13606
13071
  }
@@ -13612,7 +13077,7 @@ var useLocaleStore = create((set) => ({
13612
13077
  locale: getPersistedLocale(),
13613
13078
  setLocale: (locale) => {
13614
13079
  try {
13615
- localStorage.setItem(STORAGE_KEY3, locale);
13080
+ localStorage.setItem(STORAGE_KEY, locale);
13616
13081
  } catch {
13617
13082
  }
13618
13083
  set({ locale });
@@ -14498,23 +13963,23 @@ var TYPING_LEAD_MS = 420;
14498
13963
  var TYPING_MS_PER_WORD = 55;
14499
13964
  var TYPING_CEILING_MS = 1200;
14500
13965
  var TYPING_FRAME_MS = 45;
14501
- function say(text2, cards) {
13966
+ function say(text3, cards) {
14502
13967
  const chat = useChatStore.getState();
14503
13968
  const id = `guided-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
14504
- const trimmed = text2.trim();
13969
+ const trimmed = text3.trim();
14505
13970
  chat.addMessage({
14506
13971
  id,
14507
13972
  role: "assistant",
14508
13973
  // Empty content is what renders the typing dots (see ChatMessages).
14509
- content: trimmed ? "" : text2,
13974
+ content: trimmed ? "" : text3,
14510
13975
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
14511
13976
  ...cards ? { cards } : {}
14512
13977
  });
14513
13978
  chat.setOpen(true);
14514
- if (trimmed) typeInto(id, text2);
13979
+ if (trimmed) typeInto(id, text3);
14515
13980
  }
14516
- function typeInto(id, text2) {
14517
- const words2 = text2.split(/(\s+)/);
13981
+ function typeInto(id, text3) {
13982
+ const words2 = text3.split(/(\s+)/);
14518
13983
  const wordCount = words2.filter((w) => w.trim()).length;
14519
13984
  const total = Math.min(TYPING_CEILING_MS, wordCount * TYPING_MS_PER_WORD);
14520
13985
  const frames = Math.max(1, Math.round(total / TYPING_FRAME_MS));
@@ -14524,7 +13989,7 @@ function typeInto(id, text2) {
14524
13989
  const finish = () => {
14525
13990
  if (timer) clearTimeout(timer);
14526
13991
  typers.delete(finish);
14527
- useChatStore.getState().setMessageContent(id, text2);
13992
+ useChatStore.getState().setMessageContent(id, text3);
14528
13993
  };
14529
13994
  const step = () => {
14530
13995
  cursor += perFrame;
@@ -14544,8 +14009,8 @@ function flushTyping() {
14544
14009
  var BEAT_FLOOR_MS = 1400;
14545
14010
  var MS_PER_WORD = 260;
14546
14011
  var BEAT_CEILING_MS = 6e3;
14547
- function readingTime(text2) {
14548
- const words2 = text2.trim().split(/\s+/).length;
14012
+ function readingTime(text3) {
14013
+ const words2 = text3.trim().split(/\s+/).length;
14549
14014
  return Math.min(BEAT_CEILING_MS, BEAT_FLOOR_MS + words2 * MS_PER_WORD);
14550
14015
  }
14551
14016
  var NAV_MS = 1e3;
@@ -16074,7 +15539,7 @@ function ActivationProvider() {
16074
15539
  const orgName = useOrganizationStore((s) => s.currentOrg?.name);
16075
15540
  const user = useAuthStore((s) => s.user);
16076
15541
  const setCatalog = useActivationStore((s) => s.setCatalog);
16077
- const load = useActivationStore((s) => s.load);
15542
+ const load2 = useActivationStore((s) => s.load);
16078
15543
  const programs = runtime?.onboardingPrograms ?? [];
16079
15544
  const settingsIds = useSettingsTabsStore((s) => s.ids);
16080
15545
  const routeKey = (runtime?.routes.length ?? 0) + ":" + settingsIds.join(",");
@@ -16097,7 +15562,7 @@ function ActivationProvider() {
16097
15562
  if (!tenantId2) return;
16098
15563
  let cancelled = false;
16099
15564
  void (async () => {
16100
- await load(tenantId2);
15565
+ await load2(tenantId2);
16101
15566
  if (cancelled || !user) return;
16102
15567
  const rows = useActivationStore.getState().rows ?? [];
16103
15568
  const stale = /* @__PURE__ */ new Set([
@@ -16119,12 +15584,12 @@ function ActivationProvider() {
16119
15584
  userName: user.fullName || user.email,
16120
15585
  items: missing
16121
15586
  });
16122
- if (ok && !cancelled) await load(tenantId2);
15587
+ if (ok && !cancelled) await load2(tenantId2);
16123
15588
  })();
16124
15589
  return () => {
16125
15590
  cancelled = true;
16126
15591
  };
16127
- }, [tenantId2, catalog, answers, hasRoute, settingsIds, user?.id, load]);
15592
+ }, [tenantId2, catalog, answers, hasRoute, settingsIds, user?.id, load2]);
16128
15593
  React133.useEffect(() => {
16129
15594
  if (!tenantId2) {
16130
15595
  useBusinessProfileStore.getState().clear();
@@ -16201,8 +15666,8 @@ var useHandbookStore = create((set, get) => ({
16201
15666
  open: async (path) => {
16202
15667
  const { tenantId: tenantId2, pages } = get();
16203
15668
  if (!tenantId2) return null;
16204
- const cached3 = (pages ?? []).find((p) => p.path === path);
16205
- if (cached3) return cached3;
15669
+ const cached2 = (pages ?? []).find((p) => p.path === path);
15670
+ if (cached2) return cached2;
16206
15671
  return readHandbookPage(tenantId2, path);
16207
15672
  },
16208
15673
  write: async (input) => {
@@ -17048,14 +16513,14 @@ function NotebookRailPanel() {
17048
16513
  function HandbookProvider() {
17049
16514
  const tenantId2 = useOrganizationStore((s) => s.currentOrg?.id);
17050
16515
  const userId = useAuthStore((s) => s.user?.id);
17051
- const load = useHandbookStore((s) => s.load);
16516
+ const load2 = useHandbookStore((s) => s.load);
17052
16517
  const setUser = useHandbookStore((s) => s.setUser);
17053
16518
  React133.useEffect(() => {
17054
16519
  setUser(userId);
17055
16520
  }, [userId, setUser]);
17056
16521
  React133.useEffect(() => {
17057
- if (tenantId2) void load(tenantId2);
17058
- }, [tenantId2, load]);
16522
+ if (tenantId2) void load2(tenantId2);
16523
+ }, [tenantId2, load2]);
17059
16524
  useLocalNotesImport(tenantId2, userId);
17060
16525
  return /* @__PURE__ */ jsxs(Fragment, { children: [
17061
16526
  /* @__PURE__ */ jsx(NotebookRailPanel, {}),
@@ -17113,9 +16578,9 @@ function useUnitBootstrap() {
17113
16578
  const orgId = tenant?.org?.id;
17114
16579
  React133.useEffect(() => {
17115
16580
  if (!orgId) return;
17116
- const { loadedFor, load, reset } = useUnitStore.getState();
16581
+ const { loadedFor, load: load2, reset } = useUnitStore.getState();
17117
16582
  if (loadedFor && loadedFor !== orgId) reset();
17118
- void load(orgId, userId);
16583
+ void load2(orgId, userId);
17119
16584
  }, [orgId, userId]);
17120
16585
  }
17121
16586
  var NO_EXTRA_ROLE = "__none__";
@@ -17501,14 +16966,14 @@ function startFayzEventBridge(override) {
17501
16966
  };
17502
16967
  }
17503
16968
  debug(`started \u2192 ${connection.apiBaseUrl} (project ${connection.projectId})`);
17504
- const client3 = createFayzEventsClient({
16969
+ const client2 = createFayzEventsClient({
17505
16970
  baseUrl: connection.apiBaseUrl,
17506
16971
  projectId: connection.projectId,
17507
16972
  publishableKey: connection.publishableKey
17508
16973
  });
17509
16974
  const off = registerEventSink((event) => {
17510
- debug(`enqueue ${event.key}`, { tenantId: event.tenantId, pending: client3.pending() + 1 });
17511
- client3.enqueue({
16975
+ debug(`enqueue ${event.key}`, { tenantId: event.tenantId, pending: client2.pending() + 1 });
16976
+ client2.enqueue({
17512
16977
  // The dedupe id is minted at the sink, once per emission — a transport
17513
16978
  // retry reuses it, so the server never runs the same fact twice.
17514
16979
  id: crypto.randomUUID(),
@@ -17520,7 +16985,7 @@ function startFayzEventBridge(override) {
17520
16985
  subject: event.subject
17521
16986
  });
17522
16987
  });
17523
- active = { client: client3, off };
16988
+ active = { client: client2, off };
17524
16989
  return stopFayzEventBridge;
17525
16990
  }
17526
16991
  function stopFayzEventBridge() {
@@ -17773,6 +17238,24 @@ function tripletLuminance(triplet) {
17773
17238
  });
17774
17239
  return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2];
17775
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
+ }
17776
17259
  function inkOnTriplet(triplet) {
17777
17260
  const l = tripletLuminance(triplet);
17778
17261
  return l != null && l > 0.45 ? "0 0% 10%" : "0 0% 100%";
@@ -17960,6 +17443,9 @@ function applyTheme(theme, element) {
17960
17443
  target.style.setProperty(cssVar, value);
17961
17444
  }
17962
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);
17963
17449
  persistBootPalette(theme.colors);
17964
17450
  }
17965
17451
  function hexToHslTriplet(hex) {
@@ -17986,14 +17472,14 @@ function hexToHslTriplet(hex) {
17986
17472
  }
17987
17473
 
17988
17474
  // src/stores/theme.store.ts
17989
- var STORAGE_KEY4 = "saas-core:theme-mode";
17475
+ var STORAGE_KEY2 = "saas-core:theme-mode";
17990
17476
  function getSystemPreference() {
17991
17477
  if (typeof window === "undefined") return "light";
17992
17478
  return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
17993
17479
  }
17994
17480
  function getSavedMode() {
17995
17481
  if (typeof window === "undefined") return "light";
17996
- const saved = localStorage.getItem(STORAGE_KEY4);
17482
+ const saved = localStorage.getItem(STORAGE_KEY2);
17997
17483
  if (saved === "light" || saved === "dark" || saved === "system") return saved;
17998
17484
  return "light";
17999
17485
  }
@@ -18045,7 +17531,7 @@ function createThemeStore() {
18045
17531
  const resolved = resolveMode(mode);
18046
17532
  set({ mode, resolvedMode: resolved });
18047
17533
  if (typeof window !== "undefined") {
18048
- localStorage.setItem(STORAGE_KEY4, mode);
17534
+ localStorage.setItem(STORAGE_KEY2, mode);
18049
17535
  }
18050
17536
  const { overrides } = get();
18051
17537
  const baseTheme = resolved === "dark" ? darkTheme : lightTheme;
@@ -18375,12 +17861,12 @@ function PublicSurveyPage({ token, appName }) {
18375
17861
  const [failed, setFailed] = React133__default.useState(null);
18376
17862
  React133__default.useEffect(() => {
18377
17863
  let alive = true;
18378
- const client3 = getFayzSupabaseClientOptional();
18379
- if (!client3) {
17864
+ const client2 = getFayzSupabaseClientOptional();
17865
+ if (!client2) {
18380
17866
  setLoaded({ status: "not_found" });
18381
17867
  return;
18382
17868
  }
18383
- 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 }) => {
18384
17870
  if (!alive) return;
18385
17871
  setLoaded(error ? { status: "not_found" } : data);
18386
17872
  });
@@ -18399,9 +17885,9 @@ function PublicSurveyPage({ token, appName }) {
18399
17885
  if (missing.length > 0 || sending) return;
18400
17886
  setSending(true);
18401
17887
  setFailed(null);
18402
- const client3 = getFayzSupabaseClientOptional();
17888
+ const client2 = getFayzSupabaseClientOptional();
18403
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() !== "");
18404
- const { data, error } = await client3.rpc("crm_survey_invite_submit", {
17890
+ const { data, error } = await client2.rpc("crm_survey_invite_submit", {
18405
17891
  p_token: token,
18406
17892
  p_answers: answers,
18407
17893
  p_respondent_name: name.trim() || null
@@ -19018,8 +18504,8 @@ function coerceField(field, value) {
19018
18504
  }
19019
18505
  const first = Array.isArray(value) ? value[0] : value;
19020
18506
  if (typeof first !== "string") return void 0;
19021
- const text2 = field.normalize ? field.normalize(first) : first.trim();
19022
- return text2 || void 0;
18507
+ const text3 = field.normalize ? field.normalize(first) : first.trim();
18508
+ return text3 || void 0;
19023
18509
  }
19024
18510
 
19025
18511
  // src/onboarding/analyze-site.ts
@@ -19440,14 +18926,14 @@ var useAppDirectoryStore = create((set, get) => ({
19440
18926
  load: async (tenantId2, currentAppId, deps) => {
19441
18927
  const state = get();
19442
18928
  if (state.status !== "idle" && state.tenantId === tenantId2) return;
19443
- const client3 = deps?.client === void 0 ? getFayzSupabaseClientOptional() : deps.client;
19444
- if (!client3) {
18929
+ const client2 = deps?.client === void 0 ? getFayzSupabaseClientOptional() : deps.client;
18930
+ if (!client2) {
19445
18931
  set({ status: "done", tenantId: tenantId2 });
19446
18932
  return;
19447
18933
  }
19448
18934
  set({ status: "loading", tenantId: tenantId2 });
19449
18935
  try {
19450
- const config = await fetchAppConfig(client3, { tenantId: tenantId2 });
18936
+ const config = await fetchAppConfig(client2, { tenantId: tenantId2 });
19451
18937
  set({ apps: normalize(config.apps, currentAppId), status: "done", tenantId: tenantId2 });
19452
18938
  } catch {
19453
18939
  set({ status: "done", tenantId: tenantId2 });
@@ -19463,10 +18949,10 @@ function resetAppDirectory() {
19463
18949
  function useAppDirectory() {
19464
18950
  const tenantId2 = useActiveTenantId();
19465
18951
  const apps = useAppDirectoryStore((s) => s.apps);
19466
- const load = useAppDirectoryStore((s) => s.load);
18952
+ const load2 = useAppDirectoryStore((s) => s.load);
19467
18953
  React133.useEffect(() => {
19468
- if (tenantId2) void load(tenantId2, resolveAppId());
19469
- }, [tenantId2, load]);
18954
+ if (tenantId2) void load2(tenantId2, resolveAppId());
18955
+ }, [tenantId2, load2]);
19470
18956
  return { apps };
19471
18957
  }
19472
18958
  var FAMILY_SUFFIX = "Control";
@@ -20292,9 +19778,9 @@ function WorkspaceUnitRow({ canCreate = true }) {
20292
19778
  }
20293
19779
  var TABLE2 = "published_sites";
20294
19780
  function db() {
20295
- const client3 = getSupabaseClientOptional();
20296
- if (!client3) throw new Error("[fayz-projects] Supabase not initialized");
20297
- return client3;
19781
+ const client2 = getSupabaseClientOptional();
19782
+ if (!client2) throw new Error("[fayz-projects] Supabase not initialized");
19783
+ return client2;
20298
19784
  }
20299
19785
  function tenantId() {
20300
19786
  return useOrganizationStore.getState().currentOrg?.id ?? getActiveTenantId();
@@ -20438,7 +19924,7 @@ function SeuSiteWidget({ fallback, onEdit }) {
20438
19924
  const t = useTranslation();
20439
19925
  const currentOrgId = useOrganizationStore((s) => s.currentOrg?.id);
20440
19926
  const projects = useFayzProjectsStore((s) => s.projects);
20441
- const load = useFayzProjectsStore((s) => s.load);
19927
+ const load2 = useFayzProjectsStore((s) => s.load);
20442
19928
  const loadedFor = useFayzProjectsStore((s) => s.loadedFor);
20443
19929
  const collapsed = useLayoutStore((s) => s.sidebarCollapsed);
20444
19930
  const [selectedId, setSelectedId] = React133.useState(null);
@@ -20462,8 +19948,8 @@ function SeuSiteWidget({ fallback, onEdit }) {
20462
19948
  };
20463
19949
  React133.useEffect(() => () => cancelClose(), []);
20464
19950
  React133.useEffect(() => {
20465
- if (loadedFor !== (currentOrgId ?? null)) void load(currentOrgId);
20466
- }, [currentOrgId, loadedFor, load]);
19951
+ if (loadedFor !== (currentOrgId ?? null)) void load2(currentOrgId);
19952
+ }, [currentOrgId, loadedFor, load2]);
20467
19953
  const active2 = projects.find((p) => p.id === selectedId) ?? defaultProjectOf(projects) ?? synthFromFallback(fallback);
20468
19954
  if (!active2) return null;
20469
19955
  const Icon = KIND_ICON2[active2.kind] ?? Globe;
@@ -21537,17 +21023,17 @@ function ConsentBody({
21537
21023
  busy
21538
21024
  }) {
21539
21025
  if (!payload) return /* @__PURE__ */ jsx(ConsentSkeleton, {});
21540
- const { client: client3, access, organizations } = payload;
21026
+ const { client: client2, access, organizations } = payload;
21541
21027
  const org = organizations.find((o) => o.tenantId === tenantId2);
21542
- 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);
21543
21029
  return /* @__PURE__ */ jsxs(Fragment, { children: [
21544
21030
  /* @__PURE__ */ jsxs("div", { className: "mb-6 flex items-center justify-center gap-3", children: [
21545
- /* @__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 }),
21546
21032
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "\u21C4" }),
21547
21033
  /* @__PURE__ */ jsx(MarkBadge, { fallback: product, children: logo })
21548
21034
  ] }),
21549
21035
  /* @__PURE__ */ jsxs("h1", { className: "text-center text-xl font-semibold text-foreground", children: [
21550
- client3.name,
21036
+ client2.name,
21551
21037
  " quer acessar seus dados"
21552
21038
  ] }),
21553
21039
  /* @__PURE__ */ jsxs("dl", { className: "mt-6 divide-y divide-border overflow-hidden rounded-xl border border-border text-sm", children: [
@@ -21556,8 +21042,8 @@ function ConsentBody({
21556
21042
  {
21557
21043
  label: "Aplicativo",
21558
21044
  value: /* @__PURE__ */ jsxs("span", { children: [
21559
- client3.name,
21560
- 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
21561
21047
  // perfectly legitimate. But the user is about to hand over an
21562
21048
  // organization's data, and "this name is self-declared" is a
21563
21049
  // fact they are entitled to before deciding.
@@ -21565,14 +21051,14 @@ function ConsentBody({
21565
21051
  ] })
21566
21052
  }
21567
21053
  ),
21568
- client3.website && /* @__PURE__ */ jsx(
21054
+ client2.website && /* @__PURE__ */ jsx(
21569
21055
  Row2,
21570
21056
  {
21571
21057
  label: "Site",
21572
- 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 })
21573
21059
  }
21574
21060
  ),
21575
- /* @__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 }) }),
21576
21062
  /* @__PURE__ */ jsx(
21577
21063
  Row2,
21578
21064
  {
@@ -21619,7 +21105,7 @@ function ConsentBody({
21619
21105
  ] }),
21620
21106
  /* @__PURE__ */ jsxs("p", { className: "mt-5 text-xs leading-relaxed text-muted-foreground", children: [
21621
21107
  "Ao aprovar, ",
21622
- client3.name,
21108
+ client2.name,
21623
21109
  " poder\xE1 ler os dados",
21624
21110
  org ? ` de ${org.name}` : " da organiza\xE7\xE3o escolhida",
21625
21111
  " at\xE9 voc\xEA desconectar. Voc\xEA pode desfazer isso a qualquer momento em ",
@@ -22117,7 +21603,7 @@ var ICON = {
22117
21603
  failed: { Icon: XCircle, className: "text-destructive", label: "N\xE3o foi" }
22118
21604
  };
22119
21605
  function ConnectorDeliveries({
22120
- load,
21606
+ load: load2,
22121
21607
  providerName,
22122
21608
  limit = 10
22123
21609
  }) {
@@ -22125,7 +21611,7 @@ function ConnectorDeliveries({
22125
21611
  const [rows, setRows] = React133__default.useState(null);
22126
21612
  React133__default.useEffect(() => {
22127
21613
  let cancelled = false;
22128
- void load({ limit }).then((r) => {
21614
+ void load2({ limit }).then((r) => {
22129
21615
  if (!cancelled) setRows(r);
22130
21616
  }).catch(() => {
22131
21617
  if (!cancelled) setRows([]);
@@ -22133,7 +21619,7 @@ function ConnectorDeliveries({
22133
21619
  return () => {
22134
21620
  cancelled = true;
22135
21621
  };
22136
- }, [load, limit]);
21622
+ }, [load2, limit]);
22137
21623
  if (rows === null) {
22138
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" }) });
22139
21625
  }
@@ -22292,7 +21778,7 @@ function UnitModeCard() {
22292
21778
  const unitMode = useUnitStore((s) => s.unitMode);
22293
21779
  const units = useUnitStore((s) => s.units);
22294
21780
  const setMode = useUnitStore((s) => s.setMode);
22295
- const load = useUnitStore((s) => s.load);
21781
+ const load2 = useUnitStore((s) => s.load);
22296
21782
  const [unbound, setUnbound] = React133.useState(null);
22297
21783
  const [bindEveryone, setBindEveryone] = React133.useState(true);
22298
21784
  const [pending2, setPending] = React133.useState(null);
@@ -22322,7 +21808,7 @@ function UnitModeCard() {
22322
21808
  await setUnitModeRemote(org.id, on);
22323
21809
  setMode(on);
22324
21810
  emitDataChanged();
22325
- await load(org.id, user?.id);
21811
+ await load2(org.id, user?.id);
22326
21812
  toast.success(on ? "Gest\xE3o por unidades ligada" : "Gest\xE3o por unidades desligada");
22327
21813
  } catch (err) {
22328
21814
  toast.error("N\xE3o deu para mudar", { description: err?.message });
@@ -22440,11 +21926,11 @@ function ConnectedCompanySettings() {
22440
21926
  const handleSave = async (data) => {
22441
21927
  if (!adapter || !currentOrg) return;
22442
21928
  try {
22443
- const currentSettings = toTenantSettings(currentOrg.settings);
21929
+ const raw = currentOrg.settings && typeof currentOrg.settings === "object" ? currentOrg.settings : {};
22444
21930
  const updated = await adapter.updateOrg(currentOrg.id, {
22445
21931
  name: data.name,
22446
21932
  settings: {
22447
- ...currentSettings,
21933
+ ...raw,
22448
21934
  timezone: data.timezone,
22449
21935
  currency: data.currency
22450
21936
  }
@@ -22570,11 +22056,11 @@ function UserProfile({ user, onSave, onAvatarChange }) {
22570
22056
  ] }) })
22571
22057
  ] }) });
22572
22058
  }
22573
- function client2() {
22059
+ function client() {
22574
22060
  return getSupabaseClientOptional();
22575
22061
  }
22576
22062
  async function fetchMyPersonRecord(tenantId2, userId) {
22577
- const db2 = client2();
22063
+ const db2 = client();
22578
22064
  if (!db2) return null;
22579
22065
  const { data, error } = await db2.from("v_team_members").select("person_id").eq("tenant_id", tenantId2).eq("user_id", userId).maybeSingle();
22580
22066
  if (error || !data?.person_id) return null;
@@ -22583,7 +22069,7 @@ async function fetchMyPersonRecord(tenantId2, userId) {
22583
22069
  return { id: person.id, name: person.name ?? "", kind: person.kind ?? null };
22584
22070
  }
22585
22071
  async function findMyPersonCandidate(tenantId2, email, staffKinds) {
22586
- const db2 = client2();
22072
+ const db2 = client();
22587
22073
  if (!db2 || !email || staffKinds.length === 0) return null;
22588
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);
22589
22075
  if (error || !data || data.length !== 1) return null;
@@ -22593,13 +22079,13 @@ async function findMyPersonCandidate(tenantId2, email, staffKinds) {
22593
22079
  return { id: candidate.id, name: candidate.name ?? "", kind: candidate.kind ?? null };
22594
22080
  }
22595
22081
  async function linkPersonToLogin(tenantId2, userId, personId) {
22596
- const db2 = client2();
22082
+ const db2 = client();
22597
22083
  if (!db2) throw new Error("sem conex\xE3o");
22598
22084
  const { error } = await db2.rpc("people_link_membership", { p_person: personId, p_user: userId });
22599
22085
  if (error) throw error;
22600
22086
  }
22601
22087
  async function fetchMyPersonId(tenantId2, userId) {
22602
- const db2 = client2();
22088
+ const db2 = client();
22603
22089
  if (!db2) return null;
22604
22090
  const { data, error } = await db2.from("v_team_members").select("person_id").eq("tenant_id", tenantId2).eq("user_id", userId).maybeSingle();
22605
22091
  if (error) return null;
@@ -22622,7 +22108,7 @@ function useMyPersonId(enabled = true) {
22622
22108
  return personId;
22623
22109
  }
22624
22110
  async function fetchPersonAccess(personId) {
22625
- const db2 = client2();
22111
+ const db2 = client();
22626
22112
  if (!db2) return null;
22627
22113
  const { data, error } = await db2.from("v_team_members").select("id, user_id, role, created_at").eq("person_id", personId).maybeSingle();
22628
22114
  if (error || !data) return null;
@@ -22637,7 +22123,7 @@ async function fetchPersonAccess(personId) {
22637
22123
  };
22638
22124
  }
22639
22125
  async function setPersonEmail(personId, email) {
22640
- const db2 = client2();
22126
+ const db2 = client();
22641
22127
  if (!db2) throw new Error("sem conex\xE3o");
22642
22128
  const { error } = await db2.from("people").update({ email }).eq("id", personId);
22643
22129
  if (error) throw error;
@@ -22674,15 +22160,15 @@ function MyWorkspaceCard() {
22674
22160
  const [linking, setLinking] = React133.useState(false);
22675
22161
  const orgId = currentOrg?.id;
22676
22162
  const userId = user?.id;
22677
- const load = React133.useCallback(async () => {
22163
+ const load2 = React133.useCallback(async () => {
22678
22164
  if (!orgId || !userId) return;
22679
22165
  const linked = await fetchMyPersonRecord(orgId, userId);
22680
22166
  setPerson(linked);
22681
22167
  setCandidate(linked ? null : await findMyPersonCandidate(orgId, user?.email, staffKinds));
22682
22168
  }, [orgId, userId, user?.email, staffKinds]);
22683
22169
  React133.useEffect(() => {
22684
- void load();
22685
- }, [load]);
22170
+ void load2();
22171
+ }, [load2]);
22686
22172
  if (!currentOrg) return null;
22687
22173
  const myRole = members.find((m) => m.userId === userId)?.profileName;
22688
22174
  async function link() {
@@ -22691,7 +22177,7 @@ function MyWorkspaceCard() {
22691
22177
  try {
22692
22178
  await linkPersonToLogin(orgId, userId, candidate.id);
22693
22179
  toast.success(`Login ligado ao cadastro de ${candidate.name}`);
22694
- await load();
22180
+ await load2();
22695
22181
  } catch (err) {
22696
22182
  toast.error("S\xF3 um administrador pode ligar um login a um cadastro", { description: err?.message });
22697
22183
  } finally {
@@ -22795,9 +22281,9 @@ function useUserLabel(userId) {
22795
22281
  const [resolved, setResolved] = useState(null);
22796
22282
  useEffect(() => {
22797
22283
  if (!userId || fromMembers) return;
22798
- const cached3 = userLabelCache.get(userId);
22799
- if (cached3 !== void 0) {
22800
- setResolved(cached3);
22284
+ const cached2 = userLabelCache.get(userId);
22285
+ if (cached2 !== void 0) {
22286
+ setResolved(cached2);
22801
22287
  return;
22802
22288
  }
22803
22289
  let alive = true;
@@ -22983,15 +22469,15 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
22983
22469
  const [deleting, setDeleting] = useState(null);
22984
22470
  const ownerId = record?.id;
22985
22471
  const db2 = () => getSupabaseClientOptional();
22986
- const load = useCallback(async () => {
22987
- const client3 = db2();
22988
- if (!client3 || !ownerId) {
22472
+ const load2 = useCallback(async () => {
22473
+ const client2 = db2();
22474
+ if (!client2 || !ownerId) {
22989
22475
  setLoading(false);
22990
22476
  return;
22991
22477
  }
22992
22478
  setLoading(true);
22993
22479
  setError(null);
22994
- let q = client3.from("addresses").select("*").eq("owner_id", ownerId);
22480
+ let q = client2.from("addresses").select("*").eq("owner_id", ownerId);
22995
22481
  if (ownerType !== "person") q = q.eq("owner_type", ownerType);
22996
22482
  const { data, error: err } = await q.order("is_default", { ascending: false });
22997
22483
  if (err) setError(err.message);
@@ -22999,8 +22485,8 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
22999
22485
  setLoading(false);
23000
22486
  }, [ownerId, ownerType]);
23001
22487
  useEffect(() => {
23002
- void load();
23003
- }, [load]);
22488
+ void load2();
22489
+ }, [load2]);
23004
22490
  const openCreate = () => {
23005
22491
  setEditing(null);
23006
22492
  setForm(single ? { ...EMPTY_FORM, kind: "main", is_default: true } : EMPTY_FORM);
@@ -23090,8 +22576,8 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
23090
22576
  }
23091
22577
  };
23092
22578
  const handleSave = async () => {
23093
- const client3 = db2();
23094
- if (!client3 || !ownerId || !canSave) return;
22579
+ const client2 = db2();
22580
+ if (!client2 || !ownerId || !canSave) return;
23095
22581
  const tenantId2 = getActiveTenantId();
23096
22582
  if (!tenantId2) {
23097
22583
  toast.error(t("crud.archetype.addresses.noTenant"));
@@ -23117,12 +22603,12 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
23117
22603
  longitude: coordPair(form).lng
23118
22604
  };
23119
22605
  if (form.is_default) {
23120
- 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);
23121
22607
  if (editing) q = q.neq("id", editing.id);
23122
22608
  const { error: clearErr } = await q;
23123
22609
  if (clearErr) throw clearErr;
23124
22610
  }
23125
- 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({
23126
22612
  ...values,
23127
22613
  tenant_id: tenantId2,
23128
22614
  owner_type: ownerType,
@@ -23130,7 +22616,7 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
23130
22616
  });
23131
22617
  if (err) throw err;
23132
22618
  setFormOpen(false);
23133
- await load();
22619
+ await load2();
23134
22620
  toast.success(editing ? t("crud.archetype.addresses.updated") : t("crud.archetype.addresses.created"));
23135
22621
  } catch (e) {
23136
22622
  toast.error(t("crud.archetype.addresses.saveFailed"), { description: e?.message });
@@ -23139,15 +22625,15 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
23139
22625
  }
23140
22626
  };
23141
22627
  const handleDelete = async () => {
23142
- const client3 = db2();
23143
- if (!client3 || !deleting) return;
23144
- 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);
23145
22631
  setDeleting(null);
23146
22632
  if (err) {
23147
22633
  toast.error(t("crud.archetype.addresses.deleteFailed"), { description: err.message });
23148
22634
  return;
23149
22635
  }
23150
- await load();
22636
+ await load2();
23151
22637
  toast.success(t("crud.archetype.addresses.deleted"));
23152
22638
  };
23153
22639
  if (loading) {
@@ -23424,28 +22910,28 @@ function PayeeAccountsSection({
23424
22910
  const canEdit = can("financial", "edit");
23425
22911
  const canDelete = can("financial", "delete");
23426
22912
  const db2 = () => getSupabaseClientOptional();
23427
- const load = useCallback(async () => {
23428
- const client3 = db2();
23429
- if (!client3 || !ownerId) {
22913
+ const load2 = useCallback(async () => {
22914
+ const client2 = db2();
22915
+ if (!client2 || !ownerId) {
23430
22916
  setLoading(false);
23431
22917
  return;
23432
22918
  }
23433
22919
  setLoading(true);
23434
22920
  setError(null);
23435
- 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 });
23436
22922
  if (err) setError(err.message);
23437
22923
  else setRows(data ?? []);
23438
22924
  setLoading(false);
23439
22925
  }, [ownerId, ownerType]);
23440
22926
  useEffect(() => {
23441
- void load();
23442
- }, [load]);
22927
+ void load2();
22928
+ }, [load2]);
23443
22929
  const set = (key, value) => setForm((prev) => ({ ...prev, [key]: value }));
23444
22930
  const canSave = !!blank(form.accountNumber ?? null) || !!blank(form.pixKey ?? null);
23445
22931
  const handleSave = async () => {
23446
- const client3 = db2();
22932
+ const client2 = db2();
23447
22933
  const tenantId2 = getActiveTenantId();
23448
- if (!client3 || !ownerId || !tenantId2 || !canSave) return;
22934
+ if (!client2 || !ownerId || !tenantId2 || !canSave) return;
23449
22935
  setSaving(true);
23450
22936
  try {
23451
22937
  const pix = form.method === "pix";
@@ -23466,9 +22952,9 @@ function PayeeAccountsSection({
23466
22952
  holder_document: b("holderDocument")
23467
22953
  };
23468
22954
  if (form.is_default) {
23469
- 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);
23470
22956
  }
23471
- 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({
23472
22958
  ...values,
23473
22959
  tenant_id: tenantId2,
23474
22960
  owner_type: ownerType,
@@ -23476,7 +22962,7 @@ function PayeeAccountsSection({
23476
22962
  });
23477
22963
  if (err) throw err;
23478
22964
  setFormOpen(false);
23479
- await load();
22965
+ await load2();
23480
22966
  toast.success(t("crud.archetype.payeeAccounts.saved"));
23481
22967
  } catch (e) {
23482
22968
  toast.error(t("crud.archetype.payeeAccounts.saveFailed"), { description: e?.message });
@@ -23485,15 +22971,15 @@ function PayeeAccountsSection({
23485
22971
  }
23486
22972
  };
23487
22973
  const handleDelete = async () => {
23488
- const client3 = db2();
23489
- if (!client3 || !deleting) return;
23490
- 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);
23491
22977
  setDeleting(null);
23492
22978
  if (err) {
23493
22979
  toast.error(t("crud.archetype.payeeAccounts.deleteFailed"), { description: err.message });
23494
22980
  return;
23495
22981
  }
23496
- await load();
22982
+ await load2();
23497
22983
  toast.success(t("crud.archetype.payeeAccounts.deleted"));
23498
22984
  };
23499
22985
  if (!canRead) return null;
@@ -23784,7 +23270,7 @@ function CrudRecordModal({
23784
23270
  onSaved,
23785
23271
  entityDef,
23786
23272
  mode = "edit",
23787
- load,
23273
+ load: load2,
23788
23274
  initialData,
23789
23275
  save,
23790
23276
  title,
@@ -23801,14 +23287,14 @@ function CrudRecordModal({
23801
23287
  React133.useEffect(() => {
23802
23288
  if (!open) return;
23803
23289
  setError(null);
23804
- if (mode === "create" || !load) {
23290
+ if (mode === "create" || !load2) {
23805
23291
  setRecord(initialData ?? {});
23806
23292
  setLoading(false);
23807
23293
  return;
23808
23294
  }
23809
23295
  let cancelled = false;
23810
23296
  setLoading(true);
23811
- load().then((found) => {
23297
+ load2().then((found) => {
23812
23298
  if (!cancelled) setRecord(found);
23813
23299
  }).catch((err) => {
23814
23300
  if (!cancelled) setError(errorMessage(err));
@@ -23939,6 +23425,57 @@ function useRelationOptions(r) {
23939
23425
  const labelFor2 = (value) => options.find((o) => o.value === String(value))?.label ?? "";
23940
23426
  return { options, loading, labelFor: labelFor2 };
23941
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
+ }
23942
23479
  function RelationSelect({
23943
23480
  relation,
23944
23481
  value,
@@ -23948,6 +23485,11 @@ function RelationSelect({
23948
23485
  placeholder
23949
23486
  }) {
23950
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
+ }
23951
23493
  return /* @__PURE__ */ jsxs(
23952
23494
  Select,
23953
23495
  {
@@ -24053,7 +23595,7 @@ function RelatedSection({ parentId, related, compact }) {
24053
23595
  const [error, setError] = React133.useState(null);
24054
23596
  const [adding, setAdding] = React133.useState(false);
24055
23597
  const [draft, setDraft] = React133.useState(null);
24056
- const load = React133.useCallback(async () => {
23598
+ const load2 = React133.useCallback(async () => {
24057
23599
  if (orfa) {
24058
23600
  setLoading(false);
24059
23601
  return;
@@ -24070,8 +23612,8 @@ function RelatedSection({ parentId, related, compact }) {
24070
23612
  }
24071
23613
  }, [provider2, orfa]);
24072
23614
  React133.useEffect(() => {
24073
- void load();
24074
- }, [load]);
23615
+ void load2();
23616
+ }, [load2]);
24075
23617
  const guardadas = React133.useRef([]);
24076
23618
  guardadas.current = rows;
24077
23619
  React133.useEffect(() => {
@@ -24186,7 +23728,7 @@ function RelatedSection({ parentId, related, compact }) {
24186
23728
  try {
24187
23729
  await provider2.create(pronto);
24188
23730
  setDraft(null);
24189
- await load();
23731
+ await load2();
24190
23732
  } catch (e) {
24191
23733
  toast.error(errorMessage(e));
24192
23734
  } finally {
@@ -24203,7 +23745,7 @@ function RelatedSection({ parentId, related, compact }) {
24203
23745
  }
24204
23746
  try {
24205
23747
  await provider2.create(copia);
24206
- await load();
23748
+ await load2();
24207
23749
  } catch (e) {
24208
23750
  toast.error(errorMessage(e));
24209
23751
  }
@@ -24423,7 +23965,7 @@ function RelatedSection({ parentId, related, compact }) {
24423
23965
  mode: "create",
24424
23966
  save: async (data) => {
24425
23967
  await provider2.create(data);
24426
- await load();
23968
+ await load2();
24427
23969
  },
24428
23970
  onSaved: () => setAdding(false)
24429
23971
  }
@@ -25167,10 +24709,10 @@ function useSuggestions(table) {
25167
24709
  const [tags, setTags] = useState(() => table ? suggestionCache.get(table) ?? [] : []);
25168
24710
  useEffect(() => {
25169
24711
  if (!table || suggestionCache.has(table)) return;
25170
- const client3 = getSupabaseClientOptional();
25171
- if (!client3) return;
24712
+ const client2 = getSupabaseClientOptional();
24713
+ if (!client2) return;
25172
24714
  let alive = true;
25173
- 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 }) => {
25174
24716
  const all = /* @__PURE__ */ new Set();
25175
24717
  for (const r of data ?? []) for (const t of r.tags ?? []) all.add(t);
25176
24718
  const list = [...all].sort();
@@ -28606,17 +28148,17 @@ function PersonAvailabilityTab({ item }) {
28606
28148
  const [busy, setBusy] = React133.useState(false);
28607
28149
  const [availabilityReady, setAvailabilityReady] = React133.useState(true);
28608
28150
  const db2 = () => getSupabaseClientOptional();
28609
- const load = React133.useCallback(async () => {
28610
- const client3 = db2();
28611
- if (!client3 || !personId) {
28151
+ const load2 = React133.useCallback(async () => {
28152
+ const client2 = db2();
28153
+ if (!client2 || !personId) {
28612
28154
  setLoading(false);
28613
28155
  return;
28614
28156
  }
28615
28157
  setLoading(true);
28616
28158
  try {
28617
28159
  const [{ data: unitRows, error: unitError }, { data: unitIds, error: grantError }] = await Promise.all([
28618
- client3.from("v_units").select("id,name,city").eq("is_active", true).order("name"),
28619
- 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 })
28620
28162
  ]);
28621
28163
  if (unitError) throw unitError;
28622
28164
  setUnits(unitRows ?? []);
@@ -28636,14 +28178,14 @@ function PersonAvailabilityTab({ item }) {
28636
28178
  }
28637
28179
  }, [personId]);
28638
28180
  React133.useEffect(() => {
28639
- void load();
28640
- }, [load]);
28181
+ void load2();
28182
+ }, [load2]);
28641
28183
  async function makeOrganizationWide() {
28642
- const client3 = db2();
28643
- if (!client3 || !personId || busy) return;
28184
+ const client2 = db2();
28185
+ if (!client2 || !personId || busy) return;
28644
28186
  setBusy(true);
28645
28187
  try {
28646
- const { error } = await client3.rpc("people_set_available_units", {
28188
+ const { error } = await client2.rpc("people_set_available_units", {
28647
28189
  p_person: personId,
28648
28190
  p_unit_ids: []
28649
28191
  });
@@ -28657,19 +28199,19 @@ function PersonAvailabilityTab({ item }) {
28657
28199
  }
28658
28200
  }
28659
28201
  async function toggle(unitId, enabled) {
28660
- const client3 = db2();
28661
- if (!client3 || !personId || busy) return;
28202
+ const client2 = db2();
28203
+ if (!client2 || !personId || busy) return;
28662
28204
  setBusy(true);
28663
28205
  try {
28664
28206
  const next = new Set(selected);
28665
28207
  if (enabled) next.add(unitId);
28666
28208
  else next.delete(unitId);
28667
- const { error } = await client3.rpc("people_set_available_units", {
28209
+ const { error } = await client2.rpc("people_set_available_units", {
28668
28210
  p_person: personId,
28669
28211
  p_unit_ids: Array.from(next)
28670
28212
  });
28671
28213
  if (error) throw error;
28672
- await load();
28214
+ await load2();
28673
28215
  toast.success("Unidades atualizadas.");
28674
28216
  } catch (error) {
28675
28217
  toast.error("N\xE3o foi poss\xEDvel atualizar as unidades", { description: error?.message });
@@ -28714,7 +28256,7 @@ function PersonAvailabilityTab({ item }) {
28714
28256
  ] }) });
28715
28257
  }
28716
28258
  var ScheduleEditor2 = React133__default.lazy(
28717
- () => import('./ScheduleEditor-ZEG6PG3Z.js').then((m) => ({ default: m.ScheduleEditor }))
28259
+ () => import('./ScheduleEditor-MNHZCQIG.js').then((m) => ({ default: m.ScheduleEditor }))
28718
28260
  );
28719
28261
  var PersonTimeline2 = React133__default.lazy(
28720
28262
  () => import('./timeline-LECYQ4IA.js').then((m) => ({ default: m.PersonTimeline }))
@@ -30048,7 +29590,7 @@ function MyRecordPanel() {
30048
29590
  const members = useOrganizationStore((s) => s.members);
30049
29591
  const myRole = members.find((m) => m.userId === userId)?.profileName;
30050
29592
  const [state, setState] = React133.useState({ status: "loading" });
30051
- const load = React133.useCallback(async () => {
29593
+ const load2 = React133.useCallback(async () => {
30052
29594
  if (!orgId || !userId) return;
30053
29595
  const person = await dedup(`self:record:${orgId}:${userId}`, () => fetchMyPersonRecord(orgId, userId));
30054
29596
  if (!person) return setState({ status: "none" });
@@ -30066,8 +29608,8 @@ function MyRecordPanel() {
30066
29608
  }
30067
29609
  }, [orgId, userId]);
30068
29610
  React133.useEffect(() => {
30069
- void load();
30070
- }, [load]);
29611
+ void load2();
29612
+ }, [load2]);
30071
29613
  const changePhoto = React133.useCallback(async (file) => {
30072
29614
  if (state.status !== "ready") return;
30073
29615
  const supabase = getFayzSupabaseClientOptional();
@@ -31138,13 +30680,13 @@ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["READY", "ERROR", "ABANDONED",
31138
30680
  function ProjectsSettings() {
31139
30681
  const currentOrgId = useOrganizationStore((s) => s.currentOrg?.id);
31140
30682
  const projects = useFayzProjectsStore((s) => s.projects);
31141
- const load = useFayzProjectsStore((s) => s.load);
30683
+ const load2 = useFayzProjectsStore((s) => s.load);
31142
30684
  const refresh = useFayzProjectsStore((s) => s.refresh);
31143
30685
  const [linking, setLinking] = React133.useState(false);
31144
30686
  const connected = isPlatformConnected();
31145
30687
  React133.useEffect(() => {
31146
- void load(currentOrgId);
31147
- }, [currentOrgId, load]);
30688
+ void load2(currentOrgId);
30689
+ }, [currentOrgId, load2]);
31148
30690
  React133.useEffect(() => {
31149
30691
  if (!connected || projects.length === 0) return;
31150
30692
  let cancelled = false;
@@ -31893,29 +31435,29 @@ function ModulesSettings({ hidden = [], onToggle, permits, busy, catalog = [] })
31893
31435
  }
31894
31436
 
31895
31437
  // src/app/app-config-cache.ts
31896
- var STORAGE_KEY5 = "fayz:app-config";
31897
- var VERSION2 = 1;
31438
+ var STORAGE_KEY3 = "fayz:app-config";
31439
+ var VERSION = 1;
31898
31440
  var APP_CONFIG_TTL_MS = 5 * 60 * 1e3;
31899
- var MAX_AGE_MS2 = 24 * 60 * 60 * 1e3;
31900
- var MAX_BYTES2 = 256 * 1024;
31901
- function storage2() {
31441
+ var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
31442
+ var MAX_BYTES = 256 * 1024;
31443
+ function storage() {
31902
31444
  try {
31903
31445
  return globalThis.localStorage ?? null;
31904
31446
  } catch {
31905
31447
  return null;
31906
31448
  }
31907
31449
  }
31908
- var keyFor = (tenantId2) => `${STORAGE_KEY5}:${tenantId2}`;
31450
+ var keyFor = (tenantId2) => `${STORAGE_KEY3}:${tenantId2}`;
31909
31451
  function readAppConfigSnapshot(tenantId2) {
31910
- const store = storage2();
31452
+ const store = storage();
31911
31453
  if (!store) return null;
31912
31454
  try {
31913
31455
  const raw = store.getItem(keyFor(tenantId2));
31914
31456
  if (!raw) return null;
31915
31457
  const snap = JSON.parse(raw);
31916
- if (snap.version !== VERSION2 || snap.tenantId !== tenantId2) return null;
31458
+ if (snap.version !== VERSION || snap.tenantId !== tenantId2) return null;
31917
31459
  const age = Date.now() - snap.savedAt;
31918
- if (age > MAX_AGE_MS2) {
31460
+ if (age > MAX_AGE_MS) {
31919
31461
  store.removeItem(keyFor(tenantId2));
31920
31462
  return null;
31921
31463
  }
@@ -31925,17 +31467,17 @@ function readAppConfigSnapshot(tenantId2) {
31925
31467
  }
31926
31468
  }
31927
31469
  function writeAppConfigSnapshot(tenantId2, config) {
31928
- const store = storage2();
31470
+ const store = storage();
31929
31471
  if (!store) return;
31930
31472
  try {
31931
- const payload = JSON.stringify({ version: VERSION2, tenantId: tenantId2, savedAt: Date.now(), config });
31932
- 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;
31933
31475
  store.setItem(keyFor(tenantId2), payload);
31934
31476
  } catch {
31935
31477
  }
31936
31478
  }
31937
31479
  function clearAppConfigSnapshot(tenantId2) {
31938
- const store = storage2();
31480
+ const store = storage();
31939
31481
  if (!store) return;
31940
31482
  try {
31941
31483
  if (tenantId2) {
@@ -31944,7 +31486,7 @@ function clearAppConfigSnapshot(tenantId2) {
31944
31486
  }
31945
31487
  for (let i = store.length - 1; i >= 0; i -= 1) {
31946
31488
  const key = store.key(i);
31947
- if (key?.startsWith(`${STORAGE_KEY5}:`)) store.removeItem(key);
31489
+ if (key?.startsWith(`${STORAGE_KEY3}:`)) store.removeItem(key);
31948
31490
  }
31949
31491
  } catch {
31950
31492
  }
@@ -32591,19 +32133,19 @@ function UnitIndicator({
32591
32133
  const reachable = myUnitIds.length > 0 ? myUnitIds : units.filter((u) => u.kind !== "region").map((u) => u.id);
32592
32134
  if (reachable.length === 0) return null;
32593
32135
  const current2 = activeUnitId ? byId[activeUnitId] : void 0;
32594
- const text2 = current2?.name ?? (reachable.length > 1 ? "Todas as unidades" : byId[reachable[0]]?.name ?? "");
32595
- if (!text2) return null;
32136
+ const text3 = current2?.name ?? (reachable.length > 1 ? "Todas as unidades" : byId[reachable[0]]?.name ?? "");
32137
+ if (!text3) return null;
32596
32138
  if (collapsed) {
32597
- 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" }) });
32598
32140
  }
32599
32141
  const body = /* @__PURE__ */ jsxs(Fragment, { children: [
32600
32142
  /* @__PURE__ */ jsx(Building2, { className: "h-3 w-3 shrink-0 text-sidebar-muted/70" }),
32601
- /* @__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 })
32602
32144
  ] });
32603
32145
  if (inline) {
32604
- 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 });
32605
32147
  }
32606
- 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 });
32607
32149
  }
32608
32150
  var UNIT_DETAIL_ZONES = {
32609
32151
  rooms: "unit.detail.rooms",
@@ -34371,7 +33913,7 @@ var CommandPalette = React133.lazy(
34371
33913
  () => import('./CommandPalette-B5PMQFDG.js').then((m) => ({ default: m.CommandPalette }))
34372
33914
  );
34373
33915
  var SubscriptionPage = React133.lazy(
34374
- () => import('./SubscriptionPage-VXZ37WZZ.js').then((m) => ({ default: m.SubscriptionPage }))
33916
+ () => import('./SubscriptionPage-JWWS44SE.js').then((m) => ({ default: m.SubscriptionPage }))
34375
33917
  );
34376
33918
  function WorkspaceSwitcher({
34377
33919
  variant = "sidebar",
@@ -34455,17 +33997,20 @@ function WorkspaceSwitcher({
34455
33997
  ) }),
34456
33998
  /* @__PURE__ */ jsxs(DropdownContent, { align: "start", className: "w-64", children: [
34457
33999
  /* @__PURE__ */ jsx(DropdownLabel, { children: tr("organization.workspaces", "Workspaces") }),
34458
- search.searchable && /* @__PURE__ */ jsx("div", { className: "px-2 pb-1.5 pt-1", children: /* @__PURE__ */ jsx(
34459
- "input",
34460
- {
34461
- value: query,
34462
- onChange: (e) => setQuery(e.target.value),
34463
- placeholder: tr("organization.searchWorkspace", "Buscar conta\u2026"),
34464
- autoFocus: true,
34465
- onKeyDown: (e) => e.stopPropagation(),
34466
- className: "w-full rounded-md border border-border bg-background px-2 py-1.5 text-sm text-foreground outline-none placeholder:text-muted-foreground focus:border-primary"
34467
- }
34468
- ) }),
34000
+ search.searchable && /* @__PURE__ */ jsxs("div", { className: "relative px-2 pb-1 pt-0.5", children: [
34001
+ /* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute left-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }),
34002
+ /* @__PURE__ */ jsx(
34003
+ "input",
34004
+ {
34005
+ value: query,
34006
+ onChange: (e) => setQuery(e.target.value),
34007
+ placeholder: tr("organization.searchWorkspace", "Buscar conta\u2026"),
34008
+ autoFocus: true,
34009
+ onKeyDown: (e) => e.stopPropagation(),
34010
+ className: "h-8 w-full border-0 bg-transparent pl-7 pr-2 text-[13px] text-foreground outline-none placeholder:text-muted-foreground focus:ring-0"
34011
+ }
34012
+ )
34013
+ ] }),
34469
34014
  /* @__PURE__ */ jsx(DropdownSeparator, {}),
34470
34015
  search.visible.length === 0 && /* @__PURE__ */ jsx("div", { className: "px-3 py-3 text-sm text-muted-foreground", children: tr("organization.noWorkspaceMatch", "Nenhuma conta com esse nome.") }),
34471
34016
  search.visible.map((m) => /* @__PURE__ */ jsxs(
@@ -36721,11 +36266,14 @@ function Badge26({ badge, className = "" }) {
36721
36266
  /* @__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 })
36722
36267
  );
36723
36268
  }
36724
- function OrderDetailBlock({ title, hint, children }) {
36269
+ function OrderDetailBlock({ title, hint, actions, children }) {
36725
36270
  return /* @__PURE__ */ jsxs("div", { className: "rounded-card border bg-card p-4", children: [
36726
- (title || hint) && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
36727
- title && /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: title }),
36728
- hint && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: hint })
36271
+ (title || hint || actions) && /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-start justify-between gap-2", children: [
36272
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
36273
+ title && /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: title }),
36274
+ hint && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: hint })
36275
+ ] }),
36276
+ actions && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: actions })
36729
36277
  ] }),
36730
36278
  children
36731
36279
  ] });
@@ -36784,7 +36332,8 @@ function OrderDetailView(props) {
36784
36332
  banner,
36785
36333
  embedded
36786
36334
  } = props;
36787
- const actionSlots = Math.max(0, ...items.map((it) => it.actions?.length ?? 0));
36335
+ const itemMenu = !!props.itemActionsMenu;
36336
+ const actionSlots = itemMenu ? items.some((it) => (it.actions?.length ?? 0) > 0) ? 1 : 0 : Math.max(0, ...items.map((it) => it.actions?.length ?? 0));
36788
36337
  const hasBadges = badges.length > 0 || !!props.badgesNode;
36789
36338
  const titleNode = hasBadges ? /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
36790
36339
  /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: title }),
@@ -36826,7 +36375,8 @@ function OrderDetailView(props) {
36826
36375
  /* @__PURE__ */ jsx(Thumbnail, { src: item.imageUrl, size: "sm", icon: item.icon }),
36827
36376
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
36828
36377
  /* @__PURE__ */ jsx("p", { className: cn$1("truncate text-sm font-medium", item.struck && "text-muted-foreground line-through"), children: item.name }),
36829
- item.description ? /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null
36378
+ item.description ? /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null,
36379
+ item.note ? /* @__PURE__ */ jsx("p", { className: "truncate text-xs", children: item.note }) : null
36830
36380
  ] }),
36831
36381
  item.account && /* @__PURE__ */ jsx(Badge, { variant: "secondary", title: item.account, className: "fz-tight-hide max-w-[12rem] shrink-0 truncate", children: item.account }),
36832
36382
  /* @__PURE__ */ jsxs("span", { className: cn$1("shrink-0 text-xs text-muted-foreground tabular-nums", item.struck && "line-through"), children: [
@@ -36842,26 +36392,42 @@ function OrderDetailView(props) {
36842
36392
  // ficam visíveis o tempo todo (`pointer: coarse`).
36843
36393
  // Every row reserves the widest row's slot, so a line with fewer
36844
36394
  // actions (a cancelled one has none) keeps its numbers in the column.
36845
- /* @__PURE__ */ jsx(
36395
+ /* @__PURE__ */ jsxs(
36846
36396
  "span",
36847
36397
  {
36848
- style: { width: actionSlots * 28 + (actionSlots - 1) * 2 },
36398
+ style: { width: itemMenu ? 36 : actionSlots * 28 + (actionSlots - 1) * 2 },
36849
36399
  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",
36850
- children: (item.actions ?? []).map((a) => {
36851
- const Icon = a.icon;
36852
- return /* @__PURE__ */ jsx(Hint, { label: a.label, children: /* @__PURE__ */ jsx(
36853
- Button,
36400
+ children: [
36401
+ itemMenu && /* @__PURE__ */ jsx(
36402
+ RowActions,
36854
36403
  {
36855
- type: "button",
36856
- variant: "ghost",
36857
- size: "icon",
36858
- className: "h-7 w-7",
36859
- "aria-label": a.label,
36860
- onClick: () => a.onSelect(item),
36861
- children: Icon ? /* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-3.5 w-3.5" })
36404
+ inlineLimit: 0,
36405
+ actions: (item.actions ?? []).map((a) => ({
36406
+ id: a.id,
36407
+ label: a.label,
36408
+ icon: a.icon,
36409
+ intent: a.intent,
36410
+ disabled: a.disabled,
36411
+ onSelect: () => a.onSelect(item)
36412
+ }))
36862
36413
  }
36863
- ) }, a.id);
36864
- })
36414
+ ),
36415
+ !itemMenu && (item.actions ?? []).map((a) => {
36416
+ const Icon = a.icon;
36417
+ return /* @__PURE__ */ jsx(Hint, { label: a.label, children: /* @__PURE__ */ jsx(
36418
+ Button,
36419
+ {
36420
+ type: "button",
36421
+ variant: "ghost",
36422
+ size: "icon",
36423
+ className: "h-7 w-7",
36424
+ "aria-label": a.label,
36425
+ onClick: () => a.onSelect(item),
36426
+ children: Icon ? /* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-3.5 w-3.5" })
36427
+ }
36428
+ ) }, a.id);
36429
+ })
36430
+ ]
36865
36431
  }
36866
36432
  )
36867
36433
  ] }, item.id ?? i)) }) }),
@@ -37124,7 +36690,10 @@ function OrderFormItemRow({
37124
36690
  labels,
37125
36691
  extraFieldGroups,
37126
36692
  readOnly = false,
37127
- pickOnly = false
36693
+ pickOnly = false,
36694
+ note,
36695
+ imageUrl,
36696
+ icon
37128
36697
  }) {
37129
36698
  const l = { ...ITEM_LABELS, ...labels };
37130
36699
  const total = quantity * unitPrice - (discount ?? 0) + (surcharge ?? 0);
@@ -37167,8 +36736,14 @@ function OrderFormItemRow({
37167
36736
  index + 1,
37168
36737
  "."
37169
36738
  ] }),
37170
- 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 }),
37171
- /* @__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 }) }),
36739
+ (imageUrl || icon) && /* @__PURE__ */ jsx(Thumbnail, { src: imageUrl, size: "sm", icon }),
36740
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 text-sm", children: [
36741
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
36742
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: description || /* @__PURE__ */ jsx("span", { className: "italic text-muted-foreground", children: l.noDescription }) }),
36743
+ 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 })
36744
+ ] }),
36745
+ note && /* @__PURE__ */ jsx("span", { className: "mt-0.5 block truncate text-xs", children: note })
36746
+ ] }),
37172
36747
  (extraFieldGroups ?? []).filter((g) => g.summary).map((g) => /* @__PURE__ */ jsx(
37173
36748
  Badge,
37174
36749
  {
@@ -37508,26 +37083,30 @@ function OrderFormItemsCard({
37508
37083
  emptyLabel = "Nenhum item adicionado",
37509
37084
  emptyActionLabel = "Adicione o primeiro item",
37510
37085
  children,
37511
- "data-tour": dataTour
37086
+ "data-tour": dataTour,
37087
+ headerExtra
37512
37088
  }) {
37513
37089
  return /* @__PURE__ */ jsxs("div", { "data-tour": dataTour, className: "flex flex-col overflow-hidden rounded-card border bg-card", children: [
37514
37090
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b px-4 py-3", children: [
37515
37091
  /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: label3 }),
37516
- onAdd && /* @__PURE__ */ jsxs(
37517
- "button",
37518
- {
37519
- type: "button",
37520
- onClick: onAdd,
37521
- disabled: addDisabled,
37522
- title: addDisabled ? addDisabledHint : void 0,
37523
- 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",
37524
- children: [
37525
- /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
37526
- " ",
37527
- addLabel
37528
- ]
37529
- }
37530
- )
37092
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
37093
+ headerExtra,
37094
+ onAdd && /* @__PURE__ */ jsxs(
37095
+ "button",
37096
+ {
37097
+ type: "button",
37098
+ onClick: onAdd,
37099
+ disabled: addDisabled,
37100
+ title: addDisabled ? addDisabledHint : void 0,
37101
+ 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",
37102
+ children: [
37103
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
37104
+ " ",
37105
+ addLabel
37106
+ ]
37107
+ }
37108
+ )
37109
+ ] })
37531
37110
  ] }),
37532
37111
  /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
37533
37112
  header,
@@ -38523,6 +38102,13 @@ function OrderListView({
38523
38102
  searchText,
38524
38103
  searchPlaceholder,
38525
38104
  pageSize = 25,
38105
+ search: searchProp,
38106
+ onSearchChange,
38107
+ page: pageProp,
38108
+ total,
38109
+ onPageChange,
38110
+ filters,
38111
+ mobileLayout,
38526
38112
  bulkActions,
38527
38113
  rowId,
38528
38114
  selectedRowId,
@@ -38532,8 +38118,15 @@ function OrderListView({
38532
38118
  boards,
38533
38119
  viewKey
38534
38120
  }) {
38535
- const [search, setSearch] = React133.useState("");
38536
- const [page, setPage] = React133.useState(1);
38121
+ const [localSearch, setLocalSearch] = React133.useState("");
38122
+ const [localPage, setLocalPage] = React133.useState(1);
38123
+ const serverPaged = total != null;
38124
+ const search = onSearchChange ? searchProp ?? "" : localSearch;
38125
+ const setSearch = onSearchChange ?? setLocalSearch;
38126
+ const page = serverPaged ? pageProp ?? 1 : localPage;
38127
+ const setPage = serverPaged ? onPageChange ?? (() => {
38128
+ }) : setLocalPage;
38129
+ const searchable = !!searchText || !!onSearchChange;
38537
38130
  const [rawSelection, setRawSelection] = React133.useState([]);
38538
38131
  const offered = React133.useMemo(
38539
38132
  () => views && views.length > 0 ? views : ["list"],
@@ -38588,6 +38181,7 @@ function OrderListView({
38588
38181
  const cols = React133.useMemo(
38589
38182
  () => columns.map((c) => ({
38590
38183
  id: c.key,
38184
+ ...c.mobile ? { meta: { mobile: c.mobile } } : {},
38591
38185
  header: () => /* @__PURE__ */ jsx("div", { className: c.align === "right" ? "text-right" : "", children: c.header }),
38592
38186
  cell: ({ row }) => /* @__PURE__ */ jsx("div", { className: c.align === "right" ? "text-right" : "", children: c.render(row.original) })
38593
38187
  })),
@@ -38595,13 +38189,14 @@ function OrderListView({
38595
38189
  );
38596
38190
  const filtered = React133.useMemo(() => {
38597
38191
  const term = search.trim().toLowerCase();
38598
- if (!term || !searchText) return rows;
38192
+ if (!term || !searchText || onSearchChange) return rows;
38599
38193
  return rows.filter((row) => searchText(row).toLowerCase().includes(term));
38600
38194
  }, [rows, search, searchText]);
38601
38195
  React133.useEffect(() => {
38602
- setPage(1);
38603
- }, [search]);
38604
- const paged = pageSize > 0 ? filtered.slice((page - 1) * pageSize, page * pageSize) : filtered;
38196
+ setLocalPage(1);
38197
+ }, [localSearch]);
38198
+ const paged = serverPaged || pageSize <= 0 ? filtered : filtered.slice((page - 1) * pageSize, page * pageSize);
38199
+ const totalRows = serverPaged ? total : filtered.length;
38605
38200
  const getId = React133.useCallback(
38606
38201
  (row) => rowId ? rowId(row) : String(row.id ?? ""),
38607
38202
  [rowId]
@@ -38659,19 +38254,26 @@ function OrderListView({
38659
38254
  }
38660
38255
  ) : null,
38661
38256
  tiles.length > 0 && /* @__PURE__ */ jsx(StatTiles, { tiles, loading }),
38662
- activeCustom ? activeCustom() : showingBoard ? /* @__PURE__ */ jsx(
38663
- OrderBoardView,
38664
- {
38665
- board: activeBoard,
38666
- rows: filtered,
38667
- loading,
38668
- empty,
38669
- onRowClick,
38670
- rowId,
38671
- selectedRowId
38672
- }
38673
- ) : /* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
38674
- (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(
38257
+ activeCustom ? activeCustom() : showingBoard ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
38258
+ (searchable || filters) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
38259
+ searchable && /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: /* @__PURE__ */ jsx(SearchField, { value: search, onChange: setSearch, placeholder: searchPlaceholder ?? "Buscar\u2026" }) }),
38260
+ filters
38261
+ ] }),
38262
+ /* @__PURE__ */ jsx(
38263
+ OrderBoardView,
38264
+ {
38265
+ board: activeBoard,
38266
+ rows: filtered,
38267
+ loading,
38268
+ empty,
38269
+ onRowClick,
38270
+ rowId,
38271
+ selectedRowId
38272
+ }
38273
+ ),
38274
+ serverPaged && !loading && totalRows > pageSize && pageSize > 0 && /* @__PURE__ */ jsx(ChevronPager, { page, pageSize, total: totalRows, onPageChange: setPage })
38275
+ ] }) : /* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
38276
+ (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(
38675
38277
  BulkActionBar,
38676
38278
  {
38677
38279
  variant: "inline",
@@ -38681,14 +38283,17 @@ function OrderListView({
38681
38283
  onClear: () => setRawSelection([]),
38682
38284
  actions: barActions
38683
38285
  }
38684
- ) : /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: /* @__PURE__ */ jsx(
38685
- SearchField,
38686
- {
38687
- value: search,
38688
- onChange: setSearch,
38689
- placeholder: searchPlaceholder ?? "Buscar\u2026"
38690
- }
38691
- ) }) }),
38286
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
38287
+ searchable && /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: /* @__PURE__ */ jsx(
38288
+ SearchField,
38289
+ {
38290
+ value: search,
38291
+ onChange: setSearch,
38292
+ placeholder: searchPlaceholder ?? "Buscar\u2026"
38293
+ }
38294
+ ) }),
38295
+ filters
38296
+ ] }) }),
38692
38297
  /* @__PURE__ */ jsx(
38693
38298
  DataTable,
38694
38299
  {
@@ -38701,15 +38306,16 @@ function OrderListView({
38701
38306
  data: loading ? [] : paged,
38702
38307
  emptyMessage: search.trim() ? "Nada encontrado para esta busca." : empty,
38703
38308
  loading,
38704
- onRowClick: onRowClick ? (row) => onRowClick(row) : void 0
38309
+ onRowClick: onRowClick ? (row) => onRowClick(row) : void 0,
38310
+ ...mobileLayout ? { mobileLayout } : {}
38705
38311
  }
38706
38312
  ),
38707
- !loading && filtered.length > 0 && pageSize > 0 && /* @__PURE__ */ jsx(
38313
+ !loading && totalRows > 0 && pageSize > 0 && /* @__PURE__ */ jsx(
38708
38314
  ChevronPager,
38709
38315
  {
38710
38316
  page,
38711
38317
  pageSize,
38712
- total: filtered.length,
38318
+ total: totalRows,
38713
38319
  onPageChange: setPage
38714
38320
  }
38715
38321
  )
@@ -38767,7 +38373,7 @@ function PaymentStatusBadge({
38767
38373
  React133__default.useEffect(() => {
38768
38374
  setLines(null);
38769
38375
  }, [status, paidAmount]);
38770
- const load = React133__default.useCallback(() => {
38376
+ const load2 = React133__default.useCallback(() => {
38771
38377
  if (lines || !onLoadDetails) return;
38772
38378
  void onLoadDetails().then(setLines).catch(() => setLines([]));
38773
38379
  }, [lines, onLoadDetails]);
@@ -38782,7 +38388,7 @@ function PaymentStatusBadge({
38782
38388
  onMouseEnter: onLoadDetails ? () => {
38783
38389
  timer.current = setTimeout(() => {
38784
38390
  setOpen(true);
38785
- load();
38391
+ load2();
38786
38392
  }, 500);
38787
38393
  } : void 0,
38788
38394
  onMouseLeave: onLoadDetails ? () => {
@@ -38803,7 +38409,7 @@ function PaymentStatusBadge({
38803
38409
  const remaining = totalAmount != null && paidAmount != null ? totalAmount - paidAmount : null;
38804
38410
  return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: (v) => {
38805
38411
  setOpen(v);
38806
- if (v) load();
38412
+ if (v) load2();
38807
38413
  }, children: [
38808
38414
  /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: trigger }),
38809
38415
  /* @__PURE__ */ jsxs(PopoverContent, { align: "end", sideOffset: 6, className: "w-60 p-3", children: [
@@ -38908,7 +38514,7 @@ function useOrdersPaymentStatus(orderIds) {
38908
38514
  );
38909
38515
  const [byOrder, setByOrder] = React133.useState(() => /* @__PURE__ */ new Map());
38910
38516
  const [loading, setLoading] = React133.useState(false);
38911
- const load = React133.useCallback(async (force = false) => {
38517
+ const load2 = React133.useCallback(async (force = false) => {
38912
38518
  const ids = key ? key.split(",") : [];
38913
38519
  if (ids.length === 0) {
38914
38520
  setByOrder(/* @__PURE__ */ new Map());
@@ -38940,9 +38546,9 @@ function useOrdersPaymentStatus(orderIds) {
38940
38546
  setByOrder(new Map(ids.map((id) => [id, cache2.get(id)]).filter(([, v]) => Boolean(v))));
38941
38547
  }, [key]);
38942
38548
  React133.useEffect(() => {
38943
- void load();
38944
- }, [load]);
38945
- return { byOrder, loading, reload: () => load(true) };
38549
+ void load2();
38550
+ }, [load2]);
38551
+ return { byOrder, loading, reload: () => load2(true) };
38946
38552
  }
38947
38553
  var ORDER_KIND_LABELS = {
38948
38554
  sale: "Venda",
@@ -38975,7 +38581,9 @@ var ORDER_CHANNEL_LABELS = {
38975
38581
  balcao: "Balc\xE3o",
38976
38582
  shop: "Loja",
38977
38583
  dine_in: "Sal\xE3o",
38978
- delivery: "Delivery"
38584
+ delivery: "Delivery",
38585
+ retirada: "Retirada",
38586
+ ticketing: "Bilheteria"
38979
38587
  };
38980
38588
  function Badge28({ children }) {
38981
38589
  return /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium", children });
@@ -39024,7 +38632,7 @@ function useOrderDetail(orderId) {
39024
38632
  try {
39025
38633
  const db2 = getSupabaseClientOptional();
39026
38634
  if (!db2) throw new Error("Supabase client is not configured");
39027
- 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();
38635
+ 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();
39028
38636
  if (rowError) throw new Error(rowError.message);
39029
38637
  if (!row) throw new Error("Pedido n\xE3o encontrado");
39030
38638
  const [{ data: items }, { data: party }] = await Promise.all([
@@ -39047,6 +38655,7 @@ function useOrderDetail(orderId) {
39047
38655
  kind: row.kind ?? void 0,
39048
38656
  channel: row.channel ?? void 0,
39049
38657
  status: row.status ?? void 0,
38658
+ fulfillmentStatus: row.fulfillment_status ?? void 0,
39050
38659
  partyName: party?.name ?? void 0,
39051
38660
  notes: row.notes ?? void 0,
39052
38661
  currency: row.currency ?? "BRL",
@@ -39343,6 +38952,155 @@ function toOrderDetailReceivable(receivable, money4, options = {}) {
39343
38952
  ...options.actions ? { actions: options.actions } : {}
39344
38953
  };
39345
38954
  }
38955
+
38956
+ // src/crud/archetypes/orderStage.ts
38957
+ var ORDER_STAGES = ["to_receive", "to_ship", "shipped", "done", "cancelled"];
38958
+ var ORDER_STAGE_LABELS = {
38959
+ to_receive: "A receber",
38960
+ to_ship: "A enviar",
38961
+ shipped: "Enviado",
38962
+ done: "Conclu\xEDdo",
38963
+ cancelled: "Cancelado"
38964
+ };
38965
+ var ORDER_STAGE_COLORS = {
38966
+ to_receive: "bg-amber-500",
38967
+ to_ship: "bg-blue-500",
38968
+ shipped: "bg-cyan-500",
38969
+ done: "bg-emerald-500",
38970
+ cancelled: "bg-gray-400"
38971
+ };
38972
+ var SHIPPING_CHANNELS = /* @__PURE__ */ new Set(["shop", "delivery"]);
38973
+ function orderStage(order) {
38974
+ if (order.status === "cancelled") return "cancelled";
38975
+ const owed = ["pending", "open", "partial", "overdue"].includes(order.paymentStatus ?? "");
38976
+ if (order.status === "completed") return owed ? "to_receive" : "done";
38977
+ if (order.paymentStatus !== "paid") return "to_receive";
38978
+ const shipments = (order.shipmentStatuses ?? []).filter((s) => s !== "cancelled");
38979
+ const delivered = shipments.length > 0 && shipments.every((s) => s === "delivered" || s === "completed");
38980
+ if (shipments.some((s) => s === "in_transit")) return "shipped";
38981
+ if (order.fulfillmentStatus === "fulfilled" || delivered) return "done";
38982
+ const ships = shipments.length > 0 || SHIPPING_CHANNELS.has(order.channel ?? "");
38983
+ return ships ? "to_ship" : "done";
38984
+ }
38985
+ var STATUS_LABEL = {
38986
+ pending: "Aguardando envio",
38987
+ in_progress: "Em preparo",
38988
+ in_transit: "Em tr\xE2nsito",
38989
+ delivered: "Entregue",
38990
+ completed: "Entregue",
38991
+ failed: "Falhou",
38992
+ returned: "Devolvido",
38993
+ cancelled: "Cancelado"
38994
+ };
38995
+ var KIND_LABEL = { shipment: "Envio", pickup: "Retirada" };
38996
+ function text2(value) {
38997
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
38998
+ }
38999
+ function useOrderFulfillments(orderId) {
39000
+ const [fulfillments, setFulfillments] = React133.useState([]);
39001
+ const [loading, setLoading] = React133.useState(false);
39002
+ const [error, setError] = React133.useState(null);
39003
+ const [nonce, setNonce] = React133.useState(0);
39004
+ const reload2 = React133.useCallback(() => setNonce((n) => n + 1), []);
39005
+ React133.useEffect(() => {
39006
+ if (!orderId) {
39007
+ setFulfillments([]);
39008
+ setError(null);
39009
+ return;
39010
+ }
39011
+ let cancelled = false;
39012
+ setLoading(true);
39013
+ setError(null);
39014
+ void (async () => {
39015
+ try {
39016
+ const db2 = getSupabaseClientOptional();
39017
+ if (!db2) return;
39018
+ 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 });
39019
+ if (rowsError) throw new Error(rowsError.message);
39020
+ const addressIds = [...new Set((rows ?? []).map((r) => r.address_id).filter(Boolean))];
39021
+ 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 };
39022
+ if (addressError) throw new Error(addressError.message);
39023
+ if (cancelled) return;
39024
+ const addressById = new Map((addresses ?? []).map((a) => [a.id, a]));
39025
+ setFulfillments((rows ?? []).map((r) => {
39026
+ const meta = r.metadata ?? {};
39027
+ const a = r.address_id ? addressById.get(r.address_id) : void 0;
39028
+ return {
39029
+ id: r.id,
39030
+ kind: r.kind,
39031
+ status: r.status,
39032
+ // Older rows carry these in metadata; the columns win when set.
39033
+ carrier: text2(r.carrier) ?? text2(meta.carrier),
39034
+ trackingCode: text2(r.tracking_code) ?? text2(meta.tracking_code),
39035
+ trackingUrl: text2(r.tracking_url) ?? text2(meta.tracking_url),
39036
+ shippedAt: r.shipped_at ?? void 0,
39037
+ deliveredAt: r.delivered_at ?? void 0,
39038
+ estimatedDeliveryAt: r.estimated_delivery_at ?? void 0,
39039
+ address: a ? {
39040
+ recipient: text2(a.recipient),
39041
+ phone: text2(a.phone),
39042
+ line1: [a.street, a.number].filter(Boolean).join(", ") + (a.complement ? ` \u2014 ${a.complement}` : ""),
39043
+ line2: [a.district, [a.city, a.state].filter(Boolean).join("/"), a.postal_code].filter(Boolean).join(" \xB7 ")
39044
+ } : void 0
39045
+ };
39046
+ }));
39047
+ } catch (err) {
39048
+ if (!cancelled) {
39049
+ setFulfillments([]);
39050
+ setError(err instanceof Error ? err.message : String(err));
39051
+ }
39052
+ } finally {
39053
+ if (!cancelled) setLoading(false);
39054
+ }
39055
+ })();
39056
+ return () => {
39057
+ cancelled = true;
39058
+ };
39059
+ }, [orderId, nonce]);
39060
+ return { fulfillments, loading, error, reload: reload2 };
39061
+ }
39062
+ function day(value) {
39063
+ return value ? new Date(value).toLocaleDateString("pt-BR") : void 0;
39064
+ }
39065
+ function OrderDeliveryBlock({ fulfillments, error }) {
39066
+ if (error) {
39067
+ 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." }) });
39068
+ }
39069
+ if (fulfillments.length === 0) {
39070
+ 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." }) });
39071
+ }
39072
+ 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: [
39073
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
39074
+ /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
39075
+ KIND_LABEL[f.kind] ?? f.kind,
39076
+ f.carrier ? ` \xB7 ${f.carrier}` : ""
39077
+ ] }),
39078
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: STATUS_LABEL[f.status] ?? f.status })
39079
+ ] }),
39080
+ f.trackingCode && /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground", children: [
39081
+ "Rastreio:",
39082
+ " ",
39083
+ 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 })
39084
+ ] }),
39085
+ (f.shippedAt || f.deliveredAt || f.estimatedDeliveryAt) && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: [
39086
+ f.shippedAt && `Enviado em ${day(f.shippedAt)}`,
39087
+ f.deliveredAt ? `Entregue em ${day(f.deliveredAt)}` : f.estimatedDeliveryAt && `Previs\xE3o ${day(f.estimatedDeliveryAt)}`
39088
+ ].filter(Boolean).join(" \xB7 ") }),
39089
+ f.address && /* @__PURE__ */ jsxs("address", { className: "not-italic text-muted-foreground", children: [
39090
+ f.address.recipient && /* @__PURE__ */ jsx("span", { className: "block text-foreground", children: f.address.recipient }),
39091
+ /* @__PURE__ */ jsx("span", { className: "block", children: f.address.line1 }),
39092
+ /* @__PURE__ */ jsx("span", { className: "block", children: f.address.line2 }),
39093
+ f.address.phone && /* @__PURE__ */ jsx("span", { className: "block", children: f.address.phone })
39094
+ ] })
39095
+ ] }, f.id)) }) });
39096
+ }
39097
+ var STAGE_TONE = {
39098
+ to_receive: "warning",
39099
+ to_ship: "info",
39100
+ shipped: "info",
39101
+ done: "success",
39102
+ cancelled: "destructive"
39103
+ };
39346
39104
  function money3(value, currency) {
39347
39105
  return value.toLocaleString("pt-BR", { style: "currency", currency: currency || "BRL" });
39348
39106
  }
@@ -39355,9 +39113,10 @@ function OrderDetailPage({
39355
39113
  mapData,
39356
39114
  receivableActions
39357
39115
  }) {
39358
- const { order, loading, error } = useOrderDetail(orderId);
39116
+ const { order, loading, error, reload: reload2 } = useOrderDetail(orderId);
39117
+ const { fulfillments, error: fulfillmentsError } = useOrderFulfillments(orderId);
39359
39118
  const { receivable, reload: reloadReceivable } = useOrderReceivable(orderId);
39360
- if (loading) return /* @__PURE__ */ jsx(OrderDetailSkeleton, {});
39119
+ if (loading && !order) return /* @__PURE__ */ jsx(OrderDetailSkeleton, {});
39361
39120
  if (error || !order) {
39362
39121
  return /* @__PURE__ */ jsxs("div", { className: "p-6", children: [
39363
39122
  /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error ?? "Pedido n\xE3o encontrado" }),
@@ -39374,27 +39133,18 @@ function OrderDetailPage({
39374
39133
  }
39375
39134
  const currency = order.currency;
39376
39135
  const verbs = receivableActions?.(order, { receivable, reload: reloadReceivable });
39136
+ const stage = orderStage({
39137
+ status: order.status,
39138
+ channel: order.channel,
39139
+ paymentStatus: receivable?.balance.status ?? "none",
39140
+ fulfillmentStatus: order.fulfillmentStatus,
39141
+ shipmentStatuses: fulfillments.map((f) => f.status)
39142
+ });
39377
39143
  const base = {
39378
39144
  title: order.referenceNumber,
39379
- // Kind and channel are the two axes the archetype actually stores; status
39380
- // heads them because it is what changes.
39381
- // Through the shared vocabulary, not raw. The column holds `confirmed`,
39382
- // `dine_in`, `balcao` — machine words, and printing them is how a screen
39383
- // ends up saying "dine_in" to a waiter. Anything the vocabulary has not
39384
- // named falls through to the raw value rather than being guessed at.
39385
- badges: [
39386
- ...order.status ? [{ label: ORDER_STATUS_LABELS[order.status] ?? order.status, tone: orderStatusTone(order.status) }] : [],
39387
- ...order.kind ? [{ label: ORDER_KIND_LABELS[order.kind] ?? order.kind, tone: "muted" }] : [],
39388
- ...order.channel ? [{ label: ORDER_CHANNEL_LABELS[order.channel] ?? order.channel, tone: "muted" }] : [],
39389
- // O estado do DINHEIRO ao lado do estado do PEDIDO. Ate aqui a resposta
39390
- // existia so no bloco de baixo, e quem abre a ficha para saber se ja
39391
- // recebeu tinha de rolar a tela para descobrir. So aparece depois de
39392
- // faturado — sem fatura nao ha o que dizer, e o bloco de baixo ja diz.
39393
- ...receivable ? [{
39394
- label: RECEIVABLE_LABEL[receivable.balance.status] ?? receivable.balance.status,
39395
- tone: receivableTone(receivable.balance.status)
39396
- }] : []
39397
- ],
39145
+ // ONE badge, the same word the list and the board use for this order.
39146
+ // Status, kind, channel and money as four chips read as four states.
39147
+ badges: [{ label: ORDER_STAGE_LABELS[stage], tone: STAGE_TONE[stage] }],
39398
39148
  // The date belongs in the provenance footer, where every other ficha in the
39399
39149
  // app keeps "criado em" — beside the order number it competes with what the
39400
39150
  // person opened the screen to read. `meta` is what RecordMetaFooter reads.
@@ -39425,8 +39175,12 @@ function OrderDetailPage({
39425
39175
  // dois ramos: dois `createElement` distintos remontariam o componente na
39426
39176
  // troca de ramo, e com ele o modal aberto.
39427
39177
  receivable: toOrderDetailReceivable(receivable, (value) => money3(value, currency), { actions: verbs }) ?? { rows: [], installments: [], actions: verbs },
39428
- ...actions ? { actions: actions(order) } : {},
39429
- ...extraSections ? { extraSections: extraSections(order) } : {},
39178
+ ...actions ? { actions: actions(order, { reload: reload2 }) } : {},
39179
+ // Beside the customer, where the shop's own page keeps it.
39180
+ extraSections: /* @__PURE__ */ jsxs(Fragment, { children: [
39181
+ /* @__PURE__ */ jsx(OrderDeliveryBlock, { fulfillments, error: fulfillmentsError }),
39182
+ extraSections?.(order)
39183
+ ] }),
39430
39184
  backLabel,
39431
39185
  onBack: () => navigateTo(backTo)
39432
39186
  };
@@ -39544,6 +39298,43 @@ function useOrderEditor(orderId) {
39544
39298
  save
39545
39299
  };
39546
39300
  }
39301
+ var cache4 = null;
39302
+ function load() {
39303
+ cache4 ?? (cache4 = (async () => {
39304
+ const db2 = getSupabaseClientOptional();
39305
+ if (!db2) return /* @__PURE__ */ new Map();
39306
+ const { data, error } = await db2.from("order_kinds").select("kind, transitions");
39307
+ if (error) {
39308
+ cache4 = null;
39309
+ return /* @__PURE__ */ new Map();
39310
+ }
39311
+ return new Map((data ?? []).map((r) => [r.kind, r.transitions ?? {}]));
39312
+ })());
39313
+ return cache4;
39314
+ }
39315
+ var TERMINAL = /* @__PURE__ */ new Set(["completed", "cancelled"]);
39316
+ function nextOrderStatuses(transitions, status) {
39317
+ if (!transitions || !status) return [];
39318
+ const declared = transitions[status] ?? transitions["*"] ?? [];
39319
+ if (declared.includes("*")) return TERMINAL.has(status) ? [] : ["cancelled"];
39320
+ return declared;
39321
+ }
39322
+ function useOrderKindTransitions(kind, status) {
39323
+ const [byKind, setByKind] = React133.useState(null);
39324
+ React133.useEffect(() => {
39325
+ let live = true;
39326
+ void load().then((map) => {
39327
+ if (live) setByKind(map);
39328
+ });
39329
+ return () => {
39330
+ live = false;
39331
+ };
39332
+ }, []);
39333
+ return React133.useMemo(
39334
+ () => nextOrderStatuses(kind ? byKind?.get(kind) : void 0, status),
39335
+ [byKind, kind, status]
39336
+ );
39337
+ }
39547
39338
 
39548
39339
  // src/lib/create-client-orders-provider.ts
39549
39340
  var STAGE_FILTER_MAP = {
@@ -39764,6 +39555,39 @@ function ModuleActionBar({
39764
39555
  trailing
39765
39556
  ] });
39766
39557
  }
39558
+ function formatCurrency4(value, currency) {
39559
+ if (!currency) return formatCurrency$1(value);
39560
+ return new Intl.NumberFormat(currency.locale, {
39561
+ style: "currency",
39562
+ currency: currency.code,
39563
+ minimumFractionDigits: 2
39564
+ }).format(value);
39565
+ }
39566
+ function useHouseCurrency() {
39567
+ return React133.useSyncExternalStore(subscribeHouseCurrency, getHouseCurrency, getHouseCurrency);
39568
+ }
39569
+ var CurrencyScopeContext = React133.createContext(null);
39570
+ function CurrencyScope({ code, children }) {
39571
+ const outer = React133.useContext(CurrencyScopeContext);
39572
+ return React133.createElement(CurrencyScopeContext.Provider, { value: code || outer }, children);
39573
+ }
39574
+ function useCurrencyScope() {
39575
+ return React133.useContext(CurrencyScopeContext);
39576
+ }
39577
+ function useCurrency(declared, documentCode) {
39578
+ const house = useHouseCurrency();
39579
+ const scope = useCurrencyScope();
39580
+ const code = documentCode || scope;
39581
+ return React133.useMemo(
39582
+ () => resolveCurrency(declared, code),
39583
+ // `house` is read inside resolveCurrency; listed so a switch re-resolves.
39584
+ // eslint-disable-next-line react-hooks/exhaustive-deps
39585
+ [declared, code, house]
39586
+ );
39587
+ }
39588
+ function isCurrencyConfig(value) {
39589
+ return !!value && typeof value === "object" && typeof value.code === "string" && typeof value.locale === "string";
39590
+ }
39767
39591
  function createPluginContext(displayName) {
39768
39592
  const ConfigContext = React133__default.createContext(null);
39769
39593
  const ProviderContext = React133__default.createContext(null);
@@ -39777,8 +39601,16 @@ function createPluginContext(displayName) {
39777
39601
  ContextProvider.displayName = `${displayName}ContextProvider`;
39778
39602
  function useConfig() {
39779
39603
  const ctx = React133__default.useContext(ConfigContext);
39780
- if (!ctx) throw new Error(`useConfig must be used within ${displayName}`);
39781
- return ctx;
39604
+ const house = useHouseCurrency();
39605
+ const scope = useCurrencyScope();
39606
+ const resolved = React133__default.useMemo(() => {
39607
+ const declared = ctx?.currency;
39608
+ const code = scope || house;
39609
+ if (!ctx || !code || !isCurrencyConfig(declared) || declared.code === code) return ctx;
39610
+ return { ...ctx, currency: resolveCurrency(declared, scope) };
39611
+ }, [ctx, house, scope]);
39612
+ if (!resolved) throw new Error(`useConfig must be used within ${displayName}`);
39613
+ return resolved;
39782
39614
  }
39783
39615
  function useProvider() {
39784
39616
  const ctx = React133__default.useContext(ProviderContext);
@@ -39806,14 +39638,6 @@ function createViewRouter(routes, fallbackId) {
39806
39638
  return route ? route.render({ id }) : null;
39807
39639
  };
39808
39640
  }
39809
- function formatCurrency4(value, currency) {
39810
- if (!currency) return formatCurrency$1(value);
39811
- return new Intl.NumberFormat(currency.locale, {
39812
- style: "currency",
39813
- currency: currency.code,
39814
- minimumFractionDigits: 2
39815
- }).format(value);
39816
- }
39817
39641
  function RegistryCrudView({ registry: registry4, basePath }) {
39818
39642
  const useStore2 = useMemo(() => {
39819
39643
  const data = registry4.mockData ?? registry4.seedData ?? [];
@@ -40211,7 +40035,7 @@ function ContactPicker({
40211
40035
  () => lookup ?? createArchetypeLookup({ archetype: "person", kind }),
40212
40036
  [lookup, kind]
40213
40037
  );
40214
- const create32 = useMemo(() => {
40038
+ const create31 = useMemo(() => {
40215
40039
  if (createEntityDef?.data?.table) {
40216
40040
  const def2 = createEntityDef;
40217
40041
  return {
@@ -40247,8 +40071,8 @@ function ContactPicker({
40247
40071
  }
40248
40072
  };
40249
40073
  }, [createEntityDef, resolvedLookup]);
40250
- const createFeature = create32?.def.permission?.feature;
40251
- const canCreate = !!create32 && (!createFeature || can(createFeature, "create"));
40074
+ const createFeature = create31?.def.permission?.feature;
40075
+ const canCreate = !!create31 && (!createFeature || can(createFeature, "create"));
40252
40076
  const [search, setSearch] = useState(value?.id ? value.name : value?.name ?? "");
40253
40077
  const [options, setOptions] = useState([]);
40254
40078
  const [searching, setSearching] = useState(false);
@@ -40371,17 +40195,17 @@ function ContactPicker({
40371
40195
  ] })
40372
40196
  );
40373
40197
  }
40374
- if (creating && create32) {
40375
- const nameKey = create32.def.displayField ?? create32.def.fields[0]?.key ?? "name";
40198
+ if (creating && create31) {
40199
+ const nameKey = create31.def.displayField ?? create31.def.fields[0]?.key ?? "name";
40376
40200
  return frame(
40377
40201
  /* @__PURE__ */ jsx(
40378
40202
  LookupCreateInline,
40379
40203
  {
40380
- entityDef: create32.def,
40204
+ entityDef: create31.def,
40381
40205
  initialData: { [nameKey]: newName },
40382
40206
  onCancel: () => setCreating(false),
40383
40207
  save: async (data) => {
40384
- const person = await create32.write(data);
40208
+ const person = await create31.write(data);
40385
40209
  setSearch(person.name || newName);
40386
40210
  setCreating(false);
40387
40211
  onChange({ ...person, name: person.name || newName });
@@ -40699,9 +40523,9 @@ function clearDocumentOpeners() {
40699
40523
  function createOneShotAsk(override) {
40700
40524
  const connection = resolveFayzAgentConnection(override);
40701
40525
  if (!connection) return null;
40702
- const client3 = getFayzAgentClient(connection);
40526
+ const client2 = getFayzAgentClient(connection);
40703
40527
  return async ({ message, inlineFiles, signal }) => {
40704
- const reply = await client3.chat({
40528
+ const reply = await client2.chat({
40705
40529
  message,
40706
40530
  ...inlineFiles?.length ? { inlineFiles } : {},
40707
40531
  ...signal ? { signal } : {},
@@ -40927,7 +40751,7 @@ function useFeatureHelp(def) {
40927
40751
  }
40928
40752
  function HelpButton({
40929
40753
  icon: Icon,
40930
- text: text2,
40754
+ text: text3,
40931
40755
  hint,
40932
40756
  ariaLabel,
40933
40757
  className,
@@ -40945,7 +40769,7 @@ function HelpButton({
40945
40769
  onClick,
40946
40770
  children: [
40947
40771
  /* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }),
40948
- text2
40772
+ text3
40949
40773
  ]
40950
40774
  }
40951
40775
  ) }),
@@ -41310,6 +41134,6 @@ var renderApp = (...args) => {
41310
41134
  return renderApp$1(...args);
41311
41135
  };
41312
41136
 
41313
- 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 };
41137
+ 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 };
41314
41138
  //# sourceMappingURL=index.js.map
41315
41139
  //# sourceMappingURL=index.js.map