manager users

This commit is contained in:
hamid zarghami
2026-07-12 11:43:56 +03:30
parent ee8da0b88c
commit 61282e1d1b
4 changed files with 103 additions and 32 deletions
@@ -1,6 +1,7 @@
import { type FC, useEffect, useState } from "react";
import { type FC, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "react-toastify";
import { useGetUsers } from "../../../users/hooks/useUserData";
import TaskDetailAttachmentPopover from "./attachment/TaskDetailAttachmentPopover";
import { DEFAULT_DATE_RANGE } from "./date/constants";
import TaskDetailDatePopover from "./date/TaskDetailDatePopover";
@@ -16,10 +17,9 @@ import type { LabelsView, TaskLabel } from "./labels/types";
import TaskDetailActionBar from "./TaskDetailActionBar";
import TaskDetailMetadataPreview from "./TaskDetailMetadataPreview";
import type { TaskDetailTab } from "./types";
import { DEFAULT_USERS } from "./users/constants";
import TaskDetailUsersPopover from "./users/TaskDetailUsersPopover";
import type { TaskDetailType } from "../../task/types/TaskTypes";
import { useCreateTaskRemark } from "../../task/hooks/useTaskData";
import { useCreateTaskRemark, useUpdateTask } from "../../task/hooks/useTaskData";
import { ErrorType } from "../../../../helpers/types";
type Props = {
@@ -38,10 +38,12 @@ const parseDate = (value?: string): DateObject | null => {
const TaskDetailToolbar: FC<Props> = ({ activeTab, onTabChange, taskDetail, taskId }) => {
const { t } = useTranslation("global");
const createTaskRemark = useCreateTaskRemark();
const updateTask = useUpdateTask();
const getUsers = useGetUsers("");
const [labelsView, setLabelsView] = useState<LabelsView>("list");
const [labels, setLabels] = useState<TaskLabel[]>([]);
const [selectedLabelIds, setSelectedLabelIds] = useState<Set<string>>(new Set());
const [selectedUserIds, setSelectedUserIds] = useState<Set<string>>(new Set(["1"]));
const [selectedUserIds, setSelectedUserIds] = useState<Set<string>>(new Set());
const [checklists, setChecklists] = useState<TaskChecklist[]>(DEFAULT_CHECKLISTS);
const [startDate, setStartDate] = useState<DateObject | null>(DEFAULT_DATE_RANGE.startDate);
const [endDate, setEndDate] = useState<DateObject | null>(DEFAULT_DATE_RANGE.endDate);
@@ -61,6 +63,8 @@ const TaskDetailToolbar: FC<Props> = ({ activeTab, onTabChange, taskDetail, task
if (taskDetail.users?.length) {
setSelectedUserIds(new Set(taskDetail.users.map((user) => user.id)));
} else {
setSelectedUserIds(new Set());
}
if (taskDetail.checklists?.length) {
@@ -74,12 +78,27 @@ const TaskDetailToolbar: FC<Props> = ({ activeTab, onTabChange, taskDetail, task
}, [taskDetail]);
const selectedLabels = labels.filter((label) => selectedLabelIds.has(label.id));
const users = taskDetail?.users?.length
? taskDetail.users.map((user) => ({
const users = useMemo(() => {
const apiUsers =
getUsers.data?.data?.users?.map((user) => ({
id: user.id,
name: `${user.firstName} ${user.lastName}`.trim(),
}))
: DEFAULT_USERS;
})) ?? [];
const taskUsers =
taskDetail?.users?.map((user) => ({
id: user.id,
name: `${user.firstName} ${user.lastName}`.trim(),
})) ?? [];
const userMap = new Map(apiUsers.map((user) => [user.id, user]));
taskUsers.forEach((user) => {
if (!userMap.has(user.id)) {
userMap.set(user.id, user);
}
});
return Array.from(userMap.values());
}, [getUsers.data, taskDetail?.users]);
const selectedUsers = users.filter((user) => selectedUserIds.has(user.id));
const isLabelsOpen = activeTab === "labels";
const isUsersOpen = activeTab === "users";
@@ -107,15 +126,31 @@ const TaskDetailToolbar: FC<Props> = ({ activeTab, onTabChange, taskDetail, task
};
const handleUserToggle = (id: string) => {
setSelectedUserIds((prev) => {
const next = new Set(prev);
if (next.has(id)) {
next.delete(id);
} else {
next.add(id);
}
return next;
});
const effectiveTaskId = taskId || taskDetail?.id;
if (!effectiveTaskId) return;
const previous = selectedUserIds;
const next = new Set(previous);
if (next.has(id)) {
next.delete(id);
} else {
next.add(id);
}
setSelectedUserIds(next);
updateTask.mutate(
{ id: effectiveTaskId, params: { userIds: Array.from(next) } },
{
onSuccess: () => {
toast.success(t("success"));
},
onError: (error: ErrorType) => {
toast.error(error.response?.data?.error.message[0]);
setSelectedUserIds(previous);
},
},
);
};
const handleCreate = (title: string, color: string) => {
@@ -200,7 +235,13 @@ const TaskDetailToolbar: FC<Props> = ({ activeTab, onTabChange, taskDetail, task
}
usersPopover={
isUsersOpen ? (
<TaskDetailUsersPopover users={users} selectedIds={selectedUserIds} onToggle={handleUserToggle} />
<TaskDetailUsersPopover
users={users}
selectedIds={selectedUserIds}
onToggle={handleUserToggle}
isLoading={getUsers.isPending}
isSubmitting={updateTask.isPending}
/>
) : null
}
checklistPopover={