@open-kingdom/shared-frontend-feature-user-management 0.0.2-14 → 0.0.2-16

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 (42) hide show
  1. package/README.md +136 -4
  2. package/dist/index.d.ts +2 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +293 -167
  5. package/dist/lib/components/invitations/InvitationList.component.d.ts +2 -0
  6. package/dist/lib/components/invitations/InvitationList.component.d.ts.map +1 -0
  7. package/dist/lib/components/invitations/index.d.ts +1 -0
  8. package/dist/lib/components/invitations/index.d.ts.map +1 -1
  9. package/dist/lib/components/shared/StatusBadge.component.d.ts +7 -0
  10. package/dist/lib/components/shared/StatusBadge.component.d.ts.map +1 -0
  11. package/dist/lib/components/users/UserList.component.d.ts.map +1 -1
  12. package/dist/lib/styles.d.ts +1 -0
  13. package/dist/lib/styles.d.ts.map +1 -1
  14. package/dist/lib/types.d.ts +10 -0
  15. package/dist/lib/types.d.ts.map +1 -1
  16. package/package.json +6 -1
  17. package/.babelrc +0 -12
  18. package/jest.config.cts +0 -14
  19. package/src/index.ts +0 -4
  20. package/src/lib/components/invitations/AcceptInvitation.component.spec.tsx +0 -154
  21. package/src/lib/components/invitations/AcceptInvitation.component.tsx +0 -197
  22. package/src/lib/components/invitations/InviteUserModal.component.spec.tsx +0 -79
  23. package/src/lib/components/invitations/InviteUserModal.component.tsx +0 -121
  24. package/src/lib/components/invitations/index.ts +0 -2
  25. package/src/lib/components/shared/ConfirmDialog.component.spec.tsx +0 -45
  26. package/src/lib/components/shared/ConfirmDialog.component.tsx +0 -58
  27. package/src/lib/components/shared/FormField.component.spec.tsx +0 -50
  28. package/src/lib/components/shared/FormField.component.tsx +0 -34
  29. package/src/lib/components/shared/ModalOverlay.component.spec.tsx +0 -81
  30. package/src/lib/components/shared/ModalOverlay.component.tsx +0 -45
  31. package/src/lib/components/shared/RoleBadge.component.spec.tsx +0 -20
  32. package/src/lib/components/shared/RoleBadge.component.tsx +0 -25
  33. package/src/lib/components/shared/StatusCard.component.spec.tsx +0 -44
  34. package/src/lib/components/shared/StatusCard.component.tsx +0 -47
  35. package/src/lib/components/users/UserList.component.spec.tsx +0 -216
  36. package/src/lib/components/users/UserList.component.tsx +0 -153
  37. package/src/lib/styles.ts +0 -19
  38. package/src/lib/types.ts +0 -9
  39. package/tsconfig.json +0 -13
  40. package/tsconfig.lib.json +0 -47
  41. package/tsconfig.spec.json +0 -27
  42. package/vite.config.mts +0 -58
