@elevasis/ui 2.66.0 → 2.68.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/dist/api/index.d.ts +1 -1
  2. package/dist/api/index.js +3 -3
  3. package/dist/app/index.d.ts +16 -15
  4. package/dist/app/index.js +31 -21
  5. package/dist/auth/index.js +10 -12
  6. package/dist/charts/index.js +10 -12
  7. package/dist/chunk-2MTP3H3A.js +425 -0
  8. package/dist/chunk-3KMDHCAR.js +52 -0
  9. package/dist/chunk-3MEXPLWT.js +265 -0
  10. package/dist/{chunk-XNW3O6QW.js → chunk-5NRJ2BLQ.js} +1 -1
  11. package/dist/chunk-75NOC536.js +2162 -0
  12. package/dist/chunk-76IVMVI3.js +1764 -0
  13. package/dist/chunk-AH52XQB7.js +1 -0
  14. package/dist/chunk-BZZCNLT6.js +12 -0
  15. package/dist/chunk-DLR4SDZW.js +51 -0
  16. package/dist/chunk-FK3K2VK2.js +2103 -0
  17. package/dist/chunk-GBXTRSAU.js +37 -0
  18. package/dist/chunk-HJVPVS57.js +1934 -0
  19. package/dist/{chunk-M535KHLW.js → chunk-JC5W55J3.js} +1 -1
  20. package/dist/{chunk-I7BZVVVU.js → chunk-L3HFJFYF.js} +89 -382
  21. package/dist/chunk-LGKLC5MG.js +44 -0
  22. package/dist/{chunk-4DV4ECMG.js → chunk-N7U24M2J.js} +4 -0
  23. package/dist/chunk-NDHMZT2G.js +383 -0
  24. package/dist/chunk-OOACTYRA.js +10 -0
  25. package/dist/chunk-PDHTXPSF.js +12 -0
  26. package/dist/chunk-QYI5BZKM.js +85 -0
  27. package/dist/{chunk-4OEVLV66.js → chunk-R6NMRXNO.js} +112 -147
  28. package/dist/chunk-SIVUCZXQ.js +1194 -0
  29. package/dist/{chunk-JFBZ6XDW.js → chunk-SNZDFCOQ.js} +3 -49
  30. package/dist/chunk-TGPJNKDU.js +1595 -0
  31. package/dist/chunk-TUMSNGTX.js +35 -0
  32. package/dist/chunk-TYKAKJGW.js +67 -0
  33. package/dist/chunk-UD657ICS.js +589 -0
  34. package/dist/chunk-WPIASV3H.js +194 -0
  35. package/dist/chunk-ZFISGKYW.js +39 -0
  36. package/dist/chunk-ZGCWTWBD.js +16127 -0
  37. package/dist/chunk-ZNKZMK2E.js +4528 -0
  38. package/dist/chunk-ZWS3TCQR.js +11032 -0
  39. package/dist/components/chat/index.js +2 -1
  40. package/dist/components/index.d.ts +23 -11
  41. package/dist/components/index.js +2773 -14
  42. package/dist/components/navigation/index.js +11 -12
  43. package/dist/features/auth/index.d.ts +0 -4
  44. package/dist/features/auth/index.js +12 -13
  45. package/dist/features/clients/index.js +14 -12
  46. package/dist/features/crm/index.d.ts +1371 -15
  47. package/dist/features/crm/index.js +15 -12
  48. package/dist/features/dashboard/index.d.ts +1 -2
  49. package/dist/features/dashboard/index.js +15 -12
  50. package/dist/features/delivery/index.d.ts +0 -4
  51. package/dist/features/delivery/index.js +15 -12
  52. package/dist/features/knowledge/index.js +10 -12
  53. package/dist/features/lead-gen/index.d.ts +35 -15
  54. package/dist/features/lead-gen/index.js +16 -12
  55. package/dist/features/monitoring/index.js +15 -12
  56. package/dist/features/monitoring/requests/index.js +13 -13
  57. package/dist/features/operations/index.d.ts +1 -2
  58. package/dist/features/operations/index.js +21 -12
  59. package/dist/features/public-agent-chat/index.js +2 -1
  60. package/dist/features/seo/index.js +2 -1
  61. package/dist/features/settings/index.d.ts +0 -4
  62. package/dist/features/settings/index.js +14 -12
  63. package/dist/hooks/access/index.js +10 -12
  64. package/dist/hooks/delivery/index.d.ts +0 -4
  65. package/dist/hooks/delivery/index.js +2 -23
  66. package/dist/hooks/index.d.ts +13 -7
  67. package/dist/hooks/index.js +10 -12
  68. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +1 -2
  69. package/dist/hooks/published.d.ts +13 -7
  70. package/dist/hooks/published.js +10 -12
  71. package/dist/initialization/index.d.ts +1 -5
  72. package/dist/knowledge/index.d.ts +1 -2
  73. package/dist/knowledge/index.js +15 -13
  74. package/dist/layout/index.js +14 -12
  75. package/dist/organization/index.d.ts +3 -3
  76. package/dist/organization/index.js +1 -21
  77. package/dist/profile/index.d.ts +0 -4
  78. package/dist/provider/index.d.ts +2 -7
  79. package/dist/provider/index.js +10 -12
  80. package/dist/provider/published.d.ts +2 -7
  81. package/dist/provider/published.js +10 -12
  82. package/dist/supabase/index.d.ts +0 -8
  83. package/dist/test-utils/index.d.ts +5 -0
  84. package/dist/test-utils/index.js +5 -5
  85. package/dist/test-utils/setup-integration.js +1 -1
  86. package/dist/test-utils/setup.js +1 -1
  87. package/dist/theme/index.js +2 -1
  88. package/dist/typeform/index.js +2049 -1
  89. package/dist/types/index.d.ts +13 -7
  90. package/dist/utils/index.d.ts +1 -2
  91. package/dist/utils/index.js +1 -1
  92. package/package.json +5 -5
  93. package/dist/chunk-ANNM5R7S.js +0 -51404
  94. package/dist/chunk-AUDNF2Q7.js +0 -2050
  95. package/dist/index.css +0 -659
  96. package/dist/index.d.ts +0 -17888
  97. package/dist/index.js +0 -30
  98. package/dist/{chunk-GMXGDO3I.js → chunk-MISHPEJX.js} +1 -1
