From 77475f09cd1d7dcef700131a3131454090aa4a96 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sat, 25 Jul 2026 15:28:09 +0330 Subject: [PATCH] project users --- .env | 4 +- .../task-detail/TaskDetailModal.tsx | 1 + .../task-detail/TaskDetailToolbar.tsx | 71 +++++++------------ .../project/hooks/useProjectData.ts | 11 +++ .../project/service/ProjectService.ts | 7 +- .../taskmanager/project/types/ProjectTypes.ts | 4 ++ 6 files changed, 49 insertions(+), 49 deletions(-) diff --git a/.env b/.env index 0312aab..fd19687 100644 --- a/.env +++ b/.env @@ -1,5 +1,5 @@ VITE_TOKEN_NAME = 'admin_token' VITE_REFRESH_TOKEN_NAME = 'admin_refresh_token' -VITE_BASE_URL = 'https://api.danakcorp.com' +# VITE_BASE_URL = 'https://api.danakcorp.com' -# VITE_BASE_URL = 'http://192.168.99.131:3500' \ No newline at end of file +VITE_BASE_URL = 'http://192.168.99.131:3500' \ No newline at end of file diff --git a/src/pages/taskmanager/components/task-detail/TaskDetailModal.tsx b/src/pages/taskmanager/components/task-detail/TaskDetailModal.tsx index 1c8a015..7d76a46 100644 --- a/src/pages/taskmanager/components/task-detail/TaskDetailModal.tsx +++ b/src/pages/taskmanager/components/task-detail/TaskDetailModal.tsx @@ -199,6 +199,7 @@ const TaskDetailModal: FC = ({ open, task, columns, projectId, onClose, o onTabChange={handleTabChange} taskDetail={taskDetail} taskId={task.id} + projectId={taskDetail?.projectId ?? projectId} /> diff --git a/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx b/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx index a904bc3..55d65bb 100644 --- a/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx +++ b/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx @@ -1,7 +1,6 @@ import { type FC, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { toast } from '../../../../components/Toast'; -import { useGetUsersInfinite } from "../../../users/hooks/useUserData"; import TaskDetailAttachmentPopover from "./attachment/TaskDetailAttachmentPopover"; import TaskDetailDatePopover from "./date/TaskDetailDatePopover"; import { parseApiDate, toApiDate } from "./date/utils"; @@ -15,7 +14,6 @@ import type { TaskDetailTab } from "./types"; import TaskDetailUsersPopover from "./users/TaskDetailUsersPopover"; import TaskDetailTimePopover from "./time/TaskDetailTimePopover"; import type { TaskUser } from "./users/types"; -import type { UserItemType } from "../../../users/types/UserTypes"; import type { TaskDetailType } from "../../task/types/TaskTypes"; import { useCreateCheckListItem, @@ -24,6 +22,8 @@ import { useDeleteTaskRemark, useUpdateTask, } from "../../task/hooks/useTaskData"; +import { useGetProjectUsers } from "../../project/hooks/useProjectData"; +import type { ProjectUserType } from "../../project/types/ProjectTypes"; import { useSingleUpload } from "../../../service/hooks/useServiceData"; import { ErrorType } from "../../../../helpers/types"; @@ -32,9 +32,10 @@ type Props = { onTabChange: (tab: TaskDetailTab) => void; taskDetail?: TaskDetailType; taskId: string; + projectId: string; }; -const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, taskId }) => { +const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, taskId, projectId }) => { const { t } = useTranslation("global"); const createTaskRemark = useCreateTaskRemark(); const deleteTaskRemark = useDeleteTaskRemark(); @@ -44,14 +45,7 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task const updateTask = useUpdateTask(); const isUsersOpen = activeTab === "users"; const [userSearch, setUserSearch] = useState(""); - const [debouncedUserSearch, setDebouncedUserSearch] = useState(""); - const { - data: usersData, - isPending: isUsersPending, - isFetchingNextPage: isFetchingNextUsersPage, - fetchNextPage: fetchNextUsersPage, - hasNextPage: hasNextUsersPage, - } = useGetUsersInfinite(debouncedUserSearch, undefined, isUsersOpen); + const { data: usersData, isPending: isUsersPending } = useGetProjectUsers(projectId, isUsersOpen); const [labelsView, setLabelsView] = useState("list"); const [labels, setLabels] = useState([]); const [selectedLabelIds, setSelectedLabelIds] = useState>(new Set()); @@ -59,14 +53,6 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task const [startDate, setStartDate] = useState(null); const [endDate, setEndDate] = useState(null); - useEffect(() => { - const timeoutId = window.setTimeout(() => { - setDebouncedUserSearch(userSearch.trim()); - }, 300); - - return () => window.clearTimeout(timeoutId); - }, [userSearch]); - useEffect(() => { if (!taskDetail) return; @@ -91,16 +77,13 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task }, [taskDetail]); const selectedLabels = labels.filter((label) => selectedLabelIds.has(label.id)); - const users = useMemo((): TaskUser[] => { + const projectUsers = useMemo((): TaskUser[] => { const apiUsers: TaskUser[] = - usersData?.pages.flatMap( - (page) => - page.data?.users?.map((user: UserItemType) => ({ - id: user.id, - name: `${user.firstName} ${user.lastName}`.trim(), - avatar: user.profilePic, - })) ?? [], - ) ?? []; + usersData?.data?.map((user: ProjectUserType) => ({ + id: user.id, + name: `${user.firstName} ${user.lastName}`.trim(), + avatar: user.profilePic, + })) ?? []; const taskUsers: TaskUser[] = taskDetail?.users?.map((user) => ({ id: user.id, @@ -123,20 +106,21 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task }); return Array.from(userMap.values()); - }, [usersData?.pages, taskDetail?.users]); + }, [usersData?.data, taskDetail?.users]); const listUsers = useMemo((): TaskUser[] => { - return ( - usersData?.pages.flatMap( - (page) => - page.data?.users?.map((user: UserItemType) => ({ - id: user.id, - name: `${user.firstName} ${user.lastName}`.trim(), - avatar: user.profilePic, - })) ?? [], - ) ?? [] - ); - }, [usersData?.pages]); - const selectedUsers = users.filter((user) => selectedUserIds.has(user.id)); + const query = userSearch.trim().toLowerCase(); + const apiUsers: TaskUser[] = + usersData?.data?.map((user: ProjectUserType) => ({ + id: user.id, + name: `${user.firstName} ${user.lastName}`.trim(), + avatar: user.profilePic, + })) ?? []; + + if (!query) return apiUsers; + + return apiUsers.filter((user) => user.name.toLowerCase().includes(query)); + }, [usersData?.data, userSearch]); + const selectedUsers = projectUsers.filter((user) => selectedUserIds.has(user.id)); const isLabelsOpen = activeTab === "labels"; const isChecklistOpen = activeTab === "checklist"; const isAttachmentOpen = activeTab === "attachment"; @@ -382,11 +366,6 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task onToggle={handleUserToggle} isLoading={isUsersPending} isSubmitting={updateTask.isPending} - hasNextPage={hasNextUsersPage} - isFetchingNextPage={isFetchingNextUsersPage} - onLoadMore={() => { - void fetchNextUsersPage(); - }} search={userSearch} onSearchChange={setUserSearch} /> diff --git a/src/pages/taskmanager/project/hooks/useProjectData.ts b/src/pages/taskmanager/project/hooks/useProjectData.ts index 78fbf19..2c7fa1a 100644 --- a/src/pages/taskmanager/project/hooks/useProjectData.ts +++ b/src/pages/taskmanager/project/hooks/useProjectData.ts @@ -26,6 +26,14 @@ export const useGetProject = (id: string) => { }); }; +export const useGetProjectUsers = (id: string, enabled = true) => { + return useQuery({ + queryKey: ["project-users", id], + queryFn: () => api.getProjectUsers(id), + enabled: !!id && enabled, + }); +}; + export const useCreateProject = () => { const queryClient = useQueryClient(); @@ -49,6 +57,9 @@ export const useUpdateProject = () => { queryClient.invalidateQueries({ queryKey: ["project-detail", variables.id], }); + queryClient.invalidateQueries({ + queryKey: ["project-users", variables.id], + }); }, }); }; diff --git a/src/pages/taskmanager/project/service/ProjectService.ts b/src/pages/taskmanager/project/service/ProjectService.ts index e216854..d9fbec0 100644 --- a/src/pages/taskmanager/project/service/ProjectService.ts +++ b/src/pages/taskmanager/project/service/ProjectService.ts @@ -1,5 +1,5 @@ import axios from "../../../../config/axios"; -import { CreateProjectType, GetProjectResponse, UpdateProjectType } from "../types/ProjectTypes"; +import { CreateProjectType, GetProjectResponse, GetProjectUsersResponse, UpdateProjectType } from "../types/ProjectTypes"; export const getProjectsByWorkspace = async (workspaceId: string) => { const { data } = await axios.get(`/task-manager/projects/user/workspace/${workspaceId}`); @@ -16,6 +16,11 @@ export const getProject = async (id: string): Promise => { return data; }; +export const getProjectUsers = async (id: string): Promise => { + const { data } = await axios.get(`/task-manager/projects/${id}/users`); + return data; +}; + export const createProject = async (params: CreateProjectType) => { const { data } = await axios.post(`/task-manager/projects`, params); return data; diff --git a/src/pages/taskmanager/project/types/ProjectTypes.ts b/src/pages/taskmanager/project/types/ProjectTypes.ts index 692035a..144b1fb 100644 --- a/src/pages/taskmanager/project/types/ProjectTypes.ts +++ b/src/pages/taskmanager/project/types/ProjectTypes.ts @@ -53,3 +53,7 @@ export type ProjectWithPhasesType = { export interface GetProjectResponse extends IResponse { statusCode: number; } + +export interface GetProjectUsersResponse extends IResponse { + statusCode: number; +}