feature/IO-3497-Ant-Design-v5-to-v6 - Signed off Files (Checkpoint)

This commit is contained in:
Dave
2026-01-12 12:06:47 -05:00
parent c119a66f27
commit dd3eda12ce
153 changed files with 4819 additions and 4524 deletions

View File

@@ -4,27 +4,27 @@ import AlertComponent from "./alert.component";
describe("AlertComponent", () => { describe("AlertComponent", () => {
it("renders with default props", () => { it("renders with default props", () => {
render(<AlertComponent message="Default Alert" />); render(<AlertComponent title="Default Alert" />);
expect(screen.getByText("Default Alert")).toBeInTheDocument(); expect(screen.getByText("Default Alert")).toBeInTheDocument();
expect(screen.getByRole("alert")).toHaveClass("ant-alert"); expect(screen.getByRole("alert")).toHaveClass("ant-alert");
}); });
it("applies type prop correctly", () => { it("applies type prop correctly", () => {
render(<AlertComponent message="Success Alert" type="success" />); render(<AlertComponent title="Success Alert" type="success" />);
const alert = screen.getByRole("alert"); const alert = screen.getByRole("alert");
expect(screen.getByText("Success Alert")).toBeInTheDocument(); expect(screen.getByText("Success Alert")).toBeInTheDocument();
expect(alert).toHaveClass("ant-alert-success"); expect(alert).toHaveClass("ant-alert-success");
}); });
it("displays description when provided", () => { it("displays description when provided", () => {
render(<AlertComponent message="Error Alert" description="Something went wrong" type="error" />); render(<AlertComponent title="Error Alert" description="Something went wrong" type="error" />);
expect(screen.getByText("Error Alert")).toBeInTheDocument(); expect(screen.getByText("Error Alert")).toBeInTheDocument();
expect(screen.getByText("Something went wrong")).toBeInTheDocument(); expect(screen.getByText("Something went wrong")).toBeInTheDocument();
expect(screen.getByRole("alert")).toHaveClass("ant-alert-error"); expect(screen.getByRole("alert")).toHaveClass("ant-alert-error");
}); });
it("is closable and shows icon when props are set", () => { it("is closable and shows icon when props are set", () => {
render(<AlertComponent message="Warning Alert" type="warning" showIcon closable />); render(<AlertComponent title="Warning Alert" type="warning" showIcon closable />);
expect(screen.getByText("Warning Alert")).toBeInTheDocument(); expect(screen.getByText("Warning Alert")).toBeInTheDocument();
expect(screen.getByRole("button", { name: /close/i })).toBeInTheDocument(); // Close button expect(screen.getByRole("button", { name: /close/i })).toBeInTheDocument(); // Close button
}); });

View File

@@ -17,7 +17,7 @@ export default function AuditTrailListContainer({ recordId }) {
return ( return (
<div> <div>
{error ? ( {error ? (
<AlertComponent type="error" message={error.message} /> <AlertComponent type="error" title={error.message} />
) : ( ) : (
<Row gutter={[16, 16]}> <Row gutter={[16, 16]}>
<Card> <Card>

View File

@@ -148,7 +148,7 @@ export function BillDetailEditcontainer({ insertAuditTrail, bodyshop }) {
setUpdateLoading(false); setUpdateLoading(false);
}; };
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
if (!search.billid) return <></>; //<div>{t("bills.labels.noneselected")}</div>; if (!search.billid) return <></>; //<div>{t("bills.labels.noneselected")}</div>;
const exported = data?.bills_by_pk && data.bills_by_pk.exported; const exported = data?.bills_by_pk && data.bills_by_pk.exported;

View File

@@ -421,7 +421,7 @@ export function BillFormComponent({
/> />
</Space> </Space>
{form.getFieldValue("is_credit_memo") ? ( {form.getFieldValue("is_credit_memo") ? (
<AlertComponent type="warning" message={t("bills.labels.enteringcreditmemo")} /> <AlertComponent type="warning" title={t("bills.labels.enteringcreditmemo")} />
) : null} ) : null}
</div> </div>
); );

View File

@@ -67,7 +67,7 @@ export default function BillsVendorsList() {
setState({ ...state, search: e.target.value }); setState({ ...state, search: e.target.value });
}; };
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
const dataSource = state.search const dataSource = state.search
? data.vendors.filter( ? data.vendors.filter(

View File

@@ -51,10 +51,11 @@ const CardPaymentModalComponent = ({
const { t } = useTranslation(); const { t } = useTranslation();
const notification = useNotification(); const notification = useNotification();
const [, { data, refetch, queryLoading }] = useLazyQuery(QUERY_RO_AND_OWNER_BY_JOB_PKS, { const [executeQuery, { data, loading: queryLoading }] = useLazyQuery(QUERY_RO_AND_OWNER_BY_JOB_PKS);
variables: { jobids: [context.jobid] },
skip: !context?.jobid const refetch = (variables) => {
}); return executeQuery({ variables });
};
const collectIPayFields = () => { const collectIPayFields = () => {
const iPayFields = document.querySelectorAll(".ipayfield"); const iPayFields = document.querySelectorAll(".ipayfield");

View File

@@ -27,7 +27,7 @@ export function ChatConversationComponent({
if (conversation?.archived) return null; if (conversation?.archived) return null;
if (loading) return <LoadingSkeleton />; if (loading) return <LoadingSkeleton />;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<div <div

View File

@@ -63,7 +63,7 @@ export function ChatMediaSelector({ bodyshop, selectedMedia, setSelectedMedia, c
const content = ( const content = (
<div className="media-selector-content"> <div className="media-selector-content">
{loading && <LoadingSpinner />} {loading && <LoadingSpinner />}
{error && <AlertComponent message={error.message} type="error" />} {error && <AlertComponent title={error.message} type="error" />}
{selectedMedia.filter((s) => s.isSelected).length >= 10 ? ( {selectedMedia.filter((s) => s.isSelected).length >= 10 ? (
<div className="error-message">{t("messaging.labels.maxtenimages")}</div> <div className="error-message">{t("messaging.labels.maxtenimages")}</div>
) : null} ) : null}

View File

@@ -51,21 +51,29 @@ export function ChatPopupComponent({ chatVisible, selectedConversation, toggleCh
// Query for unread count when chat is not visible and socket is not connected. // Query for unread count when chat is not visible and socket is not connected.
// (Once socket connects, we stop this query; we keep the last known value in state.) // (Once socket connects, we stop this query; we keep the last known value in state.)
useQuery(UNREAD_CONVERSATION_COUNT, { const { data: unreadData, error: unreadError } = useQuery(UNREAD_CONVERSATION_COUNT, {
fetchPolicy: "network-only", fetchPolicy: "network-only",
nextFetchPolicy: "network-only", nextFetchPolicy: "network-only",
skip: chatVisible || socket?.connected, skip: chatVisible || socket?.connected,
pollInterval: socket?.connected ? 0 : 60 * 1000, pollInterval: socket?.connected ? 0 : 60 * 1000
onCompleted: (result) => {
const nextCount = result?.messages_aggregate?.aggregate?.count;
if (typeof nextCount === "number") setUnreadAggregateCount(nextCount);
},
onError: (err) => {
// Keep last known count; do not force badge to zero on transient failures
console.warn("UNREAD_CONVERSATION_COUNT failed:", err?.message || err);
}
}); });
// Handle unread count updates in useEffect
useEffect(() => {
if (unreadData) {
const nextCount = unreadData?.messages_aggregate?.aggregate?.count;
if (typeof nextCount === "number") setUnreadAggregateCount(nextCount);
}
}, [unreadData]);
// Handle unread count errors in useEffect
useEffect(() => {
if (unreadError) {
// Keep last known count; do not force badge to zero on transient failures
console.warn("UNREAD_CONVERSATION_COUNT failed:", unreadError?.message || unreadError);
}
}, [unreadError]);
// Socket connection status -> polling strategy for CONVERSATION_LIST_QUERY // Socket connection status -> polling strategy for CONVERSATION_LIST_QUERY
useEffect(() => { useEffect(() => {
const handleSocketStatus = () => { const handleSocketStatus = () => {

View File

@@ -74,7 +74,7 @@ function ChatSendMessageComponent({ conversation, bodyshop, sendMessage, isSendi
<Alert <Alert
showIcon={true} showIcon={true}
icon={<ExclamationCircleOutlined />} icon={<ExclamationCircleOutlined />}
message={t("messaging.errors.no_consent")} title={t("messaging.errors.no_consent")}
type="error" type="error"
/> />
</Tooltip> </Tooltip>

View File

@@ -24,7 +24,7 @@ export default function ContractCarsContainer({ selectedCarState, form }) {
}); });
}; };
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<ContractCarsComponent <ContractCarsComponent
handleSelect={handleSelect} handleSelect={handleSelect}

View File

@@ -26,7 +26,7 @@ export function ContractJobsContainer({ selectedJobState, bodyshop }) {
setSelectedJob(record.id); setSelectedJob(record.id);
}; };
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<ContractJobsComponent <ContractJobsComponent
handleSelect={handleSelect} handleSelect={handleSelect}

View File

@@ -63,7 +63,7 @@ export function ContractsFindModalContainer({ contractFinderModal, toggleModalVi
<Button onClick={() => form.submit()} type="primary" loading={loading}> <Button onClick={() => form.submit()} type="primary" loading={loading}>
{t("general.labels.search")} {t("general.labels.search")}
</Button> </Button>
{error && <AlertComponent type="error" message={JSON.stringify(error)} />} {error && <AlertComponent type="error" title={JSON.stringify(error)} />}
<Table <Table
loading={loading} loading={loading}
columns={[ columns={[

View File

@@ -36,7 +36,7 @@ export default function CsiResponseFormContainer() {
); );
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<Card> <Card>

View File

@@ -156,7 +156,7 @@ export function DashboardGridComponent({ currentUser }) {
); );
if (loading || dashboardLoading) return <LoadingSkeleton message={t("general.labels.loading")} />; if (loading || dashboardLoading) return <LoadingSkeleton message={t("general.labels.loading")} />;
if (error || dashboardError) return <AlertComponent message={(error || dashboardError).message} type="error" />; if (error || dashboardError) return <AlertComponent title={(error || dashboardError).message} type="error" />;
const handleLayoutChange = async (layout, layouts) => { const handleLayoutChange = async (layout, layouts) => {
logImEXEvent("dashboard_change_layout"); logImEXEvent("dashboard_change_layout");

View File

@@ -112,7 +112,7 @@ export function DmsAllocationsSummary({ mode, socket, bodyshop, jobId, title, on
} }
> >
{bodyshop.pbs_configuration?.disablebillwip && ( {bodyshop.pbs_configuration?.disablebillwip && (
<Alert type="warning" message={t("jobs.labels.dms.disablebillwip")} /> <Alert type="warning" title={t("jobs.labels.dms.disablebillwip")} />
)} )}
<Table <Table

View File

@@ -331,10 +331,10 @@ export function RrAllocationsSummary({ socket, bodyshop, jobId, title, onAllocat
} }
> >
{bodyshop.pbs_configuration?.disablebillwip && ( {bodyshop.pbs_configuration?.disablebillwip && (
<Alert type="warning" message={t("jobs.labels.dms.disablebillwip")} /> <Alert type="warning" title={t("jobs.labels.dms.disablebillwip")} />
)} )}
{error && <Alert type="error" style={{ marginTop: 8, marginBottom: 8 }} message={error} />} {error && <Alert type="error" style={{ marginTop: 8, marginBottom: 8 }} title={error} />}
<Tabs defaultActiveKey="rogog" items={tabItems} /> <Tabs defaultActiveKey="rogog" items={tabItems} />
</Card> </Card>

View File

@@ -56,7 +56,7 @@ export function DmsCdkVehicles({ form, job }) {
setOpen(false); setOpen(false);
}} }}
> >
{error && <AlertComponent error={error.message} />} {error && <AlertComponent title={error.message} type="error" />}
<Table <Table
title={() => ( title={() => (
<Input.Search <Input.Search

View File

@@ -179,7 +179,7 @@ export default function RRCustomerSelector({
<Alert <Alert
type="error" type="error"
showIcon showIcon
message="Open RO limit reached in Reynolds" title="Open RO limit reached in Reynolds"
description={ description={
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}> <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
<div> <div>
@@ -201,7 +201,7 @@ export default function RRCustomerSelector({
<Alert <Alert
type="info" type="info"
showIcon showIcon
message="Complete Validation in Reynolds" title="Complete Validation in Reynolds"
description={ description={
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}> <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
<div> <div>
@@ -234,7 +234,7 @@ export default function RRCustomerSelector({
<Alert <Alert
type="warning" type="warning"
showIcon showIcon
message="VIN ownership enforced" title="VIN ownership enforced"
description={ description={
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12 }}> <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12 }}>
<div> <div>

View File

@@ -51,7 +51,7 @@ export function DocumentEditorContainer({ setBodyshop }) {
}, [dataShop, setBodyshop]); }, [dataShop, setBodyshop]);
if (loadingShop) return <LoadingSpinner />; if (loadingShop) return <LoadingSpinner />;
if (errorShop) return <AlertComponent message={errorShop.message} type="error" />; if (errorShop) return <AlertComponent title={errorShop.message} type="error" />;
if (isLocalMedia) { if (isLocalMedia) {
if (imageUrl && filename && jobid) { if (imageUrl && filename && jobid) {
@@ -66,7 +66,7 @@ export function DocumentEditorContainer({ setBodyshop }) {
} }
if (loadingDoc) return <LoadingSpinner />; if (loadingDoc) return <LoadingSpinner />;
if (errorDoc) return <AlertComponent message={errorDoc.message} type="error" />; if (errorDoc) return <AlertComponent title={errorDoc.message} type="error" />;
if (!dataDoc || !dataDoc.documents_by_pk) return <Result status="404" title={t("general.errors.notfound")} />; if (!dataDoc || !dataDoc.documents_by_pk) return <Result status="404" title={t("general.errors.notfound")} />;
return ( return (

View File

@@ -45,7 +45,7 @@ export function EmailDocumentsComponent({ emailConfig, form, selectedMediaState,
return ( return (
<div> <div>
{loading && <LoadingSpinner />} {loading && <LoadingSpinner />}
{error && <AlertComponent message={error.message} type="error" />} {error && <AlertComponent title={error.message} type="error" />}
{selectedMedia.filter((s) => s.isSelected).length >= 10 ? ( {selectedMedia.filter((s) => s.isSelected).length >= 10 ? (
<div style={{ color: "red" }}>{t("messaging.labels.maxtenimages")}</div> <div style={{ color: "red" }}>{t("messaging.labels.maxtenimages")}</div>
) : null} ) : null}

View File

@@ -9,7 +9,7 @@ import AlertComponent from "../alert/alert.component";
const EmployeeTeamSearchSelect = ({ ...props }) => { const EmployeeTeamSearchSelect = ({ ...props }) => {
const { loading, error, data } = useQuery(QUERY_TEAMS); const { loading, error, data } = useQuery(QUERY_TEAMS);
if (error) return <AlertComponent message={JSON.stringify(error)} />; if (error) return <AlertComponent title={JSON.stringify(error)} type="error" />;
return ( return (
<Select <Select
showSearch showSearch

View File

@@ -122,14 +122,23 @@ class ErrorBoundary extends React.Component {
/> />
<Row> <Row>
<Col offset={6} span={12}> <Col offset={6} span={12}>
<Collapse bordered={false}> <Collapse
<Collapse.Panel key="errors-panel" header={t("general.labels.errors")}> bordered={false}
<div> items={[
<strong>{this.state.error.message}</strong> {
</div> key: "errors-panel",
<div>{this.state.error.stack}</div> label: t("general.labels.errors"),
</Collapse.Panel> children: (
</Collapse> <>
<div>
<strong>{this.state.error.message}</strong>
</div>
<div>{this.state.error.stack}</div>
</>
)
}
]}
/>
</Col> </Col>
</Row> </Row>
</div> </div>

View File

@@ -56,7 +56,7 @@ function FeatureWrapper({
return ( return (
noauth || ( noauth || (
<AlertComponent <AlertComponent
message={t("general.messages.nofeatureaccess", { title={t("general.messages.nofeatureaccess", {
app: InstanceRenderManager({ app: InstanceRenderManager({
imex: "$t(titles.imexonline)", imex: "$t(titles.imexonline)",
rome: "$t(titles.romeonline)" rome: "$t(titles.romeonline)"

View File

@@ -21,7 +21,7 @@ export default function FormsFieldChanged({ form, skipPrompt }) {
<Prompt when={!skipPrompt} beforeUnload={true} message={t("general.messages.unsavedchangespopup")} /> <Prompt when={!skipPrompt} beforeUnload={true} message={t("general.messages.unsavedchangespopup")} />
<AlertComponent <AlertComponent
type="warning" type="warning"
message={ title={
<div> <div>
<span>{t("general.messages.unsavedchanges")} </span> <span>{t("general.messages.unsavedchanges")} </span>
<span <span
@@ -39,7 +39,7 @@ export default function FormsFieldChanged({ form, skipPrompt }) {
{errors.length > 0 && ( {errors.length > 0 && (
<AlertComponent <AlertComponent
type="error" type="error"
message={ title={
<div> <div>
<ul>{errors.map((e, idx) => e.errors.map((e2, idx2) => <li key={`${idx}${idx2}`}>{e2}</li>))}</ul> <ul>{errors.map((e, idx) => e.errors.map((e2, idx2) => <li key={`${idx}${idx2}`}>{e2}</li>))}</ul>
</div> </div>

View File

@@ -1,22 +1,20 @@
import { MailFilled } from "@ant-design/icons"; import { MailFilled } from "@ant-design/icons";
import { Input } from "antd"; import { Button, Input, Space } from "antd";
import { forwardRef } from "react"; import { forwardRef } from "react";
function FormItemEmail(props, ref) { function FormItemEmail(props, ref) {
const { defaultValue, value, ...restProps } = props;
const emailValue = defaultValue || value;
return ( return (
<Input <Space.Compact style={{ width: "100%" }}>
{...props} <Input {...restProps} ref={ref} value={value} defaultValue={defaultValue} />
ref={ref} {emailValue ? (
addonAfter={ <Button icon={<MailFilled />} href={`mailto:${emailValue}`} target="_blank" rel="noopener noreferrer" />
props.defaultValue || props.value ? ( ) : (
<a href={`mailto:${props.defaultValue || props.value}`}> <Button icon={<MailFilled />} disabled />
<MailFilled /> )}
</a> </Space.Compact>
) : (
<MailFilled />
)
}
/>
); );
} }

View File

@@ -46,7 +46,7 @@ export default function GlobalSearchOs() {
value: job.ro_number || "N/A", value: job.ro_number || "N/A",
label: ( label: (
<Link to={`/manage/jobs/${job.id}`}> <Link to={`/manage/jobs/${job.id}`}>
<Space size="small" split={<Divider type="vertical" />}> <Space size="small" split={<Divider orientation="vertical" />}>
<strong>{job.ro_number || t("general.labels.na")}</strong> <strong>{job.ro_number || t("general.labels.na")}</strong>
<span>{`${job.status || ""}`}</span> <span>{`${job.status || ""}`}</span>
<span> <span>
@@ -69,7 +69,7 @@ export default function GlobalSearchOs() {
value: OwnerNameDisplayFunction(owner), value: OwnerNameDisplayFunction(owner),
label: ( label: (
<Link to={`/manage/owners/${owner.id}`}> <Link to={`/manage/owners/${owner.id}`}>
<Space size="small" split={<Divider type="vertical" />} wrap> <Space size="small" split={<Divider orientation="vertical" />} wrap>
<span> <span>
<OwnerNameDisplay ownerObject={owner} /> <OwnerNameDisplay ownerObject={owner} />
</span> </span>
@@ -89,7 +89,7 @@ export default function GlobalSearchOs() {
value: `${vehicle.v_model_yr || ""} ${vehicle.v_make_desc || ""} ${vehicle.v_model_desc || ""}`, value: `${vehicle.v_model_yr || ""} ${vehicle.v_make_desc || ""} ${vehicle.v_model_desc || ""}`,
label: ( label: (
<Link to={`/manage/vehicles/${vehicle.id}`}> <Link to={`/manage/vehicles/${vehicle.id}`}>
<Space size="small" split={<Divider type="vertical" />}> <Space size="small" split={<Divider orientation="vertical" />}>
<span> <span>
{`${vehicle.v_model_yr || ""} ${vehicle.v_make_desc || ""} ${vehicle.v_model_desc || ""}`} {`${vehicle.v_model_yr || ""} ${vehicle.v_make_desc || ""} ${vehicle.v_model_desc || ""}`}
</span> </span>
@@ -111,7 +111,7 @@ export default function GlobalSearchOs() {
value: `${payment.job?.ro_number} ${payment.amount}`, value: `${payment.job?.ro_number} ${payment.amount}`,
label: ( label: (
<Link to={`/manage/jobs/${payment.job?.id}`}> <Link to={`/manage/jobs/${payment.job?.id}`}>
<Space size="small" split={<Divider type="vertical" />}> <Space size="small" split={<Divider orientation="vertical" />}>
<span>{payment.paymentnum}</span> <span>{payment.paymentnum}</span>
<span>{payment.job?.ro_number}</span> <span>{payment.job?.ro_number}</span>
<span>{payment.memo || ""}</span> <span>{payment.memo || ""}</span>
@@ -131,7 +131,7 @@ export default function GlobalSearchOs() {
value: `${bill.invoice_number} - ${bill.vendor.name}`, value: `${bill.invoice_number} - ${bill.vendor.name}`,
label: ( label: (
<Link to={`/manage/bills?billid=${bill.id}`}> <Link to={`/manage/bills?billid=${bill.id}`}>
<Space size="small" split={<Divider type="vertical" />}> <Space size="small" split={<Divider orientation="vertical" />}>
<span>{bill.invoice_number}</span> <span>{bill.invoice_number}</span>
<span>{bill.vendor.name}</span> <span>{bill.vendor.name}</span>
<span>{bill.date}</span> <span>{bill.date}</span>
@@ -151,7 +151,7 @@ export default function GlobalSearchOs() {
// }`, // }`,
// label: ( // label: (
// <Link to={`/manage/phonebook?phonebookentry=${pb.id}`}> // <Link to={`/manage/phonebook?phonebookentry=${pb.id}`}>
// <Space size="small" split={<Divider type="vertical" />}> // <Space size="small" split={<Divider orientation="vertical" />}>
// <span>{`${pb.firstname || ""} ${pb.lastname || ""} ${ // <span>{`${pb.firstname || ""} ${pb.lastname || ""} ${
// pb.company || "" // pb.company || ""
// }`}</span> // }`}</span>

View File

@@ -152,7 +152,7 @@ export default function GlobalSearch() {
] ]
: []; : [];
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<AutoComplete <AutoComplete

View File

@@ -33,7 +33,7 @@ export function InventoryList() {
} }
}); });
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<InventoryListPaginated <InventoryListPaginated
refetch={refetch} refetch={refetch}

View File

@@ -33,7 +33,7 @@ export function JobBillsTotalComponent({
if (showWarning && warningCallback && typeof warningCallback === "function") { if (showWarning && warningCallback && typeof warningCallback === "function") {
warningCallback({ key: "bills", warning: t("jobs.errors.nofinancial") }); warningCallback({ key: "bills", warning: t("jobs.errors.nofinancial") });
} }
return <AlertComponent type="error" message={t("jobs.errors.nofinancial")} />; return <AlertComponent type="error" title={t("jobs.errors.nofinancial")} />;
} }
const totals = jobTotals; const totals = jobTotals;
@@ -264,7 +264,7 @@ export function JobBillsTotalComponent({
<Alert <Alert
style={{ margin: "8px 0px" }} style={{ margin: "8px 0px" }}
type="warning" type="warning"
message={t("jobs.labels.outstanding_reconciliation_discrep")} title={t("jobs.labels.outstanding_reconciliation_discrep")}
/> />
)} )}
</Card> </Card>
@@ -337,7 +337,7 @@ export function JobBillsTotalComponent({
</Tooltip> </Tooltip>
</Space> </Space>
{showWarning && calculatedCreditsNotReceived.getAmount() > 0 && ( {showWarning && calculatedCreditsNotReceived.getAmount() > 0 && (
<Alert style={{ margin: "8px 0px" }} type="warning" message={t("jobs.labels.outstanding_credit_memos")} /> <Alert style={{ margin: "8px 0px" }} type="warning" title={t("jobs.labels.outstanding_credit_memos")} />
)} )}
</Card> </Card>
</Col> </Col>

View File

@@ -30,7 +30,7 @@ export function JobCloseRoGuardLabor({ job, bodyshop, warningCallback }) {
}); });
if (loading) return <LoadingSkeleton />; if (loading) return <LoadingSkeleton />;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return Enhanced_Payroll.treatment === "on" ? ( return Enhanced_Payroll.treatment === "on" ? (
<PayrollLaborAllocationsTable <PayrollLaborAllocationsTable

View File

@@ -49,7 +49,7 @@ export function JobCloseRoGuardProfit({ job, warningCallback }) {
{balance.toFormat()} {balance.toFormat()}
</DataLabel> </DataLabel>
{balance.getAmount() !== 0 && ( {balance.getAmount() !== 0 && (
<Alert style={{ margin: "8px 0px" }} type="warning" message={t("jobs.labels.outstanding_ar")} /> <Alert style={{ margin: "8px 0px" }} type="warning" title={t("jobs.labels.outstanding_ar")} />
)} )}
</Card> </Card>
); );

View File

@@ -18,7 +18,7 @@ export function JobCloseRoGuardBills({ job, warningCallback }) {
nextFetchPolicy: "network-only" nextFetchPolicy: "network-only"
}); });
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<JobBillsTotalComponent <JobBillsTotalComponent

View File

@@ -66,164 +66,176 @@ export function JobCloseRoGuardContainer({ job, jobRO, bodyshop, form }) {
</Card> </Card>
)} )}
<Collapse> <Collapse
<Collapse.Panel forceRender key="roguard" header={t("jobs.labels.roguard")}> items={[
<Row gutter={[32, 32]}> {
<Col span={24}> key: "roguard",
<JobCloseRoGuardBills job={job} form={form} warningCallback={warningCallback} /> label: t("jobs.labels.roguard"),
</Col> forceRender: true,
<Col className="ro-guard-col-multiple" md={24} lg={6}> children: (
<Row gutter={[32, 32]} style={{ height: "100%" }}> <>
<Col span={24}> <Row gutter={[32, 32]}>
<JobCloseRoGuardProfit job={job} form={form} warningCallback={warningCallback} /> <Col span={24}>
</Col> <JobCloseRoGuardBills job={job} form={form} warningCallback={warningCallback} />
<Col span={24}> </Col>
<JobCloseRoGuardAr job={job} form={form} warningCallback={warningCallback} /> <Col className="ro-guard-col-multiple" md={24} lg={6}>
<Row gutter={[32, 32]} style={{ height: "100%" }}>
<Col span={24}>
<JobCloseRoGuardProfit job={job} form={form} warningCallback={warningCallback} />
</Col>
<Col span={24}>
<JobCloseRoGuardAr job={job} form={form} warningCallback={warningCallback} />
</Col>
</Row>
</Col>
{InstanceRenderManager({
rome: (
<Col md={24} lg={8}>
{/* <JobCloseRoGuardSublet job={job} warningCallback={warningCallback} /> */}
<JobCloseRoGuardPpd job={job} warningCallback={warningCallback} />
</Col>
)
})}
<Col className="ro-guard-col" md={24} lg={10}>
<JobCloseRoGuardLabor job={job} form={form} warningCallback={warningCallback} />
</Col>
</Row>
<Form.Item
name="masterbypass"
label={t("jobs.labels.masterbypass")}
rules={[
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_bills &&
warnings.find((w) => w.key === "bills")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_bills")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_cm &&
warnings.find((w) => w.key === "cm")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_cm")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_profit &&
warnings.find((w) => w.key === "profit")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_profit")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_ar &&
warnings.find((w) => w.key === "ar")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_ar")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_sublet &&
warnings.find((w) => w.key === "sublet")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_sublet")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_ppd &&
warnings.find((w) => w.key === "ppd")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_ppd")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_labor &&
warnings.find((w) => w.key === "labor")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_labor")
})
);
}
return Promise.resolve();
}
})
]}
>
<Input prefix={<LockOutlined />} type="password" placeholder="Password" disabled={jobRO} />
</Form.Item>
</>
)
},
{
key: "job-performance",
label: t("jobs.labels.performance"),
children: (
<Row gutter={[32, 32]}>
<Col className="ro-guard-col" span={24}>
<JobCloseRoGuardTtLifecycle job={job} />
</Col> </Col>
</Row> </Row>
</Col> )
{InstanceRenderManager({ }
rome: ( ]}
<Col md={24} lg={8}> />
{/* <JobCloseRoGuardSublet job={job} warningCallback={warningCallback} /> */}
<JobCloseRoGuardPpd job={job} warningCallback={warningCallback} />
</Col>
)
})}
<Col className="ro-guard-col" md={24} lg={10}>
<JobCloseRoGuardLabor job={job} form={form} warningCallback={warningCallback} />
</Col>
</Row>
<Form.Item
name="masterbypass"
label={t("jobs.labels.masterbypass")}
rules={[
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_bills &&
warnings.find((w) => w.key === "bills")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_bills")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_cm &&
warnings.find((w) => w.key === "cm")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_cm")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_profit &&
warnings.find((w) => w.key === "profit")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_profit")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_ar &&
warnings.find((w) => w.key === "ar")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_ar")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_sublet &&
warnings.find((w) => w.key === "sublet")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_sublet")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_ppd &&
warnings.find((w) => w.key === "ppd")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_ppd")
})
);
}
return Promise.resolve();
}
}),
() => ({
validator(_, value) {
if (
!PasswordCheck({ bodyshop, value }) &&
bodyshop.md_ro_guard.enforce_labor &&
warnings.find((w) => w.key === "labor")
) {
return Promise.reject(
t("jobs.labels.ro_guard.enforce_validation", {
message: t("jobs.labels.ro_guard.enforce_labor")
})
);
}
return Promise.resolve();
}
})
]}
>
<Input prefix={<LockOutlined />} type="password" placeholder="Password" disabled={jobRO} />
</Form.Item>
</Collapse.Panel>
<Collapse.Panel key="job-performance" header={t("jobs.labels.performance")}>
<Row gutter={[32, 32]}>
<Col className="ro-guard-col" span={24}>
<JobCloseRoGuardTtLifecycle job={job} />
</Col>
</Row>
</Collapse.Panel>
</Collapse>
</> </>
); );
} }

View File

@@ -70,7 +70,7 @@ export function JobCloseRGuardPpd({ job, warningCallback }) {
<Card title={t("jobs.labels.ppdnotexported")}> <Card title={t("jobs.labels.ppdnotexported")}>
<Table dataSource={linesWithPPD} columns={columns} pagination={false} rowKey="id" bordered size="small" /> <Table dataSource={linesWithPPD} columns={columns} pagination={false} rowKey="id" bordered size="small" />
{linesWithPPD.length > 0 && ( {linesWithPPD.length > 0 && (
<Alert style={{ margin: "8px 0px" }} type="warning" message={t("jobs.labels.outstanding_ppd")} /> <Alert style={{ margin: "8px 0px" }} type="warning" title={t("jobs.labels.outstanding_ppd")} />
)} )}
</Card> </Card>
); );

View File

@@ -54,7 +54,7 @@ export function JobCloseRoGuardProfit({ job, bodyshop, warningCallback }) {
<Card title={t("jobs.labels.profits")} style={{ height: "100%" }}> <Card title={t("jobs.labels.profits")} style={{ height: "100%" }}>
<JobCostingStatistics summaryData={costingData?.summaryData} onlyGP /> <JobCostingStatistics summaryData={costingData?.summaryData} onlyGP />
{enforceProfitPassword && ( {enforceProfitPassword && (
<Alert style={{ margin: "8px 0px" }} type="warning" message={t("jobs.labels.profitbypassrequired")} /> <Alert style={{ margin: "8px 0px" }} type="warning" title={t("jobs.labels.profitbypassrequired")} />
)} )}
</Card> </Card>
); );

View File

@@ -64,7 +64,7 @@ export function JobCloseRGuardSublet({ job, warningCallback }) {
<Card title={t("jobs.labels.subletsnotcompleted")}> <Card title={t("jobs.labels.subletsnotcompleted")}>
<Table dataSource={subletsNotDone} columns={columns} pagination={false} rowKey="id" bordered size="small" /> <Table dataSource={subletsNotDone} columns={columns} pagination={false} rowKey="id" bordered size="small" />
{subletsNotDone.length > 0 && ( {subletsNotDone.length > 0 && (
<Alert style={{ margin: "8px 0px" }} type="warning" message={t("jobs.labels.outstanding_sublets")} /> <Alert style={{ margin: "8px 0px" }} type="warning" title={t("jobs.labels.outstanding_sublets")} />
)} )}
</Card> </Card>
); );

View File

@@ -95,7 +95,7 @@ export function JobDetailCards({ bodyshop, setPrintCenterContext, insertAuditTra
return ( return (
<Drawer open={!!selected} destroyOnHidden width={drawerPercentage} placement="right" onClose={handleDrawerClose}> <Drawer open={!!selected} destroyOnHidden width={drawerPercentage} placement="right" onClose={handleDrawerClose}>
{loading ? <LoadingSpinner /> : null} {loading ? <LoadingSpinner /> : null}
{error ? <AlertComponent message={error.message} type="error" /> : null} {error ? <AlertComponent title={error.message} type="error" /> : null}
{data ? ( {data ? (
<Card <Card
title={ title={

View File

@@ -15,7 +15,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "date_last_contacted", key: "date_last_contacted",
children: ( content: (
<> <>
<label>{t("jobs.fields.date_last_contacted")}: </label> <label>{t("jobs.fields.date_last_contacted")}: </label>
<DateTimeFormatter>{data.date_last_contacted}</DateTimeFormatter> <DateTimeFormatter>{data.date_last_contacted}</DateTimeFormatter>
@@ -28,7 +28,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "date_open", key: "date_open",
children: ( content: (
<> <>
<label>{t("jobs.fields.date_open")}: </label> <label>{t("jobs.fields.date_open")}: </label>
<DateTimeFormatter>{data.date_open}</DateTimeFormatter> <DateTimeFormatter>{data.date_open}</DateTimeFormatter>
@@ -41,7 +41,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "date_estimated", key: "date_estimated",
children: ( content: (
<> <>
<label>{t("jobs.fields.date_estimated")}: </label> <label>{t("jobs.fields.date_estimated")}: </label>
<DateTimeFormatter>{data.date_estimated}</DateTimeFormatter> <DateTimeFormatter>{data.date_estimated}</DateTimeFormatter>
@@ -54,7 +54,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "date_scheduled", key: "date_scheduled",
children: ( content: (
<> <>
<label>{t("jobs.fields.date_scheduled")}: </label> <label>{t("jobs.fields.date_scheduled")}: </label>
<DateTimeFormatter>{data.date_scheduled}</DateTimeFormatter> <DateTimeFormatter>{data.date_scheduled}</DateTimeFormatter>
@@ -67,7 +67,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "scheduled_in", key: "scheduled_in",
children: ( content: (
<> <>
<label>{t("jobs.fields.scheduled_in")}: </label> <label>{t("jobs.fields.scheduled_in")}: </label>
<DateTimeFormatter>{data.scheduled_in}</DateTimeFormatter> <DateTimeFormatter>{data.scheduled_in}</DateTimeFormatter>
@@ -80,7 +80,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "actual_in", key: "actual_in",
children: ( content: (
<> <>
<label>{t("jobs.fields.actual_in")}: </label> <label>{t("jobs.fields.actual_in")}: </label>
<DateTimeFormatter>{data.actual_in}</DateTimeFormatter> <DateTimeFormatter>{data.actual_in}</DateTimeFormatter>
@@ -93,7 +93,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "date_repairstarted", key: "date_repairstarted",
children: ( content: (
<> <>
<label>{t("jobs.fields.date_repairstarted")}: </label> <label>{t("jobs.fields.date_repairstarted")}: </label>
<DateTimeFormatter>{data.date_repairstarted}</DateTimeFormatter> <DateTimeFormatter>{data.date_repairstarted}</DateTimeFormatter>
@@ -106,7 +106,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "scheduled_completion", key: "scheduled_completion",
children: ( content: (
<> <>
<label>{t("jobs.fields.scheduled_completion")}: </label> <label>{t("jobs.fields.scheduled_completion")}: </label>
<DateTimeFormatter>{data.scheduled_completion}</DateTimeFormatter> <DateTimeFormatter>{data.scheduled_completion}</DateTimeFormatter>
@@ -119,7 +119,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "actual_completion", key: "actual_completion",
children: ( content: (
<> <>
<label>{t("jobs.fields.actual_completion")}: </label> <label>{t("jobs.fields.actual_completion")}: </label>
<DateTimeFormatter>{data.actual_completion}</DateTimeFormatter> <DateTimeFormatter>{data.actual_completion}</DateTimeFormatter>
@@ -132,7 +132,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "scheduled_delivery", key: "scheduled_delivery",
children: ( content: (
<> <>
<label>{t("jobs.fields.scheduled_delivery")}: </label> <label>{t("jobs.fields.scheduled_delivery")}: </label>
<DateTimeFormatter>{data.scheduled_delivery}</DateTimeFormatter> <DateTimeFormatter>{data.scheduled_delivery}</DateTimeFormatter>
@@ -145,7 +145,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "actual_delivery", key: "actual_delivery",
children: ( content: (
<> <>
<label>{t("jobs.fields.actual_delivery")}: </label> <label>{t("jobs.fields.actual_delivery")}: </label>
<DateTimeFormatter>{data.actual_delivery}</DateTimeFormatter> <DateTimeFormatter>{data.actual_delivery}</DateTimeFormatter>
@@ -158,7 +158,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "date_invoiced", key: "date_invoiced",
children: ( content: (
<> <>
<label>{t("jobs.fields.date_invoiced")}: </label> <label>{t("jobs.fields.date_invoiced")}: </label>
<DateTimeFormatter>{data.date_invoiced}</DateTimeFormatter> <DateTimeFormatter>{data.date_invoiced}</DateTimeFormatter>
@@ -171,7 +171,7 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
? [ ? [
{ {
key: "date_exported", key: "date_exported",
children: ( content: (
<> <>
<label>{t("jobs.fields.date_exported")}: </label> <label>{t("jobs.fields.date_exported")}: </label>
<DateTimeFormatter>{data.date_exported}</DateTimeFormatter> <DateTimeFormatter>{data.date_exported}</DateTimeFormatter>

View File

@@ -36,7 +36,7 @@ export function JobLinesExpander({ jobline, jobid, bodyshop, technician }) {
}); });
if (loading) return <Skeleton />; if (loading) return <Skeleton />;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<Row> <Row>

View File

@@ -28,7 +28,7 @@ export function JobLinesExpanderSimple({ jobline, jobid, technician }) {
}); });
if (loading) return <Skeleton />; if (loading) return <Skeleton />;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<Row> <Row>

View File

@@ -11,6 +11,6 @@ export default function JobProfileDataWarning({ job }) {
Object.keys(job.materials).length === 0; Object.keys(job.materials).length === 0;
if (missingProfileInfo && InstanceRenderManager({ rome: true })) if (missingProfileInfo && InstanceRenderManager({ rome: true }))
return <Alert type="error" message={t("jobs.labels.missingprofileinfo")}></Alert>; return <Alert type="error" title={t("jobs.labels.missingprofileinfo")}></Alert>;
return null; return null;
} }

View File

@@ -47,7 +47,7 @@ function JobReconciliationModalContainer({ reconciliationModal, toggleModalVisib
className="imex-reconciliation-modal" className="imex-reconciliation-modal"
> >
{loading && <LoadingSpinner loading={loading} />} {loading && <LoadingSpinner loading={loading} />}
{error && <AlertComponent message={error.message} type="error" />} {error && <AlertComponent title={error.message} type="error" />}
{data && <JobReconciliationModalComponent job={data?.jobs_by_pk} bills={data?.bills} />} {data && <JobReconciliationModalComponent job={data?.jobs_by_pk} bills={data?.bills} />}
</Modal> </Modal>
); );

View File

@@ -95,8 +95,8 @@ const JobSearchSelect = (
: null} : null}
</Select> </Select>
{error ? <AlertComponent message={error.message} type="error" /> : null} {error ? <AlertComponent title={error.message} type="error" /> : null}
{idError ? <AlertComponent message={idError.message} type="error" /> : null} {idError ? <AlertComponent title={idError.message} type="error" /> : null}
</div> </div>
); );
}; };

View File

@@ -65,23 +65,29 @@ export function JobsTotalsTableComponent({ jobRO, currentUser, job }) {
<Col span={24}> <Col span={24}>
<Card title="DEVELOPMENT USE ONLY"> <Card title="DEVELOPMENT USE ONLY">
<JobCalculateTotals job={job} disabled={jobRO} /> <JobCalculateTotals job={job} disabled={jobRO} />
<Collapse> <Collapse
<Collapse.Panel key="json-totals" header="JSON Tree Totals"> items={[
<div> {
<pre> key: "json-totals",
{JSON.stringify( label: "JSON Tree Totals",
{ children: (
CIECA: job.cieca_ttl?.data, <div>
CIECASTL: job.cieca_stl?.data, <pre>
ImEXCalc: job.job_totals {JSON.stringify(
}, {
null, CIECA: job.cieca_ttl?.data,
2 CIECASTL: job.cieca_stl?.data,
)} ImEXCalc: job.job_totals
</pre> },
</div> null,
</Collapse.Panel> 2
</Collapse> )}
</pre>
</div>
)
}
]}
/>
</Card> </Card>
</Col> </Col>
)} )}

View File

@@ -148,7 +148,7 @@ export function JobsAvailableComponent({ bodyshop, loading, data, refetch, addJo
</Button> </Button>
</> </>
)} )}
{isClosed && <Alert type="error" message={t("jobs.labels.alreadyclosed")}></Alert>} {isClosed && <Alert type="error" title={t("jobs.labels.alreadyclosed")}></Alert>}
</Space> </Space>
); );
} }

View File

@@ -382,7 +382,7 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail
if (availableJobId && clm_no) addJobAsSupp({ id: availableJobId, clm_no: clm_no }); if (availableJobId && clm_no) addJobAsSupp({ id: availableJobId, clm_no: clm_no });
}, [addJobAsSupp, availableJobId, clm_no]); }, [addJobAsSupp, availableJobId, clm_no]);
if (error) return <AlertComponent type="error" message={error.message} />; if (error) return <AlertComponent type="error" title={error.message} />;
return ( return (
<LoadingSpinner loading={insertLoading} message={t("jobs.labels.creating_new_job")}> <LoadingSpinner loading={insertLoading} message={t("jobs.labels.creating_new_job")}>

View File

@@ -41,282 +41,306 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
return ( return (
<div> <div>
<Collapse defaultActiveKey="insurance"> <Collapse
<Collapse.Panel key="insurance" header={t("menus.jobsdetail.insurance")} forceRender> defaultActiveKey="insurance"
<LayoutFormRow> items={[
<Form.Item label={t("jobs.fields.clm_no")} name="clm_no"> {
<Input /> key: "insurance",
</Form.Item> label: t("menus.jobsdetail.insurance"),
<Form.Item label={t("jobs.fields.policy_no")} name="policy_no"> forceRender: true,
<Input /> children: (
</Form.Item>
<Form.Item label={t("jobs.fields.regie_number")} name="regie_number">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_co_nm")} name="ins_co_nm">
<Select onChange={handleInsCoChange}>
{bodyshop.md_ins_cos.map((s) => (
<Select.Option key={s.name} value={s.name}>
{s.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item label={t("jobs.fields.ins_addr1")} name="ins_addr1">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_city")} name="ins_city">
<Input />
</Form.Item>
<Form.Item
label={
<Space>
{t("jobs.fields.ins_ct_ln")}
<JobsDetailChangeFilehandler form={form} />
</Space>
}
name="ins_ct_ln"
>
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_ct_fn")} name="ins_ct_fn">
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.ins_ph1")}
name="ins_ph1"
rules={[({ getFieldValue }) => PhoneItemFormatterValidation(getFieldValue, "ins_ph1")]}
>
<FormItemPhone />
</Form.Item>
<Form.Item
label={t("jobs.fields.ins_ea")}
name="ins_ea"
rules={[
{
type: "email",
message: "This is not a valid email address."
}
]}
>
<FormItemEmail email={getFieldValue("ins_ea")} />
</Form.Item>
<Form.Item label={t("jobs.fields.loss_date")} name="loss_date">
<DateTimePicker isDateOnly />
</Form.Item>
<Form.Item label={t("jobs.fields.kmin")} name="kmin">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm">
<Input />
</Form.Item>
<Form.Item
label={
<Space>
{t("jobs.fields.est_ct_fn")}
<JobsDetailChangeEstimator form={form} />
</Space>
}
name="est_ct_fn"
>
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.est_ct_ln")} name="est_ct_ln">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.est_ph1")} name="est_ph1">
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.est_ea")}
name="est_ea"
rules={[
{
type: "email",
message: "This is not a valid email address."
}
]}
>
<FormItemEmail email={getFieldValue("est_ea")} />
</Form.Item>
<Form.Item label={t("jobs.fields.selling_dealer")} name="selling_dealer">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.servicing_dealer")} name="servicing_dealer">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.selling_dealer_contact")} name="selling_dealer_contact">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.servicing_dealer_contact")} name="servicing_dealer_contact">
<Input />
</Form.Item>
</LayoutFormRow>
</Collapse.Panel>
<Collapse.Panel forceRender key="claim" header={t("menus.jobsdetail.claimdetail")}>
<LayoutFormRow>
<Form.Item label={t("jobs.fields.loss_desc")} name="loss_desc">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.loss_of_use")} name="loss_of_use">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.ponumber")} name="po_number">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.unitnumber")} name="unit_number">
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.specialcoveragepolicy")}
valuePropName="checked"
name="special_coverage_policy"
>
<Switch />
</Form.Item>
<Form.Item label={t("jobs.fields.kmin")} name="kmin">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.kmout")} name="kmout">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.referralsource")} name="referral_source">
<Select>
{bodyshop.md_referral_sources.map((s) => (
<Select.Option key={s} value={s}>
{s}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item label={t("jobs.fields.referral_source_extra")} name="referral_source_extra">
<Input />
</Form.Item>
</LayoutFormRow>
</Collapse.Panel>
<Collapse.Panel forceRender key="financial" header={t("menus.jobsdetail.financials")}>
<JobsDetailRatesChangeButton form={form} />
{InstanceRenderManager({
imex: <JobsMarkPstExempt form={form} />
})}
<LayoutFormRow>
<Form.Item label={t("jobs.fields.ded_amt")} name="ded_amt">
<CurrencyInput min={0} />
</Form.Item>
<Form.Item label={t("jobs.fields.ded_status")} name="ded_status">
<Select allowClear>
<Select.Option value="W">{t("jobs.labels.deductible.waived")}</Select.Option>
<Select.Option value="Y">{t("jobs.labels.deductible.stands")}</Select.Option>
</Select>
</Form.Item>
<Form.Item label={t("jobs.fields.depreciation_taxes")} name="depreciation_taxes">
<CurrencyInput />
</Form.Item>
{bodyshop.region_config.toLowerCase().startsWith("ca") && (
<Form.Item label={t("jobs.fields.ca_gst_registrant")} name="ca_gst_registrant" valuePropName="checked">
<Switch />
</Form.Item>
)}
<Form.Item label={t("jobs.fields.other_amount_payable")} name="other_amount_payable">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.towing_payable")} name="towing_payable">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.storage_payable")} name="storage_payable">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.adjustment_bottom_line")} name="adjustment_bottom_line">
<CurrencyInput />
</Form.Item>
</LayoutFormRow>
{InstanceRenderManager({
imex: (
<LayoutFormRow> <LayoutFormRow>
<Form.Item label={t("jobs.fields.federal_tax_rate")} name="federal_tax_rate"> <Form.Item label={t("jobs.fields.clm_no")} name="clm_no">
<InputNumber min={0} max={1} precision={2} /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.state_tax_rate")} name="state_tax_rate"> <Form.Item label={t("jobs.fields.policy_no")} name="policy_no">
<InputNumber min={0} max={1} precision={2} /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.local_tax_rate")} name="local_tax_rate"> <Form.Item label={t("jobs.fields.regie_number")} name="regie_number">
<InputNumber min={0} max={1} precision={2} /> <Input />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_co_nm")} name="ins_co_nm">
<Select onChange={handleInsCoChange}>
{bodyshop.md_ins_cos.map((s) => (
<Select.Option key={s.name} value={s.name}>
{s.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item label={t("jobs.fields.ins_addr1")} name="ins_addr1">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_city")} name="ins_city">
<Input />
</Form.Item>
<Form.Item
label={
<Space>
{t("jobs.fields.ins_ct_ln")}
<JobsDetailChangeFilehandler form={form} />
</Space>
}
name="ins_ct_ln"
>
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_ct_fn")} name="ins_ct_fn">
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.ins_ph1")}
name="ins_ph1"
rules={[({ getFieldValue }) => PhoneItemFormatterValidation(getFieldValue, "ins_ph1")]}
>
<FormItemPhone />
</Form.Item>
<Form.Item
label={t("jobs.fields.ins_ea")}
name="ins_ea"
rules={[
{
type: "email",
message: "This is not a valid email address."
}
]}
>
<FormItemEmail email={getFieldValue("ins_ea")} />
</Form.Item>
<Form.Item label={t("jobs.fields.loss_date")} name="loss_date">
<DateTimePicker isDateOnly />
</Form.Item>
<Form.Item label={t("jobs.fields.kmin")} name="kmin">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm">
<Input />
</Form.Item>
<Form.Item
label={
<Space>
{t("jobs.fields.est_ct_fn")}
<JobsDetailChangeEstimator form={form} />
</Space>
}
name="est_ct_fn"
>
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.est_ct_ln")} name="est_ct_ln">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.est_ph1")} name="est_ph1">
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.est_ea")}
name="est_ea"
rules={[
{
type: "email",
message: "This is not a valid email address."
}
]}
>
<FormItemEmail email={getFieldValue("est_ea")} />
</Form.Item>
<Form.Item label={t("jobs.fields.selling_dealer")} name="selling_dealer">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.servicing_dealer")} name="servicing_dealer">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.selling_dealer_contact")} name="selling_dealer_contact">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.servicing_dealer_contact")} name="servicing_dealer_contact">
<Input />
</Form.Item> </Form.Item>
</LayoutFormRow> </LayoutFormRow>
) )
})} },
<LayoutFormRow> {
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab"> key: "claim",
<CurrencyInput /> label: t("menus.jobsdetail.claimdetail"),
</Form.Item> forceRender: true,
<Form.Item label={t("jobs.fields.rate_lad")} name="rate_lad"> children: (
<CurrencyInput /> <LayoutFormRow>
</Form.Item> <Form.Item label={t("jobs.fields.loss_desc")} name="loss_desc">
<Form.Item label={t("jobs.fields.rate_lae")} name="rate_lae"> <Input />
<CurrencyInput /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.loss_of_use")} name="loss_of_use">
<Form.Item label={t("jobs.fields.rate_lar")} name="rate_lar"> <Input />
<CurrencyInput /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.ponumber")} name="po_number">
<Form.Item label={t("jobs.fields.rate_las")} name="rate_las"> <Input />
<CurrencyInput /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.unitnumber")} name="unit_number">
<Form.Item label={t("jobs.fields.rate_laf")} name="rate_laf"> <Input />
<CurrencyInput /> </Form.Item>
</Form.Item> <Form.Item
<Form.Item label={t("jobs.fields.rate_lam")} name="rate_lam"> label={t("jobs.fields.specialcoveragepolicy")}
<CurrencyInput /> valuePropName="checked"
</Form.Item> name="special_coverage_policy"
<Form.Item label={t("jobs.fields.rate_lag")} name="rate_lag"> >
<CurrencyInput /> <Switch />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lau")} name="rate_lau"> <Form.Item label={t("jobs.fields.kmin")} name="kmin">
<CurrencyInput /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_la1")} name="rate_la1"> <Form.Item label={t("jobs.fields.kmout")} name="kmout">
<CurrencyInput /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_la2")} name="rate_la2"> <Form.Item label={t("jobs.fields.referralsource")} name="referral_source">
<CurrencyInput /> <Select>
</Form.Item> {bodyshop.md_referral_sources.map((s) => (
<Form.Item label={t("jobs.fields.rate_la3")} name="rate_la3"> <Select.Option key={s} value={s}>
<CurrencyInput /> {s}
</Form.Item> </Select.Option>
<Form.Item label={t("jobs.fields.rate_la4")} name="rate_la4"> ))}
<CurrencyInput /> </Select>
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_mapa")} name="rate_mapa"> <Form.Item label={t("jobs.fields.referral_source_extra")} name="referral_source_extra">
<CurrencyInput /> <Input />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_mash")} name="rate_mash"> </LayoutFormRow>
<CurrencyInput /> )
</Form.Item> },
<Form.Item label={t("jobs.fields.rate_mahw")} name="rate_mahw"> {
<CurrencyInput /> key: "financial",
</Form.Item> label: t("menus.jobsdetail.financials"),
<Form.Item label={t("jobs.fields.rate_ma2s")} name="rate_ma2s"> forceRender: true,
<CurrencyInput /> children: (
</Form.Item> <>
<Form.Item label={t("jobs.fields.rate_ma3s")} name="rate_ma3s"> <JobsDetailRatesChangeButton form={form} />
<CurrencyInput /> {InstanceRenderManager({
</Form.Item> imex: <JobsMarkPstExempt form={form} />
{ })}
// <Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl"> <LayoutFormRow>
// <CurrencyInput /> <Form.Item label={t("jobs.fields.ded_amt")} name="ded_amt">
// </Form.Item> <CurrencyInput min={0} />
// <Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs"> </Form.Item>
// <CurrencyInput /> <Form.Item label={t("jobs.fields.ded_status")} name="ded_status">
// </Form.Item> <Select allowClear>
} <Select.Option value="W">{t("jobs.labels.deductible.waived")}</Select.Option>
<Form.Item label={t("jobs.fields.rate_matd")} name="rate_matd"> <Select.Option value="Y">{t("jobs.labels.deductible.stands")}</Select.Option>
<CurrencyInput /> </Select>
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_laa")} name="rate_laa"> <Form.Item label={t("jobs.fields.depreciation_taxes")} name="depreciation_taxes">
<CurrencyInput /> <CurrencyInput />
</Form.Item> </Form.Item>
</LayoutFormRow> {bodyshop.region_config.toLowerCase().startsWith("ca") && (
</Collapse.Panel> <Form.Item
</Collapse> label={t("jobs.fields.ca_gst_registrant")}
name="ca_gst_registrant"
valuePropName="checked"
>
<Switch />
</Form.Item>
)}
<Form.Item label={t("jobs.fields.other_amount_payable")} name="other_amount_payable">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.towing_payable")} name="towing_payable">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.storage_payable")} name="storage_payable">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.adjustment_bottom_line")} name="adjustment_bottom_line">
<CurrencyInput />
</Form.Item>
</LayoutFormRow>
{InstanceRenderManager({
imex: (
<LayoutFormRow>
<Form.Item label={t("jobs.fields.federal_tax_rate")} name="federal_tax_rate">
<InputNumber min={0} max={1} precision={2} />
</Form.Item>
<Form.Item label={t("jobs.fields.state_tax_rate")} name="state_tax_rate">
<InputNumber min={0} max={1} precision={2} />
</Form.Item>
<Form.Item label={t("jobs.fields.local_tax_rate")} name="local_tax_rate">
<InputNumber min={0} max={1} precision={2} />
</Form.Item>
</LayoutFormRow>
)
})}
<LayoutFormRow>
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lad")} name="rate_lad">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lae")} name="rate_lae">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lar")} name="rate_lar">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_las")} name="rate_las">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_laf")} name="rate_laf">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lam")} name="rate_lam">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lag")} name="rate_lag">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lau")} name="rate_lau">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la1")} name="rate_la1">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la2")} name="rate_la2">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la3")} name="rate_la3">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la4")} name="rate_la4">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mapa")} name="rate_mapa">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mash")} name="rate_mash">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mahw")} name="rate_mahw">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma2s")} name="rate_ma2s">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma3s")} name="rate_ma3s">
<CurrencyInput />
</Form.Item>
{
// <Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl">
// <CurrencyInput />
// </Form.Item>
// <Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs">
// <CurrencyInput />
// </Form.Item>
}
<Form.Item label={t("jobs.fields.rate_matd")} name="rate_matd">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_laa")} name="rate_laa">
<CurrencyInput />
</Form.Item>
</LayoutFormRow>
</>
)
}
]}
/>
<JobsDetailRatesParts jobRO={false} expanded required={selected && true} form={form} /> <JobsDetailRatesParts jobRO={false} expanded required={selected && true} form={form} />
{InstanceRenderManager({ {InstanceRenderManager({
rome: ( rome: (

View File

@@ -14,6 +14,6 @@ export default function JobsCreateOwnerContainer() {
nextFetchPolicy: "network-only" nextFetchPolicy: "network-only"
}); });
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return <JobsCreateOwnerInfoComponent loading={loading} owners={data ? data.search_owners : null} />; return <JobsCreateOwnerInfoComponent loading={loading} owners={data ? data.search_owners : null} />;
} }

View File

@@ -14,7 +14,7 @@ export default function JobsCreateVehicleInfoContainer({ form }) {
nextFetchPolicy: "network-only" nextFetchPolicy: "network-only"
}); });
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return <JobsCreateVehicleInfoComponent loading={loading} vehicles={data ? data.search_vehicles : null} form={form} />; return <JobsCreateVehicleInfoComponent loading={loading} vehicles={data ? data.search_vehicles : null} form={form} />;
} }

View File

@@ -11,7 +11,7 @@ export default function JobsDetailLaborContainer({ jobId, techConsole, job }) {
nextFetchPolicy: "network-only" nextFetchPolicy: "network-only"
}); });
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<JobsDetailLaborComponent <JobsDetailLaborComponent

View File

@@ -41,7 +41,7 @@ export function JobsDetailPliComponent({
return ( return (
<div> <div>
<PartsOrderModal /> <PartsOrderModal />
{billsQuery.error ? <AlertComponent message={billsQuery.error.message} type="error" /> : null} {billsQuery.error ? <AlertComponent title={billsQuery.error.message} type="error" /> : null}
<BillDetailEditcontainer /> <BillDetailEditcontainer />
<Row gutter={[16, 16]}> <Row gutter={[16, 16]}>
<Col span={24}> <Col span={24}>

View File

@@ -13,152 +13,162 @@ export function JobsDetailRatesMaterials({ jobRO, expanded, form }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Collapse defaultActiveKey={expanded && "rates"}> <Collapse
<Collapse.Panel forceRender header={t("jobs.fields.materials.materials")} key="materials"> defaultActiveKey={expanded && "rates"}
<LayoutFormRow header={t("jobs.fields.materials.MAPA")}> items={[
<Form.Item label={t("jobs.fields.materials.cal_maxdlr")} name={["materials", "MAPA", "cal_maxdlr"]}> {
<InputNumber min={0} precision={2} disabled={jobRO} /> key: "materials",
</Form.Item> label: t("jobs.fields.materials.materials"),
<Form.Item label={t("jobs.fields.materials.cal_opcode")} name={["materials", "MAPA", "cal_opcode"]}> forceRender: true,
<Input disabled={jobRO} /> children: (
</Form.Item> <>
<Form.Item label={t("jobs.fields.materials.mat_adjp")} name={["materials", "MAPA", "mat_adjp"]}> <LayoutFormRow header={t("jobs.fields.materials.MAPA")}>
<InputNumber min={-100} max={100} precision={4} disabled={jobRO} /> <Form.Item label={t("jobs.fields.materials.cal_maxdlr")} name={["materials", "MAPA", "cal_maxdlr"]}>
</Form.Item> <InputNumber min={0} precision={2} disabled={jobRO} />
<Form.Item
label={t("jobs.fields.materials.tax_ind")}
name={["materials", "MAPA", "tax_ind"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item shouldUpdate>
{() => {
return (
<Form.Item
label={t("jobs.fields.materials.mat_taxp")}
name={["materials", "MAPA", "mat_taxp"]}
rules={[
{
required: form.getFieldValue(["materials", "MAPA", "tax_ind"])
//message: t("general.validation.required"),
}
]}
>
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
</Form.Item> </Form.Item>
); <Form.Item label={t("jobs.fields.materials.cal_opcode")} name={["materials", "MAPA", "cal_opcode"]}>
}} <Input disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in1")}
name={["materials", "MAPA", "mat_tx_in1"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in2")}
name={["materials", "MAPA", "mat_tx_in2"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in3")}
name={["materials", "MAPA", "mat_tx_in3"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in4")}
name={["materials", "MAPA", "mat_tx_in4"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in5")}
name={["materials", "MAPA", "mat_tx_in5"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("jobs.fields.materials.MASH")}>
<Form.Item label={t("jobs.fields.materials.cal_maxdlr")} name={["materials", "MASH", "cal_maxdlr"]}>
<InputNumber min={0} precision={2} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.materials.cal_opcode")} name={["materials", "MASH", "cal_opcode"]}>
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.materials.mat_adjp")} name={["materials", "MAPA", "mat_adjp"]}>
<InputNumber min={-100} max={100} precision={4} disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.tax_ind")}
name={["materials", "MASH", "tax_ind"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item shouldUpdate>
{() => {
return (
<Form.Item
label={t("jobs.fields.materials.mat_taxp")}
name={["materials", "MASH", "mat_taxp"]}
rules={[
{
required: form.getFieldValue(["materials", "MASH", "tax_ind"])
//message: t("general.validation.required"),
}
]}
>
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
</Form.Item> </Form.Item>
); <Form.Item label={t("jobs.fields.materials.mat_adjp")} name={["materials", "MAPA", "mat_adjp"]}>
}} <InputNumber min={-100} max={100} precision={4} disabled={jobRO} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.materials.mat_tx_in1")} label={t("jobs.fields.materials.tax_ind")}
name={["materials", "MASH", "mat_tx_in1"]} name={["materials", "MAPA", "tax_ind"]}
valuePropName="checked" valuePropName="checked"
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item <Form.Item shouldUpdate>
label={t("jobs.fields.materials.mat_tx_in2")} {() => {
name={["materials", "MASH", "mat_tx_in2"]} return (
valuePropName="checked" <Form.Item
> label={t("jobs.fields.materials.mat_taxp")}
<Switch /> name={["materials", "MAPA", "mat_taxp"]}
</Form.Item> rules={[
<Form.Item {
label={t("jobs.fields.materials.mat_tx_in3")} required: form.getFieldValue(["materials", "MAPA", "tax_ind"])
name={["materials", "MASH", "mat_tx_in3"]} //message: t("general.validation.required"),
valuePropName="checked" }
> ]}
<Switch /> >
</Form.Item> <InputNumber min={0} max={100} precision={4} disabled={jobRO} />
<Form.Item </Form.Item>
label={t("jobs.fields.materials.mat_tx_in4")} );
name={["materials", "MASH", "mat_tx_in4"]} }}
valuePropName="checked" </Form.Item>
> <Form.Item
<Switch /> label={t("jobs.fields.materials.mat_tx_in1")}
</Form.Item> name={["materials", "MAPA", "mat_tx_in1"]}
<Form.Item valuePropName="checked"
label={t("jobs.fields.materials.mat_tx_in5")} >
name={["materials", "MASH", "mat_tx_in5"]} <Switch />
valuePropName="checked" </Form.Item>
> <Form.Item
<Switch /> label={t("jobs.fields.materials.mat_tx_in2")}
</Form.Item> name={["materials", "MAPA", "mat_tx_in2"]}
</LayoutFormRow> valuePropName="checked"
</Collapse.Panel> >
</Collapse> <Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in3")}
name={["materials", "MAPA", "mat_tx_in3"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in4")}
name={["materials", "MAPA", "mat_tx_in4"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in5")}
name={["materials", "MAPA", "mat_tx_in5"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("jobs.fields.materials.MASH")}>
<Form.Item label={t("jobs.fields.materials.cal_maxdlr")} name={["materials", "MASH", "cal_maxdlr"]}>
<InputNumber min={0} precision={2} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.materials.cal_opcode")} name={["materials", "MASH", "cal_opcode"]}>
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.materials.mat_adjp")} name={["materials", "MAPA", "mat_adjp"]}>
<InputNumber min={-100} max={100} precision={4} disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.tax_ind")}
name={["materials", "MASH", "tax_ind"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item shouldUpdate>
{() => {
return (
<Form.Item
label={t("jobs.fields.materials.mat_taxp")}
name={["materials", "MASH", "mat_taxp"]}
rules={[
{
required: form.getFieldValue(["materials", "MASH", "tax_ind"])
//message: t("general.validation.required"),
}
]}
>
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
</Form.Item>
);
}}
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in1")}
name={["materials", "MASH", "mat_tx_in1"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in2")}
name={["materials", "MASH", "mat_tx_in2"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in3")}
name={["materials", "MASH", "mat_tx_in3"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in4")}
name={["materials", "MASH", "mat_tx_in4"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.materials.mat_tx_in5")}
name={["materials", "MASH", "mat_tx_in5"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
</LayoutFormRow>
</>
)
}
]}
/>
); );
} }

View File

@@ -10,83 +10,93 @@ export function JobsDetailRatesOther({ expanded }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Collapse defaultActiveKey={expanded && "rates"}> <Collapse
<Collapse.Panel forceRender header={t("jobs.labels.cieca_pfo")} key="cieca_pfo"> defaultActiveKey={expanded && "rates"}
<LayoutFormRow noDivider> items={[
<Form.Item {
label={t("jobs.fields.cieca_pfo.tow_t_in1")} key: "cieca_pfo",
name={["cieca_pfo", "tow_t_in1"]} label: t("jobs.labels.cieca_pfo"),
valuePropName="checked" forceRender: true,
> children: (
<Switch /> <>
</Form.Item> <LayoutFormRow noDivider>
<Form.Item <Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in2")} label={t("jobs.fields.cieca_pfo.tow_t_in1")}
name={["cieca_pfo", "tow_t_in2"]} name={["cieca_pfo", "tow_t_in1"]}
valuePropName="checked" valuePropName="checked"
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in3")} label={t("jobs.fields.cieca_pfo.tow_t_in2")}
name={["cieca_pfo", "tow_t_in3"]} name={["cieca_pfo", "tow_t_in2"]}
valuePropName="checked" valuePropName="checked"
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in4")} label={t("jobs.fields.cieca_pfo.tow_t_in3")}
name={["cieca_pfo", "tow_t_in4"]} name={["cieca_pfo", "tow_t_in3"]}
valuePropName="checked" valuePropName="checked"
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in5")} label={t("jobs.fields.cieca_pfo.tow_t_in4")}
name={["cieca_pfo", "tow_t_in5"]} name={["cieca_pfo", "tow_t_in4"]}
valuePropName="checked" valuePropName="checked"
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in5")}
name={["cieca_pfo", "tow_t_in5"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in1")} label={t("jobs.fields.cieca_pfo.stor_t_in1")}
name={["cieca_pfo", "stor_t_in1"]} name={["cieca_pfo", "stor_t_in1"]}
valuePropName="checked" valuePropName="checked"
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in2")} label={t("jobs.fields.cieca_pfo.stor_t_in2")}
name={["cieca_pfo", "stor_t_in2"]} name={["cieca_pfo", "stor_t_in2"]}
valuePropName="checked" valuePropName="checked"
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in3")} label={t("jobs.fields.cieca_pfo.stor_t_in3")}
name={["cieca_pfo", "stor_t_in3"]} name={["cieca_pfo", "stor_t_in3"]}
valuePropName="checked" valuePropName="checked"
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in4")} label={t("jobs.fields.cieca_pfo.stor_t_in4")}
name={["cieca_pfo", "stor_t_in4"]} name={["cieca_pfo", "stor_t_in4"]}
valuePropName="checked" valuePropName="checked"
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in5")} label={t("jobs.fields.cieca_pfo.stor_t_in5")}
name={["cieca_pfo", "stor_t_in5"]} name={["cieca_pfo", "stor_t_in5"]}
valuePropName="checked" valuePropName="checked"
> >
<Switch /> <Switch />
</Form.Item> </Form.Item>
</LayoutFormRow> </LayoutFormRow>
</Collapse.Panel> </>
</Collapse> )
}
]}
/>
); );
} }

View File

@@ -47,11 +47,17 @@ export function JobsDetailRatesTaxes({ jobRO, expanded, bodyshop }) {
); );
} }
return ( return (
<Collapse defaultActiveKey={expanded && "rates"}> <Collapse
<Collapse.Panel forceRender header={t("jobs.labels.cieca_pft")} key="cieca_pft"> defaultActiveKey={expanded && "rates"}
{formItems} items={[
</Collapse.Panel> {
</Collapse> key: "cieca_pft",
label: t("jobs.labels.cieca_pft"),
forceRender: true,
children: formItems
}
]}
/>
); );
} }

View File

@@ -48,7 +48,7 @@ export function JobsDocumentsContainer({
}); });
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent type="error" message={error.message} />; if (error) return <AlertComponent type="error" title={error.message} />;
if (Imgproxy.treatment === "on") { if (Imgproxy.treatment === "on") {
return ( return (

View File

@@ -21,7 +21,7 @@ export default function JobsDocumentsImgproxyContainer({ jobId, billId, document
}); });
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent type="error" message={error.message} />; if (error) return <AlertComponent type="error" title={error.message} />;
return ( return (
<JobDocuments <JobDocuments

View File

@@ -133,7 +133,7 @@ export function JobsDocumentsLocalGallery({
<Col span={24}> <Col span={24}>
<Card title={t("jobs.labels.documents-images")}> <Card title={t("jobs.labels.documents-images")}>
{optimized && ( {optimized && (
<Alert style={{ margin: "4px" }} message={t("documents.labels.optimizedimage")} type="success" /> <Alert style={{ margin: "4px" }} title={t("documents.labels.optimizedimage")} type="success" />
)} )}
<LocalMediaGrid <LocalMediaGrid
images={jobMedia.images} images={jobMedia.images}

View File

@@ -69,7 +69,7 @@ export default connect(
{...modalProps} {...modalProps}
> >
{loading ? <LoadingSpinner /> : null} {loading ? <LoadingSpinner /> : null}
{error ? <AlertComponent message={error.message} type="error" /> : null} {error ? <AlertComponent title={error.message} type="error" /> : null}
<JobsFindModalComponent <JobsFindModalComponent
selectedJob={selectedJob} selectedJob={selectedJob}
setSelectedJob={setSelectedJob} setSelectedJob={setSelectedJob}

View File

@@ -46,7 +46,7 @@ export function JobsList({ bodyshop }) {
const history = useNavigate(); const history = useNavigate();
const [searchText, setSearchText] = useState(""); const [searchText, setSearchText] = useState("");
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
const jobs = data const jobs = data
? searchText === "" ? searchText === ""

View File

@@ -53,7 +53,7 @@ export function JobNotesContainer({ jobId, insertAuditTrail }) {
}; };
//if (loading) return <SpinComponent />; //if (loading) return <SpinComponent />;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<JobNotesComponent <JobNotesComponent
jobId={jobId} jobId={jobId}

View File

@@ -53,7 +53,7 @@ export function JobsReadyList({ bodyshop }) {
const history = useNavigate(); const history = useNavigate();
const [searchText, setSearchText] = useState(""); const [searchText, setSearchText] = useState("");
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
const jobs = data const jobs = data
? searchText === "" ? searchText === ""

View File

@@ -264,7 +264,7 @@ export function LaborAllocationsTable({
</Col> </Col>
)} )}
{showWarning && Math.abs(summary.difference.toFixed(1)) !== 0 && ( {showWarning && Math.abs(summary.difference.toFixed(1)) !== 0 && (
<Alert style={{ margin: "8px 0px" }} type="warning" message={t("jobs.labels.outstandinghours")} /> <Alert style={{ margin: "8px 0px" }} type="warning" title={t("jobs.labels.outstandinghours")} />
)} )}
</Row> </Row>
); );

View File

@@ -304,7 +304,7 @@ export function PayrollLaborAllocationsTable({
</Col> </Col>
)} )}
{showWarning && summary.difference !== 0 && ( {showWarning && summary.difference !== 0 && (
<Alert style={{ margin: "8px 0px" }} type="warning" message={t("jobs.labels.outstandinghours")} /> <Alert style={{ margin: "8px 0px" }} type="warning" title={t("jobs.labels.outstandinghours")} />
)} )}
</Row> </Row>
); );

View File

@@ -113,7 +113,7 @@ const NotificationCenterComponent = forwardRef(
</div> </div>
{!isEmployee ? ( {!isEmployee ? (
<div style={{ padding: 10 }}> <div style={{ padding: 10 }}>
<Alert message={t("notifications.labels.employee-notification")} type="warning" /> <Alert title={t("notifications.labels.employee-notification")} type="warning" />
</div> </div>
) : ( ) : (
<Virtuoso <Virtuoso

View File

@@ -123,7 +123,7 @@ const NotificationSettingsForm = ({ currentUser, bodyshop }) => {
setIsDirty(false); setIsDirty(false);
}; };
if (error) return <AlertComponent type="error" message={error.message} />; if (error) return <AlertComponent type="error" title={error.message} />;
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
const columns = [ const columns = [
@@ -201,7 +201,7 @@ const NotificationSettingsForm = ({ currentUser, bodyshop }) => {
> >
{!isEmployee && ( {!isEmployee && (
<div style={{ width: "100%", marginBottom: "10px" }}> <div style={{ width: "100%", marginBottom: "10px" }}>
<Alert message={t("notifications.labels.employee-notification")} type="warning" /> <Alert title={t("notifications.labels.employee-notification")} type="warning" />
</div> </div>
)} )}
<Table dataSource={dataSource} columns={columns} pagination={false} bordered rowKey="key" /> <Table dataSource={dataSource} columns={columns} pagination={false} bordered rowKey="key" />

View File

@@ -45,7 +45,7 @@ export default function OwnerFindModalContainer({
{...modalProps} {...modalProps}
> >
{loading ? <LoadingSpinner /> : null} {loading ? <LoadingSpinner /> : null}
{error ? <AlertComponent message={error.message} type="error" /> : null} {error ? <AlertComponent title={error.message} type="error" /> : null}
{owner ? ( {owner ? (
<> <>
<Input.Search <Input.Search

View File

@@ -56,14 +56,15 @@ const OwnerSearchSelect = ({ value, onChange, onBlur, disabled }, ref) => {
<Select <Select
ref={ref} ref={ref}
disabled={disabled} disabled={disabled}
showSearch showSearch={{
filterOption: false,
onSearch: handleSearch
}}
autoFocus autoFocus
value={option} value={option}
style={{ style={{
width: "100%" width: "100%"
}} }}
filterOption={false}
onSearch={handleSearch}
// onChange={setOption} // onChange={setOption}
onChange={handleSelect} onChange={handleSelect}
onSelect={handleSelect} onSelect={handleSelect}
@@ -79,8 +80,8 @@ const OwnerSearchSelect = ({ value, onChange, onBlur, disabled }, ref) => {
: null} : null}
</Select> </Select>
{idLoading || loading ? <LoadingOutlined /> : null} {idLoading || loading ? <LoadingOutlined /> : null}
{error ? <AlertComponent message={error.message} type="error" /> : null} {error ? <AlertComponent title={error.message} type="error" /> : null}
{idError ? <AlertComponent message={idError.message} type="error" /> : null} {idError ? <AlertComponent title={idError.message} type="error" /> : null}
</div> </div>
); );
}; };

View File

@@ -24,7 +24,7 @@ export default function OwnersListContainer() {
} }
}); });
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<OwnersListComponent <OwnersListComponent
loading={loading} loading={loading}

View File

@@ -2,6 +2,7 @@ import { DownOutlined } from "@ant-design/icons";
import { Dropdown, InputNumber, Space } from "antd"; import { Dropdown, InputNumber, Space } from "antd";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { logImEXEvent } from "../../firebase/firebase.utils"; import { logImEXEvent } from "../../firebase/firebase.utils";
export default function PartsOrderModalPriceChange({ form, field }) { export default function PartsOrderModalPriceChange({ form, field }) {
const { t } = useTranslation(); const { t } = useTranslation();
const menu = { const menu = {

View File

@@ -334,7 +334,7 @@ export function PartsOrderModalContainer({
width="75%" width="75%"
forceRender forceRender
> >
{error ? <AlertComponent message={error.message} type="error" /> : null} {error ? <AlertComponent title={error.message} type="error" /> : null}
<Form form={form} layout="vertical" autoComplete="no" onFinish={handleFinish} initialValues={initialValues}> <Form form={form} layout="vertical" autoComplete="no" onFinish={handleFinish} initialValues={initialValues}>
{loading ? ( {loading ? (
<LoadingSpinner /> <LoadingSpinner />

View File

@@ -50,7 +50,7 @@ export default function PartsQueueDetailCard() {
return ( return (
<Drawer open={!!selected} destroyOnHidden width={drawerPercentage} placement="right" onClose={handleDrawerClose}> <Drawer open={!!selected} destroyOnHidden width={drawerPercentage} placement="right" onClose={handleDrawerClose}>
{loading ? <LoadingSpinner /> : null} {loading ? <LoadingSpinner /> : null}
{error ? <AlertComponent message={error.message} type="error" /> : null} {error ? <AlertComponent title={error.message} type="error" /> : null}
{data ? ( {data ? (
<Card <Card
title={ title={

View File

@@ -44,7 +44,7 @@ export function PartsQueueListComponent({ bodyshop }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [searchText, setSearchText] = useState(""); const [searchText, setSearchText] = useState("");
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
const jobs = data const jobs = data
? searchText === "" ? searchText === ""

View File

@@ -45,7 +45,7 @@ export default function PartsShopInfoContainer() {
if (data) form.resetFields(); if (data) form.resetFields();
}, [form, data]); }, [form, data]);
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
return ( return (

View File

@@ -17,7 +17,7 @@ export default function PaymentFormTotalPayments({ jobid }) {
}); });
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
if (!data) return <></>; if (!data) return <></>;
const totalPayments = data.jobs_by_pk.payments.reduce((acc, val) => { const totalPayments = data.jobs_by_pk.payments.reduce((acc, val) => {

View File

@@ -132,7 +132,7 @@ function PhonebookFormContainer({ refetch, bodyshop }) {
}, [data, form, phonebookentry]); }, [data, form, phonebookentry]);
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<Form <Form

View File

@@ -132,7 +132,7 @@ export function ProductionListDetail({ bodyshop, jobs, setPrintCenterContext, te
open={selected} open={selected}
> >
{loading && <LoadingSkeleton />} {loading && <LoadingSkeleton />}
{error && <AlertComponent error={JSON.stringify(error)} />} {error && <AlertComponent title={JSON.stringify(error)} type="error" />}
{!loading && data && ( {!loading && data && (
<div> <div>
<CardTemplate title={t("jobs.labels.employeeassignments")} loading={loading}> <CardTemplate title={t("jobs.labels.employeeassignments")} loading={loading}>

View File

@@ -219,7 +219,7 @@ export function ProductionListTable({ loading, data, refetch, bodyshop, technici
{hasUnsavedChanges && ( {hasUnsavedChanges && (
<AlertComponent <AlertComponent
type="warning" type="warning"
message={ title={
<div> <div>
<span>{t("general.messages.unsavedchanges")} </span> <span>{t("general.messages.unsavedchanges")} </span>
<span <span

View File

@@ -59,7 +59,7 @@ export function ProfileShopsContainer({ bodyshop, currentUser }) {
window.location.reload(); window.location.reload();
}; };
if (error) return <AlertComponent type="error" message={error.message} />; if (error) return <AlertComponent type="error" title={error.message} />;
return ( return (
<ProfileShopsComponent <ProfileShopsComponent
loading={loading} loading={loading}

View File

@@ -21,7 +21,7 @@ function RbacWrapper({ authLevel, bodyshop, requiredAuthLevel, noauth, children,
return children; return children;
//return <div>{React.cloneElement(children, restProps)}</div>; //return <div>{React.cloneElement(children, restProps)}</div>;
return noauth || <AlertComponent message={t("general.messages.rbacunauth")} type="warning" />; return noauth || <AlertComponent title={t("general.messages.rbacunauth")} type="warning" />;
} }
export function HasRbacAccess({ authLevel, bodyshop, requiredAuthLevel, action }) { export function HasRbacAccess({ authLevel, bodyshop, requiredAuthLevel, action }) {

View File

@@ -80,40 +80,46 @@ export function ScheduleCalendarWrapperComponent({
{HasFeatureAccess({ featureName: "smartscheduling", bodyshop }) && {HasFeatureAccess({ featureName: "smartscheduling", bodyshop }) &&
problemJobs && problemJobs &&
(problemJobs.length > 2 ? ( (problemJobs.length > 2 ? (
<Collapse style={{ marginBottom: "5px" }}> <Collapse
<Collapse.Panel style={{ marginBottom: "5px" }}
key="1" items={[
header={ {
<span style={{ color: "var(--error-header-text)" }}>{t("appointments.labels.severalerrorsfound")}</span> key: "1",
} label: (
> <span style={{ color: "var(--error-header-text)" }}>
<Space orientation="vertical" style={{ width: "100%" }}> {t("appointments.labels.severalerrorsfound")}
{problemJobs.map((problem) => ( </span>
<Alert ),
key={problem.id} children: (
type="error" <Space orientation="vertical" style={{ width: "100%" }}>
message={ {problemJobs.map((problem) => (
<Trans <Alert
i18nKey="appointments.labels.dataconsistency" key={problem.id}
components={[<Link key={problem.id} to={`/manage/jobs/${problem.id}`} target="_blank" />]} type="error"
values={{ title={
ro_number: problem.ro_number, <Trans
code: problem.code i18nKey="appointments.labels.dataconsistency"
}} components={[<Link key={problem.id} to={`/manage/jobs/${problem.id}`} target="_blank" />]}
values={{
ro_number: problem.ro_number,
code: problem.code
}}
/>
}
/> />
} ))}
/> </Space>
))} )
</Space> }
</Collapse.Panel> ]}
</Collapse> />
) : ( ) : (
<Space orientation="vertical" style={{ width: "100%", marginBottom: "5px" }}> <Space orientation="vertical" style={{ width: "100%", marginBottom: "5px" }}>
{problemJobs.map((problem) => ( {problemJobs.map((problem) => (
<Alert <Alert
key={problem.id} key={problem.id}
type="error" type="error"
message={ title={
<Trans <Trans
i18nKey="appointments.labels.dataconsistency" i18nKey="appointments.labels.dataconsistency"
components={[<Link key={problem.id} to={`/manage/jobs/${problem.id}`} target="_blank" />]} components={[<Link key={problem.id} to={`/manage/jobs/${problem.id}`} target="_blank" />]}

View File

@@ -42,7 +42,7 @@ export function ScheduleCalendarContainer({ calculateScheduleLoad }) {
}, [data, range, calculateScheduleLoad]); }, [data, range, calculateScheduleLoad]);
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
let normalizedData = [ let normalizedData = [
...data.appointments.map((e) => { ...data.appointments.map((e) => {
//Required because Hasura returns a string instead of a date object. //Required because Hasura returns a string instead of a date object.

View File

@@ -7,7 +7,7 @@ import { DateTimeFormatter } from "../../utils/DateFormatter";
export default function ScheduleExistingAppointmentsList({ existingAppointments }) { export default function ScheduleExistingAppointmentsList({ existingAppointments }) {
const { t } = useTranslation(); const { t } = useTranslation();
if (existingAppointments.loading) return <LoadingSpinner />; if (existingAppointments.loading) return <LoadingSpinner />;
if (existingAppointments.error) return <AlertComponent message={existingAppointments.error.message} type="error" />; if (existingAppointments.error) return <AlertComponent title={existingAppointments.error.message} type="error" />;
return ( return (
<div> <div>

View File

@@ -19,7 +19,7 @@ export default function ScheduleProductionList() {
<Card> <Card>
<div onClick={(e) => e.stopPropagation()} className="jobs-in-production-table"> <div onClick={(e) => e.stopPropagation()} className="jobs-in-production-table">
{loading ? <LoadingSkeleton /> : null} {loading ? <LoadingSkeleton /> : null}
{error ? <AlertComponent message={error.message} type="error" /> : null} {error ? <AlertComponent title={error.message} type="error" /> : null}
{data ? ( {data ? (
<table> <table>
<tbody> <tbody>

View File

@@ -119,7 +119,7 @@ export default function ScoreboardJobsList() {
})) }))
} }
> >
{error && <AlertComponent type="error" message={JSON.stringify(error)} />} {error && <AlertComponent type="error" title={JSON.stringify(error)} />}
<Card <Card
extra={ extra={
<Space align="middle" wrap> <Space align="middle" wrap>

View File

@@ -293,7 +293,7 @@ export function ScoreboardTimeTicketsStats({ bodyshop }) {
}; };
}, [fixedPeriods, data, bodyshop]); }, [fixedPeriods, data, bodyshop]);
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
return ( return (
<Row gutter={[16, 16]}> <Row gutter={[16, 16]}>

View File

@@ -219,7 +219,7 @@ export default function ScoreboardTimeTickets() {
}; };
}, [fixedPeriods, data, startDate, endDate]); }, [fixedPeriods, data, startDate, endDate]);
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
return ( return (
<Row gutter={[16, 16]}> <Row gutter={[16, 16]}>

View File

@@ -19,7 +19,7 @@ export default function ShopCsiConfig() {
const { t } = useTranslation(); const { t } = useTranslation();
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<div> <div>
<Row> <Row>

View File

@@ -113,7 +113,7 @@ export function ShopEmployeesFormComponent({ bodyshop }) {
}; };
if (!search.employeeId) return null; if (!search.employeeId) return null;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
const columns = [ const columns = [
{ {

View File

@@ -15,7 +15,7 @@ function ShopEmployeesContainer() {
nextFetchPolicy: "network-only" nextFetchPolicy: "network-only"
}); });
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<div> <div>

View File

@@ -68,7 +68,7 @@ export default function ShopInfoContainer() {
preserveHiddenFormData(); preserveHiddenFormData();
}, [data, form, preserveHiddenFormData]); }, [data, form, preserveHiddenFormData]);
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
if (loading) return <LoadingSpinner />; if (loading) return <LoadingSpinner />;
return ( return (
<Form <Form

View File

@@ -168,7 +168,6 @@ export default function ShopInfoPartsScan({ form }) {
label={t("bodyshop.fields.md_parts_scan.caseInsensitive")} label={t("bodyshop.fields.md_parts_scan.caseInsensitive")}
name={[field.name, "caseInsensitive"]} name={[field.name, "caseInsensitive"]}
valuePropName="checked" valuePropName="checked"
initialValue={true}
labelCol={{ span: 14 }} labelCol={{ span: 14 }}
wrapperCol={{ span: 10 }} wrapperCol={{ span: 10 }}
> >
@@ -183,7 +182,6 @@ export default function ShopInfoPartsScan({ form }) {
label={t("bodyshop.fields.md_parts_scan.mark_critical")} label={t("bodyshop.fields.md_parts_scan.mark_critical")}
name={[field.name, "mark_critical"]} name={[field.name, "mark_critical"]}
valuePropName="checked" valuePropName="checked"
initialValue={true}
labelCol={{ span: 14 }} labelCol={{ span: 14 }}
wrapperCol={{ span: 10 }} wrapperCol={{ span: 10 }}
> >
@@ -242,7 +240,14 @@ export default function ShopInfoPartsScan({ form }) {
<Form.Item> <Form.Item>
<Button <Button
type="dashed" type="dashed"
onClick={() => add({ field: "line_desc", operation: "contains" })} onClick={() =>
add({
field: "line_desc",
operation: "contains",
mark_critical: true,
caseInsensitive: true
})
}
style={{ width: "100%" }} style={{ width: "100%" }}
> >
{t("bodyshop.actions.addpartsrule")} {t("bodyshop.actions.addpartsrule")}

View File

@@ -25,7 +25,7 @@ export function ShopInfoIntellipay({ bodyshop, form }) {
const { intellipay_config } = form.getFieldsValue(); const { intellipay_config } = form.getFieldsValue();
if (intellipay_config?.enable_cash_discount) if (intellipay_config?.enable_cash_discount)
return <Alert message={t("bodyshop.labels.intellipay_cash_discount")} />; return <Alert title={t("bodyshop.labels.intellipay_cash_discount")} />;
}} }}
</Form.Item> </Form.Item>

View File

@@ -112,7 +112,7 @@ export function ShopEmployeeTeamsFormComponent({ bodyshop }) {
}; };
if (!search.employeeTeamId) return null; if (!search.employeeTeamId) return null;
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<Card <Card

View File

@@ -16,7 +16,7 @@ function ShopTeamsContainer() {
nextFetchPolicy: "network-only" nextFetchPolicy: "network-only"
}); });
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
return ( return (
<div> <div>

View File

@@ -19,7 +19,7 @@ export default function ShopTemplatesListContainer({ openState }) {
const { t } = useTranslation(); const { t } = useTranslation();
const search = queryString.parse(useLocation().search); const search = queryString.parse(useLocation().search);
const history = useNavigate(); const history = useNavigate();
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent title={error.message} type="error" />;
const handleEdit = (record) => { const handleEdit = (record) => {
if (record) { if (record) {

View File

@@ -62,7 +62,7 @@ export function ShopInfoUsersComponent({ bodyshop }) {
]; ];
if (error) { if (error) {
return <AlertComponent type="error" message={JSON.stringify(error)} />; return <AlertComponent type="error" title={JSON.stringify(error)} />;
} }
return ( return (
<div> <div>

Some files were not shown because too many files have changed in this diff Show More