Added predefined shop labor rates BOD-395

This commit is contained in:
Patrick Fic
2020-09-02 09:17:00 -07:00
parent 1126665dfc
commit 2202683876
17 changed files with 881 additions and 13 deletions

View File

@@ -0,0 +1,45 @@
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { DownOutlined } from "@ant-design/icons";
import { Dropdown, Menu } from "antd";
import { useTranslation } from "react-i18next";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
export function JobsDetailRatesChangeButton({ form, bodyshop }) {
const { t } = useTranslation();
const handleClick = ({ item, key, keyPath }) => {
const rate = item.props.value;
console.log("handleClick -> rate", rate);
form.setFieldsValue(rate);
};
const menu = (
<Menu onClick={handleClick}>
{bodyshop.md_labor_rates.map((rate, idx) => (
<Menu.Item value={rate} key={idx}>
{rate.label}
</Menu.Item>
))}
</Menu>
);
return (
<Dropdown overlay={menu}>
<a
className="ant-dropdown-link"
href=" #"
onClick={(e) => e.preventDefault()}
>
{t("jobs.actions.changelaborrate")} <DownOutlined />
</a>
</Dropdown>
);
}
export default connect(mapStateToProps, null)(JobsDetailRatesChangeButton);

View File

@@ -1,17 +1,11 @@
import { Form, Select } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import FormRow from "../layout-form-row/layout-form-row.component";
import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
export function JobsDetailRates({ job, bodyshop }) {
export default function JobsDetailRates({ job, form }) {
const { t } = useTranslation();
return (
@@ -57,6 +51,7 @@ export function JobsDetailRates({ job, bodyshop }) {
<CurrencyInput />
</Form.Item>
</FormRow>
<JobsDetailRatesChangeButton form={form} />
<FormRow header={t("jobs.forms.laborrates")}>
<Form.Item label={t("jobs.fields.rate_laa")} name="rate_laa">
<CurrencyInput />
@@ -131,4 +126,3 @@ export function JobsDetailRates({ job, bodyshop }) {
</div>
);
}
export default connect(mapStateToProps, null)(JobsDetailRates);

View File

@@ -20,6 +20,7 @@ import ShopInfoResponsibilityCenterComponent from "./shop-info.responsibilitycen
import ShopInfoROStatusComponent from "./shop-info.rostatus.component";
import ShopInfoSchedulingComponent from "./shop-info.scheduling.component";
import ShopInfoSpeedPrint from "./shop-info.speedprint.component";
import ShopInfoLaborRates from "./shop-info.laborrates.component";
export default function ShopInfoComponent({ form, saveLoading }) {
const { t } = useTranslation();
@@ -499,6 +500,12 @@ export default function ShopInfoComponent({ form, saveLoading }) {
<Collapse.Panel key="intake" header={t("bodyshop.labels.intake")}>
<ShopInfoIntakeChecklistComponent form={form} />
</Collapse.Panel>
<Collapse.Panel
key="laborrates"
header={t("bodyshop.labels.laborrates")}
>
<ShopInfoLaborRates form={form} />
</Collapse.Panel>
</Collapse>
</div>
);

View File

@@ -0,0 +1,337 @@
import { DeleteFilled } from "@ant-design/icons";
import { Button, Form, Input } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
export default function ShopInfoLaborRates({ form }) {
const { t } = useTranslation();
return (
<div>
<Form.List name={["md_labor_rates"]}>
{(fields, { add, remove, move }) => {
return (
<div>
{fields.map((field, index) => (
<Form.Item key={field.key}>
<LayoutFormRow>
<Form.Item
label={t("jobs.fields.labor_rate_desc")}
key={`${index}rate_label`}
name={[field.name, "rate_label"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_laa")}
key={`${index}rate_laa`}
name={[field.name, "rate_laa"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lab")}
key={`${index}rate_lab`}
name={[field.name, "rate_lab"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lad")}
key={`${index}rate_lad`}
name={[field.name, "rate_lad"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lae")}
key={`${index}rate_lae`}
name={[field.name, "rate_lae"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_laf")}
key={`${index}rate_laf`}
name={[field.name, "rate_laf"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lag")}
key={`${index}rate_lag`}
name={[field.name, "rate_lag"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lam")}
key={`${index}rate_lam`}
name={[field.name, "rate_lam"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lar")}
key={`${index}rate_lar`}
name={[field.name, "rate_lar"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_las")}
key={`${index}rate_las`}
name={[field.name, "rate_las"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_la1")}
key={`${index}rate_la1`}
name={[field.name, "rate_la1"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_la2")}
key={`${index}rate_la2`}
name={[field.name, "rate_la2"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_la3")}
key={`${index}rate_la3`}
name={[field.name, "rate_la3"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_la4")}
key={`${index}rate_la4`}
name={[field.name, "rate_la4"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_mash")}
key={`${index}rate_mash`}
name={[field.name, "rate_mash"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_mapa")}
key={`${index}rate_mapa`}
name={[field.name, "rate_mapa"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_ma2s")}
key={`${index}rate_ma2s`}
name={[field.name, "rate_ma2s"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_ma3s")}
key={`${index}rate_ma3s`}
name={[field.name, "rate_ma3s"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_mabl")}
key={`${index}rate_mabl`}
name={[field.name, "rate_mabl"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_macs")}
key={`${index}rate_macs`}
name={[field.name, "rate_macs"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_matd")}
key={`${index}rate_matd`}
name={[field.name, "rate_matd"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_mahw")}
key={`${index}rate_mahw`}
name={[field.name, "rate_mahw"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput />
</Form.Item>
<DeleteFilled
onClick={() => {
remove(field.name);
}}
/>
<FormListMoveArrows
move={move}
index={index}
total={fields.rate_length}
/>
</LayoutFormRow>
</Form.Item>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
style={{ width: "100%" }}
>
{t("bodyshop.actions.newlaborrate")}
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
</div>
);
}

View File

@@ -58,6 +58,7 @@ export const QUERY_BODYSHOP = gql`
md_ins_cos
md_categories
enforce_class
md_labor_rates
employees {
id
first_name
@@ -122,6 +123,7 @@ export const UPDATE_SHOP = gql`
md_ins_cos
md_categories
enforce_class
md_labor_rates
employees {
id
first_name

View File

@@ -197,7 +197,7 @@ export function JobsDetailPage({
}
key="rates"
>
<JobsDetailRates job={job} />
<JobsDetailRates job={job} form={form} />
</Tabs.TabPane>
<Tabs.TabPane
tab={

View File

@@ -79,6 +79,7 @@
"addpartslocation": "Add Parts Location",
"addspeedprint": "Add Speed Print",
"addtemplate": "Add Template",
"newlaborrate": "New Labor Rate",
"newstatus": "Add Status"
},
"errors": {
@@ -260,6 +261,7 @@
"customtemplates": "Custom Templates",
"intake": "Job Intake",
"jobstatuses": "Job Statuses",
"laborrates": "Labor Rates",
"notemplatesavailable": "No templates available to add.",
"orderstatuses": "Order Statuses",
"rbac": "Role Based Access Control",
@@ -737,6 +739,7 @@
"addtoscoreboard": "Add to Scoreboard",
"allocate": "Allocate",
"autoallocate": "Auto Allocate",
"changelaborrate": "Change Labor Rate",
"changestatus": "Change Status",
"convert": "Convert",
"export": "Export",
@@ -844,8 +847,14 @@
"lau": "LAU",
"loss_date": "Loss Date",
"loss_desc": "Loss Description",
"ma2s": "2 Stage Paint",
"ma3s": "3 Stage Pain",
"mabl": "MABL?",
"macs": "MACS?",
"mahw": "Hazardous Waste",
"mapa": "Paint Materials",
"mash": "Shop Materials",
"matd": "Tire Disposal",
"other_amount_payable": "Other Amount Payable",
"owner": "Owner",
"owner_owing": "Cust. Owes",
@@ -877,7 +886,7 @@
"rate_lam": "Mechanical",
"rate_lar": "Refinish",
"rate_las": "Sublet",
"rate_lau": "Aluminum",
"rate_lau": "Aluminum (USER)",
"rate_ma2s": "2 Stage Paint",
"rate_ma3s": "3 Stage Paint",
"rate_mabl": "MABL??",

View File

@@ -79,6 +79,7 @@
"addpartslocation": "",
"addspeedprint": "",
"addtemplate": "",
"newlaborrate": "",
"newstatus": ""
},
"errors": {
@@ -260,6 +261,7 @@
"customtemplates": "",
"intake": "",
"jobstatuses": "",
"laborrates": "",
"notemplatesavailable": "",
"orderstatuses": "",
"rbac": "",
@@ -737,6 +739,7 @@
"addtoscoreboard": "",
"allocate": "",
"autoallocate": "",
"changelaborrate": "",
"changestatus": "Cambiar Estado",
"convert": "Convertir",
"export": "",
@@ -844,8 +847,14 @@
"lau": "",
"loss_date": "Fecha de pérdida",
"loss_desc": "",
"ma2s": "",
"ma3s": "",
"mabl": "",
"macs": "",
"mahw": "",
"mapa": "",
"mash": "",
"matd": "",
"other_amount_payable": "Otra cantidad a pagar",
"owner": "Propietario",
"owner_owing": "Cust. Debe",
@@ -877,7 +886,7 @@
"rate_lam": "Tasa mecánica",
"rate_lar": "Tasa de acabado",
"rate_las": "Tasa de subarriendo",
"rate_lau": "Tasa de aluminio",
"rate_lau": "Tasa de aluminio (USER)",
"rate_ma2s": "Velocidad de pintura de 2 etapas",
"rate_ma3s": "Tasa de pintura de 3 etapas",
"rate_mabl": "MABL ??",

View File

@@ -79,6 +79,7 @@
"addpartslocation": "",
"addspeedprint": "",
"addtemplate": "",
"newlaborrate": "",
"newstatus": ""
},
"errors": {
@@ -260,6 +261,7 @@
"customtemplates": "",
"intake": "",
"jobstatuses": "",
"laborrates": "",
"notemplatesavailable": "",
"orderstatuses": "",
"rbac": "",
@@ -737,6 +739,7 @@
"addtoscoreboard": "",
"allocate": "",
"autoallocate": "",
"changelaborrate": "",
"changestatus": "Changer le statut",
"convert": "Convertir",
"export": "",
@@ -844,8 +847,14 @@
"lau": "",
"loss_date": "Date de perte",
"loss_desc": "",
"ma2s": "",
"ma3s": "",
"mabl": "",
"macs": "",
"mahw": "",
"mapa": "",
"mash": "",
"matd": "",
"other_amount_payable": "Autre montant à payer",
"owner": "Propriétaire",
"owner_owing": "Cust. Owes",
@@ -877,7 +886,7 @@
"rate_lam": "Taux mécanique",
"rate_lar": "Taux de finition",
"rate_las": "Taux de sous-location",
"rate_lau": "Taux d'aluminium",
"rate_lau": "Taux d'aluminium (USER)",
"rate_ma2s": "Taux de peinture en 2 étapes",
"rate_ma3s": "Taux de peinture en 3 étapes",
"rate_mabl": "MABL ??",