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", () => {
it("renders with default props", () => {
render(<AlertComponent message="Default Alert" />);
render(<AlertComponent title="Default Alert" />);
expect(screen.getByText("Default Alert")).toBeInTheDocument();
expect(screen.getByRole("alert")).toHaveClass("ant-alert");
});
it("applies type prop correctly", () => {
render(<AlertComponent message="Success Alert" type="success" />);
render(<AlertComponent title="Success Alert" type="success" />);
const alert = screen.getByRole("alert");
expect(screen.getByText("Success Alert")).toBeInTheDocument();
expect(alert).toHaveClass("ant-alert-success");
});
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("Something went wrong")).toBeInTheDocument();
expect(screen.getByRole("alert")).toHaveClass("ant-alert-error");
});
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.getByRole("button", { name: /close/i })).toBeInTheDocument(); // Close button
});

View File

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

View File

@@ -148,7 +148,7 @@ export function BillDetailEditcontainer({ insertAuditTrail, bodyshop }) {
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>;
const exported = data?.bills_by_pk && data.bills_by_pk.exported;

View File

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

View File

@@ -67,7 +67,7 @@ export default function BillsVendorsList() {
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
? data.vendors.filter(

View File

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

View File

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

View File

@@ -63,7 +63,7 @@ export function ChatMediaSelector({ bodyshop, selectedMedia, setSelectedMedia, c
const content = (
<div className="media-selector-content">
{loading && <LoadingSpinner />}
{error && <AlertComponent message={error.message} type="error" />}
{error && <AlertComponent title={error.message} type="error" />}
{selectedMedia.filter((s) => s.isSelected).length >= 10 ? (
<div className="error-message">{t("messaging.labels.maxtenimages")}</div>
) : 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.
// (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",
nextFetchPolicy: "network-only",
skip: chatVisible || socket?.connected,
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);
}
pollInterval: socket?.connected ? 0 : 60 * 1000
});
// 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
useEffect(() => {
const handleSocketStatus = () => {

View File

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

View File

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

View File

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

View File

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

View File

@@ -156,7 +156,7 @@ export function DashboardGridComponent({ currentUser }) {
);
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) => {
logImEXEvent("dashboard_change_layout");

View File

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

View File

@@ -331,10 +331,10 @@ export function RrAllocationsSummary({ socket, bodyshop, jobId, title, onAllocat
}
>
{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} />
</Card>

View File

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

View File

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

View File

@@ -51,7 +51,7 @@ export function DocumentEditorContainer({ setBodyshop }) {
}, [dataShop, setBodyshop]);
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 (imageUrl && filename && jobid) {
@@ -66,7 +66,7 @@ export function DocumentEditorContainer({ setBodyshop }) {
}
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")} />;
return (

View File

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

View File

@@ -9,7 +9,7 @@ import AlertComponent from "../alert/alert.component";
const EmployeeTeamSearchSelect = ({ ...props }) => {
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 (
<Select
showSearch

View File

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

View File

@@ -56,7 +56,7 @@ function FeatureWrapper({
return (
noauth || (
<AlertComponent
message={t("general.messages.nofeatureaccess", {
title={t("general.messages.nofeatureaccess", {
app: InstanceRenderManager({
imex: "$t(titles.imexonline)",
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")} />
<AlertComponent
type="warning"
message={
title={
<div>
<span>{t("general.messages.unsavedchanges")} </span>
<span
@@ -39,7 +39,7 @@ export default function FormsFieldChanged({ form, skipPrompt }) {
{errors.length > 0 && (
<AlertComponent
type="error"
message={
title={
<div>
<ul>{errors.map((e, idx) => e.errors.map((e2, idx2) => <li key={`${idx}${idx2}`}>{e2}</li>))}</ul>
</div>

View File

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

View File

@@ -46,7 +46,7 @@ export default function GlobalSearchOs() {
value: job.ro_number || "N/A",
label: (
<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>
<span>{`${job.status || ""}`}</span>
<span>
@@ -69,7 +69,7 @@ export default function GlobalSearchOs() {
value: OwnerNameDisplayFunction(owner),
label: (
<Link to={`/manage/owners/${owner.id}`}>
<Space size="small" split={<Divider type="vertical" />} wrap>
<Space size="small" split={<Divider orientation="vertical" />} wrap>
<span>
<OwnerNameDisplay ownerObject={owner} />
</span>
@@ -89,7 +89,7 @@ export default function GlobalSearchOs() {
value: `${vehicle.v_model_yr || ""} ${vehicle.v_make_desc || ""} ${vehicle.v_model_desc || ""}`,
label: (
<Link to={`/manage/vehicles/${vehicle.id}`}>
<Space size="small" split={<Divider type="vertical" />}>
<Space size="small" split={<Divider orientation="vertical" />}>
<span>
{`${vehicle.v_model_yr || ""} ${vehicle.v_make_desc || ""} ${vehicle.v_model_desc || ""}`}
</span>
@@ -111,7 +111,7 @@ export default function GlobalSearchOs() {
value: `${payment.job?.ro_number} ${payment.amount}`,
label: (
<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.job?.ro_number}</span>
<span>{payment.memo || ""}</span>
@@ -131,7 +131,7 @@ export default function GlobalSearchOs() {
value: `${bill.invoice_number} - ${bill.vendor.name}`,
label: (
<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.vendor.name}</span>
<span>{bill.date}</span>
@@ -151,7 +151,7 @@ export default function GlobalSearchOs() {
// }`,
// label: (
// <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 || ""} ${
// pb.company || ""
// }`}</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 (
<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 (
<InventoryListPaginated
refetch={refetch}

View File

@@ -33,7 +33,7 @@ export function JobBillsTotalComponent({
if (showWarning && warningCallback && typeof warningCallback === "function") {
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;
@@ -264,7 +264,7 @@ export function JobBillsTotalComponent({
<Alert
style={{ margin: "8px 0px" }}
type="warning"
message={t("jobs.labels.outstanding_reconciliation_discrep")}
title={t("jobs.labels.outstanding_reconciliation_discrep")}
/>
)}
</Card>
@@ -337,7 +337,7 @@ export function JobBillsTotalComponent({
</Tooltip>
</Space>
{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>
</Col>

View File

@@ -30,7 +30,7 @@ export function JobCloseRoGuardLabor({ job, bodyshop, warningCallback }) {
});
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" ? (
<PayrollLaborAllocationsTable

View File

@@ -49,7 +49,7 @@ export function JobCloseRoGuardProfit({ job, warningCallback }) {
{balance.toFormat()}
</DataLabel>
{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>
);

View File

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

View File

@@ -66,164 +66,176 @@ export function JobCloseRoGuardContainer({ job, jobRO, bodyshop, form }) {
</Card>
)}
<Collapse>
<Collapse.Panel forceRender key="roguard" header={t("jobs.labels.roguard")}>
<Row gutter={[32, 32]}>
<Col span={24}>
<JobCloseRoGuardBills job={job} form={form} warningCallback={warningCallback} />
</Col>
<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} />
<Collapse
items={[
{
key: "roguard",
label: t("jobs.labels.roguard"),
forceRender: true,
children: (
<>
<Row gutter={[32, 32]}>
<Col span={24}>
<JobCloseRoGuardBills job={job} form={form} warningCallback={warningCallback} />
</Col>
<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>
</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")}>
<Table dataSource={linesWithPPD} columns={columns} pagination={false} rowKey="id" bordered size="small" />
{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>
);

View File

@@ -54,7 +54,7 @@ export function JobCloseRoGuardProfit({ job, bodyshop, warningCallback }) {
<Card title={t("jobs.labels.profits")} style={{ height: "100%" }}>
<JobCostingStatistics summaryData={costingData?.summaryData} onlyGP />
{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>
);

View File

@@ -64,7 +64,7 @@ export function JobCloseRGuardSublet({ job, warningCallback }) {
<Card title={t("jobs.labels.subletsnotcompleted")}>
<Table dataSource={subletsNotDone} columns={columns} pagination={false} rowKey="id" bordered size="small" />
{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>
);

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,6 +11,6 @@ export default function JobProfileDataWarning({ job }) {
Object.keys(job.materials).length === 0;
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;
}

View File

@@ -47,7 +47,7 @@ function JobReconciliationModalContainer({ reconciliationModal, toggleModalVisib
className="imex-reconciliation-modal"
>
{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} />}
</Modal>
);

View File

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

View File

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

View File

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

View File

@@ -382,7 +382,7 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail
if (availableJobId && clm_no) addJobAsSupp({ id: availableJobId, clm_no: 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 (
<LoadingSpinner loading={insertLoading} message={t("jobs.labels.creating_new_job")}>

View File

@@ -41,282 +41,306 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
return (
<div>
<Collapse defaultActiveKey="insurance">
<Collapse.Panel key="insurance" header={t("menus.jobsdetail.insurance")} forceRender>
<LayoutFormRow>
<Form.Item label={t("jobs.fields.clm_no")} name="clm_no">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.policy_no")} name="policy_no">
<Input />
</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: (
<Collapse
defaultActiveKey="insurance"
items={[
{
key: "insurance",
label: t("menus.jobsdetail.insurance"),
forceRender: true,
children: (
<LayoutFormRow>
<Form.Item label={t("jobs.fields.federal_tax_rate")} name="federal_tax_rate">
<InputNumber min={0} max={1} precision={2} />
<Form.Item label={t("jobs.fields.clm_no")} name="clm_no">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.state_tax_rate")} name="state_tax_rate">
<InputNumber min={0} max={1} precision={2} />
<Form.Item label={t("jobs.fields.policy_no")} name="policy_no">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.local_tax_rate")} name="local_tax_rate">
<InputNumber min={0} max={1} precision={2} />
<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>
)
})}
<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>
</Collapse.Panel>
</Collapse>
},
{
key: "claim",
label: t("menus.jobsdetail.claimdetail"),
forceRender: true,
children: (
<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>
)
},
{
key: "financial",
label: t("menus.jobsdetail.financials"),
forceRender: true,
children: (
<>
<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>
<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} />
{InstanceRenderManager({
rome: (

View File

@@ -14,6 +14,6 @@ export default function JobsCreateOwnerContainer() {
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} />;
}

View File

@@ -14,7 +14,7 @@ export default function JobsCreateVehicleInfoContainer({ form }) {
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} />;
}

View File

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

View File

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

View File

@@ -13,152 +13,162 @@ export function JobsDetailRatesMaterials({ jobRO, expanded, form }) {
const { t } = useTranslation();
return (
<Collapse defaultActiveKey={expanded && "rates"}>
<Collapse.Panel forceRender header={t("jobs.fields.materials.materials")} key="materials">
<LayoutFormRow header={t("jobs.fields.materials.MAPA")}>
<Form.Item label={t("jobs.fields.materials.cal_maxdlr")} name={["materials", "MAPA", "cal_maxdlr"]}>
<InputNumber min={0} precision={2} disabled={jobRO} />
</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_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", "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} />
<Collapse
defaultActiveKey={expanded && "rates"}
items={[
{
key: "materials",
label: t("jobs.fields.materials.materials"),
forceRender: true,
children: (
<>
<LayoutFormRow header={t("jobs.fields.materials.MAPA")}>
<Form.Item label={t("jobs.fields.materials.cal_maxdlr")} name={["materials", "MAPA", "cal_maxdlr"]}>
<InputNumber min={0} precision={2} disabled={jobRO} />
</Form.Item>
);
}}
</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 label={t("jobs.fields.materials.cal_opcode")} name={["materials", "MAPA", "cal_opcode"]}>
<Input 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>
</Collapse.Panel>
</Collapse>
<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", "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.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_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();
return (
<Collapse defaultActiveKey={expanded && "rates"}>
<Collapse.Panel forceRender header={t("jobs.labels.cieca_pfo")} key="cieca_pfo">
<LayoutFormRow noDivider>
<Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in1")}
name={["cieca_pfo", "tow_t_in1"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in2")}
name={["cieca_pfo", "tow_t_in2"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in3")}
name={["cieca_pfo", "tow_t_in3"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in4")}
name={["cieca_pfo", "tow_t_in4"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in5")}
name={["cieca_pfo", "tow_t_in5"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Collapse
defaultActiveKey={expanded && "rates"}
items={[
{
key: "cieca_pfo",
label: t("jobs.labels.cieca_pfo"),
forceRender: true,
children: (
<>
<LayoutFormRow noDivider>
<Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in1")}
name={["cieca_pfo", "tow_t_in1"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in2")}
name={["cieca_pfo", "tow_t_in2"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in3")}
name={["cieca_pfo", "tow_t_in3"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.tow_t_in4")}
name={["cieca_pfo", "tow_t_in4"]}
valuePropName="checked"
>
<Switch />
</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
label={t("jobs.fields.cieca_pfo.stor_t_in1")}
name={["cieca_pfo", "stor_t_in1"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in2")}
name={["cieca_pfo", "stor_t_in2"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in3")}
name={["cieca_pfo", "stor_t_in3"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in4")}
name={["cieca_pfo", "stor_t_in4"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in5")}
name={["cieca_pfo", "stor_t_in5"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
</LayoutFormRow>
</Collapse.Panel>
</Collapse>
<Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in1")}
name={["cieca_pfo", "stor_t_in1"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in2")}
name={["cieca_pfo", "stor_t_in2"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in3")}
name={["cieca_pfo", "stor_t_in3"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in4")}
name={["cieca_pfo", "stor_t_in4"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.cieca_pfo.stor_t_in5")}
name={["cieca_pfo", "stor_t_in5"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
</LayoutFormRow>
</>
)
}
]}
/>
);
}

View File

@@ -47,11 +47,17 @@ export function JobsDetailRatesTaxes({ jobRO, expanded, bodyshop }) {
);
}
return (
<Collapse defaultActiveKey={expanded && "rates"}>
<Collapse.Panel forceRender header={t("jobs.labels.cieca_pft")} key="cieca_pft">
{formItems}
</Collapse.Panel>
</Collapse>
<Collapse
defaultActiveKey={expanded && "rates"}
items={[
{
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 (error) return <AlertComponent type="error" message={error.message} />;
if (error) return <AlertComponent type="error" title={error.message} />;
if (Imgproxy.treatment === "on") {
return (

View File

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

View File

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

View File

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

View File

@@ -46,7 +46,7 @@ export function JobsList({ bodyshop }) {
const history = useNavigate();
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
? searchText === ""

View File

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

View File

@@ -53,7 +53,7 @@ export function JobsReadyList({ bodyshop }) {
const history = useNavigate();
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
? searchText === ""

View File

@@ -264,7 +264,7 @@ export function LaborAllocationsTable({
</Col>
)}
{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>
);

View File

@@ -304,7 +304,7 @@ export function PayrollLaborAllocationsTable({
</Col>
)}
{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>
);

View File

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

View File

@@ -123,7 +123,7 @@ const NotificationSettingsForm = ({ currentUser, bodyshop }) => {
setIsDirty(false);
};
if (error) return <AlertComponent type="error" message={error.message} />;
if (error) return <AlertComponent type="error" title={error.message} />;
if (loading) return <LoadingSpinner />;
const columns = [
@@ -201,7 +201,7 @@ const NotificationSettingsForm = ({ currentUser, bodyshop }) => {
>
{!isEmployee && (
<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>
)}
<Table dataSource={dataSource} columns={columns} pagination={false} bordered rowKey="key" />

View File

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

View File

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

View File

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

View File

@@ -334,7 +334,7 @@ export function PartsOrderModalContainer({
width="75%"
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}>
{loading ? (
<LoadingSpinner />

View File

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

View File

@@ -44,7 +44,7 @@ export function PartsQueueListComponent({ bodyshop }) {
const { t } = useTranslation();
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
? searchText === ""

View File

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

View File

@@ -17,7 +17,7 @@ export default function PaymentFormTotalPayments({ jobid }) {
});
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 <></>;
const totalPayments = data.jobs_by_pk.payments.reduce((acc, val) => {

View File

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

View File

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

View File

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

View File

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

View File

@@ -21,7 +21,7 @@ function RbacWrapper({ authLevel, bodyshop, requiredAuthLevel, noauth, children,
return children;
//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 }) {

View File

@@ -80,40 +80,46 @@ export function ScheduleCalendarWrapperComponent({
{HasFeatureAccess({ featureName: "smartscheduling", bodyshop }) &&
problemJobs &&
(problemJobs.length > 2 ? (
<Collapse style={{ marginBottom: "5px" }}>
<Collapse.Panel
key="1"
header={
<span style={{ color: "var(--error-header-text)" }}>{t("appointments.labels.severalerrorsfound")}</span>
}
>
<Space orientation="vertical" style={{ width: "100%" }}>
{problemJobs.map((problem) => (
<Alert
key={problem.id}
type="error"
message={
<Trans
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
}}
<Collapse
style={{ marginBottom: "5px" }}
items={[
{
key: "1",
label: (
<span style={{ color: "var(--error-header-text)" }}>
{t("appointments.labels.severalerrorsfound")}
</span>
),
children: (
<Space orientation="vertical" style={{ width: "100%" }}>
{problemJobs.map((problem) => (
<Alert
key={problem.id}
type="error"
title={
<Trans
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>
</Collapse.Panel>
</Collapse>
))}
</Space>
)
}
]}
/>
) : (
<Space orientation="vertical" style={{ width: "100%", marginBottom: "5px" }}>
{problemJobs.map((problem) => (
<Alert
key={problem.id}
type="error"
message={
title={
<Trans
i18nKey="appointments.labels.dataconsistency"
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]);
if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type="error" />;
if (error) return <AlertComponent title={error.message} type="error" />;
let normalizedData = [
...data.appointments.map((e) => {
//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 }) {
const { t } = useTranslation();
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 (
<div>

View File

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

View File

@@ -293,7 +293,7 @@ export function ScoreboardTimeTicketsStats({ 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 />;
return (
<Row gutter={[16, 16]}>

View File

@@ -219,7 +219,7 @@ export default function ScoreboardTimeTickets() {
};
}, [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 />;
return (
<Row gutter={[16, 16]}>

View File

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

View File

@@ -113,7 +113,7 @@ export function ShopEmployeesFormComponent({ bodyshop }) {
};
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 = [
{

View File

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

View File

@@ -68,7 +68,7 @@ export default function ShopInfoContainer() {
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 />;
return (
<Form

View File

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

View File

@@ -25,7 +25,7 @@ export function ShopInfoIntellipay({ bodyshop, form }) {
const { intellipay_config } = form.getFieldsValue();
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>

View File

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

View File

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

View File

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

View File

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

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