@greatapps/common 1.1.49 → 1.1.51

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.
Files changed (27) hide show
  1. package/dist/components/layouts/UsersSelectorPopover.mjs +155 -139
  2. package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
  3. package/dist/index.mjs +8 -3
  4. package/dist/index.mjs.map +1 -1
  5. package/dist/modules/projects/actions/list-available-users.action.mjs +2 -2
  6. package/dist/modules/projects/actions/list-available-users.action.mjs.map +1 -1
  7. package/dist/modules/projects/actions/list-project-users.action.mjs +2 -2
  8. package/dist/modules/projects/actions/list-project-users.action.mjs.map +1 -1
  9. package/dist/modules/projects/hooks/list-available-users.hook.mjs +27 -0
  10. package/dist/modules/projects/hooks/list-available-users.hook.mjs.map +1 -0
  11. package/dist/modules/projects/hooks/list-project-users.hook.mjs +27 -0
  12. package/dist/modules/projects/hooks/list-project-users.hook.mjs.map +1 -0
  13. package/dist/modules/projects/services/project-users.service.mjs +24 -13
  14. package/dist/modules/projects/services/project-users.service.mjs.map +1 -1
  15. package/dist/modules/projects/types.mjs.map +1 -1
  16. package/package.json +1 -1
  17. package/src/components/layouts/UsersSelectorPopover.tsx +119 -126
  18. package/src/index.ts +4 -3
  19. package/src/modules/projects/actions/list-available-users.action.ts +3 -3
  20. package/src/modules/projects/actions/list-project-users.action.ts +3 -3
  21. package/src/modules/projects/hooks/list-available-users.hook.ts +26 -0
  22. package/src/modules/projects/hooks/list-project-users.hook.ts +26 -0
  23. package/src/modules/projects/services/project-users.service.ts +26 -13
  24. package/src/modules/projects/types.ts +13 -1
  25. package/dist/modules/projects/hooks/project-users.hook.mjs +0 -70
  26. package/dist/modules/projects/hooks/project-users.hook.mjs.map +0 -1
  27. package/src/modules/projects/hooks/project-users.hook.ts +0 -81
@@ -2,13 +2,16 @@ import 'server-only';
2
2
 
3
3
  import { api } from '../../../infra/api/client';
4
4
  import { ApiError } from '../../../infra/api/types';
5
+ import { buildQueryParams } from '../../../infra/utils/params';
5
6
  import { getUserContext } from '../../auth/utils/get-user-context';
6
7
  import {
7
8
  AccountUser,
8
9
  AccountUserSchema,
9
10
  AddRemoveProjectUsersParams,
11
+ ListUsersParams,
10
12
  ProjectUser,
11
13
  ProjectUserSchema,
14
+ UsersPage,
12
15
  } from '../types';
13
16
 
14
17
  interface ApiListResponse<T> {
@@ -24,11 +27,12 @@ interface ApiActionResponse {
24
27
  }
25
28
 
26
29
  class ProjectUsersService {
27
- async listInProject(id_project: number): Promise<ProjectUser[]> {
30
+ async listInProject(projectId: number, params: ListUsersParams = {}): Promise<UsersPage<ProjectUser>> {
28
31
  const { id_account, id_user } = await getUserContext();
29
- const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
32
+ const query = buildQueryParams(params as Record<string, string | number | boolean | undefined>);
33
+ const url = `/account/${id_account}/user/${id_user}/projects/${projectId}/users${query ? `?${query}` : ''}`;
30
34
 
31
- const response = await api.pages.get<ApiListResponse<ProjectUser>>(url);
35
+ const response = await api.apps.get<ApiListResponse<ProjectUser>>(url);
32
36
 
33
37
  if (response.status === 0) {
34
38
  throw new ApiError(
@@ -38,12 +42,17 @@ class ProjectUsersService {
38
42
  );
39
43
  }
40
44
 
41
- return response.data.map((item) => ProjectUserSchema.parse(item));
45
+ return {
46
+ data: response.data.map((item) => ProjectUserSchema.parse(item)),
47
+ total: response.total,
48
+ page: params.page ?? 1,
49
+ };
42
50
  }
43
51
 
44
- async listNotInProject(id_project: number): Promise<AccountUser[]> {
52
+ async listNotInProject(projectId: number, params: ListUsersParams = {}): Promise<UsersPage<AccountUser>> {
45
53
  const { id_account } = await getUserContext();
46
- const url = `/accounts/${id_account}/users?notInProject=${id_project}`;
54
+ const query = buildQueryParams({ notInProject: projectId, ...params } as Record<string, string | number | boolean | undefined>);
55
+ const url = `/accounts/${id_account}/users${query ? `?${query}` : ''}`;
47
56
 
48
57
  const response = await api.apps.get<ApiListResponse<AccountUser>>(url);
49
58
 
@@ -55,14 +64,18 @@ class ProjectUsersService {
55
64
  );
56
65
  }
57
66
 
58
- return response.data.map((item) => AccountUserSchema.parse(item));
67
+ return {
68
+ data: response.data.map((item) => AccountUserSchema.parse(item)),
69
+ total: response.total,
70
+ page: params.page ?? 1,
71
+ };
59
72
  }
60
73
 
61
- async addToProject({ id_project, users }: AddRemoveProjectUsersParams): Promise<void> {
74
+ async addToProject({ projectId, users }: AddRemoveProjectUsersParams): Promise<void> {
62
75
  const { id_account, id_user } = await getUserContext();
63
- const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
76
+ const url = `/account/${id_account}/user/${id_user}/projects/${projectId}/users`;
64
77
 
65
- const response = await api.pages.post<ApiActionResponse>(url, { users });
78
+ const response = await api.apps.post<ApiActionResponse>(url, { users });
66
79
 
67
80
  if (response.status === 0) {
68
81
  throw new ApiError(
@@ -73,11 +86,11 @@ class ProjectUsersService {
73
86
  }
74
87
  }
75
88
 
76
- async removeFromProject({ id_project, users }: AddRemoveProjectUsersParams): Promise<void> {
89
+ async removeFromProject({ projectId, users }: AddRemoveProjectUsersParams): Promise<void> {
77
90
  const { id_account, id_user } = await getUserContext();
78
- const url = `/account/${id_account}/user/${id_user}/projects/${id_project}/users`;
91
+ const url = `/account/${id_account}/user/${id_user}/projects/${projectId}/users`;
79
92
 
80
- const response = await api.pages.delete<ApiActionResponse>(url, {
93
+ const response = await api.apps.delete<ApiActionResponse>(url, {
81
94
  body: JSON.stringify({ users }),
82
95
  });
83
96
 
@@ -23,6 +23,18 @@ export const AccountUserSchema = z.object({
23
23
  export type AccountUser = z.infer<typeof AccountUserSchema>;
24
24
 
25
25
  export interface AddRemoveProjectUsersParams {
26
- id_project: number;
26
+ projectId: number;
27
27
  users: number[];
28
28
  }
29
+
30
+ export interface ListUsersParams {
31
+ search?: string;
32
+ page?: number;
33
+ limit?: number;
34
+ }
35
+
36
+ export interface UsersPage<T> {
37
+ data: T[];
38
+ total: number;
39
+ page: number;
40
+ }
@@ -1,70 +0,0 @@
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
@@ -1 +0,0 @@
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":[]}
@@ -1,81 +0,0 @@
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
- }