@mesob/auth-react 0.4.3 → 0.4.5

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 (183) hide show
  1. package/dist/{chunk-XEFPJKBB.js → chunk-4ABXALRN.js} +2 -2
  2. package/dist/{chunk-DXTZQ2VY.js → chunk-4NUO6F3J.js} +2 -2
  3. package/dist/{chunk-CC3HI442.js → chunk-5AEV7RAN.js} +3 -3
  4. package/dist/{chunk-VA2XUED4.js → chunk-5HAABEAS.js} +2 -2
  5. package/dist/{chunk-EKZYBYZQ.js → chunk-5SDS2E3F.js} +2 -2
  6. package/dist/{chunk-ODDTS4RN.js → chunk-6IEX2RLA.js} +3 -3
  7. package/dist/{chunk-HM4MAF2I.js → chunk-A3GIMM2R.js} +3 -3
  8. package/dist/{chunk-4QMUNU5E.js → chunk-A7ORWWM5.js} +6 -4
  9. package/dist/{chunk-4QMUNU5E.js.map → chunk-A7ORWWM5.js.map} +1 -1
  10. package/dist/{chunk-XCJ3ZH7D.js → chunk-AWSAC7RT.js} +1 -1
  11. package/dist/{chunk-XCJ3ZH7D.js.map → chunk-AWSAC7RT.js.map} +1 -1
  12. package/dist/{chunk-V4VX55TT.js → chunk-CP4TTRV4.js} +2 -2
  13. package/dist/{chunk-GB3Q5IWT.js → chunk-CXMPZWMX.js} +4 -4
  14. package/dist/{chunk-AKEBT5PJ.js → chunk-DG6GRTPG.js} +2 -2
  15. package/dist/{chunk-KTZSXSHV.js → chunk-DY3NVBLJ.js} +2 -2
  16. package/dist/{chunk-OK7WPIHQ.js → chunk-EPEXIGKB.js} +2 -2
  17. package/dist/{chunk-F6IMR5XS.js → chunk-EQWOGD4F.js} +2 -2
  18. package/dist/{chunk-RZFSMM3X.js → chunk-ETOCBXDT.js} +3 -3
  19. package/dist/{chunk-LNG736CV.js → chunk-EWXK56WQ.js} +1 -1
  20. package/dist/chunk-FPYQ7XGV.js +415 -0
  21. package/dist/chunk-FPYQ7XGV.js.map +1 -0
  22. package/dist/chunk-G74DDR4O.js +153 -0
  23. package/dist/chunk-G74DDR4O.js.map +1 -0
  24. package/dist/{chunk-HH347MJI.js → chunk-GVEBIL3O.js} +2 -2
  25. package/dist/{chunk-M6ZUEZJT.js → chunk-HXHI4FU6.js} +3 -3
  26. package/dist/{chunk-VU4Z2XSQ.js → chunk-IFAVSKHE.js} +3 -3
  27. package/dist/{chunk-WD2COCQW.js → chunk-KOBZ34XU.js} +4 -4
  28. package/dist/{chunk-ZE3R37PI.js → chunk-L32Z3TPA.js} +213 -54
  29. package/dist/chunk-L32Z3TPA.js.map +1 -0
  30. package/dist/{chunk-CDECLPL4.js → chunk-LHZ4EEN6.js} +3 -3
  31. package/dist/{chunk-REHGRIUT.js → chunk-MQI6Q2S4.js} +7 -25
  32. package/dist/chunk-MQI6Q2S4.js.map +1 -0
  33. package/dist/{chunk-6F5LEXYI.js → chunk-MVVAPYUD.js} +2 -2
  34. package/dist/chunk-NUWAI3FE.js +350 -0
  35. package/dist/chunk-NUWAI3FE.js.map +1 -0
  36. package/dist/{chunk-S3KIMVDE.js → chunk-OQUUS5ZX.js} +4 -4
  37. package/dist/chunk-OW75JENQ.js +19 -0
  38. package/dist/chunk-OW75JENQ.js.map +1 -0
  39. package/dist/{chunk-KM5GOJ75.js → chunk-PG65ZD7A.js} +4 -4
  40. package/dist/{chunk-NFBOIG3D.js → chunk-RBXITSE2.js} +5 -5
  41. package/dist/{chunk-BMZTYXGO.js → chunk-RMJNENJB.js} +2 -2
  42. package/dist/{chunk-5NKPFZ2Q.js → chunk-SGDXNT7M.js} +3 -3
  43. package/dist/{chunk-SJHJ63HK.js → chunk-SW7WD64K.js} +15 -6
  44. package/dist/chunk-SW7WD64K.js.map +1 -0
  45. package/dist/{chunk-ABF34UFW.js → chunk-SXVTYYUT.js} +3 -3
  46. package/dist/{chunk-ABF34UFW.js.map → chunk-SXVTYYUT.js.map} +1 -1
  47. package/dist/{chunk-GIGXCAGH.js → chunk-TB2ZPGLW.js} +3 -3
  48. package/dist/{chunk-RJBNA7OH.js → chunk-TLQMK2QF.js} +4 -4
  49. package/dist/{chunk-RXHL7LUV.js → chunk-UAKGEJUN.js} +3 -3
  50. package/dist/{chunk-3HV5KQFZ.js → chunk-UGQP733V.js} +2 -2
  51. package/dist/{chunk-YHZLPAYD.js → chunk-UY55LEIG.js} +2 -2
  52. package/dist/{chunk-QJVZHT27.js → chunk-W3D4HG5W.js} +3 -3
  53. package/dist/{chunk-YLWCA2WK.js → chunk-WQ3UUUKF.js} +10 -3
  54. package/dist/chunk-WQ3UUUKF.js.map +1 -0
  55. package/dist/{chunk-JRHJNMG3.js → chunk-WY2JJNZW.js} +2 -2
  56. package/dist/{chunk-4BFHC4JI.js → chunk-X2BHF4KC.js} +2 -2
  57. package/dist/{chunk-SYT5Z7EF.js → chunk-YFQNNSSC.js} +2 -2
  58. package/dist/{chunk-JED4SG3W.js → chunk-YN7OEQI7.js} +4 -4
  59. package/dist/{chunk-JED4SG3W.js.map → chunk-YN7OEQI7.js.map} +1 -1
  60. package/dist/{chunk-PS2KBGDB.js → chunk-Z34NJZRL.js} +3 -3
  61. package/dist/{chunk-EGZYJMSA.js → chunk-ZXKEG3X5.js} +2 -2
  62. package/dist/{chunk-L2W6FXSZ.js → chunk-ZZ6D4KE4.js} +2 -2
  63. package/dist/components/auth/countdown.js +3 -3
  64. package/dist/components/auth/forgot-password.js +3 -3
  65. package/dist/components/auth/reset-password-form.js +3 -3
  66. package/dist/components/auth/set-password.js +3 -3
  67. package/dist/components/auth/sign-in.js +3 -3
  68. package/dist/components/auth/sign-up.js +3 -3
  69. package/dist/components/auth/verification-form.js +4 -4
  70. package/dist/components/auth/verify-email.js +5 -5
  71. package/dist/components/auth/verify-phone.js +5 -5
  72. package/dist/components/authorization/deny.js +2 -2
  73. package/dist/components/authorization/grant.js +2 -2
  74. package/dist/components/iam/permission-selector.js +2 -2
  75. package/dist/components/iam/permissions-page.js +2 -2
  76. package/dist/components/iam/permissions.js +2 -2
  77. package/dist/components/iam/role-detail-layout.js +2 -2
  78. package/dist/components/iam/role-detail-page.js +2 -2
  79. package/dist/components/iam/role-permissions-page.js +3 -3
  80. package/dist/components/iam/roles-page.js +6 -5
  81. package/dist/components/iam/roles.js +2 -2
  82. package/dist/components/iam/sessions-page.js +4 -4
  83. package/dist/components/iam/sessions.js +2 -2
  84. package/dist/components/iam/tenants-page.js +5 -5
  85. package/dist/components/iam/tenants.js +2 -2
  86. package/dist/components/iam/users-page.js +6 -5
  87. package/dist/components/iam/users.js +2 -2
  88. package/dist/components/profile/account.js +2 -2
  89. package/dist/components/profile/change-email-form.js +8 -8
  90. package/dist/components/profile/change-password-form.js +2 -2
  91. package/dist/components/profile/change-phone-form.js +8 -8
  92. package/dist/components/profile/otp-verification-modal.js +5 -5
  93. package/dist/components/profile/profile-layout.js +3 -3
  94. package/dist/components/profile/request-change-email-form.js +2 -2
  95. package/dist/components/profile/request-change-phone-form.js +2 -2
  96. package/dist/components/profile/security.js +13 -13
  97. package/dist/components/profile/verify-change-email-form.js +6 -6
  98. package/dist/components/profile/verify-change-phone-form.js +6 -6
  99. package/dist/index.js +50 -48
  100. package/dist/index.js.map +1 -1
  101. package/dist/pages/auth/forgot-password.js +3 -3
  102. package/dist/pages/auth/layout.js +1 -1
  103. package/dist/pages/auth/reset-password.js +3 -3
  104. package/dist/pages/auth/set-password.js +3 -3
  105. package/dist/pages/auth/sign-in.js +3 -3
  106. package/dist/pages/auth/sign-up.js +3 -3
  107. package/dist/pages/auth/verify-email.js +5 -5
  108. package/dist/pages/auth/verify-phone.js +5 -5
  109. package/dist/pages/iam/permissions.js +2 -2
  110. package/dist/pages/iam/role-detail-layout.js +2 -2
  111. package/dist/pages/iam/role-detail.js +2 -2
  112. package/dist/pages/iam/role-permissions.js +3 -3
  113. package/dist/pages/iam/role-users.js +7 -5
  114. package/dist/pages/iam/role-users.js.map +1 -1
  115. package/dist/pages/iam/roles.js +6 -5
  116. package/dist/pages/iam/sessions.js +4 -4
  117. package/dist/pages/iam/tenant-detail.js +3 -3
  118. package/dist/pages/iam/tenants/tenant-selector.js +150 -0
  119. package/dist/pages/iam/tenants/tenant-selector.js.map +1 -0
  120. package/dist/pages/iam/tenants/tenants-data.js +7 -0
  121. package/dist/pages/iam/tenants/tenants-data.js.map +1 -0
  122. package/dist/pages/iam/tenants.js +5 -5
  123. package/dist/pages/iam/user-activity.js +6 -5
  124. package/dist/pages/iam/user-activity.js.map +1 -1
  125. package/dist/pages/iam/user-detail-layout.js +2 -2
  126. package/dist/pages/iam/user-detail.js +2 -2
  127. package/dist/pages/iam/users/_components/users-data.d.ts +4 -4
  128. package/dist/pages/iam/users/user-selector.js +14 -0
  129. package/dist/pages/iam/users/user-selector.js.map +1 -0
  130. package/dist/pages/iam/users/users-data.js +1 -0
  131. package/dist/pages/iam/users/users-data.js.map +1 -0
  132. package/dist/pages/iam/users.js +6 -5
  133. package/dist/pages/profile/account.js +2 -2
  134. package/dist/pages/profile/layout.js +3 -3
  135. package/dist/pages/profile/security.js +13 -13
  136. package/dist/types.d.ts +2 -0
  137. package/package.json +20 -3
  138. package/dist/chunk-GYFHM72X.js +0 -486
  139. package/dist/chunk-GYFHM72X.js.map +0 -1
  140. package/dist/chunk-REHGRIUT.js.map +0 -1
  141. package/dist/chunk-SJHJ63HK.js.map +0 -1
  142. package/dist/chunk-UCNNUST6.js +0 -271
  143. package/dist/chunk-UCNNUST6.js.map +0 -1
  144. package/dist/chunk-YLWCA2WK.js.map +0 -1
  145. package/dist/chunk-ZE3R37PI.js.map +0 -1
  146. /package/dist/{chunk-XEFPJKBB.js.map → chunk-4ABXALRN.js.map} +0 -0
  147. /package/dist/{chunk-DXTZQ2VY.js.map → chunk-4NUO6F3J.js.map} +0 -0
  148. /package/dist/{chunk-CC3HI442.js.map → chunk-5AEV7RAN.js.map} +0 -0
  149. /package/dist/{chunk-VA2XUED4.js.map → chunk-5HAABEAS.js.map} +0 -0
  150. /package/dist/{chunk-EKZYBYZQ.js.map → chunk-5SDS2E3F.js.map} +0 -0
  151. /package/dist/{chunk-ODDTS4RN.js.map → chunk-6IEX2RLA.js.map} +0 -0
  152. /package/dist/{chunk-HM4MAF2I.js.map → chunk-A3GIMM2R.js.map} +0 -0
  153. /package/dist/{chunk-V4VX55TT.js.map → chunk-CP4TTRV4.js.map} +0 -0
  154. /package/dist/{chunk-GB3Q5IWT.js.map → chunk-CXMPZWMX.js.map} +0 -0
  155. /package/dist/{chunk-AKEBT5PJ.js.map → chunk-DG6GRTPG.js.map} +0 -0
  156. /package/dist/{chunk-KTZSXSHV.js.map → chunk-DY3NVBLJ.js.map} +0 -0
  157. /package/dist/{chunk-OK7WPIHQ.js.map → chunk-EPEXIGKB.js.map} +0 -0
  158. /package/dist/{chunk-F6IMR5XS.js.map → chunk-EQWOGD4F.js.map} +0 -0
  159. /package/dist/{chunk-RZFSMM3X.js.map → chunk-ETOCBXDT.js.map} +0 -0
  160. /package/dist/{chunk-LNG736CV.js.map → chunk-EWXK56WQ.js.map} +0 -0
  161. /package/dist/{chunk-HH347MJI.js.map → chunk-GVEBIL3O.js.map} +0 -0
  162. /package/dist/{chunk-M6ZUEZJT.js.map → chunk-HXHI4FU6.js.map} +0 -0
  163. /package/dist/{chunk-VU4Z2XSQ.js.map → chunk-IFAVSKHE.js.map} +0 -0
  164. /package/dist/{chunk-WD2COCQW.js.map → chunk-KOBZ34XU.js.map} +0 -0
  165. /package/dist/{chunk-CDECLPL4.js.map → chunk-LHZ4EEN6.js.map} +0 -0
  166. /package/dist/{chunk-6F5LEXYI.js.map → chunk-MVVAPYUD.js.map} +0 -0
  167. /package/dist/{chunk-S3KIMVDE.js.map → chunk-OQUUS5ZX.js.map} +0 -0
  168. /package/dist/{chunk-KM5GOJ75.js.map → chunk-PG65ZD7A.js.map} +0 -0
  169. /package/dist/{chunk-NFBOIG3D.js.map → chunk-RBXITSE2.js.map} +0 -0
  170. /package/dist/{chunk-BMZTYXGO.js.map → chunk-RMJNENJB.js.map} +0 -0
  171. /package/dist/{chunk-5NKPFZ2Q.js.map → chunk-SGDXNT7M.js.map} +0 -0
  172. /package/dist/{chunk-GIGXCAGH.js.map → chunk-TB2ZPGLW.js.map} +0 -0
  173. /package/dist/{chunk-RJBNA7OH.js.map → chunk-TLQMK2QF.js.map} +0 -0
  174. /package/dist/{chunk-RXHL7LUV.js.map → chunk-UAKGEJUN.js.map} +0 -0
  175. /package/dist/{chunk-3HV5KQFZ.js.map → chunk-UGQP733V.js.map} +0 -0
  176. /package/dist/{chunk-YHZLPAYD.js.map → chunk-UY55LEIG.js.map} +0 -0
  177. /package/dist/{chunk-QJVZHT27.js.map → chunk-W3D4HG5W.js.map} +0 -0
  178. /package/dist/{chunk-JRHJNMG3.js.map → chunk-WY2JJNZW.js.map} +0 -0
  179. /package/dist/{chunk-4BFHC4JI.js.map → chunk-X2BHF4KC.js.map} +0 -0
  180. /package/dist/{chunk-SYT5Z7EF.js.map → chunk-YFQNNSSC.js.map} +0 -0
  181. /package/dist/{chunk-PS2KBGDB.js.map → chunk-Z34NJZRL.js.map} +0 -0
  182. /package/dist/{chunk-EGZYJMSA.js.map → chunk-ZXKEG3X5.js.map} +0 -0
  183. /package/dist/{chunk-L2W6FXSZ.js.map → chunk-ZZ6D4KE4.js.map} +0 -0
