- Progress commit

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-03-27 17:00:07 -04:00
parent 301c680bff
commit ae9e9f4b72
9 changed files with 237 additions and 140 deletions

View File

@@ -145,7 +145,7 @@ function TaskListComponent({
key: "priority",
sorter: true,
sortOrder: sortcolumn === "priority" && sortorder,
width: '5%',
width: '8%',
render: (text, record) => <PriorityLabel priority={record.priority}
/>
},
@@ -157,7 +157,6 @@ function TaskListComponent({
<Space direction='horizontal'>
<Button title={t('tasks.buttons.edit')} onClick={() => {
setTaskUpsertContext({
actions: {},
context: {
existingTask: record,
},

View File

@@ -2,15 +2,19 @@ import queryString from "query-string";
import {useLocation} from "react-router-dom";
import {useMutation, useQuery} from "@apollo/client";
import {
MUTATION_TOGGLE_TASK_COMPLETED, MUTATION_TOGGLE_TASK_DELETED,
MUTATION_TOGGLE_TASK_COMPLETED,
MUTATION_TOGGLE_TASK_DELETED,
QUERY_MY_TASKS_PAGINATED
} from "../../graphql/tasks.queries.js";
import {pageLimit} from "../../utils/config.js";
import AlertComponent from "../alert/alert.component.jsx";
import React, {useEffect} from "react";
import TaskListComponent from "./task-list.component.jsx";
import {notification} from "antd";
import {useTranslation} from "react-i18next";
export default function TaskListContainer({bodyshop, currentUser}) {
const {t} = useTranslation();
const searchParams = queryString.parse(useLocation().search);
const {page, sortcolumn, sortorder, deleted, completed} = searchParams;
const {loading, error, data, refetch} = useQuery(
@@ -45,7 +49,8 @@ export default function TaskListContainer({bodyshop, currentUser}) {
const handleTaskUpdated = () => {
refetch().catch((e) => {
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
}); };
});
};
}, [refetch]);
/**
@@ -61,16 +66,26 @@ export default function TaskListContainer({bodyshop, currentUser}) {
*/
const toggleCompletedStatus = async (id, currentStatus) => {
const completed_at = !currentStatus ? new Date().toISOString() : null;
await toggleTaskCompleted({
variables: {
id: id,
completed: !currentStatus,
completed_at: completed_at
}
});
refetch().catch((e) => {
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
}); };
try {
await toggleTaskCompleted({
variables: {
id: id,
completed: !currentStatus,
completed_at: completed_at
}
});
refetch().catch((e) => {
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
});
notification["success"]({
message: t("tasks.successes.completed"),
});
} catch (err) {
notification["error"]({
message: t("tasks.failures.completed"),
});
}
};
/**
* Toggle task deleted mutation
@@ -85,20 +100,30 @@ export default function TaskListContainer({bodyshop, currentUser}) {
*/
const toggleDeletedStatus = async (id, currentStatus) => {
const deleted_at = !currentStatus ? new Date().toISOString() : null;
await toggleTaskDeleted({
variables: {
id: id,
deleted: !currentStatus,
deleted_at: deleted_at
}
});
refetch().catch((e) => {
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
});
try {
await toggleTaskDeleted({
variables: {
id: id,
deleted: !currentStatus,
deleted_at: deleted_at
}
});
refetch().catch((e) => {
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
});
notification["success"]({
message: t("tasks.successes.deleted"),
});
} catch (err) {
notification["error"]({
message: t("tasks.failures.deleted"),
});
}
};
if (error) return <AlertComponent message={error.message} type="error"/>;
return (
<TaskListComponent
loading={loading}

View File

@@ -8,6 +8,7 @@ import dayjs from '../../utils/day';
import {connect} from "react-redux";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component.jsx";
import JobSearchSelectComponent from "../job-search-select/job-search-select.component.jsx";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -41,8 +42,27 @@ export function TaskUpsertModalComponent({
{label: t('tasks.date_presets.three_weeks'), value: dayjs().add(3, 'weeks')},
{label: t('tasks.date_presets.one_month'), value: dayjs().add(1, 'month')},
];
if (loading || error) return <LoadingSkeleton active/>;
const clearRelations = () => {
form.setFieldsValue({
billid: null,
partsorderid: null,
joblineid: null
});
}
/**
* Change the selected job id
* @param jobId
*/
const changeJobId = (jobId) => {
setSelectedJobId(jobId || null);
// Reset the form fields when selectedJobId changes
clearRelations();
};
if (!data || loading || error) return <LoadingSkeleton active/>;
return (
<>
@@ -80,20 +100,95 @@ export function TaskUpsertModalComponent({
label={t("tasks.fields.completed")}
name="completed"
valuePropName="checked"
initialValue={false}
rules={[
{
required: true,
},
]}
>
<Switch/>
</Form.Item>
</Col>
</Row>
<Row gutter={[16, 16]}>
<Col span={24}>
<Form.Item
name="jobid"
// initialValue={selectedJobId}
label={t("tasks.fields.jobid")}
rules={[
{
required: true,
},
]}
>
<JobSearchSelectComponent placeholder={t('tasks.placeholders.jobid')}
onSelect={changeJobId} onClear={changeJobId}/>
</Form.Item>
</Col>
</Row>
<Row gutter={[16, 16]}>
<Col span={8}>
<Form.Item
label={t("tasks.fields.joblineid")}
name="joblineid"
>
<Select allowClear placeholder={t("tasks.placeholders.joblineid")}
disabled={!selectedJobDetails || !selectedJobId}>
{selectedJobDetails?.joblines?.map((jobline) => (
<Select.Option key={jobline.id} value={jobline.id}>
{jobline.line_desc}
</Select.Option>
))}
</Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label={t("tasks.fields.partsorderid")}
name="partsorderid"
>
<Select allowClear placeholder={t("tasks.placeholders.partsorderid")}
disabled={!selectedJobDetails || !selectedJobId}>
{selectedJobDetails?.parts_orders?.map((partsOrder) => (
<Select.Option key={partsOrder.id} value={partsOrder.id}>
{partsOrder.order_number} - {partsOrder.vendor.name}
</Select.Option>
))}
</Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label={t("tasks.fields.billid")}
name="billid"
>
<Select allowClear placeholder={t("tasks.placeholders.billid")}
disabled={!selectedJobDetails || !selectedJobId}>
{selectedJobDetails?.bills?.map((bill) => (
<Select.Option key={bill.id} value={bill.id}>
{bill.invoice_number} - {bill.vendor.name}
</Select.Option>
))}
</Select>
</Form.Item>
</Col>
</Row>
<Row gutter={[16, 16]}>
<Col span={8}>
<Form.Item
label={t("tasks.fields.assigned_to")}
name="assigned_to"
initialValue={currentUser.email}
rules={[
{
required: true,
},
]}
>
<Select placeholder={t("tasks.labels.selectemployee")}>
{bodyshop.employees.map((employee) => (
{bodyshop.employees.filter(x => x.active).map((employee) => (
<Select.Option key={employee.id} value={employee.user_email}>
{employee.first_name} {employee.last_name}
</Select.Option>
@@ -131,71 +226,6 @@ export function TaskUpsertModalComponent({
</Form.Item>
</Col>
</Row>
<Row gutter={[16, 16]}>
<Col span={24}>
<Form.Item
name="jobid"
label={t("tasks.fields.jobid")}
rules={[
{
required: true,
},1
]}
>
<Select placeholder={t('tasks.placeholders.jobid')} 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}>
<Form.Item
label={t("tasks.fields.joblineid")}
name="joblineid"
>
<Select placeholder={t("tasks.placeholders.joblineid")} disabled={!selectedJobDetails}>
{selectedJobDetails?.joblines?.map((jobline) => (
<Select.Option key={jobline.id} value={jobline.id}>
{jobline.line_desc}
</Select.Option>
))}
</Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label={t("tasks.fields.partsorderid")}
name="partsorderid"
>
<Select placeholder={t("tasks.placeholders.partsorderid")} disabled={!selectedJobDetails}>
{selectedJobDetails?.parts_orders?.map((partsOrder) => (
<Select.Option key={partsOrder.id} value={partsOrder.id}>
{partsOrder.order_number} - {partsOrder.vendor.name}
</Select.Option>
))}
</Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label={t("tasks.fields.billid")}
name="billid"
>
<Select placeholder={t("tasks.placeholders.billid")} disabled={!selectedJobDetails}>
{selectedJobDetails?.bills?.map((bill) => (
<Select.Option key={bill.id} value={bill.id}>
{bill.invoice_number} - {bill.vendor.name}
</Select.Option>
))}
</Select>
</Form.Item>
</Col>
</Row>
</>
);
}

View File

@@ -5,14 +5,12 @@ import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
import {createStructuredSelector} from "reselect";
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 {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";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
@@ -41,16 +39,14 @@ export function TaskUpsertModalContainer({
const [selectedJobDetails, setSelectedJobDetails] = useState(null);
const [jobIdState, setJobIdState] = useState(null);
const {
loading: jobDetailsLoading,
error: jobDetailsError,
data: jobDetailsData
loading: loading,
error: error,
data: data
} = useQuery(QUERY_GET_TASKS_JOB_DETAILS_BY_ID, {
variables: {id: jobIdState},
skip: !jobIdState, // Skip the query if jobIdState is null
skip: !jobIdState,
});
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
@@ -72,16 +68,6 @@ export function TaskUpsertModalContainer({
}
}, [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
@@ -97,10 +83,11 @@ export function TaskUpsertModalContainer({
* Set the selected job details when the job details query is successful
*/
useEffect(() => {
if (!jobDetailsLoading && !jobDetailsError && jobDetailsData) {
setSelectedJobDetails(jobDetailsData.jobs_by_pk);
if (!loading && !error && data) {
setSelectedJobDetails(data.jobs_by_pk);
}
}, [jobDetailsLoading, jobDetailsError, jobDetailsData]);
}, [loading, error, data]);
/**
* Handle the form submit
@@ -109,13 +96,11 @@ export function TaskUpsertModalContainer({
*/
const handleFinish = async (formValues) => {
const {...values} = formValues;
if (existingTask) {
await updateTask({
variables: {
taskId: existingTask.id,
task: values,
jobid: selectedJobId,
task: replaceUndefinedWithNull(values)
},
});
@@ -128,19 +113,19 @@ export function TaskUpsertModalContainer({
await insertTask({
variables: {
taskInput: [
{...values, jobid: selectedJobId, created_by: currentUser.email, bodyshopid: bodyshop.id},
{
...replaceUndefinedWithNull(values),
created_by: currentUser.email,
bodyshopid: bodyshop.id
},
],
},
updateQueries: {
query: QUERY_GET_TASKS_JOB_DETAILS,
},
update(cache) {
cache.modify({
fields: {
tasks(existingTasks) {
return [{
...values,
jobid: selectedJobId,
created_by: currentUser.email,
bodyshopid: bodyshop.id
}, ...existingTasks]
@@ -154,7 +139,7 @@ export function TaskUpsertModalContainer({
form.resetFields();
toggleModalVisible();
notification["success"]({
message: t("tasks.successes.create"),
message: t("tasks.successes.created"),
});
}
};
@@ -176,7 +161,7 @@ export function TaskUpsertModalContainer({
>
<Form form={form} onFinish={handleFinish} layout="vertical">
<TaskUpsertModalComponent form={form} loading={loading} error={error} data={data}
selectedJobId={setSelectedJobId}
selectedJobId={selectedJobId}
setSelectedJobId={setSelectedJobId}
selectedJobDetails={selectedJobDetails}/>