@greatapps/common 1.1.494 → 1.1.495
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/navigation/ProjectSelectorPopover.mjs +0 -1
- package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
- package/dist/components/navigation/subcomponents/ProjectSelector.mjs +10 -11
- package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
- package/dist/index.mjs +22 -0
- package/dist/index.mjs.map +1 -1
- package/dist/modules/projects/actions/create-project.action.mjs +10 -0
- package/dist/modules/projects/actions/create-project.action.mjs.map +1 -0
- package/dist/modules/projects/actions/delete-project.action.mjs +10 -0
- package/dist/modules/projects/actions/delete-project.action.mjs.map +1 -0
- package/dist/modules/projects/actions/list-projects.action.mjs +10 -0
- package/dist/modules/projects/actions/list-projects.action.mjs.map +1 -0
- package/dist/modules/projects/actions/update-project.action.mjs +10 -0
- package/dist/modules/projects/actions/update-project.action.mjs.map +1 -0
- package/dist/modules/projects/hooks/create-project.hook.mjs +20 -0
- package/dist/modules/projects/hooks/create-project.hook.mjs.map +1 -0
- package/dist/modules/projects/hooks/delete-project.hook.mjs +20 -0
- package/dist/modules/projects/hooks/delete-project.hook.mjs.map +1 -0
- package/dist/modules/projects/hooks/list-infinite-projects.hook.mjs +38 -0
- package/dist/modules/projects/hooks/list-infinite-projects.hook.mjs.map +1 -0
- package/dist/modules/projects/hooks/list-projects.hook.mjs +22 -0
- package/dist/modules/projects/hooks/list-projects.hook.mjs.map +1 -0
- package/dist/modules/projects/hooks/update-project.hook.mjs +20 -0
- package/dist/modules/projects/hooks/update-project.hook.mjs.map +1 -0
- package/dist/modules/projects/services/projects.service.mjs +83 -0
- package/dist/modules/projects/services/projects.service.mjs.map +1 -0
- package/dist/modules/projects/types.mjs +15 -0
- package/dist/modules/projects/types.mjs.map +1 -1
- package/dist/server.mjs +10 -0
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/navigation/ProjectSelectorPopover.tsx +5 -7
- package/src/components/navigation/subcomponents/ProjectSelector.tsx +14 -19
- package/src/index.ts +18 -1
- package/src/modules/projects/actions/create-project.action.ts +9 -0
- package/src/modules/projects/actions/delete-project.action.ts +8 -0
- package/src/modules/projects/actions/list-projects.action.ts +16 -0
- package/src/modules/projects/actions/update-project.action.ts +9 -0
- package/src/modules/projects/hooks/create-project.hook.ts +21 -0
- package/src/modules/projects/hooks/delete-project.hook.ts +20 -0
- package/src/modules/projects/hooks/list-infinite-projects.hook.ts +42 -0
- package/src/modules/projects/hooks/list-projects.hook.ts +23 -0
- package/src/modules/projects/hooks/update-project.hook.ts +21 -0
- package/src/modules/projects/services/projects.service.ts +123 -0
- package/src/modules/projects/types.ts +46 -0
- package/src/server.ts +7 -0
- package/dist/components/navigation/types.mjs +0 -1
- package/dist/components/navigation/types.mjs.map +0 -1
- package/src/components/navigation/types.ts +0 -6
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import "server-only";
|
|
2
|
+
import { api } from "../../../infra/api/client";
|
|
3
|
+
import { ApiError } from "../../../infra/api/types";
|
|
4
|
+
import { buildQueryParams } from "../../../infra/utils/params";
|
|
5
|
+
import { getUserContext } from "../../auth/utils/get-user-context";
|
|
6
|
+
import { assertManagementSubscription } from "../../auth/utils/assert-management-subscription";
|
|
7
|
+
import {
|
|
8
|
+
ProjectSchema
|
|
9
|
+
} from "../types";
|
|
10
|
+
class ProjectsService {
|
|
11
|
+
async list(params = {}) {
|
|
12
|
+
const { id_account, id_user } = await getUserContext();
|
|
13
|
+
const query = buildQueryParams(params);
|
|
14
|
+
const url = `/account/${id_account}/user/${id_user}/projects${query ? `?${query}` : ""}`;
|
|
15
|
+
const response = await api.apps.get(url);
|
|
16
|
+
if (response.status === 0) {
|
|
17
|
+
throw new ApiError(
|
|
18
|
+
response.message || "Erro ao listar projetos",
|
|
19
|
+
"LIST_PROJECTS_FAILED",
|
|
20
|
+
400
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
data: (response.data || []).map((item) => ProjectSchema.parse(item)),
|
|
25
|
+
total: response.total || 0,
|
|
26
|
+
page: params.page ?? 1
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async create(data) {
|
|
30
|
+
await assertManagementSubscription();
|
|
31
|
+
const { id_account, id_user } = await getUserContext();
|
|
32
|
+
const url = `/account/${id_account}/user/${id_user}/projects`;
|
|
33
|
+
const response = await api.apps.post(url, data);
|
|
34
|
+
if (response.status === 0) {
|
|
35
|
+
throw new ApiError(
|
|
36
|
+
response.message || "Erro ao criar projeto",
|
|
37
|
+
"CREATE_PROJECT_FAILED",
|
|
38
|
+
400
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
if (!response.data || response.data.length === 0) {
|
|
42
|
+
throw new ApiError("Resposta inv\xE1lida ao criar projeto", "INVALID_RESPONSE", 500);
|
|
43
|
+
}
|
|
44
|
+
return ProjectSchema.parse(response.data[0]);
|
|
45
|
+
}
|
|
46
|
+
async update(projectId, data) {
|
|
47
|
+
await assertManagementSubscription();
|
|
48
|
+
const { id_account, id_user } = await getUserContext();
|
|
49
|
+
const url = `/account/${id_account}/user/${id_user}/projects/${projectId}`;
|
|
50
|
+
const response = await api.apps.put(url, data);
|
|
51
|
+
if (response.status === 0) {
|
|
52
|
+
throw new ApiError(
|
|
53
|
+
response.message || "Erro ao atualizar projeto",
|
|
54
|
+
"UPDATE_PROJECT_FAILED",
|
|
55
|
+
400
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
if (!response.data || response.data.length === 0) {
|
|
59
|
+
throw new ApiError("Resposta inv\xE1lida ao atualizar projeto", "INVALID_RESPONSE", 500);
|
|
60
|
+
}
|
|
61
|
+
return ProjectSchema.parse(response.data[0]);
|
|
62
|
+
}
|
|
63
|
+
async delete(projectId, moveToProjectId) {
|
|
64
|
+
await assertManagementSubscription();
|
|
65
|
+
const { id_account, id_user } = await getUserContext();
|
|
66
|
+
const url = `/account/${id_account}/user/${id_user}/projects/${projectId}`;
|
|
67
|
+
const response = await api.apps.delete(url, {
|
|
68
|
+
body: JSON.stringify({ id_project_to_move: moveToProjectId })
|
|
69
|
+
});
|
|
70
|
+
if (response.status === 0) {
|
|
71
|
+
throw new ApiError(
|
|
72
|
+
response.message || "Erro ao deletar projeto",
|
|
73
|
+
"DELETE_PROJECT_FAILED",
|
|
74
|
+
400
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const projectsService = new ProjectsService();
|
|
80
|
+
export {
|
|
81
|
+
projectsService
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=projects.service.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/projects/services/projects.service.ts"],"sourcesContent":["import 'server-only';\n\nimport { api } from '../../../infra/api/client';\nimport { ApiError } from '../../../infra/api/types';\nimport { buildQueryParams } from '../../../infra/utils/params';\nimport { getUserContext } from '../../auth/utils/get-user-context';\nimport { assertManagementSubscription } from '../../auth/utils/assert-management-subscription';\nimport {\n Project,\n ProjectSchema,\n ProjectsPage,\n CreateProjectRequest,\n UpdateProjectRequest,\n} from '../types';\n\ninterface ApiListResponse<T> {\n data: T[];\n total: number;\n status: number;\n message?: string;\n}\n\ninterface ApiMutationResponse {\n status: number;\n message?: string;\n data?: Project[];\n}\n\ninterface ListProjectsParams {\n page?: number;\n limit?: number;\n sort?: string;\n search?: string;\n deleted?: number;\n}\n\nclass ProjectsService {\n async list(params: ListProjectsParams = {}): Promise<ProjectsPage> {\n const { id_account, id_user } = await getUserContext();\n const query = buildQueryParams(params as Record<string, string | number | boolean | undefined>);\n const url = `/account/${id_account}/user/${id_user}/projects${query ? `?${query}` : ''}`;\n\n const response = await api.apps.get<ApiListResponse<Project>>(url);\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao listar projetos',\n 'LIST_PROJECTS_FAILED',\n 400\n );\n }\n\n return {\n data: (response.data || []).map((item) => ProjectSchema.parse(item)),\n total: response.total || 0,\n page: params.page ?? 1,\n };\n }\n\n async create(data: CreateProjectRequest): Promise<Project> {\n await assertManagementSubscription();\n const { id_account, id_user } = await getUserContext();\n const url = `/account/${id_account}/user/${id_user}/projects`;\n\n const response = await api.apps.post<ApiMutationResponse>(url, data);\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao criar projeto',\n 'CREATE_PROJECT_FAILED',\n 400\n );\n }\n\n if (!response.data || response.data.length === 0) {\n throw new ApiError('Resposta inválida ao criar projeto', 'INVALID_RESPONSE', 500);\n }\n\n return ProjectSchema.parse(response.data[0]);\n }\n\n async update(projectId: number, data: UpdateProjectRequest): Promise<Project> {\n await assertManagementSubscription();\n const { id_account, id_user } = await getUserContext();\n const url = `/account/${id_account}/user/${id_user}/projects/${projectId}`;\n\n const response = await api.apps.put<ApiMutationResponse>(url, data);\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar projeto',\n 'UPDATE_PROJECT_FAILED',\n 400\n );\n }\n\n if (!response.data || response.data.length === 0) {\n throw new ApiError('Resposta inválida ao atualizar projeto', 'INVALID_RESPONSE', 500);\n }\n\n return ProjectSchema.parse(response.data[0]);\n }\n\n async delete(projectId: number, moveToProjectId: number): Promise<void> {\n await assertManagementSubscription();\n const { id_account, id_user } = await getUserContext();\n const url = `/account/${id_account}/user/${id_user}/projects/${projectId}`;\n\n const response = await api.apps.delete<ApiMutationResponse>(url, {\n body: JSON.stringify({ id_project_to_move: moveToProjectId }),\n });\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao deletar projeto',\n 'DELETE_PROJECT_FAILED',\n 400\n );\n }\n }\n}\n\nexport const projectsService = new ProjectsService();\n"],"mappings":"AAAA,OAAO;AAEP,SAAS,WAAW;AACpB,SAAS,gBAAgB;AACzB,SAAS,wBAAwB;AACjC,SAAS,sBAAsB;AAC/B,SAAS,oCAAoC;AAC7C;AAAA,EAEE;AAAA,OAIK;AAuBP,MAAM,gBAAgB;AAAA,EACpB,MAAM,KAAK,SAA6B,CAAC,GAA0B;AACjE,UAAM,EAAE,YAAY,QAAQ,IAAI,MAAM,eAAe;AACrD,UAAM,QAAQ,iBAAiB,MAA+D;AAC9F,UAAM,MAAM,YAAY,UAAU,SAAS,OAAO,YAAY,QAAQ,IAAI,KAAK,KAAK,EAAE;AAEtF,UAAM,WAAW,MAAM,IAAI,KAAK,IAA8B,GAAG;AAEjE,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO,SAAS,QAAQ,CAAC,GAAG,IAAI,CAAC,SAAS,cAAc,MAAM,IAAI,CAAC;AAAA,MACnE,OAAO,SAAS,SAAS;AAAA,MACzB,MAAM,OAAO,QAAQ;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,MAA8C;AACzD,UAAM,6BAA6B;AACnC,UAAM,EAAE,YAAY,QAAQ,IAAI,MAAM,eAAe;AACrD,UAAM,MAAM,YAAY,UAAU,SAAS,OAAO;AAElD,UAAM,WAAW,MAAM,IAAI,KAAK,KAA0B,KAAK,IAAI;AAEnE,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,QAAQ,SAAS,KAAK,WAAW,GAAG;AAChD,YAAM,IAAI,SAAS,yCAAsC,oBAAoB,GAAG;AAAA,IAClF;AAEA,WAAO,cAAc,MAAM,SAAS,KAAK,CAAC,CAAC;AAAA,EAC7C;AAAA,EAEA,MAAM,OAAO,WAAmB,MAA8C;AAC5E,UAAM,6BAA6B;AACnC,UAAM,EAAE,YAAY,QAAQ,IAAI,MAAM,eAAe;AACrD,UAAM,MAAM,YAAY,UAAU,SAAS,OAAO,aAAa,SAAS;AAExE,UAAM,WAAW,MAAM,IAAI,KAAK,IAAyB,KAAK,IAAI;AAElE,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,QAAQ,SAAS,KAAK,WAAW,GAAG;AAChD,YAAM,IAAI,SAAS,6CAA0C,oBAAoB,GAAG;AAAA,IACtF;AAEA,WAAO,cAAc,MAAM,SAAS,KAAK,CAAC,CAAC;AAAA,EAC7C;AAAA,EAEA,MAAM,OAAO,WAAmB,iBAAwC;AACtE,UAAM,6BAA6B;AACnC,UAAM,EAAE,YAAY,QAAQ,IAAI,MAAM,eAAe;AACrD,UAAM,MAAM,YAAY,UAAU,SAAS,OAAO,aAAa,SAAS;AAExE,UAAM,WAAW,MAAM,IAAI,KAAK,OAA4B,KAAK;AAAA,MAC/D,MAAM,KAAK,UAAU,EAAE,oBAAoB,gBAAgB,CAAC;AAAA,IAC9D,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,kBAAkB,IAAI,gBAAgB;","names":[]}
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
const ProjectSchema = z.object({
|
|
3
|
+
id: z.union([z.number(), z.string()]).transform(Number),
|
|
4
|
+
id_wl: z.union([z.number(), z.string()]).transform(Number),
|
|
5
|
+
id_account: z.union([z.number(), z.string()]).transform(Number),
|
|
6
|
+
title: z.string(),
|
|
7
|
+
photo: z.string().nullable().optional(),
|
|
8
|
+
id_api: z.union([z.number(), z.string()]).nullable().optional(),
|
|
9
|
+
id_form_integration: z.union([z.number(), z.string()]).nullable().optional(),
|
|
10
|
+
total_users: z.string().optional(),
|
|
11
|
+
deleted: z.union([z.boolean(), z.number()]).transform((v) => Boolean(v)).default(false),
|
|
12
|
+
datetime_add: z.string().nullable().optional(),
|
|
13
|
+
datetime_alt: z.string().nullable().optional(),
|
|
14
|
+
datetime_del: z.string().nullable().optional()
|
|
15
|
+
});
|
|
2
16
|
const ProjectUserSchema = z.object({
|
|
3
17
|
id_user: z.union([z.number(), z.string()]).transform(Number),
|
|
4
18
|
id_account: z.union([z.number(), z.string()]).transform(Number),
|
|
@@ -18,6 +32,7 @@ const AccountUserSchema = z.object({
|
|
|
18
32
|
});
|
|
19
33
|
export {
|
|
20
34
|
AccountUserSchema,
|
|
35
|
+
ProjectSchema,
|
|
21
36
|
ProjectUserSchema
|
|
22
37
|
};
|
|
23
38
|
//# sourceMappingURL=types.mjs.map
|
|
@@ -1 +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().nullable(),\r\n email: z.string().nullable(),\r\n profile: z.string().nullable().optional().default(\"viewer\"),\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().nullable(),\r\n email: z.string().nullable(),\r\n profile: z.string().nullable().optional().default(\"viewer\"),\r\n photo: z.string().nullable().optional(),\r\n in_project: z.boolean().optional(),\r\n});\r\n\r\nexport type AccountUser = z.infer<typeof AccountUserSchema>;\r\n\r\nexport interface AddRemoveProjectUsersParams {\r\n projectId: number;\r\n users: number[];\r\n}\r\n\r\nexport interface ListUsersParams {\r\n search?: string;\r\n page?: number;\r\n limit?: number;\r\n inProject?: number;\r\n}\r\n\r\nexport interface UsersPage<T> {\r\n data: T[];\r\n total: number;\r\n page: number;\r\n}\r\n"],"mappings":"AAAA,SAAS,SAAS;
|
|
1
|
+
{"version":3,"sources":["../../../src/modules/projects/types.ts"],"sourcesContent":["import { z } from \"zod\";\r\n\r\n// ============================================================================\r\n// Project\r\n// ============================================================================\r\n\r\nexport const ProjectSchema = z.object({\r\n id: z.union([z.number(), z.string()]).transform(Number),\r\n id_wl: z.union([z.number(), z.string()]).transform(Number),\r\n id_account: z.union([z.number(), z.string()]).transform(Number),\r\n title: z.string(),\r\n photo: z.string().nullable().optional(),\r\n id_api: z.union([z.number(), z.string()]).nullable().optional(),\r\n id_form_integration: z.union([z.number(), z.string()]).nullable().optional(),\r\n total_users: z.string().optional(),\r\n deleted: z\r\n .union([z.boolean(), z.number()])\r\n .transform((v) => Boolean(v))\r\n .default(false),\r\n datetime_add: z.string().nullable().optional(),\r\n datetime_alt: z.string().nullable().optional(),\r\n datetime_del: z.string().nullable().optional(),\r\n});\r\n\r\nexport type Project = z.infer<typeof ProjectSchema>;\r\n\r\nexport interface ProjectsPage {\r\n data: Project[];\r\n total: number;\r\n page: number;\r\n}\r\n\r\nexport interface CreateProjectRequest {\r\n title: string;\r\n photo?: string;\r\n id_api?: number;\r\n users?: number[];\r\n}\r\n\r\nexport interface UpdateProjectRequest {\r\n title: string;\r\n photo?: string;\r\n}\r\n\r\n// ============================================================================\r\n// Project Users\r\n// ============================================================================\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().nullable(),\r\n email: z.string().nullable(),\r\n profile: z.string().nullable().optional().default(\"viewer\"),\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().nullable(),\r\n email: z.string().nullable(),\r\n profile: z.string().nullable().optional().default(\"viewer\"),\r\n photo: z.string().nullable().optional(),\r\n in_project: z.boolean().optional(),\r\n});\r\n\r\nexport type AccountUser = z.infer<typeof AccountUserSchema>;\r\n\r\nexport interface AddRemoveProjectUsersParams {\r\n projectId: number;\r\n users: number[];\r\n}\r\n\r\nexport interface ListUsersParams {\r\n search?: string;\r\n page?: number;\r\n limit?: number;\r\n inProject?: number;\r\n}\r\n\r\nexport interface UsersPage<T> {\r\n data: T[];\r\n total: number;\r\n page: number;\r\n}\r\n"],"mappings":"AAAA,SAAS,SAAS;AAMX,MAAM,gBAAgB,EAAE,OAAO;AAAA,EACpC,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,UAAU,MAAM;AAAA,EACtD,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,UAAU,MAAM;AAAA,EACzD,YAAY,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,UAAU,MAAM;AAAA,EAC9D,OAAO,EAAE,OAAO;AAAA,EAChB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACtC,QAAQ,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EAC9D,qBAAqB,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EAC3E,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,SAAS,EACN,MAAM,CAAC,EAAE,QAAQ,GAAG,EAAE,OAAO,CAAC,CAAC,EAC/B,UAAU,CAAC,MAAM,QAAQ,CAAC,CAAC,EAC3B,QAAQ,KAAK;AAAA,EAChB,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC7C,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC7C,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAC/C,CAAC;AA0BM,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,EAAE,SAAS;AAAA,EAC1B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,QAAQ;AAAA,EAC1D,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,EAAE,SAAS;AAAA,EAC1B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,QAAQ;AAAA,EAC1D,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACtC,YAAY,EAAE,QAAQ,EAAE,SAAS;AACnC,CAAC;","names":[]}
|
package/dist/server.mjs
CHANGED
|
@@ -25,6 +25,11 @@ import { createCardAction } from "./modules/cards/actions/create-card.action";
|
|
|
25
25
|
import { resolvePlanExtrasPrices } from "./modules/subscriptions/utils/resolve-plan-extras-prices";
|
|
26
26
|
import { hasSubscriptionExpired } from "./modules/subscriptions/utils/has-subscription-expired";
|
|
27
27
|
import { listIaCreditsAction } from "./modules/ia-credits/actions/list-ia-credits.action";
|
|
28
|
+
import { projectsService } from "./modules/projects/services/projects.service";
|
|
29
|
+
import { listProjectsAction } from "./modules/projects/actions/list-projects.action";
|
|
30
|
+
import { createProjectAction } from "./modules/projects/actions/create-project.action";
|
|
31
|
+
import { updateProjectAction } from "./modules/projects/actions/update-project.action";
|
|
32
|
+
import { deleteProjectAction } from "./modules/projects/actions/delete-project.action";
|
|
28
33
|
import { projectUsersService } from "./modules/projects/services/project-users.service";
|
|
29
34
|
import { listProjectUsersAction } from "./modules/projects/actions/list-project-users.action";
|
|
30
35
|
import { listAvailableUsersAction } from "./modules/projects/actions/list-available-users.action";
|
|
@@ -76,8 +81,10 @@ export {
|
|
|
76
81
|
confirmTwoFactorAction,
|
|
77
82
|
createAccountUserAction,
|
|
78
83
|
createCardAction,
|
|
84
|
+
createProjectAction,
|
|
79
85
|
deleteAccountAction,
|
|
80
86
|
deleteAccountUserAction,
|
|
87
|
+
deleteProjectAction,
|
|
81
88
|
disableTwoFactorAction,
|
|
82
89
|
findCurrentAccount,
|
|
83
90
|
findPlanByIdAction,
|
|
@@ -94,11 +101,13 @@ export {
|
|
|
94
101
|
listIaCreditsAction,
|
|
95
102
|
listPlansAction,
|
|
96
103
|
listProjectUsersAction,
|
|
104
|
+
listProjectsAction,
|
|
97
105
|
listSubscriptionsAction,
|
|
98
106
|
plansService,
|
|
99
107
|
processImage,
|
|
100
108
|
processImageAction,
|
|
101
109
|
projectUsersService,
|
|
110
|
+
projectsService,
|
|
102
111
|
removeProjectUserAction,
|
|
103
112
|
requestEmailChangeAction,
|
|
104
113
|
requestPhoneChangeAction,
|
|
@@ -109,6 +118,7 @@ export {
|
|
|
109
118
|
twoFactorService,
|
|
110
119
|
updateAccountAction,
|
|
111
120
|
updateAccountUserByIdAction,
|
|
121
|
+
updateProjectAction,
|
|
112
122
|
updateSubscriptionPlanAction,
|
|
113
123
|
updateUserAction,
|
|
114
124
|
validateSessionAction,
|
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 { revalidateWhitelabelAction } from './modules/whitelabel/actions/revalidate-whitelabel.action';\r\nexport { assertManagementPermission } from './modules/auth/utils/assert-management-permission';\r\nexport { assertManagementSubscription } from './modules/auth/utils/assert-management-subscription';\r\nexport { assertSubscriptionAddon } from './modules/auth/utils/assert-subscription-addon';\r\nexport { assertPaidSubscription } from './modules/auth/utils/assert-paid-subscription';\r\nexport { subscriptionsService } from './modules/subscriptions/services/subscriptions.service';\r\nexport { plansService } from './modules/plans/services/plans.service';\r\nexport { cardsService } from './modules/cards/services/cards.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 { findUserById } from './modules/users/action/find-user-by-id.action';\r\nexport { findCurrentAccount } from './modules/accounts/actions/find-current-account.action';\r\nexport { listSubscriptionsAction } from './modules/subscriptions/actions/list-subscriptions.action';\r\nexport { findPlanByIdAction } from './modules/plans/actions/find-plan-by-id.action';\r\nexport { listPlansAction } from './modules/plans/actions/list-plans.action';\r\nexport { calculateSubscriptionAction } from './modules/subscriptions/actions/calculate-subscription.action';\r\nexport { updateSubscriptionPlanAction } from './modules/subscriptions/actions/update-subscription-plan.action';\r\nexport { listCardsAction } from './modules/cards/actions/list-cards.action';\r\nexport { createCardAction } from './modules/cards/actions/create-card.action';\r\nexport { resolvePlanExtrasPrices } from './modules/subscriptions/utils/resolve-plan-extras-prices';\r\nexport { hasSubscriptionExpired } from './modules/subscriptions/utils/has-subscription-expired';\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\nexport { buildWlOverride, buildWlOverrideFromJwt } from './modules/auth/utils/build-wl-override';\r\nexport { safeServerAction } from './utils/safeServerAction';\r\n\r\n// Image Processing (server-side)\r\nexport { processImageAction } from './modules/images/actions/process-image.action';\r\nexport { processImage } from './modules/images/services/image-processing.service';\r\nexport type {\r\n ProcessImageInput,\r\n ProcessImageOutput,\r\n ProcessImageActionInput,\r\n ProcessImageActionOutput,\r\n} from './modules/images/types/image.type';\r\n"],"mappings":"AAAA,OAAO;AAGP,SAAS,WAAW,KAAK,iBAAiB;AAG1C,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,kCAAkC;AAC3C,SAAS,kCAAkC;AAC3C,SAAS,oCAAoC;AAC7C,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AAGjC,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AACtC,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,+BAA+B;AACxC,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAChC,SAAS,mCAAmC;AAC5C,SAAS,oCAAoC;AAC7C,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AACjC,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,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;AAC/B,SAAS,iBAAiB,8BAA8B;AACxD,SAAS,wBAAwB;AAGjC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;","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 { revalidateWhitelabelAction } from './modules/whitelabel/actions/revalidate-whitelabel.action';\r\nexport { assertManagementPermission } from './modules/auth/utils/assert-management-permission';\r\nexport { assertManagementSubscription } from './modules/auth/utils/assert-management-subscription';\r\nexport { assertSubscriptionAddon } from './modules/auth/utils/assert-subscription-addon';\r\nexport { assertPaidSubscription } from './modules/auth/utils/assert-paid-subscription';\r\nexport { subscriptionsService } from './modules/subscriptions/services/subscriptions.service';\r\nexport { plansService } from './modules/plans/services/plans.service';\r\nexport { cardsService } from './modules/cards/services/cards.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 { findUserById } from './modules/users/action/find-user-by-id.action';\r\nexport { findCurrentAccount } from './modules/accounts/actions/find-current-account.action';\r\nexport { listSubscriptionsAction } from './modules/subscriptions/actions/list-subscriptions.action';\r\nexport { findPlanByIdAction } from './modules/plans/actions/find-plan-by-id.action';\r\nexport { listPlansAction } from './modules/plans/actions/list-plans.action';\r\nexport { calculateSubscriptionAction } from './modules/subscriptions/actions/calculate-subscription.action';\r\nexport { updateSubscriptionPlanAction } from './modules/subscriptions/actions/update-subscription-plan.action';\r\nexport { listCardsAction } from './modules/cards/actions/list-cards.action';\r\nexport { createCardAction } from './modules/cards/actions/create-card.action';\r\nexport { resolvePlanExtrasPrices } from './modules/subscriptions/utils/resolve-plan-extras-prices';\r\nexport { hasSubscriptionExpired } from './modules/subscriptions/utils/has-subscription-expired';\r\nexport { listIaCreditsAction } from './modules/ia-credits/actions/list-ia-credits.action';\r\n\r\n// Project Services & Actions (server-only)\r\nexport { projectsService } from './modules/projects/services/projects.service';\r\nexport { listProjectsAction } from './modules/projects/actions/list-projects.action';\r\nexport { createProjectAction } from './modules/projects/actions/create-project.action';\r\nexport { updateProjectAction } from './modules/projects/actions/update-project.action';\r\nexport { deleteProjectAction } from './modules/projects/actions/delete-project.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\nexport { buildWlOverride, buildWlOverrideFromJwt } from './modules/auth/utils/build-wl-override';\r\nexport { safeServerAction } from './utils/safeServerAction';\r\n\r\n// Image Processing (server-side)\r\nexport { processImageAction } from './modules/images/actions/process-image.action';\r\nexport { processImage } from './modules/images/services/image-processing.service';\r\nexport type {\r\n ProcessImageInput,\r\n ProcessImageOutput,\r\n ProcessImageActionInput,\r\n ProcessImageActionOutput,\r\n} from './modules/images/types/image.type';\r\n"],"mappings":"AAAA,OAAO;AAGP,SAAS,WAAW,KAAK,iBAAiB;AAG1C,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,kCAAkC;AAC3C,SAAS,kCAAkC;AAC3C,SAAS,oCAAoC;AAC7C,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AAGjC,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AACtC,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,+BAA+B;AACxC,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAChC,SAAS,mCAAmC;AAC5C,SAAS,oCAAoC;AAC7C,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AACjC,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,2BAA2B;AAGpC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AACpC,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;AAC/B,SAAS,iBAAiB,8BAA8B;AACxD,SAAS,wBAAwB;AAGjC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;","names":[]}
|
package/package.json
CHANGED
|
@@ -14,20 +14,19 @@ import {
|
|
|
14
14
|
UserAvatar,
|
|
15
15
|
} from '../../index';
|
|
16
16
|
import { IconCheck, IconChevronDown, IconFolderOpen } from '@tabler/icons-react';
|
|
17
|
-
import type {
|
|
17
|
+
import type { Project } from '../../modules/projects/types';
|
|
18
18
|
|
|
19
|
-
interface ProjectSelectorPopoverProps {
|
|
19
|
+
export interface ProjectSelectorPopoverProps {
|
|
20
20
|
open: boolean;
|
|
21
21
|
setOpen: Dispatch<SetStateAction<boolean>>;
|
|
22
22
|
titleRef?: RefObject<HTMLSpanElement | null>;
|
|
23
|
-
projects:
|
|
24
|
-
selectedProject:
|
|
23
|
+
projects: Project[];
|
|
24
|
+
selectedProject: Project | null;
|
|
25
25
|
isLoading?: boolean;
|
|
26
26
|
isFetchingNextPage?: boolean;
|
|
27
27
|
hasNextPage?: boolean;
|
|
28
28
|
onLoadMore?: () => void | Promise<unknown>;
|
|
29
|
-
onSelectProject: (project:
|
|
30
|
-
onAddProject?: () => void;
|
|
29
|
+
onSelectProject: (project: Project) => void;
|
|
31
30
|
onManageProjects?: () => void;
|
|
32
31
|
children?: React.ReactNode;
|
|
33
32
|
}
|
|
@@ -55,7 +54,6 @@ export function ProjectSelectorPopover({
|
|
|
55
54
|
hasNextPage,
|
|
56
55
|
onLoadMore,
|
|
57
56
|
onSelectProject,
|
|
58
|
-
onAddProject,
|
|
59
57
|
onManageProjects,
|
|
60
58
|
children,
|
|
61
59
|
}: ProjectSelectorPopoverProps) {
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useState, useRef, useEffect, RefObject } from 'react';
|
|
3
|
+
import { useState, useRef, useEffect, useMemo, RefObject } from 'react';
|
|
4
4
|
import { useMobileNavbarSheet } from '../../../store/useMobileNavbarSheet';
|
|
5
5
|
import { useAppNavigationContext } from '../AppNavigationContext';
|
|
6
6
|
import { ProjectSelectorPopover } from '../ProjectSelectorPopover';
|
|
7
7
|
import { cn, Command, CommandEmpty, CommandInput, CommandItem, CommandList, UserAvatar, useWhitelabel } from '../../../index';
|
|
8
|
+
import { useInfiniteProjects } from '../../../modules/projects/hooks/list-infinite-projects.hook';
|
|
8
9
|
import { IconChevronDown } from '@tabler/icons-react';
|
|
9
|
-
import type {
|
|
10
|
+
import type { Project } from '../../../modules/projects/types';
|
|
10
11
|
|
|
11
12
|
export interface ProjectSelectorProps {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
isLoading?: boolean;
|
|
15
|
-
isFetchingNextPage?: boolean;
|
|
16
|
-
hasNextPage?: boolean;
|
|
17
|
-
onLoadMore?: () => void | Promise<unknown>;
|
|
18
|
-
onSelectProject: (project: NavigationProject) => void;
|
|
13
|
+
selectedProject: Project | null;
|
|
14
|
+
onSelectProject: (project: Project) => void;
|
|
19
15
|
onAddProject?: () => void;
|
|
20
16
|
onManageProjects?: () => void;
|
|
21
17
|
}
|
|
@@ -30,14 +26,8 @@ function ProjectItemSkeleton() {
|
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
export function ProjectSelector({
|
|
33
|
-
projects,
|
|
34
29
|
selectedProject,
|
|
35
|
-
isLoading,
|
|
36
|
-
isFetchingNextPage,
|
|
37
|
-
hasNextPage,
|
|
38
|
-
onLoadMore,
|
|
39
30
|
onSelectProject,
|
|
40
|
-
onAddProject,
|
|
41
31
|
onManageProjects,
|
|
42
32
|
}: ProjectSelectorProps) {
|
|
43
33
|
const { whitelabel } = useWhitelabel();
|
|
@@ -47,6 +37,12 @@ export function ProjectSelector({
|
|
|
47
37
|
const titleRef = useRef<HTMLDivElement>(null);
|
|
48
38
|
const { openProjectList, clearProjectList } = useMobileNavbarSheet();
|
|
49
39
|
|
|
40
|
+
const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } = useInfiniteProjects({
|
|
41
|
+
sort: 'title',
|
|
42
|
+
limit: 100,
|
|
43
|
+
});
|
|
44
|
+
const projects = useMemo(() => data?.pages.flatMap((page) => page.data) ?? [], [data]);
|
|
45
|
+
|
|
50
46
|
useEffect(() => {
|
|
51
47
|
if (openProjectList && breakpoint === 'mobile') {
|
|
52
48
|
setActiveSection('projects');
|
|
@@ -70,9 +66,8 @@ export function ProjectSelector({
|
|
|
70
66
|
isLoading={isLoading}
|
|
71
67
|
isFetchingNextPage={isFetchingNextPage}
|
|
72
68
|
hasNextPage={hasNextPage}
|
|
73
|
-
onLoadMore={
|
|
69
|
+
onLoadMore={() => fetchNextPage()}
|
|
74
70
|
onSelectProject={onSelectProject}
|
|
75
|
-
onAddProject={onAddProject}
|
|
76
71
|
onManageProjects={onManageProjects}
|
|
77
72
|
>
|
|
78
73
|
<div className="flex items-center gap-2 truncate select-none cursor-pointer" ref={titleRef}>
|
|
@@ -121,13 +116,13 @@ export function ProjectSelector({
|
|
|
121
116
|
<CommandList
|
|
122
117
|
className="custom-scrollbar paragraph-small-medium text-gray-600 h-[227px]"
|
|
123
118
|
onScroll={(event) => {
|
|
124
|
-
if (!hasNextPage || isFetchingNextPage || !
|
|
119
|
+
if (!hasNextPage || isFetchingNextPage || !fetchNextPage) return;
|
|
125
120
|
|
|
126
121
|
const target = event.currentTarget;
|
|
127
122
|
const distanceToBottom = target.scrollHeight - target.scrollTop - target.clientHeight;
|
|
128
123
|
|
|
129
124
|
if (distanceToBottom <= 80) {
|
|
130
|
-
|
|
125
|
+
fetchNextPage();
|
|
131
126
|
}
|
|
132
127
|
}}
|
|
133
128
|
>
|
package/src/index.ts
CHANGED
|
@@ -26,13 +26,31 @@ export {
|
|
|
26
26
|
LIST_ALL_ACCOUNT_USERS_QUERY_KEY,
|
|
27
27
|
LIST_ALL_ACCOUNT_USERS_BASE_KEY,
|
|
28
28
|
} from "./modules/projects/hooks/list-all-account-users.hook";
|
|
29
|
+
export {
|
|
30
|
+
useProjects,
|
|
31
|
+
PROJECTS_BASE_KEY,
|
|
32
|
+
PROJECTS_QUERY_KEY,
|
|
33
|
+
} from "./modules/projects/hooks/list-projects.hook";
|
|
34
|
+
export {
|
|
35
|
+
useInfiniteProjects,
|
|
36
|
+
INFINITE_PROJECTS_QUERY_KEY,
|
|
37
|
+
} from "./modules/projects/hooks/list-infinite-projects.hook";
|
|
38
|
+
export { useCreateProject } from "./modules/projects/hooks/create-project.hook";
|
|
39
|
+
export { useUpdateProject } from "./modules/projects/hooks/update-project.hook";
|
|
40
|
+
export { useDeleteProject } from "./modules/projects/hooks/delete-project.hook";
|
|
29
41
|
export type {
|
|
42
|
+
Project,
|
|
43
|
+
ProjectsPage,
|
|
44
|
+
CreateProjectRequest,
|
|
45
|
+
UpdateProjectRequest,
|
|
30
46
|
ProjectUser,
|
|
31
47
|
AccountUser,
|
|
32
48
|
AddRemoveProjectUsersParams,
|
|
33
49
|
ListUsersParams,
|
|
34
50
|
UsersPage,
|
|
35
51
|
} from "./modules/projects/types";
|
|
52
|
+
export { ProjectSchema } from "./modules/projects/types";
|
|
53
|
+
export type { ListProjectsActionParams } from "./modules/projects/actions/list-projects.action";
|
|
36
54
|
export {
|
|
37
55
|
useUserQuery,
|
|
38
56
|
useUserValidateSession,
|
|
@@ -192,7 +210,6 @@ export type { NavBarItemProps } from "./components/layouts/NavBarItem";
|
|
|
192
210
|
export { AppNavigation } from "./components/navigation/AppNavigation";
|
|
193
211
|
export { CancelledSubscriptionBanner } from "./components/navigation/CancelledSubscriptionBanner";
|
|
194
212
|
export type { NavItemConfig } from "./components/navigation/subcomponents/NavItems";
|
|
195
|
-
export type { NavigationProject } from "./components/navigation/types";
|
|
196
213
|
export { useMobileNavbarSheet } from "./store/useMobileNavbarSheet";
|
|
197
214
|
|
|
198
215
|
// Auth Query Key Utilities
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { safeServerAction } from '../../../utils/safeServerAction';
|
|
4
|
+
import { projectsService } from '../services/projects.service';
|
|
5
|
+
import type { CreateProjectRequest } from '../types';
|
|
6
|
+
|
|
7
|
+
export async function createProjectAction(data: CreateProjectRequest) {
|
|
8
|
+
return safeServerAction(() => projectsService.create(data));
|
|
9
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { safeServerAction } from '../../../utils/safeServerAction';
|
|
4
|
+
import { projectsService } from '../services/projects.service';
|
|
5
|
+
|
|
6
|
+
export async function deleteProjectAction(projectId: number, moveToProjectId: number) {
|
|
7
|
+
return safeServerAction(() => projectsService.delete(projectId, moveToProjectId));
|
|
8
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { safeServerAction } from '../../../utils/safeServerAction';
|
|
4
|
+
import { projectsService } from '../services/projects.service';
|
|
5
|
+
|
|
6
|
+
export interface ListProjectsActionParams {
|
|
7
|
+
page?: number;
|
|
8
|
+
limit?: number;
|
|
9
|
+
sort?: string;
|
|
10
|
+
search?: string;
|
|
11
|
+
deleted?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function listProjectsAction(params?: ListProjectsActionParams) {
|
|
15
|
+
return safeServerAction(() => projectsService.list(params));
|
|
16
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { safeServerAction } from '../../../utils/safeServerAction';
|
|
4
|
+
import { projectsService } from '../services/projects.service';
|
|
5
|
+
import type { UpdateProjectRequest } from '../types';
|
|
6
|
+
|
|
7
|
+
export async function updateProjectAction(projectId: number, data: UpdateProjectRequest) {
|
|
8
|
+
return safeServerAction(() => projectsService.update(projectId, data));
|
|
9
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
4
|
+
import { createProjectAction } from '../actions/create-project.action';
|
|
5
|
+
import { withAction } from '../../../utils/withAction';
|
|
6
|
+
import { useAuthQueryKey } from '../../../hooks/useAuthQueryKey';
|
|
7
|
+
import { PROJECTS_BASE_KEY } from './list-projects.hook';
|
|
8
|
+
import type { CreateProjectRequest } from '../types';
|
|
9
|
+
|
|
10
|
+
export function useCreateProject() {
|
|
11
|
+
const queryClient = useQueryClient();
|
|
12
|
+
const projectsKey = useAuthQueryKey([...PROJECTS_BASE_KEY]);
|
|
13
|
+
|
|
14
|
+
return useMutation({
|
|
15
|
+
mutationFn: (data: CreateProjectRequest) =>
|
|
16
|
+
withAction(createProjectAction)(data),
|
|
17
|
+
onSuccess: () => {
|
|
18
|
+
queryClient.invalidateQueries({ queryKey: projectsKey });
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
4
|
+
import { deleteProjectAction } from '../actions/delete-project.action';
|
|
5
|
+
import { withAction } from '../../../utils/withAction';
|
|
6
|
+
import { useAuthQueryKey } from '../../../hooks/useAuthQueryKey';
|
|
7
|
+
import { PROJECTS_BASE_KEY } from './list-projects.hook';
|
|
8
|
+
|
|
9
|
+
export function useDeleteProject() {
|
|
10
|
+
const queryClient = useQueryClient();
|
|
11
|
+
const projectsKey = useAuthQueryKey([...PROJECTS_BASE_KEY]);
|
|
12
|
+
|
|
13
|
+
return useMutation({
|
|
14
|
+
mutationFn: ({ projectId, moveToProjectId }: { projectId: number; moveToProjectId: number }) =>
|
|
15
|
+
withAction(deleteProjectAction)(projectId, moveToProjectId),
|
|
16
|
+
onSuccess: () => {
|
|
17
|
+
queryClient.invalidateQueries({ queryKey: projectsKey });
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useInfiniteQuery } from "@tanstack/react-query";
|
|
4
|
+
import { listProjectsAction } from "../actions/list-projects.action";
|
|
5
|
+
import type { ListProjectsActionParams } from "../actions/list-projects.action";
|
|
6
|
+
import { withAction } from "../../../utils/withAction";
|
|
7
|
+
import { useAuthQueryKey } from "../../../hooks/useAuthQueryKey";
|
|
8
|
+
import { PROJECTS_BASE_KEY } from "./list-projects.hook";
|
|
9
|
+
|
|
10
|
+
const PAGE_SIZE = 20;
|
|
11
|
+
|
|
12
|
+
export const INFINITE_PROJECTS_QUERY_KEY = (
|
|
13
|
+
params?: Omit<ListProjectsActionParams, "page">,
|
|
14
|
+
) => [...PROJECTS_BASE_KEY, "infinite", params] as const;
|
|
15
|
+
|
|
16
|
+
export function useInfiniteProjects({
|
|
17
|
+
limit = PAGE_SIZE,
|
|
18
|
+
...params
|
|
19
|
+
}: Omit<ListProjectsActionParams, "page">) {
|
|
20
|
+
const queryKey = useAuthQueryKey([...INFINITE_PROJECTS_QUERY_KEY(params)]);
|
|
21
|
+
|
|
22
|
+
return useInfiniteQuery({
|
|
23
|
+
queryKey,
|
|
24
|
+
queryFn: ({ pageParam }) =>
|
|
25
|
+
withAction(() =>
|
|
26
|
+
listProjectsAction({
|
|
27
|
+
...params,
|
|
28
|
+
page: pageParam as number,
|
|
29
|
+
limit: PAGE_SIZE,
|
|
30
|
+
}),
|
|
31
|
+
)(),
|
|
32
|
+
initialPageParam: 1,
|
|
33
|
+
getNextPageParam: (lastPage, allPages) => {
|
|
34
|
+
const loaded = allPages.reduce((sum, p) => sum + p.data.length, 0);
|
|
35
|
+
return loaded < lastPage.total ? allPages.length + 1 : undefined;
|
|
36
|
+
},
|
|
37
|
+
staleTime: 30_000,
|
|
38
|
+
refetchOnMount: true,
|
|
39
|
+
refetchOnWindowFocus: true,
|
|
40
|
+
refetchOnReconnect: true,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useQuery, keepPreviousData } from '@tanstack/react-query';
|
|
4
|
+
import { listProjectsAction } from '../actions/list-projects.action';
|
|
5
|
+
import type { ListProjectsActionParams } from '../actions/list-projects.action';
|
|
6
|
+
import { withAction } from '../../../utils/withAction';
|
|
7
|
+
import { useAuthQueryKey } from '../../../hooks/useAuthQueryKey';
|
|
8
|
+
|
|
9
|
+
export const PROJECTS_BASE_KEY = ['projects'] as const;
|
|
10
|
+
|
|
11
|
+
export const PROJECTS_QUERY_KEY = (params?: ListProjectsActionParams) =>
|
|
12
|
+
[...PROJECTS_BASE_KEY, params] as const;
|
|
13
|
+
|
|
14
|
+
export function useProjects(params?: ListProjectsActionParams) {
|
|
15
|
+
const queryKey = useAuthQueryKey([...PROJECTS_QUERY_KEY(params)]);
|
|
16
|
+
|
|
17
|
+
return useQuery({
|
|
18
|
+
queryKey,
|
|
19
|
+
queryFn: withAction(() => listProjectsAction(params)),
|
|
20
|
+
staleTime: 30_000,
|
|
21
|
+
placeholderData: keepPreviousData,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
4
|
+
import { updateProjectAction } from '../actions/update-project.action';
|
|
5
|
+
import { withAction } from '../../../utils/withAction';
|
|
6
|
+
import { useAuthQueryKey } from '../../../hooks/useAuthQueryKey';
|
|
7
|
+
import { PROJECTS_BASE_KEY } from './list-projects.hook';
|
|
8
|
+
import type { UpdateProjectRequest } from '../types';
|
|
9
|
+
|
|
10
|
+
export function useUpdateProject() {
|
|
11
|
+
const queryClient = useQueryClient();
|
|
12
|
+
const projectsKey = useAuthQueryKey([...PROJECTS_BASE_KEY]);
|
|
13
|
+
|
|
14
|
+
return useMutation({
|
|
15
|
+
mutationFn: ({ projectId, data }: { projectId: number; data: UpdateProjectRequest }) =>
|
|
16
|
+
withAction(updateProjectAction)(projectId, data),
|
|
17
|
+
onSuccess: () => {
|
|
18
|
+
queryClient.invalidateQueries({ queryKey: projectsKey });
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
}
|