UI fixes for manual job creation + owners pages + vehicles pages + all jobs BOD-155

This commit is contained in:
Patrick Fic
2020-06-12 17:54:20 -07:00
parent a88785fc43
commit 05bf94e808
37 changed files with 1339 additions and 972 deletions

View File

@@ -11077,27 +11077,6 @@
<folder_node> <folder_node>
<name>cards</name> <name>cards</name>
<children> <children>
<concept_node>
<name>appraiser</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node> <concept_node>
<name>customer</name> <name>customer</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -13867,6 +13846,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>ownr_co_nm</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node> <concept_node>
<name>ownr_ctry</name> <name>ownr_ctry</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -14058,6 +14058,74 @@
</concept_node> </concept_node>
</children> </children>
</folder_node> </folder_node>
<folder_node>
<name>forms</name>
<children>
<concept_node>
<name>address</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>contact</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>name</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node> <folder_node>
<name>labels</name> <name>labels</name>
<children> <children>
@@ -17514,6 +17582,74 @@
</concept_node> </concept_node>
</children> </children>
</folder_node> </folder_node>
<folder_node>
<name>forms</name>
<children>
<concept_node>
<name>detail</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>misc</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>registration</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node> <folder_node>
<name>labels</name> <name>labels</name>
<children> <children>

View File

@@ -22,7 +22,12 @@
&__margin { &__margin {
margin: 0.2rem 0.2rem; margin: 0.2rem 0.2rem;
} }
&__margin-large { &__margin-large {
margin: 0.5rem 0.5rem; margin: 0.5rem 0.5rem;
} }
&__flex-space-around {
justify-content: space-around;
}
} }

View File

@@ -1,10 +1,10 @@
import { Table, Button } from "antd"; import { Table, Button, Input } from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
import { SyncOutlined } from "@ant-design/icons";
export default function CourtesyCarsList({ loading, courtesycars }) { export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
const [state, setState] = useState({ const [state, setState] = useState({
sortedInfo: {}, sortedInfo: {},
filteredInfo: { text: "" }, filteredInfo: { text: "" },
@@ -74,14 +74,28 @@ export default function CourtesyCarsList({ loading, courtesycars }) {
<Table <Table
loading={loading} loading={loading}
title={() => ( title={() => (
<Link to={`/manage/courtesycars/new`}> <div className='imex-table-header'>
<Button>{t("courtesycars.actions.new")}</Button> <Button onClick={() => refetch()}>
</Link> <SyncOutlined />
</Button>
<Link to={`/manage/courtesycars/new`}>
<Button>{t("courtesycars.actions.new")}</Button>
</Link>
<Input.Search
className='imex-table-header__search'
placeholder={t("general.labels.search")}
onChange={(e) => {
//setSearchText(e.target.value);
}}
//value={searchText}
enterButton
/>
</div>
)} )}
size="small" size='small'
pagination={{ position: "top" }} pagination={{ position: "top" }}
columns={columns.map((item) => ({ ...item }))} columns={columns.map((item) => ({ ...item }))}
rowKey="id" rowKey='id'
dataSource={courtesycars} dataSource={courtesycars}
onChange={handleTableChange} onChange={handleTableChange}
/> />

View File

@@ -76,8 +76,7 @@ export function JobDetailCards({ setPrintCenterContext }) {
destroyOnClose destroyOnClose
width={drawerPercentage} width={drawerPercentage}
placement='right' placement='right'
onClose={handleDrawerClose} onClose={handleDrawerClose}>
footer={<div>The footer.</div>}>
{loading ? <LoadingSpinner /> : null} {loading ? <LoadingSpinner /> : null}
{error ? <AlertComponent message={error.message} type='error' /> : null} {error ? <AlertComponent message={error.message} type='error' /> : null}
{data ? ( {data ? (

View File

@@ -17,7 +17,7 @@ export default function JobDetailCardsTotalsComponent({ loading, data }) {
return ( return (
<CardTemplate loading={loading} title={t("jobs.labels.cards.totals")}> <CardTemplate loading={loading} title={t("jobs.labels.cards.totals")}>
{totals ? ( {totals ? (
<div className='imex-flex-row'> <div className='imex-flex-row imex-flex-row__flex-space-around'>
<Statistic <Statistic
className='imex-flex-row__margin-large' className='imex-flex-row__margin-large'
title={t("jobs.labels.total_repairs")} title={t("jobs.labels.total_repairs")}

View File

@@ -3,127 +3,145 @@ import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import FormItemEmail from "../form-items-formatted/email-form-item.component"; import FormItemEmail from "../form-items-formatted/email-form-item.component";
import FormItemPhone from "../form-items-formatted/phone-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 JobsCreateJobsInfo({ form }) { export default function JobsCreateJobsInfo({ form }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { getFieldValue } = form; const { getFieldValue } = form;
return ( return (
<div> <div>
<Collapse defaultActiveKey="insurance"> <Collapse defaultActiveKey='insurance'>
<Collapse.Panel <Collapse.Panel
key="insurance" key='insurance'
header={t("menus.jobsdetail.insurance")} header={t("menus.jobsdetail.insurance")}>
> <LayoutFormRow>
<Form.Item label={t("jobs.fields.ins_co_id")} name="ins_co_id"> <Form.Item label={t("jobs.fields.ins_co_id")} name='ins_co_id'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.policy_no")} name="policy_no"> <Form.Item label={t("jobs.fields.policy_no")} name='policy_no'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.clm_no")} name="clm_no"> <Form.Item label={t("jobs.fields.clm_no")} name='clm_no'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.regie_number")} name="regie_number"> <Form.Item
<Input /> label={t("jobs.fields.regie_number")}
</Form.Item> name='regie_number'>
TODO: missing KOL field??? <Input />
<Form.Item label={t("jobs.fields.loss_date")} name="loss_date"> </Form.Item>
<DatePicker /> <Form.Item label={t("jobs.fields.loss_date")} name='loss_date'>
</Form.Item> <DatePicker />
CAA # seems not correct based on field mapping Class seems not correct </Form.Item>
based on field mapping <Form.Item label={t("jobs.fields.ins_co_nm")} name='ins_co_nm'>
<Form.Item label={t("jobs.fields.ins_co_nm")} name="ins_co_nm"> <Input />
<Input /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.ins_addr1")} name='ins_addr1'>
<Form.Item label={t("jobs.fields.ins_addr1")} name="ins_addr1"> <Input />
<Input /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.ins_city")} name='ins_city'>
<Form.Item label={t("jobs.fields.ins_city")} name="ins_city"> <Input />
<Input /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.ins_ct_ln")} name='ins_ct_ln'>
<Form.Item label={t("jobs.fields.ins_ct_ln")} name="ins_ct_ln"> <Input />
<Input /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.ins_ct_fn")} name='ins_ct_fn'>
<Form.Item label={t("jobs.fields.ins_ct_fn")} name="ins_ct_fn"> <Input />
<Input /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.ins_ph1")} name='ins_ph1'>
<Form.Item label={t("jobs.fields.ins_ph1")} name="ins_ph1"> <FormItemPhone customInput={Input} />
<FormItemPhone customInput={Input} /> </Form.Item>
</Form.Item> <Form.Item
<Form.Item label={t("jobs.fields.ins_ea")}
label={t("jobs.fields.ins_ea")} name='ins_ea'
name="ins_ea" rules={[
rules={[ {
{ type: "email",
type: "email", message: "This is not a valid email address.",
message: "This is not a valid email address." },
} ]}>
]} <FormItemEmail email={getFieldValue("ins_ea")} />
> </Form.Item>
<FormItemEmail email={getFieldValue("ins_ea")} /> Appraiser Info
</Form.Item> <Form.Item label={t("jobs.fields.est_co_nm")} name='est_co_nm'>
Appraiser Info <Input />
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm"> </Form.Item>
<Input /> <Form.Item label={t("jobs.fields.est_ct_fn")} name='est_ct_fn'>
</Form.Item> <Input />
<Form.Item label={t("jobs.fields.est_ct_fn")} name="est_ct_fn"> </Form.Item>
<Input /> <Form.Item label={t("jobs.fields.est_ct_ln")} name='est_ct_ln'>
</Form.Item> <Input />
<Form.Item label={t("jobs.fields.est_ct_ln")} name="est_ct_ln"> </Form.Item>
<Input /> <Form.Item label={t("jobs.fields.pay_date")} name='pay_date'>
</Form.Item> <Input />
TODO: Field is pay date but title is inspection date. Likely </Form.Item>
incorrect? <Form.Item label={t("jobs.fields.est_ph1")} name='est_ph1'>
<Form.Item label={t("jobs.fields.pay_date")} name="pay_date"> <Input />
<Input /> </Form.Item>
</Form.Item> <Form.Item
<Form.Item label={t("jobs.fields.est_ph1")} name="est_ph1"> label={t("jobs.fields.est_ea")}
<Input /> name='est_ea'
</Form.Item> rules={[
<Form.Item {
label={t("jobs.fields.est_ea")} type: "email",
name="est_ea" message: "This is not a valid email address.",
rules={[ },
{ ]}>
type: "email", <FormItemEmail email={getFieldValue("est_ea")} />
message: "This is not a valid email address." </Form.Item>
} <Form.Item
]} label={t("jobs.fields.selling_dealer")}
> name='selling_dealer'>
<FormItemEmail email={getFieldValue("est_ea")} /> <Input />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.selling_dealer")} label={t("jobs.fields.servicing_dealer")}
name="selling_dealer" name='servicing_dealer'>
> <Input />
<Input /> </Form.Item>
</Form.Item> <Form.Item
<Form.Item label={t("jobs.fields.selling_dealer_contact")}
label={t("jobs.fields.servicing_dealer")} name='selling_dealer_contact'>
name="servicing_dealer" <Input />
> </Form.Item>
<Input /> <Form.Item
</Form.Item> label={t("jobs.fields.servicing_dealer_contact")}
<Form.Item name='servicing_dealer_contact'>
label={t("jobs.fields.selling_dealer_contact")} <Input />
name="selling_dealer_contact" </Form.Item>
> </LayoutFormRow>
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.servicing_dealer_contact")}
name="servicing_dealer_contact"
>
<Input />
</Form.Item>
</Collapse.Panel> </Collapse.Panel>
<Collapse.Panel key="claim" header={t("menus.jobsdetail.claimdetail")}> <Collapse.Panel key='claim' header={t("menus.jobsdetail.claimdetail")}>
<Form.Item label={t("jobs.fields.csr")} name="csr"> <LayoutFormRow>
<Input /> <Form.Item label={t("jobs.fields.csr")} name='csr'>
</Form.Item> <Input />
<Form.Item label={t("jobs.fields.loss_desc")} name="loss_desc"> </Form.Item>
<Input /> <Form.Item label={t("jobs.fields.loss_desc")} name='loss_desc'>
</Form.Item> <Input />
</Form.Item>
<Form.Item label={t("jobs.fields.ponumber")} name='po_number'>
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.unitnumber")} name='unit_number'>
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.specialcoveragepolicy")}
valuePropName='checked'
name='special_coverage_policy'>
<Switch />
</Form.Item>
<Form.Item label={t("jobs.fields.kmin")} name='kmin'>
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.kmout")} name='kmout'>
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.referralsource")}
name='referral_source'>
<Input />
</Form.Item>
</LayoutFormRow>
TODO How to handle different taxes and marking them as exempt? TODO How to handle different taxes and marking them as exempt?
{ {
// <Form.Item label={t("jobs.fields.exempt")}> // <Form.Item label={t("jobs.fields.exempt")}>
@@ -132,157 +150,125 @@ export default function JobsCreateJobsInfo({ form }) {
// })(<Input name='exempt' />)} // })(<Input name='exempt' />)}
// </Form.Item> // </Form.Item>
} }
<Form.Item label={t("jobs.fields.ponumber")} name="po_number">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.unitnumber")} name="unit_number">
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.specialcoveragepolicy")}
valuePropName="checked"
name="special_coverage_policy"
>
<Switch />
</Form.Item>
<Form.Item label={t("jobs.fields.kmin")} name="kmin">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.kmout")} name="kmout">
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.referralsource")}
name="referral_source"
>
<Input />
</Form.Item>
</Collapse.Panel> </Collapse.Panel>
<Collapse.Panel <Collapse.Panel
key="financial" key='financial'
header={t("menus.jobsdetail.financials")} header={t("menus.jobsdetail.financials")}>
> <LayoutFormRow>
<Form.Item label={t("jobs.fields.ded_amt")} name="ded_amt"> <Form.Item label={t("jobs.fields.ded_amt")} name='ded_amt'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.ded_status")} name="ded_status"> <Form.Item label={t("jobs.fields.ded_status")} name='ded_status'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.depreciation_taxes")} label={t("jobs.fields.depreciation_taxes")}
name="depreciation_taxes" name='depreciation_taxes'>
> <InputNumber />
<InputNumber /> </Form.Item>
</Form.Item> TODO This is equivalent of GST payable.
TODO This is equivalent of GST payable. <Form.Item
<Form.Item label={t("jobs.fields.federal_tax_payable")}
label={t("jobs.fields.federal_tax_payable")} name='federal_tax_payable'>
name="federal_tax_payable" <InputNumber />
> </Form.Item>
<InputNumber /> <Form.Item
</Form.Item> label={t("jobs.fields.other_amount_payable")}
TODO equivalent of other customer amount name='other_amount_payable'>
<Form.Item <InputNumber />
label={t("jobs.fields.other_amount_payable")} </Form.Item>
name="other_amount_payable" <Form.Item
> label={t("jobs.fields.towing_payable")}
<InputNumber /> name='towing_payable'>
</Form.Item> <InputNumber />
<Form.Item </Form.Item>
label={t("jobs.fields.towing_payable")} <Form.Item
name="towing_payable" label={t("jobs.fields.storage_payable")}
> name='storage_payable'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.storage_payable")} label={t("jobs.fields.adjustment_bottom_line")}
name="storage_payable" name='adjustment_bottom_line'>
> <InputNumber />
<InputNumber /> </Form.Item>
</Form.Item> Totals Table
<Form.Item <Form.Item
label={t("jobs.fields.adjustment_bottom_line")} label={t("jobs.fields.labor_rate_desc")}
name="adjustment_bottom_line" name='labor_rate_desc'>
> <Input />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_lab")} name='rate_lab'>
Totals Table <InputNumber />
<Form.Item </Form.Item>
label={t("jobs.fields.labor_rate_desc")} <Form.Item label={t("jobs.fields.rate_lad")} name='rate_lad'>
name="labor_rate_desc" <InputNumber />
> </Form.Item>
<Input /> <Form.Item label={t("jobs.fields.rate_lae")} name='rate_lae'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_lar")} name='rate_lar'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_lad")} name="rate_lad"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_las")} name='rate_las'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_lae")} name="rate_lae"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_laf")} name='rate_laf'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_lar")} name="rate_lar"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_lam")} name='rate_lam'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_las")} name="rate_las"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_lag")} name='rate_lag'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_laf")} name="rate_laf"> </Form.Item>
<InputNumber /> Note //TODO Remove ATP rate?
</Form.Item> <Form.Item label={t("jobs.fields.rate_atp")} name='rate_atp'>
<Form.Item label={t("jobs.fields.rate_lam")} name="rate_lam"> <InputNumber />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_lau")} name='rate_lau'>
<Form.Item label={t("jobs.fields.rate_lag")} name="rate_lag"> <InputNumber />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_la1")} name='rate_la1'>
Note //TODO Remove ATP rate? <InputNumber />
<Form.Item label={t("jobs.fields.rate_atp")} name="rate_atp"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_la2")} name='rate_la2'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_lau")} name="rate_lau"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_la3")} name='rate_la3'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_la1")} name="rate_la1"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_la4")} name='rate_la4'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_la2")} name="rate_la2"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_mapa")} name='rate_mapa'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_la3")} name="rate_la3"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_mash")} name='rate_mash'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_la4")} name="rate_la4"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_mahw")} name='rate_mahw'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_mapa")} name="rate_mapa"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_ma2s")} name='rate_ma2s'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_mash")} name="rate_mash"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_ma3s")} name='rate_ma3s'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_mahw")} name="rate_mahw"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_mabl")} name='rate_mabl'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_ma2s")} name="rate_ma2s"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_macs")} name='rate_macs'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_ma3s")} name="rate_ma3s"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_matd")} name='rate_matd'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl"> </Form.Item>
<InputNumber /> <Form.Item label={t("jobs.fields.rate_laa")} name='rate_laa'>
</Form.Item> <InputNumber />
<Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs"> </Form.Item>
<InputNumber /> </LayoutFormRow>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_matd")} name="rate_matd">
<InputNumber />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_laa")} name="rate_laa">
<InputNumber />
</Form.Item>
</Collapse.Panel> </Collapse.Panel>
</Collapse> </Collapse>
</div> </div>

