From e1fe0303164bf0352da4c00293a3dd03dbd9afed Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sun, 12 Jul 2026 12:15:55 +0330 Subject: [PATCH] setting date --- .../task-detail/TaskDetailToolbar.tsx | 55 +++++++++++++------ .../task-detail/date/TaskDetailDateForm.tsx | 34 +++++++++--- .../date/TaskDetailDatePopover.tsx | 21 ++++++- .../components/task-detail/date/utils.ts | 12 ++++ 4 files changed, 95 insertions(+), 27 deletions(-) diff --git a/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx b/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx index 8dae7ba..7bbac34 100644 --- a/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx +++ b/src/pages/taskmanager/components/task-detail/TaskDetailToolbar.tsx @@ -3,12 +3,9 @@ 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"; +import { parseApiDate, toApiDate } from "./date/utils"; 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 TaskDetailChecklistPopover from "./checklist/TaskDetailChecklistPopover"; import TaskDetailLabelsPopover from "./labels/TaskDetailLabelsPopover"; import type { LabelsView, TaskLabel } from "./labels/types"; @@ -28,12 +25,6 @@ type Props = { taskId: string; }; -const parseDate = (value?: string): DateObject | null => { - if (!value) return null; - const date = new DateObjectClass({ date: value, calendar: persian, locale: persian_fa }); - return date.isValid ? date : null; -}; - const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, taskId }) => { const { t } = useTranslation("global"); const createTaskRemark = useCreateTaskRemark(); @@ -46,8 +37,8 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task const [labels, setLabels] = useState([]); const [selectedLabelIds, setSelectedLabelIds] = useState>(new Set()); const [selectedUserIds, setSelectedUserIds] = useState>(new Set()); - const [startDate, setStartDate] = useState(DEFAULT_DATE_RANGE.startDate); - const [endDate, setEndDate] = useState(DEFAULT_DATE_RANGE.endDate); + const [startDate, setStartDate] = useState(null); + const [endDate, setEndDate] = useState(null); useEffect(() => { if (!taskDetail) return; @@ -68,10 +59,8 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task setSelectedUserIds(new Set()); } - const parsedStartDate = parseDate(taskDetail.startDate); - const parsedEndDate = parseDate(taskDetail.endDate); - if (parsedStartDate) setStartDate(parsedStartDate); - if (parsedEndDate) setEndDate(parsedEndDate); + setStartDate(parseApiDate(taskDetail.startDate)); + setEndDate(parseApiDate(taskDetail.endDate)); }, [taskDetail]); const selectedLabels = labels.filter((label) => selectedLabelIds.has(label.id)); @@ -252,9 +241,33 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task }; const handleDateSubmit = (data: { startDate: DateObject | null; endDate: DateObject | null }) => { + const effectiveTaskId = taskId || taskDetail?.id; + if (!effectiveTaskId) return; + + const previousStartDate = startDate; + const previousEndDate = endDate; + const params = { + startDate: data.startDate ? toApiDate(data.startDate) : null, + endDate: data.endDate ? toApiDate(data.endDate) : null, + }; + setStartDate(data.startDate); setEndDate(data.endDate); - handleDateClose(); + + updateTask.mutate( + { id: effectiveTaskId, params }, + { + onSuccess: () => { + handleDateClose(); + toast.success(t("success")); + }, + onError: (error: ErrorType) => { + toast.error(error.response?.data?.error.message[0]); + setStartDate(previousStartDate); + setEndDate(previousEndDate); + }, + }, + ); }; return ( @@ -306,7 +319,13 @@ const TaskDetailToolbar: FC = ({ activeTab, onTabChange, taskDetail, task } datePopover={ isDateOpen ? ( - + ) : null } /> diff --git a/src/pages/taskmanager/components/task-detail/date/TaskDetailDateForm.tsx b/src/pages/taskmanager/components/task-detail/date/TaskDetailDateForm.tsx index 6073c9c..633da3c 100644 --- a/src/pages/taskmanager/components/task-detail/date/TaskDetailDateForm.tsx +++ b/src/pages/taskmanager/components/task-detail/date/TaskDetailDateForm.tsx @@ -12,14 +12,23 @@ import { formatDateLabel } from "./utils"; type Props = { onClose: () => void; onSubmit: (data: { startDate: DateObject | null; endDate: DateObject | null }) => void; + initialStartDate?: DateObject | null; + initialEndDate?: DateObject | null; + isSubmitting?: boolean; }; -const TaskDetailDateForm: FC = ({ onClose, onSubmit }) => { +const TaskDetailDateForm: FC = ({ + onClose, + onSubmit, + initialStartDate = null, + initialEndDate = null, + isSubmitting = false, +}) => { const { t } = useTranslation("global"); - const [startDate, setStartDate] = useState(null); - const [endDate, setEndDate] = useState(null); - const [startEnabled, setStartEnabled] = useState(true); - const [endEnabled, setEndEnabled] = useState(false); + const [startDate, setStartDate] = useState(initialStartDate); + const [endDate, setEndDate] = useState(initialEndDate); + const [startEnabled, setStartEnabled] = useState(Boolean(initialStartDate) || !initialEndDate); + const [endEnabled, setEndEnabled] = useState(Boolean(initialEndDate)); const [activeField, setActiveField] = useState("start"); const calendarValue = (() => { @@ -135,10 +144,21 @@ const TaskDetailDateForm: FC = ({ onClose, onSubmit }) => {
- -
diff --git a/src/pages/taskmanager/components/task-detail/date/TaskDetailDatePopover.tsx b/src/pages/taskmanager/components/task-detail/date/TaskDetailDatePopover.tsx index 233d8ef..c2e38ee 100644 --- a/src/pages/taskmanager/components/task-detail/date/TaskDetailDatePopover.tsx +++ b/src/pages/taskmanager/components/task-detail/date/TaskDetailDatePopover.tsx @@ -5,10 +5,27 @@ import TaskDetailDateForm from "./TaskDetailDateForm"; type Props = { onClose: () => void; onSubmit: (data: { startDate: DateObject | null; endDate: DateObject | null }) => void; + initialStartDate?: DateObject | null; + initialEndDate?: DateObject | null; + isSubmitting?: boolean; }; -const TaskDetailDatePopover: FC = ({ onClose, onSubmit }) => { - return ; +const TaskDetailDatePopover: FC = ({ + onClose, + onSubmit, + initialStartDate, + initialEndDate, + isSubmitting, +}) => { + return ( + + ); }; export default TaskDetailDatePopover; diff --git a/src/pages/taskmanager/components/task-detail/date/utils.ts b/src/pages/taskmanager/components/task-detail/date/utils.ts index e2fe4a4..b64ab02 100644 --- a/src/pages/taskmanager/components/task-detail/date/utils.ts +++ b/src/pages/taskmanager/components/task-detail/date/utils.ts @@ -1,7 +1,19 @@ import DateObject from "react-date-object"; +import gregorian from "react-date-object/calendars/gregorian"; import persian from "react-date-object/calendars/persian"; +import gregorian_en from "react-date-object/locales/gregorian_en"; import persian_fa from "react-date-object/locales/persian_fa"; +export const parseApiDate = (value?: string | null): DateObject | null => { + if (!value) return null; + const date = new DateObject({ date: value, calendar: gregorian }); + return date.isValid ? date : null; +}; + +export const toApiDate = (date: DateObject): string => { + return date.convert(gregorian, gregorian_en).format("YYYY-MM-DD"); +}; + export const formatDateLabel = (date: DateObject | null) => { if (!date) return ""; return date.convert(persian, persian_fa).format("D MMMM");