@greatapps/greatauth-ui 0.3.6 → 0.3.8

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.js CHANGED
@@ -7,15 +7,15 @@ var { useSession, signIn, signUp, signOut } = authClient;
7
7
  import { NextResponse } from "next/server";
8
8
  function createAuthMiddleware(config) {
9
9
  const { publicPaths, preserveSearchParams = false } = config;
10
- return function middleware(request) {
11
- const { pathname, search } = request.nextUrl;
10
+ return function middleware(request2) {
11
+ const { pathname, search } = request2.nextUrl;
12
12
  if (publicPaths.some((path) => pathname.startsWith(path))) {
13
13
  return NextResponse.next();
14
14
  }
15
- const sessionToken = request.cookies.get("better-auth.session_token")?.value || request.cookies.get("__Secure-better-auth.session_token")?.value;
15
+ const sessionToken = request2.cookies.get("better-auth.session_token")?.value || request2.cookies.get("__Secure-better-auth.session_token")?.value;
16
16
  if (!sessionToken) {
17
17
  const callbackUrl = preserveSearchParams ? pathname + search : pathname;
18
- const loginUrl = new URL("/login", request.url);
18
+ const loginUrl = new URL("/login", request2.url);
19
19
  loginUrl.searchParams.set("callbackUrl", callbackUrl);
20
20
  return NextResponse.redirect(loginUrl);
21
21
  }
@@ -346,6 +346,16 @@ function SheetDescription({
346
346
 
347
347
  // src/components/ui/skeleton.tsx
348
348
  import { jsx as jsx6 } from "react/jsx-runtime";
349
+ function Skeleton({ className, ...props }) {
350
+ return /* @__PURE__ */ jsx6(
351
+ "div",
352
+ {
353
+ "data-slot": "skeleton",
354
+ className: cn("bg-muted rounded-md animate-pulse", className),
355
+ ...props
356
+ }
357
+ );
358
+ }
349
359
 
350
360
  // src/components/ui/sidebar.tsx
351
361
  import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
@@ -1312,16 +1322,1426 @@ function LoginForm({ config }) {
1312
1322
  /* @__PURE__ */ jsx18("p", { className: "mt-6 text-center text-xs text-muted-foreground", children: config.footerText || "Acesso restrito a utilizadores autorizados" })
1313
1323
  ] }) });
1314
1324
  }