View File

@@ -1,8 +1,13 @@
import { Col, Row, Typography } from "antd";
import React from "react"; import React from "react";
import { Row, Col, Typography } from "antd"; import { useTranslation } from "react-i18next";
import JobsCreateOwnerInfoNewComponent from "./jobs-create-owner-info.new.component"; import JobsCreateOwnerInfoNewComponent from "./jobs-create-owner-info.new.component";
import JobsCreateOwnerInfoSearchComponent from "./jobs-create-owner-info.search.component"; import JobsCreateOwnerInfoSearchComponent from "./jobs-create-owner-info.search.component";
import { useTranslation } from "react-i18next";
const colSpan = {
sm: { span: 24 },
lg: { span: 12 },
};
export default function JobsCreateOwnerInfoComponent({ loading, owners }) { export default function JobsCreateOwnerInfoComponent({ loading, owners }) {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -11,15 +16,15 @@ export default function JobsCreateOwnerInfoComponent({ loading, owners }) {
<Row> <Row>
<Typography.Title>{t("jobs.labels.create.ownerinfo")}</Typography.Title> <Typography.Title>{t("jobs.labels.create.ownerinfo")}</Typography.Title>
</Row> </Row>
<Row gutter={4}> <Row gutter={[32, 32]}>
<Col span={16}> <Col {...colSpan}>
<JobsCreateOwnerInfoSearchComponent <JobsCreateOwnerInfoSearchComponent
loading={loading} loading={loading}
owners={owners} owners={owners}
/> />
</Col> </Col>
<Col span={8}> <Col {...colSpan}>
<JobsCreateOwnerInfoNewComponent /> <JobsCreateOwnerInfoNewComponent />
</Col> </Col>
</Row> </Row>

View File

@@ -1,18 +1,18 @@
import React, { useContext } from "react";
import JobsCreateOwnerInfoComponent from "./jobs-create-owner-info.component";
import JobCreateContext from "../../pages/jobs-create/jobs-create.context";
import { QUERY_SEARCH_OWNER_BY_IDX } from "../../graphql/owners.queries";
import { useQuery } from "@apollo/react-hooks"; import { useQuery } from "@apollo/react-hooks";
import React, { useContext } from "react";
import { QUERY_SEARCH_OWNER_BY_IDX } from "../../graphql/owners.queries";
import JobCreateContext from "../../pages/jobs-create/jobs-create.context";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
import JobsCreateOwnerInfoComponent from "./jobs-create-owner-info.component";
export default function JobsCreateOwnerContainer() { export default function JobsCreateOwnerContainer() {
const [state] = useContext(JobCreateContext); const [state] = useContext(JobCreateContext);
const { loading, error, data } = useQuery(QUERY_SEARCH_OWNER_BY_IDX, { const { loading, error, data } = useQuery(QUERY_SEARCH_OWNER_BY_IDX, {
variables: { search: `%${state.owner.search}%` }, variables: { search: `%${state.owner.search}%` },
skip: !state.owner.search skip: !state.owner.search,
}); });
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent message={error.message} type='error' />;
return ( return (
<JobsCreateOwnerInfoComponent <JobsCreateOwnerInfoComponent
loading={loading} loading={loading}

View File

@@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next";
import JobCreateContext from "../../pages/jobs-create/jobs-create.context"; import JobCreateContext from "../../pages/jobs-create/jobs-create.context";
import FormItemEmail from "../form-items-formatted/email-form-item.component"; import FormItemEmail from "../form-items-formatted/email-form-item.component";
import FormItemPhone from "../form-items-formatted/phone-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 JobsCreateOwnerInfoNewComponent() { export default function JobsCreateOwnerInfoNewComponent() {
const [state, setState] = useContext(JobCreateContext); const [state, setState] = useContext(JobCreateContext);
@@ -20,103 +21,111 @@ export default function JobsCreateOwnerInfoNewComponent() {
owner: { owner: {
...state.owner, ...state.owner,
new: !state.owner.new, new: !state.owner.new,
selectedid: null selectedid: null,
} },
}); });
}} }}>
>
{t("jobs.labels.create.newowner")} {t("jobs.labels.create.newowner")}
</Checkbox> </Checkbox>
<Form.Item <LayoutFormRow header={t("owners.forms.name")} grow>
label={t("owners.fields.ownr_ln")} <Form.Item
name={["owner", "data", "ownr_ln"]} label={t("owners.fields.ownr_ln")}
> name={["owner", "data", "ownr_ln"]}>
<Input disabled={!state.owner.new} /> <Input disabled={!state.owner.new} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("owners.fields.ownr_fn")} label={t("owners.fields.ownr_fn")}
name={["owner", "data", "ownr_fn"]} name={["owner", "data", "ownr_fn"]}>
> <Input disabled={!state.owner.new} />
<Input disabled={!state.owner.new} /> </Form.Item>
</Form.Item> </LayoutFormRow>
<Form.Item
label={t("owners.fields.allow_text_message")}
valuePropName="checked"
name={["owner", "data", "allow_text_message"]}
>
<Switch disabled={!state.owner.new} />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_addr1")}
name={["owner", "data", "ownr_addr1"]}
>
<Input disabled={!state.owner.new} />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_addr2")}
name={["owner", "data", "ownr_addr2"]}
>
<Input disabled={!state.owner.new} />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_city")}
name={["owner", "data", "ownr_city"]}
>
<Input disabled={!state.owner.new} />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_ctry")}
name={["owner", "data", "ownr_ctry"]}
>
<Input disabled={!state.owner.new} />
</Form.Item>
<Form.Item <LayoutFormRow grow>
label={t("owners.fields.ownr_ea")} <Form.Item
rules={[ label={t("owners.fields.ownr_title")}
{ name={["owner", "data", "ownr_title"]}>
type: "email", <Input disabled={!state.owner.new} />
message: "This is not a valid email address." </Form.Item>
} <Form.Item
]} label={t("owners.fields.ownr_co_nm")}
name={["owner", "data", "ownr_ea"]} name={["owner", "data", "ownr_co_nm"]}>
> <Input disabled={!state.owner.new} />
<FormItemEmail </Form.Item>
//TODO Fix this email={getFieldValue("ownr_ea")} </LayoutFormRow>
disabled={!state.owner.new}
/> <LayoutFormRow header={t("owners.forms.address")} grow>
</Form.Item> <Form.Item
<Form.Item label={t("owners.fields.ownr_addr1")}
label={t("owners.fields.ownr_ph1")} name={["owner", "data", "ownr_addr1"]}>
name={["owner", "data", "ownr_ph1"]} <Input disabled={!state.owner.new} />
> </Form.Item>
<FormItemPhone customInput={Input} disabled={!state.owner.new} /> <Form.Item
</Form.Item> label={t("owners.fields.ownr_addr2")}
<Form.Item name={["owner", "data", "ownr_addr2"]}>
label={t("owners.fields.ownr_st")} <Input disabled={!state.owner.new} />
name={["owner", "data", "ownr_st"]} </Form.Item>
> </LayoutFormRow>
<Input disabled={!state.owner.new} />
</Form.Item> <LayoutFormRow grow>
<Form.Item <Form.Item
label={t("owners.fields.ownr_zip")} label={t("owners.fields.ownr_city")}
name={["owner", "data", "ownr_zip"]} name={["owner", "data", "ownr_city"]}>
> <Input disabled={!state.owner.new} />
<Input disabled={!state.owner.new} /> </Form.Item>
</Form.Item> <Form.Item
<Form.Item label={t("owners.fields.ownr_st")}
label={t("owners.fields.preferred_contact")} name={["owner", "data", "ownr_st"]}>
name={["owner", "data", "preferred_contact"]} <Input disabled={!state.owner.new} />
> </Form.Item>
<Input disabled={!state.owner.new} /> </LayoutFormRow>
</Form.Item> <LayoutFormRow grow>
<Form.Item <Form.Item
label={t("owners.fields.ownr_title")} label={t("owners.fields.ownr_zip")}
name={["owner", "data", "ownr_title"]} name={["owner", "data", "ownr_zip"]}>
> <Input disabled={!state.owner.new} />
<Input disabled={!state.owner.new} /> </Form.Item>
</Form.Item> <Form.Item
label={t("owners.fields.ownr_ctry")}
name={["owner", "data", "ownr_ctry"]}>
<Input disabled={!state.owner.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("owners.forms.contact")} grow>
<Form.Item
label={t("owners.fields.ownr_ea")}
rules={[
{
type: "email",
message: "This is not a valid email address.",
},
]}
name={["owner", "data", "ownr_ea"]}>
<FormItemEmail
//TODO Fix this email={getFieldValue("ownr_ea")}
disabled={!state.owner.new}
/>
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_ph1")}
name={["owner", "data", "ownr_ph1"]}>
<FormItemPhone customInput={Input} disabled={!state.owner.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item
label={t("owners.fields.preferred_contact")}
name={["owner", "data", "preferred_contact"]}>
<Input disabled={!state.owner.new} />
</Form.Item>
<Form.Item
label={t("owners.fields.allow_text_message")}
valuePropName='checked'
name={["owner", "data", "allow_text_message"]}>
<Switch disabled={!state.owner.new} />
</Form.Item>
</LayoutFormRow>
</div> </div>
); );
} }

