Updated groupings modal and final 1.3.0 release.

This commit is contained in:
Patrick Fic
2024-08-16 08:55:38 -07:00
parent 0b2b741123
commit 1895adb9ea
8 changed files with 787 additions and 664 deletions

View File

@@ -161,7 +161,7 @@
},
"1.3.0": {
"title": "Release Notes for 1.3.0",
"date": "08/15/2024",
"notes": "Improvements\n* Additional SUV models added."
"date": "08/16/2024",
"notes": "New Features\n* Added support for new MPI rules. The rules will apply to all jobs with an R4P date on or after September 1, 2024. If a job R4P date is changed across this date, the job will need to be reimported to have correct scoring."
}
}

View File

@@ -3,7 +3,7 @@
"productName": "ImEX RPS",
"author": "ImEX Systems Inc. <support@thinkimex.com>",
"description": "ImEX RPS",
"version": "1.3.0-alpha",
"version": "1.3.0",
"main": "electron/main.js",
"homepage": "./",
"dependencies": {

View File

@@ -52,18 +52,18 @@ export function JobGroupMolecule({ bodyshop, jobId, group, job }) {
onClick={handleMenuClick}
disabled
items={[
{ label: "Group 1", value: "Group 1", },
{ label: "Group 2", value: "Group 2", },
{ label: "Group 3", value: "Group 3", },
{ label: "Group 4", value: "Group 4", },
{ label: "Group 5", value: "Group 5", },
{ label: "Group 6", value: "Group 6", },
{ label: "Group 7", value: "Group 7", },
{ label: "Group 8", value: "Group 8", },
{ label: "Group 9", value: "Group 9", },
{ label: "Group 10", value: "Group 10", },
{ label: "Group 11", value: "Group 11", },
{ label: "Group 12", value: "Group 12", }
{ label: "Group 1", value: "Group 1" },
{ label: "Group 2", value: "Group 2" },
{ label: "Group 3", value: "Group 3" },
{ label: "Group 4", value: "Group 4" },
{ label: "Group 5", value: "Group 5" },
{ label: "Group 6", value: "Group 6" },
{ label: "Group 7", value: "Group 7" },
{ label: "Group 8", value: "Group 8" },
{ label: "Group 9", value: "Group 9" },
{ label: "Group 10", value: "Group 10" },
{ label: "Group 11", value: "Group 11" },
{ label: "Group 12", value: "Group 12" }
]}
></Menu>
) : (
@@ -72,7 +72,7 @@ export function JobGroupMolecule({ bodyshop, jobId, group, job }) {
return (
<Space align="top">
<Dropdown overlay={menu} trigger={["click"]}>
<Dropdown overlay={menu} disabled={RulesetToApply === "V3"} trigger={["click"]}>
<a href=" #" onClick={(e) => e.preventDefault()}>
{group}
<DownOutlined style={{ marginLeft: ".2rem" }} />
@@ -89,7 +89,7 @@ export function JobGroupMolecule({ bodyshop, jobId, group, job }) {
<GroupVerifySwitch job={job} loading={loading} loadingCallback={setLoading} />
</div>
)}
<JobsGroupModalMolecule />
<JobsGroupModalMolecule job={job} />
{loading && <LoadingOutlined />}
</Space>
);

View File

@@ -1,16 +1,16 @@
import { Alert, Descriptions, Skeleton, Tooltip, Space } from "antd";
import { WarningOutlined } from "@ant-design/icons";
import { PageHeader } from "@ant-design/pro-layout";
import { Alert, Descriptions, Skeleton, Space, Tooltip } from "antd";
import React from "react";
import { DateFormat, WhichRulesetToApply } from "../../../util/constants";
import dayjs from "../../../util/day.js";
import CurrencyFormatterAtom from "../../atoms/currency-formatter/currency-formatter.atom";
import DeleteJobAtom from "../../atoms/delete-job/delete-job.atom";
import ErrorResultAtom from "../../atoms/error-result/error-result.atom";
import TimeAgoFormatter from "../../atoms/time-ago-formatter/time-ago-formatter.atom";
import VehicleGroupAlertAtom from "../../atoms/vehicle-group-alert/vehicle-group-alert.atom";
import CloseDateDisplayMolecule from "../close-date-display/close-date-display.molecule";
import JobGroupMolecule from "../job-group/job-group.molecule";
import DeleteJobAtom from "../../atoms/delete-job/delete-job.atom";
import VehicleGroupAlertAtom from "../../atoms/vehicle-group-alert/vehicle-group-alert.atom";
import { DateFormat } from "../../../util/constants";
import dayjs from "../../../util/day.js";
import { PageHeader } from "@ant-design/pro-layout";
export default function JobsDetailDescriptionMolecule({ loading, job }) {
if (loading) return <Skeleton active />;
@@ -19,7 +19,7 @@ export default function JobsDetailDescriptionMolecule({ loading, job }) {
return (
<ErrorResultAtom title="Error displaying job header data." errorMessage="It looks like this job doesn't exist." />
);
const ruleSetToApply = WhichRulesetToApply(job.close_date);
return (
<div>
<PageHeader
@@ -42,7 +42,7 @@ export default function JobsDetailDescriptionMolecule({ loading, job }) {
<DeleteJobAtom key="delete" jobId={job.id} />
]}
>
<Descriptions column={{ xxl: 5, xl: 4, lg: 3, md: 3, sm: 2, xs: 1 }}>
<Descriptions column={{ xxl: 5, xl: 4, lg: 3, md: 2, sm: 1, xs: 1 }}>
<Descriptions.Item label="Owner">{`${job.ownr_fn} ${job.ownr_ln}`}</Descriptions.Item>
<Descriptions.Item label="Vehicle">
<VehicleGroupAlertAtom job={job} />
@@ -73,9 +73,13 @@ export default function JobsDetailDescriptionMolecule({ loading, job }) {
{job.loss_date ? dayjs(job.loss_date).format(DateFormat) : "No Loss Date"}
</Descriptions.Item>
<Descriptions.Item label="Mileage">
<Space>
<Space size="small">
{job.v_mileage}
{job.v_mileage < 20000 && <WarningOutlined style={{ color: "tomato" }} />}
{ruleSetToApply === "V3" && job.v_mileage < 20000 && (
<Tooltip title="Vehicle is under 20,000 KMs. No expected savings.">
<WarningOutlined style={{ color: "seagreen" }} />
</Tooltip>
)}
</Space>
</Descriptions.Item>
</Descriptions>

View File

@@ -1,6 +1,10 @@
import { Modal, List, Card, Input } from "antd";
import { Modal, List, Card, Input, Row, Col, Table } from "antd";
import _ from "lodash";
import React, { useState } from "react";
import { InfoCircleFilled } from "@ant-design/icons";
import { FakedTargetsForV3WithMake } from "../../../ipc/ipc-estimate-utils";
import { WhichRulesetToApply } from "../../../util/constants";
import { alphaSort } from "../../../util/sorters";
const data = [
{
@@ -8,279 +12,284 @@ const data = [
list: [
{
make: "ALFA ROMEO",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "AUDI",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "GENESIS*",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "JAGUAR",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "LAND ROVER",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "LINCOLN",
type: "Truck",
type: "Truck"
},
{
make: "MERCEDES BENZ",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "MERCEDES BENZ",
type: "Cargo Van",
type: "Cargo Van"
},
{
make: "PORSCHE",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "RAM",
type: "Cargo Van",
type: "Cargo Van"
},
{
make: "SMART",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "TESLA",
type: "Car, SUV, or Passenger Van",
},
],
type: "Car, SUV, or Passenger Van"
}
]
},
{
group: "Group 2",
list: [
{
make: "BMW",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "LEXUS",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "MINI",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "NISSAN",
type: "Cargo Van",
type: "Cargo Van"
},
{
make: "SAAB",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "SUBARU",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "VOLVO",
type: "Car, SUV, or Passenger Van",
},
],
type: "Car, SUV, or Passenger Van"
}
]
},
{
group: "Group 3",
list: [
{
make: "DODGE",
type: "Cargo Van",
type: "Cargo Van"
},
{
make: "FIAT",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "FORD",
type: "Cargo Van",
type: "Cargo Van"
},
{
make: "FORD",
type: "Truck",
type: "Truck"
},
{
make: "HUMMER",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "HYUNDAI*",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "INFINITI",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "JEEP",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "JEEP",
type: "Truck",
type: "Truck"
},
{
make: "KIA",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "LINCOLN",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "MAZDA",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "MAZDA",
type: "Truck",
type: "Truck"
},
{
make: "NISSAN",
type: "Truck",
type: "Truck"
},
{
make: "SCION",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "TOYOTA",
type: "Truck",
type: "Truck"
},
{
make: "VOLKSWAGEN",
type: "Car, SUV, or Passenger Van",
},
],
type: "Car, SUV, or Passenger Van"
}
]
},
{
group: "Group 4",
list: [
{
make: "ACURA",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "BUICK",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "CADILLAC",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "CHEVROLET",
type: "Truck",
type: "Truck"
},
{
make: "DODGE",
type: "Truck",
type: "Truck"
},
{
make: "FORD",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "GMC",
type: "Truck",
type: "Truck"
},
{
make: "HONDA",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "HONDA",
type: "Truck",
type: "Truck"
},
{
make: "MITSUBISHI",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "NISSAN",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "PLYMOUTH",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "RAM",
type: "Truck",
type: "Truck"
},
{
make: "TOYOTA",
type: "Car, SUV, or Passenger Van",
},
],
type: "Car, SUV, or Passenger Van"
}
]
},
{
group: "Group 5",
list: [
{
make: "CHEVROLET",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "CHRYSLER",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "DODGE",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "GMC",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "SUZUKI",
type: "Car, SUV, or Passenger Van",
},
],
type: "Car, SUV, or Passenger Van"
}
]
},
{
group: "Group 6",
list: [
{
make: "CHEVROLET",
type: "Cargo Van",
type: "Cargo Van"
},
{
make: "GMC",
type: "Cargo Van",
type: "Cargo Van"
},
{
make: "MERCURY",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "OLDSMOBILE",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "PONTIAC",
type: "Car, SUV, or Passenger Van",
type: "Car, SUV, or Passenger Van"
},
{
make: "SATURN",
type: "Car, SUV, or Passenger Van",
},
],
},
type: "Car, SUV, or Passenger Van"
}
]
}
];
export default function JobsGroupModalMolecule() {
export default function JobsGroupModalMolecule({ job }) {
const RulesetToApply = WhichRulesetToApply(job.close_date);
return RulesetToApply === "V3" ? <JobsGroupV3ModalMolecule /> : <JobsGroupPreV3ModalMolecule />;
}
export function JobsGroupPreV3ModalMolecule() {
const [visible, setVisible] = useState(false);
const [search, setSearch] = useState("");
return (
@@ -309,7 +318,7 @@ export default function JobsGroupModalMolecule() {
style={{
//backgroundColor: "tomato",
width: "100%",
borderCollapse: "collapse",
borderCollapse: "collapse"
}}
>
<thead>
@@ -325,12 +334,7 @@ export default function JobsGroupModalMolecule() {
borderBottom: "1px solid #dddddd",
backgroundColor:
search &&
item.make
.toLowerCase()
.includes(search.toLowerCase())
? "yellow"
: "",
search && item.make.toLowerCase().includes(search.toLowerCase()) ? "yellow" : ""
}}
key={idx}
>
@@ -344,9 +348,85 @@ export default function JobsGroupModalMolecule() {
)}
/>
<div>
This grouping information is provided for reference only and is not
guaranteed to be correct. Please confirm with grouping guidelines
provided by MPI.
This grouping information is provided for reference only and is not guaranteed to be correct. Please confirm
with grouping guidelines provided by MPI.
</div>
</div>
</Modal>
<InfoCircleFilled onClick={() => setVisible(true)} />
</div>
);
}
const v3DataSource = _.sortBy(
FakedTargetsForV3WithMake.filter((f) => (f.name = "V3")),
"make"
);
export function JobsGroupV3ModalMolecule() {
const [visible, setVisible] = useState(false);
const [search, setSearch] = useState("");
const v3DataSourceFiltered =
search === null || search.trim() === ""
? v3DataSource
: v3DataSource.filter((i) => i.make.toLowerCase().includes(search.toLowerCase()));
return (
<div style={{ margin: ".2rem" }}>
<Modal
open={visible}
onCancel={() => setVisible(false)}
onOk={() => setVisible(false)}
width="90%"
title="MPI Group Guidelines"
>
<div>
<Input.Search
placeholder="Search for Make"
value={search}
onChange={(e) => setSearch(e.target.value)}
style={{ marginBottom: ".5rem" }}
/>
<Table
dataSource={v3DataSourceFiltered}
pagination={{ pageSize: 20 }}
columns={[
{
title: "Make",
dataIndex: "make",
key: "make",
sorter: (a, b) => alphaSort(a.make - b.make),
filters: _.uniq(v3DataSource.map((i) => i.make)).map((i) => ({ text: i, value: i })),
filterSearch: true,
onFilter: (value, record) => record.make.startsWith(value)
},
{
title: "Type",
dataIndex: "desc",
key: "desc"
},
{
title: "Age Group",
dataIndex: "ageDesc",
key: "ageDesc"
},
{
title: "Target",
dataIndex: "target",
key: "target",
render: (text, record) => `${(record.target * 100).toFixed(1)}%`
}
]}
/>
<div>
If a vehicle make, type and age combination is not listed, it is subject to a default savings target of
2.3%.
</div>
<div>
This grouping information is provided for reference only and is not guaranteed to be correct. Please confirm
with grouping guidelines provided by MPI.
</div>
</div>
</Modal>

View File

@@ -7,6 +7,7 @@ import { createStructuredSelector } from "reselect";
import { selectSelectedJobTargetPc } from "../../../redux/application/application.selectors";
import { CalculateJobRpsDollars, CalculateJobRpsPc } from "../../../util/CalculateJobRps";
import ErrorResultAtom from "../../atoms/error-result/error-result.atom";
import { WhichRulesetToApply } from "../../../util/constants";
const mapStateToProps = createStructuredSelector({
selectedJobTargetPc: selectSelectedJobTargetPc
@@ -30,11 +31,13 @@ export function JobsTargetsStatsMolecule({ loading, job, selectedJobTargetPc })
if (loading) return <Skeleton active />;
if (!job)
return (
<ErrorResultAtom title="Error displaying job totals." errorMessage="It looks like this job doesn't exist." />
<ErrorResultAtom title="Error displaying job." errorMessage="It looks like this job doesn't exist." />
);
const targetRpsDollars = dbPriceSum.percentage(selectedJobTargetPc * 100);
const dollarDiff = jobRpsDollars.subtract(targetRpsDollars);
const ruleSetToApply = WhichRulesetToApply(job.close_date);
return (
<div
style={{
@@ -50,11 +53,11 @@ export function JobsTargetsStatsMolecule({ loading, job, selectedJobTargetPc })
title="Target RPS %"
value={(selectedJobTargetPc * 100).toFixed(1)}
suffix={
<Space>
%{" "}
{job.v_mileage < 20000 && (
<Tooltip title="Vehicle is under 20,000 KMs. No expected savings.">
<WarningOutlined style={{ color: "tomato" }} />
<Space size="small">
%
{ruleSetToApply === "V3" && job.v_mileage < 20000 && (
<Tooltip title="Vehicle is under 20,000 KMs. No expected savings.">
<WarningOutlined style={{ color: "seagreen" }} />
</Tooltip>
)}
</Space>

View File

@@ -113,7 +113,7 @@ export function ReportingJobsListMolecule({ scoreCard, reportingLoading, reportD
{`${record.jobRpsDollars.toFormat()} / ${record.expectedRpsDollars.toFormat()}`}
{record.v_mileage < 20000 && (
<Tooltip title="Vehicle is under 20,000 KMs. No expected savings.">
<WarningOutlined style={{ color: "tomato" }} />
<WarningOutlined style={{ color: "seagreen" }} />
</Tooltip>
)}
</Space>

File diff suppressed because it is too large Load Diff