Further UI Updates.

This commit is contained in:
Patrick Fic
2021-03-30 17:13:33 -07:00
parent a0654bdb2c
commit a61be6a44f
48 changed files with 755 additions and 616 deletions

View File

@@ -8238,6 +8238,48 @@
<folder_node> <folder_node>
<name>labels</name> <name>labels</name>
<children> <children>
<concept_node>
<name>agreement</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>availablecars</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>
<folder_node> <folder_node>
<name>convertform</name> <name>convertform</name>
<children> <children>
@@ -8306,6 +8348,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>driverinformation</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>noteconvertedfrom</name> <name>noteconvertedfrom</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -8348,6 +8411,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>rates</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>vehicle</name> <name>vehicle</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>

View File

@@ -75,7 +75,7 @@ export default function AuditTrailListComponent({ loading, data }) {
{...formItemLayout} {...formItemLayout}
loading={loading} loading={loading}
pagination={{ position: "top", defaultPageSize: 25 }} pagination={{ position: "top", defaultPageSize: 25 }}
columns={columns.map((item) => ({ ...item }))} columns={columns}
rowKey="id" rowKey="id"
dataSource={data} dataSource={data}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -1,5 +1,5 @@
import { useMutation, useQuery } from "@apollo/client"; import { useMutation, useQuery } from "@apollo/client";
import { Button, Form, Popconfirm } from "antd"; import { Button, Form, PageHeader, Popconfirm } from "antd";
import moment from "moment"; import moment from "moment";
import queryString from "query-string"; import queryString from "query-string";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
@@ -112,27 +112,36 @@ export default function BillDetailEditcontainer() {
return ( return (
<LoadingSkeleton loading={loading}> <LoadingSkeleton loading={loading}>
<Popconfirm <PageHeader
visible={visible} title={
onConfirm={() => form.submit()} data &&
onCancel={() => setVisible(false)} `${data.bills_by_pk.invoice_number} - ${data.bills_by_pk.vendor.name}`
okButtonProps={{ loading: updateLoading }} }
title={t("bills.labels.editadjwarning")} extra={
> <Popconfirm
<Button visible={visible}
htmlType="submit" onConfirm={() => form.submit()}
disabled={exported} onCancel={() => setVisible(false)}
onClick={handleSave} okButtonProps={{ loading: updateLoading }}
loading={updateLoading} title={t("bills.labels.editadjwarning")}
type="primary" >
> <Button
{t("general.actions.save")} htmlType="submit"
</Button> disabled={exported}
</Popconfirm> onClick={handleSave}
loading={updateLoading}
type="primary"
>
{t("general.actions.save")}
</Button>
</Popconfirm>
}
/>
<Form <Form
form={form} form={form}
onFinish={handleFinish} onFinish={handleFinish}
initialValues={transformData(data)} initialValues={transformData(data)}
layout="vertical"
> >
<BillFormContainer form={form} billEdit disabled={exported} /> <BillFormContainer form={form} billEdit disabled={exported} />
<JobDocumentsGallery <JobDocumentsGallery

View File

@@ -1,4 +1,4 @@
import { Input, Table } from "antd"; import { Card, 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 { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
@@ -97,32 +97,36 @@ export default function ContractsCarsComponent({
); );
return ( return (
<Table <Card
loading={loading} title={t("contracts.labels.availablecars")}
title={() => ( extra={
<Input.Search <Input.Search
placeholder={t("general.labels.search")} placeholder={t("general.labels.search")}
value={state.search} value={state.search}
onChange={(e) => setState({ ...state, search: e.target.value })} onChange={(e) => setState({ ...state, search: e.target.value })}
/> />
)} }
pagination={{ position: "top" }} >
columns={columns.map((item) => ({ ...item }))} <Table
rowKey="id" loading={loading}
dataSource={filteredData} pagination={{ position: "top" }}
onChange={handleTableChange} columns={columns}
rowSelection={{ rowKey="id"
onSelect: handleSelect, dataSource={filteredData}
type: "radio", onChange={handleTableChange}
selectedRowKeys: [selectedCar], rowSelection={{
}} onSelect: handleSelect,
onRow={(record, rowIndex) => { type: "radio",
return { selectedRowKeys: [selectedCar],
onClick: (event) => { }}
handleSelect(record); onRow={(record, rowIndex) => {
}, return {
}; onClick: (event) => {
}} handleSelect(record);
/> },
};
}}
/>
</Card>
); );
} }

View File

@@ -15,10 +15,6 @@ export default function ContractCarsContainer({ selectedCarState, form }) {
const handleSelect = (record) => { const handleSelect = (record) => {
setSelectedCar(record.id); setSelectedCar(record.id);
console.log(
"🚀 ~ file: contract-cars.container.jsx ~ line 19 ~ record",
record
);
form.setFieldsValue({ form.setFieldsValue({
kmstart: record.mileage, kmstart: record.mileage,
dailyrate: record.dailycost, dailyrate: record.dailycost,
@@ -28,13 +24,11 @@ export default function ContractCarsContainer({ selectedCarState, form }) {
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent message={error.message} type="error" />;
return ( return (
<div> <ContractCarsComponent
<ContractCarsComponent handleSelect={handleSelect}
handleSelect={handleSelect} selectedCar={selectedCar}
selectedCar={selectedCar} loading={loading}
loading={loading} data={data ? data.courtesycars : []}
data={data ? data.courtesycars : []} />
/>
</div>
); );
} }

View File

@@ -1,25 +1,31 @@
import { Card } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Descriptions, Card } from "antd";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import DataLabel from "../data-label/data-label.component";
export default function ContractCourtesyCarBlock({ courtesyCar }) { export default function ContractCourtesyCarBlock({ courtesyCar }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Link to={`/manage/courtesycars/${courtesyCar && courtesyCar.id}`}> <Link to={`/manage/courtesycars/${courtesyCar && courtesyCar.id}`}>
<Card title={t("courtesycars.labels.courtesycar")}> <Card
<Descriptions column={1}> className="ant-card-grid-hoverable"
<Descriptions.Item label={t("courtesycars.fields.fleetnumber")}> style={{ height: "100%" }}
title={t("courtesycars.labels.courtesycar")}
>
<div>
<DataLabel label={t("courtesycars.fields.fleetnumber")}>
{(courtesyCar && courtesyCar.fleetnumber) || ""} {(courtesyCar && courtesyCar.fleetnumber) || ""}
</Descriptions.Item> </DataLabel>
<Descriptions.Item label={t("courtesycars.fields.plate")}> <DataLabel label={t("courtesycars.fields.plate")}>
{(courtesyCar && courtesyCar.plate) || ""} {(courtesyCar && courtesyCar.plate) || ""}
</Descriptions.Item> </DataLabel>
<Descriptions.Item label={t("courtesycars.labels.vehicle")}> <DataLabel label={t("courtesycars.labels.vehicle")}>
{`${(courtesyCar && courtesyCar.year) || ""} ${ {`${(courtesyCar && courtesyCar.year) || ""} ${
(courtesyCar && courtesyCar.make) || "" (courtesyCar && courtesyCar.make) || ""
} ${(courtesyCar && courtesyCar.model) || ""}`} } ${(courtesyCar && courtesyCar.model) || ""}`}
</Descriptions.Item> </DataLabel>
</Descriptions> </div>
</Card> </Card>
</Link> </Link>
); );

View File

@@ -12,6 +12,7 @@ import InputPhone, {
} from "../form-items-formatted/phone-form-item.component"; } from "../form-items-formatted/phone-form-item.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import ContractFormJobPrefill from "./contract-form-job-prefill.component"; import ContractFormJobPrefill from "./contract-form-job-prefill.component";
export default function ContractFormComponent({ export default function ContractFormComponent({
form, form,
create = false, create = false,
@@ -83,10 +84,11 @@ export default function ContractFormComponent({
</Form.Item> </Form.Item>
)} )}
</LayoutFormRow> </LayoutFormRow>
<LayoutFormRow grow> <LayoutFormRow>
<Form.Item <Form.Item
label={t("contracts.fields.fuelout")} label={t("contracts.fields.fuelout")}
name="fuelout" name="fuelout"
span={8}
rules={[ rules={[
{ {
required: true, required: true,
@@ -97,23 +99,29 @@ export default function ContractFormComponent({
<CourtesyCarFuelSlider /> <CourtesyCarFuelSlider />
</Form.Item> </Form.Item>
{create ? null : ( {create ? null : (
<Form.Item label={t("contracts.fields.fuelin")} name="fuelin"> <Form.Item
label={t("contracts.fields.fuelin")}
name="fuelin"
span={8}
>
<CourtesyCarFuelSlider /> <CourtesyCarFuelSlider />
</Form.Item> </Form.Item>
)} )}
</LayoutFormRow> </LayoutFormRow>
<Space wrap> <div>
{selectedJobState && ( <Space wrap>
<div> {selectedJobState && (
<ContractFormJobPrefill <div>
jobId={selectedJobState && selectedJobState[0]} <ContractFormJobPrefill
form={form} jobId={selectedJobState && selectedJobState[0]}
/> form={form}
</div> />
)} </div>
<ContractLicenseDecodeButton form={form} /> )}
</Space> <ContractLicenseDecodeButton form={form} />
<LayoutFormRow> </Space>
</div>
<LayoutFormRow header={t("contracts.labels.driverinformation")}>
<Form.Item <Form.Item
label={t("contracts.fields.driver_dlnumber")} label={t("contracts.fields.driver_dlnumber")}
name="driver_dlnumber" name="driver_dlnumber"
@@ -222,7 +230,7 @@ export default function ContractFormComponent({
<FormDatePicker /> <FormDatePicker />
</Form.Item> </Form.Item>
</LayoutFormRow> </LayoutFormRow>
<LayoutFormRow> <LayoutFormRow header={t("contracts.labels.rates")}>
<Form.Item label={t("contracts.fields.dailyrate")} name="dailyrate"> <Form.Item label={t("contracts.fields.dailyrate")} name="dailyrate">
<InputNumber precision={2} /> <InputNumber precision={2} />
</Form.Item> </Form.Item>

View File

@@ -1,28 +1,33 @@
import { Card } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Descriptions, Card } from "antd";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import DataLabel from "../data-label/data-label.component";
export default function ContractJobBlock({ job }) { export default function ContractJobBlock({ job }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Link to={`/manage/jobs/${job && job.id}`}> <Link to={`/manage/jobs/${job && job.id}`}>
<Card title={t("jobs.labels.job")}> <Card
<Descriptions column={1}> className="ant-card-grid-hoverable"
<Descriptions.Item label={t("jobs.fields.ro_number")}> style={{ height: "100%" }}
title={t("jobs.labels.job")}
>
<div>
<DataLabel label={t("jobs.fields.ro_number")}>
{(job && job.ro_number) || ""} {(job && job.ro_number) || ""}
</Descriptions.Item> </DataLabel>
<Descriptions.Item label={t("jobs.fields.vehicle")}> <DataLabel label={t("jobs.fields.vehicle")}>
{`${(job && job.v_model_yr) || ""} ${ {`${(job && job.v_model_yr) || ""} ${
(job && job.v_make_desc) || "" (job && job.v_make_desc) || ""
} ${(job && job.v_model_desc) || ""}`} } ${(job && job.v_model_desc) || ""}`}
</Descriptions.Item> </DataLabel>
<Descriptions.Item label={t("jobs.fields.owner")}> <DataLabel label={t("jobs.fields.owner")}>
{`${(job && job.ownr_fn) || ""} ${(job && job.ownr_ln) || ""} ${ {`${(job && job.ownr_fn) || ""} ${(job && job.ownr_ln) || ""} ${
(job && job.ownr_co_nm) || "" (job && job.ownr_co_nm) || ""
}`} }`}
</Descriptions.Item> </DataLabel>
</Descriptions> </div>
</Card> </Card>
</Link> </Link>
); );

View File

@@ -1,4 +1,4 @@
import { Input, Table } from "antd"; import { Card, Input, Table } from "antd";
import React, { useMemo, useState } from "react"; import React, { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
@@ -162,44 +162,48 @@ export default function ContractsJobsComponent({
const defaultCurrent = useMemo(() => { const defaultCurrent = useMemo(() => {
const page = const page =
Math.floor( Math.floor(
(filteredData.findIndex((v) => v.id === selectedJob) || 0) / 3 (filteredData.findIndex((v) => v.id === selectedJob) || 0) / 10
) + 1; ) + 1;
if (page === 0) return 1;
return page; return page;
}, [filteredData, selectedJob]); }, [filteredData, selectedJob]);
if (loading) return <LoadingSkeleton />; if (loading) return <LoadingSkeleton />;
return ( return (
<Table <Card
loading={loading} title={t("jobs.labels.availablejobs")}
title={() => ( extra={
<Input.Search <Input.Search
placeholder={t("general.labels.search")} placeholder={t("general.labels.search")}
value={state.search} value={state.search}
onChange={(e) => setState({ ...state, search: e.target.value })} onChange={(e) => setState({ ...state, search: e.target.value })}
/> />
)} }
pagination={{ >
position: "top", <Table
defaultPageSize: 3, loading={loading}
defaultCurrent: defaultCurrent, pagination={{
}} position: "top",
columns={columns} defaultPageSize: 10,
rowKey="id" defaultCurrent: defaultCurrent,
dataSource={filteredData} }}
onChange={handleTableChange} columns={columns}
rowSelection={{ rowKey="id"
onSelect: handleSelect, dataSource={filteredData}
type: "radio", onChange={handleTableChange}
selectedRowKeys: [selectedJob], rowSelection={{
}} onSelect: handleSelect,
onRow={(record, rowIndex) => { type: "radio",
return { selectedRowKeys: [selectedJob],
onClick: (event) => { }}
handleSelect(record); onRow={(record, rowIndex) => {
}, return {
}; onClick: (event) => {
}} handleSelect(record);
/> },
};
}}
/>
</Card>
); );
} }

View File

@@ -25,14 +25,12 @@ export function ContractJobsContainer({ selectedJobState, bodyshop }) {
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent message={error.message} type="error" />;
return ( return (
<div> <ContractJobsComponent
<ContractJobsComponent handleSelect={handleSelect}
handleSelect={handleSelect} selectedJob={selectedJob}
selectedJob={selectedJob} loading={loading}
loading={loading} data={data ? data.jobs : []}
data={data ? data.jobs : []} />
/>
</div>
); );
} }
export default connect(mapStateToProps, null)(ContractJobsContainer); export default connect(mapStateToProps, null)(ContractJobsContainer);

View File

@@ -1,5 +1,5 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Input, Table } from "antd"; import { Button, Card, Input, Space, Table } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -123,38 +123,39 @@ export default function ContractsList({ loading, contracts, refetch, total }) {
}; };
return ( return (
<Table <Card
loading={loading} extra={
title={() => ( <Space wrap>
<div className="imex-table-header">
<Button onClick={() => refetch()}> <Button onClick={() => refetch()}>
<SyncOutlined /> <SyncOutlined />
</Button> </Button>
<div>
<TimeTicketsDatesSelector /> <TimeTicketsDatesSelector />
</div>
<div className="imex-table-header__search"> <Input.Search
<Input.Search placeholder={t("general.labels.search")}
placeholder={t("general.labels.search")} onSearch={(value) => {
onSearch={(value) => { search.search = value;
search.search = value; history.push({ search: queryString.stringify(search) });
history.push({ search: queryString.stringify(search) }); }}
}} />
/> </Space>
</div> }
</div> >
)} <Table
scroll={{ x: "50%", y: "40rem" }} loading={loading}
pagination={{ scroll={{ x: "50%", y: "40rem" }}
position: "top", pagination={{
pageSize: 25, position: "top",
current: parseInt(page || 1), pageSize: 25,
total: total, current: parseInt(page || 1),
}} total: total,
columns={columns} }}
rowKey="id" columns={columns}
dataSource={contracts} rowKey="id"
onChange={handleTableChange} dataSource={contracts}
/> onChange={handleTableChange}
/>
</Card>
); );
} }

View File

@@ -27,6 +27,14 @@ const CourtesyCarFuelComponent = (props, ref) => {
}, },
}; };
return <Slider ref={ref} marks={marks} step={null} {...props} />; return (
<Slider
ref={ref}
marks={marks}
step={null}
style={{ marginLeft: "2rem", marginRight: "2rem" }}
{...props}
/>
);
}; };
export default forwardRef(CourtesyCarFuelComponent); export default forwardRef(CourtesyCarFuelComponent);

View File

@@ -143,7 +143,7 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
<Table <Table
loading={loading} loading={loading}
pagination={{ position: "top" }} pagination={{ position: "top" }}
columns={columns.map((item) => ({ ...item }))} columns={columns}
rowKey="id" rowKey="id"
dataSource={tableData} dataSource={tableData}
onChange={handleTableChange} onChange={handleTableChange}

View File

@@ -39,7 +39,7 @@ export function JobsTotalsTableComponent({ jobRO, job }) {
return ( return (
<div> <div>
<Row gutter={[32, 32]}> <Row gutter={[16, 16]}>
<Col {...colSpan}> <Col {...colSpan}>
<Card title={t("jobs.labels.labortotals")}> <Card title={t("jobs.labels.labortotals")}>
<JobTotalsTableLabor job={job} /> <JobTotalsTableLabor job={job} />

View File

@@ -1,6 +1,7 @@
import { Col, Row, Typography } from "antd"; import { Checkbox, Col, Row } from "antd";
import React 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 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";
@@ -11,12 +12,30 @@ const colSpan = {
export default function JobsCreateOwnerInfoComponent({ loading, owners }) { export default function JobsCreateOwnerInfoComponent({ loading, owners }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [state, setState] = useContext(JobCreateContext);
return ( return (
<div> <div>
<Row> <Row gutter={[16, 16]}>
<Typography.Title>{t("jobs.labels.create.ownerinfo")}</Typography.Title> <Col span={24}>
</Row> <Checkbox
<Row gutter={[32, 32]}> defaultChecked={state.owner.new}
checked={state.owner.new}
onChange={() => {
setState({
...state,
owner: {
...state.owner,
new: !state.owner.new,
selectedid: null,
},
});
}}
>
{t("jobs.labels.create.newowner")}
</Checkbox>
</Col>
<Col {...colSpan}> <Col {...colSpan}>
<JobsCreateOwnerInfoSearchComponent <JobsCreateOwnerInfoSearchComponent
loading={loading} loading={loading}

View File

@@ -1,4 +1,4 @@
import { Form, Input, Checkbox, Switch } from "antd"; import { Form, Input, Switch } 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";
@@ -9,28 +9,11 @@ import FormItemPhone, {
import LayoutFormRow from "../layout-form-row/layout-form-row.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] = useContext(JobCreateContext);
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div> <div>
<Checkbox
defaultChecked={state.owner.new}
checked={state.owner.new}
onChange={() => {
setState({
...state,
owner: {
...state.owner,
new: !state.owner.new,
selectedid: null,
},
});
}}
>
{t("jobs.labels.create.newowner")}
</Checkbox>
<LayoutFormRow header={t("owners.forms.name")} grow> <LayoutFormRow header={t("owners.forms.name")} grow>
<Form.Item <Form.Item
label={t("owners.fields.ownr_ln")} label={t("owners.fields.ownr_ln")}

View File

@@ -1,4 +1,4 @@
import { Input, Table } from "antd"; import { Card, Input, Table } from "antd";
import React, { useContext, useState } from "react"; import React, { useContext, useState } 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";
@@ -91,65 +91,63 @@ export default function JobsCreateOwnerInfoSearchComponent({
}; };
return ( return (
<Table <Card
loading={loading} extra={
title={() => { <Input.Search
return ( placeholder={t("general.labels.search")}
<div className="imex-table-header"> onSearch={(value) => {
<Input.Search
className="imex-table-header__search"
placeholder={t("general.labels.search")}
onSearch={(value) => {
setState({
...state,
owner: { ...state.owner, search: value },
});
}}
enterButton
/>
</div>
);
}}
scroll={{ x: true }}
pagination={{ position: "top" }}
columns={columns}
rowKey="id"
dataSource={owners}
onChange={handleTableChange}
rowSelection={{
onSelect: (props) => {
setState({
...state,
owner: { ...state.owner, new: false, selectedid: props.id },
});
},
type: "radio",
selectedRowKeys: [state.owner.selectedid],
}}
onRow={(record, rowIndex) => {
return {
onClick: (event) => {
if (record) {
if (record.id) {
setState({
...state,
owner: {
...state.owner,
new: false,
selectedid: record.id,
},
});
return;
}
}
setState({ setState({
...state, ...state,
owner: { ...state.owner, selectedid: null }, owner: { ...state.owner, search: value },
});
}}
enterButton
/>
}
>
<Table
loading={loading}
scroll={{ x: true }}
pagination={{ position: "top" }}
columns={columns}
rowKey="id"
dataSource={owners}
onChange={handleTableChange}
rowSelection={{
onSelect: (props) => {
setState({
...state,
owner: { ...state.owner, new: false, selectedid: props.id },
}); });
}, },
}; type: "radio",
}} selectedRowKeys: [state.owner.selectedid],
/> }}
onRow={(record, rowIndex) => {
return {
onClick: (event) => {
if (record) {
if (record.id) {
setState({
...state,
owner: {
...state.owner,
new: false,
selectedid: record.id,
},
});
return;
}
}
setState({
...state,
owner: { ...state.owner, selectedid: null },
});
},
};
}}
/>
</Card>
); );
} }

View File

@@ -1,20 +1,56 @@
import { Col, Row, Typography } from "antd"; import { Checkbox, Col, Row } from "antd";
import React from "react"; import React, { useContext } from "react";
import { useTranslation } from "react-i18next"; import JobCreateContext from "../../pages/jobs-create/jobs-create.context";
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";
import { useTranslation } from "react-i18next";
const colSpan = { const colSpan = {
sm: { span: 24 }, sm: { span: 24 },
lg: { span: 12 }, lg: { span: 12 },
}; };
export default function JobsCreateVehicleInfoComponent({ loading, vehicles }) { export default function JobsCreateVehicleInfoComponent({ loading, vehicles }) {
const [state, setState] = useContext(JobCreateContext);
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div> <div>
<Typography.Title>{t("jobs.labels.create.vehicleinfo")}</Typography.Title> <Row gutter={[16, 16]}>
<Row gutter={[32, 32]}> <Col span={24}>
<Checkbox
defaultChecked={state.vehicle.new}
checked={state.vehicle.new}
onChange={() => {
setState({
...state,
vehicle: {
...state.vehicle,
none: false,
new: !state.vehicle.new,
selectedid: null,
},
});
}}
>
{t("jobs.labels.create.newvehicle")}
</Checkbox>
<Checkbox
defaultChecked={state.vehicle.none}
checked={state.vehicle.none}
onChange={() => {
setState({
...state,
vehicle: {
...state.vehicle,
new: false,
none: !state.vehicle.none,
selectedid: null,
},
});
}}
>
{t("jobs.labels.create.novehicle")}
</Checkbox>
</Col>
<Col {...colSpan}> <Col {...colSpan}>
<JobsCreateVehicleInfoSearchComponent <JobsCreateVehicleInfoSearchComponent
loading={loading} loading={loading}

View File

@@ -1,4 +1,4 @@
import { Checkbox, Form, Input } from "antd"; import { Form, Input } 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";
@@ -6,46 +6,11 @@ import FormDatePicker from "../form-date-picker/form-date-picker.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component"; 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] = useContext(JobCreateContext);
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div> <div>
<Checkbox
defaultChecked={state.vehicle.new}
checked={state.vehicle.new}
onChange={() => {
setState({
...state,
vehicle: {
...state.vehicle,
none: false,
new: !state.vehicle.new,
selectedid: null,
},
});
}}
>
{t("jobs.labels.create.newvehicle")}
</Checkbox>
<Checkbox
defaultChecked={state.vehicle.none}
checked={state.vehicle.none}
onChange={() => {
setState({
...state,
vehicle: {
...state.vehicle,
new: false,
none: !state.vehicle.none,
selectedid: null,
},
});
}}
>
{t("jobs.labels.create.novehicle")}
</Checkbox>
<LayoutFormRow header={t("vehicles.forms.detail")} grow> <LayoutFormRow header={t("vehicles.forms.detail")} grow>
<Form.Item <Form.Item
label={t("vehicles.fields.v_vin")} label={t("vehicles.fields.v_vin")}

View File

@@ -1,6 +1,6 @@
import React, { useContext, useState } from "react"; import React, { useContext, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Table, Input } from "antd"; import { Table, Input, Card, Space } from "antd";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { alphaSort } from "../../utils/sorters"; import { alphaSort } from "../../utils/sorters";
import JobCreateContext from "../../pages/jobs-create/jobs-create.context"; import JobCreateContext from "../../pages/jobs-create/jobs-create.context";
@@ -55,73 +55,77 @@ export default function JobsCreateVehicleInfoSearchComponent({
}; };
return ( return (
<Table <Card
loading={loading} extra={
title={() => { <Space wrap>
return ( <Input.Search
<div className="imex-table-header"> placeholder={t("general.labels.search")}
<Input.Search onSearch={(value) => {
className="imex-table-header__search" setState({
placeholder={t("general.labels.search")} ...state,
onSearch={(value) => { vehicle: { ...state.vehicle, search: value },
setState({ });
...state, }}
vehicle: { ...state.vehicle, search: value }, enterButton
}); />
}} </Space>
enterButton }
/> >
</div> <Table
); loading={loading}
}} scroll={{ x: true }}
scroll={{ x: true }} pagination={{ position: "top" }}
pagination={{ position: "top" }} columns={columns}
columns={columns} rowKey="id"
rowKey="id" dataSource={vehicles}
dataSource={vehicles} onChange={handleTableChange}
onChange={handleTableChange} rowSelection={{
rowSelection={{ onSelect: (props) => {
onSelect: (props) => {
setState({
...state,
vehicle: {
...state.vehicle,
none: false,
new: false,
selectedid: props.id,
vehicleObj: props,
},
});
},
type: "radio",
selectedRowKeys: [state.vehicle.selectedid],
}}
onRow={(record, rowIndex) => {
return {
onClick: (event) => {
if (record) {
if (record.id) {
setState({
...state,
vehicle: {
...state.vehicle,
none: false,
new: false,
selectedid: record.id,
vehicleObj: record,
},
});
return;
}
}
setState({ setState({
...state, ...state,
vehicle: { ...state.vehicle, selectedid: null, vehicleObj: null }, vehicle: {
...state.vehicle,
none: false,
new: false,
selectedid: props.id,
vehicleObj: props,
},
}); });
}, },
}; type: "radio",
}} selectedRowKeys: [state.vehicle.selectedid],
/> }}
onRow={(record, rowIndex) => {
return {
onClick: (event) => {
if (record) {
if (record.id) {
setState({
...state,
vehicle: {
...state.vehicle,
none: false,
new: false,
selectedid: record.id,
vehicleObj: record,
},
});
return;
}
}
setState({
...state,
vehicle: {
...state.vehicle,
selectedid: null,
vehicleObj: null,
},
});
},
};
}}
/>
</Card>
); );
} }

View File

@@ -142,46 +142,6 @@ export function JobsDetailHeader({ job, bodyshop }) {
</Col> </Col>
</Row> </Row>
); );
// return (
// <PageHeader
// title={job.ro_number || t("general.labels.na")}
// subTitle={job.status}
// tags={[
// <OwnerTagPopoverComponent key="owner" job={job} />,
// <VehicleTagPopoverComponent key="vehicle" job={job} />,
// <Tag
// color="#f50"
// key="production"
// style={{ display: job.inproduction ? "" : "none" }}
// >
// {t("jobs.labels.inproduction")}
// </Tag>,
// <Tag title={t("jobs.fields.repairtotal")} key="total" color="green">
// <CurrencyFormatter>{job.clm_total}</CurrencyFormatter>
// <span style={{ margin: "0rem .5rem" }}>/</span>
// <CurrencyFormatter>{job.owner_owing}</CurrencyFormatter>
// </Tag>,
// ]}
// extra={menuExtra}
// >
// <div style={{ display: "flex", justifyContent: "flex-end" }}>
// {(job.inproduction || jobInPostProduction) && (
// <>
// <div style={{ display: "flex", flex: 1 }}>
// <div style={{ marginRight: "2rem" }}>
// {t("jobs.fields.production_vars.note")}
// </div>
// <ProductionListColumnProductionNote record={job} />
// </div>
// <Divider type="vertical" />
// </>
// )}
//
// </div>
// </PageHeader>
// );
} }
export default connect(mapStateToProps, mapDispatchToProps)(JobsDetailHeader); export default connect(mapStateToProps, mapDispatchToProps)(JobsDetailHeader);

View File

@@ -156,7 +156,7 @@ export default function JobsFindModalComponent({
</div> </div>
)} )}
pagination={{ position: "bottom" }} pagination={{ position: "bottom" }}
columns={columns.map((item) => ({ ...item }))} columns={columns}
rowKey="id" rowKey="id"
loading={jobsListLoading} loading={jobsListLoading}
dataSource={jobsList} dataSource={jobsList}

View File

@@ -1,5 +1,5 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Input, Table } from "antd"; import { Button, Card, Input, Space, Table } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -191,7 +191,23 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
}; };
return ( return (
<div> <Card
extra={
<Space wrap>
<Button onClick={() => refetch()}>
<SyncOutlined />
</Button>
<Input.Search
placeholder={t("general.labels.search")}
onSearch={(value) => {
search.search = value;
history.push({ search: queryString.stringify(search) });
}}
enterButton
/>
</Space>
}
>
<Table <Table
loading={loading} loading={loading}
scroll={{ x: true }} scroll={{ x: true }}
@@ -205,26 +221,8 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
rowKey="id" rowKey="id"
dataSource={jobs} dataSource={jobs}
onChange={handleTableChange} onChange={handleTableChange}
title={() => {
return (
<div className="imex-table-header">
<Button onClick={() => refetch()}>
<SyncOutlined />
</Button>
<Input.Search
className="imex-table-header__search"
placeholder={t("general.labels.search")}
onSearch={(value) => {
search.search = value;
history.push({ search: queryString.stringify(search) });
}}
enterButton
/>
</div>
);
}}
/> />
</div> </Card>
); );
} }
export default connect(mapStateToProps, mapDispatchToProps)(JobsList); export default connect(mapStateToProps, mapDispatchToProps)(JobsList);

View File

@@ -68,7 +68,7 @@ export default function OwnerFindModalComponent({
<Table <Table
title={() => t("owners.labels.existing_owners")} title={() => t("owners.labels.existing_owners")}
pagination={{ position: "bottom" }} pagination={{ position: "bottom" }}
columns={columns.map((item) => ({ ...item }))} columns={columns}
rowKey="id" rowKey="id"
loading={ownersListLoading} loading={ownersListLoading}
dataSource={ownersList} dataSource={ownersList}

View File

@@ -1,4 +1,4 @@
import { Input } from "antd"; import { Input, PageHeader, Space, Spin } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -17,25 +17,35 @@ export default connect(
mapDispatchToProps mapDispatchToProps
)(ProductionBoardFilters); )(ProductionBoardFilters);
export function ProductionBoardFilters({ bodyshop, filter, setFilter }) { export function ProductionBoardFilters({
bodyshop,
filter,
setFilter,
loading,
}) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div style={{ display: "flex" }}> <PageHeader
<Input.Search extra={
//value={filter.search} <Space wrap>
placeholder={t("general.labels.search")} {loading && <Spin />}
onChange={(e) => { <Input.Search
setFilter({ ...filter, search: e.target.value }); //value={filter.search}
}} placeholder={t("general.labels.search")}
/> onChange={(e) => {
<EmployeeSearchSelectComponent setFilter({ ...filter, search: e.target.value });
options={bodyshop.employees.filter((e) => e.active)} }}
value={filter.employeeId} />
placeholder={t("production.labels.employeesearch")} <EmployeeSearchSelectComponent
onChange={(emp) => setFilter({ ...filter, employeeId: emp })} options={bodyshop.employees.filter((e) => e.active)}
allowClear value={filter.employeeId}
/> placeholder={t("production.labels.employeesearch")}
</div> onChange={(emp) => setFilter({ ...filter, employeeId: emp })}
allowClear
/>
</Space>
}
></PageHeader>
); );
} }

View File

@@ -1,3 +1,9 @@
.imex-kanban-card { .imex-kanban-card {
padding: 0px !important; padding: 0px !important;
.ant-card-body {
padding: 0.8rem;
}
.ant-card-head {
padding: 0rem 0.8rem;
}
} }

View File

@@ -24,7 +24,7 @@ export default function ProductionBoardCard(technician, card) {
<Dropdown overlay={menu} trigger={["contextMenu"]}> <Dropdown overlay={menu} trigger={["contextMenu"]}>
<Card <Card
className="react-kanban-card imex-kanban-card tight-antd-rows" className="react-kanban-card imex-kanban-card tight-antd-rows"
style={{ margin: ".2rem 0rem" }} //style={{ margin: ".2rem 0rem" }}
title={`${card.ro_number || t("general.labels.na")} - ${ title={`${card.ro_number || t("general.labels.na")} - ${
card.v_model_yr card.v_model_yr
} ${card.v_make_desc || ""} ${card.v_model_desc || ""}`} } ${card.v_make_desc || ""} ${card.v_model_desc || ""}`}

View File

@@ -116,7 +116,11 @@ export function ProductionBoardKanbanComponent({ data, bodyshop, technician }) {
return ( return (
<div> <div>
<IndefiniteLoading loading={isMoving} /> <IndefiniteLoading loading={isMoving} />
<ProductionBoardFilters filter={filter} setFilter={setFilter} /> <ProductionBoardFilters
filter={filter}
setFilter={setFilter}
loading={isMoving}
/>
<Board <Board
children={boardLanes} children={boardLanes}
disableCardDrag={isMoving} disableCardDrag={isMoving}

View File

@@ -11,11 +11,10 @@ const mapStateToProps = createStructuredSelector({
}); });
export function ProductionBoardKanbanContainer({ bodyshop }) { export function ProductionBoardKanbanContainer({ bodyshop }) {
const { loading, data } = useSubscription(SUBSCRIPTION_JOBS_IN_PRODUCTION, { const { loading, data } = useSubscription(
// variables: { SUBSCRIPTION_JOBS_IN_PRODUCTION,
// statusList: bodyshop.md_ro_statuses.production_statuses || [], {}
// }, );
});
return ( return (
<ProductionBoardKanbanComponent <ProductionBoardKanbanComponent

View File

@@ -1,5 +1,14 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Dropdown, Input, Menu, Table } from "antd"; import {
Button,
Card,
Dropdown,
Input,
Menu,
PageHeader,
Space,
Table,
} from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import ReactDragListView from "react-drag-listview"; import ReactDragListView from "react-drag-listview";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -108,24 +117,7 @@ export function ProductionListTable({
.includes(searchText.toLowerCase()) .includes(searchText.toLowerCase())
); );
const tableTitle = () => ( const tableTitle = () => <div style={{ display: "flex" }}></div>;
<div style={{ display: "flex" }}>
<ProductionListColumnsAdd columnState={columnState} />
<ProductionListSaveConfigButton columns={columns} tableState={state} />
<Button
onClick={() => {
if (refetch) refetch();
}}
>
<SyncOutlined />
</Button>
<Input
onChange={(e) => setSearchText(e.target.value)}
placeholder={t("general.labels.search")}
value={searchText}
/>
</div>
);
// const handleSelectRecord = (record) => { // const handleSelectRecord = (record) => {
// if (selected !== record.id) { // if (selected !== record.id) {
@@ -139,6 +131,29 @@ export function ProductionListTable({
return ( return (
<div> <div>
<PageHeader
extra={
<Space wrap>
<ProductionListColumnsAdd columnState={columnState} />
<ProductionListSaveConfigButton
columns={columns}
tableState={state}
/>
<Button
onClick={() => {
if (refetch) refetch();
}}
>
<SyncOutlined />
</Button>
<Input
onChange={(e) => setSearchText(e.target.value)}
placeholder={t("general.labels.search")}
value={searchText}
/>
</Space>
}
/>
<ProductionListDetail jobs={dataSource} /> <ProductionListDetail jobs={dataSource} />
<ReactDragListView.DragColumn <ReactDragListView.DragColumn
onDragEnd={onDragEnd} onDragEnd={onDragEnd}
@@ -147,6 +162,7 @@ export function ProductionListTable({
> >
<Table <Table
pagination={false} pagination={false}
size="small"
components={{ components={{
header: { header: {
cell: ResizeableTitle, cell: ResizeableTitle,
@@ -168,15 +184,8 @@ export function ProductionListTable({
rowKey="id" rowKey="id"
loading={loading} loading={loading}
dataSource={dataSource} dataSource={dataSource}
scrol={{ x: true }}
onChange={handleTableChange} onChange={handleTableChange}
// rowClassName={(record, index) => {
// // const classes = [];
// // if (!!record.scheduled_completion) {
// // if (new Date(record.scheduled_completion) - Now < OneCalendarDay)
// // classes.push("production-completion-1");
// // }
// // return classes.join(" ");
// }}
/> />
</ReactDragListView.DragColumn> </ReactDragListView.DragColumn>
</div> </div>

View File

@@ -16,11 +16,10 @@ const mapStateToProps = createStructuredSelector({
export default connect(mapStateToProps, null)(ProductionListTableContainer); export default connect(mapStateToProps, null)(ProductionListTableContainer);
export function ProductionListTableContainer({ bodyshop, technician }) { export function ProductionListTableContainer({ bodyshop, technician }) {
const { loading, data } = useSubscription(SUBSCRIPTION_JOBS_IN_PRODUCTION, { const { loading, data } = useSubscription(
// variables: { SUBSCRIPTION_JOBS_IN_PRODUCTION,
// statusList: bodyshop.md_ro_statuses.production_statuses || [], {}
// }, );
});
const columnState = useState( const columnState = useState(
(bodyshop.production_config && (bodyshop.production_config &&

View File

@@ -48,7 +48,7 @@ export default function ProfileShopsComponent({
</Typography.Title> </Typography.Title>
)} )}
loading={loading} loading={loading}
columns={columns.map((item) => ({ ...item }))} columns={columns}
rowKey="id" rowKey="id"
dataSource={data} dataSource={data}
/> />

View File

@@ -63,7 +63,7 @@ export function ScheduleJobModalComponent({
}; };
return ( return (
<Row gutter={[32, 32]}> <Row gutter={[16, 16]}>
<Col span={12}> <Col span={12}>
<LayoutFormRow grow> <LayoutFormRow grow>
<Form.Item <Form.Item

View File

@@ -71,7 +71,7 @@ export default function ShopEmployeesListComponent({
}} }}
loading={loading} loading={loading}
pagination={{ position: "top" }} pagination={{ position: "top" }}
columns={columns.map((item) => ({ ...item }))} columns={columns}
rowKey="id" rowKey="id"
dataSource={employees} dataSource={employees}
rowSelection={{ rowSelection={{

View File

@@ -49,7 +49,7 @@ export default function ShopInfoUsersComponent() {
<Table <Table
loading={loading} loading={loading}
pagination={{ position: "top" }} pagination={{ position: "top" }}
columns={columns.map((item) => ({ ...item }))} columns={columns}
rowKey="id" rowKey="id"
dataSource={data && data.associations} dataSource={data && data.associations}
/> />

View File

@@ -33,15 +33,13 @@ export default function TimeTicketsDatesSelector() {
}; };
return ( return (
<div> <DatePicker.RangePicker
<DatePicker.RangePicker defaultValue={[
defaultValue={[ start ? moment(start) : moment().startOf("week").subtract(7, "days"),
start ? moment(start) : moment().startOf("week").subtract(7, "days"), end ? moment(end) : moment().endOf("week"),
end ? moment(end) : moment().endOf("week"), ]}
]} ranges={DatePickerRanges}
ranges={DatePickerRanges} onCalendarChange={handleChange}
onCalendarChange={handleChange} />
/>
</div>
); );
} }

View File

@@ -1,5 +1,5 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Checkbox, Input, Space, Table, Typography } from "antd"; import { Button, Card, Checkbox, Input, Space, Table } from "antd";
import queryString from "query-string"; import queryString from "query-string";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -201,37 +201,39 @@ export function BillsListPage({
}; };
return ( return (
<div> <Card
title={t("bills.labels.bills")}
extra={
<Space wrap>
<Button onClick={() => refetch()}>
<SyncOutlined />
</Button>
<Button
onClick={() => {
setBillEnterContext({
actions: { refetch: refetch },
context: {},
});
}}
>
{t("jobs.actions.postbills")}
</Button>
<div className="imex-table-header__search">
<Input.Search
placeholder={t("general.labels.search")}
onSearch={(value) => {
search.search = value;
history.push({ search: queryString.stringify(search) });
}}
/>
</div>
</Space>
}
>
<PartsOrderModalContainer /> <PartsOrderModalContainer />
<Typography.Title level={4}>{t("bills.labels.bills")}</Typography.Title>
<Table <Table
loading={loading} loading={loading}
title={() => (
<div className="imex-table-header">
<Button onClick={() => refetch()}>
<SyncOutlined />
</Button>
<Button
onClick={() => {
setBillEnterContext({
actions: { refetch: refetch },
context: {},
});
}}
>
{t("jobs.actions.postbills")}
</Button>
<div className="imex-table-header__search">
<Input.Search
placeholder={t("general.labels.search")}
onSearch={(value) => {
search.search = value;
history.push({ search: queryString.stringify(search) });
}}
/>
</div>
</div>
)}
scroll={{ x: "50%", y: "40rem" }} scroll={{ x: "50%", y: "40rem" }}
pagination={{ pagination={{
position: "top", position: "top",
@@ -244,7 +246,7 @@ export function BillsListPage({
dataSource={data} dataSource={data}
onChange={handleTableChange} onChange={handleTableChange}
/> />
</div> </Card>
); );
} }
export default connect(null, mapDispatchToProps)(BillsListPage); export default connect(null, mapDispatchToProps)(BillsListPage);

View File

@@ -1,4 +1,4 @@
import { Button } from "antd"; import { Button, Col, PageHeader, Row } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import ContractCarsContainer from "../../components/contract-cars/contract-cars.container"; import ContractCarsContainer from "../../components/contract-cars/contract-cars.container";
@@ -25,22 +25,31 @@ export default function ContractCreatePageComponent({
return ( return (
<div> <div>
{CreateButton} <Row gutter={[16, 16]}>
<ContractJobsContainer selectedJobState={selectedJobState} /> <Col span={24}>
<ContractCarsContainer selectedCarState={selectedCarState} form={form} /> <ContractJobsContainer selectedJobState={selectedJobState} />
</Col>
<div <Col span={24}>
style={{ <ContractCarsContainer
display: selectedJobState[0] && selectedCarState[0] ? "" : "none", selectedCarState={selectedCarState}
}} form={form}
> />
<ContractFormComponent </Col>
create <Col span={24}>
form={form} <div
selectedJobState={selectedJobState} style={{
/> display: selectedJobState[0] && selectedCarState[0] ? "" : "none",
</div> }}
{CreateButton} >
<ContractFormComponent
create
form={form}
selectedJobState={selectedJobState}
/>
</div>
</Col>
</Row>
<PageHeader extra={CreateButton} />
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
import { Button, Col, Row, Space, Typography, Form } from "antd"; import { Button, Col, Row, Space, Typography, Form, PageHeader } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -28,17 +28,14 @@ export function ContractDetailPage({
return ( return (
<div> <div>
<Row align="middle"> <Row align="middle">
<Typography.Title>{`Agreement ${ <Typography.Title></Typography.Title>
(contract && contract.agreementnumber) || ""
} - ${t((contract && contract.status) || "")}`}</Typography.Title>
</Row> </Row>
<PageHeader
<Row> title={t("contracts.labels.agreement", {
<Col span={4} offset={1}> agreement_num: contract && contract.agreementnumber,
<ContractJobBlock job={job} /> status: t(contract && contract.status),
<ContractCourtesyCarBlock courtesyCar={courtesyCar} /> })}
</Col> extra={
<Col span={18} offset={1}>
<Form.Item shouldUpdate> <Form.Item shouldUpdate>
{() => { {() => {
return ( return (
@@ -94,6 +91,16 @@ export function ContractDetailPage({
); );
}} }}
</Form.Item> </Form.Item>
}
/>
<Row gutter={[16, 16]}>
<Col sm={24} md={12}>
<ContractJobBlock job={job} />
</Col>
<Col sm={24} md={12}>
<ContractCourtesyCarBlock courtesyCar={courtesyCar} />
</Col>
<Col span={24}>
<ContractFormComponent form={form} /> <ContractFormComponent form={form} />
</Col> </Col>
</Row> </Row>

View File

@@ -8,13 +8,11 @@ export default function ContractsPageComponent({
total, total,
}) { }) {
return ( return (
<div> <ContractsList
<ContractsList loading={loading}
loading={loading} contracts={data}
contracts={data} refetch={refetch}
refetch={refetch} total={total}
total={total} />
/>
</div>
); );
} }

View File

@@ -72,7 +72,7 @@ export function JobsChecklistViewContainer({
return ( return (
<RbacWrapper action="jobs:checklist-view"> <RbacWrapper action="jobs:checklist-view">
<Row gutter={[32, 32]}> <Row gutter={[16, 16]}>
<Col span={12}> <Col span={12}>
<Typography.Title level={4}> <Typography.Title level={4}>
{t("jobs.labels.intakechecklist")} {t("jobs.labels.intakechecklist")}

View File

@@ -1,4 +1,4 @@
import { Button, Result, Steps } from "antd"; import { Button, PageHeader, Result, Space, Steps } from "antd";
import React, { useContext, useState } from "react"; import React, { useContext, 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";
@@ -44,36 +44,68 @@ export default function JobsCreateComponent({ form }) {
}; };
const { Step } = Steps; const { Step } = Steps;
const ProgressButtons = () => { const ProgressButtons = ({ top }) => {
return ( return (
<div style={{ margin: "1rem" }}> <PageHeader
{pageIndex > 0 && <Button onClick={() => prev()}>Previous</Button>} extra={
{pageIndex < steps.length - 1 && ( <Space wrap>
<Button {pageIndex > 0 && <Button onClick={() => prev()}>Previous</Button>}
type="primary" {pageIndex < steps.length - 1 && (
onClick={() => { <Button
form type="primary"
.validateFields() onClick={() => {
.then((r) => { form
if (steps[pageIndex].validation) { .validateFields()
setErrorMessage(null); .then((r) => {
next(); if (steps[pageIndex].validation) {
} else { setErrorMessage(null);
setErrorMessage(steps[pageIndex].error); next();
} } else {
}) setErrorMessage(steps[pageIndex].error);
.catch((error) => console.log("error", error)); }
}} })
> .catch((error) => console.log("error", error));
Next }}
</Button> >
Next
</Button>
)}
{pageIndex === steps.length - 1 && (
<Button type="primary" htmlType="submit">
Done
</Button>
)}
</Space>
}
>
{top && (
<Steps current={pageIndex}>
{steps.map((item, idx) => (
<Step
key={item.title}
title={item.title}
style={{
cursor: "pointer",
fontWeight: idx === pageIndex && "bolder",
}}
onClick={() => {
form
.validateFields()
.then((r) => {
if (steps[pageIndex].validation) {
setErrorMessage(null);
setPageIndex(idx);
} else {
setErrorMessage(steps[pageIndex].error);
}
})
.catch((error) => console.log("error", error));
}}
/>
))}
</Steps>
)} )}
{pageIndex === steps.length - 1 && ( </PageHeader>
<Button type="primary" htmlType="submit">
Done
</Button>
)}
</div>
); );
}; };
@@ -96,29 +128,7 @@ export default function JobsCreateComponent({ form }) {
</div> </div>
) : ( ) : (
<div> <div>
<Steps current={pageIndex}> <ProgressButtons top />
{steps.map((item, idx) => (
<Step
key={item.title}
title={item.title}
style={{ cursor: "pointer" }}
onClick={() => {
form
.validateFields()
.then((r) => {
if (steps[pageIndex].validation) {
setErrorMessage(null);
setPageIndex(idx);
} else {
setErrorMessage(steps[pageIndex].error);
}
})
.catch((error) => console.log("error", error));
}}
/>
))}
</Steps>
<ProgressButtons />
{errorMessage ? ( {errorMessage ? (
<div> <div>

View File

@@ -149,6 +149,7 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
<JobCreateContext.Provider value={contextState}> <JobCreateContext.Provider value={contextState}>
<RbacWrapper action="jobs:create"> <RbacWrapper action="jobs:create">
<Form <Form
scrollToFirstError
form={form} form={form}
onFinish={handleFinish} onFinish={handleFinish}
layout="vertical" layout="vertical"

View File

@@ -1,6 +1,6 @@
import React from "react"; import React from "react";
import ProductionListTable from "../../components/production-list-table/production-list-table.container"; import ProductionListTable from "../../components/production-list-table/production-list-table.container";
export default function ProductionListComponent({ columnState }) { export default function ProductionListComponent() {
return <ProductionListTable />; return <ProductionListTable />;
} }

View File

@@ -1,18 +1,12 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
import { import {
setBreadcrumbs, setBreadcrumbs,
setSelectedHeader, setSelectedHeader,
} from "../../redux/application/application.actions"; } from "../../redux/application/application.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import ProductionListComponent from "./production-list.component"; import ProductionListComponent from "./production-list.component";
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
@@ -21,7 +15,7 @@ const mapDispatchToProps = (dispatch) => ({
export function ProductionListContainer({ export function ProductionListContainer({
setBreadcrumbs, setBreadcrumbs,
bodyshop,
setSelectedHeader, setSelectedHeader,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -40,7 +34,4 @@ export function ProductionListContainer({
</RbacWrapper> </RbacWrapper>
); );
} }
export default connect( export default connect(null, mapDispatchToProps)(ProductionListContainer);
mapStateToProps,
mapDispatchToProps
)(ProductionListContainer);

View File

@@ -520,13 +520,17 @@
"status": "Status" "status": "Status"
}, },
"labels": { "labels": {
"agreement": "Agreement {{agreement_num}} - {{status}}",
"availablecars": "Available Cars",
"convertform": { "convertform": {
"applycleanupcharge": "Apply cleanup charge?", "applycleanupcharge": "Apply cleanup charge?",
"refuelqty": "Refuel qty.?" "refuelqty": "Refuel qty.?"
}, },
"correctdataonform": "Please review the information above. If any of it is not correct, you can fix it later.", "correctdataonform": "Please review the information above. If any of it is not correct, you can fix it later.",
"driverinformation": "Driver's Information",
"noteconvertedfrom": "R.O. created from converted Courtesy Car Contract {{agreementnumber}}.", "noteconvertedfrom": "R.O. created from converted Courtesy Car Contract {{agreementnumber}}.",
"populatefromjob": "Populate from Job", "populatefromjob": "Populate from Job",
"rates": "Contract Rates",
"vehicle": "Vehicle", "vehicle": "Vehicle",
"waitingforscan": "Please scan driver's license barcode..." "waitingforscan": "Please scan driver's license barcode..."
}, },

View File

@@ -520,13 +520,17 @@
"status": "" "status": ""
}, },
"labels": { "labels": {
"agreement": "",
"availablecars": "",
"convertform": { "convertform": {
"applycleanupcharge": "", "applycleanupcharge": "",
"refuelqty": "" "refuelqty": ""
}, },
"correctdataonform": "", "correctdataonform": "",
"driverinformation": "",
"noteconvertedfrom": "", "noteconvertedfrom": "",
"populatefromjob": "", "populatefromjob": "",
"rates": "",
"vehicle": "", "vehicle": "",
"waitingforscan": "" "waitingforscan": ""
}, },

View File

@@ -520,13 +520,17 @@
"status": "" "status": ""
}, },
"labels": { "labels": {
"agreement": "",
"availablecars": "",
"convertform": { "convertform": {
"applycleanupcharge": "", "applycleanupcharge": "",
"refuelqty": "" "refuelqty": ""
}, },
"correctdataonform": "", "correctdataonform": "",
"driverinformation": "",
"noteconvertedfrom": "", "noteconvertedfrom": "",
"populatefromjob": "", "populatefromjob": "",
"rates": "",
"vehicle": "", "vehicle": "",
"waitingforscan": "" "waitingforscan": ""
}, },