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={() => (
<div className='imex-table-header'>
<Button onClick={() => refetch()}>
<SyncOutlined />
</Button>
<Link to={`/manage/courtesycars/new`}> <Link to={`/manage/courtesycars/new`}>
<Button>{t("courtesycars.actions.new")}</Button> <Button>{t("courtesycars.actions.new")}</Button>
</Link> </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
label={t("jobs.fields.regie_number")}
name='regie_number'>
<Input /> <Input />
</Form.Item> </Form.Item>
TODO: missing KOL field??? <Form.Item label={t("jobs.fields.loss_date")} name='loss_date'>
<Form.Item label={t("jobs.fields.loss_date")} name="loss_date">
<DatePicker /> <DatePicker />
</Form.Item> </Form.Item>
CAA # seems not correct based on field mapping Class seems not correct <Form.Item label={t("jobs.fields.ins_co_nm")} name='ins_co_nm'>
based on field mapping
<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")} /> <FormItemEmail email={getFieldValue("ins_ea")} />
</Form.Item> </Form.Item>
Appraiser Info Appraiser Info
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm"> <Form.Item label={t("jobs.fields.est_co_nm")} name='est_co_nm'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.est_ct_fn")} name="est_ct_fn"> <Form.Item label={t("jobs.fields.est_ct_fn")} name='est_ct_fn'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.est_ct_ln")} name="est_ct_ln"> <Form.Item label={t("jobs.fields.est_ct_ln")} name='est_ct_ln'>
<Input /> <Input />
</Form.Item> </Form.Item>
TODO: Field is pay date but title is inspection date. Likely <Form.Item label={t("jobs.fields.pay_date")} name='pay_date'>
incorrect?
<Form.Item label={t("jobs.fields.pay_date")} name="pay_date">
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.est_ph1")} name="est_ph1"> <Form.Item label={t("jobs.fields.est_ph1")} name='est_ph1'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.est_ea")} label={t("jobs.fields.est_ea")}
name="est_ea" name='est_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("est_ea")} /> <FormItemEmail email={getFieldValue("est_ea")} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.selling_dealer")} label={t("jobs.fields.selling_dealer")}
name="selling_dealer" name='selling_dealer'>
>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.servicing_dealer")} label={t("jobs.fields.servicing_dealer")}
name="servicing_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.selling_dealer_contact")}
name="selling_dealer_contact" name='selling_dealer_contact'>
>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.servicing_dealer_contact")} label={t("jobs.fields.servicing_dealer_contact")}
name="servicing_dealer_contact" name='servicing_dealer_contact'>
>
<Input /> <Input />
</Form.Item> </Form.Item>
</LayoutFormRow>
</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>
<Form.Item label={t("jobs.fields.csr")} name='csr'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.loss_desc")} name="loss_desc"> <Form.Item label={t("jobs.fields.loss_desc")} name='loss_desc'>
<Input /> <Input />
</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>
</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 /> <InputNumber />
</Form.Item> </Form.Item>
TODO equivalent of other customer amount
<Form.Item <Form.Item
label={t("jobs.fields.other_amount_payable")} label={t("jobs.fields.other_amount_payable")}
name="other_amount_payable" name='other_amount_payable'>
>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.towing_payable")} label={t("jobs.fields.towing_payable")}
name="towing_payable" name='towing_payable'>
>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.storage_payable")} label={t("jobs.fields.storage_payable")}
name="storage_payable" name='storage_payable'>
>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.adjustment_bottom_line")} label={t("jobs.fields.adjustment_bottom_line")}
name="adjustment_bottom_line" name='adjustment_bottom_line'>
>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
Totals Table Totals Table
<Form.Item <Form.Item
label={t("jobs.fields.labor_rate_desc")} label={t("jobs.fields.labor_rate_desc")}
name="labor_rate_desc" name='labor_rate_desc'>
>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab"> <Form.Item label={t("jobs.fields.rate_lab")} name='rate_lab'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lad")} name="rate_lad"> <Form.Item label={t("jobs.fields.rate_lad")} name='rate_lad'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lae")} name="rate_lae"> <Form.Item label={t("jobs.fields.rate_lae")} name='rate_lae'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lar")} name="rate_lar"> <Form.Item label={t("jobs.fields.rate_lar")} name='rate_lar'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_las")} name="rate_las"> <Form.Item label={t("jobs.fields.rate_las")} name='rate_las'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_laf")} name="rate_laf"> <Form.Item label={t("jobs.fields.rate_laf")} name='rate_laf'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lam")} name="rate_lam"> <Form.Item label={t("jobs.fields.rate_lam")} name='rate_lam'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lag")} name="rate_lag"> <Form.Item label={t("jobs.fields.rate_lag")} name='rate_lag'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
Note //TODO Remove ATP rate? Note //TODO Remove ATP rate?
<Form.Item label={t("jobs.fields.rate_atp")} name="rate_atp"> <Form.Item label={t("jobs.fields.rate_atp")} name='rate_atp'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lau")} name="rate_lau"> <Form.Item label={t("jobs.fields.rate_lau")} name='rate_lau'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_la1")} name="rate_la1"> <Form.Item label={t("jobs.fields.rate_la1")} name='rate_la1'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_la2")} name="rate_la2"> <Form.Item label={t("jobs.fields.rate_la2")} name='rate_la2'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_la3")} name="rate_la3"> <Form.Item label={t("jobs.fields.rate_la3")} name='rate_la3'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_la4")} name="rate_la4"> <Form.Item label={t("jobs.fields.rate_la4")} name='rate_la4'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_mapa")} name="rate_mapa"> <Form.Item label={t("jobs.fields.rate_mapa")} name='rate_mapa'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_mash")} name="rate_mash"> <Form.Item label={t("jobs.fields.rate_mash")} name='rate_mash'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_mahw")} name="rate_mahw"> <Form.Item label={t("jobs.fields.rate_mahw")} name='rate_mahw'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_ma2s")} name="rate_ma2s"> <Form.Item label={t("jobs.fields.rate_ma2s")} name='rate_ma2s'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_ma3s")} name="rate_ma3s"> <Form.Item label={t("jobs.fields.rate_ma3s")} name='rate_ma3s'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl"> <Form.Item label={t("jobs.fields.rate_mabl")} name='rate_mabl'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs"> <Form.Item label={t("jobs.fields.rate_macs")} name='rate_macs'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_matd")} name="rate_matd"> <Form.Item label={t("jobs.fields.rate_matd")} name='rate_matd'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_laa")} name="rate_laa"> <Form.Item label={t("jobs.fields.rate_laa")} name='rate_laa'>
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
</LayoutFormRow>
</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,68 +21,87 @@ 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>
<LayoutFormRow header={t("owners.forms.name")} grow>
<Form.Item <Form.Item
label={t("owners.fields.ownr_ln")} label={t("owners.fields.ownr_ln")}
name={["owner", "data", "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} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item
label={t("owners.fields.ownr_title")}
name={["owner", "data", "ownr_title"]}>
<Input disabled={!state.owner.new} /> <Input disabled={!state.owner.new} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("owners.fields.allow_text_message")} label={t("owners.fields.ownr_co_nm")}
valuePropName="checked" name={["owner", "data", "ownr_co_nm"]}>
name={["owner", "data", "allow_text_message"]} <Input disabled={!state.owner.new} />
>
<Switch disabled={!state.owner.new} />
</Form.Item> </Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("owners.forms.address")} grow>
<Form.Item <Form.Item
label={t("owners.fields.ownr_addr1")} label={t("owners.fields.ownr_addr1")}
name={["owner", "data", "ownr_addr1"]} name={["owner", "data", "ownr_addr1"]}>
>
<Input disabled={!state.owner.new} /> <Input disabled={!state.owner.new} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("owners.fields.ownr_addr2")} label={t("owners.fields.ownr_addr2")}
name={["owner", "data", "ownr_addr2"]} name={["owner", "data", "ownr_addr2"]}>
> <Input disabled={!state.owner.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item
label={t("owners.fields.ownr_city")}
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_city")} label={t("owners.fields.ownr_st")}
name={["owner", "data", "ownr_city"]} name={["owner", "data", "ownr_st"]}>
> <Input disabled={!state.owner.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item
label={t("owners.fields.ownr_zip")}
name={["owner", "data", "ownr_zip"]}>
<Input disabled={!state.owner.new} /> <Input disabled={!state.owner.new} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("owners.fields.ownr_ctry")} label={t("owners.fields.ownr_ctry")}
name={["owner", "data", "ownr_ctry"]} name={["owner", "data", "ownr_ctry"]}>
>
<Input disabled={!state.owner.new} /> <Input disabled={!state.owner.new} />
</Form.Item> </Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("owners.forms.contact")} grow>
<Form.Item <Form.Item
label={t("owners.fields.ownr_ea")} label={t("owners.fields.ownr_ea")}
rules={[ rules={[
{ {
type: "email", type: "email",
message: "This is not a valid email address." message: "This is not a valid email address.",
} },
]} ]}
name={["owner", "data", "ownr_ea"]} name={["owner", "data", "ownr_ea"]}>
>
<FormItemEmail <FormItemEmail
//TODO Fix this email={getFieldValue("ownr_ea")} //TODO Fix this email={getFieldValue("ownr_ea")}
disabled={!state.owner.new} disabled={!state.owner.new}
@@ -89,34 +109,23 @@ export default function JobsCreateOwnerInfoNewComponent() {
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("owners.fields.ownr_ph1")} label={t("owners.fields.ownr_ph1")}
name={["owner", "data", "ownr_ph1"]} name={["owner", "data", "ownr_ph1"]}>
>
<FormItemPhone customInput={Input} disabled={!state.owner.new} /> <FormItemPhone customInput={Input} disabled={!state.owner.new} />
</Form.Item> </Form.Item>
<Form.Item </LayoutFormRow>
label={t("owners.fields.ownr_st")} <LayoutFormRow grow>
name={["owner", "data", "ownr_st"]}
>
<Input disabled={!state.owner.new} />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_zip")}
name={["owner", "data", "ownr_zip"]}
>
<Input disabled={!state.owner.new} />
</Form.Item>
<Form.Item <Form.Item
label={t("owners.fields.preferred_contact")} label={t("owners.fields.preferred_contact")}
name={["owner", "data", "preferred_contact"]} name={["owner", "data", "preferred_contact"]}>
>
<Input disabled={!state.owner.new} /> <Input disabled={!state.owner.new} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("owners.fields.ownr_title")} label={t("owners.fields.allow_text_message")}
name={["owner", "data", "ownr_title"]} valuePropName='checked'
> name={["owner", "data", "allow_text_message"]}>
<Input disabled={!state.owner.new} /> <Switch disabled={!state.owner.new} />
</Form.Item> </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 (
<div className='imex-table-header'>
<Input.Search <Input.Search
placeholder="Search..." className='imex-table-header__search'
onSearch={value => { placeholder={t("general.labels.search")}
onSearch={(value) => {
setState({ setState({
...state, ...state,
owner: { ...state.owner, search: value } 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,8 +128,8 @@ export default function JobsCreateOwnerInfoSearchComponent({
owner: { owner: {
...state.owner, ...state.owner,
new: false, new: false,
selectedid: record.id selectedid: record.id,
} },
}); });
return; return;
@@ -134,9 +137,9 @@ export default function JobsCreateOwnerInfoSearchComponent({
} }
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,98 +19,36 @@ 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>
<LayoutFormRow header={t("vehicles.forms.detail")} grow>
<Form.Item <Form.Item
label={t("vehicles.fields.v_vin")} label={t("vehicles.fields.v_vin")}
name={["vehicle", "data", "v_vin"]} name={["vehicle", "data", "v_vin"]}
rules={[ rules={[
{ {
required: state.vehicle.new, required: state.vehicle.new,
message: t("general.validation.required") message: t("general.validation.required"),
} },
]} ]}>
>
<Input disabled={!state.vehicle.new} /> <Input disabled={!state.vehicle.new} />
</Form.Item> </Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item <Form.Item
label={t("vehicles.fields.plate_no")} label={t("vehicles.fields.v_color")}
name={["vehicle", "data", "plate_no"]} name={["vehicle", "data", "v_color"]}
rules={[ rules={[
{ {
required: state.vehicle.new, required: state.vehicle.new,
message: t("general.validation.required") message: t("general.validation.required"),
} },
]} ]}>
>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.plate_st")}
name={["vehicle", "data", "plate_st"]}
rules={[
{
required: state.vehicle.new,
message: t("general.validation.required")
}
]}
>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_type")}
name={["vehicle", "data", "v_type"]}
>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_trimcode")}
name={["vehicle", "data", "v_trimcode"]}
>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_tone")}
name={["vehicle", "data", "v_tone"]}
>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_bstyle")}
name={["vehicle", "data", "v_bstyle"]}
>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_stage")}
name={["vehicle", "data", "v_stage"]}
>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_prod_dt")}
name={["vehicle", "data", "v_prod_dt"]}
>
<DatePicker disabled={!state.vehicle.new} />
</Form.Item>
{
//TODO Add handling for paint code json
}
<Form.Item
label={t("vehicles.fields.v_paint_codes")}
name={["vehicle", "data", "v_paint_codes"]}
>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_options")}
name={["vehicle", "data", "v_options"]}
>
<Input disabled={!state.vehicle.new} /> <Input disabled={!state.vehicle.new} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
@@ -118,10 +57,23 @@ export default function JobsCreateVehicleInfoNewComponent() {
rules={[ rules={[
{ {
required: state.vehicle.new, required: state.vehicle.new,
message: t("general.validation.required") message: t("general.validation.required"),
} },
]} ]}>
> <Input disabled={!state.vehicle.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item
label={t("vehicles.fields.v_make_desc")}
name={["vehicle", "data", "v_make_desc"]}
rules={[
{
required: state.vehicle.new,
message: t("general.validation.required"),
},
]}>
<Input disabled={!state.vehicle.new} /> <Input disabled={!state.vehicle.new} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
@@ -130,66 +82,118 @@ export default function JobsCreateVehicleInfoNewComponent() {
rules={[ rules={[
{ {
required: state.vehicle.new, required: state.vehicle.new,
message: t("general.validation.required") message: t("general.validation.required"),
} },
]} ]}>
> <Input disabled={!state.vehicle.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("vehicles.forms.registration")} grow>
<Form.Item
label={t("vehicles.fields.plate_st")}
name={["vehicle", "data", "plate_st"]}
rules={[
{
required: state.vehicle.new,
message: t("general.validation.required"),
},
]}>
<Input disabled={!state.vehicle.new} /> <Input disabled={!state.vehicle.new} />
</Form.Item> </Form.Item>
<Form.Item
label={t("vehicles.fields.plate_no")}
name={["vehicle", "data", "plate_no"]}
rules={[
{
required: state.vehicle.new,
message: t("general.validation.required"),
},
]}>
<Input disabled={!state.vehicle.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("vehicles.forms.misc")} grow>
<Form.Item
label={t("vehicles.fields.v_type")}
name={["vehicle", "data", "v_type"]}>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_trimcode")}
name={["vehicle", "data", "v_trimcode"]}>
<Input disabled={!state.vehicle.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item
label={t("vehicles.fields.v_tone")}
name={["vehicle", "data", "v_tone"]}>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_bstyle")}
name={["vehicle", "data", "v_bstyle"]}>
<Input disabled={!state.vehicle.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item
label={t("vehicles.fields.v_stage")}
name={["vehicle", "data", "v_stage"]}>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_prod_dt")}
name={["vehicle", "data", "v_prod_dt"]}>
<DatePicker disabled={!state.vehicle.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item
label={t("vehicles.fields.v_paint_codes")}
name={["vehicle", "data", "v_paint_codes"]}>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_options")}
name={["vehicle", "data", "v_options"]}>
<Input disabled={!state.vehicle.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item <Form.Item
label={t("vehicles.fields.trim_color")} label={t("vehicles.fields.trim_color")}
name={["vehicle", "data", "trim_color"]} name={["vehicle", "data", "trim_color"]}>
>
<Input disabled={!state.vehicle.new} /> <Input disabled={!state.vehicle.new} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("vehicles.fields.v_mldgcode")} label={t("vehicles.fields.v_mldgcode")}
name={["vehicle", "data", "v_mldgcode"]} name={["vehicle", "data", "v_mldgcode"]}>
>
<Input disabled={!state.vehicle.new} /> <Input disabled={!state.vehicle.new} />
</Form.Item> </Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item <Form.Item
label={t("vehicles.fields.v_makecode")} label={t("vehicles.fields.v_makecode")}
name={["vehicle", "data", "v_makecode"]} name={["vehicle", "data", "v_makecode"]}>
>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_make_desc")}
name={["vehicle", "data", "v_make_desc"]}
rules={[
{
required: state.vehicle.new,
message: t("general.validation.required")
}
]}
>
<Input disabled={!state.vehicle.new} /> <Input disabled={!state.vehicle.new} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("vehicles.fields.v_engine")} label={t("vehicles.fields.v_engine")}
name={["vehicle", "data", "v_engine"]} name={["vehicle", "data", "v_engine"]}>
>
<Input disabled={!state.vehicle.new} /> <Input disabled={!state.vehicle.new} />
</Form.Item> </Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item <Form.Item
label={t("vehicles.fields.v_cond")} label={t("vehicles.fields.v_cond")}
name={["vehicle", "data", "v_cond"]} name={["vehicle", "data", "v_cond"]}>
>
<Input disabled={!state.vehicle.new} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_color")}
name={["vehicle", "data", "v_color"]}
rules={[
{
required: state.vehicle.new,
message: t("general.validation.required")
}
]}
>
<Input disabled={!state.vehicle.new} /> <Input disabled={!state.vehicle.new} />
</Form.Item> </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 (
<div className='imex-table-header'>
<Input.Search <Input.Search
placeholder="Search..." className='imex-table-header__search'
onSearch={value => { placeholder={t("general.labels.search")}
onSearch={(value) => {
setState({ setState({
...state, ...state,
vehicle: { ...state.vehicle, search: value } 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'>
<Button
className='imex-flex-row__margin-large'
type='primary'
key='submit'
htmlType='submit'>
{t("general.actions.save")} {t("general.actions.save")}
</Button> </Button>
<Row> <div className='imex-flex-row__grow imex-flex-row__margin-large'>
<Col span={8}> <FormFieldsChanged form={form} />
</div>
</div>
<LayoutFormRow header={t("owners.forms.name")}>
<Form.Item label={t("owners.fields.ownr_title")} name='ownr_title'>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_ln")} name='ownr_ln'> <Form.Item label={t("owners.fields.ownr_ln")} name='ownr_ln'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("owners.fields.ownr_fn")} name='ownr_fn'> <Form.Item label={t("owners.fields.ownr_fn")} name='ownr_fn'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("owners.fields.ownr_co_nm")} name='ownr_co_nm'>
<Input />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("owners.forms.address")}>
<Form.Item
label={t("owners.fields.ownr_addr1")}
name='ownr_addr1'
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_addr2")} name='ownr_addr2'>
<Input />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_city")}
name='ownr_city'
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<Input />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_st")}
name='ownr_st'
rules={[
{
required: true,
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 <Form.Item
label={t("owners.fields.allow_text_message")} label={t("owners.fields.allow_text_message")}
name='allow_text_message' name='allow_text_message'
valuePropName='checked'> valuePropName='checked'>
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item label={t("owners.fields.ownr_addr1")} name='ownr_addr1'>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_addr2")} name='ownr_addr2'>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_city")} name='ownr_city'>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_ctry")} name='ownr_ctry'>
<Input />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item <Form.Item
label={t("owners.fields.ownr_ea")} label={t("owners.fields.ownr_ea")}
name='ownr_ea' name='ownr_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("ownr_ea")} /> <FormItemEmail email={getFieldValue("ownr_ea")} />
</Form.Item> </Form.Item>
<Form.Item label={t("owners.fields.ownr_ph1")} name='ownr_ph1'> <Form.Item label={t("owners.fields.ownr_ph1")} name='ownr_ph1'>
<FormItemPhone customInput={Input} /> <FormItemPhone customInput={Input} />
</Form.Item> </Form.Item>
<Form.Item label={t("owners.fields.ownr_st")} name='ownr_st'>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_zip")} name='ownr_zip'>
<Input />
</Form.Item>
<Form.Item <Form.Item
label={t("owners.fields.preferred_contact")} label={t("owners.fields.preferred_contact")}
name='preferred_contact'> name='preferred_contact'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("owners.fields.ownr_title")} name='ownr_title'> </LayoutFormRow>
<Input />
</Form.Item>
</Col>
</Row>
</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 (
<div className='imex-table-header'>
<Button onClick={() => refetch()}>
<SyncOutlined />
</Button>
<Input.Search <Input.Search
placeholder="Search..." className='imex-table-header__search'
onSearch={value => { placeholder={t("general.labels.search")}
console.log(value); onChange={(e) => {
//setSearchText(e.target.value);
}} }}
//vale={searchText}
enterButton 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,34 +24,35 @@ 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>
@@ -60,9 +62,6 @@ export default function ScheduleEventComponent({ event, handleCancel }) {
{t("appointments.actions.cancel")} {t("appointments.actions.cancel")}
</Button> </Button>
<Button disabled={event.arrived}> <Button disabled={event.arrived}>
{
//TODO Add reschedule Func.
}
{t("appointments.actions.reschedule")} {t("appointments.actions.reschedule")}
</Button> </Button>
{event.isintake ? ( {event.isintake ? (
@@ -77,6 +76,7 @@ export default function ScheduleEventComponent({ event, handleCancel }) {
</Link> </Link>
) : null} ) : null}
</div> </div>
</div>
); );
const RegularEvent = event.isintake ? ( const RegularEvent = event.isintake ? (
@@ -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,43 +1,128 @@
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'>
<Button
className='imex-flex-row__margin-large'
type='primary'
key='submit'
htmlType='submit'>
{t("general.actions.save")} {t("general.actions.save")}
</Button> </Button>
<Row> <div className='imex-flex-row__grow imex-flex-row__margin-large'>
<Col span={8}> <FormFieldsChanged form={form} />
<Form.Item label={t("vehicles.fields.v_vin")} name="v_vin"> </div>
</div>
<LayoutFormRow header={t("vehicles.forms.detail")}>
<Form.Item
label={t("vehicles.fields.v_model_yr")}
name='v_model_yr'
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<InputNumber precision={0} />
</Form.Item>
<Form.Item
label={t("vehicles.fields.v_make_desc")}
name='v_make_desc'
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("vehicles.fields.plate_no")} name="plate_no"> <Form.Item
label={t("vehicles.fields.v_model_desc")}
name='v_model_desc'
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("vehicles.fields.plate_st")} name="plate_st"> <Form.Item
label={t("vehicles.fields.v_color")}
name='v_color'
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("vehicles.fields.v_type")} name="v_type"> <Form.Item
label={t("vehicles.fields.v_vin")}
name='v_vin'
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("vehicles.fields.v_trimcode")} name="v_trimcode"> </LayoutFormRow>
<LayoutFormRow header={t("vehicles.forms.registration")}>
<Form.Item
label={t("vehicles.fields.plate_st")}
name='plate_st'
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("vehicles.fields.v_tone")} name="v_tone"> <Form.Item
label={t("vehicles.fields.plate_no")}
name='plate_no'
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("vehicles.fields.v_bstyle")} name="v_bstyle"> </LayoutFormRow>
<LayoutFormRow header={t("vehicles.forms.misc")}>
<Form.Item label={t("vehicles.fields.v_type")} name='v_type'>
<Input /> <Input />
</Form.Item> </Form.Item>
</Col> <Form.Item label={t("vehicles.fields.v_trimcode")} name='v_trimcode'>
<Col span={8}>
<Form.Item label={t("vehicles.fields.v_stage")} name="v_stage">
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("vehicles.fields.v_prod_dt")} name="v_prod_dt"> <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 /> <DatePicker />
</Form.Item> </Form.Item>
{ {
@@ -45,50 +130,31 @@ export default function VehicleDetailFormComponent() {
} }
<Form.Item <Form.Item
label={t("vehicles.fields.v_paint_codes")} label={t("vehicles.fields.v_paint_codes")}
name="v_paint_codes" name='v_paint_codes'>
>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("vehicles.fields.v_options")} name="v_options"> <Form.Item label={t("vehicles.fields.v_options")} name='v_options'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("vehicles.fields.v_model_yr")} name="v_model_yr">
<Form.Item label={t("vehicles.fields.trim_color")} name='trim_color'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item
label={t("vehicles.fields.v_model_desc")} <Form.Item label={t("vehicles.fields.v_mldgcode")} name='v_mldgcode'>
name="v_model_desc"
>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("vehicles.fields.trim_color")} name="trim_color"> <Form.Item label={t("vehicles.fields.v_makecode")} name='v_makecode'>
<Input /> <Input />
</Form.Item> </Form.Item>
</Col>
<Col span={8}> <Form.Item label={t("vehicles.fields.v_engine")} name='v_engine'>
<Form.Item label={t("vehicles.fields.v_mldgcode")} name="v_mldgcode">
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("vehicles.fields.v_makecode")} name="v_makecode"> <Form.Item label={t("vehicles.fields.v_cond")} name='v_cond'>
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item </LayoutFormRow>
label={t("vehicles.fields.v_make_desc")}
name="v_make_desc"
>
<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>
<Form.Item label={t("vehicles.fields.v_color")} name="v_color">
<Input />
</Form.Item>
</Col>
</Row>
</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 (
<div className='imex-table-header'>
<Button onClick={() => refetch()}>
<SyncOutlined />
</Button>
<Input.Search <Input.Search
placeholder="Search..." className='imex-table-header__search'
onSearch={value => { placeholder={t("general.labels.search")}
console.log(value); onChange={(e) => {
//setSearchText(e.target.value);
}} }}
//vale={searchText}
enterButton 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": ""
}, },