Merged in feature/IO-1828-Front-End-Package-Updates (pull request #1146)
Feature/IO-1828 Front End Package Updates
This commit is contained in:
@@ -16,6 +16,7 @@ const BillLineSearchSelect = (
|
||||
ref={ref}
|
||||
showSearch
|
||||
popupMatchSelectWidth={false}
|
||||
optionLabelProp={"name"}
|
||||
// optionFilterProp="line_desc"
|
||||
filterOption={(inputValue, option) => {
|
||||
return (
|
||||
@@ -57,6 +58,9 @@ const BillLineSearchSelect = (
|
||||
style={{
|
||||
...(item.removed ? { textDecoration: "line-through" } : {}),
|
||||
}}
|
||||
name={`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
|
||||
item.oem_partno ? ` - ${item.oem_partno}` : ""
|
||||
}${item.alt_partno ? ` (${item.alt_partno})` : ""}`.trim()}
|
||||
>
|
||||
<span>
|
||||
{`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
|
||||
|
||||
@@ -76,7 +76,7 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
const mileageOver = nextservicekm ? nextservicekm <= mileage : false;
|
||||
|
||||
const dueForService =
|
||||
nextservicedate && dayjs(nextservicedate).end('day').isSameOrBefore(dayjs());
|
||||
nextservicedate && dayjs(nextservicedate).endOf('day').isSameOrBefore(dayjs());
|
||||
|
||||
return (
|
||||
<Space>
|
||||
|
||||
@@ -222,7 +222,7 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
||||
{`${job.v_vin || t("general.labels.na")}`}
|
||||
</VehicleVinDisplay>
|
||||
{bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid ? (
|
||||
job.v_vin.length !== 17 ? (
|
||||
job.v_vin?.length !== 17 ? (
|
||||
<WarningFilled style={{ color: "tomato", marginLeft: ".3rem" }} />
|
||||
) : null
|
||||
) : null}
|
||||
|
||||
@@ -1,105 +1,105 @@
|
||||
import _ from "lodash/";
|
||||
import {groupBy} from "lodash";
|
||||
|
||||
const sortByParentId = (arr) => {
|
||||
// return arr.reduce((accumulator, currentValue) => {
|
||||
// //Find the parent item.
|
||||
// let item = accumulator.find((x) => x.id === currentValue.kanbanparent);
|
||||
// //Get index of praent item
|
||||
// let index = accumulator.indexOf(item);
|
||||
// return arr.reduce((accumulator, currentValue) => {
|
||||
// //Find the parent item.
|
||||
// let item = accumulator.find((x) => x.id === currentValue.kanbanparent);
|
||||
// //Get index of parent item
|
||||
// let index = accumulator.indexOf(item);
|
||||
|
||||
// index = index !== -1 ? index + 1 : 0;
|
||||
// accumulator.splice(index, 0, currentValue);
|
||||
// return accumulator;
|
||||
// }, []);
|
||||
// index = index !== -1 ? index + 1 : 0;
|
||||
// accumulator.splice(index, 0, currentValue);
|
||||
// return accumulator;
|
||||
// }, []);
|
||||
|
||||
var parentId = "-1";
|
||||
var sortedList = [];
|
||||
var byParentsIdsList = _.groupBy(arr, "kanbanparent"); // Create a new array with objects indexed by parentId
|
||||
//console.log("sortByParentId -> byParentsIdsList", byParentsIdsList);
|
||||
let parentId = "-1";
|
||||
const sortedList = [];
|
||||
const byParentsIdsList = groupBy(arr, "kanbanparent"); // Create a new array with objects indexed by parentId
|
||||
//console.log("sortByParentId -> byParentsIdsList", byParentsIdsList);
|
||||
|
||||
while (byParentsIdsList[parentId]) {
|
||||
sortedList.push(byParentsIdsList[parentId][0]);
|
||||
parentId = byParentsIdsList[parentId][0].id;
|
||||
}
|
||||
while (byParentsIdsList[parentId]) {
|
||||
sortedList.push(byParentsIdsList[parentId][0]);
|
||||
parentId = byParentsIdsList[parentId][0].id;
|
||||
}
|
||||
|
||||
if (byParentsIdsList["null"])
|
||||
byParentsIdsList["null"].map((i) => sortedList.push(i));
|
||||
if (byParentsIdsList["null"])
|
||||
byParentsIdsList["null"].map((i) => sortedList.push(i));
|
||||
|
||||
//Validate that the 2 arrays are of the same length and no children are missing.
|
||||
if (arr.length !== sortedList.length) {
|
||||
arr.map((origItem) => {
|
||||
if (!!!sortedList.find((s) => s.id === origItem.id)) {
|
||||
sortedList.push(origItem);
|
||||
console.log("DATA CONSISTENCY ERROR: ", origItem.ro_number);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
//Validate that the 2 arrays are of the same length and no children are missing.
|
||||
if (arr.length !== sortedList.length) {
|
||||
arr.map((origItem) => {
|
||||
if (!!!sortedList.find((s) => s.id === origItem.id)) {
|
||||
sortedList.push(origItem);
|
||||
console.log("DATA CONSISTENCY ERROR: ", origItem.ro_number);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
return sortedList;
|
||||
return sortedList;
|
||||
};
|
||||
|
||||
export const createBoardData = (AllStatuses, Jobs, filter) => {
|
||||
const { search, employeeId } = filter;
|
||||
console.log("==========GENERATING BOARD DATA=============");
|
||||
const boardLanes = {
|
||||
columns: AllStatuses.map((s) => {
|
||||
return {
|
||||
id: s,
|
||||
title: s,
|
||||
cards: [],
|
||||
};
|
||||
}),
|
||||
};
|
||||
const {search, employeeId} = filter;
|
||||
const boardLanes = {
|
||||
columns: AllStatuses.map((s) => {
|
||||
return {
|
||||
id: s,
|
||||
title: s,
|
||||
cards: [],
|
||||
};
|
||||
}),
|
||||
};
|
||||
|
||||
const filteredJobs =
|
||||
(search === "" || !search) && !employeeId
|
||||
? Jobs
|
||||
: Jobs.filter((j) => {
|
||||
let include = false;
|
||||
if (search && search !== "") {
|
||||
include = CheckSearch(search, j);
|
||||
}
|
||||
const filteredJobs =
|
||||
(search === "" || !search) && !employeeId
|
||||
? Jobs
|
||||
: Jobs.filter((j) => {
|
||||
let include = false;
|
||||
if (search && search !== "") {
|
||||
include = CheckSearch(search, j);
|
||||
}
|
||||
|
||||
if (!!employeeId) {
|
||||
include =
|
||||
include ||
|
||||
j.employee_body === employeeId ||
|
||||
j.employee_prep === employeeId ||
|
||||
j.employee_csr === employeeId ||
|
||||
j.employee_refinish === employeeId;
|
||||
}
|
||||
if (!!employeeId) {
|
||||
include =
|
||||
include ||
|
||||
j.employee_body === employeeId ||
|
||||
j.employee_prep === employeeId ||
|
||||
j.employee_csr === employeeId ||
|
||||
j.employee_refinish === employeeId;
|
||||
}
|
||||
|
||||
return include;
|
||||
});
|
||||
return include;
|
||||
});
|
||||
|
||||
const DataGroupedByStatus = _.groupBy(filteredJobs, (d) => d.status);
|
||||
const DataGroupedByStatus = groupBy(filteredJobs, (d) => d.status);
|
||||
|
||||
Object.keys(DataGroupedByStatus).map((statusGroupKey) => {
|
||||
try {
|
||||
boardLanes.columns.find((l) => l.id === statusGroupKey).cards =
|
||||
sortByParentId(DataGroupedByStatus[statusGroupKey]);
|
||||
} catch (error) {
|
||||
console.log("Error while creating board card", error);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
Object.keys(DataGroupedByStatus).map((statusGroupKey) => {
|
||||
try {
|
||||
const needle = boardLanes.columns.find((l) => l.id === statusGroupKey);
|
||||
if (!needle?.cards) return null;
|
||||
needle.cards = sortByParentId(DataGroupedByStatus[statusGroupKey]);
|
||||
} catch (error) {
|
||||
console.log("Error while creating board card", error);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
return boardLanes;
|
||||
return boardLanes;
|
||||
};
|
||||
|
||||
const CheckSearch = (search, job) => {
|
||||
return (
|
||||
(job.ro_number || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.ownr_fn || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.ownr_co_nm || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.ownr_ln || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.status || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.v_make_desc || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.v_model_desc || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.clm_no || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.plate_no || "").toLowerCase().includes(search.toLowerCase())
|
||||
);
|
||||
return (
|
||||
(job.ro_number || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.ownr_fn || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.ownr_co_nm || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.ownr_ln || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.status || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.v_make_desc || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.v_model_desc || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.clm_no || "").toLowerCase().includes(search.toLowerCase()) ||
|
||||
(job.plate_no || "").toLowerCase().includes(search.toLowerCase())
|
||||
);
|
||||
};
|
||||
|
||||
// export const updateBoardOnMove = (board, card, source, destination) => {
|
||||
|
||||
@@ -1,89 +1,92 @@
|
||||
import { HeartOutlined } from "@ant-design/icons";
|
||||
import { Select, Space, Tag } from "antd";
|
||||
import React, { forwardRef, useEffect, useState } from "react";
|
||||
import {HeartOutlined} from "@ant-design/icons";
|
||||
import {Select, Space, Tag} from "antd";
|
||||
import React, {forwardRef, useEffect, useState} from "react";
|
||||
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
||||
const { Option } = Select;
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
//To be used as a form element only.
|
||||
|
||||
const VendorSearchSelect = (
|
||||
{ value, onChange, options, onSelect, disabled, preferredMake, showPhone },
|
||||
ref
|
||||
{value, onChange, options, onSelect, disabled, preferredMake, showPhone},
|
||||
ref
|
||||
) => {
|
||||
const [option, setOption] = useState(value);
|
||||
const [option, setOption] = useState(value);
|
||||
|
||||
useEffect(() => {
|
||||
if (value !== option && onChange) {
|
||||
onChange(option);
|
||||
}
|
||||
}, [value, option, onChange]);
|
||||
useEffect(() => {
|
||||
if (value !== option && onChange) {
|
||||
onChange(option);
|
||||
}
|
||||
}, [value, option, onChange]);
|
||||
|
||||
const favorites =
|
||||
preferredMake && options
|
||||
? options.filter(
|
||||
(o) =>
|
||||
o.favorite.filter(
|
||||
(f) => f.toLowerCase() === preferredMake.toLowerCase()
|
||||
).length > 0
|
||||
)
|
||||
: [];
|
||||
const favorites =
|
||||
preferredMake && options
|
||||
? options.filter(
|
||||
(o) =>
|
||||
o.favorite.filter(
|
||||
(f) => f.toLowerCase() === preferredMake.toLowerCase()
|
||||
).length > 0
|
||||
)
|
||||
: [];
|
||||
|
||||
return (
|
||||
<Select
|
||||
ref={ref}
|
||||
showSearch
|
||||
value={option}
|
||||
style={{
|
||||
width: "100%",
|
||||
}}
|
||||
popupMatchSelectWidth={false}
|
||||
onChange={setOption}
|
||||
optionFilterProp="name"
|
||||
onSelect={onSelect}
|
||||
disabled={disabled || false}
|
||||
>
|
||||
{favorites
|
||||
? favorites.map((o) => (
|
||||
<Option
|
||||
key={`favorite-${o.id}`}
|
||||
value={o.id}
|
||||
name={o.name}
|
||||
discount={o.discount}
|
||||
>
|
||||
<div className="imex-flex-row">
|
||||
<div style={{ flex: 1 }}>{o.name}</div>
|
||||
<Space style={{ marginLeft: "1rem" }}>
|
||||
<HeartOutlined style={{ color: "red" }} />
|
||||
{o.phone && showPhone && (
|
||||
<PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>
|
||||
)}
|
||||
{o.discount && o.discount !== 0 ? (
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
{options
|
||||
? options.map((o) => (
|
||||
<Option key={o.id} value={o.id} name={o.name} discount={o.discount}>
|
||||
<div className="imex-flex-row" style={{ width: "100%" }}>
|
||||
<div style={{ flex: 1 }}>{o.name}</div>
|
||||
return (
|
||||
<Select
|
||||
ref={ref}
|
||||
showSearch
|
||||
value={option}
|
||||
style={{
|
||||
width: "100%",
|
||||
}}
|
||||
popupMatchSelectWidth={false}
|
||||
onChange={setOption}
|
||||
optionFilterProp="name"
|
||||
onSelect={onSelect}
|
||||
disabled={disabled || false}
|
||||
optionLabelProp={"name"}
|
||||
>
|
||||
{favorites
|
||||
? favorites.map((o) => (
|
||||
<Option
|
||||
key={`favorite-${o.id}`}
|
||||
value={o.id}
|
||||
name={o.name}
|
||||
discount={o.discount}
|
||||
>
|
||||
<div className="imex-flex-row">
|
||||
<div style={{flex: 1}}>{o.name}</div>
|
||||
<Space style={{marginLeft: "1rem"}}>
|
||||
<HeartOutlined style={{color: "red"}}/>
|
||||
{o.phone && showPhone && (
|
||||
<PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>
|
||||
)}
|
||||
{o.discount && o.discount !== 0 ? (
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
{options
|
||||
? options.map((o) => (
|
||||
<Option key={o.id} value={o.id} name={o.name} discount={o.discount}>
|
||||
<div className="imex-flex-row" style={{width: "100%"}}>
|
||||
<div style={{flex: 1}}>{o.name}</div>
|
||||
|
||||
<Space style={{ marginLeft: "1rem" }}>
|
||||
{o.phone && showPhone && (
|
||||
<PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>
|
||||
)}
|
||||
{o.discount && o.discount !== 0 ? (
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
</Select>
|
||||
);
|
||||
<Space style={{marginLeft: "1rem"}}>
|
||||
{o.phone && showPhone && (
|
||||
<PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>
|
||||
)}
|
||||
{o.discount && o.discount !== 0 ? (
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
</Option>
|
||||
|
||||
))
|
||||
: null}
|
||||
</Select>
|
||||
);
|
||||
};
|
||||
export default forwardRef(VendorSearchSelect);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useMutation, useQuery } from "@apollo/client";
|
||||
import { Form, notification } from "antd";
|
||||
import dayjs from "dayjs";
|
||||
import dayjs from "../../utils/day";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
Reference in New Issue
Block a user