@famgia/omnify-react-sso 2.2.2 → 2.2.4

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 (55) hide show
  1. package/dist/ant/index.cjs +3235 -0
  2. package/dist/ant/index.cjs.map +1 -0
  3. package/dist/ant/index.d.cts +685 -0
  4. package/dist/ant/index.d.ts +685 -0
  5. package/dist/ant/index.js +3268 -0
  6. package/dist/ant/index.js.map +1 -0
  7. package/dist/core/index.cjs +2432 -0
  8. package/dist/core/index.cjs.map +1 -0
  9. package/dist/core/index.d.cts +112 -0
  10. package/dist/core/index.d.ts +112 -0
  11. package/dist/core/index.js +2360 -0
  12. package/dist/core/index.js.map +1 -0
  13. package/dist/{testing → core/testing}/index.cjs +1 -1
  14. package/dist/core/testing/index.cjs.map +1 -0
  15. package/dist/{testing → core/testing}/index.d.cts +1 -1
  16. package/dist/{testing → core/testing}/index.d.ts +1 -1
  17. package/dist/{testing → core/testing}/index.js +1 -1
  18. package/dist/core/testing/index.js.map +1 -0
  19. package/dist/index-CHuDTvHg.d.ts +2250 -0
  20. package/dist/index-DVssHZFD.d.cts +2250 -0
  21. package/dist/index.cjs +2514 -234
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +10 -1451
  24. package/dist/index.d.ts +10 -1451
  25. package/dist/index.js +2578 -234
  26. package/dist/index.js.map +1 -1
  27. package/dist/{types-CJmA2a9r.d.ts → types-BxClyvTX.d.cts} +2 -3
  28. package/dist/{types-CJmA2a9r.d.cts → types-BxClyvTX.d.ts} +2 -3
  29. package/dist/userService-DH9-vPSg.d.cts +269 -0
  30. package/dist/userService-DH9-vPSg.d.ts +269 -0
  31. package/package.json +102 -110
  32. package/dist/@omnify-base/package.json +0 -16
  33. package/dist/@omnify-base/schemas/Branch.ts +0 -131
  34. package/dist/@omnify-base/schemas/BranchCache.ts +0 -131
  35. package/dist/@omnify-base/schemas/OrganizationCache.ts +0 -117
  36. package/dist/@omnify-base/schemas/Permission.ts +0 -114
  37. package/dist/@omnify-base/schemas/Role.ts +0 -121
  38. package/dist/@omnify-base/schemas/RolePermission.ts +0 -97
  39. package/dist/@omnify-base/schemas/Team.ts +0 -110
  40. package/dist/@omnify-base/schemas/TeamCache.ts +0 -110
  41. package/dist/@omnify-base/schemas/TeamPermission.ts +0 -109
  42. package/dist/@omnify-base/schemas/User.ts +0 -135
  43. package/dist/@omnify-base/schemas/UserCache.ts +0 -135
  44. package/dist/@omnify-base/schemas/common.ts +0 -47
  45. package/dist/@omnify-base/schemas/i18n.ts +0 -118
  46. package/dist/schemas/index.cjs +0 -635
  47. package/dist/schemas/index.cjs.map +0 -1
  48. package/dist/schemas/index.d.cts +0 -254
  49. package/dist/schemas/index.d.ts +0 -254
  50. package/dist/schemas/index.js +0 -547
  51. package/dist/schemas/index.js.map +0 -1
  52. package/dist/testing/index.cjs.map +0 -1
  53. package/dist/testing/index.js.map +0 -1
  54. package/scripts/build-schemas.ts +0 -191
  55. package/scripts/postinstall.cjs +0 -43
