Added some additional save indiactors BOD-134

This commit is contained in:
Patrick Fic
2020-08-21 17:17:36 -07:00
parent 4a92ef03cc
commit dd1016eef3
13 changed files with 127 additions and 81 deletions

View File

@@ -3,10 +3,7 @@ import { Select } from "antd";
import { useTranslation } from "react-i18next";
const { Option } = Select;
const ContractStatusComponent = (
{ value = "contracts.status.new", onChange },
ref
) => {
const ContractStatusComponent = ({ value, onChange }, ref) => {
const [option, setOption] = useState(value);
const { t } = useTranslation();

View File

@@ -3,15 +3,15 @@ import React from "react";
import { useTranslation } from "react-i18next";
import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component";
import CourtesyCarStatus from "../courtesy-car-status-select/courtesy-car-status-select.component";
import FormDatePicker from '../form-date-picker/form-date-picker.component';
import FormDatePicker from "../form-date-picker/form-date-picker.component";
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
export default function CourtesyCarCreateFormComponent({ form }) {
export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
const { t } = useTranslation();
return (
<div>
<Button type="primary" htmlType="submit">
<Button type="primary" loading={saveLoading} htmlType="submit">
{t("general.actions.save")}
</Button>
<div className="imex-flex-row__grow imex-flex-row__margin-large">

View File

@@ -41,7 +41,7 @@ export function JobsDetailHeaderActions({
const client = useApolloClient();
const history = useHistory();
const statusmenu = (
<Menu key='popovermenu'>
<Menu key="popovermenu">
<Menu.Item
onClick={() => {
logImEXEvent("job_header_schedule");
@@ -53,16 +53,21 @@ export function JobsDetailHeaderActions({
job: job,
},
});
}}>
}}
>
{t("jobs.actions.schedule")}
</Menu.Item>
<Menu.Item>
<Link to={`/manage/jobs/${job.id}/intake`}>
{t("jobs.actions.intake")}
</Link>
<Menu.Item disabled={!!job.intakechecklist}>
{!!job.intakechecklist ? (
t("jobs.actions.intake")
) : (
<Link to={`/manage/jobs/${job.id}/intake`}>
{t("jobs.actions.intake")}
</Link>
)}
</Menu.Item>
<Menu.Item
key='enterpayments'
key="enterpayments"
onClick={() => {
logImEXEvent("job_header_enter_payment");
@@ -70,29 +75,32 @@ export function JobsDetailHeaderActions({
actions: {},
context: { jobId: job.id },
});
}}>
}}
>
{t("menus.header.enterpayment")}
</Menu.Item>
<Menu.Item key='cccontract'>
<Menu.Item key="cccontract">
<Link
to={{
pathname: "/manage/courtesycars/contracts/new",
state: { jobId: job.id },
}}>
}}
>
{t("menus.jobsactions.newcccontract")}
</Link>
</Menu.Item>
<Menu.Item
key='addtoproduction'
key="addtoproduction"
disabled={!!!job.converted || !!job.inproduction}
onClick={() => AddToProduction(client, job.id, refetch)}>
onClick={() => AddToProduction(client, job.id, refetch)}
>
{t("jobs.actions.addtoproduction")}
</Menu.Item>
<Menu.Item key='duplicatejob'>
<Menu.Item key="duplicatejob">
<Popconfirm
title={t("jobs.labels.duplicateconfirm")}
okText='Yes'
cancelText='No'
okText="Yes"
cancelText="No"
onClick={(e) => e.stopPropagation()}
onConfirm={() =>
DuplicateJob(
@@ -104,12 +112,13 @@ export function JobsDetailHeaderActions({
}
)
}
getPopupContainer={(trigger) => trigger.parentNode}>
getPopupContainer={(trigger) => trigger.parentNode}
>
{t("menus.jobsactions.duplicate")}
</Popconfirm>
</Menu.Item>
<Menu.Item
key='postinvoices'
key="postinvoices"
onClick={() => {
logImEXEvent("job_header_enter_invoice");
@@ -119,20 +128,22 @@ export function JobsDetailHeaderActions({
job: job,
},
});
}}>
}}
>
{t("jobs.actions.postInvoices")}
</Menu.Item>
<Menu.Item key='closejob'>
<Menu.Item key="closejob">
<Link
to={{
pathname: `/manage/jobs/${job.id}/close`,
}}>
}}
>
{t("menus.jobsactions.closejob")}
</Link>
</Menu.Item>
<JobsDetaiLheaderCsi job={job} />
<Menu.Item
key='jobcosting'
key="jobcosting"
onClick={() => {
logImEXEvent("job_header_job_costing");
@@ -142,17 +153,19 @@ export function JobsDetailHeaderActions({
jobId: job.id,
},
});
}}>
}}
>
{t("jobs.labels.jobcosting")}
</Menu.Item>
</Menu>
);
return (
<Dropdown
className='imex-flex-row__margin'
className="imex-flex-row__margin"
overlay={statusmenu}
trigger={["click"]}
key='changestatus'>
key="changestatus"
>
<Button>
{t("general.labels.actions")} <DownCircleFilled />
</Button>

View File

@@ -6,35 +6,37 @@ import FormItemEmail from "../form-items-formatted/email-form-item.component";
import FormItemPhone from "../form-items-formatted/phone-form-item.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
export default function OwnerDetailFormComponent({ form }) {
export default function OwnerDetailFormComponent({ form, loading }) {
const { t } = useTranslation();
const { getFieldValue } = form;
return (
<div>
<div className='imex-flex-row imex-flex-row__flex-space-around'>
<div className="imex-flex-row imex-flex-row__flex-space-around">
<Button
className='imex-flex-row__margin-large'
type='primary'
key='submit'
htmlType='submit'>
className="imex-flex-row__margin-large"
type="primary"
key="submit"
loading={loading}
htmlType="submit"
>
{t("general.actions.save")}
</Button>
<div className='imex-flex-row__grow imex-flex-row__margin-large'>
<div className="imex-flex-row__grow imex-flex-row__margin-large">
<FormFieldsChanged form={form} />
</div>
</div>
<LayoutFormRow header={t("owners.forms.name")}>
<Form.Item label={t("owners.fields.ownr_title")} name='ownr_title'>
<Form.Item label={t("owners.fields.ownr_title")} name="ownr_title">
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_ln")} name='ownr_ln'>
<Form.Item label={t("owners.fields.ownr_ln")} name="ownr_ln">
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_fn")} name='ownr_fn'>
<Form.Item label={t("owners.fields.ownr_fn")} name="ownr_fn">
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_co_nm")} name='ownr_co_nm'>
<Form.Item label={t("owners.fields.ownr_co_nm")} name="ownr_co_nm">
<Input />
</Form.Item>
</LayoutFormRow>
@@ -42,52 +44,56 @@ export default function OwnerDetailFormComponent({ form }) {
<LayoutFormRow header={t("owners.forms.address")}>
<Form.Item
label={t("owners.fields.ownr_addr1")}
name='ownr_addr1'
name="ownr_addr1"
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
]}
>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_addr2")} name='ownr_addr2'>
<Form.Item label={t("owners.fields.ownr_addr2")} name="ownr_addr2">
<Input />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_city")}
name='ownr_city'
name="ownr_city"
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
]}
>
<Input />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_st")}
name='ownr_st'
name="ownr_st"
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
]}
>
<Input />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_zip")}
name='ownr_zip'
name="ownr_zip"
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
]}
>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_ctry")} name='ownr_ctry'>
<Form.Item label={t("owners.fields.ownr_ctry")} name="ownr_ctry">
<Input />
</Form.Item>
</LayoutFormRow>
@@ -95,27 +101,30 @@ export default function OwnerDetailFormComponent({ form }) {
<LayoutFormRow header={t("owners.forms.contact")}>
<Form.Item
label={t("owners.fields.allow_text_message")}
name='allow_text_message'
valuePropName='checked'>
name="allow_text_message"
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_ea")}
name='ownr_ea'
name="ownr_ea"
rules={[
{
type: "email",
message: "This is not a valid email address.",
},
]}>
]}
>
<FormItemEmail email={getFieldValue("ownr_ea")} />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_ph1")} name='ownr_ph1'>
<Form.Item label={t("owners.fields.ownr_ph1")} name="ownr_ph1">
<FormItemPhone customInput={Input} />
</Form.Item>
<Form.Item
label={t("owners.fields.preferred_contact")}
name='preferred_contact'>
name="preferred_contact"
>
<Input />
</Form.Item>
</LayoutFormRow>

