@greatapps/greatauth-ui 0.3.7 → 0.3.9
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 +102 -1
- package/dist/index.js +940 -5
- package/dist/index.js.map +1 -1
- package/package.json +10 -7
- package/src/components/users/data-table.tsx +185 -0
- package/src/components/users/user-form-dialog.tsx +166 -0
- package/src/components/users/user-profile-badge.tsx +31 -0
- package/src/components/users/users-page.tsx +271 -0
- package/src/hooks/use-users.ts +82 -0
- package/src/index.ts +16 -0
- package/src/types/users.ts +46 -0
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(
|
|
11
|
-
const { pathname, search } =
|
|
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 =
|
|
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",
|
|
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";
|
|
@@ -1797,10 +1807,927 @@ function ImageCropUpload({
|
|
|
1797
1807
|
] }) })
|
|
1798
1808
|
] });
|
|
1799
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 PROFILE_OPTIONS = [
|
|
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
|
+
renderPhones
|
|
2029
|
+
}) {
|
|
2030
|
+
const isEditing = !!user;
|
|
2031
|
+
const createUser = useCreateUser(config);
|
|
2032
|
+
const updateUser = useUpdateUser(config);
|
|
2033
|
+
const [name, setName] = useState5("");
|
|
2034
|
+
const [lastName, setLastName] = useState5("");
|
|
2035
|
+
const [email, setEmail] = useState5("");
|
|
2036
|
+
const [profile, setProfile] = useState5("collaborator");
|
|
2037
|
+
const [password, setPassword] = useState5("");
|
|
2038
|
+
const [photo, setPhoto] = useState5("");
|
|
2039
|
+
useEffect3(() => {
|
|
2040
|
+
if (user) {
|
|
2041
|
+
setName(user.name || "");
|
|
2042
|
+
setLastName(user.last_name || "");
|
|
2043
|
+
setEmail(user.email || "");
|
|
2044
|
+
setProfile(user.profile || "collaborator");
|
|
2045
|
+
setPhoto(user.photo || "");
|
|
2046
|
+
} else {
|
|
2047
|
+
setName("");
|
|
2048
|
+
setLastName("");
|
|
2049
|
+
setEmail("");
|
|
2050
|
+
setProfile("collaborator");
|
|
2051
|
+
setPhoto("");
|
|
2052
|
+
}
|
|
2053
|
+
setPassword("");
|
|
2054
|
+
}, [user, open]);
|
|
2055
|
+
const isPending = createUser.isPending || updateUser.isPending;
|
|
2056
|
+
async function handleSubmit(e) {
|
|
2057
|
+
e.preventDefault();
|
|
2058
|
+
if (!name.trim() || !email.trim()) return;
|
|
2059
|
+
try {
|
|
2060
|
+
if (isEditing) {
|
|
2061
|
+
await updateUser.mutateAsync({
|
|
2062
|
+
id: user.id,
|
|
2063
|
+
body: {
|
|
2064
|
+
name: name.trim(),
|
|
2065
|
+
last_name: lastName.trim() || void 0,
|
|
2066
|
+
email: email.trim(),
|
|
2067
|
+
profile,
|
|
2068
|
+
photo: photo || null
|
|
2069
|
+
}
|
|
2070
|
+
});
|
|
2071
|
+
toast2.success("Usu\xE1rio atualizado");
|
|
2072
|
+
} else {
|
|
2073
|
+
await createUser.mutateAsync({
|
|
2074
|
+
name: name.trim(),
|
|
2075
|
+
last_name: lastName.trim() || void 0,
|
|
2076
|
+
email: email.trim(),
|
|
2077
|
+
profile,
|
|
2078
|
+
password: password || void 0,
|
|
2079
|
+
photo: photo || null
|
|
2080
|
+
});
|
|
2081
|
+
toast2.success("Usu\xE1rio criado");
|
|
2082
|
+
}
|
|
2083
|
+
onOpenChange(false);
|
|
2084
|
+
} catch {
|
|
2085
|
+
toast2.error(isEditing ? "Erro ao atualizar usu\xE1rio" : "Erro ao criar usu\xE1rio");
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
return /* @__PURE__ */ jsx24(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs16(DialogContent, { children: [
|
|
2089
|
+
/* @__PURE__ */ jsx24(DialogHeader, { children: /* @__PURE__ */ jsx24(DialogTitle, { children: isEditing ? "Editar Usu\xE1rio" : "Novo Usu\xE1rio" }) }),
|
|
2090
|
+
/* @__PURE__ */ jsxs16("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
|
|
2091
|
+
/* @__PURE__ */ jsx24("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx24(
|
|
2092
|
+
ImageCropUpload,
|
|
2093
|
+
{
|
|
2094
|
+
value: photo || null,
|
|
2095
|
+
onChange: setPhoto,
|
|
2096
|
+
onRemove: () => setPhoto(""),
|
|
2097
|
+
entityType: "users",
|
|
2098
|
+
entityId: user?.id,
|
|
2099
|
+
idAccount: Number(config.accountId) || 0,
|
|
2100
|
+
name: `${name} ${lastName}`.trim() || null,
|
|
2101
|
+
disabled: isPending
|
|
2102
|
+
}
|
|
2103
|
+
) }),
|
|
2104
|
+
/* @__PURE__ */ jsxs16("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
2105
|
+
/* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
|
|
2106
|
+
/* @__PURE__ */ jsx24(Label, { htmlFor: "user-name", children: "Nome *" }),
|
|
2107
|
+
/* @__PURE__ */ jsx24(Input, { id: "user-name", value: name, onChange: (e) => setName(e.target.value), placeholder: "Nome", required: true, disabled: isPending })
|
|
2108
|
+
] }),
|
|
2109
|
+
/* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
|
|
2110
|
+
/* @__PURE__ */ jsx24(Label, { htmlFor: "user-lastname", children: "Sobrenome" }),
|
|
2111
|
+
/* @__PURE__ */ jsx24(Input, { id: "user-lastname", value: lastName, onChange: (e) => setLastName(e.target.value), placeholder: "Sobrenome", disabled: isPending })
|
|
2112
|
+
] })
|
|
2113
|
+
] }),
|
|
2114
|
+
/* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
|
|
2115
|
+
/* @__PURE__ */ jsx24(Label, { htmlFor: "user-email", children: "E-mail *" }),
|
|
2116
|
+
/* @__PURE__ */ jsx24(Input, { id: "user-email", type: "email", value: email, onChange: (e) => setEmail(e.target.value), placeholder: "email@exemplo.com", required: true, disabled: isPending })
|
|
2117
|
+
] }),
|
|
2118
|
+
!isEditing && /* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
|
|
2119
|
+
/* @__PURE__ */ jsx24(Label, { htmlFor: "user-password", children: "Senha" }),
|
|
2120
|
+
/* @__PURE__ */ jsx24(Input, { id: "user-password", type: "password", value: password, onChange: (e) => setPassword(e.target.value), placeholder: "Senha inicial (opcional)", disabled: isPending })
|
|
2121
|
+
] }),
|
|
2122
|
+
/* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
|
|
2123
|
+
/* @__PURE__ */ jsx24(Label, { children: "Perfil de acesso" }),
|
|
2124
|
+
/* @__PURE__ */ jsxs16(Select, { value: profile, onValueChange: setProfile, disabled: isPending, children: [
|
|
2125
|
+
/* @__PURE__ */ jsx24(SelectTrigger, { className: "w-full", children: /* @__PURE__ */ jsx24(SelectValue, {}) }),
|
|
2126
|
+
/* @__PURE__ */ jsx24(SelectContent, { children: PROFILE_OPTIONS.map((opt) => /* @__PURE__ */ jsx24(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
|
|
2127
|
+
] })
|
|
2128
|
+
] }),
|
|
2129
|
+
isEditing && renderPhones && /* @__PURE__ */ jsx24("div", { className: "border-t pt-4", children: renderPhones(user.id) }),
|
|
2130
|
+
/* @__PURE__ */ jsxs16(DialogFooter, { children: [
|
|
2131
|
+
/* @__PURE__ */ jsx24(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), disabled: isPending, children: "Cancelar" }),
|
|
2132
|
+
/* @__PURE__ */ jsxs16(Button, { type: "submit", disabled: isPending || !name.trim() || !email.trim(), children: [
|
|
2133
|
+
isPending && /* @__PURE__ */ jsx24(Loader22, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
2134
|
+
isEditing ? "Salvar" : "Criar"
|
|
2135
|
+
] })
|
|
2136
|
+
] })
|
|
2137
|
+
] })
|
|
2138
|
+
] }) });
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
// src/components/users/user-profile-badge.tsx
|
|
2142
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
2143
|
+
var profileConfig = {
|
|
2144
|
+
owner: { label: "Propriet\xE1rio", className: "bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200" },
|
|
2145
|
+
proprietario: { label: "Propriet\xE1rio", className: "bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200" },
|
|
2146
|
+
admin: { label: "Administrador", className: "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200" },
|
|
2147
|
+
administrador: { label: "Administrador", className: "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200" },
|
|
2148
|
+
manager: { label: "Gerente", className: "bg-teal-100 text-teal-800 dark:bg-teal-900 dark:text-teal-200" },
|
|
2149
|
+
gerente: { label: "Gerente", className: "bg-teal-100 text-teal-800 dark:bg-teal-900 dark:text-teal-200" },
|
|
2150
|
+
supervisor: { label: "Supervisor", className: "bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200" },
|
|
2151
|
+
collaborator: { label: "Colaborador", className: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200" },
|
|
2152
|
+
colaborador: { label: "Colaborador", className: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200" },
|
|
2153
|
+
attendant: { label: "Atendente", className: "bg-amber-100 text-amber-800 dark:bg-amber-900 dark:text-amber-200" },
|
|
2154
|
+
viewer: { label: "Visualizador", className: "bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200" }
|
|
2155
|
+
};
|
|
2156
|
+
function UserProfileBadge({ profile }) {
|
|
2157
|
+
const config = profileConfig[profile] || { label: profile, className: "" };
|
|
2158
|
+
return /* @__PURE__ */ jsx25(Badge, { variant: "secondary", className: config.className, children: config.label });
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
// src/components/users/data-table.tsx
|
|
2162
|
+
import {
|
|
2163
|
+
flexRender,
|
|
2164
|
+
getCoreRowModel,
|
|
2165
|
+
getSortedRowModel,
|
|
2166
|
+
useReactTable
|
|
2167
|
+
} from "@tanstack/react-table";
|
|
2168
|
+
import { useState as useState6 } from "react";
|
|
2169
|
+
|
|
2170
|
+
// src/components/ui/table.tsx
|
|
2171
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
2172
|
+
function Table({ className, ...props }) {
|
|
2173
|
+
return /* @__PURE__ */ jsx26("div", { "data-slot": "table-container", className: "relative w-full overflow-x-auto", children: /* @__PURE__ */ jsx26(
|
|
2174
|
+
"table",
|
|
2175
|
+
{
|
|
2176
|
+
"data-slot": "table",
|
|
2177
|
+
className: cn("w-full caption-bottom text-sm", className),
|
|
2178
|
+
...props
|
|
2179
|
+
}
|
|
2180
|
+
) });
|
|
2181
|
+
}
|
|
2182
|
+
function TableHeader({ className, ...props }) {
|
|
2183
|
+
return /* @__PURE__ */ jsx26(
|
|
2184
|
+
"thead",
|
|
2185
|
+
{
|
|
2186
|
+
"data-slot": "table-header",
|
|
2187
|
+
className: cn("[&_tr]:border-b", className),
|
|
2188
|
+
...props
|
|
2189
|
+
}
|
|
2190
|
+
);
|
|
2191
|
+
}
|
|
2192
|
+
function TableBody({ className, ...props }) {
|
|
2193
|
+
return /* @__PURE__ */ jsx26(
|
|
2194
|
+
"tbody",
|
|
2195
|
+
{
|
|
2196
|
+
"data-slot": "table-body",
|
|
2197
|
+
className: cn("[&_tr:last-child]:border-0", className),
|
|
2198
|
+
...props
|
|
2199
|
+
}
|
|
2200
|
+
);
|
|
2201
|
+
}
|
|
2202
|
+
function TableRow({ className, ...props }) {
|
|
2203
|
+
return /* @__PURE__ */ jsx26(
|
|
2204
|
+
"tr",
|
|
2205
|
+
{
|
|
2206
|
+
"data-slot": "table-row",
|
|
2207
|
+
className: cn("hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors", className),
|
|
2208
|
+
...props
|
|
2209
|
+
}
|
|
2210
|
+
);
|
|
2211
|
+
}
|
|
2212
|
+
function TableHead({ className, ...props }) {
|
|
2213
|
+
return /* @__PURE__ */ jsx26(
|
|
2214
|
+
"th",
|
|
2215
|
+
{
|
|
2216
|
+
"data-slot": "table-head",
|
|
2217
|
+
className: cn("text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0", className),
|
|
2218
|
+
...props
|
|
2219
|
+
}
|
|
2220
|
+
);
|
|
2221
|
+
}
|
|
2222
|
+
function TableCell({ className, ...props }) {
|
|
2223
|
+
return /* @__PURE__ */ jsx26(
|
|
2224
|
+
"td",
|
|
2225
|
+
{
|
|
2226
|
+
"data-slot": "table-cell",
|
|
2227
|
+
className: cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0", className),
|
|
2228
|
+
...props
|
|
2229
|
+
}
|
|
2230
|
+
);
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
// src/components/users/data-table.tsx
|
|
2234
|
+
import { ChevronLeft, ChevronRight as ChevronRight4, ArrowUp, ArrowDown, ArrowUpDown } from "lucide-react";
|
|
2235
|
+
import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2236
|
+
function DataTable({
|
|
2237
|
+
columns,
|
|
2238
|
+
data,
|
|
2239
|
+
isLoading,
|
|
2240
|
+
emptyMessage = "Nenhum registro encontrado",
|
|
2241
|
+
total,
|
|
2242
|
+
page = 1,
|
|
2243
|
+
onPageChange,
|
|
2244
|
+
pageSize = 15,
|
|
2245
|
+
onRowClick,
|
|
2246
|
+
selectedRowId,
|
|
2247
|
+
getRowId,
|
|
2248
|
+
compact
|
|
2249
|
+
}) {
|
|
2250
|
+
const [sorting, setSorting] = useState6([]);
|
|
2251
|
+
const table = useReactTable({
|
|
2252
|
+
data,
|
|
2253
|
+
columns,
|
|
2254
|
+
getCoreRowModel: getCoreRowModel(),
|
|
2255
|
+
getSortedRowModel: getSortedRowModel(),
|
|
2256
|
+
onSortingChange: setSorting,
|
|
2257
|
+
state: { sorting }
|
|
2258
|
+
});
|
|
2259
|
+
const totalPages = total ? Math.ceil(total / pageSize) : 1;
|
|
2260
|
+
const showPagination = onPageChange && total && total > pageSize;
|
|
2261
|
+
return /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
|
|
2262
|
+
/* @__PURE__ */ jsx27("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs17(Table, { children: [
|
|
2263
|
+
/* @__PURE__ */ jsx27(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx27(TableRow, { children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx27(
|
|
2264
|
+
TableHead,
|
|
2265
|
+
{
|
|
2266
|
+
className: cn(compact && "py-1.5 text-xs"),
|
|
2267
|
+
style: { width: header.getSize() !== 150 ? header.getSize() : void 0 },
|
|
2268
|
+
children: header.isPlaceholder ? null : header.column.getCanSort() ? /* @__PURE__ */ jsxs17(
|
|
2269
|
+
"button",
|
|
2270
|
+
{
|
|
2271
|
+
type: "button",
|
|
2272
|
+
className: "flex items-center gap-1 hover:text-foreground -ml-1 px-1 py-0.5 rounded cursor-pointer select-none",
|
|
2273
|
+
onClick: header.column.getToggleSortingHandler(),
|
|
2274
|
+
children: [
|
|
2275
|
+
flexRender(header.column.columnDef.header, header.getContext()),
|
|
2276
|
+
{
|
|
2277
|
+
asc: /* @__PURE__ */ jsx27(ArrowUp, { className: "h-3.5 w-3.5" }),
|
|
2278
|
+
desc: /* @__PURE__ */ jsx27(ArrowDown, { className: "h-3.5 w-3.5" })
|
|
2279
|
+
}[header.column.getIsSorted()] ?? /* @__PURE__ */ jsx27(ArrowUpDown, { className: "h-3.5 w-3.5 text-muted-foreground/50" })
|
|
2280
|
+
]
|
|
2281
|
+
}
|
|
2282
|
+
) : flexRender(header.column.columnDef.header, header.getContext())
|
|
2283
|
+
},
|
|
2284
|
+
header.id
|
|
2285
|
+
)) }, headerGroup.id)) }),
|
|
2286
|
+
/* @__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(
|
|
2287
|
+
TableCell,
|
|
2288
|
+
{
|
|
2289
|
+
colSpan: columns.length,
|
|
2290
|
+
className: cn(
|
|
2291
|
+
"text-center text-muted-foreground",
|
|
2292
|
+
compact ? "py-4" : "py-8"
|
|
2293
|
+
),
|
|
2294
|
+
children: emptyMessage
|
|
2295
|
+
}
|
|
2296
|
+
) }) : table.getRowModel().rows.map((row) => {
|
|
2297
|
+
const rowId = getRowId ? getRowId(row.original) : void 0;
|
|
2298
|
+
const isSelected = selectedRowId != null && rowId != null && rowId === selectedRowId;
|
|
2299
|
+
return /* @__PURE__ */ jsx27(
|
|
2300
|
+
TableRow,
|
|
2301
|
+
{
|
|
2302
|
+
className: cn(
|
|
2303
|
+
onRowClick && "cursor-pointer",
|
|
2304
|
+
isSelected && "bg-accent"
|
|
2305
|
+
),
|
|
2306
|
+
onClick: () => onRowClick?.(row.original),
|
|
2307
|
+
children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx27(TableCell, { className: cn(compact && "py-1.5"), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
|
|
2308
|
+
},
|
|
2309
|
+
row.id
|
|
2310
|
+
);
|
|
2311
|
+
}) })
|
|
2312
|
+
] }) }),
|
|
2313
|
+
showPagination && /* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between px-2", children: [
|
|
2314
|
+
/* @__PURE__ */ jsxs17("p", { className: "text-sm text-muted-foreground", children: [
|
|
2315
|
+
total,
|
|
2316
|
+
" registro",
|
|
2317
|
+
total !== 1 ? "s" : ""
|
|
2318
|
+
] }),
|
|
2319
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
|
|
2320
|
+
/* @__PURE__ */ jsxs17(
|
|
2321
|
+
Button,
|
|
2322
|
+
{
|
|
2323
|
+
variant: "outline",
|
|
2324
|
+
size: "sm",
|
|
2325
|
+
onClick: () => onPageChange(page - 1),
|
|
2326
|
+
disabled: page <= 1,
|
|
2327
|
+
children: [
|
|
2328
|
+
/* @__PURE__ */ jsx27(ChevronLeft, { className: "h-4 w-4" }),
|
|
2329
|
+
"Anterior"
|
|
2330
|
+
]
|
|
2331
|
+
}
|
|
2332
|
+
),
|
|
2333
|
+
/* @__PURE__ */ jsxs17("span", { className: "text-sm text-muted-foreground", children: [
|
|
2334
|
+
page,
|
|
2335
|
+
" de ",
|
|
2336
|
+
totalPages
|
|
2337
|
+
] }),
|
|
2338
|
+
/* @__PURE__ */ jsxs17(
|
|
2339
|
+
Button,
|
|
2340
|
+
{
|
|
2341
|
+
variant: "outline",
|
|
2342
|
+
size: "sm",
|
|
2343
|
+
onClick: () => onPageChange(page + 1),
|
|
2344
|
+
disabled: page >= totalPages,
|
|
2345
|
+
children: [
|
|
2346
|
+
"Pr\xF3ximo",
|
|
2347
|
+
/* @__PURE__ */ jsx27(ChevronRight4, { className: "h-4 w-4" })
|
|
2348
|
+
]
|
|
2349
|
+
}
|
|
2350
|
+
)
|
|
2351
|
+
] })
|
|
2352
|
+
] })
|
|
2353
|
+
] });
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
// src/components/ui/alert-dialog.tsx
|
|
2357
|
+
import { AlertDialog as AlertDialogPrimitive } from "radix-ui";
|
|
2358
|
+
import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2359
|
+
function AlertDialog({
|
|
2360
|
+
...props
|
|
2361
|
+
}) {
|
|
2362
|
+
return /* @__PURE__ */ jsx28(AlertDialogPrimitive.Root, { "data-slot": "alert-dialog", ...props });
|
|
2363
|
+
}
|
|
2364
|
+
function AlertDialogPortal({
|
|
2365
|
+
...props
|
|
2366
|
+
}) {
|
|
2367
|
+
return /* @__PURE__ */ jsx28(AlertDialogPrimitive.Portal, { "data-slot": "alert-dialog-portal", ...props });
|
|
2368
|
+
}
|
|
2369
|
+
function AlertDialogOverlay({
|
|
2370
|
+
className,
|
|
2371
|
+
...props
|
|
2372
|
+
}) {
|
|
2373
|
+
return /* @__PURE__ */ jsx28(
|
|
2374
|
+
AlertDialogPrimitive.Overlay,
|
|
2375
|
+
{
|
|
2376
|
+
"data-slot": "alert-dialog-overlay",
|
|
2377
|
+
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),
|
|
2378
|
+
...props
|
|
2379
|
+
}
|
|
2380
|
+
);
|
|
2381
|
+
}
|
|
2382
|
+
function AlertDialogContent({
|
|
2383
|
+
className,
|
|
2384
|
+
size = "default",
|
|
2385
|
+
...props
|
|
2386
|
+
}) {
|
|
2387
|
+
return /* @__PURE__ */ jsxs18(AlertDialogPortal, { children: [
|
|
2388
|
+
/* @__PURE__ */ jsx28(AlertDialogOverlay, {}),
|
|
2389
|
+
/* @__PURE__ */ jsx28(
|
|
2390
|
+
AlertDialogPrimitive.Content,
|
|
2391
|
+
{
|
|
2392
|
+
"data-slot": "alert-dialog-content",
|
|
2393
|
+
"data-size": size,
|
|
2394
|
+
className: cn(
|
|
2395
|
+
"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",
|
|
2396
|
+
className
|
|
2397
|
+
),
|
|
2398
|
+
...props
|
|
2399
|
+
}
|
|
2400
|
+
)
|
|
2401
|
+
] });
|
|
2402
|
+
}
|
|
2403
|
+
function AlertDialogHeader({
|
|
2404
|
+
className,
|
|
2405
|
+
...props
|
|
2406
|
+
}) {
|
|
2407
|
+
return /* @__PURE__ */ jsx28(
|
|
2408
|
+
"div",
|
|
2409
|
+
{
|
|
2410
|
+
"data-slot": "alert-dialog-header",
|
|
2411
|
+
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),
|
|
2412
|
+
...props
|
|
2413
|
+
}
|
|
2414
|
+
);
|
|
2415
|
+
}
|
|
2416
|
+
function AlertDialogFooter({
|
|
2417
|
+
className,
|
|
2418
|
+
...props
|
|
2419
|
+
}) {
|
|
2420
|
+
return /* @__PURE__ */ jsx28(
|
|
2421
|
+
"div",
|
|
2422
|
+
{
|
|
2423
|
+
"data-slot": "alert-dialog-footer",
|
|
2424
|
+
className: cn(
|
|
2425
|
+
"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",
|
|
2426
|
+
className
|
|
2427
|
+
),
|
|
2428
|
+
...props
|
|
2429
|
+
}
|
|
2430
|
+
);
|
|
2431
|
+
}
|
|
2432
|
+
function AlertDialogTitle({
|
|
2433
|
+
className,
|
|
2434
|
+
...props
|
|
2435
|
+
}) {
|
|
2436
|
+
return /* @__PURE__ */ jsx28(
|
|
2437
|
+
AlertDialogPrimitive.Title,
|
|
2438
|
+
{
|
|
2439
|
+
"data-slot": "alert-dialog-title",
|
|
2440
|
+
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),
|
|
2441
|
+
...props
|
|
2442
|
+
}
|
|
2443
|
+
);
|
|
2444
|
+
}
|
|
2445
|
+
function AlertDialogDescription({
|
|
2446
|
+
className,
|
|
2447
|
+
...props
|
|
2448
|
+
}) {
|
|
2449
|
+
return /* @__PURE__ */ jsx28(
|
|
2450
|
+
AlertDialogPrimitive.Description,
|
|
2451
|
+
{
|
|
2452
|
+
"data-slot": "alert-dialog-description",
|
|
2453
|
+
className: cn("text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3", className),
|
|
2454
|
+
...props
|
|
2455
|
+
}
|
|
2456
|
+
);
|
|
2457
|
+
}
|
|
2458
|
+
function AlertDialogAction({
|
|
2459
|
+
className,
|
|
2460
|
+
variant = "default",
|
|
2461
|
+
size = "default",
|
|
2462
|
+
...props
|
|
2463
|
+
}) {
|
|
2464
|
+
return /* @__PURE__ */ jsx28(Button, { variant, size, asChild: true, children: /* @__PURE__ */ jsx28(
|
|
2465
|
+
AlertDialogPrimitive.Action,
|
|
2466
|
+
{
|
|
2467
|
+
"data-slot": "alert-dialog-action",
|
|
2468
|
+
className: cn(className),
|
|
2469
|
+
...props
|
|
2470
|
+
}
|
|
2471
|
+
) });
|
|
2472
|
+
}
|
|
2473
|
+
function AlertDialogCancel({
|
|
2474
|
+
className,
|
|
2475
|
+
variant = "outline",
|
|
2476
|
+
size = "default",
|
|
2477
|
+
...props
|
|
2478
|
+
}) {
|
|
2479
|
+
return /* @__PURE__ */ jsx28(Button, { variant, size, asChild: true, children: /* @__PURE__ */ jsx28(
|
|
2480
|
+
AlertDialogPrimitive.Cancel,
|
|
2481
|
+
{
|
|
2482
|
+
"data-slot": "alert-dialog-cancel",
|
|
2483
|
+
className: cn(className),
|
|
2484
|
+
...props
|
|
2485
|
+
}
|
|
2486
|
+
) });
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
// src/components/users/users-page.tsx
|
|
2490
|
+
import { Pencil, Trash2 as Trash22, Search, Forward, Plus } from "lucide-react";
|
|
2491
|
+
import { format } from "date-fns";
|
|
2492
|
+
import { ptBR } from "date-fns/locale";
|
|
2493
|
+
import { toast as toast3 } from "sonner";
|
|
2494
|
+
import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2495
|
+
var PAGE_SIZE = 15;
|
|
2496
|
+
var PROFILE_FILTER_OPTIONS = [
|
|
2497
|
+
{ value: "all", label: "Todos os perfis" },
|
|
2498
|
+
{ value: "owner", label: "Propriet\xE1rio" },
|
|
2499
|
+
{ value: "admin", label: "Administrador" },
|
|
2500
|
+
{ value: "collaborator", label: "Colaborador" },
|
|
2501
|
+
{ value: "attendant", label: "Atendente" },
|
|
2502
|
+
{ value: "viewer", label: "Visualizador" }
|
|
2503
|
+
];
|
|
2504
|
+
function useColumns(onEdit, onDelete, onResetPassword) {
|
|
2505
|
+
return [
|
|
2506
|
+
{
|
|
2507
|
+
accessorKey: "name",
|
|
2508
|
+
header: "Nome",
|
|
2509
|
+
cell: ({ row }) => /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
2510
|
+
/* @__PURE__ */ jsx29(
|
|
2511
|
+
EntityAvatar,
|
|
2512
|
+
{
|
|
2513
|
+
photo: row.original.photo,
|
|
2514
|
+
name: `${row.original.name} ${row.original.last_name}`.trim(),
|
|
2515
|
+
size: "sm"
|
|
2516
|
+
}
|
|
2517
|
+
),
|
|
2518
|
+
/* @__PURE__ */ jsxs19("span", { className: "font-medium", children: [
|
|
2519
|
+
row.original.name,
|
|
2520
|
+
" ",
|
|
2521
|
+
row.original.last_name
|
|
2522
|
+
] })
|
|
2523
|
+
] }),
|
|
2524
|
+
sortingFn: (rowA, rowB) => {
|
|
2525
|
+
const a = `${rowA.original.name} ${rowA.original.last_name}`.toLowerCase();
|
|
2526
|
+
const b = `${rowB.original.name} ${rowB.original.last_name}`.toLowerCase();
|
|
2527
|
+
return a.localeCompare(b);
|
|
2528
|
+
}
|
|
2529
|
+
},
|
|
2530
|
+
{
|
|
2531
|
+
accessorKey: "email",
|
|
2532
|
+
header: "E-mail"
|
|
2533
|
+
},
|
|
2534
|
+
{
|
|
2535
|
+
accessorKey: "profile",
|
|
2536
|
+
header: "Perfil",
|
|
2537
|
+
cell: ({ row }) => /* @__PURE__ */ jsx29(UserProfileBadge, { profile: row.original.profile }),
|
|
2538
|
+
sortingFn: (rowA, rowB) => rowA.original.profile.localeCompare(rowB.original.profile)
|
|
2539
|
+
},
|
|
2540
|
+
{
|
|
2541
|
+
accessorKey: "last_login",
|
|
2542
|
+
header: "\xDAltimo acesso",
|
|
2543
|
+
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" })
|
|
2544
|
+
},
|
|
2545
|
+
{
|
|
2546
|
+
accessorKey: "datetime_add",
|
|
2547
|
+
header: "Criado em",
|
|
2548
|
+
cell: ({ row }) => /* @__PURE__ */ jsx29("span", { className: "text-muted-foreground text-sm", children: format(new Date(row.original.datetime_add), "dd/MM/yyyy", { locale: ptBR }) })
|
|
2549
|
+
},
|
|
2550
|
+
{
|
|
2551
|
+
id: "actions",
|
|
2552
|
+
size: 120,
|
|
2553
|
+
enableSorting: false,
|
|
2554
|
+
cell: ({ row }) => /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-1", children: [
|
|
2555
|
+
/* @__PURE__ */ jsxs19(Tooltip, { children: [
|
|
2556
|
+
/* @__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" }) }) }),
|
|
2557
|
+
/* @__PURE__ */ jsx29(TooltipContent, { children: "Resetar senha" })
|
|
2558
|
+
] }),
|
|
2559
|
+
/* @__PURE__ */ jsxs19(Tooltip, { children: [
|
|
2560
|
+
/* @__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" }) }) }),
|
|
2561
|
+
/* @__PURE__ */ jsx29(TooltipContent, { children: "Editar" })
|
|
2562
|
+
] }),
|
|
2563
|
+
/* @__PURE__ */ jsxs19(Tooltip, { children: [
|
|
2564
|
+
/* @__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" }) }) }),
|
|
2565
|
+
/* @__PURE__ */ jsx29(TooltipContent, { children: "Excluir" })
|
|
2566
|
+
] })
|
|
2567
|
+
] })
|
|
2568
|
+
}
|
|
2569
|
+
];
|
|
2570
|
+
}
|
|
2571
|
+
function UsersPage({ config, renderPhones }) {
|
|
2572
|
+
const [search, setSearch] = useState7("");
|
|
2573
|
+
const [profileFilter, setProfileFilter] = useState7("all");
|
|
2574
|
+
const [page, setPage] = useState7(1);
|
|
2575
|
+
const queryParams = useMemo3(() => {
|
|
2576
|
+
const params = {
|
|
2577
|
+
limit: String(PAGE_SIZE),
|
|
2578
|
+
page: String(page)
|
|
2579
|
+
};
|
|
2580
|
+
if (profileFilter !== "all") params.profile = profileFilter;
|
|
2581
|
+
return params;
|
|
2582
|
+
}, [profileFilter, page]);
|
|
2583
|
+
const { data, isLoading } = useUsers(config, queryParams);
|
|
2584
|
+
const deleteUser = useDeleteUser(config);
|
|
2585
|
+
const resetPassword = useResetPassword(config);
|
|
2586
|
+
const [editUser, setEditUser] = useState7(null);
|
|
2587
|
+
const [formOpen, setFormOpen] = useState7(false);
|
|
2588
|
+
const [deleteId, setDeleteId] = useState7(null);
|
|
2589
|
+
const [resetUser, setResetUser] = useState7(null);
|
|
2590
|
+
const users = data?.data || [];
|
|
2591
|
+
const total = data?.total || 0;
|
|
2592
|
+
const filtered = useMemo3(() => {
|
|
2593
|
+
if (!search) return users;
|
|
2594
|
+
const term = search.toLowerCase();
|
|
2595
|
+
return users.filter(
|
|
2596
|
+
(u) => `${u.name} ${u.last_name}`.toLowerCase().includes(term) || u.email.toLowerCase().includes(term)
|
|
2597
|
+
);
|
|
2598
|
+
}, [users, search]);
|
|
2599
|
+
const columns = useColumns(
|
|
2600
|
+
(u) => {
|
|
2601
|
+
setEditUser(u);
|
|
2602
|
+
setFormOpen(true);
|
|
2603
|
+
},
|
|
2604
|
+
(id) => setDeleteId(id),
|
|
2605
|
+
(u) => setResetUser(u)
|
|
2606
|
+
);
|
|
2607
|
+
function handleDelete() {
|
|
2608
|
+
if (!deleteId) return;
|
|
2609
|
+
deleteUser.mutate(deleteId, {
|
|
2610
|
+
onSuccess: () => {
|
|
2611
|
+
toast3.success("Usu\xE1rio exclu\xEDdo");
|
|
2612
|
+
setDeleteId(null);
|
|
2613
|
+
},
|
|
2614
|
+
onError: () => toast3.error("Erro ao excluir usu\xE1rio")
|
|
2615
|
+
});
|
|
2616
|
+
}
|
|
2617
|
+
function handleResetPassword() {
|
|
2618
|
+
if (!resetUser) return;
|
|
2619
|
+
resetPassword.mutate(resetUser.id, {
|
|
2620
|
+
onSuccess: () => {
|
|
2621
|
+
toast3.success("Senha resetada e email enviado");
|
|
2622
|
+
setResetUser(null);
|
|
2623
|
+
},
|
|
2624
|
+
onError: () => {
|
|
2625
|
+
toast3.error("Erro ao resetar senha");
|
|
2626
|
+
setResetUser(null);
|
|
2627
|
+
}
|
|
2628
|
+
});
|
|
2629
|
+
}
|
|
2630
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-4 p-4", children: [
|
|
2631
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between", children: [
|
|
2632
|
+
/* @__PURE__ */ jsxs19("div", { children: [
|
|
2633
|
+
/* @__PURE__ */ jsx29("h1", { className: "text-xl font-semibold", children: "Usu\xE1rios" }),
|
|
2634
|
+
/* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground", children: "Gest\xE3o de usu\xE1rios da conta" })
|
|
2635
|
+
] }),
|
|
2636
|
+
/* @__PURE__ */ jsxs19(Button, { onClick: () => {
|
|
2637
|
+
setEditUser(null);
|
|
2638
|
+
setFormOpen(true);
|
|
2639
|
+
}, size: "sm", children: [
|
|
2640
|
+
/* @__PURE__ */ jsx29(Plus, { className: "mr-2 h-4 w-4" }),
|
|
2641
|
+
"Novo Usu\xE1rio"
|
|
2642
|
+
] })
|
|
2643
|
+
] }),
|
|
2644
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-3", children: [
|
|
2645
|
+
/* @__PURE__ */ jsxs19("div", { className: "relative flex-1 max-w-md", children: [
|
|
2646
|
+
/* @__PURE__ */ jsx29(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
2647
|
+
/* @__PURE__ */ jsx29(
|
|
2648
|
+
Input,
|
|
2649
|
+
{
|
|
2650
|
+
placeholder: "Buscar por nome ou e-mail...",
|
|
2651
|
+
value: search,
|
|
2652
|
+
onChange: (e) => {
|
|
2653
|
+
setSearch(e.target.value);
|
|
2654
|
+
setPage(1);
|
|
2655
|
+
},
|
|
2656
|
+
className: "pl-9"
|
|
2657
|
+
}
|
|
2658
|
+
)
|
|
2659
|
+
] }),
|
|
2660
|
+
/* @__PURE__ */ jsxs19(Select, { value: profileFilter, onValueChange: (v) => {
|
|
2661
|
+
setProfileFilter(v);
|
|
2662
|
+
setPage(1);
|
|
2663
|
+
}, children: [
|
|
2664
|
+
/* @__PURE__ */ jsx29(SelectTrigger, { className: "w-[180px]", children: /* @__PURE__ */ jsx29(SelectValue, {}) }),
|
|
2665
|
+
/* @__PURE__ */ jsx29(SelectContent, { children: PROFILE_FILTER_OPTIONS.map((opt) => /* @__PURE__ */ jsx29(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
|
|
2666
|
+
] })
|
|
2667
|
+
] }),
|
|
2668
|
+
/* @__PURE__ */ jsx29(
|
|
2669
|
+
DataTable,
|
|
2670
|
+
{
|
|
2671
|
+
columns,
|
|
2672
|
+
data: search ? filtered : users,
|
|
2673
|
+
isLoading,
|
|
2674
|
+
emptyMessage: "Nenhum usu\xE1rio encontrado",
|
|
2675
|
+
total: search ? filtered.length : total,
|
|
2676
|
+
page,
|
|
2677
|
+
onPageChange: setPage,
|
|
2678
|
+
pageSize: PAGE_SIZE
|
|
2679
|
+
}
|
|
2680
|
+
),
|
|
2681
|
+
/* @__PURE__ */ jsx29(
|
|
2682
|
+
UserFormDialog,
|
|
2683
|
+
{
|
|
2684
|
+
open: formOpen,
|
|
2685
|
+
onOpenChange: (open) => {
|
|
2686
|
+
setFormOpen(open);
|
|
2687
|
+
if (!open) setEditUser(null);
|
|
2688
|
+
},
|
|
2689
|
+
user: editUser ?? void 0,
|
|
2690
|
+
config,
|
|
2691
|
+
renderPhones
|
|
2692
|
+
}
|
|
2693
|
+
),
|
|
2694
|
+
/* @__PURE__ */ jsx29(AlertDialog, { open: !!deleteId, onOpenChange: (open) => !open && setDeleteId(null), children: /* @__PURE__ */ jsxs19(AlertDialogContent, { children: [
|
|
2695
|
+
/* @__PURE__ */ jsxs19(AlertDialogHeader, { children: [
|
|
2696
|
+
/* @__PURE__ */ jsx29(AlertDialogTitle, { children: "Excluir usu\xE1rio?" }),
|
|
2697
|
+
/* @__PURE__ */ jsx29(AlertDialogDescription, { children: "Esta a\xE7\xE3o n\xE3o pode ser desfeita. O usu\xE1rio ser\xE1 removido permanentemente." })
|
|
2698
|
+
] }),
|
|
2699
|
+
/* @__PURE__ */ jsxs19(AlertDialogFooter, { children: [
|
|
2700
|
+
/* @__PURE__ */ jsx29(AlertDialogCancel, { children: "Cancelar" }),
|
|
2701
|
+
/* @__PURE__ */ jsx29(AlertDialogAction, { onClick: handleDelete, className: "bg-destructive text-destructive-foreground hover:bg-destructive/90", children: "Excluir" })
|
|
2702
|
+
] })
|
|
2703
|
+
] }) }),
|
|
2704
|
+
/* @__PURE__ */ jsx29(AlertDialog, { open: !!resetUser, onOpenChange: (open) => !open && setResetUser(null), children: /* @__PURE__ */ jsxs19(AlertDialogContent, { children: [
|
|
2705
|
+
/* @__PURE__ */ jsxs19(AlertDialogHeader, { children: [
|
|
2706
|
+
/* @__PURE__ */ jsx29(AlertDialogTitle, { children: "Resetar senha?" }),
|
|
2707
|
+
/* @__PURE__ */ jsxs19(AlertDialogDescription, { children: [
|
|
2708
|
+
"A senha de ",
|
|
2709
|
+
/* @__PURE__ */ jsxs19("strong", { children: [
|
|
2710
|
+
resetUser?.name,
|
|
2711
|
+
" ",
|
|
2712
|
+
resetUser?.last_name
|
|
2713
|
+
] }),
|
|
2714
|
+
" (",
|
|
2715
|
+
resetUser?.email,
|
|
2716
|
+
") ser\xE1 removida e um email com link para definir nova senha ser\xE1 enviado."
|
|
2717
|
+
] })
|
|
2718
|
+
] }),
|
|
2719
|
+
/* @__PURE__ */ jsxs19(AlertDialogFooter, { children: [
|
|
2720
|
+
/* @__PURE__ */ jsx29(AlertDialogCancel, { children: "Cancelar" }),
|
|
2721
|
+
/* @__PURE__ */ jsx29(AlertDialogAction, { onClick: handleResetPassword, children: "Resetar e enviar" })
|
|
2722
|
+
] })
|
|
2723
|
+
] }) })
|
|
2724
|
+
] });
|
|
2725
|
+
}
|
|
1800
2726
|
export {
|
|
1801
2727
|
AppHeader,
|
|
1802
2728
|
AppShell,
|
|
1803
2729
|
AppSidebar,
|
|
2730
|
+
DataTable,
|
|
1804
2731
|
EntityAvatar,
|
|
1805
2732
|
ImageCropUpload,
|
|
1806
2733
|
LoginForm,
|
|
@@ -1809,6 +2736,9 @@ export {
|
|
|
1809
2736
|
SidebarTrigger,
|
|
1810
2737
|
ThemeToggle,
|
|
1811
2738
|
TooltipProvider,
|
|
2739
|
+
UserFormDialog,
|
|
2740
|
+
UserProfileBadge,
|
|
2741
|
+
UsersPage,
|
|
1812
2742
|
authClient,
|
|
1813
2743
|
authMiddlewareConfig,
|
|
1814
2744
|
cn,
|
|
@@ -1817,7 +2747,12 @@ export {
|
|
|
1817
2747
|
signIn,
|
|
1818
2748
|
signOut,
|
|
1819
2749
|
signUp,
|
|
2750
|
+
useCreateUser,
|
|
2751
|
+
useDeleteUser,
|
|
2752
|
+
useResetPassword,
|
|
1820
2753
|
useSession,
|
|
1821
|
-
useSidebar
|
|
2754
|
+
useSidebar,
|
|
2755
|
+
useUpdateUser,
|
|
2756
|
+
useUsers
|
|
1822
2757
|
};
|
|
1823
2758
|
//# sourceMappingURL=index.js.map
|