@burdenoff/microfe-assethandler 2026.624.1 → 2026.625.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/assethandler/pages/AiPredictionsPage.js +49 -42
- package/dist/assethandler/pages/AiPredictionsPage.js.map +1 -1
- package/dist/assethandler/pages/AnalyticsPage.js +539 -514
- package/dist/assethandler/pages/AnalyticsPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetCategoriesPage.js +143 -133
- package/dist/assethandler/pages/AssetsAssetCategoriesPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetCheckInOutPage.js +90 -92
- package/dist/assethandler/pages/AssetsAssetCheckInOutPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetCreatePage.js +131 -124
- package/dist/assethandler/pages/AssetsAssetCreatePage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetDetailPage.js +220 -191
- package/dist/assethandler/pages/AssetsAssetDetailPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetEditPage.js +168 -156
- package/dist/assethandler/pages/AssetsAssetEditPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetListPage.js +219 -193
- package/dist/assethandler/pages/AssetsAssetListPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetTrackingPage.js +82 -71
- package/dist/assethandler/pages/AssetsAssetTrackingPage.js.map +1 -1
- package/dist/assethandler/pages/AuditTrailPage.js +127 -109
- package/dist/assethandler/pages/AuditTrailPage.js.map +1 -1
- package/dist/assethandler/pages/CmdbBrowserPage.js +39 -34
- package/dist/assethandler/pages/CmdbBrowserPage.js.map +1 -1
- package/dist/assethandler/pages/DashboardPage.js +245 -197
- package/dist/assethandler/pages/DashboardPage.js.map +1 -1
- package/dist/assethandler/pages/DigitalTwinPage.js +32 -27
- package/dist/assethandler/pages/DigitalTwinPage.js.map +1 -1
- package/dist/assethandler/pages/DiscoveryJobsPage.js +57 -51
- package/dist/assethandler/pages/DiscoveryJobsPage.js.map +1 -1
- package/dist/assethandler/pages/EsgDashboardPage.js +50 -43
- package/dist/assethandler/pages/EsgDashboardPage.js.map +1 -1
- package/dist/assethandler/pages/FinanceBudgetDetailPage.js +98 -84
- package/dist/assethandler/pages/FinanceBudgetDetailPage.js.map +1 -1
- package/dist/assethandler/pages/FinanceFinanceHubPage.js +151 -117
- package/dist/assethandler/pages/FinanceFinanceHubPage.js.map +1 -1
- package/dist/assethandler/pages/FinanceInvoiceDetailPage.js +77 -66
- package/dist/assethandler/pages/FinanceInvoiceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/IotDevicesPage.js +41 -36
- package/dist/assethandler/pages/IotDevicesPage.js.map +1 -1
- package/dist/assethandler/pages/ItilChangeDetailPage.js +236 -199
- package/dist/assethandler/pages/ItilChangeDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilChangeManagementPage.js +69 -67
- package/dist/assethandler/pages/ItilChangeManagementPage.js.map +1 -1
- package/dist/assethandler/pages/ItilIncidentDetailPage.js +237 -200
- package/dist/assethandler/pages/ItilIncidentDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilIncidentManagementPage.js +103 -101
- package/dist/assethandler/pages/ItilIncidentManagementPage.js.map +1 -1
- package/dist/assethandler/pages/ItilItilhubPage.js +168 -124
- package/dist/assethandler/pages/ItilItilhubPage.js.map +1 -1
- package/dist/assethandler/pages/ItilProblemDetailPage.js +193 -156
- package/dist/assethandler/pages/ItilProblemDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilProblemManagementPage.js +66 -64
- package/dist/assethandler/pages/ItilProblemManagementPage.js.map +1 -1
- package/dist/assethandler/pages/KnowledgeBasePage.js +52 -44
- package/dist/assethandler/pages/KnowledgeBasePage.js.map +1 -1
- package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js +72 -70
- package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js.map +1 -1
- package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js +77 -62
- package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js.map +1 -1
- package/dist/assethandler/pages/MarketplaceMarketplaceDetailPage.js +162 -151
- package/dist/assethandler/pages/MarketplaceMarketplaceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/MarketplaceMarketplaceListPage.js +68 -61
- package/dist/assethandler/pages/MarketplaceMarketplaceListPage.js.map +1 -1
- package/dist/assethandler/pages/MarketplaceMarketplaceOrdersPage.js +125 -108
- package/dist/assethandler/pages/MarketplaceMarketplaceOrdersPage.js.map +1 -1
- package/dist/assethandler/pages/MarketplaceMarketplaceSellPage.js +67 -61
- package/dist/assethandler/pages/MarketplaceMarketplaceSellPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js +203 -166
- package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsOperationsHubPage.js +126 -96
- package/dist/assethandler/pages/OperationsOperationsHubPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js +165 -151
- package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js.map +1 -1
- package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js +123 -105
- package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js.map +1 -1
- package/dist/assethandler/pages/ProvenancePage.js +60 -52
- package/dist/assethandler/pages/ProvenancePage.js.map +1 -1
- package/dist/assethandler/pages/ReportsReportBuilderPage.js +80 -73
- package/dist/assethandler/pages/ReportsReportBuilderPage.js.map +1 -1
- package/dist/assethandler/pages/ReportsReportsDashboardPage.js +114 -79
- package/dist/assethandler/pages/ReportsReportsDashboardPage.js.map +1 -1
- package/dist/assethandler/pages/ReportsReportsListPage.js +119 -103
- package/dist/assethandler/pages/ReportsReportsListPage.js.map +1 -1
- package/dist/assethandler/pages/SamLicensesPage.js +39 -34
- package/dist/assethandler/pages/SamLicensesPage.js.map +1 -1
- package/dist/assethandler/pages/SecurityComplianceDetailPage.js +63 -55
- package/dist/assethandler/pages/SecurityComplianceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecurityPolicyDetailPage.js +134 -117
- package/dist/assethandler/pages/SecurityPolicyDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecurityScheduleBackupPage.js +64 -58
- package/dist/assethandler/pages/SecurityScheduleBackupPage.js.map +1 -1
- package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js +131 -117
- package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecuritySecurityHubPage.js +151 -117
- package/dist/assethandler/pages/SecuritySecurityHubPage.js.map +1 -1
- package/dist/assethandler/pages/TransactionsTransactionDetailPage.js +235 -218
- package/dist/assethandler/pages/TransactionsTransactionDetailPage.js.map +1 -1
- package/dist/assethandler/pages/TransactionsTransactionListPage.js +145 -127
- package/dist/assethandler/pages/TransactionsTransactionListPage.js.map +1 -1
- package/dist/assethandler/pages/UsersPage.js +135 -110
- package/dist/assethandler/pages/UsersPage.js.map +1 -1
- package/dist/assethandler/pages/UsersUserCreatePage.js +74 -67
- package/dist/assethandler/pages/UsersUserCreatePage.js.map +1 -1
- package/dist/assethandler/pages/UsersUserManagementHubPage.js +178 -130
- package/dist/assethandler/pages/UsersUserManagementHubPage.js.map +1 -1
- package/dist/assethandler/pages/WorkflowsWorkflowBuilderPage.js +211 -193
- package/dist/assethandler/pages/WorkflowsWorkflowBuilderPage.js.map +1 -1
- package/dist/assethandler/pages/WorkflowsWorkflowExecutionsPage.js +126 -108
- package/dist/assethandler/pages/WorkflowsWorkflowExecutionsPage.js.map +1 -1
- package/dist/assethandler/pages/WorkflowsWorkflowListPage.js +71 -63
- package/dist/assethandler/pages/WorkflowsWorkflowListPage.js.map +1 -1
- package/dist/assethandler/pages/WorkflowsWorkflowTemplatesPage.js +96 -81
- package/dist/assethandler/pages/WorkflowsWorkflowTemplatesPage.js.map +1 -1
- package/package.json +2 -2
|
@@ -2,151 +2,171 @@ import { useAssetHandlerStore as e } from "../store/assethandlerStore.js";
|
|
|
2
2
|
import { tWithFallback as t } from "../utils/i18n.js";
|
|
3
3
|
import { useState as n } from "react";
|
|
4
4
|
import { Building as r, Filter as i, Plus as a, Search as o, Shield as s, UserCheck as c, Users as l } from "lucide-react";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { useNavigate as u } from "react-router-dom";
|
|
6
|
+
import { Badge as d, Button as f, Card as p, CardContent as m, CardHeader as h, CardTitle as g, GlassCard as _, GradientText as v, IllustratedEmptyState as y, Input as b, PagePurpose as x, Select as S, SelectContent as C, SelectItem as w, SelectTrigger as T, SelectValue as E, Table as D, TableBody as O, TableCell as k, TableHead as A, TableHeader as j, TableRow as M } from "@burdenoff/fe-libs/ui";
|
|
7
|
+
import { useI18n as N } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
8
|
+
import { jsx as P, jsxs as F } from "react/jsx-runtime";
|
|
8
9
|
//#region src/assethandler/pages/UsersPage.tsx
|
|
9
|
-
var
|
|
10
|
+
var I = {
|
|
10
11
|
admin: "destructive",
|
|
11
12
|
manager: "default",
|
|
12
13
|
technician: "secondary",
|
|
13
14
|
viewer: "outline",
|
|
14
15
|
auditor: "secondary"
|
|
15
|
-
},
|
|
16
|
+
}, L = {
|
|
16
17
|
active: "default",
|
|
17
18
|
inactive: "secondary",
|
|
18
19
|
suspended: "destructive",
|
|
19
20
|
pending: "outline"
|
|
20
21
|
};
|
|
21
|
-
function
|
|
22
|
-
let { t:
|
|
23
|
-
if (
|
|
24
|
-
if (
|
|
25
|
-
let t =
|
|
22
|
+
function R() {
|
|
23
|
+
let { t: R } = N(), z = u(), { users: B } = e(), [V, H] = n(""), [U, W] = n("all"), G = B.filter((e) => {
|
|
24
|
+
if (U !== "all" && e.role !== U) return !1;
|
|
25
|
+
if (V) {
|
|
26
|
+
let t = V.toLowerCase();
|
|
26
27
|
return e.firstName.toLowerCase().includes(t) || e.lastName.toLowerCase().includes(t) || e.email.toLowerCase().includes(t);
|
|
27
28
|
}
|
|
28
29
|
return !0;
|
|
29
|
-
}),
|
|
30
|
-
return /* @__PURE__ */
|
|
30
|
+
}), K = B.filter((e) => e.status === "active").length, q = B.filter((e) => e.role === "admin").length, J = [...new Set(B.map((e) => e.department))].length;
|
|
31
|
+
return /* @__PURE__ */ F("div", {
|
|
31
32
|
className: "space-y-6 p-6",
|
|
32
33
|
children: [
|
|
33
|
-
/* @__PURE__ */
|
|
34
|
+
/* @__PURE__ */ F("div", {
|
|
34
35
|
className: "flex items-center justify-between",
|
|
35
|
-
children: [/* @__PURE__ */
|
|
36
|
+
children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("h1", {
|
|
36
37
|
className: "text-2xl font-semibold",
|
|
37
|
-
children: t(
|
|
38
|
-
}), /* @__PURE__ */
|
|
38
|
+
children: /* @__PURE__ */ P(v, { children: t(R, "assethandler.users.title", "Users") })
|
|
39
|
+
}), /* @__PURE__ */ P("p", {
|
|
39
40
|
className: "text-sm text-text-secondary",
|
|
40
|
-
children: t(
|
|
41
|
-
})] }), /* @__PURE__ */
|
|
41
|
+
children: t(R, "assethandler.users.description", "Manage user accounts, roles, and access permissions.")
|
|
42
|
+
})] }), /* @__PURE__ */ F(f, {
|
|
42
43
|
size: "sm",
|
|
43
|
-
|
|
44
|
+
onClick: () => z("/users/user-create"),
|
|
45
|
+
children: [/* @__PURE__ */ P(a, { className: "mr-2 h-4 w-4" }), t(R, "assethandler.users.actions.addUser", "Add User")]
|
|
44
46
|
})]
|
|
45
47
|
}),
|
|
46
|
-
/* @__PURE__ */
|
|
48
|
+
/* @__PURE__ */ P(x, { children: t(R, "assethandler.users.purpose", "The directory of everyone who uses Asset Handler — their role, department, status and how many assets they hold. Use it to onboard and offboard people, adjust access, and see at a glance who is responsible for what.") }),
|
|
49
|
+
/* @__PURE__ */ F("div", {
|
|
47
50
|
className: "grid gap-4 md:grid-cols-4",
|
|
48
51
|
children: [
|
|
49
|
-
/* @__PURE__ */
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
className: "
|
|
67
|
-
children:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
className: "
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
className: "
|
|
81
|
-
children: [/* @__PURE__ */
|
|
82
|
-
className: "
|
|
83
|
-
children:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
children:
|
|
88
|
-
|
|
52
|
+
/* @__PURE__ */ F(_, {
|
|
53
|
+
treatment: "glass",
|
|
54
|
+
glow: !0,
|
|
55
|
+
className: "border-border-seam",
|
|
56
|
+
children: [/* @__PURE__ */ F(h, {
|
|
57
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
58
|
+
children: [/* @__PURE__ */ P(g, {
|
|
59
|
+
className: "text-sm font-medium",
|
|
60
|
+
children: t(R, "assethandler.users.stats.totalUsers", "Total Users")
|
|
61
|
+
}), /* @__PURE__ */ P(l, { className: "h-4 w-4 text-text-secondary" })]
|
|
62
|
+
}), /* @__PURE__ */ P(m, { children: /* @__PURE__ */ P("div", {
|
|
63
|
+
className: "text-2xl font-bold tabular-nums",
|
|
64
|
+
children: B.length
|
|
65
|
+
}) })]
|
|
66
|
+
}),
|
|
67
|
+
/* @__PURE__ */ F(_, {
|
|
68
|
+
treatment: "metric",
|
|
69
|
+
className: "border-border-seam",
|
|
70
|
+
children: [/* @__PURE__ */ F(h, {
|
|
71
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
72
|
+
children: [/* @__PURE__ */ P(g, {
|
|
73
|
+
className: "text-sm font-medium",
|
|
74
|
+
children: t(R, "assethandler.users.stats.activeUsers", "Active Users")
|
|
75
|
+
}), /* @__PURE__ */ P(c, { className: "h-4 w-4 text-status-success-text" })]
|
|
76
|
+
}), /* @__PURE__ */ P(m, { children: /* @__PURE__ */ P("div", {
|
|
77
|
+
className: "text-2xl font-bold tabular-nums",
|
|
78
|
+
children: K
|
|
79
|
+
}) })]
|
|
80
|
+
}),
|
|
81
|
+
/* @__PURE__ */ F(_, {
|
|
82
|
+
treatment: "metric",
|
|
83
|
+
className: "border-border-seam",
|
|
84
|
+
children: [/* @__PURE__ */ F(h, {
|
|
85
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
86
|
+
children: [/* @__PURE__ */ P(g, {
|
|
87
|
+
className: "text-sm font-medium",
|
|
88
|
+
children: t(R, "assethandler.users.stats.administrators", "Administrators")
|
|
89
|
+
}), /* @__PURE__ */ P(s, { className: "h-4 w-4 text-status-error-text" })]
|
|
90
|
+
}), /* @__PURE__ */ P(m, { children: /* @__PURE__ */ P("div", {
|
|
91
|
+
className: "text-2xl font-bold tabular-nums",
|
|
92
|
+
children: q
|
|
93
|
+
}) })]
|
|
94
|
+
}),
|
|
95
|
+
/* @__PURE__ */ F(_, {
|
|
96
|
+
treatment: "metric",
|
|
97
|
+
className: "border-border-seam",
|
|
98
|
+
children: [/* @__PURE__ */ F(h, {
|
|
99
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
100
|
+
children: [/* @__PURE__ */ P(g, {
|
|
101
|
+
className: "text-sm font-medium",
|
|
102
|
+
children: t(R, "assethandler.users.stats.departments", "Departments")
|
|
103
|
+
}), /* @__PURE__ */ P(r, { className: "h-4 w-4 text-text-secondary" })]
|
|
104
|
+
}), /* @__PURE__ */ P(m, { children: /* @__PURE__ */ P("div", {
|
|
105
|
+
className: "text-2xl font-bold tabular-nums",
|
|
106
|
+
children: J
|
|
107
|
+
}) })]
|
|
108
|
+
})
|
|
89
109
|
]
|
|
90
110
|
}),
|
|
91
|
-
/* @__PURE__ */
|
|
111
|
+
/* @__PURE__ */ F(p, { children: [/* @__PURE__ */ P(h, { children: /* @__PURE__ */ F("div", {
|
|
92
112
|
className: "flex items-center justify-between",
|
|
93
|
-
children: [/* @__PURE__ */
|
|
113
|
+
children: [/* @__PURE__ */ P(g, { children: t(R, "assethandler.users.table.title", "All Users") }), /* @__PURE__ */ F("div", {
|
|
94
114
|
className: "flex items-center gap-2",
|
|
95
|
-
children: [/* @__PURE__ */
|
|
115
|
+
children: [/* @__PURE__ */ F("div", {
|
|
96
116
|
className: "relative",
|
|
97
|
-
children: [/* @__PURE__ */
|
|
98
|
-
placeholder: t(
|
|
99
|
-
value:
|
|
100
|
-
onChange: (e) =>
|
|
117
|
+
children: [/* @__PURE__ */ P(o, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary" }), /* @__PURE__ */ P(b, {
|
|
118
|
+
placeholder: t(R, "assethandler.users.search.placeholder", "Search users..."),
|
|
119
|
+
value: V,
|
|
120
|
+
onChange: (e) => H(e.target.value),
|
|
101
121
|
className: "pl-9 w-[220px]"
|
|
102
122
|
})]
|
|
103
|
-
}), /* @__PURE__ */
|
|
104
|
-
value:
|
|
105
|
-
onValueChange:
|
|
106
|
-
children: [/* @__PURE__ */
|
|
123
|
+
}), /* @__PURE__ */ F(S, {
|
|
124
|
+
value: U,
|
|
125
|
+
onValueChange: W,
|
|
126
|
+
children: [/* @__PURE__ */ F(T, {
|
|
107
127
|
className: "w-[150px]",
|
|
108
|
-
children: [/* @__PURE__ */
|
|
109
|
-
}), /* @__PURE__ */
|
|
110
|
-
/* @__PURE__ */
|
|
128
|
+
children: [/* @__PURE__ */ P(i, { className: "mr-2 h-4 w-4" }), /* @__PURE__ */ P(E, { placeholder: t(R, "assethandler.users.filters.role.placeholder", "Role") })]
|
|
129
|
+
}), /* @__PURE__ */ F(C, { children: [
|
|
130
|
+
/* @__PURE__ */ P(w, {
|
|
111
131
|
value: "all",
|
|
112
|
-
children: t(
|
|
132
|
+
children: t(R, "assethandler.users.filters.role.all", "All Roles")
|
|
113
133
|
}),
|
|
114
|
-
/* @__PURE__ */
|
|
134
|
+
/* @__PURE__ */ P(w, {
|
|
115
135
|
value: "admin",
|
|
116
|
-
children: t(
|
|
136
|
+
children: t(R, "assethandler.users.filters.role.admin", "Admin")
|
|
117
137
|
}),
|
|
118
|
-
/* @__PURE__ */
|
|
138
|
+
/* @__PURE__ */ P(w, {
|
|
119
139
|
value: "manager",
|
|
120
|
-
children: t(
|
|
140
|
+
children: t(R, "assethandler.users.filters.role.manager", "Manager")
|
|
121
141
|
}),
|
|
122
|
-
/* @__PURE__ */
|
|
142
|
+
/* @__PURE__ */ P(w, {
|
|
123
143
|
value: "technician",
|
|
124
|
-
children: t(
|
|
144
|
+
children: t(R, "assethandler.users.filters.role.technician", "Technician")
|
|
125
145
|
}),
|
|
126
|
-
/* @__PURE__ */
|
|
146
|
+
/* @__PURE__ */ P(w, {
|
|
127
147
|
value: "viewer",
|
|
128
|
-
children: t(
|
|
148
|
+
children: t(R, "assethandler.users.filters.role.viewer", "Viewer")
|
|
129
149
|
}),
|
|
130
|
-
/* @__PURE__ */
|
|
150
|
+
/* @__PURE__ */ P(w, {
|
|
131
151
|
value: "auditor",
|
|
132
|
-
children: t(
|
|
152
|
+
children: t(R, "assethandler.users.filters.role.auditor", "Auditor")
|
|
133
153
|
})
|
|
134
154
|
] })]
|
|
135
155
|
})]
|
|
136
156
|
})]
|
|
137
|
-
}) }), /* @__PURE__ */
|
|
138
|
-
/* @__PURE__ */
|
|
139
|
-
/* @__PURE__ */
|
|
140
|
-
/* @__PURE__ */
|
|
141
|
-
/* @__PURE__ */
|
|
142
|
-
/* @__PURE__ */
|
|
143
|
-
/* @__PURE__ */
|
|
144
|
-
/* @__PURE__ */
|
|
157
|
+
}) }), /* @__PURE__ */ F(m, { children: [/* @__PURE__ */ F(D, { children: [/* @__PURE__ */ P(j, { children: /* @__PURE__ */ F(M, { children: [
|
|
158
|
+
/* @__PURE__ */ P(A, { children: t(R, "assethandler.users.table.name", "Name") }),
|
|
159
|
+
/* @__PURE__ */ P(A, { children: t(R, "assethandler.users.table.email", "Email") }),
|
|
160
|
+
/* @__PURE__ */ P(A, { children: t(R, "assethandler.users.table.role", "Role") }),
|
|
161
|
+
/* @__PURE__ */ P(A, { children: t(R, "assethandler.users.table.department", "Department") }),
|
|
162
|
+
/* @__PURE__ */ P(A, { children: t(R, "assethandler.users.table.status", "Status") }),
|
|
163
|
+
/* @__PURE__ */ P(A, { children: t(R, "assethandler.users.table.lastLogin", "Last Login") }),
|
|
164
|
+
/* @__PURE__ */ P(A, {
|
|
145
165
|
className: "text-right",
|
|
146
|
-
children: t(
|
|
166
|
+
children: t(R, "assethandler.users.table.assets", "Assets")
|
|
147
167
|
})
|
|
148
|
-
] }) }), /* @__PURE__ */
|
|
149
|
-
/* @__PURE__ */
|
|
168
|
+
] }) }), /* @__PURE__ */ P(O, { children: G.map((e) => /* @__PURE__ */ F(M, { children: [
|
|
169
|
+
/* @__PURE__ */ F(k, {
|
|
150
170
|
className: "font-medium",
|
|
151
171
|
children: [
|
|
152
172
|
e.firstName,
|
|
@@ -154,30 +174,35 @@ function N() {
|
|
|
154
174
|
e.lastName
|
|
155
175
|
]
|
|
156
176
|
}),
|
|
157
|
-
/* @__PURE__ */ k
|
|
158
|
-
/* @__PURE__ */ k
|
|
159
|
-
variant:
|
|
177
|
+
/* @__PURE__ */ P(k, { children: e.email }),
|
|
178
|
+
/* @__PURE__ */ P(k, { children: /* @__PURE__ */ P(d, {
|
|
179
|
+
variant: I[e.role] || "secondary",
|
|
160
180
|
children: e.role
|
|
161
181
|
}) }),
|
|
162
|
-
/* @__PURE__ */ k
|
|
163
|
-
/* @__PURE__ */ k
|
|
164
|
-
variant:
|
|
182
|
+
/* @__PURE__ */ P(k, { children: e.department }),
|
|
183
|
+
/* @__PURE__ */ P(k, { children: /* @__PURE__ */ P(d, {
|
|
184
|
+
variant: L[e.status] || "secondary",
|
|
165
185
|
children: e.status
|
|
166
186
|
}) }),
|
|
167
|
-
/* @__PURE__ */ k
|
|
168
|
-
/* @__PURE__ */ k
|
|
187
|
+
/* @__PURE__ */ P(k, { children: new Date(e.lastLogin).toLocaleDateString() }),
|
|
188
|
+
/* @__PURE__ */ P(k, {
|
|
169
189
|
className: "text-right",
|
|
170
190
|
children: e.assetsAssigned
|
|
171
191
|
})
|
|
172
|
-
] }, e.id)),
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
192
|
+
] }, e.id)) })] }), G.length === 0 && /* @__PURE__ */ P(y, {
|
|
193
|
+
illustration: "empty-people",
|
|
194
|
+
title: t(R, "assethandler.users.empty", "No users found"),
|
|
195
|
+
description: "No users match your search or filters. Add a user or clear the filters to see results.",
|
|
196
|
+
action: /* @__PURE__ */ F(f, {
|
|
197
|
+
size: "sm",
|
|
198
|
+
onClick: () => z("/users/user-create"),
|
|
199
|
+
children: [/* @__PURE__ */ P(a, { className: "mr-2 h-4 w-4" }), t(R, "assethandler.users.actions.addUser", "Add User")]
|
|
200
|
+
})
|
|
201
|
+
})] })] })
|
|
177
202
|
]
|
|
178
203
|
});
|
|
179
204
|
}
|
|
180
205
|
//#endregion
|
|
181
|
-
export {
|
|
206
|
+
export { R as UsersPage };
|
|
182
207
|
|
|
183
208
|
//# sourceMappingURL=UsersPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UsersPage.js","names":[],"sources":["../../../src/assethandler/pages/UsersPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Input,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@burdenoff/fe-libs/ui';\nimport { Plus, Search, Filter, Users, UserCheck, Shield, Building } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport { tWithFallback } from '../utils/i18n';\n\nconst roleColors: Record<string, 'default' | 'secondary' | 'destructive' | 'outline'> = {\n admin: 'destructive',\n manager: 'default',\n technician: 'secondary',\n viewer: 'outline',\n auditor: 'secondary',\n};\n\nconst statusColors: Record<string, 'default' | 'secondary' | 'destructive' | 'outline'> = {\n active: 'default',\n inactive: 'secondary',\n suspended: 'destructive',\n pending: 'outline',\n};\n\nexport function UsersPage() {\n const { t } = useI18n();\n const { users } = useAssetHandlerStore();\n const [search, setSearch] = useState('');\n const [roleFilter, setRoleFilter] = useState('all');\n\n const filtered = users.filter((u) => {\n if (roleFilter !== 'all' && u.role !== roleFilter) return false;\n if (search) {\n const q = search.toLowerCase();\n return (\n u.firstName.toLowerCase().includes(q) ||\n u.lastName.toLowerCase().includes(q) ||\n u.email.toLowerCase().includes(q)\n );\n }\n return true;\n });\n\n const activeUsers = users.filter((u) => u.status === 'active').length;\n const adminCount = users.filter((u) => u.role === 'admin').length;\n const departments = [...new Set(users.map((u) => u.department))].length;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n {tWithFallback(t, 'assethandler.users.title', 'Users')}\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n 'assethandler.users.description',\n 'Manage user accounts, roles, and access permissions.'\n )}\n </p>\n </div>\n <Button size=\"sm\">\n <Plus className=\"mr-2 h-4 w-4\" />\n {tWithFallback(t, 'assethandler.users.actions.addUser', 'Add User')}\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-4\">\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">\n {tWithFallback(t, 'assethandler.users.stats.totalUsers', 'Total Users')}\n </CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold\">{users.length}</div>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">\n {tWithFallback(t, 'assethandler.users.stats.activeUsers', 'Active Users')}\n </CardTitle>\n <UserCheck className=\"h-4 w-4 text-green-500\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold\">{activeUsers}</div>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">\n {tWithFallback(t, 'assethandler.users.stats.administrators', 'Administrators')}\n </CardTitle>\n <Shield className=\"h-4 w-4 text-red-500\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold\">{adminCount}</div>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">\n {tWithFallback(t, 'assethandler.users.stats.departments', 'Departments')}\n </CardTitle>\n <Building className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold\">{departments}</div>\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle>{tWithFallback(t, 'assethandler.users.table.title', 'All Users')}</CardTitle>\n <div className=\"flex items-center gap-2\">\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input\n placeholder={tWithFallback(\n t,\n 'assethandler.users.search.placeholder',\n 'Search users...'\n )}\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"pl-9 w-[220px]\"\n />\n </div>\n <Select value={roleFilter} onValueChange={setRoleFilter}>\n <SelectTrigger className=\"w-[150px]\">\n <Filter className=\"mr-2 h-4 w-4\" />\n <SelectValue\n placeholder={tWithFallback(\n t,\n 'assethandler.users.filters.role.placeholder',\n 'Role'\n )}\n />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">\n {tWithFallback(t, 'assethandler.users.filters.role.all', 'All Roles')}\n </SelectItem>\n <SelectItem value=\"admin\">\n {tWithFallback(t, 'assethandler.users.filters.role.admin', 'Admin')}\n </SelectItem>\n <SelectItem value=\"manager\">\n {tWithFallback(t, 'assethandler.users.filters.role.manager', 'Manager')}\n </SelectItem>\n <SelectItem value=\"technician\">\n {tWithFallback(t, 'assethandler.users.filters.role.technician', 'Technician')}\n </SelectItem>\n <SelectItem value=\"viewer\">\n {tWithFallback(t, 'assethandler.users.filters.role.viewer', 'Viewer')}\n </SelectItem>\n <SelectItem value=\"auditor\">\n {tWithFallback(t, 'assethandler.users.filters.role.auditor', 'Auditor')}\n </SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tWithFallback(t, 'assethandler.users.table.name', 'Name')}</TableHead>\n <TableHead>{tWithFallback(t, 'assethandler.users.table.email', 'Email')}</TableHead>\n <TableHead>{tWithFallback(t, 'assethandler.users.table.role', 'Role')}</TableHead>\n <TableHead>\n {tWithFallback(t, 'assethandler.users.table.department', 'Department')}\n </TableHead>\n <TableHead>\n {tWithFallback(t, 'assethandler.users.table.status', 'Status')}\n </TableHead>\n <TableHead>\n {tWithFallback(t, 'assethandler.users.table.lastLogin', 'Last Login')}\n </TableHead>\n <TableHead className=\"text-right\">\n {tWithFallback(t, 'assethandler.users.table.assets', 'Assets')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {filtered.map((user) => (\n <TableRow key={user.id}>\n <TableCell className=\"font-medium\">\n {user.firstName} {user.lastName}\n </TableCell>\n <TableCell>{user.email}</TableCell>\n <TableCell>\n <Badge variant={roleColors[user.role] || 'secondary'}>{user.role}</Badge>\n </TableCell>\n <TableCell>{user.department}</TableCell>\n <TableCell>\n <Badge variant={statusColors[user.status] || 'secondary'}>{user.status}</Badge>\n </TableCell>\n <TableCell>{new Date(user.lastLogin).toLocaleDateString()}</TableCell>\n <TableCell className=\"text-right\">{user.assetsAssigned}</TableCell>\n </TableRow>\n ))}\n {filtered.length === 0 && (\n <TableRow>\n <TableCell colSpan={7} className=\"text-center text-text-secondary py-8\">\n {tWithFallback(t, 'assethandler.users.empty', 'No users found.')}\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UsersPage.js","names":[],"sources":["../../../src/assethandler/pages/UsersPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Input,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n GradientText,\n GlassCard,\n PagePurpose,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\nimport { Plus, Search, Filter, Users, UserCheck, Shield, Building } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useNavigate } from 'react-router-dom';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport { tWithFallback } from '../utils/i18n';\n\nconst roleColors: Record<string, 'default' | 'secondary' | 'destructive' | 'outline'> = {\n admin: 'destructive',\n manager: 'default',\n technician: 'secondary',\n viewer: 'outline',\n auditor: 'secondary',\n};\n\nconst statusColors: Record<string, 'default' | 'secondary' | 'destructive' | 'outline'> = {\n active: 'default',\n inactive: 'secondary',\n suspended: 'destructive',\n pending: 'outline',\n};\n\nexport function UsersPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { users } = useAssetHandlerStore();\n const [search, setSearch] = useState('');\n const [roleFilter, setRoleFilter] = useState('all');\n\n const filtered = users.filter((u) => {\n if (roleFilter !== 'all' && u.role !== roleFilter) return false;\n if (search) {\n const q = search.toLowerCase();\n return (\n u.firstName.toLowerCase().includes(q) ||\n u.lastName.toLowerCase().includes(q) ||\n u.email.toLowerCase().includes(q)\n );\n }\n return true;\n });\n\n const activeUsers = users.filter((u) => u.status === 'active').length;\n const adminCount = users.filter((u) => u.role === 'admin').length;\n const departments = [...new Set(users.map((u) => u.department))].length;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>{tWithFallback(t, 'assethandler.users.title', 'Users')}</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n 'assethandler.users.description',\n 'Manage user accounts, roles, and access permissions.'\n )}\n </p>\n </div>\n <Button size=\"sm\" onClick={() => navigate('/users/user-create')}>\n <Plus className=\"mr-2 h-4 w-4\" />\n {tWithFallback(t, 'assethandler.users.actions.addUser', 'Add User')}\n </Button>\n </div>\n\n <PagePurpose>\n {tWithFallback(\n t,\n 'assethandler.users.purpose',\n 'The directory of everyone who uses Asset Handler — their role, department, status and how many assets they hold. Use it to onboard and offboard people, adjust access, and see at a glance who is responsible for what.'\n )}\n </PagePurpose>\n\n <div className=\"grid gap-4 md:grid-cols-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">\n {tWithFallback(t, 'assethandler.users.stats.totalUsers', 'Total Users')}\n </CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{users.length}</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">\n {tWithFallback(t, 'assethandler.users.stats.activeUsers', 'Active Users')}\n </CardTitle>\n <UserCheck className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activeUsers}</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">\n {tWithFallback(t, 'assethandler.users.stats.administrators', 'Administrators')}\n </CardTitle>\n <Shield className=\"h-4 w-4 text-status-error-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{adminCount}</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">\n {tWithFallback(t, 'assethandler.users.stats.departments', 'Departments')}\n </CardTitle>\n <Building className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{departments}</div>\n </CardContent>\n </GlassCard>\n </div>\n\n <Card>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle>{tWithFallback(t, 'assethandler.users.table.title', 'All Users')}</CardTitle>\n <div className=\"flex items-center gap-2\">\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input\n placeholder={tWithFallback(\n t,\n 'assethandler.users.search.placeholder',\n 'Search users...'\n )}\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"pl-9 w-[220px]\"\n />\n </div>\n <Select value={roleFilter} onValueChange={setRoleFilter}>\n <SelectTrigger className=\"w-[150px]\">\n <Filter className=\"mr-2 h-4 w-4\" />\n <SelectValue\n placeholder={tWithFallback(\n t,\n 'assethandler.users.filters.role.placeholder',\n 'Role'\n )}\n />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">\n {tWithFallback(t, 'assethandler.users.filters.role.all', 'All Roles')}\n </SelectItem>\n <SelectItem value=\"admin\">\n {tWithFallback(t, 'assethandler.users.filters.role.admin', 'Admin')}\n </SelectItem>\n <SelectItem value=\"manager\">\n {tWithFallback(t, 'assethandler.users.filters.role.manager', 'Manager')}\n </SelectItem>\n <SelectItem value=\"technician\">\n {tWithFallback(t, 'assethandler.users.filters.role.technician', 'Technician')}\n </SelectItem>\n <SelectItem value=\"viewer\">\n {tWithFallback(t, 'assethandler.users.filters.role.viewer', 'Viewer')}\n </SelectItem>\n <SelectItem value=\"auditor\">\n {tWithFallback(t, 'assethandler.users.filters.role.auditor', 'Auditor')}\n </SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tWithFallback(t, 'assethandler.users.table.name', 'Name')}</TableHead>\n <TableHead>{tWithFallback(t, 'assethandler.users.table.email', 'Email')}</TableHead>\n <TableHead>{tWithFallback(t, 'assethandler.users.table.role', 'Role')}</TableHead>\n <TableHead>\n {tWithFallback(t, 'assethandler.users.table.department', 'Department')}\n </TableHead>\n <TableHead>\n {tWithFallback(t, 'assethandler.users.table.status', 'Status')}\n </TableHead>\n <TableHead>\n {tWithFallback(t, 'assethandler.users.table.lastLogin', 'Last Login')}\n </TableHead>\n <TableHead className=\"text-right\">\n {tWithFallback(t, 'assethandler.users.table.assets', 'Assets')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {filtered.map((user) => (\n <TableRow key={user.id}>\n <TableCell className=\"font-medium\">\n {user.firstName} {user.lastName}\n </TableCell>\n <TableCell>{user.email}</TableCell>\n <TableCell>\n <Badge variant={roleColors[user.role] || 'secondary'}>{user.role}</Badge>\n </TableCell>\n <TableCell>{user.department}</TableCell>\n <TableCell>\n <Badge variant={statusColors[user.status] || 'secondary'}>{user.status}</Badge>\n </TableCell>\n <TableCell>{new Date(user.lastLogin).toLocaleDateString()}</TableCell>\n <TableCell className=\"text-right\">{user.assetsAssigned}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n {filtered.length === 0 && (\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title={tWithFallback(t, 'assethandler.users.empty', 'No users found')}\n description=\"No users match your search or filters. Add a user or clear the filters to see results.\"\n action={\n <Button size=\"sm\" onClick={() => navigate('/users/user-create')}>\n <Plus className=\"mr-2 h-4 w-4\" />\n {tWithFallback(t, 'assethandler.users.actions.addUser', 'Add User')}\n </Button>\n }\n />\n )}\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AA+BA,IAAM,IAAkF;CACtF,OAAO;CACP,SAAS;CACT,YAAY;CACZ,QAAQ;CACR,SAAS;CACV,EAEK,IAAoF;CACxF,QAAQ;CACR,UAAU;CACV,WAAW;CACX,SAAS;CACV;AAED,SAAgB,IAAY;CAC1B,IAAM,EAAE,SAAM,GAAS,EACjB,IAAW,GAAa,EACxB,EAAE,aAAU,GAAsB,EAClC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAY,KAAiB,EAAS,MAAM,EAE7C,IAAW,EAAM,QAAQ,MAAM;AACnC,MAAI,MAAe,SAAS,EAAE,SAAS,EAAY,QAAO;AAC1D,MAAI,GAAQ;GACV,IAAM,IAAI,EAAO,aAAa;AAC9B,UACE,EAAE,UAAU,aAAa,CAAC,SAAS,EAAE,IACrC,EAAE,SAAS,aAAa,CAAC,SAAS,EAAE,IACpC,EAAE,MAAM,aAAa,CAAC,SAAS,EAAE;;AAGrC,SAAO;GACP,EAEI,IAAc,EAAM,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC,QACzD,IAAa,EAAM,QAAQ,MAAM,EAAE,SAAS,QAAQ,CAAC,QACrD,IAAc,CAAC,GAAG,IAAI,IAAI,EAAM,KAAK,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;AAEjE,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eACZ,kBAAC,GAAD,EAAA,UAAe,EAAc,GAAG,4BAA4B,QAAQ,EAAgB,CAAA;KACjF,CAAA,EACL,kBAAC,KAAD;KAAG,WAAU;eACV,EACC,GACA,kCACA,uDACD;KACC,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,GAAD;KAAQ,MAAK;KAAK,eAAe,EAAS,qBAAqB;eAA/D,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAChC,EAAc,GAAG,sCAAsC,WAAW,CAC5D;OACL;;GAEN,kBAAC,GAAD,EAAA,UACG,EACC,GACA,8BACA,0NACD,EACW,CAAA;GAEd,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MAAW,WAAU;MAAQ,MAAA;MAAK,WAAU;gBAA5C,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAc,GAAG,uCAAuC,cAAc;QAC7D,CAAA,EACZ,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,CACtC;UACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;OAAK,WAAU;iBAAmC,EAAM;OAAa,CAAA,EACzD,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAc,GAAG,wCAAwC,eAAe;QAC/D,CAAA,EACZ,kBAAC,GAAD,EAAW,WAAU,oCAAqC,CAAA,CAC/C;UACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;OAAK,WAAU;iBAAmC;OAAkB,CAAA,EACxD,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAc,GAAG,2CAA2C,iBAAiB;QACpE,CAAA,EACZ,kBAAC,GAAD,EAAQ,WAAU,kCAAmC,CAAA,CAC1C;UACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;OAAK,WAAU;iBAAmC;OAAiB,CAAA,EACvD,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAc,GAAG,wCAAwC,cAAc;QAC9D,CAAA,EACZ,kBAAC,GAAD,EAAU,WAAU,+BAAgC,CAAA,CACzC;UACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;OAAK,WAAU;iBAAmC;OAAkB,CAAA,EACxD,CAAA,CACJ;;KACR;;GAEN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAA,UAAY,EAAc,GAAG,kCAAkC,YAAY,EAAa,CAAA,EACxF,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAQ,WAAU,wEAAyE,CAAA,EAC3F,kBAAC,GAAD;OACE,aAAa,EACX,GACA,yCACA,kBACD;OACD,OAAO;OACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;OAC1C,WAAU;OACV,CAAA,CACE;SACN,kBAAC,GAAD;MAAQ,OAAO;MAAY,eAAe;gBAA1C,CACE,kBAAC,GAAD;OAAe,WAAU;iBAAzB,CACE,kBAAC,GAAD,EAAQ,WAAU,gBAAiB,CAAA,EACnC,kBAAC,GAAD,EACE,aAAa,EACX,GACA,+CACA,OACD,EACD,CAAA,CACY;UAChB,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD;QAAY,OAAM;kBACf,EAAc,GAAG,uCAAuC,YAAY;QAC1D,CAAA;OACb,kBAAC,GAAD;QAAY,OAAM;kBACf,EAAc,GAAG,yCAAyC,QAAQ;QACxD,CAAA;OACb,kBAAC,GAAD;QAAY,OAAM;kBACf,EAAc,GAAG,2CAA2C,UAAU;QAC5D,CAAA;OACb,kBAAC,GAAD;QAAY,OAAM;kBACf,EAAc,GAAG,8CAA8C,aAAa;QAClE,CAAA;OACb,kBAAC,GAAD;QAAY,OAAM;kBACf,EAAc,GAAG,0CAA0C,SAAS;QAC1D,CAAA;OACb,kBAAC,GAAD;QAAY,OAAM;kBACf,EAAc,GAAG,2CAA2C,UAAU;QAC5D,CAAA;OACC,EAAA,CAAA,CACT;QACL;OACF;OACK,CAAA,EACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA;IACE,kBAAC,GAAD,EAAA,UAAY,EAAc,GAAG,iCAAiC,OAAO,EAAa,CAAA;IAClF,kBAAC,GAAD,EAAA,UAAY,EAAc,GAAG,kCAAkC,QAAQ,EAAa,CAAA;IACpF,kBAAC,GAAD,EAAA,UAAY,EAAc,GAAG,iCAAiC,OAAO,EAAa,CAAA;IAClF,kBAAC,GAAD,EAAA,UACG,EAAc,GAAG,uCAAuC,aAAa,EAC5D,CAAA;IACZ,kBAAC,GAAD,EAAA,UACG,EAAc,GAAG,mCAAmC,SAAS,EACpD,CAAA;IACZ,kBAAC,GAAD,EAAA,UACG,EAAc,GAAG,sCAAsC,aAAa,EAC3D,CAAA;IACZ,kBAAC,GAAD;KAAW,WAAU;eAClB,EAAc,GAAG,mCAAmC,SAAS;KACpD,CAAA;IACH,EAAA,CAAA,EACC,CAAA,EACd,kBAAC,GAAD,EAAA,UACG,EAAS,KAAK,MACb,kBAAC,GAAD,EAAA,UAAA;IACE,kBAAC,GAAD;KAAW,WAAU;eAArB;MACG,EAAK;MAAU;MAAE,EAAK;MACb;;IACZ,kBAAC,GAAD,EAAA,UAAY,EAAK,OAAkB,CAAA;IACnC,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;KAAO,SAAS,EAAW,EAAK,SAAS;eAAc,EAAK;KAAa,CAAA,EAC/D,CAAA;IACZ,kBAAC,GAAD,EAAA,UAAY,EAAK,YAAuB,CAAA;IACxC,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;KAAO,SAAS,EAAa,EAAK,WAAW;eAAc,EAAK;KAAe,CAAA,EACrE,CAAA;IACZ,kBAAC,GAAD,EAAA,UAAY,IAAI,KAAK,EAAK,UAAU,CAAC,oBAAoB,EAAa,CAAA;IACtE,kBAAC,GAAD;KAAW,WAAU;eAAc,EAAK;KAA2B,CAAA;IAC1D,EAAA,EAdI,EAAK,GAcT,CACX,EACQ,CAAA,CACN,EAAA,CAAA,EACP,EAAS,WAAW,KACnB,kBAAC,GAAD;IACE,cAAa;IACb,OAAO,EAAc,GAAG,4BAA4B,iBAAiB;IACrE,aAAY;IACZ,QACE,kBAAC,GAAD;KAAQ,MAAK;KAAK,eAAe,EAAS,qBAAqB;eAA/D,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAChC,EAAc,GAAG,sCAAsC,WAAW,CAC5D;;IAEX,CAAA,CAEQ,EAAA,CAAA,CACT,EAAA,CAAA;GACH"}
|