View File

@@ -1,5 +1,5 @@
import { Form, notification } from "antd";
import React from "react";
import React, { useState } from "react";
import { useMutation } from "@apollo/react-hooks";
import { useTranslation } from "react-i18next";
import { UPDATE_OWNER } from "../../graphql/owners.queries";
@@ -8,10 +8,11 @@ import OwnerDetailFormComponent from "./owner-detail-form.component";
function OwnerDetailFormContainer({ owner, refetch }) {
const { t } = useTranslation();
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [updateOwner] = useMutation(UPDATE_OWNER);
const handleFinish = async (values) => {
setLoading(true);
const result = await updateOwner({
variables: { ownerId: owner.id, owner: values },
});
@@ -32,6 +33,7 @@ function OwnerDetailFormContainer({ owner, refetch }) {
if (refetch) await refetch();
form.resetFields();
form.resetFields();
setLoading(false);
};
return (
@@ -42,7 +44,7 @@ function OwnerDetailFormContainer({ owner, refetch }) {
layout="vertical"
initialValues={owner}
>
<OwnerDetailFormComponent form={form} />
<OwnerDetailFormComponent loading={loading} form={form} />
</Form>
);
}

View File

@@ -5,7 +5,7 @@ import FormDatePicker from "../form-date-picker/form-date-picker.component";
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
export default function VehicleDetailFormComponent({ form }) {
export default function VehicleDetailFormComponent({ form, loading }) {
const { t } = useTranslation();
return (
@@ -16,6 +16,7 @@ export default function VehicleDetailFormComponent({ form }) {
type="primary"
key="submit"
htmlType="submit"
loading={loading}
>
{t("general.actions.save")}
</Button>

View File

@@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import { Form, notification } from "antd";
import { useMutation } from "@apollo/react-hooks";
import VehicleDetailFormComponent from "./vehicle-detail-form.component";
@@ -10,8 +10,10 @@ function VehicleDetailFormContainer({ vehicle, refetch }) {
const { t } = useTranslation();
const [updateVehicle] = useMutation(UPDATE_VEHICLE);
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const handleFinish = async (values) => {
setLoading(true);
const result = await updateVehicle({
variables: { vehId: vehicle.id, vehicle: values },
});
@@ -31,6 +33,7 @@ function VehicleDetailFormContainer({ vehicle, refetch }) {
if (refetch) await refetch();
form.resetFields();
form.resetFields();
setLoading(false);
};
return (
@@ -44,7 +47,7 @@ function VehicleDetailFormContainer({ vehicle, refetch }) {
v_prod_dt: vehicle.v_prod_dt ? moment(vehicle.v_prod_dt) : null,
}}
>
<VehicleDetailFormComponent form={form} />
<VehicleDetailFormComponent form={form} loading={loading} />
</Form>
);
}

View File

@@ -231,6 +231,7 @@ export const GET_JOB_BY_PK = gql`
first_name
last_name
}
intakechecklist
csr
loss_desc
kmin

View File

@@ -9,11 +9,14 @@ export default function ContractCreatePageComponent({
form,
selectedJobState,
selectedCarState,
loading,
}) {
const { t } = useTranslation();
return (
<div>
<Button htmlType="submit">{t("general.actions.create")}</Button>
<Button type="primary" onClick={() => form.submit()} loading={loading}>
{t("general.actions.create")}
</Button>
<ContractJobsContainer selectedJobState={selectedJobState} />
<ContractCarsContainer selectedCarState={selectedCarState} />
<ContractLicenseDecodeButton form={form} />

View File

@@ -23,6 +23,7 @@ export function ContractCreatePageContainer({ bodyshop, setBreadcrumbs }) {
const { t } = useTranslation();
const history = useHistory();
const location = useLocation();
const [loading, setLoading] = useState(false);
const selectedCarState = useState(null);
const selectedJobState = useState(
(location.state && location.state.jobId) || null
@@ -31,6 +32,7 @@ export function ContractCreatePageContainer({ bodyshop, setBreadcrumbs }) {
const handleFinish = (values) => {
if (!!selectedCarState[0] && !!selectedJobState[0]) {
setLoading(true);
insertContract({
variables: {
contract: {
@@ -61,6 +63,7 @@ export function ContractCreatePageContainer({ bodyshop, setBreadcrumbs }) {
message: t("contracts.errors.selectjobandcar"),
});
}
setLoading(false);
};
useEffect(() => {
@@ -84,9 +87,11 @@ export function ContractCreatePageContainer({ bodyshop, setBreadcrumbs }) {
form={form}
layout="vertical"
autoComplete="no"
initialValues={{ status: "contracts.status.new" }}
onFinish={handleFinish}
>
<ContractCreatePageComponent
loading={loading}
form={form}
selectedJobState={selectedJobState}
selectedCarState={selectedCarState}

View File

@@ -2,10 +2,14 @@ import React from "react";
import CourtesyCarCreateFormComponent from "../../components/courtesy-car-form/courtesy-car-form.component";
import CourtesyCarContractListComponent from "../../components/courtesy-car-contract-list/courtesy-car-contract-list.component";
export default function CourtesyCarDetailPageComponent({ contracts, form }) {
export default function CourtesyCarDetailPageComponent({
contracts,
form,
saveLoading,
}) {
return (
<div>
<CourtesyCarCreateFormComponent form={form} />
<CourtesyCarCreateFormComponent form={form} saveLoading={saveLoading} />
<CourtesyCarContractListComponent contracts={contracts} />
</div>
);

View File

@@ -1,7 +1,7 @@
import { useMutation, useQuery } from "@apollo/react-hooks";
import { Form, notification } from "antd";
import moment from "moment";
import React, { useEffect } from "react";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useParams } from "react-router-dom";
@@ -27,7 +27,7 @@ export function CourtesyCarDetailPageContainer({
const [insertCourtesyCar] = useMutation(UPDATE_CC);
const [form] = Form.useForm();
const { ccId } = useParams();
const [saveLoading, setSaveLoading] = useState(false);
const { loading, error, data } = useQuery(QUERY_CC_BY_PK, {
variables: { id: ccId },
});
@@ -63,18 +63,24 @@ export function CourtesyCarDetailPageContainer({
);
}, [t, data, error, loading, setBreadcrumbs, ccId, addRecentItem]);
const handleFinish = (values) => {
insertCourtesyCar({
const handleFinish = async (values) => {
setSaveLoading(true);
const result = await insertCourtesyCar({
variables: { cc: { ...values }, ccId: ccId },
})
.then((response) => {
notification["success"]({ message: t("courtesycars.successes.saved") });
})
.catch((error) =>
notification["error"]({
message: t("courtesycars.errors.saving", { error: error }),
})
);
});
if (!!result.errors) {
notification["error"]({
message: t("courtesycars.errors.saving", { error: error }),
});
}
notification["success"]({
message: t("courtesycars.successes.saved"),
});
setSaveLoading(false);
};
useEffect(() => {
@@ -120,6 +126,7 @@ export function CourtesyCarDetailPageContainer({
<CourtesyCarDetailPageComponent
contracts={data ? data.courtesycars_by_pk.cccontracts : []}
form={form}
saveLoading={saveLoading}
/>
</Form>
</RbacWrapper>

View File

@@ -8,9 +8,10 @@ export function DateFormatter(props) {
<Moment format="MM/DD/YYYY ">{props.children}</Moment>
) : null;
}
export function DateTimeFormatter(props) {
return props.children ? (
<Moment format="MM/DD/YYYY @ HH:mm">{props.children}</Moment>
<Moment format="MM/DD/YYYY hh:mm a">{props.children}</Moment>
) : null;
}