View File

@@ -7,12 +7,12 @@ import { alphaSort } from "../../utils/sorters";
export default function JobsCreateOwnerInfoSearchComponent({ export default function JobsCreateOwnerInfoSearchComponent({
loading, loading,
owners owners,
}) { }) {
const [state, setState] = useContext(JobCreateContext); const [state, setState] = useContext(JobCreateContext);
const [tableState, setTableState] = useState({ const [tableState, setTableState] = useState({
sortedInfo: {}, sortedInfo: {},
filteredInfo: { text: "" } filteredInfo: { text: "" },
}); });
const { t } = useTranslation(); const { t } = useTranslation();
@@ -25,7 +25,7 @@ export default function JobsCreateOwnerInfoSearchComponent({
sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
sortOrder: sortOrder:
tableState.sortedInfo.columnKey === "ownr_ln" && tableState.sortedInfo.columnKey === "ownr_ln" &&
tableState.sortedInfo.order tableState.sortedInfo.order,
}, },
{ {
title: t("owners.fields.ownr_fn"), title: t("owners.fields.ownr_fn"),
@@ -34,7 +34,7 @@ export default function JobsCreateOwnerInfoSearchComponent({
sorter: (a, b) => alphaSort(a.ownr_fn, b.ownr_fn), sorter: (a, b) => alphaSort(a.ownr_fn, b.ownr_fn),
sortOrder: sortOrder:
tableState.sortedInfo.columnKey === "ownr_fn" && tableState.sortedInfo.columnKey === "ownr_fn" &&
tableState.sortedInfo.order tableState.sortedInfo.order,
}, },
{ {
title: t("owners.fields.ownr_addr1"), title: t("owners.fields.ownr_addr1"),
@@ -43,7 +43,7 @@ export default function JobsCreateOwnerInfoSearchComponent({
sorter: (a, b) => alphaSort(a.ownr_addr1, b.ownr_addr1), sorter: (a, b) => alphaSort(a.ownr_addr1, b.ownr_addr1),
sortOrder: sortOrder:
tableState.sortedInfo.columnKey === "ownr_addr1" && tableState.sortedInfo.columnKey === "ownr_addr1" &&
tableState.sortedInfo.order tableState.sortedInfo.order,
}, },
{ {
title: t("owners.fields.ownr_city"), title: t("owners.fields.ownr_city"),
@@ -52,7 +52,7 @@ export default function JobsCreateOwnerInfoSearchComponent({
sorter: (a, b) => alphaSort(a.ownr_city, b.ownr_city), sorter: (a, b) => alphaSort(a.ownr_city, b.ownr_city),
sortOrder: sortOrder:
tableState.sortedInfo.columnKey === "ownr_city" && tableState.sortedInfo.columnKey === "ownr_city" &&
tableState.sortedInfo.order tableState.sortedInfo.order,
}, },
{ {
title: t("owners.fields.ownr_ea"), title: t("owners.fields.ownr_ea"),
@@ -61,7 +61,7 @@ export default function JobsCreateOwnerInfoSearchComponent({
sorter: (a, b) => alphaSort(a.ownr_ea, b.ownr_ea), sorter: (a, b) => alphaSort(a.ownr_ea, b.ownr_ea),
sortOrder: sortOrder:
tableState.sortedInfo.columnKey === "ownr_ea" && tableState.sortedInfo.columnKey === "ownr_ea" &&
tableState.sortedInfo.order tableState.sortedInfo.order,
}, },
{ {
title: t("owners.fields.ownr_ph1"), title: t("owners.fields.ownr_ph1"),
@@ -73,51 +73,54 @@ export default function JobsCreateOwnerInfoSearchComponent({
sorter: (a, b) => alphaSort(a.ownr_ph1, b.ownr_ph1), sorter: (a, b) => alphaSort(a.ownr_ph1, b.ownr_ph1),
sortOrder: sortOrder:
tableState.sortedInfo.columnKey === "ownr_ph1" && tableState.sortedInfo.columnKey === "ownr_ph1" &&
tableState.sortedInfo.order tableState.sortedInfo.order,
} },
]; ];
const handleTableChange = (pagination, filters, sorter) => { const handleTableChange = (pagination, filters, sorter) => {
setTableState({ ...tableState, filteredInfo: filters, sortedInfo: sorter }); setTableState({ ...tableState, filteredInfo: filters, sortedInfo: sorter });
}; };
//TODO Implement searching & pagination
return ( return (
<Table <Table
loading={loading} loading={loading}
title={() => { title={() => {
return ( return (
<Input.Search <div className='imex-table-header'>
placeholder="Search..." <Input.Search
onSearch={value => { className='imex-table-header__search'
setState({ placeholder={t("general.labels.search")}
...state, onSearch={(value) => {
owner: { ...state.owner, search: value } setState({
}); ...state,
}} owner: { ...state.owner, search: value },
enterButton });
/> }}
enterButton
/>
</div>
); );
}} }}
size="small" size='small'
scroll={{ x: true }}
pagination={{ position: "top" }} pagination={{ position: "top" }}
columns={columns.map(item => ({ ...item }))} columns={columns}
rowKey="id" rowKey='id'
dataSource={owners} dataSource={owners}
onChange={handleTableChange} onChange={handleTableChange}
rowSelection={{ rowSelection={{
onSelect: props => { onSelect: (props) => {
setState({ setState({
...state, ...state,
owner: { ...state.owner, new: false, selectedid: props.id } owner: { ...state.owner, new: false, selectedid: props.id },
}); });
}, },
type: "radio", type: "radio",
selectedRowKeys: [state.owner.selectedid] selectedRowKeys: [state.owner.selectedid],
}} }}
onRow={(record, rowIndex) => { onRow={(record, rowIndex) => {
return { return {
onClick: event => { onClick: (event) => {
if (record) { if (record) {
if (record.id) { if (record.id) {
setState({ setState({
@@ -125,18 +128,18 @@ export default function JobsCreateOwnerInfoSearchComponent({
owner: { owner: {
...state.owner, ...state.owner,
new: false, new: false,
selectedid: record.id selectedid: record.id,
} },
}); });
return; return;
} }
} }
setState({ setState({
...state, ...state,
owner: { ...state.owner, selectedid: null } owner: { ...state.owner, selectedid: null },
}); });
} },
}; };
}} }}
/> />

View File

@@ -4,19 +4,24 @@ import { useTranslation } from "react-i18next";
import JobsCreateVehicleInfoNewComponent from "./jobs-create-vehicle-info.new.component"; import JobsCreateVehicleInfoNewComponent from "./jobs-create-vehicle-info.new.component";
import JobsCreateVehicleInfoSearchComponent from "./jobs-create-vehicle-info.search.component"; import JobsCreateVehicleInfoSearchComponent from "./jobs-create-vehicle-info.search.component";
const colSpan = {
sm: { span: 24 },
lg: { span: 12 },
};
export default function JobsCreateVehicleInfoComponent({ loading, vehicles }) { export default function JobsCreateVehicleInfoComponent({ loading, vehicles }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div> <div>
<Typography.Title>{t("jobs.labels.create.vehicleinfo")}</Typography.Title> <Typography.Title>{t("jobs.labels.create.vehicleinfo")}</Typography.Title>
<Row> <Row gutter={[32, 32]}>
<Col span={16}> <Col {...colSpan}>
<JobsCreateVehicleInfoSearchComponent <JobsCreateVehicleInfoSearchComponent
loading={loading} loading={loading}
vehicles={vehicles} vehicles={vehicles}
/> />
</Col> </Col>
<Col span={8}> <Col {...colSpan}>
<JobsCreateVehicleInfoNewComponent /> <JobsCreateVehicleInfoNewComponent />
</Col> </Col>
</Row> </Row>

View File

@@ -9,9 +9,11 @@ export default function JobsCreateVehicleInfoContainer({ form }) {
const [state] = useContext(JobCreateContext); const [state] = useContext(JobCreateContext);
const { loading, error, data } = useQuery(SEARCH_VEHICLE_BY_VIN, { const { loading, error, data } = useQuery(SEARCH_VEHICLE_BY_VIN, {
variables: { vin: `%${state.vehicle.search}%` }, variables: { vin: `%${state.vehicle.search}%` },
skip: !state.vehicle.search skip: !state.vehicle.search,
}); });
if (error) return <AlertComponent message={error.message} type='error' />; if (error) return <AlertComponent message={error.message} type='error' />;
return ( return (
<JobsCreateVehicleInfoComponent <JobsCreateVehicleInfoComponent
loading={loading} loading={loading}

View File

@@ -2,6 +2,7 @@ import { DatePicker, Form, Input, Checkbox } from "antd";
import React, { useContext } from "react"; import React, { useContext } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import JobCreateContext from "../../pages/jobs-create/jobs-create.context"; import JobCreateContext from "../../pages/jobs-create/jobs-create.context";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
export default function JobsCreateVehicleInfoNewComponent() { export default function JobsCreateVehicleInfoNewComponent() {
const [state, setState] = useContext(JobCreateContext); const [state, setState] = useContext(JobCreateContext);
@@ -18,178 +19,181 @@ export default function JobsCreateVehicleInfoNewComponent() {
vehicle: { vehicle: {
...state.vehicle, ...state.vehicle,
new: !state.vehicle.new, new: !state.vehicle.new,
selectedid: null selectedid: null,
} },
}); });
}} }}>
>
{t("jobs.labels.create.newvehicle")} {t("jobs.labels.create.newvehicle")}
</Checkbox> </Checkbox>
<Form.Item
label={t("vehicles.fields.v_vin")} <LayoutFormRow header={t("vehicles.forms.detail")} grow>
name={["vehicle", "data", "v_vin"]} <Form.Item
rules={[ label={t("vehicles.fields.v_vin")}
{ name={["vehicle", "data", "v_vin"]}
required: state.vehicle.new, rules={[
message: t("general.validation.required") {
} required: state.vehicle.new,
]} message: t("general.validation.required"),
> },
<Input disabled={!state.vehicle.new} /> ]}>
</Form.Item> <Input disabled={!state.vehicle.new} />
<Form.Item </Form.Item>
label={t("vehicles.fields.plate_no")} </LayoutFormRow>
name={["vehicle", "data", "plate_no"]} <LayoutFormRow grow>
rules={[ <Form.Item
{ label={t("vehicles.fields.v_color")}
required: state.vehicle.new, name={["vehicle", "data", "v_color"]}
message: t("general.validation.required") rules={[
} {
]} required: state.vehicle.new,
> message: t("general.validation.required"),
<Input disabled={!state.vehicle.new} /> },
</Form.Item> ]}>
<Form.Item <Input disabled={!state.vehicle.new} />
label={t("vehicles.fields.plate_st")} </Form.Item>
name={["vehicle", "data", "plate_st"]} <Form.Item
rules={[ label={t("vehicles.fields.v_model_yr")}
{ name={["vehicle", "data", "v_model_yr"]}
required: state.vehicle.new, rules={[
message: t("general.validation.required") {
} required: state.vehicle.new,
]} message: t("general.validation.required"),
> },
<Input disabled={!state.vehicle.new} /> ]}>
</Form.Item> <Input disabled={!state.vehicle.new} />
<Form.Item </Form.Item>
label={t("vehicles.fields.v_type")} </LayoutFormRow>
name={["vehicle", "data", "v_type"]}
> <LayoutFormRow grow>
<Input disabled={!state.vehicle.new} /> <Form.Item
</Form.Item> label={t("vehicles.fields.v_make_desc")}
<Form.Item name={["vehicle", "data", "v_make_desc"]}
label={t("vehicles.fields.v_trimcode")} rules={[
name={["vehicle", "data", "v_trimcode"]} {
> required: state.vehicle.new,
<Input disabled={!state.vehicle.new} /> message: t("general.validation.required"),
</Form.Item> },
<Form.Item ]}>
label={t("vehicles.fields.v_tone")} <Input disabled={!state.vehicle.new} />
name={["vehicle", "data", "v_tone"]} </Form.Item>
> <Form.Item
<Input disabled={!state.vehicle.new} /> label={t("vehicles.fields.v_model_desc")}
</Form.Item> name={["vehicle", "data", "v_model_desc"]}
<Form.Item rules={[
label={t("vehicles.fields.v_bstyle")} {
name={["vehicle", "data", "v_bstyle"]} required: state.vehicle.new,
> message: t("general.validation.required"),
<Input disabled={!state.vehicle.new} /> },
</Form.Item> ]}>
<Form.Item <Input disabled={!state.vehicle.new} />
label={t("vehicles.fields.v_stage")} </Form.Item>
name={["vehicle", "data", "v_stage"]} </LayoutFormRow>
>
<Input disabled={!state.vehicle.new} /> <LayoutFormRow header={t("vehicles.forms.registration")} grow>
</Form.Item> <Form.Item
<Form.Item label={t("vehicles.fields.plate_st")}
label={t("vehicles.fields.v_prod_dt")} name={["vehicle", "data", "plate_st"]}
name={["vehicle", "data", "v_prod_dt"]} rules={[
> {
<DatePicker disabled={!state.vehicle.new} /> required: state.vehicle.new,
</Form.Item> message: t("general.validation.required"),
{ },
//TODO Add handling for paint code json ]}>
} <Input disabled={!state.vehicle.new} />
<Form.Item </Form.Item>
label={t("vehicles.fields.v_paint_codes")} <Form.Item
name={["vehicle", "data", "v_paint_codes"]} label={t("vehicles.fields.plate_no")}
> name={["vehicle", "data", "plate_no"]}
<Input disabled={!state.vehicle.new} /> rules={[
</Form.Item> {
<Form.Item required: state.vehicle.new,
label={t("vehicles.fields.v_options")} message: t("general.validation.required"),
name={["vehicle", "data", "v_options"]} },
> ]}>
<Input disabled={!state.vehicle.new} /> <Input disabled={!state.vehicle.new} />
</Form.Item> </Form.Item>
<Form.Item </LayoutFormRow>
label={t("vehicles.fields.v_model_yr")}
name={["vehicle", "data", "v_model_yr"]} <LayoutFormRow header={t("vehicles.forms.misc")} grow>
rules={[ <Form.Item
{ label={t("vehicles.fields.v_type")}
required: state.vehicle.new, name={["vehicle", "data", "v_type"]}>
message: t("general.validation.required") <Input disabled={!state.vehicle.new} />
} </Form.Item>
]} <Form.Item
> label={t("vehicles.fields.v_trimcode")}
<Input disabled={!state.vehicle.new} /> name={["vehicle", "data", "v_trimcode"]}>
</Form.Item> <Input disabled={!state.vehicle.new} />
<Form.Item </Form.Item>
label={t("vehicles.fields.v_model_desc")} </LayoutFormRow>
name={["vehicle", "data", "v_model_desc"]} <LayoutFormRow grow>
rules={[ <Form.Item
{ label={t("vehicles.fields.v_tone")}
required: state.vehicle.new, name={["vehicle", "data", "v_tone"]}>
message: t("general.validation.required") <Input disabled={!state.vehicle.new} />
} </Form.Item>
]} <Form.Item
> label={t("vehicles.fields.v_bstyle")}
<Input disabled={!state.vehicle.new} /> name={["vehicle", "data", "v_bstyle"]}>
</Form.Item> <Input disabled={!state.vehicle.new} />
<Form.Item </Form.Item>
label={t("vehicles.fields.trim_color")} </LayoutFormRow>
name={["vehicle", "data", "trim_color"]} <LayoutFormRow grow>
> <Form.Item
<Input disabled={!state.vehicle.new} /> label={t("vehicles.fields.v_stage")}
</Form.Item> name={["vehicle", "data", "v_stage"]}>
<Form.Item <Input disabled={!state.vehicle.new} />
label={t("vehicles.fields.v_mldgcode")} </Form.Item>
name={["vehicle", "data", "v_mldgcode"]} <Form.Item
> label={t("vehicles.fields.v_prod_dt")}
<Input disabled={!state.vehicle.new} /> name={["vehicle", "data", "v_prod_dt"]}>
</Form.Item> <DatePicker disabled={!state.vehicle.new} />
<Form.Item </Form.Item>
label={t("vehicles.fields.v_makecode")} </LayoutFormRow>
name={["vehicle", "data", "v_makecode"]} <LayoutFormRow grow>
> <Form.Item
<Input disabled={!state.vehicle.new} /> label={t("vehicles.fields.v_paint_codes")}
</Form.Item> name={["vehicle", "data", "v_paint_codes"]}>
<Form.Item <Input disabled={!state.vehicle.new} />
label={t("vehicles.fields.v_make_desc")} </Form.Item>
name={["vehicle", "data", "v_make_desc"]} <Form.Item
rules={[ label={t("vehicles.fields.v_options")}
{ name={["vehicle", "data", "v_options"]}>
required: state.vehicle.new, <Input disabled={!state.vehicle.new} />
message: t("general.validation.required") </Form.Item>
} </LayoutFormRow>
]} <LayoutFormRow grow>
> <Form.Item
<Input disabled={!state.vehicle.new} /> label={t("vehicles.fields.trim_color")}
</Form.Item> name={["vehicle", "data", "trim_color"]}>
<Form.Item <Input disabled={!state.vehicle.new} />
label={t("vehicles.fields.v_engine")} </Form.Item>
name={["vehicle", "data", "v_engine"]} <Form.Item
> label={t("vehicles.fields.v_mldgcode")}
<Input disabled={!state.vehicle.new} /> name={["vehicle", "data", "v_mldgcode"]}>
</Form.Item> <Input disabled={!state.vehicle.new} />
<Form.Item </Form.Item>
label={t("vehicles.fields.v_cond")} </LayoutFormRow>
name={["vehicle", "data", "v_cond"]} <LayoutFormRow grow>
> <Form.Item
<Input disabled={!state.vehicle.new} /> label={t("vehicles.fields.v_makecode")}
</Form.Item> name={["vehicle", "data", "v_makecode"]}>
<Form.Item <Input disabled={!state.vehicle.new} />
label={t("vehicles.fields.v_color")} </Form.Item>
name={["vehicle", "data", "v_color"]} <Form.Item
rules={[ label={t("vehicles.fields.v_engine")}
{ name={["vehicle", "data", "v_engine"]}>
required: state.vehicle.new, <Input disabled={!state.vehicle.new} />
message: t("general.validation.required") </Form.Item>
} </LayoutFormRow>
]}
> <LayoutFormRow grow>
<Input disabled={!state.vehicle.new} /> <Form.Item
</Form.Item> label={t("vehicles.fields.v_cond")}
name={["vehicle", "data", "v_cond"]}>
<Input disabled={!state.vehicle.new} />
</Form.Item>
</LayoutFormRow>
</div> </div>
); );
} }

View File

@@ -7,12 +7,12 @@ import JobCreateContext from "../../pages/jobs-create/jobs-create.context";
export default function JobsCreateVehicleInfoSearchComponent({ export default function JobsCreateVehicleInfoSearchComponent({
loading, loading,
vehicles vehicles,
}) { }) {
const [state, setState] = useContext(JobCreateContext); const [state, setState] = useContext(JobCreateContext);
const [tableState, setTableState] = useState({ const [tableState, setTableState] = useState({
sortedInfo: {}, sortedInfo: {},
filteredInfo: { text: "" } filteredInfo: { text: "" },
}); });
const { t } = useTranslation(); const { t } = useTranslation();
@@ -28,7 +28,7 @@ export default function JobsCreateVehicleInfoSearchComponent({
tableState.sortedInfo.order, tableState.sortedInfo.order,
render: (text, record) => ( render: (text, record) => (
<Link to={"/manage/vehicles/" + record.id}>{record.v_vin}</Link> <Link to={"/manage/vehicles/" + record.id}>{record.v_vin}</Link>
) ),
}, },
{ {
title: t("vehicles.fields.description"), title: t("vehicles.fields.description"),
@@ -38,7 +38,7 @@ export default function JobsCreateVehicleInfoSearchComponent({
return ( return (
<span>{`${record.v_model_yr} ${record.v_make_desc} ${record.v_model_desc} ${record.v_color}`}</span> <span>{`${record.v_model_yr} ${record.v_make_desc} ${record.v_model_desc} ${record.v_color}`}</span>
); );
} },
}, },
{ {
title: t("vehicles.fields.plate_no"), title: t("vehicles.fields.plate_no"),
@@ -46,56 +46,59 @@ export default function JobsCreateVehicleInfoSearchComponent({
key: "plate", key: "plate",
render: (text, record) => { render: (text, record) => {
return <span>{`${record.plate_st} | ${record.plate_no}`}</span>; return <span>{`${record.plate_st} | ${record.plate_no}`}</span>;
} },
} },
]; ];
const handleTableChange = (pagination, filters, sorter) => { const handleTableChange = (pagination, filters, sorter) => {
setTableState({ ...tableState, filteredInfo: filters, sortedInfo: sorter }); setTableState({ ...tableState, filteredInfo: filters, sortedInfo: sorter });
}; };
//TODO Implement searching & pagination
return ( return (
<Table <Table
loading={loading} loading={loading}
title={() => { title={() => {
return ( return (
<Input.Search <div className='imex-table-header'>
placeholder="Search..." <Input.Search
onSearch={value => { className='imex-table-header__search'
setState({ placeholder={t("general.labels.search")}
...state, onSearch={(value) => {
vehicle: { ...state.vehicle, search: value } setState({
}); ...state,
}} vehicle: { ...state.vehicle, search: value },
enterButton });
/> }}
enterButton
/>
</div>
); );
}} }}
size="small" size='small'
scroll={{ x: true }}
pagination={{ position: "top" }} pagination={{ position: "top" }}
columns={columns.map(item => ({ ...item }))} columns={columns}
rowKey="id" rowKey='id'
dataSource={vehicles} dataSource={vehicles}
onChange={handleTableChange} onChange={handleTableChange}
rowSelection={{ rowSelection={{
onSelect: props => { onSelect: (props) => {
setState({ setState({
...state, ...state,
vehicle: { vehicle: {
...state.vehicle, ...state.vehicle,
new: false, new: false,
selectedid: props.id, selectedid: props.id,
vehicleObj: props vehicleObj: props,
} },
}); });
}, },
type: "radio", type: "radio",
selectedRowKeys: [state.vehicle.selectedid] selectedRowKeys: [state.vehicle.selectedid],
}} }}
onRow={(record, rowIndex) => { onRow={(record, rowIndex) => {
return { return {
onClick: event => { onClick: (event) => {
if (record) { if (record) {
if (record.id) { if (record.id) {
setState({ setState({
@@ -104,8 +107,8 @@ export default function JobsCreateVehicleInfoSearchComponent({
...state.vehicle, ...state.vehicle,
new: false, new: false,
selectedid: record.id, selectedid: record.id,
vehicleObj: record vehicleObj: record,
} },
}); });
return; return;
@@ -113,9 +116,9 @@ export default function JobsCreateVehicleInfoSearchComponent({
} }
setState({ setState({
...state, ...state,
vehicle: { ...state.vehicle, selectedid: null, vehicleObj: null } vehicle: { ...state.vehicle, selectedid: null, vehicleObj: null },
}); });
} },
}; };
}} }}
/> />

View File

@@ -1,4 +1,4 @@
import { DatePicker, Form } from "antd"; import { Form } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component"; import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";

View File

@@ -167,7 +167,6 @@ export default function JobsList({ refetch, loading, jobs, total }) {
const handleTableChange = (pagination, filters, sorter) => { const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
console.log("handleTableChange -> sorter", sorter);
search.page = pagination.current; search.page = pagination.current;
search.sortcolumn = sorter.columnKey; search.sortcolumn = sorter.columnKey;
search.sortorder = sorter.order; search.sortorder = sorter.order;
@@ -178,13 +177,26 @@ export default function JobsList({ refetch, loading, jobs, total }) {
<div> <div>
<Table <Table
loading={loading} loading={loading}
size='small'
scroll={{ x: true }}
pagination={{
position: "top",
pageSize: 25,
current: parseInt(page || 1),
total: total,
}}
columns={columns}
rowKey='id'
dataSource={jobs}
onChange={handleTableChange}
title={() => { title={() => {
return ( return (
<div style={{ display: "flex" }}> <div className='imex-table-header'>
<Button onClick={() => refetch()}> <Button onClick={() => refetch()}>
<SyncOutlined /> <SyncOutlined />
</Button> </Button>
<Input.Search <Input.Search
className='imex-table-header__search'
placeholder={t("general.labels.search")} placeholder={t("general.labels.search")}
onSearch={(value) => { onSearch={(value) => {
search.search = value; search.search = value;
@@ -195,17 +207,6 @@ export default function JobsList({ refetch, loading, jobs, total }) {
</div> </div>
); );
}} }}
size="small"
pagination={{
position: "top",
pageSize: 25,
current: parseInt(page || 1),
total: total,
}}
columns={columns}
rowKey="id"
dataSource={jobs}
onChange={handleTableChange}
/> />
</div> </div>
); );

View File

@@ -261,7 +261,7 @@ export function JobsList({ bodyshop }) {
onChange={(e) => { onChange={(e) => {
setSearchText(e.target.value); setSearchText(e.target.value);
}} }}
vale={searchText} value={searchText}
enterButton enterButton
/> />
</div> </div>

View File

@@ -2,10 +2,17 @@ import React from "react";
import { Row, Col, Typography } from "antd"; import { Row, Col, Typography } from "antd";
import "./layout-form-row.styles.scss"; import "./layout-form-row.styles.scss";
export default function LayoutFormRow({ header, children }) { export default function LayoutFormRow({ header, children, grow = false }) {
if (!!!children.length) { if (!!!children.length) {
//We have only one element. It's going to get the whole thing. //We have only one element. It's going to get the whole thing.
return children; return (
<div className='imex-form-row'>
{header ? (
<Typography.Title level={4}>{header}</Typography.Title>
) : null}
{children}
</div>
);
} }
const rowGutter = { gutter: [16, 16] }; const rowGutter = { gutter: [16, 16] };
@@ -15,16 +22,16 @@ export default function LayoutFormRow({ header, children }) {
span: 24, span: 24,
}, },
sm: { sm: {
span: 12, span: !grow ? 12 : Math.max(12, 24 / children.length),
}, },
md: { md: {
span: 8, span: !grow ? 8 : Math.max(8, 24 / children.length),
}, },
lg: { lg: {
span: 6, span: !grow ? 6 : Math.max(6, 24 / children.length),
}, },
xl: { xl: {
span: 4, span: !grow ? 4 : Math.max(4, 24 / children.length),
}, },
}; };
}; };

View File

@@ -1,75 +1,124 @@
import { Button, Col, Form, Input, Row, Switch } from "antd"; import { Button, Form, Input, Switch } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
import FormItemEmail from "../form-items-formatted/email-form-item.component"; import FormItemEmail from "../form-items-formatted/email-form-item.component";
import FormItemPhone from "../form-items-formatted/phone-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 }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { getFieldValue } = form; const { getFieldValue } = form;
return ( return (
<div> <div>
<Button type='primary' key='submit' htmlType='submit'> <div className='imex-flex-row imex-flex-row__flex-space-around'>
{t("general.actions.save")} <Button
</Button> className='imex-flex-row__margin-large'
<Row> type='primary'
<Col span={8}> key='submit'
<Form.Item label={t("owners.fields.ownr_ln")} name='ownr_ln'> htmlType='submit'>
<Input /> {t("general.actions.save")}
</Form.Item> </Button>
<Form.Item label={t("owners.fields.ownr_fn")} name='ownr_fn'> <div className='imex-flex-row__grow imex-flex-row__margin-large'>
<Input /> <FormFieldsChanged form={form} />
</Form.Item> </div>
<Form.Item </div>
label={t("owners.fields.allow_text_message")}
name='allow_text_message' <LayoutFormRow header={t("owners.forms.name")}>
valuePropName='checked'> <Form.Item label={t("owners.fields.ownr_title")} name='ownr_title'>
<Switch /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("owners.fields.ownr_addr1")} name='ownr_addr1'> <Form.Item label={t("owners.fields.ownr_ln")} name='ownr_ln'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("owners.fields.ownr_addr2")} name='ownr_addr2'> <Form.Item label={t("owners.fields.ownr_fn")} name='ownr_fn'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("owners.fields.ownr_city")} name='ownr_city'> <Form.Item label={t("owners.fields.ownr_co_nm")} name='ownr_co_nm'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("owners.fields.ownr_ctry")} name='ownr_ctry'> </LayoutFormRow>
<Input />
</Form.Item> <LayoutFormRow header={t("owners.forms.address")}>
</Col> <Form.Item
<Col span={8}> label={t("owners.fields.ownr_addr1")}
<Form.Item name='ownr_addr1'
label={t("owners.fields.ownr_ea")} rules={[
name='ownr_ea' {
rules={[ required: true,
{ message: t("general.validation.required"),
type: "email", },
message: "This is not a valid email address." ]}>
} <Input />
]}> </Form.Item>
<FormItemEmail email={getFieldValue("ownr_ea")} /> <Form.Item label={t("owners.fields.ownr_addr2")} name='ownr_addr2'>
</Form.Item> <Input />
<Form.Item label={t("owners.fields.ownr_ph1")} name='ownr_ph1'> </Form.Item>
<FormItemPhone customInput={Input} /> <Form.Item
</Form.Item> label={t("owners.fields.ownr_city")}
<Form.Item label={t("owners.fields.ownr_st")} name='ownr_st'> name='ownr_city'
<Input /> rules={[
</Form.Item> {
<Form.Item label={t("owners.fields.ownr_zip")} name='ownr_zip'> required: true,
<Input /> message: t("general.validation.required"),
</Form.Item> },
<Form.Item ]}>
label={t("owners.fields.preferred_contact")} <Input />
name='preferred_contact'> </Form.Item>
<Input /> <Form.Item
</Form.Item> label={t("owners.fields.ownr_st")}
<Form.Item label={t("owners.fields.ownr_title")} name='ownr_title'> name='ownr_st'
<Input /> rules={[
</Form.Item> {
</Col> required: true,
</Row> message: t("general.validation.required"),
},
]}>
<Input />
</Form.Item>
<Form.Item
label={t("owners.fields.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'>
<Input />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("owners.forms.contact")}>
<Form.Item
label={t("owners.fields.allow_text_message")}
name='allow_text_message'
valuePropName='checked'>
<Switch />
</Form.Item>
<Form.Item
label={t("owners.fields.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'>
<FormItemPhone customInput={Input} />
</Form.Item>
<Form.Item
label={t("owners.fields.preferred_contact")}
name='preferred_contact'>
<Input />
</Form.Item>
</LayoutFormRow>
</div> </div>
); );
} }

View File

@@ -11,12 +11,12 @@ function OwnerDetailFormContainer({ owner, refetch }) {
const [updateOwner] = useMutation(UPDATE_OWNER); const [updateOwner] = useMutation(UPDATE_OWNER);
const handleFinish = values => { const handleFinish = (values) => {
updateOwner({ updateOwner({
variables: { ownerId: owner.id, owner: values } variables: { ownerId: owner.id, owner: values },
}).then(r => { }).then((r) => {
notification["success"]({ notification["success"]({
message: t("owners.successes.save") message: t("owners.successes.save"),
}); });
//TODO Better way to reset the field decorators? //TODO Better way to reset the field decorators?
if (refetch) refetch().then(); if (refetch) refetch().then();
@@ -28,9 +28,9 @@ function OwnerDetailFormContainer({ owner, refetch }) {
<Form <Form
form={form} form={form}
onFinish={handleFinish} onFinish={handleFinish}
autoComplete="off" autoComplete='off'
initialValues={owner} layout='vertical'
> initialValues={owner}>
<OwnerDetailFormComponent form={form} /> <OwnerDetailFormComponent form={form} />
</Form> </Form>
); );

View File

@@ -9,7 +9,7 @@ import CurrencyFormatter from "../../utils/CurrencyFormatter";
import OwnerDetailUpdateJobsComponent from "../owner-detail-update-jobs/owner-detail-update-jobs.component"; import OwnerDetailUpdateJobsComponent from "../owner-detail-update-jobs/owner-detail-update-jobs.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop,
}); });
function OwnerDetailJobsComponent({ bodyshop, owner }) { function OwnerDetailJobsComponent({ bodyshop, owner }) {
@@ -25,7 +25,7 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
<Link to={`/manage/jobs/${record.id}`}> <Link to={`/manage/jobs/${record.id}`}>
{record.ro_number ? record.ro_number : `EST ${record.est_number}`} {record.ro_number ? record.ro_number : `EST ${record.est_number}`}
</Link> </Link>
) ),
}, },
{ {
title: t("jobs.fields.vehicle"), title: t("jobs.fields.vehicle"),
@@ -35,17 +35,17 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
<Link to={`/manage/vehicles/${record.vehicleid}`}> <Link to={`/manage/vehicles/${record.vehicleid}`}>
{`${record.v_model_yr} ${record.v_make_desc} ${record.v_model_desc}`} {`${record.v_model_yr} ${record.v_make_desc} ${record.v_model_desc}`}
</Link> </Link>
) ),
}, },
{ {
title: t("jobs.fields.clm_no"), title: t("jobs.fields.clm_no"),
dataIndex: "clm_no", dataIndex: "clm_no",
key: "clm_no" key: "clm_no",
}, },
{ {
title: t("jobs.fields.status"), title: t("jobs.fields.status"),
dataIndex: "status", dataIndex: "status",
key: "status" key: "status",
}, },
{ {
@@ -54,8 +54,8 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
key: "clm_total", key: "clm_total",
render: (text, record) => ( render: (text, record) => (
<CurrencyFormatter>{record.clm_total}</CurrencyFormatter> <CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
) ),
} },
]; ];
return ( return (
@@ -70,20 +70,31 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
</div> </div>
)} )}
pagination={{ position: "bottom" }} pagination={{ position: "bottom" }}
columns={columns.map(item => ({ ...item }))} columns={columns}
rowKey="id" scroll={{ x: true }}
rowKey='id'
dataSource={owner.jobs} dataSource={owner.jobs}
rowSelection={{ rowSelection={{
onSelect: (record, selected, selectedRows) => { onSelect: (record, selected, selectedRows) => {
setSelectedJobs(selectedRows ? selectedRows.map(i => i.id) : []); setSelectedJobs(selectedRows ? selectedRows.map((i) => i.id) : []);
},
onSelectAll: (selected, selectedRows, changeRows) => {
setSelectedJobs(
selectedRows
? selectedRows
.filter((i) =>
bodyshop.md_ro_statuses.open_statuses.includes(i.status)
)
.map((i) => i.id)
: []
);
}, },
selectedRowKeys: selectedJobs, selectedRowKeys: selectedJobs,
getCheckboxProps: record => ({ getCheckboxProps: (record) => ({
disabled: bodyshop.md_ro_statuses.open_statuses disabled: bodyshop.md_ro_statuses.open_statuses
? !bodyshop.md_ro_statuses.open_statuses.includes(record.status) ? !bodyshop.md_ro_statuses.open_statuses.includes(record.status)
: true : true,
}) }),
}} }}
/> />
); );

View File

@@ -1,4 +1,5 @@
import { Input, Table } from "antd"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Input, Table } from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@@ -8,7 +9,7 @@ import { alphaSort } from "../../utils/sorters";
export default function OwnersListComponent({ loading, owners, refetch }) { export default function OwnersListComponent({ loading, owners, refetch }) {
const [state, setState] = useState({ const [state, setState] = useState({
sortedInfo: {}, sortedInfo: {},
filteredInfo: { text: "" } filteredInfo: { text: "" },
}); });
const { t } = useTranslation(); const { t } = useTranslation();
@@ -18,17 +19,14 @@ export default function OwnersListComponent({ loading, owners, refetch }) {
title: t("owners.fields.name"), title: t("owners.fields.name"),
dataIndex: "name", dataIndex: "name",
key: "name", key: "name",
// onFilter: (value, record) => record.ro_number.includes(value),
// filteredValue: state.filteredInfo.text || null,
sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
sortOrder: sortOrder:
state.sortedInfo.columnKey === "name" && state.sortedInfo.order, state.sortedInfo.columnKey === "name" && state.sortedInfo.order,
render: (text, record) => ( render: (text, record) => (
<Link to={"/manage/owners/" + record.id}> <Link to={"/manage/owners/" + record.id}>
{`${record.ownr_fn} ${record.ownr_ln}`} {`${record.ownr_fn} ${record.ownr_ln}`}
</Link> </Link>
) ),
}, },
{ {
title: t("owners.fields.ownr_ph1"), title: t("owners.fields.ownr_ph1"),
@@ -39,12 +37,12 @@ export default function OwnersListComponent({ loading, owners, refetch }) {
state.sortedInfo.columnKey === "ownr_ph1" && state.sortedInfo.order, state.sortedInfo.columnKey === "ownr_ph1" && state.sortedInfo.order,
render: (text, record) => { render: (text, record) => {
return <PhoneFormatter>{record.ownr_ph1}</PhoneFormatter>; return <PhoneFormatter>{record.ownr_ph1}</PhoneFormatter>;
} },
}, },
{ {
title: t("owners.fields.ownr_ea"), title: t("owners.fields.ownr_ea"),
dataIndex: "ownr_ea", dataIndex: "ownr_ea",
key: "ownr_ea" key: "ownr_ea",
}, },
{ {
title: t("owners.fields.address"), title: t("owners.fields.address"),
@@ -52,36 +50,43 @@ export default function OwnersListComponent({ loading, owners, refetch }) {
key: "address", key: "address",
render: (text, record) => { render: (text, record) => {
return ( return (
<div>{`${record.ownr_addr1 || ""} ${record.ownr_addr2 || <div>{`${record.ownr_addr1 || ""} ${record.ownr_addr2 || ""} ${
""} ${record.ownr_city || ""} ${record.ownr_st || record.ownr_city || ""
""} ${record.ownr_zip || ""}`}</div> } ${record.ownr_st || ""} ${record.ownr_zip || ""}`}</div>
); );
} },
} },
]; ];
const handleTableChange = (pagination, filters, sorter) => { const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
}; };
//TODO Implement searching & pagination
return ( return (
<Table <Table
loading={loading} loading={loading}
title={() => { title={() => {
return ( return (
<Input.Search <div className='imex-table-header'>
placeholder="Search..." <Button onClick={() => refetch()}>
onSearch={value => { <SyncOutlined />
console.log(value); </Button>
}} <Input.Search
enterButton className='imex-table-header__search'
/> placeholder={t("general.labels.search")}
onChange={(e) => {
//setSearchText(e.target.value);
}}
//vale={searchText}
enterButton
/>
</div>
); );
}} }}
size="small" size='small'
pagination={{ position: "top" }} pagination={{ position: "top" }}
columns={columns.map(item => ({ ...item }))} columns={columns}
rowKey="id" rowKey='id'
scroll={{ x: true }}
dataSource={owners} dataSource={owners}
onChange={handleTableChange} onChange={handleTableChange}
/> />

View File

@@ -1,15 +1,15 @@
import React from "react";
import { useQuery } from "@apollo/react-hooks"; import { useQuery } from "@apollo/react-hooks";
import React from "react";
import { QUERY_ALL_OWNERS } from "../../graphql/owners.queries"; import { QUERY_ALL_OWNERS } from "../../graphql/owners.queries";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
import OwnersListComponent from "./owners-list.component"; import OwnersListComponent from "./owners-list.component";
export default function OwnersListContainer() { export default function OwnersListContainer() {
const { loading, error, data, refetch } = useQuery(QUERY_ALL_OWNERS, { const { loading, error, data, refetch } = useQuery(QUERY_ALL_OWNERS, {
fetchPolicy: "network-only" fetchPolicy: "network-only",
}); });
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent message={error.message} type='error' />;
return ( return (
<OwnersListComponent <OwnersListComponent
loading={loading} loading={loading}

View File

@@ -4,6 +4,7 @@ import CurrencyFormatter from "../../utils/CurrencyFormatter";
import PhoneFormatter from "../../utils/PhoneFormatter"; import PhoneFormatter from "../../utils/PhoneFormatter";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import DataLabel from "../data-label/data-label.component";
export default function ScheduleEventComponent({ event, handleCancel }) { export default function ScheduleEventComponent({ event, handleCancel }) {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -23,59 +24,58 @@ export default function ScheduleEventComponent({ event, handleCancel }) {
</span> </span>
</div> </div>
)} )}
{event.job ? ( {event.job ? (
<div> <div>
<div>{`${t("jobs.fields.ro_number")}: ${ <DataLabel label={t("jobs.fields.ro_number")}>
(event.job && event.job.ro_number) || "" {(event.job && event.job.ro_number) || ""}
}`}</div> </DataLabel>
<div> <DataLabel label={t("jobs.fields.clm_total")}>
{t("jobs.fields.clm_total")}:
<CurrencyFormatter> <CurrencyFormatter>
{(event.job && event.job.clm_total) || ""} {(event.job && event.job.clm_total) || ""}
</CurrencyFormatter> </CurrencyFormatter>
</div> </DataLabel>
<div>{`${t("jobs.fields.clm_no")}: ${ <DataLabel hideIfNull label={t("jobs.fields.ins_co_nm")}>
(event.job && event.job.clm_no) || "" {(event.job && event.job.ins_co_nm) || ""}
}`}</div> </DataLabel>
<div> <DataLabel hideIfNull label={t("jobs.fields.clm_no")}>
{t("jobs.fields.ownr_ea")}:{(event.job && event.job.ownr_ea) || ""} {(event.job && event.job.clm_no) || ""}
</div> </DataLabel>
<div> <DataLabel label={t("jobs.fields.ownr_ea")}>
{t("jobs.fields.ownr_ph1")}: {(event.job && event.job.ownr_ea) || ""}
</DataLabel>
<DataLabel label={t("jobs.fields.ownr_ph1")}>
<PhoneFormatter> <PhoneFormatter>
{(event.job && event.job.ownr_ph1) || ""} {(event.job && event.job.ownr_ph1) || ""}
</PhoneFormatter> </PhoneFormatter>
</div> </DataLabel>
</div> </div>
) : null} ) : null}
{
//TODO Add phone 1 MessagingActionTypes. <div className='imex-flex-row'>
} {event.job ? (
{event.job ? ( <Link to={`/manage/jobs/${event.job && event.job.id}`}>
<Link to={`/manage/jobs/${event.job && event.job.id}`}> <Button>{t("appointments.actions.viewjob")}</Button>
<Button>{t("appointments.actions.viewjob")}</Button> </Link>
</Link> ) : null}
) : null} <Button onClick={() => handleCancel(event.id)} disabled={event.arrived}>
<Button onClick={() => handleCancel(event.id)} disabled={event.arrived}> {t("appointments.actions.cancel")}
{t("appointments.actions.cancel")} </Button>
</Button> <Button disabled={event.arrived}>
<Button disabled={event.arrived}> {t("appointments.actions.reschedule")}
{ </Button>
//TODO Add reschedule Func. {event.isintake ? (
} <Link
{t("appointments.actions.reschedule")} to={{
</Button> pathname: `/manage/jobs/${event.job && event.job.id}/intake`,
{event.isintake ? ( search: `?appointmentId=${event.id}`,
<Link }}>
to={{ <Button disabled={event.arrived}>
pathname: `/manage/jobs/${event.job && event.job.id}/intake`, {t("appointments.actions.intake")}
search: `?appointmentId=${event.id}`, </Button>
}}> </Link>
<Button disabled={event.arrived}> ) : null}
{t("appointments.actions.intake")} </div>
</Button>
</Link>
) : null}
</div> </div>
); );
@@ -96,14 +96,9 @@ export default function ScheduleEventComponent({ event, handleCancel }) {
</div> </div>
); );
const Load = (
<div className='load'>
<Progress percent={77} showInfo={false} />
</div>
);
return ( return (
<Popover content={popoverContent}> <Popover trigger='click' content={popoverContent}>
<div>{event.allDay ? Load : RegularEvent}</div> {RegularEvent}
</Popover> </Popover>
); );
} }

View File

@@ -1,94 +1,160 @@
import { Button, Col, DatePicker, Form, Input, Row } from "antd"; import { Button, DatePicker, Form, Input, InputNumber } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
export default function VehicleDetailFormComponent() { 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 }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div> <div>
<Button type="primary" key="submit" htmlType="submit"> <div className='imex-flex-row imex-flex-row__flex-space-around'>
{t("general.actions.save")} <Button
</Button> className='imex-flex-row__margin-large'
<Row> type='primary'
<Col span={8}> key='submit'
<Form.Item label={t("vehicles.fields.v_vin")} name="v_vin"> htmlType='submit'>
<Input /> {t("general.actions.save")}
</Form.Item> </Button>
<Form.Item label={t("vehicles.fields.plate_no")} name="plate_no"> <div className='imex-flex-row__grow imex-flex-row__margin-large'>
<Input /> <FormFieldsChanged form={form} />
</Form.Item> </div>
<Form.Item label={t("vehicles.fields.plate_st")} name="plate_st"> </div>
<Input />
</Form.Item> <LayoutFormRow header={t("vehicles.forms.detail")}>
<Form.Item label={t("vehicles.fields.v_type")} name="v_type"> <Form.Item
<Input /> label={t("vehicles.fields.v_model_yr")}
</Form.Item> name='v_model_yr'
<Form.Item label={t("vehicles.fields.v_trimcode")} name="v_trimcode"> rules={[
<Input /> {
</Form.Item> required: true,
<Form.Item label={t("vehicles.fields.v_tone")} name="v_tone"> message: t("general.validation.required"),
<Input /> },
</Form.Item> ]}>
<Form.Item label={t("vehicles.fields.v_bstyle")} name="v_bstyle"> <InputNumber precision={0} />
<Input /> </Form.Item>
</Form.Item> <Form.Item
</Col> label={t("vehicles.fields.v_make_desc")}
<Col span={8}> name='v_make_desc'
<Form.Item label={t("vehicles.fields.v_stage")} name="v_stage"> rules={[
<Input /> {
</Form.Item> required: true,
<Form.Item label={t("vehicles.fields.v_prod_dt")} name="v_prod_dt"> message: t("general.validation.required"),
<DatePicker /> },
</Form.Item> ]}>
{ <Input />
//TODO Add handling for paint code json </Form.Item>
} <Form.Item
<Form.Item label={t("vehicles.fields.v_model_desc")}
label={t("vehicles.fields.v_paint_codes")} name='v_model_desc'
name="v_paint_codes" rules={[
> {
<Input /> required: true,
</Form.Item> message: t("general.validation.required"),
<Form.Item label={t("vehicles.fields.v_options")} name="v_options"> },
<Input /> ]}>
</Form.Item> <Input />
<Form.Item label={t("vehicles.fields.v_model_yr")} name="v_model_yr"> </Form.Item>
<Input /> <Form.Item
</Form.Item> label={t("vehicles.fields.v_color")}
<Form.Item name='v_color'
label={t("vehicles.fields.v_model_desc")} rules={[
name="v_model_desc" {
> required: true,
<Input /> message: t("general.validation.required"),
</Form.Item> },
<Form.Item label={t("vehicles.fields.trim_color")} name="trim_color"> ]}>
<Input /> <Input />
</Form.Item> </Form.Item>
</Col> <Form.Item
<Col span={8}> label={t("vehicles.fields.v_vin")}
<Form.Item label={t("vehicles.fields.v_mldgcode")} name="v_mldgcode"> name='v_vin'
<Input /> rules={[
</Form.Item> {
<Form.Item label={t("vehicles.fields.v_makecode")} name="v_makecode"> required: true,
<Input /> message: t("general.validation.required"),
</Form.Item> },
<Form.Item ]}>
label={t("vehicles.fields.v_make_desc")} <Input />
name="v_make_desc" </Form.Item>
> </LayoutFormRow>
<Input />
</Form.Item> <LayoutFormRow header={t("vehicles.forms.registration")}>
<Form.Item label={t("vehicles.fields.v_engine")} name="v_engine"> <Form.Item
<Input /> label={t("vehicles.fields.plate_st")}
</Form.Item> name='plate_st'
<Form.Item label={t("vehicles.fields.v_cond")} name="v_cond"> rules={[
<Input /> {
</Form.Item> required: true,
<Form.Item label={t("vehicles.fields.v_color")} name="v_color"> message: t("general.validation.required"),
<Input /> },
</Form.Item> ]}>
</Col> <Input />
</Row> </Form.Item>
<Form.Item
label={t("vehicles.fields.plate_no")}
name='plate_no'
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<Input />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("vehicles.forms.misc")}>
<Form.Item label={t("vehicles.fields.v_type")} name='v_type'>
<Input />
</Form.Item>
<Form.Item label={t("vehicles.fields.v_trimcode")} name='v_trimcode'>
<Input />
</Form.Item>
<Form.Item label={t("vehicles.fields.v_tone")} name='v_tone'>
<Input />
</Form.Item>
<Form.Item label={t("vehicles.fields.v_bstyle")} name='v_bstyle'>
<Input />
</Form.Item>
<Form.Item label={t("vehicles.fields.v_stage")} name='v_stage'>
<Input />
</Form.Item>
<Form.Item label={t("vehicles.fields.v_prod_dt")} name='v_prod_dt'>
<DatePicker />
</Form.Item>
{
//TODO Add handling for paint code json
}
<Form.Item
label={t("vehicles.fields.v_paint_codes")}
name='v_paint_codes'>
<Input />
</Form.Item>
<Form.Item label={t("vehicles.fields.v_options")} name='v_options'>
<Input />
</Form.Item>
<Form.Item label={t("vehicles.fields.trim_color")} name='trim_color'>
<Input />
</Form.Item>
<Form.Item label={t("vehicles.fields.v_mldgcode")} name='v_mldgcode'>
<Input />
</Form.Item>
<Form.Item label={t("vehicles.fields.v_makecode")} name='v_makecode'>
<Input />
</Form.Item>
<Form.Item label={t("vehicles.fields.v_engine")} name='v_engine'>
<Input />
</Form.Item>
<Form.Item label={t("vehicles.fields.v_cond")} name='v_cond'>
<Input />
</Form.Item>
</LayoutFormRow>
</div> </div>
); );
} }

View File

@@ -11,12 +11,12 @@ function VehicleDetailFormContainer({ vehicle, refetch }) {
const [updateVehicle] = useMutation(UPDATE_VEHICLE); const [updateVehicle] = useMutation(UPDATE_VEHICLE);
const [form] = Form.useForm(); const [form] = Form.useForm();
const handleFinish = values => { const handleFinish = (values) => {
updateVehicle({ updateVehicle({
variables: { vehId: vehicle.id, vehicle: values } variables: { vehId: vehicle.id, vehicle: values },
}).then(r => { }).then((r) => {
notification["success"]({ notification["success"]({
message: t("vehicles.successes.save") message: t("vehicles.successes.save"),
}); });
//TODO Better way to reset the field decorators? //TODO Better way to reset the field decorators?
if (refetch) refetch(); if (refetch) refetch();
@@ -27,13 +27,13 @@ function VehicleDetailFormContainer({ vehicle, refetch }) {
<Form <Form
onFinish={handleFinish} onFinish={handleFinish}
form={form} form={form}
autoComplete="off" autoComplete='off'
layout='vertical'
initialValues={{ initialValues={{
...vehicle, ...vehicle,
v_prod_dt: vehicle.v_prod_dt ? moment(vehicle.v_prod_dt) : null v_prod_dt: vehicle.v_prod_dt ? moment(vehicle.v_prod_dt) : null,
}} }}>
> <VehicleDetailFormComponent form={form} />
<VehicleDetailFormComponent />
</Form> </Form>
); );
} }

View File

@@ -1,15 +1,15 @@
import React, { useState } from "react";
import { Table } from "antd"; import { Table } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import VehicleDetailUpdateJobsComponent from "../vehicle-detail-update-jobs/vehicle-detail-update-jobs.component"; import VehicleDetailUpdateJobsComponent from "../vehicle-detail-update-jobs/vehicle-detail-update-jobs.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop,
}); });
export function VehicleDetailJobsComponent({ vehicle, bodyshop }) { export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
@@ -26,7 +26,7 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
<Link to={`/manage/jobs/${record.id}`}> <Link to={`/manage/jobs/${record.id}`}>
{record.ro_number ? record.ro_number : `EST ${record.est_number}`} {record.ro_number ? record.ro_number : `EST ${record.est_number}`}
</Link> </Link>
) ),
}, },
{ {
title: t("jobs.fields.owner"), title: t("jobs.fields.owner"),
@@ -36,17 +36,17 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
<Link to={`/manage/owners/${record.owner.id}`}> <Link to={`/manage/owners/${record.owner.id}`}>
{`${record.ownr_fn} ${record.ownr_ln}`} {`${record.ownr_fn} ${record.ownr_ln}`}
</Link> </Link>
) ),
}, },
{ {
title: t("jobs.fields.clm_no"), title: t("jobs.fields.clm_no"),
dataIndex: "clm_no", dataIndex: "clm_no",
key: "clm_no" key: "clm_no",
}, },
{ {
title: t("jobs.fields.status"), title: t("jobs.fields.status"),
dataIndex: "status", dataIndex: "status",
key: "status" key: "status",
}, },
{ {
@@ -55,8 +55,8 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
key: "clm_total", key: "clm_total",
render: (text, record) => ( render: (text, record) => (
<CurrencyFormatter>{record.clm_total}</CurrencyFormatter> <CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
) ),
} },
]; ];
return ( return (
@@ -71,20 +71,31 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
</div> </div>
)} )}
pagination={{ position: "bottom" }} pagination={{ position: "bottom" }}
columns={columns.map(item => ({ ...item }))} columns={columns}
rowKey="id" rowKey='id'
scroll={{ x: true }}
dataSource={vehicle.jobs} dataSource={vehicle.jobs}
rowSelection={{ rowSelection={{
onSelect: (record, selected, selectedRows) => { onSelect: (record, selected, selectedRows) => {
setSelectedJobs(selectedRows ? selectedRows.map(i => i.id) : []); setSelectedJobs(selectedRows ? selectedRows.map((i) => i.id) : []);
},
onSelectAll: (selected, selectedRows, changeRows) => {
setSelectedJobs(
selectedRows
? selectedRows
.filter((i) =>
bodyshop.md_ro_statuses.open_statuses.includes(i.status)
)
.map((i) => i.id)
: []
);
}, },
selectedRowKeys: selectedJobs, selectedRowKeys: selectedJobs,
getCheckboxProps: record => ({ getCheckboxProps: (record) => ({
disabled: bodyshop.md_ro_statuses.open_statuses disabled: bodyshop.md_ro_statuses.open_statuses
? !bodyshop.md_ro_statuses.open_statuses.includes(record.status) ? !bodyshop.md_ro_statuses.open_statuses.includes(record.status)
: true : true,
}) }),
}} }}
/> />
); );

