diff --git a/client/src/components/task-list/task-list.component.jsx b/client/src/components/task-list/task-list.component.jsx index 4116a27ed..f97171c89 100644 --- a/client/src/components/task-list/task-list.component.jsx +++ b/client/src/components/task-list/task-list.component.jsx @@ -163,7 +163,7 @@ function TaskListComponent({ width: "8%", render: (text, record) => record.job ? ( - {record.job.ro_number || t("general.labels.na")} + {record.job.ro_number || t("general.labels.na")} ) : ( t("general.labels.na") ) diff --git a/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx b/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx index 344e1fb89..8c7387cc2 100644 --- a/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx +++ b/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx @@ -27,12 +27,13 @@ export function TaskUpsertModalComponent({ selectedJobId, setSelectedJobId, selectedJobDetails, + existingTask, loading, error }) { const { t } = useTranslation(); const datePickerPresets = [ - { label: t("tasks.date_presets.today"), value: dayjs() }, + { label: t("tasks.date_presets.today"), value: dayjs().add(1, "hour") }, { label: t("tasks.date_presets.tomorrow"), value: dayjs().add(1, "day") }, { label: t("tasks.date_presets.next_week"), value: dayjs().add(1, "week") }, { label: t("tasks.date_presets.two_weeks"), value: dayjs().add(2, "weeks") }, @@ -195,11 +196,38 @@ export function TaskUpsertModalComponent({ - + { + if (!value || existingTask?.due_date === value || dayjs(value).isAfter(dayjs())) { + return Promise.resolve(); + } + return Promise.reject(new Error(t("tasks.validation.due_at_error_message"))); + } + } + ]} + /> - + { + if (!value || existingTask?.remind_at === value || dayjs(value).isAfter(dayjs().add(30, "minute"))) { + return Promise.resolve(); + } + return Promise.reject(new Error(t("tasks.validation.remind_at_error_message"))); + } + } + ]} + > diff --git a/client/src/components/task-upsert-modal/task-upsert-modal.container.jsx b/client/src/components/task-upsert-modal/task-upsert-modal.container.jsx index a2df073b6..3af9651dd 100644 --- a/client/src/components/task-upsert-modal/task-upsert-modal.container.jsx +++ b/client/src/components/task-upsert-modal/task-upsert-modal.container.jsx @@ -16,6 +16,7 @@ import axios from "axios"; import dayjs from "../../utils/day"; import { insertAuditTrail } from "../../redux/application/application.actions.js"; import AuditTrailMapping from "../../utils/AuditTrailMappings.js"; +import { isEqual } from "lodash"; const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, @@ -33,13 +34,13 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to const history = useNavigate(); const [insertTask] = useMutation(MUTATION_INSERT_NEW_TASK); const [updateTask] = useMutation(MUTATION_UPDATE_TASK); - const { open, context, actions } = taskUpsert; + const { open, context } = taskUpsert; const { jobid, joblineid, billid, partsorderid, taskId, existingTask, query } = context; - const { refetch } = actions; const [form] = Form.useForm(); const [selectedJobId, setSelectedJobId] = useState(null); const [selectedJobDetails, setSelectedJobDetails] = useState(null); const [jobIdState, setJobIdState] = useState(null); + const [isTouched, setIsTouched] = useState(false); const { loading, error, data } = useQuery(QUERY_GET_TASKS_JOB_DETAILS_BY_ID, { variables: { id: jobIdState }, @@ -91,6 +92,7 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to } return () => { setSelectedJobId(null); + setIsTouched(false); }; }, [jobid, existingTask, form, open, joblineid, billid, partsorderid]); @@ -164,8 +166,6 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to message: t("tasks.successes.updated") }); - if (refetch) await refetch(); - toggleModalVisible(); }; @@ -181,19 +181,6 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to ] }, refetchQueries: ["GET_JOB_BY_PK"] - // update(cache, { data }) { - // cache.modify({ - // fields: { - // tasks(cached) { - // const newTasks = data?.insert_tasks?.returning.map(task => cache.writeFragment({ - // data: task, - // fragment: PARTIAL_TASK_FIELDS_WRAPPER - // })); - // return [...cached, ...newTasks]; - // } - // } - // }); - // } }; if (query && Object.keys(query).length) { @@ -213,8 +200,6 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to }); } - if (refetch) await refetch(); - form.resetFields(); toggleModalVisible(); @@ -253,12 +238,16 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to * @returns {Promise<[{jobid, bodyshopid, created_by},...*]>} */ const handleFinish = async (formValues) => { - const { ...values } = formValues; - if (existingTask) { - await handleExistingTask(values); + const dirtyValues = Object.keys(formValues).reduce((acc, key) => { + if (!isEqual(formValues[key], existingTask[key])) { + acc[key] = formValues[key]; + } + return acc; + }, {}); + await handleExistingTask(dirtyValues); } else { - await handleNewTask(values); + await handleNewTask(formValues); } }; @@ -276,14 +265,23 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to removeTaskIdFromUrl(); toggleModalVisible(); }} + okButtonProps={{ disabled: !isTouched }} destroyOnClose > -
+ { + setIsTouched(true); + }} + >