@alepha/ui 0.14.2 → 0.14.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/AdminAudits-DIrCCPk3.js.map +1 -1
- package/dist/admin/AdminNotifications-cIbywWKi.js.map +1 -1
- package/dist/admin/AdminParameters-D-q3Qmhv.js.map +1 -1
- package/dist/admin/AdminSessions-vOgkrQ2U.js.map +1 -1
- package/dist/admin/AdminUserAudits-CSsN1fIC.js.map +1 -1
- package/dist/admin/AdminUserCreate-B72nu-3W.js.map +1 -1
- package/dist/admin/AdminUserDetails-CKM2IEMr.js +475 -0
- package/dist/admin/AdminUserDetails-CKM2IEMr.js.map +1 -0
- package/dist/admin/{AdminUserDetails-z1y8kJeB.js → AdminUserDetails-Zib_B6Al.js} +1 -1
- package/dist/admin/{AdminUserLayout-DyQYacQQ.js → AdminUserLayout-BNBOEiAO.js} +1 -1
- package/dist/admin/AdminUserLayout-D7En9UBq.js +334 -0
- package/dist/admin/AdminUserLayout-D7En9UBq.js.map +1 -0
- package/dist/admin/AdminUserSessions-DEaGu6n6.js.map +1 -1
- package/dist/admin/{AdminUserSettings-CR7MxX_R.js → AdminUserSettings-Di73D7g2.js} +6 -5
- package/dist/admin/AdminUserSettings-Di73D7g2.js.map +1 -0
- package/dist/admin/AdminUserSettings-yI-JECf5.js +3 -0
- package/dist/admin/AdminUsers-BnGIRvmV.js.map +1 -1
- package/dist/admin/index.d.ts +10 -10
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +18 -18
- package/dist/admin/index.js.map +1 -1
- package/dist/auth/index.js +4 -4
- package/dist/auth/index.js.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +6 -5
- package/dist/core/index.js.map +1 -1
- package/package.json +11 -11
- package/src/admin/AdminRouter.ts +23 -20
- package/src/admin/MainRouter.ts +1 -1
- package/src/admin/components/audits/AdminAudits.tsx +2 -2
- package/src/admin/components/jobs/AdminJobs.tsx +2 -2
- package/src/admin/components/notifications/AdminNotifications.tsx +2 -2
- package/src/admin/components/parameters/AdminParameters.tsx +2 -2
- package/src/admin/components/sessions/AdminSessions.tsx +2 -2
- package/src/admin/components/shared/AdminResourceHeader.tsx +281 -0
- package/src/admin/components/shared/AdminResourceTabs.tsx +94 -0
- package/src/admin/components/shared/index.ts +10 -0
- package/src/admin/components/users/AdminUserAudits.tsx +2 -2
- package/src/admin/components/users/AdminUserCreate.tsx +2 -2
- package/src/admin/components/users/AdminUserDetails.tsx +337 -85
- package/src/admin/components/users/AdminUserLayout.tsx +164 -108
- package/src/admin/components/users/AdminUserSessions.tsx +2 -2
- package/src/admin/components/users/AdminUserSettings.tsx +10 -5
- package/src/admin/components/users/AdminUsers.tsx +6 -2
- package/src/auth/AuthRouter.ts +4 -4
- package/src/core/components/form/TypeForm.tsx +3 -2
- package/src/core/components/layout/AlephaMantineProvider.tsx +5 -1
- package/src/core/components/layout/Sidebar.tsx +9 -6
- package/dist/admin/AdminUserDetails-BCt8Su-4.js +0 -222
- package/dist/admin/AdminUserDetails-BCt8Su-4.js.map +0 -1
- package/dist/admin/AdminUserLayout-Ck0GLRE5.js +0 -151
- package/dist/admin/AdminUserLayout-Ck0GLRE5.js.map +0 -1
- package/dist/admin/AdminUserSettings-CE66UTIP.js +0 -3
- package/dist/admin/AdminUserSettings-CR7MxX_R.js.map +0 -1
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import { ActionButton, ClipboardButton, Control } from "@alepha/ui";
|
|
2
|
+
import { t } from "alepha";
|
|
3
|
+
import { useRouterState } from "@alepha/react/router";
|
|
4
|
+
import { IconActivity, IconCalendar, IconCheck, IconDevices, IconKey, IconShieldCheck, IconUser, IconX } from "@tabler/icons-react";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { useClient } from "@alepha/react";
|
|
7
|
+
import { useI18n } from "@alepha/react/i18n";
|
|
8
|
+
import { Badge, Box, Card, Center, Divider, Grid, Group, Loader, Paper, SimpleGrid, Stack, Text as Text$1, ThemeIcon } from "@mantine/core";
|
|
9
|
+
import { useEffect, useState } from "react";
|
|
10
|
+
import { useForm } from "@alepha/react/form";
|
|
11
|
+
|
|
12
|
+
//#region ../../src/admin/components/users/AdminUserDetails.tsx
|
|
13
|
+
const DataRow = ({ label, value, copyValue }) => /* @__PURE__ */ jsxs(Group, {
|
|
14
|
+
justify: "space-between",
|
|
15
|
+
py: 8,
|
|
16
|
+
wrap: "nowrap",
|
|
17
|
+
style: { borderBottom: "1px solid var(--mantine-color-default-border)" },
|
|
18
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
19
|
+
size: "sm",
|
|
20
|
+
c: "dimmed",
|
|
21
|
+
style: { flexShrink: 0 },
|
|
22
|
+
children: label
|
|
23
|
+
}), /* @__PURE__ */ jsxs(Group, {
|
|
24
|
+
gap: 6,
|
|
25
|
+
wrap: "nowrap",
|
|
26
|
+
style: { minWidth: 0 },
|
|
27
|
+
children: [typeof value === "string" ? /* @__PURE__ */ jsx(Text$1, {
|
|
28
|
+
size: "sm",
|
|
29
|
+
fw: 500,
|
|
30
|
+
truncate: true,
|
|
31
|
+
style: { maxWidth: 220 },
|
|
32
|
+
children: value || "—"
|
|
33
|
+
}) : value, copyValue && /* @__PURE__ */ jsx(ClipboardButton, {
|
|
34
|
+
value: copyValue,
|
|
35
|
+
size: "xs",
|
|
36
|
+
variant: "subtle",
|
|
37
|
+
c: "dimmed"
|
|
38
|
+
})]
|
|
39
|
+
})]
|
|
40
|
+
});
|
|
41
|
+
const StatCard = ({ icon, label, value, color }) => /* @__PURE__ */ jsx(Paper, {
|
|
42
|
+
p: "md",
|
|
43
|
+
radius: "md",
|
|
44
|
+
withBorder: true,
|
|
45
|
+
children: /* @__PURE__ */ jsxs(Group, {
|
|
46
|
+
gap: "sm",
|
|
47
|
+
children: [/* @__PURE__ */ jsx(ThemeIcon, {
|
|
48
|
+
size: "lg",
|
|
49
|
+
radius: "md",
|
|
50
|
+
variant: "light",
|
|
51
|
+
color,
|
|
52
|
+
children: icon
|
|
53
|
+
}), /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text$1, {
|
|
54
|
+
size: "xl",
|
|
55
|
+
fw: 700,
|
|
56
|
+
lh: 1,
|
|
57
|
+
children: value
|
|
58
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
59
|
+
size: "xs",
|
|
60
|
+
c: "dimmed",
|
|
61
|
+
children: label
|
|
62
|
+
})] })]
|
|
63
|
+
})
|
|
64
|
+
});
|
|
65
|
+
const AdminUserDetails = (props) => {
|
|
66
|
+
const state = useRouterState();
|
|
67
|
+
const client = useClient();
|
|
68
|
+
const { l } = useI18n();
|
|
69
|
+
const userId = state.params.userId;
|
|
70
|
+
const [user, setUser] = useState(null);
|
|
71
|
+
const [loading, setLoading] = useState(true);
|
|
72
|
+
const [editing, setEditing] = useState(false);
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
const loadUser = async () => {
|
|
75
|
+
try {
|
|
76
|
+
setUser(await client.getUser({
|
|
77
|
+
params: { id: userId },
|
|
78
|
+
query: { userRealmName: props.userRealmName }
|
|
79
|
+
}));
|
|
80
|
+
} finally {
|
|
81
|
+
setLoading(false);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
loadUser();
|
|
85
|
+
}, [userId]);
|
|
86
|
+
const form = useForm({
|
|
87
|
+
schema: t.object({
|
|
88
|
+
email: t.optional(t.email()),
|
|
89
|
+
phoneNumber: t.optional(t.e164()),
|
|
90
|
+
firstName: t.optional(t.string()),
|
|
91
|
+
lastName: t.optional(t.string()),
|
|
92
|
+
roles: t.optional(t.array(t.string())),
|
|
93
|
+
enabled: t.optional(t.boolean())
|
|
94
|
+
}),
|
|
95
|
+
handler: async (data) => {
|
|
96
|
+
setUser(await client.updateUser({
|
|
97
|
+
params: { id: userId },
|
|
98
|
+
query: { userRealmName: props.userRealmName },
|
|
99
|
+
body: data
|
|
100
|
+
}));
|
|
101
|
+
setEditing(false);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
if (user) {
|
|
106
|
+
form.input.email?.set(user.email ?? "");
|
|
107
|
+
form.input.phoneNumber?.set(user.phoneNumber ?? "");
|
|
108
|
+
form.input.firstName?.set(user.firstName ?? "");
|
|
109
|
+
form.input.lastName?.set(user.lastName ?? "");
|
|
110
|
+
form.input.roles?.set(user.roles ?? []);
|
|
111
|
+
form.input.enabled?.set(user.enabled);
|
|
112
|
+
}
|
|
113
|
+
}, [user]);
|
|
114
|
+
if (loading) return /* @__PURE__ */ jsx(Center, {
|
|
115
|
+
flex: 1,
|
|
116
|
+
py: "xl",
|
|
117
|
+
children: /* @__PURE__ */ jsx(Loader, {})
|
|
118
|
+
});
|
|
119
|
+
if (!user) return /* @__PURE__ */ jsx(Center, {
|
|
120
|
+
flex: 1,
|
|
121
|
+
py: "xl",
|
|
122
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
123
|
+
align: "center",
|
|
124
|
+
gap: "xs",
|
|
125
|
+
children: [/* @__PURE__ */ jsx(IconUser, {
|
|
126
|
+
size: 48,
|
|
127
|
+
opacity: .3
|
|
128
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
129
|
+
c: "dimmed",
|
|
130
|
+
children: "User not found"
|
|
131
|
+
})]
|
|
132
|
+
})
|
|
133
|
+
});
|
|
134
|
+
const displayName = user.firstName && user.lastName ? `${user.firstName} ${user.lastName}` : user.firstName || user.lastName || null;
|
|
135
|
+
return /* @__PURE__ */ jsxs(Stack, {
|
|
136
|
+
gap: "md",
|
|
137
|
+
children: [
|
|
138
|
+
/* @__PURE__ */ jsxs(SimpleGrid, {
|
|
139
|
+
cols: {
|
|
140
|
+
base: 2,
|
|
141
|
+
sm: 4
|
|
142
|
+
},
|
|
143
|
+
children: [
|
|
144
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
145
|
+
icon: /* @__PURE__ */ jsx(IconDevices, { size: 18 }),
|
|
146
|
+
label: "Sessions",
|
|
147
|
+
value: 0,
|
|
148
|
+
color: "blue"
|
|
149
|
+
}),
|
|
150
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
151
|
+
icon: /* @__PURE__ */ jsx(IconActivity, { size: 18 }),
|
|
152
|
+
label: "API Calls",
|
|
153
|
+
value: 0,
|
|
154
|
+
color: "green"
|
|
155
|
+
}),
|
|
156
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
157
|
+
icon: /* @__PURE__ */ jsx(IconKey, { size: 18 }),
|
|
158
|
+
label: "Failed Logins",
|
|
159
|
+
value: 0,
|
|
160
|
+
color: "orange"
|
|
161
|
+
}),
|
|
162
|
+
/* @__PURE__ */ jsx(StatCard, {
|
|
163
|
+
icon: /* @__PURE__ */ jsx(IconShieldCheck, { size: 18 }),
|
|
164
|
+
label: "Roles",
|
|
165
|
+
value: user.roles.length,
|
|
166
|
+
color: "violet"
|
|
167
|
+
})
|
|
168
|
+
]
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ jsxs(Grid, { children: [/* @__PURE__ */ jsx(Grid.Col, {
|
|
171
|
+
span: {
|
|
172
|
+
base: 12,
|
|
173
|
+
md: 6
|
|
174
|
+
},
|
|
175
|
+
children: /* @__PURE__ */ jsxs(Card, {
|
|
176
|
+
padding: 0,
|
|
177
|
+
radius: "md",
|
|
178
|
+
withBorder: true,
|
|
179
|
+
h: "100%",
|
|
180
|
+
children: [/* @__PURE__ */ jsx(Group, {
|
|
181
|
+
justify: "space-between",
|
|
182
|
+
p: "md",
|
|
183
|
+
pb: 0,
|
|
184
|
+
children: /* @__PURE__ */ jsx(Text$1, {
|
|
185
|
+
fw: 600,
|
|
186
|
+
size: "sm",
|
|
187
|
+
children: "Account Details"
|
|
188
|
+
})
|
|
189
|
+
}), /* @__PURE__ */ jsxs(Box, {
|
|
190
|
+
px: "md",
|
|
191
|
+
pb: "md",
|
|
192
|
+
children: [
|
|
193
|
+
/* @__PURE__ */ jsx(DataRow, {
|
|
194
|
+
label: "User ID",
|
|
195
|
+
value: user.id,
|
|
196
|
+
copyValue: user.id
|
|
197
|
+
}),
|
|
198
|
+
/* @__PURE__ */ jsx(DataRow, {
|
|
199
|
+
label: "Username",
|
|
200
|
+
value: user.username || "—",
|
|
201
|
+
copyValue: user.username
|
|
202
|
+
}),
|
|
203
|
+
/* @__PURE__ */ jsx(DataRow, {
|
|
204
|
+
label: "Email",
|
|
205
|
+
value: /* @__PURE__ */ jsxs(Group, {
|
|
206
|
+
gap: 6,
|
|
207
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
208
|
+
size: "sm",
|
|
209
|
+
fw: 500,
|
|
210
|
+
children: user.email || "—"
|
|
211
|
+
}), user.email && /* @__PURE__ */ jsx(Badge, {
|
|
212
|
+
size: "xs",
|
|
213
|
+
variant: "light",
|
|
214
|
+
color: user.emailVerified ? "green" : "orange",
|
|
215
|
+
children: user.emailVerified ? "verified" : "unverified"
|
|
216
|
+
})]
|
|
217
|
+
}),
|
|
218
|
+
copyValue: user.email
|
|
219
|
+
}),
|
|
220
|
+
/* @__PURE__ */ jsx(DataRow, {
|
|
221
|
+
label: "Phone",
|
|
222
|
+
value: user.phoneNumber || "—",
|
|
223
|
+
copyValue: user.phoneNumber
|
|
224
|
+
}),
|
|
225
|
+
/* @__PURE__ */ jsx(DataRow, {
|
|
226
|
+
label: "Realm",
|
|
227
|
+
value: user.realm
|
|
228
|
+
}),
|
|
229
|
+
/* @__PURE__ */ jsx(DataRow, {
|
|
230
|
+
label: "Status",
|
|
231
|
+
value: /* @__PURE__ */ jsxs(Group, {
|
|
232
|
+
gap: 4,
|
|
233
|
+
children: [/* @__PURE__ */ jsx(ThemeIcon, {
|
|
234
|
+
size: 16,
|
|
235
|
+
radius: "xl",
|
|
236
|
+
color: user.enabled ? "green" : "red",
|
|
237
|
+
variant: "filled",
|
|
238
|
+
children: user.enabled ? /* @__PURE__ */ jsx(IconCheck, { size: 10 }) : /* @__PURE__ */ jsx(IconX, { size: 10 })
|
|
239
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
240
|
+
size: "sm",
|
|
241
|
+
fw: 500,
|
|
242
|
+
children: user.enabled ? "Active" : "Disabled"
|
|
243
|
+
})]
|
|
244
|
+
})
|
|
245
|
+
})
|
|
246
|
+
]
|
|
247
|
+
})]
|
|
248
|
+
})
|
|
249
|
+
}), /* @__PURE__ */ jsx(Grid.Col, {
|
|
250
|
+
span: {
|
|
251
|
+
base: 12,
|
|
252
|
+
md: 6
|
|
253
|
+
},
|
|
254
|
+
children: /* @__PURE__ */ jsxs(Card, {
|
|
255
|
+
padding: 0,
|
|
256
|
+
radius: "md",
|
|
257
|
+
withBorder: true,
|
|
258
|
+
h: "100%",
|
|
259
|
+
children: [/* @__PURE__ */ jsxs(Group, {
|
|
260
|
+
justify: "space-between",
|
|
261
|
+
p: "md",
|
|
262
|
+
pb: 0,
|
|
263
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
264
|
+
fw: 600,
|
|
265
|
+
size: "sm",
|
|
266
|
+
children: "Personal Information"
|
|
267
|
+
}), !editing && /* @__PURE__ */ jsx(ActionButton, {
|
|
268
|
+
variant: "subtle",
|
|
269
|
+
size: "xs",
|
|
270
|
+
onClick: () => setEditing(true),
|
|
271
|
+
children: "Edit"
|
|
272
|
+
})]
|
|
273
|
+
}), editing ? /* @__PURE__ */ jsx(Box, {
|
|
274
|
+
p: "md",
|
|
275
|
+
children: /* @__PURE__ */ jsx("form", {
|
|
276
|
+
...form.props,
|
|
277
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
278
|
+
gap: "sm",
|
|
279
|
+
children: [
|
|
280
|
+
/* @__PURE__ */ jsxs(SimpleGrid, {
|
|
281
|
+
cols: 2,
|
|
282
|
+
children: [/* @__PURE__ */ jsx(Control, {
|
|
283
|
+
title: "First Name",
|
|
284
|
+
input: form.input.firstName
|
|
285
|
+
}), /* @__PURE__ */ jsx(Control, {
|
|
286
|
+
title: "Last Name",
|
|
287
|
+
input: form.input.lastName
|
|
288
|
+
})]
|
|
289
|
+
}),
|
|
290
|
+
/* @__PURE__ */ jsxs(SimpleGrid, {
|
|
291
|
+
cols: 2,
|
|
292
|
+
children: [/* @__PURE__ */ jsx(Control, {
|
|
293
|
+
title: "Email",
|
|
294
|
+
input: form.input.email
|
|
295
|
+
}), /* @__PURE__ */ jsx(Control, {
|
|
296
|
+
title: "Phone",
|
|
297
|
+
input: form.input.phoneNumber
|
|
298
|
+
})]
|
|
299
|
+
}),
|
|
300
|
+
/* @__PURE__ */ jsx(Control, {
|
|
301
|
+
title: "Roles",
|
|
302
|
+
input: form.input.roles
|
|
303
|
+
}),
|
|
304
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
305
|
+
/* @__PURE__ */ jsxs(Group, {
|
|
306
|
+
justify: "flex-end",
|
|
307
|
+
gap: "xs",
|
|
308
|
+
children: [/* @__PURE__ */ jsx(ActionButton, {
|
|
309
|
+
variant: "subtle",
|
|
310
|
+
size: "xs",
|
|
311
|
+
onClick: () => setEditing(false),
|
|
312
|
+
children: "Cancel"
|
|
313
|
+
}), /* @__PURE__ */ jsx(ActionButton, {
|
|
314
|
+
size: "xs",
|
|
315
|
+
form,
|
|
316
|
+
children: "Save"
|
|
317
|
+
})]
|
|
318
|
+
})
|
|
319
|
+
]
|
|
320
|
+
})
|
|
321
|
+
})
|
|
322
|
+
}) : /* @__PURE__ */ jsxs(Box, {
|
|
323
|
+
px: "md",
|
|
324
|
+
pb: "md",
|
|
325
|
+
children: [
|
|
326
|
+
/* @__PURE__ */ jsx(DataRow, {
|
|
327
|
+
label: "First Name",
|
|
328
|
+
value: user.firstName || "—"
|
|
329
|
+
}),
|
|
330
|
+
/* @__PURE__ */ jsx(DataRow, {
|
|
331
|
+
label: "Last Name",
|
|
332
|
+
value: user.lastName || "—"
|
|
333
|
+
}),
|
|
334
|
+
/* @__PURE__ */ jsx(DataRow, {
|
|
335
|
+
label: "Display Name",
|
|
336
|
+
value: displayName || "—"
|
|
337
|
+
}),
|
|
338
|
+
/* @__PURE__ */ jsx(DataRow, {
|
|
339
|
+
label: "Roles",
|
|
340
|
+
value: user.roles.length > 0 ? /* @__PURE__ */ jsx(Group, {
|
|
341
|
+
gap: 4,
|
|
342
|
+
children: user.roles.map((role) => /* @__PURE__ */ jsx(Badge, {
|
|
343
|
+
size: "xs",
|
|
344
|
+
variant: "light",
|
|
345
|
+
children: role
|
|
346
|
+
}, role))
|
|
347
|
+
}) : /* @__PURE__ */ jsx(Text$1, {
|
|
348
|
+
size: "sm",
|
|
349
|
+
c: "dimmed",
|
|
350
|
+
children: "No roles"
|
|
351
|
+
})
|
|
352
|
+
})
|
|
353
|
+
]
|
|
354
|
+
})]
|
|
355
|
+
})
|
|
356
|
+
})] }),
|
|
357
|
+
/* @__PURE__ */ jsxs(Card, {
|
|
358
|
+
padding: 0,
|
|
359
|
+
radius: "md",
|
|
360
|
+
withBorder: true,
|
|
361
|
+
children: [/* @__PURE__ */ jsx(Group, {
|
|
362
|
+
justify: "space-between",
|
|
363
|
+
p: "md",
|
|
364
|
+
pb: 0,
|
|
365
|
+
children: /* @__PURE__ */ jsx(Text$1, {
|
|
366
|
+
fw: 600,
|
|
367
|
+
size: "sm",
|
|
368
|
+
children: "Activity Timeline"
|
|
369
|
+
})
|
|
370
|
+
}), /* @__PURE__ */ jsxs(SimpleGrid, {
|
|
371
|
+
cols: {
|
|
372
|
+
base: 2,
|
|
373
|
+
sm: 4
|
|
374
|
+
},
|
|
375
|
+
p: "md",
|
|
376
|
+
children: [
|
|
377
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
378
|
+
/* @__PURE__ */ jsxs(Group, {
|
|
379
|
+
gap: 6,
|
|
380
|
+
mb: 4,
|
|
381
|
+
children: [/* @__PURE__ */ jsx(IconCalendar, {
|
|
382
|
+
size: 14,
|
|
383
|
+
style: { opacity: .5 }
|
|
384
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
385
|
+
size: "xs",
|
|
386
|
+
c: "dimmed",
|
|
387
|
+
children: "Created"
|
|
388
|
+
})]
|
|
389
|
+
}),
|
|
390
|
+
/* @__PURE__ */ jsx(Text$1, {
|
|
391
|
+
size: "sm",
|
|
392
|
+
fw: 500,
|
|
393
|
+
children: l(user.createdAt, { date: "ll" })
|
|
394
|
+
}),
|
|
395
|
+
/* @__PURE__ */ jsx(Text$1, {
|
|
396
|
+
size: "xs",
|
|
397
|
+
c: "dimmed",
|
|
398
|
+
children: l(user.createdAt, { date: "fromNow" })
|
|
399
|
+
})
|
|
400
|
+
] }),
|
|
401
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
402
|
+
/* @__PURE__ */ jsxs(Group, {
|
|
403
|
+
gap: 6,
|
|
404
|
+
mb: 4,
|
|
405
|
+
children: [/* @__PURE__ */ jsx(IconCalendar, {
|
|
406
|
+
size: 14,
|
|
407
|
+
style: { opacity: .5 }
|
|
408
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
409
|
+
size: "xs",
|
|
410
|
+
c: "dimmed",
|
|
411
|
+
children: "Updated"
|
|
412
|
+
})]
|
|
413
|
+
}),
|
|
414
|
+
/* @__PURE__ */ jsx(Text$1, {
|
|
415
|
+
size: "sm",
|
|
416
|
+
fw: 500,
|
|
417
|
+
children: l(user.updatedAt, { date: "ll" })
|
|
418
|
+
}),
|
|
419
|
+
/* @__PURE__ */ jsx(Text$1, {
|
|
420
|
+
size: "xs",
|
|
421
|
+
c: "dimmed",
|
|
422
|
+
children: l(user.updatedAt, { date: "fromNow" })
|
|
423
|
+
})
|
|
424
|
+
] }),
|
|
425
|
+
/* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsxs(Group, {
|
|
426
|
+
gap: 6,
|
|
427
|
+
mb: 4,
|
|
428
|
+
children: [/* @__PURE__ */ jsx(IconDevices, {
|
|
429
|
+
size: 14,
|
|
430
|
+
style: { opacity: .5 }
|
|
431
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
432
|
+
size: "xs",
|
|
433
|
+
c: "dimmed",
|
|
434
|
+
children: "Last Login"
|
|
435
|
+
})]
|
|
436
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
437
|
+
size: "sm",
|
|
438
|
+
c: "dimmed",
|
|
439
|
+
children: "—"
|
|
440
|
+
})] }),
|
|
441
|
+
/* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsxs(Group, {
|
|
442
|
+
gap: 6,
|
|
443
|
+
mb: 4,
|
|
444
|
+
children: [/* @__PURE__ */ jsx(IconCheck, {
|
|
445
|
+
size: 14,
|
|
446
|
+
style: { opacity: .5 }
|
|
447
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
448
|
+
size: "xs",
|
|
449
|
+
c: "dimmed",
|
|
450
|
+
children: "Email Verified"
|
|
451
|
+
})]
|
|
452
|
+
}), user.emailVerified ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Text$1, {
|
|
453
|
+
size: "sm",
|
|
454
|
+
fw: 500,
|
|
455
|
+
children: l(user.updatedAt, { date: "ll" })
|
|
456
|
+
}), /* @__PURE__ */ jsx(Text$1, {
|
|
457
|
+
size: "xs",
|
|
458
|
+
c: "dimmed",
|
|
459
|
+
children: l(user.updatedAt, { date: "fromNow" })
|
|
460
|
+
})] }) : /* @__PURE__ */ jsx(Text$1, {
|
|
461
|
+
size: "sm",
|
|
462
|
+
c: "dimmed",
|
|
463
|
+
children: "Not verified"
|
|
464
|
+
})] })
|
|
465
|
+
]
|
|
466
|
+
})]
|
|
467
|
+
})
|
|
468
|
+
]
|
|
469
|
+
});
|
|
470
|
+
};
|
|
471
|
+
var AdminUserDetails_default = AdminUserDetails;
|
|
472
|
+
|
|
473
|
+
//#endregion
|
|
474
|
+
export { AdminUserDetails_default as t };
|
|
475
|
+
//# sourceMappingURL=AdminUserDetails-CKM2IEMr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminUserDetails-CKM2IEMr.js","names":["Text"],"sources":["../../src/admin/components/users/AdminUserDetails.tsx"],"sourcesContent":["import { useClient } from \"@alepha/react\";\nimport { useForm } from \"@alepha/react/form\";\nimport { useI18n } from \"@alepha/react/i18n\";\nimport { useRouterState } from \"@alepha/react/router\";\nimport { ActionButton, ClipboardButton, Control } from \"@alepha/ui\";\nimport {\n Badge,\n Box,\n Card,\n Center,\n Divider,\n Grid,\n Group,\n Loader,\n Paper,\n SimpleGrid,\n Stack,\n Text,\n ThemeIcon,\n} from \"@mantine/core\";\nimport {\n IconActivity,\n IconCalendar,\n IconCheck,\n IconDevices,\n IconKey,\n IconShieldCheck,\n IconUser,\n IconX,\n} from \"@tabler/icons-react\";\nimport { t } from \"alepha\";\nimport type { AdminUserController, UserEntity } from \"alepha/api/users\";\nimport { type ReactNode, useEffect, useState } from \"react\";\n\nexport interface AdminUserDetailsProps {\n userRealmName?: string;\n}\n\ninterface DataRowProps {\n label: string;\n value: ReactNode;\n copyValue?: string;\n}\n\nconst DataRow = ({ label, value, copyValue }: DataRowProps) => (\n <Group\n justify=\"space-between\"\n py={8}\n wrap=\"nowrap\"\n style={{ borderBottom: \"1px solid var(--mantine-color-default-border)\" }}\n >\n <Text size=\"sm\" c=\"dimmed\" style={{ flexShrink: 0 }}>\n {label}\n </Text>\n <Group gap={6} wrap=\"nowrap\" style={{ minWidth: 0 }}>\n {typeof value === \"string\" ? (\n <Text size=\"sm\" fw={500} truncate style={{ maxWidth: 220 }}>\n {value || \"—\"}\n </Text>\n ) : (\n value\n )}\n {copyValue && (\n <ClipboardButton\n value={copyValue}\n size=\"xs\"\n variant=\"subtle\"\n c=\"dimmed\"\n />\n )}\n </Group>\n </Group>\n);\n\ninterface StatCardProps {\n icon: ReactNode;\n label: string;\n value: string | number;\n color: string;\n}\n\nconst StatCard = ({ icon, label, value, color }: StatCardProps) => (\n <Paper p=\"md\" radius=\"md\" withBorder>\n <Group gap=\"sm\">\n <ThemeIcon size=\"lg\" radius=\"md\" variant=\"light\" color={color}>\n {icon}\n </ThemeIcon>\n <Box>\n <Text size=\"xl\" fw={700} lh={1}>\n {value}\n </Text>\n <Text size=\"xs\" c=\"dimmed\">\n {label}\n </Text>\n </Box>\n </Group>\n </Paper>\n);\n\nconst AdminUserDetails = (props: AdminUserDetailsProps) => {\n const state = useRouterState();\n const client = useClient<AdminUserController>();\n const { l } = useI18n();\n const userId = state.params.userId as string;\n\n const [user, setUser] = useState<UserEntity | null>(null);\n const [loading, setLoading] = useState(true);\n const [editing, setEditing] = useState(false);\n\n useEffect(() => {\n const loadUser = async () => {\n try {\n const data = await client.getUser({\n params: { id: userId },\n query: { userRealmName: props.userRealmName },\n });\n setUser(data);\n } finally {\n setLoading(false);\n }\n };\n\n loadUser();\n }, [userId]);\n\n const form = useForm({\n schema: t.object({\n email: t.optional(t.email()),\n phoneNumber: t.optional(t.e164()),\n firstName: t.optional(t.string()),\n lastName: t.optional(t.string()),\n roles: t.optional(t.array(t.string())),\n enabled: t.optional(t.boolean()),\n }),\n handler: async (data) => {\n const updated = await client.updateUser({\n params: { id: userId },\n query: { userRealmName: props.userRealmName },\n body: data,\n });\n setUser(updated);\n setEditing(false);\n },\n });\n\n useEffect(() => {\n if (user) {\n form.input.email?.set(user.email ?? \"\");\n form.input.phoneNumber?.set(user.phoneNumber ?? \"\");\n form.input.firstName?.set(user.firstName ?? \"\");\n form.input.lastName?.set(user.lastName ?? \"\");\n form.input.roles?.set(user.roles ?? []);\n form.input.enabled?.set(user.enabled);\n }\n }, [user]);\n\n if (loading) {\n return (\n <Center flex={1} py=\"xl\">\n <Loader />\n </Center>\n );\n }\n\n if (!user) {\n return (\n <Center flex={1} py=\"xl\">\n <Stack align=\"center\" gap=\"xs\">\n <IconUser size={48} opacity={0.3} />\n <Text c=\"dimmed\">User not found</Text>\n </Stack>\n </Center>\n );\n }\n\n const displayName =\n user.firstName && user.lastName\n ? `${user.firstName} ${user.lastName}`\n : user.firstName || user.lastName || null;\n\n return (\n <Stack gap=\"md\">\n {/* Stats Overview */}\n <SimpleGrid cols={{ base: 2, sm: 4 }}>\n <StatCard\n icon={<IconDevices size={18} />}\n label=\"Sessions\"\n value={0}\n color=\"blue\"\n />\n <StatCard\n icon={<IconActivity size={18} />}\n label=\"API Calls\"\n value={0}\n color=\"green\"\n />\n <StatCard\n icon={<IconKey size={18} />}\n label=\"Failed Logins\"\n value={0}\n color=\"orange\"\n />\n <StatCard\n icon={<IconShieldCheck size={18} />}\n label=\"Roles\"\n value={user.roles.length}\n color=\"violet\"\n />\n </SimpleGrid>\n\n <Grid>\n {/* Left Column - Account Details */}\n <Grid.Col span={{ base: 12, md: 6 }}>\n <Card padding={0} radius=\"md\" withBorder h=\"100%\">\n <Group justify=\"space-between\" p=\"md\" pb={0}>\n <Text fw={600} size=\"sm\">\n Account Details\n </Text>\n </Group>\n <Box px=\"md\" pb=\"md\">\n <DataRow label=\"User ID\" value={user.id} copyValue={user.id} />\n <DataRow\n label=\"Username\"\n value={user.username || \"—\"}\n copyValue={user.username}\n />\n <DataRow\n label=\"Email\"\n value={\n <Group gap={6}>\n <Text size=\"sm\" fw={500}>\n {user.email || \"—\"}\n </Text>\n {user.email && (\n <Badge\n size=\"xs\"\n variant=\"light\"\n color={user.emailVerified ? \"green\" : \"orange\"}\n >\n {user.emailVerified ? \"verified\" : \"unverified\"}\n </Badge>\n )}\n </Group>\n }\n copyValue={user.email}\n />\n <DataRow\n label=\"Phone\"\n value={user.phoneNumber || \"—\"}\n copyValue={user.phoneNumber}\n />\n <DataRow label=\"Realm\" value={user.realm} />\n <DataRow\n label=\"Status\"\n value={\n <Group gap={4}>\n <ThemeIcon\n size={16}\n radius=\"xl\"\n color={user.enabled ? \"green\" : \"red\"}\n variant=\"filled\"\n >\n {user.enabled ? (\n <IconCheck size={10} />\n ) : (\n <IconX size={10} />\n )}\n </ThemeIcon>\n <Text size=\"sm\" fw={500}>\n {user.enabled ? \"Active\" : \"Disabled\"}\n </Text>\n </Group>\n }\n />\n </Box>\n </Card>\n </Grid.Col>\n\n {/* Right Column - Personal Info */}\n <Grid.Col span={{ base: 12, md: 6 }}>\n <Card padding={0} radius=\"md\" withBorder h=\"100%\">\n <Group justify=\"space-between\" p=\"md\" pb={0}>\n <Text fw={600} size=\"sm\">\n Personal Information\n </Text>\n {!editing && (\n <ActionButton\n variant=\"subtle\"\n size=\"xs\"\n onClick={() => setEditing(true)}\n >\n Edit\n </ActionButton>\n )}\n </Group>\n\n {editing ? (\n <Box p=\"md\">\n <form {...form.props}>\n <Stack gap=\"sm\">\n <SimpleGrid cols={2}>\n <Control\n title=\"First Name\"\n input={form.input.firstName}\n />\n <Control title=\"Last Name\" input={form.input.lastName} />\n </SimpleGrid>\n <SimpleGrid cols={2}>\n <Control title=\"Email\" input={form.input.email} />\n <Control title=\"Phone\" input={form.input.phoneNumber} />\n </SimpleGrid>\n <Control title=\"Roles\" input={form.input.roles} />\n <Divider />\n <Group justify=\"flex-end\" gap=\"xs\">\n <ActionButton\n variant=\"subtle\"\n size=\"xs\"\n onClick={() => setEditing(false)}\n >\n Cancel\n </ActionButton>\n <ActionButton size=\"xs\" form={form}>\n Save\n </ActionButton>\n </Group>\n </Stack>\n </form>\n </Box>\n ) : (\n <Box px=\"md\" pb=\"md\">\n <DataRow label=\"First Name\" value={user.firstName || \"—\"} />\n <DataRow label=\"Last Name\" value={user.lastName || \"—\"} />\n <DataRow label=\"Display Name\" value={displayName || \"—\"} />\n <DataRow\n label=\"Roles\"\n value={\n user.roles.length > 0 ? (\n <Group gap={4}>\n {user.roles.map((role) => (\n <Badge key={role} size=\"xs\" variant=\"light\">\n {role}\n </Badge>\n ))}\n </Group>\n ) : (\n <Text size=\"sm\" c=\"dimmed\">\n No roles\n </Text>\n )\n }\n />\n </Box>\n )}\n </Card>\n </Grid.Col>\n </Grid>\n\n {/* Timeline */}\n <Card padding={0} radius=\"md\" withBorder>\n <Group justify=\"space-between\" p=\"md\" pb={0}>\n <Text fw={600} size=\"sm\">\n Activity Timeline\n </Text>\n </Group>\n <SimpleGrid cols={{ base: 2, sm: 4 }} p=\"md\">\n <Box>\n <Group gap={6} mb={4}>\n <IconCalendar size={14} style={{ opacity: 0.5 }} />\n <Text size=\"xs\" c=\"dimmed\">\n Created\n </Text>\n </Group>\n <Text size=\"sm\" fw={500}>\n {l(user.createdAt, { date: \"ll\" })}\n </Text>\n <Text size=\"xs\" c=\"dimmed\">\n {l(user.createdAt, { date: \"fromNow\" })}\n </Text>\n </Box>\n <Box>\n <Group gap={6} mb={4}>\n <IconCalendar size={14} style={{ opacity: 0.5 }} />\n <Text size=\"xs\" c=\"dimmed\">\n Updated\n </Text>\n </Group>\n <Text size=\"sm\" fw={500}>\n {l(user.updatedAt, { date: \"ll\" })}\n </Text>\n <Text size=\"xs\" c=\"dimmed\">\n {l(user.updatedAt, { date: \"fromNow\" })}\n </Text>\n </Box>\n <Box>\n <Group gap={6} mb={4}>\n <IconDevices size={14} style={{ opacity: 0.5 }} />\n <Text size=\"xs\" c=\"dimmed\">\n Last Login\n </Text>\n </Group>\n <Text size=\"sm\" c=\"dimmed\">\n —\n </Text>\n </Box>\n <Box>\n <Group gap={6} mb={4}>\n <IconCheck size={14} style={{ opacity: 0.5 }} />\n <Text size=\"xs\" c=\"dimmed\">\n Email Verified\n </Text>\n </Group>\n {user.emailVerified ? (\n <>\n <Text size=\"sm\" fw={500}>\n {l(user.updatedAt, { date: \"ll\" })}\n </Text>\n <Text size=\"xs\" c=\"dimmed\">\n {l(user.updatedAt, { date: \"fromNow\" })}\n </Text>\n </>\n ) : (\n <Text size=\"sm\" c=\"dimmed\">\n Not verified\n </Text>\n )}\n </Box>\n </SimpleGrid>\n </Card>\n </Stack>\n );\n};\n\nexport default AdminUserDetails;\n"],"mappings":";;;;;;;;;;;;AA4CA,MAAM,WAAW,EAAE,OAAO,OAAO,gBAC/B,qBAAC;CACC,SAAQ;CACR,IAAI;CACJ,MAAK;CACL,OAAO,EAAE,cAAc,iDAAiD;YAExE,oBAACA;EAAK,MAAK;EAAK,GAAE;EAAS,OAAO,EAAE,YAAY,GAAG;YAChD;GACI,EACP,qBAAC;EAAM,KAAK;EAAG,MAAK;EAAS,OAAO,EAAE,UAAU,GAAG;aAChD,OAAO,UAAU,WAChB,oBAACA;GAAK,MAAK;GAAK,IAAI;GAAK;GAAS,OAAO,EAAE,UAAU,KAAK;aACvD,SAAS;IACL,GAEP,OAED,aACC,oBAAC;GACC,OAAO;GACP,MAAK;GACL,SAAQ;GACR,GAAE;IACF;GAEE;EACF;AAUV,MAAM,YAAY,EAAE,MAAM,OAAO,OAAO,YACtC,oBAAC;CAAM,GAAE;CAAK,QAAO;CAAK;WACxB,qBAAC;EAAM,KAAI;aACT,oBAAC;GAAU,MAAK;GAAK,QAAO;GAAK,SAAQ;GAAe;aACrD;IACS,EACZ,qBAAC,kBACC,oBAACA;GAAK,MAAK;GAAK,IAAI;GAAK,IAAI;aAC1B;IACI,EACP,oBAACA;GAAK,MAAK;GAAK,GAAE;aACf;IACI,IACH;GACA;EACF;AAGV,MAAM,oBAAoB,UAAiC;CACzD,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,SAAS,WAAgC;CAC/C,MAAM,EAAE,MAAM,SAAS;CACvB,MAAM,SAAS,MAAM,OAAO;CAE5B,MAAM,CAAC,MAAM,WAAW,SAA4B,KAAK;CACzD,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAC5C,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;AAE7C,iBAAgB;EACd,MAAM,WAAW,YAAY;AAC3B,OAAI;AAKF,YAJa,MAAM,OAAO,QAAQ;KAChC,QAAQ,EAAE,IAAI,QAAQ;KACtB,OAAO,EAAE,eAAe,MAAM,eAAe;KAC9C,CAAC,CACW;aACL;AACR,eAAW,MAAM;;;AAIrB,YAAU;IACT,CAAC,OAAO,CAAC;CAEZ,MAAM,OAAO,QAAQ;EACnB,QAAQ,EAAE,OAAO;GACf,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC;GAC5B,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC;GACjC,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC;GACjC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC;GAChC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;GACtC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;GACjC,CAAC;EACF,SAAS,OAAO,SAAS;AAMvB,WALgB,MAAM,OAAO,WAAW;IACtC,QAAQ,EAAE,IAAI,QAAQ;IACtB,OAAO,EAAE,eAAe,MAAM,eAAe;IAC7C,MAAM;IACP,CAAC,CACc;AAChB,cAAW,MAAM;;EAEpB,CAAC;AAEF,iBAAgB;AACd,MAAI,MAAM;AACR,QAAK,MAAM,OAAO,IAAI,KAAK,SAAS,GAAG;AACvC,QAAK,MAAM,aAAa,IAAI,KAAK,eAAe,GAAG;AACnD,QAAK,MAAM,WAAW,IAAI,KAAK,aAAa,GAAG;AAC/C,QAAK,MAAM,UAAU,IAAI,KAAK,YAAY,GAAG;AAC7C,QAAK,MAAM,OAAO,IAAI,KAAK,SAAS,EAAE,CAAC;AACvC,QAAK,MAAM,SAAS,IAAI,KAAK,QAAQ;;IAEtC,CAAC,KAAK,CAAC;AAEV,KAAI,QACF,QACE,oBAAC;EAAO,MAAM;EAAG,IAAG;YAClB,oBAAC,WAAS;GACH;AAIb,KAAI,CAAC,KACH,QACE,oBAAC;EAAO,MAAM;EAAG,IAAG;YAClB,qBAAC;GAAM,OAAM;GAAS,KAAI;cACxB,oBAAC;IAAS,MAAM;IAAI,SAAS;KAAO,EACpC,oBAACA;IAAK,GAAE;cAAS;KAAqB;IAChC;GACD;CAIb,MAAM,cACJ,KAAK,aAAa,KAAK,WACnB,GAAG,KAAK,UAAU,GAAG,KAAK,aAC1B,KAAK,aAAa,KAAK,YAAY;AAEzC,QACE,qBAAC;EAAM,KAAI;;GAET,qBAAC;IAAW,MAAM;KAAE,MAAM;KAAG,IAAI;KAAG;;KAClC,oBAAC;MACC,MAAM,oBAAC,eAAY,MAAM,KAAM;MAC/B,OAAM;MACN,OAAO;MACP,OAAM;OACN;KACF,oBAAC;MACC,MAAM,oBAAC,gBAAa,MAAM,KAAM;MAChC,OAAM;MACN,OAAO;MACP,OAAM;OACN;KACF,oBAAC;MACC,MAAM,oBAAC,WAAQ,MAAM,KAAM;MAC3B,OAAM;MACN,OAAO;MACP,OAAM;OACN;KACF,oBAAC;MACC,MAAM,oBAAC,mBAAgB,MAAM,KAAM;MACnC,OAAM;MACN,OAAO,KAAK,MAAM;MAClB,OAAM;OACN;;KACS;GAEb,qBAAC,mBAEC,oBAAC,KAAK;IAAI,MAAM;KAAE,MAAM;KAAI,IAAI;KAAG;cACjC,qBAAC;KAAK,SAAS;KAAG,QAAO;KAAK;KAAW,GAAE;gBACzC,oBAAC;MAAM,SAAQ;MAAgB,GAAE;MAAK,IAAI;gBACxC,oBAACA;OAAK,IAAI;OAAK,MAAK;iBAAK;QAElB;OACD,EACR,qBAAC;MAAI,IAAG;MAAK,IAAG;;OACd,oBAAC;QAAQ,OAAM;QAAU,OAAO,KAAK;QAAI,WAAW,KAAK;SAAM;OAC/D,oBAAC;QACC,OAAM;QACN,OAAO,KAAK,YAAY;QACxB,WAAW,KAAK;SAChB;OACF,oBAAC;QACC,OAAM;QACN,OACE,qBAAC;SAAM,KAAK;oBACV,oBAACA;UAAK,MAAK;UAAK,IAAI;oBACjB,KAAK,SAAS;WACV,EACN,KAAK,SACJ,oBAAC;UACC,MAAK;UACL,SAAQ;UACR,OAAO,KAAK,gBAAgB,UAAU;oBAErC,KAAK,gBAAgB,aAAa;WAC7B;UAEJ;QAEV,WAAW,KAAK;SAChB;OACF,oBAAC;QACC,OAAM;QACN,OAAO,KAAK,eAAe;QAC3B,WAAW,KAAK;SAChB;OACF,oBAAC;QAAQ,OAAM;QAAQ,OAAO,KAAK;SAAS;OAC5C,oBAAC;QACC,OAAM;QACN,OACE,qBAAC;SAAM,KAAK;oBACV,oBAAC;UACC,MAAM;UACN,QAAO;UACP,OAAO,KAAK,UAAU,UAAU;UAChC,SAAQ;oBAEP,KAAK,UACJ,oBAAC,aAAU,MAAM,KAAM,GAEvB,oBAAC,SAAM,MAAM,KAAM;WAEX,EACZ,oBAACA;UAAK,MAAK;UAAK,IAAI;oBACjB,KAAK,UAAU,WAAW;WACtB;UACD;SAEV;;OACE;MACD;KACE,EAGX,oBAAC,KAAK;IAAI,MAAM;KAAE,MAAM;KAAI,IAAI;KAAG;cACjC,qBAAC;KAAK,SAAS;KAAG,QAAO;KAAK;KAAW,GAAE;gBACzC,qBAAC;MAAM,SAAQ;MAAgB,GAAE;MAAK,IAAI;iBACxC,oBAACA;OAAK,IAAI;OAAK,MAAK;iBAAK;QAElB,EACN,CAAC,WACA,oBAAC;OACC,SAAQ;OACR,MAAK;OACL,eAAe,WAAW,KAAK;iBAChC;QAEc;OAEX,EAEP,UACC,oBAAC;MAAI,GAAE;gBACL,oBAAC;OAAK,GAAI,KAAK;iBACb,qBAAC;QAAM,KAAI;;SACT,qBAAC;UAAW,MAAM;qBAChB,oBAAC;WACC,OAAM;WACN,OAAO,KAAK,MAAM;YAClB,EACF,oBAAC;WAAQ,OAAM;WAAY,OAAO,KAAK,MAAM;YAAY;WAC9C;SACb,qBAAC;UAAW,MAAM;qBAChB,oBAAC;WAAQ,OAAM;WAAQ,OAAO,KAAK,MAAM;YAAS,EAClD,oBAAC;WAAQ,OAAM;WAAQ,OAAO,KAAK,MAAM;YAAe;WAC7C;SACb,oBAAC;UAAQ,OAAM;UAAQ,OAAO,KAAK,MAAM;WAAS;SAClD,oBAAC,YAAU;SACX,qBAAC;UAAM,SAAQ;UAAW,KAAI;qBAC5B,oBAAC;WACC,SAAQ;WACR,MAAK;WACL,eAAe,WAAW,MAAM;qBACjC;YAEc,EACf,oBAAC;WAAa,MAAK;WAAW;qBAAM;YAErB;WACT;;SACF;QACH;OACH,GAEN,qBAAC;MAAI,IAAG;MAAK,IAAG;;OACd,oBAAC;QAAQ,OAAM;QAAa,OAAO,KAAK,aAAa;SAAO;OAC5D,oBAAC;QAAQ,OAAM;QAAY,OAAO,KAAK,YAAY;SAAO;OAC1D,oBAAC;QAAQ,OAAM;QAAe,OAAO,eAAe;SAAO;OAC3D,oBAAC;QACC,OAAM;QACN,OACE,KAAK,MAAM,SAAS,IAClB,oBAAC;SAAM,KAAK;mBACT,KAAK,MAAM,KAAK,SACf,oBAAC;UAAiB,MAAK;UAAK,SAAQ;oBACjC;YADS,KAEJ,CACR;UACI,GAER,oBAACA;SAAK,MAAK;SAAK,GAAE;mBAAS;UAEpB;SAGX;;OACE;MAEH;KACE,IACN;GAGP,qBAAC;IAAK,SAAS;IAAG,QAAO;IAAK;eAC5B,oBAAC;KAAM,SAAQ;KAAgB,GAAE;KAAK,IAAI;eACxC,oBAACA;MAAK,IAAI;MAAK,MAAK;gBAAK;OAElB;MACD,EACR,qBAAC;KAAW,MAAM;MAAE,MAAM;MAAG,IAAI;MAAG;KAAE,GAAE;;MACtC,qBAAC;OACC,qBAAC;QAAM,KAAK;QAAG,IAAI;mBACjB,oBAAC;SAAa,MAAM;SAAI,OAAO,EAAE,SAAS,IAAK;UAAI,EACnD,oBAACA;SAAK,MAAK;SAAK,GAAE;mBAAS;UAEpB;SACD;OACR,oBAACA;QAAK,MAAK;QAAK,IAAI;kBACjB,EAAE,KAAK,WAAW,EAAE,MAAM,MAAM,CAAC;SAC7B;OACP,oBAACA;QAAK,MAAK;QAAK,GAAE;kBACf,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;SAClC;UACH;MACN,qBAAC;OACC,qBAAC;QAAM,KAAK;QAAG,IAAI;mBACjB,oBAAC;SAAa,MAAM;SAAI,OAAO,EAAE,SAAS,IAAK;UAAI,EACnD,oBAACA;SAAK,MAAK;SAAK,GAAE;mBAAS;UAEpB;SACD;OACR,oBAACA;QAAK,MAAK;QAAK,IAAI;kBACjB,EAAE,KAAK,WAAW,EAAE,MAAM,MAAM,CAAC;SAC7B;OACP,oBAACA;QAAK,MAAK;QAAK,GAAE;kBACf,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;SAClC;UACH;MACN,qBAAC,kBACC,qBAAC;OAAM,KAAK;OAAG,IAAI;kBACjB,oBAAC;QAAY,MAAM;QAAI,OAAO,EAAE,SAAS,IAAK;SAAI,EAClD,oBAACA;QAAK,MAAK;QAAK,GAAE;kBAAS;SAEpB;QACD,EACR,oBAACA;OAAK,MAAK;OAAK,GAAE;iBAAS;QAEpB,IACH;MACN,qBAAC,kBACC,qBAAC;OAAM,KAAK;OAAG,IAAI;kBACjB,oBAAC;QAAU,MAAM;QAAI,OAAO,EAAE,SAAS,IAAK;SAAI,EAChD,oBAACA;QAAK,MAAK;QAAK,GAAE;kBAAS;SAEpB;QACD,EACP,KAAK,gBACJ,4CACE,oBAACA;OAAK,MAAK;OAAK,IAAI;iBACjB,EAAE,KAAK,WAAW,EAAE,MAAM,MAAM,CAAC;QAC7B,EACP,oBAACA;OAAK,MAAK;OAAK,GAAE;iBACf,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;QAClC,IACN,GAEH,oBAACA;OAAK,MAAK;OAAK,GAAE;iBAAS;QAEpB,IAEL;;MACK;KACR;;GACD;;AAIZ,+BAAe"}
|