IO-3515 Improve confidence display.

This commit is contained in:
Patrick Fic
2026-02-18 10:56:51 -08:00
parent e5f930b8c8
commit d4bbdd7383
13 changed files with 477 additions and 1289 deletions

View File

@@ -5,14 +5,15 @@ import { useRef } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { selectDarkMode } from "../../redux/application/application.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CiecaSelect from "../../utils/Ciecaselect";
import { bodyshopHasDmsKey } from "../../utils/dmsUtils.js";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
import BillLineSearchSelect from "../bill-line-search-select/bill-line-search-select.component";
import BilllineAddInventory from "../billline-add-inventory/billline-add-inventory.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import { bodyshopHasDmsKey } from "../../utils/dmsUtils.js";
import ConfidenceDisplay from "./bill-form.lines.confidence.component.jsx";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -216,13 +217,20 @@ export function BillEnterModalLinesComponent({
title: t("billlines.fields.confidence"),
dataIndex: "confidence",
editable: true,
width: "4rem",
width: "5rem",
formItemProps: (field) => ({
key: `${field.index}confidence`,
name: [field.name, "confidence"],
label: t("billlines.fields.confidence")
}),
formInput: () => <Input disabled={disabled} />
formInput: (record) => {
const confidenceValue = getFieldValue(["billlines", record.name, "confidence"]);
return (
<div style={{ display: "flex", alignItems: "center", justifyContent: "center" }}>
<ConfidenceDisplay value={confidenceValue} />
</div>
);
}
},
{
title: t("billlines.fields.quantity"),

View File

@@ -0,0 +1,81 @@
import { Progress, Tag, Tooltip } from "antd";
import { useTranslation } from "react-i18next";
const parseConfidence = (confidenceStr) => {
if (!confidenceStr || typeof confidenceStr !== "string") return null;
const match = confidenceStr.match(/T([\d.]+)\s*-\s*O([\d.]+)\s*-\s*J([\d.]+)/);
if (!match) return null;
return {
total: parseFloat(match[1]),
ocr: parseFloat(match[2]),
jobMatch: parseFloat(match[3])
};
};
const getConfidenceColor = (value) => {
if (value >= 80) return "green";
if (value >= 60) return "orange";
if (value >= 40) return "gold";
return "red";
};
const ConfidenceDisplay = ({ value }) => {
const { t } = useTranslation();
const parsed = parseConfidence(value);
if (!parsed) {
return <span style={{ color: "#999", fontSize: "0.85em" }}>N/A</span>;
}
const { total, ocr, jobMatch } = parsed;
const color = getConfidenceColor(total);
return (
<Tooltip
title={
<div style={{ padding: "4px 0" }}>
<div style={{ marginBottom: 8, fontWeight: 600 }}>
{t("billlines.confidence.breakdown", { defaultValue: "Confidence Breakdown" })}
</div>
<div style={{ marginBottom: 4 }}>
<strong>{t("billlines.confidence.overall", { defaultValue: "Overall" })}:</strong> {total.toFixed(1)}%
<Progress
percent={total}
size="small"
strokeColor={getConfidenceColor(total)}
showInfo={false}
style={{ marginTop: 2 }}
/>
</div>
<div style={{ marginBottom: 4 }}>
<strong>{t("billlines.confidence.ocr", { defaultValue: "OCR" })}:</strong> {ocr.toFixed(1)}%
<Progress
percent={ocr}
size="small"
strokeColor={getConfidenceColor(ocr)}
showInfo={false}
style={{ marginTop: 2 }}
/>
</div>
<div>
<strong>{t("billlines.confidence.match", { defaultValue: "Job Match" })}:</strong> {jobMatch.toFixed(1)}%
<Progress
percent={jobMatch}
size="small"
strokeColor={getConfidenceColor(jobMatch)}
showInfo={false}
style={{ marginTop: 2 }}
/>
</div>
</div>
}
>
<Tag color={color} style={{ margin: 0, cursor: "help", userSelect: "none" }}>
{total.toFixed(0)}%
</Tag>
</Tooltip>
);
};
export default ConfidenceDisplay;