@greatapps/common 1.1.47 → 1.1.49
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/UsersSelectorPopover.mjs +100 -22
- package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -1
- package/dist/modules/projects/actions/add-project-user.action.mjs +9 -0
- package/dist/modules/projects/actions/add-project-user.action.mjs.map +1 -0
- package/dist/modules/projects/actions/list-available-users.action.mjs +9 -0
- package/dist/modules/projects/actions/list-available-users.action.mjs.map +1 -0
- package/dist/modules/projects/actions/list-project-users.action.mjs +9 -0
- package/dist/modules/projects/actions/list-project-users.action.mjs.map +1 -0
- package/dist/modules/projects/actions/remove-project-user.action.mjs +9 -0
- package/dist/modules/projects/actions/remove-project-user.action.mjs.map +1 -0
- package/dist/modules/projects/hooks/project-users.hook.mjs +70 -0
- package/dist/modules/projects/hooks/project-users.hook.mjs.map +1 -0
- package/dist/modules/projects/services/project-users.service.mjs +67 -0
- package/dist/modules/projects/services/project-users.service.mjs.map +1 -0
- package/dist/modules/projects/types.mjs +22 -0
- package/dist/modules/projects/types.mjs.map +1 -0
- package/dist/server.mjs +10 -0
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/layouts/UsersSelectorPopover.tsx +167 -64
- package/src/index.ts +2 -0
- package/src/modules/projects/actions/add-project-user.action.ts +8 -0
- package/src/modules/projects/actions/list-available-users.action.ts +8 -0
- package/src/modules/projects/actions/list-project-users.action.ts +8 -0
- package/src/modules/projects/actions/remove-project-user.action.ts +8 -0
- package/src/modules/projects/hooks/project-users.hook.ts +81 -0
- package/src/modules/projects/services/project-users.service.ts +94 -0
- package/src/modules/projects/types.ts +28 -0
- package/src/server.ts +7 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState } from "react";
|
|
4
|
-
import { Plus, Settings, User } from "lucide-react";
|
|
4
|
+
import { Plus, Settings, User, Users } from "lucide-react";
|
|
5
5
|
import Image from "next/image";
|
|
6
6
|
import { useRouter } from "next/navigation";
|
|
7
7
|
import { Popover, PopoverContent, PopoverTrigger } from "../ui/overlay/Popover";
|
|
@@ -10,30 +10,30 @@ import { Command, CommandEmpty, CommandInput, CommandItem, CommandList } from ".
|
|
|
10
10
|
import { Checkbox } from "../ui/form/Checkbox";
|
|
11
11
|
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/overlay/Tooltip";
|
|
12
12
|
import { cn } from "../../infra/utils/clsx";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
import { useProjectUsers } from "../../modules/projects/hooks/project-users.hook";
|
|
14
|
+
function UserItemSkeleton() {
|
|
15
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-2 py-1.5 gap-2", children: [
|
|
16
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-1", children: [
|
|
17
|
+
/* @__PURE__ */ jsx("div", { className: "size-8 rounded-full bg-gray-100 animate-pulse shrink-0" }),
|
|
18
|
+
/* @__PURE__ */ jsx("div", { className: "h-3.5 w-28 rounded bg-gray-100 animate-pulse" })
|
|
19
|
+
] }),
|
|
20
|
+
/* @__PURE__ */ jsx("div", { className: "size-4 rounded bg-gray-100 animate-pulse shrink-0" })
|
|
21
|
+
] });
|
|
22
|
+
}
|
|
23
|
+
function UsersSelectorPopoverContent({
|
|
24
|
+
users,
|
|
25
|
+
isLoading,
|
|
26
|
+
userCount,
|
|
27
|
+
toggleUser,
|
|
28
|
+
addRoute,
|
|
29
|
+
manageRoute,
|
|
19
30
|
side,
|
|
20
31
|
align,
|
|
21
32
|
contentClassName
|
|
22
33
|
}) {
|
|
23
34
|
const route = useRouter();
|
|
24
35
|
const [open, setOpen] = useState(false);
|
|
25
|
-
const [internalUsers, setInternalUsers] = useState(externalUsers ?? []);
|
|
26
36
|
const [hoveredId, setHoveredId] = useState(null);
|
|
27
|
-
const users = externalUsers ?? internalUsers;
|
|
28
|
-
const toggleUser = (id) => {
|
|
29
|
-
if (onToggleUser) {
|
|
30
|
-
onToggleUser(id);
|
|
31
|
-
} else {
|
|
32
|
-
setInternalUsers(
|
|
33
|
-
(prev) => prev.map((u) => u.id === id ? { ...u, checked: !u.checked } : u)
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
37
|
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
38
38
|
/* @__PURE__ */ jsx(PopoverTrigger, { className: "cursor-pointer", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-gray-950 px-3 py-2 border border-gray-200 rounded-full hover:border-gray-950", children: [
|
|
39
39
|
/* @__PURE__ */ jsx("span", { className: "paragraph-small-semibold", children: userCount }),
|
|
@@ -81,11 +81,23 @@ function UsersSelectorPopover({
|
|
|
81
81
|
] }),
|
|
82
82
|
/* @__PURE__ */ jsxs(Command, { className: "gap-2", value: "", children: [
|
|
83
83
|
/* @__PURE__ */ jsx(CommandInput, { placeholder: "Busque aqui" }),
|
|
84
|
-
/* @__PURE__ */
|
|
85
|
-
/* @__PURE__ */ jsx(
|
|
84
|
+
/* @__PURE__ */ jsx(CommandList, { className: "custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]", children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
85
|
+
/* @__PURE__ */ jsx(UserItemSkeleton, {}),
|
|
86
|
+
/* @__PURE__ */ jsx(UserItemSkeleton, {}),
|
|
87
|
+
/* @__PURE__ */ jsx(UserItemSkeleton, {})
|
|
88
|
+
] }) : users.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4", children: [
|
|
89
|
+
/* @__PURE__ */ jsx(Users, { size: 28, className: "text-gray-300" }),
|
|
90
|
+
/* @__PURE__ */ jsxs("span", { className: "paragraph-small-medium text-center text-gray-500", children: [
|
|
91
|
+
"Nenhum usu\xE1rio neste projeto.",
|
|
92
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
93
|
+
"Adicione um usu\xE1rio para come\xE7ar."
|
|
94
|
+
] })
|
|
95
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
96
|
+
/* @__PURE__ */ jsx(CommandEmpty, { children: "Nenhum resultado encontrado." }),
|
|
86
97
|
users.map((user) => /* @__PURE__ */ jsx(
|
|
87
98
|
CommandItem,
|
|
88
99
|
{
|
|
100
|
+
value: user.name,
|
|
89
101
|
autoFocus: false,
|
|
90
102
|
onPointerEnter: () => setHoveredId(user.id),
|
|
91
103
|
onPointerLeave: () => setHoveredId(null),
|
|
@@ -129,13 +141,79 @@ function UsersSelectorPopover({
|
|
|
129
141
|
},
|
|
130
142
|
user.id
|
|
131
143
|
))
|
|
132
|
-
] })
|
|
144
|
+
] }) })
|
|
133
145
|
] })
|
|
134
146
|
] })
|
|
135
147
|
}
|
|
136
148
|
)
|
|
137
149
|
] });
|
|
138
150
|
}
|
|
151
|
+
function ConnectedUsersSelectorPopover({
|
|
152
|
+
projectId,
|
|
153
|
+
addRoute,
|
|
154
|
+
manageRoute,
|
|
155
|
+
side,
|
|
156
|
+
align,
|
|
157
|
+
contentClassName
|
|
158
|
+
}) {
|
|
159
|
+
const { users, isLoading, userCount, toggleUser } = useProjectUsers(projectId);
|
|
160
|
+
return /* @__PURE__ */ jsx(
|
|
161
|
+
UsersSelectorPopoverContent,
|
|
162
|
+
{
|
|
163
|
+
users,
|
|
164
|
+
isLoading,
|
|
165
|
+
userCount,
|
|
166
|
+
toggleUser,
|
|
167
|
+
addRoute: addRoute ?? "/my-teams?createNew=true",
|
|
168
|
+
manageRoute: manageRoute ?? "/my-teams",
|
|
169
|
+
side,
|
|
170
|
+
align,
|
|
171
|
+
contentClassName
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
function StaticUsersSelectorPopover({
|
|
176
|
+
users: externalUsers = [],
|
|
177
|
+
onToggleUser,
|
|
178
|
+
userCount = 5,
|
|
179
|
+
addRoute = "/my-teams?createNew=true",
|
|
180
|
+
manageRoute = "/my-teams",
|
|
181
|
+
side,
|
|
182
|
+
align,
|
|
183
|
+
contentClassName
|
|
184
|
+
}) {
|
|
185
|
+
const [internalUsers, setInternalUsers] = useState(externalUsers);
|
|
186
|
+
const users = externalUsers.length > 0 ? externalUsers : internalUsers;
|
|
187
|
+
const toggleUser = (id) => {
|
|
188
|
+
if (onToggleUser) {
|
|
189
|
+
onToggleUser(id);
|
|
190
|
+
} else {
|
|
191
|
+
setInternalUsers(
|
|
192
|
+
(prev) => prev.map((u) => u.id === id ? { ...u, checked: !u.checked } : u)
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
return /* @__PURE__ */ jsx(
|
|
197
|
+
UsersSelectorPopoverContent,
|
|
198
|
+
{
|
|
199
|
+
users,
|
|
200
|
+
isLoading: false,
|
|
201
|
+
userCount,
|
|
202
|
+
toggleUser,
|
|
203
|
+
addRoute,
|
|
204
|
+
manageRoute,
|
|
205
|
+
side,
|
|
206
|
+
align,
|
|
207
|
+
contentClassName
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
function UsersSelectorPopover(props) {
|
|
212
|
+
if (props.projectId != null) {
|
|
213
|
+
return /* @__PURE__ */ jsx(ConnectedUsersSelectorPopover, { ...props, projectId: props.projectId });
|
|
214
|
+
}
|
|
215
|
+
return /* @__PURE__ */ jsx(StaticUsersSelectorPopover, { ...props });
|
|
216
|
+
}
|
|
139
217
|
export {
|
|
140
218
|
UsersSelectorPopover
|
|
141
219
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/layouts/UsersSelectorPopover.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { useState } from 'react';\r\nimport { Plus, Settings, User } from 'lucide-react';\r\nimport Image from 'next/image';\r\nimport { useRouter } from 'next/navigation';\r\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/overlay/Popover';\r\nimport { Button } from '../ui/buttons/Button';\r\nimport { Command, CommandEmpty, CommandInput, CommandItem, CommandList } from '../ui/overlay/Command';\r\nimport { Checkbox } from '../ui/form/Checkbox';\r\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../ui/overlay/Tooltip';\r\nimport { cn } from '../../infra/utils/clsx';\r\n\r\nexport interface UserSelectorItem {\r\n id: number;\r\n name: string;\r\n avatar: string;\r\n checked: boolean;\r\n}\r\n\r\nexport interface UsersSelectorPopoverProps {\r\n users?: UserSelectorItem[];\r\n onToggleUser?: (id: number) => void;\r\n addRoute?: string;\r\n manageRoute?: string;\r\n userCount?: number;\r\n side?: 'top' | 'bottom' | 'left' | 'right';\r\n align?: 'start' | 'center' | 'end';\r\n contentClassName?: string;\r\n}\r\n\r\nfunction UsersSelectorPopover({\r\n users: externalUsers,\r\n onToggleUser,\r\n addRoute = '/my-teams?createNew=true',\r\n manageRoute = '/my-teams',\r\n userCount = 5,\r\n side,\r\n align,\r\n contentClassName,\r\n}: UsersSelectorPopoverProps) {\r\n const route = useRouter();\r\n const [open, setOpen] = useState(false);\r\n const [internalUsers, setInternalUsers] = useState<UserSelectorItem[]>(externalUsers ?? []);\r\n const [hoveredId, setHoveredId] = useState<number | null>(null);\r\n\r\n const users = externalUsers ?? internalUsers;\r\n\r\n const toggleUser = (id: number) => {\r\n if (onToggleUser) {\r\n onToggleUser(id);\r\n } else {\r\n setInternalUsers((prev) =>\r\n prev.map((u) => (u.id === id ? { ...u, checked: !u.checked } : u))\r\n );\r\n }\r\n };\r\n\r\n return (\r\n <Popover open={open} onOpenChange={setOpen}>\r\n <PopoverTrigger className=\"cursor-pointer\">\r\n <div className=\"flex items-center gap-2 text-gray-950 px-3 py-2 border border-gray-200 rounded-full hover:border-gray-950\">\r\n <span className=\"paragraph-small-semibold\">{userCount}</span>\r\n <User size={16} />\r\n </div>\r\n </PopoverTrigger>\r\n\r\n <PopoverContent\r\n className={cn(\r\n 'absolute right-[-88px] w-[273px] p-0 bg-white rounded-2xl shadow-md border border-gray-200',\r\n contentClassName\r\n )}\r\n side={side}\r\n align={align}\r\n sideOffset={8}\r\n >\r\n <div className=\"flex flex-col p-3 gap-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"paragraph-small-semibold\">Usuários</span>\r\n <div className=\"flex items-center gap-1.5\">\r\n <Button\r\n variant=\"secondary\"\r\n className=\"h-8 paragraph-small-semibold text-gray-950\"\r\n onClick={() => route.push(addRoute)}\r\n >\r\n <Plus size={16} />\r\n Adicionar\r\n </Button>\r\n\r\n <Tooltip>\r\n <TooltipTrigger asChild>\r\n <Button\r\n variant=\"secondary\"\r\n className=\"p-0 size-8\"\r\n onClick={() => route.push(manageRoute)}\r\n >\r\n <Settings size={18} />\r\n </Button>\r\n </TooltipTrigger>\r\n <TooltipContent>Visualizar todos usuários</TooltipContent>\r\n </Tooltip>\r\n </div>\r\n </div>\r\n\r\n <Command className=\"gap-2\" value=\"\">\r\n <CommandInput placeholder=\"Busque aqui\" />\r\n <CommandList className=\"custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]\">\r\n <CommandEmpty>No results found.</CommandEmpty>\r\n {users.map((user) => (\r\n <CommandItem\r\n key={user.id}\r\n autoFocus={false}\r\n onPointerEnter={() => setHoveredId(user.id)}\r\n onPointerLeave={() => setHoveredId(null)}\r\n onFocus={() => setHoveredId(user.id)}\r\n onBlur={() => setHoveredId(null)}\r\n onSelect={() => toggleUser(user.id)}\r\n className=\"cursor-pointer\"\r\n >\r\n <div className=\"flex items-center justify-between w-full\">\r\n <div className=\"flex items-center gap-2\">\r\n <Image\r\n alt=\"Avatar\"\r\n src={user.avatar}\r\n width={32}\r\n height={32}\r\n className=\"rounded-full\"\r\n />\r\n {user.name}\r\n </div>\r\n\r\n <Tooltip open={hoveredId === user.id}>\r\n <TooltipTrigger\r\n onClick={(e) => e.stopPropagation()}\r\n onPointerDown={(e) => e.stopPropagation()}\r\n >\r\n <Checkbox\r\n checked={user.checked}\r\n onCheckedChange={() => toggleUser(user.id)}\r\n className={hoveredId === user.id ? 'border-gray-950' : ''}\r\n />\r\n </TooltipTrigger>\r\n <TooltipContent>\r\n {user.checked ? 'Remover do projeto' : 'Adicionar ao projeto'}\r\n </TooltipContent>\r\n </Tooltip>\r\n </div>\r\n </CommandItem>\r\n ))}\r\n </CommandList>\r\n </Command>\r\n </div>\r\n </PopoverContent>\r\n </Popover>\r\n );\r\n}\r\n\r\nexport { UsersSelectorPopover };\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/layouts/UsersSelectorPopover.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { useState } from 'react';\r\nimport { Plus, Settings, User, Users } from 'lucide-react';\r\nimport Image from 'next/image';\r\nimport { useRouter } from 'next/navigation';\r\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/overlay/Popover';\r\nimport { Button } from '../ui/buttons/Button';\r\nimport { Command, CommandEmpty, CommandInput, CommandItem, CommandList } from '../ui/overlay/Command';\r\nimport { Checkbox } from '../ui/form/Checkbox';\r\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../ui/overlay/Tooltip';\r\nimport { cn } from '../../infra/utils/clsx';\r\nimport { useProjectUsers } from '../../modules/projects/hooks/project-users.hook';\r\n\r\nexport interface UserSelectorItem {\r\n id: number;\r\n name: string;\r\n avatar: string;\r\n checked: boolean;\r\n}\r\n\r\nfunction UserItemSkeleton() {\r\n return (\r\n <div className=\"flex items-center justify-between px-2 py-1.5 gap-2\">\r\n <div className=\"flex items-center gap-2 flex-1\">\r\n <div className=\"size-8 rounded-full bg-gray-100 animate-pulse shrink-0\" />\r\n <div className=\"h-3.5 w-28 rounded bg-gray-100 animate-pulse\" />\r\n </div>\r\n <div className=\"size-4 rounded bg-gray-100 animate-pulse shrink-0\" />\r\n </div>\r\n );\r\n}\r\n\r\nexport interface UsersSelectorPopoverProps {\r\n projectId?: number;\r\n users?: UserSelectorItem[];\r\n onToggleUser?: (id: number) => void;\r\n addRoute?: string;\r\n manageRoute?: string;\r\n userCount?: number;\r\n side?: 'top' | 'bottom' | 'left' | 'right';\r\n align?: 'start' | 'center' | 'end';\r\n contentClassName?: string;\r\n}\r\n\r\ninterface ContentProps {\r\n users: UserSelectorItem[];\r\n isLoading: boolean;\r\n userCount: number;\r\n toggleUser: (id: number) => void;\r\n addRoute: string;\r\n manageRoute: string;\r\n side?: UsersSelectorPopoverProps['side'];\r\n align?: UsersSelectorPopoverProps['align'];\r\n contentClassName?: string;\r\n}\r\n\r\nfunction UsersSelectorPopoverContent({\r\n users,\r\n isLoading,\r\n userCount,\r\n toggleUser,\r\n addRoute,\r\n manageRoute,\r\n side,\r\n align,\r\n contentClassName,\r\n}: ContentProps) {\r\n const route = useRouter();\r\n const [open, setOpen] = useState(false);\r\n const [hoveredId, setHoveredId] = useState<number | null>(null);\r\n\r\n return (\r\n <Popover open={open} onOpenChange={setOpen}>\r\n <PopoverTrigger className=\"cursor-pointer\">\r\n <div className=\"flex items-center gap-2 text-gray-950 px-3 py-2 border border-gray-200 rounded-full hover:border-gray-950\">\r\n <span className=\"paragraph-small-semibold\">{userCount}</span>\r\n <User size={16} />\r\n </div>\r\n </PopoverTrigger>\r\n\r\n <PopoverContent\r\n className={cn(\r\n 'absolute right-[-88px] w-[273px] p-0 bg-white rounded-2xl shadow-md border border-gray-200',\r\n contentClassName\r\n )}\r\n side={side}\r\n align={align}\r\n sideOffset={8}\r\n >\r\n <div className=\"flex flex-col p-3 gap-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"paragraph-small-semibold\">Usuários</span>\r\n <div className=\"flex items-center gap-1.5\">\r\n <Button\r\n variant=\"secondary\"\r\n className=\"h-8 paragraph-small-semibold text-gray-950\"\r\n onClick={() => route.push(addRoute)}\r\n >\r\n <Plus size={16} />\r\n Adicionar\r\n </Button>\r\n <Tooltip>\r\n <TooltipTrigger asChild>\r\n <Button\r\n variant=\"secondary\"\r\n className=\"p-0 size-8\"\r\n onClick={() => route.push(manageRoute)}\r\n >\r\n <Settings size={18} />\r\n </Button>\r\n </TooltipTrigger>\r\n <TooltipContent>Visualizar todos usuários</TooltipContent>\r\n </Tooltip>\r\n </div>\r\n </div>\r\n\r\n <Command className=\"gap-2\" value=\"\">\r\n <CommandInput placeholder=\"Busque aqui\" />\r\n <CommandList className=\"custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]\">\r\n {isLoading ? (\r\n <>\r\n <UserItemSkeleton />\r\n <UserItemSkeleton />\r\n <UserItemSkeleton />\r\n </>\r\n ) : users.length === 0 ? (\r\n <div className=\"flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4\">\r\n <Users size={28} className=\"text-gray-300\" />\r\n <span className=\"paragraph-small-medium text-center text-gray-500\">\r\n Nenhum usuário neste projeto.\r\n <br />\r\n Adicione um usuário para começar.\r\n </span>\r\n </div>\r\n ) : (\r\n <>\r\n <CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>\r\n {users.map((user) => (\r\n <CommandItem\r\n key={user.id}\r\n value={user.name}\r\n autoFocus={false}\r\n onPointerEnter={() => setHoveredId(user.id)}\r\n onPointerLeave={() => setHoveredId(null)}\r\n onFocus={() => setHoveredId(user.id)}\r\n onBlur={() => setHoveredId(null)}\r\n onSelect={() => toggleUser(user.id)}\r\n className=\"cursor-pointer\"\r\n >\r\n <div className=\"flex items-center justify-between w-full\">\r\n <div className=\"flex items-center gap-2\">\r\n <Image\r\n alt=\"Avatar\"\r\n src={user.avatar}\r\n width={32}\r\n height={32}\r\n className=\"rounded-full\"\r\n />\r\n {user.name}\r\n </div>\r\n <Tooltip open={hoveredId === user.id}>\r\n <TooltipTrigger\r\n onClick={(e) => e.stopPropagation()}\r\n onPointerDown={(e) => e.stopPropagation()}\r\n >\r\n <Checkbox\r\n checked={user.checked}\r\n onCheckedChange={() => toggleUser(user.id)}\r\n className={hoveredId === user.id ? 'border-gray-950' : ''}\r\n />\r\n </TooltipTrigger>\r\n <TooltipContent>\r\n {user.checked ? 'Remover do projeto' : 'Adicionar ao projeto'}\r\n </TooltipContent>\r\n </Tooltip>\r\n </div>\r\n </CommandItem>\r\n ))}\r\n </>\r\n )}\r\n </CommandList>\r\n </Command>\r\n </div>\r\n </PopoverContent>\r\n </Popover>\r\n );\r\n}\r\n\r\nfunction ConnectedUsersSelectorPopover({\r\n projectId,\r\n addRoute,\r\n manageRoute,\r\n side,\r\n align,\r\n contentClassName,\r\n}: Required<Pick<UsersSelectorPopoverProps, 'projectId'>> &\r\n Pick<UsersSelectorPopoverProps, 'addRoute' | 'manageRoute' | 'side' | 'align' | 'contentClassName'>) {\r\n const { users, isLoading, userCount, toggleUser } = useProjectUsers(projectId);\r\n return (\r\n <UsersSelectorPopoverContent\r\n users={users}\r\n isLoading={isLoading}\r\n userCount={userCount}\r\n toggleUser={toggleUser}\r\n addRoute={addRoute ?? '/my-teams?createNew=true'}\r\n manageRoute={manageRoute ?? '/my-teams'}\r\n side={side}\r\n align={align}\r\n contentClassName={contentClassName}\r\n />\r\n );\r\n}\r\n\r\nfunction StaticUsersSelectorPopover({\r\n users: externalUsers = [],\r\n onToggleUser,\r\n userCount = 5,\r\n addRoute = '/my-teams?createNew=true',\r\n manageRoute = '/my-teams',\r\n side,\r\n align,\r\n contentClassName,\r\n}: Omit<UsersSelectorPopoverProps, 'projectId'>) {\r\n const [internalUsers, setInternalUsers] = useState<UserSelectorItem[]>(externalUsers);\r\n\r\n const users = externalUsers.length > 0 ? externalUsers : internalUsers;\r\n\r\n const toggleUser = (id: number) => {\r\n if (onToggleUser) {\r\n onToggleUser(id);\r\n } else {\r\n setInternalUsers((prev) =>\r\n prev.map((u) => (u.id === id ? { ...u, checked: !u.checked } : u))\r\n );\r\n }\r\n };\r\n\r\n return (\r\n <UsersSelectorPopoverContent\r\n users={users}\r\n isLoading={false}\r\n userCount={userCount}\r\n toggleUser={toggleUser}\r\n addRoute={addRoute}\r\n manageRoute={manageRoute}\r\n side={side}\r\n align={align}\r\n contentClassName={contentClassName}\r\n />\r\n );\r\n}\r\n\r\nfunction UsersSelectorPopover(props: UsersSelectorPopoverProps) {\r\n if (props.projectId != null) {\r\n return <ConnectedUsersSelectorPopover {...props} projectId={props.projectId} />;\r\n }\r\n return <StaticUsersSelectorPopover {...props} />;\r\n}\r\n\r\nexport { UsersSelectorPopover };\r\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./infra/api/types";
|
|
|
5
5
|
export * from "./providers/query.provider";
|
|
6
6
|
export * from "./providers/auth.provider";
|
|
7
7
|
export * from "./providers/whitelabel.provider";
|
|
8
|
+
import { useProjectUsers, projectUsersQueryKey } from "./modules/projects/hooks/project-users.hook";
|
|
8
9
|
import { useUserQuery, useUserValidateSession, useInvalidateUser, useSetUserData, USER_QUERY_KEY } from "./modules/auth/hooks/useUserQuery";
|
|
9
10
|
import { useSubscriptions, SUBSCRIPTIONS_QUERY_KEY } from "./modules/subscriptions/hooks/list-subscriptions.hook";
|
|
10
11
|
import { useActiveSubscription } from "./modules/subscriptions/hooks/find-active-subscription.hook";
|
|
@@ -268,6 +269,7 @@ export {
|
|
|
268
269
|
formatTimer,
|
|
269
270
|
parseResult,
|
|
270
271
|
parseSchema,
|
|
272
|
+
projectUsersQueryKey,
|
|
271
273
|
readFromClipboard,
|
|
272
274
|
stopChain,
|
|
273
275
|
timezoneService,
|
|
@@ -284,6 +286,7 @@ export {
|
|
|
284
286
|
useMdSidebarStore,
|
|
285
287
|
useModalManager,
|
|
286
288
|
default5 as usePasswordVisibility,
|
|
289
|
+
useProjectUsers,
|
|
287
290
|
useSetUserData,
|
|
288
291
|
useSubscriptions,
|
|
289
292
|
useUpdateAccount,
|
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';\nexport { useSubscriptions, SUBSCRIPTIONS_QUERY_KEY } from './modules/subscriptions/hooks/list-subscriptions.hook';\nexport { useActiveSubscription } from './modules/subscriptions/hooks/find-active-subscription.hook';\nexport { useIaCredits } from './modules/ia-credits/hooks/ia-credits.hook';\nexport type { IaCreditsSummary, IaCreditOperation } from './modules/ia-credits/types';\nexport type { Subscription, SubscriptionItem, FindSubscriptionsParams } from './modules/subscriptions/types';\nexport { SubscriptionSchema, SubscriptionItemSchema } from './modules/subscriptions/types';\nexport { ADDON_IDS } from './modules/subscriptions/constants/addons.constants';\nexport type { AddonKindEnum } from './modules/subscriptions/constants/addons.constants';\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';\nexport { parseSchema, parseResult } from './infra/utils/parser';\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 { AppNavBar } from './components/layouts/AppNavBar';\nexport type { AppNavBarProps } from './components/layouts/AppNavBar';\nexport { AppMobileNavBar } from './components/layouts/AppMobileNavBar';\nexport type { AppMobileNavBarProps } from './components/layouts/AppMobileNavBar';\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 { NotificationsPopover } from './components/layouts/NotificationsPopover';\nexport type { NotificationsPopoverProps, NotificationData } from './components/layouts/NotificationsPopover';\nexport { UsersSelectorPopover } from './components/layouts/UsersSelectorPopover';\nexport type { UsersSelectorPopoverProps, UserSelectorItem } from './components/layouts/UsersSelectorPopover';\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';\n\n// UI - Buttons\nexport { Button, buttonVariants } from './components/ui/buttons/Button';\nexport { CopyButton } from './components/ui/buttons/CopyButton';\nexport { default as CancelButton } from './components/ui/buttons/CancelButton';\n\n// UI - Data Display\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from './components/ui/data-display/Accordion';\nexport { Badge, badgeVariants } from './components/ui/data-display/Badge';\nexport { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent } from './components/ui/data-display/Card';\nexport { Pagination, PaginationContent, PaginationLink, PaginationItem, PaginationPrevious, PaginationNext, PaginationEllipsis } from './components/ui/data-display/Pagination';\nexport { ScrollArea, ScrollBar } from './components/ui/data-display/ScrollArea';\nexport { Separator } from './components/ui/data-display/Separator';\nexport { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption } from './components/ui/data-display/Table';\nexport { Tabs, TabsList, TabsTrigger, TabsContent } from './components/ui/data-display/Tabs';\nexport { UserAvatar } from './components/ui/data-display/UserAvatar';\nexport type { UserAvatarProps } from './components/ui/data-display/UserAvatar';\n\n// UI - Feedback\nexport { default as CircularProgress } from './components/ui/feedback/CircularProgress';\nexport { default as DefaultCircularProgress } from './components/ui/feedback/DefaultCircularProgress';\nexport { Progress } from './components/ui/feedback/Progress';\nexport { LoadingOverlay } from './components/ui/feedback/LoadingOverlay';\nexport { Toast, toastVariants, toastIconContainerVariants } from './components/ui/feedback/Toast';\nexport type { ToastProps } from './components/ui/feedback/Toast';\n\n// UI - Form\nexport { Calendar, CalendarDayButton } from './components/ui/form/Calendar';\nexport { Checkbox } from './components/ui/form/Checkbox';\nexport { DatePicker } from './components/ui/form/DatePicker';\nexport { DateRangePicker } from './components/ui/form/DateRangePicker';\nexport { Input } from './components/ui/form/Input';\nexport { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } from './components/ui/form/InputOtp';\nexport { RadioGroup, RadioGroupItem } from './components/ui/form/RadioGroup';\nexport { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue } from './components/ui/form/Select';\nexport { Switch } from './components/ui/form/Switch';\nexport { Textarea } from './components/ui/form/Textarea';\n\n// UI - Overlay\nexport { Command, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandShortcut, CommandSeparator } from './components/ui/overlay/Command';\nexport { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './components/ui/overlay/Dialog';\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } from './components/ui/overlay/Popover';\nexport { Sheet, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription } from './components/ui/overlay/Sheet';\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './components/ui/overlay/Tooltip';\n\n// Store\nexport { useMdSidebarStore } from './store/useMdSidebarStore';\nexport { useModalManager } from './store/useModalManager';\nexport type { ModalData } from './store/useModalManager';\n\n// Enums\nexport { AccountSectionType } from './enums/AccountSectionType';\n\n// Hooks\nexport { default as usePasswordVisibility } from './hooks/usePasswordVisibility';\nexport { default as useCountdownTimer } from './hooks/useCountdownTimer';\nexport { default as useIsMobile } from './hooks/useIsMobile';\n\n// Utils\nexport { formatPhone, formatTimer, formatFullName, formatCPF, formatCardNumber } from './utils/format/masks';\nexport { timezoneService } from './modules/accounts/services/timezone.service';\nexport type { TimezoneOption } from './modules/accounts/services/timezone.service';\nexport { buildLocaleOptions, LANGUAGE_OPTIONS as LOCALE_LANGUAGE_OPTIONS } from './utils/intl/locales';\nexport type { LocaleOption } from './utils/intl/locales';\nexport { copyToClipboard, readFromClipboard } from './utils/browser/clipboard';\n\n// UI - Form (new widgets)\nexport { FormField } from './components/ui/form/FormField';\nexport { SelectField } from './components/ui/form/SelectField';\nexport { ComboboxField } from './components/ui/form/ComboboxField';\nexport type { ComboboxOption } from './components/ui/form/ComboboxField';\nexport { default as PhoneInput } from './components/ui/form/PhoneInput';\nexport { default as SwitchOptionFieldWithIcon } from './components/ui/form/SwitchOptionFieldWithIcon';\nexport { TextAreaField } from './components/ui/form/TextAreaField';\n\n// Account Module - Hooks\nexport {\n useUpdateAccount,\n useUpdateAccountUser,\n useUpdateAccountUserById,\n useDeleteAccountUser,\n useDeleteAccount,\n} from './modules/accounts/hooks/useAccountManagement';\n\n// Account Types\nexport type {\n UpdateAccountRequest,\n UpdateAccountUserRequest,\n ChangePasswordRequest,\n DeleteAccountActionResult,\n DeleteUserActionResult,\n UpdateAccountActionResult,\n UpdateUserActionResult,\n TwoFactorGenerateResult,\n TwoFactorActionResult,\n ContactResetResult,\n} from './modules/accounts/types';\n\nexport { default as AccountModals } from './components/account/AccountModals';\nexport { useAccountModals } from './store/useAccountModals';\nexport type { AccountModalsConfig } from './store/useAccountModals';\n\nexport { ModalManager } from './components/modals/ModalManager';\nexport { Modals } from './components/modals/Modals';\n\nexport { default as TwoFactorAuthModal } from './components/account/TwoFactorAuthModal';\nexport { default as DisableTwoFactorAuthModal } from './components/account/DisableTwoFactorAuthModal';\nexport { default as ConfirmGlobalPreferencesModal } from './components/account/ConfirmGlobalPreferencesModal';\nexport { MyProfileSection } from './components/account/sections/MyProfileSection';\nexport { PreferencesSection } from './components/account/sections/PreferencesSection';\nexport { SecuritySection } from './components/account/sections/SecuritySection';\nexport { ChangePasswordSection } from './components/account/sections/ChangePasswordSection';\nexport { ChangeEmailModal } from './components/account/sections/ChangeEmailModal';\nexport { ChangePhoneModal } from './components/account/sections/ChangePhoneModal';\n\n// Account Constants\nexport {\n GENDER_OPTIONS,\n CURRENCY_OPTIONS,\n TIME_FORMAT_OPTIONS,\n NOTIFICATION_TYPES,\n LANGUAGE_OPTIONS,\n} from './components/account/constants';\n"],"mappings":"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","names":["default","LANGUAGE_OPTIONS"]}
|
|
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 { useProjectUsers, projectUsersQueryKey } from './modules/projects/hooks/project-users.hook';\nexport type { ProjectUser, AccountUser, AddRemoveProjectUsersParams } from './modules/projects/types';\nexport { useUserQuery, useUserValidateSession, useInvalidateUser, useSetUserData, USER_QUERY_KEY } from './modules/auth/hooks/useUserQuery';\nexport { useSubscriptions, SUBSCRIPTIONS_QUERY_KEY } from './modules/subscriptions/hooks/list-subscriptions.hook';\nexport { useActiveSubscription } from './modules/subscriptions/hooks/find-active-subscription.hook';\nexport { useIaCredits } from './modules/ia-credits/hooks/ia-credits.hook';\nexport type { IaCreditsSummary, IaCreditOperation } from './modules/ia-credits/types';\nexport type { Subscription, SubscriptionItem, FindSubscriptionsParams } from './modules/subscriptions/types';\nexport { SubscriptionSchema, SubscriptionItemSchema } from './modules/subscriptions/types';\nexport { ADDON_IDS } from './modules/subscriptions/constants/addons.constants';\nexport type { AddonKindEnum } from './modules/subscriptions/constants/addons.constants';\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';\nexport { parseSchema, parseResult } from './infra/utils/parser';\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 { AppNavBar } from './components/layouts/AppNavBar';\nexport type { AppNavBarProps } from './components/layouts/AppNavBar';\nexport { AppMobileNavBar } from './components/layouts/AppMobileNavBar';\nexport type { AppMobileNavBarProps } from './components/layouts/AppMobileNavBar';\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 { NotificationsPopover } from './components/layouts/NotificationsPopover';\nexport type { NotificationsPopoverProps, NotificationData } from './components/layouts/NotificationsPopover';\nexport { UsersSelectorPopover } from './components/layouts/UsersSelectorPopover';\nexport type { UsersSelectorPopoverProps, UserSelectorItem } from './components/layouts/UsersSelectorPopover';\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';\n\n// UI - Buttons\nexport { Button, buttonVariants } from './components/ui/buttons/Button';\nexport { CopyButton } from './components/ui/buttons/CopyButton';\nexport { default as CancelButton } from './components/ui/buttons/CancelButton';\n\n// UI - Data Display\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from './components/ui/data-display/Accordion';\nexport { Badge, badgeVariants } from './components/ui/data-display/Badge';\nexport { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent } from './components/ui/data-display/Card';\nexport { Pagination, PaginationContent, PaginationLink, PaginationItem, PaginationPrevious, PaginationNext, PaginationEllipsis } from './components/ui/data-display/Pagination';\nexport { ScrollArea, ScrollBar } from './components/ui/data-display/ScrollArea';\nexport { Separator } from './components/ui/data-display/Separator';\nexport { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption } from './components/ui/data-display/Table';\nexport { Tabs, TabsList, TabsTrigger, TabsContent } from './components/ui/data-display/Tabs';\nexport { UserAvatar } from './components/ui/data-display/UserAvatar';\nexport type { UserAvatarProps } from './components/ui/data-display/UserAvatar';\n\n// UI - Feedback\nexport { default as CircularProgress } from './components/ui/feedback/CircularProgress';\nexport { default as DefaultCircularProgress } from './components/ui/feedback/DefaultCircularProgress';\nexport { Progress } from './components/ui/feedback/Progress';\nexport { LoadingOverlay } from './components/ui/feedback/LoadingOverlay';\nexport { Toast, toastVariants, toastIconContainerVariants } from './components/ui/feedback/Toast';\nexport type { ToastProps } from './components/ui/feedback/Toast';\n\n// UI - Form\nexport { Calendar, CalendarDayButton } from './components/ui/form/Calendar';\nexport { Checkbox } from './components/ui/form/Checkbox';\nexport { DatePicker } from './components/ui/form/DatePicker';\nexport { DateRangePicker } from './components/ui/form/DateRangePicker';\nexport { Input } from './components/ui/form/Input';\nexport { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } from './components/ui/form/InputOtp';\nexport { RadioGroup, RadioGroupItem } from './components/ui/form/RadioGroup';\nexport { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue } from './components/ui/form/Select';\nexport { Switch } from './components/ui/form/Switch';\nexport { Textarea } from './components/ui/form/Textarea';\n\n// UI - Overlay\nexport { Command, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandShortcut, CommandSeparator } from './components/ui/overlay/Command';\nexport { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './components/ui/overlay/Dialog';\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } from './components/ui/overlay/Popover';\nexport { Sheet, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription } from './components/ui/overlay/Sheet';\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './components/ui/overlay/Tooltip';\n\n// Store\nexport { useMdSidebarStore } from './store/useMdSidebarStore';\nexport { useModalManager } from './store/useModalManager';\nexport type { ModalData } from './store/useModalManager';\n\n// Enums\nexport { AccountSectionType } from './enums/AccountSectionType';\n\n// Hooks\nexport { default as usePasswordVisibility } from './hooks/usePasswordVisibility';\nexport { default as useCountdownTimer } from './hooks/useCountdownTimer';\nexport { default as useIsMobile } from './hooks/useIsMobile';\n\n// Utils\nexport { formatPhone, formatTimer, formatFullName, formatCPF, formatCardNumber } from './utils/format/masks';\nexport { timezoneService } from './modules/accounts/services/timezone.service';\nexport type { TimezoneOption } from './modules/accounts/services/timezone.service';\nexport { buildLocaleOptions, LANGUAGE_OPTIONS as LOCALE_LANGUAGE_OPTIONS } from './utils/intl/locales';\nexport type { LocaleOption } from './utils/intl/locales';\nexport { copyToClipboard, readFromClipboard } from './utils/browser/clipboard';\n\n// UI - Form (new widgets)\nexport { FormField } from './components/ui/form/FormField';\nexport { SelectField } from './components/ui/form/SelectField';\nexport { ComboboxField } from './components/ui/form/ComboboxField';\nexport type { ComboboxOption } from './components/ui/form/ComboboxField';\nexport { default as PhoneInput } from './components/ui/form/PhoneInput';\nexport { default as SwitchOptionFieldWithIcon } from './components/ui/form/SwitchOptionFieldWithIcon';\nexport { TextAreaField } from './components/ui/form/TextAreaField';\n\n// Account Module - Hooks\nexport {\n useUpdateAccount,\n useUpdateAccountUser,\n useUpdateAccountUserById,\n useDeleteAccountUser,\n useDeleteAccount,\n} from './modules/accounts/hooks/useAccountManagement';\n\n// Account Types\nexport type {\n UpdateAccountRequest,\n UpdateAccountUserRequest,\n ChangePasswordRequest,\n DeleteAccountActionResult,\n DeleteUserActionResult,\n UpdateAccountActionResult,\n UpdateUserActionResult,\n TwoFactorGenerateResult,\n TwoFactorActionResult,\n ContactResetResult,\n} from './modules/accounts/types';\n\nexport { default as AccountModals } from './components/account/AccountModals';\nexport { useAccountModals } from './store/useAccountModals';\nexport type { AccountModalsConfig } from './store/useAccountModals';\n\nexport { ModalManager } from './components/modals/ModalManager';\nexport { Modals } from './components/modals/Modals';\n\nexport { default as TwoFactorAuthModal } from './components/account/TwoFactorAuthModal';\nexport { default as DisableTwoFactorAuthModal } from './components/account/DisableTwoFactorAuthModal';\nexport { default as ConfirmGlobalPreferencesModal } from './components/account/ConfirmGlobalPreferencesModal';\nexport { MyProfileSection } from './components/account/sections/MyProfileSection';\nexport { PreferencesSection } from './components/account/sections/PreferencesSection';\nexport { SecuritySection } from './components/account/sections/SecuritySection';\nexport { ChangePasswordSection } from './components/account/sections/ChangePasswordSection';\nexport { ChangeEmailModal } from './components/account/sections/ChangeEmailModal';\nexport { ChangePhoneModal } from './components/account/sections/ChangePhoneModal';\n\n// Account Constants\nexport {\n GENDER_OPTIONS,\n CURRENCY_OPTIONS,\n TIME_FORMAT_OPTIONS,\n NOTIFICATION_TYPES,\n LANGUAGE_OPTIONS,\n} from './components/account/constants';\n"],"mappings":"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","names":["default","LANGUAGE_OPTIONS"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { projectUsersService } from "../services/project-users.service";
|
|
3
|
+
async function addProjectUserAction(params) {
|
|
4
|
+
return projectUsersService.addToProject(params);
|
|
5
|
+
}
|
|
6
|
+
export {
|
|
7
|
+
addProjectUserAction
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=add-project-user.action.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/projects/actions/add-project-user.action.ts"],"sourcesContent":["'use server';\r\n\r\nimport { projectUsersService } from '../services/project-users.service';\r\nimport type { AddRemoveProjectUsersParams } from '../types';\r\n\r\nexport async function addProjectUserAction(params: AddRemoveProjectUsersParams): Promise<void> {\r\n return projectUsersService.addToProject(params);\r\n}\r\n"],"mappings":";AAEA,SAAS,2BAA2B;AAGpC,eAAsB,qBAAqB,QAAoD;AAC7F,SAAO,oBAAoB,aAAa,MAAM;AAChD;","names":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { projectUsersService } from "../services/project-users.service";
|
|
3
|
+
async function listAvailableUsersAction(id_project) {
|
|
4
|
+
return projectUsersService.listNotInProject(id_project);
|
|
5
|
+
}
|
|
6
|
+
export {
|
|
7
|
+
listAvailableUsersAction
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=list-available-users.action.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/projects/actions/list-available-users.action.ts"],"sourcesContent":["'use server';\r\n\r\nimport { projectUsersService } from '../services/project-users.service';\r\nimport type { AccountUser } from '../types';\r\n\r\nexport async function listAvailableUsersAction(id_project: number): Promise<AccountUser[]> {\r\n return projectUsersService.listNotInProject(id_project);\r\n}\r\n"],"mappings":";AAEA,SAAS,2BAA2B;AAGpC,eAAsB,yBAAyB,YAA4C;AACzF,SAAO,oBAAoB,iBAAiB,UAAU;AACxD;","names":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { projectUsersService } from "../services/project-users.service";
|
|
3
|
+
async function listProjectUsersAction(id_project) {
|
|
4
|
+
return projectUsersService.listInProject(id_project);
|
|
5
|
+
}
|
|
6
|
+
export {
|
|
7
|
+
listProjectUsersAction
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=list-project-users.action.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/projects/actions/list-project-users.action.ts"],"sourcesContent":["'use server';\r\n\r\nimport { projectUsersService } from '../services/project-users.service';\r\nimport type { ProjectUser } from '../types';\r\n\r\nexport async function listProjectUsersAction(id_project: number): Promise<ProjectUser[]> {\r\n return projectUsersService.listInProject(id_project);\r\n}\r\n"],"mappings":";AAEA,SAAS,2BAA2B;AAGpC,eAAsB,uBAAuB,YAA4C;AACvF,SAAO,oBAAoB,cAAc,UAAU;AACrD;","names":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { projectUsersService } from "../services/project-users.service";
|
|
3
|
+
async function removeProjectUserAction(params) {
|
|
4
|
+
return projectUsersService.removeFromProject(params);
|
|
5
|
+
}
|
|
6
|
+
export {
|
|
7
|
+
removeProjectUserAction
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=remove-project-user.action.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/projects/actions/remove-project-user.action.ts"],"sourcesContent":["'use server';\r\n\r\nimport { projectUsersService } from '../services/project-users.service';\r\nimport type { AddRemoveProjectUsersParams } from '../types';\r\n\r\nexport async function removeProjectUserAction(params: AddRemoveProjectUsersParams): Promise<void> {\r\n return projectUsersService.removeFromProject(params);\r\n}\r\n"],"mappings":";AAEA,SAAS,2BAA2B;AAGpC,eAAsB,wBAAwB,QAAoD;AAChG,SAAO,oBAAoB,kBAAkB,MAAM;AACrD;","names":[]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
4
|
+
import { addProjectUserAction } from "../actions/add-project-user.action";
|
|
5
|
+
import { listAvailableUsersAction } from "../actions/list-available-users.action";
|
|
6
|
+
import { listProjectUsersAction } from "../actions/list-project-users.action";
|
|
7
|
+
import { removeProjectUserAction } from "../actions/remove-project-user.action";
|
|
8
|
+
const DEFAULT_AVATAR = "/images/Logomark.png";
|
|
9
|
+
const projectUsersQueryKey = (id_project) => ["project-users", id_project];
|
|
10
|
+
function useProjectUsers(id_project) {
|
|
11
|
+
const queryClient = useQueryClient();
|
|
12
|
+
const { data: inProject = [], isLoading: isLoadingIn } = useQuery({
|
|
13
|
+
queryKey: [...projectUsersQueryKey(id_project), "in"],
|
|
14
|
+
queryFn: () => listProjectUsersAction(id_project),
|
|
15
|
+
enabled: !!id_project
|
|
16
|
+
});
|
|
17
|
+
const { data: notInProject = [], isLoading: isLoadingOut } = useQuery({
|
|
18
|
+
queryKey: [...projectUsersQueryKey(id_project), "out"],
|
|
19
|
+
queryFn: () => listAvailableUsersAction(id_project),
|
|
20
|
+
enabled: !!id_project
|
|
21
|
+
});
|
|
22
|
+
const invalidate = () => {
|
|
23
|
+
queryClient.invalidateQueries({ queryKey: projectUsersQueryKey(id_project) });
|
|
24
|
+
};
|
|
25
|
+
const addMutation = useMutation({
|
|
26
|
+
mutationFn: (user_id) => addProjectUserAction({ id_project, users: [user_id] }),
|
|
27
|
+
onSuccess: invalidate
|
|
28
|
+
});
|
|
29
|
+
const removeMutation = useMutation({
|
|
30
|
+
mutationFn: (user_id) => removeProjectUserAction({ id_project, users: [user_id] }),
|
|
31
|
+
onSuccess: invalidate
|
|
32
|
+
});
|
|
33
|
+
const users = useMemo(
|
|
34
|
+
() => [
|
|
35
|
+
...inProject.map((u) => ({
|
|
36
|
+
id: u.id_user,
|
|
37
|
+
name: u.name,
|
|
38
|
+
avatar: u.photo ?? DEFAULT_AVATAR,
|
|
39
|
+
checked: true
|
|
40
|
+
})),
|
|
41
|
+
...notInProject.map((u) => ({
|
|
42
|
+
id: u.id,
|
|
43
|
+
name: u.name,
|
|
44
|
+
avatar: u.photo ?? DEFAULT_AVATAR,
|
|
45
|
+
checked: false
|
|
46
|
+
}))
|
|
47
|
+
],
|
|
48
|
+
[inProject, notInProject]
|
|
49
|
+
);
|
|
50
|
+
const toggleUser = (id) => {
|
|
51
|
+
const user = users.find((u) => u.id === id);
|
|
52
|
+
if (!user) return;
|
|
53
|
+
if (user.checked) {
|
|
54
|
+
removeMutation.mutate(id);
|
|
55
|
+
} else {
|
|
56
|
+
addMutation.mutate(id);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
users,
|
|
61
|
+
isLoading: isLoadingIn || isLoadingOut,
|
|
62
|
+
userCount: inProject.length,
|
|
63
|
+
toggleUser
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
projectUsersQueryKey,
|
|
68
|
+
useProjectUsers
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=project-users.hook.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/projects/hooks/project-users.hook.ts"],"sourcesContent":["'use client';\r\n\r\nimport { useMemo } from 'react';\r\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\r\n\r\nimport type { UserSelectorItem } from '../../../components/layouts/UsersSelectorPopover';\r\nimport { addProjectUserAction } from '../actions/add-project-user.action';\r\nimport { listAvailableUsersAction } from '../actions/list-available-users.action';\r\nimport { listProjectUsersAction } from '../actions/list-project-users.action';\r\nimport { removeProjectUserAction } from '../actions/remove-project-user.action';\r\n\r\nconst DEFAULT_AVATAR = '/images/Logomark.png';\r\n\r\nexport const projectUsersQueryKey = (id_project: number) => ['project-users', id_project];\r\n\r\nexport function useProjectUsers(id_project: number) {\r\n const queryClient = useQueryClient();\r\n\r\n const { data: inProject = [], isLoading: isLoadingIn } = useQuery({\r\n queryKey: [...projectUsersQueryKey(id_project), 'in'],\r\n queryFn: () => listProjectUsersAction(id_project),\r\n enabled: !!id_project,\r\n });\r\n\r\n const { data: notInProject = [], isLoading: isLoadingOut } = useQuery({\r\n queryKey: [...projectUsersQueryKey(id_project), 'out'],\r\n queryFn: () => listAvailableUsersAction(id_project),\r\n enabled: !!id_project,\r\n });\r\n\r\n const invalidate = () => {\r\n queryClient.invalidateQueries({ queryKey: projectUsersQueryKey(id_project) });\r\n };\r\n\r\n const addMutation = useMutation({\r\n mutationFn: (user_id: number) =>\r\n addProjectUserAction({ id_project, users: [user_id] }),\r\n onSuccess: invalidate,\r\n });\r\n\r\n const removeMutation = useMutation({\r\n mutationFn: (user_id: number) =>\r\n removeProjectUserAction({ id_project, users: [user_id] }),\r\n onSuccess: invalidate,\r\n });\r\n\r\n const users: UserSelectorItem[] = useMemo(\r\n () => [\r\n ...inProject.map((u) => ({\r\n id: u.id_user,\r\n name: u.name,\r\n avatar: u.photo ?? DEFAULT_AVATAR,\r\n checked: true,\r\n })),\r\n ...notInProject.map((u) => ({\r\n id: u.id,\r\n name: u.name,\r\n avatar: u.photo ?? DEFAULT_AVATAR,\r\n checked: false,\r\n })),\r\n ],\r\n [inProject, notInProject]\r\n );\r\n\r\n const toggleUser = (id: number) => {\r\n const user = users.find((u) => u.id === id);\r\n if (!user) return;\r\n if (user.checked) {\r\n removeMutation.mutate(id);\r\n } else {\r\n addMutation.mutate(id);\r\n }\r\n };\r\n\r\n return {\r\n users,\r\n isLoading: isLoadingIn || isLoadingOut,\r\n userCount: inProject.length,\r\n toggleUser,\r\n };\r\n}\r\n"],"mappings":";AAEA,SAAS,eAAe;AACxB,SAAS,aAAa,UAAU,sBAAsB;AAGtD,SAAS,4BAA4B;AACrC,SAAS,gCAAgC;AACzC,SAAS,8BAA8B;AACvC,SAAS,+BAA+B;AAExC,MAAM,iBAAiB;AAEhB,MAAM,uBAAuB,CAAC,eAAuB,CAAC,iBAAiB,UAAU;AAEjF,SAAS,gBAAgB,YAAoB;AAClD,QAAM,cAAc,eAAe;AAEnC,QAAM,EAAE,MAAM,YAAY,CAAC,GAAG,WAAW,YAAY,IAAI,SAAS;AAAA,IAChE,UAAU,CAAC,GAAG,qBAAqB,UAAU,GAAG,IAAI;AAAA,IACpD,SAAS,MAAM,uBAAuB,UAAU;AAAA,IAChD,SAAS,CAAC,CAAC;AAAA,EACb,CAAC;AAED,QAAM,EAAE,MAAM,eAAe,CAAC,GAAG,WAAW,aAAa,IAAI,SAAS;AAAA,IACpE,UAAU,CAAC,GAAG,qBAAqB,UAAU,GAAG,KAAK;AAAA,IACrD,SAAS,MAAM,yBAAyB,UAAU;AAAA,IAClD,SAAS,CAAC,CAAC;AAAA,EACb,CAAC;AAED,QAAM,aAAa,MAAM;AACvB,gBAAY,kBAAkB,EAAE,UAAU,qBAAqB,UAAU,EAAE,CAAC;AAAA,EAC9E;AAEA,QAAM,cAAc,YAAY;AAAA,IAC9B,YAAY,CAAC,YACX,qBAAqB,EAAE,YAAY,OAAO,CAAC,OAAO,EAAE,CAAC;AAAA,IACvD,WAAW;AAAA,EACb,CAAC;AAED,QAAM,iBAAiB,YAAY;AAAA,IACjC,YAAY,CAAC,YACX,wBAAwB,EAAE,YAAY,OAAO,CAAC,OAAO,EAAE,CAAC;AAAA,IAC1D,WAAW;AAAA,EACb,CAAC;AAED,QAAM,QAA4B;AAAA,IAChC,MAAM;AAAA,MACJ,GAAG,UAAU,IAAI,CAAC,OAAO;AAAA,QACvB,IAAI,EAAE;AAAA,QACN,MAAM,EAAE;AAAA,QACR,QAAQ,EAAE,SAAS;AAAA,QACnB,SAAS;AAAA,MACX,EAAE;AAAA,MACF,GAAG,aAAa,IAAI,CAAC,OAAO;AAAA,QAC1B,IAAI,EAAE;AAAA,QACN,MAAM,EAAE;AAAA,QACR,QAAQ,EAAE,SAAS;AAAA,QACnB,SAAS;AAAA,MACX,EAAE;AAAA,IACJ;AAAA,IACA,CAAC,WAAW,YAAY;AAAA,EAC1B;AAEA,QAAM,aAAa,CAAC,OAAe;AACjC,UAAM,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAC1C,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,SAAS;AAChB,qBAAe,OAAO,EAAE;AAAA,IAC1B,OAAO;AACL,kBAAY,OAAO,EAAE;AAAA,IACvB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,WAAW,eAAe;AAAA,IAC1B,WAAW,UAAU;AAAA,IACrB;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import "server-only";
|
|
2
|
+
import { api } from "../../../infra/api/client";
|
|
3
|
+
import { ApiError } from "../../../infra/api/types";
|
|
4
|
+
import { getUserContext } from "../../auth/utils/get-user-context";
|
|
5
|
+
import {
|
|
6
|
+
AccountUserSchema,
|
|
7
|
+
ProjectUserSchema
|
|
8
|
+
} from "../types";
|
|
9
|
+
class ProjectUsersService {
|
|
10
|
+
async listInProject(id_project) {
|
|
11
|
+
const { id_account, id_user } = await getUserContext();
|
|
12
|
+
const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
|
|
13
|
+
const response = await api.pages.get(url);
|
|
14
|
+
if (response.status === 0) {
|
|
15
|
+
throw new ApiError(
|
|
16
|
+
response.message || "Erro ao listar usu\xE1rios do projeto",
|
|
17
|
+
"LIST_PROJECT_USERS_FAILED",
|
|
18
|
+
400
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
return response.data.map((item) => ProjectUserSchema.parse(item));
|
|
22
|
+
}
|
|
23
|
+
async listNotInProject(id_project) {
|
|
24
|
+
const { id_account } = await getUserContext();
|
|
25
|
+
const url = `/accounts/${id_account}/users?notInProject=${id_project}`;
|
|
26
|
+
const response = await api.apps.get(url);
|
|
27
|
+
if (response.status === 0) {
|
|
28
|
+
throw new ApiError(
|
|
29
|
+
response.message || "Erro ao listar usu\xE1rios dispon\xEDveis",
|
|
30
|
+
"LIST_AVAILABLE_USERS_FAILED",
|
|
31
|
+
400
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
return response.data.map((item) => AccountUserSchema.parse(item));
|
|
35
|
+
}
|
|
36
|
+
async addToProject({ id_project, users }) {
|
|
37
|
+
const { id_account, id_user } = await getUserContext();
|
|
38
|
+
const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
|
|
39
|
+
const response = await api.pages.post(url, { users });
|
|
40
|
+
if (response.status === 0) {
|
|
41
|
+
throw new ApiError(
|
|
42
|
+
response.message || "Erro ao adicionar usu\xE1rio ao projeto",
|
|
43
|
+
"ADD_PROJECT_USER_FAILED",
|
|
44
|
+
400
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async removeFromProject({ id_project, users }) {
|
|
49
|
+
const { id_account, id_user } = await getUserContext();
|
|
50
|
+
const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
|
|
51
|
+
const response = await api.pages.delete(url, {
|
|
52
|
+
body: JSON.stringify({ users })
|
|
53
|
+
});
|
|
54
|
+
if (response.status === 0) {
|
|
55
|
+
throw new ApiError(
|
|
56
|
+
response.message || "Erro ao remover usu\xE1rio do projeto",
|
|
57
|
+
"REMOVE_PROJECT_USER_FAILED",
|
|
58
|
+
400
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const projectUsersService = new ProjectUsersService();
|
|
64
|
+
export {
|
|
65
|
+
projectUsersService
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=project-users.service.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/projects/services/project-users.service.ts"],"sourcesContent":["import 'server-only';\r\n\r\nimport { api } from '../../../infra/api/client';\r\nimport { ApiError } from '../../../infra/api/types';\r\nimport { getUserContext } from '../../auth/utils/get-user-context';\r\nimport {\r\n AccountUser,\r\n AccountUserSchema,\r\n AddRemoveProjectUsersParams,\r\n ProjectUser,\r\n ProjectUserSchema,\r\n} from '../types';\r\n\r\ninterface ApiListResponse<T> {\r\n data: T[];\r\n total: number;\r\n status: number;\r\n message?: string;\r\n}\r\n\r\ninterface ApiActionResponse {\r\n status: number;\r\n message?: string;\r\n}\r\n\r\nclass ProjectUsersService {\r\n async listInProject(id_project: number): Promise<ProjectUser[]> {\r\n const { id_account, id_user } = await getUserContext();\r\n const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;\r\n\r\n const response = await api.pages.get<ApiListResponse<ProjectUser>>(url);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || 'Erro ao listar usuários do projeto',\r\n 'LIST_PROJECT_USERS_FAILED',\r\n 400\r\n );\r\n }\r\n\r\n return response.data.map((item) => ProjectUserSchema.parse(item));\r\n }\r\n\r\n async listNotInProject(id_project: number): Promise<AccountUser[]> {\r\n const { id_account } = await getUserContext();\r\n const url = `/accounts/${id_account}/users?notInProject=${id_project}`;\r\n\r\n const response = await api.apps.get<ApiListResponse<AccountUser>>(url);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || 'Erro ao listar usuários disponíveis',\r\n 'LIST_AVAILABLE_USERS_FAILED',\r\n 400\r\n );\r\n }\r\n\r\n return response.data.map((item) => AccountUserSchema.parse(item));\r\n }\r\n\r\n async addToProject({ id_project, users }: AddRemoveProjectUsersParams): Promise<void> {\r\n const { id_account, id_user } = await getUserContext();\r\n const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;\r\n\r\n const response = await api.pages.post<ApiActionResponse>(url, { users });\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || 'Erro ao adicionar usuário ao projeto',\r\n 'ADD_PROJECT_USER_FAILED',\r\n 400\r\n );\r\n }\r\n }\r\n\r\n async removeFromProject({ id_project, users }: AddRemoveProjectUsersParams): Promise<void> {\r\n const { id_account, id_user } = await getUserContext();\r\n const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;\r\n\r\n const response = await api.pages.delete<ApiActionResponse>(url, {\r\n body: JSON.stringify({ users }),\r\n });\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || 'Erro ao remover usuário do projeto',\r\n 'REMOVE_PROJECT_USER_FAILED',\r\n 400\r\n );\r\n }\r\n }\r\n}\r\n\r\nexport const projectUsersService = new ProjectUsersService();\r\n"],"mappings":"AAAA,OAAO;AAEP,SAAS,WAAW;AACpB,SAAS,gBAAgB;AACzB,SAAS,sBAAsB;AAC/B;AAAA,EAEE;AAAA,EAGA;AAAA,OACK;AAcP,MAAM,oBAAoB;AAAA,EACxB,MAAM,cAAc,YAA4C;AAC9D,UAAM,EAAE,YAAY,QAAQ,IAAI,MAAM,eAAe;AACrD,UAAM,MAAM,YAAY,UAAU,SAAS,OAAO,aAAa,UAAU;AAEzE,UAAM,WAAW,MAAM,IAAI,MAAM,IAAkC,GAAG;AAEtE,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO,SAAS,KAAK,IAAI,CAAC,SAAS,kBAAkB,MAAM,IAAI,CAAC;AAAA,EAClE;AAAA,EAEA,MAAM,iBAAiB,YAA4C;AACjE,UAAM,EAAE,WAAW,IAAI,MAAM,eAAe;AAC5C,UAAM,MAAM,aAAa,UAAU,uBAAuB,UAAU;AAEpE,UAAM,WAAW,MAAM,IAAI,KAAK,IAAkC,GAAG;AAErE,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO,SAAS,KAAK,IAAI,CAAC,SAAS,kBAAkB,MAAM,IAAI,CAAC;AAAA,EAClE;AAAA,EAEA,MAAM,aAAa,EAAE,YAAY,MAAM,GAA+C;AACpF,UAAM,EAAE,YAAY,QAAQ,IAAI,MAAM,eAAe;AACrD,UAAM,MAAM,YAAY,UAAU,SAAS,OAAO,aAAa,UAAU;AAEzE,UAAM,WAAW,MAAM,IAAI,MAAM,KAAwB,KAAK,EAAE,MAAM,CAAC;AAEvE,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,EAAE,YAAY,MAAM,GAA+C;AACzF,UAAM,EAAE,YAAY,QAAQ,IAAI,MAAM,eAAe;AACrD,UAAM,MAAM,YAAY,UAAU,SAAS,OAAO,aAAa,UAAU;AAEzE,UAAM,WAAW,MAAM,IAAI,MAAM,OAA0B,KAAK;AAAA,MAC9D,MAAM,KAAK,UAAU,EAAE,MAAM,CAAC;AAAA,IAChC,CAAC;AAED,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,MAAM,sBAAsB,IAAI,oBAAoB;","names":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const ProjectUserSchema = z.object({
|
|
3
|
+
id_user: z.union([z.number(), z.string()]).transform(Number),
|
|
4
|
+
id_account: z.union([z.number(), z.string()]).transform(Number),
|
|
5
|
+
id_project: z.union([z.number(), z.string()]).transform(Number),
|
|
6
|
+
name: z.string(),
|
|
7
|
+
email: z.string(),
|
|
8
|
+
profile: z.string().optional(),
|
|
9
|
+
photo: z.string().nullable().optional()
|
|
10
|
+
});
|
|
11
|
+
const AccountUserSchema = z.object({
|
|
12
|
+
id: z.union([z.number(), z.string()]).transform(Number),
|
|
13
|
+
name: z.string(),
|
|
14
|
+
email: z.string(),
|
|
15
|
+
profile: z.string().optional(),
|
|
16
|
+
photo: z.string().nullable().optional()
|
|
17
|
+
});
|
|
18
|
+
export {
|
|
19
|
+
AccountUserSchema,
|
|
20
|
+
ProjectUserSchema
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=types.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/modules/projects/types.ts"],"sourcesContent":["import { z } from 'zod';\r\n\r\nexport const ProjectUserSchema = z.object({\r\n id_user: z.union([z.number(), z.string()]).transform(Number),\r\n id_account: z.union([z.number(), z.string()]).transform(Number),\r\n id_project: z.union([z.number(), z.string()]).transform(Number),\r\n name: z.string(),\r\n email: z.string(),\r\n profile: z.string().optional(),\r\n photo: z.string().nullable().optional(),\r\n});\r\n\r\nexport type ProjectUser = z.infer<typeof ProjectUserSchema>;\r\n\r\nexport const AccountUserSchema = z.object({\r\n id: z.union([z.number(), z.string()]).transform(Number),\r\n name: z.string(),\r\n email: z.string(),\r\n profile: z.string().optional(),\r\n photo: z.string().nullable().optional(),\r\n});\r\n\r\nexport type AccountUser = z.infer<typeof AccountUserSchema>;\r\n\r\nexport interface AddRemoveProjectUsersParams {\r\n id_project: number;\r\n users: number[];\r\n}\r\n"],"mappings":"AAAA,SAAS,SAAS;AAEX,MAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,SAAS,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,UAAU,MAAM;AAAA,EAC3D,YAAY,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,UAAU,MAAM;AAAA,EAC9D,YAAY,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,UAAU,MAAM;AAAA,EAC9D,MAAM,EAAE,OAAO;AAAA,EACf,OAAO,EAAE,OAAO;AAAA,EAChB,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AACxC,CAAC;AAIM,MAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,UAAU,MAAM;AAAA,EACtD,MAAM,EAAE,OAAO;AAAA,EACf,OAAO,EAAE,OAAO;AAAA,EAChB,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AACxC,CAAC;","names":[]}
|
package/dist/server.mjs
CHANGED
|
@@ -8,6 +8,11 @@ import { findWhitelabel } from "./modules/whitelabel/actions/find-whitelabel.act
|
|
|
8
8
|
import { validateSessionAction } from "./modules/auth/actions/validate-session.action";
|
|
9
9
|
import { listSubscriptionsAction } from "./modules/subscriptions/actions/list-subscriptions.action";
|
|
10
10
|
import { listIaCreditsAction } from "./modules/ia-credits/actions/list-ia-credits.action";
|
|
11
|
+
import { projectUsersService } from "./modules/projects/services/project-users.service";
|
|
12
|
+
import { listProjectUsersAction } from "./modules/projects/actions/list-project-users.action";
|
|
13
|
+
import { listAvailableUsersAction } from "./modules/projects/actions/list-available-users.action";
|
|
14
|
+
import { addProjectUserAction } from "./modules/projects/actions/add-project-user.action";
|
|
15
|
+
import { removeProjectUserAction } from "./modules/projects/actions/remove-project-user.action";
|
|
11
16
|
import { accountService } from "./modules/accounts/services/account.service";
|
|
12
17
|
import { twoFactorService } from "./modules/accounts/services/two-factor.service";
|
|
13
18
|
import {
|
|
@@ -32,6 +37,7 @@ import { getUserContext } from "./modules/auth/utils/get-user-context";
|
|
|
32
37
|
export {
|
|
33
38
|
ApiClient,
|
|
34
39
|
accountService,
|
|
40
|
+
addProjectUserAction,
|
|
35
41
|
api,
|
|
36
42
|
apiClient,
|
|
37
43
|
authService,
|
|
@@ -49,8 +55,12 @@ export {
|
|
|
49
55
|
getUserContext,
|
|
50
56
|
iaCreditsService,
|
|
51
57
|
listAccountUsersAction,
|
|
58
|
+
listAvailableUsersAction,
|
|
52
59
|
listIaCreditsAction,
|
|
60
|
+
listProjectUsersAction,
|
|
53
61
|
listSubscriptionsAction,
|
|
62
|
+
projectUsersService,
|
|
63
|
+
removeProjectUserAction,
|
|
54
64
|
requestEmailChangeAction,
|
|
55
65
|
requestPhoneChangeAction,
|
|
56
66
|
subscriptionsService,
|
package/dist/server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import 'server-only';\r\n\r\n// API Client\r\nexport { ApiClient, api, apiClient } from './infra/api/client';\r\n\r\n// Services\r\nexport { authService } from './modules/auth/services/auth.service';\r\nexport { whitelabelService } from './modules/whitelabel/services/whitelabel.service';\r\nexport { subscriptionsService } from './modules/subscriptions/services/subscriptions.service';\r\nexport { iaCreditsService } from './modules/ia-credits/services/ia-credits.service';\r\n\r\n// Actions\r\nexport { findWhitelabel } from './modules/whitelabel/actions/find-whitelabel.action';\r\nexport { validateSessionAction } from './modules/auth/actions/validate-session.action';\r\nexport { listSubscriptionsAction } from './modules/subscriptions/actions/list-subscriptions.action';\r\nexport { listIaCreditsAction } from './modules/ia-credits/actions/list-ia-credits.action';\r\n\r\n// Account Services & Actions (server-only)\r\nexport { accountService } from './modules/accounts/services/account.service';\r\nexport { twoFactorService } from './modules/accounts/services/two-factor.service';\r\nexport {\r\n listAccountUsersAction,\r\n updateUserAction,\r\n updateAccountAction,\r\n updateAccountUserByIdAction,\r\n deleteAccountUserAction,\r\n deleteAccountAction,\r\n createAccountUserAction,\r\n changePasswordAction,\r\n requestEmailChangeAction,\r\n confirmEmailChangeAction,\r\n requestPhoneChangeAction,\r\n confirmPhoneChangeAction,\r\n generateTwoFactorAction,\r\n confirmTwoFactorAction,\r\n disableTwoFactorAction,\r\n} from './modules/accounts/actions/account-management.action';\r\n\r\n// Server Utils\r\nexport { getClientInfoFromRequest } from './infra/utils/client-info';\r\nexport { getUserContext } from './modules/auth/utils/get-user-context';\r\n"],"mappings":"AAAA,OAAO;AAGP,SAAS,WAAW,KAAK,iBAAiB;AAG1C,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AAGjC,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,2BAA2B;AAGpC,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,gCAAgC;AACzC,SAAS,sBAAsB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import 'server-only';\r\n\r\n// API Client\r\nexport { ApiClient, api, apiClient } from './infra/api/client';\r\n\r\n// Services\r\nexport { authService } from './modules/auth/services/auth.service';\r\nexport { whitelabelService } from './modules/whitelabel/services/whitelabel.service';\r\nexport { subscriptionsService } from './modules/subscriptions/services/subscriptions.service';\r\nexport { iaCreditsService } from './modules/ia-credits/services/ia-credits.service';\r\n\r\n// Actions\r\nexport { findWhitelabel } from './modules/whitelabel/actions/find-whitelabel.action';\r\nexport { validateSessionAction } from './modules/auth/actions/validate-session.action';\r\nexport { listSubscriptionsAction } from './modules/subscriptions/actions/list-subscriptions.action';\r\nexport { listIaCreditsAction } from './modules/ia-credits/actions/list-ia-credits.action';\r\n\r\n// Project Users Services & Actions (server-only)\r\nexport { projectUsersService } from './modules/projects/services/project-users.service';\r\nexport { listProjectUsersAction } from './modules/projects/actions/list-project-users.action';\r\nexport { listAvailableUsersAction } from './modules/projects/actions/list-available-users.action';\r\nexport { addProjectUserAction } from './modules/projects/actions/add-project-user.action';\r\nexport { removeProjectUserAction } from './modules/projects/actions/remove-project-user.action';\r\n\r\n// Account Services & Actions (server-only)\r\nexport { accountService } from './modules/accounts/services/account.service';\r\nexport { twoFactorService } from './modules/accounts/services/two-factor.service';\r\nexport {\r\n listAccountUsersAction,\r\n updateUserAction,\r\n updateAccountAction,\r\n updateAccountUserByIdAction,\r\n deleteAccountUserAction,\r\n deleteAccountAction,\r\n createAccountUserAction,\r\n changePasswordAction,\r\n requestEmailChangeAction,\r\n confirmEmailChangeAction,\r\n requestPhoneChangeAction,\r\n confirmPhoneChangeAction,\r\n generateTwoFactorAction,\r\n confirmTwoFactorAction,\r\n disableTwoFactorAction,\r\n} from './modules/accounts/actions/account-management.action';\r\n\r\n// Server Utils\r\nexport { getClientInfoFromRequest } from './infra/utils/client-info';\r\nexport { getUserContext } from './modules/auth/utils/get-user-context';\r\n"],"mappings":"AAAA,OAAO;AAGP,SAAS,WAAW,KAAK,iBAAiB;AAG1C,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AAGjC,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,2BAA2B;AAGpC,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AACvC,SAAS,gCAAgC;AACzC,SAAS,4BAA4B;AACrC,SAAS,+BAA+B;AAGxC,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,gCAAgC;AACzC,SAAS,sBAAsB;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import { useState } from 'react';
|
|
4
|
-
import { Plus, Settings, User } from 'lucide-react';
|
|
4
|
+
import { Plus, Settings, User, Users } from 'lucide-react';
|
|
5
5
|
import Image from 'next/image';
|
|
6
6
|
import { useRouter } from 'next/navigation';
|
|
7
7
|
import { Popover, PopoverContent, PopoverTrigger } from '../ui/overlay/Popover';
|
|
@@ -10,6 +10,7 @@ import { Command, CommandEmpty, CommandInput, CommandItem, CommandList } from '.
|
|
|
10
10
|
import { Checkbox } from '../ui/form/Checkbox';
|
|
11
11
|
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/overlay/Tooltip';
|
|
12
12
|
import { cn } from '../../infra/utils/clsx';
|
|
13
|
+
import { useProjectUsers } from '../../modules/projects/hooks/project-users.hook';
|
|
13
14
|
|
|
14
15
|
export interface UserSelectorItem {
|
|
15
16
|
id: number;
|
|
@@ -18,7 +19,20 @@ export interface UserSelectorItem {
|
|
|
18
19
|
checked: boolean;
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
function UserItemSkeleton() {
|
|
23
|
+
return (
|
|
24
|
+
<div className="flex items-center justify-between px-2 py-1.5 gap-2">
|
|
25
|
+
<div className="flex items-center gap-2 flex-1">
|
|
26
|
+
<div className="size-8 rounded-full bg-gray-100 animate-pulse shrink-0" />
|
|
27
|
+
<div className="h-3.5 w-28 rounded bg-gray-100 animate-pulse" />
|
|
28
|
+
</div>
|
|
29
|
+
<div className="size-4 rounded bg-gray-100 animate-pulse shrink-0" />
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
21
34
|
export interface UsersSelectorPopoverProps {
|
|
35
|
+
projectId?: number;
|
|
22
36
|
users?: UserSelectorItem[];
|
|
23
37
|
onToggleUser?: (id: number) => void;
|
|
24
38
|
addRoute?: string;
|
|
@@ -29,33 +43,33 @@ export interface UsersSelectorPopoverProps {
|
|
|
29
43
|
contentClassName?: string;
|
|
30
44
|
}
|
|
31
45
|
|
|
32
|
-
|
|
33
|
-
users:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
interface ContentProps {
|
|
47
|
+
users: UserSelectorItem[];
|
|
48
|
+
isLoading: boolean;
|
|
49
|
+
userCount: number;
|
|
50
|
+
toggleUser: (id: number) => void;
|
|
51
|
+
addRoute: string;
|
|
52
|
+
manageRoute: string;
|
|
53
|
+
side?: UsersSelectorPopoverProps['side'];
|
|
54
|
+
align?: UsersSelectorPopoverProps['align'];
|
|
55
|
+
contentClassName?: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function UsersSelectorPopoverContent({
|
|
59
|
+
users,
|
|
60
|
+
isLoading,
|
|
61
|
+
userCount,
|
|
62
|
+
toggleUser,
|
|
63
|
+
addRoute,
|
|
64
|
+
manageRoute,
|
|
38
65
|
side,
|
|
39
66
|
align,
|
|
40
67
|
contentClassName,
|
|
41
|
-
}:
|
|
68
|
+
}: ContentProps) {
|
|
42
69
|
const route = useRouter();
|
|
43
70
|
const [open, setOpen] = useState(false);
|
|
44
|
-
const [internalUsers, setInternalUsers] = useState<UserSelectorItem[]>(externalUsers ?? []);
|
|
45
71
|
const [hoveredId, setHoveredId] = useState<number | null>(null);
|
|
46
72
|
|
|
47
|
-
const users = externalUsers ?? internalUsers;
|
|
48
|
-
|
|
49
|
-
const toggleUser = (id: number) => {
|
|
50
|
-
if (onToggleUser) {
|
|
51
|
-
onToggleUser(id);
|
|
52
|
-
} else {
|
|
53
|
-
setInternalUsers((prev) =>
|
|
54
|
-
prev.map((u) => (u.id === id ? { ...u, checked: !u.checked } : u))
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
73
|
return (
|
|
60
74
|
<Popover open={open} onOpenChange={setOpen}>
|
|
61
75
|
<PopoverTrigger className="cursor-pointer">
|
|
@@ -86,7 +100,6 @@ function UsersSelectorPopover({
|
|
|
86
100
|
<Plus size={16} />
|
|
87
101
|
Adicionar
|
|
88
102
|
</Button>
|
|
89
|
-
|
|
90
103
|
<Tooltip>
|
|
91
104
|
<TooltipTrigger asChild>
|
|
92
105
|
<Button
|
|
@@ -105,48 +118,67 @@ function UsersSelectorPopover({
|
|
|
105
118
|
<Command className="gap-2" value="">
|
|
106
119
|
<CommandInput placeholder="Busque aqui" />
|
|
107
120
|
<CommandList className="custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]">
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
{user.name}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
121
|
+
{isLoading ? (
|
|
122
|
+
<>
|
|
123
|
+
<UserItemSkeleton />
|
|
124
|
+
<UserItemSkeleton />
|
|
125
|
+
<UserItemSkeleton />
|
|
126
|
+
</>
|
|
127
|
+
) : users.length === 0 ? (
|
|
128
|
+
<div className="flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4">
|
|
129
|
+
<Users size={28} className="text-gray-300" />
|
|
130
|
+
<span className="paragraph-small-medium text-center text-gray-500">
|
|
131
|
+
Nenhum usuário neste projeto.
|
|
132
|
+
<br />
|
|
133
|
+
Adicione um usuário para começar.
|
|
134
|
+
</span>
|
|
135
|
+
</div>
|
|
136
|
+
) : (
|
|
137
|
+
<>
|
|
138
|
+
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
|
139
|
+
{users.map((user) => (
|
|
140
|
+
<CommandItem
|
|
141
|
+
key={user.id}
|
|
142
|
+
value={user.name}
|
|
143
|
+
autoFocus={false}
|
|
144
|
+
onPointerEnter={() => setHoveredId(user.id)}
|
|
145
|
+
onPointerLeave={() => setHoveredId(null)}
|
|
146
|
+
onFocus={() => setHoveredId(user.id)}
|
|
147
|
+
onBlur={() => setHoveredId(null)}
|
|
148
|
+
onSelect={() => toggleUser(user.id)}
|
|
149
|
+
className="cursor-pointer"
|
|
150
|
+
>
|
|
151
|
+
<div className="flex items-center justify-between w-full">
|
|
152
|
+
<div className="flex items-center gap-2">
|
|
153
|
+
<Image
|
|
154
|
+
alt="Avatar"
|
|
155
|
+
src={user.avatar}
|
|
156
|
+
width={32}
|
|
157
|
+
height={32}
|
|
158
|
+
className="rounded-full"
|
|
159
|
+
/>
|
|
160
|
+
{user.name}
|
|
161
|
+
</div>
|
|
162
|
+
<Tooltip open={hoveredId === user.id}>
|
|
163
|
+
<TooltipTrigger
|
|
164
|
+
onClick={(e) => e.stopPropagation()}
|
|
165
|
+
onPointerDown={(e) => e.stopPropagation()}
|
|
166
|
+
>
|
|
167
|
+
<Checkbox
|
|
168
|
+
checked={user.checked}
|
|
169
|
+
onCheckedChange={() => toggleUser(user.id)}
|
|
170
|
+
className={hoveredId === user.id ? 'border-gray-950' : ''}
|
|
171
|
+
/>
|
|
172
|
+
</TooltipTrigger>
|
|
173
|
+
<TooltipContent>
|
|
174
|
+
{user.checked ? 'Remover do projeto' : 'Adicionar ao projeto'}
|
|
175
|
+
</TooltipContent>
|
|
176
|
+
</Tooltip>
|
|
177
|
+
</div>
|
|
178
|
+
</CommandItem>
|
|
179
|
+
))}
|
|
180
|
+
</>
|
|
181
|
+
)}
|
|
150
182
|
</CommandList>
|
|
151
183
|
</Command>
|
|
152
184
|
</div>
|
|
@@ -155,4 +187,75 @@ function UsersSelectorPopover({
|
|
|
155
187
|
);
|
|
156
188
|
}
|
|
157
189
|
|
|
190
|
+
function ConnectedUsersSelectorPopover({
|
|
191
|
+
projectId,
|
|
192
|
+
addRoute,
|
|
193
|
+
manageRoute,
|
|
194
|
+
side,
|
|
195
|
+
align,
|
|
196
|
+
contentClassName,
|
|
197
|
+
}: Required<Pick<UsersSelectorPopoverProps, 'projectId'>> &
|
|
198
|
+
Pick<UsersSelectorPopoverProps, 'addRoute' | 'manageRoute' | 'side' | 'align' | 'contentClassName'>) {
|
|
199
|
+
const { users, isLoading, userCount, toggleUser } = useProjectUsers(projectId);
|
|
200
|
+
return (
|
|
201
|
+
<UsersSelectorPopoverContent
|
|
202
|
+
users={users}
|
|
203
|
+
isLoading={isLoading}
|
|
204
|
+
userCount={userCount}
|
|
205
|
+
toggleUser={toggleUser}
|
|
206
|
+
addRoute={addRoute ?? '/my-teams?createNew=true'}
|
|
207
|
+
manageRoute={manageRoute ?? '/my-teams'}
|
|
208
|
+
side={side}
|
|
209
|
+
align={align}
|
|
210
|
+
contentClassName={contentClassName}
|
|
211
|
+
/>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function StaticUsersSelectorPopover({
|
|
216
|
+
users: externalUsers = [],
|
|
217
|
+
onToggleUser,
|
|
218
|
+
userCount = 5,
|
|
219
|
+
addRoute = '/my-teams?createNew=true',
|
|
220
|
+
manageRoute = '/my-teams',
|
|
221
|
+
side,
|
|
222
|
+
align,
|
|
223
|
+
contentClassName,
|
|
224
|
+
}: Omit<UsersSelectorPopoverProps, 'projectId'>) {
|
|
225
|
+
const [internalUsers, setInternalUsers] = useState<UserSelectorItem[]>(externalUsers);
|
|
226
|
+
|
|
227
|
+
const users = externalUsers.length > 0 ? externalUsers : internalUsers;
|
|
228
|
+
|
|
229
|
+
const toggleUser = (id: number) => {
|
|
230
|
+
if (onToggleUser) {
|
|
231
|
+
onToggleUser(id);
|
|
232
|
+
} else {
|
|
233
|
+
setInternalUsers((prev) =>
|
|
234
|
+
prev.map((u) => (u.id === id ? { ...u, checked: !u.checked } : u))
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
return (
|
|
240
|
+
<UsersSelectorPopoverContent
|
|
241
|
+
users={users}
|
|
242
|
+
isLoading={false}
|
|
243
|
+
userCount={userCount}
|
|
244
|
+
toggleUser={toggleUser}
|
|
245
|
+
addRoute={addRoute}
|
|
246
|
+
manageRoute={manageRoute}
|
|
247
|
+
side={side}
|
|
248
|
+
align={align}
|
|
249
|
+
contentClassName={contentClassName}
|
|
250
|
+
/>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function UsersSelectorPopover(props: UsersSelectorPopoverProps) {
|
|
255
|
+
if (props.projectId != null) {
|
|
256
|
+
return <ConnectedUsersSelectorPopover {...props} projectId={props.projectId} />;
|
|
257
|
+
}
|
|
258
|
+
return <StaticUsersSelectorPopover {...props} />;
|
|
259
|
+
}
|
|
260
|
+
|
|
158
261
|
export { UsersSelectorPopover };
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,8 @@ export * from './providers/auth.provider';
|
|
|
10
10
|
export * from './providers/whitelabel.provider';
|
|
11
11
|
|
|
12
12
|
// Hooks
|
|
13
|
+
export { useProjectUsers, projectUsersQueryKey } from './modules/projects/hooks/project-users.hook';
|
|
14
|
+
export type { ProjectUser, AccountUser, AddRemoveProjectUsersParams } from './modules/projects/types';
|
|
13
15
|
export { useUserQuery, useUserValidateSession, useInvalidateUser, useSetUserData, USER_QUERY_KEY } from './modules/auth/hooks/useUserQuery';
|
|
14
16
|
export { useSubscriptions, SUBSCRIPTIONS_QUERY_KEY } from './modules/subscriptions/hooks/list-subscriptions.hook';
|
|
15
17
|
export { useActiveSubscription } from './modules/subscriptions/hooks/find-active-subscription.hook';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { projectUsersService } from '../services/project-users.service';
|
|
4
|
+
import type { AddRemoveProjectUsersParams } from '../types';
|
|
5
|
+
|
|
6
|
+
export async function addProjectUserAction(params: AddRemoveProjectUsersParams): Promise<void> {
|
|
7
|
+
return projectUsersService.addToProject(params);
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { projectUsersService } from '../services/project-users.service';
|
|
4
|
+
import type { AccountUser } from '../types';
|
|
5
|
+
|
|
6
|
+
export async function listAvailableUsersAction(id_project: number): Promise<AccountUser[]> {
|
|
7
|
+
return projectUsersService.listNotInProject(id_project);
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { projectUsersService } from '../services/project-users.service';
|
|
4
|
+
import type { ProjectUser } from '../types';
|
|
5
|
+
|
|
6
|
+
export async function listProjectUsersAction(id_project: number): Promise<ProjectUser[]> {
|
|
7
|
+
return projectUsersService.listInProject(id_project);
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { projectUsersService } from '../services/project-users.service';
|
|
4
|
+
import type { AddRemoveProjectUsersParams } from '../types';
|
|
5
|
+
|
|
6
|
+
export async function removeProjectUserAction(params: AddRemoveProjectUsersParams): Promise<void> {
|
|
7
|
+
return projectUsersService.removeFromProject(params);
|
|
8
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
5
|
+
|
|
6
|
+
import type { UserSelectorItem } from '../../../components/layouts/UsersSelectorPopover';
|
|
7
|
+
import { addProjectUserAction } from '../actions/add-project-user.action';
|
|
8
|
+
import { listAvailableUsersAction } from '../actions/list-available-users.action';
|
|
9
|
+
import { listProjectUsersAction } from '../actions/list-project-users.action';
|
|
10
|
+
import { removeProjectUserAction } from '../actions/remove-project-user.action';
|
|
11
|
+
|
|
12
|
+
const DEFAULT_AVATAR = '/images/Logomark.png';
|
|
13
|
+
|
|
14
|
+
export const projectUsersQueryKey = (id_project: number) => ['project-users', id_project];
|
|
15
|
+
|
|
16
|
+
export function useProjectUsers(id_project: number) {
|
|
17
|
+
const queryClient = useQueryClient();
|
|
18
|
+
|
|
19
|
+
const { data: inProject = [], isLoading: isLoadingIn } = useQuery({
|
|
20
|
+
queryKey: [...projectUsersQueryKey(id_project), 'in'],
|
|
21
|
+
queryFn: () => listProjectUsersAction(id_project),
|
|
22
|
+
enabled: !!id_project,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const { data: notInProject = [], isLoading: isLoadingOut } = useQuery({
|
|
26
|
+
queryKey: [...projectUsersQueryKey(id_project), 'out'],
|
|
27
|
+
queryFn: () => listAvailableUsersAction(id_project),
|
|
28
|
+
enabled: !!id_project,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const invalidate = () => {
|
|
32
|
+
queryClient.invalidateQueries({ queryKey: projectUsersQueryKey(id_project) });
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const addMutation = useMutation({
|
|
36
|
+
mutationFn: (user_id: number) =>
|
|
37
|
+
addProjectUserAction({ id_project, users: [user_id] }),
|
|
38
|
+
onSuccess: invalidate,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const removeMutation = useMutation({
|
|
42
|
+
mutationFn: (user_id: number) =>
|
|
43
|
+
removeProjectUserAction({ id_project, users: [user_id] }),
|
|
44
|
+
onSuccess: invalidate,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const users: UserSelectorItem[] = useMemo(
|
|
48
|
+
() => [
|
|
49
|
+
...inProject.map((u) => ({
|
|
50
|
+
id: u.id_user,
|
|
51
|
+
name: u.name,
|
|
52
|
+
avatar: u.photo ?? DEFAULT_AVATAR,
|
|
53
|
+
checked: true,
|
|
54
|
+
})),
|
|
55
|
+
...notInProject.map((u) => ({
|
|
56
|
+
id: u.id,
|
|
57
|
+
name: u.name,
|
|
58
|
+
avatar: u.photo ?? DEFAULT_AVATAR,
|
|
59
|
+
checked: false,
|
|
60
|
+
})),
|
|
61
|
+
],
|
|
62
|
+
[inProject, notInProject]
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const toggleUser = (id: number) => {
|
|
66
|
+
const user = users.find((u) => u.id === id);
|
|
67
|
+
if (!user) return;
|
|
68
|
+
if (user.checked) {
|
|
69
|
+
removeMutation.mutate(id);
|
|
70
|
+
} else {
|
|
71
|
+
addMutation.mutate(id);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
users,
|
|
77
|
+
isLoading: isLoadingIn || isLoadingOut,
|
|
78
|
+
userCount: inProject.length,
|
|
79
|
+
toggleUser,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
|
|
3
|
+
import { api } from '../../../infra/api/client';
|
|
4
|
+
import { ApiError } from '../../../infra/api/types';
|
|
5
|
+
import { getUserContext } from '../../auth/utils/get-user-context';
|
|
6
|
+
import {
|
|
7
|
+
AccountUser,
|
|
8
|
+
AccountUserSchema,
|
|
9
|
+
AddRemoveProjectUsersParams,
|
|
10
|
+
ProjectUser,
|
|
11
|
+
ProjectUserSchema,
|
|
12
|
+
} from '../types';
|
|
13
|
+
|
|
14
|
+
interface ApiListResponse<T> {
|
|
15
|
+
data: T[];
|
|
16
|
+
total: number;
|
|
17
|
+
status: number;
|
|
18
|
+
message?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ApiActionResponse {
|
|
22
|
+
status: number;
|
|
23
|
+
message?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class ProjectUsersService {
|
|
27
|
+
async listInProject(id_project: number): Promise<ProjectUser[]> {
|
|
28
|
+
const { id_account, id_user } = await getUserContext();
|
|
29
|
+
const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
|
|
30
|
+
|
|
31
|
+
const response = await api.pages.get<ApiListResponse<ProjectUser>>(url);
|
|
32
|
+
|
|
33
|
+
if (response.status === 0) {
|
|
34
|
+
throw new ApiError(
|
|
35
|
+
response.message || 'Erro ao listar usuários do projeto',
|
|
36
|
+
'LIST_PROJECT_USERS_FAILED',
|
|
37
|
+
400
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return response.data.map((item) => ProjectUserSchema.parse(item));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async listNotInProject(id_project: number): Promise<AccountUser[]> {
|
|
45
|
+
const { id_account } = await getUserContext();
|
|
46
|
+
const url = `/accounts/${id_account}/users?notInProject=${id_project}`;
|
|
47
|
+
|
|
48
|
+
const response = await api.apps.get<ApiListResponse<AccountUser>>(url);
|
|
49
|
+
|
|
50
|
+
if (response.status === 0) {
|
|
51
|
+
throw new ApiError(
|
|
52
|
+
response.message || 'Erro ao listar usuários disponíveis',
|
|
53
|
+
'LIST_AVAILABLE_USERS_FAILED',
|
|
54
|
+
400
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return response.data.map((item) => AccountUserSchema.parse(item));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async addToProject({ id_project, users }: AddRemoveProjectUsersParams): Promise<void> {
|
|
62
|
+
const { id_account, id_user } = await getUserContext();
|
|
63
|
+
const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
|
|
64
|
+
|
|
65
|
+
const response = await api.pages.post<ApiActionResponse>(url, { users });
|
|
66
|
+
|
|
67
|
+
if (response.status === 0) {
|
|
68
|
+
throw new ApiError(
|
|
69
|
+
response.message || 'Erro ao adicionar usuário ao projeto',
|
|
70
|
+
'ADD_PROJECT_USER_FAILED',
|
|
71
|
+
400
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async removeFromProject({ id_project, users }: AddRemoveProjectUsersParams): Promise<void> {
|
|
77
|
+
const { id_account, id_user } = await getUserContext();
|
|
78
|
+
const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
|
|
79
|
+
|
|
80
|
+
const response = await api.pages.delete<ApiActionResponse>(url, {
|
|
81
|
+
body: JSON.stringify({ users }),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
if (response.status === 0) {
|
|
85
|
+
throw new ApiError(
|
|
86
|
+
response.message || 'Erro ao remover usuário do projeto',
|
|
87
|
+
'REMOVE_PROJECT_USER_FAILED',
|
|
88
|
+
400
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const projectUsersService = new ProjectUsersService();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const ProjectUserSchema = z.object({
|
|
4
|
+
id_user: z.union([z.number(), z.string()]).transform(Number),
|
|
5
|
+
id_account: z.union([z.number(), z.string()]).transform(Number),
|
|
6
|
+
id_project: z.union([z.number(), z.string()]).transform(Number),
|
|
7
|
+
name: z.string(),
|
|
8
|
+
email: z.string(),
|
|
9
|
+
profile: z.string().optional(),
|
|
10
|
+
photo: z.string().nullable().optional(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export type ProjectUser = z.infer<typeof ProjectUserSchema>;
|
|
14
|
+
|
|
15
|
+
export const AccountUserSchema = z.object({
|
|
16
|
+
id: z.union([z.number(), z.string()]).transform(Number),
|
|
17
|
+
name: z.string(),
|
|
18
|
+
email: z.string(),
|
|
19
|
+
profile: z.string().optional(),
|
|
20
|
+
photo: z.string().nullable().optional(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export type AccountUser = z.infer<typeof AccountUserSchema>;
|
|
24
|
+
|
|
25
|
+
export interface AddRemoveProjectUsersParams {
|
|
26
|
+
id_project: number;
|
|
27
|
+
users: number[];
|
|
28
|
+
}
|
package/src/server.ts
CHANGED
|
@@ -15,6 +15,13 @@ export { validateSessionAction } from './modules/auth/actions/validate-session.a
|
|
|
15
15
|
export { listSubscriptionsAction } from './modules/subscriptions/actions/list-subscriptions.action';
|
|
16
16
|
export { listIaCreditsAction } from './modules/ia-credits/actions/list-ia-credits.action';
|
|
17
17
|
|
|
18
|
+
// Project Users Services & Actions (server-only)
|
|
19
|
+
export { projectUsersService } from './modules/projects/services/project-users.service';
|
|
20
|
+
export { listProjectUsersAction } from './modules/projects/actions/list-project-users.action';
|
|
21
|
+
export { listAvailableUsersAction } from './modules/projects/actions/list-available-users.action';
|
|
22
|
+
export { addProjectUserAction } from './modules/projects/actions/add-project-user.action';
|
|
23
|
+
export { removeProjectUserAction } from './modules/projects/actions/remove-project-user.action';
|
|
24
|
+
|
|
18
25
|
// Account Services & Actions (server-only)
|
|
19
26
|
export { accountService } from './modules/accounts/services/account.service';
|
|
20
27
|
export { twoFactorService } from './modules/accounts/services/two-factor.service';
|