View File

@@ -1,4 +1,5 @@
import { Input, Table } from "antd"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Input, Table } from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@@ -7,7 +8,7 @@ import { alphaSort } from "../../utils/sorters";
export default function VehiclesListComponent({ loading, vehicles, refetch }) { export default function VehiclesListComponent({ loading, vehicles, refetch }) {
const [state, setState] = useState({ const [state, setState] = useState({
sortedInfo: {}, sortedInfo: {},
filteredInfo: { text: "" } filteredInfo: { text: "" },
}); });
const { t } = useTranslation(); const { t } = useTranslation();
@@ -17,15 +18,13 @@ export default function VehiclesListComponent({ loading, vehicles, refetch }) {
title: t("vehicles.fields.v_vin"), title: t("vehicles.fields.v_vin"),
dataIndex: "v_vin", dataIndex: "v_vin",
key: "v_vin", key: "v_vin",
// onFilter: (value, record) => record.ro_number.includes(value),
// filteredValue: state.filteredInfo.text || null,
sorter: (a, b) => alphaSort(a.v_vin, b.v_vin), sorter: (a, b) => alphaSort(a.v_vin, b.v_vin),
sortOrder: sortOrder:
state.sortedInfo.columnKey === "v_vin" && state.sortedInfo.order, state.sortedInfo.columnKey === "v_vin" && state.sortedInfo.order,
render: (text, record) => ( render: (text, record) => (
<Link to={"/manage/vehicles/" + record.id}>{record.v_vin}</Link> <Link to={"/manage/vehicles/" + record.id}>{record.v_vin}</Link>
) ),
}, },
{ {
title: t("vehicles.fields.description"), title: t("vehicles.fields.description"),
@@ -35,7 +34,7 @@ export default function VehiclesListComponent({ loading, vehicles, refetch }) {
return ( return (
<span>{`${record.v_model_yr} ${record.v_make_desc} ${record.v_model_desc} ${record.v_color}`}</span> <span>{`${record.v_model_yr} ${record.v_make_desc} ${record.v_model_desc} ${record.v_color}`}</span>
); );
} },
}, },
{ {
title: t("vehicles.fields.plate_no"), title: t("vehicles.fields.plate_no"),
@@ -43,32 +42,40 @@ export default function VehiclesListComponent({ loading, vehicles, refetch }) {
key: "plate", key: "plate",
render: (text, record) => { render: (text, record) => {
return <span>{`${record.plate_st} | ${record.plate_no}`}</span>; return <span>{`${record.plate_st} | ${record.plate_no}`}</span>;
} },
} },
]; ];
const handleTableChange = (pagination, filters, sorter) => { const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
}; };
//TODO Implement searching & pagination
return ( return (
<Table <Table
loading={loading} loading={loading}
title={() => { title={() => {
return ( return (
<Input.Search <div className='imex-table-header'>
placeholder="Search..." <Button onClick={() => refetch()}>
onSearch={value => { <SyncOutlined />
console.log(value); </Button>
}} <Input.Search
enterButton className='imex-table-header__search'
/> placeholder={t("general.labels.search")}
onChange={(e) => {
//setSearchText(e.target.value);
}}
//vale={searchText}
enterButton
/>
</div>
); );
}} }}
size="small" size='small'
pagination={{ position: "top" }} pagination={{ position: "top" }}
columns={columns.map(item => ({ ...item }))} columns={columns}
rowKey="id" rowKey='id'
scroll={{ x: true }}
dataSource={vehicles} dataSource={vehicles}
onChange={handleTableChange} onChange={handleTableChange}
/> />

View File

@@ -28,6 +28,7 @@ export const QUERY_ALL_ACTIVE_APPOINTMENTS = gql`
clm_total clm_total
id id
clm_no clm_no
ins_co_nm
v_model_yr v_model_yr
v_make_desc v_make_desc
v_model_desc v_model_desc

View File

@@ -1,6 +1,12 @@
import React from "react"; import React from "react";
import CourtesyCarsListComponent from "../../components/courtesy-cars-list/courtesy-cars-list.component"; import CourtesyCarsListComponent from "../../components/courtesy-cars-list/courtesy-cars-list.component";
export default function CourtesyCarsPageComponent({ loading, data }) { export default function CourtesyCarsPageComponent({ loading, data, refetch }) {
return <CourtesyCarsListComponent loading={loading} courtesycars={data} />; return (
<CourtesyCarsListComponent
loading={loading}
courtesycars={data}
refetch={refetch}
/>
);
} }

View File

@@ -12,7 +12,7 @@ const mapDispatchToProps = (dispatch) => ({
}); });
export function CourtesyCarsPageContainer({ setBreadcrumbs }) { export function CourtesyCarsPageContainer({ setBreadcrumbs }) {
const { loading, error, data } = useQuery(QUERY_ALL_CC); const { loading, error, data, refetch } = useQuery(QUERY_ALL_CC);
const { t } = useTranslation(); const { t } = useTranslation();
useEffect(() => { useEffect(() => {
document.title = t("titles.courtesycars"); document.title = t("titles.courtesycars");
@@ -21,11 +21,12 @@ export function CourtesyCarsPageContainer({ setBreadcrumbs }) {
{ link: "/manage/courtesycars", label: t("titles.bc.courtesycars") }, { link: "/manage/courtesycars", label: t("titles.bc.courtesycars") },
]); ]);
}, [setBreadcrumbs, t]); }, [setBreadcrumbs, t]);
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent message={error.message} type='error' />;
return ( return (
<CourtesyCarsPageComponent <CourtesyCarsPageComponent
loading={loading} loading={loading}
data={(data && data.courtesycars) || []} data={(data && data.courtesycars) || []}
refetch={refetch}
/> />
); );
} }

View File

@@ -19,18 +19,18 @@ export default function JobsCreateComponent({ form }) {
title: t("jobs.labels.create.vehicleinfo"), title: t("jobs.labels.create.vehicleinfo"),
content: <JobsCreateVehicleInfoContainer />, content: <JobsCreateVehicleInfoContainer />,
validation: !!state.vehicle.new || !!state.vehicle.selectedid, validation: !!state.vehicle.new || !!state.vehicle.selectedid,
error: t("vehicles.errors.selectexistingornew") error: t("vehicles.errors.selectexistingornew"),
}, },
{ {
title: t("jobs.labels.create.ownerinfo"), title: t("jobs.labels.create.ownerinfo"),
content: <JobsCreateOwnerInfoContainer />, content: <JobsCreateOwnerInfoContainer />,
validation: !!state.owner.new || !!state.owner.selectedid, validation: !!state.owner.new || !!state.owner.selectedid,
error: t("owners.errors.selectexistingornew") error: t("owners.errors.selectexistingornew"),
}, },
{ {
title: t("jobs.labels.create.jobinfo"), title: t("jobs.labels.create.jobinfo"),
content: <JobsCreateJobsInfo form={form} /> content: <JobsCreateJobsInfo form={form} />,
} },
]; ];
const next = () => { const next = () => {
@@ -43,19 +43,15 @@ export default function JobsCreateComponent({ form }) {
const ProgressButtons = () => { const ProgressButtons = () => {
return ( return (
<div> <div style={{ margin: "1rem" }}>
{pageIndex > 0 && ( {pageIndex > 0 && <Button onClick={() => prev()}>Previous</Button>}
<Button style={{ margin: 8 }} onClick={() => prev()}>
Previous
</Button>
)}
{pageIndex < steps.length - 1 && ( {pageIndex < steps.length - 1 && (
<Button <Button
type='primary' type='primary'
onClick={() => { onClick={() => {
form form
.validateFields() .validateFields()
.then(r => { .then((r) => {
if (steps[pageIndex].validation) { if (steps[pageIndex].validation) {
setErrorMessage(null); setErrorMessage(null);
next(); next();
@@ -63,7 +59,7 @@ export default function JobsCreateComponent({ form }) {
setErrorMessage(steps[pageIndex].error); setErrorMessage(steps[pageIndex].error);
} }
}) })
.catch(error => console.log("error", error)); .catch((error) => console.log("error", error));
}}> }}>
Next Next
</Button> </Button>
@@ -85,7 +81,7 @@ export default function JobsCreateComponent({ form }) {
status='success' status='success'
title={t("jobs.successes.creatednoclick")} title={t("jobs.successes.creatednoclick")}
subTitle={t("jobs.successes.created_subtitle", { subTitle={t("jobs.successes.created_subtitle", {
est_number: state.newJobEstNum est_number: state.newJobEstNum,
})} })}
extra={[ extra={[
<Link to={`/manage/jobs/${state.newJobId}`} key='gotojob'> <Link to={`/manage/jobs/${state.newJobId}`} key='gotojob'>
@@ -93,7 +89,7 @@ export default function JobsCreateComponent({ form }) {
</Link>, </Link>,
<Link to={`/manage/jobs/`} key='gotojoblist'> <Link to={`/manage/jobs/`} key='gotojoblist'>
<Button>{t("menus.header.activejobs")}</Button> <Button>{t("menus.header.activejobs")}</Button>
</Link> </Link>,
]} ]}
/> />
</div> </div>
@@ -108,7 +104,7 @@ export default function JobsCreateComponent({ form }) {
onClick={() => { onClick={() => {
form form
.validateFields() .validateFields()
.then(r => { .then((r) => {
if (steps[pageIndex].validation) { if (steps[pageIndex].validation) {
setErrorMessage(null); setErrorMessage(null);
setPageIndex(idx); setPageIndex(idx);
@@ -116,7 +112,7 @@ export default function JobsCreateComponent({ form }) {
setErrorMessage(steps[pageIndex].error); setErrorMessage(steps[pageIndex].error);
} }
}) })
.catch(error => console.log("error", error)); .catch((error) => console.log("error", error));
}} }}
/> />
))} ))}
@@ -130,7 +126,12 @@ export default function JobsCreateComponent({ form }) {
) : null} ) : null}
{steps.map((item, idx) => ( {steps.map((item, idx) => (
<div key={idx} style={{ display: idx === pageIndex ? "" : "none" }}> <div
key={idx}
style={{
display: idx === pageIndex ? "" : "none",
margin: "1rem",
}}>
{item.content} {item.content}
</div> </div>
))} ))}

View File

@@ -74,6 +74,7 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs }) {
}; };
const handleFinish = (values) => { const handleFinish = (values) => {
console.log("handleFinish -> values", values);
let job = Object.assign( let job = Object.assign(
{}, {},
values, values,
@@ -86,13 +87,14 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs }) {
ownerid: state.owner.selectedid || null, ownerid: state.owner.selectedid || null,
}, },
{ {
status: bodyshop.md_ro_statuses.default_imported || "Open*", //Pull from redux store. status: bodyshop.md_ro_statuses.default_imported || "Open*",
shopid: bodyshop.id, shopid: bodyshop.id,
} }
); );
//TODO Logic to ensure the owner is actually fetched. //TODO Logic to ensure the owner is actually fetched.
console.log("job", job);
let ownerData; let ownerData;
if (!!job.owner) { if (!!!job.ownerid) {
ownerData = job.owner.data; ownerData = job.owner.data;
ownerData.shopid = bodyshop.id; ownerData.shopid = bodyshop.id;
delete ownerData.allow_text_message; delete ownerData.allow_text_message;
@@ -103,7 +105,7 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs }) {
delete ownerData.id; delete ownerData.id;
delete ownerData.__typename; delete ownerData.__typename;
} }
if (!!job.vehicle) { if (!!!job.vehicleid) {
delete job.vehicleid; delete job.vehicleid;
job.vehicle.data.shopid = bodyshop.id; job.vehicle.data.shopid = bodyshop.id;
job.plate_no = job.vehicle.data.plate_no; job.plate_no = job.vehicle.data.plate_no;
@@ -114,8 +116,6 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs }) {
job.v_make_desc = job.vehicle.data.v_make_desc; job.v_make_desc = job.vehicle.data.v_make_desc;
job.v_color = job.vehicle.data.v_color; job.v_color = job.vehicle.data.v_color;
} else { } else {
//Vehicle selected.
job.vehicle.data.shopid = bodyshop.id;
job.plate_no = state.vehicle.vehicleObj.plate_no; job.plate_no = state.vehicle.vehicleObj.plate_no;
job.plate_st = state.vehicle.vehicleObj.plate_st; job.plate_st = state.vehicle.vehicleObj.plate_st;
job.v_vin = state.vehicle.vehicleObj.v_vin; job.v_vin = state.vehicle.vehicleObj.v_vin;
@@ -131,7 +131,11 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs }) {
return ( return (
<JobCreateContext.Provider value={contextState}> <JobCreateContext.Provider value={contextState}>
<Form form={form} onFinish={handleFinish} autoComplete={"off"}> <Form
form={form}
onFinish={handleFinish}
layout='vertical'
autoComplete={"off"}>
<JobsCreateComponent form={form} /> <JobsCreateComponent form={form} />
</Form> </Form>
</JobCreateContext.Provider> </JobCreateContext.Provider>

View File

@@ -15,6 +15,7 @@ const mapDispatchToProps = (dispatch) => ({
export function VehicleDetailContainer({ match, setBreadcrumbs }) { export function VehicleDetailContainer({ match, setBreadcrumbs }) {
const { vehId } = match.params; const { vehId } = match.params;
const { t } = useTranslation(); const { t } = useTranslation();
const { loading, data, error, refetch } = useQuery(QUERY_VEHICLE_BY_ID, { const { loading, data, error, refetch } = useQuery(QUERY_VEHICLE_BY_ID, {
variables: { id: vehId }, variables: { id: vehId },
fetchPolicy: "network-only", fetchPolicy: "network-only",

View File

@@ -686,7 +686,6 @@
"availablenew": "Available New Jobs", "availablenew": "Available New Jobs",
"availablesupplements": "Available Supplements", "availablesupplements": "Available Supplements",
"cards": { "cards": {
"appraiser": "Appraiser",
"customer": "Customer Information", "customer": "Customer Information",
"damage": "Area of Damage", "damage": "Area of Damage",
"dates": "Dates", "dates": "Dates",
@@ -855,6 +854,7 @@
"ownr_addr1": "Address", "ownr_addr1": "Address",
"ownr_addr2": "Address 2", "ownr_addr2": "Address 2",
"ownr_city": "City", "ownr_city": "City",
"ownr_co_nm": "Owner Co. Name",
"ownr_ctry": "Country", "ownr_ctry": "Country",
"ownr_ea": "Email", "ownr_ea": "Email",
"ownr_fn": "First Name", "ownr_fn": "First Name",
@@ -865,6 +865,11 @@
"ownr_zip": "Zip/Postal Code", "ownr_zip": "Zip/Postal Code",
"preferred_contact": "Preferred Contact Method" "preferred_contact": "Preferred Contact Method"
}, },
"forms": {
"address": "Address",
"contact": "Contact Information",
"name": "Owner Details"
},
"labels": { "labels": {
"create_new": "Create a new owner record.", "create_new": "Create a new owner record.",
"existing_owners": "Existing Owners", "existing_owners": "Existing Owners",
@@ -1093,6 +1098,11 @@
"v_type": "Type", "v_type": "Type",
"v_vin": "Vehicle Identification Number" "v_vin": "Vehicle Identification Number"
}, },
"forms": {
"detail": "Vehicle Details",
"misc": "Miscellaneous",
"registration": "Registration"
},
"labels": { "labels": {
"updatevehicle": "Update Vehicle Information" "updatevehicle": "Update Vehicle Information"
}, },

View File

@@ -686,7 +686,6 @@
"availablenew": "", "availablenew": "",
"availablesupplements": "", "availablesupplements": "",
"cards": { "cards": {
"appraiser": "Tasador",
"customer": "Información al cliente", "customer": "Información al cliente",
"damage": "Área de Daño", "damage": "Área de Daño",
"dates": "fechas", "dates": "fechas",
@@ -855,6 +854,7 @@
"ownr_addr1": "Dirección", "ownr_addr1": "Dirección",
"ownr_addr2": "Dirección 2", "ownr_addr2": "Dirección 2",
"ownr_city": "ciudad", "ownr_city": "ciudad",
"ownr_co_nm": "",
"ownr_ctry": "País", "ownr_ctry": "País",
"ownr_ea": "Email", "ownr_ea": "Email",
"ownr_fn": "Nombre de pila", "ownr_fn": "Nombre de pila",
@@ -865,6 +865,11 @@
"ownr_zip": "código postal", "ownr_zip": "código postal",
"preferred_contact": "Método de Contacto Preferido" "preferred_contact": "Método de Contacto Preferido"
}, },
"forms": {
"address": "",
"contact": "",
"name": ""
},
"labels": { "labels": {
"create_new": "Crea un nuevo registro de propietario.", "create_new": "Crea un nuevo registro de propietario.",
"existing_owners": "Propietarios existentes", "existing_owners": "Propietarios existentes",
@@ -1093,6 +1098,11 @@
"v_type": "Tipo", "v_type": "Tipo",
"v_vin": "Número de identificación del vehículo" "v_vin": "Número de identificación del vehículo"
}, },
"forms": {
"detail": "",
"misc": "",
"registration": ""
},
"labels": { "labels": {
"updatevehicle": "" "updatevehicle": ""
}, },

View File

@@ -686,7 +686,6 @@
"availablenew": "", "availablenew": "",
"availablesupplements": "", "availablesupplements": "",
"cards": { "cards": {
"appraiser": "Expert",
"customer": "Informations client", "customer": "Informations client",
"damage": "Zone de dommages", "damage": "Zone de dommages",
"dates": "Rendez-vous", "dates": "Rendez-vous",
@@ -855,6 +854,7 @@
"ownr_addr1": "Adresse", "ownr_addr1": "Adresse",
"ownr_addr2": "Adresse 2 ", "ownr_addr2": "Adresse 2 ",
"ownr_city": "Ville", "ownr_city": "Ville",
"ownr_co_nm": "",
"ownr_ctry": "Pays", "ownr_ctry": "Pays",
"ownr_ea": "Email", "ownr_ea": "Email",
"ownr_fn": "Prénom", "ownr_fn": "Prénom",
@@ -865,6 +865,11 @@
"ownr_zip": "Zip / code postal", "ownr_zip": "Zip / code postal",
"preferred_contact": "Méthode de contact préférée" "preferred_contact": "Méthode de contact préférée"
}, },
"forms": {
"address": "",
"contact": "",
"name": ""
},
"labels": { "labels": {
"create_new": "Créez un nouvel enregistrement de propriétaire.", "create_new": "Créez un nouvel enregistrement de propriétaire.",
"existing_owners": "Propriétaires existants", "existing_owners": "Propriétaires existants",
@@ -1093,6 +1098,11 @@
"v_type": "Type", "v_type": "Type",
"v_vin": "Plaque d'immatriculation" "v_vin": "Plaque d'immatriculation"
}, },
"forms": {
"detail": "",
"misc": "",
"registration": ""
},
"labels": { "labels": {
"updatevehicle": "" "updatevehicle": ""
}, },