1325
+
1326
+ // src/components/entity-avatar.tsx
1327
+ import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
1328
+ var COLORS = [
1329
+ "bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300",
1330
+ "bg-orange-100 text-orange-700 dark:bg-orange-900 dark:text-orange-300",
1331
+ "bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300",
1332
+ "bg-emerald-100 text-emerald-700 dark:bg-emerald-900 dark:text-emerald-300",
1333
+ "bg-cyan-100 text-cyan-700 dark:bg-cyan-900 dark:text-cyan-300",
1334
+ "bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300",
1335
+ "bg-violet-100 text-violet-700 dark:bg-violet-900 dark:text-violet-300",
1336
+ "bg-pink-100 text-pink-700 dark:bg-pink-900 dark:text-pink-300"
1337
+ ];
1338
+ var SIZE_MAP = {
1339
+ xs: "h-5 w-5 text-[9px]",
1340
+ sm: "h-6 w-6 text-[10px]",
1341
+ md: "h-8 w-8 text-xs",
1342
+ lg: "h-10 w-10 text-sm",
1343
+ xl: "h-16 w-16 text-lg"
1344
+ };
1345
+ function hashCode(str) {
1346
+ let hash = 0;
1347
+ for (let i = 0; i < str.length; i++) {
1348
+ hash = str.charCodeAt(i) + ((hash << 5) - hash);
1349
+ }
1350
+ return Math.abs(hash);
1351
+ }
1352
+ function getInitials(name) {
1353
+ const parts = name.trim().split(/\s+/);
1354
+ if (parts.length >= 2) {
1355
+ return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
1356
+ }
1357
+ return (name[0] || "?").toUpperCase();
1358
+ }
1359
+ function EntityAvatar({
1360
+ photo,
1361
+ name,
1362
+ size = "md",
1363
+ className
1364
+ }) {
1365
+ const displayName = name || "?";
1366
+ const color = COLORS[hashCode(displayName) % COLORS.length];
1367
+ const initials = getInitials(displayName);
1368
+ return /* @__PURE__ */ jsxs11(Avatar, { className: cn(SIZE_MAP[size], className), children: [
1369
+ photo && /* @__PURE__ */ jsx19(
1370
+ AvatarImage,
1371
+ {
1372
+ src: photo,
1373
+ alt: displayName,
1374
+ className: "object-cover"
1375
+ }
1376
+ ),
1377
+ /* @__PURE__ */ jsx19(AvatarFallback, { className: cn("font-medium", color), children: initials })
1378
+ ] });
1379
+ }
1380
+
1381
+ // src/components/image-crop-upload.tsx
1382
+ import { useCallback as useCallback3, useRef, useState as useState4 } from "react";
1383
+ import Cropper from "react-easy-crop";
1384
+
1385
+ // src/components/ui/dialog.tsx
1386
+ import { Dialog as DialogPrimitive } from "radix-ui";
1387
+ import { X as X2 } from "lucide-react";
1388
+ import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
1389
+ function Dialog({
1390
+ ...props
1391
+ }) {
1392
+ return /* @__PURE__ */ jsx20(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
1393
+ }
1394
+ function DialogPortal({
1395
+ ...props
1396
+ }) {
1397
+ return /* @__PURE__ */ jsx20(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
1398
+ }
1399
+ function DialogOverlay({
1400
+ className,
1401
+ ...props
1402
+ }) {
1403
+ return /* @__PURE__ */ jsx20(
1404
+ DialogPrimitive.Overlay,
1405
+ {
1406
+ "data-slot": "dialog-overlay",
1407
+ className: cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50", className),
1408
+ ...props
1409
+ }
1410
+ );
1411
+ }
1412
+ function DialogContent({
1413
+ className,
1414
+ children,
1415
+ showCloseButton = true,
1416
+ ...props
1417
+ }) {
1418
+ return /* @__PURE__ */ jsxs12(DialogPortal, { children: [
1419
+ /* @__PURE__ */ jsx20(DialogOverlay, {}),
1420
+ /* @__PURE__ */ jsxs12(
1421
+ DialogPrimitive.Content,
1422
+ {
1423
+ "data-slot": "dialog-content",
1424
+ className: cn(
1425
+ "bg-background data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid max-w-[calc(100%-2rem)] gap-6 rounded-xl p-6 text-sm ring-1 duration-100 sm:max-w-md fixed top-1/2 left-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 outline-none",
1426
+ className
1427
+ ),
1428
+ ...props,
1429
+ children: [
1430
+ children,
1431
+ showCloseButton && /* @__PURE__ */ jsx20(DialogPrimitive.Close, { "data-slot": "dialog-close", asChild: true, children: /* @__PURE__ */ jsxs12(Button, { variant: "ghost", className: "absolute top-4 right-4", size: "icon-sm", children: [
1432
+ /* @__PURE__ */ jsx20(X2, {}),
1433
+ /* @__PURE__ */ jsx20("span", { className: "sr-only", children: "Close" })
1434
+ ] }) })
1435
+ ]
1436
+ }
1437
+ )
1438
+ ] });
1439
+ }
1440
+ function DialogHeader({ className, ...props }) {
1441
+ return /* @__PURE__ */ jsx20(
1442
+ "div",
1443
+ {
1444
+ "data-slot": "dialog-header",
1445
+ className: cn("gap-2 flex flex-col", className),
1446
+ ...props
1447
+ }
1448
+ );
1449
+ }
1450
+ function DialogFooter({
1451
+ className,
1452
+ children,
1453
+ ...props
1454
+ }) {
1455
+ return /* @__PURE__ */ jsx20(
1456
+ "div",
1457
+ {
1458
+ "data-slot": "dialog-footer",
1459
+ className: cn(
1460
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
1461
+ className
1462
+ ),
1463
+ ...props,
1464
+ children
1465
+ }
1466
+ );
1467
+ }
1468
+ function DialogTitle({
1469
+ className,
1470
+ ...props
1471
+ }) {
1472
+ return /* @__PURE__ */ jsx20(
1473
+ DialogPrimitive.Title,
1474
+ {
1475
+ "data-slot": "dialog-title",
1476
+ className: cn("leading-none font-medium", className),
1477
+ ...props
1478
+ }
1479
+ );
1480
+ }
1481
+
1482
+ // src/components/ui/slider.tsx
1483
+ import * as React2 from "react";
1484
+ import { Slider as SliderPrimitive } from "radix-ui";
1485
+ import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
1486
+ function Slider({
1487
+ className,
1488
+ defaultValue,
1489
+ value,
1490
+ min = 0,
1491
+ max = 100,
1492
+ ...props
1493
+ }) {
1494
+ const _values = React2.useMemo(
1495
+ () => Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max],
1496
+ [value, defaultValue, min, max]
1497
+ );
1498
+ return /* @__PURE__ */ jsxs13(
1499
+ SliderPrimitive.Root,
1500
+ {
1501
+ "data-slot": "slider",
1502
+ defaultValue,
1503
+ value,
1504
+ min,
1505
+ max,
1506
+ className: cn(
1507
+ "data-vertical:min-h-40 relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-vertical:h-full data-vertical:w-auto data-vertical:flex-col",
1508
+ className
1509
+ ),
1510
+ ...props,
1511
+ children: [
1512
+ /* @__PURE__ */ jsx21(
1513
+ SliderPrimitive.Track,
1514
+ {
1515
+ "data-slot": "slider-track",
1516
+ className: "bg-muted rounded-full data-horizontal:h-1.5 data-vertical:w-1.5 relative grow overflow-hidden data-horizontal:w-full data-vertical:h-full",
1517
+ children: /* @__PURE__ */ jsx21(
1518
+ SliderPrimitive.Range,
1519
+ {
1520
+ "data-slot": "slider-range",
1521
+ className: "bg-primary absolute select-none data-horizontal:h-full data-vertical:w-full"
1522
+ }
1523
+ )
1524
+ }
1525
+ ),
1526
+ Array.from({ length: _values.length }, (_, index) => /* @__PURE__ */ jsx21(
1527
+ SliderPrimitive.Thumb,
1528
+ {
1529
+ "data-slot": "slider-thumb",
1530
+ className: "border-primary ring-ring/50 size-4 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden block shrink-0 select-none disabled:pointer-events-none disabled:opacity-50"
1531
+ },
1532
+ index
1533
+ ))
1534
+ ]
1535
+ }
1536
+ );
1537
+ }
1538
+
1539
+ // src/components/image-crop-upload.tsx
1540
+ import { toast } from "sonner";
1541
+ import { Camera, Trash2 } from "lucide-react";
1542
+
1543
+ // src/lib/image-utils.ts
1544
+ async function getCroppedImage(imageSrc, cropArea, outputSize = 400, quality = 0.85) {
1545
+ const image = await loadImage(imageSrc);
1546
+ const canvas = document.createElement("canvas");
1547
+ canvas.width = outputSize;
1548
+ canvas.height = outputSize;
1549
+ const ctx = canvas.getContext("2d");
1550
+ if (!ctx) throw new Error("Canvas context not available");
1551
+ ctx.drawImage(
1552
+ image,
1553
+ cropArea.x,
1554
+ cropArea.y,
1555
+ cropArea.width,
1556
+ cropArea.height,
1557
+ 0,
1558
+ 0,
1559
+ outputSize,
1560
+ outputSize
1561
+ );
1562
+ const blob = await new Promise((resolve, reject) => {
1563
+ canvas.toBlob(
1564
+ (b) => b ? resolve(b) : reject(new Error("Failed to create blob")),
1565
+ "image/webp",
1566
+ quality
1567
+ );
1568
+ });
1569
+ return blobToBase64(blob);
1570
+ }
1571
+ function loadImage(src) {
1572
+ return new Promise((resolve, reject) => {
1573
+ const img = new Image();
1574
+ img.crossOrigin = "anonymous";
1575
+ img.onload = () => resolve(img);
1576
+ img.onerror = reject;
1577
+ img.src = src;
1578
+ });
1579
+ }
1580
+ function blobToBase64(blob) {
1581
+ return new Promise((resolve, reject) => {
1582
+ const reader = new FileReader();
1583
+ reader.onload = () => {
1584
+ const result = reader.result;
1585
+ resolve(result.split(",")[1]);
1586
+ };
1587
+ reader.onerror = reject;
1588
+ reader.readAsDataURL(blob);
1589
+ });
1590
+ }
1591
+ var ACCEPTED_TYPES = ["image/png", "image/jpeg", "image/jpg", "image/webp"];
1592
+ var MAX_SIZE_BYTES = 5 * 1024 * 1024;
1593
+ function validateImageFile(file) {
1594
+ if (!ACCEPTED_TYPES.includes(file.type)) {
1595
+ return "Formato n\xE3o suportado. Use PNG, JPG ou WEBP";
1596
+ }
1597
+ if (file.size > MAX_SIZE_BYTES) {
1598
+ return "Imagem muito grande. M\xE1ximo: 5MB";
1599
+ }
1600
+ return null;
1601
+ }
1602
+ function fileToDataUrl(file) {
1603
+ return new Promise((resolve, reject) => {
1604
+ const reader = new FileReader();
1605
+ reader.onload = () => resolve(reader.result);
1606
+ reader.onerror = reject;
1607
+ reader.readAsDataURL(file);
1608
+ });
1609
+ }
1610
+
1611
+ // src/components/image-crop-upload.tsx
1612
+ import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
1613
+ var STORAGE_URL_MAP = {
1614
+ users: "https://gauth-r2-storage.greatlabs.workers.dev",
1615
+ agents: "https://gagents-r2-storage.greatlabs.workers.dev",
1616
+ contacts: "https://gchat-r2-storage.greatlabs.workers.dev",
1617
+ professionals: "https://gclinic-r2-storage.greatlabs.workers.dev",
1618
+ patients: "https://gclinic-r2-storage.greatlabs.workers.dev",
1619
+ clinics: "https://gclinic-r2-storage.greatlabs.workers.dev"
1620
+ };
1621
+ var BUCKET_MAP = {
1622
+ users: "gauth-r1-storage",
1623
+ agents: "gagents-r1-storage",
1624
+ contacts: "gchat-r1-storage",
1625
+ professionals: "gclinic-r1-storage",
1626
+ patients: "gclinic-r1-storage",
1627
+ clinics: "gclinic-r1-storage"
1628
+ };
1629
+ var DEFAULT_STORAGE_URL = "https://gauth-r2-storage.greatlabs.workers.dev";
1630
+ var DEFAULT_BUCKET = "gauth-r1-storage";
1631
+ function ImageCropUpload({
1632
+ value,
1633
+ onChange,
1634
+ onRemove,
1635
+ entityType,
1636
+ entityId,
1637
+ idAccount,
1638
+ name,
1639
+ disabled = false
1640
+ }) {
1641
+ const [imageSrc, setImageSrc] = useState4(null);
1642
+ const [crop, setCrop] = useState4({ x: 0, y: 0 });
1643
+ const [zoom, setZoom] = useState4(1);
1644
+ const [croppedArea, setCroppedArea] = useState4(null);
1645
+ const [isOpen, setIsOpen] = useState4(false);
1646
+ const [isUploading, setIsUploading] = useState4(false);
1647
+ const inputRef = useRef(null);
1648
+ const onCropComplete = useCallback3((_, croppedAreaPixels) => {
1649
+ setCroppedArea(croppedAreaPixels);
1650
+ }, []);
1651
+ const handleFileSelect = useCallback3(
1652
+ async (e) => {
1653
+ const file = e.target.files?.[0];
1654
+ if (!file) return;
1655
+ const error = validateImageFile(file);
1656
+ if (error) {
1657
+ toast.error(error);
1658
+ if (inputRef.current) inputRef.current.value = "";
1659
+ return;
1660
+ }
1661
+ const dataUrl = await fileToDataUrl(file);
1662
+ setImageSrc(dataUrl);
1663
+ setCrop({ x: 0, y: 0 });
1664
+ setZoom(1);
1665
+ setIsOpen(true);
1666
+ if (inputRef.current) inputRef.current.value = "";
1667
+ },
1668
+ []
1669
+ );
1670
+ const handleConfirmCrop = useCallback3(async () => {
1671
+ if (!imageSrc || !croppedArea) return;
1672
+ setIsUploading(true);
1673
+ try {
1674
+ const base64 = await getCroppedImage(imageSrc, croppedArea);
1675
+ const path = `${entityType}/${idAccount}/${entityId || "temp"}.webp`;
1676
+ const storageUrl = STORAGE_URL_MAP[entityType] || DEFAULT_STORAGE_URL;
1677
+ const bucket = BUCKET_MAP[entityType] || DEFAULT_BUCKET;
1678
+ const res = await fetch(storageUrl, {
1679
+ method: "POST",
1680
+ headers: { "Content-Type": "application/json" },
1681
+ body: JSON.stringify({ file: base64, bucket, path })
1682
+ });
1683
+ const data = await res.json();
1684
+ if (data.status !== 1) {
1685
+ throw new Error(data.message || "Erro ao enviar imagem");
1686
+ }
1687
+ const publicUrl = `${storageUrl}/${path}?t=${Date.now()}`;
1688
+ onChange(publicUrl);
1689
+ toast.success("Imagem atualizada");
1690
+ } catch (err) {
1691
+ toast.error(
1692
+ err instanceof Error ? err.message : "Erro ao enviar imagem"
1693
+ );
1694
+ } finally {
1695
+ setIsUploading(false);
1696
+ setIsOpen(false);
1697
+ setImageSrc(null);
1698
+ }
1699
+ }, [imageSrc, croppedArea, entityType, entityId, idAccount, onChange]);
1700
+ const handleRemove = useCallback3(async () => {
1701
+ if (!value) return;
1702
+ try {
1703
+ const path = `${entityType}/${idAccount}/${entityId || "temp"}.webp`;
1704
+ const storageUrl = STORAGE_URL_MAP[entityType] || DEFAULT_STORAGE_URL;
1705
+ const bucket = BUCKET_MAP[entityType] || DEFAULT_BUCKET;
1706
+ await fetch(storageUrl, {
1707
+ method: "DELETE",
1708
+ headers: { "Content-Type": "application/json" },
1709
+ body: JSON.stringify({ bucket, path })
1710
+ });
1711
+ onRemove?.();
1712
+ toast.success("Imagem removida");
1713
+ } catch {
1714
+ toast.error("Erro ao remover imagem");
1715
+ }
1716
+ }, [value, entityType, entityId, idAccount, onRemove]);
1717
+ return /* @__PURE__ */ jsxs14("div", { className: "flex flex-col items-center gap-2", children: [
1718
+ /* @__PURE__ */ jsxs14("div", { className: "relative group", children: [
1719
+ /* @__PURE__ */ jsx22(EntityAvatar, { photo: value, name: name ?? null, size: "xl" }),
1720
+ !disabled && /* @__PURE__ */ jsx22(
1721
+ "button",
1722
+ {
1723
+ type: "button",
1724
+ onClick: () => inputRef.current?.click(),
1725
+ className: "absolute inset-0 flex items-center justify-center rounded-full bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer",
1726
+ children: /* @__PURE__ */ jsx22(Camera, { className: "h-5 w-5 text-white" })
1727
+ }
1728
+ )
1729
+ ] }),
1730
+ /* @__PURE__ */ jsx22(
1731
+ "input",
1732
+ {
1733
+ ref: inputRef,
1734
+ type: "file",
1735
+ accept: "image/png,image/jpeg,image/webp",
1736
+ onChange: handleFileSelect,
1737
+ className: "hidden",
1738
+ disabled
1739
+ }
1740
+ ),
1741
+ !disabled && value && /* @__PURE__ */ jsxs14(
1742
+ Button,
1743
+ {
1744
+ type: "button",
1745
+ variant: "ghost",
1746
+ size: "sm",
1747
+ onClick: handleRemove,
1748
+ className: "text-destructive hover:text-destructive",
1749
+ children: [
1750
+ /* @__PURE__ */ jsx22(Trash2, { className: "h-4 w-4 mr-1" }),
1751
+ "Remover"
1752
+ ]
1753
+ }
1754
+ ),
1755
+ /* @__PURE__ */ jsx22(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs14(DialogContent, { className: "sm:max-w-md", children: [
1756
+ /* @__PURE__ */ jsx22(DialogHeader, { children: /* @__PURE__ */ jsx22(DialogTitle, { children: "Recortar imagem" }) }),
1757
+ /* @__PURE__ */ jsx22("div", { className: "relative w-full h-72 bg-muted rounded-md overflow-hidden", children: imageSrc && /* @__PURE__ */ jsx22(
1758
+ Cropper,
1759
+ {
1760
+ image: imageSrc,
1761
+ crop,
1762
+ zoom,
1763
+ aspect: 1,
1764
+ onCropChange: setCrop,
1765
+ onZoomChange: setZoom,
1766
+ onCropComplete,
1767
+ cropShape: "round",
1768
+ showGrid: false
1769
+ }
1770
+ ) }),
1771
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-3 px-1", children: [
1772
+ /* @__PURE__ */ jsx22("span", { className: "text-sm text-muted-foreground whitespace-nowrap", children: "Zoom" }),
1773
+ /* @__PURE__ */ jsx22(
1774
+ Slider,
1775
+ {
1776
+ value: [zoom],
1777
+ onValueChange: (v) => setZoom(v[0]),
1778
+ min: 1,
1779
+ max: 3,
1780
+ step: 0.1,
1781
+ className: "flex-1"
1782
+ }
1783
+ )
1784
+ ] }),
1785
+ /* @__PURE__ */ jsxs14(DialogFooter, { children: [
1786
+ /* @__PURE__ */ jsx22(
1787
+ Button,
1788
+ {
1789
+ variant: "outline",
1790
+ onClick: () => {
1791
+ setIsOpen(false);
1792
+ setImageSrc(null);
1793
+ },
1794
+ disabled: isUploading,
1795
+ children: "Cancelar"
1796
+ }
1797
+ ),
1798
+ /* @__PURE__ */ jsx22(
1799
+ Button,
1800
+ {
1801
+ onClick: handleConfirmCrop,
1802
+ disabled: isUploading || !croppedArea,
1803
+ children: isUploading ? "Enviando..." : "Confirmar"
1804
+ }
1805
+ )
1806
+ ] })
1807
+ ] }) })
1808
+ ] });
1809
+ }
1810
+
1811
+ // src/hooks/use-users.ts
1812
+ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
1813
+ function buildUrl(config, path) {
1814
+ const lang = config.language || "pt-br";
1815
+ const idWl = config.idWl || "1";
1816
+ return `${config.gauthApiUrl}/v1/${lang}/${idWl}/accounts/${config.accountId}/${path}`;
1817
+ }
1818
+ async function request(url, token, options) {
1819
+ const res = await fetch(url, {
1820
+ headers: {
1821
+ "Content-Type": "application/json",
1822
+ Authorization: `Bearer ${token}`
1823
+ },
1824
+ ...options
1825
+ });
1826
+ if (!res.ok) {
1827
+ let message = `HTTP ${res.status}`;
1828
+ try {
1829
+ const b = await res.json();
1830
+ message = b.message || message;
1831
+ } catch {
1832
+ }
1833
+ throw new Error(message);
1834
+ }
1835
+ const json = await res.json();
1836
+ if (json.status === 0) throw new Error(json.message || "Opera\xE7\xE3o falhou");
1837
+ return json;
1838
+ }
1839
+ function useUsers(config, params) {
1840
+ return useQuery({
1841
+ queryKey: ["greatauth", "users", config.accountId, params],
1842
+ queryFn: () => {
1843
+ const qs = params ? "?" + new URLSearchParams(params).toString() : "";
1844
+ return request(buildUrl(config, `users${qs}`), config.token);
1845
+ },
1846
+ enabled: !!config.token && !!config.accountId,
1847
+ select: (res) => ({ data: res.data || [], total: res.total || 0 })
1848
+ });
1849
+ }
1850
+ function useCreateUser(config) {
1851
+ const qc = useQueryClient();
1852
+ return useMutation({
1853
+ mutationFn: (data) => request(buildUrl(config, "users"), config.token, {
1854
+ method: "POST",
1855
+ body: JSON.stringify(data)
1856
+ }),
1857
+ onSuccess: () => qc.invalidateQueries({ queryKey: ["greatauth", "users"] })
1858
+ });
1859
+ }
1860
+ function useUpdateUser(config) {
1861
+ const qc = useQueryClient();
1862
+ return useMutation({
1863
+ mutationFn: ({ id, body }) => request(buildUrl(config, `users/${id}`), config.token, {
1864
+ method: "PUT",
1865
+ body: JSON.stringify(body)
1866
+ }),
1867
+ onSuccess: () => qc.invalidateQueries({ queryKey: ["greatauth", "users"] })
1868
+ });
1869
+ }
1870
+ function useDeleteUser(config) {
1871
+ const qc = useQueryClient();
1872
+ return useMutation({
1873
+ mutationFn: (id) => request(buildUrl(config, `users/${id}`), config.token, { method: "DELETE" }),
1874
+ onSuccess: () => qc.invalidateQueries({ queryKey: ["greatauth", "users"] })
1875
+ });
1876
+ }
1877
+ function useResetPassword(config) {
1878
+ const qc = useQueryClient();
1879
+ return useMutation({
1880
+ mutationFn: (id) => request(buildUrl(config, `users/${id}/reset-password`), config.token, { method: "POST" }),
1881
+ onSuccess: () => qc.invalidateQueries({ queryKey: ["greatauth", "users"] })
1882
+ });
1883
+ }
1884
+
1885
+ // src/components/users/users-page.tsx
1886
+ import { useMemo as useMemo3, useState as useState7 } from "react";
1887
+
1888
+ // src/components/users/user-form-dialog.tsx
1889
+ import { useEffect as useEffect3, useState as useState5 } from "react";
1890
+
1891
+ // src/components/ui/select.tsx
1892
+ import { Select as SelectPrimitive } from "radix-ui";
1893
+ import { ChevronsUpDown, Check as Check2, ChevronUp as ChevronUp2, ChevronDown } from "lucide-react";
1894
+ import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
1895
+ function Select({
1896
+ ...props
1897
+ }) {
1898
+ return /* @__PURE__ */ jsx23(SelectPrimitive.Root, { "data-slot": "select", ...props });
1899
+ }
1900
+ function SelectValue({
1901
+ ...props
1902
+ }) {
1903
+ return /* @__PURE__ */ jsx23(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
1904
+ }
1905
+ function SelectTrigger({
1906
+ className,
1907
+ size = "default",
1908
+ children,
1909
+ ...props
1910
+ }) {
1911
+ return /* @__PURE__ */ jsxs15(
1912
+ SelectPrimitive.Trigger,
1913
+ {
1914
+ "data-slot": "select-trigger",
1915
+ "data-size": size,
1916
+ className: cn(
1917
+ "border-input data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 gap-1.5 rounded-md border bg-transparent py-2 pr-2 pl-2.5 text-sm shadow-xs transition-[color,box-shadow] focus-visible:ring-3 aria-invalid:ring-3 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:gap-1.5 [&_svg:not([class*='size-'])]:size-4 flex w-fit items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
1918
+ className
1919
+ ),
1920
+ ...props,
1921
+ children: [
1922
+ children,
1923
+ /* @__PURE__ */ jsx23(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx23(ChevronsUpDown, { className: "text-muted-foreground size-4 pointer-events-none" }) })
1924
+ ]
1925
+ }
1926
+ );
1927
+ }
1928
+ function SelectContent({
1929
+ className,
1930
+ children,
1931
+ position = "item-aligned",
1932
+ align = "center",
1933
+ ...props
1934
+ }) {
1935
+ return /* @__PURE__ */ jsx23(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs15(
1936
+ SelectPrimitive.Content,
1937
+ {
1938
+ "data-slot": "select-content",
1939
+ "data-align-trigger": position === "item-aligned",
1940
+ className: cn("bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 min-w-36 rounded-md shadow-md ring-1 duration-100 relative z-50 max-h-(--radix-select-content-available-height) origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto data-[align-trigger=true]:animate-none", position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className),
1941
+ position,
1942
+ align,
1943
+ ...props,
1944
+ children: [
1945
+ /* @__PURE__ */ jsx23(SelectScrollUpButton, {}),
1946
+ /* @__PURE__ */ jsx23(
1947
+ SelectPrimitive.Viewport,
1948
+ {
1949
+ "data-position": position,
1950
+ className: cn(
1951
+ "data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)",
1952
+ position === "popper" && ""
1953
+ ),
1954
+ children
1955
+ }
1956
+ ),
1957
+ /* @__PURE__ */ jsx23(SelectScrollDownButton, {})
1958
+ ]
1959
+ }
1960
+ ) });
1961
+ }
1962
+ function SelectItem({
1963
+ className,
1964
+ children,
1965
+ ...props
1966
+ }) {
1967
+ return /* @__PURE__ */ jsxs15(
1968
+ SelectPrimitive.Item,
1969
+ {
1970
+ "data-slot": "select-item",
1971
+ className: cn(
1972
+ "focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 relative flex w-full cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
1973
+ className
1974
+ ),
1975
+ ...props,
1976
+ children: [
1977
+ /* @__PURE__ */ jsx23("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ jsx23(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx23(Check2, { className: "pointer-events-none" }) }) }),
1978
+ /* @__PURE__ */ jsx23(SelectPrimitive.ItemText, { children })
1979
+ ]
1980
+ }
1981
+ );
1982
+ }
1983
+ function SelectScrollUpButton({
1984
+ className,
1985
+ ...props
1986
+ }) {
1987
+ return /* @__PURE__ */ jsx23(
1988
+ SelectPrimitive.ScrollUpButton,
1989
+ {
1990
+ "data-slot": "select-scroll-up-button",
1991
+ className: cn("bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4", className),
1992
+ ...props,
1993
+ children: /* @__PURE__ */ jsx23(ChevronUp2, {})
1994
+ }
1995
+ );
1996
+ }
1997
+ function SelectScrollDownButton({
1998
+ className,
1999
+ ...props
2000
+ }) {
2001
+ return /* @__PURE__ */ jsx23(
2002
+ SelectPrimitive.ScrollDownButton,
2003
+ {
2004
+ "data-slot": "select-scroll-down-button",
2005
+ className: cn("bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4", className),
2006
+ ...props,
2007
+ children: /* @__PURE__ */ jsx23(ChevronDown, {})
2008
+ }
2009
+ );
2010
+ }
2011
+
2012
+ // src/components/users/user-form-dialog.tsx
2013
+ import { Loader2 as Loader22 } from "lucide-react";
2014
+ import { toast as toast2 } from "sonner";
2015
+ import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
2016
+ var DEFAULT_PROFILES = [
2017
+ { value: "owner", label: "Propriet\xE1rio" },
2018
+ { value: "admin", label: "Administrador" },
2019
+ { value: "collaborator", label: "Colaborador" },
2020
+ { value: "attendant", label: "Atendente" },
2021
+ { value: "viewer", label: "Visualizador" }
2022
+ ];
2023
+ function UserFormDialog({
2024
+ open,
2025
+ onOpenChange,
2026
+ user,
2027
+ config,
2028
+ profileOptions,
2029
+ renderPhones
2030
+ }) {
2031
+ const isEditing = !!user;
2032
+ const createUser = useCreateUser(config);
2033
+ const updateUser = useUpdateUser(config);
2034
+ const profiles = profileOptions || DEFAULT_PROFILES;
2035
+ const [name, setName] = useState5("");
2036
+ const [lastName, setLastName] = useState5("");
2037
+ const [email, setEmail] = useState5("");
2038
+ const [profile, setProfile] = useState5("collaborator");
2039
+ const [password, setPassword] = useState5("");
2040
+ const [photo, setPhoto] = useState5("");
2041
+ useEffect3(() => {
2042
+ if (user) {
2043
+ setName(user.name || "");
2044
+ setLastName(user.last_name || "");
2045
+ setEmail(user.email || "");
2046
+ setProfile(user.profile || "collaborator");
2047
+ setPhoto(user.photo || "");
2048
+ } else {
2049
+ setName("");
2050
+ setLastName("");
2051
+ setEmail("");
2052
+ setProfile("collaborator");
2053
+ setPhoto("");
2054
+ }
2055
+ setPassword("");
2056
+ }, [user, open]);
2057
+ const isPending = createUser.isPending || updateUser.isPending;
2058
+ async function handleSubmit(e) {
2059
+ e.preventDefault();
2060
+ if (!name.trim() || !email.trim()) return;
2061
+ try {
2062
+ if (isEditing) {
2063
+ await updateUser.mutateAsync({
2064
+ id: user.id,
2065
+ body: {
2066
+ name: name.trim(),
2067
+ last_name: lastName.trim() || void 0,
2068
+ email: email.trim(),
2069
+ profile,
2070
+ photo: photo || null
2071
+ }
2072
+ });
2073
+ toast2.success("Usu\xE1rio atualizado");
2074
+ } else {
2075
+ await createUser.mutateAsync({
2076
+ name: name.trim(),
2077
+ last_name: lastName.trim() || void 0,
2078
+ email: email.trim(),
2079
+ profile,
2080
+ password: password || void 0,
2081
+ photo: photo || null
2082
+ });
2083
+ toast2.success("Usu\xE1rio criado");
2084
+ }
2085
+ onOpenChange(false);
2086
+ } catch {
2087
+ toast2.error(isEditing ? "Erro ao atualizar usu\xE1rio" : "Erro ao criar usu\xE1rio");
2088
+ }
2089
+ }
2090
+ return /* @__PURE__ */ jsx24(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs16(DialogContent, { children: [
2091
+ /* @__PURE__ */ jsx24(DialogHeader, { children: /* @__PURE__ */ jsx24(DialogTitle, { children: isEditing ? "Editar Usu\xE1rio" : "Novo Usu\xE1rio" }) }),
2092
+ /* @__PURE__ */ jsxs16("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
2093
+ /* @__PURE__ */ jsx24("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx24(
2094
+ ImageCropUpload,
2095
+ {
2096
+ value: photo || null,
2097
+ onChange: setPhoto,
2098
+ onRemove: () => setPhoto(""),
2099
+ entityType: "users",
2100
+ entityId: user?.id,
2101
+ idAccount: Number(config.accountId) || 0,
2102
+ name: `${name} ${lastName}`.trim() || null,
2103
+ disabled: isPending
2104
+ }
2105
+ ) }),
2106
+ /* @__PURE__ */ jsxs16("div", { className: "grid grid-cols-2 gap-4", children: [
2107
+ /* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
2108
+ /* @__PURE__ */ jsx24(Label, { htmlFor: "user-name", children: "Nome *" }),
2109
+ /* @__PURE__ */ jsx24(Input, { id: "user-name", value: name, onChange: (e) => setName(e.target.value), placeholder: "Nome", required: true, disabled: isPending })
2110
+ ] }),
2111
+ /* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
2112
+ /* @__PURE__ */ jsx24(Label, { htmlFor: "user-lastname", children: "Sobrenome" }),
2113
+ /* @__PURE__ */ jsx24(Input, { id: "user-lastname", value: lastName, onChange: (e) => setLastName(e.target.value), placeholder: "Sobrenome", disabled: isPending })
2114
+ ] })
2115
+ ] }),
2116
+ /* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
2117
+ /* @__PURE__ */ jsx24(Label, { htmlFor: "user-email", children: "E-mail *" }),
2118
+ /* @__PURE__ */ jsx24(Input, { id: "user-email", type: "email", value: email, onChange: (e) => setEmail(e.target.value), placeholder: "email@exemplo.com", required: true, disabled: isPending })
2119
+ ] }),
2120
+ !isEditing && /* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
2121
+ /* @__PURE__ */ jsx24(Label, { htmlFor: "user-password", children: "Senha" }),
2122
+ /* @__PURE__ */ jsx24(Input, { id: "user-password", type: "password", value: password, onChange: (e) => setPassword(e.target.value), placeholder: "Senha inicial (opcional)", disabled: isPending })
2123
+ ] }),
2124
+ /* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
2125
+ /* @__PURE__ */ jsx24(Label, { children: "Perfil de acesso" }),
2126
+ /* @__PURE__ */ jsxs16(Select, { value: profile, onValueChange: setProfile, disabled: isPending, children: [
2127
+ /* @__PURE__ */ jsx24(SelectTrigger, { className: "w-full", children: /* @__PURE__ */ jsx24(SelectValue, {}) }),
2128
+ /* @__PURE__ */ jsx24(SelectContent, { children: profiles.map((opt) => /* @__PURE__ */ jsx24(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
2129
+ ] })
2130
+ ] }),
2131
+ isEditing && renderPhones && /* @__PURE__ */ jsx24("div", { className: "border-t pt-4", children: renderPhones(user.id) }),
2132
+ /* @__PURE__ */ jsxs16(DialogFooter, { children: [
2133
+ /* @__PURE__ */ jsx24(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), disabled: isPending, children: "Cancelar" }),
2134
+ /* @__PURE__ */ jsxs16(Button, { type: "submit", disabled: isPending || !name.trim() || !email.trim(), children: [
2135
+ isPending && /* @__PURE__ */ jsx24(Loader22, { className: "mr-2 h-4 w-4 animate-spin" }),
2136
+ isEditing ? "Salvar" : "Criar"
2137
+ ] })
2138
+ ] })
2139
+ ] })
2140
+ ] }) });
2141
+ }
2142
+
2143
+ // src/components/users/user-profile-badge.tsx
2144
+ import { jsx as jsx25 } from "react/jsx-runtime";
2145
+ var profileConfig = {
2146
+ owner: { label: "Propriet\xE1rio", className: "bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200" },
2147
+ proprietario: { label: "Propriet\xE1rio", className: "bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200" },
2148
+ admin: { label: "Administrador", className: "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200" },
2149
+ administrador: { label: "Administrador", className: "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200" },
2150
+ manager: { label: "Gerente", className: "bg-teal-100 text-teal-800 dark:bg-teal-900 dark:text-teal-200" },
2151
+ gerente: { label: "Gerente", className: "bg-teal-100 text-teal-800 dark:bg-teal-900 dark:text-teal-200" },
2152
+ supervisor: { label: "Supervisor", className: "bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200" },
2153
+ collaborator: { label: "Colaborador", className: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200" },
2154
+ colaborador: { label: "Colaborador", className: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200" },
2155
+ attendant: { label: "Atendente", className: "bg-amber-100 text-amber-800 dark:bg-amber-900 dark:text-amber-200" },
2156
+ viewer: { label: "Visualizador", className: "bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200" }
2157
+ };
2158
+ function UserProfileBadge({ profile }) {
2159
+ const config = profileConfig[profile] || { label: profile, className: "" };
2160
+ return /* @__PURE__ */ jsx25(Badge, { variant: "secondary", className: config.className, children: config.label });
2161
+ }
2162
+
2163
+ // src/components/users/data-table.tsx
2164
+ import {
2165
+ flexRender,
2166
+ getCoreRowModel,
2167
+ getSortedRowModel,
2168
+ useReactTable
2169
+ } from "@tanstack/react-table";
2170
+ import { useState as useState6 } from "react";
2171
+
2172
+ // src/components/ui/table.tsx
2173
+ import { jsx as jsx26 } from "react/jsx-runtime";
2174
+ function Table({ className, ...props }) {
2175
+ return /* @__PURE__ */ jsx26("div", { "data-slot": "table-container", className: "relative w-full overflow-x-auto", children: /* @__PURE__ */ jsx26(
2176
+ "table",
2177
+ {
2178
+ "data-slot": "table",
2179
+ className: cn("w-full caption-bottom text-sm", className),
2180
+ ...props
2181
+ }
2182
+ ) });
2183
+ }
2184
+ function TableHeader({ className, ...props }) {
2185
+ return /* @__PURE__ */ jsx26(
2186
+ "thead",
2187
+ {
2188
+ "data-slot": "table-header",
2189
+ className: cn("[&_tr]:border-b", className),
2190
+ ...props
2191
+ }
2192
+ );
2193
+ }
2194
+ function TableBody({ className, ...props }) {
2195
+ return /* @__PURE__ */ jsx26(
2196
+ "tbody",
2197
+ {
2198
+ "data-slot": "table-body",
2199
+ className: cn("[&_tr:last-child]:border-0", className),
2200
+ ...props
2201
+ }
2202
+ );
2203
+ }
2204
+ function TableRow({ className, ...props }) {
2205
+ return /* @__PURE__ */ jsx26(
2206
+ "tr",
2207
+ {
2208
+ "data-slot": "table-row",
2209
+ className: cn("hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors", className),
2210
+ ...props
2211
+ }
2212
+ );
2213
+ }
2214
+ function TableHead({ className, ...props }) {
2215
+ return /* @__PURE__ */ jsx26(
2216
+ "th",
2217
+ {
2218
+ "data-slot": "table-head",
2219
+ className: cn("text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0", className),
2220
+ ...props
2221
+ }
2222
+ );
2223
+ }
2224
+ function TableCell({ className, ...props }) {
2225
+ return /* @__PURE__ */ jsx26(
2226
+ "td",
2227
+ {
2228
+ "data-slot": "table-cell",
2229
+ className: cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0", className),
2230
+ ...props
2231
+ }
2232
+ );
2233
+ }
2234
+
2235
+ // src/components/users/data-table.tsx
2236
+ import { ChevronLeft, ChevronRight as ChevronRight4, ArrowUp, ArrowDown, ArrowUpDown } from "lucide-react";
2237
+ import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
2238
+ function DataTable({
2239
+ columns,
2240
+ data,
2241
+ isLoading,
2242
+ emptyMessage = "Nenhum registro encontrado",
2243
+ total,
2244
+ page = 1,
2245
+ onPageChange,
2246
+ pageSize = 15,
2247
+ onRowClick,
2248
+ selectedRowId,
2249
+ getRowId,
2250
+ compact
2251
+ }) {
2252
+ const [sorting, setSorting] = useState6([]);
2253
+ const table = useReactTable({
2254
+ data,
2255
+ columns,
2256
+ getCoreRowModel: getCoreRowModel(),
2257
+ getSortedRowModel: getSortedRowModel(),
2258
+ onSortingChange: setSorting,
2259
+ state: { sorting }
2260
+ });
2261
+ const totalPages = total ? Math.ceil(total / pageSize) : 1;
2262
+ const showPagination = onPageChange && total && total > pageSize;
2263
+ return /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
2264
+ /* @__PURE__ */ jsx27("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs17(Table, { children: [
2265
+ /* @__PURE__ */ jsx27(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx27(TableRow, { children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx27(
2266
+ TableHead,
2267
+ {
2268
+ className: cn(compact && "py-1.5 text-xs"),
2269
+ style: { width: header.getSize() !== 150 ? header.getSize() : void 0 },
2270
+ children: header.isPlaceholder ? null : header.column.getCanSort() ? /* @__PURE__ */ jsxs17(
2271
+ "button",
2272
+ {
2273
+ type: "button",
2274
+ className: "flex items-center gap-1 hover:text-foreground -ml-1 px-1 py-0.5 rounded cursor-pointer select-none",
2275
+ onClick: header.column.getToggleSortingHandler(),
2276
+ children: [
2277
+ flexRender(header.column.columnDef.header, header.getContext()),
2278
+ {
2279
+ asc: /* @__PURE__ */ jsx27(ArrowUp, { className: "h-3.5 w-3.5" }),
2280
+ desc: /* @__PURE__ */ jsx27(ArrowDown, { className: "h-3.5 w-3.5" })
2281
+ }[header.column.getIsSorted()] ?? /* @__PURE__ */ jsx27(ArrowUpDown, { className: "h-3.5 w-3.5 text-muted-foreground/50" })
2282
+ ]
2283
+ }
2284
+ ) : flexRender(header.column.columnDef.header, header.getContext())
2285
+ },
2286
+ header.id
2287
+ )) }, headerGroup.id)) }),
2288
+ /* @__PURE__ */ jsx27(TableBody, { children: isLoading ? Array.from({ length: compact ? 3 : 5 }).map((_, i) => /* @__PURE__ */ jsx27(TableRow, { children: columns.map((_2, j) => /* @__PURE__ */ jsx27(TableCell, { className: cn(compact && "py-1.5"), children: /* @__PURE__ */ jsx27(Skeleton, { className: "h-4 w-full max-w-[120px]" }) }, j)) }, i)) : table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx27(TableRow, { children: /* @__PURE__ */ jsx27(
2289
+ TableCell,
2290
+ {
2291
+ colSpan: columns.length,
2292
+ className: cn(
2293
+ "text-center text-muted-foreground",
2294
+ compact ? "py-4" : "py-8"
2295
+ ),
2296
+ children: emptyMessage
2297
+ }
2298
+ ) }) : table.getRowModel().rows.map((row) => {
2299
+ const rowId = getRowId ? getRowId(row.original) : void 0;
2300
+ const isSelected = selectedRowId != null && rowId != null && rowId === selectedRowId;
2301
+ return /* @__PURE__ */ jsx27(
2302
+ TableRow,
2303
+ {
2304
+ className: cn(
2305
+ onRowClick && "cursor-pointer",
2306
+ isSelected && "bg-accent"
2307
+ ),
2308
+ onClick: () => onRowClick?.(row.original),
2309
+ children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx27(TableCell, { className: cn(compact && "py-1.5"), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
2310
+ },
2311
+ row.id
2312
+ );
2313
+ }) })
2314
+ ] }) }),
2315
+ showPagination && /* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between px-2", children: [
2316
+ /* @__PURE__ */ jsxs17("p", { className: "text-sm text-muted-foreground", children: [
2317
+ total,
2318
+ " registro",
2319
+ total !== 1 ? "s" : ""
2320
+ ] }),
2321
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
2322
+ /* @__PURE__ */ jsxs17(
2323
+ Button,
2324
+ {
2325
+ variant: "outline",
2326
+ size: "sm",
2327
+ onClick: () => onPageChange(page - 1),
2328
+ disabled: page <= 1,
2329
+ children: [
2330
+ /* @__PURE__ */ jsx27(ChevronLeft, { className: "h-4 w-4" }),
2331
+ "Anterior"
2332
+ ]
2333
+ }
2334
+ ),
2335
+ /* @__PURE__ */ jsxs17("span", { className: "text-sm text-muted-foreground", children: [
2336
+ page,
2337
+ " de ",
2338
+ totalPages
2339
+ ] }),
2340
+ /* @__PURE__ */ jsxs17(
2341
+ Button,
2342
+ {
2343
+ variant: "outline",
2344
+ size: "sm",
2345
+ onClick: () => onPageChange(page + 1),
2346
+ disabled: page >= totalPages,
2347
+ children: [
2348
+ "Pr\xF3ximo",
2349
+ /* @__PURE__ */ jsx27(ChevronRight4, { className: "h-4 w-4" })
2350
+ ]
2351
+ }
2352
+ )
2353
+ ] })
2354
+ ] })
2355
+ ] });
2356
+ }
2357
+
2358
+ // src/components/ui/alert-dialog.tsx
2359
+ import { AlertDialog as AlertDialogPrimitive } from "radix-ui";
2360
+ import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
2361
+ function AlertDialog({
2362
+ ...props
2363
+ }) {
2364
+ return /* @__PURE__ */ jsx28(AlertDialogPrimitive.Root, { "data-slot": "alert-dialog", ...props });
2365
+ }
2366
+ function AlertDialogPortal({
2367
+ ...props
2368
+ }) {
2369
+ return /* @__PURE__ */ jsx28(AlertDialogPrimitive.Portal, { "data-slot": "alert-dialog-portal", ...props });
2370
+ }
2371
+ function AlertDialogOverlay({
2372
+ className,
2373
+ ...props
2374
+ }) {
2375
+ return /* @__PURE__ */ jsx28(
2376
+ AlertDialogPrimitive.Overlay,
2377
+ {
2378
+ "data-slot": "alert-dialog-overlay",
2379
+ className: cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50", className),
2380
+ ...props
2381
+ }
2382
+ );
2383
+ }
2384
+ function AlertDialogContent({
2385
+ className,
2386
+ size = "default",
2387
+ ...props
2388
+ }) {
2389
+ return /* @__PURE__ */ jsxs18(AlertDialogPortal, { children: [
2390
+ /* @__PURE__ */ jsx28(AlertDialogOverlay, {}),
2391
+ /* @__PURE__ */ jsx28(
2392
+ AlertDialogPrimitive.Content,
2393
+ {
2394
+ "data-slot": "alert-dialog-content",
2395
+ "data-size": size,
2396
+ className: cn(
2397
+ "data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 gap-6 rounded-xl p-6 ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 outline-none",
2398
+ className
2399
+ ),
2400
+ ...props
2401
+ }
2402
+ )
2403
+ ] });
2404
+ }
2405
+ function AlertDialogHeader({
2406
+ className,
2407
+ ...props
2408
+ }) {
2409
+ return /* @__PURE__ */ jsx28(
2410
+ "div",
2411
+ {
2412
+ "data-slot": "alert-dialog-header",
2413
+ className: cn("grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]", className),
2414
+ ...props
2415
+ }
2416
+ );
2417
+ }
2418
+ function AlertDialogFooter({
2419
+ className,
2420
+ ...props
2421
+ }) {
2422
+ return /* @__PURE__ */ jsx28(
2423
+ "div",
2424
+ {
2425
+ "data-slot": "alert-dialog-footer",
2426
+ className: cn(
2427
+ "flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
2428
+ className
2429
+ ),
2430
+ ...props
2431
+ }
2432
+ );
2433
+ }
2434
+ function AlertDialogTitle({
2435
+ className,
2436
+ ...props
2437
+ }) {
2438
+ return /* @__PURE__ */ jsx28(
2439
+ AlertDialogPrimitive.Title,
2440
+ {
2441
+ "data-slot": "alert-dialog-title",
2442
+ className: cn("text-lg font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2", className),
2443
+ ...props
2444
+ }
2445
+ );
2446
+ }
2447
+ function AlertDialogDescription({
2448
+ className,
2449
+ ...props
2450
+ }) {
2451
+ return /* @__PURE__ */ jsx28(
2452
+ AlertDialogPrimitive.Description,
2453
+ {
2454
+ "data-slot": "alert-dialog-description",
2455
+ className: cn("text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3", className),
2456
+ ...props
2457
+ }
2458
+ );
2459
+ }
2460
+ function AlertDialogAction({
2461
+ className,
2462
+ variant = "default",
2463
+ size = "default",
2464
+ ...props
2465
+ }) {
2466
+ return /* @__PURE__ */ jsx28(Button, { variant, size, asChild: true, children: /* @__PURE__ */ jsx28(
2467
+ AlertDialogPrimitive.Action,
2468
+ {
2469
+ "data-slot": "alert-dialog-action",
2470
+ className: cn(className),
2471
+ ...props
2472
+ }
2473
+ ) });
2474
+ }
2475
+ function AlertDialogCancel({
2476
+ className,
2477
+ variant = "outline",
2478
+ size = "default",
2479
+ ...props
2480
+ }) {
2481
+ return /* @__PURE__ */ jsx28(Button, { variant, size, asChild: true, children: /* @__PURE__ */ jsx28(
2482
+ AlertDialogPrimitive.Cancel,
2483
+ {
2484
+ "data-slot": "alert-dialog-cancel",
2485
+ className: cn(className),
2486
+ ...props
2487
+ }
2488
+ ) });
2489
+ }
2490
+
2491
+ // src/components/users/users-page.tsx
2492
+ import { Pencil, Trash2 as Trash22, Search, Forward, Plus } from "lucide-react";
2493
+ import { format } from "date-fns";
2494
+ import { ptBR } from "date-fns/locale";
2495
+ import { toast as toast3 } from "sonner";
2496
+ import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
2497
+ var PAGE_SIZE = 15;
2498
+ var PROFILE_FILTER_OPTIONS = [
2499
+ { value: "all", label: "Todos os perfis" },
2500
+ { value: "owner", label: "Propriet\xE1rio" },
2501
+ { value: "admin", label: "Administrador" },
2502
+ { value: "collaborator", label: "Colaborador" },
2503
+ { value: "attendant", label: "Atendente" },
2504
+ { value: "viewer", label: "Visualizador" }
2505
+ ];
2506
+ function useColumns(onEdit, onDelete, onResetPassword) {
2507
+ return [
2508
+ {
2509
+ accessorKey: "name",
2510
+ header: "Nome",
2511
+ cell: ({ row }) => /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
2512
+ /* @__PURE__ */ jsx29(
2513
+ EntityAvatar,
2514
+ {
2515
+ photo: row.original.photo,
2516
+ name: `${row.original.name} ${row.original.last_name}`.trim(),
2517
+ size: "sm"
2518
+ }
2519
+ ),
2520
+ /* @__PURE__ */ jsxs19("span", { className: "font-medium", children: [
2521
+ row.original.name,
2522
+ " ",
2523
+ row.original.last_name
2524
+ ] })
2525
+ ] }),
2526
+ sortingFn: (rowA, rowB) => {
2527
+ const a = `${rowA.original.name} ${rowA.original.last_name}`.toLowerCase();
2528
+ const b = `${rowB.original.name} ${rowB.original.last_name}`.toLowerCase();
2529
+ return a.localeCompare(b);
2530
+ }
2531
+ },
2532
+ {
2533
+ accessorKey: "email",
2534
+ header: "E-mail"
2535
+ },
2536
+ {
2537
+ accessorKey: "profile",
2538
+ header: "Perfil",
2539
+ cell: ({ row }) => /* @__PURE__ */ jsx29(UserProfileBadge, { profile: row.original.profile }),
2540
+ sortingFn: (rowA, rowB) => rowA.original.profile.localeCompare(rowB.original.profile)
2541
+ },
2542
+ {
2543
+ accessorKey: "last_login",
2544
+ header: "\xDAltimo acesso",
2545
+ cell: ({ row }) => /* @__PURE__ */ jsx29("span", { className: "text-muted-foreground text-sm", children: row.original.last_login ? format(new Date(row.original.last_login), "dd/MM/yyyy HH:mm", { locale: ptBR }) : "\u2014" })
2546
+ },
2547
+ {
2548
+ accessorKey: "datetime_add",
2549
+ header: "Criado em",
2550
+ cell: ({ row }) => /* @__PURE__ */ jsx29("span", { className: "text-muted-foreground text-sm", children: format(new Date(row.original.datetime_add), "dd/MM/yyyy", { locale: ptBR }) })
2551
+ },
2552
+ {
2553
+ id: "actions",
2554
+ size: 120,
2555
+ enableSorting: false,
2556
+ cell: ({ row }) => /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-1", children: [
2557
+ /* @__PURE__ */ jsxs19(Tooltip, { children: [
2558
+ /* @__PURE__ */ jsx29(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(Button, { variant: "ghost", size: "icon", className: "h-8 w-8", onClick: () => onResetPassword(row.original), children: /* @__PURE__ */ jsx29(Forward, { className: "h-4 w-4" }) }) }),
2559
+ /* @__PURE__ */ jsx29(TooltipContent, { children: "Resetar senha" })
2560
+ ] }),
2561
+ /* @__PURE__ */ jsxs19(Tooltip, { children: [
2562
+ /* @__PURE__ */ jsx29(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(Button, { variant: "ghost", size: "icon", className: "h-8 w-8", onClick: () => onEdit(row.original), children: /* @__PURE__ */ jsx29(Pencil, { className: "h-4 w-4" }) }) }),
2563
+ /* @__PURE__ */ jsx29(TooltipContent, { children: "Editar" })
2564
+ ] }),
2565
+ /* @__PURE__ */ jsxs19(Tooltip, { children: [
2566
+ /* @__PURE__ */ jsx29(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(Button, { variant: "ghost", size: "icon", className: "h-8 w-8 text-destructive hover:text-destructive", onClick: () => onDelete(row.original.id), children: /* @__PURE__ */ jsx29(Trash22, { className: "h-4 w-4" }) }) }),
2567
+ /* @__PURE__ */ jsx29(TooltipContent, { children: "Excluir" })
2568
+ ] })
2569
+ ] })
2570
+ }
2571
+ ];
2572
+ }
2573
+ function UsersPage({ config, profileOptions, renderPhones }) {
2574
+ const [search, setSearch] = useState7("");
2575
+ const [profileFilter, setProfileFilter] = useState7("all");
2576
+ const [page, setPage] = useState7(1);
2577
+ const queryParams = useMemo3(() => {
2578
+ const params = {
2579
+ limit: String(PAGE_SIZE),
2580
+ page: String(page)
2581
+ };
2582
+ if (profileFilter !== "all") params.profile = profileFilter;
2583
+ return params;
2584
+ }, [profileFilter, page]);
2585
+ const { data, isLoading } = useUsers(config, queryParams);
2586
+ const deleteUser = useDeleteUser(config);
2587
+ const resetPassword = useResetPassword(config);
2588
+ const [editUser, setEditUser] = useState7(null);
2589
+ const [formOpen, setFormOpen] = useState7(false);
2590
+ const [deleteId, setDeleteId] = useState7(null);
2591
+ const [resetUser, setResetUser] = useState7(null);
2592
+ const users = data?.data || [];
2593
+ const total = data?.total || 0;
2594
+ const filtered = useMemo3(() => {
2595
+ if (!search) return users;
2596
+ const term = search.toLowerCase();
2597
+ return users.filter(
2598
+ (u) => `${u.name} ${u.last_name}`.toLowerCase().includes(term) || u.email.toLowerCase().includes(term)
2599
+ );
2600
+ }, [users, search]);
2601
+ const columns = useColumns(
2602
+ (u) => {
2603
+ setEditUser(u);
2604
+ setFormOpen(true);
2605
+ },
2606
+ (id) => setDeleteId(id),
2607
+ (u) => setResetUser(u)
2608
+ );
2609
+ function handleDelete() {
2610
+ if (!deleteId) return;
2611
+ deleteUser.mutate(deleteId, {
2612
+ onSuccess: () => {
2613
+ toast3.success("Usu\xE1rio exclu\xEDdo");
2614
+ setDeleteId(null);
2615
+ },
2616
+ onError: () => toast3.error("Erro ao excluir usu\xE1rio")
2617
+ });
2618
+ }
2619
+ function handleResetPassword() {
2620
+ if (!resetUser) return;
2621
+ resetPassword.mutate(resetUser.id, {
2622
+ onSuccess: () => {
2623
+ toast3.success("Senha resetada e email enviado");
2624
+ setResetUser(null);
2625
+ },
2626
+ onError: () => {
2627
+ toast3.error("Erro ao resetar senha");
2628
+ setResetUser(null);
2629
+ }
2630
+ });
2631
+ }
2632
+ return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-4 p-4", children: [
2633
+ /* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between", children: [
2634
+ /* @__PURE__ */ jsxs19("div", { children: [
2635
+ /* @__PURE__ */ jsx29("h1", { className: "text-xl font-semibold", children: "Usu\xE1rios" }),
2636
+ /* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground", children: "Gest\xE3o de usu\xE1rios da conta" })
2637
+ ] }),
2638
+ /* @__PURE__ */ jsxs19(Button, { onClick: () => {
2639
+ setEditUser(null);
2640
+ setFormOpen(true);
2641
+ }, size: "sm", children: [
2642
+ /* @__PURE__ */ jsx29(Plus, { className: "mr-2 h-4 w-4" }),
2643
+ "Novo Usu\xE1rio"
2644
+ ] })
2645
+ ] }),
2646
+ /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-3", children: [
2647
+ /* @__PURE__ */ jsxs19("div", { className: "relative flex-1 max-w-md", children: [
2648
+ /* @__PURE__ */ jsx29(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
2649
+ /* @__PURE__ */ jsx29(
2650
+ Input,
2651
+ {
2652
+ placeholder: "Buscar por nome ou e-mail...",
2653
+ value: search,
2654
+ onChange: (e) => {
2655
+ setSearch(e.target.value);
2656
+ setPage(1);
2657
+ },
2658
+ className: "pl-9"
2659
+ }
2660
+ )
2661
+ ] }),
2662
+ /* @__PURE__ */ jsxs19(Select, { value: profileFilter, onValueChange: (v) => {
2663
+ setProfileFilter(v);
2664
+ setPage(1);
2665
+ }, children: [
2666
+ /* @__PURE__ */ jsx29(SelectTrigger, { className: "w-[180px]", children: /* @__PURE__ */ jsx29(SelectValue, {}) }),
2667
+ /* @__PURE__ */ jsx29(SelectContent, { children: PROFILE_FILTER_OPTIONS.map((opt) => /* @__PURE__ */ jsx29(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
2668
+ ] })
2669
+ ] }),
2670
+ /* @__PURE__ */ jsx29(
2671
+ DataTable,
2672
+ {
2673
+ columns,
2674
+ data: search ? filtered : users,
2675
+ isLoading,
2676
+ emptyMessage: "Nenhum usu\xE1rio encontrado",
2677
+ total: search ? filtered.length : total,
2678
+ page,
2679
+ onPageChange: setPage,
2680
+ pageSize: PAGE_SIZE
2681
+ }
2682
+ ),
2683
+ /* @__PURE__ */ jsx29(
2684
+ UserFormDialog,
2685
+ {
2686
+ open: formOpen,
2687
+ onOpenChange: (open) => {
2688
+ setFormOpen(open);
2689
+ if (!open) setEditUser(null);
2690
+ },
2691
+ user: editUser ?? void 0,
2692
+ config,
2693
+ profileOptions,
2694
+ renderPhones
2695
+ }
2696
+ ),
2697
+ /* @__PURE__ */ jsx29(AlertDialog, { open: !!deleteId, onOpenChange: (open) => !open && setDeleteId(null), children: /* @__PURE__ */ jsxs19(AlertDialogContent, { children: [
2698
+ /* @__PURE__ */ jsxs19(AlertDialogHeader, { children: [
2699
+ /* @__PURE__ */ jsx29(AlertDialogTitle, { children: "Excluir usu\xE1rio?" }),
2700
+ /* @__PURE__ */ jsx29(AlertDialogDescription, { children: "Esta a\xE7\xE3o n\xE3o pode ser desfeita. O usu\xE1rio ser\xE1 removido permanentemente." })
2701
+ ] }),
2702
+ /* @__PURE__ */ jsxs19(AlertDialogFooter, { children: [
2703
+ /* @__PURE__ */ jsx29(AlertDialogCancel, { children: "Cancelar" }),
2704
+ /* @__PURE__ */ jsx29(AlertDialogAction, { onClick: handleDelete, className: "bg-destructive text-destructive-foreground hover:bg-destructive/90", children: "Excluir" })
2705
+ ] })
2706
+ ] }) }),
2707
+ /* @__PURE__ */ jsx29(AlertDialog, { open: !!resetUser, onOpenChange: (open) => !open && setResetUser(null), children: /* @__PURE__ */ jsxs19(AlertDialogContent, { children: [
2708
+ /* @__PURE__ */ jsxs19(AlertDialogHeader, { children: [
2709
+ /* @__PURE__ */ jsx29(AlertDialogTitle, { children: "Resetar senha?" }),
2710
+ /* @__PURE__ */ jsxs19(AlertDialogDescription, { children: [
2711
+ "A senha de ",
2712
+ /* @__PURE__ */ jsxs19("strong", { children: [
2713
+ resetUser?.name,
2714
+ " ",
2715
+ resetUser?.last_name
2716
+ ] }),
2717
+ " (",
2718
+ resetUser?.email,
2719
+ ") ser\xE1 removida e um email com link para definir nova senha ser\xE1 enviado."
2720
+ ] })
2721
+ ] }),
2722
+ /* @__PURE__ */ jsxs19(AlertDialogFooter, { children: [
2723
+ /* @__PURE__ */ jsx29(AlertDialogCancel, { children: "Cancelar" }),
2724
+ /* @__PURE__ */ jsx29(AlertDialogAction, { onClick: handleResetPassword, children: "Resetar e enviar" })
2725
+ ] })
2726
+ ] }) })
2727
+ ] });
2728
+ }
1315
2729
  export {
1316
2730
  AppHeader,
1317
2731
  AppShell,
1318
2732
  AppSidebar,
2733
+ DataTable,
2734
+ EntityAvatar,
2735
+ ImageCropUpload,
1319
2736
  LoginForm,
1320
2737
  SidebarInset,
1321
2738
  SidebarProvider,
1322
2739
  SidebarTrigger,
1323
2740
  ThemeToggle,
1324
2741
  TooltipProvider,
2742
+ UserFormDialog,
2743
+ UserProfileBadge,
2744
+ UsersPage,
1325
2745
  authClient,
1326
2746
  authMiddlewareConfig,
1327
2747
  cn,
@@ -1330,7 +2750,12 @@ export {
1330
2750
  signIn,
1331
2751
  signOut,
1332
2752
  signUp,
2753
+ useCreateUser,
2754
+ useDeleteUser,
2755
+ useResetPassword,
1333
2756
  useSession,
1334
- useSidebar
2757
+ useSidebar,
2758
+ useUpdateUser,
2759
+ useUsers
1335
2760
  };
1336
2761
  //# sourceMappingURL=index.js.map