@burdenoff/microfe-admin 2026.625.1 → 2026.712.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/admin/AdminRoot.js +2 -2
  2. package/dist/admin/AdminRoot.js.map +1 -1
  3. package/dist/admin/AdminRoutes.js +130 -78
  4. package/dist/admin/AdminRoutes.js.map +1 -1
  5. package/dist/admin/components/AccessDenied.js +2 -2
  6. package/dist/admin/components/AccessDenied.js.map +1 -1
  7. package/dist/admin/components/ActivityFeed.js +4 -4
  8. package/dist/admin/components/ActivityFeed.js.map +1 -1
  9. package/dist/admin/components/Charts.js.map +1 -1
  10. package/dist/admin/components/ConfirmDialog.js +1 -1
  11. package/dist/admin/components/ConfirmDialog.js.map +1 -1
  12. package/dist/admin/components/DataTable.js.map +1 -1
  13. package/dist/admin/components/FormSheet.js +1 -1
  14. package/dist/admin/components/FormSheet.js.map +1 -1
  15. package/dist/admin/components/TenantSsoPanel.js +1 -1
  16. package/dist/admin/components/TenantSsoPanel.js.map +1 -1
  17. package/dist/admin/components/Toast.js +11 -11
  18. package/dist/admin/components/Toast.js.map +1 -1
  19. package/dist/admin/components/forms/SubscriptionForm.js +2 -2
  20. package/dist/admin/components/forms/SubscriptionForm.js.map +1 -1
  21. package/dist/admin/components/forms/TenantForm.js +1 -1
  22. package/dist/admin/components/forms/UserForm.js +1 -1
  23. package/dist/admin/components/ui.js +3 -3
  24. package/dist/admin/components/ui.js.map +1 -1
  25. package/dist/admin/constants/featureFlags.js +12 -0
  26. package/dist/admin/constants/featureFlags.js.map +1 -0
  27. package/dist/admin/constants/index.js +33 -24
  28. package/dist/admin/constants/index.js.map +1 -1
  29. package/dist/admin/pages/AuditLogsPage.js +92 -77
  30. package/dist/admin/pages/AuditLogsPage.js.map +1 -1
  31. package/dist/admin/pages/BillingPage.js +95 -51
  32. package/dist/admin/pages/BillingPage.js.map +1 -1
  33. package/dist/admin/pages/CommunicationsPage.js +97 -92
  34. package/dist/admin/pages/CommunicationsPage.js.map +1 -1
  35. package/dist/admin/pages/ContentPagesPage.js +274 -259
  36. package/dist/admin/pages/ContentPagesPage.js.map +1 -1
  37. package/dist/admin/pages/DashboardPage.js +113 -84
  38. package/dist/admin/pages/DashboardPage.js.map +1 -1
  39. package/dist/admin/pages/FeatureFlagsPage.js +93 -75
  40. package/dist/admin/pages/FeatureFlagsPage.js.map +1 -1
  41. package/dist/admin/pages/OrganizationsListPage.js +105 -87
  42. package/dist/admin/pages/OrganizationsListPage.js.map +1 -1
  43. package/dist/admin/pages/ProductsPage.js +138 -130
  44. package/dist/admin/pages/ProductsPage.js.map +1 -1
  45. package/dist/admin/pages/ReferralsPage.js +70 -52
  46. package/dist/admin/pages/ReferralsPage.js.map +1 -1
  47. package/dist/admin/pages/RolesPermissionsPage.js +136 -118
  48. package/dist/admin/pages/RolesPermissionsPage.js.map +1 -1
  49. package/dist/admin/pages/SREPage.js +34 -32
  50. package/dist/admin/pages/SREPage.js.map +1 -1
  51. package/dist/admin/pages/SandboxSettingsPage.js +360 -322
  52. package/dist/admin/pages/SandboxSettingsPage.js.map +1 -1
  53. package/dist/admin/pages/SettingsPage.js +64 -61
  54. package/dist/admin/pages/SettingsPage.js.map +1 -1
  55. package/dist/admin/pages/SyncFailuresPage.js +120 -118
  56. package/dist/admin/pages/SyncFailuresPage.js.map +1 -1
  57. package/dist/admin/pages/TenantDetailPage.js +286 -231
  58. package/dist/admin/pages/TenantDetailPage.js.map +1 -1
  59. package/dist/admin/pages/TenantFormRoutePage.js +78 -73
  60. package/dist/admin/pages/TenantFormRoutePage.js.map +1 -1
  61. package/dist/admin/pages/TenantsListPage.js +182 -155
  62. package/dist/admin/pages/TenantsListPage.js.map +1 -1
  63. package/dist/admin/pages/UsersListPage.js +128 -113
  64. package/dist/admin/pages/UsersListPage.js.map +1 -1
  65. package/dist/admin/pages/WaitlistPage.js +78 -63
  66. package/dist/admin/pages/WaitlistPage.js.map +1 -1
  67. package/dist/admin/pages/WorkflowsPage.js +107 -102
  68. package/dist/admin/pages/WorkflowsPage.js.map +1 -1
  69. package/dist/admin/pages/WorkspacesListPage.js +61 -49
  70. package/dist/admin/pages/WorkspacesListPage.js.map +1 -1
  71. package/dist/node_modules/@hookform/resolvers/dist/resolvers.js +2 -2
  72. package/dist/node_modules/@hookform/resolvers/dist/resolvers.js.map +1 -1
  73. package/dist/node_modules/@hookform/resolvers/zod/dist/zod.js +35 -26
  74. package/dist/node_modules/@hookform/resolvers/zod/dist/zod.js.map +1 -1
  75. package/dist/node_modules/react-hook-form/dist/index.esm.js +609 -516
  76. package/dist/node_modules/react-hook-form/dist/index.esm.js.map +1 -1
  77. package/package.json +2 -2
@@ -7,7 +7,7 @@ import { jsx as b } from "react/jsx-runtime";
7
7
  import { FeatureFlagProvider as x } from "@burdenoff/fe-libs/shared/feature-flags";
8
8
  //#region src/admin/AdminRoot.tsx
