@greatapps/common 1.1.218 → 1.1.221
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/account/ConfigurationsMyAccountModal.mjs +6 -6
- package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
- package/dist/components/account/ConfirmDeleteAccountModal.mjs +2 -2
- package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/ConfirmGlobalPreferencesModal.mjs +2 -2
- package/dist/components/account/ConfirmGlobalPreferencesModal.mjs.map +1 -1
- package/dist/components/account/DeleteAccountModal.mjs +3 -3
- package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/DisableTwoFactorAuthModal.mjs +2 -2
- package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -1
- package/dist/components/account/IsntPossibleDeleteAccountModal.mjs +2 -2
- package/dist/components/account/IsntPossibleDeleteAccountModal.mjs.map +1 -1
- package/dist/components/account/TwoFactorAuthModal.mjs +6 -6
- package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -1
- package/dist/components/account/sections/ChangeEmailModal.mjs +6 -6
- package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
- package/dist/components/account/sections/ChangePasswordSection.mjs +4 -4
- package/dist/components/account/sections/ChangePasswordSection.mjs.map +1 -1
- package/dist/components/account/sections/ChangePhoneModal.mjs +5 -5
- package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
- package/dist/components/account/sections/MyProfileSection.mjs +3 -3
- package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
- package/dist/components/account/sections/PreferencesSection.mjs +6 -6
- package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
- package/dist/components/account/sections/SecuritySection.mjs +3 -3
- package/dist/components/account/sections/SecuritySection.mjs.map +1 -1
- package/dist/components/layouts/AppMobileNavBar.mjs +0 -1
- package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
- package/dist/components/layouts/MdSideBarNavigation.mjs +2 -2
- package/dist/components/layouts/MdSideBarNavigation.mjs.map +1 -1
- package/dist/components/layouts/NavBar.mjs +2 -2
- package/dist/components/layouts/NavBar.mjs.map +1 -1
- package/dist/components/layouts/NotificationsPopover.mjs +4 -4
- package/dist/components/layouts/NotificationsPopover.mjs.map +1 -1
- package/dist/components/layouts/ProfilePopover.mjs +7 -10
- package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
- package/dist/components/layouts/UsersSelectorPopover.mjs +5 -5
- package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
- package/dist/components/navigation/ProjectSelectorPopover.mjs +6 -6
- package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
- package/dist/components/navigation/subcomponents/ProjectSelector.mjs +5 -5
- package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
- package/dist/components/pages/notifications/Notifications.mjs +4 -4
- package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
- package/dist/components/ui/buttons/CopyButton.mjs +2 -2
- package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
- package/dist/components/ui/data-display/Accordion.mjs +2 -2
- package/dist/components/ui/data-display/Accordion.mjs.map +1 -1
- package/dist/components/ui/data-display/Pagination.mjs +7 -7
- package/dist/components/ui/data-display/Pagination.mjs.map +1 -1
- package/dist/components/ui/feedback/Toast.mjs +7 -7
- package/dist/components/ui/feedback/Toast.mjs.map +1 -1
- package/dist/components/ui/form/Calendar.mjs +7 -7
- package/dist/components/ui/form/Calendar.mjs.map +1 -1
- package/dist/components/ui/form/Checkbox.mjs +2 -2
- package/dist/components/ui/form/Checkbox.mjs.map +1 -1
- package/dist/components/ui/form/ComboboxField.mjs +4 -4
- package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
- package/dist/components/ui/form/DateRangePicker.mjs +2 -2
- package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
- package/dist/components/ui/form/FormField.mjs +3 -3
- package/dist/components/ui/form/FormField.mjs.map +1 -1
- package/dist/components/ui/form/InputOtp.mjs +2 -2
- package/dist/components/ui/form/InputOtp.mjs.map +1 -1
- package/dist/components/ui/form/RadioGroup.mjs +2 -2
- package/dist/components/ui/form/RadioGroup.mjs.map +1 -1
- package/dist/components/ui/form/Select.mjs +5 -5
- package/dist/components/ui/form/Select.mjs.map +1 -1
- package/dist/components/ui/form/SwitchOptionFieldWithIcon.mjs.map +1 -1
- package/dist/components/ui/overlay/Command.mjs +2 -2
- package/dist/components/ui/overlay/Command.mjs.map +1 -1
- package/dist/components/ui/overlay/Dialog.mjs +2 -2
- package/dist/components/ui/overlay/Dialog.mjs.map +1 -1
- package/dist/components/ui/overlay/Sheet.mjs +2 -2
- package/dist/components/ui/overlay/Sheet.mjs.map +1 -1
- package/dist/components/widgets/notifications/NotificationCard.mjs +2 -2
- package/dist/components/widgets/notifications/NotificationCard.mjs.map +1 -1
- package/package.json +1 -2
- package/src/components/account/ConfigurationsMyAccountModal.tsx +150 -150
- package/src/components/account/ConfirmDeleteAccountModal.tsx +2 -2
- package/src/components/account/ConfirmGlobalPreferencesModal.tsx +66 -66
- package/src/components/account/DeleteAccountModal.tsx +3 -3
- package/src/components/account/DisableTwoFactorAuthModal.tsx +86 -86
- package/src/components/account/IsntPossibleDeleteAccountModal.tsx +2 -2
- package/src/components/account/TwoFactorAuthModal.tsx +223 -223
- package/src/components/account/sections/ChangeEmailModal.tsx +225 -225
- package/src/components/account/sections/ChangePasswordSection.tsx +64 -64
- package/src/components/account/sections/ChangePhoneModal.tsx +5 -5
- package/src/components/account/sections/MyProfileSection.tsx +327 -327
- package/src/components/account/sections/PreferencesSection.tsx +273 -273
- package/src/components/account/sections/SecuritySection.tsx +160 -160
- package/src/components/layouts/AppMobileNavBar.tsx +0 -1
- package/src/components/layouts/MdSideBarNavigation.tsx +54 -54
- package/src/components/layouts/NavBar.tsx +2 -2
- package/src/components/layouts/NotificationsPopover.tsx +115 -115
- package/src/components/layouts/ProfilePopover.tsx +179 -184
- package/src/components/layouts/UsersSelectorPopover.tsx +5 -5
- package/src/components/navigation/ProjectSelectorPopover.tsx +151 -151
- package/src/components/navigation/subcomponents/ProjectSelector.tsx +149 -149
- package/src/components/pages/notifications/Notifications.tsx +4 -4
- package/src/components/ui/buttons/CopyButton.tsx +2 -2
- package/src/components/ui/data-display/Accordion.tsx +2 -2
- package/src/components/ui/data-display/Pagination.tsx +7 -7
- package/src/components/ui/feedback/Toast.tsx +7 -7
- package/src/components/ui/form/Calendar.tsx +7 -7
- package/src/components/ui/form/Checkbox.tsx +2 -2
- package/src/components/ui/form/ComboboxField.tsx +154 -154
- package/src/components/ui/form/DateRangePicker.tsx +2 -2
- package/src/components/ui/form/FormField.tsx +131 -130
- package/src/components/ui/form/InputOtp.tsx +2 -2
- package/src/components/ui/form/RadioGroup.tsx +2 -2
- package/src/components/ui/form/Select.tsx +5 -5
- package/src/components/ui/form/SwitchOptionFieldWithIcon.tsx +2 -2
- package/src/components/ui/overlay/Command.tsx +2 -2
- package/src/components/ui/overlay/Dialog.tsx +2 -2
- package/src/components/ui/overlay/Sheet.tsx +2 -2
- package/src/components/widgets/notifications/NotificationCard.tsx +68 -68
|
@@ -1,151 +1,151 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Dispatch, RefObject, SetStateAction } from 'react';
|
|
4
|
-
import {
|
|
5
|
-
Button,
|
|
6
|
-
Command,
|
|
7
|
-
CommandEmpty,
|
|
8
|
-
CommandInput,
|
|
9
|
-
CommandItem,
|
|
10
|
-
CommandList,
|
|
11
|
-
Popover,
|
|
12
|
-
PopoverContent,
|
|
13
|
-
PopoverTrigger,
|
|
14
|
-
Tooltip,
|
|
15
|
-
TooltipContent,
|
|
16
|
-
TooltipTrigger,
|
|
17
|
-
UserAvatar,
|
|
18
|
-
} from '../../index';
|
|
19
|
-
import {
|
|
20
|
-
import type { NavigationProject } from './types';
|
|
21
|
-
|
|
22
|
-
interface ProjectSelectorPopoverProps {
|
|
23
|
-
open: boolean;
|
|
24
|
-
setOpen: Dispatch<SetStateAction<boolean>>;
|
|
25
|
-
titleRef?: RefObject<HTMLSpanElement | null>;
|
|
26
|
-
projects: NavigationProject[];
|
|
27
|
-
selectedProject: NavigationProject | null;
|
|
28
|
-
onSelectProject: (project: NavigationProject) => void;
|
|
29
|
-
onAddProject: () => void;
|
|
30
|
-
onManageProjects: () => void;
|
|
31
|
-
children?: React.ReactNode;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function ProjectItemSkeleton() {
|
|
35
|
-
return (
|
|
36
|
-
<div className="flex items-center justify-between px-2 py-1.5 gap-2">
|
|
37
|
-
<div className="flex items-center gap-2 flex-1">
|
|
38
|
-
<div className="skeleton size-8 rounded-lg shrink-0" />
|
|
39
|
-
<div className="skeleton h-3.5 w-32 rounded" />
|
|
40
|
-
</div>
|
|
41
|
-
<div className="skeleton size-4 rounded-full shrink-0" />
|
|
42
|
-
</div>
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function ProjectSelectorPopover({
|
|
47
|
-
open,
|
|
48
|
-
setOpen,
|
|
49
|
-
titleRef,
|
|
50
|
-
projects,
|
|
51
|
-
selectedProject,
|
|
52
|
-
onSelectProject,
|
|
53
|
-
onAddProject,
|
|
54
|
-
onManageProjects,
|
|
55
|
-
children,
|
|
56
|
-
}: ProjectSelectorPopoverProps) {
|
|
57
|
-
return (
|
|
58
|
-
<Popover open={open} onOpenChange={setOpen}>
|
|
59
|
-
<PopoverTrigger asChild>
|
|
60
|
-
{children ?? (
|
|
61
|
-
<button className="cursor-pointer">
|
|
62
|
-
<
|
|
63
|
-
size={20}
|
|
64
|
-
className={`transition-transform duration-200 ${open ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
|
|
65
|
-
/>
|
|
66
|
-
</button>
|
|
67
|
-
)}
|
|
68
|
-
</PopoverTrigger>
|
|
69
|
-
<PopoverContent
|
|
70
|
-
className="w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200"
|
|
71
|
-
align="start"
|
|
72
|
-
sideOffset={8}
|
|
73
|
-
onOpenAutoFocus={(e: Event) => e.preventDefault()}
|
|
74
|
-
onInteractOutside={(event: Event) => {
|
|
75
|
-
if (titleRef?.current?.contains(event.target as Node)) {
|
|
76
|
-
event.preventDefault();
|
|
77
|
-
}
|
|
78
|
-
}}
|
|
79
|
-
>
|
|
80
|
-
<div className="flex flex-col p-3 gap-2">
|
|
81
|
-
<div className="flex items-center justify-between">
|
|
82
|
-
<span className="paragraph-small-semibold">Projetos</span>
|
|
83
|
-
<div className="flex items-center gap-1.5">
|
|
84
|
-
<Button
|
|
85
|
-
variant="secondary"
|
|
86
|
-
className="h-8! paragraph-small-semibold text-gray-950"
|
|
87
|
-
onClick={onAddProject}
|
|
88
|
-
>
|
|
89
|
-
<
|
|
90
|
-
Adicionar
|
|
91
|
-
</Button>
|
|
92
|
-
<Tooltip>
|
|
93
|
-
<TooltipTrigger asChild>
|
|
94
|
-
<Button variant="secondary" className="p-0 size-8" onClick={onManageProjects}>
|
|
95
|
-
<
|
|
96
|
-
</Button>
|
|
97
|
-
</TooltipTrigger>
|
|
98
|
-
<TooltipContent className="z-[1002]">Visualizar todos projetos</TooltipContent>
|
|
99
|
-
</Tooltip>
|
|
100
|
-
</div>
|
|
101
|
-
</div>
|
|
102
|
-
<Command className="gap-2">
|
|
103
|
-
<CommandInput placeholder="Busque aqui" />
|
|
104
|
-
<CommandList className="custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]">
|
|
105
|
-
{projects.length === 0 ? (
|
|
106
|
-
<div className="flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4">
|
|
107
|
-
<
|
|
108
|
-
<span className="paragraph-small-medium text-center text-gray-500">
|
|
109
|
-
Nenhum projeto encontrado.
|
|
110
|
-
<br />
|
|
111
|
-
Crie um projeto para começar.
|
|
112
|
-
</span>
|
|
113
|
-
</div>
|
|
114
|
-
) : (
|
|
115
|
-
<>
|
|
116
|
-
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
|
117
|
-
{projects.map((project) => {
|
|
118
|
-
const isSelected = selectedProject?.id === project.id;
|
|
119
|
-
return (
|
|
120
|
-
<CommandItem
|
|
121
|
-
key={project.id}
|
|
122
|
-
value={`${project.title}-${project.id}`}
|
|
123
|
-
keywords={[project.title]}
|
|
124
|
-
className={isSelected ? 'bg-gray-50' : ''}
|
|
125
|
-
onSelect={() => onSelectProject(project)}
|
|
126
|
-
>
|
|
127
|
-
<div className="flex items-center justify-between w-full cursor-pointer">
|
|
128
|
-
<div className="flex items-center gap-2 w-full">
|
|
129
|
-
<UserAvatar
|
|
130
|
-
photo={project.photo}
|
|
131
|
-
name={project.title}
|
|
132
|
-
size={32}
|
|
133
|
-
/>
|
|
134
|
-
{project.title}
|
|
135
|
-
</div>
|
|
136
|
-
{isSelected && (
|
|
137
|
-
<
|
|
138
|
-
)}
|
|
139
|
-
</div>
|
|
140
|
-
</CommandItem>
|
|
141
|
-
);
|
|
142
|
-
})}
|
|
143
|
-
</>
|
|
144
|
-
)}
|
|
145
|
-
</CommandList>
|
|
146
|
-
</Command>
|
|
147
|
-
</div>
|
|
148
|
-
</PopoverContent>
|
|
149
|
-
</Popover>
|
|
150
|
-
);
|
|
151
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Dispatch, RefObject, SetStateAction } from 'react';
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
Command,
|
|
7
|
+
CommandEmpty,
|
|
8
|
+
CommandInput,
|
|
9
|
+
CommandItem,
|
|
10
|
+
CommandList,
|
|
11
|
+
Popover,
|
|
12
|
+
PopoverContent,
|
|
13
|
+
PopoverTrigger,
|
|
14
|
+
Tooltip,
|
|
15
|
+
TooltipContent,
|
|
16
|
+
TooltipTrigger,
|
|
17
|
+
UserAvatar,
|
|
18
|
+
} from '../../index';
|
|
19
|
+
import { IconCheck, IconChevronDown, IconFolderOpen, IconPlus, IconSettings } from '@tabler/icons-react';
|
|
20
|
+
import type { NavigationProject } from './types';
|
|
21
|
+
|
|
22
|
+
interface ProjectSelectorPopoverProps {
|
|
23
|
+
open: boolean;
|
|
24
|
+
setOpen: Dispatch<SetStateAction<boolean>>;
|
|
25
|
+
titleRef?: RefObject<HTMLSpanElement | null>;
|
|
26
|
+
projects: NavigationProject[];
|
|
27
|
+
selectedProject: NavigationProject | null;
|
|
28
|
+
onSelectProject: (project: NavigationProject) => void;
|
|
29
|
+
onAddProject: () => void;
|
|
30
|
+
onManageProjects: () => void;
|
|
31
|
+
children?: React.ReactNode;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function ProjectItemSkeleton() {
|
|
35
|
+
return (
|
|
36
|
+
<div className="flex items-center justify-between px-2 py-1.5 gap-2">
|
|
37
|
+
<div className="flex items-center gap-2 flex-1">
|
|
38
|
+
<div className="skeleton size-8 rounded-lg shrink-0" />
|
|
39
|
+
<div className="skeleton h-3.5 w-32 rounded" />
|
|
40
|
+
</div>
|
|
41
|
+
<div className="skeleton size-4 rounded-full shrink-0" />
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function ProjectSelectorPopover({
|
|
47
|
+
open,
|
|
48
|
+
setOpen,
|
|
49
|
+
titleRef,
|
|
50
|
+
projects,
|
|
51
|
+
selectedProject,
|
|
52
|
+
onSelectProject,
|
|
53
|
+
onAddProject,
|
|
54
|
+
onManageProjects,
|
|
55
|
+
children,
|
|
56
|
+
}: ProjectSelectorPopoverProps) {
|
|
57
|
+
return (
|
|
58
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
59
|
+
<PopoverTrigger asChild>
|
|
60
|
+
{children ?? (
|
|
61
|
+
<button className="cursor-pointer">
|
|
62
|
+
<IconChevronDown
|
|
63
|
+
size={20}
|
|
64
|
+
className={`transition-transform duration-200 ${open ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
|
|
65
|
+
/>
|
|
66
|
+
</button>
|
|
67
|
+
)}
|
|
68
|
+
</PopoverTrigger>
|
|
69
|
+
<PopoverContent
|
|
70
|
+
className="w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200"
|
|
71
|
+
align="start"
|
|
72
|
+
sideOffset={8}
|
|
73
|
+
onOpenAutoFocus={(e: Event) => e.preventDefault()}
|
|
74
|
+
onInteractOutside={(event: Event) => {
|
|
75
|
+
if (titleRef?.current?.contains(event.target as Node)) {
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
}
|
|
78
|
+
}}
|
|
79
|
+
>
|
|
80
|
+
<div className="flex flex-col p-3 gap-2">
|
|
81
|
+
<div className="flex items-center justify-between">
|
|
82
|
+
<span className="paragraph-small-semibold">Projetos</span>
|
|
83
|
+
<div className="flex items-center gap-1.5">
|
|
84
|
+
<Button
|
|
85
|
+
variant="secondary"
|
|
86
|
+
className="h-8! paragraph-small-semibold text-gray-950"
|
|
87
|
+
onClick={onAddProject}
|
|
88
|
+
>
|
|
89
|
+
<IconPlus size={16} />
|
|
90
|
+
Adicionar
|
|
91
|
+
</Button>
|
|
92
|
+
<Tooltip>
|
|
93
|
+
<TooltipTrigger asChild>
|
|
94
|
+
<Button variant="secondary" className="p-0 size-8" onClick={onManageProjects}>
|
|
95
|
+
<IconSettings size={18} />
|
|
96
|
+
</Button>
|
|
97
|
+
</TooltipTrigger>
|
|
98
|
+
<TooltipContent className="z-[1002]">Visualizar todos projetos</TooltipContent>
|
|
99
|
+
</Tooltip>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
<Command className="gap-2">
|
|
103
|
+
<CommandInput placeholder="Busque aqui" />
|
|
104
|
+
<CommandList className="custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]">
|
|
105
|
+
{projects.length === 0 ? (
|
|
106
|
+
<div className="flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4">
|
|
107
|
+
<IconFolderOpen size={28} className="text-gray-300" />
|
|
108
|
+
<span className="paragraph-small-medium text-center text-gray-500">
|
|
109
|
+
Nenhum projeto encontrado.
|
|
110
|
+
<br />
|
|
111
|
+
Crie um projeto para começar.
|
|
112
|
+
</span>
|
|
113
|
+
</div>
|
|
114
|
+
) : (
|
|
115
|
+
<>
|
|
116
|
+
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
|
117
|
+
{projects.map((project) => {
|
|
118
|
+
const isSelected = selectedProject?.id === project.id;
|
|
119
|
+
return (
|
|
120
|
+
<CommandItem
|
|
121
|
+
key={project.id}
|
|
122
|
+
value={`${project.title}-${project.id}`}
|
|
123
|
+
keywords={[project.title]}
|
|
124
|
+
className={isSelected ? 'bg-gray-50' : ''}
|
|
125
|
+
onSelect={() => onSelectProject(project)}
|
|
126
|
+
>
|
|
127
|
+
<div className="flex items-center justify-between w-full cursor-pointer">
|
|
128
|
+
<div className="flex items-center gap-2 w-full">
|
|
129
|
+
<UserAvatar
|
|
130
|
+
photo={project.photo}
|
|
131
|
+
name={project.title}
|
|
132
|
+
size={32}
|
|
133
|
+
/>
|
|
134
|
+
{project.title}
|
|
135
|
+
</div>
|
|
136
|
+
{isSelected && (
|
|
137
|
+
<IconCheck className="size-4 text-gray-950" />
|
|
138
|
+
)}
|
|
139
|
+
</div>
|
|
140
|
+
</CommandItem>
|
|
141
|
+
);
|
|
142
|
+
})}
|
|
143
|
+
</>
|
|
144
|
+
)}
|
|
145
|
+
</CommandList>
|
|
146
|
+
</Command>
|
|
147
|
+
</div>
|
|
148
|
+
</PopoverContent>
|
|
149
|
+
</Popover>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
@@ -1,149 +1,149 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useState, useRef, useEffect, RefObject } from 'react';
|
|
4
|
-
import { useMobileNavbarSheet } from '../../../store/useMobileNavbarSheet';
|
|
5
|
-
import { useAppNavigationContext } from '../AppNavigationContext';
|
|
6
|
-
import { ProjectSelectorPopover } from '../ProjectSelectorPopover';
|
|
7
|
-
import { UsersSelectorPopover } from '../../layouts/UsersSelectorPopover';
|
|
8
|
-
import { Button, Command, CommandEmpty, CommandInput, CommandItem, CommandList, UserAvatar } from '../../../index';
|
|
9
|
-
import {
|
|
10
|
-
import type { NavigationProject } from '../types';
|
|
11
|
-
|
|
12
|
-
export interface ProjectSelectorProps {
|
|
13
|
-
projects: NavigationProject[];
|
|
14
|
-
selectedProject: NavigationProject | null;
|
|
15
|
-
isLoading?: boolean;
|
|
16
|
-
onSelectProject: (project: NavigationProject) => void;
|
|
17
|
-
onAddProject: () => void;
|
|
18
|
-
onManageProjects: () => void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function ProjectItemSkeleton() {
|
|
22
|
-
return (
|
|
23
|
-
<div className="flex items-center gap-2 p-2">
|
|
24
|
-
<div className="skeleton size-8 rounded-lg shrink-0" />
|
|
25
|
-
<div className="skeleton h-3.5 w-32 rounded" />
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function ProjectSelector({
|
|
31
|
-
projects,
|
|
32
|
-
selectedProject,
|
|
33
|
-
isLoading,
|
|
34
|
-
onSelectProject,
|
|
35
|
-
onAddProject,
|
|
36
|
-
onManageProjects,
|
|
37
|
-
}: ProjectSelectorProps) {
|
|
38
|
-
const { breakpoint } = useAppNavigationContext();
|
|
39
|
-
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
|
40
|
-
const [activeSection, setActiveSection] = useState<'projects' | null>(null);
|
|
41
|
-
const titleRef = useRef<HTMLDivElement>(null);
|
|
42
|
-
const { openProjectList, clearProjectList } = useMobileNavbarSheet();
|
|
43
|
-
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
if (openProjectList && breakpoint === 'mobile') {
|
|
46
|
-
setActiveSection('projects');
|
|
47
|
-
clearProjectList();
|
|
48
|
-
}
|
|
49
|
-
}, [openProjectList, breakpoint, clearProjectList]);
|
|
50
|
-
|
|
51
|
-
// Desktop and md: title + popover + users selector (same visual as current gpages sidebars)
|
|
52
|
-
if (breakpoint === 'desktop' || breakpoint === 'md') {
|
|
53
|
-
return (
|
|
54
|
-
<div className="flex items-center justify-between">
|
|
55
|
-
<ProjectSelectorPopover
|
|
56
|
-
open={isPopoverOpen}
|
|
57
|
-
setOpen={setIsPopoverOpen}
|
|
58
|
-
titleRef={titleRef as unknown as RefObject<HTMLSpanElement | null>}
|
|
59
|
-
projects={projects}
|
|
60
|
-
selectedProject={selectedProject}
|
|
61
|
-
onSelectProject={onSelectProject}
|
|
62
|
-
onAddProject={onAddProject}
|
|
63
|
-
onManageProjects={onManageProjects}
|
|
64
|
-
>
|
|
65
|
-
<div className="flex items-center gap-2 truncate select-none cursor-pointer" ref={titleRef}>
|
|
66
|
-
{isLoading ? (
|
|
67
|
-
<div className="skeleton h-4 w-32 rounded" />
|
|
68
|
-
) : (
|
|
69
|
-
<span className="paragraph-medium-semibold text-gray-600 truncate max-w-[120px] inline-block">
|
|
70
|
-
{selectedProject?.title}
|
|
71
|
-
</span>
|
|
72
|
-
)}
|
|
73
|
-
<
|
|
74
|
-
size={20}
|
|
75
|
-
className={`transition-transform duration-200 ${isPopoverOpen ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
|
|
76
|
-
/>
|
|
77
|
-
</div>
|
|
78
|
-
</ProjectSelectorPopover>
|
|
79
|
-
<div className="flex items-center gap-2">
|
|
80
|
-
<UsersSelectorPopover projectId={selectedProject?.id} />
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Mobile: inline collapsible accordion
|
|
87
|
-
return (
|
|
88
|
-
<div className="flex flex-col gap-2.5">
|
|
89
|
-
<div className="flex items-center justify-between">
|
|
90
|
-
<div className="flex items-center gap-1">
|
|
91
|
-
<span className="paragraph-medium-semibold text-gray-600">{selectedProject?.title}</span>
|
|
92
|
-
<
|
|
93
|
-
size={20}
|
|
94
|
-
onClick={() => setActiveSection(activeSection === 'projects' ? null : 'projects')}
|
|
95
|
-
className={`transition-transform duration-200 cursor-pointer ${
|
|
96
|
-
activeSection === 'projects' ? 'rotate-180 text-gray-950' : 'text-gray-400'
|
|
97
|
-
}`}
|
|
98
|
-
/>
|
|
99
|
-
</div>
|
|
100
|
-
<UsersSelectorPopover projectId={selectedProject?.id} />
|
|
101
|
-
</div>
|
|
102
|
-
{activeSection === 'projects' && (
|
|
103
|
-
<div className="flex flex-col p-3 gap-2 border border-gray-200 rounded-lg animate-in fade-in duration-400">
|
|
104
|
-
<div className="flex items-center justify-between">
|
|
105
|
-
<span className="paragraph-small-semibold">Projetos</span>
|
|
106
|
-
<div className="flex items-center gap-1.5">
|
|
107
|
-
<Button variant="secondary" className="h-8! paragraph-small-semibold text-gray-950" onClick={onAddProject}>
|
|
108
|
-
<
|
|
109
|
-
Adicionar
|
|
110
|
-
</Button>
|
|
111
|
-
<Button variant="secondary" className="p-0 size-8" onClick={onManageProjects}>
|
|
112
|
-
<
|
|
113
|
-
</Button>
|
|
114
|
-
</div>
|
|
115
|
-
</div>
|
|
116
|
-
<Command className="gap-2">
|
|
117
|
-
<CommandInput placeholder="Busque aqui" />
|
|
118
|
-
<CommandList className="custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]">
|
|
119
|
-
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
|
120
|
-
{isLoading ? (
|
|
121
|
-
<>
|
|
122
|
-
<ProjectItemSkeleton />
|
|
123
|
-
<ProjectItemSkeleton />
|
|
124
|
-
</>
|
|
125
|
-
) : (
|
|
126
|
-
projects.map((project) => (
|
|
127
|
-
<CommandItem
|
|
128
|
-
key={project.id}
|
|
129
|
-
value={`${project.title}-${project.id}`}
|
|
130
|
-
keywords={[project.title]}
|
|
131
|
-
className={selectedProject?.id === project.id ? 'bg-gray-50' : ''}
|
|
132
|
-
onSelect={() => { onSelectProject(project); setActiveSection(null); }}
|
|
133
|
-
>
|
|
134
|
-
<UserAvatar
|
|
135
|
-
photo={project.photo}
|
|
136
|
-
name={project.title}
|
|
137
|
-
size={32}
|
|
138
|
-
/>
|
|
139
|
-
{project.title}
|
|
140
|
-
</CommandItem>
|
|
141
|
-
))
|
|
142
|
-
)}
|
|
143
|
-
</CommandList>
|
|
144
|
-
</Command>
|
|
145
|
-
</div>
|
|
146
|
-
)}
|
|
147
|
-
</div>
|
|
148
|
-
);
|
|
149
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useRef, useEffect, RefObject } from 'react';
|
|
4
|
+
import { useMobileNavbarSheet } from '../../../store/useMobileNavbarSheet';
|
|
5
|
+
import { useAppNavigationContext } from '../AppNavigationContext';
|
|
6
|
+
import { ProjectSelectorPopover } from '../ProjectSelectorPopover';
|
|
7
|
+
import { UsersSelectorPopover } from '../../layouts/UsersSelectorPopover';
|
|
8
|
+
import { Button, Command, CommandEmpty, CommandInput, CommandItem, CommandList, UserAvatar } from '../../../index';
|
|
9
|
+
import { IconChevronDown, IconPlus, IconSettings } from '@tabler/icons-react';
|
|
10
|
+
import type { NavigationProject } from '../types';
|
|
11
|
+
|
|
12
|
+
export interface ProjectSelectorProps {
|
|
13
|
+
projects: NavigationProject[];
|
|
14
|
+
selectedProject: NavigationProject | null;
|
|
15
|
+
isLoading?: boolean;
|
|
16
|
+
onSelectProject: (project: NavigationProject) => void;
|
|
17
|
+
onAddProject: () => void;
|
|
18
|
+
onManageProjects: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function ProjectItemSkeleton() {
|
|
22
|
+
return (
|
|
23
|
+
<div className="flex items-center gap-2 p-2">
|
|
24
|
+
<div className="skeleton size-8 rounded-lg shrink-0" />
|
|
25
|
+
<div className="skeleton h-3.5 w-32 rounded" />
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function ProjectSelector({
|
|
31
|
+
projects,
|
|
32
|
+
selectedProject,
|
|
33
|
+
isLoading,
|
|
34
|
+
onSelectProject,
|
|
35
|
+
onAddProject,
|
|
36
|
+
onManageProjects,
|
|
37
|
+
}: ProjectSelectorProps) {
|
|
38
|
+
const { breakpoint } = useAppNavigationContext();
|
|
39
|
+
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
|
40
|
+
const [activeSection, setActiveSection] = useState<'projects' | null>(null);
|
|
41
|
+
const titleRef = useRef<HTMLDivElement>(null);
|
|
42
|
+
const { openProjectList, clearProjectList } = useMobileNavbarSheet();
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (openProjectList && breakpoint === 'mobile') {
|
|
46
|
+
setActiveSection('projects');
|
|
47
|
+
clearProjectList();
|
|
48
|
+
}
|
|
49
|
+
}, [openProjectList, breakpoint, clearProjectList]);
|
|
50
|
+
|
|
51
|
+
// Desktop and md: title + popover + users selector (same visual as current gpages sidebars)
|
|
52
|
+
if (breakpoint === 'desktop' || breakpoint === 'md') {
|
|
53
|
+
return (
|
|
54
|
+
<div className="flex items-center justify-between">
|
|
55
|
+
<ProjectSelectorPopover
|
|
56
|
+
open={isPopoverOpen}
|
|
57
|
+
setOpen={setIsPopoverOpen}
|
|
58
|
+
titleRef={titleRef as unknown as RefObject<HTMLSpanElement | null>}
|
|
59
|
+
projects={projects}
|
|
60
|
+
selectedProject={selectedProject}
|
|
61
|
+
onSelectProject={onSelectProject}
|
|
62
|
+
onAddProject={onAddProject}
|
|
63
|
+
onManageProjects={onManageProjects}
|
|
64
|
+
>
|
|
65
|
+
<div className="flex items-center gap-2 truncate select-none cursor-pointer" ref={titleRef}>
|
|
66
|
+
{isLoading ? (
|
|
67
|
+
<div className="skeleton h-4 w-32 rounded" />
|
|
68
|
+
) : (
|
|
69
|
+
<span className="paragraph-medium-semibold text-gray-600 truncate max-w-[120px] inline-block">
|
|
70
|
+
{selectedProject?.title}
|
|
71
|
+
</span>
|
|
72
|
+
)}
|
|
73
|
+
<IconChevronDown
|
|
74
|
+
size={20}
|
|
75
|
+
className={`transition-transform duration-200 ${isPopoverOpen ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
|
|
76
|
+
/>
|
|
77
|
+
</div>
|
|
78
|
+
</ProjectSelectorPopover>
|
|
79
|
+
<div className="flex items-center gap-2">
|
|
80
|
+
<UsersSelectorPopover projectId={selectedProject?.id} />
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Mobile: inline collapsible accordion
|
|
87
|
+
return (
|
|
88
|
+
<div className="flex flex-col gap-2.5">
|
|
89
|
+
<div className="flex items-center justify-between">
|
|
90
|
+
<div className="flex items-center gap-1">
|
|
91
|
+
<span className="paragraph-medium-semibold text-gray-600">{selectedProject?.title}</span>
|
|
92
|
+
<IconChevronDown
|
|
93
|
+
size={20}
|
|
94
|
+
onClick={() => setActiveSection(activeSection === 'projects' ? null : 'projects')}
|
|
95
|
+
className={`transition-transform duration-200 cursor-pointer ${
|
|
96
|
+
activeSection === 'projects' ? 'rotate-180 text-gray-950' : 'text-gray-400'
|
|
97
|
+
}`}
|
|
98
|
+
/>
|
|
99
|
+
</div>
|
|
100
|
+
<UsersSelectorPopover projectId={selectedProject?.id} />
|
|
101
|
+
</div>
|
|
102
|
+
{activeSection === 'projects' && (
|
|
103
|
+
<div className="flex flex-col p-3 gap-2 border border-gray-200 rounded-lg animate-in fade-in duration-400">
|
|
104
|
+
<div className="flex items-center justify-between">
|
|
105
|
+
<span className="paragraph-small-semibold">Projetos</span>
|
|
106
|
+
<div className="flex items-center gap-1.5">
|
|
107
|
+
<Button variant="secondary" className="h-8! paragraph-small-semibold text-gray-950" onClick={onAddProject}>
|
|
108
|
+
<IconPlus size={16} />
|
|
109
|
+
Adicionar
|
|
110
|
+
</Button>
|
|
111
|
+
<Button variant="secondary" className="p-0 size-8" onClick={onManageProjects}>
|
|
112
|
+
<IconSettings size={18} />
|
|
113
|
+
</Button>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
<Command className="gap-2">
|
|
117
|
+
<CommandInput placeholder="Busque aqui" />
|
|
118
|
+
<CommandList className="custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]">
|
|
119
|
+
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
|
120
|
+
{isLoading ? (
|
|
121
|
+
<>
|
|
122
|
+
<ProjectItemSkeleton />
|
|
123
|
+
<ProjectItemSkeleton />
|
|
124
|
+
</>
|
|
125
|
+
) : (
|
|
126
|
+
projects.map((project) => (
|
|
127
|
+
<CommandItem
|
|
128
|
+
key={project.id}
|
|
129
|
+
value={`${project.title}-${project.id}`}
|
|
130
|
+
keywords={[project.title]}
|
|
131
|
+
className={selectedProject?.id === project.id ? 'bg-gray-50' : ''}
|
|
132
|
+
onSelect={() => { onSelectProject(project); setActiveSection(null); }}
|
|
133
|
+
>
|
|
134
|
+
<UserAvatar
|
|
135
|
+
photo={project.photo}
|
|
136
|
+
name={project.title}
|
|
137
|
+
size={32}
|
|
138
|
+
/>
|
|
139
|
+
{project.title}
|
|
140
|
+
</CommandItem>
|
|
141
|
+
))
|
|
142
|
+
)}
|
|
143
|
+
</CommandList>
|
|
144
|
+
</Command>
|
|
145
|
+
</div>
|
|
146
|
+
)}
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { IconBell, IconCheck, IconLoader2 } from '@tabler/icons-react';
|
|
4
4
|
import { Button } from "../../ui/buttons/Button";
|
|
5
5
|
import {
|
|
6
6
|
Tabs,
|
|
@@ -47,7 +47,7 @@ function NotificationsList({
|
|
|
47
47
|
{notifications.map((notification, index) => (
|
|
48
48
|
<NotificationCard
|
|
49
49
|
key={notification.id}
|
|
50
|
-
icon={<
|
|
50
|
+
icon={<IconBell size={20} className="text-pages-600" />}
|
|
51
51
|
iconBgColor="bg-pages-100"
|
|
52
52
|
title={notification.subject}
|
|
53
53
|
description={notification.message}
|
|
@@ -62,7 +62,7 @@ function NotificationsList({
|
|
|
62
62
|
))}
|
|
63
63
|
{isFetchingNextPage && (
|
|
64
64
|
<div className="flex items-center justify-center py-4">
|
|
65
|
-
<
|
|
65
|
+
<IconLoader2 size={20} className="animate-spin text-gray-400" />
|
|
66
66
|
</div>
|
|
67
67
|
)}
|
|
68
68
|
</div>
|
|
@@ -117,7 +117,7 @@ export function NotificationPageContent() {
|
|
|
117
117
|
onClick={handleMarkAllAsRead}
|
|
118
118
|
disabled={isMarkingAll || totalUnread === 0}
|
|
119
119
|
>
|
|
120
|
-
{isMarkingAll ? <
|
|
120
|
+
{isMarkingAll ? <IconLoader2 size={20} className="animate-spin" /> : <IconCheck size={20} />}
|
|
121
121
|
<span className="lg:block hidden">Marcar todos como lidos</span>
|
|
122
122
|
<span className="lg:hidden">Marcar como lidos</span>
|
|
123
123
|
</Button>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { IconCheck, IconCopy } from '@tabler/icons-react';
|
|
4
4
|
import { toast } from "sonner";
|
|
5
5
|
import { Toast } from "../feedback/Toast";
|
|
6
6
|
import { Tooltip, TooltipContent, TooltipTrigger } from "../overlay/Tooltip";
|
|
@@ -45,7 +45,7 @@ export function CopyButton({
|
|
|
45
45
|
}}
|
|
46
46
|
>
|
|
47
47
|
<span className={cn("cursor-pointer text-gray-500", className)}>
|
|
48
|
-
{isCopied ? <
|
|
48
|
+
{isCopied ? <IconCheck size={size} /> : <IconCopy size={size} />}
|
|
49
49
|
</span>
|
|
50
50
|
</TooltipTrigger>
|
|
51
51
|
<TooltipContent>{isCopied ? "Copiado!" : tooltipText}</TooltipContent>
|