@open-kingdom/shared-frontend-feature-user-management 0.0.2-13 → 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.
- package/README.md +136 -4
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +293 -167
- package/dist/lib/components/invitations/InvitationList.component.d.ts +2 -0
- package/dist/lib/components/invitations/InvitationList.component.d.ts.map +1 -0
- package/dist/lib/components/invitations/index.d.ts +1 -0
- package/dist/lib/components/invitations/index.d.ts.map +1 -1
- package/dist/lib/components/shared/StatusBadge.component.d.ts +7 -0
- package/dist/lib/components/shared/StatusBadge.component.d.ts.map +1 -0
- package/dist/lib/components/users/UserList.component.d.ts.map +1 -1
- package/dist/lib/styles.d.ts +1 -0
- package/dist/lib/styles.d.ts.map +1 -1
- package/dist/lib/types.d.ts +10 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/package.json +6 -1
- package/.babelrc +0 -12
- package/jest.config.cts +0 -14
- package/src/index.ts +0 -4
- package/src/lib/components/invitations/AcceptInvitation.component.spec.tsx +0 -154
- package/src/lib/components/invitations/AcceptInvitation.component.tsx +0 -197
- package/src/lib/components/invitations/InviteUserModal.component.spec.tsx +0 -79
- package/src/lib/components/invitations/InviteUserModal.component.tsx +0 -121
- package/src/lib/components/invitations/index.ts +0 -2
- package/src/lib/components/shared/ConfirmDialog.component.spec.tsx +0 -45
- package/src/lib/components/shared/ConfirmDialog.component.tsx +0 -58
- package/src/lib/components/shared/FormField.component.spec.tsx +0 -50
- package/src/lib/components/shared/FormField.component.tsx +0 -34
- package/src/lib/components/shared/ModalOverlay.component.spec.tsx +0 -81
- package/src/lib/components/shared/ModalOverlay.component.tsx +0 -45
- package/src/lib/components/shared/RoleBadge.component.spec.tsx +0 -20
- package/src/lib/components/shared/RoleBadge.component.tsx +0 -25
- package/src/lib/components/shared/StatusCard.component.spec.tsx +0 -44
- package/src/lib/components/shared/StatusCard.component.tsx +0 -47
- package/src/lib/components/users/UserList.component.spec.tsx +0 -216
- package/src/lib/components/users/UserList.component.tsx +0 -153
- package/src/lib/styles.ts +0 -19
- package/src/lib/types.ts +0 -9
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -47
- package/tsconfig.spec.json +0 -27
- package/vite.config.mts +0 -58
package/dist/index.js
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
import { jsx as e, jsxs as
|
|
2
|
-
import { useCallback as
|
|
3
|
-
import { useDispatch as
|
|
4
|
-
import { useInvitationsControllerInviteMutation as
|
|
5
|
-
import { showSuccessNotification as
|
|
6
|
-
import { DataGrid as
|
|
7
|
-
import { useTheme as
|
|
8
|
-
import { useKeyboardEvent as
|
|
9
|
-
import { useForm as
|
|
10
|
-
import { zodResolver as
|
|
11
|
-
import { z as
|
|
12
|
-
|
|
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:
|
|
17
|
+
children: i
|
|
17
18
|
}) {
|
|
18
|
-
|
|
19
|
+
X("Escape", () => {
|
|
19
20
|
t && a();
|
|
20
21
|
});
|
|
21
|
-
const
|
|
22
|
-
|
|
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:
|
|
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: (
|
|
39
|
-
children:
|
|
39
|
+
onClick: (s) => s.stopPropagation(),
|
|
40
|
+
children: i
|
|
40
41
|
}
|
|
41
42
|
)
|
|
42
43
|
}
|
|
43
44
|
) : null;
|
|
44
45
|
}
|
|
45
|
-
const
|
|
46
|
-
function
|
|
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:
|
|
51
|
-
onConfirm:
|
|
52
|
-
onCancel:
|
|
53
|
-
isLoading:
|
|
51
|
+
confirmLabel: i = "Confirm",
|
|
52
|
+
onConfirm: l,
|
|
53
|
+
onCancel: s,
|
|
54
|
+
isLoading: c = !1
|
|
54
55
|
}) {
|
|
55
|
-
const
|
|
56
|
-
return /* @__PURE__ */
|
|
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:
|
|
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__ */
|
|
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:
|
|
73
|
-
disabled:
|
|
74
|
-
className:
|
|
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:
|
|
84
|
-
disabled:
|
|
85
|
-
className:
|
|
86
|
-
children:
|
|
84
|
+
onClick: l,
|
|
85
|
+
disabled: c,
|
|
86
|
+
className: _,
|
|
87
|
+
children: i
|
|
87
88
|
}
|
|
88
89
|
)
|
|
89
90
|
] })
|
|
90
91
|
] });
|
|
91
92
|
}
|
|
92
|
-
const
|
|
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
|
|
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 ${
|
|
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
|
|
109
|
+
function y({
|
|
109
110
|
label: t,
|
|
110
111
|
htmlFor: a,
|
|
111
112
|
required: r,
|
|
112
|
-
error:
|
|
113
|
-
children:
|
|
113
|
+
error: i,
|
|
114
|
+
children: l
|
|
114
115
|
}) {
|
|
115
|
-
return /* @__PURE__ */
|
|
116
|
-
/* @__PURE__ */
|
|
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
|
-
|
|
122
|
-
|
|
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:
|
|
128
|
+
children: i
|
|
128
129
|
}
|
|
129
130
|
)
|
|
130
131
|
] });
|
|
131
132
|
}
|
|
132
|
-
const
|
|
133
|
-
email:
|
|
134
|
-
role:
|
|
133
|
+
const ae = h.object({
|
|
134
|
+
email: h.string().email("Invalid email address"),
|
|
135
|
+
role: h.enum(["guest", "user", "admin"])
|
|
135
136
|
});
|
|
136
|
-
function
|
|
137
|
-
const r =
|
|
138
|
-
register:
|
|
139
|
-
handleSubmit:
|
|
140
|
-
reset:
|
|
141
|
-
formState: { errors:
|
|
142
|
-
} =
|
|
143
|
-
resolver:
|
|
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
|
-
}),
|
|
146
|
-
|
|
146
|
+
}), d = "invite-modal-title", m = () => {
|
|
147
|
+
u(), a();
|
|
147
148
|
};
|
|
148
|
-
return /* @__PURE__ */
|
|
149
|
-
|
|
149
|
+
return /* @__PURE__ */ n(
|
|
150
|
+
M,
|
|
150
151
|
{
|
|
151
152
|
isOpen: t,
|
|
152
|
-
onClose:
|
|
153
|
-
ariaLabelledBy:
|
|
153
|
+
onClose: m,
|
|
154
|
+
ariaLabelledBy: d,
|
|
154
155
|
children: [
|
|
155
156
|
/* @__PURE__ */ e(
|
|
156
157
|
"h3",
|
|
157
158
|
{
|
|
158
|
-
id:
|
|
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__ */
|
|
164
|
+
/* @__PURE__ */ n("form", { onSubmit: c(async (f) => {
|
|
164
165
|
try {
|
|
165
|
-
await
|
|
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
|
-
|
|
171
|
+
y,
|
|
171
172
|
{
|
|
172
173
|
label: "Email",
|
|
173
174
|
htmlFor: "invite-email",
|
|
174
175
|
required: !0,
|
|
175
|
-
error:
|
|
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:
|
|
184
|
-
...
|
|
184
|
+
className: v,
|
|
185
|
+
...s("email")
|
|
185
186
|
}
|
|
186
187
|
)
|
|
187
188
|
}
|
|
188
189
|
),
|
|
189
|
-
/* @__PURE__ */ e(
|
|
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:
|
|
195
|
-
...
|
|
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__ */
|
|
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:
|
|
210
|
-
disabled:
|
|
211
|
-
className:
|
|
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:
|
|
221
|
-
className:
|
|
222
|
-
children:
|
|
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
|
|
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:
|
|
240
|
+
children: i
|
|
240
241
|
}) {
|
|
241
|
-
return t === "loading" ? /* @__PURE__ */ e("div", { className:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
250
|
+
i
|
|
250
251
|
]
|
|
251
252
|
}
|
|
252
253
|
);
|
|
253
254
|
}
|
|
254
|
-
const
|
|
255
|
-
firstName:
|
|
256
|
-
lastName:
|
|
257
|
-
password:
|
|
258
|
-
confirmPassword:
|
|
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
|
|
264
|
+
function Ae({ token: t, loginPath: a }) {
|
|
264
265
|
const {
|
|
265
266
|
data: r,
|
|
266
|
-
isLoading:
|
|
267
|
-
error:
|
|
268
|
-
} =
|
|
269
|
-
register:
|
|
270
|
-
handleSubmit:
|
|
271
|
-
formState: { errors:
|
|
272
|
-
} =
|
|
273
|
-
resolver:
|
|
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
|
-
}),
|
|
281
|
+
}), b = r?.email ?? "", f = r?.role ?? "user", x = async (g) => {
|
|
281
282
|
try {
|
|
282
|
-
await
|
|
283
|
+
await s({
|
|
283
284
|
acceptInvitationDto: {
|
|
284
285
|
token: t,
|
|
285
|
-
password:
|
|
286
|
-
firstName:
|
|
287
|
-
lastName:
|
|
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
|
|
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
|
-
) :
|
|
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__ */
|
|
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__ */
|
|
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:
|
|
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:
|
|
331
|
+
/* @__PURE__ */ e("strong", { "data-testid": "accept-email", children: b })
|
|
331
332
|
] }),
|
|
332
|
-
/* @__PURE__ */
|
|
333
|
-
/* @__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:
|
|
341
|
-
...
|
|
341
|
+
className: v,
|
|
342
|
+
...o("firstName")
|
|
342
343
|
}
|
|
343
344
|
) }),
|
|
344
|
-
/* @__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:
|
|
352
|
-
...
|
|
352
|
+
className: v,
|
|
353
|
+
...o("lastName")
|
|
353
354
|
}
|
|
354
355
|
) }),
|
|
355
356
|
/* @__PURE__ */ e(
|
|
356
|
-
|
|
357
|
+
y,
|
|
357
358
|
{
|
|
358
359
|
label: "Password",
|
|
359
360
|
htmlFor: "accept-password",
|
|
360
361
|
required: !0,
|
|
361
|
-
error:
|
|
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:
|
|
370
|
-
...
|
|
370
|
+
className: v,
|
|
371
|
+
...o("password")
|
|
371
372
|
}
|
|
372
373
|
)
|
|
373
374
|
}
|
|
374
375
|
),
|
|
375
376
|
/* @__PURE__ */ e(
|
|
376
|
-
|
|
377
|
+
y,
|
|
377
378
|
{
|
|
378
379
|
label: "Confirm Password",
|
|
379
380
|
htmlFor: "accept-confirmPassword",
|
|
380
381
|
required: !0,
|
|
381
|
-
error:
|
|
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:
|
|
390
|
-
...
|
|
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:
|
|
401
|
-
className: `w-full ${
|
|
402
|
-
children:
|
|
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
|
-
|
|
416
|
-
|
|
417
|
-
|
|
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
|
|
544
|
+
await o({ id: f.id }).unwrap(), a(D("User deleted successfully"));
|
|
420
545
|
} catch {
|
|
421
546
|
} finally {
|
|
422
|
-
|
|
547
|
+
x(null);
|
|
423
548
|
}
|
|
424
|
-
}, [
|
|
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: (
|
|
431
|
-
const { firstName: N, lastName:
|
|
432
|
-
return [N,
|
|
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: (
|
|
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: (
|
|
447
|
-
if (!
|
|
448
|
-
const N =
|
|
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: () =>
|
|
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
|
|
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:
|
|
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__ */
|
|
484
|
-
/* @__PURE__ */
|
|
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: () =>
|
|
498
|
-
className:
|
|
622
|
+
onClick: () => b(!0),
|
|
623
|
+
className: F,
|
|
499
624
|
children: "Invite User"
|
|
500
625
|
}
|
|
501
626
|
)
|
|
502
627
|
] }),
|
|
503
628
|
/* @__PURE__ */ e(
|
|
504
|
-
|
|
629
|
+
U,
|
|
505
630
|
{
|
|
506
|
-
rowData:
|
|
507
|
-
columnDefs:
|
|
508
|
-
mode:
|
|
631
|
+
rowData: g,
|
|
632
|
+
columnDefs: q,
|
|
633
|
+
mode: i,
|
|
509
634
|
theme: r,
|
|
510
|
-
loading:
|
|
635
|
+
loading: s
|
|
511
636
|
}
|
|
512
637
|
),
|
|
513
638
|
/* @__PURE__ */ e(
|
|
514
|
-
|
|
639
|
+
re,
|
|
515
640
|
{
|
|
516
|
-
isOpen:
|
|
517
|
-
onClose: () =>
|
|
641
|
+
isOpen: m,
|
|
642
|
+
onClose: () => b(!1)
|
|
518
643
|
}
|
|
519
644
|
),
|
|
520
645
|
/* @__PURE__ */ e(
|
|
521
|
-
|
|
646
|
+
B,
|
|
522
647
|
{
|
|
523
|
-
isOpen: !!
|
|
648
|
+
isOpen: !!f,
|
|
524
649
|
title: "Delete User",
|
|
525
|
-
message: `Are you sure you want to delete ${
|
|
526
|
-
confirmLabel:
|
|
527
|
-
onConfirm:
|
|
528
|
-
onCancel: () =>
|
|
529
|
-
isLoading:
|
|
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
|
-
|
|
660
|
+
Ae as AcceptInvitation,
|
|
661
|
+
Fe as InvitationList,
|
|
536
662
|
w as StatusCard,
|
|
537
|
-
|
|
663
|
+
Le as UserList
|
|
538
664
|
};
|