9
9
  var S = (S) => {
10
- let { registerNavItems: C, registerFooterItems: w, basePath: T = "" } = S;
10
+ let { registerNavItems: C, registerFooterItems: w, basePath: T = "", workspaceId: E } = S;
11
11
  return r(() => {
12
12
  if (C) return C([
13
13
  {
@@ -168,7 +168,7 @@ var S = (S) => {
168
168
  section: "left"
169
169
  }]);
170
170
  }, [w]), /* @__PURE__ */ b(x, {
171
- workspaceId: null,
171
+ workspaceId: E || null,
172
172
  gateway: "global",
173
173
  defaultEnabled: !0,
174
174
  children: /* @__PURE__ */ b(e, {
@@ -1 +1 @@
1
- {"version":3,"file":"AdminRoot.js","names":[],"sources":["../../src/admin/AdminRoot.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect } from 'react';\nimport {\n LayoutDashboard,\n Building2,\n Users,\n CreditCard,\n Settings,\n Server,\n Mail,\n FileText,\n Box,\n Building,\n Layout,\n ToggleLeft,\n ShieldCheck,\n GitBranch,\n Link2,\n AlertOctagon,\n} from 'lucide-react';\nimport { AdminProvider } from './providers/AdminProvider';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport type { NavItem, AdminRootProps } from './types';\nimport { AdminRoutes } from './AdminRoutes';\nimport { joinPath } from './utils/navigation';\n\n/**\n * Root component for the Admin microfrontend.\n *\n * This is the main entry point that host applications import and render.\n * It sets up the necessary providers and renders the internal routing.\n * Automatically registers navigation items with the shell if registration functions are provided.\n *\n * @example\n * ```tsx\n * import { AdminRoot, type AdminRootProps } from '@burdenoff/microfe-admin';\n *\n * function App() {\n * const props: AdminRootProps = {\n * basePath: '/admin',\n * navigate: (path) => router.push(path),\n * currentUser: { id: '1', email: 'admin@example.com', role: 'PLATFORM_SUPERADMIN' },\n * tenantId: 'tenant-123',\n * apiGatewayUrl: 'https://api.example.com',\n * authToken: 'token',\n * registerNavItems: (items) => { return () => {}; },\n * };\n *\n * return <AdminRoot {...props} />;\n * }\n * ```\n */\nexport const AdminRoot: FC<AdminRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '' } = props;\n\n // Register navigation items with the shell\n useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n {\n id: 'admin-dashboard',\n label: 'Dashboard',\n path: joinPath(basePath, 'dashboard'),\n icon: <LayoutDashboard size={20} />,\n order: 10,\n group: 'admin',\n },\n {\n id: 'admin-tenants',\n label: 'Tenants',\n path: joinPath(basePath, 'tenants'),\n icon: <Building2 size={20} />,\n order: 20,\n group: 'admin',\n },\n {\n id: 'admin-organizations',\n label: 'Organizations',\n path: joinPath(basePath, 'organizations'),\n icon: <Building size={20} />,\n order: 25,\n group: 'admin',\n },\n {\n id: 'admin-workspaces',\n label: 'Workspaces',\n path: joinPath(basePath, 'workspaces'),\n icon: <Layout size={20} />,\n order: 26,\n group: 'admin',\n },\n {\n id: 'admin-users',\n label: 'Users',\n path: joinPath(basePath, 'users'),\n icon: <Users size={20} />,\n order: 30,\n group: 'admin',\n },\n {\n id: 'admin-roles',\n label: 'Roles & Permissions',\n path: joinPath(basePath, 'roles'),\n icon: <ShieldCheck size={20} />,\n order: 35,\n group: 'admin',\n },\n {\n id: 'admin-billing',\n label: 'Billing',\n path: joinPath(basePath, 'billing'),\n icon: <CreditCard size={20} />,\n order: 40,\n group: 'admin',\n children: [\n {\n id: 'admin-billing-subscriptions',\n label: 'Subscriptions',\n path: joinPath(basePath, 'billing/subscriptions'),\n order: 1,\n },\n {\n id: 'admin-billing-invoices',\n label: 'Invoices',\n path: joinPath(basePath, 'billing/invoices'),\n order: 2,\n },\n {\n id: 'admin-billing-plans',\n label: 'Plans',\n path: joinPath(basePath, 'billing/plans'),\n order: 3,\n },\n ],\n },\n {\n id: 'admin-communications',\n label: 'Communications',\n path: joinPath(basePath, 'communications'),\n icon: <Mail size={20} />,\n order: 50,\n group: 'admin',\n },\n {\n id: 'admin-feature-flags',\n label: 'Feature Flags',\n path: joinPath(basePath, 'feature-flags'),\n icon: <ToggleLeft size={20} />,\n order: 60,\n group: 'admin',\n },\n {\n id: 'admin-workflows',\n label: 'Workflows',\n path: joinPath(basePath, 'workflows'),\n icon: <GitBranch size={20} />,\n order: 70,\n group: 'admin',\n },\n {\n id: 'admin-sre',\n label: 'SRE',\n path: joinPath(basePath, 'sre'),\n icon: <Server size={20} />,\n order: 80,\n group: 'admin',\n },\n {\n id: 'admin-sync-failures',\n label: 'Sync Failures',\n path: joinPath(basePath, 'sync-failures'),\n icon: <AlertOctagon size={20} />,\n order: 82,\n group: 'admin',\n },\n {\n id: 'admin-audit',\n label: 'Audit Logs',\n path: joinPath(basePath, 'audit'),\n icon: <FileText size={20} />,\n order: 85,\n group: 'admin',\n },\n {\n id: 'admin-referrals',\n label: 'Referrals',\n path: joinPath(basePath, 'referrals'),\n icon: <Link2 size={20} />,\n order: 86,\n group: 'admin',\n },\n {\n id: 'admin-sandbox',\n label: 'Sandbox',\n path: joinPath(basePath, 'sandbox'),\n icon: <Box size={20} />,\n order: 87,\n group: 'admin',\n },\n {\n id: 'admin-settings',\n label: 'Settings',\n path: joinPath(basePath, 'settings'),\n icon: <Settings size={20} />,\n order: 90,\n group: 'admin',\n },\n ];\n\n // Register and get cleanup function\n const cleanup = registerNavItems(navItems);\n\n // Return cleanup function to unregister on unmount\n return cleanup;\n }, [registerNavItems, basePath]);\n\n // Register footer items\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: 'admin-status',\n label: 'Admin Console Ready',\n type: 'status' as const,\n order: 10,\n section: 'left' as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems]);\n\n return (\n <FeatureFlagProvider workspaceId={null} gateway=\"global\" defaultEnabled={true}>\n <AdminProvider {...props}>\n <AdminRoutes />\n </AdminProvider>\n </FeatureFlagProvider>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdminRoot.js","names":[],"sources":["../../src/admin/AdminRoot.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect } from 'react';\nimport {\n LayoutDashboard,\n Building2,\n Users,\n CreditCard,\n Settings,\n Server,\n Mail,\n FileText,\n Box,\n Building,\n Layout,\n ToggleLeft,\n ShieldCheck,\n GitBranch,\n Link2,\n AlertOctagon,\n} from 'lucide-react';\nimport { AdminProvider } from './providers/AdminProvider';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport type { NavItem, AdminRootProps } from './types';\nimport { AdminRoutes } from './AdminRoutes';\nimport { joinPath } from './utils/navigation';\n\n/**\n * Root component for the Admin microfrontend.\n *\n * This is the main entry point that host applications import and render.\n * It sets up the necessary providers and renders the internal routing.\n * Automatically registers navigation items with the shell if registration functions are provided.\n *\n * @example\n * ```tsx\n * import { AdminRoot, type AdminRootProps } from '@burdenoff/microfe-admin';\n *\n * function App() {\n * const props: AdminRootProps = {\n * basePath: '/admin',\n * navigate: (path) => router.push(path),\n * currentUser: { id: '1', email: 'admin@example.com', role: 'PLATFORM_SUPERADMIN' },\n * tenantId: 'tenant-123',\n * apiGatewayUrl: 'https://api.example.com',\n * authToken: 'token',\n * registerNavItems: (items) => { return () => {}; },\n * };\n *\n * return <AdminRoot {...props} />;\n * }\n * ```\n */\nexport const AdminRoot: FC<AdminRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '', workspaceId } = props;\n\n // Register navigation items with the shell\n useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n {\n id: 'admin-dashboard',\n label: 'Dashboard',\n path: joinPath(basePath, 'dashboard'),\n icon: <LayoutDashboard size={20} />,\n order: 10,\n group: 'admin',\n },\n {\n id: 'admin-tenants',\n label: 'Tenants',\n path: joinPath(basePath, 'tenants'),\n icon: <Building2 size={20} />,\n order: 20,\n group: 'admin',\n },\n {\n id: 'admin-organizations',\n label: 'Organizations',\n path: joinPath(basePath, 'organizations'),\n icon: <Building size={20} />,\n order: 25,\n group: 'admin',\n },\n {\n id: 'admin-workspaces',\n label: 'Workspaces',\n path: joinPath(basePath, 'workspaces'),\n icon: <Layout size={20} />,\n order: 26,\n group: 'admin',\n },\n {\n id: 'admin-users',\n label: 'Users',\n path: joinPath(basePath, 'users'),\n icon: <Users size={20} />,\n order: 30,\n group: 'admin',\n },\n {\n id: 'admin-roles',\n label: 'Roles & Permissions',\n path: joinPath(basePath, 'roles'),\n icon: <ShieldCheck size={20} />,\n order: 35,\n group: 'admin',\n },\n {\n id: 'admin-billing',\n label: 'Billing',\n path: joinPath(basePath, 'billing'),\n icon: <CreditCard size={20} />,\n order: 40,\n group: 'admin',\n children: [\n {\n id: 'admin-billing-subscriptions',\n label: 'Subscriptions',\n path: joinPath(basePath, 'billing/subscriptions'),\n order: 1,\n },\n {\n id: 'admin-billing-invoices',\n label: 'Invoices',\n path: joinPath(basePath, 'billing/invoices'),\n order: 2,\n },\n {\n id: 'admin-billing-plans',\n label: 'Plans',\n path: joinPath(basePath, 'billing/plans'),\n order: 3,\n },\n ],\n },\n {\n id: 'admin-communications',\n label: 'Communications',\n path: joinPath(basePath, 'communications'),\n icon: <Mail size={20} />,\n order: 50,\n group: 'admin',\n },\n {\n id: 'admin-feature-flags',\n label: 'Feature Flags',\n path: joinPath(basePath, 'feature-flags'),\n icon: <ToggleLeft size={20} />,\n order: 60,\n group: 'admin',\n },\n {\n id: 'admin-workflows',\n label: 'Workflows',\n path: joinPath(basePath, 'workflows'),\n icon: <GitBranch size={20} />,\n order: 70,\n group: 'admin',\n },\n {\n id: 'admin-sre',\n label: 'SRE',\n path: joinPath(basePath, 'sre'),\n icon: <Server size={20} />,\n order: 80,\n group: 'admin',\n },\n {\n id: 'admin-sync-failures',\n label: 'Sync Failures',\n path: joinPath(basePath, 'sync-failures'),\n icon: <AlertOctagon size={20} />,\n order: 82,\n group: 'admin',\n },\n {\n id: 'admin-audit',\n label: 'Audit Logs',\n path: joinPath(basePath, 'audit'),\n icon: <FileText size={20} />,\n order: 85,\n group: 'admin',\n },\n {\n id: 'admin-referrals',\n label: 'Referrals',\n path: joinPath(basePath, 'referrals'),\n icon: <Link2 size={20} />,\n order: 86,\n group: 'admin',\n },\n {\n id: 'admin-sandbox',\n label: 'Sandbox',\n path: joinPath(basePath, 'sandbox'),\n icon: <Box size={20} />,\n order: 87,\n group: 'admin',\n },\n {\n id: 'admin-settings',\n label: 'Settings',\n path: joinPath(basePath, 'settings'),\n icon: <Settings size={20} />,\n order: 90,\n group: 'admin',\n },\n ];\n\n // Register and get cleanup function\n const cleanup = registerNavItems(navItems);\n\n // Return cleanup function to unregister on unmount\n return cleanup;\n }, [registerNavItems, basePath]);\n\n // Register footer items\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: 'admin-status',\n label: 'Admin Console Ready',\n type: 'status' as const,\n order: 10,\n section: 'left' as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems]);\n\n return (\n <FeatureFlagProvider workspaceId={workspaceId || null} gateway=\"global\" defaultEnabled={true}>\n <AdminProvider {...props}>\n <AdminRoutes />\n </AdminProvider>\n </FeatureFlagProvider>\n );\n};\n"],"mappings":"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"}
@@ -1,144 +1,196 @@
1
1
  import { useAdmin as e } from "./providers/AdminProvider.js";
2
- import { DashboardPage as t } from "./pages/DashboardPage.js";
2
+ import { tWithFallback as t } from "./utils/i18n.js";
3
+ import { DashboardPage as n } from "./pages/DashboardPage.js";
4
+ import { TENANT_FEATURE_FLAGS as r } from "./constants/featureFlags.js";
3
5
  import "./pages/index.js";
4
- import { Suspense as n, lazy as r } from "react";
5
- import { Navigate as i, Route as a, Routes as o } from "react-router-dom";
6
- import { jsx as s, jsxs as c } from "react/jsx-runtime";
6
+ import { Suspense as i, lazy as a } from "react";
7
+ import { Navigate as o, Route as s, Routes as c } from "react-router-dom";
8
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
9
+ import { FeatureGate as d } from "@burdenoff/fe-libs/shared/feature-flags";
10
+ import { useI18n as f } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
7
11
  //#region src/admin/AdminRoutes.tsx
8
- var l = r(() => import("./pages/TenantsListPage.js").then((e) => ({ default: e.TenantsListPage }))), u = r(() => import("./pages/TenantDetailPage.js").then((e) => ({ default: e.TenantDetailPage }))), d = r(() => import("./pages/TenantFormRoutePage.js").then((e) => ({ default: e.TenantFormRoutePage }))), f = r(() => import("./pages/UsersListPage.js").then((e) => ({ default: e.UsersListPage }))), p = r(() => import("./pages/BillingPage.js").then((e) => ({ default: e.BillingPage }))), m = r(() => import("./pages/SettingsPage.js").then((e) => ({ default: e.SettingsPage }))), h = r(() => import("./pages/CommunicationsPage.js").then((e) => ({ default: e.CommunicationsPage }))), g = r(() => import("./pages/SREPage.js").then((e) => ({ default: e.SREPage }))), _ = r(() => import("./pages/SyncFailuresPage.js").then((e) => ({ default: e.SyncFailuresPage }))), v = r(() => import("./pages/AuditLogsPage.js").then((e) => ({ default: e.AuditLogsPage }))), y = r(() => import("./pages/SandboxSettingsPage.js").then((e) => ({ default: e.SandboxSettingsPage }))), b = r(() => import("./pages/OrganizationsListPage.js").then((e) => ({ default: e.OrganizationsListPage }))), x = r(() => import("./pages/WorkspacesListPage.js").then((e) => ({ default: e.WorkspacesListPage }))), S = r(() => import("./pages/FeatureFlagsPage.js").then((e) => ({ default: e.FeatureFlagsPage }))), C = r(() => import("./pages/RolesPermissionsPage.js").then((e) => ({ default: e.RolesPermissionsPage }))), w = r(() => import("./pages/WorkflowsPage.js").then((e) => ({ default: e.WorkflowsPage }))), T = r(() => import("./pages/ProductsPage.js").then((e) => ({ default: e.ProductsPage }))), E = r(() => import("./pages/ContentPagesPage.js").then((e) => ({ default: e.ContentPagesPage }))), D = r(() => import("./pages/WaitlistPage.js").then((e) => ({ default: e.WaitlistPage }))), O = r(() => import("./pages/ReferralsPage.js").then((e) => ({ default: e.ReferralsPage })));
9
- function k() {
10
- return /* @__PURE__ */ s("div", {
12
+ var p = a(() => import("./pages/TenantsListPage.js").then((e) => ({ default: e.TenantsListPage }))), m = a(() => import("./pages/TenantDetailPage.js").then((e) => ({ default: e.TenantDetailPage }))), h = a(() => import("./pages/TenantFormRoutePage.js").then((e) => ({ default: e.TenantFormRoutePage }))), g = a(() => import("./pages/UsersListPage.js").then((e) => ({ default: e.UsersListPage }))), _ = a(() => import("./pages/BillingPage.js").then((e) => ({ default: e.BillingPage }))), v = a(() => import("./pages/SettingsPage.js").then((e) => ({ default: e.SettingsPage }))), y = a(() => import("./pages/CommunicationsPage.js").then((e) => ({ default: e.CommunicationsPage }))), b = a(() => import("./pages/SREPage.js").then((e) => ({ default: e.SREPage }))), x = a(() => import("./pages/SyncFailuresPage.js").then((e) => ({ default: e.SyncFailuresPage }))), S = a(() => import("./pages/AuditLogsPage.js").then((e) => ({ default: e.AuditLogsPage }))), C = a(() => import("./pages/SandboxSettingsPage.js").then((e) => ({ default: e.SandboxSettingsPage }))), w = a(() => import("./pages/OrganizationsListPage.js").then((e) => ({ default: e.OrganizationsListPage }))), T = a(() => import("./pages/WorkspacesListPage.js").then((e) => ({ default: e.WorkspacesListPage }))), E = a(() => import("./pages/FeatureFlagsPage.js").then((e) => ({ default: e.FeatureFlagsPage }))), D = a(() => import("./pages/RolesPermissionsPage.js").then((e) => ({ default: e.RolesPermissionsPage }))), O = a(() => import("./pages/WorkflowsPage.js").then((e) => ({ default: e.WorkflowsPage }))), k = a(() => import("./pages/ProductsPage.js").then((e) => ({ default: e.ProductsPage }))), A = a(() => import("./pages/ContentPagesPage.js").then((e) => ({ default: e.ContentPagesPage }))), j = a(() => import("./pages/WaitlistPage.js").then((e) => ({ default: e.WaitlistPage }))), M = a(() => import("./pages/ReferralsPage.js").then((e) => ({ default: e.ReferralsPage })));
13
+ function N() {
14
+ return /* @__PURE__ */ l("div", {
11
15
  className: "flex h-64 items-center justify-center",
12
- children: /* @__PURE__ */ s("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" })
16
+ children: /* @__PURE__ */ l("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" })
13
17
  });
14
18
  }
15
- function A() {
16
- let { basePath: r } = e(), A = r || "/admin";
17
- return /* @__PURE__ */ s(n, {
18
- fallback: /* @__PURE__ */ s(k, {}),
19
- children: /* @__PURE__ */ c(o, { children: [
20
- /* @__PURE__ */ s(a, {
19
+ function P() {
20
+ let { t: e } = f();
21
+ return /* @__PURE__ */ l("div", {
22
+ className: "flex min-h-[400px] items-center justify-center p-8 text-center",
23
+ children: /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("h2", {
24
+ className: "mb-2 text-lg font-semibold text-foreground",
25
+ children: t(e, "admin.routes.tenantFeatureDisabledTitle", "Tenant management unavailable")
26
+ }), /* @__PURE__ */ l("p", {
27
+ className: "text-sm text-muted-foreground",
28
+ children: t(e, "admin.routes.tenantFeatureDisabled", "This feature is currently disabled.")
29
+ })] })
30
+ });
31
+ }
32
+ function F(e, t, n) {
33
+ return /* @__PURE__ */ l(d, {
34
+ flag: e,
35
+ defaultValue: n,
36
+ fallback: /* @__PURE__ */ l(P, {}),
37
+ children: t
38
+ });
39
+ }
40
+ function I(e, t) {
41
+ return e.reduceRight((e, t) => F(t.flag, e, t.defaultValue), t);
42
+ }
43
+ function L() {
44
+ let { basePath: t } = e(), a = t || "/admin";
45
+ return /* @__PURE__ */ l(i, {
46
+ fallback: /* @__PURE__ */ l(N, {}),
47
+ children: /* @__PURE__ */ u(c, { children: [
48
+ /* @__PURE__ */ l(s, {
21
49
  index: !0,
22
- element: /* @__PURE__ */ s(i, {
23
- to: `${A}/dashboard`,
50
+ element: /* @__PURE__ */ l(o, {
51
+ to: `${a}/dashboard`,
24
52
  replace: !0
25
53
  })
26
54
  }),
27
- /* @__PURE__ */ s(a, {
55
+ /* @__PURE__ */ l(s, {
28
56
  path: "dashboard",
29
- element: /* @__PURE__ */ s(t, {})
57
+ element: /* @__PURE__ */ l(n, {})
30
58
  }),
31
- /* @__PURE__ */ s(a, {
59
+ /* @__PURE__ */ l(s, {
32
60
  path: "tenants",
33
- element: /* @__PURE__ */ s(l, {})
34
- }),
35
- /* @__PURE__ */ s(a, {
61
+ element: I([{
62
+ flag: r.management,
63
+ defaultValue: !0
64
+ }, {
65
+ flag: r.list,
66
+ defaultValue: !0
67
+ }], /* @__PURE__ */ l(p, {}))
68
+ }),
69
+ /* @__PURE__ */ l(s, {
36
70
  path: "tenants/new",
37
- element: /* @__PURE__ */ s(d, { mode: "create" })
38
- }),
39
- /* @__PURE__ */ s(a, {
71
+ element: I([{
72
+ flag: r.management,
73
+ defaultValue: !0
74
+ }, {
75
+ flag: r.create,
76
+ defaultValue: !0
77
+ }], /* @__PURE__ */ l(h, { mode: "create" }))
78
+ }),
79
+ /* @__PURE__ */ l(s, {
40
80
  path: "tenants/:tenantId",
41
- element: /* @__PURE__ */ s(u, {})
42
- }),
43
- /* @__PURE__ */ s(a, {
81
+ element: I([{
82
+ flag: r.management,
83
+ defaultValue: !0
84
+ }, {
85
+ flag: r.detail,
86
+ defaultValue: !0
87
+ }], /* @__PURE__ */ l(m, {}))
88
+ }),
89
+ /* @__PURE__ */ l(s, {
44
90
  path: "tenants/:tenantId/edit",
45
- element: /* @__PURE__ */ s(d, { mode: "edit" })
46
- }),
47
- /* @__PURE__ */ s(a, {
91
+ element: I([{
92
+ flag: r.management,
93
+ defaultValue: !0
94
+ }, {
95
+ flag: r.edit,
96
+ defaultValue: !0
97
+ }], /* @__PURE__ */ l(h, { mode: "edit" }))
98
+ }),
99
+ /* @__PURE__ */ l(s, {
48
100
  path: "organizations",
49
- element: /* @__PURE__ */ s(b, {})
101
+ element: /* @__PURE__ */ l(w, {})
50
102
  }),
51
- /* @__PURE__ */ s(a, {
103
+ /* @__PURE__ */ l(s, {
52
104
  path: "workspaces",
53
- element: /* @__PURE__ */ s(x, {})
105
+ element: /* @__PURE__ */ l(T, {})
54
106
  }),
55
- /* @__PURE__ */ s(a, {
107
+ /* @__PURE__ */ l(s, {
56
108
  path: "users",
57
- element: /* @__PURE__ */ s(f, {})
109
+ element: /* @__PURE__ */ l(g, {})
58
110
  }),
59
- /* @__PURE__ */ s(a, {
111
+ /* @__PURE__ */ l(s, {
60
112
  path: "users/:userId",
61
- element: /* @__PURE__ */ s(f, {})
113
+ element: /* @__PURE__ */ l(g, {})
62
114
  }),
63
- /* @__PURE__ */ s(a, {
115
+ /* @__PURE__ */ l(s, {
64
116
  path: "roles",
65
- element: /* @__PURE__ */ s(C, {})
117
+ element: /* @__PURE__ */ l(D, {})
66
118
  }),
67
- /* @__PURE__ */ s(a, {
119
+ /* @__PURE__ */ l(s, {
68
120
  path: "feature-flags",
69
- element: /* @__PURE__ */ s(S, {})
121
+ element: /* @__PURE__ */ l(E, {})
70
122
  }),
71
- /* @__PURE__ */ s(a, {
123
+ /* @__PURE__ */ l(s, {
72
124
  path: "workflows",
73
- element: /* @__PURE__ */ s(w, {})
125
+ element: /* @__PURE__ */ l(O, {})
74
126
  }),
75
- /* @__PURE__ */ s(a, {
127
+ /* @__PURE__ */ l(s, {
76
128
  path: "billing",
77
- element: /* @__PURE__ */ s(p, {})
129
+ element: /* @__PURE__ */ l(_, {})
78
130
  }),
79
- /* @__PURE__ */ s(a, {
131
+ /* @__PURE__ */ l(s, {
80
132
  path: "billing/subscriptions",
81
- element: /* @__PURE__ */ s(p, {})
133
+ element: /* @__PURE__ */ l(_, {})
82
134
  }),
83
- /* @__PURE__ */ s(a, {
135
+ /* @__PURE__ */ l(s, {
84
136
  path: "billing/invoices",
85
- element: /* @__PURE__ */ s(p, {})
137
+ element: /* @__PURE__ */ l(_, {})
86
138
  }),
87
- /* @__PURE__ */ s(a, {
139
+ /* @__PURE__ */ l(s, {
88
140
  path: "billing/plans",
89
- element: /* @__PURE__ */ s(p, {})
141
+ element: /* @__PURE__ */ l(_, {})
90
142
  }),
91
- /* @__PURE__ */ s(a, {
143
+ /* @__PURE__ */ l(s, {
92
144
  path: "support/*",
93
- element: /* @__PURE__ */ s(i, {
145
+ element: /* @__PURE__ */ l(o, {
94
146
  to: "/support",
95
147
  replace: !0
96
148
  })
97
149
  }),
98
- /* @__PURE__ */ s(a, {
150
+ /* @__PURE__ */ l(s, {
99
151
  path: "communications",
100
- element: /* @__PURE__ */ s(h, {})
152
+ element: /* @__PURE__ */ l(y, {})
101
153
  }),
102
- /* @__PURE__ */ s(a, {
154
+ /* @__PURE__ */ l(s, {
103
155
  path: "sre",
104
- element: /* @__PURE__ */ s(g, {})
156
+ element: /* @__PURE__ */ l(b, {})
105
157
  }),
106
- /* @__PURE__ */ s(a, {
158
+ /* @__PURE__ */ l(s, {
107
159
  path: "sync-failures",
108
- element: /* @__PURE__ */ s(_, {})
160
+ element: /* @__PURE__ */ l(x, {})
109
161
  }),
110
- /* @__PURE__ */ s(a, {
162
+ /* @__PURE__ */ l(s, {
111
163
  path: "audit",
112
- element: /* @__PURE__ */ s(v, {})
164
+ element: /* @__PURE__ */ l(S, {})
113
165
  }),
114
- /* @__PURE__ */ s(a, {
166
+ /* @__PURE__ */ l(s, {
115
167
  path: "referrals",
116
- element: /* @__PURE__ */ s(O, {})
168
+ element: /* @__PURE__ */ l(M, {})
117
169
  }),
118
- /* @__PURE__ */ s(a, {
170
+ /* @__PURE__ */ l(s, {
119
171
  path: "sandbox",
120
- element: /* @__PURE__ */ s(y, {})
172
+ element: /* @__PURE__ */ l(C, {})
121
173
  }),
122
- /* @__PURE__ */ s(a, {
174
+ /* @__PURE__ */ l(s, {
123
175
  path: "products",
124
- element: /* @__PURE__ */ s(T, {})
176
+ element: /* @__PURE__ */ l(k, {})
125
177
  }),
126
- /* @__PURE__ */ s(a, {
178
+ /* @__PURE__ */ l(s, {
127
179
  path: "content",
128
- element: /* @__PURE__ */ s(E, {})
180
+ element: /* @__PURE__ */ l(A, {})
129
181
  }),
130
- /* @__PURE__ */ s(a, {
182
+ /* @__PURE__ */ l(s, {
131
183
  path: "waitlist",
132
- element: /* @__PURE__ */ s(D, {})
184
+ element: /* @__PURE__ */ l(j, {})
133
185
  }),
134
- /* @__PURE__ */ s(a, {
186
+ /* @__PURE__ */ l(s, {
135
187
  path: "settings",
136
- element: /* @__PURE__ */ s(m, {})
188
+ element: /* @__PURE__ */ l(v, {})
137
189
  }),
138
- /* @__PURE__ */ s(a, {
190
+ /* @__PURE__ */ l(s, {
139
191
  path: "*",
140
- element: /* @__PURE__ */ s(i, {
141
- to: `${A}/dashboard`,
192
+ element: /* @__PURE__ */ l(o, {
193
+ to: `${a}/dashboard`,
142
194
  replace: !0
143
195
  })
144
196
  })
@@ -146,6 +198,6 @@ function A() {
146
198
  });
147
199
  }
148
200
  //#endregion
149
- export { A as AdminRoutes };
201
+ export { L as AdminRoutes };
150
202
 
151
203
  //# sourceMappingURL=AdminRoutes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdminRoutes.js","names":[],"sources":["../../src/admin/AdminRoutes.tsx"],"sourcesContent":["import { lazy, Suspense } from 'react';\nimport { Navigate, Route, Routes } from 'react-router-dom';\nimport { DashboardPage } from './pages';\nimport { useAdmin } from './providers/AdminProvider';\n\n// Lazy loaded pages\nconst TenantsListPage = lazy(() =>\n import('./pages/TenantsListPage').then((m) => ({ default: m.TenantsListPage }))\n);\nconst TenantDetailPage = lazy(() =>\n import('./pages/TenantDetailPage').then((m) => ({ default: m.TenantDetailPage }))\n);\nconst TenantFormRoutePage = lazy(() =>\n import('./pages/TenantFormRoutePage').then((m) => ({ default: m.TenantFormRoutePage }))\n);\nconst UsersListPage = lazy(() =>\n import('./pages/UsersListPage').then((m) => ({ default: m.UsersListPage }))\n);\nconst BillingPage = lazy(() =>\n import('./pages/BillingPage').then((m) => ({ default: m.BillingPage }))\n);\nconst SettingsPage = lazy(() =>\n import('./pages/SettingsPage').then((m) => ({ default: m.SettingsPage }))\n);\nconst CommunicationsPage = lazy(() =>\n import('./pages/CommunicationsPage').then((m) => ({ default: m.CommunicationsPage }))\n);\nconst SREPage = lazy(() => import('./pages/SREPage').then((m) => ({ default: m.SREPage })));\nconst SyncFailuresPage = lazy(() =>\n import('./pages/SyncFailuresPage').then((m) => ({ default: m.SyncFailuresPage }))\n);\nconst AuditLogsPage = lazy(() =>\n import('./pages/AuditLogsPage').then((m) => ({ default: m.AuditLogsPage }))\n);\nconst SandboxSettingsPage = lazy(() =>\n import('./pages/SandboxSettingsPage').then((m) => ({ default: m.SandboxSettingsPage }))\n);\nconst OrganizationsListPage = lazy(() =>\n import('./pages/OrganizationsListPage').then((m) => ({ default: m.OrganizationsListPage }))\n);\nconst WorkspacesListPage = lazy(() =>\n import('./pages/WorkspacesListPage').then((m) => ({ default: m.WorkspacesListPage }))\n);\nconst FeatureFlagsPage = lazy(() =>\n import('./pages/FeatureFlagsPage').then((m) => ({ default: m.FeatureFlagsPage }))\n);\nconst RolesPermissionsPage = lazy(() =>\n import('./pages/RolesPermissionsPage').then((m) => ({ default: m.RolesPermissionsPage }))\n);\nconst WorkflowsPage = lazy(() =>\n import('./pages/WorkflowsPage').then((m) => ({ default: m.WorkflowsPage }))\n);\nconst ProductsPage = lazy(() =>\n import('./pages/ProductsPage').then((m) => ({ default: m.ProductsPage }))\n);\nconst ContentPagesPage = lazy(() =>\n import('./pages/ContentPagesPage').then((m) => ({ default: m.ContentPagesPage }))\n);\nconst WaitlistPage = lazy(() =>\n import('./pages/WaitlistPage').then((m) => ({ default: m.WaitlistPage }))\n);\nconst ReferralsPage = lazy(() =>\n import('./pages/ReferralsPage').then((m) => ({ default: m.ReferralsPage }))\n);\n\n// Loading fallback component\nfunction PageLoader() {\n return (\n <div className=\"flex h-64 items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent\" />\n </div>\n );\n}\n\n/**\n * Internal router for the Admin microfrontend.\n * This component handles routing within the microfrontend using React Router v7.\n *\n * Routes:\n * - / → Dashboard (redirect)\n * - /dashboard → Dashboard\n * - /tenants → Tenants list\n * - /tenants/new → Create new tenant\n * - /tenants/:tenantId → Tenant detail\n * - /tenants/:tenantId/edit → Edit tenant\n * - /users → Users list\n * - /users/:userId → User detail\n * - /billing → Billing overview\n * - /billing/subscriptions → Subscriptions list\n * - /billing/invoices → Invoices list\n * - /billing/plans → Plans management\n * - /support → Support overview\n * - /support/tickets → Tickets list\n * - /support/tickets/:ticketId → Ticket detail\n * - /products → Products management\n * - /communications → Communications center\n * - /sre → SRE Monitoring\n * - /audit → Audit logs\n * - /sandbox → Sandbox settings\n * - /settings → Settings\n */\nexport function AdminRoutes() {\n const { basePath } = useAdmin();\n const base = basePath || '/admin';\n\n return (\n <Suspense fallback={<PageLoader />}>\n <Routes>\n {/* Default redirect to dashboard */}\n <Route index element={<Navigate to={`${base}/dashboard`} replace />} />\n\n {/* Dashboard - eager loaded for fast initial render */}\n <Route path=\"dashboard\" element={<DashboardPage />} />\n\n {/* Tenants */}\n <Route path=\"tenants\" element={<TenantsListPage />} />\n <Route path=\"tenants/new\" element={<TenantFormRoutePage mode=\"create\" />} />\n <Route path=\"tenants/:tenantId\" element={<TenantDetailPage />} />\n <Route path=\"tenants/:tenantId/edit\" element={<TenantFormRoutePage mode=\"edit\" />} />\n\n {/* Organizations */}\n <Route path=\"organizations\" element={<OrganizationsListPage />} />\n\n {/* Workspaces */}\n <Route path=\"workspaces\" element={<WorkspacesListPage />} />\n\n {/* Users */}\n <Route path=\"users\" element={<UsersListPage />} />\n <Route path=\"users/:userId\" element={<UsersListPage />} />\n\n {/* Roles & Permissions */}\n <Route path=\"roles\" element={<RolesPermissionsPage />} />\n\n {/* Feature Flags */}\n <Route path=\"feature-flags\" element={<FeatureFlagsPage />} />\n\n {/* Workflows */}\n <Route path=\"workflows\" element={<WorkflowsPage />} />\n\n {/* Billing */}\n <Route path=\"billing\" element={<BillingPage />} />\n <Route path=\"billing/subscriptions\" element={<BillingPage />} />\n <Route path=\"billing/invoices\" element={<BillingPage />} />\n <Route path=\"billing/plans\" element={<BillingPage />} />\n\n {/* Support — redirects to shell-level /support/* route (microfe-support MFE) */}\n <Route path=\"support/*\" element={<Navigate to=\"/support\" replace />} />\n\n {/* Communications */}\n <Route path=\"communications\" element={<CommunicationsPage />} />\n\n {/* SRE Monitoring */}\n <Route path=\"sre\" element={<SREPage />} />\n\n {/* Sync Failures (cross-layer sync outbox) */}\n <Route path=\"sync-failures\" element={<SyncFailuresPage />} />\n\n {/* Audit Logs */}\n <Route path=\"audit\" element={<AuditLogsPage />} />\n\n {/* Referrals */}\n <Route path=\"referrals\" element={<ReferralsPage />} />\n\n {/* Sandbox */}\n <Route path=\"sandbox\" element={<SandboxSettingsPage />} />\n\n {/* Products */}\n <Route path=\"products\" element={<ProductsPage />} />\n\n {/* Content (blog / case studies / changelog) */}\n <Route path=\"content\" element={<ContentPagesPage />} />\n\n {/* Waitlist */}\n <Route path=\"waitlist\" element={<WaitlistPage />} />\n\n {/* Settings */}\n <Route path=\"settings\" element={<SettingsPage />} />\n\n {/* Catch-all route - redirect to dashboard (absolute path to prevent infinite loops) */}\n <Route path=\"*\" element={<Navigate to={`${base}/dashboard`} replace />} />\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdminRoutes.js","names":[],"sources":["../../src/admin/AdminRoutes.tsx"],"sourcesContent":["import { lazy, Suspense } from 'react';\nimport type { ReactElement, ReactNode } from 'react';\nimport { Navigate, Route, Routes } from 'react-router-dom';\nimport { FeatureGate } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { DashboardPage } from './pages';\nimport { useAdmin } from './providers/AdminProvider';\nimport { TENANT_FEATURE_FLAGS } from './constants/featureFlags';\nimport { tWithFallback } from './utils/i18n';\n\n// Lazy loaded pages\nconst TenantsListPage = lazy(() =>\n import('./pages/TenantsListPage').then((m) => ({ default: m.TenantsListPage }))\n);\nconst TenantDetailPage = lazy(() =>\n import('./pages/TenantDetailPage').then((m) => ({ default: m.TenantDetailPage }))\n);\nconst TenantFormRoutePage = lazy(() =>\n import('./pages/TenantFormRoutePage').then((m) => ({ default: m.TenantFormRoutePage }))\n);\nconst UsersListPage = lazy(() =>\n import('./pages/UsersListPage').then((m) => ({ default: m.UsersListPage }))\n);\nconst BillingPage = lazy(() =>\n import('./pages/BillingPage').then((m) => ({ default: m.BillingPage }))\n);\nconst SettingsPage = lazy(() =>\n import('./pages/SettingsPage').then((m) => ({ default: m.SettingsPage }))\n);\nconst CommunicationsPage = lazy(() =>\n import('./pages/CommunicationsPage').then((m) => ({ default: m.CommunicationsPage }))\n);\nconst SREPage = lazy(() => import('./pages/SREPage').then((m) => ({ default: m.SREPage })));\nconst SyncFailuresPage = lazy(() =>\n import('./pages/SyncFailuresPage').then((m) => ({ default: m.SyncFailuresPage }))\n);\nconst AuditLogsPage = lazy(() =>\n import('./pages/AuditLogsPage').then((m) => ({ default: m.AuditLogsPage }))\n);\nconst SandboxSettingsPage = lazy(() =>\n import('./pages/SandboxSettingsPage').then((m) => ({ default: m.SandboxSettingsPage }))\n);\nconst OrganizationsListPage = lazy(() =>\n import('./pages/OrganizationsListPage').then((m) => ({ default: m.OrganizationsListPage }))\n);\nconst WorkspacesListPage = lazy(() =>\n import('./pages/WorkspacesListPage').then((m) => ({ default: m.WorkspacesListPage }))\n);\nconst FeatureFlagsPage = lazy(() =>\n import('./pages/FeatureFlagsPage').then((m) => ({ default: m.FeatureFlagsPage }))\n);\nconst RolesPermissionsPage = lazy(() =>\n import('./pages/RolesPermissionsPage').then((m) => ({ default: m.RolesPermissionsPage }))\n);\nconst WorkflowsPage = lazy(() =>\n import('./pages/WorkflowsPage').then((m) => ({ default: m.WorkflowsPage }))\n);\nconst ProductsPage = lazy(() =>\n import('./pages/ProductsPage').then((m) => ({ default: m.ProductsPage }))\n);\nconst ContentPagesPage = lazy(() =>\n import('./pages/ContentPagesPage').then((m) => ({ default: m.ContentPagesPage }))\n);\nconst WaitlistPage = lazy(() =>\n import('./pages/WaitlistPage').then((m) => ({ default: m.WaitlistPage }))\n);\nconst ReferralsPage = lazy(() =>\n import('./pages/ReferralsPage').then((m) => ({ default: m.ReferralsPage }))\n);\n\n// Loading fallback component\nfunction PageLoader() {\n return (\n <div className=\"flex h-64 items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent\" />\n </div>\n );\n}\n\nfunction FeatureDisabledFallback() {\n const { t } = useI18n();\n\n return (\n <div className=\"flex min-h-[400px] items-center justify-center p-8 text-center\">\n <div>\n <h2 className=\"mb-2 text-lg font-semibold text-foreground\">\n {tWithFallback(\n t,\n 'admin.routes.tenantFeatureDisabledTitle',\n 'Tenant management unavailable'\n )}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {tWithFallback(\n t,\n 'admin.routes.tenantFeatureDisabled',\n 'This feature is currently disabled.'\n )}\n </p>\n </div>\n </div>\n );\n}\n\nfunction gated(flag: string, element: ReactNode, defaultValue: boolean): ReactElement {\n return (\n <FeatureGate flag={flag} defaultValue={defaultValue} fallback={<FeatureDisabledFallback />}>\n {element}\n </FeatureGate>\n );\n}\n\nfunction gatedAll(\n gates: Array<{ flag: string; defaultValue: boolean }>,\n element: ReactElement\n): ReactElement {\n return gates.reduceRight((child, gate) => gated(gate.flag, child, gate.defaultValue), element);\n}\n\n/**\n * Internal router for the Admin microfrontend.\n * This component handles routing within the microfrontend using React Router v7.\n *\n * Routes:\n * - / → Dashboard (redirect)\n * - /dashboard → Dashboard\n * - /tenants → Tenants list\n * - /tenants/new → Create new tenant\n * - /tenants/:tenantId → Tenant detail\n * - /tenants/:tenantId/edit → Edit tenant\n * - /users → Users list\n * - /users/:userId → User detail\n * - /billing → Billing overview\n * - /billing/subscriptions → Subscriptions list\n * - /billing/invoices → Invoices list\n * - /billing/plans → Plans management\n * - /support → Support overview\n * - /support/tickets → Tickets list\n * - /support/tickets/:ticketId → Ticket detail\n * - /products → Products management\n * - /communications → Communications center\n * - /sre → SRE Monitoring\n * - /audit → Audit logs\n * - /sandbox → Sandbox settings\n * - /settings → Settings\n */\nexport function AdminRoutes() {\n const { basePath } = useAdmin();\n const base = basePath || '/admin';\n\n return (\n <Suspense fallback={<PageLoader />}>\n <Routes>\n {/* Default redirect to dashboard */}\n <Route index element={<Navigate to={`${base}/dashboard`} replace />} />\n\n {/* Dashboard - eager loaded for fast initial render */}\n <Route path=\"dashboard\" element={<DashboardPage />} />\n\n {/* Tenants */}\n <Route\n path=\"tenants\"\n element={gatedAll(\n [\n { flag: TENANT_FEATURE_FLAGS.management, defaultValue: true },\n { flag: TENANT_FEATURE_FLAGS.list, defaultValue: true },\n ],\n <TenantsListPage />\n )}\n />\n <Route\n path=\"tenants/new\"\n element={gatedAll(\n [\n { flag: TENANT_FEATURE_FLAGS.management, defaultValue: true },\n { flag: TENANT_FEATURE_FLAGS.create, defaultValue: true },\n ],\n <TenantFormRoutePage mode=\"create\" />\n )}\n />\n <Route\n path=\"tenants/:tenantId\"\n element={gatedAll(\n [\n { flag: TENANT_FEATURE_FLAGS.management, defaultValue: true },\n { flag: TENANT_FEATURE_FLAGS.detail, defaultValue: true },\n ],\n <TenantDetailPage />\n )}\n />\n <Route\n path=\"tenants/:tenantId/edit\"\n element={gatedAll(\n [\n { flag: TENANT_FEATURE_FLAGS.management, defaultValue: true },\n { flag: TENANT_FEATURE_FLAGS.edit, defaultValue: true },\n ],\n <TenantFormRoutePage mode=\"edit\" />\n )}\n />\n\n {/* Organizations */}\n <Route path=\"organizations\" element={<OrganizationsListPage />} />\n\n {/* Workspaces */}\n <Route path=\"workspaces\" element={<WorkspacesListPage />} />\n\n {/* Users */}\n <Route path=\"users\" element={<UsersListPage />} />\n <Route path=\"users/:userId\" element={<UsersListPage />} />\n\n {/* Roles & Permissions */}\n <Route path=\"roles\" element={<RolesPermissionsPage />} />\n\n {/* Feature Flags */}\n <Route path=\"feature-flags\" element={<FeatureFlagsPage />} />\n\n {/* Workflows */}\n <Route path=\"workflows\" element={<WorkflowsPage />} />\n\n {/* Billing */}\n <Route path=\"billing\" element={<BillingPage />} />\n <Route path=\"billing/subscriptions\" element={<BillingPage />} />\n <Route path=\"billing/invoices\" element={<BillingPage />} />\n <Route path=\"billing/plans\" element={<BillingPage />} />\n\n {/* Support — redirects to shell-level /support/* route (microfe-support MFE) */}\n <Route path=\"support/*\" element={<Navigate to=\"/support\" replace />} />\n\n {/* Communications */}\n <Route path=\"communications\" element={<CommunicationsPage />} />\n\n {/* SRE Monitoring */}\n <Route path=\"sre\" element={<SREPage />} />\n\n {/* Sync Failures (cross-layer sync outbox) */}\n <Route path=\"sync-failures\" element={<SyncFailuresPage />} />\n\n {/* Audit Logs */}\n <Route path=\"audit\" element={<AuditLogsPage />} />\n\n {/* Referrals */}\n <Route path=\"referrals\" element={<ReferralsPage />} />\n\n {/* Sandbox */}\n <Route path=\"sandbox\" element={<SandboxSettingsPage />} />\n\n {/* Products */}\n <Route path=\"products\" element={<ProductsPage />} />\n\n {/* Content (blog / case studies / changelog) */}\n <Route path=\"content\" element={<ContentPagesPage />} />\n\n {/* Waitlist */}\n <Route path=\"waitlist\" element={<WaitlistPage />} />\n\n {/* Settings */}\n <Route path=\"settings\" element={<SettingsPage />} />\n\n {/* Catch-all route - redirect to dashboard (absolute path to prevent infinite loops) */}\n <Route path=\"*\" element={<Navigate to={`${base}/dashboard`} replace />} />\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":"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"}
@@ -8,8 +8,8 @@ var r = ({ message: r = "You don't have permission to access this page." }) => /
8
8
  className: "text-center space-y-3",
9
9
  children: [
10
10
  /* @__PURE__ */ t("div", {
11
- className: "w-14 h-14 mx-auto rounded-full bg-red-50 dark:bg-red-950/30 flex items-center justify-center",
12
- children: /* @__PURE__ */ t(e, { className: "w-7 h-7 text-red-500" })
11
+ className: "w-14 h-14 mx-auto rounded-full bg-status-error-bg border border-status-error-border flex items-center justify-center",
12
+ children: /* @__PURE__ */ t(e, { className: "w-7 h-7 text-status-error-text" })
13
13
  }),
14
14
  /* @__PURE__ */ t("h2", {
15
15
  className: "text-lg font-semibold text-text-primary",
@@ -1 +1 @@
1
- {"version":3,"file":"AccessDenied.js","names":[],"sources":["../../../src/admin/components/AccessDenied.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { ShieldOff } from 'lucide-react';\n\ninterface AccessDeniedProps {\n message?: string;\n}\n\nexport const AccessDenied: FC<AccessDeniedProps> = ({\n message = \"You don't have permission to access this page.\",\n}) => {\n return (\n <div role=\"alert\" className=\"flex items-center justify-center h-full min-h-[400px]\">\n <div className=\"text-center space-y-3\">\n <div className=\"w-14 h-14 mx-auto rounded-full bg-red-50 dark:bg-red-950/30 flex items-center justify-center\">\n <ShieldOff className=\"w-7 h-7 text-red-500\" />\n </div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary max-w-sm\">{message}</p>\n </div>\n </div>\n );\n};\n"],"mappings":";;;AAOA,IAAa,KAAuC,EAClD,aAAU,uDAGR,kBAAC,OAAD;CAAK,MAAK;CAAQ,WAAU;WAC1B,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD,EAAW,WAAU,wBAAyB,CAAA;IAC1C,CAAA;GACN,kBAAC,MAAD;IAAI,WAAU;cAA0C;IAAkB,CAAA;GAC1E,kBAAC,KAAD;IAAG,WAAU;cAAwC;IAAY,CAAA;GAC7D;;CACF,CAAA"}
1
+ {"version":3,"file":"AccessDenied.js","names":[],"sources":["../../../src/admin/components/AccessDenied.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { ShieldOff } from 'lucide-react';\n\ninterface AccessDeniedProps {\n message?: string;\n}\n\nexport const AccessDenied: FC<AccessDeniedProps> = ({\n message = \"You don't have permission to access this page.\",\n}) => {\n return (\n <div role=\"alert\" className=\"flex items-center justify-center h-full min-h-[400px]\">\n <div className=\"text-center space-y-3\">\n <div className=\"w-14 h-14 mx-auto rounded-full bg-status-error-bg border border-status-error-border flex items-center justify-center\">\n <ShieldOff className=\"w-7 h-7 text-status-error-text\" />\n </div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary max-w-sm\">{message}</p>\n </div>\n </div>\n );\n};\n"],"mappings":";;;AAOA,IAAa,KAAuC,EAClD,aAAU,uDAGR,kBAAC,OAAD;CAAK,MAAK;CAAQ,WAAU;WAC1B,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD,EAAW,WAAU,kCAAmC,CAAA;IACpD,CAAA;GACN,kBAAC,MAAD;IAAI,WAAU;cAA0C;IAAkB,CAAA;GAC1E,kBAAC,KAAD;IAAG,WAAU;cAAwC;IAAY,CAAA;GAC7D;;CACF,CAAA"}
@@ -37,10 +37,10 @@ function C({ activity: t }) {
37
37
  className: "flex items-start gap-3",
38
38
  children: [/* @__PURE__ */ b("div", {
39
39
  className: e("rounded-full p-2", {
40
- info: "bg-info/10 text-info",
41
- warning: "bg-warning/10 text-warning",
42
- error: "bg-status-error-bg/10 text-status-error-text",
43
- success: "bg-success/10 text-success"
40
+ info: "bg-status-info-bg text-status-info-text",
41
+ warning: "bg-status-warning-bg text-status-warning-text",
42
+ error: "bg-status-error-bg text-status-error-text",
43
+ success: "bg-status-success-bg text-status-success-text"
44
44
  }[t.severity || "info"]),
45
45
  children: n
46
46
  }), /* @__PURE__ */ x("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"ActivityFeed.js","names":[],"sources":["../../../src/admin/components/ActivityFeed.tsx"],"sourcesContent":["import { Link } from 'react-router-dom';\nimport {\n Plus,\n Ban,\n AlertTriangle,\n CheckCircle,\n UserPlus,\n Rocket,\n XCircle,\n Activity,\n CreditCard,\n Mail,\n Settings,\n Shield,\n} from 'lucide-react';\nimport { Card, CardHeader, CardTitle, CardContent, Skeleton } from './ui';\nimport { cn } from '../utils/cn';\nimport { formatRelativeTime } from '../utils/formatters';\nimport type { Activity as ActivityType } from '../types';\n\ninterface ActivityFeedProps {\n /** List of activities */\n activities: ActivityType[];\n /** Maximum items to display */\n maxItems?: number;\n /** Loading state */\n loading?: boolean;\n /** Link to view all activities */\n viewAllLink?: string;\n /** Additional class name */\n className?: string;\n}\n\n/**\n * Activity feed component showing recent platform activities\n */\nexport function ActivityFeed({\n activities,\n maxItems = 10,\n loading,\n viewAllLink = '/activity',\n className,\n}: ActivityFeedProps) {\n const displayActivities = activities.slice(0, maxItems);\n\n return (\n <Card className={className}>\n <CardHeader className=\"flex flex-row items-center justify-between\">\n <CardTitle className=\"text-lg\">Recent Activity</CardTitle>\n <Link to={viewAllLink} className=\"text-sm text-primary hover:underline\">\n View All\n </Link>\n </CardHeader>\n <CardContent>\n {loading ? (\n <div className=\"space-y-4\">\n {Array.from({ length: 5 }).map((_, i) => (\n <ActivityItemSkeleton key={i} />\n ))}\n </div>\n ) : displayActivities.length === 0 ? (\n <p className=\"py-8 text-center text-sm text-text-secondary\">No recent activity</p>\n ) : (\n <div className=\"space-y-4\">\n {displayActivities.map((activity) => (\n <ActivityItem key={activity.id} activity={activity} />\n ))}\n </div>\n )}\n </CardContent>\n </Card>\n );\n}\n\ninterface ActivityItemProps {\n activity: ActivityType;\n}\n\nfunction ActivityItem({ activity }: ActivityItemProps) {\n const icon = getActivityIcon(activity.type);\n const severityColors = {\n info: 'bg-info/10 text-info',\n warning: 'bg-warning/10 text-warning',\n error: 'bg-status-error-bg/10 text-status-error-text',\n success: 'bg-success/10 text-success',\n };\n const severity = activity.severity || 'info';\n\n return (\n <div className=\"flex items-start gap-3\">\n <div className={cn('rounded-full p-2', severityColors[severity])}>{icon}</div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">{activity.description}</p>\n <div className=\"mt-1 flex items-center gap-2 text-xs text-text-secondary\">\n <span>{activity.actor}</span>\n <span>-</span>\n <span>{formatRelativeTime(activity.timestamp)}</span>\n </div>\n </div>\n </div>\n );\n}\n\nfunction ActivityItemSkeleton() {\n return (\n <div className=\"flex items-start gap-3\">\n <Skeleton className=\"h-9 w-9 rounded-full\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n </div>\n );\n}\n\nfunction getActivityIcon(type: string) {\n const iconMap: Record<string, React.ReactNode> = {\n 'tenant.created': <Plus className=\"h-4 w-4\" />,\n 'tenant.suspended': <Ban className=\"h-4 w-4\" />,\n 'tenant.activated': <CheckCircle className=\"h-4 w-4\" />,\n 'payment.failed': <AlertTriangle className=\"h-4 w-4\" />,\n 'payment.succeeded': <CreditCard className=\"h-4 w-4\" />,\n 'user.created': <UserPlus className=\"h-4 w-4\" />,\n 'user.blocked': <Ban className=\"h-4 w-4\" />,\n 'deployment.started': <Rocket className=\"h-4 w-4\" />,\n 'deployment.completed': <CheckCircle className=\"h-4 w-4\" />,\n 'deployment.failed': <XCircle className=\"h-4 w-4\" />,\n 'newsletter.sent': <Mail className=\"h-4 w-4\" />,\n 'settings.changed': <Settings className=\"h-4 w-4\" />,\n 'security.alert': <Shield className=\"h-4 w-4\" />,\n };\n\n return iconMap[type] || <Activity className=\"h-4 w-4\" />;\n}\n"],"mappings":";;;;;;;AAoCA,SAAgB,EAAa,EAC3B,eACA,cAAW,IACX,YACA,iBAAc,aACd,gBACoB;CACpB,IAAM,IAAoB,EAAW,MAAM,GAAG,EAAS;AAEvD,QACE,kBAAC,GAAD;EAAiB;YAAjB,CACE,kBAAC,GAAD;GAAY,WAAU;aAAtB,CACE,kBAAC,GAAD;IAAW,WAAU;cAAU;IAA2B,CAAA,EAC1D,kBAAC,GAAD;IAAM,IAAI;IAAa,WAAU;cAAuC;IAEjE,CAAA,CACI;MACb,kBAAC,GAAD,EAAA,UACG,IACC,kBAAC,OAAD;GAAK,WAAU;aACZ,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,MACjC,kBAAC,GAAD,EAAgC,EAAL,EAAK,CAChC;GACE,CAAA,GACJ,EAAkB,WAAW,IAC/B,kBAAC,KAAD;GAAG,WAAU;aAA+C;GAAsB,CAAA,GAElF,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAkB,KAAK,MACtB,kBAAC,GAAD,EAA0C,aAAY,EAAnC,EAAS,GAA0B,CACtD;GACE,CAAA,EAEI,CAAA,CACT;;;AAQX,SAAS,EAAa,EAAE,eAA+B;CACrD,IAAM,IAAO,EAAgB,EAAS,KAAK;AAS3C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAW,EAAG,oBAVA;IACrB,MAAM;IACN,SAAS;IACT,OAAO;IACP,SAAS;IACV,CACgB,EAAS,YAAY,QAI8B;aAAG;GAAW,CAAA,EAC9E,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAyC,EAAS;IAAgB,CAAA,EAC/E,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,QAAD,EAAA,UAAO,EAAS,OAAa,CAAA;KAC7B,kBAAC,QAAD,EAAA,UAAM,KAAQ,CAAA;KACd,kBAAC,QAAD,EAAA,UAAO,EAAmB,EAAS,UAAU,EAAQ,CAAA;KACjD;MACF;KACF;;;AAIV,SAAS,IAAuB;AAC9B,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD,EAAU,WAAU,wBAAyB,CAAA,EAC7C,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,EAClC,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,CAC9B;KACF;;;AAIV,SAAS,EAAgB,GAAc;AAiBrC,QAhBiD;EAC/C,kBAAkB,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;EAC9C,oBAAoB,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA;EAC/C,oBAAoB,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA;EACvD,kBAAkB,kBAAC,GAAD,EAAe,WAAU,WAAY,CAAA;EACvD,qBAAqB,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;EACvD,gBAAgB,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;EAChD,gBAAgB,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA;EAC3C,sBAAsB,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;EACpD,wBAAwB,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA;EAC3D,qBAAqB,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;EACpD,mBAAmB,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;EAC/C,oBAAoB,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;EACpD,kBAAkB,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;EACjD,CAEc,MAAS,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA"}
1
+ {"version":3,"file":"ActivityFeed.js","names":[],"sources":["../../../src/admin/components/ActivityFeed.tsx"],"sourcesContent":["import { Link } from 'react-router-dom';\nimport {\n Plus,\n Ban,\n AlertTriangle,\n CheckCircle,\n UserPlus,\n Rocket,\n XCircle,\n Activity,\n CreditCard,\n Mail,\n Settings,\n Shield,\n} from 'lucide-react';\nimport { Card, CardHeader, CardTitle, CardContent, Skeleton } from './ui';\nimport { cn } from '../utils/cn';\nimport { formatRelativeTime } from '../utils/formatters';\nimport type { Activity as ActivityType } from '../types';\n\ninterface ActivityFeedProps {\n /** List of activities */\n activities: ActivityType[];\n /** Maximum items to display */\n maxItems?: number;\n /** Loading state */\n loading?: boolean;\n /** Link to view all activities */\n viewAllLink?: string;\n /** Additional class name */\n className?: string;\n}\n\n/**\n * Activity feed component showing recent platform activities\n */\nexport function ActivityFeed({\n activities,\n maxItems = 10,\n loading,\n viewAllLink = '/activity',\n className,\n}: ActivityFeedProps) {\n const displayActivities = activities.slice(0, maxItems);\n\n return (\n <Card className={className}>\n <CardHeader className=\"flex flex-row items-center justify-between\">\n <CardTitle className=\"text-lg\">Recent Activity</CardTitle>\n <Link to={viewAllLink} className=\"text-sm text-primary hover:underline\">\n View All\n </Link>\n </CardHeader>\n <CardContent>\n {loading ? (\n <div className=\"space-y-4\">\n {Array.from({ length: 5 }).map((_, i) => (\n <ActivityItemSkeleton key={i} />\n ))}\n </div>\n ) : displayActivities.length === 0 ? (\n <p className=\"py-8 text-center text-sm text-text-secondary\">No recent activity</p>\n ) : (\n <div className=\"space-y-4\">\n {displayActivities.map((activity) => (\n <ActivityItem key={activity.id} activity={activity} />\n ))}\n </div>\n )}\n </CardContent>\n </Card>\n );\n}\n\ninterface ActivityItemProps {\n activity: ActivityType;\n}\n\nfunction ActivityItem({ activity }: ActivityItemProps) {\n const icon = getActivityIcon(activity.type);\n const severityColors = {\n info: 'bg-status-info-bg text-status-info-text',\n warning: 'bg-status-warning-bg text-status-warning-text',\n error: 'bg-status-error-bg text-status-error-text',\n success: 'bg-status-success-bg text-status-success-text',\n };\n const severity = activity.severity || 'info';\n\n return (\n <div className=\"flex items-start gap-3\">\n <div className={cn('rounded-full p-2', severityColors[severity])}>{icon}</div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">{activity.description}</p>\n <div className=\"mt-1 flex items-center gap-2 text-xs text-text-secondary\">\n <span>{activity.actor}</span>\n <span>-</span>\n <span>{formatRelativeTime(activity.timestamp)}</span>\n </div>\n </div>\n </div>\n );\n}\n\nfunction ActivityItemSkeleton() {\n return (\n <div className=\"flex items-start gap-3\">\n <Skeleton className=\"h-9 w-9 rounded-full\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n </div>\n );\n}\n\nfunction getActivityIcon(type: string) {\n const iconMap: Record<string, React.ReactNode> = {\n 'tenant.created': <Plus className=\"h-4 w-4\" />,\n 'tenant.suspended': <Ban className=\"h-4 w-4\" />,\n 'tenant.activated': <CheckCircle className=\"h-4 w-4\" />,\n 'payment.failed': <AlertTriangle className=\"h-4 w-4\" />,\n 'payment.succeeded': <CreditCard className=\"h-4 w-4\" />,\n 'user.created': <UserPlus className=\"h-4 w-4\" />,\n 'user.blocked': <Ban className=\"h-4 w-4\" />,\n 'deployment.started': <Rocket className=\"h-4 w-4\" />,\n 'deployment.completed': <CheckCircle className=\"h-4 w-4\" />,\n 'deployment.failed': <XCircle className=\"h-4 w-4\" />,\n 'newsletter.sent': <Mail className=\"h-4 w-4\" />,\n 'settings.changed': <Settings className=\"h-4 w-4\" />,\n 'security.alert': <Shield className=\"h-4 w-4\" />,\n };\n\n return iconMap[type] || <Activity className=\"h-4 w-4\" />;\n}\n"],"mappings":";;;;;;;AAoCA,SAAgB,EAAa,EAC3B,eACA,cAAW,IACX,YACA,iBAAc,aACd,gBACoB;CACpB,IAAM,IAAoB,EAAW,MAAM,GAAG,EAAS;AAEvD,QACE,kBAAC,GAAD;EAAiB;YAAjB,CACE,kBAAC,GAAD;GAAY,WAAU;aAAtB,CACE,kBAAC,GAAD;IAAW,WAAU;cAAU;IAA2B,CAAA,EAC1D,kBAAC,GAAD;IAAM,IAAI;IAAa,WAAU;cAAuC;IAEjE,CAAA,CACI;MACb,kBAAC,GAAD,EAAA,UACG,IACC,kBAAC,OAAD;GAAK,WAAU;aACZ,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,MACjC,kBAAC,GAAD,EAAgC,EAAL,EAAK,CAChC;GACE,CAAA,GACJ,EAAkB,WAAW,IAC/B,kBAAC,KAAD;GAAG,WAAU;aAA+C;GAAsB,CAAA,GAElF,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAkB,KAAK,MACtB,kBAAC,GAAD,EAA0C,aAAY,EAAnC,EAAS,GAA0B,CACtD;GACE,CAAA,EAEI,CAAA,CACT;;;AAQX,SAAS,EAAa,EAAE,eAA+B;CACrD,IAAM,IAAO,EAAgB,EAAS,KAAK;AAS3C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAW,EAAG,oBAVA;IACrB,MAAM;IACN,SAAS;IACT,OAAO;IACP,SAAS;IACV,CACgB,EAAS,YAAY,QAI8B;aAAG;GAAW,CAAA,EAC9E,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAyC,EAAS;IAAgB,CAAA,EAC/E,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,QAAD,EAAA,UAAO,EAAS,OAAa,CAAA;KAC7B,kBAAC,QAAD,EAAA,UAAM,KAAQ,CAAA;KACd,kBAAC,QAAD,EAAA,UAAO,EAAmB,EAAS,UAAU,EAAQ,CAAA;KACjD;MACF;KACF;;;AAIV,SAAS,IAAuB;AAC9B,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD,EAAU,WAAU,wBAAyB,CAAA,EAC7C,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,EAClC,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,CAC9B;KACF;;;AAIV,SAAS,EAAgB,GAAc;AAiBrC,QAhBiD;EAC/C,kBAAkB,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;EAC9C,oBAAoB,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA;EAC/C,oBAAoB,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA;EACvD,kBAAkB,kBAAC,GAAD,EAAe,WAAU,WAAY,CAAA;EACvD,qBAAqB,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;EACvD,gBAAgB,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;EAChD,gBAAgB,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA;EAC3C,sBAAsB,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;EACpD,wBAAwB,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA;EAC3D,qBAAqB,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;EACpD,mBAAmB,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;EAC/C,oBAAoB,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;EACpD,kBAAkB,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;EACjD,CAEc,MAAS,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Charts.js","names":[],"sources":["../../../src/admin/components/Charts.tsx"],"sourcesContent":["import {\n LineChart,\n Line,\n AreaChart,\n Area,\n PieChart,\n Pie,\n Cell,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n Legend,\n ResponsiveContainer,\n} from 'recharts';\nimport { Card, CardHeader, CardTitle, CardContent, Skeleton } from './ui';\nimport { cn } from '../utils/cn';\nimport { formatCurrency, formatNumber } from '../utils/formatters';\nimport type { RevenueTrendPoint, TenantGrowthPoint, ProductUsagePoint } from '../types';\n\n// Chart colors using CSS variables for theme support\nconst CHART_COLORS = [\n 'hsl(var(--chart-1, 221.2 83.2% 53.3%))',\n 'hsl(var(--chart-2, 142.1 76.2% 36.3%))',\n 'hsl(var(--chart-3, 47.9 95.8% 53.1%))',\n 'hsl(var(--chart-4, 0 84.2% 60.2%))',\n 'hsl(var(--chart-5, 262.1 83.3% 57.8%))',\n];\n\n// ============================================================================\n// Revenue Trend Chart (Line Chart)\n// ============================================================================\n\ninterface RevenueTrendChartProps {\n data: RevenueTrendPoint[];\n loading?: boolean;\n className?: string;\n}\n\nexport function RevenueTrendChart({ data, loading, className }: RevenueTrendChartProps) {\n return (\n <Card className={className}>\n <CardHeader>\n <CardTitle className=\"text-lg\">Revenue Trend</CardTitle>\n </CardHeader>\n <CardContent>\n {loading ? (\n <Skeleton className=\"h-[300px] w-full\" />\n ) : (\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={data} margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>\n <CartesianGrid strokeDasharray=\"3 3\" className=\"stroke-border\" />\n <XAxis\n dataKey=\"date\"\n className=\"text-xs fill-muted-foreground\"\n tick={{ fill: 'currentColor' }}\n />\n <YAxis\n className=\"text-xs fill-muted-foreground\"\n tick={{ fill: 'currentColor' }}\n tickFormatter={(value) => formatCurrency(value)}\n />\n <Tooltip\n contentStyle={{\n backgroundColor: 'hsl(var(--card))',\n border: '1px solid hsl(var(--border))',\n borderRadius: '6px',\n }}\n labelStyle={{ color: 'hsl(var(--foreground))' }}\n formatter={(value: number) => [formatCurrency(value), '']}\n />\n <Legend />\n <Line\n type=\"monotone\"\n dataKey=\"mrr\"\n name=\"MRR\"\n stroke={CHART_COLORS[0]}\n strokeWidth={2}\n dot={false}\n activeDot={{ r: 6 }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"arr\"\n name=\"ARR\"\n stroke={CHART_COLORS[1]}\n strokeWidth={2}\n dot={false}\n activeDot={{ r: 6 }}\n />\n </LineChart>\n </ResponsiveContainer>\n )}\n </CardContent>\n </Card>\n );\n}\n\n// ============================================================================\n// Tenant Growth Chart (Area Chart)\n// ============================================================================\n\ninterface TenantGrowthChartProps {\n data: TenantGrowthPoint[];\n loading?: boolean;\n className?: string;\n}\n\nexport function TenantGrowthChart({ data, loading, className }: TenantGrowthChartProps) {\n return (\n <Card className={className}>\n <CardHeader>\n <CardTitle className=\"text-lg\">Tenant Growth</CardTitle>\n </CardHeader>\n <CardContent>\n {loading ? (\n <Skeleton className=\"h-[250px] w-full\" />\n ) : (\n <ResponsiveContainer width=\"100%\" height={250}>\n <AreaChart data={data} margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>\n <CartesianGrid strokeDasharray=\"3 3\" className=\"stroke-border\" />\n <XAxis\n dataKey=\"date\"\n className=\"text-xs fill-muted-foreground\"\n tick={{ fill: 'currentColor' }}\n />\n <YAxis className=\"text-xs fill-muted-foreground\" tick={{ fill: 'currentColor' }} />\n <Tooltip\n contentStyle={{\n backgroundColor: 'hsl(var(--card))',\n border: '1px solid hsl(var(--border))',\n borderRadius: '6px',\n }}\n labelStyle={{ color: 'hsl(var(--foreground))' }}\n />\n <Legend />\n <Area\n type=\"monotone\"\n dataKey=\"new\"\n name=\"New\"\n stackId=\"1\"\n stroke={CHART_COLORS[0]}\n fill={CHART_COLORS[0]}\n fillOpacity={0.6}\n />\n <Area\n type=\"monotone\"\n dataKey=\"active\"\n name=\"Active\"\n stackId=\"2\"\n stroke={CHART_COLORS[1]}\n fill={CHART_COLORS[1]}\n fillOpacity={0.6}\n />\n <Area\n type=\"monotone\"\n dataKey=\"churned\"\n name=\"Churned\"\n stackId=\"3\"\n stroke={CHART_COLORS[3]}\n fill={CHART_COLORS[3]}\n fillOpacity={0.6}\n />\n </AreaChart>\n </ResponsiveContainer>\n )}\n </CardContent>\n </Card>\n );\n}\n\n// ============================================================================\n// Product Usage Chart (Pie Chart)\n// ============================================================================\n\ninterface ProductUsageChartProps {\n data: ProductUsagePoint[];\n loading?: boolean;\n className?: string;\n}\n\nexport function ProductUsageChart({ data, loading, className }: ProductUsageChartProps) {\n return (\n <Card className={className}>\n <CardHeader>\n <CardTitle className=\"text-lg\">Product Usage</CardTitle>\n </CardHeader>\n <CardContent>\n {loading ? (\n <Skeleton className=\"h-[250px] w-full\" />\n ) : (\n <ResponsiveContainer width=\"100%\" height={250}>\n <PieChart>\n <Pie\n data={data}\n dataKey=\"tenants\"\n nameKey=\"product\"\n cx=\"50%\"\n cy=\"50%\"\n outerRadius={80}\n label={({ name, percent }: { name: string; percent: number }) =>\n `${name} (${(percent * 100).toFixed(0)}%)`\n }\n labelLine={false}\n >\n {data.map((entry, index) => (\n <Cell\n key={`cell-${index}`}\n fill={entry.color || CHART_COLORS[index % CHART_COLORS.length]}\n />\n ))}\n </Pie>\n <Tooltip\n contentStyle={{\n backgroundColor: 'hsl(var(--card))',\n border: '1px solid hsl(var(--border))',\n borderRadius: '6px',\n }}\n formatter={(value: number) => [formatNumber(value) + ' tenants', '']}\n />\n <Legend />\n </PieChart>\n </ResponsiveContainer>\n )}\n </CardContent>\n </Card>\n );\n}\n\n// ============================================================================\n// Quick Links Card\n// ============================================================================\n\ninterface QuickLink {\n to: string;\n icon: React.ReactNode;\n label: string;\n description?: string;\n}\n\ninterface QuickLinksProps {\n links: QuickLink[];\n className?: string;\n}\n\nexport function QuickLinks({ links, className }: QuickLinksProps) {\n return (\n <Card className={className}>\n <CardHeader>\n <CardTitle className=\"text-lg\">Quick Actions</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {links.map((link) => (\n <a\n key={link.to}\n href={link.to}\n className={cn(\n 'flex items-center gap-3 rounded-lg border border-border-subtle p-3',\n 'transition-colors hover:bg-accent'\n )}\n >\n <div className=\"rounded-md bg-action-primary-bg/10 p-2 text-primary\">{link.icon}</div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"font-medium text-text-primary\">{link.label}</p>\n {link.description && (\n <p className=\"truncate text-xs text-text-secondary\">{link.description}</p>\n )}\n </div>\n </a>\n ))}\n </div>\n </CardContent>\n </Card>\n );\n}\n"],"mappings":";;;;;AAqPA,SAAgB,EAAW,EAAE,UAAO,gBAA8B;AAChE,QACE,kBAAC,GAAD;EAAiB;YAAjB,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;GAAW,WAAU;aAAU;GAAyB,CAAA,EAC7C,CAAA,EACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAM,KAAK,MACV,kBAAC,KAAD;IAEE,MAAM,EAAK;IACX,WAAW,EACT,sEACA,oCACD;cANH,CAQE,kBAAC,OAAD;KAAK,WAAU;eAAuD,EAAK;KAAW,CAAA,EACtF,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAiC,EAAK;MAAU,CAAA,EAC5D,EAAK,eACJ,kBAAC,KAAD;MAAG,WAAU;gBAAwC,EAAK;MAAgB,CAAA,CAExE;OACJ;MAdG,EAAK,GAcR,CACJ;GACE,CAAA,EACM,CAAA,CACT"}
1
+ {"version":3,"file":"Charts.js","names":[],"sources":["../../../src/admin/components/Charts.tsx"],"sourcesContent":["import {\n LineChart,\n Line,\n AreaChart,\n Area,\n PieChart,\n Pie,\n Cell,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n Legend,\n ResponsiveContainer,\n} from 'recharts';\nimport { Card, CardHeader, CardTitle, CardContent, Skeleton } from './ui';\nimport { cn } from '../utils/cn';\nimport { formatCurrency, formatNumber } from '../utils/formatters';\nimport type { RevenueTrendPoint, TenantGrowthPoint, ProductUsagePoint } from '../types';\n\n// Chart colors using semantic chart tokens (theme-aware; resolve correctly in\n// every theme + dark mode — no hardcoded hsl() fallbacks).\nconst CHART_COLORS = [\n 'var(--color-chart-1)',\n 'var(--color-chart-2)',\n 'var(--color-chart-3)',\n 'var(--color-chart-4)',\n 'var(--color-chart-5)',\n];\n\n// Shared tooltip styling resolved from semantic surface tokens so popovers stay\n// legible (strong contrast) in dark mode rather than rendering invalid colors.\nconst CHART_TOOLTIP_CONTENT_STYLE = {\n backgroundColor: 'var(--color-bg-elevated)',\n border: '1px solid var(--color-border-seam)',\n borderRadius: '6px',\n} as const;\n\nconst CHART_TOOLTIP_LABEL_STYLE = { color: 'var(--color-text-primary)' } as const;\n\n// ============================================================================\n// Revenue Trend Chart (Line Chart)\n// ============================================================================\n\ninterface RevenueTrendChartProps {\n data: RevenueTrendPoint[];\n loading?: boolean;\n className?: string;\n}\n\nexport function RevenueTrendChart({ data, loading, className }: RevenueTrendChartProps) {\n return (\n <Card className={className}>\n <CardHeader>\n <CardTitle className=\"text-lg\">Revenue Trend</CardTitle>\n </CardHeader>\n <CardContent>\n {loading ? (\n <Skeleton className=\"h-[300px] w-full\" />\n ) : (\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={data} margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>\n <CartesianGrid strokeDasharray=\"3 3\" className=\"stroke-border\" />\n <XAxis\n dataKey=\"date\"\n className=\"text-xs fill-muted-foreground\"\n tick={{ fill: 'currentColor' }}\n />\n <YAxis\n className=\"text-xs fill-muted-foreground\"\n tick={{ fill: 'currentColor' }}\n tickFormatter={(value) => formatCurrency(value)}\n />\n <Tooltip\n contentStyle={CHART_TOOLTIP_CONTENT_STYLE}\n labelStyle={CHART_TOOLTIP_LABEL_STYLE}\n formatter={(value: number) => [formatCurrency(value), '']}\n />\n <Legend />\n <Line\n type=\"monotone\"\n dataKey=\"mrr\"\n name=\"MRR\"\n stroke={CHART_COLORS[0]}\n strokeWidth={2}\n dot={false}\n activeDot={{ r: 6 }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"arr\"\n name=\"ARR\"\n stroke={CHART_COLORS[1]}\n strokeWidth={2}\n dot={false}\n activeDot={{ r: 6 }}\n />\n </LineChart>\n </ResponsiveContainer>\n )}\n </CardContent>\n </Card>\n );\n}\n\n// ============================================================================\n// Tenant Growth Chart (Area Chart)\n// ============================================================================\n\ninterface TenantGrowthChartProps {\n data: TenantGrowthPoint[];\n loading?: boolean;\n className?: string;\n}\n\nexport function TenantGrowthChart({ data, loading, className }: TenantGrowthChartProps) {\n return (\n <Card className={className}>\n <CardHeader>\n <CardTitle className=\"text-lg\">Tenant Growth</CardTitle>\n </CardHeader>\n <CardContent>\n {loading ? (\n <Skeleton className=\"h-[250px] w-full\" />\n ) : (\n <ResponsiveContainer width=\"100%\" height={250}>\n <AreaChart data={data} margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>\n <CartesianGrid strokeDasharray=\"3 3\" className=\"stroke-border\" />\n <XAxis\n dataKey=\"date\"\n className=\"text-xs fill-muted-foreground\"\n tick={{ fill: 'currentColor' }}\n />\n <YAxis className=\"text-xs fill-muted-foreground\" tick={{ fill: 'currentColor' }} />\n <Tooltip\n contentStyle={CHART_TOOLTIP_CONTENT_STYLE}\n labelStyle={CHART_TOOLTIP_LABEL_STYLE}\n />\n <Legend />\n <Area\n type=\"monotone\"\n dataKey=\"new\"\n name=\"New\"\n stackId=\"1\"\n stroke={CHART_COLORS[0]}\n fill={CHART_COLORS[0]}\n fillOpacity={0.6}\n />\n <Area\n type=\"monotone\"\n dataKey=\"active\"\n name=\"Active\"\n stackId=\"2\"\n stroke={CHART_COLORS[1]}\n fill={CHART_COLORS[1]}\n fillOpacity={0.6}\n />\n <Area\n type=\"monotone\"\n dataKey=\"churned\"\n name=\"Churned\"\n stackId=\"3\"\n stroke={CHART_COLORS[3]}\n fill={CHART_COLORS[3]}\n fillOpacity={0.6}\n />\n </AreaChart>\n </ResponsiveContainer>\n )}\n </CardContent>\n </Card>\n );\n}\n\n// ============================================================================\n// Product Usage Chart (Pie Chart)\n// ============================================================================\n\ninterface ProductUsageChartProps {\n data: ProductUsagePoint[];\n loading?: boolean;\n className?: string;\n}\n\nexport function ProductUsageChart({ data, loading, className }: ProductUsageChartProps) {\n return (\n <Card className={className}>\n <CardHeader>\n <CardTitle className=\"text-lg\">Product Usage</CardTitle>\n </CardHeader>\n <CardContent>\n {loading ? (\n <Skeleton className=\"h-[250px] w-full\" />\n ) : (\n <ResponsiveContainer width=\"100%\" height={250}>\n <PieChart>\n <Pie\n data={data}\n dataKey=\"tenants\"\n nameKey=\"product\"\n cx=\"50%\"\n cy=\"50%\"\n outerRadius={80}\n label={({ name, percent }: { name: string; percent: number }) =>\n `${name} (${(percent * 100).toFixed(0)}%)`\n }\n labelLine={false}\n >\n {data.map((entry, index) => (\n <Cell\n key={`cell-${index}`}\n fill={entry.color || CHART_COLORS[index % CHART_COLORS.length]}\n />\n ))}\n </Pie>\n <Tooltip\n contentStyle={CHART_TOOLTIP_CONTENT_STYLE}\n formatter={(value: number) => [formatNumber(value) + ' tenants', '']}\n />\n <Legend />\n </PieChart>\n </ResponsiveContainer>\n )}\n </CardContent>\n </Card>\n );\n}\n\n// ============================================================================\n// Quick Links Card\n// ============================================================================\n\ninterface QuickLink {\n to: string;\n icon: React.ReactNode;\n label: string;\n description?: string;\n}\n\ninterface QuickLinksProps {\n links: QuickLink[];\n className?: string;\n}\n\nexport function QuickLinks({ links, className }: QuickLinksProps) {\n return (\n <Card className={className}>\n <CardHeader>\n <CardTitle className=\"text-lg\">Quick Actions</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {links.map((link) => (\n <a\n key={link.to}\n href={link.to}\n className={cn(\n 'flex items-center gap-3 rounded-lg border border-border-subtle p-3',\n 'transition-colors hover:bg-accent'\n )}\n >\n <div className=\"rounded-md bg-action-primary-bg/10 p-2 text-primary\">{link.icon}</div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"font-medium text-text-primary\">{link.label}</p>\n {link.description && (\n <p className=\"truncate text-xs text-text-secondary\">{link.description}</p>\n )}\n </div>\n </a>\n ))}\n </div>\n </CardContent>\n </Card>\n );\n}\n"],"mappings":";;;;;AAoPA,SAAgB,EAAW,EAAE,UAAO,gBAA8B;AAChE,QACE,kBAAC,GAAD;EAAiB;YAAjB,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;GAAW,WAAU;aAAU;GAAyB,CAAA,EAC7C,CAAA,EACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAM,KAAK,MACV,kBAAC,KAAD;IAEE,MAAM,EAAK;IACX,WAAW,EACT,sEACA,oCACD;cANH,CAQE,kBAAC,OAAD;KAAK,WAAU;eAAuD,EAAK;KAAW,CAAA,EACtF,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAiC,EAAK;MAAU,CAAA,EAC5D,EAAK,eACJ,kBAAC,KAAD;MAAG,WAAU;gBAAwC,EAAK;MAAgB,CAAA,CAExE;OACJ;MAdG,EAAK,GAcR,CACJ;GACE,CAAA,EACM,CAAA,CACT"}
@@ -31,7 +31,7 @@ function l({ open: o, onClose: l, onConfirm: u, title: d, description: f, confir
31
31
  return /* @__PURE__ */ c("div", {
32
32
  className: "fixed inset-0 z-50 flex items-center justify-center",
33
33
  children: [/* @__PURE__ */ s("div", {
34
- className: "fixed inset-0 bg-black/50 transition-opacity",
34
+ className: "fixed inset-0 bg-overlay transition-opacity",
35
35
  onClick: g ? void 0 : l,
36
36
  "aria-hidden": "true"
37
37
  }), /* @__PURE__ */ c("div", {