@greatapps/common 1.1.48 → 1.1.50

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.
@@ -1,7 +1,7 @@
1
1
  "use client";
2
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";
@@ -85,7 +85,14 @@ function UsersSelectorPopoverContent({
85
85
  /* @__PURE__ */ jsx(UserItemSkeleton, {}),
86
86
  /* @__PURE__ */ jsx(UserItemSkeleton, {}),
87
87
  /* @__PURE__ */ jsx(UserItemSkeleton, {})
88
- ] }) : users.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsx("span", { className: "paragraph-small-medium text-center text-gray-500", children: "Nenhum usu\xE1rio encontrado." }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
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: [
89
96
  /* @__PURE__ */ jsx(CommandEmpty, { children: "Nenhum resultado encontrado." }),
90
97
  users.map((user) => /* @__PURE__ */ jsx(
91
98
  CommandItem,
@@ -142,14 +149,14 @@ function UsersSelectorPopoverContent({
142
149
  ] });
143
150
  }
144
151
  function ConnectedUsersSelectorPopover({
145
- id_project,
152
+ projectId,
146
153
  addRoute,
147
154
  manageRoute,
148
155
  side,
149
156
  align,
150
157
  contentClassName
151
158
  }) {
152
- const { users, isLoading, userCount, toggleUser } = useProjectUsers(id_project);
159
+ const { users, isLoading, userCount, toggleUser } = useProjectUsers(projectId);
153
160
  return /* @__PURE__ */ jsx(
154
161
  UsersSelectorPopoverContent,
155
162
  {
@@ -202,8 +209,8 @@ function StaticUsersSelectorPopover({
202
209
  );
203
210
  }
204
211
  function UsersSelectorPopover(props) {
205
- if (props.id_project != null) {
206
- return /* @__PURE__ */ jsx(ConnectedUsersSelectorPopover, { ...props, id_project: props.id_project });
212
+ if (props.projectId != null) {
213
+ return /* @__PURE__ */ jsx(ConnectedUsersSelectorPopover, { ...props, projectId: props.projectId });
207
214
  }
208
215
  return /* @__PURE__ */ jsx(StaticUsersSelectorPopover, { ...props });
209
216
  }
@@ -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\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 id_project?: 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 items-center justify-center h-full\">\r\n <span className=\"paragraph-small-medium text-center text-gray-500\">\r\n Nenhum usuário encontrado.\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 id_project,\r\n addRoute,\r\n manageRoute,\r\n side,\r\n align,\r\n contentClassName,\r\n}: Required<Pick<UsersSelectorPopoverProps, 'id_project'>> &\r\n Pick<UsersSelectorPopoverProps, 'addRoute' | 'manageRoute' | 'side' | 'align' | 'contentClassName'>) {\r\n const { users, isLoading, userCount, toggleUser } = useProjectUsers(id_project);\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, 'id_project'>) {\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.id_project != null) {\r\n return <ConnectedUsersSelectorPopover {...props} id_project={props.id_project} />;\r\n }\r\n return <StaticUsersSelectorPopover {...props} />;\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":[]}
@@ -10,7 +10,7 @@ class ProjectUsersService {
10
10
  async listInProject(id_project) {
11
11
  const { id_account, id_user } = await getUserContext();
12
12
  const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
13
- const response = await api.pages.get(url);
13
+ const response = await api.apps.get(url);
14
14
  if (response.status === 0) {
15
15
  throw new ApiError(
16
16
  response.message || "Erro ao listar usu\xE1rios do projeto",
@@ -36,7 +36,7 @@ class ProjectUsersService {
36
36
  async addToProject({ id_project, users }) {
37
37
  const { id_account, id_user } = await getUserContext();
38
38
  const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
39
- const response = await api.pages.post(url, { users });
39
+ const response = await api.apps.post(url, { users });
40
40
  if (response.status === 0) {
41
41
  throw new ApiError(
42
42
  response.message || "Erro ao adicionar usu\xE1rio ao projeto",
@@ -48,7 +48,7 @@ class ProjectUsersService {
48
48
  async removeFromProject({ id_project, users }) {
49
49
  const { id_account, id_user } = await getUserContext();
50
50
  const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
51
- const response = await api.pages.delete(url, {
51
+ const response = await api.apps.delete(url, {
52
52
  body: JSON.stringify({ users })
53
53
  });
54
54
  if (response.status === 0) {
@@ -1 +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":[]}
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.apps.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.apps.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.apps.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,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,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,KAAK,KAAwB,KAAK,EAAE,MAAM,CAAC;AAEtE,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,KAAK,OAA0B,KAAK;AAAA,MAC7D,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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.48",
3
+ "version": "1.1.50",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -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';
@@ -32,7 +32,7 @@ function UserItemSkeleton() {
32
32
  }
33
33
 
34
34
  export interface UsersSelectorPopoverProps {
35
- id_project?: number;
35
+ projectId?: number;
36
36
  users?: UserSelectorItem[];
37
37
  onToggleUser?: (id: number) => void;
38
38
  addRoute?: string;
@@ -125,9 +125,12 @@ function UsersSelectorPopoverContent({
125
125
  <UserItemSkeleton />
126
126
  </>
127
127
  ) : users.length === 0 ? (
128
- <div className="flex items-center justify-center h-full">
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" />
129
130
  <span className="paragraph-small-medium text-center text-gray-500">
130
- Nenhum usuário encontrado.
131
+ Nenhum usuário neste projeto.
132
+ <br />
133
+ Adicione um usuário para começar.
131
134
  </span>
132
135
  </div>
133
136
  ) : (
@@ -185,15 +188,15 @@ function UsersSelectorPopoverContent({
185
188
  }
186
189
 
187
190
  function ConnectedUsersSelectorPopover({
188
- id_project,
191
+ projectId,
189
192
  addRoute,
190
193
  manageRoute,
191
194
  side,
192
195
  align,
193
196
  contentClassName,
194
- }: Required<Pick<UsersSelectorPopoverProps, 'id_project'>> &
197
+ }: Required<Pick<UsersSelectorPopoverProps, 'projectId'>> &
195
198
  Pick<UsersSelectorPopoverProps, 'addRoute' | 'manageRoute' | 'side' | 'align' | 'contentClassName'>) {
196
- const { users, isLoading, userCount, toggleUser } = useProjectUsers(id_project);
199
+ const { users, isLoading, userCount, toggleUser } = useProjectUsers(projectId);
197
200
  return (
198
201
  <UsersSelectorPopoverContent
199
202
  users={users}
@@ -218,7 +221,7 @@ function StaticUsersSelectorPopover({
218
221
  side,
219
222
  align,
220
223
  contentClassName,
221
- }: Omit<UsersSelectorPopoverProps, 'id_project'>) {
224
+ }: Omit<UsersSelectorPopoverProps, 'projectId'>) {
222
225
  const [internalUsers, setInternalUsers] = useState<UserSelectorItem[]>(externalUsers);
223
226
 
224
227
  const users = externalUsers.length > 0 ? externalUsers : internalUsers;
@@ -249,8 +252,8 @@ function StaticUsersSelectorPopover({
249
252
  }
250
253
 
251
254
  function UsersSelectorPopover(props: UsersSelectorPopoverProps) {
252
- if (props.id_project != null) {
253
- return <ConnectedUsersSelectorPopover {...props} id_project={props.id_project} />;
255
+ if (props.projectId != null) {
256
+ return <ConnectedUsersSelectorPopover {...props} projectId={props.projectId} />;
254
257
  }
255
258
  return <StaticUsersSelectorPopover {...props} />;
256
259
  }
@@ -28,7 +28,7 @@ class ProjectUsersService {
28
28
  const { id_account, id_user } = await getUserContext();
29
29
  const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
30
30
 
31
- const response = await api.pages.get<ApiListResponse<ProjectUser>>(url);
31
+ const response = await api.apps.get<ApiListResponse<ProjectUser>>(url);
32
32
 
33
33
  if (response.status === 0) {
34
34
  throw new ApiError(
@@ -62,7 +62,7 @@ class ProjectUsersService {
62
62
  const { id_account, id_user } = await getUserContext();
63
63
  const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
64
64
 
65
- const response = await api.pages.post<ApiActionResponse>(url, { users });
65
+ const response = await api.apps.post<ApiActionResponse>(url, { users });
66
66
 
67
67
  if (response.status === 0) {
68
68
  throw new ApiError(
@@ -77,7 +77,7 @@ class ProjectUsersService {
77
77
  const { id_account, id_user } = await getUserContext();
78
78
  const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
79
79
 
80
- const response = await api.pages.delete<ApiActionResponse>(url, {
80
+ const response = await api.apps.delete<ApiActionResponse>(url, {
81
81
  body: JSON.stringify({ users }),
82
82
  });
83
83