@@ -0,0 +1,3235 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/ant/index.ts
31
+ var ant_exports = {};
32
+ __export(ant_exports, {
33
+ AntdThemeProvider: () => AntdThemeProvider,
34
+ BranchGate: () => BranchGate,
35
+ LocaleSwitcher: () => LocaleSwitcher,
36
+ OrgBranchSelectorModal: () => OrgBranchSelectorModal,
37
+ OrganizationSwitcher: () => OrganizationSwitcher,
38
+ PROTABLE_DEFAULT_TEXTS: () => DEFAULT_TEXTS,
39
+ PageContainer: () => PageContainer,
40
+ PermissionsListCard: () => PermissionsListCard,
41
+ ProTable: () => ProTable,
42
+ ProtectedRoute: () => ProtectedRoute,
43
+ RoleCreateModal: () => RoleCreateModal,
44
+ RolesListCard: () => RolesListCard,
45
+ ScopeLabel: () => ScopeLabel,
46
+ ScopeTag: () => ScopeTag,
47
+ SsoCallback: () => SsoCallback,
48
+ TeamsListCard: () => TeamsListCard,
49
+ UserDetailCard: () => UserDetailCard,
50
+ UserPermissionsModal: () => UserPermissionsModal,
51
+ UserRoleAssignModal: () => UserRoleAssignModal,
52
+ getScopeColor: () => getScopeColor,
53
+ getScopeIcon: () => getScopeIcon,
54
+ useBranchGate: () => useBranchGate
55
+ });
56
+ module.exports = __toCommonJS(ant_exports);
57
+
58
+ // src/ant/components/SsoCallback/SsoCallback.tsx
59
+ var import_react2 = require("react");
60
+
61
+ // src/core/context/SsoContext.tsx
62
+ var import_react = require("react");
63
+ var SsoContext = (0, import_react.createContext)(null);
64
+ function useSsoContext() {
65
+ const context = (0, import_react.useContext)(SsoContext);
66
+ if (!context) {
67
+ throw new Error("useSsoContext must be used within a SsoProvider");
68
+ }
69
+ return context;
70
+ }
71
+
72
+ // src/ant/components/SsoCallback/SsoCallback.tsx
73
+ var import_jsx_runtime = require("react/jsx-runtime");
74
+ function transformUser(data) {
75
+ return {
76
+ id: data.id,
77
+ consoleUserId: data.console_user_id,
78
+ email: data.email,
79
+ name: data.name
80
+ };
81
+ }
82
+ function transformOrganizations(data) {
83
+ return data.map((org) => ({
84
+ id: org.organization_id,
85
+ slug: org.organization_slug,
86
+ name: org.organization_name,
87
+ orgRole: org.org_role,
88
+ serviceRole: org.service_role
89
+ }));
90
+ }
91
+ function DefaultLoading() {
92
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
93
+ display: "flex",
94
+ justifyContent: "center",
95
+ alignItems: "center",
96
+ minHeight: "200px"
97
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: "Authenticating..." }) });
98
+ }
99
+ function DefaultError({ error }) {
100
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
101
+ display: "flex",
102
+ flexDirection: "column",
103
+ justifyContent: "center",
104
+ alignItems: "center",
105
+ minHeight: "200px",
106
+ color: "red"
107
+ }, children: [
108
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: "Authentication Error" }),
109
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: "0.875rem", marginTop: "0.5rem" }, children: error.message })
110
+ ] });
111
+ }
112
+ function SsoCallback({
113
+ onSuccess,
114
+ onError,
115
+ redirectTo = "/",
116
+ loadingComponent,
117
+ errorComponent
118
+ }) {
119
+ const { config, refreshUser } = useSsoContext();
120
+ const [error, setError] = (0, import_react2.useState)(null);
121
+ const [isProcessing, setIsProcessing] = (0, import_react2.useState)(true);
122
+ const isProcessingRef = (0, import_react2.useRef)(false);
123
+ (0, import_react2.useEffect)(() => {
124
+ if (isProcessingRef.current) {
125
+ return;
126
+ }
127
+ isProcessingRef.current = true;
128
+ const processCallback = async () => {
129
+ try {
130
+ const urlParams = new URLSearchParams(window.location.search);
131
+ const code = urlParams.get("code");
132
+ const redirectParam = urlParams.get("redirect");
133
+ if (!code) {
134
+ throw new Error("No authorization code received");
135
+ }
136
+ await fetch(`${config.apiUrl}/sanctum/csrf-cookie`, {
137
+ credentials: "include"
138
+ });
139
+ const xsrfToken = document.cookie.split("; ").find((row) => row.startsWith("XSRF-TOKEN="))?.split("=")[1];
140
+ const response = await fetch(`${config.apiUrl}/api/sso/callback`, {
141
+ method: "POST",
142
+ headers: {
143
+ "Content-Type": "application/json",
144
+ "Accept": "application/json",
145
+ ...xsrfToken ? { "X-XSRF-TOKEN": decodeURIComponent(xsrfToken) } : {}
146
+ },
147
+ credentials: "include",
148
+ body: JSON.stringify({ code })
149
+ });
150
+ if (!response.ok) {
151
+ const errorData = await response.json().catch(() => ({}));
152
+ throw new Error(errorData.message || "Failed to authenticate");
153
+ }
154
+ const data = await response.json();
155
+ const user = transformUser(data.user);
156
+ const organizations = transformOrganizations(data.organizations);
157
+ await refreshUser();
158
+ onSuccess?.(user, organizations);
159
+ const finalRedirect = redirectParam || redirectTo;
160
+ window.location.href = finalRedirect;
161
+ } catch (err) {
162
+ const error2 = err instanceof Error ? err : new Error("Authentication failed");
163
+ setError(error2);
164
+ onError?.(error2);
165
+ isProcessingRef.current = false;
166
+ } finally {
167
+ setIsProcessing(false);
168
+ }
169
+ };
170
+ processCallback();
171
+ }, []);
172
+ if (error) {
173
+ if (errorComponent) {
174
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: errorComponent(error) });
175
+ }
176
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultError, { error });
177
+ }
178
+ if (isProcessing) {
179
+ if (loadingComponent) {
180
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: loadingComponent });
181
+ }
182
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultLoading, {});
183
+ }
184
+ return null;
185
+ }
186
+
187
+ // src/ant/components/OrganizationSwitcher/OrganizationSwitcher.tsx
188
+ var import_react4 = __toESM(require("react"), 1);
189
+ var import_antd = require("antd");
190
+ var import_icons = require("@ant-design/icons");
191
+
192
+ // src/core/hooks/useOrganization.ts
193
+ var import_react3 = require("react");
194
+ var ROLE_LEVELS = {
195
+ admin: 100,
196
+ manager: 50,
197
+ member: 10
198
+ };
199
+ function useOrganization() {
200
+ const { organizations, currentOrg, switchOrg } = useSsoContext();
201
+ const hasMultipleOrgs = organizations.length > 1;
202
+ const currentRole = currentOrg?.serviceRole ?? null;
203
+ const hasRole = (0, import_react3.useCallback)(
204
+ (role) => {
205
+ if (!currentRole) return false;
206
+ const requiredLevel = ROLE_LEVELS[role] ?? 0;
207
+ const userLevel = ROLE_LEVELS[currentRole] ?? 0;
208
+ return userLevel >= requiredLevel;
209
+ },
210
+ [currentRole]
211
+ );
212
+ const handleSwitchOrg = (0, import_react3.useCallback)(
213
+ (orgId) => {
214
+ switchOrg(orgId);
215
+ },
216
+ [switchOrg]
217
+ );
218
+ return (0, import_react3.useMemo)(
219
+ () => ({
220
+ organizations,
221
+ currentOrg,
222
+ hasMultipleOrgs,
223
+ switchOrg: handleSwitchOrg,
224
+ currentRole,
225
+ hasRole
226
+ }),
227
+ [organizations, currentOrg, hasMultipleOrgs, handleSwitchOrg, currentRole, hasRole]
228
+ );
229
+ }
230
+
231
+ // src/ant/components/OrganizationSwitcher/OrganizationSwitcher.tsx
232
+ var import_jsx_runtime2 = require("react/jsx-runtime");
233
+ var { Text } = import_antd.Typography;
234
+ function OrganizationSwitcher({
235
+ className,
236
+ renderTrigger,
237
+ renderOption,
238
+ onChange
239
+ }) {
240
+ const { organizations, currentOrg, hasMultipleOrgs, switchOrg } = useOrganization();
241
+ const [isOpen, setIsOpen] = import_react4.default.useState(false);
242
+ const handleSelect = (0, import_react4.useCallback)(
243
+ (org) => {
244
+ switchOrg(org.slug);
245
+ setIsOpen(false);
246
+ onChange?.(org);
247
+ },
248
+ [switchOrg, onChange]
249
+ );
250
+ const menuItems = (0, import_react4.useMemo)(() => {
251
+ return organizations.map((org) => {
252
+ const isSelected = currentOrg?.slug === org.slug;
253
+ if (renderOption) {
254
+ return {
255
+ key: org.slug,
256
+ label: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { onClick: () => handleSelect(org), children: renderOption(org, isSelected) })
257
+ };
258
+ }
259
+ return {
260
+ key: org.slug,
261
+ label: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_antd.Space, { style: { width: "100%", justifyContent: "space-between" }, children: [
262
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_antd.Space, { direction: "vertical", size: 0, children: [
263
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { strong: isSelected, children: org.name }),
264
+ org.serviceRole && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { type: "secondary", style: { fontSize: 12 }, children: org.serviceRole })
265
+ ] }),
266
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.CheckOutlined, { style: { color: "#1890ff" } })
267
+ ] }),
268
+ onClick: () => handleSelect(org)
269
+ };
270
+ });
271
+ }, [organizations, currentOrg, renderOption, handleSelect]);
272
+ if (!hasMultipleOrgs) {
273
+ return null;
274
+ }
275
+ if (renderTrigger) {
276
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
277
+ import_antd.Dropdown,
278
+ {
279
+ menu: { items: menuItems },
280
+ trigger: ["click"],
281
+ open: isOpen,
282
+ onOpenChange: setIsOpen,
283
+ className,
284
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { cursor: "pointer" }, children: renderTrigger(currentOrg, isOpen) })
285
+ }
286
+ );
287
+ }
288
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
289
+ import_antd.Dropdown,
290
+ {
291
+ menu: { items: menuItems },
292
+ trigger: ["click"],
293
+ open: isOpen,
294
+ onOpenChange: setIsOpen,
295
+ className,
296
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_antd.Button, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_antd.Space, { children: [
297
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_antd.Badge, { status: "success" }),
298
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: currentOrg?.name ?? "Select Organization" }),
299
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.SwapOutlined, {})
300
+ ] }) })
301
+ }
302
+ );
303
+ }
304
+
305
+ // src/ant/components/ProtectedRoute/ProtectedRoute.tsx
306
+ var import_react6 = require("react");
307
+
308
+ // src/core/hooks/useAuth.ts
309
+ var import_react5 = require("react");
310
+ function useAuth() {
311
+ const { user, isLoading, isAuthenticated, login, logout, globalLogout, refreshUser } = useSsoContext();
312
+ const handleLogin = (0, import_react5.useCallback)(
313
+ (redirectTo) => {
314
+ login(redirectTo);
315
+ },
316
+ [login]
317
+ );
318
+ const handleLogout = (0, import_react5.useCallback)(async () => {
319
+ await logout();
320
+ }, [logout]);
321
+ const handleGlobalLogout = (0, import_react5.useCallback)(
322
+ (redirectTo) => {
323
+ globalLogout(redirectTo);
324
+ },
325
+ [globalLogout]
326
+ );
327
+ return {
328
+ user,
329
+ isLoading,
330
+ isAuthenticated,
331
+ login: handleLogin,
332
+ logout: handleLogout,
333
+ globalLogout: handleGlobalLogout,
334
+ refreshUser
335
+ };
336
+ }
337
+
338
+ // src/ant/components/ProtectedRoute/ProtectedRoute.tsx
339
+ var import_jsx_runtime3 = require("react/jsx-runtime");
340
+ function DefaultLoading2() {
341
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: {
342
+ display: "flex",
343
+ justifyContent: "center",
344
+ alignItems: "center",
345
+ minHeight: "200px"
346
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: "Loading..." }) });
347
+ }
348
+ function DefaultLoginFallback({ login }) {
349
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: {
350
+ display: "flex",
351
+ flexDirection: "column",
352
+ justifyContent: "center",
353
+ alignItems: "center",
354
+ minHeight: "200px",
355
+ gap: "1rem"
356
+ }, children: [
357
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: "Please log in to continue" }),
358
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
359
+ "button",
360
+ {
361
+ onClick: login,
362
+ style: {
363
+ padding: "0.5rem 1rem",
364
+ background: "#0070f3",
365
+ color: "white",
366
+ border: "none",
367
+ borderRadius: "0.375rem",
368
+ cursor: "pointer"
369
+ },
370
+ children: "Log In"
371
+ }
372
+ )
373
+ ] });
374
+ }
375
+ function DefaultAccessDenied({ reason }) {
376
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: {
377
+ display: "flex",
378
+ flexDirection: "column",
379
+ justifyContent: "center",
380
+ alignItems: "center",
381
+ minHeight: "200px",
382
+ color: "#dc2626"
383
+ }, children: [
384
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontSize: "1.5rem", fontWeight: 600 }, children: "Access Denied" }),
385
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { marginTop: "0.5rem" }, children: reason })
386
+ ] });
387
+ }
388
+ function ProtectedRoute({
389
+ children,
390
+ fallback,
391
+ loginFallback,
392
+ requiredRole,
393
+ requiredPermission,
394
+ onAccessDenied
395
+ }) {
396
+ const { user, isLoading, isAuthenticated, login } = useAuth();
397
+ const { hasRole, currentOrg } = useOrganization();
398
+ (0, import_react6.useEffect)(() => {
399
+ if (isLoading) return;
400
+ if (!isAuthenticated) {
401
+ onAccessDenied?.("unauthenticated");
402
+ } else if (requiredRole && !hasRole(requiredRole)) {
403
+ onAccessDenied?.("insufficient_role");
404
+ }
405
+ }, [isLoading, isAuthenticated, requiredRole, hasRole, onAccessDenied]);
406
+ if (isLoading) {
407
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: fallback ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultLoading2, {}) });
408
+ }
409
+ if (!isAuthenticated) {
410
+ if (loginFallback) {
411
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: loginFallback });
412
+ }
413
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultLoginFallback, { login: () => login() });
414
+ }
415
+ if (requiredRole && !hasRole(requiredRole)) {
416
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
417
+ DefaultAccessDenied,
418
+ {
419
+ reason: `This page requires ${requiredRole} role. Your role: ${currentOrg?.serviceRole ?? "none"}`
420
+ }
421
+ );
422
+ }
423
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children });
424
+ }
425
+
426
+ // src/ant/components/OrgBranchSelectorModal/OrgBranchSelectorModal.tsx
427
+ var import_react7 = require("react");
428
+ var import_antd2 = require("antd");
429
+ var import_icons2 = require("@ant-design/icons");
430
+ var import_react_query = require("@tanstack/react-query");
431
+
432
+ // src/core/services/utils.ts
433
+ function getXsrfToken() {
434
+ if (typeof document === "undefined") return void 0;
435
+ return document.cookie.split("; ").find((row) => row.startsWith("XSRF-TOKEN="))?.split("=")[1];
436
+ }
437
+ function buildHeaders(orgId) {
438
+ const headers = {
439
+ "Content-Type": "application/json",
440
+ Accept: "application/json"
441
+ };
442
+ const xsrfToken = getXsrfToken();
443
+ if (xsrfToken) {
444
+ headers["X-XSRF-TOKEN"] = decodeURIComponent(xsrfToken);
445
+ }
446
+ if (orgId) {
447
+ headers["X-Organization-Id"] = orgId;
448
+ }
449
+ return headers;
450
+ }
451
+ async function request(apiUrl, path, options = {}) {
452
+ const response = await fetch(`${apiUrl}${path}`, {
453
+ ...options,
454
+ credentials: "include"
455
+ });
456
+ if (!response.ok) {
457
+ const error = await response.json().catch(() => ({}));
458
+ throw new Error(error.message || `HTTP ${response.status}`);
459
+ }
460
+ if (response.status === 204) {
461
+ return void 0;
462
+ }
463
+ return response.json();
464
+ }
465
+
466
+ // src/core/services/branchService.ts
467
+ function createBranchService(config) {
468
+ const { apiUrl } = config;
469
+ return {
470
+ /**
471
+ * Get branches for current user in organization
472
+ * GET /api/sso/branches
473
+ * @param orgId - Organization ID or slug (sent via X-Organization-Id header)
474
+ */
475
+ list: async (orgId) => {
476
+ return request(apiUrl, `/api/sso/branches`, {
477
+ headers: buildHeaders(orgId)
478
+ });
479
+ },
480
+ /**
481
+ * Get a specific branch by ID
482
+ * GET /api/sso/branches/{id}
483
+ */
484
+ get: async (branchId) => {
485
+ const response = await request(
486
+ apiUrl,
487
+ `/api/sso/branches/${branchId}`,
488
+ { headers: buildHeaders() }
489
+ );
490
+ return "data" in response ? response.data : response;
491
+ },
492
+ /**
493
+ * Get headquarters branch for organization
494
+ * @param orgId - Organization ID or slug (sent via X-Organization-Id header)
495
+ */
496
+ getHeadquarters: async (orgId) => {
497
+ try {
498
+ const data = await request(
499
+ apiUrl,
500
+ `/api/sso/branches`,
501
+ { headers: buildHeaders(orgId) }
502
+ );
503
+ return data.branches.find((b) => b.is_headquarters) ?? null;
504
+ } catch {
505
+ return null;
506
+ }
507
+ },
508
+ /**
509
+ * Get primary branch for current user
510
+ * @param orgId - Organization ID or slug (sent via X-Organization-Id header)
511
+ */
512
+ getPrimary: async (orgId) => {
513
+ try {
514
+ const data = await request(
515
+ apiUrl,
516
+ `/api/sso/branches`,
517
+ { headers: buildHeaders(orgId) }
518
+ );
519
+ if (data.primary_branch_id) {
520
+ return data.branches.find((b) => b.id === data.primary_branch_id) ?? null;
521
+ }
522
+ return null;
523
+ } catch {
524
+ return null;
525
+ }
526
+ }
527
+ };
528
+ }
529
+
530
+ // src/core/queryKeys.ts
531
+ var ssoQueryKeys = {
532
+ all: ["sso"],
533
+ // =========================================================================
534
+ // Auth (authService)
535
+ // =========================================================================
536
+ auth: {
537
+ all: () => [...ssoQueryKeys.all, "auth"],
538
+ user: () => [...ssoQueryKeys.auth.all(), "user"],
539
+ globalLogoutUrl: (redirectUri) => [...ssoQueryKeys.auth.all(), "global-logout-url", redirectUri]
540
+ },
541
+ // =========================================================================
542
+ // Tokens (tokenService)
543
+ // =========================================================================
544
+ tokens: {
545
+ all: () => [...ssoQueryKeys.all, "tokens"],
546
+ list: () => [...ssoQueryKeys.tokens.all(), "list"]
547
+ },
548
+ // =========================================================================
549
+ // Roles (roleService)
550
+ // =========================================================================
551
+ roles: {
552
+ all: () => [...ssoQueryKeys.all, "roles"],
553
+ list: () => [...ssoQueryKeys.roles.all(), "list"],
554
+ detail: (id) => [...ssoQueryKeys.roles.all(), "detail", id],
555
+ permissions: (id) => [...ssoQueryKeys.roles.all(), id, "permissions"]
556
+ },
557
+ // =========================================================================
558
+ // Permissions (permissionService)
559
+ // =========================================================================
560
+ permissions: {
561
+ all: () => [...ssoQueryKeys.all, "permissions"],
562
+ list: (params) => [...ssoQueryKeys.permissions.all(), "list", params],
563
+ detail: (id) => [...ssoQueryKeys.permissions.all(), "detail", id],
564
+ matrix: () => [...ssoQueryKeys.permissions.all(), "matrix"]
565
+ },
566
+ // =========================================================================
567
+ // Teams (teamService)
568
+ // =========================================================================
569
+ teams: {
570
+ all: () => [...ssoQueryKeys.all, "teams"],
571
+ list: () => [...ssoQueryKeys.teams.all(), "list"],
572
+ permissions: (teamId) => [...ssoQueryKeys.teams.all(), teamId, "permissions"],
573
+ orphaned: () => [...ssoQueryKeys.teams.all(), "orphaned"]
574
+ },
575
+ // =========================================================================
576
+ // User Roles (userRoleService) - Scoped Role Assignments
577
+ // =========================================================================
578
+ userRoles: {
579
+ all: () => [...ssoQueryKeys.all, "user-roles"],
580
+ list: (userId) => [...ssoQueryKeys.userRoles.all(), userId],
581
+ byBranch: (userId, orgId, branchId) => [...ssoQueryKeys.userRoles.all(), userId, orgId, branchId]
582
+ },
583
+ // =========================================================================
584
+ // Branches (branchService)
585
+ // =========================================================================
586
+ branches: {
587
+ all: () => [...ssoQueryKeys.all, "branches"],
588
+ list: (orgId) => [...ssoQueryKeys.branches.all(), "list", orgId],
589
+ detail: (branchId) => [...ssoQueryKeys.branches.all(), "detail", branchId],
590
+ headquarters: (orgId) => [...ssoQueryKeys.branches.all(), "headquarters", orgId],
591
+ primary: (orgId) => [...ssoQueryKeys.branches.all(), "primary", orgId]
592
+ },
593
+ // =========================================================================
594
+ // Admin variants (with org context)
595
+ // =========================================================================
596
+ admin: {
597
+ roles: {
598
+ all: (orgId) => [...ssoQueryKeys.all, "admin", orgId, "roles"],
599
+ list: (orgId) => [...ssoQueryKeys.admin.roles.all(orgId), "list"],
600
+ detail: (orgId, id) => [...ssoQueryKeys.admin.roles.all(orgId), "detail", id],
601
+ permissions: (orgId, id) => [...ssoQueryKeys.admin.roles.all(orgId), id, "permissions"]
602
+ },
603
+ permissions: {
604
+ all: (orgId) => [...ssoQueryKeys.all, "admin", orgId, "permissions"],
605
+ list: (orgId, params) => [...ssoQueryKeys.admin.permissions.all(orgId), "list", params],
606
+ detail: (orgId, id) => [...ssoQueryKeys.admin.permissions.all(orgId), "detail", id],
607
+ matrix: (orgId) => [...ssoQueryKeys.admin.permissions.all(orgId), "matrix"]
608
+ },
609
+ teams: {
610
+ all: (orgId) => [...ssoQueryKeys.all, "admin", orgId, "teams"],
611
+ list: (orgId) => [...ssoQueryKeys.admin.teams.all(orgId), "list"],
612
+ permissions: (orgId, teamId) => [...ssoQueryKeys.admin.teams.all(orgId), teamId, "permissions"],
613
+ orphaned: (orgId) => [...ssoQueryKeys.admin.teams.all(orgId), "orphaned"]
614
+ },
615
+ userRoles: {
616
+ all: (orgId) => [...ssoQueryKeys.all, "admin", orgId, "user-roles"],
617
+ list: (orgId, userId) => [...ssoQueryKeys.admin.userRoles.all(orgId), userId],
618
+ byBranch: (orgId, userId, consoleOrgId, branchId) => [...ssoQueryKeys.admin.userRoles.all(orgId), userId, consoleOrgId, branchId]
619
+ },
620
+ users: {
621
+ all: (orgId) => [...ssoQueryKeys.all, "admin", orgId, "users"],
622
+ list: (orgId, params) => [...ssoQueryKeys.admin.users.all(orgId), "list", params],
623
+ detail: (orgId, id) => [...ssoQueryKeys.admin.users.all(orgId), "detail", id],
624
+ permissions: (orgId, userId, consoleOrgId, branchId) => [...ssoQueryKeys.admin.users.all(orgId), userId, "permissions", consoleOrgId, branchId]
625
+ }
626
+ }
627
+ };
628
+
629
+ // src/ant/components/OrgBranchSelectorModal/OrgBranchSelectorModal.tsx
630
+ var import_jsx_runtime4 = require("react/jsx-runtime");
631
+ var { Text: Text2, Title } = import_antd2.Typography;
632
+ function OrgBranchSelectorModal({
633
+ open,
634
+ onClose,
635
+ onConfirm,
636
+ title = "Select Organization & Branch",
637
+ requireBranch = true,
638
+ loadingComponent
639
+ }) {
640
+ const { config } = useSsoContext();
641
+ const { organizations, currentOrg, hasMultipleOrgs } = useOrganization();
642
+ const [form] = import_antd2.Form.useForm();
643
+ const [selectedOrgSlug, setSelectedOrgSlug] = (0, import_react7.useState)(
644
+ currentOrg?.slug ?? null
645
+ );
646
+ const branchService = (0, import_react7.useMemo)(
647
+ () => createBranchService({ apiUrl: config.apiUrl }),
648
+ [config.apiUrl]
649
+ );
650
+ const {
651
+ data: branchesData,
652
+ isLoading: branchesLoading,
653
+ error: branchesError
654
+ } = (0, import_react_query.useQuery)({
655
+ queryKey: ssoQueryKeys.branches.list(selectedOrgSlug ?? void 0),
656
+ queryFn: () => branchService.list(selectedOrgSlug ?? void 0),
657
+ enabled: open && !!selectedOrgSlug
658
+ });
659
+ const branches = branchesData?.branches ?? [];
660
+ const hasMultipleBranches = branches.length > 1;
661
+ const selectedOrg = (0, import_react7.useMemo)(
662
+ () => organizations.find((o) => o.slug === selectedOrgSlug) ?? null,
663
+ [organizations, selectedOrgSlug]
664
+ );
665
+ (0, import_react7.useEffect)(() => {
666
+ if (!open) return;
667
+ if (organizations.length === 1 && !selectedOrgSlug) {
668
+ setSelectedOrgSlug(organizations[0].slug);
669
+ form.setFieldValue("organization_id", organizations[0].id);
670
+ } else if (currentOrg && !selectedOrgSlug) {
671
+ setSelectedOrgSlug(currentOrg.slug);
672
+ form.setFieldValue("organization_id", currentOrg.id);
673
+ }
674
+ }, [open, organizations, currentOrg, selectedOrgSlug, form]);
675
+ (0, import_react7.useEffect)(() => {
676
+ if (!open || branchesLoading) return;
677
+ if (branches.length === 1) {
678
+ form.setFieldValue("branch_id", branches[0].id);
679
+ } else if (branches.length > 0) {
680
+ const primaryId = branchesData?.primary_branch_id;
681
+ if (primaryId) {
682
+ form.setFieldValue("branch_id", primaryId);
683
+ } else {
684
+ const hq = branches.find((b) => b.is_headquarters);
685
+ if (hq) {
686
+ form.setFieldValue("branch_id", hq.id);
687
+ }
688
+ }
689
+ }
690
+ }, [open, branches, branchesLoading, branchesData, form]);
691
+ (0, import_react7.useEffect)(() => {
692
+ if (!open || branchesLoading) return;
693
+ const orgId = form.getFieldValue("organization_id");
694
+ const branchId = form.getFieldValue("branch_id");
695
+ if (orgId && branchId && !hasMultipleOrgs && !hasMultipleBranches) {
696
+ const timer = setTimeout(() => {
697
+ onConfirm(orgId, branchId);
698
+ }, 100);
699
+ return () => clearTimeout(timer);
700
+ }
701
+ }, [open, branchesLoading, hasMultipleOrgs, hasMultipleBranches, form, onConfirm]);
702
+ const handleOrgChange = (0, import_react7.useCallback)((orgId) => {
703
+ const org = organizations.find((o) => o.id === orgId);
704
+ if (org) {
705
+ setSelectedOrgSlug(org.slug);
706
+ form.setFieldValue("branch_id", void 0);
707
+ }
708
+ }, [organizations, form]);
709
+ const handleSubmit = (0, import_react7.useCallback)(() => {
710
+ form.validateFields().then((values) => {
711
+ onConfirm(values.organization_id, values.branch_id);
712
+ });
713
+ }, [form, onConfirm]);
714
+ const handleClose = (0, import_react7.useCallback)(() => {
715
+ form.resetFields();
716
+ setSelectedOrgSlug(currentOrg?.slug ?? null);
717
+ onClose();
718
+ }, [form, currentOrg, onClose]);
719
+ const isInitialLoading = open && (!organizations.length || selectedOrgSlug && branchesLoading && !branches.length);
720
+ const needsSelection = hasMultipleOrgs || hasMultipleBranches;
721
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
722
+ import_antd2.Modal,
723
+ {
724
+ title: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_antd2.Space, { children: [
725
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.BankOutlined, {}),
726
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: title })
727
+ ] }),
728
+ open,
729
+ onCancel: handleClose,
730
+ onOk: handleSubmit,
731
+ okText: "Confirm",
732
+ cancelText: "Cancel",
733
+ destroyOnHidden: true,
734
+ width: 480,
735
+ children: isInitialLoading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { textAlign: "center", padding: 40 }, children: [
736
+ loadingComponent ?? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_antd2.Spin, { size: "large" }),
737
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text2, { type: "secondary", children: "Loading..." }) })
738
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
739
+ import_antd2.Form,
740
+ {
741
+ form,
742
+ layout: "vertical",
743
+ style: { marginTop: 16 },
744
+ children: [
745
+ branchesError && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
746
+ import_antd2.Alert,
747
+ {
748
+ type: "error",
749
+ message: "Failed to load branches",
750
+ description: branchesError.message,
751
+ style: { marginBottom: 16 }
752
+ }
753
+ ),
754
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
755
+ import_antd2.Form.Item,
756
+ {
757
+ name: "organization_id",
758
+ label: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_antd2.Space, { children: [
759
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.BankOutlined, {}),
760
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Organization" }),
761
+ !hasMultipleOrgs && selectedOrg && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_antd2.Badge, { status: "success", text: "Auto-selected" })
762
+ ] }),
763
+ rules: [{ required: true, message: "Please select an organization" }],
764
+ children: hasMultipleOrgs ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
765
+ import_antd2.Select,
766
+ {
767
+ placeholder: "Select organization",
768
+ onChange: handleOrgChange,
769
+ size: "large",
770
+ optionLabelProp: "label",
771
+ children: organizations.map((org) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
772
+ import_antd2.Select.Option,
773
+ {
774
+ value: org.id,
775
+ label: org.name,
776
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_antd2.Space, { style: { width: "100%", justifyContent: "space-between" }, children: [
777
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
778
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text2, { strong: true, children: org.name }),
779
+ org.serviceRole && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text2, { type: "secondary", style: { marginLeft: 8, fontSize: 12 }, children: [
780
+ "(",
781
+ org.serviceRole,
782
+ ")"
783
+ ] })
784
+ ] }),
785
+ org.slug === currentOrg?.slug && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.CheckCircleFilled, { style: { color: "#52c41a" } })
786
+ ] })
787
+ },
788
+ org.id
789
+ ))
790
+ }
791
+ ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
792
+ "div",
793
+ {
794
+ style: {
795
+ padding: "8px 12px",
796
+ background: "#f5f5f5",
797
+ borderRadius: 6,
798
+ border: "1px solid #d9d9d9"
799
+ },
800
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_antd2.Space, { children: [
801
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.BankOutlined, { style: { color: "#1677ff" } }),
802
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text2, { strong: true, children: selectedOrg?.name })
803
+ ] })
804
+ }
805
+ )
806
+ }
807
+ ),
808
+ selectedOrgSlug && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
809
+ import_antd2.Form.Item,
810
+ {
811
+ name: "branch_id",
812
+ label: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_antd2.Space, { children: [
813
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.ApartmentOutlined, {}),
814
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Branch" }),
815
+ !hasMultipleBranches && branches.length === 1 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_antd2.Badge, { status: "success", text: "Auto-selected" })
816
+ ] }),
817
+ rules: requireBranch ? [{ required: true, message: "Please select a branch" }] : void 0,
818
+ children: branchesLoading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { padding: "8px 12px", textAlign: "center" }, children: [
819
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_antd2.Spin, { size: "small" }),
820
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text2, { type: "secondary", style: { marginLeft: 8 }, children: "Loading branches..." })
821
+ ] }) : hasMultipleBranches ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
822
+ import_antd2.Select,
823
+ {
824
+ placeholder: "Select branch",
825
+ size: "large",
826
+ optionLabelProp: "label",
827
+ children: branches.map((branch) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
828
+ import_antd2.Select.Option,
829
+ {
830
+ value: branch.id,
831
+ label: branch.name,
832
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_antd2.Space, { style: { width: "100%", justifyContent: "space-between" }, children: [
833
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
834
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text2, { strong: true, children: branch.name }),
835
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text2, { type: "secondary", style: { marginLeft: 8, fontSize: 12 }, children: branch.code })
836
+ ] }),
837
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_antd2.Space, { size: 4, children: [
838
+ branch.is_headquarters && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_antd2.Badge, { color: "blue", text: "HQ" }),
839
+ branch.is_primary && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_antd2.Badge, { color: "green", text: "Primary" })
840
+ ] })
841
+ ] })
842
+ },
843
+ branch.id
844
+ ))
845
+ }
846
+ ) : branches.length === 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
847
+ "div",
848
+ {
849
+ style: {
850
+ padding: "8px 12px",
851
+ background: "#f5f5f5",
852
+ borderRadius: 6,
853
+ border: "1px solid #d9d9d9"
854
+ },
855
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_antd2.Space, { children: [
856
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.ApartmentOutlined, { style: { color: "#1677ff" } }),
857
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text2, { strong: true, children: branches[0].name }),
858
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text2, { type: "secondary", children: [
859
+ "(",
860
+ branches[0].code,
861
+ ")"
862
+ ] })
863
+ ] })
864
+ }
865
+ ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
866
+ import_antd2.Alert,
867
+ {
868
+ type: "warning",
869
+ message: "No branches available",
870
+ description: "You don't have access to any branches in this organization."
871
+ }
872
+ )
873
+ }
874
+ ),
875
+ !needsSelection && selectedOrg && branches.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
876
+ import_antd2.Alert,
877
+ {
878
+ type: "info",
879
+ message: "Auto-selected",
880
+ description: `Using ${selectedOrg.name} / ${branches[0]?.name ?? "Default"}`,
881
+ icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.CheckCircleFilled, {}),
882
+ showIcon: true
883
+ }
884
+ )
885
+ ]
886
+ }
887
+ )
888
+ }
889
+ );
890
+ }
891
+
892
+ // src/ant/components/BranchGate/BranchGate.tsx
893
+ var import_react8 = __toESM(require("react"), 1);
894
+ var import_antd3 = require("antd");
895
+ var import_icons3 = require("@ant-design/icons");
896
+ var import_react_query2 = require("@tanstack/react-query");
897
+ var import_jsx_runtime5 = require("react/jsx-runtime");
898
+ var { Text: Text3, Title: Title2 } = import_antd3.Typography;
899
+ var DEFAULT_STORAGE_KEY = "omnify_branch_gate_selection";
900
+ function BranchGate({
901
+ children,
902
+ onSelectionChange,
903
+ storageKey = DEFAULT_STORAGE_KEY,
904
+ loadingComponent,
905
+ title,
906
+ description
907
+ }) {
908
+ const { config, isAuthenticated } = useSsoContext();
909
+ const { organizations, currentOrg, hasMultipleOrgs } = useOrganization();
910
+ const [storedSelection, setStoredSelection] = (0, import_react8.useState)(null);
911
+ const [isInitialized, setIsInitialized] = (0, import_react8.useState)(false);
912
+ const [tempOrgId, setTempOrgId] = (0, import_react8.useState)(null);
913
+ const [tempBranchId, setTempBranchId] = (0, import_react8.useState)(null);
914
+ const branchService = import_react8.default.useMemo(
915
+ () => createBranchService({ apiUrl: config.apiUrl }),
916
+ [config.apiUrl]
917
+ );
918
+ const activeOrgSlug = import_react8.default.useMemo(() => {
919
+ if (tempOrgId) {
920
+ return organizations.find((o) => String(o.id) === tempOrgId)?.slug;
921
+ }
922
+ return storedSelection?.orgId ?? currentOrg?.slug;
923
+ }, [tempOrgId, organizations, storedSelection, currentOrg]);
924
+ const { data: branchesData, isLoading: branchesLoading } = (0, import_react_query2.useQuery)({
925
+ queryKey: ssoQueryKeys.branches.list(activeOrgSlug),
926
+ queryFn: () => branchService.list(activeOrgSlug),
927
+ enabled: isAuthenticated && !!activeOrgSlug
928
+ });
929
+ const branches = branchesData?.branches ?? [];
930
+ const hasMultipleBranches = branches.length > 1;
931
+ (0, import_react8.useEffect)(() => {
932
+ if (typeof window === "undefined") return;
933
+ const saved = localStorage.getItem(storageKey);
934
+ if (saved) {
935
+ try {
936
+ const parsed = JSON.parse(saved);
937
+ setStoredSelection(parsed);
938
+ onSelectionChange?.(parsed);
939
+ } catch {
940
+ localStorage.removeItem(storageKey);
941
+ }
942
+ }
943
+ setIsInitialized(true);
944
+ }, [storageKey, onSelectionChange]);
945
+ (0, import_react8.useEffect)(() => {
946
+ if (!isAuthenticated || !isInitialized || storedSelection) return;
947
+ if (organizations.length === 1 && !tempOrgId) {
948
+ setTempOrgId(String(organizations[0].id));
949
+ }
950
+ }, [isAuthenticated, isInitialized, organizations, storedSelection, tempOrgId]);
951
+ (0, import_react8.useEffect)(() => {
952
+ if (!tempOrgId || branchesLoading || storedSelection) return;
953
+ if (branches.length === 1 && !tempBranchId) {
954
+ setTempBranchId(String(branches[0].id));
955
+ } else if (branches.length > 0 && !tempBranchId) {
956
+ const primaryId = branchesData?.primary_branch_id;
957
+ if (primaryId) {
958
+ setTempBranchId(String(primaryId));
959
+ } else {
960
+ const hq = branches.find((b) => b.is_headquarters);
961
+ if (hq) {
962
+ setTempBranchId(String(hq.id));
963
+ }
964
+ }
965
+ }
966
+ }, [tempOrgId, branches, branchesLoading, branchesData, storedSelection, tempBranchId]);
967
+ (0, import_react8.useEffect)(() => {
968
+ if (storedSelection || !isInitialized) return;
969
+ if (!tempOrgId || !tempBranchId || branchesLoading) return;
970
+ if (!hasMultipleOrgs && !hasMultipleBranches) {
971
+ confirmSelection();
972
+ }
973
+ }, [tempOrgId, tempBranchId, branchesLoading, hasMultipleOrgs, hasMultipleBranches, storedSelection, isInitialized]);
974
+ const confirmSelection = import_react8.default.useCallback(() => {
975
+ if (!tempOrgId || !tempBranchId) return;
976
+ const org = organizations.find((o) => String(o.id) === tempOrgId);
977
+ const branch = branches.find((b) => String(b.id) === tempBranchId);
978
+ if (!org || !branch) return;
979
+ const selection = {
980
+ orgId: org.slug,
981
+ orgName: org.name,
982
+ branchId: String(branch.id),
983
+ branchName: branch.name,
984
+ branchCode: branch.code
985
+ };
986
+ localStorage.setItem(storageKey, JSON.stringify(selection));
987
+ setStoredSelection(selection);
988
+ onSelectionChange?.(selection);
989
+ setTempOrgId(null);
990
+ setTempBranchId(null);
991
+ }, [tempOrgId, tempBranchId, organizations, branches, storageKey, onSelectionChange]);
992
+ const clearSelection = import_react8.default.useCallback(() => {
993
+ localStorage.removeItem(storageKey);
994
+ setStoredSelection(null);
995
+ onSelectionChange?.(null);
996
+ }, [storageKey, onSelectionChange]);
997
+ const needsSelection = isAuthenticated && isInitialized && !storedSelection && (hasMultipleOrgs || hasMultipleBranches);
998
+ const isLoading = !isAuthenticated || !isInitialized || !!activeOrgSlug && branchesLoading && !storedSelection;
999
+ if (isLoading && !needsSelection) {
1000
+ if (loadingComponent) {
1001
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: loadingComponent });
1002
+ }
1003
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
1004
+ display: "flex",
1005
+ justifyContent: "center",
1006
+ alignItems: "center",
1007
+ minHeight: "100vh",
1008
+ background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)"
1009
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_antd3.Spin, { size: "large" }) });
1010
+ }
1011
+ if (needsSelection) {
1012
+ const canConfirm = tempOrgId && tempBranchId;
1013
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
1014
+ minHeight: "100vh",
1015
+ background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
1016
+ display: "flex",
1017
+ alignItems: "center",
1018
+ justifyContent: "center",
1019
+ padding: 24
1020
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: {
1021
+ background: "#fff",
1022
+ borderRadius: 16,
1023
+ padding: 32,
1024
+ maxWidth: 480,
1025
+ width: "100%",
1026
+ boxShadow: "0 20px 60px rgba(0,0,0,0.3)"
1027
+ }, children: [
1028
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { textAlign: "center", marginBottom: 24 }, children: [
1029
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
1030
+ width: 64,
1031
+ height: 64,
1032
+ borderRadius: "50%",
1033
+ background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
1034
+ display: "flex",
1035
+ alignItems: "center",
1036
+ justifyContent: "center",
1037
+ margin: "0 auto 16px"
1038
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons3.BankOutlined, { style: { fontSize: 28, color: "#fff" } }) }),
1039
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Title2, { level: 3, style: { margin: 0 }, children: title ?? "Select Organization" }),
1040
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text3, { type: "secondary", children: description ?? "Please select your organization and branch to continue" })
1041
+ ] }),
1042
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { marginBottom: 20 }, children: [
1043
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text3, { strong: true, style: { display: "block", marginBottom: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_antd3.Space, { children: [
1044
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons3.BankOutlined, {}),
1045
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Organization" }),
1046
+ !hasMultipleOrgs && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_antd3.Badge, { status: "success", text: "Auto-selected" })
1047
+ ] }) }),
1048
+ hasMultipleOrgs ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1049
+ import_antd3.Select,
1050
+ {
1051
+ value: tempOrgId,
1052
+ onChange: (value) => {
1053
+ setTempOrgId(String(value));
1054
+ setTempBranchId(null);
1055
+ },
1056
+ placeholder: "Select organization",
1057
+ size: "large",
1058
+ style: { width: "100%" },
1059
+ optionLabelProp: "label",
1060
+ children: organizations.map((org) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_antd3.Select.Option, { value: String(org.id), label: org.name, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_antd3.Space, { style: { width: "100%", justifyContent: "space-between" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
1061
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text3, { strong: true, children: org.name }),
1062
+ org.serviceRole && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text3, { type: "secondary", style: { marginLeft: 8, fontSize: 12 }, children: [
1063
+ "(",
1064
+ org.serviceRole,
1065
+ ")"
1066
+ ] })
1067
+ ] }) }) }, org.id))
1068
+ }
1069
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
1070
+ padding: "8px 12px",
1071
+ background: "#f5f5f5",
1072
+ borderRadius: 6,
1073
+ border: "1px solid #d9d9d9"
1074
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_antd3.Space, { children: [
1075
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons3.BankOutlined, { style: { color: "#1677ff" } }),
1076
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text3, { strong: true, children: organizations[0]?.name })
1077
+ ] }) })
1078
+ ] }),
1079
+ tempOrgId && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { marginBottom: 24 }, children: [
1080
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text3, { strong: true, style: { display: "block", marginBottom: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_antd3.Space, { children: [
1081
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons3.ApartmentOutlined, {}),
1082
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Branch" }),
1083
+ !hasMultipleBranches && branches.length === 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_antd3.Badge, { status: "success", text: "Auto-selected" })
1084
+ ] }) }),
1085
+ branchesLoading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { padding: "12px", textAlign: "center" }, children: [
1086
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_antd3.Spin, { size: "small" }),
1087
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text3, { type: "secondary", style: { marginLeft: 8 }, children: "Loading..." })
1088
+ ] }) : hasMultipleBranches ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1089
+ import_antd3.Select,
1090
+ {
1091
+ value: tempBranchId,
1092
+ onChange: (value) => setTempBranchId(String(value)),
1093
+ placeholder: "Select branch",
1094
+ size: "large",
1095
+ style: { width: "100%" },
1096
+ optionLabelProp: "label",
1097
+ children: branches.map((branch) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_antd3.Select.Option, { value: String(branch.id), label: branch.name, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_antd3.Space, { style: { width: "100%", justifyContent: "space-between" }, children: [
1098
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
1099
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text3, { strong: true, children: branch.name }),
1100
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text3, { type: "secondary", style: { marginLeft: 8, fontSize: 12 }, children: branch.code })
1101
+ ] }),
1102
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_antd3.Space, { size: 4, children: [
1103
+ branch.is_headquarters && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_antd3.Badge, { color: "blue", text: "HQ" }),
1104
+ branch.is_primary && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_antd3.Badge, { color: "green", text: "Primary" })
1105
+ ] })
1106
+ ] }) }, branch.id))
1107
+ }
1108
+ ) : branches.length === 1 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: {
1109
+ padding: "8px 12px",
1110
+ background: "#f5f5f5",
1111
+ borderRadius: 6,
1112
+ border: "1px solid #d9d9d9"
1113
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_antd3.Space, { children: [
1114
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons3.ApartmentOutlined, { style: { color: "#1677ff" } }),
1115
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text3, { strong: true, children: branches[0].name }),
1116
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text3, { type: "secondary", children: [
1117
+ "(",
1118
+ branches[0].code,
1119
+ ")"
1120
+ ] })
1121
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1122
+ import_antd3.Alert,
1123
+ {
1124
+ type: "warning",
1125
+ message: "No branches available",
1126
+ description: "You don't have access to any branches in this organization."
1127
+ }
1128
+ )
1129
+ ] }),
1130
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1131
+ import_antd3.Button,
1132
+ {
1133
+ type: "primary",
1134
+ size: "large",
1135
+ block: true,
1136
+ disabled: !canConfirm,
1137
+ onClick: confirmSelection,
1138
+ icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons3.CheckCircleFilled, {}),
1139
+ style: {
1140
+ height: 48,
1141
+ fontSize: 16,
1142
+ background: canConfirm ? "linear-gradient(135deg, #667eea 0%, #764ba2 100%)" : void 0,
1143
+ border: "none"
1144
+ },
1145
+ children: "Confirm"
1146
+ }
1147
+ )
1148
+ ] }) });
1149
+ }
1150
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
1151
+ }
1152
+ function useBranchGate(storageKey = DEFAULT_STORAGE_KEY) {
1153
+ const [selection, setSelection] = (0, import_react8.useState)(null);
1154
+ (0, import_react8.useEffect)(() => {
1155
+ if (typeof window === "undefined") return;
1156
+ const saved = localStorage.getItem(storageKey);
1157
+ if (saved) {
1158
+ try {
1159
+ setSelection(JSON.parse(saved));
1160
+ } catch {
1161
+ }
1162
+ }
1163
+ const handleStorage = (e) => {
1164
+ if (e.key === storageKey) {
1165
+ if (e.newValue) {
1166
+ try {
1167
+ setSelection(JSON.parse(e.newValue));
1168
+ } catch {
1169
+ setSelection(null);
1170
+ }
1171
+ } else {
1172
+ setSelection(null);
1173
+ }
1174
+ }
1175
+ };
1176
+ window.addEventListener("storage", handleStorage);
1177
+ return () => window.removeEventListener("storage", handleStorage);
1178
+ }, [storageKey]);
1179
+ const clearSelection = import_react8.default.useCallback(() => {
1180
+ localStorage.removeItem(storageKey);
1181
+ setSelection(null);
1182
+ }, [storageKey]);
1183
+ return {
1184
+ selection,
1185
+ selectedOrg: selection ? { id: selection.orgId, slug: selection.orgId, name: selection.orgName } : null,
1186
+ selectedBranch: selection ? { id: selection.branchId, name: selection.branchName, code: selection.branchCode } : null,
1187
+ clearSelection
1188
+ };
1189
+ }
1190
+
1191
+ // src/ant/components/ProTable/ProTable.tsx
1192
+ var import_icons4 = require("@ant-design/icons");
1193
+ var import_react_query3 = require("@tanstack/react-query");
1194
+ var import_antd4 = require("antd");
1195
+ var import_react9 = require("react");
1196
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1197
+ var { Link } = import_antd4.Typography;
1198
+ var { RangePicker } = import_antd4.DatePicker;
1199
+ var InertiaLink = null;
1200
+ try {
1201
+ InertiaLink = require("@inertiajs/react").Link;
1202
+ } catch {
1203
+ }
1204
+ var DEFAULT_TEXTS = {
1205
+ search: "\u691C\u7D22",
1206
+ reset: "\u30EA\u30BB\u30C3\u30C8",
1207
+ expand: "\u5C55\u958B",
1208
+ collapse: "\u53CE\u7D0D",
1209
+ add: "\u65B0\u898F",
1210
+ refresh: "\u66F4\u65B0",
1211
+ columnSettings: "\u5217\u8A2D\u5B9A",
1212
+ actions: "\u64CD\u4F5C",
1213
+ yes: "\u306F\u3044",
1214
+ no: "\u3044\u3044\u3048",
1215
+ cancel: "\u30AD\u30E3\u30F3\u30BB\u30EB",
1216
+ totalItems: (total) => `\u5168 ${total} \u4EF6`,
1217
+ selectPlaceholder: "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
1218
+ inputPlaceholder: "\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
1219
+ startDate: "\u958B\u59CB\u65E5",
1220
+ endDate: "\u7D42\u4E86\u65E5"
1221
+ };
1222
+ var DEFAULT_STATUS_CONFIG = {
1223
+ active: { color: "#52c41a", text: "\u6709\u52B9" },
1224
+ Active: { color: "#52c41a", text: "\u6709\u52B9" },
1225
+ inactive: { color: "#d9d9d9", text: "\u7121\u52B9" },
1226
+ Inactive: { color: "#d9d9d9", text: "\u7121\u52B9" },
1227
+ pending: { color: "#faad14", text: "\u4FDD\u7559\u4E2D" },
1228
+ Pending: { color: "#faad14", text: "\u4FDD\u7559\u4E2D" },
1229
+ error: { color: "#ff4d4f", text: "\u30A8\u30E9\u30FC" },
1230
+ Error: { color: "#ff4d4f", text: "\u30A8\u30E9\u30FC" },
1231
+ closed: { color: "#ff4d4f", text: "\u9589\u9396" },
1232
+ Closed: { color: "#ff4d4f", text: "\u9589\u9396" }
1233
+ };
1234
+ function renderSearchField(field, texts) {
1235
+ switch (field.type) {
1236
+ case "select":
1237
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1238
+ import_antd4.Select,
1239
+ {
1240
+ allowClear: true,
1241
+ placeholder: field.placeholder || texts.selectPlaceholder,
1242
+ options: field.options,
1243
+ style: { width: "100%" }
1244
+ }
1245
+ );
1246
+ case "date":
1247
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1248
+ import_antd4.DatePicker,
1249
+ {
1250
+ placeholder: field.placeholder,
1251
+ style: { width: "100%" }
1252
+ }
1253
+ );
1254
+ case "dateRange":
1255
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1256
+ RangePicker,
1257
+ {
1258
+ placeholder: [texts.startDate, texts.endDate],
1259
+ style: { width: "100%" }
1260
+ }
1261
+ );
1262
+ case "number":
1263
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1264
+ import_antd4.InputNumber,
1265
+ {
1266
+ placeholder: field.placeholder,
1267
+ style: { width: "100%" }
1268
+ }
1269
+ );
1270
+ default:
1271
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1272
+ import_antd4.Input,
1273
+ {
1274
+ allowClear: true,
1275
+ placeholder: field.placeholder || texts.inputPlaceholder
1276
+ }
1277
+ );
1278
+ }
1279
+ }
1280
+ function SmartLink({ href, children }) {
1281
+ if (InertiaLink) {
1282
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(InertiaLink, { href, children });
1283
+ }
1284
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href, children });
1285
+ }
1286
+ function renderValue(value, valueType, statusConfig) {
1287
+ if (value === null || value === void 0) {
1288
+ return "-";
1289
+ }
1290
+ switch (valueType) {
1291
+ case "status": {
1292
+ const config = { ...DEFAULT_STATUS_CONFIG, ...statusConfig };
1293
+ const statusValue = String(value);
1294
+ const status = config[statusValue] || { color: "#d9d9d9", text: statusValue };
1295
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_antd4.Space, { children: [
1296
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1297
+ "span",
1298
+ {
1299
+ style: {
1300
+ display: "inline-block",
1301
+ width: 6,
1302
+ height: 6,
1303
+ borderRadius: "50%",
1304
+ backgroundColor: status.color
1305
+ }
1306
+ }
1307
+ ),
1308
+ status.text
1309
+ ] });
1310
+ }
1311
+ case "date":
1312
+ return value ? new Date(String(value)).toLocaleDateString("ja-JP") : "-";
1313
+ case "datetime":
1314
+ return value ? new Date(String(value)).toLocaleString("ja-JP") : "-";
1315
+ case "number":
1316
+ return typeof value === "number" ? value.toLocaleString("ja-JP") : String(value);
1317
+ case "currency":
1318
+ return typeof value === "number" ? `\xA5${value.toLocaleString("ja-JP")}` : String(value);
1319
+ case "boolean":
1320
+ return value ? "\u306F\u3044" : "\u3044\u3044\u3048";
1321
+ default:
1322
+ return String(value);
1323
+ }
1324
+ }
1325
+ function ProTable({
1326
+ // Header
1327
+ title,
1328
+ icon,
1329
+ subTitle,
1330
+ // Search
1331
+ searchFields = [],
1332
+ defaultSearchValues = {},
1333
+ // Columns
1334
+ columns,
1335
+ // Data
1336
+ dataSource: externalDataSource,
1337
+ rowKey = "id",
1338
+ loading: externalLoading,
1339
+ // Query
1340
+ queryKey,
1341
+ queryFn,
1342
+ queryResult: externalQueryResult,
1343
+ queryEnabled = true,
1344
+ // Toolbar
1345
+ onAdd,
1346
+ addButtonLink,
1347
+ addLabel = "\u65B0\u898F",
1348
+ toolbarExtra,
1349
+ showRefresh = true,
1350
+ showColumnSettings = true,
1351
+ // Row actions
1352
+ rowActions,
1353
+ // Pagination
1354
+ pagination = true,
1355
+ defaultPageSize = 15,
1356
+ // Events
1357
+ onSearch,
1358
+ onReset,
1359
+ onChange,
1360
+ // Style
1361
+ className,
1362
+ style,
1363
+ cardStyle,
1364
+ tableProps,
1365
+ // i18n
1366
+ texts: customTexts
1367
+ }) {
1368
+ const { token } = import_antd4.theme.useToken();
1369
+ const texts = { ...DEFAULT_TEXTS, ...customTexts };
1370
+ const [searchForm] = import_antd4.Form.useForm();
1371
+ const [expanded, setExpanded] = (0, import_react9.useState)(false);
1372
+ const [queryParams, setQueryParams] = (0, import_react9.useState)({
1373
+ page: 1,
1374
+ per_page: defaultPageSize,
1375
+ ...defaultSearchValues
1376
+ });
1377
+ const visibleFields = searchFields.filter((f) => !f.hidden);
1378
+ const hiddenFields = searchFields.filter((f) => f.hidden);
1379
+ const hasHiddenFields = hiddenFields.length > 0;
1380
+ const internalQuery = (0, import_react_query3.useQuery)({
1381
+ queryKey: queryKey ? [...queryKey, queryParams] : ["proTable", queryParams],
1382
+ queryFn: () => queryFn(queryParams),
1383
+ enabled: !!queryFn && queryEnabled
1384
+ });
1385
+ const queryResult = externalQueryResult || internalQuery;
1386
+ const dataSource = externalDataSource || queryResult.data?.data || [];
1387
+ const loading = externalLoading ?? queryResult.isLoading;
1388
+ const meta = queryResult.data?.meta;
1389
+ const handleSearch = (0, import_react9.useCallback)((values) => {
1390
+ const newParams = {
1391
+ ...queryParams,
1392
+ ...values,
1393
+ page: 1
1394
+ };
1395
+ setQueryParams(newParams);
1396
+ onSearch?.(values);
1397
+ }, [queryParams, onSearch]);
1398
+ const handleReset = (0, import_react9.useCallback)(() => {
1399
+ searchForm.resetFields();
1400
+ const newParams = {
1401
+ page: 1,
1402
+ per_page: defaultPageSize
1403
+ };
1404
+ setQueryParams(newParams);
1405
+ onReset?.();
1406
+ }, [searchForm, defaultPageSize, onReset]);
1407
+ const handleTableChange = (0, import_react9.useCallback)(
1408
+ (pag, _filters, sorter, _extra) => {
1409
+ const sortInfo = Array.isArray(sorter) ? sorter[0] : sorter;
1410
+ const newParams = {
1411
+ ...queryParams,
1412
+ page: pag.current || 1,
1413
+ per_page: pag.pageSize || defaultPageSize
1414
+ };
1415
+ if (sortInfo?.field && sortInfo?.order) {
1416
+ newParams.sort = String(sortInfo.field);
1417
+ newParams.order = sortInfo.order === "ascend" ? "asc" : "desc";
1418
+ } else {
1419
+ delete newParams.sort;
1420
+ delete newParams.order;
1421
+ }
1422
+ setQueryParams(newParams);
1423
+ onChange?.(pag, _filters, sorter, _extra);
1424
+ },
1425
+ [queryParams, defaultPageSize, onChange]
1426
+ );
1427
+ const tableColumns = (0, import_react9.useMemo)(() => {
1428
+ const cols = columns.filter((col) => !col.hidden).map((col) => ({
1429
+ ...col,
1430
+ key: col.key || (Array.isArray(col.dataIndex) ? col.dataIndex.join(".") : col.dataIndex),
1431
+ sorter: col.sortable ? true : void 0,
1432
+ render: col.render ? col.render : (value) => renderValue(value, col.valueType, col.statusConfig)
1433
+ }));
1434
+ if (rowActions) {
1435
+ cols.push({
1436
+ title: texts.actions,
1437
+ key: "_actions",
1438
+ width: 150,
1439
+ render: (_, record) => {
1440
+ const actions = rowActions(record).filter(
1441
+ (a) => !a.hidden?.(record)
1442
+ );
1443
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Space, { size: 0, children: actions.map((action, idx) => {
1444
+ const isLast = idx === actions.length - 1;
1445
+ let actionElement;
1446
+ if (action.href) {
1447
+ actionElement = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SmartLink, { href: action.href, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Link, { style: action.danger ? { color: token.colorError } : void 0, children: action.label }) });
1448
+ } else {
1449
+ const linkElement = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1450
+ Link,
1451
+ {
1452
+ style: action.danger ? { color: token.colorError } : void 0,
1453
+ onClick: action.confirm ? void 0 : () => action.onClick?.(record),
1454
+ children: action.label
1455
+ }
1456
+ );
1457
+ if (action.confirm) {
1458
+ actionElement = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1459
+ import_antd4.Popconfirm,
1460
+ {
1461
+ title: typeof action.confirm === "string" ? action.confirm : `${action.label}\u3057\u307E\u3059\u304B\uFF1F`,
1462
+ onConfirm: () => action.onClick?.(record),
1463
+ okText: texts.yes,
1464
+ cancelText: texts.cancel,
1465
+ okButtonProps: action.danger ? { danger: true } : void 0,
1466
+ children: linkElement
1467
+ }
1468
+ );
1469
+ } else {
1470
+ actionElement = linkElement;
1471
+ }
1472
+ }
1473
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
1474
+ actionElement,
1475
+ !isLast && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Divider, { type: "vertical" })
1476
+ ] }, idx);
1477
+ }) });
1478
+ }
1479
+ });
1480
+ }
1481
+ return cols;
1482
+ }, [columns, rowActions, texts]);
1483
+ const paginationConfig = (0, import_react9.useMemo)(() => {
1484
+ if (pagination === false) return false;
1485
+ return {
1486
+ current: meta?.current_page || queryParams.page,
1487
+ pageSize: meta?.per_page || queryParams.per_page,
1488
+ total: meta?.total || 0,
1489
+ showSizeChanger: true,
1490
+ showTotal: texts.totalItems,
1491
+ ...typeof pagination === "object" ? pagination : {}
1492
+ };
1493
+ }, [pagination, meta, queryParams, texts]);
1494
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className, style, children: [
1495
+ searchFields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Card, { style: { marginBottom: 24, ...cardStyle }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1496
+ import_antd4.Form,
1497
+ {
1498
+ form: searchForm,
1499
+ layout: "horizontal",
1500
+ onFinish: handleSearch,
1501
+ labelCol: { flex: "100px" },
1502
+ wrapperCol: { flex: 1 },
1503
+ initialValues: defaultSearchValues,
1504
+ children: [
1505
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_antd4.Row, { gutter: 24, children: [
1506
+ visibleFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Col, { span: 8, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Form.Item, { name: field.name, label: field.label, children: renderSearchField(field, texts) }) }, field.name)),
1507
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Col, { span: visibleFields.length === 1 ? 16 : 8, style: { textAlign: "right" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_antd4.Space, { children: [
1508
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Button, { onClick: handleReset, children: texts.reset }),
1509
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Button, { type: "primary", htmlType: "submit", children: texts.search }),
1510
+ hasHiddenFields && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1511
+ import_antd4.Button,
1512
+ {
1513
+ type: "link",
1514
+ onClick: () => setExpanded(!expanded),
1515
+ children: [
1516
+ expanded ? texts.collapse : texts.expand,
1517
+ expanded ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons4.UpOutlined, {}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons4.DownOutlined, {})
1518
+ ]
1519
+ }
1520
+ )
1521
+ ] }) })
1522
+ ] }),
1523
+ expanded && hiddenFields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Row, { gutter: 24, style: { marginTop: 16 }, children: hiddenFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Col, { span: 8, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Form.Item, { name: field.name, label: field.label, children: renderSearchField(field, texts) }) }, field.name)) })
1524
+ ]
1525
+ }
1526
+ ) }),
1527
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1528
+ import_antd4.Card,
1529
+ {
1530
+ title: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_antd4.Space, { children: [
1531
+ icon,
1532
+ title,
1533
+ subTitle && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: {
1534
+ fontWeight: "normal",
1535
+ fontSize: 14,
1536
+ color: token.colorTextSecondary
1537
+ }, children: subTitle })
1538
+ ] }),
1539
+ extra: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_antd4.Space, { size: "small", children: [
1540
+ toolbarExtra,
1541
+ addButtonLink && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SmartLink, { href: addButtonLink, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Button, { type: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons4.PlusOutlined, {}), children: addLabel || texts.add }) }),
1542
+ onAdd && !addButtonLink && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Button, { type: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons4.PlusOutlined, {}), onClick: onAdd, children: addLabel || texts.add }),
1543
+ showRefresh && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Tooltip, { title: texts.refresh, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1544
+ import_antd4.Button,
1545
+ {
1546
+ icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons4.ReloadOutlined, {}),
1547
+ onClick: () => queryResult.refetch?.(),
1548
+ loading: queryResult.isFetching
1549
+ }
1550
+ ) }),
1551
+ showColumnSettings && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Tooltip, { title: texts.columnSettings, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons4.SettingOutlined, {}) }) })
1552
+ ] }),
1553
+ style: cardStyle,
1554
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1555
+ import_antd4.Table,
1556
+ {
1557
+ ...tableProps,
1558
+ columns: tableColumns,
1559
+ dataSource,
1560
+ rowKey,
1561
+ loading,
1562
+ pagination: paginationConfig,
1563
+ onChange: handleTableChange
1564
+ }
1565
+ )
1566
+ }
1567
+ )
1568
+ ] });
1569
+ }
1570
+
1571
+ // src/ant/components/PageContainer/PageContainer.tsx
1572
+ var import_antd5 = require("antd");
1573
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1574
+ function PageContainer({
1575
+ title,
1576
+ subTitle,
1577
+ icon,
1578
+ extra,
1579
+ breadcrumb,
1580
+ children,
1581
+ showHeader = true,
1582
+ className,
1583
+ style
1584
+ }) {
1585
+ const { token } = import_antd5.theme.useToken();
1586
+ const breadcrumbProps = breadcrumb ? Array.isArray(breadcrumb) ? { items: breadcrumb } : breadcrumb : void 0;
1587
+ const hasHeader = showHeader && (title || subTitle || breadcrumb);
1588
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className, style, children: [
1589
+ hasHeader && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1590
+ "div",
1591
+ {
1592
+ style: {
1593
+ marginBottom: 24
1594
+ },
1595
+ children: [
1596
+ breadcrumbProps && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1597
+ import_antd5.Breadcrumb,
1598
+ {
1599
+ ...breadcrumbProps,
1600
+ style: {
1601
+ marginBottom: 12,
1602
+ ...breadcrumbProps.style
1603
+ }
1604
+ }
1605
+ ),
1606
+ (title || extra) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1607
+ "div",
1608
+ {
1609
+ style: {
1610
+ display: "flex",
1611
+ justifyContent: "space-between",
1612
+ alignItems: "flex-start"
1613
+ },
1614
+ children: [
1615
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
1616
+ title && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1617
+ "h1",
1618
+ {
1619
+ style: {
1620
+ margin: 0,
1621
+ fontSize: 20,
1622
+ fontWeight: 600,
1623
+ lineHeight: 1.4,
1624
+ color: token.colorText,
1625
+ display: "flex",
1626
+ alignItems: "center",
1627
+ gap: 8
1628
+ },
1629
+ children: [
1630
+ icon && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 20 }, children: icon }),
1631
+ title
1632
+ ]
1633
+ }
1634
+ ),
1635
+ subTitle && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1636
+ "div",
1637
+ {
1638
+ style: {
1639
+ marginTop: 4,
1640
+ fontSize: 14,
1641
+ color: token.colorTextSecondary
1642
+ },
1643
+ children: subTitle
1644
+ }
1645
+ )
1646
+ ] }),
1647
+ extra && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flexShrink: 0 }, children: extra })
1648
+ ]
1649
+ }
1650
+ )
1651
+ ]
1652
+ }
1653
+ ),
1654
+ children
1655
+ ] });
1656
+ }
1657
+
1658
+ // src/ant/components/LocaleSwitcher/LocaleSwitcher.tsx
1659
+ var import_icons5 = require("@ant-design/icons");
1660
+ var import_antd6 = require("antd");
1661
+ var import_react_i18next2 = require("react-i18next");
1662
+
1663
+ // src/core/i18n/index.tsx
1664
+ var import_react10 = require("react");
1665
+ var import_react_i18next = require("react-i18next");
1666
+ var import_i18next = __toESM(require("i18next"), 1);
1667
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1668
+ var locales = ["ja", "en", "vi"];
1669
+ var localeNames = {
1670
+ ja: "\u65E5\u672C\u8A9E",
1671
+ en: "English",
1672
+ vi: "Ti\u1EBFng Vi\u1EC7t"
1673
+ };
1674
+ var defaultLocale = "ja";
1675
+ var I18nContext = (0, import_react10.createContext)(null);
1676
+ function useLocale() {
1677
+ const context = (0, import_react10.useContext)(I18nContext);
1678
+ const { i18n: i18nInstance } = (0, import_react_i18next.useTranslation)();
1679
+ if (context) {
1680
+ return context.locale;
1681
+ }
1682
+ return i18nInstance?.language || defaultLocale;
1683
+ }
1684
+
1685
+ // src/ant/components/LocaleSwitcher/LocaleSwitcher.tsx
1686
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1687
+ function LocaleSwitcher() {
1688
+ const { i18n: i18n2 } = (0, import_react_i18next2.useTranslation)();
1689
+ const locale = i18n2.language || "ja";
1690
+ const handleChange = (newLocale) => {
1691
+ i18n2.changeLanguage(newLocale);
1692
+ document.cookie = `locale=${newLocale};path=/;max-age=31536000`;
1693
+ };
1694
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1695
+ import_antd6.Select,
1696
+ {
1697
+ value: locale,
1698
+ onChange: handleChange,
1699
+ style: { width: 100 },
1700
+ size: "small",
1701
+ suffixIcon: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_icons5.GlobalOutlined, {}),
1702
+ options: locales.map((l) => ({
1703
+ value: l,
1704
+ label: localeNames[l]
1705
+ }))
1706
+ }
1707
+ );
1708
+ }
1709
+
1710
+ // src/ant/components/UserRoleAssignModal/UserRoleAssignModal.tsx
1711
+ var import_icons7 = require("@ant-design/icons");
1712
+ var import_antd8 = require("antd");
1713
+ var import_react11 = require("react");
1714
+
1715
+ // src/ant/components/ScopeUtils/ScopeUtils.tsx
1716
+ var import_icons6 = require("@ant-design/icons");
1717
+ var import_antd7 = require("antd");
1718
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1719
+ function getScopeIcon(scope) {
1720
+ switch (scope) {
1721
+ case "global":
1722
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons6.GlobalOutlined, {});
1723
+ case "org-wide":
1724
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons6.BankOutlined, {});
1725
+ case "branch":
1726
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons6.BranchesOutlined, {});
1727
+ default:
1728
+ return null;
1729
+ }
1730
+ }
1731
+ function getScopeColor(scope) {
1732
+ switch (scope) {
1733
+ case "global":
1734
+ return "purple";
1735
+ case "org-wide":
1736
+ return "blue";
1737
+ case "branch":
1738
+ return "green";
1739
+ default:
1740
+ return "default";
1741
+ }
1742
+ }
1743
+ function ScopeTag({ scope, label, showIcon = true }) {
1744
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_antd7.Tag, { color: getScopeColor(scope), icon: showIcon ? getScopeIcon(scope) : void 0, children: label || scope });
1745
+ }
1746
+ function ScopeLabel({ scope, label }) {
1747
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_antd7.Space, { children: [
1748
+ getScopeIcon(scope),
1749
+ label
1750
+ ] });
1751
+ }
1752
+
1753
+ // src/ant/components/UserRoleAssignModal/UserRoleAssignModal.tsx
1754
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1755
+ var { Text: Text4 } = import_antd8.Typography;
1756
+ var defaultTranslations = {
1757
+ title: "\u30ED\u30FC\u30EB\u5272\u308A\u5F53\u3066",
1758
+ selectRole: "\u30ED\u30FC\u30EB\u3092\u9078\u629E",
1759
+ scope: "\u30B9\u30B3\u30FC\u30D7",
1760
+ global: "\u30B0\u30ED\u30FC\u30D0\u30EB",
1761
+ orgWide: "\u7D44\u7E54\u5168\u4F53",
1762
+ branchSpecific: "\u62E0\u70B9\u9650\u5B9A",
1763
+ organization: "\u7D44\u7E54",
1764
+ selectBranches: "\u62E0\u70B9\u3092\u9078\u629E",
1765
+ assign: "\u5272\u308A\u5F53\u3066",
1766
+ cancel: "\u30AD\u30E3\u30F3\u30BB\u30EB",
1767
+ assignRole: "\u30ED\u30FC\u30EB\u5272\u308A\u5F53\u3066",
1768
+ required: "\u5FC5\u9808\u9805\u76EE\u3067\u3059"
1769
+ };
1770
+ function UserRoleAssignModal({
1771
+ open,
1772
+ userName,
1773
+ roles,
1774
+ organizations,
1775
+ branches,
1776
+ currentOrgId,
1777
+ loading = false,
1778
+ onAssign,
1779
+ onCancel,
1780
+ translations: t = {}
1781
+ }) {
1782
+ const [form] = import_antd8.Form.useForm();
1783
+ const [isSubmitting, setIsSubmitting] = (0, import_react11.useState)(false);
1784
+ const labels = { ...defaultTranslations, ...t };
1785
+ const handleFinish = async (values) => {
1786
+ setIsSubmitting(true);
1787
+ try {
1788
+ await onAssign(values);
1789
+ form.resetFields();
1790
+ } finally {
1791
+ setIsSubmitting(false);
1792
+ }
1793
+ };
1794
+ const handleCancel = () => {
1795
+ form.resetFields();
1796
+ onCancel();
1797
+ };
1798
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1799
+ import_antd8.Modal,
1800
+ {
1801
+ title: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_antd8.Space, { children: [
1802
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons7.SafetyOutlined, {}),
1803
+ labels.title,
1804
+ " ",
1805
+ userName ? `- ${userName}` : ""
1806
+ ] }),
1807
+ open,
1808
+ onCancel: handleCancel,
1809
+ footer: null,
1810
+ destroyOnHidden: true,
1811
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1812
+ import_antd8.Form,
1813
+ {
1814
+ form,
1815
+ layout: "vertical",
1816
+ onFinish: handleFinish,
1817
+ initialValues: { scope: "org-wide", org_id: currentOrgId },
1818
+ children: [
1819
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1820
+ import_antd8.Form.Item,
1821
+ {
1822
+ name: "role_id",
1823
+ label: labels.selectRole,
1824
+ rules: [{ required: true, message: labels.required }],
1825
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Select, { placeholder: labels.selectRole, children: roles.map((role) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Select.Option, { value: role.id, children: role.name }, role.id)) })
1826
+ }
1827
+ ),
1828
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Form.Item, { name: "scope", label: labels.scope, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_antd8.Radio.Group, { children: [
1829
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Radio, { value: "global", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScopeLabel, { scope: "global", label: labels.global }) }),
1830
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Radio, { value: "org-wide", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScopeLabel, { scope: "org-wide", label: labels.orgWide }) }),
1831
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Radio, { value: "branch", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScopeLabel, { scope: "branch", label: labels.branchSpecific }) })
1832
+ ] }) }),
1833
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Form.Item, { noStyle: true, shouldUpdate: (prev, curr) => prev.scope !== curr.scope, children: ({ getFieldValue }) => (getFieldValue("scope") === "org-wide" || getFieldValue("scope") === "branch") && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1834
+ import_antd8.Form.Item,
1835
+ {
1836
+ name: "org_id",
1837
+ label: labels.organization,
1838
+ rules: [{ required: true, message: labels.required }],
1839
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Select, { placeholder: labels.organization, children: organizations.map((org) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Select.Option, { value: String(org.id), children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_antd8.Space, { children: [
1840
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons7.BankOutlined, {}),
1841
+ org.name
1842
+ ] }) }, org.id)) })
1843
+ }
1844
+ ) }),
1845
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Form.Item, { noStyle: true, shouldUpdate: (prev, curr) => prev.scope !== curr.scope, children: ({ getFieldValue }) => getFieldValue("scope") === "branch" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1846
+ import_antd8.Form.Item,
1847
+ {
1848
+ name: "branch_ids",
1849
+ label: labels.selectBranches,
1850
+ rules: [{ required: true, message: labels.required }],
1851
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Select, { mode: "multiple", placeholder: labels.selectBranches, children: branches?.map((branch) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Select.Option, { value: String(branch.id), children: branch.name }, branch.id)) })
1852
+ }
1853
+ ) }),
1854
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Form.Item, { noStyle: true, shouldUpdate: true, children: ({ getFieldValue }) => {
1855
+ const scope = getFieldValue("scope");
1856
+ const selectedOrgId = getFieldValue("org_id");
1857
+ const selectedBranchIds = getFieldValue("branch_ids") || [];
1858
+ const selectedRole = roles.find((r) => r.id === getFieldValue("role_id"));
1859
+ const selectedOrg = organizations.find((o) => String(o.id) === selectedOrgId);
1860
+ const selectedBranches = branches?.filter((b) => selectedBranchIds.includes(String(b.id))) || [];
1861
+ if (!selectedRole) return null;
1862
+ let scopeText = "";
1863
+ if (scope === "global") {
1864
+ scopeText = labels.global;
1865
+ } else if (scope === "org-wide" && selectedOrg) {
1866
+ scopeText = `${selectedOrg.name} (${labels.orgWide})`;
1867
+ } else if (scope === "branch" && selectedBranches.length > 0) {
1868
+ scopeText = selectedBranches.map((b) => b.name).join(", ");
1869
+ }
1870
+ return scopeText ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1871
+ "div",
1872
+ {
1873
+ style: {
1874
+ padding: "8px 12px",
1875
+ background: "#f5f5f5",
1876
+ borderRadius: 4,
1877
+ marginBottom: 16
1878
+ },
1879
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text4, { type: "secondary", children: [
1880
+ labels.assignRole,
1881
+ ": ",
1882
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text4, { strong: true, children: selectedRole.name }),
1883
+ " \u2192 ",
1884
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Tag, { color: getScopeColor(scope), children: scopeText })
1885
+ ] })
1886
+ }
1887
+ ) : null;
1888
+ } }),
1889
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Form.Item, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_antd8.Space, { children: [
1890
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Button, { type: "primary", htmlType: "submit", loading: loading || isSubmitting, children: labels.assign }),
1891
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_antd8.Button, { onClick: handleCancel, children: labels.cancel })
1892
+ ] }) })
1893
+ ]
1894
+ }
1895
+ )
1896
+ }
1897
+ );
1898
+ }
1899
+
1900
+ // src/ant/components/UserPermissionsModal/UserPermissionsModal.tsx
1901
+ var import_icons8 = require("@ant-design/icons");
1902
+ var import_antd9 = require("antd");
1903
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1904
+ var { Text: Text5 } = import_antd9.Typography;
1905
+ var defaultTranslations2 = {
1906
+ permissionBreakdown: "\u6A29\u9650\u30D6\u30EC\u30FC\u30AF\u30C0\u30A6\u30F3",
1907
+ userInfo: "\u30E6\u30FC\u30B6\u30FC\u60C5\u5831",
1908
+ email: "\u30E1\u30FC\u30EB",
1909
+ primaryOrganization: "\u6240\u5C5E\u7D44\u7E54",
1910
+ global: "\u30B0\u30ED\u30FC\u30D0\u30EB",
1911
+ currentContext: "\u73FE\u5728\u306E\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8",
1912
+ roleAssignments: "\u30ED\u30FC\u30EB\u5272\u308A\u5F53\u3066",
1913
+ noRolesAssigned: "\u30ED\u30FC\u30EB\u304C\u5272\u308A\u5F53\u3066\u3089\u308C\u3066\u3044\u307E\u305B\u3093",
1914
+ add: "\u8FFD\u52A0",
1915
+ permissions: "\u6A29\u9650",
1916
+ teamMemberships: "\u30C1\u30FC\u30E0\u30E1\u30F3\u30D0\u30FC\u30B7\u30C3\u30D7",
1917
+ noTeamMemberships: "\u30C1\u30FC\u30E0\u306B\u6240\u5C5E\u3057\u3066\u3044\u307E\u305B\u3093",
1918
+ teamLeader: "\u30EA\u30FC\u30C0\u30FC",
1919
+ teamsFromConsole: "\u30C1\u30FC\u30E0\u306F\u30B3\u30F3\u30BD\u30FC\u30EB\u304B\u3089\u7BA1\u7406\u3057\u307E\u3059",
1920
+ aggregatedPermissions: "\u96C6\u7D04\u3055\u308C\u305F\u6A29\u9650",
1921
+ noData: "\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093",
1922
+ ungrouped: "\u672A\u5206\u985E",
1923
+ orgWide: "\u7D44\u7E54\u5168\u4F53",
1924
+ confirmRemoveRole: "\u3053\u306E\u30ED\u30FC\u30EB\u3092\u524A\u9664\u3057\u3066\u3082\u3088\u308D\u3057\u3044\u3067\u3059\u304B\uFF1F"
1925
+ };
1926
+ function UserPermissionsModal({
1927
+ open,
1928
+ userName,
1929
+ permissions,
1930
+ loading = false,
1931
+ currentOrg,
1932
+ currentBranch,
1933
+ branches,
1934
+ onClose,
1935
+ onAddRole,
1936
+ onAddTeam,
1937
+ onRemoveRole,
1938
+ translations: t = {}
1939
+ }) {
1940
+ const labels = { ...defaultTranslations2, ...t };
1941
+ const getBranchName = (branchId) => {
1942
+ if (!branchId || !branches) return "";
1943
+ const branch = branches.find((b) => String(b.id) === branchId);
1944
+ return branch?.name || branchId;
1945
+ };
1946
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1947
+ import_antd9.Modal,
1948
+ {
1949
+ title: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd9.Space, { children: [
1950
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.UserOutlined, {}),
1951
+ userName,
1952
+ " - ",
1953
+ labels.permissionBreakdown
1954
+ ] }),
1955
+ open,
1956
+ onCancel: onClose,
1957
+ footer: null,
1958
+ width: 800,
1959
+ destroyOnHidden: true,
1960
+ children: loading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { textAlign: "center", padding: 40 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Spin, { size: "large" }) }) : permissions ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
1961
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Card, { size: "small", title: labels.userInfo, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
1962
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
1963
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text5, { type: "secondary", children: [
1964
+ labels.email,
1965
+ ": "
1966
+ ] }),
1967
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text5, { children: permissions.user?.email })
1968
+ ] }),
1969
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
1970
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text5, { type: "secondary", children: [
1971
+ labels.primaryOrganization,
1972
+ ": "
1973
+ ] }),
1974
+ permissions.user?.organization ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Tag, { icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.BankOutlined, {}), color: "blue", children: permissions.user.organization.name }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Tag, { icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.GlobalOutlined, {}), color: "purple", children: labels.global })
1975
+ ] })
1976
+ ] }) }),
1977
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Card, { size: "small", title: labels.currentContext, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd9.Space, { wrap: true, children: [
1978
+ currentOrg && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Tag, { icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.BankOutlined, {}), color: "blue", children: currentOrg.name }),
1979
+ currentBranch && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Tag, { icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.BranchesOutlined, {}), color: "green", children: currentBranch.name })
1980
+ ] }) }),
1981
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1982
+ import_antd9.Card,
1983
+ {
1984
+ size: "small",
1985
+ title: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd9.Space, { children: [
1986
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.SafetyOutlined, {}),
1987
+ labels.roleAssignments,
1988
+ " (",
1989
+ permissions.role_assignments.length,
1990
+ ")"
1991
+ ] }),
1992
+ extra: onAddRole && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Button, { type: "primary", size: "small", icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.PlusOutlined, {}), onClick: onAddRole, children: labels.add }),
1993
+ children: permissions.role_assignments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Empty, { description: labels.noRolesAssigned }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Collapse, { ghost: true, children: permissions.role_assignments.map((assignment, index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1994
+ import_antd9.Collapse.Panel,
1995
+ {
1996
+ header: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd9.Space, { wrap: true, children: [
1997
+ getScopeIcon(assignment.scope),
1998
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text5, { strong: true, children: assignment.role.name }),
1999
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Tag, { color: getScopeColor(assignment.scope), children: assignment.scope === "global" ? labels.global : assignment.scope === "org-wide" ? assignment.org_name || labels.orgWide : assignment.branch_name || getBranchName(assignment.console_branch_id) }),
2000
+ assignment.scope === "branch" && assignment.org_name && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Tag, { color: "blue", icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.BankOutlined, {}), children: assignment.org_name }),
2001
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd9.Tag, { children: [
2002
+ assignment.permissions.length,
2003
+ " ",
2004
+ labels.permissions
2005
+ ] }),
2006
+ onRemoveRole && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2007
+ import_antd9.Popconfirm,
2008
+ {
2009
+ title: labels.confirmRemoveRole,
2010
+ onConfirm: () => {
2011
+ onRemoveRole(
2012
+ assignment.role.id,
2013
+ assignment.console_org_id,
2014
+ assignment.console_branch_id
2015
+ );
2016
+ },
2017
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2018
+ import_antd9.Button,
2019
+ {
2020
+ size: "small",
2021
+ danger: true,
2022
+ icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.DeleteOutlined, {}),
2023
+ onClick: (e) => e.stopPropagation()
2024
+ }
2025
+ )
2026
+ }
2027
+ )
2028
+ ] }),
2029
+ children: Object.entries(
2030
+ assignment.permissions.reduce(
2031
+ (groups, perm) => {
2032
+ const group = perm.group || labels.ungrouped;
2033
+ if (!groups[group]) groups[group] = [];
2034
+ groups[group].push({ slug: perm.slug, name: perm.name });
2035
+ return groups;
2036
+ },
2037
+ {}
2038
+ )
2039
+ ).map(([group, perms]) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { marginBottom: 8 }, children: [
2040
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text5, { type: "secondary", style: { fontSize: 12 }, children: group }),
2041
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 4, marginTop: 4 }, children: perms.map((perm) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Tag, { color: "blue", children: perm.name }, perm.slug)) })
2042
+ ] }, group))
2043
+ },
2044
+ index
2045
+ )) })
2046
+ }
2047
+ ),
2048
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2049
+ import_antd9.Card,
2050
+ {
2051
+ size: "small",
2052
+ title: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd9.Space, { children: [
2053
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.TeamOutlined, {}),
2054
+ labels.teamMemberships,
2055
+ " (",
2056
+ permissions.team_memberships.length,
2057
+ ")"
2058
+ ] }),
2059
+ extra: onAddTeam && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Button, { size: "small", icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.PlusOutlined, {}), onClick: onAddTeam, children: labels.add }),
2060
+ children: permissions.team_memberships.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Empty, { description: labels.noTeamMemberships }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Collapse, { ghost: true, children: permissions.team_memberships.map((membership, index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2061
+ import_antd9.Collapse.Panel,
2062
+ {
2063
+ header: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd9.Space, { children: [
2064
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.TeamOutlined, {}),
2065
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text5, { strong: true, children: membership.team.name }),
2066
+ membership.is_leader && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Tag, { color: "gold", children: labels.teamLeader }),
2067
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd9.Tag, { children: [
2068
+ membership.permissions.length,
2069
+ " ",
2070
+ labels.permissions
2071
+ ] })
2072
+ ] }),
2073
+ children: Object.entries(
2074
+ membership.permissions.reduce(
2075
+ (groups, perm) => {
2076
+ const group = perm.group || labels.ungrouped;
2077
+ if (!groups[group]) groups[group] = [];
2078
+ groups[group].push({ slug: perm.slug, name: perm.name });
2079
+ return groups;
2080
+ },
2081
+ {}
2082
+ )
2083
+ ).map(([group, perms]) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { marginBottom: 8 }, children: [
2084
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text5, { type: "secondary", style: { fontSize: 12 }, children: group }),
2085
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 4, marginTop: 4 }, children: perms.map((perm) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Tag, { color: "cyan", children: perm.name }, perm.slug)) })
2086
+ ] }, group))
2087
+ },
2088
+ index
2089
+ )) })
2090
+ }
2091
+ ),
2092
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2093
+ import_antd9.Card,
2094
+ {
2095
+ size: "small",
2096
+ title: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd9.Space, { children: [
2097
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.SafetyOutlined, {}),
2098
+ labels.aggregatedPermissions,
2099
+ " (",
2100
+ permissions.aggregated_permissions.length,
2101
+ ")"
2102
+ ] }),
2103
+ children: permissions.aggregated_permissions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Empty, { description: labels.noData }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Collapse, { ghost: true, children: Object.entries(
2104
+ permissions.aggregated_permissions.reduce(
2105
+ (groups, perm) => {
2106
+ const parts = perm.split(".");
2107
+ const group = parts.length > 1 ? parts.slice(0, -1).join(".") : labels.ungrouped;
2108
+ if (!groups[group]) groups[group] = [];
2109
+ groups[group].push(perm);
2110
+ return groups;
2111
+ },
2112
+ {}
2113
+ )
2114
+ ).map(([group, perms]) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2115
+ import_antd9.Collapse.Panel,
2116
+ {
2117
+ header: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd9.Space, { children: [
2118
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons8.SafetyOutlined, {}),
2119
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text5, { strong: true, children: group }),
2120
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Tag, { color: "green", children: perms.length })
2121
+ ] }),
2122
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: perms.map((perm) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_antd9.Tag, { color: "green", children: perm.split(".").pop() }, perm)) })
2123
+ },
2124
+ group
2125
+ )) })
2126
+ }
2127
+ )
2128
+ ] }) : null
2129
+ }
2130
+ );
2131
+ }
2132
+
2133
+ // src/ant/components/UserDetailCard/UserDetailCard.tsx
2134
+ var import_icons9 = require("@ant-design/icons");
2135
+ var import_antd10 = require("antd");
2136
+ var import_react12 = require("react");
2137
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2138
+ var { Title: Title3, Text: Text6, Link: AntLink } = import_antd10.Typography;
2139
+ var defaultTranslations3 = {
2140
+ email: "\u30E1\u30FC\u30EB",
2141
+ primaryOrganization: "\u6240\u5C5E\u7D44\u7E54",
2142
+ currentContext: "\u73FE\u5728\u306E\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8",
2143
+ global: "\u30B0\u30ED\u30FC\u30D0\u30EB",
2144
+ created: "\u4F5C\u6210\u65E5",
2145
+ lastSignIn: "\u6700\u7D42\u30B5\u30A4\u30F3\u30A4\u30F3",
2146
+ roleAssignments: "\u30ED\u30FC\u30EB\u5272\u308A\u5F53\u3066",
2147
+ roles: "\u30ED\u30FC\u30EB",
2148
+ permissions: "\u6A29\u9650",
2149
+ teams: "\u30C1\u30FC\u30E0",
2150
+ aggregatedPermissions: "\u96C6\u7D04\u3055\u308C\u305F\u6A29\u9650",
2151
+ permissionPolicies: "\u6A29\u9650\u30DD\u30EA\u30B7\u30FC",
2152
+ permissionsDescription: "\u6A29\u9650\u306E\u8AAC\u660E",
2153
+ searchPermissions: "\u6A29\u9650\u3092\u691C\u7D22",
2154
+ allTypes: "\u3059\u3079\u3066\u306E\u30BF\u30A4\u30D7",
2155
+ viaRole: "\u30ED\u30FC\u30EB\u7D4C\u7531",
2156
+ viaTeam: "\u30C1\u30FC\u30E0\u7D4C\u7531",
2157
+ attachedVia: "\u4ED8\u4E0E\u5143",
2158
+ filterByType: "\u30BF\u30A4\u30D7\u3067\u30D5\u30A3\u30EB\u30BF",
2159
+ remove: "\u524A\u9664",
2160
+ addPermissions: "\u6A29\u9650\u3092\u8FFD\u52A0",
2161
+ assignRole: "\u30ED\u30FC\u30EB\u5272\u308A\u5F53\u3066",
2162
+ noRolesAssigned: "\u30ED\u30FC\u30EB\u304C\u5272\u308A\u5F53\u3066\u3089\u308C\u3066\u3044\u307E\u305B\u3093",
2163
+ level: "\u30EC\u30D9\u30EB",
2164
+ actions: "\u64CD\u4F5C",
2165
+ confirmRemoveRole: "\u3053\u306E\u30ED\u30FC\u30EB\u3092\u524A\u9664\u3057\u3066\u3082\u3088\u308D\u3057\u3044\u3067\u3059\u304B\uFF1F",
2166
+ teamMemberships: "\u30C1\u30FC\u30E0\u30E1\u30F3\u30D0\u30FC\u30B7\u30C3\u30D7",
2167
+ noTeamMemberships: "\u30C1\u30FC\u30E0\u306B\u6240\u5C5E\u3057\u3066\u3044\u307E\u305B\u3093",
2168
+ teamLeader: "\u30EA\u30FC\u30C0\u30FC",
2169
+ noPermissions: "\u6A29\u9650\u304C\u3042\u308A\u307E\u305B\u3093",
2170
+ group: "\u30B0\u30EB\u30FC\u30D7"
2171
+ };
2172
+ function UserDetailCard({
2173
+ user,
2174
+ roleAssignments,
2175
+ teamMemberships,
2176
+ aggregatedPermissions,
2177
+ currentOrg,
2178
+ currentBranch,
2179
+ onRefresh,
2180
+ onAssignRole,
2181
+ onRemoveRole,
2182
+ onRoleClick,
2183
+ removeLoading = false,
2184
+ translations: t = {}
2185
+ }) {
2186
+ const labels = { ...defaultTranslations3, ...t };
2187
+ const [permissionSearch, setPermissionSearch] = (0, import_react12.useState)("");
2188
+ const [permissionTypeFilter, setPermissionTypeFilter] = (0, import_react12.useState)("all");
2189
+ const getScopeLabel = (assignment) => {
2190
+ if (assignment.scope === "global") return labels.global;
2191
+ if (assignment.scope === "org-wide") return assignment.org_name || labels.global;
2192
+ return assignment.branch_name || labels.global;
2193
+ };
2194
+ const permissionsTableData = roleAssignments.flatMap(
2195
+ (assignment) => assignment.permissions.map((perm) => ({
2196
+ key: `${assignment.role.id}-${perm.slug}`,
2197
+ permission: perm.slug,
2198
+ permissionName: perm.name,
2199
+ permissionGroup: perm.group,
2200
+ type: "role",
2201
+ attachedVia: assignment.role.name,
2202
+ scope: assignment.scope,
2203
+ roleId: assignment.role.id,
2204
+ consoleOrgId: assignment.console_org_id,
2205
+ consoleBranchId: assignment.console_branch_id
2206
+ }))
2207
+ );
2208
+ const teamPermissionsData = teamMemberships.flatMap(
2209
+ (membership) => membership.permissions.map((perm) => ({
2210
+ key: `team-${membership.team.id}-${perm.slug}`,
2211
+ permission: perm.slug,
2212
+ permissionName: perm.name,
2213
+ permissionGroup: perm.group,
2214
+ type: "team",
2215
+ attachedVia: membership.team.name,
2216
+ scope: "team"
2217
+ }))
2218
+ );
2219
+ const allPermissionsData = [...permissionsTableData, ...teamPermissionsData];
2220
+ const filteredPermissions = allPermissionsData.filter((p) => {
2221
+ const matchesSearch = !permissionSearch || p.permission.toLowerCase().includes(permissionSearch.toLowerCase());
2222
+ const matchesType = permissionTypeFilter === "all" || p.type === permissionTypeFilter;
2223
+ return matchesSearch && matchesType;
2224
+ });
2225
+ const groupedAggregatedPermissions = (0, import_react12.useMemo)(
2226
+ () => aggregatedPermissions.reduce((acc, perm) => {
2227
+ const group = perm.split(".").slice(0, -1).join(".") || "other";
2228
+ if (!acc[group]) acc[group] = [];
2229
+ acc[group].push(perm);
2230
+ return acc;
2231
+ }, {}),
2232
+ [aggregatedPermissions]
2233
+ );
2234
+ const tabItems = [
2235
+ {
2236
+ key: "permissions",
2237
+ label: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
2238
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.KeyOutlined, {}),
2239
+ " ",
2240
+ labels.permissions
2241
+ ] }),
2242
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2243
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2244
+ "div",
2245
+ {
2246
+ style: {
2247
+ display: "flex",
2248
+ justifyContent: "space-between",
2249
+ alignItems: "center",
2250
+ marginBottom: 16
2251
+ },
2252
+ children: [
2253
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2254
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Title3, { level: 5, style: { margin: 0 }, children: [
2255
+ labels.permissionPolicies,
2256
+ " (",
2257
+ allPermissionsData.length,
2258
+ ")"
2259
+ ] }),
2260
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { type: "secondary", style: { fontSize: 12 }, children: labels.permissionsDescription })
2261
+ ] }),
2262
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_antd10.Space, { children: [
2263
+ onRefresh && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.ReloadOutlined, {}), onClick: onRefresh }),
2264
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Button, { type: "default", children: labels.remove }),
2265
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Button, { type: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.PlusOutlined, {}), children: labels.addPermissions })
2266
+ ] })
2267
+ ]
2268
+ }
2269
+ ),
2270
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", gap: 16, marginBottom: 16 }, children: [
2271
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2272
+ import_antd10.Input,
2273
+ {
2274
+ placeholder: labels.searchPermissions,
2275
+ prefix: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.KeyOutlined, {}),
2276
+ value: permissionSearch,
2277
+ onChange: (e) => setPermissionSearch(e.target.value),
2278
+ style: { width: 300 }
2279
+ }
2280
+ ),
2281
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2282
+ import_antd10.Select,
2283
+ {
2284
+ value: permissionTypeFilter,
2285
+ onChange: setPermissionTypeFilter,
2286
+ style: { width: 200 },
2287
+ options: [
2288
+ { value: "all", label: labels.allTypes },
2289
+ { value: "role", label: labels.viaRole },
2290
+ { value: "team", label: labels.viaTeam }
2291
+ ]
2292
+ }
2293
+ )
2294
+ ] }),
2295
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2296
+ import_antd10.Table,
2297
+ {
2298
+ dataSource: filteredPermissions,
2299
+ pagination: { pageSize: 10 },
2300
+ columns: [
2301
+ {
2302
+ title: labels.permissions,
2303
+ dataIndex: "permission",
2304
+ key: "permission",
2305
+ render: (perm) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_antd10.Space, { children: [
2306
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.KeyOutlined, { style: { color: "#faad14" } }),
2307
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AntLink, { children: perm })
2308
+ ] })
2309
+ },
2310
+ {
2311
+ title: labels.filterByType,
2312
+ dataIndex: "type",
2313
+ key: "type",
2314
+ width: 150,
2315
+ render: (type) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Tag, { color: type === "role" ? "blue" : "green", children: type === "role" ? labels.viaRole : labels.viaTeam })
2316
+ },
2317
+ {
2318
+ title: labels.attachedVia,
2319
+ dataIndex: "attachedVia",
2320
+ key: "attachedVia",
2321
+ width: 200,
2322
+ render: (via, record) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_antd10.Space, { children: [
2323
+ record.type === "role" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.SafetyOutlined, {}) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.TeamOutlined, {}),
2324
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { children: via }),
2325
+ record.scope && record.scope !== "team" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Tag, { color: getScopeColor(record.scope), style: { fontSize: 12 }, children: record.scope })
2326
+ ] })
2327
+ }
2328
+ ]
2329
+ }
2330
+ )
2331
+ ] })
2332
+ },
2333
+ {
2334
+ key: "roles",
2335
+ label: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
2336
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.SafetyOutlined, {}),
2337
+ " ",
2338
+ labels.roles,
2339
+ " (",
2340
+ roleAssignments.length,
2341
+ ")"
2342
+ ] }),
2343
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2344
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2345
+ "div",
2346
+ {
2347
+ style: {
2348
+ display: "flex",
2349
+ justifyContent: "space-between",
2350
+ alignItems: "center",
2351
+ marginBottom: 16
2352
+ },
2353
+ children: [
2354
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Title3, { level: 5, style: { margin: 0 }, children: labels.roleAssignments }),
2355
+ onAssignRole && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Button, { type: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.PlusOutlined, {}), onClick: onAssignRole, children: labels.assignRole })
2356
+ ]
2357
+ }
2358
+ ),
2359
+ roleAssignments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Empty, { description: labels.noRolesAssigned }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2360
+ import_antd10.Table,
2361
+ {
2362
+ dataSource: roleAssignments,
2363
+ rowKey: (r) => `${r.role.id}-${r.console_org_id}-${r.console_branch_id}`,
2364
+ columns: [
2365
+ {
2366
+ title: labels.roles,
2367
+ key: "role",
2368
+ render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_antd10.Space, { children: [
2369
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.SafetyOutlined, { style: { color: "#1890ff" } }),
2370
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2371
+ Text6,
2372
+ {
2373
+ strong: true,
2374
+ style: { color: "#1890ff", cursor: onRoleClick ? "pointer" : "default" },
2375
+ onClick: () => onRoleClick?.(record.role.id),
2376
+ children: record.role.name
2377
+ }
2378
+ ),
2379
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Tag, { color: "default", children: record.role.slug })
2380
+ ] })
2381
+ },
2382
+ {
2383
+ title: labels.global,
2384
+ key: "scope",
2385
+ width: 200,
2386
+ render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Tag, { color: getScopeColor(record.scope), children: getScopeLabel(record) })
2387
+ },
2388
+ {
2389
+ title: labels.level,
2390
+ dataIndex: ["role", "level"],
2391
+ key: "level",
2392
+ width: 100
2393
+ },
2394
+ {
2395
+ title: labels.permissions,
2396
+ key: "permissions",
2397
+ width: 150,
2398
+ render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text6, { children: [
2399
+ record.permissions.length,
2400
+ " ",
2401
+ labels.permissions.toLowerCase()
2402
+ ] })
2403
+ },
2404
+ {
2405
+ title: labels.actions,
2406
+ key: "actions",
2407
+ width: 100,
2408
+ render: (_, record) => onRemoveRole && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2409
+ import_antd10.Popconfirm,
2410
+ {
2411
+ title: labels.confirmRemoveRole,
2412
+ onConfirm: () => onRemoveRole(
2413
+ record.role.id,
2414
+ record.console_org_id,
2415
+ record.console_branch_id
2416
+ ),
2417
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2418
+ import_antd10.Button,
2419
+ {
2420
+ type: "text",
2421
+ danger: true,
2422
+ icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.DeleteOutlined, {}),
2423
+ loading: removeLoading
2424
+ }
2425
+ )
2426
+ }
2427
+ )
2428
+ }
2429
+ ]
2430
+ }
2431
+ )
2432
+ ] })
2433
+ },
2434
+ {
2435
+ key: "teams",
2436
+ label: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
2437
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.TeamOutlined, {}),
2438
+ " ",
2439
+ labels.teams,
2440
+ " (",
2441
+ teamMemberships.length,
2442
+ ")"
2443
+ ] }),
2444
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2445
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Title3, { level: 5, style: { marginBottom: 16 }, children: labels.teamMemberships }),
2446
+ teamMemberships.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Empty, { description: labels.noTeamMemberships }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2447
+ import_antd10.Table,
2448
+ {
2449
+ dataSource: teamMemberships,
2450
+ rowKey: (m) => m.team.id,
2451
+ columns: [
2452
+ {
2453
+ title: labels.teams,
2454
+ key: "team",
2455
+ render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_antd10.Space, { children: [
2456
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.TeamOutlined, { style: { color: "#52c41a" } }),
2457
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { strong: true, children: record.team.name }),
2458
+ record.team.path && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text6, { type: "secondary", children: [
2459
+ "(",
2460
+ record.team.path,
2461
+ ")"
2462
+ ] })
2463
+ ] })
2464
+ },
2465
+ {
2466
+ title: labels.teamLeader,
2467
+ key: "leader",
2468
+ width: 150,
2469
+ render: (_, record) => record.is_leader ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Tag, { color: "gold", children: labels.teamLeader }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { type: "secondary", children: "-" })
2470
+ },
2471
+ {
2472
+ title: labels.permissions,
2473
+ key: "permissions",
2474
+ width: 150,
2475
+ render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text6, { children: [
2476
+ record.permissions.length,
2477
+ " ",
2478
+ labels.permissions.toLowerCase()
2479
+ ] })
2480
+ }
2481
+ ]
2482
+ }
2483
+ )
2484
+ ] })
2485
+ },
2486
+ {
2487
+ key: "aggregated",
2488
+ label: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
2489
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.SafetyOutlined, {}),
2490
+ " ",
2491
+ labels.aggregatedPermissions,
2492
+ " (",
2493
+ aggregatedPermissions.length,
2494
+ ")"
2495
+ ] }),
2496
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2497
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Title3, { level: 5, style: { marginBottom: 16 }, children: labels.aggregatedPermissions }),
2498
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { type: "secondary", style: { display: "block", marginBottom: 16 }, children: "\u3059\u3079\u3066\u306E\u30ED\u30FC\u30EB\u3068\u30C1\u30FC\u30E0\u304B\u3089\u96C6\u7D04\u3055\u308C\u305F\u6A29\u9650\u306E\u4E00\u89A7\u3067\u3059\u3002" }),
2499
+ aggregatedPermissions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Empty, { description: labels.noPermissions }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2500
+ import_antd10.Table,
2501
+ {
2502
+ dataSource: aggregatedPermissions.map((perm) => ({
2503
+ key: perm,
2504
+ permission: perm,
2505
+ group: perm.split(".").slice(0, -1).join(".") || "other",
2506
+ action: perm.split(".").pop() || perm
2507
+ })),
2508
+ pagination: { pageSize: 20 },
2509
+ size: "small",
2510
+ columns: [
2511
+ {
2512
+ title: labels.group,
2513
+ dataIndex: "group",
2514
+ key: "group",
2515
+ width: 200,
2516
+ filters: Object.keys(groupedAggregatedPermissions).map((g) => ({
2517
+ text: g,
2518
+ value: g
2519
+ })),
2520
+ onFilter: (value, record) => record.group === value,
2521
+ render: (group) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Tag, { icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.SafetyOutlined, {}), color: "blue", children: group })
2522
+ },
2523
+ {
2524
+ title: labels.permissions,
2525
+ dataIndex: "permission",
2526
+ key: "permission",
2527
+ render: (perm) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_antd10.Space, { children: [
2528
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.KeyOutlined, { style: { color: "#faad14" } }),
2529
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { children: perm })
2530
+ ] })
2531
+ },
2532
+ {
2533
+ title: "Action",
2534
+ dataIndex: "action",
2535
+ key: "action",
2536
+ width: 150,
2537
+ render: (action) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Tag, { color: "green", children: action })
2538
+ }
2539
+ ]
2540
+ }
2541
+ )
2542
+ ] })
2543
+ }
2544
+ ];
2545
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2546
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Card, { size: "small", style: { marginBottom: 24 }, styles: { body: { padding: "16px 24px" } }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2547
+ "div",
2548
+ {
2549
+ style: {
2550
+ display: "grid",
2551
+ gridTemplateColumns: "repeat(3, 1fr)",
2552
+ gap: "20px 48px"
2553
+ },
2554
+ children: [
2555
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2556
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { type: "secondary", style: { fontSize: 12, display: "block", marginBottom: 4 }, children: labels.email }),
2557
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { copyable: true, style: { fontSize: 14 }, children: user?.email || "-" })
2558
+ ] }),
2559
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2560
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { type: "secondary", style: { fontSize: 12, display: "block", marginBottom: 4 }, children: labels.primaryOrganization }),
2561
+ user?.organization ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_antd10.Space, { size: 4, children: [
2562
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.BankOutlined, { style: { color: "#1890ff" } }),
2563
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { style: { fontSize: 14 }, children: user.organization.name })
2564
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_antd10.Space, { size: 4, children: [
2565
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.GlobalOutlined, { style: { color: "#722ed1" } }),
2566
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { style: { fontSize: 14 }, children: labels.global })
2567
+ ] })
2568
+ ] }),
2569
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2570
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { type: "secondary", style: { fontSize: 12, display: "block", marginBottom: 4 }, children: labels.currentContext }),
2571
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_antd10.Space, { size: 16, wrap: true, children: [
2572
+ currentOrg && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_antd10.Space, { size: 4, children: [
2573
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.BankOutlined, { style: { color: "#1890ff" } }),
2574
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { style: { fontSize: 14 }, children: currentOrg.name })
2575
+ ] }),
2576
+ currentBranch && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_antd10.Space, { size: 4, children: [
2577
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons9.BranchesOutlined, { style: { color: "#52c41a" } }),
2578
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { style: { fontSize: 14 }, children: currentBranch.name })
2579
+ ] })
2580
+ ] })
2581
+ ] }),
2582
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2583
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { type: "secondary", style: { fontSize: 12, display: "block", marginBottom: 4 }, children: labels.created }),
2584
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { style: { fontSize: 14 }, children: user?.created_at ? new Date(user.created_at).toLocaleDateString() : "-" })
2585
+ ] }),
2586
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2587
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { type: "secondary", style: { fontSize: 12, display: "block", marginBottom: 4 }, children: labels.lastSignIn }),
2588
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { style: { fontSize: 14 }, children: "-" })
2589
+ ] }),
2590
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2591
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { type: "secondary", style: { fontSize: 12, display: "block", marginBottom: 4 }, children: labels.roleAssignments }),
2592
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text6, { style: { fontSize: 14 }, children: [
2593
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text6, { strong: true, children: roleAssignments.length }),
2594
+ " ",
2595
+ labels.roles.toLowerCase()
2596
+ ] })
2597
+ ] })
2598
+ ]
2599
+ }
2600
+ ) }),
2601
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Card, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_antd10.Tabs, { defaultActiveKey: "permissions", items: tabItems }) })
2602
+ ] });
2603
+ }
2604
+
2605
+ // src/ant/components/RoleCreateModal/RoleCreateModal.tsx
2606
+ var import_icons10 = require("@ant-design/icons");
2607
+ var import_antd11 = require("antd");
2608
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2609
+ var defaultTranslations4 = {
2610
+ title: "\u30ED\u30FC\u30EB\u4F5C\u6210",
2611
+ name: "\u540D\u524D",
2612
+ slug: "\u30B9\u30E9\u30C3\u30B0",
2613
+ description: "\u8AAC\u660E",
2614
+ level: "\u30EC\u30D9\u30EB",
2615
+ scope: "\u30B9\u30B3\u30FC\u30D7",
2616
+ global: "\u30B0\u30ED\u30FC\u30D0\u30EB",
2617
+ orgRole: "\u7D44\u7E54\u30ED\u30FC\u30EB",
2618
+ organization: "\u7D44\u7E54",
2619
+ create: "\u4F5C\u6210",
2620
+ cancel: "\u30AD\u30E3\u30F3\u30BB\u30EB",
2621
+ required: "\u5FC5\u9808\u9805\u76EE\u3067\u3059"
2622
+ };
2623
+ function RoleCreateModal({
2624
+ open,
2625
+ organizations,
2626
+ currentOrgId,
2627
+ loading = false,
2628
+ onSubmit,
2629
+ onCancel,
2630
+ translations: t = {}
2631
+ }) {
2632
+ const [form] = import_antd11.Form.useForm();
2633
+ const labels = { ...defaultTranslations4, ...t };
2634
+ const handleFinish = async (values) => {
2635
+ await onSubmit(values);
2636
+ form.resetFields();
2637
+ };
2638
+ const handleCancel = () => {
2639
+ form.resetFields();
2640
+ onCancel();
2641
+ };
2642
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2643
+ import_antd11.Modal,
2644
+ {
2645
+ title: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_antd11.Space, { children: [
2646
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons10.PlusOutlined, {}),
2647
+ labels.title
2648
+ ] }),
2649
+ open,
2650
+ onCancel: handleCancel,
2651
+ footer: null,
2652
+ destroyOnHidden: true,
2653
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2654
+ import_antd11.Form,
2655
+ {
2656
+ form,
2657
+ layout: "vertical",
2658
+ onFinish: handleFinish,
2659
+ initialValues: { level: 50, scope: "org", org_id: currentOrgId },
2660
+ children: [
2661
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2662
+ import_antd11.Form.Item,
2663
+ {
2664
+ name: "scope",
2665
+ label: labels.scope,
2666
+ rules: [{ required: true, message: labels.required }],
2667
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_antd11.Radio.Group, { children: [
2668
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Radio, { value: "global", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_antd11.Space, { children: [
2669
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons10.GlobalOutlined, {}),
2670
+ labels.global
2671
+ ] }) }),
2672
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Radio, { value: "org", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_antd11.Space, { children: [
2673
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons10.BankOutlined, {}),
2674
+ labels.orgRole
2675
+ ] }) })
2676
+ ] })
2677
+ }
2678
+ ),
2679
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Form.Item, { noStyle: true, shouldUpdate: (prev, curr) => prev.scope !== curr.scope, children: ({ getFieldValue }) => getFieldValue("scope") === "org" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2680
+ import_antd11.Form.Item,
2681
+ {
2682
+ name: "org_id",
2683
+ label: labels.organization,
2684
+ rules: [{ required: true, message: labels.required }],
2685
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Select, { placeholder: labels.organization, children: organizations.map((org) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Select.Option, { value: String(org.id), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_antd11.Space, { children: [
2686
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons10.BankOutlined, {}),
2687
+ org.name
2688
+ ] }) }, org.id)) })
2689
+ }
2690
+ ) }),
2691
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2692
+ import_antd11.Form.Item,
2693
+ {
2694
+ name: "name",
2695
+ label: labels.name,
2696
+ rules: [{ required: true, message: labels.required }],
2697
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Input, {})
2698
+ }
2699
+ ),
2700
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2701
+ import_antd11.Form.Item,
2702
+ {
2703
+ name: "slug",
2704
+ label: labels.slug,
2705
+ rules: [{ required: true, message: labels.required }],
2706
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Input, {})
2707
+ }
2708
+ ),
2709
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Form.Item, { name: "description", label: labels.description, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Input.TextArea, { rows: 3 }) }),
2710
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2711
+ import_antd11.Form.Item,
2712
+ {
2713
+ name: "level",
2714
+ label: labels.level,
2715
+ rules: [{ required: true, message: labels.required }],
2716
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.InputNumber, { min: 1, max: 100, style: { width: "100%" } })
2717
+ }
2718
+ ),
2719
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Form.Item, { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_antd11.Space, { children: [
2720
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Button, { type: "primary", htmlType: "submit", loading, children: labels.create }),
2721
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_antd11.Button, { onClick: handleCancel, children: labels.cancel })
2722
+ ] }) })
2723
+ ]
2724
+ }
2725
+ )
2726
+ }
2727
+ );
2728
+ }
2729
+
2730
+ // src/ant/components/RolesListCard/RolesListCard.tsx
2731
+ var import_icons11 = require("@ant-design/icons");
2732
+ var import_antd12 = require("antd");
2733
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2734
+ var { Text: Text7 } = import_antd12.Typography;
2735
+ var defaultTranslations5 = {
2736
+ name: "\u540D\u524D",
2737
+ scope: "\u30B9\u30B3\u30FC\u30D7",
2738
+ level: "\u30EC\u30D9\u30EB",
2739
+ description: "\u8AAC\u660E",
2740
+ actions: "\u64CD\u4F5C",
2741
+ detail: "\u8A73\u7D30",
2742
+ global: "\u30B0\u30ED\u30FC\u30D0\u30EB",
2743
+ orgRole: "\u7D44\u7E54\u30ED\u30FC\u30EB",
2744
+ all: "\u3059\u3079\u3066",
2745
+ confirmDeleteRole: "\u3053\u306E\u30ED\u30FC\u30EB\u3092\u524A\u9664\u3057\u3066\u3082\u3088\u308D\u3057\u3044\u3067\u3059\u304B\uFF1F"
2746
+ };
2747
+ function RolesListCard({
2748
+ roles,
2749
+ loading = false,
2750
+ scopeFilter,
2751
+ onScopeFilterChange,
2752
+ onCreateClick,
2753
+ onViewClick,
2754
+ onDeleteClick,
2755
+ translations: t = {}
2756
+ }) {
2757
+ const labels = { ...defaultTranslations5, ...t };
2758
+ const columns = [
2759
+ {
2760
+ title: labels.name,
2761
+ dataIndex: "name",
2762
+ key: "name",
2763
+ render: (name, record) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_antd12.Space, { children: [
2764
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons11.SafetyOutlined, { style: { color: "#1890ff" } }),
2765
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text7, { strong: true, children: name }),
2766
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_antd12.Tag, { children: record.slug })
2767
+ ] })
2768
+ },
2769
+ {
2770
+ title: labels.scope,
2771
+ dataIndex: "console_org_id",
2772
+ key: "scope",
2773
+ width: 180,
2774
+ render: (_, record) => record.console_org_id ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_antd12.Tag, { icon: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons11.BankOutlined, {}), color: "blue", children: record.organization?.name || record.console_org_id }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_antd12.Tag, { icon: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons11.GlobalOutlined, {}), color: "purple", children: labels.global })
2775
+ },
2776
+ {
2777
+ title: labels.level,
2778
+ dataIndex: "level",
2779
+ key: "level",
2780
+ width: 100,
2781
+ render: (level) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_antd12.Tag, { color: "blue", children: level })
2782
+ },
2783
+ {
2784
+ title: labels.description,
2785
+ dataIndex: "description",
2786
+ key: "description",
2787
+ ellipsis: true
2788
+ },
2789
+ {
2790
+ title: labels.actions,
2791
+ key: "actions",
2792
+ width: 180,
2793
+ render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_antd12.Space, { children: [
2794
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_antd12.Button, { size: "small", icon: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons11.EyeOutlined, {}), onClick: () => onViewClick(record), children: labels.detail }),
2795
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_antd12.Popconfirm, { title: labels.confirmDeleteRole, onConfirm: () => onDeleteClick(record), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_antd12.Button, { size: "small", danger: true, icon: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons11.DeleteOutlined, {}) }) })
2796
+ ] })
2797
+ }
2798
+ ];
2799
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2800
+ import_antd12.Card,
2801
+ {
2802
+ title: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_antd12.Space, { children: [
2803
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons11.SafetyOutlined, {}),
2804
+ "Roles"
2805
+ ] }),
2806
+ extra: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_antd12.Button, { type: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons11.PlusOutlined, {}), onClick: onCreateClick, children: "Create" }),
2807
+ children: [
2808
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { marginBottom: 16, display: "flex", gap: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2809
+ import_antd12.Select,
2810
+ {
2811
+ value: scopeFilter,
2812
+ onChange: onScopeFilterChange,
2813
+ style: { minWidth: 200 },
2814
+ children: [
2815
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_antd12.Select.Option, { value: "all", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_antd12.Space, { children: [
2816
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons11.SafetyOutlined, {}),
2817
+ labels.all
2818
+ ] }) }),
2819
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_antd12.Select.Option, { value: "global", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_antd12.Space, { children: [
2820
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons11.GlobalOutlined, {}),
2821
+ labels.global
2822
+ ] }) }),
2823
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_antd12.Select.Option, { value: "org", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_antd12.Space, { children: [
2824
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons11.BankOutlined, {}),
2825
+ labels.orgRole
2826
+ ] }) })
2827
+ ]
2828
+ }
2829
+ ) }),
2830
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2831
+ import_antd12.Table,
2832
+ {
2833
+ columns,
2834
+ dataSource: roles,
2835
+ rowKey: "id",
2836
+ loading,
2837
+ pagination: { pageSize: 10 }
2838
+ }
2839
+ )
2840
+ ]
2841
+ }
2842
+ );
2843
+ }
2844
+
2845
+ // src/ant/components/PermissionsListCard/PermissionsListCard.tsx
2846
+ var import_icons12 = require("@ant-design/icons");
2847
+ var import_antd13 = require("antd");
2848
+ var import_react13 = require("react");
2849
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2850
+ var { Text: Text8 } = import_antd13.Typography;
2851
+ var defaultTranslations6 = {
2852
+ searchPermissions: "\u6A29\u9650\u3092\u691C\u7D22",
2853
+ name: "\u540D\u524D",
2854
+ slug: "\u30B9\u30E9\u30C3\u30B0",
2855
+ group: "\u30B0\u30EB\u30FC\u30D7",
2856
+ noData: "\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093"
2857
+ };
2858
+ function PermissionsListCard({
2859
+ permissions,
2860
+ groups,
2861
+ loading = false,
2862
+ translations: t = {},
2863
+ onGroupLabelRender
2864
+ }) {
2865
+ const [search, setSearch] = (0, import_react13.useState)("");
2866
+ const labels = { ...defaultTranslations6, ...t };
2867
+ const filteredPermissions = (0, import_react13.useMemo)(() => {
2868
+ if (!search) return permissions;
2869
+ const lowerSearch = search.toLowerCase();
2870
+ return permissions.filter(
2871
+ (p) => p.name.toLowerCase().includes(lowerSearch) || p.slug.toLowerCase().includes(lowerSearch) || (p.group || "").toLowerCase().includes(lowerSearch)
2872
+ );
2873
+ }, [permissions, search]);
2874
+ const groupedPermissions = (0, import_react13.useMemo)(() => {
2875
+ const grouped = {};
2876
+ filteredPermissions.forEach((perm) => {
2877
+ const group = perm.group || "other";
2878
+ if (!grouped[group]) grouped[group] = [];
2879
+ grouped[group].push(perm);
2880
+ });
2881
+ return grouped;
2882
+ }, [filteredPermissions]);
2883
+ const getGroupLabel = (group) => {
2884
+ if (onGroupLabelRender) return onGroupLabelRender(group);
2885
+ return group;
2886
+ };
2887
+ const columns = [
2888
+ {
2889
+ title: labels.name,
2890
+ dataIndex: "name",
2891
+ key: "name",
2892
+ render: (name) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_antd13.Space, { children: [
2893
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_icons12.KeyOutlined, { style: { color: "#52c41a" } }),
2894
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text8, { strong: true, children: name })
2895
+ ] })
2896
+ },
2897
+ {
2898
+ title: labels.slug,
2899
+ dataIndex: "slug",
2900
+ key: "slug",
2901
+ render: (slug) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_antd13.Tag, { color: "blue", children: slug })
2902
+ },
2903
+ {
2904
+ title: labels.group,
2905
+ dataIndex: "group",
2906
+ key: "group",
2907
+ render: (group) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_antd13.Tag, { icon: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_icons12.AppstoreOutlined, {}), color: "purple", children: getGroupLabel(group || "other") })
2908
+ }
2909
+ ];
2910
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_antd13.Card, { children: [
2911
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { marginBottom: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2912
+ import_antd13.Input.Search,
2913
+ {
2914
+ placeholder: labels.searchPermissions,
2915
+ allowClear: true,
2916
+ onSearch: setSearch,
2917
+ onChange: (e) => !e.target.value && setSearch(""),
2918
+ style: { maxWidth: 300 }
2919
+ }
2920
+ ) }),
2921
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_antd13.Collapse, { defaultActiveKey: groups, ghost: true, children: Object.entries(groupedPermissions).map(([group, perms]) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2922
+ import_antd13.Collapse.Panel,
2923
+ {
2924
+ header: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_antd13.Space, { children: [
2925
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_icons12.AppstoreOutlined, { style: { color: "#722ed1" } }),
2926
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text8, { strong: true, children: getGroupLabel(group) }),
2927
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_antd13.Tag, { children: perms.length })
2928
+ ] }),
2929
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2930
+ import_antd13.Table,
2931
+ {
2932
+ columns,
2933
+ dataSource: perms,
2934
+ rowKey: "id",
2935
+ loading,
2936
+ pagination: false,
2937
+ size: "small"
2938
+ }
2939
+ )
2940
+ },
2941
+ group
2942
+ )) }),
2943
+ filteredPermissions.length === 0 && !loading && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { textAlign: "center", padding: 40 }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text8, { type: "secondary", children: labels.noData }) })
2944
+ ] });
2945
+ }
2946
+
2947
+ // src/ant/components/TeamsListCard/TeamsListCard.tsx
2948
+ var import_icons13 = require("@ant-design/icons");
2949
+ var import_antd14 = require("antd");
2950
+ var import_jsx_runtime17 = require("react/jsx-runtime");
2951
+ var { Text: Text9 } = import_antd14.Typography;
2952
+ var defaultTranslations7 = {
2953
+ name: "\u540D\u524D",
2954
+ memberCount: "\u30E1\u30F3\u30D0\u30FC\u6570",
2955
+ permissions: "\u6A29\u9650",
2956
+ noTeams: "\u30C1\u30FC\u30E0\u304C\u3042\u308A\u307E\u305B\u3093",
2957
+ teamsFromConsole: "\u30C1\u30FC\u30E0\u306F\u30B3\u30F3\u30BD\u30FC\u30EB\u304B\u3089\u7BA1\u7406\u3055\u308C\u307E\u3059",
2958
+ teamPermissions: "\u30C1\u30FC\u30E0\u6A29\u9650",
2959
+ noData: "\u30C7\u30FC\u30BF\u304C\u3042\u308A\u307E\u305B\u3093"
2960
+ };
2961
+ function TeamsListCard({
2962
+ teams,
2963
+ loading = false,
2964
+ translations: t = {}
2965
+ }) {
2966
+ const labels = { ...defaultTranslations7, ...t };
2967
+ const columns = [
2968
+ {
2969
+ title: labels.name,
2970
+ dataIndex: "name",
2971
+ key: "name",
2972
+ render: (name) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
2973
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_icons13.TeamOutlined, { style: { marginRight: 8, color: "#1890ff" } }),
2974
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text9, { strong: true, children: name })
2975
+ ] })
2976
+ },
2977
+ {
2978
+ title: labels.memberCount,
2979
+ dataIndex: "member_count",
2980
+ key: "member_count",
2981
+ width: 120,
2982
+ render: (count) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_antd14.Tag, { icon: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_icons13.UserOutlined, {}), children: count })
2983
+ },
2984
+ {
2985
+ title: labels.permissions,
2986
+ dataIndex: "permissions",
2987
+ key: "permissions",
2988
+ render: (permissions) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: permissions.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_antd14.Tag, { color: "blue", children: [
2989
+ permissions.length,
2990
+ " ",
2991
+ labels.permissions
2992
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_antd14.Tag, { children: [
2993
+ "0 ",
2994
+ labels.permissions
2995
+ ] }) })
2996
+ }
2997
+ ];
2998
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_antd14.Card, { children: teams.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2999
+ import_antd14.Empty,
3000
+ {
3001
+ description: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
3002
+ labels.noTeams,
3003
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("br", {}),
3004
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text9, { type: "secondary", style: { fontSize: 12 }, children: labels.teamsFromConsole })
3005
+ ] })
3006
+ }
3007
+ ) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3008
+ import_antd14.Table,
3009
+ {
3010
+ columns,
3011
+ dataSource: teams,
3012
+ rowKey: "id",
3013
+ loading,
3014
+ pagination: { pageSize: 10 },
3015
+ expandable: {
3016
+ expandedRowRender: (record) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: { padding: "8px 0" }, children: [
3017
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text9, { strong: true, style: { marginBottom: 8, display: "block" }, children: [
3018
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_icons13.KeyOutlined, { style: { marginRight: 4 } }),
3019
+ labels.teamPermissions,
3020
+ ":"
3021
+ ] }),
3022
+ record.permissions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text9, { type: "secondary", children: labels.noData }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: record.permissions.map((perm) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_antd14.Tag, { color: "cyan", children: perm }, perm)) })
3023
+ ] })
3024
+ }
3025
+ }
3026
+ ) });
3027
+ }
3028
+
3029
+ // src/ant/theme/AntdThemeProvider.tsx
3030
+ var import_antd15 = require("antd");
3031
+ var import_en_US = __toESM(require("antd/locale/en_US"), 1);
3032
+ var import_ja_JP = __toESM(require("antd/locale/ja_JP"), 1);
3033
+ var import_vi_VN = __toESM(require("antd/locale/vi_VN"), 1);
3034
+ var import_react14 = require("react");
3035
+ var import_jsx_runtime18 = require("react/jsx-runtime");
3036
+ var antdLocales = {
3037
+ ja: import_ja_JP.default,
3038
+ en: import_en_US.default,
3039
+ vi: import_vi_VN.default
3040
+ };
3041
+ var fontFamilies = {
3042
+ // Japanese - CJK optimized fonts
3043
+ ja: "'Noto Sans JP', 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif",
3044
+ // English - Modern western fonts
3045
+ en: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
3046
+ // Vietnamese - Light, clean font with good diacritics
3047
+ vi: "'Inter', 'Nunito Sans', -apple-system, BlinkMacSystemFont, sans-serif"
3048
+ };
3049
+ var themeColors = {
3050
+ dashboard: {
3051
+ primary: "#7C3AED",
3052
+ // Violet
3053
+ siderBg: "#7C3AED",
3054
+ menuDarkItemBg: "#7C3AED",
3055
+ menuDarkSubMenuItemBg: "#6D28D9",
3056
+ menuDarkItemSelectedBg: "#9061F9",
3057
+ menuDarkItemHoverBg: "rgba(144, 97, 249, 0.6)"
3058
+ },
3059
+ admin: {
3060
+ primary: "#64748B",
3061
+ // Slate gray - professional admin look
3062
+ siderBg: "#475569",
3063
+ menuDarkItemBg: "#475569",
3064
+ menuDarkSubMenuItemBg: "#334155",
3065
+ menuDarkItemSelectedBg: "#64748B",
3066
+ menuDarkItemHoverBg: "rgba(100, 116, 139, 0.6)"
3067
+ }
3068
+ };
3069
+ function AntdThemeProvider({ children, variant = "dashboard", setDayjsLocale }) {
3070
+ const locale = useLocale();
3071
+ const antdLocale = antdLocales[locale] ?? import_ja_JP.default;
3072
+ const fontFamily = fontFamilies[locale] ?? fontFamilies.ja;
3073
+ const colors = themeColors[variant];
3074
+ (0, import_react14.useEffect)(() => {
3075
+ setDayjsLocale?.(locale);
3076
+ }, [locale, setDayjsLocale]);
3077
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3078
+ import_antd15.ConfigProvider,
3079
+ {
3080
+ locale: antdLocale,
3081
+ theme: {
3082
+ algorithm: import_antd15.theme.defaultAlgorithm,
3083
+ token: {
3084
+ // ===========================================
3085
+ // Tempofast Design System (HSL-based harmony)
3086
+ // ===========================================
3087
+ // Primary - Dynamic based on variant
3088
+ colorPrimary: colors.primary,
3089
+ colorInfo: colors.primary,
3090
+ // Semantic Colors (Complementary harmony)
3091
+ colorSuccess: "#10B981",
3092
+ // HSL(160, 84%, 39%) - Teal-green, cool tone
3093
+ colorWarning: "#F59E0B",
3094
+ // HSL(38, 92%, 50%) - Amber, warm accent
3095
+ colorError: "#EF4444",
3096
+ // HSL(0, 84%, 60%) - Red, same saturation
3097
+ // Text - Neutral with slight violet undertone
3098
+ colorText: "#1E1B2E",
3099
+ // Near black with violet tint
3100
+ colorTextSecondary: "#4B5563",
3101
+ // Cool gray
3102
+ colorTextTertiary: "#9CA3AF",
3103
+ // Light cool gray
3104
+ // Background - Cool neutrals
3105
+ colorBgLayout: "#F8F7FA",
3106
+ // Very light violet-gray
3107
+ colorBgContainer: "#FFFFFF",
3108
+ colorBgElevated: "#FFFFFF",
3109
+ // Border - Subtle
3110
+ colorBorder: "#E5E7EB",
3111
+ colorBorderSecondary: "#F3F4F6",
3112
+ // Border Radius - Compact
3113
+ borderRadius: 4,
3114
+ borderRadiusSM: 2,
3115
+ borderRadiusLG: 6,
3116
+ // Control Heights - Compact
3117
+ controlHeight: 32,
3118
+ controlHeightLG: 36,
3119
+ controlHeightSM: 28,
3120
+ // Font - Dynamic based on locale
3121
+ fontFamily,
3122
+ fontSize: 13,
3123
+ fontSizeLG: 14,
3124
+ fontSizeHeading1: 24,
3125
+ fontSizeHeading2: 20,
3126
+ fontSizeHeading3: 16,
3127
+ fontSizeHeading4: 14,
3128
+ fontSizeHeading5: 13,
3129
+ // Spacing - Tight
3130
+ padding: 12,
3131
+ paddingLG: 16,
3132
+ paddingSM: 8,
3133
+ paddingXS: 4,
3134
+ margin: 12,
3135
+ marginLG: 16,
3136
+ marginSM: 8,
3137
+ marginXS: 4,
3138
+ // Shadows - Almost flat (Japanese style)
3139
+ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.03)",
3140
+ boxShadowSecondary: "0 1px 3px rgba(0, 0, 0, 0.04)",
3141
+ // Line Height
3142
+ lineHeight: 1.5
3143
+ },
3144
+ components: {
3145
+ // Global icon margin in Space component
3146
+ Space: {
3147
+ marginXS: 6
3148
+ },
3149
+ Button: {
3150
+ controlHeight: 32,
3151
+ paddingInline: 12,
3152
+ fontWeight: 500
3153
+ },
3154
+ Statistic: {
3155
+ contentFontSize: 24,
3156
+ titleFontSize: 13
3157
+ },
3158
+ Input: {
3159
+ controlHeight: 32,
3160
+ paddingInline: 8
3161
+ },
3162
+ Select: {
3163
+ controlHeight: 32
3164
+ },
3165
+ Table: {
3166
+ cellPaddingBlock: 8,
3167
+ cellPaddingInline: 8,
3168
+ headerBg: "#F8F7FA"
3169
+ },
3170
+ Card: {
3171
+ paddingLG: 16
3172
+ },
3173
+ Form: {
3174
+ itemMarginBottom: 16,
3175
+ verticalLabelPadding: "0 0 4px"
3176
+ },
3177
+ Menu: {
3178
+ itemHeight: 36,
3179
+ itemMarginBlock: 2,
3180
+ itemMarginInline: 4,
3181
+ darkItemBg: colors.menuDarkItemBg,
3182
+ darkSubMenuItemBg: colors.menuDarkSubMenuItemBg,
3183
+ darkItemSelectedBg: colors.menuDarkItemSelectedBg,
3184
+ darkItemSelectedColor: "#FFFFFF",
3185
+ darkItemColor: "rgba(255, 255, 255, 0.9)",
3186
+ darkItemHoverBg: colors.menuDarkItemHoverBg,
3187
+ darkItemHoverColor: "#FFFFFF"
3188
+ },
3189
+ Layout: {
3190
+ siderBg: colors.siderBg,
3191
+ headerPadding: "0 16px",
3192
+ headerHeight: 48
3193
+ },
3194
+ Typography: {
3195
+ titleMarginBottom: 8,
3196
+ titleMarginTop: 0
3197
+ },
3198
+ Modal: {
3199
+ paddingContentHorizontalLG: 16
3200
+ },
3201
+ Descriptions: {
3202
+ itemPaddingBottom: 8
3203
+ }
3204
+ }
3205
+ },
3206
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_antd15.App, { children })
3207
+ }
3208
+ );
3209
+ }
3210
+ // Annotate the CommonJS export names for ESM import in node:
3211
+ 0 && (module.exports = {
3212
+ AntdThemeProvider,
3213
+ BranchGate,
3214
+ LocaleSwitcher,
3215
+ OrgBranchSelectorModal,
3216
+ OrganizationSwitcher,
3217
+ PROTABLE_DEFAULT_TEXTS,
3218
+ PageContainer,
3219
+ PermissionsListCard,
3220
+ ProTable,
3221
+ ProtectedRoute,
3222
+ RoleCreateModal,
3223
+ RolesListCard,
3224
+ ScopeLabel,
3225
+ ScopeTag,
3226
+ SsoCallback,
3227
+ TeamsListCard,
3228
+ UserDetailCard,
3229
+ UserPermissionsModal,
3230
+ UserRoleAssignModal,
3231
+ getScopeColor,
3232
+ getScopeIcon,
3233
+ useBranchGate
3234
+ });
3235
+ //# sourceMappingURL=index.cjs.map