@fayz-ai/admin 0.43.2 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ScheduleEditor-MNHZCQIG.js +6 -0
- package/dist/{ScheduleEditor-ZEG6PG3Z.js.map → ScheduleEditor-MNHZCQIG.js.map} +1 -1
- package/dist/SubscriptionPage-JWWS44SE.js +9 -0
- package/dist/{SubscriptionPage-VXZ37WZZ.js.map → SubscriptionPage-JWWS44SE.js.map} +1 -1
- package/dist/{chunk-A5UZL52H.js → chunk-OINP2UYL.js} +3 -3
- package/dist/{chunk-A5UZL52H.js.map → chunk-OINP2UYL.js.map} +1 -1
- package/dist/{chunk-KP3LNCNP.js → chunk-V2IBAF4O.js} +954 -23
- package/dist/chunk-V2IBAF4O.js.map +1 -0
- package/dist/{chunk-HOMD2MAG.js → chunk-VH4LLIMH.js} +3 -3
- package/dist/{chunk-HOMD2MAG.js.map → chunk-VH4LLIMH.js.map} +1 -1
- package/dist/components/connect/useConnectors.d.ts.map +1 -1
- package/dist/components/settings/ConnectedCompanySettings.d.ts.map +1 -1
- package/dist/crud/archetypes/OrderDeliveryBlock.d.ts +32 -0
- package/dist/crud/archetypes/OrderDeliveryBlock.d.ts.map +1 -0
- package/dist/crud/archetypes/OrderDetailPage.d.ts +4 -2
- package/dist/crud/archetypes/OrderDetailPage.d.ts.map +1 -1
- package/dist/crud/archetypes/OrderDetailRail.d.ts +2 -0
- package/dist/crud/archetypes/OrderDetailRail.d.ts.map +1 -1
- package/dist/crud/archetypes/OrderDetailView.d.ts +11 -1
- package/dist/crud/archetypes/OrderDetailView.d.ts.map +1 -1
- package/dist/crud/archetypes/OrderFormView.d.ts +10 -2
- package/dist/crud/archetypes/OrderFormView.d.ts.map +1 -1
- package/dist/crud/archetypes/OrderListView.d.ts +20 -1
- package/dist/crud/archetypes/OrderListView.d.ts.map +1 -1
- package/dist/crud/archetypes/orderStage.d.ts +16 -0
- package/dist/crud/archetypes/orderStage.d.ts.map +1 -0
- package/dist/crud/archetypes/orderVocabulary.d.ts.map +1 -1
- package/dist/crud/archetypes/useOrderKindTransitions.d.ts +10 -0
- package/dist/crud/archetypes/useOrderKindTransitions.d.ts.map +1 -0
- package/dist/crud/relation-field.d.ts.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +740 -918
- package/dist/index.js.map +1 -1
- package/dist/lib/currency.d.ts +33 -5
- package/dist/lib/currency.d.ts.map +1 -1
- package/dist/lib/format.d.ts.map +1 -1
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/index.js +1 -2
- package/dist/plugins/createPluginContext.d.ts.map +1 -1
- package/dist/theme/utils.d.ts +9 -0
- package/dist/theme/utils.d.ts.map +1 -1
- package/dist/units/useHouseCurrencySync.d.ts +9 -0
- package/dist/units/useHouseCurrencySync.d.ts.map +1 -0
- package/dist/units/useUnitBootstrap.d.ts.map +1 -1
- package/package.json +6 -6
- package/dist/ScheduleEditor-ZEG6PG3Z.js +0 -7
- package/dist/SubscriptionPage-VXZ37WZZ.js +0 -9
- package/dist/chunk-3C5Q4OGJ.js +0 -375
- package/dist/chunk-3C5Q4OGJ.js.map +0 -1
- 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-
|
|
3
|
-
export { AccessProvider, UPGRADE_URL, agentDenial, checkAccess, getAccessSnapshot, guardLimit, invalidateLimit, isEntitledByPlan, resolveAccess, useAccess, useAccessOptional, useLimit, useLimitGuard, useModuleNavAccess, useUpgradeModalStore } from './chunk-
|
|
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-
|
|
14
|
-
export { ScheduleDateExceptions, ScheduleEditor, ScheduleGridPanel, createArchetypeLookup, deleteSchedule, getPersonBookable, getPersonLookup, getScheduleBlockConfig, getSchedules, mergeBlockSettings, parseBlockSettings, registerPersonLookup, replaceWeeklySchedules, saveSchedule, setPersonBookable, setScheduleBlockConfig, subscribeScheduleBlockConfig } from './chunk-
|
|
15
|
-
import { getFayzSupabaseClientOptional, getSupabaseClientOptional as getSupabaseClientOptional$1, useAppConfigStore, activePluginIds, hasPlugin, useWorkspaceSwitchingStore, searchWorkspaces, OrgMark, WorkspaceChooserGate, WorkspaceSwitchingHost, createFayzSupabaseClient, resolveAppId, createSupabaseOrgAdapter, createMockOrgAdapter, getFayzSupabaseClient } from './chunk-
|
|
16
|
-
export { OrgMark, activePluginIds, createFayzSupabaseClient, createMockOrgAdapter, createSupabaseOrgAdapter, getFayzSupabaseClient, getFayzSupabaseClientOptional, hasPlugin, orgInitials, useAppConfigStore } from './chunk-
|
|
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,
|
|
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(
|
|
1138
|
-
return
|
|
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
|
|
1260
|
-
const delimiter = detectDelimiter(
|
|
1261
|
-
const { rows } = parseDelimited(
|
|
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:
|
|
1324
|
-
const preview =
|
|
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
|
-
...
|
|
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:
|
|
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(
|
|
1338
|
-
const sheet = buildSheet(file.name.replace(CSV_EXT, ""), parseDelimited(
|
|
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(
|
|
1392
|
+
function detectDelimiter(text3, forced) {
|
|
1395
1393
|
if (forced) return forced;
|
|
1396
|
-
const firstLine =
|
|
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(
|
|
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 =
|
|
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
|
|
1469
|
-
return
|
|
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(
|
|
1633
|
-
return
|
|
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(
|
|
1636
|
-
if (!
|
|
1633
|
+
function sanitizeAssistantText(text3) {
|
|
1634
|
+
if (!text3 || !text3.includes("{") && !text3.includes("[")) return text3;
|
|
1637
1635
|
const cleaned = mapOutsideCode(
|
|
1638
|
-
|
|
1636
|
+
text3,
|
|
1639
1637
|
(chunk) => chunk.replace(TOOL_IN_BRACES, "").replace(FAKE_BUTTON_LINE, "")
|
|
1640
1638
|
);
|
|
1641
|
-
if (cleaned ===
|
|
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
|
-
(
|
|
2571
|
-
const trimmed =
|
|
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,
|
|
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:
|
|
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
|
|
5237
|
+
var cached = null;
|
|
5773
5238
|
function getFayzAgentClient(connection) {
|
|
5774
5239
|
const key = `${connection.apiBaseUrl}|${connection.projectId}|${connection.publishableKey}`;
|
|
5775
|
-
if (
|
|
5776
|
-
const
|
|
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
|
-
|
|
5782
|
-
return
|
|
5246
|
+
cached = { key, client: client2 };
|
|
5247
|
+
return client2;
|
|
5783
5248
|
}
|
|
5784
5249
|
|
|
5785
5250
|
// src/components/connect/useConnectors.ts
|
|
@@ -5920,7 +5385,8 @@ function useConnectors(options = {}) {
|
|
|
5920
5385
|
}, [call2, tenantId2, includeGrants, connection, nonce]);
|
|
5921
5386
|
const revokeGrant = React133__default.useCallback(
|
|
5922
5387
|
async (connector) => {
|
|
5923
|
-
|
|
5388
|
+
if (!tenantId2) throw new Error("Nenhuma conta selecionada.");
|
|
5389
|
+
const response = await call2(`/${connector.id}?tenantId=${encodeURIComponent(tenantId2)}`, { method: "DELETE" });
|
|
5924
5390
|
if (!response.ok) {
|
|
5925
5391
|
const body = await response.json().catch(() => ({}));
|
|
5926
5392
|
throw new Error(body.message ?? "N\xE3o foi poss\xEDvel desconectar.");
|
|
@@ -5928,7 +5394,7 @@ function useConnectors(options = {}) {
|
|
|
5928
5394
|
invalidateGrants();
|
|
5929
5395
|
setGrants((current2) => (current2 ?? []).filter((g) => g.id !== connector.id));
|
|
5930
5396
|
},
|
|
5931
|
-
[call2]
|
|
5397
|
+
[call2, tenantId2]
|
|
5932
5398
|
);
|
|
5933
5399
|
const waitingGrants = includeGrants && !!connection && !!tenantId2 && grants === null;
|
|
5934
5400
|
const connectors = React133__default.useMemo(() => {
|
|
@@ -6748,8 +6214,8 @@ function summaryRows(values) {
|
|
|
6748
6214
|
const rows = [];
|
|
6749
6215
|
const push = (label3, raw) => {
|
|
6750
6216
|
if (raw === void 0 || raw === null || raw === "") return;
|
|
6751
|
-
const
|
|
6752
|
-
if (
|
|
6217
|
+
const text3 = Array.isArray(raw) ? raw.join(", ") : String(raw);
|
|
6218
|
+
if (text3.trim()) rows.push({ label: label3, value: text3 });
|
|
6753
6219
|
};
|
|
6754
6220
|
push(tl("Workspace", "\xC1rea de trabalho"), values[NAME_FIELD]);
|
|
6755
6221
|
push(tl("Contact", "Contato"), values["workspace.email"]);
|
|
@@ -7180,9 +6646,9 @@ function startNativeDictation(locale, cb) {
|
|
|
7180
6646
|
let interim = "";
|
|
7181
6647
|
for (let i = event.resultIndex; i < event.results.length; i++) {
|
|
7182
6648
|
const result = event.results[i];
|
|
7183
|
-
const
|
|
7184
|
-
if (result.isFinal) finalText +=
|
|
7185
|
-
else interim +=
|
|
6649
|
+
const text3 = result[0]?.transcript ?? "";
|
|
6650
|
+
if (result.isFinal) finalText += text3;
|
|
6651
|
+
else interim += text3;
|
|
7186
6652
|
}
|
|
7187
6653
|
cb.onInterim?.((finalText + interim).trim());
|
|
7188
6654
|
};
|
|
@@ -7285,9 +6751,9 @@ function pickVoice(locale) {
|
|
|
7285
6751
|
function stopSpeaking() {
|
|
7286
6752
|
if (isSpeechOutputSupported()) window.speechSynthesis.cancel();
|
|
7287
6753
|
}
|
|
7288
|
-
function speak(
|
|
6754
|
+
function speak(text3, options = { locale: "pt-BR" }) {
|
|
7289
6755
|
if (!isSpeechOutputSupported()) return;
|
|
7290
|
-
const content =
|
|
6756
|
+
const content = text3.trim();
|
|
7291
6757
|
if (!content) return;
|
|
7292
6758
|
window.speechSynthesis.cancel();
|
|
7293
6759
|
const utterance = new SpeechSynthesisUtterance(content);
|
|
@@ -7417,7 +6883,7 @@ function useChat(options) {
|
|
|
7417
6883
|
searchableTools: searchable,
|
|
7418
6884
|
carriedTools: [...pinned]
|
|
7419
6885
|
};
|
|
7420
|
-
const
|
|
6886
|
+
const client2 = getFayzAgentClient(activeConnection);
|
|
7421
6887
|
const upcoming = Array.from({ length: 7 }, (_, i) => {
|
|
7422
6888
|
const d = new Date(Date.now() + (i + 1) * 864e5);
|
|
7423
6889
|
return `${d.toLocaleDateString("pt-BR", { weekday: "long" })}=${d.toISOString().slice(0, 10)}`;
|
|
@@ -7448,7 +6914,7 @@ function useChat(options) {
|
|
|
7448
6914
|
for (let round = 0; round <= MAX_TOOL_ROUNDS; round++) {
|
|
7449
6915
|
toolset = buildToolset();
|
|
7450
6916
|
toolContext.writeTools = toolset.map((t2) => toolByName.get(t2.name)).filter((d) => d?.mode === "persist").map((d) => ({ name: d.name, action: d.permission?.action }));
|
|
7451
|
-
const response = await
|
|
6917
|
+
const response = await client2.chatStream({
|
|
7452
6918
|
message,
|
|
7453
6919
|
toolResults,
|
|
7454
6920
|
confirmAction,
|
|
@@ -7660,8 +7126,8 @@ ${JSON.stringify(snapshot.length === 1 ? snapshot[0] : snapshot)}` : void 0
|
|
|
7660
7126
|
return;
|
|
7661
7127
|
}
|
|
7662
7128
|
const data = await response.json();
|
|
7663
|
-
const
|
|
7664
|
-
store.updateLastAssistant(
|
|
7129
|
+
const text3 = data.choices?.[0]?.message?.content ?? data.content ?? "No response.";
|
|
7130
|
+
store.updateLastAssistant(text3);
|
|
7665
7131
|
} catch {
|
|
7666
7132
|
store.updateLastAssistant("Sorry, I could not connect. Please try again later.");
|
|
7667
7133
|
} finally {
|
|
@@ -7812,12 +7278,12 @@ var AGENT_WAIT_MS = 2500;
|
|
|
7812
7278
|
function prefersReducedMotion2() {
|
|
7813
7279
|
return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
7814
7280
|
}
|
|
7815
|
-
function TypewriterText({ text:
|
|
7281
|
+
function TypewriterText({ text: text3, speed = 26, onDone }) {
|
|
7816
7282
|
const [displayed, setDisplayed] = React133.useState("");
|
|
7817
7283
|
const indexRef = React133.useRef(0);
|
|
7818
7284
|
React133.useEffect(() => {
|
|
7819
7285
|
if (prefersReducedMotion2()) {
|
|
7820
|
-
setDisplayed(
|
|
7286
|
+
setDisplayed(text3);
|
|
7821
7287
|
onDone?.();
|
|
7822
7288
|
return;
|
|
7823
7289
|
}
|
|
@@ -7825,18 +7291,18 @@ function TypewriterText({ text: text2, speed = 26, onDone }) {
|
|
|
7825
7291
|
indexRef.current = 0;
|
|
7826
7292
|
const interval = setInterval(() => {
|
|
7827
7293
|
indexRef.current++;
|
|
7828
|
-
if (indexRef.current >
|
|
7294
|
+
if (indexRef.current > text3.length) {
|
|
7829
7295
|
clearInterval(interval);
|
|
7830
7296
|
onDone?.();
|
|
7831
7297
|
return;
|
|
7832
7298
|
}
|
|
7833
|
-
setDisplayed(
|
|
7299
|
+
setDisplayed(text3.slice(0, indexRef.current));
|
|
7834
7300
|
}, speed);
|
|
7835
7301
|
return () => clearInterval(interval);
|
|
7836
|
-
}, [
|
|
7302
|
+
}, [text3, speed]);
|
|
7837
7303
|
return /* @__PURE__ */ jsxs("span", { children: [
|
|
7838
7304
|
displayed,
|
|
7839
|
-
displayed.length <
|
|
7305
|
+
displayed.length < text3.length && /* @__PURE__ */ jsx("span", { className: "ml-0.5 -mb-px inline-block h-3 w-[2px] bg-current/60 motion-safe:animate-pulse" })
|
|
7840
7306
|
] });
|
|
7841
7307
|
}
|
|
7842
7308
|
var STYLE_ID = "chat-fab-anims";
|
|
@@ -9815,14 +9281,14 @@ function SettingRow({
|
|
|
9815
9281
|
}
|
|
9816
9282
|
);
|
|
9817
9283
|
default: {
|
|
9818
|
-
const
|
|
9819
|
-
const bad = !matchesPattern(setting,
|
|
9284
|
+
const text3 = typeof value === "string" ? value : "";
|
|
9285
|
+
const bad = !matchesPattern(setting, text3);
|
|
9820
9286
|
return /* @__PURE__ */ jsx(
|
|
9821
9287
|
TextRow,
|
|
9822
9288
|
{
|
|
9823
9289
|
label: setting.label,
|
|
9824
9290
|
description: description || void 0,
|
|
9825
|
-
value:
|
|
9291
|
+
value: text3,
|
|
9826
9292
|
placeholder: setting.placeholder,
|
|
9827
9293
|
hint: setting.patternHint,
|
|
9828
9294
|
invalid: bad,
|
|
@@ -10565,10 +10031,10 @@ function useDictation({
|
|
|
10565
10031
|
sessionRef.current = startDictation(
|
|
10566
10032
|
{ locale: resolvedLocale, transcribeEndpoint },
|
|
10567
10033
|
{
|
|
10568
|
-
onInterim: (
|
|
10569
|
-
onFinal: (
|
|
10034
|
+
onInterim: (text3) => callbacks.current.onInterim?.(text3),
|
|
10035
|
+
onFinal: (text3) => {
|
|
10570
10036
|
finish();
|
|
10571
|
-
if (
|
|
10037
|
+
if (text3) callbacks.current.onTranscript(text3);
|
|
10572
10038
|
},
|
|
10573
10039
|
onError: (code) => {
|
|
10574
10040
|
sessionRef.current = null;
|
|
@@ -10891,8 +10357,8 @@ function ChatComposer({
|
|
|
10891
10357
|
const parsing = attachments.some((a) => a.status === "parsing");
|
|
10892
10358
|
const readyAttachments = attachments.filter((a) => a.status === "ready").length;
|
|
10893
10359
|
const submit = React133.useCallback(
|
|
10894
|
-
(
|
|
10895
|
-
const trimmed =
|
|
10360
|
+
(text3) => {
|
|
10361
|
+
const trimmed = text3.trim();
|
|
10896
10362
|
const media = useChatStore.getState().composerMedia;
|
|
10897
10363
|
if (!trimmed && !readyAttachments && !media || parsing || isStreaming || !isConfigured || blocked) return;
|
|
10898
10364
|
setInput("");
|
|
@@ -10906,17 +10372,17 @@ function ChatComposer({
|
|
|
10906
10372
|
const dictation = useDictation({
|
|
10907
10373
|
locale: voice?.locale,
|
|
10908
10374
|
transcribeEndpoint: voice?.transcribeEndpoint,
|
|
10909
|
-
onInterim: (
|
|
10910
|
-
onTranscript: (
|
|
10375
|
+
onInterim: (text3) => setInput(text3),
|
|
10376
|
+
onTranscript: (text3) => {
|
|
10911
10377
|
if (autoSend) {
|
|
10912
|
-
submit(
|
|
10378
|
+
submit(text3);
|
|
10913
10379
|
return;
|
|
10914
10380
|
}
|
|
10915
|
-
setInput(
|
|
10381
|
+
setInput(text3);
|
|
10916
10382
|
const el = textareaRef.current;
|
|
10917
10383
|
if (el) {
|
|
10918
10384
|
el.focus();
|
|
10919
|
-
requestAnimationFrame(() => el.setSelectionRange(
|
|
10385
|
+
requestAnimationFrame(() => el.setSelectionRange(text3.length, text3.length));
|
|
10920
10386
|
}
|
|
10921
10387
|
}
|
|
10922
10388
|
});
|
|
@@ -11069,8 +10535,8 @@ function ChatComposer({
|
|
|
11069
10535
|
if (!canAttach) return;
|
|
11070
10536
|
const files = Array.from(event.clipboardData?.files ?? []);
|
|
11071
10537
|
if (!files.length) return;
|
|
11072
|
-
const
|
|
11073
|
-
if (
|
|
10538
|
+
const text3 = event.clipboardData?.getData("text/plain");
|
|
10539
|
+
if (text3 && files.every((f) => f.type.startsWith("image/"))) return;
|
|
11074
10540
|
event.preventDefault();
|
|
11075
10541
|
receiveFiles(files);
|
|
11076
10542
|
},
|
|
@@ -11390,14 +10856,14 @@ function MdLink({ href, children }) {
|
|
|
11390
10856
|
}
|
|
11391
10857
|
);
|
|
11392
10858
|
}
|
|
11393
|
-
function renderInline(
|
|
10859
|
+
function renderInline(text3, keyBase) {
|
|
11394
10860
|
const out = [];
|
|
11395
10861
|
const pattern = /(`[^`]+`)|(\*\*[^*]+\*\*)|(\*[^*]+\*)|(\[[^\]]+\]\([^)\s]+\))/g;
|
|
11396
10862
|
let last = 0;
|
|
11397
10863
|
let match;
|
|
11398
10864
|
let i = 0;
|
|
11399
|
-
while ((match = pattern.exec(
|
|
11400
|
-
if (match.index > last) out.push(
|
|
10865
|
+
while ((match = pattern.exec(text3)) !== null) {
|
|
10866
|
+
if (match.index > last) out.push(text3.slice(last, match.index));
|
|
11401
10867
|
const token = match[0];
|
|
11402
10868
|
const key = `${keyBase}-${i++}`;
|
|
11403
10869
|
if (token.startsWith("`")) {
|
|
@@ -11420,7 +10886,7 @@ function renderInline(text2, keyBase) {
|
|
|
11420
10886
|
}
|
|
11421
10887
|
last = match.index + token.length;
|
|
11422
10888
|
}
|
|
11423
|
-
if (last <
|
|
10889
|
+
if (last < text3.length) out.push(text3.slice(last));
|
|
11424
10890
|
return out;
|
|
11425
10891
|
}
|
|
11426
10892
|
var LIST_RE = /^(\s*)([-*]|\d+[.)])\s+(.*)$/;
|
|
@@ -12201,13 +11667,13 @@ function formatValue(value) {
|
|
|
12201
11667
|
if (typeof value === "boolean") return value ? "\u2713" : "\u2014";
|
|
12202
11668
|
if (Array.isArray(value)) return value.map((v) => formatValue(v)).join(", ");
|
|
12203
11669
|
if (value && typeof value === "object") return JSON.stringify(value);
|
|
12204
|
-
const
|
|
12205
|
-
const iso = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})/.exec(
|
|
11670
|
+
const text3 = String(value);
|
|
11671
|
+
const iso = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})/.exec(text3);
|
|
12206
11672
|
if (iso) {
|
|
12207
|
-
const parsed = new Date(
|
|
11673
|
+
const parsed = new Date(text3);
|
|
12208
11674
|
if (!Number.isNaN(parsed.getTime())) return parsed.toLocaleString();
|
|
12209
11675
|
}
|
|
12210
|
-
return
|
|
11676
|
+
return text3;
|
|
12211
11677
|
}
|
|
12212
11678
|
var PLAIN_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
12213
11679
|
function toInputDate(value, type) {
|
|
@@ -12322,7 +11788,7 @@ function usePrefersReducedMotion() {
|
|
|
12322
11788
|
return reduced;
|
|
12323
11789
|
}
|
|
12324
11790
|
function TypedText({
|
|
12325
|
-
text:
|
|
11791
|
+
text: text3,
|
|
12326
11792
|
className,
|
|
12327
11793
|
as: Tag3 = "p",
|
|
12328
11794
|
start = true,
|
|
@@ -12330,7 +11796,7 @@ function TypedText({
|
|
|
12330
11796
|
onDone
|
|
12331
11797
|
}) {
|
|
12332
11798
|
const reduced = usePrefersReducedMotion();
|
|
12333
|
-
const [count, setCount] = React133.useState(reduced ?
|
|
11799
|
+
const [count, setCount] = React133.useState(reduced ? text3.length : 0);
|
|
12334
11800
|
const done = React133.useRef(onDone);
|
|
12335
11801
|
done.current = onDone;
|
|
12336
11802
|
React133.useEffect(() => {
|
|
@@ -12338,19 +11804,19 @@ function TypedText({
|
|
|
12338
11804
|
setCount(0);
|
|
12339
11805
|
return;
|
|
12340
11806
|
}
|
|
12341
|
-
if (reduced || !
|
|
12342
|
-
setCount(
|
|
11807
|
+
if (reduced || !text3) {
|
|
11808
|
+
setCount(text3.length);
|
|
12343
11809
|
const id = setTimeout(() => done.current?.(), 0);
|
|
12344
11810
|
return () => clearTimeout(id);
|
|
12345
11811
|
}
|
|
12346
11812
|
setCount(0);
|
|
12347
|
-
const step = Math.min(MAX_CHAR_MS, Math.max(MIN_CHAR_MS, Math.round(TYPE_MS /
|
|
11813
|
+
const step = Math.min(MAX_CHAR_MS, Math.max(MIN_CHAR_MS, Math.round(TYPE_MS / text3.length)));
|
|
12348
11814
|
let i = 0;
|
|
12349
11815
|
let timer;
|
|
12350
11816
|
const first = setTimeout(function tick() {
|
|
12351
11817
|
i += 1;
|
|
12352
11818
|
setCount(i);
|
|
12353
|
-
if (i >=
|
|
11819
|
+
if (i >= text3.length) {
|
|
12354
11820
|
done.current?.();
|
|
12355
11821
|
return;
|
|
12356
11822
|
}
|
|
@@ -12360,11 +11826,11 @@ function TypedText({
|
|
|
12360
11826
|
clearTimeout(first);
|
|
12361
11827
|
clearTimeout(timer);
|
|
12362
11828
|
};
|
|
12363
|
-
}, [
|
|
11829
|
+
}, [text3, reduced, start, startDelay]);
|
|
12364
11830
|
return /* @__PURE__ */ jsxs(Tag3, { className: cn("grid", className), children: [
|
|
12365
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "invisible", style: { gridArea: "1 / 1" }, children:
|
|
12366
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children:
|
|
12367
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": true, style: { gridArea: "1 / 1" }, children:
|
|
11831
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "invisible", style: { gridArea: "1 / 1" }, children: text3 }),
|
|
11832
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: text3 }),
|
|
11833
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, style: { gridArea: "1 / 1" }, children: text3.slice(0, count) })
|
|
12368
11834
|
] });
|
|
12369
11835
|
}
|
|
12370
11836
|
function RevealSequence({
|
|
@@ -12655,11 +12121,11 @@ function ChatConversation({
|
|
|
12655
12121
|
const el = event.currentTarget;
|
|
12656
12122
|
setAtBottom(el.scrollHeight - el.scrollTop - el.clientHeight < 48);
|
|
12657
12123
|
};
|
|
12658
|
-
const send = (
|
|
12124
|
+
const send = (text3) => {
|
|
12659
12125
|
setView("thread");
|
|
12660
12126
|
setAtBottom(true);
|
|
12661
12127
|
setSuggestionsOpen(false);
|
|
12662
|
-
sendMessage(
|
|
12128
|
+
sendMessage(text3);
|
|
12663
12129
|
};
|
|
12664
12130
|
const queuedPrompt = useChatStore((s) => s.queuedPrompt);
|
|
12665
12131
|
const consumeQueuedPrompt = useChatStore((s) => s.consumeQueuedPrompt);
|
|
@@ -13032,7 +12498,7 @@ function AgentAvatar({
|
|
|
13032
12498
|
className
|
|
13033
12499
|
}) {
|
|
13034
12500
|
const [failed, setFailed] = React133.useState(false);
|
|
13035
|
-
const { box, text:
|
|
12501
|
+
const { box, text: text3, px } = SIZES[size];
|
|
13036
12502
|
if (Face) {
|
|
13037
12503
|
return /* @__PURE__ */ jsx(
|
|
13038
12504
|
"span",
|
|
@@ -13051,7 +12517,7 @@ function AgentAvatar({
|
|
|
13051
12517
|
"relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-full",
|
|
13052
12518
|
"bg-muted font-medium text-muted-foreground",
|
|
13053
12519
|
box,
|
|
13054
|
-
|
|
12520
|
+
text3,
|
|
13055
12521
|
className
|
|
13056
12522
|
),
|
|
13057
12523
|
children: [
|
|
@@ -13596,10 +13062,10 @@ function TaskQuickAdd({ parentId }) {
|
|
|
13596
13062
|
)
|
|
13597
13063
|
] });
|
|
13598
13064
|
}
|
|
13599
|
-
var
|
|
13065
|
+
var STORAGE_KEY = "saas-core:locale";
|
|
13600
13066
|
function readPersistedLocale() {
|
|
13601
13067
|
try {
|
|
13602
|
-
return localStorage.getItem(
|
|
13068
|
+
return localStorage.getItem(STORAGE_KEY) ?? void 0;
|
|
13603
13069
|
} catch {
|
|
13604
13070
|
return void 0;
|
|
13605
13071
|
}
|
|
@@ -13611,7 +13077,7 @@ var useLocaleStore = create((set) => ({
|
|
|
13611
13077
|
locale: getPersistedLocale(),
|
|
13612
13078
|
setLocale: (locale) => {
|
|
13613
13079
|
try {
|
|
13614
|
-
localStorage.setItem(
|
|
13080
|
+
localStorage.setItem(STORAGE_KEY, locale);
|
|
13615
13081
|
} catch {
|
|
13616
13082
|
}
|
|
13617
13083
|
set({ locale });
|
|
@@ -14497,23 +13963,23 @@ var TYPING_LEAD_MS = 420;
|
|
|
14497
13963
|
var TYPING_MS_PER_WORD = 55;
|
|
14498
13964
|
var TYPING_CEILING_MS = 1200;
|
|
14499
13965
|
var TYPING_FRAME_MS = 45;
|
|
14500
|
-
function say(
|
|
13966
|
+
function say(text3, cards) {
|
|
14501
13967
|
const chat = useChatStore.getState();
|
|
14502
13968
|
const id = `guided-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
14503
|
-
const trimmed =
|
|
13969
|
+
const trimmed = text3.trim();
|
|
14504
13970
|
chat.addMessage({
|
|
14505
13971
|
id,
|
|
14506
13972
|
role: "assistant",
|
|
14507
13973
|
// Empty content is what renders the typing dots (see ChatMessages).
|
|
14508
|
-
content: trimmed ? "" :
|
|
13974
|
+
content: trimmed ? "" : text3,
|
|
14509
13975
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14510
13976
|
...cards ? { cards } : {}
|
|
14511
13977
|
});
|
|
14512
13978
|
chat.setOpen(true);
|
|
14513
|
-
if (trimmed) typeInto(id,
|
|
13979
|
+
if (trimmed) typeInto(id, text3);
|
|
14514
13980
|
}
|
|
14515
|
-
function typeInto(id,
|
|
14516
|
-
const words2 =
|
|
13981
|
+
function typeInto(id, text3) {
|
|
13982
|
+
const words2 = text3.split(/(\s+)/);
|
|
14517
13983
|
const wordCount = words2.filter((w) => w.trim()).length;
|
|
14518
13984
|
const total = Math.min(TYPING_CEILING_MS, wordCount * TYPING_MS_PER_WORD);
|
|
14519
13985
|
const frames = Math.max(1, Math.round(total / TYPING_FRAME_MS));
|
|
@@ -14523,7 +13989,7 @@ function typeInto(id, text2) {
|
|
|
14523
13989
|
const finish = () => {
|
|
14524
13990
|
if (timer) clearTimeout(timer);
|
|
14525
13991
|
typers.delete(finish);
|
|
14526
|
-
useChatStore.getState().setMessageContent(id,
|
|
13992
|
+
useChatStore.getState().setMessageContent(id, text3);
|
|
14527
13993
|
};
|
|
14528
13994
|
const step = () => {
|
|
14529
13995
|
cursor += perFrame;
|
|
@@ -14543,8 +14009,8 @@ function flushTyping() {
|
|
|
14543
14009
|
var BEAT_FLOOR_MS = 1400;
|
|
14544
14010
|
var MS_PER_WORD = 260;
|
|
14545
14011
|
var BEAT_CEILING_MS = 6e3;
|
|
14546
|
-
function readingTime(
|
|
14547
|
-
const words2 =
|
|
14012
|
+
function readingTime(text3) {
|
|
14013
|
+
const words2 = text3.trim().split(/\s+/).length;
|
|
14548
14014
|
return Math.min(BEAT_CEILING_MS, BEAT_FLOOR_MS + words2 * MS_PER_WORD);
|
|
14549
14015
|
}
|
|
14550
14016
|
var NAV_MS = 1e3;
|
|
@@ -16073,7 +15539,7 @@ function ActivationProvider() {
|
|
|
16073
15539
|
const orgName = useOrganizationStore((s) => s.currentOrg?.name);
|
|
16074
15540
|
const user = useAuthStore((s) => s.user);
|
|
16075
15541
|
const setCatalog = useActivationStore((s) => s.setCatalog);
|
|
16076
|
-
const
|
|
15542
|
+
const load2 = useActivationStore((s) => s.load);
|
|
16077
15543
|
const programs = runtime?.onboardingPrograms ?? [];
|
|
16078
15544
|
const settingsIds = useSettingsTabsStore((s) => s.ids);
|
|
16079
15545
|
const routeKey = (runtime?.routes.length ?? 0) + ":" + settingsIds.join(",");
|
|
@@ -16096,7 +15562,7 @@ function ActivationProvider() {
|
|
|
16096
15562
|
if (!tenantId2) return;
|
|
16097
15563
|
let cancelled = false;
|
|
16098
15564
|
void (async () => {
|
|
16099
|
-
await
|
|
15565
|
+
await load2(tenantId2);
|
|
16100
15566
|
if (cancelled || !user) return;
|
|
16101
15567
|
const rows = useActivationStore.getState().rows ?? [];
|
|
16102
15568
|
const stale = /* @__PURE__ */ new Set([
|
|
@@ -16118,12 +15584,12 @@ function ActivationProvider() {
|
|
|
16118
15584
|
userName: user.fullName || user.email,
|
|
16119
15585
|
items: missing
|
|
16120
15586
|
});
|
|
16121
|
-
if (ok && !cancelled) await
|
|
15587
|
+
if (ok && !cancelled) await load2(tenantId2);
|
|
16122
15588
|
})();
|
|
16123
15589
|
return () => {
|
|
16124
15590
|
cancelled = true;
|
|
16125
15591
|
};
|
|
16126
|
-
}, [tenantId2, catalog, answers, hasRoute, settingsIds, user?.id,
|
|
15592
|
+
}, [tenantId2, catalog, answers, hasRoute, settingsIds, user?.id, load2]);
|
|
16127
15593
|
React133.useEffect(() => {
|
|
16128
15594
|
if (!tenantId2) {
|
|
16129
15595
|
useBusinessProfileStore.getState().clear();
|
|
@@ -16200,8 +15666,8 @@ var useHandbookStore = create((set, get) => ({
|
|
|
16200
15666
|
open: async (path) => {
|
|
16201
15667
|
const { tenantId: tenantId2, pages } = get();
|
|
16202
15668
|
if (!tenantId2) return null;
|
|
16203
|
-
const
|
|
16204
|
-
if (
|
|
15669
|
+
const cached2 = (pages ?? []).find((p) => p.path === path);
|
|
15670
|
+
if (cached2) return cached2;
|
|
16205
15671
|
return readHandbookPage(tenantId2, path);
|
|
16206
15672
|
},
|
|
16207
15673
|
write: async (input) => {
|
|
@@ -17047,14 +16513,14 @@ function NotebookRailPanel() {
|
|
|
17047
16513
|
function HandbookProvider() {
|
|
17048
16514
|
const tenantId2 = useOrganizationStore((s) => s.currentOrg?.id);
|
|
17049
16515
|
const userId = useAuthStore((s) => s.user?.id);
|
|
17050
|
-
const
|
|
16516
|
+
const load2 = useHandbookStore((s) => s.load);
|
|
17051
16517
|
const setUser = useHandbookStore((s) => s.setUser);
|
|
17052
16518
|
React133.useEffect(() => {
|
|
17053
16519
|
setUser(userId);
|
|
17054
16520
|
}, [userId, setUser]);
|
|
17055
16521
|
React133.useEffect(() => {
|
|
17056
|
-
if (tenantId2) void
|
|
17057
|
-
}, [tenantId2,
|
|
16522
|
+
if (tenantId2) void load2(tenantId2);
|
|
16523
|
+
}, [tenantId2, load2]);
|
|
17058
16524
|
useLocalNotesImport(tenantId2, userId);
|
|
17059
16525
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
17060
16526
|
/* @__PURE__ */ jsx(NotebookRailPanel, {}),
|
|
@@ -17112,9 +16578,9 @@ function useUnitBootstrap() {
|
|
|
17112
16578
|
const orgId = tenant?.org?.id;
|
|
17113
16579
|
React133.useEffect(() => {
|
|
17114
16580
|
if (!orgId) return;
|
|
17115
|
-
const { loadedFor, load, reset } = useUnitStore.getState();
|
|
16581
|
+
const { loadedFor, load: load2, reset } = useUnitStore.getState();
|
|
17116
16582
|
if (loadedFor && loadedFor !== orgId) reset();
|
|
17117
|
-
void
|
|
16583
|
+
void load2(orgId, userId);
|
|
17118
16584
|
}, [orgId, userId]);
|
|
17119
16585
|
}
|
|
17120
16586
|
var NO_EXTRA_ROLE = "__none__";
|
|
@@ -17500,14 +16966,14 @@ function startFayzEventBridge(override) {
|
|
|
17500
16966
|
};
|
|
17501
16967
|
}
|
|
17502
16968
|
debug(`started \u2192 ${connection.apiBaseUrl} (project ${connection.projectId})`);
|
|
17503
|
-
const
|
|
16969
|
+
const client2 = createFayzEventsClient({
|
|
17504
16970
|
baseUrl: connection.apiBaseUrl,
|
|
17505
16971
|
projectId: connection.projectId,
|
|
17506
16972
|
publishableKey: connection.publishableKey
|
|
17507
16973
|
});
|
|
17508
16974
|
const off = registerEventSink((event) => {
|
|
17509
|
-
debug(`enqueue ${event.key}`, { tenantId: event.tenantId, pending:
|
|
17510
|
-
|
|
16975
|
+
debug(`enqueue ${event.key}`, { tenantId: event.tenantId, pending: client2.pending() + 1 });
|
|
16976
|
+
client2.enqueue({
|
|
17511
16977
|
// The dedupe id is minted at the sink, once per emission — a transport
|
|
17512
16978
|
// retry reuses it, so the server never runs the same fact twice.
|
|
17513
16979
|
id: crypto.randomUUID(),
|
|
@@ -17519,7 +16985,7 @@ function startFayzEventBridge(override) {
|
|
|
17519
16985
|
subject: event.subject
|
|
17520
16986
|
});
|
|
17521
16987
|
});
|
|
17522
|
-
active = { client:
|
|
16988
|
+
active = { client: client2, off };
|
|
17523
16989
|
return stopFayzEventBridge;
|
|
17524
16990
|
}
|
|
17525
16991
|
function stopFayzEventBridge() {
|
|
@@ -17772,6 +17238,24 @@ function tripletLuminance(triplet) {
|
|
|
17772
17238
|
});
|
|
17773
17239
|
return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2];
|
|
17774
17240
|
}
|
|
17241
|
+
function contrast(a, b) {
|
|
17242
|
+
return (Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05);
|
|
17243
|
+
}
|
|
17244
|
+
function readableInkOn(primary, surface) {
|
|
17245
|
+
const surfaceL = tripletLuminance(surface);
|
|
17246
|
+
const primaryL = tripletLuminance(primary);
|
|
17247
|
+
if (!primary || surfaceL == null || primaryL == null) return primary;
|
|
17248
|
+
if (contrast(primaryL, surfaceL) >= 3) return primary;
|
|
17249
|
+
const [h, sat, light] = primary.trim().split("/")[0].trim().split(/\s+/);
|
|
17250
|
+
const step = surfaceL > 0.5 ? -2 : 2;
|
|
17251
|
+
let l = parseFloat(light);
|
|
17252
|
+
for (let i = 0; i < 50; i++) {
|
|
17253
|
+
l = Math.min(100, Math.max(0, l + step));
|
|
17254
|
+
const candidate = `${h} ${sat} ${Math.round(l * 10) / 10}%`;
|
|
17255
|
+
if (contrast(tripletLuminance(candidate) ?? surfaceL, surfaceL) >= 4.5 || l === 0 || l === 100) return candidate;
|
|
17256
|
+
}
|
|
17257
|
+
return primary;
|
|
17258
|
+
}
|
|
17775
17259
|
function inkOnTriplet(triplet) {
|
|
17776
17260
|
const l = tripletLuminance(triplet);
|
|
17777
17261
|
return l != null && l > 0.45 ? "0 0% 10%" : "0 0% 100%";
|
|
@@ -17959,6 +17443,9 @@ function applyTheme(theme, element) {
|
|
|
17959
17443
|
target.style.setProperty(cssVar, value);
|
|
17960
17444
|
}
|
|
17961
17445
|
}
|
|
17446
|
+
const paper = tripletLuminance(theme.colors.content) != null ? theme.colors.content : theme.colors.background;
|
|
17447
|
+
const ink = readableInkOn(theme.colors.primary, paper);
|
|
17448
|
+
if (ink) target.style.setProperty("--primary-ink", ink);
|
|
17962
17449
|
persistBootPalette(theme.colors);
|
|
17963
17450
|
}
|
|
17964
17451
|
function hexToHslTriplet(hex) {
|
|
@@ -17985,14 +17472,14 @@ function hexToHslTriplet(hex) {
|
|
|
17985
17472
|
}
|
|
17986
17473
|
|
|
17987
17474
|
// src/stores/theme.store.ts
|
|
17988
|
-
var
|
|
17475
|
+
var STORAGE_KEY2 = "saas-core:theme-mode";
|
|
17989
17476
|
function getSystemPreference() {
|
|
17990
17477
|
if (typeof window === "undefined") return "light";
|
|
17991
17478
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
17992
17479
|
}
|
|
17993
17480
|
function getSavedMode() {
|
|
17994
17481
|
if (typeof window === "undefined") return "light";
|
|
17995
|
-
const saved = localStorage.getItem(
|
|
17482
|
+
const saved = localStorage.getItem(STORAGE_KEY2);
|
|
17996
17483
|
if (saved === "light" || saved === "dark" || saved === "system") return saved;
|
|
17997
17484
|
return "light";
|
|
17998
17485
|
}
|
|
@@ -18044,7 +17531,7 @@ function createThemeStore() {
|
|
|
18044
17531
|
const resolved = resolveMode(mode);
|
|
18045
17532
|
set({ mode, resolvedMode: resolved });
|
|
18046
17533
|
if (typeof window !== "undefined") {
|
|
18047
|
-
localStorage.setItem(
|
|
17534
|
+
localStorage.setItem(STORAGE_KEY2, mode);
|
|
18048
17535
|
}
|
|
18049
17536
|
const { overrides } = get();
|
|
18050
17537
|
const baseTheme = resolved === "dark" ? darkTheme : lightTheme;
|
|
@@ -18374,12 +17861,12 @@ function PublicSurveyPage({ token, appName }) {
|
|
|
18374
17861
|
const [failed, setFailed] = React133__default.useState(null);
|
|
18375
17862
|
React133__default.useEffect(() => {
|
|
18376
17863
|
let alive = true;
|
|
18377
|
-
const
|
|
18378
|
-
if (!
|
|
17864
|
+
const client2 = getFayzSupabaseClientOptional();
|
|
17865
|
+
if (!client2) {
|
|
18379
17866
|
setLoaded({ status: "not_found" });
|
|
18380
17867
|
return;
|
|
18381
17868
|
}
|
|
18382
|
-
|
|
17869
|
+
client2.rpc("crm_survey_invite_load", { p_token: token }).then(({ data, error }) => {
|
|
18383
17870
|
if (!alive) return;
|
|
18384
17871
|
setLoaded(error ? { status: "not_found" } : data);
|
|
18385
17872
|
});
|
|
@@ -18398,9 +17885,9 @@ function PublicSurveyPage({ token, appName }) {
|
|
|
18398
17885
|
if (missing.length > 0 || sending) return;
|
|
18399
17886
|
setSending(true);
|
|
18400
17887
|
setFailed(null);
|
|
18401
|
-
const
|
|
17888
|
+
const client2 = getFayzSupabaseClientOptional();
|
|
18402
17889
|
const answers = questions.map((q) => ({ question_id: q.id, rating: draft[q.id]?.rating ?? null, comment: draft[q.id]?.comment ?? null })).filter((a) => a.rating != null || (a.comment ?? "").trim() !== "");
|
|
18403
|
-
const { data, error } = await
|
|
17890
|
+
const { data, error } = await client2.rpc("crm_survey_invite_submit", {
|
|
18404
17891
|
p_token: token,
|
|
18405
17892
|
p_answers: answers,
|
|
18406
17893
|
p_respondent_name: name.trim() || null
|
|
@@ -19017,8 +18504,8 @@ function coerceField(field, value) {
|
|
|
19017
18504
|
}
|
|
19018
18505
|
const first = Array.isArray(value) ? value[0] : value;
|
|
19019
18506
|
if (typeof first !== "string") return void 0;
|
|
19020
|
-
const
|
|
19021
|
-
return
|
|
18507
|
+
const text3 = field.normalize ? field.normalize(first) : first.trim();
|
|
18508
|
+
return text3 || void 0;
|
|
19022
18509
|
}
|
|
19023
18510
|
|
|
19024
18511
|
// src/onboarding/analyze-site.ts
|
|
@@ -19439,14 +18926,14 @@ var useAppDirectoryStore = create((set, get) => ({
|
|
|
19439
18926
|
load: async (tenantId2, currentAppId, deps) => {
|
|
19440
18927
|
const state = get();
|
|
19441
18928
|
if (state.status !== "idle" && state.tenantId === tenantId2) return;
|
|
19442
|
-
const
|
|
19443
|
-
if (!
|
|
18929
|
+
const client2 = deps?.client === void 0 ? getFayzSupabaseClientOptional() : deps.client;
|
|
18930
|
+
if (!client2) {
|
|
19444
18931
|
set({ status: "done", tenantId: tenantId2 });
|
|
19445
18932
|
return;
|
|
19446
18933
|
}
|
|
19447
18934
|
set({ status: "loading", tenantId: tenantId2 });
|
|
19448
18935
|
try {
|
|
19449
|
-
const config = await fetchAppConfig(
|
|
18936
|
+
const config = await fetchAppConfig(client2, { tenantId: tenantId2 });
|
|
19450
18937
|
set({ apps: normalize(config.apps, currentAppId), status: "done", tenantId: tenantId2 });
|
|
19451
18938
|
} catch {
|
|
19452
18939
|
set({ status: "done", tenantId: tenantId2 });
|
|
@@ -19462,10 +18949,10 @@ function resetAppDirectory() {
|
|
|
19462
18949
|
function useAppDirectory() {
|
|
19463
18950
|
const tenantId2 = useActiveTenantId();
|
|
19464
18951
|
const apps = useAppDirectoryStore((s) => s.apps);
|
|
19465
|
-
const
|
|
18952
|
+
const load2 = useAppDirectoryStore((s) => s.load);
|
|
19466
18953
|
React133.useEffect(() => {
|
|
19467
|
-
if (tenantId2) void
|
|
19468
|
-
}, [tenantId2,
|
|
18954
|
+
if (tenantId2) void load2(tenantId2, resolveAppId());
|
|
18955
|
+
}, [tenantId2, load2]);
|
|
19469
18956
|
return { apps };
|
|
19470
18957
|
}
|
|
19471
18958
|
var FAMILY_SUFFIX = "Control";
|
|
@@ -20291,9 +19778,9 @@ function WorkspaceUnitRow({ canCreate = true }) {
|
|
|
20291
19778
|
}
|
|
20292
19779
|
var TABLE2 = "published_sites";
|
|
20293
19780
|
function db() {
|
|
20294
|
-
const
|
|
20295
|
-
if (!
|
|
20296
|
-
return
|
|
19781
|
+
const client2 = getSupabaseClientOptional();
|
|
19782
|
+
if (!client2) throw new Error("[fayz-projects] Supabase not initialized");
|
|
19783
|
+
return client2;
|
|
20297
19784
|
}
|
|
20298
19785
|
function tenantId() {
|
|
20299
19786
|
return useOrganizationStore.getState().currentOrg?.id ?? getActiveTenantId();
|
|
@@ -20437,7 +19924,7 @@ function SeuSiteWidget({ fallback, onEdit }) {
|
|
|
20437
19924
|
const t = useTranslation();
|
|
20438
19925
|
const currentOrgId = useOrganizationStore((s) => s.currentOrg?.id);
|
|
20439
19926
|
const projects = useFayzProjectsStore((s) => s.projects);
|
|
20440
|
-
const
|
|
19927
|
+
const load2 = useFayzProjectsStore((s) => s.load);
|
|
20441
19928
|
const loadedFor = useFayzProjectsStore((s) => s.loadedFor);
|
|
20442
19929
|
const collapsed = useLayoutStore((s) => s.sidebarCollapsed);
|
|
20443
19930
|
const [selectedId, setSelectedId] = React133.useState(null);
|
|
@@ -20461,8 +19948,8 @@ function SeuSiteWidget({ fallback, onEdit }) {
|
|
|
20461
19948
|
};
|
|
20462
19949
|
React133.useEffect(() => () => cancelClose(), []);
|
|
20463
19950
|
React133.useEffect(() => {
|
|
20464
|
-
if (loadedFor !== (currentOrgId ?? null)) void
|
|
20465
|
-
}, [currentOrgId, loadedFor,
|
|
19951
|
+
if (loadedFor !== (currentOrgId ?? null)) void load2(currentOrgId);
|
|
19952
|
+
}, [currentOrgId, loadedFor, load2]);
|
|
20466
19953
|
const active2 = projects.find((p) => p.id === selectedId) ?? defaultProjectOf(projects) ?? synthFromFallback(fallback);
|
|
20467
19954
|
if (!active2) return null;
|
|
20468
19955
|
const Icon = KIND_ICON2[active2.kind] ?? Globe;
|
|
@@ -21536,17 +21023,17 @@ function ConsentBody({
|
|
|
21536
21023
|
busy
|
|
21537
21024
|
}) {
|
|
21538
21025
|
if (!payload) return /* @__PURE__ */ jsx(ConsentSkeleton, {});
|
|
21539
|
-
const { client:
|
|
21026
|
+
const { client: client2, access, organizations } = payload;
|
|
21540
21027
|
const org = organizations.find((o) => o.tenantId === tenantId2);
|
|
21541
|
-
const mark =
|
|
21028
|
+
const mark = client2.logoUri ?? knownClientMark(client2.website, client2.identityVerified === true, client2.name);
|
|
21542
21029
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
21543
21030
|
/* @__PURE__ */ jsxs("div", { className: "mb-6 flex items-center justify-center gap-3", children: [
|
|
21544
|
-
/* @__PURE__ */ jsx(MarkBadge, { fallback:
|
|
21031
|
+
/* @__PURE__ */ jsx(MarkBadge, { fallback: client2.name, children: mark ? /* @__PURE__ */ jsx("img", { src: mark, alt: "", className: "h-full w-full object-cover" }) : null }),
|
|
21545
21032
|
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "\u21C4" }),
|
|
21546
21033
|
/* @__PURE__ */ jsx(MarkBadge, { fallback: product, children: logo })
|
|
21547
21034
|
] }),
|
|
21548
21035
|
/* @__PURE__ */ jsxs("h1", { className: "text-center text-xl font-semibold text-foreground", children: [
|
|
21549
|
-
|
|
21036
|
+
client2.name,
|
|
21550
21037
|
" quer acessar seus dados"
|
|
21551
21038
|
] }),
|
|
21552
21039
|
/* @__PURE__ */ jsxs("dl", { className: "mt-6 divide-y divide-border overflow-hidden rounded-xl border border-border text-sm", children: [
|
|
@@ -21555,8 +21042,8 @@ function ConsentBody({
|
|
|
21555
21042
|
{
|
|
21556
21043
|
label: "Aplicativo",
|
|
21557
21044
|
value: /* @__PURE__ */ jsxs("span", { children: [
|
|
21558
|
-
|
|
21559
|
-
|
|
21045
|
+
client2.name,
|
|
21046
|
+
client2.identityVerified !== true && // Not an alarm — most CLI clients register themselves and are
|
|
21560
21047
|
// perfectly legitimate. But the user is about to hand over an
|
|
21561
21048
|
// organization's data, and "this name is self-declared" is a
|
|
21562
21049
|
// fact they are entitled to before deciding.
|
|
@@ -21564,14 +21051,14 @@ function ConsentBody({
|
|
|
21564
21051
|
] })
|
|
21565
21052
|
}
|
|
21566
21053
|
),
|
|
21567
|
-
|
|
21054
|
+
client2.website && /* @__PURE__ */ jsx(
|
|
21568
21055
|
Row2,
|
|
21569
21056
|
{
|
|
21570
21057
|
label: "Site",
|
|
21571
|
-
value: /* @__PURE__ */ jsx("a", { href:
|
|
21058
|
+
value: /* @__PURE__ */ jsx("a", { href: client2.website, target: "_blank", rel: "noreferrer noopener", className: "text-primary hover:underline", children: client2.website })
|
|
21572
21059
|
}
|
|
21573
21060
|
),
|
|
21574
|
-
/* @__PURE__ */ jsx(Row2, { label: "Retorna para", value: /* @__PURE__ */ jsx("span", { className: "break-all font-mono text-xs", children:
|
|
21061
|
+
/* @__PURE__ */ jsx(Row2, { label: "Retorna para", value: /* @__PURE__ */ jsx("span", { className: "break-all font-mono text-xs", children: client2.redirectUri }) }),
|
|
21575
21062
|
/* @__PURE__ */ jsx(
|
|
21576
21063
|
Row2,
|
|
21577
21064
|
{
|
|
@@ -21618,7 +21105,7 @@ function ConsentBody({
|
|
|
21618
21105
|
] }),
|
|
21619
21106
|
/* @__PURE__ */ jsxs("p", { className: "mt-5 text-xs leading-relaxed text-muted-foreground", children: [
|
|
21620
21107
|
"Ao aprovar, ",
|
|
21621
|
-
|
|
21108
|
+
client2.name,
|
|
21622
21109
|
" poder\xE1 ler os dados",
|
|
21623
21110
|
org ? ` de ${org.name}` : " da organiza\xE7\xE3o escolhida",
|
|
21624
21111
|
" at\xE9 voc\xEA desconectar. Voc\xEA pode desfazer isso a qualquer momento em ",
|
|
@@ -22116,7 +21603,7 @@ var ICON = {
|
|
|
22116
21603
|
failed: { Icon: XCircle, className: "text-destructive", label: "N\xE3o foi" }
|
|
22117
21604
|
};
|
|
22118
21605
|
function ConnectorDeliveries({
|
|
22119
|
-
load,
|
|
21606
|
+
load: load2,
|
|
22120
21607
|
providerName,
|
|
22121
21608
|
limit = 10
|
|
22122
21609
|
}) {
|
|
@@ -22124,7 +21611,7 @@ function ConnectorDeliveries({
|
|
|
22124
21611
|
const [rows, setRows] = React133__default.useState(null);
|
|
22125
21612
|
React133__default.useEffect(() => {
|
|
22126
21613
|
let cancelled = false;
|
|
22127
|
-
void
|
|
21614
|
+
void load2({ limit }).then((r) => {
|
|
22128
21615
|
if (!cancelled) setRows(r);
|
|
22129
21616
|
}).catch(() => {
|
|
22130
21617
|
if (!cancelled) setRows([]);
|
|
@@ -22132,7 +21619,7 @@ function ConnectorDeliveries({
|
|
|
22132
21619
|
return () => {
|
|
22133
21620
|
cancelled = true;
|
|
22134
21621
|
};
|
|
22135
|
-
}, [
|
|
21622
|
+
}, [load2, limit]);
|
|
22136
21623
|
if (rows === null) {
|
|
22137
21624
|
return /* @__PURE__ */ jsx("p", { className: "flex justify-center py-4", children: /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) });
|
|
22138
21625
|
}
|
|
@@ -22291,7 +21778,7 @@ function UnitModeCard() {
|
|
|
22291
21778
|
const unitMode = useUnitStore((s) => s.unitMode);
|
|
22292
21779
|
const units = useUnitStore((s) => s.units);
|
|
22293
21780
|
const setMode = useUnitStore((s) => s.setMode);
|
|
22294
|
-
const
|
|
21781
|
+
const load2 = useUnitStore((s) => s.load);
|
|
22295
21782
|
const [unbound, setUnbound] = React133.useState(null);
|
|
22296
21783
|
const [bindEveryone, setBindEveryone] = React133.useState(true);
|
|
22297
21784
|
const [pending2, setPending] = React133.useState(null);
|
|
@@ -22321,7 +21808,7 @@ function UnitModeCard() {
|
|
|
22321
21808
|
await setUnitModeRemote(org.id, on);
|
|
22322
21809
|
setMode(on);
|
|
22323
21810
|
emitDataChanged();
|
|
22324
|
-
await
|
|
21811
|
+
await load2(org.id, user?.id);
|
|
22325
21812
|
toast.success(on ? "Gest\xE3o por unidades ligada" : "Gest\xE3o por unidades desligada");
|
|
22326
21813
|
} catch (err) {
|
|
22327
21814
|
toast.error("N\xE3o deu para mudar", { description: err?.message });
|
|
@@ -22439,11 +21926,11 @@ function ConnectedCompanySettings() {
|
|
|
22439
21926
|
const handleSave = async (data) => {
|
|
22440
21927
|
if (!adapter || !currentOrg) return;
|
|
22441
21928
|
try {
|
|
22442
|
-
const
|
|
21929
|
+
const raw = currentOrg.settings && typeof currentOrg.settings === "object" ? currentOrg.settings : {};
|
|
22443
21930
|
const updated = await adapter.updateOrg(currentOrg.id, {
|
|
22444
21931
|
name: data.name,
|
|
22445
21932
|
settings: {
|
|
22446
|
-
...
|
|
21933
|
+
...raw,
|
|
22447
21934
|
timezone: data.timezone,
|
|
22448
21935
|
currency: data.currency
|
|
22449
21936
|
}
|
|
@@ -22569,11 +22056,11 @@ function UserProfile({ user, onSave, onAvatarChange }) {
|
|
|
22569
22056
|
] }) })
|
|
22570
22057
|
] }) });
|
|
22571
22058
|
}
|
|
22572
|
-
function
|
|
22059
|
+
function client() {
|
|
22573
22060
|
return getSupabaseClientOptional();
|
|
22574
22061
|
}
|
|
22575
22062
|
async function fetchMyPersonRecord(tenantId2, userId) {
|
|
22576
|
-
const db2 =
|
|
22063
|
+
const db2 = client();
|
|
22577
22064
|
if (!db2) return null;
|
|
22578
22065
|
const { data, error } = await db2.from("v_team_members").select("person_id").eq("tenant_id", tenantId2).eq("user_id", userId).maybeSingle();
|
|
22579
22066
|
if (error || !data?.person_id) return null;
|
|
@@ -22582,7 +22069,7 @@ async function fetchMyPersonRecord(tenantId2, userId) {
|
|
|
22582
22069
|
return { id: person.id, name: person.name ?? "", kind: person.kind ?? null };
|
|
22583
22070
|
}
|
|
22584
22071
|
async function findMyPersonCandidate(tenantId2, email, staffKinds) {
|
|
22585
|
-
const db2 =
|
|
22072
|
+
const db2 = client();
|
|
22586
22073
|
if (!db2 || !email || staffKinds.length === 0) return null;
|
|
22587
22074
|
const { data, error } = await db2.from("people").select("id, name, kind, email").eq("tenant_id", tenantId2).in("kind", staffKinds).ilike("email", email).limit(2);
|
|
22588
22075
|
if (error || !data || data.length !== 1) return null;
|
|
@@ -22592,13 +22079,13 @@ async function findMyPersonCandidate(tenantId2, email, staffKinds) {
|
|
|
22592
22079
|
return { id: candidate.id, name: candidate.name ?? "", kind: candidate.kind ?? null };
|
|
22593
22080
|
}
|
|
22594
22081
|
async function linkPersonToLogin(tenantId2, userId, personId) {
|
|
22595
|
-
const db2 =
|
|
22082
|
+
const db2 = client();
|
|
22596
22083
|
if (!db2) throw new Error("sem conex\xE3o");
|
|
22597
22084
|
const { error } = await db2.rpc("people_link_membership", { p_person: personId, p_user: userId });
|
|
22598
22085
|
if (error) throw error;
|
|
22599
22086
|
}
|
|
22600
22087
|
async function fetchMyPersonId(tenantId2, userId) {
|
|
22601
|
-
const db2 =
|
|
22088
|
+
const db2 = client();
|
|
22602
22089
|
if (!db2) return null;
|
|
22603
22090
|
const { data, error } = await db2.from("v_team_members").select("person_id").eq("tenant_id", tenantId2).eq("user_id", userId).maybeSingle();
|
|
22604
22091
|
if (error) return null;
|
|
@@ -22621,7 +22108,7 @@ function useMyPersonId(enabled = true) {
|
|
|
22621
22108
|
return personId;
|
|
22622
22109
|
}
|
|
22623
22110
|
async function fetchPersonAccess(personId) {
|
|
22624
|
-
const db2 =
|
|
22111
|
+
const db2 = client();
|
|
22625
22112
|
if (!db2) return null;
|
|
22626
22113
|
const { data, error } = await db2.from("v_team_members").select("id, user_id, role, created_at").eq("person_id", personId).maybeSingle();
|
|
22627
22114
|
if (error || !data) return null;
|
|
@@ -22636,7 +22123,7 @@ async function fetchPersonAccess(personId) {
|
|
|
22636
22123
|
};
|
|
22637
22124
|
}
|
|
22638
22125
|
async function setPersonEmail(personId, email) {
|
|
22639
|
-
const db2 =
|
|
22126
|
+
const db2 = client();
|
|
22640
22127
|
if (!db2) throw new Error("sem conex\xE3o");
|
|
22641
22128
|
const { error } = await db2.from("people").update({ email }).eq("id", personId);
|
|
22642
22129
|
if (error) throw error;
|
|
@@ -22673,15 +22160,15 @@ function MyWorkspaceCard() {
|
|
|
22673
22160
|
const [linking, setLinking] = React133.useState(false);
|
|
22674
22161
|
const orgId = currentOrg?.id;
|
|
22675
22162
|
const userId = user?.id;
|
|
22676
|
-
const
|
|
22163
|
+
const load2 = React133.useCallback(async () => {
|
|
22677
22164
|
if (!orgId || !userId) return;
|
|
22678
22165
|
const linked = await fetchMyPersonRecord(orgId, userId);
|
|
22679
22166
|
setPerson(linked);
|
|
22680
22167
|
setCandidate(linked ? null : await findMyPersonCandidate(orgId, user?.email, staffKinds));
|
|
22681
22168
|
}, [orgId, userId, user?.email, staffKinds]);
|
|
22682
22169
|
React133.useEffect(() => {
|
|
22683
|
-
void
|
|
22684
|
-
}, [
|
|
22170
|
+
void load2();
|
|
22171
|
+
}, [load2]);
|
|
22685
22172
|
if (!currentOrg) return null;
|
|
22686
22173
|
const myRole = members.find((m) => m.userId === userId)?.profileName;
|
|
22687
22174
|
async function link() {
|
|
@@ -22690,7 +22177,7 @@ function MyWorkspaceCard() {
|
|
|
22690
22177
|
try {
|
|
22691
22178
|
await linkPersonToLogin(orgId, userId, candidate.id);
|
|
22692
22179
|
toast.success(`Login ligado ao cadastro de ${candidate.name}`);
|
|
22693
|
-
await
|
|
22180
|
+
await load2();
|
|
22694
22181
|
} catch (err) {
|
|
22695
22182
|
toast.error("S\xF3 um administrador pode ligar um login a um cadastro", { description: err?.message });
|
|
22696
22183
|
} finally {
|
|
@@ -22794,9 +22281,9 @@ function useUserLabel(userId) {
|
|
|
22794
22281
|
const [resolved, setResolved] = useState(null);
|
|
22795
22282
|
useEffect(() => {
|
|
22796
22283
|
if (!userId || fromMembers) return;
|
|
22797
|
-
const
|
|
22798
|
-
if (
|
|
22799
|
-
setResolved(
|
|
22284
|
+
const cached2 = userLabelCache.get(userId);
|
|
22285
|
+
if (cached2 !== void 0) {
|
|
22286
|
+
setResolved(cached2);
|
|
22800
22287
|
return;
|
|
22801
22288
|
}
|
|
22802
22289
|
let alive = true;
|
|
@@ -22982,15 +22469,15 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
|
|
|
22982
22469
|
const [deleting, setDeleting] = useState(null);
|
|
22983
22470
|
const ownerId = record?.id;
|
|
22984
22471
|
const db2 = () => getSupabaseClientOptional();
|
|
22985
|
-
const
|
|
22986
|
-
const
|
|
22987
|
-
if (!
|
|
22472
|
+
const load2 = useCallback(async () => {
|
|
22473
|
+
const client2 = db2();
|
|
22474
|
+
if (!client2 || !ownerId) {
|
|
22988
22475
|
setLoading(false);
|
|
22989
22476
|
return;
|
|
22990
22477
|
}
|
|
22991
22478
|
setLoading(true);
|
|
22992
22479
|
setError(null);
|
|
22993
|
-
let q =
|
|
22480
|
+
let q = client2.from("addresses").select("*").eq("owner_id", ownerId);
|
|
22994
22481
|
if (ownerType !== "person") q = q.eq("owner_type", ownerType);
|
|
22995
22482
|
const { data, error: err } = await q.order("is_default", { ascending: false });
|
|
22996
22483
|
if (err) setError(err.message);
|
|
@@ -22998,8 +22485,8 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
|
|
|
22998
22485
|
setLoading(false);
|
|
22999
22486
|
}, [ownerId, ownerType]);
|
|
23000
22487
|
useEffect(() => {
|
|
23001
|
-
void
|
|
23002
|
-
}, [
|
|
22488
|
+
void load2();
|
|
22489
|
+
}, [load2]);
|
|
23003
22490
|
const openCreate = () => {
|
|
23004
22491
|
setEditing(null);
|
|
23005
22492
|
setForm(single ? { ...EMPTY_FORM, kind: "main", is_default: true } : EMPTY_FORM);
|
|
@@ -23089,8 +22576,8 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
|
|
|
23089
22576
|
}
|
|
23090
22577
|
};
|
|
23091
22578
|
const handleSave = async () => {
|
|
23092
|
-
const
|
|
23093
|
-
if (!
|
|
22579
|
+
const client2 = db2();
|
|
22580
|
+
if (!client2 || !ownerId || !canSave) return;
|
|
23094
22581
|
const tenantId2 = getActiveTenantId();
|
|
23095
22582
|
if (!tenantId2) {
|
|
23096
22583
|
toast.error(t("crud.archetype.addresses.noTenant"));
|
|
@@ -23116,12 +22603,12 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
|
|
|
23116
22603
|
longitude: coordPair(form).lng
|
|
23117
22604
|
};
|
|
23118
22605
|
if (form.is_default) {
|
|
23119
|
-
let q =
|
|
22606
|
+
let q = client2.from("addresses").update({ is_default: false }).eq("owner_id", ownerId).eq("owner_type", ownerType).eq("kind", form.kind).eq("is_default", true);
|
|
23120
22607
|
if (editing) q = q.neq("id", editing.id);
|
|
23121
22608
|
const { error: clearErr } = await q;
|
|
23122
22609
|
if (clearErr) throw clearErr;
|
|
23123
22610
|
}
|
|
23124
|
-
const { error: err } = editing ? await
|
|
22611
|
+
const { error: err } = editing ? await client2.from("addresses").update(values).eq("id", editing.id) : await client2.from("addresses").insert({
|
|
23125
22612
|
...values,
|
|
23126
22613
|
tenant_id: tenantId2,
|
|
23127
22614
|
owner_type: ownerType,
|
|
@@ -23129,7 +22616,7 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
|
|
|
23129
22616
|
});
|
|
23130
22617
|
if (err) throw err;
|
|
23131
22618
|
setFormOpen(false);
|
|
23132
|
-
await
|
|
22619
|
+
await load2();
|
|
23133
22620
|
toast.success(editing ? t("crud.archetype.addresses.updated") : t("crud.archetype.addresses.created"));
|
|
23134
22621
|
} catch (e) {
|
|
23135
22622
|
toast.error(t("crud.archetype.addresses.saveFailed"), { description: e?.message });
|
|
@@ -23138,15 +22625,15 @@ function AddressesTab({ item, ownerType = "person", single = false }) {
|
|
|
23138
22625
|
}
|
|
23139
22626
|
};
|
|
23140
22627
|
const handleDelete = async () => {
|
|
23141
|
-
const
|
|
23142
|
-
if (!
|
|
23143
|
-
const { error: err } = await
|
|
22628
|
+
const client2 = db2();
|
|
22629
|
+
if (!client2 || !deleting) return;
|
|
22630
|
+
const { error: err } = await client2.from("addresses").delete().eq("id", deleting.id);
|
|
23144
22631
|
setDeleting(null);
|
|
23145
22632
|
if (err) {
|
|
23146
22633
|
toast.error(t("crud.archetype.addresses.deleteFailed"), { description: err.message });
|
|
23147
22634
|
return;
|
|
23148
22635
|
}
|
|
23149
|
-
await
|
|
22636
|
+
await load2();
|
|
23150
22637
|
toast.success(t("crud.archetype.addresses.deleted"));
|
|
23151
22638
|
};
|
|
23152
22639
|
if (loading) {
|
|
@@ -23423,28 +22910,28 @@ function PayeeAccountsSection({
|
|
|
23423
22910
|
const canEdit = can("financial", "edit");
|
|
23424
22911
|
const canDelete = can("financial", "delete");
|
|
23425
22912
|
const db2 = () => getSupabaseClientOptional();
|
|
23426
|
-
const
|
|
23427
|
-
const
|
|
23428
|
-
if (!
|
|
22913
|
+
const load2 = useCallback(async () => {
|
|
22914
|
+
const client2 = db2();
|
|
22915
|
+
if (!client2 || !ownerId) {
|
|
23429
22916
|
setLoading(false);
|
|
23430
22917
|
return;
|
|
23431
22918
|
}
|
|
23432
22919
|
setLoading(true);
|
|
23433
22920
|
setError(null);
|
|
23434
|
-
const { data, error: err } = await
|
|
22921
|
+
const { data, error: err } = await client2.from("payee_accounts").select("*").eq("owner_type", ownerType).eq("owner_id", ownerId).order("is_default", { ascending: false });
|
|
23435
22922
|
if (err) setError(err.message);
|
|
23436
22923
|
else setRows(data ?? []);
|
|
23437
22924
|
setLoading(false);
|
|
23438
22925
|
}, [ownerId, ownerType]);
|
|
23439
22926
|
useEffect(() => {
|
|
23440
|
-
void
|
|
23441
|
-
}, [
|
|
22927
|
+
void load2();
|
|
22928
|
+
}, [load2]);
|
|
23442
22929
|
const set = (key, value) => setForm((prev) => ({ ...prev, [key]: value }));
|
|
23443
22930
|
const canSave = !!blank(form.accountNumber ?? null) || !!blank(form.pixKey ?? null);
|
|
23444
22931
|
const handleSave = async () => {
|
|
23445
|
-
const
|
|
22932
|
+
const client2 = db2();
|
|
23446
22933
|
const tenantId2 = getActiveTenantId();
|
|
23447
|
-
if (!
|
|
22934
|
+
if (!client2 || !ownerId || !tenantId2 || !canSave) return;
|
|
23448
22935
|
setSaving(true);
|
|
23449
22936
|
try {
|
|
23450
22937
|
const pix = form.method === "pix";
|
|
@@ -23465,9 +22952,9 @@ function PayeeAccountsSection({
|
|
|
23465
22952
|
holder_document: b("holderDocument")
|
|
23466
22953
|
};
|
|
23467
22954
|
if (form.is_default) {
|
|
23468
|
-
await
|
|
22955
|
+
await client2.from("payee_accounts").update({ is_default: false }).eq("owner_type", ownerType).eq("owner_id", ownerId);
|
|
23469
22956
|
}
|
|
23470
|
-
const { error: err } = editing ? await
|
|
22957
|
+
const { error: err } = editing ? await client2.from("payee_accounts").update(values).eq("id", editing.id) : await client2.from("payee_accounts").insert({
|
|
23471
22958
|
...values,
|
|
23472
22959
|
tenant_id: tenantId2,
|
|
23473
22960
|
owner_type: ownerType,
|
|
@@ -23475,7 +22962,7 @@ function PayeeAccountsSection({
|
|
|
23475
22962
|
});
|
|
23476
22963
|
if (err) throw err;
|
|
23477
22964
|
setFormOpen(false);
|
|
23478
|
-
await
|
|
22965
|
+
await load2();
|
|
23479
22966
|
toast.success(t("crud.archetype.payeeAccounts.saved"));
|
|
23480
22967
|
} catch (e) {
|
|
23481
22968
|
toast.error(t("crud.archetype.payeeAccounts.saveFailed"), { description: e?.message });
|
|
@@ -23484,15 +22971,15 @@ function PayeeAccountsSection({
|
|
|
23484
22971
|
}
|
|
23485
22972
|
};
|
|
23486
22973
|
const handleDelete = async () => {
|
|
23487
|
-
const
|
|
23488
|
-
if (!
|
|
23489
|
-
const { error: err } = await
|
|
22974
|
+
const client2 = db2();
|
|
22975
|
+
if (!client2 || !deleting) return;
|
|
22976
|
+
const { error: err } = await client2.from("payee_accounts").delete().eq("id", deleting.id);
|
|
23490
22977
|
setDeleting(null);
|
|
23491
22978
|
if (err) {
|
|
23492
22979
|
toast.error(t("crud.archetype.payeeAccounts.deleteFailed"), { description: err.message });
|
|
23493
22980
|
return;
|
|
23494
22981
|
}
|
|
23495
|
-
await
|
|
22982
|
+
await load2();
|
|
23496
22983
|
toast.success(t("crud.archetype.payeeAccounts.deleted"));
|
|
23497
22984
|
};
|
|
23498
22985
|
if (!canRead) return null;
|
|
@@ -23783,7 +23270,7 @@ function CrudRecordModal({
|
|
|
23783
23270
|
onSaved,
|
|
23784
23271
|
entityDef,
|
|
23785
23272
|
mode = "edit",
|
|
23786
|
-
load,
|
|
23273
|
+
load: load2,
|
|
23787
23274
|
initialData,
|
|
23788
23275
|
save,
|
|
23789
23276
|
title,
|
|
@@ -23800,14 +23287,14 @@ function CrudRecordModal({
|
|
|
23800
23287
|
React133.useEffect(() => {
|
|
23801
23288
|
if (!open) return;
|
|
23802
23289
|
setError(null);
|
|
23803
|
-
if (mode === "create" || !
|
|
23290
|
+
if (mode === "create" || !load2) {
|
|
23804
23291
|
setRecord(initialData ?? {});
|
|
23805
23292
|
setLoading(false);
|
|
23806
23293
|
return;
|
|
23807
23294
|
}
|
|
23808
23295
|
let cancelled = false;
|
|
23809
23296
|
setLoading(true);
|
|
23810
|
-
|
|
23297
|
+
load2().then((found) => {
|
|
23811
23298
|
if (!cancelled) setRecord(found);
|
|
23812
23299
|
}).catch((err) => {
|
|
23813
23300
|
if (!cancelled) setError(errorMessage(err));
|
|
@@ -23938,6 +23425,57 @@ function useRelationOptions(r) {
|
|
|
23938
23425
|
const labelFor2 = (value) => options.find((o) => o.value === String(value))?.label ?? "";
|
|
23939
23426
|
return { options, loading, labelFor: labelFor2 };
|
|
23940
23427
|
}
|
|
23428
|
+
async function createOption(r, label3) {
|
|
23429
|
+
const supabase = getSupabaseClientOptional();
|
|
23430
|
+
if (!supabase) throw new Error("no client");
|
|
23431
|
+
const valueField = r.valueField ?? "id";
|
|
23432
|
+
const row = {
|
|
23433
|
+
...r.filter ?? {},
|
|
23434
|
+
...r.create?.defaults ?? {},
|
|
23435
|
+
[(r.labelFields ?? [r.labelField ?? "name"])[0]]: label3
|
|
23436
|
+
};
|
|
23437
|
+
if (r.tenantScoped !== false) row.tenant_id = getActiveTenantId();
|
|
23438
|
+
const { data, error } = await (r.schema ? supabase.schema(r.schema) : supabase).from(r.table).insert(row).select(valueField).single();
|
|
23439
|
+
if (error) throw error;
|
|
23440
|
+
invalidateRelationOptions();
|
|
23441
|
+
return String(data[valueField]);
|
|
23442
|
+
}
|
|
23443
|
+
function CreatableRelationSelect({ relation, value, onChange, required, placeholder }) {
|
|
23444
|
+
const [created, setCreated] = useState([]);
|
|
23445
|
+
const { options } = useRelationOptions(relation);
|
|
23446
|
+
const all = [...options, ...created.filter((c) => !options.some((o) => o.value === c.value))];
|
|
23447
|
+
return /* @__PURE__ */ jsx(
|
|
23448
|
+
SearchSelect,
|
|
23449
|
+
{
|
|
23450
|
+
value: value ? String(value) : void 0,
|
|
23451
|
+
displayValue: all.find((o) => o.value === String(value))?.label,
|
|
23452
|
+
required,
|
|
23453
|
+
placeholder,
|
|
23454
|
+
minChars: 0,
|
|
23455
|
+
noResultsLabel: "Nada encontrado",
|
|
23456
|
+
searchingLabel: "Buscando\u2026",
|
|
23457
|
+
createLabel: "Cadastrar",
|
|
23458
|
+
clearLabel: "Limpar",
|
|
23459
|
+
allowCreate: true,
|
|
23460
|
+
onSearch: (query) => {
|
|
23461
|
+
const q = query.trim().toLowerCase();
|
|
23462
|
+
return all.filter((o) => !q || o.label.toLowerCase().includes(q)).map((o) => ({ id: o.value, label: o.label }));
|
|
23463
|
+
},
|
|
23464
|
+
onChange: (id) => onChange(id || null),
|
|
23465
|
+
onCreate: async (query) => {
|
|
23466
|
+
const label3 = query.trim();
|
|
23467
|
+
if (!label3) return;
|
|
23468
|
+
try {
|
|
23469
|
+
const id = await createOption(relation, label3);
|
|
23470
|
+
setCreated((prev) => [...prev, { value: id, label: label3 }]);
|
|
23471
|
+
onChange(id);
|
|
23472
|
+
} catch (err) {
|
|
23473
|
+
toast.error(describeError(err));
|
|
23474
|
+
}
|
|
23475
|
+
}
|
|
23476
|
+
}
|
|
23477
|
+
);
|
|
23478
|
+
}
|
|
23941
23479
|
function RelationSelect({
|
|
23942
23480
|
relation,
|
|
23943
23481
|
value,
|
|
@@ -23947,6 +23485,11 @@ function RelationSelect({
|
|
|
23947
23485
|
placeholder
|
|
23948
23486
|
}) {
|
|
23949
23487
|
const { options, loading } = useRelationOptions(relation);
|
|
23488
|
+
const can = usePermissionOptional();
|
|
23489
|
+
const mayCreate = !!relation?.create && (!relation.create.permission || can(relation.create.permission.feature, relation.create.permission.action ?? "edit"));
|
|
23490
|
+
if (relation && mayCreate) {
|
|
23491
|
+
return /* @__PURE__ */ jsx(CreatableRelationSelect, { relation, value, onChange, required, placeholder });
|
|
23492
|
+
}
|
|
23950
23493
|
return /* @__PURE__ */ jsxs(
|
|
23951
23494
|
Select,
|
|
23952
23495
|
{
|
|
@@ -24052,7 +23595,7 @@ function RelatedSection({ parentId, related, compact }) {
|
|
|
24052
23595
|
const [error, setError] = React133.useState(null);
|
|
24053
23596
|
const [adding, setAdding] = React133.useState(false);
|
|
24054
23597
|
const [draft, setDraft] = React133.useState(null);
|
|
24055
|
-
const
|
|
23598
|
+
const load2 = React133.useCallback(async () => {
|
|
24056
23599
|
if (orfa) {
|
|
24057
23600
|
setLoading(false);
|
|
24058
23601
|
return;
|
|
@@ -24069,8 +23612,8 @@ function RelatedSection({ parentId, related, compact }) {
|
|
|
24069
23612
|
}
|
|
24070
23613
|
}, [provider2, orfa]);
|
|
24071
23614
|
React133.useEffect(() => {
|
|
24072
|
-
void
|
|
24073
|
-
}, [
|
|
23615
|
+
void load2();
|
|
23616
|
+
}, [load2]);
|
|
24074
23617
|
const guardadas = React133.useRef([]);
|
|
24075
23618
|
guardadas.current = rows;
|
|
24076
23619
|
React133.useEffect(() => {
|
|
@@ -24185,7 +23728,7 @@ function RelatedSection({ parentId, related, compact }) {
|
|
|
24185
23728
|
try {
|
|
24186
23729
|
await provider2.create(pronto);
|
|
24187
23730
|
setDraft(null);
|
|
24188
|
-
await
|
|
23731
|
+
await load2();
|
|
24189
23732
|
} catch (e) {
|
|
24190
23733
|
toast.error(errorMessage(e));
|
|
24191
23734
|
} finally {
|
|
@@ -24202,7 +23745,7 @@ function RelatedSection({ parentId, related, compact }) {
|
|
|
24202
23745
|
}
|
|
24203
23746
|
try {
|
|
24204
23747
|
await provider2.create(copia);
|
|
24205
|
-
await
|
|
23748
|
+
await load2();
|
|
24206
23749
|
} catch (e) {
|
|
24207
23750
|
toast.error(errorMessage(e));
|
|
24208
23751
|
}
|
|
@@ -24422,7 +23965,7 @@ function RelatedSection({ parentId, related, compact }) {
|
|
|
24422
23965
|
mode: "create",
|
|
24423
23966
|
save: async (data) => {
|
|
24424
23967
|
await provider2.create(data);
|
|
24425
|
-
await
|
|
23968
|
+
await load2();
|
|
24426
23969
|
},
|
|
24427
23970
|
onSaved: () => setAdding(false)
|
|
24428
23971
|
}
|
|
@@ -25166,10 +24709,10 @@ function useSuggestions(table) {
|
|
|
25166
24709
|
const [tags, setTags] = useState(() => table ? suggestionCache.get(table) ?? [] : []);
|
|
25167
24710
|
useEffect(() => {
|
|
25168
24711
|
if (!table || suggestionCache.has(table)) return;
|
|
25169
|
-
const
|
|
25170
|
-
if (!
|
|
24712
|
+
const client2 = getSupabaseClientOptional();
|
|
24713
|
+
if (!client2) return;
|
|
25171
24714
|
let alive = true;
|
|
25172
|
-
void
|
|
24715
|
+
void client2.from(table).select("tags").not("tags", "is", null).limit(500).then(({ data }) => {
|
|
25173
24716
|
const all = /* @__PURE__ */ new Set();
|
|
25174
24717
|
for (const r of data ?? []) for (const t of r.tags ?? []) all.add(t);
|
|
25175
24718
|
const list = [...all].sort();
|
|
@@ -28605,17 +28148,17 @@ function PersonAvailabilityTab({ item }) {
|
|
|
28605
28148
|
const [busy, setBusy] = React133.useState(false);
|
|
28606
28149
|
const [availabilityReady, setAvailabilityReady] = React133.useState(true);
|
|
28607
28150
|
const db2 = () => getSupabaseClientOptional();
|
|
28608
|
-
const
|
|
28609
|
-
const
|
|
28610
|
-
if (!
|
|
28151
|
+
const load2 = React133.useCallback(async () => {
|
|
28152
|
+
const client2 = db2();
|
|
28153
|
+
if (!client2 || !personId) {
|
|
28611
28154
|
setLoading(false);
|
|
28612
28155
|
return;
|
|
28613
28156
|
}
|
|
28614
28157
|
setLoading(true);
|
|
28615
28158
|
try {
|
|
28616
28159
|
const [{ data: unitRows, error: unitError }, { data: unitIds, error: grantError }] = await Promise.all([
|
|
28617
|
-
|
|
28618
|
-
|
|
28160
|
+
client2.from("v_units").select("id,name,city").eq("is_active", true).order("name"),
|
|
28161
|
+
client2.rpc("people_available_unit_ids", { p_person: personId })
|
|
28619
28162
|
]);
|
|
28620
28163
|
if (unitError) throw unitError;
|
|
28621
28164
|
setUnits(unitRows ?? []);
|
|
@@ -28635,14 +28178,14 @@ function PersonAvailabilityTab({ item }) {
|
|
|
28635
28178
|
}
|
|
28636
28179
|
}, [personId]);
|
|
28637
28180
|
React133.useEffect(() => {
|
|
28638
|
-
void
|
|
28639
|
-
}, [
|
|
28181
|
+
void load2();
|
|
28182
|
+
}, [load2]);
|
|
28640
28183
|
async function makeOrganizationWide() {
|
|
28641
|
-
const
|
|
28642
|
-
if (!
|
|
28184
|
+
const client2 = db2();
|
|
28185
|
+
if (!client2 || !personId || busy) return;
|
|
28643
28186
|
setBusy(true);
|
|
28644
28187
|
try {
|
|
28645
|
-
const { error } = await
|
|
28188
|
+
const { error } = await client2.rpc("people_set_available_units", {
|
|
28646
28189
|
p_person: personId,
|
|
28647
28190
|
p_unit_ids: []
|
|
28648
28191
|
});
|
|
@@ -28656,19 +28199,19 @@ function PersonAvailabilityTab({ item }) {
|
|
|
28656
28199
|
}
|
|
28657
28200
|
}
|
|
28658
28201
|
async function toggle(unitId, enabled) {
|
|
28659
|
-
const
|
|
28660
|
-
if (!
|
|
28202
|
+
const client2 = db2();
|
|
28203
|
+
if (!client2 || !personId || busy) return;
|
|
28661
28204
|
setBusy(true);
|
|
28662
28205
|
try {
|
|
28663
28206
|
const next = new Set(selected);
|
|
28664
28207
|
if (enabled) next.add(unitId);
|
|
28665
28208
|
else next.delete(unitId);
|
|
28666
|
-
const { error } = await
|
|
28209
|
+
const { error } = await client2.rpc("people_set_available_units", {
|
|
28667
28210
|
p_person: personId,
|
|
28668
28211
|
p_unit_ids: Array.from(next)
|
|
28669
28212
|
});
|
|
28670
28213
|
if (error) throw error;
|
|
28671
|
-
await
|
|
28214
|
+
await load2();
|
|
28672
28215
|
toast.success("Unidades atualizadas.");
|
|
28673
28216
|
} catch (error) {
|
|
28674
28217
|
toast.error("N\xE3o foi poss\xEDvel atualizar as unidades", { description: error?.message });
|
|
@@ -28713,7 +28256,7 @@ function PersonAvailabilityTab({ item }) {
|
|
|
28713
28256
|
] }) });
|
|
28714
28257
|
}
|
|
28715
28258
|
var ScheduleEditor2 = React133__default.lazy(
|
|
28716
|
-
() => import('./ScheduleEditor-
|
|
28259
|
+
() => import('./ScheduleEditor-MNHZCQIG.js').then((m) => ({ default: m.ScheduleEditor }))
|
|
28717
28260
|
);
|
|
28718
28261
|
var PersonTimeline2 = React133__default.lazy(
|
|
28719
28262
|
() => import('./timeline-LECYQ4IA.js').then((m) => ({ default: m.PersonTimeline }))
|
|
@@ -30047,7 +29590,7 @@ function MyRecordPanel() {
|
|
|
30047
29590
|
const members = useOrganizationStore((s) => s.members);
|
|
30048
29591
|
const myRole = members.find((m) => m.userId === userId)?.profileName;
|
|
30049
29592
|
const [state, setState] = React133.useState({ status: "loading" });
|
|
30050
|
-
const
|
|
29593
|
+
const load2 = React133.useCallback(async () => {
|
|
30051
29594
|
if (!orgId || !userId) return;
|
|
30052
29595
|
const person = await dedup(`self:record:${orgId}:${userId}`, () => fetchMyPersonRecord(orgId, userId));
|
|
30053
29596
|
if (!person) return setState({ status: "none" });
|
|
@@ -30065,8 +29608,8 @@ function MyRecordPanel() {
|
|
|
30065
29608
|
}
|
|
30066
29609
|
}, [orgId, userId]);
|
|
30067
29610
|
React133.useEffect(() => {
|
|
30068
|
-
void
|
|
30069
|
-
}, [
|
|
29611
|
+
void load2();
|
|
29612
|
+
}, [load2]);
|
|
30070
29613
|
const changePhoto = React133.useCallback(async (file) => {
|
|
30071
29614
|
if (state.status !== "ready") return;
|
|
30072
29615
|
const supabase = getFayzSupabaseClientOptional();
|
|
@@ -31137,13 +30680,13 @@ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["READY", "ERROR", "ABANDONED",
|
|
|
31137
30680
|
function ProjectsSettings() {
|
|
31138
30681
|
const currentOrgId = useOrganizationStore((s) => s.currentOrg?.id);
|
|
31139
30682
|
const projects = useFayzProjectsStore((s) => s.projects);
|
|
31140
|
-
const
|
|
30683
|
+
const load2 = useFayzProjectsStore((s) => s.load);
|
|
31141
30684
|
const refresh = useFayzProjectsStore((s) => s.refresh);
|
|
31142
30685
|
const [linking, setLinking] = React133.useState(false);
|
|
31143
30686
|
const connected = isPlatformConnected();
|
|
31144
30687
|
React133.useEffect(() => {
|
|
31145
|
-
void
|
|
31146
|
-
}, [currentOrgId,
|
|
30688
|
+
void load2(currentOrgId);
|
|
30689
|
+
}, [currentOrgId, load2]);
|
|
31147
30690
|
React133.useEffect(() => {
|
|
31148
30691
|
if (!connected || projects.length === 0) return;
|
|
31149
30692
|
let cancelled = false;
|
|
@@ -31892,29 +31435,29 @@ function ModulesSettings({ hidden = [], onToggle, permits, busy, catalog = [] })
|
|
|
31892
31435
|
}
|
|
31893
31436
|
|
|
31894
31437
|
// src/app/app-config-cache.ts
|
|
31895
|
-
var
|
|
31896
|
-
var
|
|
31438
|
+
var STORAGE_KEY3 = "fayz:app-config";
|
|
31439
|
+
var VERSION = 1;
|
|
31897
31440
|
var APP_CONFIG_TTL_MS = 5 * 60 * 1e3;
|
|
31898
|
-
var
|
|
31899
|
-
var
|
|
31900
|
-
function
|
|
31441
|
+
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
31442
|
+
var MAX_BYTES = 256 * 1024;
|
|
31443
|
+
function storage() {
|
|
31901
31444
|
try {
|
|
31902
31445
|
return globalThis.localStorage ?? null;
|
|
31903
31446
|
} catch {
|
|
31904
31447
|
return null;
|
|
31905
31448
|
}
|
|
31906
31449
|
}
|
|
31907
|
-
var keyFor = (tenantId2) => `${
|
|
31450
|
+
var keyFor = (tenantId2) => `${STORAGE_KEY3}:${tenantId2}`;
|
|
31908
31451
|
function readAppConfigSnapshot(tenantId2) {
|
|
31909
|
-
const store =
|
|
31452
|
+
const store = storage();
|
|
31910
31453
|
if (!store) return null;
|
|
31911
31454
|
try {
|
|
31912
31455
|
const raw = store.getItem(keyFor(tenantId2));
|
|
31913
31456
|
if (!raw) return null;
|
|
31914
31457
|
const snap = JSON.parse(raw);
|
|
31915
|
-
if (snap.version !==
|
|
31458
|
+
if (snap.version !== VERSION || snap.tenantId !== tenantId2) return null;
|
|
31916
31459
|
const age = Date.now() - snap.savedAt;
|
|
31917
|
-
if (age >
|
|
31460
|
+
if (age > MAX_AGE_MS) {
|
|
31918
31461
|
store.removeItem(keyFor(tenantId2));
|
|
31919
31462
|
return null;
|
|
31920
31463
|
}
|
|
@@ -31924,17 +31467,17 @@ function readAppConfigSnapshot(tenantId2) {
|
|
|
31924
31467
|
}
|
|
31925
31468
|
}
|
|
31926
31469
|
function writeAppConfigSnapshot(tenantId2, config) {
|
|
31927
|
-
const store =
|
|
31470
|
+
const store = storage();
|
|
31928
31471
|
if (!store) return;
|
|
31929
31472
|
try {
|
|
31930
|
-
const payload = JSON.stringify({ version:
|
|
31931
|
-
if (payload.length >
|
|
31473
|
+
const payload = JSON.stringify({ version: VERSION, tenantId: tenantId2, savedAt: Date.now(), config });
|
|
31474
|
+
if (payload.length > MAX_BYTES) return;
|
|
31932
31475
|
store.setItem(keyFor(tenantId2), payload);
|
|
31933
31476
|
} catch {
|
|
31934
31477
|
}
|
|
31935
31478
|
}
|
|
31936
31479
|
function clearAppConfigSnapshot(tenantId2) {
|
|
31937
|
-
const store =
|
|
31480
|
+
const store = storage();
|
|
31938
31481
|
if (!store) return;
|
|
31939
31482
|
try {
|
|
31940
31483
|
if (tenantId2) {
|
|
@@ -31943,7 +31486,7 @@ function clearAppConfigSnapshot(tenantId2) {
|
|
|
31943
31486
|
}
|
|
31944
31487
|
for (let i = store.length - 1; i >= 0; i -= 1) {
|
|
31945
31488
|
const key = store.key(i);
|
|
31946
|
-
if (key?.startsWith(`${
|
|
31489
|
+
if (key?.startsWith(`${STORAGE_KEY3}:`)) store.removeItem(key);
|
|
31947
31490
|
}
|
|
31948
31491
|
} catch {
|
|
31949
31492
|
}
|
|
@@ -32590,19 +32133,19 @@ function UnitIndicator({
|
|
|
32590
32133
|
const reachable = myUnitIds.length > 0 ? myUnitIds : units.filter((u) => u.kind !== "region").map((u) => u.id);
|
|
32591
32134
|
if (reachable.length === 0) return null;
|
|
32592
32135
|
const current2 = activeUnitId ? byId[activeUnitId] : void 0;
|
|
32593
|
-
const
|
|
32594
|
-
if (!
|
|
32136
|
+
const text3 = current2?.name ?? (reachable.length > 1 ? "Todas as unidades" : byId[reachable[0]]?.name ?? "");
|
|
32137
|
+
if (!text3) return null;
|
|
32595
32138
|
if (collapsed) {
|
|
32596
|
-
return /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-0.5", title:
|
|
32139
|
+
return /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-0.5", title: text3, children: /* @__PURE__ */ jsx(Building2, { className: "h-3 w-3 text-sidebar-muted" }) });
|
|
32597
32140
|
}
|
|
32598
32141
|
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
32599
32142
|
/* @__PURE__ */ jsx(Building2, { className: "h-3 w-3 shrink-0 text-sidebar-muted/70" }),
|
|
32600
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-[11px] leading-none text-sidebar-muted/90", children:
|
|
32143
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-[11px] leading-none text-sidebar-muted/90", children: text3 })
|
|
32601
32144
|
] });
|
|
32602
32145
|
if (inline) {
|
|
32603
|
-
return /* @__PURE__ */ jsx("span", { className: "mt-0.5 flex min-w-0 items-center gap-1", title:
|
|
32146
|
+
return /* @__PURE__ */ jsx("span", { className: "mt-0.5 flex min-w-0 items-center gap-1", title: text3, children: body });
|
|
32604
32147
|
}
|
|
32605
|
-
return /* @__PURE__ */ jsx("div", { className: "flex min-w-0 items-center gap-1.5 pl-12 pr-1.5 pb-1", title:
|
|
32148
|
+
return /* @__PURE__ */ jsx("div", { className: "flex min-w-0 items-center gap-1.5 pl-12 pr-1.5 pb-1", title: text3, children: body });
|
|
32606
32149
|
}
|
|
32607
32150
|
var UNIT_DETAIL_ZONES = {
|
|
32608
32151
|
rooms: "unit.detail.rooms",
|
|
@@ -34370,7 +33913,7 @@ var CommandPalette = React133.lazy(
|
|
|
34370
33913
|
() => import('./CommandPalette-B5PMQFDG.js').then((m) => ({ default: m.CommandPalette }))
|
|
34371
33914
|
);
|
|
34372
33915
|
var SubscriptionPage = React133.lazy(
|
|
34373
|
-
() => import('./SubscriptionPage-
|
|
33916
|
+
() => import('./SubscriptionPage-JWWS44SE.js').then((m) => ({ default: m.SubscriptionPage }))
|
|
34374
33917
|
);
|
|
34375
33918
|
function WorkspaceSwitcher({
|
|
34376
33919
|
variant = "sidebar",
|
|
@@ -36720,11 +36263,14 @@ function Badge26({ badge, className = "" }) {
|
|
|
36720
36263
|
/* @__PURE__ */ jsx("span", { className: `inline-flex shrink-0 items-center rounded-full px-2 py-0.5 text-xs font-medium ${TONE_CLASS[badge.tone ?? "muted"]} ${className}`, children: badge.label })
|
|
36721
36264
|
);
|
|
36722
36265
|
}
|
|
36723
|
-
function OrderDetailBlock({ title, hint, children }) {
|
|
36266
|
+
function OrderDetailBlock({ title, hint, actions, children }) {
|
|
36724
36267
|
return /* @__PURE__ */ jsxs("div", { className: "rounded-card border bg-card p-4", children: [
|
|
36725
|
-
(title || hint) && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
|
|
36726
|
-
|
|
36727
|
-
|
|
36268
|
+
(title || hint || actions) && /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-start justify-between gap-2", children: [
|
|
36269
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
36270
|
+
title && /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: title }),
|
|
36271
|
+
hint && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: hint })
|
|
36272
|
+
] }),
|
|
36273
|
+
actions && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: actions })
|
|
36728
36274
|
] }),
|
|
36729
36275
|
children
|
|
36730
36276
|
] });
|
|
@@ -36783,7 +36329,8 @@ function OrderDetailView(props) {
|
|
|
36783
36329
|
banner,
|
|
36784
36330
|
embedded
|
|
36785
36331
|
} = props;
|
|
36786
|
-
const
|
|
36332
|
+
const itemMenu = !!props.itemActionsMenu;
|
|
36333
|
+
const actionSlots = itemMenu ? items.some((it) => (it.actions?.length ?? 0) > 0) ? 1 : 0 : Math.max(0, ...items.map((it) => it.actions?.length ?? 0));
|
|
36787
36334
|
const hasBadges = badges.length > 0 || !!props.badgesNode;
|
|
36788
36335
|
const titleNode = hasBadges ? /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
36789
36336
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: title }),
|
|
@@ -36825,7 +36372,8 @@ function OrderDetailView(props) {
|
|
|
36825
36372
|
/* @__PURE__ */ jsx(Thumbnail, { src: item.imageUrl, size: "sm", icon: item.icon }),
|
|
36826
36373
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
36827
36374
|
/* @__PURE__ */ jsx("p", { className: cn$1("truncate text-sm font-medium", item.struck && "text-muted-foreground line-through"), children: item.name }),
|
|
36828
|
-
item.description ? /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null
|
|
36375
|
+
item.description ? /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null,
|
|
36376
|
+
item.note ? /* @__PURE__ */ jsx("p", { className: "truncate text-xs", children: item.note }) : null
|
|
36829
36377
|
] }),
|
|
36830
36378
|
item.account && /* @__PURE__ */ jsx(Badge, { variant: "secondary", title: item.account, className: "fz-tight-hide max-w-[12rem] shrink-0 truncate", children: item.account }),
|
|
36831
36379
|
/* @__PURE__ */ jsxs("span", { className: cn$1("shrink-0 text-xs text-muted-foreground tabular-nums", item.struck && "line-through"), children: [
|
|
@@ -36841,26 +36389,42 @@ function OrderDetailView(props) {
|
|
|
36841
36389
|
// ficam visíveis o tempo todo (`pointer: coarse`).
|
|
36842
36390
|
// Every row reserves the widest row's slot, so a line with fewer
|
|
36843
36391
|
// actions (a cancelled one has none) keeps its numbers in the column.
|
|
36844
|
-
/* @__PURE__ */
|
|
36392
|
+
/* @__PURE__ */ jsxs(
|
|
36845
36393
|
"span",
|
|
36846
36394
|
{
|
|
36847
|
-
style: { width: actionSlots * 28 + (actionSlots - 1) * 2 },
|
|
36395
|
+
style: { width: itemMenu ? 36 : actionSlots * 28 + (actionSlots - 1) * 2 },
|
|
36848
36396
|
className: "flex shrink-0 items-center justify-end gap-0.5 opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100 [@media(pointer:coarse)]:opacity-100",
|
|
36849
|
-
children:
|
|
36850
|
-
|
|
36851
|
-
|
|
36852
|
-
Button,
|
|
36397
|
+
children: [
|
|
36398
|
+
itemMenu && /* @__PURE__ */ jsx(
|
|
36399
|
+
RowActions,
|
|
36853
36400
|
{
|
|
36854
|
-
|
|
36855
|
-
|
|
36856
|
-
|
|
36857
|
-
|
|
36858
|
-
|
|
36859
|
-
|
|
36860
|
-
|
|
36401
|
+
inlineLimit: 0,
|
|
36402
|
+
actions: (item.actions ?? []).map((a) => ({
|
|
36403
|
+
id: a.id,
|
|
36404
|
+
label: a.label,
|
|
36405
|
+
icon: a.icon,
|
|
36406
|
+
intent: a.intent,
|
|
36407
|
+
disabled: a.disabled,
|
|
36408
|
+
onSelect: () => a.onSelect(item)
|
|
36409
|
+
}))
|
|
36861
36410
|
}
|
|
36862
|
-
)
|
|
36863
|
-
|
|
36411
|
+
),
|
|
36412
|
+
!itemMenu && (item.actions ?? []).map((a) => {
|
|
36413
|
+
const Icon = a.icon;
|
|
36414
|
+
return /* @__PURE__ */ jsx(Hint, { label: a.label, children: /* @__PURE__ */ jsx(
|
|
36415
|
+
Button,
|
|
36416
|
+
{
|
|
36417
|
+
type: "button",
|
|
36418
|
+
variant: "ghost",
|
|
36419
|
+
size: "icon",
|
|
36420
|
+
className: "h-7 w-7",
|
|
36421
|
+
"aria-label": a.label,
|
|
36422
|
+
onClick: () => a.onSelect(item),
|
|
36423
|
+
children: Icon ? /* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-3.5 w-3.5" })
|
|
36424
|
+
}
|
|
36425
|
+
) }, a.id);
|
|
36426
|
+
})
|
|
36427
|
+
]
|
|
36864
36428
|
}
|
|
36865
36429
|
)
|
|
36866
36430
|
] }, item.id ?? i)) }) }),
|
|
@@ -37123,7 +36687,10 @@ function OrderFormItemRow({
|
|
|
37123
36687
|
labels,
|
|
37124
36688
|
extraFieldGroups,
|
|
37125
36689
|
readOnly = false,
|
|
37126
|
-
pickOnly = false
|
|
36690
|
+
pickOnly = false,
|
|
36691
|
+
note,
|
|
36692
|
+
imageUrl,
|
|
36693
|
+
icon
|
|
37127
36694
|
}) {
|
|
37128
36695
|
const l = { ...ITEM_LABELS, ...labels };
|
|
37129
36696
|
const total = quantity * unitPrice - (discount ?? 0) + (surcharge ?? 0);
|
|
@@ -37166,8 +36733,14 @@ function OrderFormItemRow({
|
|
|
37166
36733
|
index + 1,
|
|
37167
36734
|
"."
|
|
37168
36735
|
] }),
|
|
37169
|
-
|
|
37170
|
-
/* @__PURE__ */
|
|
36736
|
+
(imageUrl || icon) && /* @__PURE__ */ jsx(Thumbnail, { src: imageUrl, size: "sm", icon }),
|
|
36737
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 text-sm", children: [
|
|
36738
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
36739
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: description || /* @__PURE__ */ jsx("span", { className: "italic text-muted-foreground", children: l.noDescription }) }),
|
|
36740
|
+
kindLabel && /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0 items-center rounded bg-muted px-1.5 py-0.5 text-[9px] font-medium text-muted-foreground", children: kindLabel })
|
|
36741
|
+
] }),
|
|
36742
|
+
note && /* @__PURE__ */ jsx("span", { className: "mt-0.5 block truncate text-xs", children: note })
|
|
36743
|
+
] }),
|
|
37171
36744
|
(extraFieldGroups ?? []).filter((g) => g.summary).map((g) => /* @__PURE__ */ jsx(
|
|
37172
36745
|
Badge,
|
|
37173
36746
|
{
|
|
@@ -37507,26 +37080,30 @@ function OrderFormItemsCard({
|
|
|
37507
37080
|
emptyLabel = "Nenhum item adicionado",
|
|
37508
37081
|
emptyActionLabel = "Adicione o primeiro item",
|
|
37509
37082
|
children,
|
|
37510
|
-
"data-tour": dataTour
|
|
37083
|
+
"data-tour": dataTour,
|
|
37084
|
+
headerExtra
|
|
37511
37085
|
}) {
|
|
37512
37086
|
return /* @__PURE__ */ jsxs("div", { "data-tour": dataTour, className: "flex flex-col overflow-hidden rounded-card border bg-card", children: [
|
|
37513
37087
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b px-4 py-3", children: [
|
|
37514
37088
|
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: label3 }),
|
|
37515
|
-
|
|
37516
|
-
|
|
37517
|
-
|
|
37518
|
-
|
|
37519
|
-
|
|
37520
|
-
|
|
37521
|
-
|
|
37522
|
-
|
|
37523
|
-
|
|
37524
|
-
|
|
37525
|
-
|
|
37526
|
-
|
|
37527
|
-
|
|
37528
|
-
|
|
37529
|
-
|
|
37089
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
37090
|
+
headerExtra,
|
|
37091
|
+
onAdd && /* @__PURE__ */ jsxs(
|
|
37092
|
+
"button",
|
|
37093
|
+
{
|
|
37094
|
+
type: "button",
|
|
37095
|
+
onClick: onAdd,
|
|
37096
|
+
disabled: addDisabled,
|
|
37097
|
+
title: addDisabled ? addDisabledHint : void 0,
|
|
37098
|
+
className: "fz-tap inline-flex items-center gap-2 rounded-button border border-primary bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground shadow-button-primary transition-colors hover:bg-primary/90 active:shadow-button-inset disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-primary",
|
|
37099
|
+
children: [
|
|
37100
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
|
|
37101
|
+
" ",
|
|
37102
|
+
addLabel
|
|
37103
|
+
]
|
|
37104
|
+
}
|
|
37105
|
+
)
|
|
37106
|
+
] })
|
|
37530
37107
|
] }),
|
|
37531
37108
|
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
37532
37109
|
header,
|
|
@@ -38522,6 +38099,13 @@ function OrderListView({
|
|
|
38522
38099
|
searchText,
|
|
38523
38100
|
searchPlaceholder,
|
|
38524
38101
|
pageSize = 25,
|
|
38102
|
+
search: searchProp,
|
|
38103
|
+
onSearchChange,
|
|
38104
|
+
page: pageProp,
|
|
38105
|
+
total,
|
|
38106
|
+
onPageChange,
|
|
38107
|
+
filters,
|
|
38108
|
+
mobileLayout,
|
|
38525
38109
|
bulkActions,
|
|
38526
38110
|
rowId,
|
|
38527
38111
|
selectedRowId,
|
|
@@ -38531,8 +38115,15 @@ function OrderListView({
|
|
|
38531
38115
|
boards,
|
|
38532
38116
|
viewKey
|
|
38533
38117
|
}) {
|
|
38534
|
-
const [
|
|
38535
|
-
const [
|
|
38118
|
+
const [localSearch, setLocalSearch] = React133.useState("");
|
|
38119
|
+
const [localPage, setLocalPage] = React133.useState(1);
|
|
38120
|
+
const serverPaged = total != null;
|
|
38121
|
+
const search = onSearchChange ? searchProp ?? "" : localSearch;
|
|
38122
|
+
const setSearch = onSearchChange ?? setLocalSearch;
|
|
38123
|
+
const page = serverPaged ? pageProp ?? 1 : localPage;
|
|
38124
|
+
const setPage = serverPaged ? onPageChange ?? (() => {
|
|
38125
|
+
}) : setLocalPage;
|
|
38126
|
+
const searchable = !!searchText || !!onSearchChange;
|
|
38536
38127
|
const [rawSelection, setRawSelection] = React133.useState([]);
|
|
38537
38128
|
const offered = React133.useMemo(
|
|
38538
38129
|
() => views && views.length > 0 ? views : ["list"],
|
|
@@ -38587,6 +38178,7 @@ function OrderListView({
|
|
|
38587
38178
|
const cols = React133.useMemo(
|
|
38588
38179
|
() => columns.map((c) => ({
|
|
38589
38180
|
id: c.key,
|
|
38181
|
+
...c.mobile ? { meta: { mobile: c.mobile } } : {},
|
|
38590
38182
|
header: () => /* @__PURE__ */ jsx("div", { className: c.align === "right" ? "text-right" : "", children: c.header }),
|
|
38591
38183
|
cell: ({ row }) => /* @__PURE__ */ jsx("div", { className: c.align === "right" ? "text-right" : "", children: c.render(row.original) })
|
|
38592
38184
|
})),
|
|
@@ -38594,13 +38186,14 @@ function OrderListView({
|
|
|
38594
38186
|
);
|
|
38595
38187
|
const filtered = React133.useMemo(() => {
|
|
38596
38188
|
const term = search.trim().toLowerCase();
|
|
38597
|
-
if (!term || !searchText) return rows;
|
|
38189
|
+
if (!term || !searchText || onSearchChange) return rows;
|
|
38598
38190
|
return rows.filter((row) => searchText(row).toLowerCase().includes(term));
|
|
38599
38191
|
}, [rows, search, searchText]);
|
|
38600
38192
|
React133.useEffect(() => {
|
|
38601
|
-
|
|
38602
|
-
}, [
|
|
38603
|
-
const paged = pageSize
|
|
38193
|
+
setLocalPage(1);
|
|
38194
|
+
}, [localSearch]);
|
|
38195
|
+
const paged = serverPaged || pageSize <= 0 ? filtered : filtered.slice((page - 1) * pageSize, page * pageSize);
|
|
38196
|
+
const totalRows = serverPaged ? total : filtered.length;
|
|
38604
38197
|
const getId = React133.useCallback(
|
|
38605
38198
|
(row) => rowId ? rowId(row) : String(row.id ?? ""),
|
|
38606
38199
|
[rowId]
|
|
@@ -38658,19 +38251,26 @@ function OrderListView({
|
|
|
38658
38251
|
}
|
|
38659
38252
|
) : null,
|
|
38660
38253
|
tiles.length > 0 && /* @__PURE__ */ jsx(StatTiles, { tiles, loading }),
|
|
38661
|
-
activeCustom ? activeCustom() : showingBoard ? /* @__PURE__ */
|
|
38662
|
-
|
|
38663
|
-
|
|
38664
|
-
|
|
38665
|
-
|
|
38666
|
-
|
|
38667
|
-
|
|
38668
|
-
|
|
38669
|
-
|
|
38670
|
-
|
|
38671
|
-
|
|
38672
|
-
|
|
38673
|
-
|
|
38254
|
+
activeCustom ? activeCustom() : showingBoard ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
38255
|
+
(searchable || filters) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
38256
|
+
searchable && /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: /* @__PURE__ */ jsx(SearchField, { value: search, onChange: setSearch, placeholder: searchPlaceholder ?? "Buscar\u2026" }) }),
|
|
38257
|
+
filters
|
|
38258
|
+
] }),
|
|
38259
|
+
/* @__PURE__ */ jsx(
|
|
38260
|
+
OrderBoardView,
|
|
38261
|
+
{
|
|
38262
|
+
board: activeBoard,
|
|
38263
|
+
rows: filtered,
|
|
38264
|
+
loading,
|
|
38265
|
+
empty,
|
|
38266
|
+
onRowClick,
|
|
38267
|
+
rowId,
|
|
38268
|
+
selectedRowId
|
|
38269
|
+
}
|
|
38270
|
+
),
|
|
38271
|
+
serverPaged && !loading && totalRows > pageSize && pageSize > 0 && /* @__PURE__ */ jsx(ChevronPager, { page, pageSize, total: totalRows, onPageChange: setPage })
|
|
38272
|
+
] }) : /* @__PURE__ */ jsxs(Card, { className: "overflow-hidden", children: [
|
|
38273
|
+
(searchable || filters || hasSelection) && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-2", children: hasSelection ? /* @__PURE__ */ jsx(
|
|
38674
38274
|
BulkActionBar,
|
|
38675
38275
|
{
|
|
38676
38276
|
variant: "inline",
|
|
@@ -38680,14 +38280,17 @@ function OrderListView({
|
|
|
38680
38280
|
onClear: () => setRawSelection([]),
|
|
38681
38281
|
actions: barActions
|
|
38682
38282
|
}
|
|
38683
|
-
) : /* @__PURE__ */
|
|
38684
|
-
|
|
38685
|
-
|
|
38686
|
-
|
|
38687
|
-
|
|
38688
|
-
|
|
38689
|
-
|
|
38690
|
-
|
|
38283
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38284
|
+
searchable && /* @__PURE__ */ jsx("div", { className: "min-w-[10rem] flex-1", children: /* @__PURE__ */ jsx(
|
|
38285
|
+
SearchField,
|
|
38286
|
+
{
|
|
38287
|
+
value: search,
|
|
38288
|
+
onChange: setSearch,
|
|
38289
|
+
placeholder: searchPlaceholder ?? "Buscar\u2026"
|
|
38290
|
+
}
|
|
38291
|
+
) }),
|
|
38292
|
+
filters
|
|
38293
|
+
] }) }),
|
|
38691
38294
|
/* @__PURE__ */ jsx(
|
|
38692
38295
|
DataTable,
|
|
38693
38296
|
{
|
|
@@ -38700,15 +38303,16 @@ function OrderListView({
|
|
|
38700
38303
|
data: loading ? [] : paged,
|
|
38701
38304
|
emptyMessage: search.trim() ? "Nada encontrado para esta busca." : empty,
|
|
38702
38305
|
loading,
|
|
38703
|
-
onRowClick: onRowClick ? (row) => onRowClick(row) : void 0
|
|
38306
|
+
onRowClick: onRowClick ? (row) => onRowClick(row) : void 0,
|
|
38307
|
+
...mobileLayout ? { mobileLayout } : {}
|
|
38704
38308
|
}
|
|
38705
38309
|
),
|
|
38706
|
-
!loading &&
|
|
38310
|
+
!loading && totalRows > 0 && pageSize > 0 && /* @__PURE__ */ jsx(
|
|
38707
38311
|
ChevronPager,
|
|
38708
38312
|
{
|
|
38709
38313
|
page,
|
|
38710
38314
|
pageSize,
|
|
38711
|
-
total:
|
|
38315
|
+
total: totalRows,
|
|
38712
38316
|
onPageChange: setPage
|
|
38713
38317
|
}
|
|
38714
38318
|
)
|
|
@@ -38766,7 +38370,7 @@ function PaymentStatusBadge({
|
|
|
38766
38370
|
React133__default.useEffect(() => {
|
|
38767
38371
|
setLines(null);
|
|
38768
38372
|
}, [status, paidAmount]);
|
|
38769
|
-
const
|
|
38373
|
+
const load2 = React133__default.useCallback(() => {
|
|
38770
38374
|
if (lines || !onLoadDetails) return;
|
|
38771
38375
|
void onLoadDetails().then(setLines).catch(() => setLines([]));
|
|
38772
38376
|
}, [lines, onLoadDetails]);
|
|
@@ -38781,7 +38385,7 @@ function PaymentStatusBadge({
|
|
|
38781
38385
|
onMouseEnter: onLoadDetails ? () => {
|
|
38782
38386
|
timer.current = setTimeout(() => {
|
|
38783
38387
|
setOpen(true);
|
|
38784
|
-
|
|
38388
|
+
load2();
|
|
38785
38389
|
}, 500);
|
|
38786
38390
|
} : void 0,
|
|
38787
38391
|
onMouseLeave: onLoadDetails ? () => {
|
|
@@ -38802,7 +38406,7 @@ function PaymentStatusBadge({
|
|
|
38802
38406
|
const remaining = totalAmount != null && paidAmount != null ? totalAmount - paidAmount : null;
|
|
38803
38407
|
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: (v) => {
|
|
38804
38408
|
setOpen(v);
|
|
38805
|
-
if (v)
|
|
38409
|
+
if (v) load2();
|
|
38806
38410
|
}, children: [
|
|
38807
38411
|
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: trigger }),
|
|
38808
38412
|
/* @__PURE__ */ jsxs(PopoverContent, { align: "end", sideOffset: 6, className: "w-60 p-3", children: [
|
|
@@ -38907,7 +38511,7 @@ function useOrdersPaymentStatus(orderIds) {
|
|
|
38907
38511
|
);
|
|
38908
38512
|
const [byOrder, setByOrder] = React133.useState(() => /* @__PURE__ */ new Map());
|
|
38909
38513
|
const [loading, setLoading] = React133.useState(false);
|
|
38910
|
-
const
|
|
38514
|
+
const load2 = React133.useCallback(async (force = false) => {
|
|
38911
38515
|
const ids = key ? key.split(",") : [];
|
|
38912
38516
|
if (ids.length === 0) {
|
|
38913
38517
|
setByOrder(/* @__PURE__ */ new Map());
|
|
@@ -38939,9 +38543,9 @@ function useOrdersPaymentStatus(orderIds) {
|
|
|
38939
38543
|
setByOrder(new Map(ids.map((id) => [id, cache2.get(id)]).filter(([, v]) => Boolean(v))));
|
|
38940
38544
|
}, [key]);
|
|
38941
38545
|
React133.useEffect(() => {
|
|
38942
|
-
void
|
|
38943
|
-
}, [
|
|
38944
|
-
return { byOrder, loading, reload: () =>
|
|
38546
|
+
void load2();
|
|
38547
|
+
}, [load2]);
|
|
38548
|
+
return { byOrder, loading, reload: () => load2(true) };
|
|
38945
38549
|
}
|
|
38946
38550
|
var ORDER_KIND_LABELS = {
|
|
38947
38551
|
sale: "Venda",
|
|
@@ -38974,7 +38578,9 @@ var ORDER_CHANNEL_LABELS = {
|
|
|
38974
38578
|
balcao: "Balc\xE3o",
|
|
38975
38579
|
shop: "Loja",
|
|
38976
38580
|
dine_in: "Sal\xE3o",
|
|
38977
|
-
delivery: "Delivery"
|
|
38581
|
+
delivery: "Delivery",
|
|
38582
|
+
retirada: "Retirada",
|
|
38583
|
+
ticketing: "Bilheteria"
|
|
38978
38584
|
};
|
|
38979
38585
|
function Badge28({ children }) {
|
|
38980
38586
|
return /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium", children });
|
|
@@ -39023,7 +38629,7 @@ function useOrderDetail(orderId) {
|
|
|
39023
38629
|
try {
|
|
39024
38630
|
const db2 = getSupabaseClientOptional();
|
|
39025
38631
|
if (!db2) throw new Error("Supabase client is not configured");
|
|
39026
|
-
const { data: row, error: rowError } = await db2.from("v_orders").select("id, reference_number, kind, channel, status, party_id, subtotal, discount, tax, total, currency, notes, created_at").eq("id", orderId).maybeSingle();
|
|
38632
|
+
const { data: row, error: rowError } = await db2.from("v_orders").select("id, reference_number, kind, channel, status, fulfillment_status, party_id, subtotal, discount, tax, total, currency, notes, created_at").eq("id", orderId).maybeSingle();
|
|
39027
38633
|
if (rowError) throw new Error(rowError.message);
|
|
39028
38634
|
if (!row) throw new Error("Pedido n\xE3o encontrado");
|
|
39029
38635
|
const [{ data: items }, { data: party }] = await Promise.all([
|
|
@@ -39046,6 +38652,7 @@ function useOrderDetail(orderId) {
|
|
|
39046
38652
|
kind: row.kind ?? void 0,
|
|
39047
38653
|
channel: row.channel ?? void 0,
|
|
39048
38654
|
status: row.status ?? void 0,
|
|
38655
|
+
fulfillmentStatus: row.fulfillment_status ?? void 0,
|
|
39049
38656
|
partyName: party?.name ?? void 0,
|
|
39050
38657
|
notes: row.notes ?? void 0,
|
|
39051
38658
|
currency: row.currency ?? "BRL",
|
|
@@ -39342,6 +38949,155 @@ function toOrderDetailReceivable(receivable, money4, options = {}) {
|
|
|
39342
38949
|
...options.actions ? { actions: options.actions } : {}
|
|
39343
38950
|
};
|
|
39344
38951
|
}
|
|
38952
|
+
|
|
38953
|
+
// src/crud/archetypes/orderStage.ts
|
|
38954
|
+
var ORDER_STAGES = ["to_receive", "to_ship", "shipped", "done", "cancelled"];
|
|
38955
|
+
var ORDER_STAGE_LABELS = {
|
|
38956
|
+
to_receive: "A receber",
|
|
38957
|
+
to_ship: "A enviar",
|
|
38958
|
+
shipped: "Enviado",
|
|
38959
|
+
done: "Conclu\xEDdo",
|
|
38960
|
+
cancelled: "Cancelado"
|
|
38961
|
+
};
|
|
38962
|
+
var ORDER_STAGE_COLORS = {
|
|
38963
|
+
to_receive: "bg-amber-500",
|
|
38964
|
+
to_ship: "bg-blue-500",
|
|
38965
|
+
shipped: "bg-cyan-500",
|
|
38966
|
+
done: "bg-emerald-500",
|
|
38967
|
+
cancelled: "bg-gray-400"
|
|
38968
|
+
};
|
|
38969
|
+
var SHIPPING_CHANNELS = /* @__PURE__ */ new Set(["shop", "delivery"]);
|
|
38970
|
+
function orderStage(order) {
|
|
38971
|
+
if (order.status === "cancelled") return "cancelled";
|
|
38972
|
+
const owed = ["pending", "open", "partial", "overdue"].includes(order.paymentStatus ?? "");
|
|
38973
|
+
if (order.status === "completed") return owed ? "to_receive" : "done";
|
|
38974
|
+
if (order.paymentStatus !== "paid") return "to_receive";
|
|
38975
|
+
const shipments = (order.shipmentStatuses ?? []).filter((s) => s !== "cancelled");
|
|
38976
|
+
const delivered = shipments.length > 0 && shipments.every((s) => s === "delivered" || s === "completed");
|
|
38977
|
+
if (shipments.some((s) => s === "in_transit")) return "shipped";
|
|
38978
|
+
if (order.fulfillmentStatus === "fulfilled" || delivered) return "done";
|
|
38979
|
+
const ships = shipments.length > 0 || SHIPPING_CHANNELS.has(order.channel ?? "");
|
|
38980
|
+
return ships ? "to_ship" : "done";
|
|
38981
|
+
}
|
|
38982
|
+
var STATUS_LABEL = {
|
|
38983
|
+
pending: "Aguardando envio",
|
|
38984
|
+
in_progress: "Em preparo",
|
|
38985
|
+
in_transit: "Em tr\xE2nsito",
|
|
38986
|
+
delivered: "Entregue",
|
|
38987
|
+
completed: "Entregue",
|
|
38988
|
+
failed: "Falhou",
|
|
38989
|
+
returned: "Devolvido",
|
|
38990
|
+
cancelled: "Cancelado"
|
|
38991
|
+
};
|
|
38992
|
+
var KIND_LABEL = { shipment: "Envio", pickup: "Retirada" };
|
|
38993
|
+
function text2(value) {
|
|
38994
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
38995
|
+
}
|
|
38996
|
+
function useOrderFulfillments(orderId) {
|
|
38997
|
+
const [fulfillments, setFulfillments] = React133.useState([]);
|
|
38998
|
+
const [loading, setLoading] = React133.useState(false);
|
|
38999
|
+
const [error, setError] = React133.useState(null);
|
|
39000
|
+
const [nonce, setNonce] = React133.useState(0);
|
|
39001
|
+
const reload2 = React133.useCallback(() => setNonce((n) => n + 1), []);
|
|
39002
|
+
React133.useEffect(() => {
|
|
39003
|
+
if (!orderId) {
|
|
39004
|
+
setFulfillments([]);
|
|
39005
|
+
setError(null);
|
|
39006
|
+
return;
|
|
39007
|
+
}
|
|
39008
|
+
let cancelled = false;
|
|
39009
|
+
setLoading(true);
|
|
39010
|
+
setError(null);
|
|
39011
|
+
void (async () => {
|
|
39012
|
+
try {
|
|
39013
|
+
const db2 = getSupabaseClientOptional();
|
|
39014
|
+
if (!db2) return;
|
|
39015
|
+
const { data: rows, error: rowsError } = await db2.from("fulfillments").select("id, kind, status, carrier, tracking_code, tracking_url, shipped_at, delivered_at, estimated_delivery_at, address_id, metadata").eq("order_id", orderId).in("kind", ["shipment", "pickup"]).order("occurred_at", { ascending: true });
|
|
39016
|
+
if (rowsError) throw new Error(rowsError.message);
|
|
39017
|
+
const addressIds = [...new Set((rows ?? []).map((r) => r.address_id).filter(Boolean))];
|
|
39018
|
+
const { data: addresses, error: addressError } = addressIds.length ? await db2.from("addresses").select("id, recipient, phone, postal_code, street, number, complement, district, city, state").in("id", addressIds) : { data: [], error: null };
|
|
39019
|
+
if (addressError) throw new Error(addressError.message);
|
|
39020
|
+
if (cancelled) return;
|
|
39021
|
+
const addressById = new Map((addresses ?? []).map((a) => [a.id, a]));
|
|
39022
|
+
setFulfillments((rows ?? []).map((r) => {
|
|
39023
|
+
const meta = r.metadata ?? {};
|
|
39024
|
+
const a = r.address_id ? addressById.get(r.address_id) : void 0;
|
|
39025
|
+
return {
|
|
39026
|
+
id: r.id,
|
|
39027
|
+
kind: r.kind,
|
|
39028
|
+
status: r.status,
|
|
39029
|
+
// Older rows carry these in metadata; the columns win when set.
|
|
39030
|
+
carrier: text2(r.carrier) ?? text2(meta.carrier),
|
|
39031
|
+
trackingCode: text2(r.tracking_code) ?? text2(meta.tracking_code),
|
|
39032
|
+
trackingUrl: text2(r.tracking_url) ?? text2(meta.tracking_url),
|
|
39033
|
+
shippedAt: r.shipped_at ?? void 0,
|
|
39034
|
+
deliveredAt: r.delivered_at ?? void 0,
|
|
39035
|
+
estimatedDeliveryAt: r.estimated_delivery_at ?? void 0,
|
|
39036
|
+
address: a ? {
|
|
39037
|
+
recipient: text2(a.recipient),
|
|
39038
|
+
phone: text2(a.phone),
|
|
39039
|
+
line1: [a.street, a.number].filter(Boolean).join(", ") + (a.complement ? ` \u2014 ${a.complement}` : ""),
|
|
39040
|
+
line2: [a.district, [a.city, a.state].filter(Boolean).join("/"), a.postal_code].filter(Boolean).join(" \xB7 ")
|
|
39041
|
+
} : void 0
|
|
39042
|
+
};
|
|
39043
|
+
}));
|
|
39044
|
+
} catch (err) {
|
|
39045
|
+
if (!cancelled) {
|
|
39046
|
+
setFulfillments([]);
|
|
39047
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
39048
|
+
}
|
|
39049
|
+
} finally {
|
|
39050
|
+
if (!cancelled) setLoading(false);
|
|
39051
|
+
}
|
|
39052
|
+
})();
|
|
39053
|
+
return () => {
|
|
39054
|
+
cancelled = true;
|
|
39055
|
+
};
|
|
39056
|
+
}, [orderId, nonce]);
|
|
39057
|
+
return { fulfillments, loading, error, reload: reload2 };
|
|
39058
|
+
}
|
|
39059
|
+
function day(value) {
|
|
39060
|
+
return value ? new Date(value).toLocaleDateString("pt-BR") : void 0;
|
|
39061
|
+
}
|
|
39062
|
+
function OrderDeliveryBlock({ fulfillments, error }) {
|
|
39063
|
+
if (error) {
|
|
39064
|
+
return /* @__PURE__ */ jsx(OrderDetailBlock, { title: "Entrega", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", role: "alert", "data-testid": "order-delivery-error", children: "N\xE3o foi poss\xEDvel carregar a entrega deste pedido." }) });
|
|
39065
|
+
}
|
|
39066
|
+
if (fulfillments.length === 0) {
|
|
39067
|
+
return /* @__PURE__ */ jsx(OrderDetailBlock, { title: "Entrega", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", "data-testid": "order-delivery-empty", children: "Nenhum endere\xE7o ou envio registrado neste pedido." }) });
|
|
39068
|
+
}
|
|
39069
|
+
return /* @__PURE__ */ jsx(OrderDetailBlock, { title: "Entrega", children: /* @__PURE__ */ jsx("ul", { className: "divide-y text-sm", children: fulfillments.map((f) => /* @__PURE__ */ jsxs("li", { className: "space-y-1 py-2 first:pt-0 last:pb-0", "data-testid": "order-fulfillment", children: [
|
|
39070
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
|
|
39071
|
+
/* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
39072
|
+
KIND_LABEL[f.kind] ?? f.kind,
|
|
39073
|
+
f.carrier ? ` \xB7 ${f.carrier}` : ""
|
|
39074
|
+
] }),
|
|
39075
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: STATUS_LABEL[f.status] ?? f.status })
|
|
39076
|
+
] }),
|
|
39077
|
+
f.trackingCode && /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground", children: [
|
|
39078
|
+
"Rastreio:",
|
|
39079
|
+
" ",
|
|
39080
|
+
f.trackingUrl ? /* @__PURE__ */ jsx("a", { href: f.trackingUrl, target: "_blank", rel: "noreferrer", className: "text-primary underline-offset-2 hover:underline", children: f.trackingCode }) : /* @__PURE__ */ jsx("span", { className: "text-foreground", children: f.trackingCode })
|
|
39081
|
+
] }),
|
|
39082
|
+
(f.shippedAt || f.deliveredAt || f.estimatedDeliveryAt) && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: [
|
|
39083
|
+
f.shippedAt && `Enviado em ${day(f.shippedAt)}`,
|
|
39084
|
+
f.deliveredAt ? `Entregue em ${day(f.deliveredAt)}` : f.estimatedDeliveryAt && `Previs\xE3o ${day(f.estimatedDeliveryAt)}`
|
|
39085
|
+
].filter(Boolean).join(" \xB7 ") }),
|
|
39086
|
+
f.address && /* @__PURE__ */ jsxs("address", { className: "not-italic text-muted-foreground", children: [
|
|
39087
|
+
f.address.recipient && /* @__PURE__ */ jsx("span", { className: "block text-foreground", children: f.address.recipient }),
|
|
39088
|
+
/* @__PURE__ */ jsx("span", { className: "block", children: f.address.line1 }),
|
|
39089
|
+
/* @__PURE__ */ jsx("span", { className: "block", children: f.address.line2 }),
|
|
39090
|
+
f.address.phone && /* @__PURE__ */ jsx("span", { className: "block", children: f.address.phone })
|
|
39091
|
+
] })
|
|
39092
|
+
] }, f.id)) }) });
|
|
39093
|
+
}
|
|
39094
|
+
var STAGE_TONE = {
|
|
39095
|
+
to_receive: "warning",
|
|
39096
|
+
to_ship: "info",
|
|
39097
|
+
shipped: "info",
|
|
39098
|
+
done: "success",
|
|
39099
|
+
cancelled: "destructive"
|
|
39100
|
+
};
|
|
39345
39101
|
function money3(value, currency) {
|
|
39346
39102
|
return value.toLocaleString("pt-BR", { style: "currency", currency: currency || "BRL" });
|
|
39347
39103
|
}
|
|
@@ -39354,9 +39110,10 @@ function OrderDetailPage({
|
|
|
39354
39110
|
mapData,
|
|
39355
39111
|
receivableActions
|
|
39356
39112
|
}) {
|
|
39357
|
-
const { order, loading, error } = useOrderDetail(orderId);
|
|
39113
|
+
const { order, loading, error, reload: reload2 } = useOrderDetail(orderId);
|
|
39114
|
+
const { fulfillments, error: fulfillmentsError } = useOrderFulfillments(orderId);
|
|
39358
39115
|
const { receivable, reload: reloadReceivable } = useOrderReceivable(orderId);
|
|
39359
|
-
if (loading) return /* @__PURE__ */ jsx(OrderDetailSkeleton, {});
|
|
39116
|
+
if (loading && !order) return /* @__PURE__ */ jsx(OrderDetailSkeleton, {});
|
|
39360
39117
|
if (error || !order) {
|
|
39361
39118
|
return /* @__PURE__ */ jsxs("div", { className: "p-6", children: [
|
|
39362
39119
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error ?? "Pedido n\xE3o encontrado" }),
|
|
@@ -39373,27 +39130,18 @@ function OrderDetailPage({
|
|
|
39373
39130
|
}
|
|
39374
39131
|
const currency = order.currency;
|
|
39375
39132
|
const verbs = receivableActions?.(order, { receivable, reload: reloadReceivable });
|
|
39133
|
+
const stage = orderStage({
|
|
39134
|
+
status: order.status,
|
|
39135
|
+
channel: order.channel,
|
|
39136
|
+
paymentStatus: receivable?.balance.status ?? "none",
|
|
39137
|
+
fulfillmentStatus: order.fulfillmentStatus,
|
|
39138
|
+
shipmentStatuses: fulfillments.map((f) => f.status)
|
|
39139
|
+
});
|
|
39376
39140
|
const base = {
|
|
39377
39141
|
title: order.referenceNumber,
|
|
39378
|
-
//
|
|
39379
|
-
//
|
|
39380
|
-
|
|
39381
|
-
// `dine_in`, `balcao` — machine words, and printing them is how a screen
|
|
39382
|
-
// ends up saying "dine_in" to a waiter. Anything the vocabulary has not
|
|
39383
|
-
// named falls through to the raw value rather than being guessed at.
|
|
39384
|
-
badges: [
|
|
39385
|
-
...order.status ? [{ label: ORDER_STATUS_LABELS[order.status] ?? order.status, tone: orderStatusTone(order.status) }] : [],
|
|
39386
|
-
...order.kind ? [{ label: ORDER_KIND_LABELS[order.kind] ?? order.kind, tone: "muted" }] : [],
|
|
39387
|
-
...order.channel ? [{ label: ORDER_CHANNEL_LABELS[order.channel] ?? order.channel, tone: "muted" }] : [],
|
|
39388
|
-
// O estado do DINHEIRO ao lado do estado do PEDIDO. Ate aqui a resposta
|
|
39389
|
-
// existia so no bloco de baixo, e quem abre a ficha para saber se ja
|
|
39390
|
-
// recebeu tinha de rolar a tela para descobrir. So aparece depois de
|
|
39391
|
-
// faturado — sem fatura nao ha o que dizer, e o bloco de baixo ja diz.
|
|
39392
|
-
...receivable ? [{
|
|
39393
|
-
label: RECEIVABLE_LABEL[receivable.balance.status] ?? receivable.balance.status,
|
|
39394
|
-
tone: receivableTone(receivable.balance.status)
|
|
39395
|
-
}] : []
|
|
39396
|
-
],
|
|
39142
|
+
// ONE badge, the same word the list and the board use for this order.
|
|
39143
|
+
// Status, kind, channel and money as four chips read as four states.
|
|
39144
|
+
badges: [{ label: ORDER_STAGE_LABELS[stage], tone: STAGE_TONE[stage] }],
|
|
39397
39145
|
// The date belongs in the provenance footer, where every other ficha in the
|
|
39398
39146
|
// app keeps "criado em" — beside the order number it competes with what the
|
|
39399
39147
|
// person opened the screen to read. `meta` is what RecordMetaFooter reads.
|
|
@@ -39424,8 +39172,12 @@ function OrderDetailPage({
|
|
|
39424
39172
|
// dois ramos: dois `createElement` distintos remontariam o componente na
|
|
39425
39173
|
// troca de ramo, e com ele o modal aberto.
|
|
39426
39174
|
receivable: toOrderDetailReceivable(receivable, (value) => money3(value, currency), { actions: verbs }) ?? { rows: [], installments: [], actions: verbs },
|
|
39427
|
-
...actions ? { actions: actions(order) } : {},
|
|
39428
|
-
|
|
39175
|
+
...actions ? { actions: actions(order, { reload: reload2 }) } : {},
|
|
39176
|
+
// Beside the customer, where the shop's own page keeps it.
|
|
39177
|
+
extraSections: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
39178
|
+
/* @__PURE__ */ jsx(OrderDeliveryBlock, { fulfillments, error: fulfillmentsError }),
|
|
39179
|
+
extraSections?.(order)
|
|
39180
|
+
] }),
|
|
39429
39181
|
backLabel,
|
|
39430
39182
|
onBack: () => navigateTo(backTo)
|
|
39431
39183
|
};
|
|
@@ -39543,6 +39295,43 @@ function useOrderEditor(orderId) {
|
|
|
39543
39295
|
save
|
|
39544
39296
|
};
|
|
39545
39297
|
}
|
|
39298
|
+
var cache4 = null;
|
|
39299
|
+
function load() {
|
|
39300
|
+
cache4 ?? (cache4 = (async () => {
|
|
39301
|
+
const db2 = getSupabaseClientOptional();
|
|
39302
|
+
if (!db2) return /* @__PURE__ */ new Map();
|
|
39303
|
+
const { data, error } = await db2.from("order_kinds").select("kind, transitions");
|
|
39304
|
+
if (error) {
|
|
39305
|
+
cache4 = null;
|
|
39306
|
+
return /* @__PURE__ */ new Map();
|
|
39307
|
+
}
|
|
39308
|
+
return new Map((data ?? []).map((r) => [r.kind, r.transitions ?? {}]));
|
|
39309
|
+
})());
|
|
39310
|
+
return cache4;
|
|
39311
|
+
}
|
|
39312
|
+
var TERMINAL = /* @__PURE__ */ new Set(["completed", "cancelled"]);
|
|
39313
|
+
function nextOrderStatuses(transitions, status) {
|
|
39314
|
+
if (!transitions || !status) return [];
|
|
39315
|
+
const declared = transitions[status] ?? transitions["*"] ?? [];
|
|
39316
|
+
if (declared.includes("*")) return TERMINAL.has(status) ? [] : ["cancelled"];
|
|
39317
|
+
return declared;
|
|
39318
|
+
}
|
|
39319
|
+
function useOrderKindTransitions(kind, status) {
|
|
39320
|
+
const [byKind, setByKind] = React133.useState(null);
|
|
39321
|
+
React133.useEffect(() => {
|
|
39322
|
+
let live = true;
|
|
39323
|
+
void load().then((map) => {
|
|
39324
|
+
if (live) setByKind(map);
|
|
39325
|
+
});
|
|
39326
|
+
return () => {
|
|
39327
|
+
live = false;
|
|
39328
|
+
};
|
|
39329
|
+
}, []);
|
|
39330
|
+
return React133.useMemo(
|
|
39331
|
+
() => nextOrderStatuses(kind ? byKind?.get(kind) : void 0, status),
|
|
39332
|
+
[byKind, kind, status]
|
|
39333
|
+
);
|
|
39334
|
+
}
|
|
39546
39335
|
|
|
39547
39336
|
// src/lib/create-client-orders-provider.ts
|
|
39548
39337
|
var STAGE_FILTER_MAP = {
|
|
@@ -39763,6 +39552,39 @@ function ModuleActionBar({
|
|
|
39763
39552
|
trailing
|
|
39764
39553
|
] });
|
|
39765
39554
|
}
|
|
39555
|
+
function formatCurrency4(value, currency) {
|
|
39556
|
+
if (!currency) return formatCurrency$1(value);
|
|
39557
|
+
return new Intl.NumberFormat(currency.locale, {
|
|
39558
|
+
style: "currency",
|
|
39559
|
+
currency: currency.code,
|
|
39560
|
+
minimumFractionDigits: 2
|
|
39561
|
+
}).format(value);
|
|
39562
|
+
}
|
|
39563
|
+
function useHouseCurrency() {
|
|
39564
|
+
return React133.useSyncExternalStore(subscribeHouseCurrency, getHouseCurrency, getHouseCurrency);
|
|
39565
|
+
}
|
|
39566
|
+
var CurrencyScopeContext = React133.createContext(null);
|
|
39567
|
+
function CurrencyScope({ code, children }) {
|
|
39568
|
+
const outer = React133.useContext(CurrencyScopeContext);
|
|
39569
|
+
return React133.createElement(CurrencyScopeContext.Provider, { value: code || outer }, children);
|
|
39570
|
+
}
|
|
39571
|
+
function useCurrencyScope() {
|
|
39572
|
+
return React133.useContext(CurrencyScopeContext);
|
|
39573
|
+
}
|
|
39574
|
+
function useCurrency(declared, documentCode) {
|
|
39575
|
+
const house = useHouseCurrency();
|
|
39576
|
+
const scope = useCurrencyScope();
|
|
39577
|
+
const code = documentCode || scope;
|
|
39578
|
+
return React133.useMemo(
|
|
39579
|
+
() => resolveCurrency(declared, code),
|
|
39580
|
+
// `house` is read inside resolveCurrency; listed so a switch re-resolves.
|
|
39581
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
39582
|
+
[declared, code, house]
|
|
39583
|
+
);
|
|
39584
|
+
}
|
|
39585
|
+
function isCurrencyConfig(value) {
|
|
39586
|
+
return !!value && typeof value === "object" && typeof value.code === "string" && typeof value.locale === "string";
|
|
39587
|
+
}
|
|
39766
39588
|
function createPluginContext(displayName) {
|
|
39767
39589
|
const ConfigContext = React133__default.createContext(null);
|
|
39768
39590
|
const ProviderContext = React133__default.createContext(null);
|
|
@@ -39776,8 +39598,16 @@ function createPluginContext(displayName) {
|
|
|
39776
39598
|
ContextProvider.displayName = `${displayName}ContextProvider`;
|
|
39777
39599
|
function useConfig() {
|
|
39778
39600
|
const ctx = React133__default.useContext(ConfigContext);
|
|
39779
|
-
|
|
39780
|
-
|
|
39601
|
+
const house = useHouseCurrency();
|
|
39602
|
+
const scope = useCurrencyScope();
|
|
39603
|
+
const resolved = React133__default.useMemo(() => {
|
|
39604
|
+
const declared = ctx?.currency;
|
|
39605
|
+
const code = scope || house;
|
|
39606
|
+
if (!ctx || !code || !isCurrencyConfig(declared) || declared.code === code) return ctx;
|
|
39607
|
+
return { ...ctx, currency: resolveCurrency(declared, scope) };
|
|
39608
|
+
}, [ctx, house, scope]);
|
|
39609
|
+
if (!resolved) throw new Error(`useConfig must be used within ${displayName}`);
|
|
39610
|
+
return resolved;
|
|
39781
39611
|
}
|
|
39782
39612
|
function useProvider() {
|
|
39783
39613
|
const ctx = React133__default.useContext(ProviderContext);
|
|
@@ -39805,14 +39635,6 @@ function createViewRouter(routes, fallbackId) {
|
|
|
39805
39635
|
return route ? route.render({ id }) : null;
|
|
39806
39636
|
};
|
|
39807
39637
|
}
|
|
39808
|
-
function formatCurrency4(value, currency) {
|
|
39809
|
-
if (!currency) return formatCurrency$1(value);
|
|
39810
|
-
return new Intl.NumberFormat(currency.locale, {
|
|
39811
|
-
style: "currency",
|
|
39812
|
-
currency: currency.code,
|
|
39813
|
-
minimumFractionDigits: 2
|
|
39814
|
-
}).format(value);
|
|
39815
|
-
}
|
|
39816
39638
|
function RegistryCrudView({ registry: registry4, basePath }) {
|
|
39817
39639
|
const useStore2 = useMemo(() => {
|
|
39818
39640
|
const data = registry4.mockData ?? registry4.seedData ?? [];
|
|
@@ -40210,7 +40032,7 @@ function ContactPicker({
|
|
|
40210
40032
|
() => lookup ?? createArchetypeLookup({ archetype: "person", kind }),
|
|
40211
40033
|
[lookup, kind]
|
|
40212
40034
|
);
|
|
40213
|
-
const
|
|
40035
|
+
const create31 = useMemo(() => {
|
|
40214
40036
|
if (createEntityDef?.data?.table) {
|
|
40215
40037
|
const def2 = createEntityDef;
|
|
40216
40038
|
return {
|
|
@@ -40246,8 +40068,8 @@ function ContactPicker({
|
|
|
40246
40068
|
}
|
|
40247
40069
|
};
|
|
40248
40070
|
}, [createEntityDef, resolvedLookup]);
|
|
40249
|
-
const createFeature =
|
|
40250
|
-
const canCreate = !!
|
|
40071
|
+
const createFeature = create31?.def.permission?.feature;
|
|
40072
|
+
const canCreate = !!create31 && (!createFeature || can(createFeature, "create"));
|
|
40251
40073
|
const [search, setSearch] = useState(value?.id ? value.name : value?.name ?? "");
|
|
40252
40074
|
const [options, setOptions] = useState([]);
|
|
40253
40075
|
const [searching, setSearching] = useState(false);
|
|
@@ -40370,17 +40192,17 @@ function ContactPicker({
|
|
|
40370
40192
|
] })
|
|
40371
40193
|
);
|
|
40372
40194
|
}
|
|
40373
|
-
if (creating &&
|
|
40374
|
-
const nameKey =
|
|
40195
|
+
if (creating && create31) {
|
|
40196
|
+
const nameKey = create31.def.displayField ?? create31.def.fields[0]?.key ?? "name";
|
|
40375
40197
|
return frame(
|
|
40376
40198
|
/* @__PURE__ */ jsx(
|
|
40377
40199
|
LookupCreateInline,
|
|
40378
40200
|
{
|
|
40379
|
-
entityDef:
|
|
40201
|
+
entityDef: create31.def,
|
|
40380
40202
|
initialData: { [nameKey]: newName },
|
|
40381
40203
|
onCancel: () => setCreating(false),
|
|
40382
40204
|
save: async (data) => {
|
|
40383
|
-
const person = await
|
|
40205
|
+
const person = await create31.write(data);
|
|
40384
40206
|
setSearch(person.name || newName);
|
|
40385
40207
|
setCreating(false);
|
|
40386
40208
|
onChange({ ...person, name: person.name || newName });
|
|
@@ -40698,9 +40520,9 @@ function clearDocumentOpeners() {
|
|
|
40698
40520
|
function createOneShotAsk(override) {
|
|
40699
40521
|
const connection = resolveFayzAgentConnection(override);
|
|
40700
40522
|
if (!connection) return null;
|
|
40701
|
-
const
|
|
40523
|
+
const client2 = getFayzAgentClient(connection);
|
|
40702
40524
|
return async ({ message, inlineFiles, signal }) => {
|
|
40703
|
-
const reply = await
|
|
40525
|
+
const reply = await client2.chat({
|
|
40704
40526
|
message,
|
|
40705
40527
|
...inlineFiles?.length ? { inlineFiles } : {},
|
|
40706
40528
|
...signal ? { signal } : {},
|
|
@@ -40926,7 +40748,7 @@ function useFeatureHelp(def) {
|
|
|
40926
40748
|
}
|
|
40927
40749
|
function HelpButton({
|
|
40928
40750
|
icon: Icon,
|
|
40929
|
-
text:
|
|
40751
|
+
text: text3,
|
|
40930
40752
|
hint,
|
|
40931
40753
|
ariaLabel,
|
|
40932
40754
|
className,
|
|
@@ -40944,7 +40766,7 @@ function HelpButton({
|
|
|
40944
40766
|
onClick,
|
|
40945
40767
|
children: [
|
|
40946
40768
|
/* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }),
|
|
40947
|
-
|
|
40769
|
+
text3
|
|
40948
40770
|
]
|
|
40949
40771
|
}
|
|
40950
40772
|
) }),
|
|
@@ -41309,6 +41131,6 @@ var renderApp = (...args) => {
|
|
|
41309
41131
|
return renderApp$1(...args);
|
|
41310
41132
|
};
|
|
41311
41133
|
|
|
41312
|
-
export { ALWAYS_ON_TOOLS, ActivationChecklistCard, ActivationProvider, AddConnectorButton, AddConnectorPanel, AdminProviders, AdminScaffold, AdminShell, AskAIButton, AskAIMenuItem, AssistantInvite, BoardFrame, ChatConversation, ClientOrdersTab, ConnectConsentPage, ConnectorDeliveries, ConnectorDetail, ConnectorMark, ConnectorRow, ConnectorSyncActions, ConnectorsHub, ConnectorsTab, ContactPicker, CredentialSinkMissingError, CrudCardGrid, CrudDetailPage, CrudDetailSkeleton, CrudFormPage, CrudFormSkeleton, CrudListView, CrudPage, CrudRecordModal, DeleteConfirmDialog, DetailTabHeader, EntitlementGate, EntityLink, GetStarted, GettingStartedWidget, NotebookPanel as HandbookPanel, HandbookProvider, NotebookRailPanel as HandbookRailPanel, KanbanBoard, LimitGate, LookupCreateInline, MemberAccessRailPage, ModuleActionBar, MultiSelectRow, NOTE_LABEL_PREFIX, NotebookPanel, NotebookRailPanel, ONBOARDING_TASK_SOURCE, ORDER_CHANNEL_LABELS, ORDER_KIND_LABELS, OTHER_CONNECTOR, OrderAmount, OrderBoardView, OrderCreateScreen, OrderDetailBlock, OrderDetailPage, OrderDetailRail, OrderDetailRow, OrderDetailSkeleton, OrderDetailView, OrderFormAddItemStep, OrderDetailBlock as OrderFormBlock, OrderFormItemRow, OrderFormItemsCard, OrderFormSkeleton, OrderFormView, OrderListView, OrderPaymentChip, PAYMENT_STATUS_CONFIG, PAYMENT_STATUS_LABEL, PageActions, PaymentStatusBadge, PermissionGate, PersonLink2 as PersonLink, PlatformError, PluginOnboardingGateSkeleton, PluginRegistryManager, PluginSettingsPanel, ProjectsSettings, QUESTION_PACKS, QuickActionsButton, RECEIVABLE_LABEL, RecordPickerModal, RegistryCrudView2 as RegistryCrudView, RelatedListTab, RightRailActions, RightRailLeading, RightRailPage, RouteErrorBoundary, RouteErrorScreen, SelectRow, SettingsGroup, SettingsTabs, SetupAgentSurface, SetupMeLink, SeuSiteWidget, StateChip, TASK_PRIORITIES, TASK_STATUSES, TaskCard, TaskDetail, TaskGroup, TaskLabelBadge, TaskLabelBadges, TaskPriorityBadge, TaskQuickAdd, TaskSourceBadge, TaskStatusGroup, TasksFilterBar, TasksPanel, TasksRailPanel, TeachMeLink, TextRow, ToggleRow, UNIT_DETAIL_ZONES, UnitSwitcher, UnitsSettingsPage, UpgradePrompt, WORKSPACE_SETUP_FLOW_ID, WORKSPACE_SETUP_FLOW_VERSION, WORKSPACE_SETUP_ROUTE, WidgetSlot, WorkspaceSetupFlow, WorkspaceSetupGate, WorkspaceSwitcher, appendHandbookPage, applyFieldRules, askAI, beautyPack, brandMark, buildBusinessProfile, buildHandbookTree, buildWorkspaceSetupSteps, businessProfileBlock, categoryLabel, checkSlugAvailable, claimTasksSurface, clearDocumentOpeners, clearPersonActions, connectorOptions, connectorRoute, connectorRows, createClientOrdersProvider, createCrudPage, createFayzApp, createFayzProject, createLogoUploader, createMockTasksProvider, createCrudPage as createNativeCrudPage, createOneShotAsk, createPlaceholder, createPlatformProject, createPluginContext, createSupabaseTasksProvider, createViewRouter, currentBusinessProfileBlock,
|
|
41134
|
+
export { ALWAYS_ON_TOOLS, ActivationChecklistCard, ActivationProvider, AddConnectorButton, AddConnectorPanel, AdminProviders, AdminScaffold, AdminShell, AskAIButton, AskAIMenuItem, AssistantInvite, BoardFrame, ChatConversation, ClientOrdersTab, ConnectConsentPage, ConnectorDeliveries, ConnectorDetail, ConnectorMark, ConnectorRow, ConnectorSyncActions, ConnectorsHub, ConnectorsTab, ContactPicker, CredentialSinkMissingError, CrudCardGrid, CrudDetailPage, CrudDetailSkeleton, CrudFormPage, CrudFormSkeleton, CrudListView, CrudPage, CrudRecordModal, CurrencyScope, DeleteConfirmDialog, DetailTabHeader, EntitlementGate, EntityLink, GetStarted, GettingStartedWidget, NotebookPanel as HandbookPanel, HandbookProvider, NotebookRailPanel as HandbookRailPanel, KanbanBoard, LimitGate, LookupCreateInline, MemberAccessRailPage, ModuleActionBar, MultiSelectRow, NOTE_LABEL_PREFIX, NotebookPanel, NotebookRailPanel, ONBOARDING_TASK_SOURCE, ORDER_CHANNEL_LABELS, ORDER_KIND_LABELS, ORDER_STAGES, ORDER_STAGE_COLORS, ORDER_STAGE_LABELS, ORDER_STATUS_LABELS, OTHER_CONNECTOR, OrderAmount, OrderBoardView, OrderCreateScreen, OrderDeliveryBlock, OrderDetailBlock, OrderDetailPage, OrderDetailRail, OrderDetailRow, OrderDetailSkeleton, OrderDetailView, OrderFormAddItemStep, OrderDetailBlock as OrderFormBlock, OrderFormItemRow, OrderFormItemsCard, OrderFormSkeleton, OrderFormView, OrderListView, OrderPaymentChip, PAYMENT_STATUS_CONFIG, PAYMENT_STATUS_LABEL, PageActions, PaymentStatusBadge, PermissionGate, PersonLink2 as PersonLink, PlatformError, PluginOnboardingGateSkeleton, PluginRegistryManager, PluginSettingsPanel, ProjectsSettings, QUESTION_PACKS, QuickActionsButton, RECEIVABLE_LABEL, RecordPickerModal, RegistryCrudView2 as RegistryCrudView, RelatedListTab, RightRailActions, RightRailLeading, RightRailPage, RouteErrorBoundary, RouteErrorScreen, SelectRow, SettingsGroup, SettingsTabs, SetupAgentSurface, SetupMeLink, SeuSiteWidget, StateChip, TASK_PRIORITIES, TASK_STATUSES, TagChip, TagsField, TaskCard, TaskDetail, TaskGroup, TaskLabelBadge, TaskLabelBadges, TaskPriorityBadge, TaskQuickAdd, TaskSourceBadge, TaskStatusGroup, TasksFilterBar, TasksPanel, TasksRailPanel, TeachMeLink, TextRow, ToggleRow, UNIT_DETAIL_ZONES, UnitSwitcher, UnitsSettingsPage, UpgradePrompt, WORKSPACE_SETUP_FLOW_ID, WORKSPACE_SETUP_FLOW_VERSION, WORKSPACE_SETUP_ROUTE, WidgetSlot, WorkspaceSetupFlow, WorkspaceSetupGate, WorkspaceSwitcher, appendHandbookPage, applyFieldRules, askAI, beautyPack, brandMark, buildBusinessProfile, buildHandbookTree, buildWorkspaceSetupSteps, businessProfileBlock, categoryLabel, checkSlugAvailable, claimTasksSurface, clearDocumentOpeners, clearPersonActions, connectorOptions, connectorRoute, connectorRows, createClientOrdersProvider, createCrudPage, createFayzApp, createFayzProject, createLogoUploader, createMockTasksProvider, createCrudPage as createNativeCrudPage, createOneShotAsk, createPlaceholder, createPlatformProject, createPluginContext, createSupabaseTasksProvider, createViewRouter, currentBusinessProfileBlock, defaultProjectOf, defineSaas, deleteFayzProject, deriveAgentContract, deriveEntityKey5 as deriveEntityKey, describeAiError, describeAiGap, describeFayzAgentGap, duplicateWrite, ensureChecklist, exportToCSV, filterConnectors, foodPack, formatActivityElapsed, formatCurrency4 as formatCurrency, formatSetupGuide, getActiveAgent, getAgent, getCrudNavTabs, getDefaultFayzProject, getFayzAgentClient, getGenerationStatus, getHost, getPersonActions, getPersonPath, getPreview, getQuestionPack, getRailPage, getSetupGuide, getSetupGuideForStep, getTabCountProviders, getTasksProvider, helpWith, humanizeWriteError, inferVerticalId, invalidateOrderReceivable, invalidateOrdersPaymentStatus, invalidateRelationOptions, invalidateTabCounts, isPlatformConnected, listFayzProjects, listHandbook, listPlatformProjects, listSetupGuides, loadArea, loadTools, loadedToolNames, mergeLines, needsCredentialSink, nextOrderStatuses, normalizePath, openAssistant, openAssistantAs, openConnectorsPanel, orderChannelColumn, orderIsEditable, orderKindColumn, orderStage, orderStatusTone, orientationTour, parseViewId, publishAssistantActivity, readAttachmentBytes, readHandbookPage, readSetupAnswers, receivableTone, recordOnboardingResponse, registerAdminScaffold, registerAssistantLauncher, registerCrudNavTabs, registerDocumentOpener, registerEntityPath, registerNotesTasksAdapter, registerPersonActions, registerRailPage, registerSetupGuides, registerTabCountProvider, renderApp, renderHandbookOutline, requestChatUpload, requestProjectChange, resetLoadedTools, resolveDocumentOpener, resolveDocumentOpenerFor, resolveFayzAgentConnection, resolveSetupMode, resolveVerticalId, retailPack, revealPage, runWelcome, searchHandbook, searchSetupGuides, setServedRoutes, setTasksProvider, setUpWithMe, shrinkForVision, slugify, soleAgent, splitConnectorValues, splitOnboardingTasks, startGuidedRun, startPreview, stopPreview, submitConnection, submitWorkspaceSetup, summariseSetupGuides, taskEntityDef, tasksSurfaceOwner, teachMe, toInlineFile, toOrderDetailReceivable, unregisterAssistantLauncher, unregisterTabCountProvider, updateFayzProject, useActivationStore, useActiveAgent, useAgent, useAgentStore, useAgentSurface, useAppConfig, useAssistantActivity, useAssistantInviteStore, useAssistantLaunchers, useBusinessProfileStore, useCatalogedItemTypes, useChatStore, useConnectors, useConnectorsPanelAvailable, useContextualNav, useContextualNavStore, useCurrency, useCurrencyScope, useDelegateToAssistant, useFayzProjectsStore, useFeatureHelp, useFieldRules, useHandbookStore, useHasRightRail, useHeaderAction, useHeaderActions, useHouseCurrency, useLaunchersForRole, useLookupCreate, useMemberAccessPanel, useModuleNavigation, useNavContribution, useNavContributionsStore, useNotesTasksBridge, useOfferedPlugins, useOrderDetail, useOrderEditor, useOrderFulfillments, useOrderKindTransitions, useOrderReceivable, useOrdersPaymentStatus, usePersistedState, usePersonTabCounts, usePluginOnboardingGate, usePluginPrefs, usePresetLabel, usePublishAssistantActivity, useRegisterAssistantLauncher, useRememberedList, useRightRailDrill, useRightRailHosted, useRightRailMenu, useRightRailPanel, useRightRailStore, useScrollMemory, useSettingsTabsStore, useShellRailAvailable, useTasksStore, useTasksSummaryLine, useTeachMe, useTenantPluginSettings, useUnitBootstrap, useUnitFilter, useWidgetSurface, useWorkspaceSetupBusy, useWorkspaceSetupGate, useWorkspaceSetupStore, validateSetupGuides, withdrawAssistantActivity, writeHandbookPage };
|
|
41313
41135
|
//# sourceMappingURL=index.js.map
|
|
41314
41136
|
//# sourceMappingURL=index.js.map
|