package/dist/index.js CHANGED
@@ -1,25 +1,26 @@
1
- import { jsx as e, jsxs as i } from "react/jsx-runtime";
2
- import { useCallback as P, useState as I, useMemo as V } from "react";
3
- import { useDispatch as U } from "react-redux";
4
- import { useInvitationsControllerInviteMutation as B, useInvitationsControllerValidateQuery as E, useInvitationsControllerAcceptMutation as G, useUsersControllerFindAllQuery as q, useUsersControllerDeleteMutation as z } from "@open-kingdom/shared-frontend-data-access-api-client";
5
- import { showSuccessNotification as F } from "@open-kingdom/shared-frontend-data-access-notifications";
6
- import { DataGrid as Y } from "@open-kingdom/shared-frontend-ui-datagrid";
7
- import { useTheme as O } from "@open-kingdom/shared-frontend-ui-theme";
8
- import { useKeyboardEvent as Q } from "@react-hookz/web";
9
- import { useForm as A } from "react-hook-form";
10
- import { zodResolver as L } from "@hookform/resolvers/zod";
11
- import { z as p } from "zod";
12
- function j({
1
+ import { jsx as e, jsxs as n } from "react/jsx-runtime";
2
+ import { useCallback as L, useState as k, useMemo as P } from "react";
3
+ import { useDispatch as I } from "react-redux";
4
+ import { useInvitationsControllerInviteMutation as O, useInvitationsControllerValidateQuery as Q, useInvitationsControllerAcceptMutation as Y, useInvitationsControllerFindAllQuery as J, useInvitationsControllerCancelMutation as K, useUsersControllerFindAllQuery as H, useUsersControllerDeleteMutation as W } from "@open-kingdom/shared-frontend-data-access-api-client";
5
+ import { showSuccessNotification as D } from "@open-kingdom/shared-frontend-data-access-notifications";
6
+ import { DataGrid as U } from "@open-kingdom/shared-frontend-ui-datagrid";
7
+ import { useTheme as R } from "@open-kingdom/shared-frontend-ui-theme";
8
+ import { useKeyboardEvent as X } from "@react-hookz/web";
9
+ import { useForm as T } from "react-hook-form";
10
+ import { zodResolver as $ } from "@hookform/resolvers/zod";
11
+ import { z as h } from "zod";
12
+ import { formatDate as j } from "@open-kingdom/shared-poly-util-date";
13
+ function M({
13
14
  isOpen: t,
14
15
  onClose: a,
15
16
  ariaLabelledBy: r,
16
- children: s
17
+ children: i
17
18
  }) {
18
- Q("Escape", () => {
19
+ X("Escape", () => {
19
20
  t && a();
20
21
  });
21
- const n = P((l) => {
22
- l?.focus();
22
+ const l = L((s) => {
23
+ s?.focus();
23
24
  }, []);
24
25
  return t ? /* @__PURE__ */ e(
25
26
  "div",
@@ -29,49 +30,49 @@ function j({
29
30
  children: /* @__PURE__ */ e(
30
31
  "div",
31
32
  {
32
- ref: n,
33
+ ref: l,
33
34
  className: "w-full max-w-md rounded-lg bg-white p-6 shadow-xl dark:bg-neutral-800",
34
35
  role: "dialog",
35
36
  "aria-modal": "true",
36
37
  "aria-labelledby": r,
37
38
  tabIndex: -1,
38
- onClick: (l) => l.stopPropagation(),
39
- children: s
39
+ onClick: (s) => s.stopPropagation(),
40
+ children: i
40
41
  }
41
42
  )
42
43
  }
43
44
  ) : null;
44
45
  }
45
- const b = "w-full px-3 py-2 border border-neutral-300 dark:border-neutral-600 rounded-md bg-white dark:bg-neutral-700 text-neutral-900 dark:text-neutral-100", J = "block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-1", k = "max-w-md mx-auto mt-8 p-6 bg-white dark:bg-neutral-800 rounded-lg shadow-lg", S = "text-neutral-600 dark:text-neutral-400", C = "rounded-md px-4 py-2 text-sm font-medium transition-colors", D = `${C} bg-primary-500 text-white hover:bg-primary-600 disabled:opacity-50`, M = `${C} border border-neutral-300 text-neutral-700 hover:bg-neutral-50 dark:border-neutral-600 dark:text-neutral-300 dark:hover:bg-neutral-700`, K = `${C} bg-error-500 text-white hover:bg-error-600 disabled:opacity-50`;
46
- function H({
46
+ const v = "w-full px-3 py-2 border border-neutral-300 dark:border-neutral-600 rounded-md bg-white dark:bg-neutral-700 text-neutral-900 dark:text-neutral-100", Z = "block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-1", C = "max-w-md mx-auto mt-8 p-6 bg-white dark:bg-neutral-800 rounded-lg shadow-lg", S = "text-neutral-600 dark:text-neutral-400", A = "rounded-md px-4 py-2 text-sm font-medium transition-colors", F = `${A} bg-primary-500 text-white hover:bg-primary-600 disabled:opacity-50`, E = `${A} border border-neutral-300 text-neutral-700 hover:bg-neutral-50 dark:border-neutral-600 dark:text-neutral-300 dark:hover:bg-neutral-700`, _ = `${A} bg-error-500 text-white hover:bg-error-600 disabled:opacity-50`, ee = "rounded px-2 py-1 text-xs font-medium text-error-600 transition-colors hover:bg-error-50 disabled:cursor-not-allowed disabled:opacity-40 dark:text-error-400 dark:hover:bg-error-900/20";
47
+ function B({
47
48
  isOpen: t,
48
49
  title: a,
49
50
  message: r,
50
- confirmLabel: s = "Confirm",
51
- onConfirm: n,
52
- onCancel: l,
53
- isLoading: o = !1
51
+ confirmLabel: i = "Confirm",
52
+ onConfirm: l,
53
+ onCancel: s,
54
+ isLoading: c = !1
54
55
  }) {
55
- const d = "confirm-dialog-title";
56
- return /* @__PURE__ */ i(j, { isOpen: t, onClose: l, ariaLabelledBy: d, children: [
56
+ const u = "confirm-dialog-title";
57
+ return /* @__PURE__ */ n(M, { isOpen: t, onClose: s, ariaLabelledBy: u, children: [
57
58
  /* @__PURE__ */ e(
58
59
  "h3",
59
60
  {
60
- id: d,
61
+ id: u,
61
62
  className: "text-lg font-semibold text-neutral-900 dark:text-neutral-100",
62
63
  children: a
63
64
  }
64
65
  ),
65
66
  /* @__PURE__ */ e("p", { className: "mt-2 text-sm text-neutral-600 dark:text-neutral-400", children: r }),
66
- /* @__PURE__ */ i("div", { className: "mt-6 flex justify-end gap-3", children: [
67
+ /* @__PURE__ */ n("div", { className: "mt-6 flex justify-end gap-3", children: [
67
68
  /* @__PURE__ */ e(
68
69
  "button",
69
70
  {
70
71
  type: "button",
71
72
  "data-testid": "confirm-cancel-btn",
72
- onClick: l,
73
- disabled: o,
74
- className: M,
73
+ onClick: s,
74
+ disabled: c,
75
+ className: E,
75
76
  children: "Cancel"
76
77
  }
77
78
  ),
@@ -80,99 +81,99 @@ function H({
80
81
  {
81
82
  type: "button",
82
83
  "data-testid": "confirm-btn",
83
- onClick: n,
84
- disabled: o,
85
- className: K,
86
- children: s
84
+ onClick: l,
85
+ disabled: c,
86
+ className: _,
87
+ children: i
87
88
  }
88
89
  )
89
90
  ] })
90
91
  ] });
91
92
  }
92
- const W = {
93
+ const te = {
93
94
  admin: "bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-300",
94
95
  user: "bg-primary-100 text-primary-800 dark:bg-primary-900/30 dark:text-primary-300",
95
96
  guest: "bg-neutral-100 text-neutral-700 dark:bg-neutral-700 dark:text-neutral-300"
96
97
  };
97
- function X({ role: t }) {
98
+ function G({ role: t }) {
98
99
  if (!t) return null;
99
100
  const a = t.charAt(0).toUpperCase() + t.slice(1);
100
101
  return /* @__PURE__ */ e(
101
102
  "span",
102
103
  {
103
- className: `inline-block rounded-full px-2.5 py-0.5 text-xs font-medium ${W[t]}`,
104
+ className: `inline-block rounded-full px-2.5 py-0.5 text-xs font-medium ${te[t]}`,
104
105
  children: a
105
106
  }
106
107
  );
107
108
  }
108
- function x({
109
+ function y({
109
110
  label: t,
110
111
  htmlFor: a,
111
112
  required: r,
112
- error: s,
113
- children: n
113
+ error: i,
114
+ children: l
114
115
  }) {
115
- return /* @__PURE__ */ i("div", { children: [
116
- /* @__PURE__ */ i("label", { htmlFor: a, className: J, children: [
116
+ return /* @__PURE__ */ n("div", { children: [
117
+ /* @__PURE__ */ n("label", { htmlFor: a, className: Z, children: [
117
118
  t,
118
119
  " ",
119
120
  r && /* @__PURE__ */ e("span", { className: "text-error-500", children: "*" })
120
121
  ] }),
121
- n,
122
- s && /* @__PURE__ */ e(
122
+ l,
123
+ i && /* @__PURE__ */ e(
123
124
  "p",
124
125
  {
125
126
  "data-testid": "field-error",
126
127
  className: "mt-1 text-sm text-error-600 dark:text-error-400",
127
- children: s
128
+ children: i
128
129
  }
129
130
  )
130
131
  ] });
131
132
  }
132
- const Z = p.object({
133
- email: p.string().email("Invalid email address"),
134
- role: p.enum(["guest", "user", "admin"])
133
+ const ae = h.object({
134
+ email: h.string().email("Invalid email address"),
135
+ role: h.enum(["guest", "user", "admin"])
135
136
  });
136
- function _({ isOpen: t, onClose: a }) {
137
- const r = U(), [s, { isLoading: n }] = B(), {
138
- register: l,
139
- handleSubmit: o,
140
- reset: d,
141
- formState: { errors: c }
142
- } = A({
143
- resolver: L(Z),
137
+ function re({ isOpen: t, onClose: a }) {
138
+ const r = I(), [i, { isLoading: l }] = O(), {
139
+ register: s,
140
+ handleSubmit: c,
141
+ reset: u,
142
+ formState: { errors: o }
143
+ } = T({
144
+ resolver: $(ae),
144
145
  defaultValues: { email: "", role: "guest" }
145
- }), h = "invite-modal-title", f = () => {
146
- d(), a();
146
+ }), d = "invite-modal-title", m = () => {
147
+ u(), a();
147
148
  };
148
- return /* @__PURE__ */ i(
149
- j,
149
+ return /* @__PURE__ */ n(
150
+ M,
150
151
  {
151
152
  isOpen: t,
152
- onClose: f,
153
- ariaLabelledBy: h,
153
+ onClose: m,
154
+ ariaLabelledBy: d,
154
155
  children: [
155
156
  /* @__PURE__ */ e(
156
157
  "h3",
157
158
  {
158
- id: h,
159
+ id: d,
159
160
  className: "text-lg font-semibold text-neutral-900 dark:text-neutral-100",
160
161
  children: "Invite User"
161
162
  }
162
163
  ),
163
- /* @__PURE__ */ i("form", { onSubmit: o(async (m) => {
164
+ /* @__PURE__ */ n("form", { onSubmit: c(async (f) => {
164
165
  try {
165
- await s({ inviteUserDto: m }).unwrap(), r(F("Invitation sent successfully")), d(), a();
166
+ await i({ inviteUserDto: f }).unwrap(), r(D("Invitation sent successfully")), u(), a();
166
167
  } catch {
167
168
  }
168
169
  }), className: "mt-4 space-y-4", children: [
169
170
  /* @__PURE__ */ e(
170
- x,
171
+ y,
171
172
  {
172
173
  label: "Email",
173
174
  htmlFor: "invite-email",
174
175
  required: !0,
175
- error: c.email?.message,
176
+ error: o.email?.message,
176
177
  children: /* @__PURE__ */ e(
177
178
  "input",
178
179
  {
@@ -180,19 +181,19 @@ function _({ isOpen: t, onClose: a }) {
180
181
  "data-testid": "invite-email-input",
181
182
  type: "email",
182
183
  placeholder: "user@example.com",
183
- className: b,
184
- ...l("email")
184
+ className: v,
185
+ ...s("email")
185
186
  }
186
187
  )
187
188
  }
188
189
  ),
189
- /* @__PURE__ */ e(x, { label: "Role", htmlFor: "invite-role", children: /* @__PURE__ */ i(
190
+ /* @__PURE__ */ e(y, { label: "Role", htmlFor: "invite-role", children: /* @__PURE__ */ n(
190
191
  "select",
191
192
  {
192
193
  id: "invite-role",
193
194
  "data-testid": "invite-role-select",
194
- className: b,
195
- ...l("role"),
195
+ className: v,
196
+ ...s("role"),
196
197
  children: [
197
198
  /* @__PURE__ */ e("option", { value: "guest", children: "Guest" }),
198
199
  /* @__PURE__ */ e("option", { value: "user", children: "User" }),
@@ -200,15 +201,15 @@ function _({ isOpen: t, onClose: a }) {
200
201
  ]
201
202
  }
202
203
  ) }),
203
- /* @__PURE__ */ i("div", { className: "flex justify-end gap-3", children: [
204
+ /* @__PURE__ */ n("div", { className: "flex justify-end gap-3", children: [
204
205
  /* @__PURE__ */ e(
205
206
  "button",
206
207
  {
207
208
  type: "button",
208
209
  "data-testid": "invite-cancel-btn",
209
- onClick: f,
210
- disabled: n,
211
- className: M,
210
+ onClick: m,
211
+ disabled: l,
212
+ className: E,
212
213
  children: "Cancel"
213
214
  }
214
215
  ),
@@ -217,9 +218,9 @@ function _({ isOpen: t, onClose: a }) {
217
218
  {
218
219
  type: "submit",
219
220
  "data-testid": "invite-submit-btn",
220
- disabled: n,
221
- className: D,
222
- children: n ? "Sending..." : "Send Invitation"
221
+ disabled: l,
222
+ className: F,
223
+ children: l ? "Sending..." : "Send Invitation"
223
224
  }
224
225
  )
225
226
  ] })
@@ -228,7 +229,7 @@ function _({ isOpen: t, onClose: a }) {
228
229
  }
229
230
  );
230
231
  }
231
- const ee = {
232
+ const ne = {
232
233
  error: "text-xl font-bold text-error-700 dark:text-error-400",
233
234
  success: "text-xl font-bold text-success-700 dark:text-success-400"
234
235
  };
@@ -236,61 +237,61 @@ function w({
236
237
  variant: t,
237
238
  title: a,
238
239
  message: r,
239
- children: s
240
+ children: i
240
241
  }) {
241
- return t === "loading" ? /* @__PURE__ */ e("div", { className: k, children: /* @__PURE__ */ e("p", { className: `text-center ${S}`, children: r }) }) : /* @__PURE__ */ i(
242
+ return t === "loading" ? /* @__PURE__ */ e("div", { className: C, children: /* @__PURE__ */ e("p", { className: `text-center ${S}`, children: r }) }) : /* @__PURE__ */ n(
242
243
  "div",
243
244
  {
244
- className: k,
245
+ className: C,
245
246
  role: t === "error" ? "alert" : void 0,
246
247
  children: [
247
- a && /* @__PURE__ */ e("h2", { "data-testid": "status-card-title", className: ee[t], children: a }),
248
+ a && /* @__PURE__ */ e("h2", { "data-testid": "status-card-title", className: ne[t], children: a }),
248
249
  /* @__PURE__ */ e("p", { "data-testid": "status-card-message", className: `mt-2 ${S}`, children: r }),
249
- s
250
+ i
250
251
  ]
251
252
  }
252
253
  );
253
254
  }
254
- const te = p.object({
255
- firstName: p.string().optional(),
256
- lastName: p.string().optional(),
257
- password: p.string().min(8, "Password must be at least 8 characters"),
258
- confirmPassword: p.string()
255
+ const ie = h.object({
256
+ firstName: h.string().optional(),
257
+ lastName: h.string().optional(),
258
+ password: h.string().min(8, "Password must be at least 8 characters"),
259
+ confirmPassword: h.string()
259
260
  }).refine((t) => t.password === t.confirmPassword, {
260
261
  message: "Passwords do not match",
261
262
  path: ["confirmPassword"]
262
263
  });
263
- function pe({ token: t, loginPath: a }) {
264
+ function Ae({ token: t, loginPath: a }) {
264
265
  const {
265
266
  data: r,
266
- isLoading: s,
267
- error: n
268
- } = E({ token: t }), [l, { isLoading: o, isSuccess: d }] = G(), {
269
- register: c,
270
- handleSubmit: h,
271
- formState: { errors: f }
272
- } = A({
273
- resolver: L(te),
267
+ isLoading: i,
268
+ error: l
269
+ } = Q({ token: t }), [s, { isLoading: c, isSuccess: u }] = Y(), {
270
+ register: o,
271
+ handleSubmit: d,
272
+ formState: { errors: m }
273
+ } = T({
274
+ resolver: $(ie),
274
275
  defaultValues: {
275
276
  firstName: "",
276
277
  lastName: "",
277
278
  password: "",
278
279
  confirmPassword: ""
279
280
  }
280
- }), g = r?.email ?? "", m = r?.role ?? "user", v = async (y) => {
281
+ }), b = r?.email ?? "", f = r?.role ?? "user", x = async (g) => {
281
282
  try {
282
- await l({
283
+ await s({
283
284
  acceptInvitationDto: {
284
285
  token: t,
285
- password: y.password,
286
- firstName: y.firstName || void 0,
287
- lastName: y.lastName || void 0
286
+ password: g.password,
287
+ firstName: g.firstName || void 0,
288
+ lastName: g.lastName || void 0
288
289
  }
289
290
  }).unwrap();
290
291
  } catch {
291
292
  }
292
293
  };
293
- return d ? /* @__PURE__ */ e(
294
+ return u ? /* @__PURE__ */ e(
294
295
  w,
295
296
  {
296
297
  variant: "success",
@@ -306,14 +307,14 @@ function pe({ token: t, loginPath: a }) {
306
307
  }
307
308
  )
308
309
  }
309
- ) : s ? /* @__PURE__ */ e(w, { variant: "loading", message: "Validating invitation..." }) : n ? /* @__PURE__ */ e(
310
+ ) : i ? /* @__PURE__ */ e(w, { variant: "loading", message: "Validating invitation..." }) : l ? /* @__PURE__ */ e(
310
311
  w,
311
312
  {
312
313
  variant: "error",
313
314
  title: "Validation Failed",
314
315
  message: "Unable to validate this invitation. Please check your connection and try again."
315
316
  }
316
- ) : r?.valid ? /* @__PURE__ */ i("div", { className: k, children: [
317
+ ) : r?.valid ? /* @__PURE__ */ n("div", { className: C, children: [
317
318
  /* @__PURE__ */ e(
318
319
  "h2",
319
320
  {
@@ -322,43 +323,43 @@ function pe({ token: t, loginPath: a }) {
322
323
  children: "Accept Invitation"
323
324
  }
324
325
  ),
325
- /* @__PURE__ */ i("p", { className: `mt-1 text-sm ${S}`, children: [
326
+ /* @__PURE__ */ n("p", { className: `mt-1 text-sm ${S}`, children: [
326
327
  "You've been invited as ",
327
- /* @__PURE__ */ e("strong", { "data-testid": "accept-role", children: m }),
328
+ /* @__PURE__ */ e("strong", { "data-testid": "accept-role", children: f }),
328
329
  " ",
329
330
  "with email ",
330
- /* @__PURE__ */ e("strong", { "data-testid": "accept-email", children: g })
331
+ /* @__PURE__ */ e("strong", { "data-testid": "accept-email", children: b })
331
332
  ] }),
332
- /* @__PURE__ */ i("form", { onSubmit: h(v), className: "mt-4 space-y-4", children: [
333
- /* @__PURE__ */ e(x, { label: "First Name", htmlFor: "accept-firstName", children: /* @__PURE__ */ e(
333
+ /* @__PURE__ */ n("form", { onSubmit: d(x), className: "mt-4 space-y-4", children: [
334
+ /* @__PURE__ */ e(y, { label: "First Name", htmlFor: "accept-firstName", children: /* @__PURE__ */ e(
334
335
  "input",
335
336
  {
336
337
  id: "accept-firstName",
337
338
  "data-testid": "accept-first-name-input",
338
339
  type: "text",
339
340
  placeholder: "John",
340
- className: b,
341
- ...c("firstName")
341
+ className: v,
342
+ ...o("firstName")
342
343
  }
343
344
  ) }),
344
- /* @__PURE__ */ e(x, { label: "Last Name", htmlFor: "accept-lastName", children: /* @__PURE__ */ e(
345
+ /* @__PURE__ */ e(y, { label: "Last Name", htmlFor: "accept-lastName", children: /* @__PURE__ */ e(
345
346
  "input",
346
347
  {
347
348
  id: "accept-lastName",
348
349
  "data-testid": "accept-last-name-input",
349
350
  type: "text",
350
351
  placeholder: "Doe",
351
- className: b,
352
- ...c("lastName")
352
+ className: v,
353
+ ...o("lastName")
353
354
  }
354
355
  ) }),
355
356
  /* @__PURE__ */ e(
356
- x,
357
+ y,
357
358
  {
358
359
  label: "Password",
359
360
  htmlFor: "accept-password",
360
361
  required: !0,
361
- error: f.password?.message,
362
+ error: m.password?.message,
362
363
  children: /* @__PURE__ */ e(
363
364
  "input",
364
365
  {
@@ -366,19 +367,19 @@ function pe({ token: t, loginPath: a }) {
366
367
  "data-testid": "accept-password-input",
367
368
  type: "password",
368
369
  placeholder: "Min. 8 characters",
369
- className: b,
370
- ...c("password")
370
+ className: v,
371
+ ...o("password")
371
372
  }
372
373
  )
373
374
  }
374
375
  ),
375
376
  /* @__PURE__ */ e(
376
- x,
377
+ y,
377
378
  {
378
379
  label: "Confirm Password",
379
380
  htmlFor: "accept-confirmPassword",
380
381
  required: !0,
381
- error: f.confirmPassword?.message,
382
+ error: m.confirmPassword?.message,
382
383
  children: /* @__PURE__ */ e(
383
384
  "input",
384
385
  {
@@ -386,8 +387,8 @@ function pe({ token: t, loginPath: a }) {
386
387
  "data-testid": "accept-confirm-password-input",
387
388
  type: "password",
388
389
  placeholder: "Repeat password",
389
- className: b,
390
- ...c("confirmPassword")
390
+ className: v,
391
+ ...o("confirmPassword")
391
392
  }
392
393
  )
393
394
  }
@@ -397,9 +398,9 @@ function pe({ token: t, loginPath: a }) {
397
398
  {
398
399
  type: "submit",
399
400
  "data-testid": "accept-submit-btn",
400
- disabled: o,
401
- className: `w-full ${D}`,
402
- children: o ? "Creating account..." : "Create Account"
401
+ disabled: c,
402
+ className: `w-full ${F}`,
403
+ children: c ? "Creating account..." : "Create Account"
403
404
  }
404
405
  )
405
406
  ] })
@@ -412,44 +413,168 @@ function pe({ token: t, loginPath: a }) {
412
413
  }
413
414
  );
414
415
  }
415
- function he({ currentUserId: t }) {
416
- const a = U(), { theme: r, mode: s } = O(), { data: n, isLoading: l, error: o, refetch: d } = q(), [c, { isLoading: h }] = z(), [f, g] = I(!1), [m, v] = I(null), y = n ?? [], $ = P(async () => {
417
- if (m)
416
+ const le = {
417
+ pending: "bg-warning-100 text-warning-800 dark:bg-warning-900/30 dark:text-warning-300",
418
+ accepted: "bg-success-100 text-success-800 dark:bg-success-900/30 dark:text-success-300",
419
+ expired: "bg-neutral-100 text-neutral-700 dark:bg-neutral-700 dark:text-neutral-300"
420
+ };
421
+ function se({ status: t }) {
422
+ if (!t) return null;
423
+ const a = t.charAt(0).toUpperCase() + t.slice(1);
424
+ return /* @__PURE__ */ e(
425
+ "span",
426
+ {
427
+ className: `inline-block rounded-full px-2.5 py-0.5 text-xs font-medium ${le[t]}`,
428
+ children: a
429
+ }
430
+ );
431
+ }
432
+ const oe = {
433
+ field: "email",
434
+ headerName: "Email",
435
+ flex: 2
436
+ }, de = {
437
+ field: "role",
438
+ headerName: "Role",
439
+ flex: 1,
440
+ cellRenderer: (t) => t.data ? /* @__PURE__ */ e(G, { role: t.data.role }) : null
441
+ }, ce = {
442
+ field: "status",
443
+ headerName: "Status",
444
+ flex: 1,
445
+ cellRenderer: (t) => t.data ? /* @__PURE__ */ e(se, { status: t.data.status }) : null
446
+ }, ue = {
447
+ headerName: "Invited",
448
+ flex: 1,
449
+ valueGetter: (t) => j(t.data?.invitedAt)
450
+ }, me = {
451
+ headerName: "Expires",
452
+ flex: 1,
453
+ valueGetter: (t) => j(t.data?.tokenExpiry)
454
+ };
455
+ function fe(t) {
456
+ return {
457
+ headerName: "Actions",
458
+ flex: 1,
459
+ sortable: !1,
460
+ filter: !1,
461
+ cellRenderer: (a) => a.data ? /* @__PURE__ */ e(
462
+ "button",
463
+ {
464
+ onClick: () => a.data && t(a.data),
465
+ className: ee,
466
+ children: "Cancel"
467
+ }
468
+ ) : null
469
+ };
470
+ }
471
+ const pe = [
472
+ oe,
473
+ de,
474
+ ce,
475
+ ue,
476
+ me
477
+ ];
478
+ function he(t) {
479
+ return [...pe, fe(t)];
480
+ }
481
+ function Fe() {
482
+ const t = I(), { theme: a, mode: r } = R(), { data: i, isLoading: l, error: s, refetch: c } = J(), [u, { isLoading: o }] = K(), [d, m] = k(null), b = i ?? [];
483
+ async function f() {
484
+ if (!d) return;
485
+ "error" in await u({ id: d.id }) || t(D("Invitation cancelled successfully")), m(null);
486
+ }
487
+ const x = P(() => he(m), []);
488
+ return s ? /* @__PURE__ */ n(
489
+ "div",
490
+ {
491
+ "data-testid": "invitations-error",
492
+ className: "rounded-lg bg-error-50 p-6 text-center dark:bg-error-900/20",
493
+ role: "alert",
494
+ children: [
495
+ /* @__PURE__ */ e("p", { className: "text-error-700 dark:text-error-300", children: "Failed to load invitations." }),
496
+ /* @__PURE__ */ e(
497
+ "button",
498
+ {
499
+ "data-testid": "invitations-retry-btn",
500
+ onClick: c,
501
+ className: "mt-2 text-sm font-medium text-primary-600 hover:underline dark:text-primary-400",
502
+ children: "Try again"
503
+ }
504
+ )
505
+ ]
506
+ }
507
+ ) : /* @__PURE__ */ n("div", { children: [
508
+ /* @__PURE__ */ e("div", { className: "mb-4 flex items-center justify-between", children: /* @__PURE__ */ e(
509
+ "h2",
510
+ {
511
+ "data-testid": "invitations-heading",
512
+ className: "text-xl font-semibold text-neutral-900 dark:text-neutral-100",
513
+ children: "Invitations"
514
+ }
515
+ ) }),
516
+ /* @__PURE__ */ e(
517
+ U,
518
+ {
519
+ rowData: b,
520
+ columnDefs: x,
521
+ mode: r,
522
+ theme: a,
523
+ loading: l
524
+ }
525
+ ),
526
+ /* @__PURE__ */ e(
527
+ B,
528
+ {
529
+ isOpen: !!d,
530
+ title: "Cancel Invitation",
531
+ message: `Are you sure you want to cancel the invitation for ${d?.email}? This action cannot be undone.`,
532
+ confirmLabel: o ? "Cancelling..." : "Cancel Invitation",
533
+ onConfirm: f,
534
+ onCancel: () => m(null),
535
+ isLoading: o
536
+ }
537
+ )
538
+ ] });
539
+ }
540
+ function Le({ currentUserId: t }) {
541
+ const a = I(), { theme: r, mode: i } = R(), { data: l, isLoading: s, error: c, refetch: u } = H(), [o, { isLoading: d }] = W(), [m, b] = k(!1), [f, x] = k(null), g = l ?? [], V = L(async () => {
542
+ if (f)
418
543
  try {
419
- await c({ id: m.id }).unwrap(), a(F("User deleted successfully"));
544
+ await o({ id: f.id }).unwrap(), a(D("User deleted successfully"));
420
545
  } catch {
421
546
  } finally {
422
- v(null);
547
+ x(null);
423
548
  }
424
- }, [m, c, a]), R = V(
549
+ }, [f, o, a]), q = P(
425
550
  () => [
426
551
  { field: "email", headerName: "Email", flex: 2 },
427
552
  {
428
553
  headerName: "Name",
429
554
  flex: 2,
430
- valueGetter: (u) => {
431
- const { firstName: N, lastName: T } = u.data ?? {};
432
- return [N, T].filter(Boolean).join(" ") || "—";
555
+ valueGetter: (p) => {
556
+ const { firstName: N, lastName: z } = p.data ?? {};
557
+ return [N, z].filter(Boolean).join(" ") || "—";
433
558
  }
434
559
  },
435
560
  {
436
561
  field: "role",
437
562
  headerName: "Role",
438
563
  flex: 1,
439
- cellRenderer: (u) => u.data ? /* @__PURE__ */ e(X, { role: u.data.role }) : null
564
+ cellRenderer: (p) => p.data ? /* @__PURE__ */ e(G, { role: p.data.role }) : null
440
565
  },
441
566
  {
442
567
  headerName: "Actions",
443
568
  flex: 1,
444
569
  sortable: !1,
445
570
  filter: !1,
446
- cellRenderer: (u) => {
447
- if (!u.data) return null;
448
- const N = u.data.id === t;
571
+ cellRenderer: (p) => {
572
+ if (!p.data) return null;
573
+ const N = p.data.id === t;
449
574
  return /* @__PURE__ */ e(
450
575
  "button",
451
576
  {
452
- onClick: () => u.data && v(u.data),
577
+ onClick: () => p.data && x(p.data),
453
578
  disabled: N,
454
579
  title: N ? "Cannot delete your own account" : "Delete user",
455
580
  className: "rounded px-2 py-1 text-xs font-medium text-error-600 transition-colors hover:bg-error-50 disabled:cursor-not-allowed disabled:opacity-40 dark:text-error-400 dark:hover:bg-error-900/20",
@@ -461,7 +586,7 @@ function he({ currentUserId: t }) {
461
586
  ],
462
587
  [t]
463
588
  );
464
- return o ? /* @__PURE__ */ i(
589
+ return c ? /* @__PURE__ */ n(
465
590
  "div",
466
591
  {
467
592
  "data-testid": "users-error",
@@ -473,15 +598,15 @@ function he({ currentUserId: t }) {
473
598
  "button",
474
599
  {
475
600
  "data-testid": "users-retry-btn",
476
- onClick: d,
601
+ onClick: u,
477
602
  className: "mt-2 text-sm font-medium text-primary-600 hover:underline dark:text-primary-400",
478
603
  children: "Try again"
479
604
  }
480
605
  )
481
606
  ]
482
607
  }
483
- ) : /* @__PURE__ */ i("div", { children: [
484
- /* @__PURE__ */ i("div", { className: "mb-4 flex items-center justify-between", children: [
608
+ ) : /* @__PURE__ */ n("div", { children: [
609
+ /* @__PURE__ */ n("div", { className: "mb-4 flex items-center justify-between", children: [
485
610
  /* @__PURE__ */ e(
486
611
  "h2",
487
612
  {
@@ -494,45 +619,46 @@ function he({ currentUserId: t }) {
494
619
  "button",
495
620
  {
496
621
  "data-testid": "invite-user-btn",
497
- onClick: () => g(!0),
498
- className: D,
622
+ onClick: () => b(!0),
623
+ className: F,
499
624
  children: "Invite User"
500
625
  }
501
626
  )
502
627
  ] }),
503
628
  /* @__PURE__ */ e(
504
- Y,
629
+ U,
505
630
  {
506
- rowData: y,
507
- columnDefs: R,
508
- mode: s,
631
+ rowData: g,
632
+ columnDefs: q,
633
+ mode: i,
509
634
  theme: r,
510
- loading: l
635
+ loading: s
511
636
  }
512
637
  ),
513
638
  /* @__PURE__ */ e(
514
- _,
639
+ re,
515
640
  {
516
- isOpen: f,
517
- onClose: () => g(!1)
641
+ isOpen: m,
642
+ onClose: () => b(!1)
518
643
  }
519
644
  ),
520
645
  /* @__PURE__ */ e(
521
- H,
646
+ B,
522
647
  {
523
- isOpen: !!m,
648
+ isOpen: !!f,
524
649
  title: "Delete User",
525
- message: `Are you sure you want to delete ${m?.email}? This action cannot be undone.`,
526
- confirmLabel: h ? "Deleting..." : "Delete",
527
- onConfirm: $,
528
- onCancel: () => v(null),
529
- isLoading: h
650
+ message: `Are you sure you want to delete ${f?.email}? This action cannot be undone.`,
651
+ confirmLabel: d ? "Deleting..." : "Delete",
652
+ onConfirm: V,
653
+ onCancel: () => x(null),
654
+ isLoading: d
530
655
  }
531
656
  )
532
657
  ] });
533
658
  }
534
659
  export {
535
- pe as AcceptInvitation,
660
+ Ae as AcceptInvitation,
661
+ Fe as InvitationList,
536
662
  w as StatusCard,
537
- he as UserList
663
+ Le as UserList
538
664
  };