@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.
Files changed (54) hide show
  1. package/dist/admin/AdminAudits-DIrCCPk3.js.map +1 -1
  2. package/dist/admin/AdminNotifications-cIbywWKi.js.map +1 -1
  3. package/dist/admin/AdminParameters-D-q3Qmhv.js.map +1 -1
  4. package/dist/admin/AdminSessions-vOgkrQ2U.js.map +1 -1
  5. package/dist/admin/AdminUserAudits-CSsN1fIC.js.map +1 -1
  6. package/dist/admin/AdminUserCreate-B72nu-3W.js.map +1 -1
  7. package/dist/admin/AdminUserDetails-CKM2IEMr.js +475 -0
  8. package/dist/admin/AdminUserDetails-CKM2IEMr.js.map +1 -0
  9. package/dist/admin/{AdminUserDetails-z1y8kJeB.js → AdminUserDetails-Zib_B6Al.js} +1 -1
  10. package/dist/admin/{AdminUserLayout-DyQYacQQ.js → AdminUserLayout-BNBOEiAO.js} +1 -1
  11. package/dist/admin/AdminUserLayout-D7En9UBq.js +334 -0
  12. package/dist/admin/AdminUserLayout-D7En9UBq.js.map +1 -0
  13. package/dist/admin/AdminUserSessions-DEaGu6n6.js.map +1 -1
  14. package/dist/admin/{AdminUserSettings-CR7MxX_R.js → AdminUserSettings-Di73D7g2.js} +6 -5
  15. package/dist/admin/AdminUserSettings-Di73D7g2.js.map +1 -0
  16. package/dist/admin/AdminUserSettings-yI-JECf5.js +3 -0
  17. package/dist/admin/AdminUsers-BnGIRvmV.js.map +1 -1
  18. package/dist/admin/index.d.ts +10 -10
  19. package/dist/admin/index.d.ts.map +1 -1
  20. package/dist/admin/index.js +18 -18
  21. package/dist/admin/index.js.map +1 -1
  22. package/dist/auth/index.js +4 -4
  23. package/dist/auth/index.js.map +1 -1
  24. package/dist/core/index.d.ts.map +1 -1
  25. package/dist/core/index.js +6 -5
  26. package/dist/core/index.js.map +1 -1
  27. package/package.json +11 -11
  28. package/src/admin/AdminRouter.ts +23 -20
  29. package/src/admin/MainRouter.ts +1 -1
  30. package/src/admin/components/audits/AdminAudits.tsx +2 -2
  31. package/src/admin/components/jobs/AdminJobs.tsx +2 -2
  32. package/src/admin/components/notifications/AdminNotifications.tsx +2 -2
  33. package/src/admin/components/parameters/AdminParameters.tsx +2 -2
  34. package/src/admin/components/sessions/AdminSessions.tsx +2 -2
  35. package/src/admin/components/shared/AdminResourceHeader.tsx +281 -0
  36. package/src/admin/components/shared/AdminResourceTabs.tsx +94 -0
  37. package/src/admin/components/shared/index.ts +10 -0
  38. package/src/admin/components/users/AdminUserAudits.tsx +2 -2
  39. package/src/admin/components/users/AdminUserCreate.tsx +2 -2
  40. package/src/admin/components/users/AdminUserDetails.tsx +337 -85
  41. package/src/admin/components/users/AdminUserLayout.tsx +164 -108
  42. package/src/admin/components/users/AdminUserSessions.tsx +2 -2
  43. package/src/admin/components/users/AdminUserSettings.tsx +10 -5
  44. package/src/admin/components/users/AdminUsers.tsx +6 -2
  45. package/src/auth/AuthRouter.ts +4 -4
  46. package/src/core/components/form/TypeForm.tsx +3 -2
  47. package/src/core/components/layout/AlephaMantineProvider.tsx +5 -1
  48. package/src/core/components/layout/Sidebar.tsx +9 -6
  49. package/dist/admin/AdminUserDetails-BCt8Su-4.js +0 -222
  50. package/dist/admin/AdminUserDetails-BCt8Su-4.js.map +0 -1
  51. package/dist/admin/AdminUserLayout-Ck0GLRE5.js +0 -151
  52. package/dist/admin/AdminUserLayout-Ck0GLRE5.js.map +0 -1
  53. package/dist/admin/AdminUserSettings-CE66UTIP.js +0 -3
  54. package/dist/admin/AdminUserSettings-CR7MxX_R.js.map +0 -1
