@geekapps/auth-elements-nextjs 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +160 -20
- package/dist/index.js +759 -755
- package/dist/index.js.map +1 -1
- package/package.json +1 -2
package/dist/index.js
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/index.tsx
|
|
4
|
-
import {
|
|
5
|
-
useAccounts,
|
|
6
|
-
useAuth,
|
|
7
|
-
useOrg,
|
|
8
|
-
usePermissions,
|
|
9
|
-
useRoles,
|
|
10
|
-
useSessions,
|
|
11
|
-
useUsers
|
|
12
|
-
} from "@geekapps/auth-nextjs/client";
|
|
13
4
|
import {
|
|
14
5
|
useEffect,
|
|
15
6
|
useState
|
|
@@ -146,106 +137,236 @@ function Modal({
|
|
|
146
137
|
footer && /* @__PURE__ */ jsx("div", { className: "border-t border-slate-200 p-5", children: footer })
|
|
147
138
|
] }) });
|
|
148
139
|
}
|
|
149
|
-
function
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
tone: "primary",
|
|
159
|
-
type: "button",
|
|
160
|
-
children
|
|
161
|
-
}
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
function SignOutButton({ children = "Sair" }) {
|
|
165
|
-
const { signOut } = useAuth();
|
|
166
|
-
return /* @__PURE__ */ jsx(Button, { onClick: () => void signOut(), tone: "ghost", type: "button", children });
|
|
167
|
-
}
|
|
168
|
-
function AccountSwitcher() {
|
|
169
|
-
const {
|
|
170
|
-
accounts,
|
|
171
|
-
addAccount,
|
|
172
|
-
isLoadingAccounts,
|
|
173
|
-
refreshAccounts,
|
|
174
|
-
switchAccount
|
|
175
|
-
} = useAccounts();
|
|
176
|
-
const activeAccount = accounts.find((account) => account.isActive) ?? accounts[0] ?? null;
|
|
177
|
-
const [open, setOpen] = useState(false);
|
|
178
|
-
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
179
|
-
/* @__PURE__ */ jsx(
|
|
180
|
-
"button",
|
|
140
|
+
function createAuthElements(hooks) {
|
|
141
|
+
const { useAuth } = hooks;
|
|
142
|
+
function SignInButton({
|
|
143
|
+
children = "Entrar",
|
|
144
|
+
redirectTo
|
|
145
|
+
}) {
|
|
146
|
+
const { signIn } = useAuth();
|
|
147
|
+
return /* @__PURE__ */ jsx(
|
|
148
|
+
Button,
|
|
181
149
|
{
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
title: activeAccount?.user.name ?? activeAccount?.user.email ?? "Conta",
|
|
150
|
+
onClick: () => void signIn({ redirectTo }),
|
|
151
|
+
tone: "primary",
|
|
185
152
|
type: "button",
|
|
186
|
-
children
|
|
187
|
-
Avatar,
|
|
188
|
-
{
|
|
189
|
-
name: activeAccount?.user.name ?? activeAccount?.user.email,
|
|
190
|
-
size: "sm",
|
|
191
|
-
src: activeAccount?.user.imageUrl
|
|
192
|
-
}
|
|
193
|
-
)
|
|
153
|
+
children
|
|
194
154
|
}
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
function SignOutButton({ children = "Sair" }) {
|
|
158
|
+
const { signOut } = useAuth();
|
|
159
|
+
return /* @__PURE__ */ jsx(Button, { onClick: () => void signOut(), tone: "ghost", type: "button", children });
|
|
160
|
+
}
|
|
161
|
+
function AccountSwitcher() {
|
|
162
|
+
const {
|
|
163
|
+
accounts,
|
|
164
|
+
addAccount,
|
|
165
|
+
isLoadingAccounts,
|
|
166
|
+
refreshAccounts,
|
|
167
|
+
switchAccount
|
|
168
|
+
} = useAuth();
|
|
169
|
+
const activeAccount = accounts.find((account) => account.isActive) ?? accounts[0] ?? null;
|
|
170
|
+
const [open, setOpen] = useState(false);
|
|
171
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
172
|
+
/* @__PURE__ */ jsx(
|
|
173
|
+
"button",
|
|
174
|
+
{
|
|
175
|
+
className: "flex h-10 w-10 items-center justify-center rounded-xl transition hover:opacity-80",
|
|
176
|
+
onClick: () => setOpen((value) => !value),
|
|
177
|
+
title: activeAccount?.user.name ?? activeAccount?.user.email ?? "Conta",
|
|
178
|
+
type: "button",
|
|
179
|
+
children: /* @__PURE__ */ jsx(
|
|
180
|
+
Avatar,
|
|
204
181
|
{
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
182
|
+
name: activeAccount?.user.name ?? activeAccount?.user.email,
|
|
183
|
+
size: "sm",
|
|
184
|
+
src: activeAccount?.user.imageUrl
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
),
|
|
189
|
+
open && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
190
|
+
/* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-20", onClick: () => setOpen(false) }),
|
|
191
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute bottom-0 left-14 z-30 w-72 overflow-hidden rounded-xl border border-slate-200 bg-white shadow-lg", children: [
|
|
192
|
+
/* @__PURE__ */ jsx("div", { className: "border-b border-slate-100 px-3 py-2.5", children: /* @__PURE__ */ jsx("p", { className: "text-[11px] font-medium uppercase tracking-wider text-slate-400", children: "Contas" }) }),
|
|
193
|
+
/* @__PURE__ */ jsxs("div", { className: "p-1.5", children: [
|
|
194
|
+
isLoadingAccounts && /* @__PURE__ */ jsx("p", { className: "px-2 py-3 text-xs text-slate-400", children: "Carregando..." }),
|
|
195
|
+
accounts.map((account) => /* @__PURE__ */ jsxs(
|
|
196
|
+
"button",
|
|
197
|
+
{
|
|
198
|
+
className: cx(
|
|
199
|
+
"flex w-full items-center gap-2.5 rounded-lg px-2 py-2 text-left transition hover:bg-slate-50",
|
|
200
|
+
account.isActive && "bg-slate-50"
|
|
201
|
+
),
|
|
202
|
+
onClick: () => {
|
|
203
|
+
void switchAccount(account.sessionId ?? account.id);
|
|
204
|
+
setOpen(false);
|
|
205
|
+
},
|
|
206
|
+
type: "button",
|
|
207
|
+
children: [
|
|
208
|
+
/* @__PURE__ */ jsx(
|
|
209
|
+
Avatar,
|
|
210
|
+
{
|
|
211
|
+
name: account.user.name ?? account.user.email,
|
|
212
|
+
size: "sm",
|
|
213
|
+
src: account.user.imageUrl
|
|
214
|
+
}
|
|
215
|
+
),
|
|
216
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
217
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-sm font-medium text-slate-900", children: account.user.name ?? account.user.email }),
|
|
218
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-xs text-slate-500", children: account.user.email })
|
|
219
|
+
] }),
|
|
220
|
+
account.isActive && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs font-medium text-emerald-600", children: "\u2713" })
|
|
221
|
+
]
|
|
212
222
|
},
|
|
213
|
-
|
|
214
|
-
|
|
223
|
+
account.sessionId ?? account.id
|
|
224
|
+
))
|
|
225
|
+
] }),
|
|
226
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 border-t border-slate-100 p-1.5", children: [
|
|
227
|
+
/* @__PURE__ */ jsx(
|
|
228
|
+
Button,
|
|
229
|
+
{
|
|
230
|
+
className: "flex-1",
|
|
231
|
+
onClick: () => void addAccount(),
|
|
232
|
+
size: "sm",
|
|
233
|
+
type: "button",
|
|
234
|
+
children: "+ Conta"
|
|
235
|
+
}
|
|
236
|
+
),
|
|
237
|
+
/* @__PURE__ */ jsx(
|
|
238
|
+
Button,
|
|
239
|
+
{
|
|
240
|
+
className: "flex-1",
|
|
241
|
+
onClick: () => void refreshAccounts(),
|
|
242
|
+
size: "sm",
|
|
243
|
+
tone: "ghost",
|
|
244
|
+
type: "button",
|
|
245
|
+
children: "Atualizar"
|
|
246
|
+
}
|
|
247
|
+
)
|
|
248
|
+
] })
|
|
249
|
+
] })
|
|
250
|
+
] })
|
|
251
|
+
] });
|
|
252
|
+
}
|
|
253
|
+
function OrgSwitcher() {
|
|
254
|
+
const {
|
|
255
|
+
createOrganization,
|
|
256
|
+
currentOrg,
|
|
257
|
+
isLoadingOrganizations,
|
|
258
|
+
organizations,
|
|
259
|
+
refreshOrganizations,
|
|
260
|
+
setCurrentOrg
|
|
261
|
+
} = useAuth();
|
|
262
|
+
const [open, setOpen] = useState(false);
|
|
263
|
+
const [creating, setCreating] = useState(false);
|
|
264
|
+
async function onCreate(event) {
|
|
265
|
+
event.preventDefault();
|
|
266
|
+
const form = new FormData(event.currentTarget);
|
|
267
|
+
const name = String(form.get("name") ?? "");
|
|
268
|
+
const slug = String(form.get("slug") ?? "");
|
|
269
|
+
const result = await createOrganization({ name, slug });
|
|
270
|
+
if (result.success) {
|
|
271
|
+
setCreating(false);
|
|
272
|
+
setOpen(false);
|
|
273
|
+
await refreshOrganizations();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
277
|
+
/* @__PURE__ */ jsxs(
|
|
278
|
+
"button",
|
|
279
|
+
{
|
|
280
|
+
className: "flex w-full items-center gap-3 rounded-xl border border-slate-200 bg-white p-2 text-left hover:bg-slate-50",
|
|
281
|
+
onClick: () => setOpen((value) => !value),
|
|
282
|
+
type: "button",
|
|
283
|
+
children: [
|
|
284
|
+
/* @__PURE__ */ jsx(Avatar, { name: currentOrg?.name, src: currentOrg?.imageUrl }),
|
|
285
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
286
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-sm font-medium text-slate-950", children: currentOrg?.name ?? "Selecionar organiza\xE7\xE3o" }),
|
|
287
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-xs text-slate-500", children: isLoadingOrganizations ? "Carregando..." : `${organizations.length} organiza\xE7\xF5es` })
|
|
288
|
+
] }),
|
|
289
|
+
/* @__PURE__ */ jsx("span", { className: "text-slate-400", children: "\u2304" })
|
|
290
|
+
]
|
|
291
|
+
}
|
|
292
|
+
),
|
|
293
|
+
open && /* @__PURE__ */ jsxs("div", { className: "absolute right-0 z-30 mt-2 w-80 overflow-hidden rounded-xl border border-slate-200 bg-white shadow-lg", children: [
|
|
294
|
+
/* @__PURE__ */ jsx("div", { className: "max-h-72 overflow-y-auto p-2", children: organizations.map((organization) => /* @__PURE__ */ jsxs(
|
|
295
|
+
"button",
|
|
296
|
+
{
|
|
297
|
+
className: "flex w-full items-center gap-3 rounded-lg p-2 text-left hover:bg-slate-50",
|
|
298
|
+
onClick: () => {
|
|
299
|
+
void setCurrentOrg(organization.id);
|
|
300
|
+
setOpen(false);
|
|
301
|
+
},
|
|
302
|
+
type: "button",
|
|
303
|
+
children: [
|
|
304
|
+
/* @__PURE__ */ jsx(
|
|
305
|
+
Avatar,
|
|
306
|
+
{
|
|
307
|
+
name: organization.name,
|
|
308
|
+
size: "sm",
|
|
309
|
+
src: organization.imageUrl
|
|
310
|
+
}
|
|
311
|
+
),
|
|
312
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
313
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-sm font-medium text-slate-900", children: organization.name }),
|
|
314
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-xs text-slate-500", children: organization.slug })
|
|
315
|
+
] }),
|
|
316
|
+
organization.id === currentOrg?.id && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-emerald-600", children: "Atual" })
|
|
317
|
+
]
|
|
318
|
+
},
|
|
319
|
+
organization.id
|
|
320
|
+
)) }),
|
|
321
|
+
creating ? /* @__PURE__ */ jsxs(
|
|
322
|
+
"form",
|
|
323
|
+
{
|
|
324
|
+
className: "grid gap-2 border-t border-slate-200 p-3",
|
|
325
|
+
onSubmit: onCreate,
|
|
326
|
+
children: [
|
|
327
|
+
/* @__PURE__ */ jsx(Input, { name: "name", placeholder: "Nome da org", required: true }),
|
|
328
|
+
/* @__PURE__ */ jsx(Input, { name: "slug", placeholder: "slug-da-org", required: true }),
|
|
329
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
215
330
|
/* @__PURE__ */ jsx(
|
|
216
|
-
|
|
331
|
+
Button,
|
|
217
332
|
{
|
|
218
|
-
|
|
333
|
+
className: "flex-1",
|
|
219
334
|
size: "sm",
|
|
220
|
-
|
|
335
|
+
tone: "primary",
|
|
336
|
+
type: "submit",
|
|
337
|
+
children: "Criar"
|
|
221
338
|
}
|
|
222
339
|
),
|
|
223
|
-
/* @__PURE__ */
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
340
|
+
/* @__PURE__ */ jsx(
|
|
341
|
+
Button,
|
|
342
|
+
{
|
|
343
|
+
className: "flex-1",
|
|
344
|
+
onClick: () => setCreating(false),
|
|
345
|
+
size: "sm",
|
|
346
|
+
tone: "ghost",
|
|
347
|
+
type: "button",
|
|
348
|
+
children: "Cancelar"
|
|
349
|
+
}
|
|
350
|
+
)
|
|
351
|
+
] })
|
|
352
|
+
]
|
|
353
|
+
}
|
|
354
|
+
) : /* @__PURE__ */ jsxs("div", { className: "flex gap-2 border-t border-slate-200 p-2", children: [
|
|
234
355
|
/* @__PURE__ */ jsx(
|
|
235
356
|
Button,
|
|
236
357
|
{
|
|
237
358
|
className: "flex-1",
|
|
238
|
-
onClick: () =>
|
|
359
|
+
onClick: () => setCreating(true),
|
|
239
360
|
size: "sm",
|
|
240
361
|
type: "button",
|
|
241
|
-
children: "
|
|
362
|
+
children: "Nova org"
|
|
242
363
|
}
|
|
243
364
|
),
|
|
244
365
|
/* @__PURE__ */ jsx(
|
|
245
366
|
Button,
|
|
246
367
|
{
|
|
247
368
|
className: "flex-1",
|
|
248
|
-
onClick: () => void
|
|
369
|
+
onClick: () => void refreshOrganizations(),
|
|
249
370
|
size: "sm",
|
|
250
371
|
tone: "ghost",
|
|
251
372
|
type: "button",
|
|
@@ -254,749 +375,632 @@ function AccountSwitcher() {
|
|
|
254
375
|
)
|
|
255
376
|
] })
|
|
256
377
|
] })
|
|
257
|
-
] })
|
|
258
|
-
] });
|
|
259
|
-
}
|
|
260
|
-
function OrgSwitcher() {
|
|
261
|
-
const {
|
|
262
|
-
createOrganization,
|
|
263
|
-
currentOrg,
|
|
264
|
-
isLoadingOrganizations,
|
|
265
|
-
organizations,
|
|
266
|
-
refreshOrganizations,
|
|
267
|
-
setCurrentOrg
|
|
268
|
-
} = useOrg();
|
|
269
|
-
const [open, setOpen] = useState(false);
|
|
270
|
-
const [creating, setCreating] = useState(false);
|
|
271
|
-
async function onCreate(event) {
|
|
272
|
-
event.preventDefault();
|
|
273
|
-
const form = new FormData(event.currentTarget);
|
|
274
|
-
const name = String(form.get("name") ?? "");
|
|
275
|
-
const slug = String(form.get("slug") ?? "");
|
|
276
|
-
const result = await createOrganization({ name, slug });
|
|
277
|
-
if (result.success) {
|
|
278
|
-
setCreating(false);
|
|
279
|
-
setOpen(false);
|
|
280
|
-
await refreshOrganizations();
|
|
281
|
-
}
|
|
378
|
+
] });
|
|
282
379
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
380
|
+
function UserButton() {
|
|
381
|
+
const { user } = useAuth();
|
|
382
|
+
const [open, setOpen] = useState(false);
|
|
383
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
384
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setOpen(true), type: "button", children: /* @__PURE__ */ jsx(Avatar, { name: user?.name ?? user?.email, src: user?.imageUrl }) }),
|
|
385
|
+
/* @__PURE__ */ jsx(ProfileModal, { open, onOpenChange: setOpen })
|
|
386
|
+
] });
|
|
387
|
+
}
|
|
388
|
+
function OrganizationButton() {
|
|
389
|
+
const { currentOrg } = useAuth();
|
|
390
|
+
const [open, setOpen] = useState(false);
|
|
391
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
392
|
+
/* @__PURE__ */ jsx(
|
|
393
|
+
"button",
|
|
394
|
+
{
|
|
395
|
+
className: "flex h-10 w-10 items-center justify-center rounded-xl bg-white border border-slate-200 text-xs font-semibold text-slate-700 transition hover:bg-slate-50 hover:border-slate-300",
|
|
396
|
+
onClick: () => setOpen(true),
|
|
397
|
+
title: currentOrg?.name ?? "Organiza\xE7\xE3o",
|
|
398
|
+
type: "button",
|
|
399
|
+
children: currentOrg?.imageUrl ? /* @__PURE__ */ jsx(
|
|
400
|
+
"img",
|
|
401
|
+
{
|
|
402
|
+
alt: currentOrg.name,
|
|
403
|
+
className: "h-full w-full rounded-xl object-cover",
|
|
404
|
+
src: currentOrg.imageUrl
|
|
405
|
+
}
|
|
406
|
+
) : (currentOrg?.name ?? "O")[0]?.toUpperCase()
|
|
407
|
+
}
|
|
408
|
+
),
|
|
409
|
+
/* @__PURE__ */ jsx(ManageOrganizationModal, { open, onOpenChange: setOpen })
|
|
410
|
+
] });
|
|
411
|
+
}
|
|
412
|
+
function ProfileModal({
|
|
413
|
+
open,
|
|
414
|
+
onOpenChange
|
|
415
|
+
}) {
|
|
416
|
+
const {
|
|
417
|
+
signOut,
|
|
418
|
+
signOutAll,
|
|
419
|
+
user,
|
|
420
|
+
organizations,
|
|
421
|
+
currentOrg,
|
|
422
|
+
setCurrentOrg,
|
|
423
|
+
updateUser,
|
|
424
|
+
listUserSessions,
|
|
425
|
+
revokeUserSession
|
|
426
|
+
} = useAuth();
|
|
427
|
+
const [tab, setTab] = useState("profile");
|
|
428
|
+
const [sessions, setSessions] = useState([]);
|
|
429
|
+
const [saving, setSaving] = useState(false);
|
|
430
|
+
const [saveError, setSaveError] = useState(null);
|
|
431
|
+
const [saveSuccess, setSaveSuccess] = useState(false);
|
|
432
|
+
useEffect(() => {
|
|
433
|
+
if (!open) {
|
|
434
|
+
setTab("profile");
|
|
435
|
+
setSaveError(null);
|
|
436
|
+
setSaveSuccess(false);
|
|
437
|
+
}
|
|
438
|
+
}, [open]);
|
|
439
|
+
useEffect(() => {
|
|
440
|
+
if (open && user && tab === "sessions") {
|
|
441
|
+
void listUserSessions({ userId: user.id }).then(setSessions).catch(() => setSessions([]));
|
|
442
|
+
}
|
|
443
|
+
}, [listUserSessions, open, tab, user]);
|
|
444
|
+
async function onProfileSubmit(event) {
|
|
445
|
+
event.preventDefault();
|
|
446
|
+
if (!user) return;
|
|
447
|
+
const form = new FormData(event.currentTarget);
|
|
448
|
+
setSaving(true);
|
|
449
|
+
setSaveError(null);
|
|
450
|
+
setSaveSuccess(false);
|
|
451
|
+
try {
|
|
452
|
+
await updateUser(user.id, {
|
|
453
|
+
name: String(form.get("name") ?? "") || null,
|
|
454
|
+
phone: String(form.get("phone") ?? "") || null,
|
|
455
|
+
imageUrl: String(form.get("imageUrl") ?? "") || null
|
|
456
|
+
});
|
|
457
|
+
setSaveSuccess(true);
|
|
458
|
+
setTimeout(() => setSaveSuccess(false), 2500);
|
|
459
|
+
} catch (err) {
|
|
460
|
+
setSaveError(err instanceof Error ? err.message : "Erro ao salvar.");
|
|
461
|
+
} finally {
|
|
462
|
+
setSaving(false);
|
|
298
463
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
464
|
+
}
|
|
465
|
+
if (!open) return null;
|
|
466
|
+
return /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex max-h-[90vh] w-full max-w-lg flex-col overflow-hidden rounded-2xl bg-white shadow-2xl", children: [
|
|
467
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center justify-between border-b border-slate-100 px-6 py-4", children: [
|
|
468
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
469
|
+
/* @__PURE__ */ jsx(
|
|
470
|
+
Avatar,
|
|
471
|
+
{
|
|
472
|
+
name: user?.name ?? user?.email,
|
|
473
|
+
size: "sm",
|
|
474
|
+
src: user?.imageUrl
|
|
475
|
+
}
|
|
476
|
+
),
|
|
477
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
478
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-slate-900", children: user?.name ?? user?.email ?? "Minha conta" }),
|
|
479
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-slate-500", children: user?.email })
|
|
480
|
+
] })
|
|
481
|
+
] }),
|
|
482
|
+
/* @__PURE__ */ jsx(
|
|
483
|
+
"button",
|
|
484
|
+
{
|
|
485
|
+
"aria-label": "Fechar",
|
|
486
|
+
className: "rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-700",
|
|
487
|
+
onClick: () => onOpenChange(false),
|
|
488
|
+
type: "button",
|
|
489
|
+
children: "\u2715"
|
|
490
|
+
}
|
|
491
|
+
)
|
|
492
|
+
] }),
|
|
493
|
+
/* @__PURE__ */ jsx("div", { className: "shrink-0 flex gap-1 border-b border-slate-100 px-6 pt-3", children: [
|
|
494
|
+
{ id: "profile", label: "Perfil" },
|
|
495
|
+
{ id: "sessions", label: "Sess\xF5es" },
|
|
496
|
+
{ id: "orgs", label: "Organiza\xE7\xF5es" }
|
|
497
|
+
].map((t) => /* @__PURE__ */ jsx(
|
|
302
498
|
"button",
|
|
303
499
|
{
|
|
304
|
-
className:
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
500
|
+
className: cx(
|
|
501
|
+
"mb-[-1px] border-b-2 px-3 pb-2.5 text-xs font-medium transition",
|
|
502
|
+
tab === t.id ? "border-slate-900 text-slate-900" : "border-transparent text-slate-500 hover:text-slate-700"
|
|
503
|
+
),
|
|
504
|
+
onClick: () => setTab(t.id),
|
|
309
505
|
type: "button",
|
|
310
|
-
children:
|
|
506
|
+
children: t.label
|
|
507
|
+
},
|
|
508
|
+
t.id
|
|
509
|
+
)) }),
|
|
510
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-6 py-5", children: [
|
|
511
|
+
tab === "profile" && user && /* @__PURE__ */ jsxs("form", { className: "grid gap-4", onSubmit: onProfileSubmit, children: [
|
|
512
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 rounded-xl bg-slate-50 p-4", children: [
|
|
311
513
|
/* @__PURE__ */ jsx(
|
|
312
514
|
Avatar,
|
|
313
515
|
{
|
|
314
|
-
name:
|
|
315
|
-
size: "
|
|
316
|
-
src:
|
|
516
|
+
name: user.name ?? user.email,
|
|
517
|
+
size: "lg",
|
|
518
|
+
src: user.imageUrl
|
|
317
519
|
}
|
|
318
520
|
),
|
|
319
|
-
/* @__PURE__ */ jsxs("
|
|
320
|
-
/* @__PURE__ */ jsx("
|
|
321
|
-
/* @__PURE__ */ jsx("
|
|
322
|
-
] })
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
521
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
522
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-slate-900", children: user.name ?? "Sem nome" }),
|
|
523
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-slate-500", children: user.email })
|
|
524
|
+
] })
|
|
525
|
+
] }),
|
|
526
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [
|
|
527
|
+
/* @__PURE__ */ jsx(Field, { label: "Nome", children: /* @__PURE__ */ jsx(
|
|
528
|
+
Input,
|
|
529
|
+
{
|
|
530
|
+
defaultValue: user.name ?? "",
|
|
531
|
+
name: "name",
|
|
532
|
+
placeholder: "Seu nome"
|
|
533
|
+
}
|
|
534
|
+
) }),
|
|
535
|
+
/* @__PURE__ */ jsx(Field, { label: "Telefone", children: /* @__PURE__ */ jsx(
|
|
536
|
+
Input,
|
|
537
|
+
{
|
|
538
|
+
defaultValue: user.phone ?? "",
|
|
539
|
+
name: "phone",
|
|
540
|
+
placeholder: "+55 11 99999-9999"
|
|
541
|
+
}
|
|
542
|
+
) })
|
|
543
|
+
] }),
|
|
544
|
+
/* @__PURE__ */ jsx(Field, { label: "URL da imagem", children: /* @__PURE__ */ jsx(
|
|
545
|
+
Input,
|
|
546
|
+
{
|
|
547
|
+
defaultValue: user.imageUrl ?? "",
|
|
548
|
+
name: "imageUrl",
|
|
549
|
+
placeholder: "https://..."
|
|
550
|
+
}
|
|
551
|
+
) }),
|
|
552
|
+
saveError && /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600", children: saveError }),
|
|
553
|
+
saveSuccess && /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-emerald-50 px-3 py-2 text-xs text-emerald-600", children: "Perfil salvo com sucesso." }),
|
|
554
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-t border-slate-100 pt-2", children: [
|
|
336
555
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
337
556
|
/* @__PURE__ */ jsx(
|
|
338
557
|
Button,
|
|
339
558
|
{
|
|
340
|
-
|
|
559
|
+
onClick: () => void signOut(),
|
|
341
560
|
size: "sm",
|
|
342
|
-
tone: "
|
|
343
|
-
type: "
|
|
344
|
-
children: "
|
|
561
|
+
tone: "ghost",
|
|
562
|
+
type: "button",
|
|
563
|
+
children: "Sair"
|
|
345
564
|
}
|
|
346
565
|
),
|
|
347
566
|
/* @__PURE__ */ jsx(
|
|
348
567
|
Button,
|
|
349
568
|
{
|
|
350
|
-
|
|
351
|
-
onClick: () => setCreating(false),
|
|
569
|
+
onClick: () => void signOutAll(),
|
|
352
570
|
size: "sm",
|
|
353
|
-
tone: "
|
|
571
|
+
tone: "danger",
|
|
354
572
|
type: "button",
|
|
355
|
-
children: "
|
|
573
|
+
children: "Sair de todas"
|
|
356
574
|
}
|
|
357
575
|
)
|
|
358
|
-
] })
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
576
|
+
] }),
|
|
577
|
+
/* @__PURE__ */ jsx(
|
|
578
|
+
Button,
|
|
579
|
+
{
|
|
580
|
+
disabled: saving,
|
|
581
|
+
size: "sm",
|
|
582
|
+
tone: "primary",
|
|
583
|
+
type: "submit",
|
|
584
|
+
children: saving ? "Salvando\u2026" : "Salvar"
|
|
585
|
+
}
|
|
586
|
+
)
|
|
587
|
+
] })
|
|
588
|
+
] }),
|
|
589
|
+
tab === "sessions" && /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
590
|
+
sessions.length === 0 && /* @__PURE__ */ jsx("p", { className: "py-6 text-center text-sm text-slate-400", children: "Nenhuma sess\xE3o ativa." }),
|
|
591
|
+
sessions.map((session) => {
|
|
592
|
+
const expired = isExpired(session.expiresAt);
|
|
593
|
+
return /* @__PURE__ */ jsxs(
|
|
594
|
+
"div",
|
|
595
|
+
{
|
|
596
|
+
className: "flex items-center justify-between gap-4 rounded-xl border border-slate-200 p-4",
|
|
597
|
+
children: [
|
|
598
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
599
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-slate-900", children: session.deviceName ?? "Dispositivo" }),
|
|
600
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-0.5 truncate text-xs text-slate-500", children: [
|
|
601
|
+
session.ip ?? "IP desconhecido",
|
|
602
|
+
" \xB7",
|
|
603
|
+
" ",
|
|
604
|
+
/* @__PURE__ */ jsx("span", { className: expired ? "text-amber-600" : "", children: expired ? "Expirada" : `Expira ${formatDate(session.expiresAt)}` })
|
|
605
|
+
] })
|
|
606
|
+
] }),
|
|
607
|
+
/* @__PURE__ */ jsx(
|
|
608
|
+
Button,
|
|
609
|
+
{
|
|
610
|
+
onClick: async () => {
|
|
611
|
+
await revokeUserSession(session.id);
|
|
612
|
+
setSessions(
|
|
613
|
+
(s) => s.filter((x) => x.id !== session.id)
|
|
614
|
+
);
|
|
615
|
+
},
|
|
616
|
+
size: "sm",
|
|
617
|
+
tone: "danger",
|
|
618
|
+
type: "button",
|
|
619
|
+
children: "Revogar"
|
|
620
|
+
}
|
|
621
|
+
)
|
|
622
|
+
]
|
|
623
|
+
},
|
|
624
|
+
session.id
|
|
625
|
+
);
|
|
626
|
+
})
|
|
627
|
+
] }),
|
|
628
|
+
tab === "orgs" && /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
629
|
+
organizations.length === 0 && /* @__PURE__ */ jsx("p", { className: "py-6 text-center text-sm text-slate-400", children: "Nenhuma organiza\xE7\xE3o." }),
|
|
630
|
+
organizations.map((org) => /* @__PURE__ */ jsxs(
|
|
631
|
+
"button",
|
|
632
|
+
{
|
|
633
|
+
className: cx(
|
|
634
|
+
"flex w-full items-center gap-3 rounded-xl border p-3 text-left transition",
|
|
635
|
+
org.id === currentOrg?.id ? "border-slate-900 bg-slate-50" : "border-slate-200 hover:border-slate-300 hover:bg-slate-50"
|
|
636
|
+
),
|
|
637
|
+
onClick: () => void setCurrentOrg(org.id),
|
|
638
|
+
type: "button",
|
|
639
|
+
children: [
|
|
640
|
+
/* @__PURE__ */ jsx(Avatar, { name: org.name, size: "sm", src: org.imageUrl }),
|
|
641
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
642
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-slate-900", children: org.name }),
|
|
643
|
+
/* @__PURE__ */ jsxs("p", { className: "truncate text-xs text-slate-500", children: [
|
|
644
|
+
"/",
|
|
645
|
+
org.slug
|
|
646
|
+
] })
|
|
647
|
+
] }),
|
|
648
|
+
org.id === currentOrg?.id && /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-slate-900 px-2 py-0.5 text-[10px] font-medium text-white", children: "Ativa" })
|
|
649
|
+
]
|
|
650
|
+
},
|
|
651
|
+
org.id
|
|
652
|
+
))
|
|
653
|
+
] })
|
|
383
654
|
] })
|
|
384
|
-
] })
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
655
|
+
] }) });
|
|
656
|
+
}
|
|
657
|
+
function ManageOrganizationModal({
|
|
658
|
+
open,
|
|
659
|
+
onOpenChange
|
|
660
|
+
}) {
|
|
661
|
+
const {
|
|
662
|
+
createOrganization,
|
|
663
|
+
currentOrg,
|
|
664
|
+
organizations,
|
|
665
|
+
refreshOrganizations,
|
|
666
|
+
setCurrentOrg,
|
|
667
|
+
updateOrganization,
|
|
668
|
+
listPermissions,
|
|
669
|
+
listRoles
|
|
670
|
+
} = useAuth();
|
|
671
|
+
const [tab, setTab] = useState("orgs");
|
|
672
|
+
const [roles, setRoles] = useState({ systemRoles: [], customRoles: [] });
|
|
673
|
+
const [permissions, setPermissions] = useState([]);
|
|
674
|
+
const [saving, setSaving] = useState(false);
|
|
675
|
+
const [saveSuccess, setSaveSuccess] = useState(false);
|
|
676
|
+
const [saveError, setSaveError] = useState(null);
|
|
677
|
+
const [creating, setCreating] = useState(false);
|
|
678
|
+
const [createError, setCreateError] = useState(null);
|
|
679
|
+
useEffect(() => {
|
|
680
|
+
if (!open) {
|
|
681
|
+
setTab("orgs");
|
|
682
|
+
setSaveError(null);
|
|
683
|
+
setSaveSuccess(false);
|
|
684
|
+
setCreating(false);
|
|
685
|
+
setCreateError(null);
|
|
414
686
|
}
|
|
415
|
-
)
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
})
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const [sessions, setSessions] = useState([]);
|
|
429
|
-
const [saving, setSaving] = useState(false);
|
|
430
|
-
const [saveError, setSaveError] = useState(null);
|
|
431
|
-
const [saveSuccess, setSaveSuccess] = useState(false);
|
|
432
|
-
useEffect(() => {
|
|
433
|
-
if (!open) {
|
|
434
|
-
setTab("profile");
|
|
687
|
+
}, [open]);
|
|
688
|
+
useEffect(() => {
|
|
689
|
+
if (!open || !currentOrg) return;
|
|
690
|
+
if (tab === "members" || tab === "roles") {
|
|
691
|
+
void listRoles({ organizationId: currentOrg.id }).then(setRoles).catch(() => setRoles({ systemRoles: [], customRoles: [] }));
|
|
692
|
+
void listPermissions({}).then(setPermissions).catch(() => setPermissions([]));
|
|
693
|
+
}
|
|
694
|
+
}, [currentOrg, listPermissions, listRoles, open, tab]);
|
|
695
|
+
async function onOrgSubmit(event) {
|
|
696
|
+
event.preventDefault();
|
|
697
|
+
if (!currentOrg) return;
|
|
698
|
+
const form = new FormData(event.currentTarget);
|
|
699
|
+
setSaving(true);
|
|
435
700
|
setSaveError(null);
|
|
436
701
|
setSaveSuccess(false);
|
|
702
|
+
try {
|
|
703
|
+
await updateOrganization(currentOrg.id, {
|
|
704
|
+
name: String(form.get("name") ?? ""),
|
|
705
|
+
description: String(form.get("description") ?? "") || null,
|
|
706
|
+
slug: String(form.get("slug") ?? ""),
|
|
707
|
+
domain: String(form.get("domain") ?? "") || null,
|
|
708
|
+
imageUrl: String(form.get("imageUrl") ?? "") || null,
|
|
709
|
+
faviconUrl: String(form.get("faviconUrl") ?? "") || null
|
|
710
|
+
});
|
|
711
|
+
setSaveSuccess(true);
|
|
712
|
+
setTimeout(() => setSaveSuccess(false), 2500);
|
|
713
|
+
} catch (err) {
|
|
714
|
+
setSaveError(err instanceof Error ? err.message : "Erro ao salvar.");
|
|
715
|
+
} finally {
|
|
716
|
+
setSaving(false);
|
|
717
|
+
}
|
|
437
718
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
setSaving(false);
|
|
719
|
+
async function onCreateOrg(event) {
|
|
720
|
+
event.preventDefault();
|
|
721
|
+
const form = new FormData(event.currentTarget);
|
|
722
|
+
setCreating(true);
|
|
723
|
+
setCreateError(null);
|
|
724
|
+
try {
|
|
725
|
+
const result = await createOrganization({
|
|
726
|
+
name: String(form.get("name") ?? ""),
|
|
727
|
+
slug: String(form.get("slug") ?? "")
|
|
728
|
+
});
|
|
729
|
+
if (result.success) {
|
|
730
|
+
await refreshOrganizations();
|
|
731
|
+
if (result.data?.id) {
|
|
732
|
+
void setCurrentOrg(result.data.id);
|
|
733
|
+
}
|
|
734
|
+
setTab("info");
|
|
735
|
+
} else {
|
|
736
|
+
setCreateError(result.error ?? "Erro ao criar organiza\xE7\xE3o.");
|
|
737
|
+
}
|
|
738
|
+
} catch (err) {
|
|
739
|
+
setCreateError(err instanceof Error ? err.message : "Erro ao criar.");
|
|
740
|
+
} finally {
|
|
741
|
+
setCreating(false);
|
|
742
|
+
}
|
|
463
743
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
744
|
+
if (!open) return null;
|
|
745
|
+
const orgTabs = [
|
|
746
|
+
{ id: "orgs", label: "Organiza\xE7\xF5es" },
|
|
747
|
+
{ id: "info", label: "Geral" },
|
|
748
|
+
{ id: "members", label: "Membros" },
|
|
749
|
+
{ id: "roles", label: "Roles" },
|
|
750
|
+
{ id: "new", label: "+ Nova org" }
|
|
751
|
+
];
|
|
752
|
+
return /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex max-h-[90vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl bg-white shadow-2xl", children: [
|
|
753
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center justify-between border-b border-slate-100 px-6 py-4", children: [
|
|
754
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
755
|
+
currentOrg?.imageUrl ? /* @__PURE__ */ jsx(
|
|
756
|
+
"img",
|
|
757
|
+
{
|
|
758
|
+
alt: currentOrg.name,
|
|
759
|
+
className: "h-8 w-8 rounded-lg object-cover",
|
|
760
|
+
src: currentOrg.imageUrl
|
|
761
|
+
}
|
|
762
|
+
) : /* @__PURE__ */ jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-slate-100 text-xs font-semibold text-slate-600", children: (currentOrg?.name ?? "O")[0]?.toUpperCase() }),
|
|
763
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
764
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-slate-900", children: currentOrg?.name ?? "Organiza\xE7\xE3o" }),
|
|
765
|
+
currentOrg?.slug && /* @__PURE__ */ jsxs("p", { className: "text-xs text-slate-500", children: [
|
|
766
|
+
"/",
|
|
767
|
+
currentOrg.slug
|
|
768
|
+
] })
|
|
769
|
+
] })
|
|
770
|
+
] }),
|
|
469
771
|
/* @__PURE__ */ jsx(
|
|
470
|
-
|
|
772
|
+
"button",
|
|
471
773
|
{
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
774
|
+
"aria-label": "Fechar",
|
|
775
|
+
className: "rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-700",
|
|
776
|
+
onClick: () => onOpenChange(false),
|
|
777
|
+
type: "button",
|
|
778
|
+
children: "\u2715"
|
|
475
779
|
}
|
|
476
|
-
)
|
|
477
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
478
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-slate-900", children: user?.name ?? user?.email ?? "Minha conta" }),
|
|
479
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-slate-500", children: user?.email })
|
|
480
|
-
] })
|
|
780
|
+
)
|
|
481
781
|
] }),
|
|
482
|
-
/* @__PURE__ */ jsx(
|
|
782
|
+
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 gap-1 border-b border-slate-100 px-6 pt-3", children: orgTabs.map((t) => /* @__PURE__ */ jsx(
|
|
483
783
|
"button",
|
|
484
784
|
{
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
785
|
+
className: cx(
|
|
786
|
+
"mb-[-1px] border-b-2 px-3 pb-2.5 text-xs font-medium transition",
|
|
787
|
+
tab === t.id ? "border-slate-900 text-slate-900" : "border-transparent text-slate-500 hover:text-slate-700"
|
|
788
|
+
),
|
|
789
|
+
onClick: () => setTab(t.id),
|
|
488
790
|
type: "button",
|
|
489
|
-
children:
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
{
|
|
500
|
-
className: cx(
|
|
501
|
-
"mb-[-1px] border-b-2 px-3 pb-2.5 text-xs font-medium transition",
|
|
502
|
-
tab === t.id ? "border-slate-900 text-slate-900" : "border-transparent text-slate-500 hover:text-slate-700"
|
|
503
|
-
),
|
|
504
|
-
onClick: () => setTab(t.id),
|
|
505
|
-
type: "button",
|
|
506
|
-
children: t.label
|
|
507
|
-
},
|
|
508
|
-
t.id
|
|
509
|
-
)) }),
|
|
510
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-6 py-5", children: [
|
|
511
|
-
tab === "profile" && user && /* @__PURE__ */ jsxs("form", { className: "grid gap-4", onSubmit: onProfileSubmit, children: [
|
|
512
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 rounded-xl bg-slate-50 p-4", children: [
|
|
513
|
-
/* @__PURE__ */ jsx(
|
|
514
|
-
Avatar,
|
|
791
|
+
children: t.label
|
|
792
|
+
},
|
|
793
|
+
t.id
|
|
794
|
+
)) }),
|
|
795
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-6 py-5", children: [
|
|
796
|
+
!currentOrg && /* @__PURE__ */ jsx("p", { className: "py-8 text-center text-sm text-slate-400", children: "Nenhuma organiza\xE7\xE3o selecionada." }),
|
|
797
|
+
tab === "orgs" && /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
798
|
+
organizations.length === 0 && /* @__PURE__ */ jsx("p", { className: "py-8 text-center text-sm text-slate-400", children: "Nenhuma organiza\xE7\xE3o dispon\xEDvel." }),
|
|
799
|
+
organizations.map((org) => /* @__PURE__ */ jsxs(
|
|
800
|
+
"button",
|
|
515
801
|
{
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
802
|
+
className: cx(
|
|
803
|
+
"flex w-full items-center gap-3 rounded-xl border p-3 text-left transition",
|
|
804
|
+
org.id === currentOrg?.id ? "border-slate-900 bg-slate-50" : "border-slate-200 hover:border-slate-300 hover:bg-slate-50"
|
|
805
|
+
),
|
|
806
|
+
onClick: () => {
|
|
807
|
+
void setCurrentOrg(org.id);
|
|
808
|
+
onOpenChange(false);
|
|
809
|
+
},
|
|
810
|
+
type: "button",
|
|
811
|
+
children: [
|
|
812
|
+
/* @__PURE__ */ jsx(Avatar, { name: org.name, size: "sm", src: org.imageUrl }),
|
|
813
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
814
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-slate-900", children: org.name }),
|
|
815
|
+
/* @__PURE__ */ jsxs("p", { className: "truncate text-xs text-slate-500", children: [
|
|
816
|
+
"/",
|
|
817
|
+
org.slug
|
|
818
|
+
] })
|
|
819
|
+
] }),
|
|
820
|
+
org.id === currentOrg?.id && /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-slate-900 px-2 py-0.5 text-[10px] font-medium text-white", children: "Ativa" })
|
|
821
|
+
]
|
|
822
|
+
},
|
|
823
|
+
org.id
|
|
824
|
+
))
|
|
525
825
|
] }),
|
|
526
|
-
/* @__PURE__ */ jsxs("
|
|
527
|
-
/* @__PURE__ */
|
|
528
|
-
Input,
|
|
826
|
+
tab === "info" && currentOrg && /* @__PURE__ */ jsxs("form", { className: "grid gap-4", onSubmit: onOrgSubmit, children: [
|
|
827
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [
|
|
828
|
+
/* @__PURE__ */ jsx(Field, { label: "Nome *", children: /* @__PURE__ */ jsx(Input, { defaultValue: currentOrg.name, name: "name", required: true }) }),
|
|
829
|
+
/* @__PURE__ */ jsx(Field, { label: "Slug *", children: /* @__PURE__ */ jsx(Input, { defaultValue: currentOrg.slug, name: "slug", required: true }) })
|
|
830
|
+
] }),
|
|
831
|
+
/* @__PURE__ */ jsx(Field, { label: "Descri\xE7\xE3o", children: /* @__PURE__ */ jsx(
|
|
832
|
+
Textarea,
|
|
529
833
|
{
|
|
530
|
-
defaultValue:
|
|
531
|
-
name: "
|
|
532
|
-
placeholder: "
|
|
834
|
+
defaultValue: currentOrg.description ?? "",
|
|
835
|
+
name: "description",
|
|
836
|
+
placeholder: "Descreva a organiza\xE7\xE3o\u2026"
|
|
533
837
|
}
|
|
534
838
|
) }),
|
|
535
|
-
/* @__PURE__ */
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
defaultValue: user.phone ?? "",
|
|
539
|
-
name: "phone",
|
|
540
|
-
placeholder: "+55 11 99999-9999"
|
|
541
|
-
}
|
|
542
|
-
) })
|
|
543
|
-
] }),
|
|
544
|
-
/* @__PURE__ */ jsx(Field, { label: "URL da imagem", children: /* @__PURE__ */ jsx(
|
|
545
|
-
Input,
|
|
546
|
-
{
|
|
547
|
-
defaultValue: user.imageUrl ?? "",
|
|
548
|
-
name: "imageUrl",
|
|
549
|
-
placeholder: "https://..."
|
|
550
|
-
}
|
|
551
|
-
) }),
|
|
552
|
-
saveError && /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600", children: saveError }),
|
|
553
|
-
saveSuccess && /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-emerald-50 px-3 py-2 text-xs text-emerald-600", children: "Perfil salvo com sucesso." }),
|
|
554
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-t border-slate-100 pt-2", children: [
|
|
555
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
556
|
-
/* @__PURE__ */ jsx(
|
|
557
|
-
Button,
|
|
839
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [
|
|
840
|
+
/* @__PURE__ */ jsx(Field, { label: "Dom\xEDnio", children: /* @__PURE__ */ jsx(
|
|
841
|
+
Input,
|
|
558
842
|
{
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
type: "button",
|
|
563
|
-
children: "Sair"
|
|
843
|
+
defaultValue: currentOrg.domain ?? "",
|
|
844
|
+
name: "domain",
|
|
845
|
+
placeholder: "acme.com"
|
|
564
846
|
}
|
|
565
|
-
),
|
|
566
|
-
/* @__PURE__ */ jsx(
|
|
567
|
-
|
|
847
|
+
) }),
|
|
848
|
+
/* @__PURE__ */ jsx(Field, { label: "URL da imagem", children: /* @__PURE__ */ jsx(
|
|
849
|
+
Input,
|
|
568
850
|
{
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
type: "button",
|
|
573
|
-
children: "Sair de todas"
|
|
851
|
+
defaultValue: currentOrg.imageUrl ?? "",
|
|
852
|
+
name: "imageUrl",
|
|
853
|
+
placeholder: "https://..."
|
|
574
854
|
}
|
|
575
|
-
)
|
|
855
|
+
) })
|
|
576
856
|
] }),
|
|
577
|
-
/* @__PURE__ */ jsx(
|
|
857
|
+
/* @__PURE__ */ jsx(Field, { label: "URL do favicon", children: /* @__PURE__ */ jsx(
|
|
858
|
+
Input,
|
|
859
|
+
{
|
|
860
|
+
defaultValue: currentOrg.faviconUrl ?? "",
|
|
861
|
+
name: "faviconUrl",
|
|
862
|
+
placeholder: "https://..."
|
|
863
|
+
}
|
|
864
|
+
) }),
|
|
865
|
+
saveError && /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600", children: saveError }),
|
|
866
|
+
saveSuccess && /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-emerald-50 px-3 py-2 text-xs text-emerald-600", children: "Organiza\xE7\xE3o atualizada." }),
|
|
867
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-end pt-1", children: /* @__PURE__ */ jsx(
|
|
578
868
|
Button,
|
|
579
869
|
{
|
|
580
870
|
disabled: saving,
|
|
581
871
|
size: "sm",
|
|
582
872
|
tone: "primary",
|
|
583
873
|
type: "submit",
|
|
584
|
-
children: saving ? "Salvando\u2026" : "Salvar"
|
|
874
|
+
children: saving ? "Salvando\u2026" : "Salvar organiza\xE7\xE3o"
|
|
585
875
|
}
|
|
586
|
-
)
|
|
587
|
-
] })
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
sessions.map((session) => {
|
|
592
|
-
const expired = isExpired(session.expiresAt);
|
|
593
|
-
return /* @__PURE__ */ jsxs(
|
|
876
|
+
) })
|
|
877
|
+
] }),
|
|
878
|
+
tab === "members" && currentOrg && /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
879
|
+
(currentOrg.members ?? []).length === 0 && /* @__PURE__ */ jsx("p", { className: "py-8 text-center text-sm text-slate-400", children: "Nenhum membro nesta organiza\xE7\xE3o." }),
|
|
880
|
+
(currentOrg.members ?? []).map((member) => /* @__PURE__ */ jsxs(
|
|
594
881
|
"div",
|
|
595
882
|
{
|
|
596
|
-
className: "flex items-center
|
|
883
|
+
className: "flex items-center gap-3 rounded-xl border border-slate-200 p-4",
|
|
597
884
|
children: [
|
|
598
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
599
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-slate-900", children: session.deviceName ?? "Dispositivo" }),
|
|
600
|
-
/* @__PURE__ */ jsxs("p", { className: "mt-0.5 truncate text-xs text-slate-500", children: [
|
|
601
|
-
session.ip ?? "IP desconhecido",
|
|
602
|
-
" \xB7",
|
|
603
|
-
" ",
|
|
604
|
-
/* @__PURE__ */ jsx("span", { className: expired ? "text-amber-600" : "", children: expired ? "Expirada" : `Expira ${formatDate(session.expiresAt)}` })
|
|
605
|
-
] })
|
|
606
|
-
] }),
|
|
607
885
|
/* @__PURE__ */ jsx(
|
|
608
|
-
|
|
886
|
+
Avatar,
|
|
609
887
|
{
|
|
610
|
-
|
|
611
|
-
await revokeUserSession(session.id);
|
|
612
|
-
setSessions(
|
|
613
|
-
(s) => s.filter((x) => x.id !== session.id)
|
|
614
|
-
);
|
|
615
|
-
},
|
|
888
|
+
name: member.user.name ?? member.user.email,
|
|
616
889
|
size: "sm",
|
|
617
|
-
|
|
618
|
-
type: "button",
|
|
619
|
-
children: "Revogar"
|
|
890
|
+
src: member.user.imageUrl
|
|
620
891
|
}
|
|
621
|
-
)
|
|
892
|
+
),
|
|
893
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
894
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-slate-900", children: member.user.name ?? member.user.email }),
|
|
895
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-xs text-slate-500", children: member.user.email })
|
|
896
|
+
] }),
|
|
897
|
+
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 flex-wrap justify-end gap-1", children: (member.roleAssignments ?? []).map((a) => /* @__PURE__ */ jsx(
|
|
898
|
+
"span",
|
|
899
|
+
{
|
|
900
|
+
className: "rounded-full bg-slate-900 px-2 py-0.5 text-[11px] font-medium text-white",
|
|
901
|
+
children: a.roleDefinition?.name ?? a.customRole?.name ?? a.id
|
|
902
|
+
},
|
|
903
|
+
a.id
|
|
904
|
+
)) })
|
|
622
905
|
]
|
|
623
906
|
},
|
|
624
|
-
|
|
625
|
-
)
|
|
626
|
-
})
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
"
|
|
632
|
-
{
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
907
|
+
member.id
|
|
908
|
+
))
|
|
909
|
+
] }),
|
|
910
|
+
tab === "new" && /* @__PURE__ */ jsxs("form", { className: "grid gap-4", onSubmit: onCreateOrg, children: [
|
|
911
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "Crie uma nova organiza\xE7\xE3o e alterne para ela automaticamente." }),
|
|
912
|
+
/* @__PURE__ */ jsx(Field, { label: "Nome *", children: /* @__PURE__ */ jsx(Input, { name: "name", placeholder: "Minha organiza\xE7\xE3o", required: true }) }),
|
|
913
|
+
/* @__PURE__ */ jsx(Field, { label: "Slug *", children: /* @__PURE__ */ jsx(Input, { name: "slug", placeholder: "minha-org", required: true }) }),
|
|
914
|
+
createError && /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600", children: createError }),
|
|
915
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
916
|
+
/* @__PURE__ */ jsx(
|
|
917
|
+
Button,
|
|
918
|
+
{
|
|
919
|
+
onClick: () => setTab("info"),
|
|
920
|
+
size: "sm",
|
|
921
|
+
tone: "ghost",
|
|
922
|
+
type: "button",
|
|
923
|
+
children: "Cancelar"
|
|
924
|
+
}
|
|
636
925
|
),
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
] }),
|
|
648
|
-
org.id === currentOrg?.id && /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-slate-900 px-2 py-0.5 text-[10px] font-medium text-white", children: "Ativa" })
|
|
649
|
-
]
|
|
650
|
-
},
|
|
651
|
-
org.id
|
|
652
|
-
))
|
|
653
|
-
] })
|
|
654
|
-
] })
|
|
655
|
-
] }) });
|
|
656
|
-
}
|
|
657
|
-
function ManageOrganizationModal({
|
|
658
|
-
open,
|
|
659
|
-
onOpenChange
|
|
660
|
-
}) {
|
|
661
|
-
const {
|
|
662
|
-
createOrganization,
|
|
663
|
-
currentOrg,
|
|
664
|
-
organizations,
|
|
665
|
-
refreshOrganizations,
|
|
666
|
-
setCurrentOrg,
|
|
667
|
-
updateOrganization
|
|
668
|
-
} = useOrg();
|
|
669
|
-
const { listPermissions } = usePermissions();
|
|
670
|
-
const { listRoles } = useRoles();
|
|
671
|
-
const [tab, setTab] = useState("orgs");
|
|
672
|
-
const [roles, setRoles] = useState({ systemRoles: [], customRoles: [] });
|
|
673
|
-
const [permissions, setPermissions] = useState([]);
|
|
674
|
-
const [saving, setSaving] = useState(false);
|
|
675
|
-
const [saveSuccess, setSaveSuccess] = useState(false);
|
|
676
|
-
const [saveError, setSaveError] = useState(null);
|
|
677
|
-
const [creating, setCreating] = useState(false);
|
|
678
|
-
const [createError, setCreateError] = useState(null);
|
|
679
|
-
useEffect(() => {
|
|
680
|
-
if (!open) {
|
|
681
|
-
setTab("orgs");
|
|
682
|
-
setSaveError(null);
|
|
683
|
-
setSaveSuccess(false);
|
|
684
|
-
setCreating(false);
|
|
685
|
-
setCreateError(null);
|
|
686
|
-
}
|
|
687
|
-
}, [open]);
|
|
688
|
-
useEffect(() => {
|
|
689
|
-
if (!open || !currentOrg) return;
|
|
690
|
-
if (tab === "members" || tab === "roles") {
|
|
691
|
-
void listRoles({ organizationId: currentOrg.id }).then(setRoles).catch(() => setRoles({ systemRoles: [], customRoles: [] }));
|
|
692
|
-
void listPermissions({}).then(setPermissions).catch(() => setPermissions([]));
|
|
693
|
-
}
|
|
694
|
-
}, [currentOrg, listPermissions, listRoles, open, tab]);
|
|
695
|
-
async function onOrgSubmit(event) {
|
|
696
|
-
event.preventDefault();
|
|
697
|
-
if (!currentOrg) return;
|
|
698
|
-
const form = new FormData(event.currentTarget);
|
|
699
|
-
setSaving(true);
|
|
700
|
-
setSaveError(null);
|
|
701
|
-
setSaveSuccess(false);
|
|
702
|
-
try {
|
|
703
|
-
await updateOrganization(currentOrg.id, {
|
|
704
|
-
name: String(form.get("name") ?? ""),
|
|
705
|
-
description: String(form.get("description") ?? "") || null,
|
|
706
|
-
slug: String(form.get("slug") ?? ""),
|
|
707
|
-
domain: String(form.get("domain") ?? "") || null,
|
|
708
|
-
imageUrl: String(form.get("imageUrl") ?? "") || null,
|
|
709
|
-
faviconUrl: String(form.get("faviconUrl") ?? "") || null
|
|
710
|
-
});
|
|
711
|
-
setSaveSuccess(true);
|
|
712
|
-
setTimeout(() => setSaveSuccess(false), 2500);
|
|
713
|
-
} catch (err) {
|
|
714
|
-
setSaveError(err instanceof Error ? err.message : "Erro ao salvar.");
|
|
715
|
-
} finally {
|
|
716
|
-
setSaving(false);
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
async function onCreateOrg(event) {
|
|
720
|
-
event.preventDefault();
|
|
721
|
-
const form = new FormData(event.currentTarget);
|
|
722
|
-
setCreating(true);
|
|
723
|
-
setCreateError(null);
|
|
724
|
-
try {
|
|
725
|
-
const result = await createOrganization({
|
|
726
|
-
name: String(form.get("name") ?? ""),
|
|
727
|
-
slug: String(form.get("slug") ?? "")
|
|
728
|
-
});
|
|
729
|
-
if (result.success) {
|
|
730
|
-
await refreshOrganizations();
|
|
731
|
-
if (result.data?.id) {
|
|
732
|
-
void setCurrentOrg(result.data.id);
|
|
733
|
-
}
|
|
734
|
-
setTab("info");
|
|
735
|
-
} else {
|
|
736
|
-
setCreateError(result.error ?? "Erro ao criar organiza\xE7\xE3o.");
|
|
737
|
-
}
|
|
738
|
-
} catch (err) {
|
|
739
|
-
setCreateError(err instanceof Error ? err.message : "Erro ao criar.");
|
|
740
|
-
} finally {
|
|
741
|
-
setCreating(false);
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
if (!open) return null;
|
|
745
|
-
const orgTabs = [
|
|
746
|
-
{ id: "orgs", label: "Organiza\xE7\xF5es" },
|
|
747
|
-
{ id: "info", label: "Geral" },
|
|
748
|
-
{ id: "members", label: "Membros" },
|
|
749
|
-
{ id: "roles", label: "Roles" },
|
|
750
|
-
{ id: "new", label: "+ Nova org" }
|
|
751
|
-
];
|
|
752
|
-
return /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex max-h-[90vh] w-full max-w-2xl flex-col overflow-hidden rounded-2xl bg-white shadow-2xl", children: [
|
|
753
|
-
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center justify-between border-b border-slate-100 px-6 py-4", children: [
|
|
754
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
755
|
-
currentOrg?.imageUrl ? /* @__PURE__ */ jsx(
|
|
756
|
-
"img",
|
|
757
|
-
{
|
|
758
|
-
alt: currentOrg.name,
|
|
759
|
-
className: "h-8 w-8 rounded-lg object-cover",
|
|
760
|
-
src: currentOrg.imageUrl
|
|
761
|
-
}
|
|
762
|
-
) : /* @__PURE__ */ jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-slate-100 text-xs font-semibold text-slate-600", children: (currentOrg?.name ?? "O")[0]?.toUpperCase() }),
|
|
763
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
764
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-slate-900", children: currentOrg?.name ?? "Organiza\xE7\xE3o" }),
|
|
765
|
-
currentOrg?.slug && /* @__PURE__ */ jsxs("p", { className: "text-xs text-slate-500", children: [
|
|
766
|
-
"/",
|
|
767
|
-
currentOrg.slug
|
|
926
|
+
/* @__PURE__ */ jsx(
|
|
927
|
+
Button,
|
|
928
|
+
{
|
|
929
|
+
disabled: creating,
|
|
930
|
+
size: "sm",
|
|
931
|
+
tone: "primary",
|
|
932
|
+
type: "submit",
|
|
933
|
+
children: creating ? "Criando\u2026" : "Criar organiza\xE7\xE3o"
|
|
934
|
+
}
|
|
935
|
+
)
|
|
768
936
|
] })
|
|
769
|
-
] })
|
|
770
|
-
] }),
|
|
771
|
-
/* @__PURE__ */ jsx(
|
|
772
|
-
"button",
|
|
773
|
-
{
|
|
774
|
-
"aria-label": "Fechar",
|
|
775
|
-
className: "rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-700",
|
|
776
|
-
onClick: () => onOpenChange(false),
|
|
777
|
-
type: "button",
|
|
778
|
-
children: "\u2715"
|
|
779
|
-
}
|
|
780
|
-
)
|
|
781
|
-
] }),
|
|
782
|
-
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 gap-1 border-b border-slate-100 px-6 pt-3", children: orgTabs.map((t) => /* @__PURE__ */ jsx(
|
|
783
|
-
"button",
|
|
784
|
-
{
|
|
785
|
-
className: cx(
|
|
786
|
-
"mb-[-1px] border-b-2 px-3 pb-2.5 text-xs font-medium transition",
|
|
787
|
-
tab === t.id ? "border-slate-900 text-slate-900" : "border-transparent text-slate-500 hover:text-slate-700"
|
|
788
|
-
),
|
|
789
|
-
onClick: () => setTab(t.id),
|
|
790
|
-
type: "button",
|
|
791
|
-
children: t.label
|
|
792
|
-
},
|
|
793
|
-
t.id
|
|
794
|
-
)) }),
|
|
795
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-6 py-5", children: [
|
|
796
|
-
!currentOrg && /* @__PURE__ */ jsx("p", { className: "py-8 text-center text-sm text-slate-400", children: "Nenhuma organiza\xE7\xE3o selecionada." }),
|
|
797
|
-
tab === "orgs" && /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
798
|
-
organizations.length === 0 && /* @__PURE__ */ jsx("p", { className: "py-8 text-center text-sm text-slate-400", children: "Nenhuma organiza\xE7\xE3o dispon\xEDvel." }),
|
|
799
|
-
organizations.map((org) => /* @__PURE__ */ jsxs(
|
|
800
|
-
"button",
|
|
801
|
-
{
|
|
802
|
-
className: cx(
|
|
803
|
-
"flex w-full items-center gap-3 rounded-xl border p-3 text-left transition",
|
|
804
|
-
org.id === currentOrg?.id ? "border-slate-900 bg-slate-50" : "border-slate-200 hover:border-slate-300 hover:bg-slate-50"
|
|
805
|
-
),
|
|
806
|
-
onClick: () => {
|
|
807
|
-
void setCurrentOrg(org.id);
|
|
808
|
-
onOpenChange(false);
|
|
809
|
-
},
|
|
810
|
-
type: "button",
|
|
811
|
-
children: [
|
|
812
|
-
/* @__PURE__ */ jsx(Avatar, { name: org.name, size: "sm", src: org.imageUrl }),
|
|
813
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
814
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-slate-900", children: org.name }),
|
|
815
|
-
/* @__PURE__ */ jsxs("p", { className: "truncate text-xs text-slate-500", children: [
|
|
816
|
-
"/",
|
|
817
|
-
org.slug
|
|
818
|
-
] })
|
|
819
|
-
] }),
|
|
820
|
-
org.id === currentOrg?.id && /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-slate-900 px-2 py-0.5 text-[10px] font-medium text-white", children: "Ativa" })
|
|
821
|
-
]
|
|
822
|
-
},
|
|
823
|
-
org.id
|
|
824
|
-
))
|
|
825
|
-
] }),
|
|
826
|
-
tab === "info" && currentOrg && /* @__PURE__ */ jsxs("form", { className: "grid gap-4", onSubmit: onOrgSubmit, children: [
|
|
827
|
-
/* @__PURE__ */ jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [
|
|
828
|
-
/* @__PURE__ */ jsx(Field, { label: "Nome *", children: /* @__PURE__ */ jsx(Input, { defaultValue: currentOrg.name, name: "name", required: true }) }),
|
|
829
|
-
/* @__PURE__ */ jsx(Field, { label: "Slug *", children: /* @__PURE__ */ jsx(Input, { defaultValue: currentOrg.slug, name: "slug", required: true }) })
|
|
830
|
-
] }),
|
|
831
|
-
/* @__PURE__ */ jsx(Field, { label: "Descri\xE7\xE3o", children: /* @__PURE__ */ jsx(
|
|
832
|
-
Textarea,
|
|
833
|
-
{
|
|
834
|
-
defaultValue: currentOrg.description ?? "",
|
|
835
|
-
name: "description",
|
|
836
|
-
placeholder: "Descreva a organiza\xE7\xE3o\u2026"
|
|
837
|
-
}
|
|
838
|
-
) }),
|
|
839
|
-
/* @__PURE__ */ jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [
|
|
840
|
-
/* @__PURE__ */ jsx(Field, { label: "Dom\xEDnio", children: /* @__PURE__ */ jsx(
|
|
841
|
-
Input,
|
|
842
|
-
{
|
|
843
|
-
defaultValue: currentOrg.domain ?? "",
|
|
844
|
-
name: "domain",
|
|
845
|
-
placeholder: "acme.com"
|
|
846
|
-
}
|
|
847
|
-
) }),
|
|
848
|
-
/* @__PURE__ */ jsx(Field, { label: "URL da imagem", children: /* @__PURE__ */ jsx(
|
|
849
|
-
Input,
|
|
850
|
-
{
|
|
851
|
-
defaultValue: currentOrg.imageUrl ?? "",
|
|
852
|
-
name: "imageUrl",
|
|
853
|
-
placeholder: "https://..."
|
|
854
|
-
}
|
|
855
|
-
) })
|
|
856
937
|
] }),
|
|
857
|
-
/* @__PURE__ */
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
Button,
|
|
869
|
-
{
|
|
870
|
-
disabled: saving,
|
|
871
|
-
size: "sm",
|
|
872
|
-
tone: "primary",
|
|
873
|
-
type: "submit",
|
|
874
|
-
children: saving ? "Salvando\u2026" : "Salvar organiza\xE7\xE3o"
|
|
875
|
-
}
|
|
876
|
-
) })
|
|
877
|
-
] }),
|
|
878
|
-
tab === "members" && currentOrg && /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
879
|
-
(currentOrg.members ?? []).length === 0 && /* @__PURE__ */ jsx("p", { className: "py-8 text-center text-sm text-slate-400", children: "Nenhum membro nesta organiza\xE7\xE3o." }),
|
|
880
|
-
(currentOrg.members ?? []).map((member) => /* @__PURE__ */ jsxs(
|
|
881
|
-
"div",
|
|
882
|
-
{
|
|
883
|
-
className: "flex items-center gap-3 rounded-xl border border-slate-200 p-4",
|
|
884
|
-
children: [
|
|
885
|
-
/* @__PURE__ */ jsx(
|
|
886
|
-
Avatar,
|
|
887
|
-
{
|
|
888
|
-
name: member.user.name ?? member.user.email,
|
|
889
|
-
size: "sm",
|
|
890
|
-
src: member.user.imageUrl
|
|
891
|
-
}
|
|
892
|
-
),
|
|
893
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
894
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-slate-900", children: member.user.name ?? member.user.email }),
|
|
895
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-xs text-slate-500", children: member.user.email })
|
|
896
|
-
] }),
|
|
897
|
-
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 flex-wrap justify-end gap-1", children: (member.roleAssignments ?? []).map((a) => /* @__PURE__ */ jsx(
|
|
898
|
-
"span",
|
|
938
|
+
tab === "roles" && /* @__PURE__ */ jsxs("div", { className: "grid gap-5 sm:grid-cols-2", children: [
|
|
939
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
940
|
+
/* @__PURE__ */ jsxs("h3", { className: "mb-3 text-xs font-semibold uppercase tracking-wider text-slate-400", children: [
|
|
941
|
+
"Roles (",
|
|
942
|
+
roles.systemRoles.length + roles.customRoles.length,
|
|
943
|
+
")"
|
|
944
|
+
] }),
|
|
945
|
+
/* @__PURE__ */ jsxs("div", { className: "max-h-[280px] space-y-2 overflow-y-auto pr-1", children: [
|
|
946
|
+
roles.systemRoles.length === 0 && roles.customRoles.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-400", children: "Nenhuma role." }),
|
|
947
|
+
[...roles.systemRoles, ...roles.customRoles].map((role) => /* @__PURE__ */ jsxs(
|
|
948
|
+
"div",
|
|
899
949
|
{
|
|
900
|
-
className: "
|
|
901
|
-
children:
|
|
950
|
+
className: "overflow-hidden rounded-xl border border-slate-200 p-3",
|
|
951
|
+
children: [
|
|
952
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold text-slate-900", children: role.name }),
|
|
953
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-xs text-slate-400", children: role.key }),
|
|
954
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-1 text-xs text-slate-500", children: [
|
|
955
|
+
role.permissions.length,
|
|
956
|
+
" permission",
|
|
957
|
+
role.permissions.length !== 1 ? "s" : ""
|
|
958
|
+
] })
|
|
959
|
+
]
|
|
902
960
|
},
|
|
903
|
-
|
|
904
|
-
))
|
|
905
|
-
]
|
|
906
|
-
},
|
|
907
|
-
member.id
|
|
908
|
-
))
|
|
909
|
-
] }),
|
|
910
|
-
tab === "new" && /* @__PURE__ */ jsxs("form", { className: "grid gap-4", onSubmit: onCreateOrg, children: [
|
|
911
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "Crie uma nova organiza\xE7\xE3o e alterne para ela automaticamente." }),
|
|
912
|
-
/* @__PURE__ */ jsx(Field, { label: "Nome *", children: /* @__PURE__ */ jsx(Input, { name: "name", placeholder: "Minha organiza\xE7\xE3o", required: true }) }),
|
|
913
|
-
/* @__PURE__ */ jsx(Field, { label: "Slug *", children: /* @__PURE__ */ jsx(Input, { name: "slug", placeholder: "minha-org", required: true }) }),
|
|
914
|
-
createError && /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-red-50 px-3 py-2 text-xs text-red-600", children: createError }),
|
|
915
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
916
|
-
/* @__PURE__ */ jsx(
|
|
917
|
-
Button,
|
|
918
|
-
{
|
|
919
|
-
onClick: () => setTab("info"),
|
|
920
|
-
size: "sm",
|
|
921
|
-
tone: "ghost",
|
|
922
|
-
type: "button",
|
|
923
|
-
children: "Cancelar"
|
|
924
|
-
}
|
|
925
|
-
),
|
|
926
|
-
/* @__PURE__ */ jsx(
|
|
927
|
-
Button,
|
|
928
|
-
{
|
|
929
|
-
disabled: creating,
|
|
930
|
-
size: "sm",
|
|
931
|
-
tone: "primary",
|
|
932
|
-
type: "submit",
|
|
933
|
-
children: creating ? "Criando\u2026" : "Criar organiza\xE7\xE3o"
|
|
934
|
-
}
|
|
935
|
-
)
|
|
936
|
-
] })
|
|
937
|
-
] }),
|
|
938
|
-
tab === "roles" && /* @__PURE__ */ jsxs("div", { className: "grid gap-5 sm:grid-cols-2", children: [
|
|
939
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
940
|
-
/* @__PURE__ */ jsxs("h3", { className: "mb-3 text-xs font-semibold uppercase tracking-wider text-slate-400", children: [
|
|
941
|
-
"Roles (",
|
|
942
|
-
roles.systemRoles.length + roles.customRoles.length,
|
|
943
|
-
")"
|
|
944
|
-
] }),
|
|
945
|
-
/* @__PURE__ */ jsxs("div", { className: "max-h-[280px] space-y-2 overflow-y-auto pr-1", children: [
|
|
946
|
-
roles.systemRoles.length === 0 && roles.customRoles.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-400", children: "Nenhuma role." }),
|
|
947
|
-
[...roles.systemRoles, ...roles.customRoles].map((role) => /* @__PURE__ */ jsxs(
|
|
948
|
-
"div",
|
|
949
|
-
{
|
|
950
|
-
className: "overflow-hidden rounded-xl border border-slate-200 p-3",
|
|
951
|
-
children: [
|
|
952
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold text-slate-900", children: role.name }),
|
|
953
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-xs text-slate-400", children: role.key }),
|
|
954
|
-
/* @__PURE__ */ jsxs("p", { className: "mt-1 text-xs text-slate-500", children: [
|
|
955
|
-
role.permissions.length,
|
|
956
|
-
" permission",
|
|
957
|
-
role.permissions.length !== 1 ? "s" : ""
|
|
958
|
-
] })
|
|
959
|
-
]
|
|
960
|
-
},
|
|
961
|
-
role.id
|
|
962
|
-
))
|
|
963
|
-
] })
|
|
964
|
-
] }),
|
|
965
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
966
|
-
/* @__PURE__ */ jsxs("h3", { className: "mb-3 text-xs font-semibold uppercase tracking-wider text-slate-400", children: [
|
|
967
|
-
"Permissions (",
|
|
968
|
-
permissions.length,
|
|
969
|
-
")"
|
|
961
|
+
role.id
|
|
962
|
+
))
|
|
963
|
+
] })
|
|
970
964
|
] }),
|
|
971
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
965
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
966
|
+
/* @__PURE__ */ jsxs("h3", { className: "mb-3 text-xs font-semibold uppercase tracking-wider text-slate-400", children: [
|
|
967
|
+
"Permissions (",
|
|
968
|
+
permissions.length,
|
|
969
|
+
")"
|
|
970
|
+
] }),
|
|
971
|
+
/* @__PURE__ */ jsxs("div", { className: "max-h-[280px] space-y-2 overflow-y-auto pr-1", children: [
|
|
972
|
+
permissions.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-400", children: "Nenhuma permission." }),
|
|
973
|
+
permissions.map((permission) => /* @__PURE__ */ jsxs(
|
|
974
|
+
"div",
|
|
975
|
+
{
|
|
976
|
+
className: "overflow-hidden rounded-xl border border-slate-200 p-3",
|
|
977
|
+
children: [
|
|
978
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold text-slate-900", children: permission.key }),
|
|
979
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-xs text-slate-400", children: permission.category ?? "custom" })
|
|
980
|
+
]
|
|
981
|
+
},
|
|
982
|
+
permission.id
|
|
983
|
+
))
|
|
984
|
+
] })
|
|
984
985
|
] })
|
|
985
986
|
] })
|
|
986
987
|
] })
|
|
987
|
-
] })
|
|
988
|
-
|
|
988
|
+
] }) });
|
|
989
|
+
}
|
|
990
|
+
return {
|
|
991
|
+
SignInButton,
|
|
992
|
+
SignOutButton,
|
|
993
|
+
AccountSwitcher,
|
|
994
|
+
OrgSwitcher,
|
|
995
|
+
UserButton,
|
|
996
|
+
OrganizationButton,
|
|
997
|
+
ProfileModal,
|
|
998
|
+
ManageOrganizationModal
|
|
999
|
+
};
|
|
989
1000
|
}
|
|
990
1001
|
export {
|
|
991
|
-
AccountSwitcher,
|
|
992
1002
|
Avatar,
|
|
993
|
-
ManageOrganizationModal,
|
|
994
1003
|
Modal,
|
|
995
|
-
|
|
996
|
-
OrganizationButton,
|
|
997
|
-
ProfileModal,
|
|
998
|
-
SignInButton,
|
|
999
|
-
SignOutButton,
|
|
1000
|
-
UserButton
|
|
1004
|
+
createAuthElements
|
|
1001
1005
|
};
|
|
1002
1006
|
//# sourceMappingURL=index.js.map
|