BOD-17 Basic creation of a contract functioning.

This commit is contained in:
Patrick Fic
2020-03-31 12:11:48 -07:00
parent 9ae3843b3b
commit 72f4d31b05
17 changed files with 884 additions and 190 deletions

View File

@@ -0,0 +1,119 @@
import { Input, Table } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters";
export default function ContractsCarsComponent({
loading,
data,
selectedCar,
handleSelect
}) {
const [state, setState] = useState({
sortedInfo: {},
filteredInfo: { text: "" },
search: ""
});
const { t } = useTranslation();
const columns = [
{
title: t("courtesycars.fields.fleetnumber"),
dataIndex: "fleetnumber",
key: "fleetnumber",
sorter: (a, b) => alphaSort(a.fleetnumber, b.fleetnumber),
sortOrder:
state.sortedInfo.columnKey === "fleetnumber" && state.sortedInfo.order
},
{
title: t("courtesycars.fields.status"),
dataIndex: "status",
key: "status",
sorter: (a, b) => alphaSort(a.status, b.status),
sortOrder:
state.sortedInfo.columnKey === "status" && state.sortedInfo.order
},
{
title: t("courtesycars.fields.year"),
dataIndex: "year",
key: "year",
sorter: (a, b) => alphaSort(a.year, b.year),
sortOrder: state.sortedInfo.columnKey === "year" && state.sortedInfo.order
},
{
title: t("courtesycars.fields.make"),
dataIndex: "make",
key: "make",
sorter: (a, b) => alphaSort(a.make, b.make),
sortOrder: state.sortedInfo.columnKey === "make" && state.sortedInfo.order
},
{
title: t("courtesycars.fields.model"),
dataIndex: "model",
key: "model",
sorter: (a, b) => alphaSort(a.model, b.model),
sortOrder:
state.sortedInfo.columnKey === "model" && state.sortedInfo.order
},
{
title: t("courtesycars.fields.plate"),
dataIndex: "plate",
key: "plate",
sorter: (a, b) => alphaSort(a.plate, b.plate),
sortOrder:
state.sortedInfo.columnKey === "plate" && state.sortedInfo.order
}
];
const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
};
const filteredData =
state.search === ""
? data
: data.filter(
cc =>
(cc.fleetnumber || "")
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(cc.status || "")
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(cc.year || "")
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(cc.make || "")
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(cc.model || "")
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(cc.plate || "").toLowerCase().includes(state.search.toLowerCase())
);
console.log("filteredData", filteredData);
return (
<Table
loading={loading}
title={() => (
<Input.Search
placeholder={t("general.labels.search")}
value={state.search}
onChange={e => setState({ ...state, search: e.target.value })}
/>
)}
size="small"
pagination={{ position: "top" }}
columns={columns.map(item => ({ ...item }))}
rowKey="id"
dataSource={filteredData}
onChange={handleTableChange}
rowSelection={{
onSelect: handleSelect,
type: "radio",
selectedRowKeys: [selectedCar]
}}
/>
);
}

View File

@@ -0,0 +1,29 @@
import { useQuery } from "@apollo/react-hooks";
import React from "react";
import { QUERY_AVAILABLE_CC } from "../../graphql/courtesy-car.queries";
import AlertComponent from "../alert/alert.component";
import ContractCarsComponent from "./contract-cars.component";
export default function ContractCarsContainer({ selectedCarState, bodyshop }) {
const { loading, error, data } = useQuery(QUERY_AVAILABLE_CC);
const [selectedCar, setSelectedCar] = selectedCarState;
const handleSelect = record => {
setSelectedCar(record.id);
};
if (error) return <AlertComponent message={error.message} type="error" />;
return (
<div>
<ContractCarsComponent
handleSelect={handleSelect}
selectedCar={selectedCar}
loading={loading}
data={data ? data.courtesycars : []}
/>
</div>
);
}

View File

