@@ -46,14 +46,6 @@ export default function TaskListContainer({bodyshop, currentUser}) {
|
|||||||
refetch().catch((e) => {
|
refetch().catch((e) => {
|
||||||
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
|
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
|
||||||
}); };
|
}); };
|
||||||
|
|
||||||
window.addEventListener('taskUpdated', handleTaskUpdated);
|
|
||||||
window.addEventListener('taskCreated', handleTaskUpdated);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('taskUpdated', handleTaskUpdated);
|
|
||||||
window.removeEventListener('taskCreated', handleTaskUpdated);
|
|
||||||
};
|
|
||||||
}, [refetch]);
|
}, [refetch]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import {Col, Form, Input, Row, Select, Switch} from "antd";
|
import {Col, Form, Input, Row, Select, Switch} from "antd";
|
||||||
import React from "react";
|
import React, {useCallback} from "react";
|
||||||
import {useTranslation} from "react-i18next";
|
import {useTranslation} from "react-i18next";
|
||||||
import {FormDatePicker} from "../form-date-picker/form-date-picker.component.jsx";
|
import {FormDatePicker} from "../form-date-picker/form-date-picker.component.jsx";
|
||||||
import {createStructuredSelector} from "reselect";
|
import {createStructuredSelector} from "reselect";
|
||||||
import {selectBodyshop} from "../../redux/user/user.selectors.js";
|
import {selectBodyshop} from "../../redux/user/user.selectors.js";
|
||||||
|
|
||||||
import {connect} from "react-redux";
|
import {connect} from "react-redux";
|
||||||
|
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component.jsx";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -18,12 +20,54 @@ export default connect(
|
|||||||
)(TaskUpsertModalComponent);
|
)(TaskUpsertModalComponent);
|
||||||
|
|
||||||
|
|
||||||
export function TaskUpsertModalComponent({form, bodyshop}) {
|
export function TaskUpsertModalComponent({
|
||||||
|
form,
|
||||||
|
bodyshop,
|
||||||
|
selectedJobId,
|
||||||
|
setSelectedJobId,
|
||||||
|
selectedJobDetails,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
data
|
||||||
|
}) {
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
|
|
||||||
|
console.dir(data)
|
||||||
|
|
||||||
|
if (loading || error) return <LoadingSkeleton active/>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={8}>
|
<Col span={18}>
|
||||||
|
<Form.Item
|
||||||
|
label={t("tasks.fields.title")}
|
||||||
|
name="title"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input placeholder={t("tasks.labels.titleplaceholder")}/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={4}>
|
||||||
|
<Form.Item
|
||||||
|
label={t("tasks.fields.priority")}
|
||||||
|
name="priority"
|
||||||
|
initialValue={1}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
options={[
|
||||||
|
{value: 3, label: t("tasks.fields.priority.low")},
|
||||||
|
{value: 2, label: t("tasks.fields.priority.medium")},
|
||||||
|
{value: 1, label: t("tasks.fields.priority.high")},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={2}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("tasks.fields.completed")}
|
label={t("tasks.fields.completed")}
|
||||||
name="completed"
|
name="completed"
|
||||||
@@ -32,6 +76,8 @@ export function TaskUpsertModalComponent({form, bodyshop}) {
|
|||||||
<Switch/>
|
<Switch/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("tasks.fields.assigned_to")}
|
label={t("tasks.fields.assigned_to")}
|
||||||
@@ -47,45 +93,6 @@ export function TaskUpsertModalComponent({form, bodyshop}) {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
<Form.Item
|
|
||||||
label={t("tasks.fields.priority")}
|
|
||||||
name="priority"
|
|
||||||
initialValue={1}
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
options={[
|
|
||||||
{value: 3, label: t("tasks.fields.priority.low")},
|
|
||||||
{value: 2, label: t("tasks.fields.priority.medium")},
|
|
||||||
{value: 1, label: t("tasks.fields.priority.high")},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</Col>
|
|
||||||
<Col span={24}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("tasks.fields.title")}
|
|
||||||
name="title"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input placeholder={t("tasks.labels.titleplaceholder")}/>
|
|
||||||
</Form.Item>
|
|
||||||
</Col>
|
|
||||||
<Col span={24}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("tasks.fields.description")}
|
|
||||||
name="description"
|
|
||||||
>
|
|
||||||
<Input.TextArea
|
|
||||||
rows={4}
|
|
||||||
placeholder={t("tasks.labels.descriptionplaceholder")}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</Col>
|
|
||||||
<Col span={24}>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("tasks.fields.due_date")}
|
label={t("tasks.fields.due_date")}
|
||||||
name="due_date"
|
name="due_date"
|
||||||
@@ -93,7 +100,7 @@ export function TaskUpsertModalComponent({form, bodyshop}) {
|
|||||||
<FormDatePicker/>
|
<FormDatePicker/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={8}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("tasks.fields.remind_at")}
|
label={t("tasks.fields.remind_at")}
|
||||||
name="remind_at"
|
name="remind_at"
|
||||||
@@ -101,13 +108,55 @@ export function TaskUpsertModalComponent({form, bodyshop}) {
|
|||||||
<FormDatePicker/>
|
<FormDatePicker/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
|
<Col span={24}>
|
||||||
|
<Form.Item
|
||||||
|
label={t("tasks.fields.description")}
|
||||||
|
name="description"
|
||||||
|
>
|
||||||
|
<Input.TextArea
|
||||||
|
rows={8}
|
||||||
|
placeholder={t("tasks.labels.descriptionplaceholder")}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
|
<Col span={24}>
|
||||||
|
<Form.Item
|
||||||
|
name="jobid"
|
||||||
|
label="Job ID"
|
||||||
|
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: 'Please select a Job ID',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Select placeholder="Select a Job ID" defaultValue={selectedJobId} onSelect={setSelectedJobId}>
|
||||||
|
{data.jobs.map((job) => (
|
||||||
|
<Select.Option key={job.id} value={job.id}>
|
||||||
|
{job.ro_number}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("tasks.fields.joblineid")}
|
label={t("tasks.fields.joblineid")}
|
||||||
name="joblineid"
|
name="joblineid"
|
||||||
>
|
>
|
||||||
<Select placeholder={t("tasks.labels.joblineidplaceholder")}>
|
<Select placeholder={t("tasks.labels.joblineidplaceholder")} disabled={!selectedJobDetails}>
|
||||||
{/* Add your options here */}
|
{selectedJobDetails?.joblines?.map((jobline) => (
|
||||||
|
<Select.Option key={jobline.id} value={jobline.id}>
|
||||||
|
{jobline.line_desc}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
@@ -116,7 +165,7 @@ export function TaskUpsertModalComponent({form, bodyshop}) {
|
|||||||
label={t("tasks.fields.partsorderid")}
|
label={t("tasks.fields.partsorderid")}
|
||||||
name="partsorderid"
|
name="partsorderid"
|
||||||
>
|
>
|
||||||
<Select placeholder={t("tasks.labels.partsorderidplaceholder")}>
|
<Select placeholder={t("tasks.labels.partsorderidplaceholder")} disabled={!selectedJobDetails}>
|
||||||
{/* Add your options here */}
|
{/* Add your options here */}
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -126,7 +175,7 @@ export function TaskUpsertModalComponent({form, bodyshop}) {
|
|||||||
label={t("tasks.fields.billid")}
|
label={t("tasks.fields.billid")}
|
||||||
name="billid"
|
name="billid"
|
||||||
>
|
>
|
||||||
<Select placeholder={t("tasks.labels.billidplaceholder")}>
|
<Select placeholder={t("tasks.labels.billidplaceholder")} disabled={!selectedJobDetails}>
|
||||||
{/* Add your options here */}
|
{/* Add your options here */}
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import {useMutation} from "@apollo/client";
|
import {useMutation, useQuery} from "@apollo/client";
|
||||||
import {Form, Modal, notification} from "antd";
|
import {Form, Modal, notification} from "antd";
|
||||||
import React, {useEffect} from "react";
|
import React, {useEffect, useState} from "react";
|
||||||
import {useTranslation} from "react-i18next";
|
import {useTranslation} from "react-i18next";
|
||||||
import {connect} from "react-redux";
|
import {connect} from "react-redux";
|
||||||
import {createStructuredSelector} from "reselect";
|
import {createStructuredSelector} from "reselect";
|
||||||
import {MUTATION_INSERT_NEW_TASK, MUTATION_UPDATE_TASK} from "../../graphql/tasks.queries";
|
import {MUTATION_INSERT_NEW_TASK, MUTATION_UPDATE_TASK} from "../../graphql/tasks.queries";
|
||||||
|
import {
|
||||||
|
QUERY_GET_TASKS_JOB_DETAILS,
|
||||||
|
QUERY_GET_TASKS_JOB_DETAILS_BY_ID
|
||||||
|
} from "../../graphql/jobs.queries.js";
|
||||||
import {toggleModalVisible} from "../../redux/modals/modals.actions";
|
import {toggleModalVisible} from "../../redux/modals/modals.actions";
|
||||||
import {selectTaskUpsert} from "../../redux/modals/modals.selectors";
|
import {selectTaskUpsert} from "../../redux/modals/modals.selectors";
|
||||||
import {selectBodyshop, selectCurrentUser} from "../../redux/user/user.selectors";
|
import {selectBodyshop, selectCurrentUser} from "../../redux/user/user.selectors";
|
||||||
@@ -33,7 +37,33 @@ export function TaskUpsertModalContainer({
|
|||||||
const {jobId, existingTask} = context;
|
const {jobId, existingTask} = context;
|
||||||
const {refetch} = actions;
|
const {refetch} = actions;
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
const [selectedJobId, setSelectedJobId] = useState(null);
|
||||||
|
const [selectedJobDetails, setSelectedJobDetails] = useState(null);
|
||||||
|
const [jobIdState, setJobIdState] = useState(null);
|
||||||
|
|
||||||
|
|
||||||
|
const {
|
||||||
|
loading: jobDetailsLoading,
|
||||||
|
error: jobDetailsError,
|
||||||
|
data: jobDetailsData
|
||||||
|
} = useQuery(QUERY_GET_TASKS_JOB_DETAILS_BY_ID, {
|
||||||
|
variables: {id: jobIdState},
|
||||||
|
skip: !jobIdState, // Skip the query if jobIdState is null
|
||||||
|
});
|
||||||
|
const {loading, error, data} = useQuery(QUERY_GET_TASKS_JOB_DETAILS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}, [jobId, existingTask]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the form values when the modal is opened and an existing task is passed as a prop
|
||||||
|
*/
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (existingTask && open) {
|
if (existingTask && open) {
|
||||||
form.setFieldsValue(existingTask);
|
form.setFieldsValue(existingTask);
|
||||||
@@ -42,37 +72,72 @@ export function TaskUpsertModalContainer({
|
|||||||
}
|
}
|
||||||
}, [existingTask, form, open]);
|
}, [existingTask, form, open]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the form values when the selected job id changes
|
||||||
|
*/
|
||||||
|
useEffect(() => {
|
||||||
|
form.setFieldsValue({
|
||||||
|
joblineid: undefined,
|
||||||
|
billid: undefined,
|
||||||
|
partsorderid: undefined,
|
||||||
|
});
|
||||||
|
}, [selectedJobId, form]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 (!jobDetailsLoading && !jobDetailsError && jobDetailsData) {
|
||||||
|
setSelectedJobDetails(jobDetailsData.jobs_by_pk);
|
||||||
|
}
|
||||||
|
}, [jobDetailsLoading, jobDetailsError, jobDetailsData]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the form submit
|
||||||
|
* @param formValues
|
||||||
|
* @returns {Promise<[{jobid, bodyshopid, created_by},...*]>}
|
||||||
|
*/
|
||||||
const handleFinish = async (formValues) => {
|
const handleFinish = async (formValues) => {
|
||||||
const {...values} = formValues;
|
const {...values} = formValues;
|
||||||
|
|
||||||
if (existingTask) {
|
if (existingTask) {
|
||||||
updateTask({
|
await updateTask({
|
||||||
variables: {
|
variables: {
|
||||||
taskId: existingTask.id,
|
taskId: existingTask.id,
|
||||||
task: values,
|
task: values,
|
||||||
|
jobid: selectedJobId,
|
||||||
},
|
},
|
||||||
}).then((r) => {
|
|
||||||
notification["success"]({
|
|
||||||
message: t("tasks.successes.updated"),
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
if (refetch) refetch();
|
|
||||||
|
notification["success"]({
|
||||||
|
message: t("tasks.successes.updated"),
|
||||||
|
});
|
||||||
|
if (refetch) await refetch();
|
||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
} else {
|
} else {
|
||||||
await insertTask({
|
await insertTask({
|
||||||
variables: {
|
variables: {
|
||||||
taskInput: [
|
taskInput: [
|
||||||
{...values, jobid: jobId, created_by: currentUser.email, bodyshopid: bodyshop.id},
|
{...values, jobid: selectedJobId, created_by: currentUser.email, bodyshopid: bodyshop.id},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
update(cache) {
|
update(cache) {
|
||||||
cache.modify({
|
cache.modify({
|
||||||
|
|
||||||
fields: {
|
fields: {
|
||||||
tasks(existingTasks) {
|
tasks(existingTasks) {
|
||||||
return [{
|
return [{
|
||||||
...values,
|
...values,
|
||||||
jobid: jobId,
|
jobid: selectedJobId,
|
||||||
created_by: currentUser.email,
|
created_by: currentUser.email,
|
||||||
bodyshopid: bodyshop.id
|
bodyshopid: bodyshop.id
|
||||||
}, ...existingTasks]
|
}, ...existingTasks]
|
||||||
@@ -82,7 +147,7 @@ export function TaskUpsertModalContainer({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (refetch) refetch();
|
if (refetch) await refetch();
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
notification["success"]({
|
notification["success"]({
|
||||||
@@ -96,16 +161,22 @@ export function TaskUpsertModalContainer({
|
|||||||
title={existingTask ? t("tasks.actions.edit") : t("tasks.actions.new")}
|
title={existingTask ? t("tasks.actions.edit") : t("tasks.actions.new")}
|
||||||
open={open}
|
open={open}
|
||||||
okText={t("general.actions.save")}
|
okText={t("general.actions.save")}
|
||||||
|
width="50%"
|
||||||
onOk={() => {
|
onOk={() => {
|
||||||
form.submit();
|
form.submit();
|
||||||
}}
|
}}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
}}
|
}}
|
||||||
|
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
>
|
>
|
||||||
<Form form={form} onFinish={handleFinish} layout="vertical">
|
<Form form={form} onFinish={handleFinish} layout="vertical">
|
||||||
<TaskUpsertModalComponent form={form}/>
|
<TaskUpsertModalComponent form={form} loading={loading} error={error} data={data}
|
||||||
|
selectedJobId={setSelectedJobId}
|
||||||
|
setSelectedJobId={setSelectedJobId}
|
||||||
|
selectedJobDetails={selectedJobDetails}/>
|
||||||
|
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2130,6 +2130,44 @@ export const DELETE_JOB = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const QUERY_GET_TASKS_JOB_DETAILS_BY_ID = gql`
|
||||||
|
query GetTasksJobDetailsById($id: uuid!) {
|
||||||
|
jobs_by_pk(id: $id) {
|
||||||
|
id
|
||||||
|
joblines {
|
||||||
|
id
|
||||||
|
line_desc
|
||||||
|
}
|
||||||
|
bills {
|
||||||
|
id
|
||||||
|
vendor {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
invoice_number
|
||||||
|
}
|
||||||
|
parts_orders {
|
||||||
|
id
|
||||||
|
vendor {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
order_number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const QUERY_GET_TASKS_JOB_DETAILS = gql`
|
||||||
|
query GetTasksJobDetails {
|
||||||
|
jobs {
|
||||||
|
id
|
||||||
|
ro_number
|
||||||
|
ownr_fn
|
||||||
|
ownr_ln
|
||||||
|
ownr_co_nm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const GET_JOB_FOR_CC_CONTRACT = gql`
|
export const GET_JOB_FOR_CC_CONTRACT = gql`
|
||||||
query GET_JOB_FOR_CC_CONTRACT($id: uuid!) {
|
query GET_JOB_FOR_CC_CONTRACT($id: uuid!) {
|
||||||
jobs_by_pk(id: $id) {
|
jobs_by_pk(id: $id) {
|
||||||
|
|||||||
Reference in New Issue
Block a user