Begin addign loading state to mutations BOD-134

This commit is contained in:
Patrick Fic
2020-07-22 10:46:34 -07:00
parent 5f2ced9b45
commit 8f8c26af54
8 changed files with 125 additions and 88 deletions

View File

@@ -1,5 +1,5 @@
import { Form, Modal, notification } from "antd";
import React from "react";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
@@ -13,48 +13,51 @@ import { useMutation } from "@apollo/react-hooks";
const mapStateToProps = createStructuredSelector({
courtesyCarReturnModal: selectCourtesyCarReturn,
bodyshop: selectBodyshop
bodyshop: selectBodyshop,
});
const mapDispatchToProps = dispatch => ({
toggleModalVisible: () => dispatch(toggleModalVisible("courtesyCarReturn"))
const mapDispatchToProps = (dispatch) => ({
toggleModalVisible: () => dispatch(toggleModalVisible("courtesyCarReturn")),
});
export function InvoiceEnterModalContainer({
courtesyCarReturnModal,
toggleModalVisible,
bodyshop
bodyshop,
}) {
const [loading, setLoading] = useState(false);
const { visible, context, actions } = courtesyCarReturnModal;
const { t } = useTranslation();
const [form] = Form.useForm();
const [updateContract] = useMutation(RETURN_CONTRACT);
const handleFinish = values => {
const handleFinish = (values) => {
setLoading(true);
updateContract({
variables: {
contractId: context.contractId,
cccontract: {
kmend: values.kmend,
actualreturn: values.actualreturn,
status: "contracts.status.returned"
status: "contracts.status.returned",
},
courtesycarid: context.courtesyCarId,
courtesycar: {
status: "courtesycars.status.in",
fuel: values.fuel,
mileage: values.kmend
}
}
mileage: values.kmend,
},
},
})
.then(r => {
.then((r) => {
if (actions.refetch) actions.refetch();
toggleModalVisible();
})
.catch(error => {
.catch((error) => {
notification["error"]({
message: t("contracts.errors.returning", { error: error })
message: t("contracts.errors.returning", { error: error }),
});
});
setLoading(false);
};
return (
@@ -65,7 +68,7 @@ export function InvoiceEnterModalContainer({
width={"90%"}
okText={t("general.actions.save")}
onOk={() => form.submit()}
okButtonProps={{ htmlType: "submit" }}
okButtonProps={{ htmlType: "submit", loading: loading }}
>
<Form
form={form}

View File

@@ -2,7 +2,7 @@ import { useMutation, useQuery } from "@apollo/react-hooks";
import { Form, Button } from "antd";
import moment from "moment";
import queryString from "query-string";
import React, { useEffect } from "react";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useLocation } from "react-router-dom";
@@ -26,6 +26,7 @@ export function InvoiceDetailEditContainer({ bodyshop }) {
const search = queryString.parse(useLocation().search);
const { t } = useTranslation();
const [form] = Form.useForm();
const [updateLoading, setUpdateLoading] = useState(false);
const [updateInvoice] = useMutation(UPDATE_INVOICE);
const [updateInvoiceLine] = useMutation(UPDATE_INVOICE_LINE);
@@ -35,9 +36,9 @@ export function InvoiceDetailEditContainer({ bodyshop }) {
});
const handleFinish = async (values) => {
setUpdateLoading(true);
const { invoicelines, upload, ...invoice } = values;
const updates = [];
console.log("Start");
updates.push(
updateInvoice({
variables: { invoiceId: search.invoiceid, invoice: invoice },
@@ -54,6 +55,7 @@ export function InvoiceDetailEditContainer({ bodyshop }) {
});
await Promise.all(updates);
setUpdateLoading(false);
};
useEffect(() => {
@@ -99,7 +101,7 @@ export function InvoiceDetailEditContainer({ bodyshop }) {
: {}
}
>
<Button htmlType="submit" type="primary">
<Button htmlType="submit" loading={updateLoading} type="primary">
{t("general.actions.save")}
</Button>
<InvoiceFormContainer form={form} invoiceEdit />

View File

@@ -1,7 +1,7 @@
import { useMutation } from "@apollo/react-hooks";
import { Button, Form, notification, Switch } from "antd";
import queryString from "query-string";
import React from "react";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useHistory, useLocation, useParams } from "react-router-dom";
@@ -23,6 +23,7 @@ const mapDispatchToProps = (dispatch) => ({
export function JobIntakeForm({ formItems, bodyshop }) {
const { t } = useTranslation();
const [intakeJob] = useMutation(UPDATE_JOB);
const [loading, setLoading] = useState(false);
const [markAptArrived] = useMutation(MARK_LATEST_APPOINTMENT_AS_ARRIVED);
const { jobId } = useParams();
const history = useHistory();
@@ -30,6 +31,7 @@ export function JobIntakeForm({ formItems, bodyshop }) {
const handleFinish = async (values) => {
console.log("values", values);
setLoading(true);
logImEXEvent("job_complete_intake");
const result = await intakeJob({
@@ -70,6 +72,7 @@ export function JobIntakeForm({ formItems, bodyshop }) {
});
}
console.log("handleFinish -> result", result);
setLoading(false);
};
const [form] = Form.useForm();
@@ -78,34 +81,40 @@ export function JobIntakeForm({ formItems, bodyshop }) {
<Form
form={form}
onFinish={handleFinish}
initialValues={{ addToProduction: true }}>
initialValues={{ addToProduction: true }}
>
{t("intake.labels.checklist")}
<ConfigFormComponents componentList={formItems} />
<Form.Item
name='addToProduction'
valuePropName='checked'
label={t("intake.labels.addtoproduction")}>
name="addToProduction"
valuePropName="checked"
label={t("intake.labels.addtoproduction")}
>
<Switch />
</Form.Item>
<Form.Item
name='scheduledCompletion'
name="scheduledCompletion"
label={t("jobs.fields.scheduled_completion")}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
]}
>
<DateTimePicker />
</Form.Item>
<Form.Item
name='scheduledDelivery'
label={t("jobs.fields.scheduled_delivery")}>
name="scheduledDelivery"
label={t("jobs.fields.scheduled_delivery")}
>
<DateTimePicker />
</Form.Item>
<Button htmlType='submit'>{t("general.actions.submit")}</Button>
<Button loading={loading} htmlType="submit">
{t("general.actions.submit")}
</Button>
</Form>
);
}

View File

@@ -7,7 +7,8 @@ export default function JobLinesUpsertModalComponent({
visible,
jobLine,
handleCancel,
handleFinish
handleFinish,
loading,
}) {
const { t } = useTranslation();
const [form] = Form.useForm();
@@ -32,6 +33,7 @@ export default function JobLinesUpsertModalComponent({
visible={visible}
okText={t("general.actions.save")}
onOk={() => form.submit()}
okButtonProps={{ loading: loading }}
onCancel={handleCancel}
>
<Form.Item
@@ -39,8 +41,8 @@ export default function JobLinesUpsertModalComponent({
rules={[
{
required: true,
message: t("general.validation.required")
}
message: t("general.validation.required"),
},
]}
name="line_desc"
>

View File

@@ -1,73 +1,78 @@
import { notification } from "antd";
import React from "react";
import React, { useState } from "react";
import { useMutation } from "@apollo/react-hooks";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { INSERT_NEW_JOB_LINE, UPDATE_JOB_LINE } from "../../graphql/jobs-lines.queries";
import {
INSERT_NEW_JOB_LINE,
UPDATE_JOB_LINE,
} from "../../graphql/jobs-lines.queries";
import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectJobLineEditModal } from "../../redux/modals/modals.selectors";
import JobLinesUpdsertModal from "./job-lines-upsert-modal.component";
const mapStateToProps = createStructuredSelector({
jobLineEditModal: selectJobLineEditModal
jobLineEditModal: selectJobLineEditModal,
});
const mapDispatchToProps = dispatch => ({
toggleModalVisible: () => dispatch(toggleModalVisible("jobLineEdit"))
const mapDispatchToProps = (dispatch) => ({
toggleModalVisible: () => dispatch(toggleModalVisible("jobLineEdit")),
});
function JobLinesUpsertModalContainer({
jobLineEditModal,
toggleModalVisible
toggleModalVisible,
}) {
const { t } = useTranslation();
const [insertJobLine] = useMutation(INSERT_NEW_JOB_LINE);
const [updateJobLine] = useMutation(UPDATE_JOB_LINE);
const handleFinish = values => {
const [loading, setLoading] = useState(false);
const handleFinish = (values) => {
setLoading(true);
if (!jobLineEditModal.context.id) {
insertJobLine({
variables: {
lineInput: [{ jobid: jobLineEditModal.context.jobid, ...values }]
}
lineInput: [{ jobid: jobLineEditModal.context.jobid, ...values }],
},
})
.then(r => {
.then((r) => {
if (jobLineEditModal.actions.refetch)
jobLineEditModal.actions.refetch();
toggleModalVisible();
notification["success"]({
message: t("joblines.successes.created")
message: t("joblines.successes.created"),
});
})
.catch(error => {
.catch((error) => {
notification["error"]({
message: t("joblines.errors.creating", {
message: error.message
})
message: error.message,
}),
});
});
} else {
updateJobLine({
variables: {
lineId: jobLineEditModal.context.id,
line: values
}
line: values,
},
})
.then(r => {
.then((r) => {
notification["success"]({
message: t("joblines.successes.updated")
message: t("joblines.successes.updated"),
});
})
.catch(error => {
.catch((error) => {
notification["success"]({
message: t("joblines.errors.updating", {
message: error.message
})
message: error.message,
}),
});
});
if (jobLineEditModal.actions.refetch) jobLineEditModal.actions.refetch();
toggleModalVisible();
}
setLoading(false);
};
const handleCancel = () => {
@@ -80,6 +85,7 @@ function JobLinesUpsertModalContainer({
jobLine={jobLineEditModal.context}
handleFinish={handleFinish}
handleCancel={handleCancel}
loading={loading}
/>
);
}

View File

@@ -1,5 +1,5 @@
import { Button, notification } from "antd";
import React from "react";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import axios from "axios";
import { useMutation } from "@apollo/react-hooks";
@@ -13,9 +13,10 @@ export default function JobsDocumentsDeleteButton({
const { t } = useTranslation();
const [deleteDocument] = useMutation(DELETE_DOCUMENT);
const imagesToDelete = galleryImages.filter((image) => image.isSelected);
const [loading, setLoading] = useState(false);
const handleDelete = () => {
logImEXEvent("job_documents_delete", { count: imagesToDelete.length });
setLoading(true);
imagesToDelete.forEach((image) => {
let timestamp = Math.floor(Date.now() / 1000);
let public_id = image.key;
@@ -65,10 +66,15 @@ export default function JobsDocumentsDeleteButton({
});
});
});
setLoading(false);
};
return (
<Button disabled={imagesToDelete.length < 1} onClick={handleDelete}>
<Button
disabled={imagesToDelete.length < 1}
loading={loading}
onClick={handleDelete}
>
{t("documents.actions.delete")}
</Button>
);

View File

@@ -1,31 +1,49 @@
import React from "react";
import JobNotesComponent from "./jobs.notes.component";
import { useQuery, useMutation } from "@apollo/react-hooks";
import AlertComponent from "../../components/alert/alert.component";
import { useMutation, useQuery } from "@apollo/react-hooks";
import { notification } from "antd";
import React, { useState } from "react";
//import SpinComponent from "../../components/loading-spinner/loading-spinner.component";
import {
QUERY_NOTES_BY_JOB_PK,
DELETE_NOTE
} from "../../graphql/notes.queries";
import { useTranslation } from "react-i18next";
import AlertComponent from "../../components/alert/alert.component";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { DELETE_NOTE, QUERY_NOTES_BY_JOB_PK } from "../../graphql/notes.queries";
import JobNotesComponent from "./jobs.notes.component";
export default function JobNotesContainer({ jobId }) {
const { loading, error, data, refetch } = useQuery(QUERY_NOTES_BY_JOB_PK, {
variables: { id: jobId },
fetchPolicy: "network-only"
fetchPolicy: "network-only",
});
const [deleteNote] = useMutation(DELETE_NOTE);
const { t } = useTranslation();
const [deleteLoading, setDeleteLoading] = useState(false);
const handleNoteDelete = (id) => {
logImEXEvent("job_note_delete");
setDeleteLoading(true);
deleteNote({
variables: {
noteId: id,
},
}).then((r) => {
refetch();
notification["success"]({
message: t("notes.successes.deleted"),
});
});
setDeleteLoading(false);
};
//if (loading) return <SpinComponent />;
if (error) return <AlertComponent message={error.message} type='error' />;
if (error) return <AlertComponent message={error.message} type="error" />;
return (
<JobNotesComponent
jobId={jobId}
loading={loading}
data={data ? data.jobs_by_pk.notes : null}
refetch={refetch}
deleteNote={deleteNote}
deleteLoading={deleteLoading}
handleNoteDelete={handleNoteDelete}
/>
);
}

View File

@@ -4,12 +4,11 @@ import {
EyeInvisibleFilled,
WarningFilled
} from "@ant-design/icons";
import { Button, notification, Table } from "antd";
import { Button, Table } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import Moment from "react-moment";
import { connect } from "react-redux";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { setModalContext } from "../../redux/modals/modals.actions";
import NoteUpsertModal from "../note-upsert-modal/note-upsert-modal.container";
@@ -22,9 +21,10 @@ export function JobNotesComponent({
loading,
data,
refetch,
deleteNote,
handleNoteDelete,
jobId,
setNoteUpsertContext,
deleteLoading,
}) {
const { t } = useTranslation();
@@ -59,7 +59,7 @@ export function JobNotesComponent({
sorter: (a, b) => new Date(a.updated_at) - new Date(b.updated_at),
render: (text, record) => (
<span>
<Moment format='MM/DD/YYYY @ HH:mm'>{record.updated_at}</Moment>
<Moment format="MM/DD/YYYY @ HH:mm">{record.updated_at}</Moment>
</span>
),
},
@@ -77,20 +77,9 @@ export function JobNotesComponent({
render: (text, record) => (
<span>
<Button
onClick={() => {
logImEXEvent("job_note_delete");
deleteNote({
variables: {
noteId: record.id,
},
}).then((r) => {
refetch();
notification["success"]({
message: t("notes.successes.deleted"),
});
});
}}>
loading={deleteLoading}
onClick={() => handleNoteDelete(record.id)}
>
<DeleteFilled />
</Button>
<Button
@@ -102,7 +91,8 @@ export function JobNotesComponent({
existingNote: record,
},
});
}}>
}}
>
<EditFilled />
</Button>
</span>
@@ -121,14 +111,15 @@ export function JobNotesComponent({
jobId: jobId,
},
});
}}>
}}
>
{t("notes.actions.new")}
</Button>
<Table
loading={loading}
pagination={{ position: "bottom" }}
columns={columns.map((item) => ({ ...item }))}
rowKey='id'
rowKey="id"
dataSource={data}
/>
</div>