@@ -1,271 +0,0 @@
1
- import {
2
- Link,
3
- authApi$
4
- } from "./chunk-QJVZHT27.js";
5
-
6
- // src/pages/iam/users/_components/user-form.tsx
7
- import { zodResolver } from "@hookform/resolvers/zod";
8
- import {
9
- EntityDrawer,
10
- EntityFormActions,
11
- Input,
12
- Label,
13
- Skeleton
14
- } from "@mesob/ui/components";
15
- import { useQueryClient } from "@tanstack/react-query";
16
- import { useEffect } from "react";
17
- import { useForm } from "react-hook-form";
18
- import { z } from "zod";
19
- import { jsx, jsxs } from "react/jsx-runtime";
20
- var schema = z.object({
21
- fullName: z.string().min(1, "Name is required"),
22
- email: z.string().email().optional().or(z.literal("")),
23
- phone: z.string().optional()
24
- });
25
- var defaults = {
26
- fullName: "",
27
- email: "",
28
- phone: ""
29
- };
30
- function UserForm({
31
- mode,
32
- userId,
33
- open,
34
- onClose,
35
- onSuccess
36
- }) {
37
- const qc = useQueryClient();
38
- const { data, isLoading } = authApi$.useQuery(
39
- "get",
40
- "/users/{id}",
41
- { params: { path: { id: userId ?? "" } } },
42
- { enabled: mode === "edit" && !!userId }
43
- );
44
- const create = authApi$.useMutation("post", "/users", {
45
- onSuccess: () => {
46
- qc.invalidateQueries({ queryKey: ["get", "/users"] });
47
- }
48
- });
49
- const update = authApi$.useMutation("put", "/users/{id}", {
50
- onSuccess: () => {
51
- qc.invalidateQueries({ queryKey: ["get", "/users"] });
52
- if (userId) {
53
- qc.invalidateQueries({ queryKey: ["get", "/users/{id}"] });
54
- }
55
- }
56
- });
57
- const del = authApi$.useMutation("delete", "/users/{id}", {
58
- onSuccess: () => {
59
- qc.invalidateQueries({ queryKey: ["get", "/users"] });
60
- }
61
- });
62
- const form = useForm({
63
- resolver: zodResolver(schema),
64
- defaultValues: defaults
65
- });
66
- const { reset, formState } = form;
67
- useEffect(() => {
68
- if (!open) {
69
- return;
70
- }
71
- if (mode === "edit" && data?.user && !isLoading) {
72
- const u = data.user;
73
- reset({
74
- fullName: u.fullName,
75
- email: u.email ?? "",
76
- phone: u.phone ?? ""
77
- });
78
- } else {
79
- reset(defaults);
80
- }
81
- }, [mode, data, open, isLoading, reset]);
82
- const onSubmit = form.handleSubmit(async (d) => {
83
- const payload = {
84
- fullName: d.fullName,
85
- email: d.email || void 0,
86
- phone: d.phone || void 0
87
- };
88
- if (mode === "new") {
89
- await create.mutateAsync({ body: payload });
90
- } else if (userId) {
91
- await update.mutateAsync({
92
- params: { path: { id: userId } },
93
- body: payload
94
- });
95
- }
96
- onSuccess?.();
97
- onClose();
98
- });
99
- const onDelete = async () => {
100
- if (!userId) {
101
- return;
102
- }
103
- await del.mutateAsync({ params: { path: { id: userId } } });
104
- onSuccess?.();
105
- onClose();
106
- };
107
- const isSubmitting = create.isPending || update.isPending;
108
- return /* @__PURE__ */ jsx(
109
- EntityDrawer,
110
- {
111
- title: mode === "new" ? "New user" : "Edit user",
112
- open,
113
- onClose,
114
- isDirty: formState.isDirty,
115
- form: isLoading ? /* @__PURE__ */ jsx(FormSkeleton, {}) : /* @__PURE__ */ jsxs("form", { onSubmit, className: "space-y-4", children: [
116
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
117
- /* @__PURE__ */ jsxs(Label, { htmlFor: "fullName", children: [
118
- "Full name ",
119
- /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" })
120
- ] }),
121
- /* @__PURE__ */ jsx(
122
- Input,
123
- {
124
- id: "fullName",
125
- placeholder: "Full name",
126
- ...form.register("fullName")
127
- }
128
- ),
129
- formState.errors.fullName && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: formState.errors.fullName.message })
130
- ] }),
131
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
132
- /* @__PURE__ */ jsx(Label, { htmlFor: "email", children: "Email" }),
133
- /* @__PURE__ */ jsx(
134
- Input,
135
- {
136
- id: "email",
137
- type: "email",
138
- placeholder: "Email",
139
- ...form.register("email")
140
- }
141
- ),
142
- formState.errors.email && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: formState.errors.email.message })
143
- ] }),
144
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
145
- /* @__PURE__ */ jsx(Label, { htmlFor: "phone", children: "Phone" }),
146
- /* @__PURE__ */ jsx(
147
- Input,
148
- {
149
- id: "phone",
150
- placeholder: "Phone",
151
- ...form.register("phone")
152
- }
153
- )
154
- ] })
155
- ] }),
156
- actions: /* @__PURE__ */ jsx(
157
- EntityFormActions,
158
- {
159
- mode,
160
- onSubmit,
161
- onReset: mode === "new" ? () => reset(defaults) : void 0,
162
- onDelete: mode === "edit" ? onDelete : void 0,
163
- isSubmitting,
164
- isDeleting: del.isPending,
165
- disabled: isLoading,
166
- itemName: "user"
167
- }
168
- )
169
- }
170
- );
171
- }
172
- function FormSkeleton() {
173
- return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
174
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
175
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-20" }),
176
- /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full" })
177
- ] }),
178
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
179
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-16" }),
180
- /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full" })
181
- ] }),
182
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
183
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-14" }),
184
- /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full" })
185
- ] }),
186
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
187
- /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-16" }),
188
- /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full" })
189
- ] })
190
- ] });
191
- }
192
-
193
- // src/pages/iam/users/_components/user-card.tsx
194
- import {
195
- Badge,
196
- Button,
197
- Card,
198
- CardContent,
199
- CardHeader,
200
- DropdownMenu,
201
- DropdownMenuContent,
202
- DropdownMenuItem,
203
- DropdownMenuPortal,
204
- DropdownMenuTrigger
205
- } from "@mesob/ui/components";
206
- import { IconDots, IconPencil } from "@tabler/icons-react";
207
- import { useState } from "react";
208
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
209
- function UserCard({ user }) {
210
- const [editOpen, setEditOpen] = useState(false);
211
- return /* @__PURE__ */ jsxs2(Fragment, { children: [
212
- /* @__PURE__ */ jsxs2(Card, { className: "group hover:shadow-md transition-shadow", children: [
213
- /* @__PURE__ */ jsx2(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-start justify-between", children: [
214
- /* @__PURE__ */ jsx2(
215
- Link,
216
- {
217
- href: `/iam/users/${user.id}`,
218
- className: "text-left font-semibold hover:text-primary hover:underline",
219
- children: user.fullName
220
- }
221
- ),
222
- /* @__PURE__ */ jsxs2(DropdownMenu, { children: [
223
- /* @__PURE__ */ jsx2(
224
- DropdownMenuTrigger,
225
- {
226
- render: /* @__PURE__ */ jsx2(
227
- Button,
228
- {
229
- variant: "ghost",
230
- size: "icon",
231
- className: "h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity"
232
- }
233
- ),
234
- children: /* @__PURE__ */ jsx2(IconDots, { className: "h-4 w-4" })
235
- }
236
- ),
237
- /* @__PURE__ */ jsx2(DropdownMenuPortal, { children: /* @__PURE__ */ jsx2(DropdownMenuContent, { children: /* @__PURE__ */ jsxs2(DropdownMenuItem, { onClick: () => setEditOpen(true), children: [
238
- /* @__PURE__ */ jsx2(IconPencil, { className: "mr-2 h-4 w-4" }),
239
- "Edit"
240
- ] }) }) })
241
- ] })
242
- ] }) }),
243
- /* @__PURE__ */ jsxs2(CardContent, { className: "space-y-2", children: [
244
- user.email && /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
245
- /* @__PURE__ */ jsx2("span", { className: "text-sm", children: user.email }),
246
- user.emailVerified && /* @__PURE__ */ jsx2(Badge, { variant: "outline", className: "text-xs", children: "Verified" })
247
- ] }),
248
- /* @__PURE__ */ jsxs2("p", { className: "text-xs text-muted-foreground", children: [
249
- "Last sign in",
250
- " ",
251
- user.lastSignInAt ? new Date(user.lastSignInAt).toLocaleDateString() : "never"
252
- ] })
253
- ] })
254
- ] }),
255
- editOpen && /* @__PURE__ */ jsx2(
256
- UserForm,
257
- {
258
- mode: "edit",
259
- userId: user.id,
260
- open: editOpen,
261
- onClose: () => setEditOpen(false)
262
- }
263
- )
264
- ] });
265
- }
266
-
267
- export {
268
- UserForm,
269
- UserCard
270
- };
271
- //# sourceMappingURL=chunk-UCNNUST6.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/pages/iam/users/_components/user-form.tsx","../src/pages/iam/users/_components/user-card.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n EntityDrawer,\n EntityFormActions,\n Input,\n Label,\n Skeleton,\n} from '@mesob/ui/components';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport { authApi$ } from '../../shared/page-helpers';\n\nconst schema = z.object({\n fullName: z.string().min(1, 'Name is required'),\n email: z.string().email().optional().or(z.literal('')),\n phone: z.string().optional(),\n});\n\ntype FormData = z.infer<typeof schema>;\n\nconst defaults: FormData = {\n fullName: '',\n email: '',\n phone: '',\n};\n\ntype UserFormProps = {\n mode: 'new' | 'edit';\n userId?: string;\n open: boolean;\n onClose: () => void;\n onSuccess?: () => void;\n};\n\nexport function UserForm({\n mode,\n userId,\n open,\n onClose,\n onSuccess,\n}: UserFormProps) {\n const qc = useQueryClient();\n const { data, isLoading } = authApi$.useQuery(\n 'get',\n '/users/{id}',\n { params: { path: { id: userId ?? '' } } },\n { enabled: mode === 'edit' && !!userId },\n );\n const create = authApi$.useMutation('post', '/users', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/users'] });\n },\n });\n const update = authApi$.useMutation('put', '/users/{id}', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/users'] });\n if (userId) {\n qc.invalidateQueries({ queryKey: ['get', '/users/{id}'] });\n }\n },\n });\n const del = authApi$.useMutation('delete', '/users/{id}', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/users'] });\n },\n });\n\n const form = useForm<FormData>({\n resolver: zodResolver(schema),\n defaultValues: defaults,\n });\n\n const { reset, formState } = form;\n\n useEffect(() => {\n if (!open) {\n return;\n }\n if (mode === 'edit' && data?.user && !isLoading) {\n const u = data.user;\n reset({\n fullName: u.fullName,\n email: u.email ?? '',\n phone: u.phone ?? '',\n });\n } else {\n reset(defaults);\n }\n }, [mode, data, open, isLoading, reset]);\n\n const onSubmit = form.handleSubmit(async (d) => {\n const payload = {\n fullName: d.fullName,\n email: d.email || undefined,\n phone: d.phone || undefined,\n };\n if (mode === 'new') {\n await create.mutateAsync({ body: payload });\n } else if (userId) {\n await update.mutateAsync({\n params: { path: { id: userId } },\n body: payload,\n });\n }\n onSuccess?.();\n onClose();\n });\n\n const onDelete = async () => {\n if (!userId) {\n return;\n }\n await del.mutateAsync({ params: { path: { id: userId } } });\n onSuccess?.();\n onClose();\n };\n\n const isSubmitting = create.isPending || update.isPending;\n\n return (\n <EntityDrawer\n title={mode === 'new' ? 'New user' : 'Edit user'}\n open={open}\n onClose={onClose}\n isDirty={formState.isDirty}\n form={\n isLoading ? (\n <FormSkeleton />\n ) : (\n <form onSubmit={onSubmit} className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"fullName\">\n Full name <span className=\"text-destructive\">*</span>\n </Label>\n <Input\n id=\"fullName\"\n placeholder=\"Full name\"\n {...form.register('fullName')}\n />\n {formState.errors.fullName && (\n <p className=\"text-sm text-destructive\">\n {formState.errors.fullName.message}\n </p>\n )}\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"email\">Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"Email\"\n {...form.register('email')}\n />\n {formState.errors.email && (\n <p className=\"text-sm text-destructive\">\n {formState.errors.email.message}\n </p>\n )}\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"phone\">Phone</Label>\n <Input\n id=\"phone\"\n placeholder=\"Phone\"\n {...form.register('phone')}\n />\n </div>\n </form>\n )\n }\n actions={\n <EntityFormActions\n mode={mode}\n onSubmit={onSubmit}\n onReset={mode === 'new' ? () => reset(defaults) : undefined}\n onDelete={mode === 'edit' ? onDelete : undefined}\n isSubmitting={isSubmitting}\n isDeleting={del.isPending}\n disabled={isLoading}\n itemName=\"user\"\n />\n }\n />\n );\n}\n\nfunction FormSkeleton() {\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-20\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-14\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n </div>\n );\n}\n","'use client';\n\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n} from '@mesob/ui/components';\nimport { IconDots, IconPencil } from '@tabler/icons-react';\nimport { useState } from 'react';\nimport { Link } from '../../shared/page-helpers';\nimport { UserForm } from './user-form';\nimport type { User } from './users-data';\n\ntype UserCardProps = { user: User };\n\nexport function UserCard({ user }: UserCardProps) {\n const [editOpen, setEditOpen] = useState(false);\n return (\n <>\n <Card className=\"group hover:shadow-md transition-shadow\">\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-start justify-between\">\n <Link\n href={`/iam/users/${user.id}`}\n className=\"text-left font-semibold hover:text-primary hover:underline\"\n >\n {user.fullName}\n </Link>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity\"\n />\n }\n >\n <IconDots className=\"h-4 w-4\" />\n </DropdownMenuTrigger>\n <DropdownMenuPortal>\n <DropdownMenuContent>\n <DropdownMenuItem onClick={() => setEditOpen(true)}>\n <IconPencil className=\"mr-2 h-4 w-4\" />\n Edit\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenuPortal>\n </DropdownMenu>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {user.email && (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm\">{user.email}</span>\n {user.emailVerified && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Verified\n </Badge>\n )}\n </div>\n )}\n <p className=\"text-xs text-muted-foreground\">\n Last sign in{' '}\n {user.lastSignInAt\n ? new Date(user.lastSignInAt).toLocaleDateString()\n : 'never'}\n </p>\n </CardContent>\n </Card>\n {editOpen && (\n <UserForm\n mode=\"edit\"\n userId={user.id}\n open={editOpen}\n onClose={() => setEditOpen(false)}\n />\n )}\n </>\n );\n}\n"],"mappings":"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","names":["jsx","jsxs"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/auth/sign-in.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n Alert,\n AlertDescription,\n AlertTitle,\n Button,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n useFormField,\n} from '@mesob/ui/components';\nimport { useMesob } from '@mesob/ui/providers';\nimport { IconAlertCircle, IconEye, IconEyeOff } from '@tabler/icons-react';\nimport type { ChangeEvent, ComponentProps } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useTranslator } from '../../hooks/use-translator';\nimport { useApi, useConfig } from '../../provider';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { handleError } from '../../utils/handle-error';\nimport { normalizePhone } from '../../utils/normalize-phone';\nimport { AuthLayout } from './auth-layout';\n\nconst isPhone = (s: string) => /^\\+?[0-9()[\\]\\s-]{6,}$/.test(s);\n\ntype PasswordInputProps = {\n field: ComponentProps<'input'> & {\n value: string;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n onBlur: () => void;\n };\n show: boolean;\n onToggle: () => void;\n};\n\nfunction PasswordInput({ field, show, onToggle }: PasswordInputProps) {\n const { formItemId, error } = useFormField();\n return (\n <div className=\"relative\">\n <Input\n {...field}\n id={formItemId}\n type={show ? 'text' : 'password'}\n autoComplete=\"current-password\"\n aria-invalid={!!error}\n className=\"pr-10\"\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-0 top-0 h-full px-3 text-muted-foreground hover:text-foreground\"\n onClick={onToggle}\n aria-label={show ? 'Hide password' : 'Show password'}\n >\n {show ? (\n <IconEyeOff className=\"h-4 w-4\" />\n ) : (\n <IconEye className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n );\n}\n\ntype SignInProps = {\n redirectUrl?: string;\n};\n\nconst signInSchema = (t: (key: string) => string, phoneRegex: RegExp) =>\n z.object({\n username: z\n .string()\n .trim()\n .min(1, { message: t('errors.requiredField') })\n .refine(\n (val) => {\n const isEmail = z.email().safeParse(val).success;\n const isPhone = phoneRegex.test(val);\n return isEmail || isPhone;\n },\n { message: t('errors.invalidEmailOrPhone') },\n ),\n password: z\n .union([\n z.literal(''),\n z\n .string()\n .min(8, t('errors.passwordLength'))\n .max(128, t('errors.longPasswordError')),\n ])\n .optional(),\n });\n\ntype SignInFormValues = z.infer<ReturnType<typeof signInSchema>>;\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: multi-step form with two form contexts\nexport const SignIn = ({ redirectUrl }: SignInProps = {}) => {\n const { hooks, setAuth } = useApi();\n const { config } = useConfig();\n const mesob = useMesob();\n const t = useTranslator('Auth.signIn');\n const Link = mesob?.navigation?.Link;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n const [showPasswordField, setShowPasswordField] = useState(false);\n const [showPassword, setShowPassword] = useState(false);\n const [username, setUsername] = useState('');\n const [isChecking, setIsChecking] = useState(false);\n\n const checkUserMutation = hooks.useMutation('post', '/check-account');\n const signInMutation = hooks.useMutation('post', '/sign-in');\n\n const phoneRegex =\n typeof config.phoneRegex === 'string'\n ? new RegExp(config.phoneRegex)\n : config.phoneRegex || /^(\\+2519|\\+2517|2519|2517|09|07)\\d{8}$/;\n\n const defaultRedirect =\n redirectUrl || config.navigation?.defaultRedirectUrl || '/';\n const forgotPasswordLink =\n config.navigation?.links?.forgotPassword || '/auth/forgot-password';\n const signUpLink = config.navigation?.links?.signUp || '/auth/sign-up';\n const setPasswordLink =\n config.navigation?.links?.setPassword || '/auth/set-password';\n const onNavigate =\n config.navigation?.onNavigate ||\n ((path: string) => {\n if (typeof window !== 'undefined') {\n window.location.href = path;\n }\n });\n const logoImage = config.ui.logoImage;\n\n const form = useForm<SignInFormValues>({\n resolver: zodResolver(signInSchema(t, phoneRegex)),\n defaultValues: { username: '', password: '' },\n mode: 'onBlur',\n });\n\n useEffect(() => {\n if (error) {\n toast.error(error.title || 'Error', {\n description: error.description,\n });\n }\n }, [error]);\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: auth branching is intentional\n const handleCheckAccount = async (usernameValue: string) => {\n setIsChecking(true);\n try {\n const normalizedUsername = phoneRegex.test(usernameValue)\n ? normalizePhone(usernameValue)\n : usernameValue;\n\n const result = await checkUserMutation.mutateAsync({\n body: {\n username: normalizedUsername,\n },\n });\n\n if (result.exists) {\n setUsername(normalizedUsername);\n form.setValue('username', normalizedUsername);\n setShowPasswordField(true);\n } else {\n const email = isPhone(normalizedUsername) ? '' : normalizedUsername;\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n if (email) {\n onNavigate(\n `${signUpLink}?email=${encodeURIComponent(email)}${redirectParam}`,\n );\n } else {\n onNavigate(\n `${signUpLink}?phone=${encodeURIComponent(normalizedUsername)}${redirectParam}`,\n );\n }\n }\n } catch {\n form.setError('username', { message: t('errors.checkAccountFailed') });\n } finally {\n setIsChecking(false);\n }\n };\n\n const onSubmit = async (values: SignInFormValues) => {\n if (showPasswordField) {\n const pwd = values.password;\n if (!pwd || pwd.length < 8) {\n form.setError('password', { message: t('errors.passwordLength') });\n return;\n }\n await handlePasswordSubmit({ password: pwd });\n } else {\n await handleCheckAccount(values.username);\n }\n };\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: auth branching is intentional\n const handlePasswordSubmit = async (values: { password: string }) => {\n setIsLoading(true);\n setError(null);\n\n try {\n const res = await signInMutation.mutateAsync({\n body: {\n identifier: username,\n password: values.password,\n },\n });\n\n if ('verificationId' in res && res.verificationId) {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n const verifyPath = isPhone(username)\n ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(username)}${redirectParam}`\n : `/auth/verify-email?verificationId=${res.verificationId}${redirectParam}`;\n onNavigate(verifyPath);\n return;\n }\n\n if ('user' in res && 'session' in res) {\n setAuth(res);\n }\n onNavigate(defaultRedirect);\n } catch (err) {\n const authError = err as { code?: string; message?: string };\n const errorCode = authError.code || authError.message;\n if (errorCode === 'HAS_NO_PASSWORD') {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n onNavigate(\n `${setPasswordLink}?identifier=${encodeURIComponent(username)}${redirectParam}`,\n );\n return;\n }\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleBack = () => {\n setShowPasswordField(false);\n setUsername('');\n form.setValue('password', '');\n };\n\n const isSubmitting =\n isLoading ||\n checkUserMutation.isPending ||\n signInMutation.isPending ||\n isChecking;\n\n let submitLabel = t('form.continue');\n if (isSubmitting) {\n submitLabel = showPasswordField ? t('form.submitting') : t('form.checking');\n } else if (showPasswordField) {\n submitLabel = t('form.submit');\n }\n\n let errorContent: AuthErrorContent | null = null;\n if (error) {\n if (typeof error === 'string') {\n errorContent = { title: 'Error', description: error };\n } else {\n errorContent = error;\n }\n }\n\n const formContent = (\n <Form {...form}>\n <form\n id=\"sign-in-form\"\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"space-y-4\"\n >\n {showPasswordField ? (\n <>\n <FormItem>\n <FormLabel className=\"flex justify-between items-center\">\n {t('form.accountLabel')}\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"sm\"\n className=\"p-0 m-0 h-auto\"\n onClick={handleBack}\n >\n {t('changeAccount')}\n </Button>\n </FormLabel>\n <Input\n id=\"sign-in-username\"\n type=\"text\"\n value={username}\n autoComplete=\"username\"\n disabled\n />\n </FormItem>\n <FormField\n control={form.control}\n name=\"password\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.passwordLabel')}</FormLabel>\n <PasswordInput\n field={{ ...field, value: field.value ?? '' }}\n show={showPassword}\n onToggle={() => setShowPassword(!showPassword)}\n />\n <FormMessage />\n </FormItem>\n )}\n />\n </>\n ) : (\n <FormField\n control={form.control}\n name=\"username\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.accountLabel')}</FormLabel>\n <FormControl>\n <Input {...field} type=\"text\" autoComplete=\"username\" />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n )}\n <Button\n type=\"submit\"\n className=\"w-full\"\n disabled={isSubmitting}\n loading={isSubmitting}\n >\n {submitLabel}\n </Button>\n </form>\n </Form>\n );\n\n return (\n <div className=\"space-y-4\">\n <AuthLayout\n title={config.ui.name}\n description={t('description')}\n logoImage={logoImage}\n footer={\n showPasswordField ? (\n <div className=\"flex items-center justify-center w-full\">\n {Link ? (\n <Link\n href={forgotPasswordLink}\n className=\"text-primary inline-block hover:underline\"\n >\n {t('footer.forgotPassword')}\n </Link>\n ) : (\n <a\n href={forgotPasswordLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(forgotPasswordLink);\n }}\n className=\"text-primary inline-block hover:underline\"\n >\n {t('footer.forgotPassword')}\n </a>\n )}\n </div>\n ) : undefined\n }\n >\n {formContent}\n {errorContent && (\n <Alert variant=\"destructive\" className=\"mt-4\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n </AuthLayout>\n </div>\n );\n};\n"],"mappings":"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","names":["isPhone"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/iam/users-page.tsx","../src/pages/iam/users/_components/bulk-invite-user-form.tsx","../src/pages/iam/users/_components/invite-user-shared.tsx","../src/pages/iam/users/_components/invite-user-form.tsx","../src/pages/iam/users/_components/users-list.tsx"],"sourcesContent":["'use client';\n\nimport {\n EntityDrawerTrigger,\n EntityFilter,\n EntityHeader,\n EntitySearch,\n EntitySort,\n EntityViewToggle,\n PageBody,\n PageContainer,\n useBreadcrumbs,\n useEntityPagination,\n useEntityParams,\n} from '@mesob/ui/components';\nimport { IconUsers } from '@tabler/icons-react';\nimport { useState } from 'react';\nimport type { paths } from '../../data/openapi';\nimport { defaultEntityQueryOptions } from '../../lib/query-options';\nimport { BulkInviteUserForm } from '../../pages/iam/users/_components/bulk-invite-user-form';\nimport { InviteUserForm } from '../../pages/iam/users/_components/invite-user-form';\nimport { UsersList } from '../../pages/iam/users/_components/users-list';\nimport { useApi, useConfig } from '../../provider';\n\nexport function UsersPage() {\n const { hooks } = useApi();\n const { config } = useConfig();\n const homeHref = config.navigation?.defaultRedirectUrl || '/';\n useBreadcrumbs({\n items: [\n { label: 'Home', href: homeHref },\n { label: 'IAM', href: '/iam/users' },\n { label: 'Users' },\n ],\n });\n const [inviteOpen, setInviteOpen] = useState(false);\n const [bulkInviteOpen, setBulkInviteOpen] = useState(false);\n\n const { queryConfig, params, setParams } = useEntityParams({\n searchKey: 'search',\n searchParamName: 'handle',\n });\n const usersQuery = queryConfig as {\n params: {\n query: NonNullable<paths['/users']['get']['parameters']['query']>;\n };\n };\n\n const { data, isPending, isFetching } = hooks.useQuery(\n 'get',\n '/users',\n usersQuery,\n defaultEntityQueryOptions,\n );\n\n const isLoading = isPending || isFetching;\n const users = data?.users ?? [];\n const { total, pageCount } = useEntityPagination({\n items: users,\n total: data?.total,\n pageSize: params.pageSize,\n });\n\n return (\n <PageContainer className=\"flex flex-1 flex-col gap-4 p-4 pt-0\">\n <PageBody className=\"px-0\">\n <EntityHeader\n icon={<IconUsers className=\"h-5 w-5\" />}\n title=\"Users\"\n actions={\n <div className=\"flex items-center gap-2\">\n <EntityDrawerTrigger\n mode=\"new\"\n entity=\"User\"\n label=\"Invite user\"\n open={inviteOpen}\n onOpenChange={setInviteOpen}\n >\n {(open, onClose) => (\n <InviteUserForm open={open} onClose={onClose} />\n )}\n </EntityDrawerTrigger>\n <EntityDrawerTrigger\n mode=\"new\"\n entity=\"User\"\n label=\"Bulk invite\"\n variant=\"outline\"\n open={bulkInviteOpen}\n onOpenChange={setBulkInviteOpen}\n >\n {(open, onClose) => (\n <BulkInviteUserForm open={open} onClose={onClose} />\n )}\n </EntityDrawerTrigger>\n </div>\n }\n search={\n <EntitySearch paramKey=\"search\" placeholder=\"Search users...\" />\n }\n filter={\n <EntityFilter\n options={[\n { label: 'All', value: '' },\n { label: 'Email Verified', value: 'emailVerified' },\n { label: 'Phone Verified', value: 'phoneVerified' },\n { label: 'Not Verified', value: 'notVerified' },\n ]}\n placeholder=\"Filter\"\n />\n }\n sort={\n <EntitySort\n options={[\n { label: 'Created', value: 'createdAt' },\n { label: 'Updated', value: 'updatedAt' },\n { label: 'Name', value: 'fullName' },\n { label: 'Last Sign In', value: 'lastSignInAt' },\n ]}\n />\n }\n view={<EntityViewToggle views={['table', 'card']} />}\n />\n <UsersList\n data={users}\n isLoading={isLoading}\n view={(params.view || 'table') as 'table' | 'card'}\n pageIndex={params.page - 1}\n pageSize={params.pageSize}\n pageCount={pageCount}\n totalRows={total}\n onCreateNew={() => setInviteOpen(true)}\n onPageChange={(p) => setParams({ page: p + 1 })}\n onPageSizeChange={(size) => setParams({ pageSize: size, page: 1 })}\n />\n </PageBody>\n </PageContainer>\n );\n}\n","'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n EntityDrawer,\n EntityFormActions,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n Textarea,\n} from '@mesob/ui/components';\nimport { IconDownload, IconUsers } from '@tabler/icons-react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport type { ChangeEvent } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { authApi$ } from '../../shared/page-helpers';\nimport type {\n BulkInviteFailure,\n BulkInviteResponse,\n} from './invite-user-shared';\nimport {\n downloadInviteTemplate,\n InviteResultCard,\n inviteTemplateCsv,\n parseBulkInviteCsv,\n} from './invite-user-shared';\n\nconst schema = z.object({\n sourceFile: z.string().optional(),\n csvText: z.string().trim().min(1, 'CSV text is required'),\n});\n\ntype FormData = z.infer<typeof schema>;\n\ntype BulkInviteUserFormProps = {\n open: boolean;\n onClose: () => void;\n};\n\nconst defaults: FormData = {\n sourceFile: '',\n csvText: '',\n};\n\nexport function BulkInviteUserForm({ open, onClose }: BulkInviteUserFormProps) {\n const qc = useQueryClient();\n const [invited, setInvited] = useState<BulkInviteResponse['invited']>([]);\n const [failed, setFailed] = useState<BulkInviteFailure[]>([]);\n\n const form = useForm<FormData>({\n resolver: zodResolver(schema),\n defaultValues: defaults,\n });\n const { control, formState, getValues, reset, setValue } = form;\n\n const inviteBulk = authApi$.useMutation('post', '/users/invite/bulk', {\n onSuccess: async () => {\n await qc.invalidateQueries({ queryKey: ['get', '/users'] });\n },\n });\n\n useEffect(() => {\n if (open) {\n return;\n }\n\n reset(defaults);\n setInvited([]);\n setFailed([]);\n }, [open, reset]);\n\n const handleFileChange = async (\n event: ChangeEvent<HTMLInputElement>,\n onChange: (value: string) => void,\n ) => {\n const file = event.target.files?.[0];\n\n if (!file) {\n return;\n }\n\n try {\n const text = await file.text();\n onChange(file.name);\n setValue('csvText', text, {\n shouldDirty: true,\n shouldValidate: true,\n });\n toast.success(`Loaded ${file.name}`);\n } catch (error) {\n toast.error(\n error instanceof Error ? error.message : 'Failed to read CSV file',\n );\n } finally {\n event.target.value = '';\n }\n };\n\n const onSubmit = form.handleSubmit(async (values) => {\n try {\n const result = await inviteBulk.mutateAsync({\n body: {\n users: parseBulkInviteCsv(values.csvText),\n },\n });\n\n setInvited(result.invited);\n setFailed(result.failed);\n toast.success(\n `Bulk invite finished: ${result.invited.length} invited, ${result.failed.length} failed`,\n );\n } catch (error) {\n toast.error(\n error instanceof Error ? error.message : 'Failed to bulk invite users',\n );\n }\n });\n\n return (\n <EntityDrawer\n title=\"Bulk invite users\"\n open={open}\n onClose={onClose}\n isDirty={formState.isDirty}\n size=\"xl\"\n form={\n <Form {...form}>\n <form onSubmit={onSubmit} className=\"space-y-4\">\n <div className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground\">\n Download the CSV template, fill it with your users, then upload\n or paste the CSV below.\n </p>\n <Button\n variant=\"outline\"\n onClick={downloadInviteTemplate}\n leftIcon={<IconDownload className=\"size-4\" />}\n >\n Download template\n </Button>\n </div>\n\n <FormField\n control={control}\n name=\"sourceFile\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>Upload CSV</FormLabel>\n <FormControl>\n <Input\n type=\"file\"\n accept=\".csv,text/csv\"\n onChange={(event) =>\n handleFileChange(event, field.onChange)\n }\n />\n </FormControl>\n {field.value ? (\n <p className=\"text-sm text-muted-foreground\">\n Loaded file: {field.value}\n </p>\n ) : null}\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={control}\n name=\"csvText\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>CSV textarea</FormLabel>\n <FormControl>\n <Textarea\n className=\"min-h-[240px] font-mono text-xs\"\n placeholder={inviteTemplateCsv}\n {...field}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n {(invited.length > 0 || failed.length > 0) && (\n <>\n <Card className=\"border-border/60\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <IconUsers className=\"size-4\" />\n Invited\n <Badge>{invited.length}</Badge>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {invited.length ? (\n invited.map((result, index) => (\n <InviteResultCard\n key={`${result.user.id}-${index}`}\n result={result}\n index={index}\n />\n ))\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n Successful invites will show here.\n </p>\n )}\n </CardContent>\n </Card>\n\n <Card className=\"border-border/60\">\n <CardHeader>\n <CardTitle className=\"text-base\">\n Failed rows\n <Badge className=\"ml-2\" variant=\"destructive\">\n {failed.length}\n </Badge>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {failed.length ? (\n failed.map((failure) => (\n <div\n key={`${failure.index}-${failure.identifier}`}\n className=\"rounded-lg border border-destructive/30 bg-destructive/5 p-4\"\n >\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"font-medium\">\n row {failure.index + 1}\n </span>\n {failure.identifier ? (\n <Badge variant=\"outline\">\n {failure.identifier}\n </Badge>\n ) : null}\n </div>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n {failure.error}\n </p>\n </div>\n ))\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n Failed invites will show here.\n </p>\n )}\n </CardContent>\n </Card>\n </>\n )}\n </form>\n </Form>\n }\n actions={\n <EntityFormActions\n mode=\"new\"\n onSubmit={onSubmit}\n onReset={() => {\n reset(defaults);\n setInvited([]);\n setFailed([]);\n }}\n isSubmitting={inviteBulk.isPending}\n submitLabel=\"Invite\"\n disabled={!getValues('csvText').trim()}\n />\n }\n />\n );\n}\n","'use client';\n\nimport {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from '@mesob/ui/components';\nimport type { paths } from '../../../../data/openapi';\n\ntype InviteUserPayload = NonNullable<\n NonNullable<\n paths['/users/invite']['post']['requestBody']\n >['content']['application/json']\n>;\n\ntype InviteResult =\n paths['/users/invite']['post']['responses'][201]['content']['application/json'];\n\ntype BulkInviteResponse =\n paths['/users/invite/bulk']['post']['responses'][200]['content']['application/json'];\n\ntype BulkInviteFailure = BulkInviteResponse['failed'][number];\n\nconst inviteTemplateCsv = `fullName,email,phone,emailVerified,phoneVerified,sendVia,password\nLulit Demo,lulit@example.com,,true,false,email,\nAbel Demo,,+251911223344,false,true,sms|email,TempPass123!\nMarta Demo,marta@example.com,+251922334455,true,true,email|sms,`;\n\nconst defaultInviteUserValues = {\n fullName: '',\n email: '',\n phone: '',\n password: '',\n emailVerified: false,\n phoneVerified: false,\n viaEmail: false,\n viaSms: false,\n};\n\nfunction buildInviteUserPayload(\n values: typeof defaultInviteUserValues,\n): InviteUserPayload {\n return {\n fullName: values.fullName.trim(),\n email: values.email.trim() || undefined,\n phone: values.phone.trim() || undefined,\n password: values.password.trim() || undefined,\n emailVerified: values.emailVerified,\n phoneVerified: values.phoneVerified,\n sendVia: [\n values.viaEmail ? 'email' : null,\n values.viaSms ? 'sms' : null,\n ].filter(Boolean) as InviteUserPayload['sendVia'],\n };\n}\n\nfunction parseCsvLine(line: string) {\n const cells: string[] = [];\n let current = '';\n let quoted = false;\n\n for (let i = 0; i < line.length; i += 1) {\n const char = line[i];\n const next = line[i + 1];\n\n if (char === '\"' && quoted && next === '\"') {\n current += '\"';\n i += 1;\n continue;\n }\n\n if (char === '\"') {\n quoted = !quoted;\n continue;\n }\n\n if (char === ',' && !quoted) {\n cells.push(current.trim());\n current = '';\n continue;\n }\n\n current += char;\n }\n\n cells.push(current.trim());\n return cells;\n}\n\nfunction parseBoolean(value: string | undefined) {\n if (!value) {\n return false;\n }\n\n return ['true', '1', 'yes', 'y'].includes(value.trim().toLowerCase());\n}\n\nfunction parseSendVia(value: string | undefined) {\n if (!value) {\n return [];\n }\n\n return value\n .split('|')\n .map((item) => item.trim().toLowerCase())\n .filter(\n (item): item is NonNullable<InviteUserPayload['sendVia']>[number] =>\n item === 'email' || item === 'sms',\n );\n}\n\nfunction parseBulkInviteCsv(text: string): InviteUserPayload[] {\n const lines = text\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean);\n\n if (!lines.length) {\n throw new Error('Paste at least one CSV row.');\n }\n\n const header = parseCsvLine(lines[0]).map((cell) => cell.toLowerCase());\n const hasHeader = header.includes('fullname');\n const rows = hasHeader ? lines.slice(1) : lines;\n\n if (!rows.length) {\n throw new Error('CSV only has a header row.');\n }\n\n const keys = hasHeader\n ? header\n : [\n 'fullName',\n 'email',\n 'phone',\n 'emailVerified',\n 'phoneVerified',\n 'sendVia',\n 'password',\n ];\n\n return rows.map((line, index) => {\n const values = parseCsvLine(line);\n const record = Object.fromEntries(\n keys.map((key, valueIndex) => [key, values[valueIndex] ?? '']),\n );\n const fullName = String(\n record.fullname || record.fullName || record.name || '',\n ).trim();\n const email = String(record.email || '').trim();\n const phone = String(record.phone || '').trim();\n\n if (!fullName) {\n throw new Error(`Row ${index + 1}: fullName is required.`);\n }\n\n if (!(email || phone)) {\n throw new Error(`Row ${index + 1}: email or phone is required.`);\n }\n\n return {\n fullName,\n email: email || undefined,\n phone: phone || undefined,\n password: String(record.password || '').trim() || undefined,\n emailVerified: parseBoolean(\n String(record.emailverified || record.emailVerified || ''),\n ),\n phoneVerified: parseBoolean(\n String(record.phoneverified || record.phoneVerified || ''),\n ),\n sendVia: parseSendVia(String(record.sendvia || record.sendVia || '')),\n };\n });\n}\n\nfunction downloadInviteTemplate() {\n const blob = new Blob([inviteTemplateCsv], {\n type: 'text/csv;charset=utf-8',\n });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n\n link.href = url;\n link.download = 'users-bulk-invite-template.csv';\n link.click();\n URL.revokeObjectURL(url);\n}\n\nfunction DeliveryBadges({ delivery }: { delivery: InviteResult['delivery'] }) {\n return (\n <div className=\"flex flex-wrap gap-2\">\n {delivery.email ? (\n <Badge\n variant={delivery.email === 'failed' ? 'destructive' : 'outline'}\n >\n email: {delivery.email}\n </Badge>\n ) : null}\n {delivery.sms ? (\n <Badge variant={delivery.sms === 'failed' ? 'destructive' : 'outline'}>\n sms: {delivery.sms}\n </Badge>\n ) : null}\n {delivery.email || delivery.sms ? null : (\n <Badge variant=\"secondary\">no delivery</Badge>\n )}\n </div>\n );\n}\n\nfunction InviteResultCard({\n result,\n index,\n}: {\n result: InviteResult;\n index?: number;\n}) {\n return (\n <Card className=\"border-border/60 bg-background/70\">\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <CardTitle className=\"text-base\">{result.user.fullName}</CardTitle>\n <CardDescription>\n {result.user.email || result.user.phone || 'No identifier'}\n </CardDescription>\n </div>\n <div className=\"flex gap-2\">\n {typeof index === 'number' ? (\n <Badge variant=\"outline\">row {index + 1}</Badge>\n ) : null}\n <Badge variant={result.hasPassword ? 'secondary' : 'default'}>\n {result.hasPassword ? 'password set' : 'set-password flow'}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3 text-sm\">\n <div className=\"flex flex-wrap gap-2\">\n <Badge variant={result.user.emailVerified ? 'default' : 'secondary'}>\n email {result.user.emailVerified ? 'verified' : 'pending'}\n </Badge>\n <Badge variant={result.user.phoneVerified ? 'default' : 'secondary'}>\n phone {result.user.phoneVerified ? 'verified' : 'pending'}\n </Badge>\n </div>\n <DeliveryBadges delivery={result.delivery} />\n {result.inviteUrl ? (\n <p className=\"rounded-md border border-dashed border-border/70 bg-muted/40 px-3 py-2 font-mono text-xs break-all\">\n {result.inviteUrl}\n </p>\n ) : null}\n </CardContent>\n </Card>\n );\n}\n\nexport {\n buildInviteUserPayload,\n defaultInviteUserValues,\n downloadInviteTemplate,\n inviteTemplateCsv,\n InviteResultCard,\n parseBulkInviteCsv,\n};\nexport type { BulkInviteFailure, BulkInviteResponse, InviteResult };\n","'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n Checkbox,\n EntityDrawer,\n EntityFormActions,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n Stack,\n} from '@mesob/ui/components';\nimport { useQueryClient } from '@tanstack/react-query';\nimport type { ComponentProps } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useForm, useWatch } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { authApi$ } from '../../shared/page-helpers';\nimport {\n buildInviteUserPayload,\n defaultInviteUserValues,\n InviteResultCard,\n} from './invite-user-shared';\n\nconst schema = z\n .object({\n fullName: z.string().trim().min(1, 'Full name is required'),\n email: z.string().email('Invalid email').or(z.literal('')),\n phone: z.string(),\n password: z.string(),\n emailVerified: z.boolean(),\n phoneVerified: z.boolean(),\n viaEmail: z.boolean(),\n viaSms: z.boolean(),\n })\n .superRefine((value, ctx) => {\n if (!(value.email.trim() || value.phone.trim())) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['email'],\n message: 'Email or phone is required',\n });\n }\n });\n\ntype FormData = z.infer<typeof schema>;\n\ntype InviteUserFormProps = {\n open: boolean;\n onClose: () => void;\n};\n\nexport function InviteUserForm({ open, onClose }: InviteUserFormProps) {\n const qc = useQueryClient();\n const [result, setResult] = useState<\n ComponentProps<typeof InviteResultCard>['result'] | null\n >(null);\n\n const form = useForm<FormData>({\n resolver: zodResolver(schema),\n defaultValues: defaultInviteUserValues,\n });\n const { control, formState, reset, setValue } = form;\n const email = useWatch({ control, name: 'email' }) ?? '';\n const phone = useWatch({ control, name: 'phone' }) ?? '';\n const hasEmail = email.trim().length > 0;\n const hasPhone = phone.trim().length > 0;\n\n const inviteUser = authApi$.useMutation('post', '/users/invite', {\n onSuccess: async () => {\n await qc.invalidateQueries({ queryKey: ['get', '/users'] });\n },\n });\n\n useEffect(() => {\n if (!hasEmail) {\n setValue('emailVerified', false, { shouldDirty: false });\n setValue('viaEmail', false, { shouldDirty: false });\n }\n }, [hasEmail, setValue]);\n\n useEffect(() => {\n if (!hasPhone) {\n setValue('phoneVerified', false, { shouldDirty: false });\n setValue('viaSms', false, { shouldDirty: false });\n }\n }, [hasPhone, setValue]);\n\n useEffect(() => {\n if (open) {\n return;\n }\n\n reset(defaultInviteUserValues);\n setResult(null);\n }, [open, reset]);\n\n const onSubmit = form.handleSubmit(async (values) => {\n try {\n const inviteResult = await inviteUser.mutateAsync({\n body: buildInviteUserPayload(values),\n });\n\n setResult(inviteResult);\n reset(defaultInviteUserValues);\n toast.success('User invited');\n } catch (error) {\n toast.error(\n error instanceof Error ? error.message : 'Failed to invite user',\n );\n }\n });\n\n return (\n <EntityDrawer\n title=\"Invite user\"\n open={open}\n onClose={onClose}\n isDirty={formState.isDirty}\n size=\"lg\"\n form={\n <Form {...form}>\n <form onSubmit={onSubmit} className=\"space-y-4\">\n <Stack>\n <FormField\n control={control}\n name=\"fullName\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n Full name <span className=\"text-destructive\">*</span>\n </FormLabel>\n <FormControl>\n <Input placeholder=\"Aster Bekele\" {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={control}\n name=\"email\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>Email</FormLabel>\n <FormControl>\n <Input\n type=\"email\"\n placeholder=\"aster@example.com\"\n {...field}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={control}\n name=\"phone\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>Phone</FormLabel>\n <FormControl>\n <Input placeholder=\"+251911223344\" {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={control}\n name=\"password\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>Password</FormLabel>\n <FormControl>\n <Input\n type=\"password\"\n placeholder=\"Optional\"\n {...field}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={control}\n name=\"emailVerified\"\n render={({ field }) => (\n <FormItem>\n <div className=\"flex items-start gap-3\">\n <FormControl>\n <Checkbox\n checked={field.value}\n disabled={!hasEmail}\n onCheckedChange={(checked) =>\n field.onChange(checked === true)\n }\n />\n </FormControl>\n <div className=\"grid gap-1\">\n <FormLabel>Email verified</FormLabel>\n <FormMessage />\n </div>\n </div>\n </FormItem>\n )}\n />\n\n <FormField\n control={control}\n name=\"phoneVerified\"\n render={({ field }) => (\n <FormItem>\n <div className=\"flex items-start gap-3\">\n <FormControl>\n <Checkbox\n checked={field.value}\n disabled={!hasPhone}\n onCheckedChange={(checked) =>\n field.onChange(checked === true)\n }\n />\n </FormControl>\n <div className=\"grid gap-1\">\n <FormLabel>Phone verified</FormLabel>\n <FormMessage />\n </div>\n </div>\n </FormItem>\n )}\n />\n\n <FormField\n control={control}\n name=\"viaEmail\"\n render={({ field }) => (\n <FormItem>\n <div className=\"flex items-start gap-3\">\n <FormControl>\n <Checkbox\n checked={field.value}\n disabled={!hasEmail}\n onCheckedChange={(checked) =>\n field.onChange(checked === true)\n }\n />\n </FormControl>\n <div className=\"grid gap-1\">\n <FormLabel>Send email invite</FormLabel>\n <FormMessage />\n </div>\n </div>\n </FormItem>\n )}\n />\n\n <FormField\n control={control}\n name=\"viaSms\"\n render={({ field }) => (\n <FormItem>\n <div className=\"flex items-start gap-3\">\n <FormControl>\n <Checkbox\n checked={field.value}\n disabled={!hasPhone}\n onCheckedChange={(checked) =>\n field.onChange(checked === true)\n }\n />\n </FormControl>\n <div className=\"grid gap-1\">\n <FormLabel>Send SMS invite</FormLabel>\n <FormMessage />\n </div>\n </div>\n </FormItem>\n )}\n />\n\n {result ? <InviteResultCard result={result} /> : null}\n </Stack>\n </form>\n </Form>\n }\n actions={\n <EntityFormActions\n mode=\"new\"\n onSubmit={onSubmit}\n onReset={() => {\n reset(defaultInviteUserValues);\n setResult(null);\n }}\n isSubmitting={inviteUser.isPending}\n submitLabel=\"Invite\"\n />\n }\n />\n );\n}\n","'use client';\n\nimport {\n Badge,\n DataTableAction,\n DataTablePagination,\n DisplayTable,\n EntityEmptyState,\n EntityLoadingState,\n Tbody,\n Td,\n Th,\n Thead,\n Tr,\n} from '@mesob/ui/components';\nimport { IconCalendar, IconUsers } from '@tabler/icons-react';\nimport { useState } from 'react';\nimport { Link } from '../../shared/page-helpers';\nimport { UserCard } from './user-card';\nimport { UserForm } from './user-form';\nimport type { User } from './users-data';\n\nconst TABLE_COLUMN_COUNT = 4;\n\ntype UsersListProps = {\n data: User[];\n isLoading?: boolean;\n view: 'table' | 'card';\n pageIndex: number;\n pageSize: number;\n pageCount: number;\n totalRows: number;\n onPageChange: (page: number) => void;\n onPageSizeChange: (size: number) => void;\n onCreateNew?: () => void;\n};\n\nexport function UsersList({\n data,\n isLoading,\n view,\n pageIndex,\n pageSize,\n pageCount,\n totalRows,\n onPageChange,\n onPageSizeChange,\n onCreateNew,\n}: UsersListProps) {\n const [editingUserId, setEditingUserId] = useState<string | null>(null);\n\n if (isLoading) {\n return (\n <EntityLoadingState\n view={view}\n rowCount={pageSize}\n columnCount={TABLE_COLUMN_COUNT}\n cardCount={pageSize}\n />\n );\n }\n if (totalRows === 0) {\n return (\n <EntityEmptyState\n icon={IconUsers}\n entityName=\"user\"\n title=\"No users yet\"\n description=\"Invite your first user to get started.\"\n actionLabel=\"Invite user\"\n onAction={onCreateNew}\n />\n );\n }\n if (view === 'table') {\n return (\n <div className=\"space-y-4\">\n {editingUserId && (\n <UserForm\n mode=\"edit\"\n userId={editingUserId}\n open\n onClose={() => setEditingUserId(null)}\n />\n )}\n <DisplayTable withTableBorder>\n <Thead>\n <Tr>\n <Th className=\"w-1/4\">Name</Th>\n <Th className=\"w-1/4\">Contact</Th>\n <Th className=\"w-1/4\">Last sign in</Th>\n <Th className=\"w-[50px]\" />\n </Tr>\n </Thead>\n <Tbody>\n {data.map((user) => (\n <Tr key={user.id} className=\"group\">\n <Td>\n <Link\n href={`/iam/users/${user.id}`}\n className=\"block text-left font-medium hover:text-primary hover:underline cursor-pointer\"\n >\n <p>{user.fullName}</p>\n </Link>\n </Td>\n <Td>\n <div className=\"space-y-1\">\n {user.email && (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm\">{user.email}</span>\n {user.emailVerified && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Verified\n </Badge>\n )}\n </div>\n )}\n {user.phone && (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm\">{user.phone}</span>\n {user.phoneVerified && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Verified\n </Badge>\n )}\n </div>\n )}\n {!(user.email || user.phone) && (\n <span className=\"text-muted-foreground\">—</span>\n )}\n </div>\n </Td>\n <Td>\n <div className=\"flex items-center gap-1 text-muted-foreground\">\n <IconCalendar className=\"h-4 w-4\" />\n {user.lastSignInAt\n ? new Date(user.lastSignInAt).toLocaleDateString()\n : 'Never'}\n </div>\n </Td>\n <Td>\n <DataTableAction onClick={() => setEditingUserId(user.id)} />\n </Td>\n </Tr>\n ))}\n </Tbody>\n </DisplayTable>\n <DataTablePagination\n pageIndex={pageIndex}\n pageSize={pageSize}\n pageCount={pageCount}\n totalRows={totalRows}\n onPageChange={onPageChange}\n onPageSizeChange={onPageSizeChange}\n />\n </div>\n );\n }\n return (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n {data.map((user) => (\n <UserCard key={user.id} user={user} />\n ))}\n </div>\n <DataTablePagination\n pageIndex={pageIndex}\n pageSize={pageSize}\n pageCount={pageCount}\n totalRows={totalRows}\n onPageChange={onPageChange}\n onPageSizeChange={onPageSizeChange}\n />\n </div>\n );\n}\n"],"mappings":"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","names":["IconUsers","useState","Badge","Card","CardContent","CardHeader","CardTitle","jsx","jsxs","Card","CardHeader","CardTitle","Badge","CardContent","zodResolver","EntityDrawer","EntityFormActions","Form","FormControl","FormField","FormItem","FormLabel","FormMessage","Input","useQueryClient","useEffect","useState","useForm","toast","z","jsx","jsxs","schema","z","useQueryClient","useState","useForm","zodResolver","useEffect","toast","EntityDrawer","Form","FormField","FormItem","FormLabel","FormControl","Input","FormMessage","EntityFormActions","Badge","IconUsers","useState","jsx","jsxs","useState","IconUsers","Badge","jsx","jsxs","useState","IconUsers"]}