import { useCallback, useMemo, useState } from "react"; import PropTypes from "prop-types"; import { Popover } from "antd"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component"; import { useTranslation } from "react-i18next"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop }); /** * Displays "Parts Received" summary (modeled after the Production Board List column), * and on click shows a popover with the Parts Status grid (existing JobPartsQueueCount UI). * @param bodyshop * @param parts * @param displayMode * @param popoverPlacement * @param countsOnly * @returns {JSX.Element} * @constructor */ export function JobPartsReceived({ bodyshop, parts, displayMode = "full", popoverPlacement = "top", countsOnly = false }) { const [open, setOpen] = useState(false); const { t } = useTranslation(); const summary = useMemo(() => { const receivedStatus = bodyshop?.md_order_statuses?.default_received; if (!Array.isArray(parts) || parts.length === 0 || !receivedStatus) { return { total: 0, received: 0, percentLabel: t("general.labels.na") }; } // Keep consistent with JobPartsQueueCount: exclude PAS / PASL from parts math const { total, received } = parts.reduce( (acc, val) => { if (val?.part_type === "PAS" || val?.part_type === "PASL") return acc; const count = Number(val?.count || 0); acc.total += count; if (val?.status === receivedStatus) { acc.received += count; } return acc; }, { total: 0, received: 0 } ); const percentLabel = total > 0 ? `${Math.round((received / total) * 100)}%` : t("general.labels.na"); return { total, received, percentLabel }; }, [parts, bodyshop?.md_order_statuses?.default_received]); const canOpen = summary.total > 0; const handleOpenChange = useCallback( (nextOpen) => { if (!canOpen) return; setOpen(nextOpen); }, [canOpen] ); if (countsOnly) return ; const displayText = displayMode === "compact" ? summary.percentLabel : `${summary.percentLabel} (${summary.received}/${summary.total})`; // Prevent row/cell click handlers (table selection, drawer selection, etc.) const stop = (e) => e.stopPropagation(); return ( } >
{displayText}
); } JobPartsReceived.propTypes = { bodyshop: PropTypes.object, parts: PropTypes.array, displayMode: PropTypes.oneOf(["full", "compact"]), popoverPlacement: PropTypes.string, countsOnly: PropTypes.bool }; export default connect(mapStateToProps)(JobPartsReceived);