@burdenoff/microfe-admin 2026.805.1 → 2026.829.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/AdminRoot.js +77 -72
- package/dist/admin/AdminRoot.js.map +1 -1
- package/dist/admin/AdminRoutes.js +28 -24
- package/dist/admin/AdminRoutes.js.map +1 -1
- package/dist/admin/components/TenantMembersPanel.js +105 -106
- package/dist/admin/components/TenantMembersPanel.js.map +1 -1
- package/dist/admin/hooks/useAdminPermissions.js +1 -0
- package/dist/admin/hooks/useAdminPermissions.js.map +1 -1
- package/dist/admin/hooks/useTr.js +14 -0
- package/dist/admin/hooks/useTr.js.map +1 -0
- package/dist/admin/pages/DashboardPage.js +71 -72
- package/dist/admin/pages/DashboardPage.js.map +1 -1
- package/dist/admin/pages/ExploreConversationsPage.js +419 -0
- package/dist/admin/pages/ExploreConversationsPage.js.map +1 -0
- package/dist/admin/pages/OrganizationsListPage.js +63 -62
- package/dist/admin/pages/OrganizationsListPage.js.map +1 -1
- package/dist/admin/pages/TenantDetailPage.js +148 -149
- package/dist/admin/pages/TenantDetailPage.js.map +1 -1
- package/dist/admin/pages/TenantsListPage.js +106 -107
- package/dist/admin/pages/TenantsListPage.js.map +1 -1
- package/dist/admin/pages/UsersListPage.js +87 -88
- package/dist/admin/pages/UsersListPage.js.map +1 -1
- package/dist/admin/pages/index.js +1 -0
- package/package.json +1 -1
|
@@ -4,128 +4,127 @@ import { PageLayout as n } from "../components/PageLayout.js";
|
|
|
4
4
|
import { MetricCard as r, MetricsGrid as i } from "../components/MetricCard.js";
|
|
5
5
|
import { ActivityFeed as a } from "../components/ActivityFeed.js";
|
|
6
6
|
import { QuickLinks as o } from "../components/Charts.js";
|
|
7
|
-
import {
|
|
8
|
-
import { PermissionGuard as c } from "../components/PermissionGuard.js";
|
|
7
|
+
import { PermissionGuard as s } from "../components/PermissionGuard.js";
|
|
9
8
|
import "../components/index.js";
|
|
10
|
-
import { joinPath as
|
|
11
|
-
import { mapActivityLogToUi as
|
|
12
|
-
import { useGetDashboardActiveWorkspaceCountQuery as
|
|
9
|
+
import { joinPath as c } from "../utils/navigation.js";
|
|
10
|
+
import { mapActivityLogToUi as l } from "../utils/mappers.js";
|
|
11
|
+
import { useGetDashboardActiveWorkspaceCountQuery as u, useGetDashboardOrganizationCountQuery as d, useGetDashboardTenantCountQuery as f, useGetDashboardUserCountQuery as p, useGetRecentActivityLogsQuery as m } from "../../generated/global-operations.js";
|
|
12
|
+
import { useTr as h } from "../hooks/useTr.js";
|
|
13
13
|
import { useMemo as g } from "react";
|
|
14
14
|
import { Briefcase as _, Building2 as v, FileText as y, HelpCircle as b, Layout as x, Plus as S, UserPlus as C, Users as w } from "lucide-react";
|
|
15
15
|
import { useNavigate as T } from "react-router";
|
|
16
16
|
import { jsx as E, jsxs as D } from "react/jsx-runtime";
|
|
17
|
-
import {
|
|
18
|
-
import { NextSteps as k, PagePurpose as A } from "@burdenoff/fe-libs/ui";
|
|
17
|
+
import { NextSteps as O, PagePurpose as k } from "@burdenoff/fe-libs/ui";
|
|
19
18
|
//#region src/admin/pages/DashboardPage.tsx
|
|
20
|
-
function
|
|
21
|
-
let { canViewDashboard:
|
|
19
|
+
function A() {
|
|
20
|
+
let { canViewDashboard: A, isLoading: j } = t(), { basePath: M = "" } = e(), N = T(), P = h(), F = j || !A, { data: I, loading: L } = f({
|
|
22
21
|
fetchPolicy: "cache-and-network",
|
|
23
|
-
skip:
|
|
24
|
-
}), { data:
|
|
22
|
+
skip: F
|
|
23
|
+
}), { data: R, loading: z } = d({
|
|
25
24
|
fetchPolicy: "cache-and-network",
|
|
26
|
-
skip:
|
|
27
|
-
}), { data:
|
|
25
|
+
skip: F
|
|
26
|
+
}), { data: B, loading: V } = u({
|
|
28
27
|
fetchPolicy: "cache-and-network",
|
|
29
|
-
skip:
|
|
30
|
-
}), { data:
|
|
28
|
+
skip: F
|
|
29
|
+
}), { data: H, loading: U } = p({
|
|
31
30
|
fetchPolicy: "cache-and-network",
|
|
32
|
-
skip:
|
|
33
|
-
}), { data:
|
|
31
|
+
skip: F
|
|
32
|
+
}), { data: W, loading: G } = m({
|
|
34
33
|
variables: { limit: 10 },
|
|
35
34
|
fetchPolicy: "cache-and-network",
|
|
36
|
-
skip:
|
|
37
|
-
}),
|
|
38
|
-
tenants:
|
|
39
|
-
organizations:
|
|
40
|
-
workspaces:
|
|
41
|
-
users:
|
|
42
|
-
},
|
|
35
|
+
skip: F
|
|
36
|
+
}), K = {
|
|
37
|
+
tenants: I?.tenants?.total ?? 0,
|
|
38
|
+
organizations: R?.allOrganizations?.total ?? 0,
|
|
39
|
+
workspaces: B?.allWorkspaces?.total ?? 0,
|
|
40
|
+
users: H?.userCount ?? 0
|
|
41
|
+
}, q = g(() => (W?.activityLogs?.nodes ?? []).map(l), [W]), J = [
|
|
43
42
|
{
|
|
44
|
-
to:
|
|
45
|
-
label:
|
|
43
|
+
to: c(M, "tenants"),
|
|
44
|
+
label: P("admin.dashboard.quickLinks.addTenant", "Add Tenant"),
|
|
46
45
|
icon: /* @__PURE__ */ E(S, { className: "h-4 w-4" }),
|
|
47
|
-
description:
|
|
46
|
+
description: P("admin.dashboard.quickLinks.addTenantDescription", "Create a new tenant")
|
|
48
47
|
},
|
|
49
48
|
{
|
|
50
|
-
to:
|
|
51
|
-
label:
|
|
49
|
+
to: c(M, "users"),
|
|
50
|
+
label: P("admin.dashboard.quickLinks.inviteUser", "Invite User"),
|
|
52
51
|
icon: /* @__PURE__ */ E(C, { className: "h-4 w-4" }),
|
|
53
|
-
description:
|
|
52
|
+
description: P("admin.dashboard.quickLinks.inviteUserDescription", "Invite a new user")
|
|
54
53
|
},
|
|
55
54
|
{
|
|
56
|
-
to:
|
|
57
|
-
label:
|
|
55
|
+
to: c(M, "audit"),
|
|
56
|
+
label: P("admin.dashboard.quickLinks.auditLogs", "Audit Logs"),
|
|
58
57
|
icon: /* @__PURE__ */ E(y, { className: "h-4 w-4" }),
|
|
59
|
-
description:
|
|
58
|
+
description: P("admin.dashboard.quickLinks.auditLogsDescription", "View security audit trail")
|
|
60
59
|
},
|
|
61
60
|
{
|
|
62
|
-
to:
|
|
63
|
-
label:
|
|
61
|
+
to: c(M, "support"),
|
|
62
|
+
label: P("admin.dashboard.quickLinks.support", "Support"),
|
|
64
63
|
icon: /* @__PURE__ */ E(b, { className: "h-4 w-4" }),
|
|
65
|
-
description:
|
|
64
|
+
description: P("admin.dashboard.quickLinks.supportDescription", "Manage support tickets")
|
|
66
65
|
}
|
|
67
|
-
],
|
|
68
|
-
return /* @__PURE__ */ E(
|
|
69
|
-
allowed:
|
|
70
|
-
isLoading:
|
|
71
|
-
pageTitle:
|
|
72
|
-
denyMessage:
|
|
66
|
+
], Y = L || z || V || U;
|
|
67
|
+
return /* @__PURE__ */ E(s, {
|
|
68
|
+
allowed: A,
|
|
69
|
+
isLoading: j,
|
|
70
|
+
pageTitle: P("admin.dashboard.title", "Dashboard"),
|
|
71
|
+
denyMessage: P("admin.dashboard.denyMessage", "You don't have permission to view the admin dashboard."),
|
|
73
72
|
children: /* @__PURE__ */ E(n, {
|
|
74
|
-
title:
|
|
75
|
-
description:
|
|
76
|
-
gradientWord:
|
|
73
|
+
title: P("admin.dashboard.title", "Dashboard"),
|
|
74
|
+
description: P("admin.dashboard.description", "Platform overview and key metrics"),
|
|
75
|
+
gradientWord: P("admin.dashboard.title", "Dashboard"),
|
|
77
76
|
aurora: !0,
|
|
78
77
|
children: /* @__PURE__ */ D("div", {
|
|
79
78
|
className: "space-y-6",
|
|
80
79
|
children: [
|
|
81
|
-
/* @__PURE__ */ E(
|
|
82
|
-
/* @__PURE__ */ E(
|
|
80
|
+
/* @__PURE__ */ E(k, { children: P("admin.dashboard.purpose", "Your control tower for the whole platform. See live tenant, organization, workspace and user counts at a glance, watch the most recent administrative activity, and jump straight into the day-to-day jobs — onboarding a tenant, inviting a user, or reviewing the audit trail.") }),
|
|
81
|
+
/* @__PURE__ */ E(O, {
|
|
83
82
|
storageKey: "admin-dashboard",
|
|
84
83
|
steps: [
|
|
85
84
|
{
|
|
86
85
|
id: "add-tenant",
|
|
87
|
-
label:
|
|
88
|
-
description:
|
|
89
|
-
onClick: () =>
|
|
86
|
+
label: P("admin.dashboard.nextSteps.addTenant", "Onboard a tenant"),
|
|
87
|
+
description: P("admin.dashboard.nextSteps.addTenantDesc", "Provision a new customer tenant to start serving them."),
|
|
88
|
+
onClick: () => N(c(M, "tenants/new"))
|
|
90
89
|
},
|
|
91
90
|
{
|
|
92
91
|
id: "invite-user",
|
|
93
|
-
label:
|
|
94
|
-
description:
|
|
95
|
-
onClick: () =>
|
|
92
|
+
label: P("admin.dashboard.nextSteps.inviteUser", "Invite a teammate"),
|
|
93
|
+
description: P("admin.dashboard.nextSteps.inviteUserDesc", "Bring another operator into the admin console."),
|
|
94
|
+
onClick: () => N(c(M, "users"))
|
|
96
95
|
},
|
|
97
96
|
{
|
|
98
97
|
id: "review-audit",
|
|
99
|
-
label:
|
|
100
|
-
description:
|
|
101
|
-
onClick: () =>
|
|
98
|
+
label: P("admin.dashboard.nextSteps.reviewAudit", "Review the audit trail"),
|
|
99
|
+
description: P("admin.dashboard.nextSteps.reviewAuditDesc", "Check who changed what across the platform."),
|
|
100
|
+
onClick: () => N(c(M, "audit"))
|
|
102
101
|
}
|
|
103
102
|
]
|
|
104
103
|
}),
|
|
105
104
|
/* @__PURE__ */ D(i, { children: [
|
|
106
105
|
/* @__PURE__ */ E(r, {
|
|
107
|
-
title:
|
|
108
|
-
value:
|
|
109
|
-
loading:
|
|
106
|
+
title: P("admin.dashboard.metrics.totalTenants", "Total Tenants"),
|
|
107
|
+
value: K.tenants,
|
|
108
|
+
loading: Y,
|
|
110
109
|
hero: !0,
|
|
111
110
|
icon: /* @__PURE__ */ E(v, { className: "h-5 w-5 text-action-primary-bg" })
|
|
112
111
|
}),
|
|
113
112
|
/* @__PURE__ */ E(r, {
|
|
114
|
-
title:
|
|
115
|
-
value:
|
|
116
|
-
loading:
|
|
113
|
+
title: P("admin.dashboard.metrics.organizations", "Organizations"),
|
|
114
|
+
value: K.organizations,
|
|
115
|
+
loading: Y,
|
|
117
116
|
icon: /* @__PURE__ */ E(_, { className: "h-5 w-5 text-text-secondary" })
|
|
118
117
|
}),
|
|
119
118
|
/* @__PURE__ */ E(r, {
|
|
120
|
-
title:
|
|
121
|
-
value:
|
|
122
|
-
loading:
|
|
119
|
+
title: P("admin.dashboard.metrics.activeWorkspaces", "Active Workspaces"),
|
|
120
|
+
value: K.workspaces,
|
|
121
|
+
loading: Y,
|
|
123
122
|
icon: /* @__PURE__ */ E(x, { className: "h-5 w-5 text-status-success-text" })
|
|
124
123
|
}),
|
|
125
124
|
/* @__PURE__ */ E(r, {
|
|
126
|
-
title:
|
|
127
|
-
value:
|
|
128
|
-
loading:
|
|
125
|
+
title: P("admin.dashboard.metrics.totalUsers", "Total Users"),
|
|
126
|
+
value: K.users,
|
|
127
|
+
loading: Y,
|
|
129
128
|
icon: /* @__PURE__ */ E(w, { className: "h-5 w-5 text-text-secondary" })
|
|
130
129
|
})
|
|
131
130
|
] }),
|
|
@@ -134,12 +133,12 @@ function j() {
|
|
|
134
133
|
children: [/* @__PURE__ */ E("div", {
|
|
135
134
|
className: "lg:col-span-2",
|
|
136
135
|
children: /* @__PURE__ */ E(a, {
|
|
137
|
-
activities:
|
|
138
|
-
loading:
|
|
136
|
+
activities: q,
|
|
137
|
+
loading: G
|
|
139
138
|
})
|
|
140
139
|
}), /* @__PURE__ */ E("div", {
|
|
141
140
|
className: "space-y-4",
|
|
142
|
-
children: /* @__PURE__ */ E(o, { links:
|
|
141
|
+
children: /* @__PURE__ */ E(o, { links: J })
|
|
143
142
|
})]
|
|
144
143
|
})
|
|
145
144
|
]
|
|
@@ -148,6 +147,6 @@ function j() {
|
|
|
148
147
|
});
|
|
149
148
|
}
|
|
150
149
|
//#endregion
|
|
151
|
-
export {
|
|
150
|
+
export { A as DashboardPage };
|
|
152
151
|
|
|
153
152
|
//# sourceMappingURL=DashboardPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/admin/pages/DashboardPage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport {\n Building2,\n Users,\n Layout,\n Briefcase,\n Plus,\n UserPlus,\n FileText,\n HelpCircle,\n} from 'lucide-react';\nimport { useAdmin } from '../providers/AdminProvider';\nimport { useAdminPermissions } from '../hooks/useAdminPermissions';\nimport {\n PageLayout,\n MetricCard,\n MetricsGrid,\n ActivityFeed,\n QuickLinks,\n PermissionGuard,\n} from '../components';\nimport { useNavigate } from 'react-router';\nimport { PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { joinPath } from '../utils/navigation';\nimport { mapActivityLogToUi } from '../utils/mappers';\nimport type { Activity } from '../types';\nimport {\n useGetDashboardTenantCountQuery,\n useGetDashboardOrganizationCountQuery,\n useGetDashboardActiveWorkspaceCountQuery,\n useGetDashboardUserCountQuery,\n useGetRecentActivityLogsQuery,\n} from '../../generated/global-operations';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\n\n/**\n * Dashboard page — platform overview with real-time metrics\n */\nexport function DashboardPage() {\n const { canViewDashboard, isLoading: permissionsLoading } = useAdminPermissions();\n const { basePath = '' } = useAdmin();\n const navigate = useNavigate();\n const { t } = useI18n();\n const tr = (key: string, fallback: string, params?: Record<string, string | number>): string =>\n tWithFallback(t, key, fallback, params);\n\n const skipQueries = permissionsLoading || !canViewDashboard;\n\n const { data: tenantData, loading: tenantLoading } = useGetDashboardTenantCountQuery({\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n const { data: orgData, loading: orgLoading } = useGetDashboardOrganizationCountQuery({\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n const { data: workspaceData, loading: workspaceLoading } =\n useGetDashboardActiveWorkspaceCountQuery({\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n const { data: userData, loading: userLoading } = useGetDashboardUserCountQuery({\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n const { data: activityData, loading: activityLoading } = useGetRecentActivityLogsQuery({\n variables: { limit: 10 },\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n\n const metrics = {\n tenants: tenantData?.tenants?.total ?? 0,\n organizations: orgData?.allOrganizations?.total ?? 0,\n workspaces: workspaceData?.allWorkspaces?.total ?? 0,\n users: userData?.userCount ?? 0,\n };\n\n const recentActivity: Activity[] = useMemo(\n () => (activityData?.activityLogs?.nodes ?? []).map(mapActivityLogToUi),\n [activityData]\n );\n\n const quickLinks = [\n {\n to: joinPath(basePath, 'tenants'),\n label: tr('admin.dashboard.quickLinks.addTenant', 'Add Tenant'),\n icon: <Plus className=\"h-4 w-4\" />,\n description: tr('admin.dashboard.quickLinks.addTenantDescription', 'Create a new tenant'),\n },\n {\n to: joinPath(basePath, 'users'),\n label: tr('admin.dashboard.quickLinks.inviteUser', 'Invite User'),\n icon: <UserPlus className=\"h-4 w-4\" />,\n description: tr('admin.dashboard.quickLinks.inviteUserDescription', 'Invite a new user'),\n },\n {\n to: joinPath(basePath, 'audit'),\n label: tr('admin.dashboard.quickLinks.auditLogs', 'Audit Logs'),\n icon: <FileText className=\"h-4 w-4\" />,\n description: tr(\n 'admin.dashboard.quickLinks.auditLogsDescription',\n 'View security audit trail'\n ),\n },\n {\n to: joinPath(basePath, 'support'),\n label: tr('admin.dashboard.quickLinks.support', 'Support'),\n icon: <HelpCircle className=\"h-4 w-4\" />,\n description: tr('admin.dashboard.quickLinks.supportDescription', 'Manage support tickets'),\n },\n ];\n\n const isLoading = tenantLoading || orgLoading || workspaceLoading || userLoading;\n\n return (\n <PermissionGuard\n allowed={canViewDashboard}\n isLoading={permissionsLoading}\n pageTitle={tr('admin.dashboard.title', 'Dashboard')}\n denyMessage={tr(\n 'admin.dashboard.denyMessage',\n \"You don't have permission to view the admin dashboard.\"\n )}\n >\n <PageLayout\n title={tr('admin.dashboard.title', 'Dashboard')}\n description={tr('admin.dashboard.description', 'Platform overview and key metrics')}\n gradientWord={tr('admin.dashboard.title', 'Dashboard')}\n aurora\n >\n <div className=\"space-y-6\">\n <PagePurpose>\n {tr(\n 'admin.dashboard.purpose',\n 'Your control tower for the whole platform. See live tenant, organization, workspace and user counts at a glance, watch the most recent administrative activity, and jump straight into the day-to-day jobs — onboarding a tenant, inviting a user, or reviewing the audit trail.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"admin-dashboard\"\n steps={[\n {\n id: 'add-tenant',\n label: tr('admin.dashboard.nextSteps.addTenant', 'Onboard a tenant'),\n description: tr(\n 'admin.dashboard.nextSteps.addTenantDesc',\n 'Provision a new customer tenant to start serving them.'\n ),\n onClick: () => navigate(joinPath(basePath, 'tenants/new')),\n },\n {\n id: 'invite-user',\n label: tr('admin.dashboard.nextSteps.inviteUser', 'Invite a teammate'),\n description: tr(\n 'admin.dashboard.nextSteps.inviteUserDesc',\n 'Bring another operator into the admin console.'\n ),\n onClick: () => navigate(joinPath(basePath, 'users')),\n },\n {\n id: 'review-audit',\n label: tr('admin.dashboard.nextSteps.reviewAudit', 'Review the audit trail'),\n description: tr(\n 'admin.dashboard.nextSteps.reviewAuditDesc',\n 'Check who changed what across the platform.'\n ),\n onClick: () => navigate(joinPath(basePath, 'audit')),\n },\n ]}\n />\n\n {/* Metrics Grid */}\n <MetricsGrid>\n <MetricCard\n title={tr('admin.dashboard.metrics.totalTenants', 'Total Tenants')}\n value={metrics.tenants}\n loading={isLoading}\n hero\n icon={<Building2 className=\"h-5 w-5 text-action-primary-bg\" />}\n />\n <MetricCard\n title={tr('admin.dashboard.metrics.organizations', 'Organizations')}\n value={metrics.organizations}\n loading={isLoading}\n icon={<Briefcase className=\"h-5 w-5 text-text-secondary\" />}\n />\n <MetricCard\n title={tr('admin.dashboard.metrics.activeWorkspaces', 'Active Workspaces')}\n value={metrics.workspaces}\n loading={isLoading}\n icon={<Layout className=\"h-5 w-5 text-status-success-text\" />}\n />\n <MetricCard\n title={tr('admin.dashboard.metrics.totalUsers', 'Total Users')}\n value={metrics.users}\n loading={isLoading}\n icon={<Users className=\"h-5 w-5 text-text-secondary\" />}\n />\n </MetricsGrid>\n\n {/* Content Area */}\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <div className=\"lg:col-span-2\">\n <ActivityFeed activities={recentActivity} loading={activityLoading} />\n </div>\n <div className=\"space-y-4\">\n <QuickLinks links={quickLinks} />\n </div>\n </div>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/admin/pages/DashboardPage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport {\n Building2,\n Users,\n Layout,\n Briefcase,\n Plus,\n UserPlus,\n FileText,\n HelpCircle,\n} from 'lucide-react';\nimport { useAdmin } from '../providers/AdminProvider';\nimport { useAdminPermissions } from '../hooks/useAdminPermissions';\nimport {\n PageLayout,\n MetricCard,\n MetricsGrid,\n ActivityFeed,\n QuickLinks,\n PermissionGuard,\n} from '../components';\nimport { useNavigate } from 'react-router';\nimport { PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { joinPath } from '../utils/navigation';\nimport { mapActivityLogToUi } from '../utils/mappers';\nimport type { Activity } from '../types';\nimport {\n useGetDashboardTenantCountQuery,\n useGetDashboardOrganizationCountQuery,\n useGetDashboardActiveWorkspaceCountQuery,\n useGetDashboardUserCountQuery,\n useGetRecentActivityLogsQuery,\n} from '../../generated/global-operations';\nimport { useTr } from '../hooks/useTr';\n\n/**\n * Dashboard page — platform overview with real-time metrics\n */\nexport function DashboardPage() {\n const { canViewDashboard, isLoading: permissionsLoading } = useAdminPermissions();\n const { basePath = '' } = useAdmin();\n const navigate = useNavigate();\n const tr = useTr();\n\n const skipQueries = permissionsLoading || !canViewDashboard;\n\n const { data: tenantData, loading: tenantLoading } = useGetDashboardTenantCountQuery({\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n const { data: orgData, loading: orgLoading } = useGetDashboardOrganizationCountQuery({\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n const { data: workspaceData, loading: workspaceLoading } =\n useGetDashboardActiveWorkspaceCountQuery({\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n const { data: userData, loading: userLoading } = useGetDashboardUserCountQuery({\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n const { data: activityData, loading: activityLoading } = useGetRecentActivityLogsQuery({\n variables: { limit: 10 },\n fetchPolicy: 'cache-and-network',\n skip: skipQueries,\n });\n\n const metrics = {\n tenants: tenantData?.tenants?.total ?? 0,\n organizations: orgData?.allOrganizations?.total ?? 0,\n workspaces: workspaceData?.allWorkspaces?.total ?? 0,\n users: userData?.userCount ?? 0,\n };\n\n const recentActivity: Activity[] = useMemo(\n () => (activityData?.activityLogs?.nodes ?? []).map(mapActivityLogToUi),\n [activityData]\n );\n\n const quickLinks = [\n {\n to: joinPath(basePath, 'tenants'),\n label: tr('admin.dashboard.quickLinks.addTenant', 'Add Tenant'),\n icon: <Plus className=\"h-4 w-4\" />,\n description: tr('admin.dashboard.quickLinks.addTenantDescription', 'Create a new tenant'),\n },\n {\n to: joinPath(basePath, 'users'),\n label: tr('admin.dashboard.quickLinks.inviteUser', 'Invite User'),\n icon: <UserPlus className=\"h-4 w-4\" />,\n description: tr('admin.dashboard.quickLinks.inviteUserDescription', 'Invite a new user'),\n },\n {\n to: joinPath(basePath, 'audit'),\n label: tr('admin.dashboard.quickLinks.auditLogs', 'Audit Logs'),\n icon: <FileText className=\"h-4 w-4\" />,\n description: tr(\n 'admin.dashboard.quickLinks.auditLogsDescription',\n 'View security audit trail'\n ),\n },\n {\n to: joinPath(basePath, 'support'),\n label: tr('admin.dashboard.quickLinks.support', 'Support'),\n icon: <HelpCircle className=\"h-4 w-4\" />,\n description: tr('admin.dashboard.quickLinks.supportDescription', 'Manage support tickets'),\n },\n ];\n\n const isLoading = tenantLoading || orgLoading || workspaceLoading || userLoading;\n\n return (\n <PermissionGuard\n allowed={canViewDashboard}\n isLoading={permissionsLoading}\n pageTitle={tr('admin.dashboard.title', 'Dashboard')}\n denyMessage={tr(\n 'admin.dashboard.denyMessage',\n \"You don't have permission to view the admin dashboard.\"\n )}\n >\n <PageLayout\n title={tr('admin.dashboard.title', 'Dashboard')}\n description={tr('admin.dashboard.description', 'Platform overview and key metrics')}\n gradientWord={tr('admin.dashboard.title', 'Dashboard')}\n aurora\n >\n <div className=\"space-y-6\">\n <PagePurpose>\n {tr(\n 'admin.dashboard.purpose',\n 'Your control tower for the whole platform. See live tenant, organization, workspace and user counts at a glance, watch the most recent administrative activity, and jump straight into the day-to-day jobs — onboarding a tenant, inviting a user, or reviewing the audit trail.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"admin-dashboard\"\n steps={[\n {\n id: 'add-tenant',\n label: tr('admin.dashboard.nextSteps.addTenant', 'Onboard a tenant'),\n description: tr(\n 'admin.dashboard.nextSteps.addTenantDesc',\n 'Provision a new customer tenant to start serving them.'\n ),\n onClick: () => navigate(joinPath(basePath, 'tenants/new')),\n },\n {\n id: 'invite-user',\n label: tr('admin.dashboard.nextSteps.inviteUser', 'Invite a teammate'),\n description: tr(\n 'admin.dashboard.nextSteps.inviteUserDesc',\n 'Bring another operator into the admin console.'\n ),\n onClick: () => navigate(joinPath(basePath, 'users')),\n },\n {\n id: 'review-audit',\n label: tr('admin.dashboard.nextSteps.reviewAudit', 'Review the audit trail'),\n description: tr(\n 'admin.dashboard.nextSteps.reviewAuditDesc',\n 'Check who changed what across the platform.'\n ),\n onClick: () => navigate(joinPath(basePath, 'audit')),\n },\n ]}\n />\n\n {/* Metrics Grid */}\n <MetricsGrid>\n <MetricCard\n title={tr('admin.dashboard.metrics.totalTenants', 'Total Tenants')}\n value={metrics.tenants}\n loading={isLoading}\n hero\n icon={<Building2 className=\"h-5 w-5 text-action-primary-bg\" />}\n />\n <MetricCard\n title={tr('admin.dashboard.metrics.organizations', 'Organizations')}\n value={metrics.organizations}\n loading={isLoading}\n icon={<Briefcase className=\"h-5 w-5 text-text-secondary\" />}\n />\n <MetricCard\n title={tr('admin.dashboard.metrics.activeWorkspaces', 'Active Workspaces')}\n value={metrics.workspaces}\n loading={isLoading}\n icon={<Layout className=\"h-5 w-5 text-status-success-text\" />}\n />\n <MetricCard\n title={tr('admin.dashboard.metrics.totalUsers', 'Total Users')}\n value={metrics.users}\n loading={isLoading}\n icon={<Users className=\"h-5 w-5 text-text-secondary\" />}\n />\n </MetricsGrid>\n\n {/* Content Area */}\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <div className=\"lg:col-span-2\">\n <ActivityFeed activities={recentActivity} loading={activityLoading} />\n </div>\n <div className=\"space-y-4\">\n <QuickLinks links={quickLinks} />\n </div>\n </div>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n}\n"],"mappings":"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"}
|