diff --git a/src/pages/taskmanager/components/task-detail/TaskDetailModal.tsx b/src/pages/taskmanager/components/task-detail/TaskDetailModal.tsx index 7c3e643..eb1e430 100644 --- a/src/pages/taskmanager/components/task-detail/TaskDetailModal.tsx +++ b/src/pages/taskmanager/components/task-detail/TaskDetailModal.tsx @@ -150,7 +150,11 @@ const TaskDetailModal: FC = ({ open, task, statusLabel, onClose }) => { - + )} diff --git a/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx b/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx index adf2af8..09d4f8b 100644 --- a/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx +++ b/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx @@ -9,9 +9,7 @@ import type DateObject from "react-date-object"; import DateObjectClass from "react-date-object"; import persian from "react-date-object/calendars/persian"; import persian_fa from "react-date-object/locales/persian_fa"; -import { DEFAULT_CHECKLISTS } from "./checklist/constants"; import TaskDetailChecklistPopover from "./checklist/TaskDetailChecklistPopover"; -import type { TaskChecklist } from "./checklist/types"; import TaskDetailLabelsPopover from "./labels/TaskDetailLabelsPopover"; import type { LabelsView, TaskLabel } from "./labels/types"; import TaskDetailActionBar from "./TaskDetailActionBar"; @@ -19,7 +17,7 @@ import TaskDetailMetadataPreview from "./TaskDetailMetadataPreview"; import type { TaskDetailTab } from "./types"; import TaskDetailUsersPopover from "./users/TaskDetailUsersPopover"; import type { TaskDetailType } from "../../task/types/TaskTypes"; -import { useCreateTaskRemark, useUpdateTask } from "../../task/hooks/useTaskData"; +import { useCreateCheckListItem, useCreateTaskRemark, useUpdateTask } from "../../task/hooks/useTaskData"; import { ErrorType } from "../../../../helpers/types"; type Props = { @@ -38,13 +36,13 @@ const parseDate = (value?: string): DateObject | null => { const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, taskId }) => { const { t } = useTranslation("global"); const createTaskRemark = useCreateTaskRemark(); + const createCheckListItem = useCreateCheckListItem(); const updateTask = useUpdateTask(); const getUsers = useGetUsers(""); const [labelsView, setLabelsView] = useState("list"); const [labels, setLabels] = useState([]); const [selectedLabelIds, setSelectedLabelIds] = useState>(new Set()); const [selectedUserIds, setSelectedUserIds] = useState>(new Set()); - const [checklists, setChecklists] = useState(DEFAULT_CHECKLISTS); const [startDate, setStartDate] = useState(DEFAULT_DATE_RANGE.startDate); const [endDate, setEndDate] = useState(DEFAULT_DATE_RANGE.endDate); @@ -67,10 +65,6 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task setSelectedUserIds(new Set()); } - if (taskDetail.checklists?.length) { - setChecklists(taskDetail.checklists.map((checklist) => ({ id: checklist.id, title: checklist.title }))); - } - const parsedStartDate = parseDate(taskDetail.startDate); const parsedEndDate = parseDate(taskDetail.endDate); if (parsedStartDate) setStartDate(parsedStartDate); @@ -188,13 +182,22 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task if (isChecklistOpen) onTabChange("checklist"); }; - const handleChecklistCreate = (title: string, _copyFromId: string) => { - const newChecklist: TaskChecklist = { - id: crypto.randomUUID(), - title, - }; - setChecklists((prev) => [...prev, newChecklist]); - handleChecklistClose(); + const handleChecklistCreate = (title: string) => { + const effectiveTaskId = taskId || taskDetail?.id; + if (!effectiveTaskId) return; + + createCheckListItem.mutate( + { title, isDone: false, taskId: effectiveTaskId }, + { + onSuccess: () => { + handleChecklistClose(); + toast.success(t("success")); + }, + onError: (error: ErrorType) => { + toast.error(error.response?.data?.error.message[0]); + }, + }, + ); }; const handleAttachmentClose = () => { @@ -247,9 +250,9 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task checklistPopover={ isChecklistOpen ? ( ) : null } diff --git a/src/pages/taskmanager/components/task-detail/checklist/List.tsx b/src/pages/taskmanager/components/task-detail/checklist/List.tsx index 11cb1fc..7ac3345 100644 --- a/src/pages/taskmanager/components/task-detail/checklist/List.tsx +++ b/src/pages/taskmanager/components/task-detail/checklist/List.tsx @@ -1,26 +1,31 @@ import { Edit } from "iconsax-react"; import ProgressBar from "../../../../../components/ProgressBar"; import TrashWithConfrim from "../../../../../components/TrashWithConfrim"; -import type { TaskChecklistType } from "../../../task/types/TaskTypes"; +import type { TaskChecklistItemType } from "../../../task/types/TaskTypes"; import ChecklistItem from "./ChecklistItem"; type Props = { - checklists?: TaskChecklistType[]; + checkListItems?: TaskChecklistItemType[]; + checkListItemCount?: number; + completedCheckListItemCount?: number; }; -const CheckLists = ({ checklists = [] }: Props) => { - const items = checklists.flatMap((checklist) => - checklist.items.map((item) => ({ - id: item.id, - title: item.title, - checked: item.isDone, - })), - ); +const CheckLists = ({ + checkListItems = [], + checkListItemCount, + completedCheckListItemCount, +}: Props) => { + const items = checkListItems.map((item) => ({ + id: item.id, + title: item.title, + checked: item.isDone, + })); - const doneCount = items.filter((item) => item.checked).length; - const progress = items.length > 0 ? Math.round((doneCount / items.length) * 100) : 0; + const totalCount = checkListItemCount ?? items.length; + const doneCount = completedCheckListItemCount ?? items.filter((item) => item.checked).length; + const progress = totalCount > 0 ? Math.round((doneCount / totalCount) * 100) : 0; - if (checklists.length === 0) return null; + if (checkListItems.length === 0) return null; return (
diff --git a/src/pages/taskmanager/components/task-detail/checklist/TaskDetailChecklistForm.tsx b/src/pages/taskmanager/components/task-detail/checklist/TaskDetailChecklistForm.tsx index 1d71bc5..046f306 100644 --- a/src/pages/taskmanager/components/task-detail/checklist/TaskDetailChecklistForm.tsx +++ b/src/pages/taskmanager/components/task-detail/checklist/TaskDetailChecklistForm.tsx @@ -3,26 +3,21 @@ import { type FC, useState } from "react"; import { useTranslation } from "react-i18next"; import Button from "../../../../../components/Button"; import Input from "../../../../../components/Input"; -import Select from "../../../../../components/Select"; -import type { TaskChecklist } from "./types"; type Props = { - checklists: TaskChecklist[]; onClose: () => void; - onSubmit: (title: string, copyFromId: string) => void; + onSubmit: (title: string) => void; + isSubmitting?: boolean; }; -const TaskDetailChecklistForm: FC = ({ checklists, onClose, onSubmit }) => { +const TaskDetailChecklistForm: FC = ({ onClose, onSubmit, isSubmitting = false }) => { const { t } = useTranslation("global"); const [title, setTitle] = useState(""); - const [copyFromId, setCopyFromId] = useState(""); - - const copyFromItems = [{ value: "", label: t("taskmanager.task_detail.none") }, ...checklists.map((checklist) => ({ value: checklist.id, label: checklist.title }))]; const handleSubmit = () => { const trimmed = title.trim(); if (!trimmed) return; - onSubmit(trimmed, copyFromId); + onSubmit(trimmed); }; return ( @@ -36,20 +31,16 @@ const TaskDetailChecklistForm: FC = ({ checklists, onClose, onSubmit }) = setTitle(e.target.value)} className="h-8 bg-white/63 border-white" labelClassName="text-xs" /> -