@@ -1,222 +0,0 @@
1
- import { ActionButton, Control, Flex, Text } from "@alepha/ui";
2
- import { t } from "alepha";
3
- import { useRouterState } from "@alepha/react/router";
4
- import { IconCheck, IconX } from "@tabler/icons-react";
5
- import { jsx, jsxs } from "react/jsx-runtime";
6
- import { useClient } from "@alepha/react";
7
- import { useI18n } from "@alepha/react/i18n";
8
- import { Card, Group, Loader, Stack } 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 AdminUserDetails = (props) => {
14
- const state = useRouterState();
15
- const client = useClient();
16
- const { l } = useI18n();
17
- const userId = state.params.userId;
18
- const [user, setUser] = useState(null);
19
- const [loading, setLoading] = useState(true);
20
- useEffect(() => {
21
- const loadUser = async () => {
22
- try {
23
- setUser(await client.getUser({
24
- params: { id: userId },
25
- query: { userRealmName: props.userRealmName }
26
- }));
27
- } finally {
28
- setLoading(false);
29
- }
30
- };
31
- loadUser();
32
- }, [userId]);
33
- const form = useForm({
34
- schema: t.object({
35
- email: t.optional(t.email()),
36
- phoneNumber: t.optional(t.e164()),
37
- firstName: t.optional(t.string()),
38
- lastName: t.optional(t.string()),
39
- roles: t.optional(t.array(t.string())),
40
- enabled: t.optional(t.boolean())
41
- }),
42
- handler: async (data) => {
43
- setUser(await client.updateUser({
44
- params: { id: userId },
45
- query: { userRealmName: props.userRealmName },
46
- body: data
47
- }));
48
- }
49
- });
50
- useEffect(() => {
51
- if (user) {
52
- form.input.email?.set(user.email ?? "");
53
- form.input.phoneNumber?.set(user.phoneNumber ?? "");
54
- form.input.firstName?.set(user.firstName ?? "");
55
- form.input.lastName?.set(user.lastName ?? "");
56
- form.input.roles?.set(user.roles ?? []);
57
- form.input.enabled?.set(user.enabled);
58
- }
59
- }, [user]);
60
- if (loading) return /* @__PURE__ */ jsx(Flex, {
61
- flex: 1,
62
- justify: "center",
63
- align: "center",
64
- children: /* @__PURE__ */ jsx(Loader, {})
65
- });
66
- if (!user) return /* @__PURE__ */ jsx(Flex, {
67
- flex: 1,
68
- justify: "center",
69
- align: "center",
70
- children: /* @__PURE__ */ jsx(Text, {
71
- c: "dimmed",
72
- children: "User not found"
73
- })
74
- });
75
- return /* @__PURE__ */ jsxs(Flex, {
76
- flex: 1,
77
- direction: "column",
78
- gap: "md",
79
- children: [/* @__PURE__ */ jsx(Card, {
80
- withBorder: true,
81
- p: "lg",
82
- children: /* @__PURE__ */ jsxs(Stack, {
83
- gap: "md",
84
- children: [/* @__PURE__ */ jsx(Text, {
85
- size: "lg",
86
- fw: 500,
87
- children: "User Details"
88
- }), /* @__PURE__ */ jsxs(Group, {
89
- gap: "xl",
90
- children: [
91
- /* @__PURE__ */ jsxs(Stack, {
92
- gap: 4,
93
- children: [/* @__PURE__ */ jsx(Text, {
94
- size: "xs",
95
- c: "dimmed",
96
- children: "User ID"
97
- }), /* @__PURE__ */ jsx(Text, {
98
- size: "sm",
99
- ff: "monospace",
100
- children: user.id
101
- })]
102
- }),
103
- /* @__PURE__ */ jsxs(Stack, {
104
- gap: 4,
105
- children: [/* @__PURE__ */ jsx(Text, {
106
- size: "xs",
107
- c: "dimmed",
108
- children: "Username"
109
- }), /* @__PURE__ */ jsx(Text, {
110
- size: "sm",
111
- children: user.username || "-"
112
- })]
113
- }),
114
- /* @__PURE__ */ jsxs(Stack, {
115
- gap: 4,
116
- children: [/* @__PURE__ */ jsx(Text, {
117
- size: "xs",
118
- c: "dimmed",
119
- children: "Email Verified"
120
- }), user.emailVerified ? /* @__PURE__ */ jsxs(Group, {
121
- gap: 4,
122
- children: [/* @__PURE__ */ jsx(IconCheck, {
123
- size: 14,
124
- color: "var(--mantine-color-green-6)"
125
- }), /* @__PURE__ */ jsx(Text, {
126
- size: "sm",
127
- c: "green",
128
- children: "Verified"
129
- })]
130
- }) : /* @__PURE__ */ jsxs(Group, {
131
- gap: 4,
132
- children: [/* @__PURE__ */ jsx(IconX, {
133
- size: 14,
134
- color: "var(--mantine-color-red-6)"
135
- }), /* @__PURE__ */ jsx(Text, {
136
- size: "sm",
137
- c: "red",
138
- children: "Not Verified"
139
- })]
140
- })]
141
- }),
142
- /* @__PURE__ */ jsxs(Stack, {
143
- gap: 4,
144
- children: [/* @__PURE__ */ jsx(Text, {
145
- size: "xs",
146
- c: "dimmed",
147
- children: "Created"
148
- }), /* @__PURE__ */ jsx(Text, {
149
- size: "sm",
150
- children: l(user.createdAt, { date: "medium" })
151
- })]
152
- }),
153
- /* @__PURE__ */ jsxs(Stack, {
154
- gap: 4,
155
- children: [/* @__PURE__ */ jsx(Text, {
156
- size: "xs",
157
- c: "dimmed",
158
- children: "Updated"
159
- }), /* @__PURE__ */ jsx(Text, {
160
- size: "sm",
161
- children: l(user.updatedAt, { date: "medium" })
162
- })]
163
- })
164
- ]
165
- })]
166
- })
167
- }), /* @__PURE__ */ jsx(Card, {
168
- withBorder: true,
169
- p: "lg",
170
- children: /* @__PURE__ */ jsx("form", {
171
- ...form.props,
172
- children: /* @__PURE__ */ jsxs(Stack, {
173
- gap: "md",
174
- children: [
175
- /* @__PURE__ */ jsx(Text, {
176
- size: "lg",
177
- fw: 500,
178
- children: "Edit User"
179
- }),
180
- /* @__PURE__ */ jsxs(Group, {
181
- grow: true,
182
- children: [/* @__PURE__ */ jsx(Control, {
183
- title: "Email",
184
- input: form.input.email
185
- }), /* @__PURE__ */ jsx(Control, {
186
- title: "Phone Number",
187
- input: form.input.phoneNumber
188
- })]
189
- }),
190
- /* @__PURE__ */ jsxs(Group, {
191
- grow: true,
192
- children: [/* @__PURE__ */ jsx(Control, {
193
- title: "First Name",
194
- input: form.input.firstName
195
- }), /* @__PURE__ */ jsx(Control, {
196
- title: "Last Name",
197
- input: form.input.lastName
198
- })]
199
- }),
200
- /* @__PURE__ */ jsx(Control, {
201
- title: "Roles",
202
- input: form.input.roles
203
- }),
204
- /* @__PURE__ */ jsx(Control, {
205
- title: "Enabled",
206
- input: form.input.enabled
207
- }),
208
- /* @__PURE__ */ jsx(Group, { children: /* @__PURE__ */ jsx(ActionButton, {
209
- form,
210
- children: "Save Changes"
211
- }) })
212
- ]
213
- })
214
- })
215
- })]
216
- });
217
- };
218
- var AdminUserDetails_default = AdminUserDetails;
219
-
220
- //#endregion
221
- export { AdminUserDetails_default as t };
222
- //# sourceMappingURL=AdminUserDetails-BCt8Su-4.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AdminUserDetails-BCt8Su-4.js","names":[],"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, Control, Flex, Text } from \"@alepha/ui\";\nimport { Card, Group, Loader, Stack } from \"@mantine/core\";\nimport { IconCheck, IconX } from \"@tabler/icons-react\";\nimport { t } from \"alepha\";\nimport type { UserController, UserEntity } from \"alepha/api/users\";\nimport { useEffect, useState } from \"react\";\n\nexport interface AdminUserDetailsProps {\n userRealmName?: string;\n}\n\nconst AdminUserDetails = (props: AdminUserDetailsProps) => {\n const state = useRouterState();\n const client = useClient<UserController>();\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\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 },\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 <Flex flex={1} justify=\"center\" align=\"center\">\n <Loader />\n </Flex>\n );\n }\n\n if (!user) {\n return (\n <Flex flex={1} justify=\"center\" align=\"center\">\n <Text c=\"dimmed\">User not found</Text>\n </Flex>\n );\n }\n\n return (\n <Flex flex={1} direction=\"column\" gap=\"md\">\n <Card withBorder p=\"lg\">\n <Stack gap=\"md\">\n <Text size=\"lg\" fw={500}>\n User Details\n </Text>\n\n <Group gap=\"xl\">\n <Stack gap={4}>\n <Text size=\"xs\" c=\"dimmed\">\n User ID\n </Text>\n <Text size=\"sm\" ff=\"monospace\">\n {user.id}\n </Text>\n </Stack>\n\n <Stack gap={4}>\n <Text size=\"xs\" c=\"dimmed\">\n Username\n </Text>\n <Text size=\"sm\">{user.username || \"-\"}</Text>\n </Stack>\n\n <Stack gap={4}>\n <Text size=\"xs\" c=\"dimmed\">\n Email Verified\n </Text>\n {user.emailVerified ? (\n <Group gap={4}>\n <IconCheck size={14} color=\"var(--mantine-color-green-6)\" />\n <Text size=\"sm\" c=\"green\">\n Verified\n </Text>\n </Group>\n ) : (\n <Group gap={4}>\n <IconX size={14} color=\"var(--mantine-color-red-6)\" />\n <Text size=\"sm\" c=\"red\">\n Not Verified\n </Text>\n </Group>\n )}\n </Stack>\n\n <Stack gap={4}>\n <Text size=\"xs\" c=\"dimmed\">\n Created\n </Text>\n <Text size=\"sm\">{l(user.createdAt, { date: \"medium\" })}</Text>\n </Stack>\n\n <Stack gap={4}>\n <Text size=\"xs\" c=\"dimmed\">\n Updated\n </Text>\n <Text size=\"sm\">{l(user.updatedAt, { date: \"medium\" })}</Text>\n </Stack>\n </Group>\n </Stack>\n </Card>\n\n <Card withBorder p=\"lg\">\n <form {...form.props}>\n <Stack gap=\"md\">\n <Text size=\"lg\" fw={500}>\n Edit User\n </Text>\n\n <Group grow>\n <Control title=\"Email\" input={form.input.email} />\n <Control title=\"Phone Number\" input={form.input.phoneNumber} />\n </Group>\n\n <Group grow>\n <Control title=\"First Name\" input={form.input.firstName} />\n <Control title=\"Last Name\" input={form.input.lastName} />\n </Group>\n\n <Control title=\"Roles\" input={form.input.roles} />\n\n <Control title=\"Enabled\" input={form.input.enabled} />\n\n <Group>\n <ActionButton form={form}>Save Changes</ActionButton>\n </Group>\n </Stack>\n </form>\n </Card>\n </Flex>\n );\n};\n\nexport default AdminUserDetails;\n"],"mappings":"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"}
@@ -1,151 +0,0 @@
1
- import { ActionButton, Flex, Text } from "@alepha/ui";
2
- import { NestedView, useRouter, useRouterState } from "@alepha/react/router";
3
- import { IconDevices, IconSettings, IconUser } from "@tabler/icons-react";
4
- import { jsx, jsxs } from "react/jsx-runtime";
5
- import { useClient } from "@alepha/react";
6
- import { Avatar, Badge, Card, Group, Loader, Stack, Tabs } from "@mantine/core";
7
- import { useEffect, useState } from "react";
8
-
9
- //#region ../../src/admin/components/users/AdminUserLayout.tsx
10
- const AdminUserLayout = (props) => {
11
- const router = useRouter();
12
- const state = useRouterState();
13
- const client = useClient();
14
- const userId = state.params.userId;
15
- const [user, setUser] = useState(null);
16
- const [loading, setLoading] = useState(true);
17
- useEffect(() => {
18
- const loadUser = async () => {
19
- try {
20
- setUser(await client.getUser({
21
- params: { id: userId },
22
- query: { userRealmName: props.userRealmName }
23
- }));
24
- } finally {
25
- setLoading(false);
26
- }
27
- };
28
- loadUser();
29
- }, [userId]);
30
- if (loading) return /* @__PURE__ */ jsx(Flex, {
31
- flex: 1,
32
- justify: "center",
33
- align: "center",
34
- children: /* @__PURE__ */ jsx(Loader, {})
35
- });
36
- if (!user) return /* @__PURE__ */ jsx(Flex, {
37
- flex: 1,
38
- justify: "center",
39
- align: "center",
40
- children: /* @__PURE__ */ jsx(Text, {
41
- c: "dimmed",
42
- children: "User not found"
43
- })
44
- });
45
- const currentPath = state.url.pathname;
46
- const detailsPath = router.path("adminUserDetails", { params: { userId } });
47
- const sessionsPath = router.path("adminUserSessions", { params: { userId } });
48
- const settingsPath = router.path("adminUserSettings", { params: { userId } });
49
- const getActiveTab = () => {
50
- if (currentPath.endsWith("/sessions")) return "sessions";
51
- if (currentPath.endsWith("/settings")) return "settings";
52
- return "details";
53
- };
54
- const activeTab = getActiveTab();
55
- const displayName = user.firstName || user.lastName ? `${user.firstName ?? ""} ${user.lastName ?? ""}`.trim() : user.username || user.email || "User";
56
- return /* @__PURE__ */ jsxs(Flex, {
57
- flex: 1,
58
- direction: "column",
59
- gap: "md",
60
- p: "md",
61
- children: [
62
- /* @__PURE__ */ jsx(Card, {
63
- withBorder: true,
64
- p: "md",
65
- children: /* @__PURE__ */ jsxs(Group, { children: [/* @__PURE__ */ jsx(Avatar, {
66
- size: "lg",
67
- radius: "xl",
68
- color: "blue",
69
- children: displayName.charAt(0).toUpperCase()
70
- }), /* @__PURE__ */ jsxs(Stack, {
71
- gap: 4,
72
- children: [
73
- /* @__PURE__ */ jsxs(Group, {
74
- gap: "xs",
75
- children: [/* @__PURE__ */ jsx(Text, {
76
- size: "lg",
77
- fw: 500,
78
- children: displayName
79
- }), /* @__PURE__ */ jsx(Badge, {
80
- size: "sm",
81
- variant: "light",
82
- color: user.enabled ? "green" : "red",
83
- children: user.enabled ? "Active" : "Disabled"
84
- })]
85
- }),
86
- /* @__PURE__ */ jsx(Text, {
87
- size: "sm",
88
- c: "dimmed",
89
- children: user.email || user.username || user.id
90
- }),
91
- user.roles.length > 0 && /* @__PURE__ */ jsx(Group, {
92
- gap: 4,
93
- children: user.roles.map((role) => /* @__PURE__ */ jsx(Badge, {
94
- size: "xs",
95
- variant: "outline",
96
- children: role
97
- }, role))
98
- })
99
- ]
100
- })] })
101
- }),
102
- /* @__PURE__ */ jsx(Tabs, {
103
- value: activeTab,
104
- children: /* @__PURE__ */ jsxs(Tabs.List, { children: [
105
- /* @__PURE__ */ jsx(ActionButton, {
106
- href: detailsPath,
107
- leftSection: /* @__PURE__ */ jsx(IconUser, { size: 16 }),
108
- c: activeTab === "details" ? void 0 : "dimmed",
109
- fw: activeTab === "details" ? 500 : 400,
110
- style: {
111
- borderBottom: activeTab === "details" ? "2px solid var(--mantine-primary-color-filled)" : "2px solid transparent",
112
- borderRadius: 0
113
- },
114
- children: "Details"
115
- }),
116
- /* @__PURE__ */ jsx(ActionButton, {
117
- href: sessionsPath,
118
- leftSection: /* @__PURE__ */ jsx(IconDevices, { size: 16 }),
119
- c: activeTab === "sessions" ? void 0 : "dimmed",
120
- fw: activeTab === "sessions" ? 500 : 400,
121
- style: {
122
- borderBottom: activeTab === "sessions" ? "2px solid var(--mantine-primary-color-filled)" : "2px solid transparent",
123
- borderRadius: 0
124
- },
125
- children: "Sessions"
126
- }),
127
- /* @__PURE__ */ jsx(ActionButton, {
128
- href: settingsPath,
129
- leftSection: /* @__PURE__ */ jsx(IconSettings, { size: 16 }),
130
- c: activeTab === "settings" ? void 0 : "dimmed",
131
- fw: activeTab === "settings" ? 500 : 400,
132
- style: {
133
- borderBottom: activeTab === "settings" ? "2px solid var(--mantine-primary-color-filled)" : "2px solid transparent",
134
- borderRadius: 0
135
- },
136
- children: "Settings"
137
- })
138
- ] })
139
- }),
140
- /* @__PURE__ */ jsx(Flex, {
141
- flex: 1,
142
- children: /* @__PURE__ */ jsx(NestedView, {})
143
- })
144
- ]
145
- });
146
- };
147
- var AdminUserLayout_default = AdminUserLayout;
148
-
149
- //#endregion
150
- export { AdminUserLayout_default as t };
151
- //# sourceMappingURL=AdminUserLayout-Ck0GLRE5.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AdminUserLayout-Ck0GLRE5.js","names":[],"sources":["../../src/admin/components/users/AdminUserLayout.tsx"],"sourcesContent":["import { useClient } from \"@alepha/react\";\nimport { NestedView, useRouter, useRouterState } from \"@alepha/react/router\";\nimport { ActionButton, Flex, Text } from \"@alepha/ui\";\nimport { Avatar, Badge, Card, Group, Loader, Stack, Tabs } from \"@mantine/core\";\nimport { IconDevices, IconSettings, IconUser } from \"@tabler/icons-react\";\nimport type { UserController, UserEntity } from \"alepha/api/users\";\nimport { useEffect, useState } from \"react\";\nimport type { AdminRouter } from \"../../AdminRouter.ts\";\n\nexport interface AdminUserLayoutProps {\n userRealmName?: string;\n}\n\nconst AdminUserLayout = (props: AdminUserLayoutProps) => {\n const router = useRouter<AdminRouter>();\n const state = useRouterState();\n const client = useClient<UserController>();\n const userId = state.params.userId as string;\n\n const [user, setUser] = useState<UserEntity | null>(null);\n const [loading, setLoading] = useState(true);\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 if (loading) {\n return (\n <Flex flex={1} justify=\"center\" align=\"center\">\n <Loader />\n </Flex>\n );\n }\n\n if (!user) {\n return (\n <Flex flex={1} justify=\"center\" align=\"center\">\n <Text c=\"dimmed\">User not found</Text>\n </Flex>\n );\n }\n\n const currentPath = state.url.pathname;\n const detailsPath = router.path(\"adminUserDetails\", { params: { userId } });\n const sessionsPath = router.path(\"adminUserSessions\", { params: { userId } });\n const settingsPath = router.path(\"adminUserSettings\", { params: { userId } });\n\n const getActiveTab = () => {\n if (currentPath.endsWith(\"/sessions\")) return \"sessions\";\n if (currentPath.endsWith(\"/settings\")) return \"settings\";\n return \"details\";\n };\n const activeTab = getActiveTab();\n\n const displayName =\n user.firstName || user.lastName\n ? `${user.firstName ?? \"\"} ${user.lastName ?? \"\"}`.trim()\n : user.username || user.email || \"User\";\n\n return (\n <Flex flex={1} direction=\"column\" gap=\"md\" p=\"md\">\n <Card withBorder p=\"md\">\n <Group>\n <Avatar size=\"lg\" radius=\"xl\" color=\"blue\">\n {displayName.charAt(0).toUpperCase()}\n </Avatar>\n <Stack gap={4}>\n <Group gap=\"xs\">\n <Text size=\"lg\" fw={500}>\n {displayName}\n </Text>\n <Badge\n size=\"sm\"\n variant=\"light\"\n color={user.enabled ? \"green\" : \"red\"}\n >\n {user.enabled ? \"Active\" : \"Disabled\"}\n </Badge>\n </Group>\n <Text size=\"sm\" c=\"dimmed\">\n {user.email || user.username || user.id}\n </Text>\n {user.roles.length > 0 && (\n <Group gap={4}>\n {user.roles.map((role: string) => (\n <Badge key={role} size=\"xs\" variant=\"outline\">\n {role}\n </Badge>\n ))}\n </Group>\n )}\n </Stack>\n </Group>\n </Card>\n\n <Tabs value={activeTab}>\n <Tabs.List>\n <ActionButton\n href={detailsPath}\n leftSection={<IconUser size={16} />}\n c={activeTab === \"details\" ? undefined : \"dimmed\"}\n fw={activeTab === \"details\" ? 500 : 400}\n style={{\n borderBottom:\n activeTab === \"details\"\n ? \"2px solid var(--mantine-primary-color-filled)\"\n : \"2px solid transparent\",\n borderRadius: 0,\n }}\n >\n Details\n </ActionButton>\n <ActionButton\n href={sessionsPath}\n leftSection={<IconDevices size={16} />}\n c={activeTab === \"sessions\" ? undefined : \"dimmed\"}\n fw={activeTab === \"sessions\" ? 500 : 400}\n style={{\n borderBottom:\n activeTab === \"sessions\"\n ? \"2px solid var(--mantine-primary-color-filled)\"\n : \"2px solid transparent\",\n borderRadius: 0,\n }}\n >\n Sessions\n </ActionButton>\n <ActionButton\n href={settingsPath}\n leftSection={<IconSettings size={16} />}\n c={activeTab === \"settings\" ? undefined : \"dimmed\"}\n fw={activeTab === \"settings\" ? 500 : 400}\n style={{\n borderBottom:\n activeTab === \"settings\"\n ? \"2px solid var(--mantine-primary-color-filled)\"\n : \"2px solid transparent\",\n borderRadius: 0,\n }}\n >\n Settings\n </ActionButton>\n </Tabs.List>\n </Tabs>\n\n <Flex flex={1}>\n <NestedView />\n </Flex>\n </Flex>\n );\n};\n\nexport default AdminUserLayout;\n"],"mappings":";;;;;;;;;AAaA,MAAM,mBAAmB,UAAgC;CACvD,MAAM,SAAS,WAAwB;CACvC,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,SAAS,WAA2B;CAC1C,MAAM,SAAS,MAAM,OAAO;CAE5B,MAAM,CAAC,MAAM,WAAW,SAA4B,KAAK;CACzD,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;AAE5C,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;AAEZ,KAAI,QACF,QACE,oBAAC;EAAK,MAAM;EAAG,SAAQ;EAAS,OAAM;YACpC,oBAAC,WAAS;GACL;AAIX,KAAI,CAAC,KACH,QACE,oBAAC;EAAK,MAAM;EAAG,SAAQ;EAAS,OAAM;YACpC,oBAAC;GAAK,GAAE;aAAS;IAAqB;GACjC;CAIX,MAAM,cAAc,MAAM,IAAI;CAC9B,MAAM,cAAc,OAAO,KAAK,oBAAoB,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;CAC3E,MAAM,eAAe,OAAO,KAAK,qBAAqB,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;CAC7E,MAAM,eAAe,OAAO,KAAK,qBAAqB,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;CAE7E,MAAM,qBAAqB;AACzB,MAAI,YAAY,SAAS,YAAY,CAAE,QAAO;AAC9C,MAAI,YAAY,SAAS,YAAY,CAAE,QAAO;AAC9C,SAAO;;CAET,MAAM,YAAY,cAAc;CAEhC,MAAM,cACJ,KAAK,aAAa,KAAK,WACnB,GAAG,KAAK,aAAa,GAAG,GAAG,KAAK,YAAY,KAAK,MAAM,GACvD,KAAK,YAAY,KAAK,SAAS;AAErC,QACE,qBAAC;EAAK,MAAM;EAAG,WAAU;EAAS,KAAI;EAAK,GAAE;;GAC3C,oBAAC;IAAK;IAAW,GAAE;cACjB,qBAAC,oBACC,oBAAC;KAAO,MAAK;KAAK,QAAO;KAAK,OAAM;eACjC,YAAY,OAAO,EAAE,CAAC,aAAa;MAC7B,EACT,qBAAC;KAAM,KAAK;;MACV,qBAAC;OAAM,KAAI;kBACT,oBAAC;QAAK,MAAK;QAAK,IAAI;kBACjB;SACI,EACP,oBAAC;QACC,MAAK;QACL,SAAQ;QACR,OAAO,KAAK,UAAU,UAAU;kBAE/B,KAAK,UAAU,WAAW;SACrB;QACF;MACR,oBAAC;OAAK,MAAK;OAAK,GAAE;iBACf,KAAK,SAAS,KAAK,YAAY,KAAK;QAChC;MACN,KAAK,MAAM,SAAS,KACnB,oBAAC;OAAM,KAAK;iBACT,KAAK,MAAM,KAAK,SACf,oBAAC;QAAiB,MAAK;QAAK,SAAQ;kBACjC;UADS,KAEJ,CACR;QACI;;MAEJ,IACF;KACH;GAEP,oBAAC;IAAK,OAAO;cACX,qBAAC,KAAK;KACJ,oBAAC;MACC,MAAM;MACN,aAAa,oBAAC,YAAS,MAAM,KAAM;MACnC,GAAG,cAAc,YAAY,SAAY;MACzC,IAAI,cAAc,YAAY,MAAM;MACpC,OAAO;OACL,cACE,cAAc,YACV,kDACA;OACN,cAAc;OACf;gBACF;OAEc;KACf,oBAAC;MACC,MAAM;MACN,aAAa,oBAAC,eAAY,MAAM,KAAM;MACtC,GAAG,cAAc,aAAa,SAAY;MAC1C,IAAI,cAAc,aAAa,MAAM;MACrC,OAAO;OACL,cACE,cAAc,aACV,kDACA;OACN,cAAc;OACf;gBACF;OAEc;KACf,oBAAC;MACC,MAAM;MACN,aAAa,oBAAC,gBAAa,MAAM,KAAM;MACvC,GAAG,cAAc,aAAa,SAAY;MAC1C,IAAI,cAAc,aAAa,MAAM;MACrC,OAAO;OACL,cACE,cAAc,aACV,kDACA;OACN,cAAc;OACf;gBACF;OAEc;QACL;KACP;GAEP,oBAAC;IAAK,MAAM;cACV,oBAAC,eAAa;KACT;;GACF;;AAIX,8BAAe"}
@@ -1,3 +0,0 @@
1
- import { t as AdminUserSettings_default } from "./AdminUserSettings-CR7MxX_R.js";
2
-
3
- export { AdminUserSettings_default as default };
@@ -1 +0,0 @@
1
- {"version":3,"file":"AdminUserSettings-CR7MxX_R.js","names":[],"sources":["../../src/admin/components/users/AdminUserSettings.tsx"],"sourcesContent":["import { useClient } from \"@alepha/react\";\nimport { useRouter, useRouterState } from \"@alepha/react/router\";\nimport { ActionButton, Flex, Text } from \"@alepha/ui\";\nimport { Alert, Card, Group, Loader, Stack } from \"@mantine/core\";\nimport {\n IconAlertCircle,\n IconCheck,\n IconMail,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport type { UserController, UserEntity } from \"alepha/api/users\";\nimport { useEffect, useState } from \"react\";\nimport type { AdminRouter } from \"../../AdminRouter.ts\";\n\nexport interface AdminUserSettingsProps {\n userRealmName?: string;\n}\n\nconst AdminUserSettings = (props: AdminUserSettingsProps) => {\n const router = useRouter<AdminRouter>();\n const state = useRouterState();\n const client = useClient<UserController>();\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 [deleteLoading, setDeleteLoading] = useState(false);\n const [verifyLoading, setVerifyLoading] = useState(false);\n const [verifySuccess, setVerifySuccess] = 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 handleDelete = async () => {\n if (!confirm(\"Are you sure you want to delete this user?\")) {\n return;\n }\n\n setDeleteLoading(true);\n try {\n await client.deleteUser({\n params: { id: userId },\n query: { userRealmName: props.userRealmName },\n });\n await router.go(\"adminUsers\");\n } finally {\n setDeleteLoading(false);\n }\n };\n\n const handleTriggerEmailVerification = async () => {\n if (!user?.email) return;\n\n setVerifyLoading(true);\n setVerifySuccess(false);\n try {\n await client.requestEmailVerification({\n query: {\n userRealmName: props.userRealmName,\n method: \"link\",\n verifyUrl: `${window.location.origin}/verify-email`,\n },\n body: { email: user.email },\n });\n setVerifySuccess(true);\n } finally {\n setVerifyLoading(false);\n }\n };\n\n if (loading) {\n return (\n <Flex flex={1} justify=\"center\" align=\"center\">\n <Loader />\n </Flex>\n );\n }\n\n if (!user) {\n return (\n <Flex flex={1} justify=\"center\" align=\"center\">\n <Text c=\"dimmed\">User not found</Text>\n </Flex>\n );\n }\n\n return (\n <Flex flex={1} direction=\"column\" gap=\"md\">\n {user.email && !user.emailVerified && (\n <Card withBorder p=\"lg\">\n <Stack gap=\"md\">\n <Text size=\"lg\" fw={500}>\n Email Verification\n </Text>\n\n <Alert variant=\"light\" color=\"yellow\" icon={<IconMail />}>\n <Text size=\"sm\">\n This user's email ({user.email}) is not verified. You can send a\n verification link to the user.\n </Text>\n </Alert>\n\n {verifySuccess && (\n <Alert variant=\"light\" color=\"green\" icon={<IconCheck />}>\n <Text size=\"sm\">\n Verification link sent successfully to {user.email}.\n </Text>\n </Alert>\n )}\n\n <Group>\n <ActionButton\n leftSection={<IconMail size={16} />}\n loading={verifyLoading}\n onClick={handleTriggerEmailVerification}\n >\n Send Verification Link\n </ActionButton>\n </Group>\n </Stack>\n </Card>\n )}\n\n <Card withBorder p=\"lg\">\n <Stack gap=\"md\">\n <Text size=\"lg\" fw={500} c=\"red\">\n Danger Zone\n </Text>\n\n <Alert variant=\"light\" color=\"red\" icon={<IconAlertCircle />}>\n <Text size=\"sm\">\n Deleting this user will permanently remove their account and all\n associated data. This action cannot be undone.\n </Text>\n </Alert>\n\n <Group>\n <ActionButton\n color=\"red\"\n leftSection={<IconTrash size={16} />}\n loading={deleteLoading}\n onClick={handleDelete}\n >\n Delete User\n </ActionButton>\n </Group>\n </Stack>\n </Card>\n </Flex>\n );\n};\n\nexport default AdminUserSettings;\n"],"mappings":";;;;;;;;;AAkBA,MAAM,qBAAqB,UAAkC;CAC3D,MAAM,SAAS,WAAwB;CACvC,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,SAAS,WAA2B;CAC1C,MAAM,SAAS,MAAM,OAAO;CAE5B,MAAM,CAAC,MAAM,WAAW,SAA4B,KAAK;CACzD,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAC5C,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;CACzD,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;CACzD,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;AAEzD,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,eAAe,YAAY;AAC/B,MAAI,CAAC,QAAQ,6CAA6C,CACxD;AAGF,mBAAiB,KAAK;AACtB,MAAI;AACF,SAAM,OAAO,WAAW;IACtB,QAAQ,EAAE,IAAI,QAAQ;IACtB,OAAO,EAAE,eAAe,MAAM,eAAe;IAC9C,CAAC;AACF,SAAM,OAAO,GAAG,aAAa;YACrB;AACR,oBAAiB,MAAM;;;CAI3B,MAAM,iCAAiC,YAAY;AACjD,MAAI,CAAC,MAAM,MAAO;AAElB,mBAAiB,KAAK;AACtB,mBAAiB,MAAM;AACvB,MAAI;AACF,SAAM,OAAO,yBAAyB;IACpC,OAAO;KACL,eAAe,MAAM;KACrB,QAAQ;KACR,WAAW,GAAG,OAAO,SAAS,OAAO;KACtC;IACD,MAAM,EAAE,OAAO,KAAK,OAAO;IAC5B,CAAC;AACF,oBAAiB,KAAK;YACd;AACR,oBAAiB,MAAM;;;AAI3B,KAAI,QACF,QACE,oBAAC;EAAK,MAAM;EAAG,SAAQ;EAAS,OAAM;YACpC,oBAAC,WAAS;GACL;AAIX,KAAI,CAAC,KACH,QACE,oBAAC;EAAK,MAAM;EAAG,SAAQ;EAAS,OAAM;YACpC,oBAAC;GAAK,GAAE;aAAS;IAAqB;GACjC;AAIX,QACE,qBAAC;EAAK,MAAM;EAAG,WAAU;EAAS,KAAI;aACnC,KAAK,SAAS,CAAC,KAAK,iBACnB,oBAAC;GAAK;GAAW,GAAE;aACjB,qBAAC;IAAM,KAAI;;KACT,oBAAC;MAAK,MAAK;MAAK,IAAI;gBAAK;OAElB;KAEP,oBAAC;MAAM,SAAQ;MAAQ,OAAM;MAAS,MAAM,oBAAC,aAAW;gBACtD,qBAAC;OAAK,MAAK;;QAAK;QACM,KAAK;QAAM;;QAE1B;OACD;KAEP,iBACC,oBAAC;MAAM,SAAQ;MAAQ,OAAM;MAAQ,MAAM,oBAAC,cAAY;gBACtD,qBAAC;OAAK,MAAK;;QAAK;QAC0B,KAAK;QAAM;;QAC9C;OACD;KAGV,oBAAC,mBACC,oBAAC;MACC,aAAa,oBAAC,YAAS,MAAM,KAAM;MACnC,SAAS;MACT,SAAS;gBACV;OAEc,GACT;;KACF;IACH,EAGT,oBAAC;GAAK;GAAW,GAAE;aACjB,qBAAC;IAAM,KAAI;;KACT,oBAAC;MAAK,MAAK;MAAK,IAAI;MAAK,GAAE;gBAAM;OAE1B;KAEP,oBAAC;MAAM,SAAQ;MAAQ,OAAM;MAAM,MAAM,oBAAC,oBAAkB;gBAC1D,oBAAC;OAAK,MAAK;iBAAK;QAGT;OACD;KAER,oBAAC,mBACC,oBAAC;MACC,OAAM;MACN,aAAa,oBAAC,aAAU,MAAM,KAAM;MACpC,SAAS;MACT,SAAS;gBACV;OAEc,GACT;;KACF;IACH;GACF;;AAIX,gCAAe"}