import { type FC, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { toast } from "react-toastify"; import DefaulModal from "../../../../components/DefaulModal"; import PageLoading from "../../../../components/PageLoading"; import { ErrorType } from "../../../../helpers/types"; import { useChangeTaskPhase, useDeleteTask, useGetTaskDetail, useUpdateTask } from "../../task/hooks/useTaskData"; import { useGetTaskTimes } from "../../task/hooks/useTaskTimeData"; import type { TaskDetailType } from "../../task/types/TaskTypes"; import type { Column, Task } from "../../types"; import AttachmentList from "./attachment/List"; import CheckLists from "./checklist/List"; import TimeList from "./time/List"; import TaskDetailCoverColorBar from "./cover/TaskDetailCoverColorBar"; import TaskDetailDescription from "./TaskDetailDescription"; import TaskDetailHeader from "./TaskDetailHeader"; import TaskDetailToolbar from "./TaskDetailToolbar"; import type { TaskDetailTab } from "./types"; type Props = { open: boolean; task: Task | null; columns: Column[]; projectId: string; onClose: () => void; onTaskPhaseChanged?: (taskId: string, taskPhaseId: string) => void; }; const TaskDetailModal: FC = ({ open, task, columns, projectId, onClose, onTaskPhaseChanged }) => { const { t } = useTranslation("global"); const [activeTab, setActiveTab] = useState(null); const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); const [color, setColor] = useState(null); const initialTitleRef = useRef(""); const initialDescriptionRef = useRef(""); const getTaskDetail = useGetTaskDetail(task?.id ?? "", open && !!task?.id); const getTaskTimes = useGetTaskTimes(task?.id ?? "", open && !!task?.id); const updateTask = useUpdateTask(); const changeTaskPhase = useChangeTaskPhase(); const deleteTask = useDeleteTask(); const rawTaskDetail = getTaskDetail.data?.data; const taskDetail: TaskDetailType | undefined = rawTaskDetail ? { ...rawTaskDetail, id: rawTaskDetail.id ?? task?.id ?? "", labels: rawTaskDetail.labels ?? rawTaskDetail.remarks, } : undefined; useEffect(() => { if (!open) { setActiveTab(null); setTitle(""); setDescription(""); setColor(null); initialTitleRef.current = ""; initialDescriptionRef.current = ""; } }, [open]); useEffect(() => { if (!rawTaskDetail) return; setTitle(rawTaskDetail.title); setDescription(rawTaskDetail.description ?? ""); setColor(rawTaskDetail.color || null); initialTitleRef.current = rawTaskDetail.title; initialDescriptionRef.current = rawTaskDetail.description ?? ""; }, [rawTaskDetail]); if (!task) return null; const selectedPhaseId = task.columnId || taskDetail?.taskPhaseId || ""; const handleTabChange = (tab: TaskDetailTab) => { setActiveTab((prev) => (prev === tab ? null : tab)); }; const handleDelete = () => { if (!task.id) return; deleteTask.mutate( { id: task.id, projectId: taskDetail?.projectId ?? "" }, { onSuccess: () => { toast.success(t("taskmanager.task_deleted")); onClose(); }, onError: (error: ErrorType) => { toast.error(error.response?.data?.error.message[0]); }, }, ); }; const saveField = (field: "title" | "description", value: string) => { const initialValue = field === "title" ? initialTitleRef.current : initialDescriptionRef.current; if (value === initialValue) return; updateTask.mutate( { id: task.id, params: { [field]: value } }, { onSuccess: () => { if (field === "title") { initialTitleRef.current = value; } else { initialDescriptionRef.current = value; } toast.success(t("success")); }, onError: (error: ErrorType) => { toast.error(error.response?.data?.error.message[0]); if (field === "title") { setTitle(initialTitleRef.current); } else { setDescription(initialDescriptionRef.current); } }, }, ); }; const handleColorChange = (newColor: string | null) => { const previousColor = color; setColor(newColor); updateTask.mutate( { id: task.id, params: { color: newColor ?? "" } }, { onSuccess: () => { toast.success(t("success")); }, onError: (error: ErrorType) => { setColor(previousColor); toast.error(error.response?.data?.error.message[0]); }, }, ); }; const handlePhaseChange = (taskPhaseId: string) => { if (taskPhaseId === selectedPhaseId) return; changeTaskPhase.mutate( { id: task.id, params: { taskPhaseId }, projectId: taskDetail?.projectId ?? projectId }, { onSuccess: () => { onTaskPhaseChanged?.(task.id, taskPhaseId); toast.success(t("success")); }, onError: (error: ErrorType) => { toast.error(error.response?.data?.error.message[0]); }, }, ); }; return ( {getTaskDetail.isPending ? ( ) : ( <> handleColorChange(newColor)} isUpdatingColor={updateTask.isPending} onClose={onClose} onDelete={handleDelete} isDeleting={deleteTask.isPending} /> {color ? ( handleColorChange(null)} isRemoving={updateTask.isPending} /> ) : null} setTitle(e.target.value)} onBlur={() => saveField("title", title)} className="mt-6 w-full text-sm font-bold bg-transparent outline-none" />
saveField("description", description)} isSaving={updateTask.isPending} /> )}
); }; export default TaskDetailModal;