setting date
This commit is contained in:
@@ -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<Props> = ({ activeTab, onTabChange, taskDetail, taskId }) => {
|
||||
const { t } = useTranslation("global");
|
||||
const createTaskRemark = useCreateTaskRemark();
|
||||
@@ -46,8 +37,8 @@ const TaskDetailToolbar: FC<Props> = ({ activeTab, onTabChange, taskDetail, task
|
||||
const [labels, setLabels] = useState<TaskLabel[]>([]);
|
||||
const [selectedLabelIds, setSelectedLabelIds] = useState<Set<string>>(new Set());
|
||||
const [selectedUserIds, setSelectedUserIds] = useState<Set<string>>(new Set());
|
||||
const [startDate, setStartDate] = useState<DateObject | null>(DEFAULT_DATE_RANGE.startDate);
|
||||
const [endDate, setEndDate] = useState<DateObject | null>(DEFAULT_DATE_RANGE.endDate);
|
||||
const [startDate, setStartDate] = useState<DateObject | null>(null);
|
||||
const [endDate, setEndDate] = useState<DateObject | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!taskDetail) return;
|
||||
@@ -68,10 +59,8 @@ const TaskDetailToolbar: FC<Props> = ({ 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<Props> = ({ 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<Props> = ({ activeTab, onTabChange, taskDetail, task
|
||||
}
|
||||
datePopover={
|
||||
isDateOpen ? (
|
||||
<TaskDetailDatePopover onClose={handleDateClose} onSubmit={handleDateSubmit} />
|
||||
<TaskDetailDatePopover
|
||||
onClose={handleDateClose}
|
||||
onSubmit={handleDateSubmit}
|
||||
initialStartDate={startDate}
|
||||
initialEndDate={endDate}
|
||||
isSubmitting={updateTask.isPending}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -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<Props> = ({ onClose, onSubmit }) => {
|
||||
const TaskDetailDateForm: FC<Props> = ({
|
||||
onClose,
|
||||
onSubmit,
|
||||
initialStartDate = null,
|
||||
initialEndDate = null,
|
||||
isSubmitting = false,
|
||||
}) => {
|
||||
const { t } = useTranslation("global");
|
||||
const [startDate, setStartDate] = useState<DateObject | null>(null);
|
||||
const [endDate, setEndDate] = useState<DateObject | null>(null);
|
||||
const [startEnabled, setStartEnabled] = useState(true);
|
||||
const [endEnabled, setEndEnabled] = useState(false);
|
||||
const [startDate, setStartDate] = useState<DateObject | null>(initialStartDate);
|
||||
const [endDate, setEndDate] = useState<DateObject | null>(initialEndDate);
|
||||
const [startEnabled, setStartEnabled] = useState(Boolean(initialStartDate) || !initialEndDate);
|
||||
const [endEnabled, setEndEnabled] = useState(Boolean(initialEndDate));
|
||||
const [activeField, setActiveField] = useState<TaskDateField>("start");
|
||||
|
||||
const calendarValue = (() => {
|
||||
@@ -135,10 +144,21 @@ const TaskDetailDateForm: FC<Props> = ({ onClose, onSubmit }) => {
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button type="button" onClick={onClose} className="h-8 bg-[#E8E4F0] text-[#292D32] rounded-xl text-xs w-[95px]">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
disabled={isSubmitting}
|
||||
className="h-8 bg-[#E8E4F0] text-[#292D32] rounded-xl text-xs w-[95px]"
|
||||
>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
<Button type="button" onClick={handleSubmit} disabled={!canSubmit} className="h-8 bg-[#292D32] text-white rounded-xl text-xs disabled:opacity-50 w-[95px]">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={handleSubmit}
|
||||
disabled={!canSubmit || isSubmitting}
|
||||
isLoading={isSubmitting}
|
||||
className="h-8 bg-[#292D32] text-white rounded-xl text-xs disabled:opacity-50 w-[95px]"
|
||||
>
|
||||
{t("taskmanager.task_detail.insert")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -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<Props> = ({ onClose, onSubmit }) => {
|
||||
return <TaskDetailDateForm onClose={onClose} onSubmit={onSubmit} />;
|
||||
const TaskDetailDatePopover: FC<Props> = ({
|
||||
onClose,
|
||||
onSubmit,
|
||||
initialStartDate,
|
||||
initialEndDate,
|
||||
isSubmitting,
|
||||
}) => {
|
||||
return (
|
||||
<TaskDetailDateForm
|
||||
onClose={onClose}
|
||||
onSubmit={onSubmit}
|
||||
initialStartDate={initialStartDate}
|
||||
initialEndDate={initialEndDate}
|
||||
isSubmitting={isSubmitting}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default TaskDetailDatePopover;
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user