220 lines
6.8 KiB
JavaScript
220 lines
6.8 KiB
JavaScript
import {useMutation, useQuery} from "@apollo/client";
|
|
import {Form, Modal, notification} from "antd";
|
|
import React, {useEffect, useState} from "react";
|
|
import {useTranslation} from "react-i18next";
|
|
import {connect} from "react-redux";
|
|
import {createStructuredSelector} from "reselect";
|
|
import {
|
|
MUTATION_INSERT_NEW_TASK,
|
|
MUTATION_UPDATE_TASK,
|
|
QUERY_GET_TASK_BY_ID
|
|
} from "../../graphql/tasks.queries";
|
|
import {QUERY_GET_TASKS_JOB_DETAILS_BY_ID} from "../../graphql/jobs.queries.js";
|
|
import {toggleModalVisible} from "../../redux/modals/modals.actions";
|
|
import {selectTaskUpsert} from "../../redux/modals/modals.selectors";
|
|
import {selectBodyshop, selectCurrentUser} from "../../redux/user/user.selectors";
|
|
import TaskUpsertModalComponent from "./task-upsert-modal.component";
|
|
import {replaceUndefinedWithNull} from "../../utils/undefinedtonull.js";
|
|
import {useNavigate} from "react-router-dom";
|
|
|
|
const mapStateToProps = createStructuredSelector({
|
|
currentUser: selectCurrentUser,
|
|
bodyshop: selectBodyshop,
|
|
taskUpsert: selectTaskUpsert,
|
|
});
|
|
const mapDispatchToProps = (dispatch) => ({
|
|
toggleModalVisible: () => dispatch(toggleModalVisible("taskUpsert")),
|
|
});
|
|
|
|
export function TaskUpsertModalContainer({
|
|
bodyshop,
|
|
currentUser,
|
|
taskUpsert,
|
|
toggleModalVisible,
|
|
}) {
|
|
const {t} = useTranslation();
|
|
const history = useNavigate();
|
|
const [insertTask] = useMutation(MUTATION_INSERT_NEW_TASK);
|
|
const [updateTask] = useMutation(MUTATION_UPDATE_TASK);
|
|
const {open, context, actions} = taskUpsert;
|
|
const {jobid, joblineid, billid, partsorderid, taskId, existingTask} = context;
|
|
const {refetch} = actions;
|
|
const [form] = Form.useForm();
|
|
const [selectedJobId, setSelectedJobId] = useState(null);
|
|
const [selectedJobDetails, setSelectedJobDetails] = useState(null);
|
|
const [jobIdState, setJobIdState] = useState(null);
|
|
|
|
const {
|
|
loading: loading,
|
|
error: error,
|
|
data: data
|
|
} = useQuery(QUERY_GET_TASKS_JOB_DETAILS_BY_ID, {
|
|
variables: {id: jobIdState},
|
|
skip: !jobIdState,
|
|
});
|
|
|
|
const {
|
|
loading: taskLoading,
|
|
error: taskError,
|
|
data: taskData
|
|
} = useQuery(QUERY_GET_TASK_BY_ID, {
|
|
variables: {id: taskId},
|
|
skip: !taskId,
|
|
});
|
|
|
|
// This takes care of the ability to deep link a task from the URL (Fills in form fields)
|
|
useEffect(() => {
|
|
if (!taskLoading && !taskError && taskData && taskData?.tasks_by_pk) {
|
|
form.setFieldsValue(taskData.tasks_by_pk);
|
|
setSelectedJobId(taskData.tasks_by_pk.jobid);
|
|
}
|
|
}, [taskLoading, taskError, taskData]);
|
|
|
|
/**
|
|
* Set the selected job id when the modal is opened and jobId is passed as a prop or when an existing task is passed as a prop
|
|
*/
|
|
useEffect(() => {
|
|
if (jobid || existingTask?.id) {
|
|
setSelectedJobId(jobid || existingTask.jobid);
|
|
}
|
|
return () => {
|
|
setSelectedJobId(null);
|
|
};
|
|
}, [jobid, existingTask]);
|
|
|
|
/**
|
|
* Set the form values when the modal is opened and an existing task is passed as a prop
|
|
*/
|
|
useEffect(() => {
|
|
if (existingTask && open) {
|
|
form.setFieldsValue(existingTask);
|
|
} else if (!existingTask && open) {
|
|
form.resetFields();
|
|
if (joblineid) form.setFieldsValue({joblineid});
|
|
if (billid) form.setFieldsValue({billid});
|
|
if (partsorderid) form.setFieldsValue({partsorderid});
|
|
}
|
|
}, [existingTask, form, open, joblineid, billid, partsorderid]);
|
|
|
|
/**
|
|
* Set the job id state when the selected job id changes
|
|
*/
|
|
useEffect(() => {
|
|
if (selectedJobId) {
|
|
// Update the state variable instead of calling useQuery
|
|
setJobIdState(selectedJobId);
|
|
}
|
|
}, [selectedJobId]);
|
|
|
|
/**
|
|
* Set the selected job details when the job details query is successful
|
|
*/
|
|
useEffect(() => {
|
|
if (!loading && !error && data) {
|
|
setSelectedJobDetails(data.jobs_by_pk);
|
|
}
|
|
}, [loading, error, data]);
|
|
|
|
|
|
const removeTaskIdFromUrl = () => {
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
urlParams.delete('taskid');
|
|
history(`${window.location.pathname}?${urlParams}`);
|
|
}
|
|
|
|
/**
|
|
* Handle the form submit
|
|
* @param formValues
|
|
* @returns {Promise<[{jobid, bodyshopid, created_by},...*]>}
|
|
*/
|
|
const handleFinish = async (formValues) => {
|
|
const {...values} = formValues;
|
|
if (existingTask) {
|
|
await updateTask({
|
|
variables: {
|
|
taskId: existingTask.id,
|
|
task: replaceUndefinedWithNull(values)
|
|
},
|
|
});
|
|
window.dispatchEvent(new CustomEvent('taskUpdated', {
|
|
detail: {message: 'A task has been created or edited.'},
|
|
}));
|
|
notification["success"]({
|
|
message: t("tasks.successes.updated"),
|
|
});
|
|
if (refetch) await refetch();
|
|
toggleModalVisible();
|
|
} else {
|
|
await insertTask({
|
|
variables: {
|
|
taskInput: [
|
|
{
|
|
...values,
|
|
created_by: currentUser.email,
|
|
bodyshopid: bodyshop.id
|
|
},
|
|
],
|
|
},
|
|
|
|
// TODO: Consult Patrick, because this fails on relationship data, and an event emitter is just much easier to use
|
|
// update(cache) {
|
|
// cache.modify({
|
|
// fields: {
|
|
// tasks(existingTasks) {
|
|
// return [{
|
|
// ...values,
|
|
// jobid: selectedJobId || values.jobid,
|
|
// created_by: currentUser.email,
|
|
// bodyshopid: bodyshop.id
|
|
// }, ...existingTasks]
|
|
// },
|
|
// },
|
|
// });
|
|
// },
|
|
|
|
});
|
|
if (refetch) await refetch();
|
|
form.resetFields();
|
|
toggleModalVisible();
|
|
window.dispatchEvent(new CustomEvent('taskUpdated', {
|
|
detail: {message: 'A task has been created or edited.'},
|
|
}));
|
|
notification["success"]({
|
|
message: t("tasks.successes.created"),
|
|
});
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Modal
|
|
title={existingTask ? t("tasks.actions.edit") : t("tasks.actions.new")}
|
|
open={open}
|
|
okText={t("general.actions.save")}
|
|
width="50%"
|
|
onOk={() => {
|
|
removeTaskIdFromUrl();
|
|
form.submit();
|
|
}}
|
|
onCancel={() => {
|
|
removeTaskIdFromUrl();
|
|
toggleModalVisible();
|
|
}}
|
|
|
|
destroyOnClose
|
|
>
|
|
<Form form={form} onFinish={handleFinish} layout="vertical">
|
|
<TaskUpsertModalComponent form={form} loading={loading || (taskId && taskLoading)} error={error} data={data}
|
|
selectedJobId={selectedJobId}
|
|
setSelectedJobId={setSelectedJobId}
|
|
selectedJobDetails={selectedJobDetails}/>
|
|
|
|
</Form>
|
|
</Modal>
|
|
);
|
|
}
|
|
|
|
export default connect(
|
|
mapStateToProps,
|
|
mapDispatchToProps
|
|
)(TaskUpsertModalContainer);
|