- Daily checkpoint, speed (grid), and presentation

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-07-08 17:57:26 -04:00
parent fa578efee4
commit 8a4fee7aea
5 changed files with 206 additions and 198 deletions

View File

@@ -28,26 +28,28 @@ const cardColor = (ssbuckets, totalHrs) => {
const getContrastYIQ = (bgColor) =>
(bgColor.r * 299 + bgColor.g * 587 + bgColor.b * 114) / 1000 >= 128 ? "black" : "white";
export default function ProductionBoardCard({ technician, card, bodyshop, cardSettings, clone, style }) {
const findEmployeeById = (employees, id) => employees.find((e) => e.id === id);
const EllipsesToolTip = React.memo(({ title, children }) => (
<Tooltip title={title}>
<div className="ellipses">{children}</div>
</Tooltip>
));
export default function ProductionBoardCard({ technician, card, bodyshop, cardSettings, clone }) {
const { t } = useTranslation();
const { metadata } = card;
const employee_body = useMemo(
() => metadata?.employee_body && bodyshop.employees.find((e) => e.id === metadata.employee_body),
[metadata?.employee_body, bodyshop.employees]
);
const employee_prep = useMemo(
() => metadata?.employee_prep && bodyshop.employees.find((e) => e.id === metadata.employee_prep),
[metadata?.employee_prep, bodyshop.employees]
);
const employee_refinish = useMemo(
() => metadata?.employee_refinish && bodyshop.employees.find((e) => e.id === metadata.employee_refinish),
[metadata?.employee_refinish, bodyshop.employees]
);
const employee_csr = useMemo(
() => metadata?.employee_csr && bodyshop.employees.find((e) => e.id === metadata.employee_csr),
[metadata?.employee_csr, bodyshop.employees]
);
const employees = useMemo(() => bodyshop.employees, [bodyshop.employees]);
const { employee_body, employee_prep, employee_refinish, employee_csr } = useMemo(() => {
return {
employee_body: metadata?.employee_body && findEmployeeById(employees, metadata.employee_body),
employee_prep: metadata?.employee_prep && findEmployeeById(employees, metadata.employee_prep),
employee_refinish: metadata?.employee_refinish && findEmployeeById(employees, metadata.employee_refinish),
employee_csr: metadata?.employee_csr && findEmployeeById(employees, metadata.employee_csr)
};
}, [metadata, employees]);
const pastDueAlert = useMemo(() => {
if (!metadata?.scheduled_completion) return null;
@@ -66,162 +68,176 @@ export default function ProductionBoardCard({ technician, card, bodyshop, cardSe
const bgColor = useMemo(() => cardColor(bodyshop.ssbuckets, totalHrs), [bodyshop.ssbuckets, totalHrs]);
const contrastYIQ = useMemo(() => getContrastYIQ(bgColor), [bgColor]);
const headerContent = (
<Space>
<ProductionAlert
record={{
id: card.id,
production_vars: card?.metadata.production_vars,
refetch: card?.refetch
}}
key="alert"
/>
{metadata?.suspended && <PauseCircleOutlined style={{ color: "orangered" }} />}
{metadata?.iouparent && (
<EllipsesToolTip title={t("jobs.labels.iou")}>
<BranchesOutlined style={{ color: "orangered" }} />
</EllipsesToolTip>
)}
<span style={{ fontWeight: "bolder" }}>
<Link to={technician ? `/tech/joblookup?selected=${card.id}` : `/manage/jobs/${card.id}`}>
{metadata?.ro_number || t("general.labels.na")}
</Link>
</span>
</Space>
);
const bodyContent = (
<Row>
{cardSettings?.ownr_nm && (
<Col span={24}>
<EllipsesToolTip title={`${metadata.ownr_ln || ""} ${metadata.ownr_co_nm || ""}`}>
{cardSettings.compact ? (
`${metadata.ownr_ln || ""} ${metadata.ownr_co_nm || ""}`
) : (
<OwnerNameDisplay ownerObject={card} />
)}
</EllipsesToolTip>
</Col>
)}
{cardSettings?.model_info && (
<Col span={24}>
<EllipsesToolTip
title={`${metadata.v_model_yr || ""} ${metadata.v_make_desc || ""} ${metadata.v_model_desc || ""}`}
>
{`${metadata.v_model_yr || ""} ${metadata.v_make_desc || ""} ${metadata.v_model_desc || ""}`}
</EllipsesToolTip>
</Col>
)}
{cardSettings?.ins_co_nm && metadata.ins_co_nm && (
<Col span={cardSettings.compact ? 24 : 12}>
<EllipsesToolTip title={metadata.ins_co_nm || ""}>{metadata.ins_co_nm || ""}</EllipsesToolTip>
</Col>
)}
{cardSettings?.clm_no && metadata.clm_no && (
<Col span={cardSettings.compact ? 24 : 12}>
<EllipsesToolTip title={metadata.clm_no || ""}>{metadata.clm_no || ""}</EllipsesToolTip>
</Col>
)}
{cardSettings?.employeeassignments && (
<Col span={24}>
<Row>
<Col span={cardSettings.compact ? 24 : 12}>
<EllipsesToolTip
title={`B: ${employee_body ? `${employee_body.first_name.substr(0, 3)} ${employee_body.last_name.charAt(0)}` : ""} ${metadata.labhrs.aggregate.sum.mod_lb_hrs || "?"}h`}
>
{`B: ${employee_body ? `${employee_body.first_name.substr(0, 3)} ${employee_body.last_name.charAt(0)}` : ""} ${metadata.labhrs.aggregate.sum.mod_lb_hrs || "?"}h`}
</EllipsesToolTip>
</Col>
<Col span={cardSettings.compact ? 24 : 12}>
<EllipsesToolTip
title={`P: ${employee_prep ? `${employee_prep.first_name.substr(0, 3)} ${employee_prep.last_name.charAt(0)}` : ""}`}
>
{`P: ${employee_prep ? `${employee_prep.first_name.substring(0, 3)} ${employee_prep.last_name.charAt(0)}` : ""}`}
</EllipsesToolTip>
</Col>
<Col span={cardSettings.compact ? 24 : 12}>
<EllipsesToolTip
title={`R: ${employee_refinish ? `${employee_refinish.first_name.substring(0, 3)} ${employee_refinish.last_name.charAt(0)}` : ""} ${metadata.larhrs.aggregate.sum.mod_lb_hrs || "?"}h`}
>
{`R: ${employee_refinish ? `${employee_refinish.first_name.substring(0, 3)} ${employee_refinish.last_name.charAt(0)}` : ""} ${metadata.larhrs.aggregate.sum.mod_lb_hrs || "?"}h`}
</EllipsesToolTip>
</Col>
<Col span={cardSettings.compact ? 24 : 12}>
<EllipsesToolTip
title={`C: ${employee_csr ? `${employee_csr.first_name} ${employee_csr.last_name}` : ""}`}
>
{`C: ${employee_csr ? `${employee_csr.first_name} ${employee_csr.last_name}` : ""}`}
</EllipsesToolTip>
</Col>
</Row>
</Col>
)}
{cardSettings?.actual_in && metadata.actual_in && (
<Col span={cardSettings.compact ? 24 : 12}>
<EllipsesToolTip title={metadata.actual_in}>
<Space>
<DownloadOutlined />
<DateTimeFormatter format="MM/DD">{metadata.actual_in}</DateTimeFormatter>
</Space>
</EllipsesToolTip>
</Col>
)}
{cardSettings?.scheduled_completion && metadata.scheduled_completion && (
<Col span={cardSettings.compact ? 24 : 12}>
<EllipsesToolTip title={metadata.scheduled_completion}>
<Space className={pastDueAlert}>
<CalendarOutlined />
<DateTimeFormatter format="MM/DD">{metadata.scheduled_completion}</DateTimeFormatter>
</Space>
</EllipsesToolTip>
</Col>
)}
{cardSettings?.ats && metadata.alt_transport && (
<Col span={12}>
<EllipsesToolTip title={metadata.alt_transport}>{metadata.alt_transport || ""}</EllipsesToolTip>
</Col>
)}
{cardSettings?.sublets && (
<Col span={12}>
<ProductionSubletsManageComponent subletJobLines={metadata.subletLines} />
</Col>
)}
{cardSettings?.production_note && (
<Col span={24}>
<ProductionListColumnProductionNote
record={{
production_vars: card?.metadata.production_vars,
id: card?.id,
refetch: card?.refetch
}}
/>
</Col>
)}
{cardSettings?.partsstatus && (
<Col span={24}>
<JobPartsQueueCount parts={metadata.joblines_status} />
</Col>
)}
</Row>
);
const isBodyEmpty = !(
cardSettings?.ownr_nm ||
cardSettings?.model_info ||
(cardSettings?.ins_co_nm && metadata.ins_co_nm) ||
(cardSettings?.clm_no && metadata.clm_no) ||
cardSettings?.employeeassignments ||
(cardSettings?.actual_in && metadata.actual_in) ||
(cardSettings?.scheduled_completion && metadata.scheduled_completion) ||
(cardSettings?.ats && metadata.alt_transport) ||
cardSettings?.sublets ||
cardSettings?.production_note ||
cardSettings?.partsstatus
);
return (
<Card
className="react-trello-card"
size="small"
style={{
backgroundColor: cardSettings?.cardcolor && `rgba(${bgColor.r},${bgColor.g},${bgColor.b},${bgColor.a})`,
color: cardSettings?.cardcolor && contrastYIQ,
...style
color: cardSettings?.cardcolor && contrastYIQ
}}
title={
<Space>
<ProductionAlert
record={{
id: card.id,
production_vars: card?.metadata.production_vars,
refetch: card?.refetch
}}
key="alert"
/>
{metadata?.suspended && <PauseCircleOutlined style={{ color: "orangered" }} />}
{metadata?.iouparent && (
<Tooltip title={t("jobs.labels.iou")}>
<BranchesOutlined style={{ color: "orangered" }} />
</Tooltip>
)}
<span style={{ fontWeight: "bolder" }}>
<Link to={technician ? `/tech/joblookup?selected=${card.id}` : `/manage/jobs/${card.id}`}>
{metadata?.ro_number || t("general.labels.na")}
</Link>
</span>
</Space>
}
title={isBodyEmpty ? null : headerContent}
extra={
<Link to={{ search: `?selected=${card.id}` }}>
<EyeFilled />
</Link>
!isBodyEmpty && (
<Link to={{ search: `?selected=${card.id}` }}>
<EyeFilled />
</Link>
)
}
>
<Row>
{cardSettings?.ownr_nm && (
<Col span={24}>
<Tooltip title={`${metadata.ownr_ln || ""} ${metadata.ownr_co_nm || ""}`}>
{cardSettings.compact ? (
<div className="ellipses">{`${metadata.ownr_ln || ""} ${metadata.ownr_co_nm || ""}`}</div>
) : (
<div className="ellipses">
<OwnerNameDisplay ownerObject={card} />
</div>
)}
</Tooltip>
</Col>
)}
{cardSettings?.model_info && (
<Col span={24}>
<Tooltip
title={`${metadata.v_model_yr || ""} ${metadata.v_make_desc || ""} ${metadata.v_model_desc || ""}`}
>
<div className="ellipses">{`${metadata.v_model_yr || ""} ${metadata.v_make_desc || ""} ${metadata.v_model_desc || ""}`}</div>
</Tooltip>
</Col>
)}
{cardSettings?.ins_co_nm && metadata.ins_co_nm && (
<Col span={cardSettings.compact ? 24 : 12}>
<Tooltip title={metadata.ins_co_nm || ""}>
<div className="ellipses">{metadata.ins_co_nm || ""}</div>
</Tooltip>
</Col>
)}
{cardSettings?.clm_no && metadata.clm_no && (
<Col span={cardSettings.compact ? 24 : 12}>
<Tooltip title={metadata.clm_no || ""}>
<div className="ellipses">{metadata.clm_no || ""}</div>
</Tooltip>
</Col>
)}
{cardSettings?.employeeassignments && (
<Col span={24}>
<Row>
<Col span={cardSettings.compact ? 24 : 12}>
<Tooltip
title={`B: ${employee_body ? `${employee_body.first_name.substr(0, 3)} ${employee_body.last_name.charAt(0)}` : ""} ${metadata.labhrs.aggregate.sum.mod_lb_hrs || "?"}h`}
>
<div className="ellipses">{`B: ${employee_body ? `${employee_body.first_name.substr(0, 3)} ${employee_body.last_name.charAt(0)}` : ""} ${metadata.labhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</div>
</Tooltip>
</Col>
<Col span={cardSettings.compact ? 24 : 12}>
<Tooltip
title={`P: ${employee_prep ? `${employee_prep.first_name.substr(0, 3)} ${employee_prep.last_name.charAt(0)}` : ""}`}
>
<div className="ellipses">{`P: ${employee_prep ? `${employee_prep.first_name.substring(0, 3)} ${employee_prep.last_name.charAt(0)}` : ""}`}</div>
</Tooltip>
</Col>
<Col span={cardSettings.compact ? 24 : 12}>
<Tooltip
title={`R: ${employee_refinish ? `${employee_refinish.first_name.substring(0, 3)} ${employee_refinish.last_name.charAt(0)}` : ""} ${metadata.larhrs.aggregate.sum.mod_lb_hrs || "?"}h`}
>
<div className="ellipses">{`R: ${employee_refinish ? `${employee_refinish.first_name.substring(0, 3)} ${employee_refinish.last_name.charAt(0)}` : ""} ${metadata.larhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</div>
</Tooltip>
</Col>
<Col span={cardSettings.compact ? 24 : 12}>
<Tooltip title={`C: ${employee_csr ? `${employee_csr.first_name} ${employee_csr.last_name}` : ""}`}>
<div className="ellipses">{`C: ${employee_csr ? `${employee_csr.first_name} ${employee_csr.last_name}` : ""}`}</div>
</Tooltip>
</Col>
</Row>
</Col>
)}
{cardSettings?.actual_in && metadata.actual_in && (
<Col span={cardSettings.compact ? 24 : 12}>
<Tooltip title={metadata.actual_in}>
<Space>
<DownloadOutlined />
<DateTimeFormatter format="MM/DD">{metadata.actual_in}</DateTimeFormatter>
</Space>
</Tooltip>
</Col>
)}
{cardSettings?.scheduled_completion && metadata.scheduled_completion && (
<Col span={cardSettings.compact ? 24 : 12}>
<Tooltip title={metadata.scheduled_completion}>
<Space className={pastDueAlert}>
<CalendarOutlined />
<DateTimeFormatter format="MM/DD">{metadata.scheduled_completion}</DateTimeFormatter>
</Space>
</Tooltip>
</Col>
)}
{cardSettings?.ats && metadata.alt_transport && (
<Col span={12}>
<Tooltip title={metadata.alt_transport}>
<div className="ellipses">{metadata.alt_transport || ""}</div>
</Tooltip>
</Col>
)}
{cardSettings?.sublets && (
<Col span={12}>
<ProductionSubletsManageComponent subletJobLines={metadata.subletLines} />
</Col>
)}
{cardSettings?.production_note && (
<Col span={24}>
<ProductionListColumnProductionNote
record={{
production_vars: card?.metadata.production_vars,
id: card?.id,
refetch: card?.refetch
}}
/>
</Col>
)}
{cardSettings?.partsstatus && (
<Col span={24}>
<JobPartsQueueCount parts={metadata.joblines_status} />
</Col>
)}
</Row>
{isBodyEmpty ? headerContent : bodyContent}
</Card>
);
}