@greatapps/common 1.1.1 → 1.1.2
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/components/layouts/NavBarItem.mjs +23 -0
- package/dist/components/layouts/NavBarItem.mjs.map +1 -0
- package/dist/components/layouts/ProfilePopover.mjs +141 -0
- package/dist/components/layouts/ProfilePopover.mjs.map +1 -0
- package/dist/components/ui/data-display/UserAvatar.mjs +49 -0
- package/dist/components/ui/data-display/UserAvatar.mjs.map +1 -0
- package/dist/index.mjs +6 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/layouts/NavBarItem.tsx +29 -0
- package/src/components/layouts/ProfilePopover.tsx +171 -0
- package/src/components/ui/data-display/UserAvatar.tsx +67 -0
- package/src/index.ts +6 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from "../../infra/utils/clsx";
|
|
4
|
+
function NavBarItem({ icon, label, onClick, className, labelClassName }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs(
|
|
6
|
+
"div",
|
|
7
|
+
{
|
|
8
|
+
className: cn(
|
|
9
|
+
"rounded-lg flex items-center gap-2 px-2 py-2 h-10 cursor-pointer transition-colors bg-white hover:bg-gray-100 active:bg-gray-50",
|
|
10
|
+
className
|
|
11
|
+
),
|
|
12
|
+
onClick,
|
|
13
|
+
children: [
|
|
14
|
+
icon,
|
|
15
|
+
/* @__PURE__ */ jsx("span", { className: cn("text-sm font-medium text-gray-950", labelClassName), children: label })
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
NavBarItem
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=NavBarItem.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/layouts/NavBarItem.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { cn } from '../../infra/utils/clsx';\r\n\r\ntype NavBarItemProps = {\r\n icon?: React.ReactNode;\r\n label: string;\r\n onClick: () => void;\r\n className?: string;\r\n labelClassName?: string;\r\n}\r\n\r\nfunction NavBarItem({ icon, label, onClick, className, labelClassName }: NavBarItemProps) {\r\n return (\r\n <div\r\n className={cn(\r\n 'rounded-lg flex items-center gap-2 px-2 py-2 h-10 cursor-pointer transition-colors bg-white hover:bg-gray-100 active:bg-gray-50',\r\n className\r\n )}\r\n onClick={onClick}\r\n >\r\n {icon}\r\n <span className={cn('text-sm font-medium text-gray-950', labelClassName)}>{label}</span>\r\n </div>\r\n );\r\n}\r\n\r\nexport { NavBarItem };\r\nexport type { NavBarItemProps };\r\n"],"mappings":";AAcI,SAQE,KARF;AAZJ,SAAS,UAAU;AAUnB,SAAS,WAAW,EAAE,MAAM,OAAO,SAAS,WAAW,eAAe,GAAoB;AACxF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,QACD,oBAAC,UAAK,WAAW,GAAG,qCAAqC,cAAc,GAAI,iBAAM;AAAA;AAAA;AAAA,EACnF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { useRouter } from "next/navigation";
|
|
5
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../ui/overlay/Popover";
|
|
6
|
+
import { Button } from "../ui/buttons/Button";
|
|
7
|
+
import { Progress } from "../ui/feedback/Progress";
|
|
8
|
+
import { Separator } from "../ui/data-display/Separator";
|
|
9
|
+
import { NavBarItem } from "./NavBarItem";
|
|
10
|
+
import { UserAvatar } from "../ui/data-display/UserAvatar";
|
|
11
|
+
import { useAuth } from "../../providers/auth.provider";
|
|
12
|
+
import { cn } from "../../infra/utils/clsx";
|
|
13
|
+
function ProfilePopover({
|
|
14
|
+
side = "top",
|
|
15
|
+
align = "start",
|
|
16
|
+
contentClassName,
|
|
17
|
+
onEditProfile,
|
|
18
|
+
credits,
|
|
19
|
+
onCreditsClick,
|
|
20
|
+
menuItems = [],
|
|
21
|
+
logoutRedirect = "/login",
|
|
22
|
+
storageUrl,
|
|
23
|
+
logoutOverlay
|
|
24
|
+
}) {
|
|
25
|
+
const router = useRouter();
|
|
26
|
+
const { user, logout } = useAuth();
|
|
27
|
+
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
|
28
|
+
const handleLogout = async () => {
|
|
29
|
+
try {
|
|
30
|
+
setIsLoggingOut(true);
|
|
31
|
+
await logout();
|
|
32
|
+
router.push(logoutRedirect);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error("Erro ao fazer logout:", error);
|
|
35
|
+
} finally {
|
|
36
|
+
setIsLoggingOut(false);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const creditsPercentage = credits && credits.total > 0 ? credits.used / credits.total * 100 : 0;
|
|
40
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
41
|
+
isLoggingOut && logoutOverlay,
|
|
42
|
+
/* @__PURE__ */ jsxs(Popover, { children: [
|
|
43
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { className: "cursor-pointer", children: user && /* @__PURE__ */ jsx(
|
|
44
|
+
UserAvatar,
|
|
45
|
+
{
|
|
46
|
+
photo: user.photo,
|
|
47
|
+
name: user.name,
|
|
48
|
+
size: 40,
|
|
49
|
+
storageUrl
|
|
50
|
+
},
|
|
51
|
+
user.id
|
|
52
|
+
) }),
|
|
53
|
+
/* @__PURE__ */ jsxs(
|
|
54
|
+
PopoverContent,
|
|
55
|
+
{
|
|
56
|
+
className: cn(
|
|
57
|
+
"w-64.75 p-0 bg-white rounded-2xl shadow-md border border-gray-200 z-99",
|
|
58
|
+
contentClassName
|
|
59
|
+
),
|
|
60
|
+
side,
|
|
61
|
+
align,
|
|
62
|
+
sideOffset: 8,
|
|
63
|
+
children: [
|
|
64
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[32px_1fr_auto] items-center gap-3 p-3 w-full", children: [
|
|
65
|
+
user && /* @__PURE__ */ jsx(
|
|
66
|
+
UserAvatar,
|
|
67
|
+
{
|
|
68
|
+
photo: user.photo,
|
|
69
|
+
name: user.name,
|
|
70
|
+
size: 32,
|
|
71
|
+
storageUrl
|
|
72
|
+
},
|
|
73
|
+
user.id
|
|
74
|
+
),
|
|
75
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [
|
|
76
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-small-semibold text-gray-950 truncate", children: user?.name || "" }),
|
|
77
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-xsmall-medium text-gray-500 truncate", children: user?.email || "" })
|
|
78
|
+
] }),
|
|
79
|
+
onEditProfile && /* @__PURE__ */ jsx(
|
|
80
|
+
Button,
|
|
81
|
+
{
|
|
82
|
+
variant: "secondary",
|
|
83
|
+
className: "paragraph-small-semibold h-8! whitespace-nowrap px-3 w-fit",
|
|
84
|
+
onClick: onEditProfile,
|
|
85
|
+
children: "Editar Perfil"
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
] }),
|
|
89
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 border-t border-gray-200 rounded-2xl p-1.5", children: [
|
|
90
|
+
credits && /* @__PURE__ */ jsxs(
|
|
91
|
+
"div",
|
|
92
|
+
{
|
|
93
|
+
className: cn(
|
|
94
|
+
"flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors",
|
|
95
|
+
onCreditsClick && "cursor-pointer hover:bg-gray-900"
|
|
96
|
+
),
|
|
97
|
+
onClick: onCreditsClick,
|
|
98
|
+
children: [
|
|
99
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
100
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-xsmall-semibold text-white truncate", children: "Cr\xE9ditos usados" }),
|
|
101
|
+
/* @__PURE__ */ jsxs("span", { className: "paragraph-xsmall-medium text-white/50", children: [
|
|
102
|
+
credits.used.toLocaleString("pt-BR"),
|
|
103
|
+
"/",
|
|
104
|
+
credits.total.toLocaleString("pt-BR")
|
|
105
|
+
] })
|
|
106
|
+
] }),
|
|
107
|
+
/* @__PURE__ */ jsx(
|
|
108
|
+
Progress,
|
|
109
|
+
{
|
|
110
|
+
className: "bg-white/10",
|
|
111
|
+
indicatorColor: "bg-white",
|
|
112
|
+
value: creditsPercentage
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
),
|
|
118
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
119
|
+
menuItems.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-col", children: menuItems.map((item, index) => /* @__PURE__ */ jsx(
|
|
120
|
+
NavBarItem,
|
|
121
|
+
{
|
|
122
|
+
icon: item.icon,
|
|
123
|
+
label: item.label,
|
|
124
|
+
onClick: item.onClick
|
|
125
|
+
},
|
|
126
|
+
index
|
|
127
|
+
)) }),
|
|
128
|
+
/* @__PURE__ */ jsx(Separator, {}),
|
|
129
|
+
/* @__PURE__ */ jsx(NavBarItem, { label: "Sair", onClick: handleLogout })
|
|
130
|
+
] })
|
|
131
|
+
] })
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
] })
|
|
136
|
+
] });
|
|
137
|
+
}
|
|
138
|
+
export {
|
|
139
|
+
ProfilePopover
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=ProfilePopover.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/layouts/ProfilePopover.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { useState } from 'react';\r\nimport { useRouter } from 'next/navigation';\r\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/overlay/Popover';\r\nimport { Button } from '../ui/buttons/Button';\r\nimport { Progress } from '../ui/feedback/Progress';\r\nimport { Separator } from '../ui/data-display/Separator';\r\nimport { NavBarItem } from './NavBarItem';\r\nimport { UserAvatar } from '../ui/data-display/UserAvatar';\r\nimport { useAuth } from '../../providers/auth.provider';\r\nimport { cn } from '../../infra/utils/clsx';\r\n\r\nexport interface ProfileMenuItem {\r\n icon?: React.ReactNode;\r\n label: string;\r\n onClick: () => void;\r\n}\r\n\r\nexport interface ProfilePopoverProps {\r\n side?: 'top' | 'bottom' | 'left' | 'right';\r\n align?: 'start' | 'center' | 'end';\r\n contentClassName?: string;\r\n onEditProfile?: () => void;\r\n credits?: { used: number; total: number };\r\n onCreditsClick?: () => void;\r\n menuItems?: ProfileMenuItem[];\r\n logoutRedirect?: string;\r\n storageUrl?: string;\r\n logoutOverlay?: React.ReactNode;\r\n}\r\n\r\nfunction ProfilePopover({\r\n side = 'top',\r\n align = 'start',\r\n contentClassName,\r\n onEditProfile,\r\n credits,\r\n onCreditsClick,\r\n menuItems = [],\r\n logoutRedirect = '/login',\r\n storageUrl,\r\n logoutOverlay,\r\n}: ProfilePopoverProps) {\r\n const router = useRouter();\r\n const { user, logout } = useAuth();\r\n const [isLoggingOut, setIsLoggingOut] = useState(false);\r\n\r\n const handleLogout = async () => {\r\n try {\r\n setIsLoggingOut(true);\r\n await logout();\r\n router.push(logoutRedirect);\r\n } catch (error) {\r\n console.error('Erro ao fazer logout:', error);\r\n } finally {\r\n setIsLoggingOut(false);\r\n }\r\n };\r\n\r\n const creditsPercentage =\r\n credits && credits.total > 0\r\n ? (credits.used / credits.total) * 100\r\n : 0;\r\n\r\n return (\r\n <>\r\n {isLoggingOut && logoutOverlay}\r\n <Popover>\r\n <PopoverTrigger className=\"cursor-pointer\">\r\n {user && (\r\n <UserAvatar\r\n key={user.id}\r\n photo={user.photo}\r\n name={user.name}\r\n size={40}\r\n storageUrl={storageUrl}\r\n />\r\n )}\r\n </PopoverTrigger>\r\n\r\n <PopoverContent\r\n className={cn(\r\n 'w-64.75 p-0 bg-white rounded-2xl shadow-md border border-gray-200 z-99',\r\n contentClassName\r\n )}\r\n side={side}\r\n align={align}\r\n sideOffset={8}\r\n >\r\n <div className=\"grid grid-cols-[32px_1fr_auto] items-center gap-3 p-3 w-full\">\r\n {user && (\r\n <UserAvatar\r\n key={user.id}\r\n photo={user.photo}\r\n name={user.name}\r\n size={32}\r\n storageUrl={storageUrl}\r\n />\r\n )}\r\n\r\n <div className=\"flex flex-col gap-0.5 min-w-0\">\r\n <span className=\"paragraph-small-semibold text-gray-950 truncate\">\r\n {user?.name || ''}\r\n </span>\r\n <span className=\"paragraph-xsmall-medium text-gray-500 truncate\">\r\n {user?.email || ''}\r\n </span>\r\n </div>\r\n\r\n {onEditProfile && (\r\n <Button\r\n variant=\"secondary\"\r\n className=\"paragraph-small-semibold h-8! whitespace-nowrap px-3 w-fit\"\r\n onClick={onEditProfile}\r\n >\r\n Editar Perfil\r\n </Button>\r\n )}\r\n </div>\r\n\r\n <div className=\"flex flex-col gap-2 border-t border-gray-200 rounded-2xl p-1.5\">\r\n {credits && (\r\n <div\r\n className={cn(\r\n 'flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors',\r\n onCreditsClick && 'cursor-pointer hover:bg-gray-900'\r\n )}\r\n onClick={onCreditsClick}\r\n >\r\n <div className=\"flex items-center justify-between gap-2\">\r\n <span className=\"paragraph-xsmall-semibold text-white truncate\">\r\n Créditos usados\r\n </span>\r\n <span className=\"paragraph-xsmall-medium text-white/50\">\r\n {credits.used.toLocaleString('pt-BR')}/\r\n {credits.total.toLocaleString('pt-BR')}\r\n </span>\r\n </div>\r\n <Progress\r\n className=\"bg-white/10\"\r\n indicatorColor=\"bg-white\"\r\n value={creditsPercentage}\r\n />\r\n </div>\r\n )}\r\n\r\n <div className=\"flex flex-col gap-2\">\r\n {menuItems.length > 0 && (\r\n <div className=\"flex flex-col\">\r\n {menuItems.map((item, index) => (\r\n <NavBarItem\r\n key={index}\r\n icon={item.icon}\r\n label={item.label}\r\n onClick={item.onClick}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n <Separator />\r\n <NavBarItem label=\"Sair\" onClick={handleLogout} />\r\n </div>\r\n </div>\r\n </PopoverContent>\r\n </Popover>\r\n </>\r\n );\r\n}\r\n\r\nexport { ProfilePopover };\r\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import Image from "next/image";
|
|
4
|
+
import { cn } from "../../../infra/utils/clsx";
|
|
5
|
+
function getInitials(name, maxLength = 2) {
|
|
6
|
+
return name.split(" ").map((n) => n[0]).join("").slice(0, maxLength).toUpperCase();
|
|
7
|
+
}
|
|
8
|
+
function UserAvatar({
|
|
9
|
+
photo,
|
|
10
|
+
name,
|
|
11
|
+
initials,
|
|
12
|
+
size = 32,
|
|
13
|
+
shape = "circle",
|
|
14
|
+
className,
|
|
15
|
+
storageUrl
|
|
16
|
+
}) {
|
|
17
|
+
const shapeClass = shape === "circle" ? "rounded-full" : "rounded-lg";
|
|
18
|
+
const displayInitials = initials || (name ? getInitials(name) : "?");
|
|
19
|
+
const photoUrl = storageUrl && photo ? `${storageUrl}/${photo}` : photo;
|
|
20
|
+
if (photoUrl) {
|
|
21
|
+
return /* @__PURE__ */ jsx(
|
|
22
|
+
Image,
|
|
23
|
+
{
|
|
24
|
+
alt: name || "imagem do usuario",
|
|
25
|
+
src: photoUrl,
|
|
26
|
+
width: size,
|
|
27
|
+
height: size,
|
|
28
|
+
className: cn("object-cover shrink-0", shapeClass, className),
|
|
29
|
+
style: { width: size, height: size }
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return /* @__PURE__ */ jsx(
|
|
34
|
+
"div",
|
|
35
|
+
{
|
|
36
|
+
className: cn(
|
|
37
|
+
"flex items-center justify-center shrink-0 bg-gray-100",
|
|
38
|
+
shapeClass,
|
|
39
|
+
className
|
|
40
|
+
),
|
|
41
|
+
style: { width: size, height: size },
|
|
42
|
+
children: /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-gray-700", children: displayInitials })
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
UserAvatar
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=UserAvatar.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ui/data-display/UserAvatar.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport Image from 'next/image';\r\nimport { cn } from '../../../infra/utils/clsx';\r\n\r\nfunction getInitials(name: string, maxLength: number = 2): string {\r\n return name\r\n .split(' ')\r\n .map((n) => n[0])\r\n .join('')\r\n .slice(0, maxLength)\r\n .toUpperCase();\r\n}\r\n\r\ninterface UserAvatarProps {\r\n photo?: string | null;\r\n name?: string;\r\n initials?: string;\r\n size?: number;\r\n shape?: 'circle' | 'square';\r\n className?: string;\r\n storageUrl?: string;\r\n}\r\n\r\nfunction UserAvatar({\r\n photo,\r\n name,\r\n initials,\r\n size = 32,\r\n shape = 'circle',\r\n className,\r\n storageUrl,\r\n}: UserAvatarProps) {\r\n const shapeClass = shape === 'circle' ? 'rounded-full' : 'rounded-lg';\r\n const displayInitials = initials || (name ? getInitials(name) : '?');\r\n\r\n const photoUrl = storageUrl && photo ? `${storageUrl}/${photo}` : photo;\r\n\r\n if (photoUrl) {\r\n return (\r\n <Image\r\n alt={name || 'imagem do usuario'}\r\n src={photoUrl}\r\n width={size}\r\n height={size}\r\n className={cn('object-cover shrink-0', shapeClass, className)}\r\n style={{ width: size, height: size }}\r\n />\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n className={cn(\r\n 'flex items-center justify-center shrink-0 bg-gray-100',\r\n shapeClass,\r\n className\r\n )}\r\n style={{ width: size, height: size }}\r\n >\r\n <span className=\"text-xs font-semibold text-gray-700\">{displayInitials}</span>\r\n </div>\r\n );\r\n}\r\n\r\nexport { UserAvatar };\r\nexport type { UserAvatarProps };\r\n"],"mappings":";AAwCM;AAtCN,OAAO,WAAW;AAClB,SAAS,UAAU;AAEnB,SAAS,YAAY,MAAc,YAAoB,GAAW;AAChE,SAAO,KACJ,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EACf,KAAK,EAAE,EACP,MAAM,GAAG,SAAS,EAClB,YAAY;AACjB;AAYA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR;AAAA,EACA;AACF,GAAoB;AAClB,QAAM,aAAa,UAAU,WAAW,iBAAiB;AACzD,QAAM,kBAAkB,aAAa,OAAO,YAAY,IAAI,IAAI;AAEhE,QAAM,WAAW,cAAc,QAAQ,GAAG,UAAU,IAAI,KAAK,KAAK;AAElE,MAAI,UAAU;AACZ,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK,QAAQ;AAAA,QACb,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,WAAW,GAAG,yBAAyB,YAAY,SAAS;AAAA,QAC5D,OAAO,EAAE,OAAO,MAAM,QAAQ,KAAK;AAAA;AAAA,IACrC;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO,EAAE,OAAO,MAAM,QAAQ,KAAK;AAAA,MAEnC,8BAAC,UAAK,WAAU,uCAAuC,2BAAgB;AAAA;AAAA,EACzE;AAEJ;","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -17,6 +17,9 @@ import { NavBar } from "./components/layouts/NavBar";
|
|
|
17
17
|
import { SideBarNavigation } from "./components/layouts/SideBarNavigation";
|
|
18
18
|
import { MdSideBarNavigation } from "./components/layouts/MdSideBarNavigation";
|
|
19
19
|
import { NotificationItem } from "./components/layouts/NotificationItem";
|
|
20
|
+
import { ProfilePopover } from "./components/layouts/ProfilePopover";
|
|
21
|
+
import { NavBarItem } from "./components/layouts/NavBarItem";
|
|
22
|
+
import { UserAvatar } from "./components/ui/data-display/UserAvatar";
|
|
20
23
|
import { useMdSidebarStore } from "./store/useMdSidebarStore";
|
|
21
24
|
export {
|
|
22
25
|
MainLayout,
|
|
@@ -25,10 +28,13 @@ export {
|
|
|
25
28
|
MainLayoutSpacer,
|
|
26
29
|
MdSideBarNavigation,
|
|
27
30
|
NavBar,
|
|
31
|
+
NavBarItem,
|
|
28
32
|
NotificationItem,
|
|
33
|
+
ProfilePopover,
|
|
29
34
|
QueryProvider,
|
|
30
35
|
SideBarNavigation,
|
|
31
36
|
USER_QUERY_KEY,
|
|
37
|
+
UserAvatar,
|
|
32
38
|
buildQueryParams,
|
|
33
39
|
cn,
|
|
34
40
|
continueChain,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Types\nexport * from './modules/auth/schema';\nexport * from './modules/users/schema';\nexport * from './modules/whitelabel/schema';\nexport * from './infra/api/types';\n\n// Contexts\nexport * from './providers/query.provider';\nexport * from './providers/auth.provider';\nexport * from './providers/whitelabel.provider';\n\n// Hooks\nexport { useUserQuery, useUserValidateSession, useInvalidateUser, useSetUserData, USER_QUERY_KEY } from './modules/auth/hooks/useUserQuery';\n\n// Providers\nexport { QueryProvider } from './providers/query.provider';\n\n// Middleware\nexport { createAuthMiddleware } from './middlewares/create-auth-middleware';\nexport { createMiddlewareChain } from './middlewares/chain';\nexport { continueChain, stopChain } from './middlewares/types';\nexport type { MiddlewareFunction, MiddlewareConfig, MiddlewareResult } from './middlewares/types';\n\n// Utils\nexport { cn } from './infra/utils/clsx';\nexport { buildQueryParams } from './infra/utils/params';\n\n// Layout\nexport { MainLayout, MainLayoutContent, MainLayoutSpacer, MainLayoutMain } from './components/layouts/MainLayout';\nexport { NavBar } from './components/layouts/NavBar';\nexport type { NavBarProps } from './components/layouts/NavBar';\nexport { SideBarNavigation } from './components/layouts/SideBarNavigation';\nexport { MdSideBarNavigation } from './components/layouts/MdSideBarNavigation';\nexport { NotificationItem } from './components/layouts/NotificationItem';\nexport type { NotificationItemProps } from './components/layouts/NotificationItem';\n\n// Store\nexport { useMdSidebarStore } from './store/useMdSidebarStore';\n"],"mappings":"AACA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,SAAS,cAAc,wBAAwB,mBAAmB,gBAAgB,sBAAsB;AAGxG,SAAS,qBAAqB;AAG9B,SAAS,4BAA4B;AACrC,SAAS,6BAA6B;AACtC,SAAS,eAAe,iBAAiB;AAIzC,SAAS,UAAU;AACnB,SAAS,wBAAwB;AAGjC,SAAS,YAAY,mBAAmB,kBAAkB,sBAAsB;AAChF,SAAS,cAAc;AAEvB,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AACpC,SAAS,wBAAwB;
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Types\nexport * from './modules/auth/schema';\nexport * from './modules/users/schema';\nexport * from './modules/whitelabel/schema';\nexport * from './infra/api/types';\n\n// Contexts\nexport * from './providers/query.provider';\nexport * from './providers/auth.provider';\nexport * from './providers/whitelabel.provider';\n\n// Hooks\nexport { useUserQuery, useUserValidateSession, useInvalidateUser, useSetUserData, USER_QUERY_KEY } from './modules/auth/hooks/useUserQuery';\n\n// Providers\nexport { QueryProvider } from './providers/query.provider';\n\n// Middleware\nexport { createAuthMiddleware } from './middlewares/create-auth-middleware';\nexport { createMiddlewareChain } from './middlewares/chain';\nexport { continueChain, stopChain } from './middlewares/types';\nexport type { MiddlewareFunction, MiddlewareConfig, MiddlewareResult } from './middlewares/types';\n\n// Utils\nexport { cn } from './infra/utils/clsx';\nexport { buildQueryParams } from './infra/utils/params';\n\n// Layout\nexport { MainLayout, MainLayoutContent, MainLayoutSpacer, MainLayoutMain } from './components/layouts/MainLayout';\nexport { NavBar } from './components/layouts/NavBar';\nexport type { NavBarProps } from './components/layouts/NavBar';\nexport { SideBarNavigation } from './components/layouts/SideBarNavigation';\nexport { MdSideBarNavigation } from './components/layouts/MdSideBarNavigation';\nexport { NotificationItem } from './components/layouts/NotificationItem';\nexport type { NotificationItemProps } from './components/layouts/NotificationItem';\nexport { ProfilePopover } from './components/layouts/ProfilePopover';\nexport type { ProfilePopoverProps, ProfileMenuItem } from './components/layouts/ProfilePopover';\nexport { NavBarItem } from './components/layouts/NavBarItem';\nexport type { NavBarItemProps } from './components/layouts/NavBarItem';\nexport { UserAvatar } from './components/ui/data-display/UserAvatar';\nexport type { UserAvatarProps } from './components/ui/data-display/UserAvatar';\n\n// Store\nexport { useMdSidebarStore } from './store/useMdSidebarStore';\n"],"mappings":"AACA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,SAAS,cAAc,wBAAwB,mBAAmB,gBAAgB,sBAAsB;AAGxG,SAAS,qBAAqB;AAG9B,SAAS,4BAA4B;AACrC,SAAS,6BAA6B;AACtC,SAAS,eAAe,iBAAiB;AAIzC,SAAS,UAAU;AACnB,SAAS,wBAAwB;AAGjC,SAAS,YAAY,mBAAmB,kBAAkB,sBAAsB;AAChF,SAAS,cAAc;AAEvB,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AACpC,SAAS,wBAAwB;AAEjC,SAAS,sBAAsB;AAE/B,SAAS,kBAAkB;AAE3B,SAAS,kBAAkB;AAI3B,SAAS,yBAAyB;","names":[]}
|
package/package.json
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { cn } from '../../infra/utils/clsx';
|
|
4
|
+
|
|
5
|
+
type NavBarItemProps = {
|
|
6
|
+
icon?: React.ReactNode;
|
|
7
|
+
label: string;
|
|
8
|
+
onClick: () => void;
|
|
9
|
+
className?: string;
|
|
10
|
+
labelClassName?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function NavBarItem({ icon, label, onClick, className, labelClassName }: NavBarItemProps) {
|
|
14
|
+
return (
|
|
15
|
+
<div
|
|
16
|
+
className={cn(
|
|
17
|
+
'rounded-lg flex items-center gap-2 px-2 py-2 h-10 cursor-pointer transition-colors bg-white hover:bg-gray-100 active:bg-gray-50',
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
onClick={onClick}
|
|
21
|
+
>
|
|
22
|
+
{icon}
|
|
23
|
+
<span className={cn('text-sm font-medium text-gray-950', labelClassName)}>{label}</span>
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { NavBarItem };
|
|
29
|
+
export type { NavBarItemProps };
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { useRouter } from 'next/navigation';
|
|
5
|
+
import { Popover, PopoverContent, PopoverTrigger } from '../ui/overlay/Popover';
|
|
6
|
+
import { Button } from '../ui/buttons/Button';
|
|
7
|
+
import { Progress } from '../ui/feedback/Progress';
|
|
8
|
+
import { Separator } from '../ui/data-display/Separator';
|
|
9
|
+
import { NavBarItem } from './NavBarItem';
|
|
10
|
+
import { UserAvatar } from '../ui/data-display/UserAvatar';
|
|
11
|
+
import { useAuth } from '../../providers/auth.provider';
|
|
12
|
+
import { cn } from '../../infra/utils/clsx';
|
|
13
|
+
|
|
14
|
+
export interface ProfileMenuItem {
|
|
15
|
+
icon?: React.ReactNode;
|
|
16
|
+
label: string;
|
|
17
|
+
onClick: () => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ProfilePopoverProps {
|
|
21
|
+
side?: 'top' | 'bottom' | 'left' | 'right';
|
|
22
|
+
align?: 'start' | 'center' | 'end';
|
|
23
|
+
contentClassName?: string;
|
|
24
|
+
onEditProfile?: () => void;
|
|
25
|
+
credits?: { used: number; total: number };
|
|
26
|
+
onCreditsClick?: () => void;
|
|
27
|
+
menuItems?: ProfileMenuItem[];
|
|
28
|
+
logoutRedirect?: string;
|
|
29
|
+
storageUrl?: string;
|
|
30
|
+
logoutOverlay?: React.ReactNode;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function ProfilePopover({
|
|
34
|
+
side = 'top',
|
|
35
|
+
align = 'start',
|
|
36
|
+
contentClassName,
|
|
37
|
+
onEditProfile,
|
|
38
|
+
credits,
|
|
39
|
+
onCreditsClick,
|
|
40
|
+
menuItems = [],
|
|
41
|
+
logoutRedirect = '/login',
|
|
42
|
+
storageUrl,
|
|
43
|
+
logoutOverlay,
|
|
44
|
+
}: ProfilePopoverProps) {
|
|
45
|
+
const router = useRouter();
|
|
46
|
+
const { user, logout } = useAuth();
|
|
47
|
+
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
|
48
|
+
|
|
49
|
+
const handleLogout = async () => {
|
|
50
|
+
try {
|
|
51
|
+
setIsLoggingOut(true);
|
|
52
|
+
await logout();
|
|
53
|
+
router.push(logoutRedirect);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error('Erro ao fazer logout:', error);
|
|
56
|
+
} finally {
|
|
57
|
+
setIsLoggingOut(false);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const creditsPercentage =
|
|
62
|
+
credits && credits.total > 0
|
|
63
|
+
? (credits.used / credits.total) * 100
|
|
64
|
+
: 0;
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<>
|
|
68
|
+
{isLoggingOut && logoutOverlay}
|
|
69
|
+
<Popover>
|
|
70
|
+
<PopoverTrigger className="cursor-pointer">
|
|
71
|
+
{user && (
|
|
72
|
+
<UserAvatar
|
|
73
|
+
key={user.id}
|
|
74
|
+
photo={user.photo}
|
|
75
|
+
name={user.name}
|
|
76
|
+
size={40}
|
|
77
|
+
storageUrl={storageUrl}
|
|
78
|
+
/>
|
|
79
|
+
)}
|
|
80
|
+
</PopoverTrigger>
|
|
81
|
+
|
|
82
|
+
<PopoverContent
|
|
83
|
+
className={cn(
|
|
84
|
+
'w-64.75 p-0 bg-white rounded-2xl shadow-md border border-gray-200 z-99',
|
|
85
|
+
contentClassName
|
|
86
|
+
)}
|
|
87
|
+
side={side}
|
|
88
|
+
align={align}
|
|
89
|
+
sideOffset={8}
|
|
90
|
+
>
|
|
91
|
+
<div className="grid grid-cols-[32px_1fr_auto] items-center gap-3 p-3 w-full">
|
|
92
|
+
{user && (
|
|
93
|
+
<UserAvatar
|
|
94
|
+
key={user.id}
|
|
95
|
+
photo={user.photo}
|
|
96
|
+
name={user.name}
|
|
97
|
+
size={32}
|
|
98
|
+
storageUrl={storageUrl}
|
|
99
|
+
/>
|
|
100
|
+
)}
|
|
101
|
+
|
|
102
|
+
<div className="flex flex-col gap-0.5 min-w-0">
|
|
103
|
+
<span className="paragraph-small-semibold text-gray-950 truncate">
|
|
104
|
+
{user?.name || ''}
|
|
105
|
+
</span>
|
|
106
|
+
<span className="paragraph-xsmall-medium text-gray-500 truncate">
|
|
107
|
+
{user?.email || ''}
|
|
108
|
+
</span>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
{onEditProfile && (
|
|
112
|
+
<Button
|
|
113
|
+
variant="secondary"
|
|
114
|
+
className="paragraph-small-semibold h-8! whitespace-nowrap px-3 w-fit"
|
|
115
|
+
onClick={onEditProfile}
|
|
116
|
+
>
|
|
117
|
+
Editar Perfil
|
|
118
|
+
</Button>
|
|
119
|
+
)}
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div className="flex flex-col gap-2 border-t border-gray-200 rounded-2xl p-1.5">
|
|
123
|
+
{credits && (
|
|
124
|
+
<div
|
|
125
|
+
className={cn(
|
|
126
|
+
'flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors',
|
|
127
|
+
onCreditsClick && 'cursor-pointer hover:bg-gray-900'
|
|
128
|
+
)}
|
|
129
|
+
onClick={onCreditsClick}
|
|
130
|
+
>
|
|
131
|
+
<div className="flex items-center justify-between gap-2">
|
|
132
|
+
<span className="paragraph-xsmall-semibold text-white truncate">
|
|
133
|
+
Créditos usados
|
|
134
|
+
</span>
|
|
135
|
+
<span className="paragraph-xsmall-medium text-white/50">
|
|
136
|
+
{credits.used.toLocaleString('pt-BR')}/
|
|
137
|
+
{credits.total.toLocaleString('pt-BR')}
|
|
138
|
+
</span>
|
|
139
|
+
</div>
|
|
140
|
+
<Progress
|
|
141
|
+
className="bg-white/10"
|
|
142
|
+
indicatorColor="bg-white"
|
|
143
|
+
value={creditsPercentage}
|
|
144
|
+
/>
|
|
145
|
+
</div>
|
|
146
|
+
)}
|
|
147
|
+
|
|
148
|
+
<div className="flex flex-col gap-2">
|
|
149
|
+
{menuItems.length > 0 && (
|
|
150
|
+
<div className="flex flex-col">
|
|
151
|
+
{menuItems.map((item, index) => (
|
|
152
|
+
<NavBarItem
|
|
153
|
+
key={index}
|
|
154
|
+
icon={item.icon}
|
|
155
|
+
label={item.label}
|
|
156
|
+
onClick={item.onClick}
|
|
157
|
+
/>
|
|
158
|
+
))}
|
|
159
|
+
</div>
|
|
160
|
+
)}
|
|
161
|
+
<Separator />
|
|
162
|
+
<NavBarItem label="Sair" onClick={handleLogout} />
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
</PopoverContent>
|
|
166
|
+
</Popover>
|
|
167
|
+
</>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export { ProfilePopover };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import Image from 'next/image';
|
|
4
|
+
import { cn } from '../../../infra/utils/clsx';
|
|
5
|
+
|
|
6
|
+
function getInitials(name: string, maxLength: number = 2): string {
|
|
7
|
+
return name
|
|
8
|
+
.split(' ')
|
|
9
|
+
.map((n) => n[0])
|
|
10
|
+
.join('')
|
|
11
|
+
.slice(0, maxLength)
|
|
12
|
+
.toUpperCase();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface UserAvatarProps {
|
|
16
|
+
photo?: string | null;
|
|
17
|
+
name?: string;
|
|
18
|
+
initials?: string;
|
|
19
|
+
size?: number;
|
|
20
|
+
shape?: 'circle' | 'square';
|
|
21
|
+
className?: string;
|
|
22
|
+
storageUrl?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function UserAvatar({
|
|
26
|
+
photo,
|
|
27
|
+
name,
|
|
28
|
+
initials,
|
|
29
|
+
size = 32,
|
|
30
|
+
shape = 'circle',
|
|
31
|
+
className,
|
|
32
|
+
storageUrl,
|
|
33
|
+
}: UserAvatarProps) {
|
|
34
|
+
const shapeClass = shape === 'circle' ? 'rounded-full' : 'rounded-lg';
|
|
35
|
+
const displayInitials = initials || (name ? getInitials(name) : '?');
|
|
36
|
+
|
|
37
|
+
const photoUrl = storageUrl && photo ? `${storageUrl}/${photo}` : photo;
|
|
38
|
+
|
|
39
|
+
if (photoUrl) {
|
|
40
|
+
return (
|
|
41
|
+
<Image
|
|
42
|
+
alt={name || 'imagem do usuario'}
|
|
43
|
+
src={photoUrl}
|
|
44
|
+
width={size}
|
|
45
|
+
height={size}
|
|
46
|
+
className={cn('object-cover shrink-0', shapeClass, className)}
|
|
47
|
+
style={{ width: size, height: size }}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div
|
|
54
|
+
className={cn(
|
|
55
|
+
'flex items-center justify-center shrink-0 bg-gray-100',
|
|
56
|
+
shapeClass,
|
|
57
|
+
className
|
|
58
|
+
)}
|
|
59
|
+
style={{ width: size, height: size }}
|
|
60
|
+
>
|
|
61
|
+
<span className="text-xs font-semibold text-gray-700">{displayInitials}</span>
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { UserAvatar };
|
|
67
|
+
export type { UserAvatarProps };
|
package/src/index.ts
CHANGED
|
@@ -33,6 +33,12 @@ export { SideBarNavigation } from './components/layouts/SideBarNavigation';
|
|
|
33
33
|
export { MdSideBarNavigation } from './components/layouts/MdSideBarNavigation';
|
|
34
34
|
export { NotificationItem } from './components/layouts/NotificationItem';
|
|
35
35
|
export type { NotificationItemProps } from './components/layouts/NotificationItem';
|
|
36
|
+
export { ProfilePopover } from './components/layouts/ProfilePopover';
|
|
37
|
+
export type { ProfilePopoverProps, ProfileMenuItem } from './components/layouts/ProfilePopover';
|
|
38
|
+
export { NavBarItem } from './components/layouts/NavBarItem';
|
|
39
|
+
export type { NavBarItemProps } from './components/layouts/NavBarItem';
|
|
40
|
+
export { UserAvatar } from './components/ui/data-display/UserAvatar';
|
|
41
|
+
export type { UserAvatarProps } from './components/ui/data-display/UserAvatar';
|
|
36
42
|
|
|
37
43
|
// Store
|
|
38
44
|
export { useMdSidebarStore } from './store/useMdSidebarStore';
|