@@ -2,6 +2,8 @@ import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { Form, Input, DatePicker, InputNumber, Button } from "antd";
import aamva from "aamva";
import InputPhone from "../form-items-formatted/phone-form-item.component";
import ContractStatusSelector from "../contract-status-select/contract-status-select.component";
export default function ContractFormComponent() {
const [state, setState] = useState("");
@@ -15,9 +17,7 @@ export default function ContractFormComponent() {
//let data = state;
var data =
"%FLDELRAY BEACH^DOE$JOHN$^4818 S FEDERAL BLVD^ ?\
;6360100462172082009=2101198299090=?\
#! 33435 I 1600 ECCECC00000?";
"%FLDELRAY BEACH^DOE$JOHN$^4818 S FEDERAL BLVD^ ? ;6360100462172082009=2101198299090=? #! 33435 I 1600 ECCECC00000?";
data = data.replace(/\n/, "");
// replace spaces with regular space
data = data.replace(/\s/g, " ");
@@ -32,7 +32,7 @@ export default function ContractFormComponent() {
</Button>
<Form.Item
label={t("contracts.fields.status")}
name="status "
name="status"
rules={[
{
required: true,
@@ -40,7 +40,7 @@ export default function ContractFormComponent() {
}
]}
>
<Input />
<ContractStatusSelector />
</Form.Item>
<Form.Item
label={t("contracts.fields.start")}
@@ -66,16 +66,7 @@ export default function ContractFormComponent() {
>
<DatePicker />
</Form.Item>
<Form.Item
label={t("contracts.fields.actualreturn")}
name="actualreturn"
rules={[
{
required: true,
message: t("general.validation.required")
}
]}
>
<Form.Item label={t("contracts.fields.actualreturn")} name="actualreturn">
<DatePicker />
</Form.Item>
<Form.Item
@@ -90,16 +81,7 @@ export default function ContractFormComponent() {
>
<InputNumber />
</Form.Item>
<Form.Item
label={t("contracts.fields.kmend")}
name="kmend"
rules={[
{
required: true,
message: t("general.validation.required")
}
]}
>
<Form.Item label={t("contracts.fields.kmend")} name="kmend">
<InputNumber />
</Form.Item>
<Form.Item
@@ -174,16 +156,7 @@ export default function ContractFormComponent() {
>
<Input />
</Form.Item>
<Form.Item
label={t("contracts.fields.driver_addr2")}
name="driver_addr2"
rules={[
{
required: true,
message: t("general.validation.required")
}
]}
>
<Form.Item label={t("contracts.fields.driver_addr2")} name="driver_addr2">
<Input />
</Form.Item>
<Form.Item
@@ -232,7 +205,7 @@ export default function ContractFormComponent() {
}
]}
>
<Input />
<InputPhone />
</Form.Item>
<Form.Item
label={t("contracts.fields.driver_dob")}

View File

@@ -0,0 +1,187 @@
import { Table, Input } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { alphaSort } from "../../utils/sorters";
export default function ContractsJobsComponent({
loading,
data,
selectedJob,
handleSelect
}) {
const [state, setState] = useState({
sortedInfo: {},
filteredInfo: { text: "" },
search: ""
});
const { t } = useTranslation();
const columns = [
{
title: t("jobs.fields.ro_number"),
dataIndex: "ro_number",
key: "ro_number",
width: "8%",
sorter: (a, b) =>
alphaSort(
a.ro_number ? a.ro_number : "EST-" + a.est_number,
b.ro_number ? b.ro_number : "EST-" + b.est_number
),
sortOrder:
state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order,
render: (text, record) => (
<span>
{record.ro_number ? record.ro_number : "EST-" + record.est_number}
</span>
)
},
{
title: t("jobs.fields.owner"),
dataIndex: "owner",
key: "owner",
ellipsis: true,
sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
width: "25%",
sortOrder:
state.sortedInfo.columnKey === "owner" && state.sortedInfo.order,
render: (text, record) => {
return record.owner ? (
<span>
{record.ownr_fn} {record.ownr_ln}
</span>
) : (
<span>{`${record.ownr_fn} ${record.ownr_ln}`}</span>
);
}
},
{
title: t("jobs.fields.status"),
dataIndex: "status",
key: "status",
width: "10%",
ellipsis: true,
sorter: (a, b) => alphaSort(a.status, b.status),
sortOrder:
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
render: (text, record) => {
return record.status || t("general.labels.na");
}
},
{
title: t("jobs.fields.vehicle"),
dataIndex: "vehicle",
key: "vehicle",
width: "15%",
ellipsis: true,
render: (text, record) => {
return record.vehicleid ? (
<span>
{`${record.v_model_yr || ""} ${record.v_make_desc ||
""} ${record.v_model_desc || ""}`}
</span>
) : (
t("jobs.errors.novehicle")
);
}
},
{
title: t("vehicles.fields.plate_no"),
dataIndex: "plate_no",
key: "plate_no",
width: "8%",
ellipsis: true,
sorter: (a, b) => alphaSort(a.plate_no, b.plate_no),
sortOrder:
state.sortedInfo.columnKey === "plate_no" && state.sortedInfo.order,
render: (text, record) => {
return record.plate_no ? (
<span>{record.plate_no}</span>
) : (
t("general.labels.unknown")
);
}
},
{
title: t("jobs.fields.clm_no"),
dataIndex: "clm_no",
key: "clm_no",
width: "12%",
ellipsis: true,
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no),
sortOrder:
state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order,
render: (text, record) => {
return record.clm_no ? (
<span>{record.clm_no}</span>
) : (
t("general.labels.unknown")
);
}
}
];
const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
};
const filteredData =
state.search === ""
? data
: data.filter(
j =>
(j.est_number || "")
.toString()
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(j.ro_number || "")
.toString()
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(j.ownr_fn || "")
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(j.ownr_ln || "")
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(j.clm_no || "")
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(j.v_make_desc || "")
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(j.v_model_desc || "")
.toLowerCase()
.includes(state.search.toLowerCase()) ||
(j.plate_no || "")
.toLowerCase()
.includes(state.search.toLowerCase())
);
console.log("filteredData", filteredData);
return (
<Table
loading={loading}
title={() => (
<Input.Search
placeholder={t("general.labels.search")}
value={state.search}
onChange={e => setState({ ...state, search: e.target.value })}
/>
)}
size="small"
pagination={{ position: "top" }}
columns={columns.map(item => ({ ...item }))}
rowKey="id"
dataSource={filteredData}
onChange={handleTableChange}
rowSelection={{
onSelect: handleSelect,
type: "radio",
selectedRowKeys: [selectedJob]
}}
/>
);
}

View File

@@ -0,0 +1,38 @@
import { useQuery } from "@apollo/react-hooks";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
import ContractJobsComponent from "./contract-jobs.component";
import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop
});
export function ContractJobsContainer({ selectedJobState, bodyshop }) {
const { loading, error, data } = useQuery(QUERY_ALL_ACTIVE_JOBS, {
variables: {
statuses: bodyshop.md_ro_statuses.open_statuses || ["Open"]
}
});
const [selectedJob, setSelectedJob] = selectedJobState;
const handleSelect = record => {
setSelectedJob(record.id);
};
if (error) return <AlertComponent message={error.message} type="error" />;
return (
<div>
<ContractJobsComponent
handleSelect={handleSelect}
selectedJob={selectedJob}
loading={loading}
data={data ? data.jobs : []}
/>
</div>
);
}
export default connect(mapStateToProps, null)(ContractJobsContainer);

View File

@@ -0,0 +1,33 @@
import React, { useState } from "react";
import { Select } from "antd";
import { useTranslation } from "react-i18next";
const { Option } = Select;
const ContractStatusComponent = ({ value = "", onChange }) => {
const [option, setOption] = useState("contracts.status.new");
const { t } = useTranslation();
const onChangeSelect = newOption => {
setOption(newOption);
if (onChange) {
onChange(newOption);
}
};
return (
<Select
value={option}
style={{
width: 100
}}
onChange={onChangeSelect}
>
<Option value="contracts.status.new">{t("contracts.status.new")}</Option>
<Option value="contracts.status.out">{t("contracts.status.out")}</Option>
<Option value="contracts.status.returned">
{t("contracts.status.returned")}
</Option>
</Select>
);
};
export default ContractStatusComponent;

View File

@@ -1,15 +1,8 @@
import {
CalendarFilled,
CarFilled,
GlobalOutlined,
HomeFilled,
TeamOutlined,
FileAddFilled,
FileFilled
} from "@ant-design/icons";
import Icon, { CarFilled, FileAddFilled, FileFilled, GlobalOutlined, HomeFilled, TeamOutlined } from "@ant-design/icons";
import { Avatar, Col, Menu, Row } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { FaCalendarAlt, FaCarCrash } from "react-icons/fa";
import { Link } from "react-router-dom";
import UserImage from "../../assets/User.svg";
import ManageSignInButton from "../manage-sign-in-button/manage-sign-in-button.component";
@@ -100,10 +93,17 @@ export default ({
{t("menus.header.home")}
</Link>
</Menu.Item>
<Menu.SubMenu title={t("menus.header.jobs")}>
<Menu.SubMenu
title={
<span>
<Icon component={FaCarCrash} />
<span>{t("menus.header.jobs")}</span>
</span>
}
>
<Menu.Item key="schedule">
<Link to="/manage/schedule">
<CalendarFilled />
<Icon component={FaCalendarAlt} />
{t("menus.header.schedule")}
</Link>
</Menu.Item>
@@ -131,7 +131,14 @@ export default ({
</Menu.Item>
</Menu.SubMenu>
<Menu.SubMenu title={t("menus.header.courtesycars")}>
<Menu.SubMenu
title={
<span>
<CarFilled />
<span>{t("menus.header.courtesycars")}</span>
</span>
}
>
<Menu.Item key="courtesycarsall">
<Link to="/manage/courtesycars">
<CarFilled />