@@ -0,0 +1,35 @@
1
+ import { Table, Group, Text, Button } from '@mantine/core';
2
+ import { IconChevronUp, IconChevronDown, IconSelector, IconTrash } from '@tabler/icons-react';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ // src/components/table/SortableHeader.tsx
6
+ function SortableHeader({ column, children, sort, onToggle, style, w }) {
7
+ const isActive = sort.column === column;
8
+ return /* @__PURE__ */ jsx(Table.Th, { style: { ...style, cursor: "pointer", userSelect: "none" }, w, onClick: () => onToggle(column), children: /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
9
+ children,
10
+ isActive ? sort.direction === "asc" ? /* @__PURE__ */ jsx(IconChevronUp, { size: 14 }) : /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(IconSelector, { size: 14, style: { opacity: 0.3 } })
11
+ ] }) });
12
+ }
13
+ function TableSelectionToolbar({ selectedCount, onDelete, isDeleting }) {
14
+ if (selectedCount === 0) return null;
15
+ return /* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
16
+ /* @__PURE__ */ jsxs(Text, { size: "sm", fw: 600, c: "blue", children: [
17
+ selectedCount,
18
+ " selected"
19
+ ] }),
20
+ onDelete && /* @__PURE__ */ jsx(
21
+ Button,
22
+ {
23
+ size: "sm",
24
+ color: "red",
25
+ variant: "light",
26
+ leftSection: /* @__PURE__ */ jsx(IconTrash, { size: 16 }),
27
+ loading: isDeleting,
28
+ onClick: onDelete,
29
+ children: "Delete"
30
+ }
31
+ )
32
+ ] });
33
+ }
34
+
35
+ export { SortableHeader, TableSelectionToolbar };
@@ -0,0 +1,67 @@
1
+ import { useCyberColors, useResourcesHealth, EmptyState, CyberLegendItem, CyberAreaChart } from './chunk-ZGCWTWBD.js';
2
+ import { CardHeader } from './chunk-62GVNH5U.js';
3
+ import { getTimeRangeDates, formatBucketTime } from './chunk-Y6I3IC45.js';
4
+ import { Paper, Center, Loader, Group } from '@mantine/core';
5
+ import { IconActivity, IconChartBar } from '@tabler/icons-react';
6
+ import { useMemo } from 'react';
7
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
+
9
+ function ResourceHealthPanel({ resourceId, resourceType, timeRange }) {
10
+ const colors = useCyberColors();
11
+ const { startDate, endDate } = useMemo(() => getTimeRangeDates(timeRange), [timeRange]);
12
+ const granularity = ["1h", "24h"].includes(timeRange) ? "hour" : "day";
13
+ const { data, isLoading } = useResourcesHealth({
14
+ resources: [{ entityType: resourceType, entityId: resourceId }],
15
+ startDate,
16
+ endDate,
17
+ granularity
18
+ });
19
+ const resourceHealth = data?.resources?.[0];
20
+ const chartData = useMemo(() => {
21
+ if (!resourceHealth?.trendData) return [];
22
+ return resourceHealth.trendData.map((point) => ({
23
+ time: point.time,
24
+ Success: (point.success || 0) - (point.warning || 0),
25
+ Warning: point.warning || 0,
26
+ Failed: point.failure || 0
27
+ }));
28
+ }, [resourceHealth?.trendData]);
29
+ const xTickFormatter = useMemo(() => (value) => formatBucketTime(value, granularity), [granularity]);
30
+ if (isLoading) {
31
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) });
32
+ }
33
+ const summary = resourceHealth?.summary;
34
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
35
+ /* @__PURE__ */ jsx(
36
+ CardHeader,
37
+ {
38
+ icon: /* @__PURE__ */ jsx(IconActivity, { size: 18 }),
39
+ title: "Execution Health",
40
+ subtitle: `${summary?.total || 0} executions, ${summary?.successRate?.toFixed(1) || 0}% success rate`
41
+ }
42
+ ),
43
+ chartData.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { icon: IconChartBar, title: "No execution data for this time range" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
44
+ /* @__PURE__ */ jsxs(Group, { gap: "lg", justify: "center", mb: "xs", h: 24, align: "center", children: [
45
+ /* @__PURE__ */ jsx(CyberLegendItem, { color: colors.green, label: "Success" }),
46
+ /* @__PURE__ */ jsx(CyberLegendItem, { color: colors.yellow, label: "Warning" }),
47
+ /* @__PURE__ */ jsx(CyberLegendItem, { color: colors.red, label: "Failed" })
48
+ ] }),
49
+ /* @__PURE__ */ jsx(
50
+ CyberAreaChart,
51
+ {
52
+ data: chartData,
53
+ series: [
54
+ { dataKey: "Success", color: "green", name: "Success" },
55
+ { dataKey: "Warning", color: "yellow", name: "Warning" },
56
+ { dataKey: "Failed", color: "red", name: "Failed" }
57
+ ],
58
+ height: 200,
59
+ yDomain: [0, "auto"],
60
+ xTickFormatter
61
+ }
62
+ )
63
+ ] })
64
+ ] });
65
+ }
66
+
67
+ export { ResourceHealthPanel };
@@ -0,0 +1,589 @@
1
+ import { OrganizationContext, useOrganization } from './chunk-DD3CCMCZ.js';
2
+ import { useProfile, useUserProfile } from './chunk-RT4KRGZT.js';
3
+ import { brandSupabaseOrgId, brandWorkOsOrgId } from './chunk-MQZE7SUI.js';
4
+ import { useAuthContext } from './chunk-BRJ3QZ4E.js';
5
+ import { useState, useRef, useEffect, useCallback, createElement } from 'react';
6
+ import { useQueryClient } from '@tanstack/react-query';
7
+ import { Badge, Group, Button, Loader, Menu, Text } from '@mantine/core';
8
+ import { IconLock, IconChevronDown, IconBuilding, IconCheck } from '@tabler/icons-react';
9
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
+ import { useAuth } from '@workos-inc/authkit-react';
11
+
12
+ // src/organization/context/invalidate-org-scoped.ts
13
+ function invalidateOrgScopedQueries(queryClient, orgIds) {
14
+ const ids = new Set(orgIds.filter((id) => !!id));
15
+ if (ids.size === 0) return;
16
+ void queryClient.invalidateQueries({
17
+ predicate: (query) => queryKeyReferencesOrg(query.queryKey, ids)
18
+ });
19
+ }
20
+ function queryKeyReferencesOrg(queryKey, orgIds) {
21
+ return queryKey.some((segment) => segmentReferencesOrg(segment, orgIds));
22
+ }
23
+ function segmentReferencesOrg(segment, orgIds) {
24
+ if (typeof segment === "string") return orgIds.has(segment);
25
+ if (Array.isArray(segment)) return segment.some((value) => typeof value === "string" && orgIds.has(value));
26
+ if (segment && typeof segment === "object") {
27
+ return Object.values(segment).some((value) => typeof value === "string" && orgIds.has(value));
28
+ }
29
+ return false;
30
+ }
31
+
32
+ // src/organization/context/OrganizationProvider.tsx
33
+ function OrganizationProvider({ apiRequest, children }) {
34
+ const { user, organizationId: workosOrgId } = useAuthContext();
35
+ const { profile, error: profileError } = useProfile();
36
+ const queryClient = useQueryClient();
37
+ const [memberships, setMemberships] = useState([]);
38
+ const [currentWorkOSOrganizationId, setCurrentWorkOSOrganizationId] = useState(null);
39
+ const [currentSupabaseOrganizationId, setCurrentSupabaseOrganizationId] = useState(null);
40
+ const [currentMembership, setCurrentMembership] = useState(null);
41
+ const [isInitializing, setIsInitializing] = useState(true);
42
+ const [isOrgRefreshing, setIsOrgRefreshing] = useState(false);
43
+ const [error, setError] = useState(null);
44
+ const hasInitializedRef = useRef(false);
45
+ const [profileLoaded, setProfileLoaded] = useState(false);
46
+ useEffect(() => {
47
+ if (profile !== void 0 && profile !== null) {
48
+ setProfileLoaded(true);
49
+ }
50
+ }, [profile]);
51
+ useEffect(() => {
52
+ if (profileError && isInitializing && !hasInitializedRef.current) {
53
+ setIsInitializing(false);
54
+ }
55
+ }, [profileError, isInitializing]);
56
+ useEffect(() => {
57
+ if (!user) {
58
+ setMemberships([]);
59
+ setCurrentWorkOSOrganizationId(null);
60
+ setCurrentSupabaseOrganizationId(null);
61
+ setCurrentMembership(null);
62
+ setIsInitializing(false);
63
+ setIsOrgRefreshing(false);
64
+ setError(null);
65
+ hasInitializedRef.current = false;
66
+ setProfileLoaded(false);
67
+ }
68
+ }, [user]);
69
+ const applyMembership = useCallback((membership) => {
70
+ setCurrentMembership(membership);
71
+ setCurrentSupabaseOrganizationId(brandSupabaseOrgId(membership?.organization?.id));
72
+ setCurrentWorkOSOrganizationId(brandWorkOsOrgId(membership?.organization?.workos_org_id));
73
+ }, []);
74
+ const selectOrganization = useCallback(
75
+ (data) => {
76
+ let selected = null;
77
+ if (workosOrgId) {
78
+ selected = data.find((m) => m.organization?.workos_org_id === workosOrgId) ?? null;
79
+ }
80
+ if (!selected && profile?.last_visited_org) {
81
+ selected = data.find((m) => m.organizationId === profile.last_visited_org) ?? null;
82
+ }
83
+ if (!selected && data.length > 0) {
84
+ selected = data[0];
85
+ }
86
+ if (selected) {
87
+ applyMembership(selected);
88
+ }
89
+ },
90
+ [profile?.last_visited_org, workosOrgId, applyMembership]
91
+ );
92
+ const fetchAndInitialize = useCallback(async () => {
93
+ if (!user?.id || !profileLoaded) return;
94
+ setError(null);
95
+ if (memberships.length === 0) {
96
+ setIsInitializing(true);
97
+ } else {
98
+ setIsOrgRefreshing(true);
99
+ }
100
+ try {
101
+ const data = await apiRequest("/memberships/my-memberships");
102
+ if (!Array.isArray(data)) {
103
+ throw new Error("Invalid memberships response");
104
+ }
105
+ setMemberships(data);
106
+ if (data.length === 0) {
107
+ hasInitializedRef.current = true;
108
+ return;
109
+ }
110
+ if (!currentWorkOSOrganizationId) {
111
+ selectOrganization(data);
112
+ } else {
113
+ const stillPresent = data.find((m) => m.organization?.workos_org_id === currentWorkOSOrganizationId);
114
+ if (!stillPresent) {
115
+ applyMembership(data[0] ?? null);
116
+ } else {
117
+ applyMembership(stillPresent);
118
+ }
119
+ }
120
+ hasInitializedRef.current = true;
121
+ } catch (err) {
122
+ setError(err instanceof Error ? err.message : "Failed to load organizations");
123
+ } finally {
124
+ setIsInitializing(false);
125
+ setIsOrgRefreshing(false);
126
+ }
127
+ }, [
128
+ user?.id,
129
+ profileLoaded,
130
+ memberships.length,
131
+ apiRequest,
132
+ currentWorkOSOrganizationId,
133
+ selectOrganization,
134
+ applyMembership
135
+ ]);
136
+ useEffect(() => {
137
+ if (!user?.id || !profileLoaded || hasInitializedRef.current) return;
138
+ fetchAndInitialize();
139
+ }, [user?.id, profileLoaded, fetchAndInitialize]);
140
+ useEffect(() => {
141
+ if (!hasInitializedRef.current) return;
142
+ if (!workosOrgId) return;
143
+ if (workosOrgId === currentWorkOSOrganizationId) return;
144
+ const target = memberships.find((m) => m.organization?.workos_org_id === workosOrgId);
145
+ if (!target) return;
146
+ const previousWorkOSOrgId = currentWorkOSOrganizationId;
147
+ const previousSupabaseOrgId = currentSupabaseOrganizationId;
148
+ applyMembership(target);
149
+ invalidateOrgScopedQueries(queryClient, [
150
+ previousWorkOSOrgId,
151
+ previousSupabaseOrgId,
152
+ target.organization?.workos_org_id,
153
+ target.organizationId
154
+ ]);
155
+ }, [
156
+ workosOrgId,
157
+ currentWorkOSOrganizationId,
158
+ currentSupabaseOrganizationId,
159
+ memberships,
160
+ applyMembership,
161
+ queryClient
162
+ ]);
163
+ const switchOrganization = useCallback(
164
+ (workosOrgId2, options) => {
165
+ const target = memberships.find((m) => m.organization?.workos_org_id === workosOrgId2);
166
+ if (!target) return;
167
+ const previousWorkOSOrgId = currentWorkOSOrganizationId;
168
+ const previousSupabaseOrgId = currentSupabaseOrganizationId;
169
+ applyMembership(target);
170
+ invalidateOrgScopedQueries(queryClient, [
171
+ previousWorkOSOrgId,
172
+ previousSupabaseOrgId,
173
+ target.organization?.workos_org_id,
174
+ target.organizationId
175
+ ]);
176
+ if (options?.persist !== false) {
177
+ void apiRequest("/users/me", {
178
+ method: "PATCH",
179
+ headers: { "Content-Type": "application/json" },
180
+ body: JSON.stringify({ lastVisitedOrg: target.organizationId })
181
+ }).catch((err) => {
182
+ console.warn("Failed to persist last_visited_org preference:", err);
183
+ });
184
+ }
185
+ },
186
+ [memberships, applyMembership, queryClient, apiRequest, currentWorkOSOrganizationId, currentSupabaseOrganizationId]
187
+ );
188
+ const retry = useCallback(async () => {
189
+ hasInitializedRef.current = false;
190
+ setError(null);
191
+ await fetchAndInitialize();
192
+ }, [fetchAndInitialize]);
193
+ const value = {
194
+ currentWorkOSOrganizationId,
195
+ currentSupabaseOrganizationId,
196
+ currentMembership,
197
+ memberships,
198
+ isInitializing,
199
+ isOrgRefreshing,
200
+ error,
201
+ switchOrganization,
202
+ retry
203
+ };
204
+ return createElement(OrganizationContext.Provider, { value }, children);
205
+ }
206
+ function RoleBadge({ name, isSystem }) {
207
+ return /* @__PURE__ */ jsx(Badge, { color: isSystem ? "gray" : "primary", variant: "light", children: /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
208
+ isSystem && /* @__PURE__ */ jsx(IconLock, { size: 10 }),
209
+ name
210
+ ] }) });
211
+ }
212
+ function OrganizationSwitcher({
213
+ currentOrganization,
214
+ memberships,
215
+ isLoading,
216
+ onSwitch
217
+ }) {
218
+ const [opened, setOpened] = useState(false);
219
+ const [switching, setSwitching] = useState(false);
220
+ const otherMemberships = memberships.filter((m) => m.organizationId !== currentOrganization?.id);
221
+ const handleSwitch = async (workosOrgId) => {
222
+ setSwitching(true);
223
+ try {
224
+ await onSwitch(workosOrgId);
225
+ setOpened(false);
226
+ } catch (error) {
227
+ console.error("Failed to switch organization:", error);
228
+ } finally {
229
+ setSwitching(false);
230
+ }
231
+ };
232
+ if (isLoading) {
233
+ return /* @__PURE__ */ jsx(Button, { variant: "light", size: "xs", disabled: true, children: /* @__PURE__ */ jsx(Loader, { size: 14 }) });
234
+ }
235
+ if (memberships.length === 0) {
236
+ return /* @__PURE__ */ jsx(Button, { variant: "light", size: "xs", disabled: true, children: "None" });
237
+ }
238
+ return /* @__PURE__ */ jsxs(Menu, { opened, onChange: setOpened, position: "bottom-start", withinPortal: true, children: [
239
+ /* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(
240
+ Button,
241
+ {
242
+ variant: "light",
243
+ size: "xs",
244
+ leftSection: /* @__PURE__ */ jsx(IconBuilding, { size: 16 }),
245
+ rightSection: /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }),
246
+ loading: switching,
247
+ children: /* @__PURE__ */ jsx(Text, { truncate: true, style: { maxWidth: 200 }, size: "xs", children: currentOrganization?.name || "Select Organization" })
248
+ }
249
+ ) }),
250
+ /* @__PURE__ */ jsxs(
251
+ Menu.Dropdown,
252
+ {
253
+ style: {
254
+ background: "var(--glass-background)",
255
+ backdropFilter: "var(--glass-blur)",
256
+ WebkitBackdropFilter: "var(--glass-blur)"
257
+ },
258
+ children: [
259
+ currentOrganization && /* @__PURE__ */ jsxs(Fragment, { children: [
260
+ /* @__PURE__ */ jsx(Menu.Label, { children: "Current Organization" }),
261
+ /* @__PURE__ */ jsx(Menu.Item, { disabled: true, rightSection: /* @__PURE__ */ jsx(IconCheck, { size: 14 }), leftSection: /* @__PURE__ */ jsx(IconBuilding, { size: 14 }), children: currentOrganization.name }),
262
+ otherMemberships.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
263
+ /* @__PURE__ */ jsx(Menu.Divider, {}),
264
+ /* @__PURE__ */ jsx(Menu.Label, { children: "Switch Organization" })
265
+ ] })
266
+ ] }),
267
+ otherMemberships.length > 0 && /* @__PURE__ */ jsx("div", { children: otherMemberships.map((membership, index) => /* @__PURE__ */ jsx(
268
+ Menu.Item,
269
+ {
270
+ leftSection: /* @__PURE__ */ jsx(IconBuilding, { size: 14 }),
271
+ rightSection: /* @__PURE__ */ jsx(
272
+ RoleBadge,
273
+ {
274
+ slug: membership.role.slug,
275
+ name: membership.role.slug.charAt(0).toUpperCase() + membership.role.slug.slice(1),
276
+ isSystem: true
277
+ }
278
+ ),
279
+ onClick: () => {
280
+ const workosOrgId = membership.organization?.workos_org_id;
281
+ if (!workosOrgId) {
282
+ console.error("Organization missing WorkOS ID:", membership.organization?.name);
283
+ return;
284
+ }
285
+ handleSwitch(workosOrgId);
286
+ },
287
+ disabled: switching,
288
+ children: membership.organization?.name || "Unknown Organization"
289
+ },
290
+ `${membership.organizationId}-${index}`
291
+ )) }, "other-memberships"),
292
+ !currentOrganization && memberships.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
293
+ /* @__PURE__ */ jsx(Menu.Label, { children: "Select Organization" }),
294
+ memberships.map((membership) => /* @__PURE__ */ jsx(
295
+ Menu.Item,
296
+ {
297
+ leftSection: /* @__PURE__ */ jsx(IconBuilding, { size: 14 }),
298
+ rightSection: /* @__PURE__ */ jsx(
299
+ RoleBadge,
300
+ {
301
+ slug: membership.role.slug,
302
+ name: membership.role.slug.charAt(0).toUpperCase() + membership.role.slug.slice(1),
303
+ isSystem: true
304
+ }
305
+ ),
306
+ onClick: () => {
307
+ const workosOrgId = membership.organization?.workos_org_id;
308
+ if (!workosOrgId) {
309
+ console.error("Organization missing WorkOS ID:", membership.organization?.name);
310
+ return;
311
+ }
312
+ handleSwitch(workosOrgId);
313
+ },
314
+ disabled: switching,
315
+ children: membership.organization?.name || "Unknown Organization"
316
+ },
317
+ membership.organizationId
318
+ ))
319
+ ] })
320
+ ]
321
+ }
322
+ )
323
+ ] });
324
+ }
325
+ function OrganizationSwitcherConnected({
326
+ isLoading: extraLoading = false,
327
+ onSwitched
328
+ } = {}) {
329
+ const { switchToOrganization } = useAuth();
330
+ const { currentMembership, memberships, isInitializing, isOrgRefreshing, switchOrganization } = useOrganization();
331
+ return /* @__PURE__ */ jsx(
332
+ OrganizationSwitcher,
333
+ {
334
+ currentOrganization: currentMembership?.organization,
335
+ memberships,
336
+ isLoading: extraLoading || isInitializing || isOrgRefreshing,
337
+ onSwitch: async (workosOrgId) => {
338
+ await switchToOrganization({ organizationId: workosOrgId });
339
+ switchOrganization(workosOrgId);
340
+ onSwitched?.(workosOrgId);
341
+ }
342
+ }
343
+ );
344
+ }
345
+
346
+ // src/organization/store/organizationsSlice.ts
347
+ var initialOrganizationsState = {
348
+ currentWorkOSOrganizationId: null,
349
+ currentSupabaseOrganizationId: null,
350
+ currentMembership: null,
351
+ isInitializing: true,
352
+ // Start as initializing
353
+ isOrgRefreshing: false,
354
+ error: null
355
+ };
356
+ var createOrganizationsSlice = (set, _get, _store) => ({
357
+ // Organizations state
358
+ organizations: initialOrganizationsState,
359
+ // Organization actions
360
+ setCurrentWorkOSOrganizationId: (workOSorgId) => {
361
+ set(
362
+ (state) => {
363
+ state.organizations.currentWorkOSOrganizationId = workOSorgId;
364
+ },
365
+ void 0,
366
+ "organizations/setCurrentWorkOSOrganizationId"
367
+ );
368
+ },
369
+ setCurrentMembership: (membership) => {
370
+ set(
371
+ (state) => {
372
+ state.organizations.currentMembership = membership;
373
+ state.organizations.currentSupabaseOrganizationId = brandSupabaseOrgId(membership?.organization?.id ?? null);
374
+ },
375
+ void 0,
376
+ "organizations/setCurrentMembership"
377
+ );
378
+ },
379
+ setOrganizationsInitializing: (initializing) => set(
380
+ (state) => {
381
+ state.organizations.isInitializing = initializing;
382
+ },
383
+ void 0,
384
+ "organizations/setInitializing"
385
+ ),
386
+ setOrganizationsLoading: (loading) => set(
387
+ (state) => {
388
+ state.organizations.isOrgRefreshing = loading;
389
+ },
390
+ void 0,
391
+ "organizations/setLoading"
392
+ ),
393
+ setOrganizationsError: (error) => set(
394
+ (state) => {
395
+ state.organizations.error = error;
396
+ },
397
+ void 0,
398
+ "organizations/setError"
399
+ )
400
+ });
401
+
402
+ // src/organization/hooks/useOrganizations.ts
403
+ function createUseOrganizations(useStore) {
404
+ return () => {
405
+ const organizations = useStore((state) => state.organizations);
406
+ const setCurrentWorkOSOrganizationId = useStore((state) => state.setCurrentWorkOSOrganizationId);
407
+ const setCurrentMembership = useStore((state) => state.setCurrentMembership);
408
+ const setOrganizationsInitializing = useStore((state) => state.setOrganizationsInitializing);
409
+ const setOrganizationsLoading = useStore((state) => state.setOrganizationsLoading);
410
+ const setOrganizationsError = useStore((state) => state.setOrganizationsError);
411
+ return {
412
+ ...organizations,
413
+ setCurrentWorkOSOrganizationId,
414
+ setCurrentMembership,
415
+ setOrganizationsInitializing,
416
+ setOrganizationsLoading,
417
+ setOrganizationsError,
418
+ organizations
419
+ // Also return the full organizations object for easy access
420
+ };
421
+ };
422
+ }
423
+ function createUseOrgInitialization(useOrganizations, useApiClient) {
424
+ return function useOrgInitialization() {
425
+ const { user, organizationId: workosOrgId } = useAuthContext();
426
+ const { apiRequest } = useApiClient();
427
+ const { profile } = useUserProfile();
428
+ const {
429
+ currentWorkOSOrganizationId,
430
+ currentMembership,
431
+ setCurrentWorkOSOrganizationId,
432
+ setCurrentMembership,
433
+ setOrganizationsInitializing,
434
+ setOrganizationsLoading,
435
+ setOrganizationsError,
436
+ organizations
437
+ } = useOrganizations();
438
+ const [memberships, setMemberships] = useState([]);
439
+ const [profileLoaded, setProfileLoaded] = useState(false);
440
+ const hasInitializedRef = useRef(false);
441
+ const currentMembershipIdRef = useRef(null);
442
+ currentMembershipIdRef.current = currentMembership?.id ?? null;
443
+ useEffect(() => {
444
+ if (profile !== void 0 && profile !== null) {
445
+ setProfileLoaded(true);
446
+ }
447
+ }, [profile]);
448
+ const selectOrganization = useCallback(
449
+ async (data) => {
450
+ let selectedMembership = null;
451
+ if (workosOrgId) {
452
+ selectedMembership = data.find((m) => m.organization?.workos_org_id === workosOrgId) || null;
453
+ }
454
+ if (!selectedMembership && profile?.last_visited_org) {
455
+ const supabaseLastVisitedOrgId = profile.last_visited_org;
456
+ selectedMembership = data.find((m) => m.organizationId === supabaseLastVisitedOrgId) || null;
457
+ }
458
+ if (!selectedMembership && data.length > 0) {
459
+ selectedMembership = data[0];
460
+ }
461
+ if (selectedMembership) {
462
+ const workosSelectedOrgId = selectedMembership.organization?.workos_org_id;
463
+ if (workosSelectedOrgId) {
464
+ setCurrentWorkOSOrganizationId(brandWorkOsOrgId(workosSelectedOrgId));
465
+ setCurrentMembership(selectedMembership);
466
+ }
467
+ }
468
+ },
469
+ [profile?.last_visited_org, workosOrgId, setCurrentWorkOSOrganizationId, setCurrentMembership]
470
+ );
471
+ const validateCurrentOrganization = useCallback(
472
+ (data) => {
473
+ const workosCurrentOrgId = currentWorkOSOrganizationId;
474
+ const currentOrg = data.find((m) => m.organization?.workos_org_id === workosCurrentOrgId);
475
+ if (!currentOrg) {
476
+ setCurrentWorkOSOrganizationId(null);
477
+ setCurrentMembership(null);
478
+ if (data.length > 0) {
479
+ const fallbackOrg = data[0];
480
+ const workosFallbackOrgId = fallbackOrg.organization?.workos_org_id;
481
+ if (workosFallbackOrgId) {
482
+ setCurrentWorkOSOrganizationId(brandWorkOsOrgId(workosFallbackOrgId));
483
+ setCurrentMembership(fallbackOrg);
484
+ }
485
+ }
486
+ } else {
487
+ if (currentOrg.id !== currentMembershipIdRef.current) {
488
+ setCurrentMembership(currentOrg);
489
+ }
490
+ }
491
+ },
492
+ [currentWorkOSOrganizationId, setCurrentWorkOSOrganizationId, setCurrentMembership]
493
+ );
494
+ useEffect(() => {
495
+ const initializeOrganizations = async () => {
496
+ if (!user?.id || !profileLoaded) {
497
+ return;
498
+ }
499
+ if (hasInitializedRef.current) {
500
+ return;
501
+ }
502
+ if (memberships.length === 0) {
503
+ setOrganizationsInitializing(true);
504
+ } else {
505
+ setOrganizationsLoading(true);
506
+ }
507
+ setOrganizationsError(null);
508
+ try {
509
+ const data = await apiRequest("/memberships/my-memberships");
510
+ if (!Array.isArray(data)) {
511
+ throw new Error("Invalid memberships response");
512
+ }
513
+ setMemberships(data);
514
+ if (data.length === 0) {
515
+ setOrganizationsError(
516
+ "No organization memberships found. Please contact your administrator or try refreshing the page."
517
+ );
518
+ hasInitializedRef.current = true;
519
+ return;
520
+ }
521
+ if (!currentWorkOSOrganizationId && data.length > 0) {
522
+ await selectOrganization(data);
523
+ } else if (currentWorkOSOrganizationId) {
524
+ validateCurrentOrganization(data);
525
+ }
526
+ hasInitializedRef.current = true;
527
+ } catch (error) {
528
+ setOrganizationsError(error instanceof Error ? error.message : "Failed to load organizations");
529
+ } finally {
530
+ setOrganizationsInitializing(false);
531
+ setOrganizationsLoading(false);
532
+ }
533
+ };
534
+ initializeOrganizations();
535
+ }, [
536
+ user?.id,
537
+ profileLoaded,
538
+ profile?.last_visited_org,
539
+ currentWorkOSOrganizationId,
540
+ apiRequest,
541
+ setOrganizationsInitializing,
542
+ setOrganizationsLoading,
543
+ setOrganizationsError,
544
+ selectOrganization,
545
+ validateCurrentOrganization
546
+ // REMOVED: memberships.length - causes feedback loop (memberships change as RESULT of effect, not INPUT)
547
+ ]);
548
+ const retryInitialization = useCallback(async () => {
549
+ hasInitializedRef.current = false;
550
+ setOrganizationsError(null);
551
+ setOrganizationsInitializing(true);
552
+ try {
553
+ const data = await apiRequest("/memberships/my-memberships");
554
+ if (!Array.isArray(data)) {
555
+ throw new Error("Invalid memberships response");
556
+ }
557
+ setMemberships(data);
558
+ if (!currentWorkOSOrganizationId && data.length > 0) {
559
+ await selectOrganization(data);
560
+ } else if (currentWorkOSOrganizationId) {
561
+ validateCurrentOrganization(data);
562
+ }
563
+ hasInitializedRef.current = true;
564
+ } catch (error) {
565
+ setOrganizationsError(error instanceof Error ? error.message : "Failed to load organizations");
566
+ } finally {
567
+ setOrganizationsInitializing(false);
568
+ }
569
+ }, [
570
+ apiRequest,
571
+ currentWorkOSOrganizationId,
572
+ setOrganizationsError,
573
+ setOrganizationsInitializing,
574
+ selectOrganization,
575
+ validateCurrentOrganization
576
+ ]);
577
+ return {
578
+ memberships,
579
+ isInitializing: organizations.isInitializing,
580
+ isLoading: organizations.isOrgRefreshing,
581
+ isInitialized: hasInitializedRef.current && !organizations.isInitializing && !organizations.isOrgRefreshing,
582
+ error: organizations.error,
583
+ currentOrganization: currentMembership?.organization || null,
584
+ retry: retryInitialization
585
+ };
586
+ };
587
+ }
588
+
589
+ export { OrganizationProvider, OrganizationSwitcher, OrganizationSwitcherConnected, RoleBadge, createOrganizationsSlice, createUseOrgInitialization, createUseOrganizations, invalidateOrgScopedQueries };