import { BranchesOutlined, CalendarOutlined, DownloadOutlined, EyeFilled, PauseCircleOutlined } from "@ant-design/icons"; import { Card, Col, Row, Space, Tooltip } from "antd"; import Dinero from "dinero.js"; import React, { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; import { DateTimeFormatter } from "../../utils/DateFormatter"; import ProductionAlert from "../production-list-columns/production-list-columns.alert.component"; import ProductionListColumnProductionNote from "../production-list-columns/production-list-columns.productionnote.component"; import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component"; import dayjs from "../../utils/day"; import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import ShareToTeamsButton from "../share-to-teams/share-to-teams.component.jsx"; import { PiMicrosoftTeamsLogo } from "react-icons/pi"; const cardColor = (ssbuckets, totalHrs) => { const bucket = ssbuckets.find((bucket) => bucket.gte <= totalHrs && (!bucket.lt || bucket.lt > totalHrs)); return bucket && bucket.color ? bucket.color.rgb || bucket.color : { r: 255, g: 255, b: 255, a: 1, fallback: "var(--card-bg-fallback)" }; }; const getContrastYIQ = (bgColor, isDarkMode = document.documentElement.getAttribute("data-theme") === "dark") => { // Use fallback if bgColor is invalid if (!bgColor || bgColor.fallback) return isDarkMode ? "var(--card-text-fallback)" : "black"; // Calculate luminance for contrast const luminance = (bgColor.r * 299 + bgColor.g * 587 + bgColor.b * 114) / 1000; // Adjust threshold for dark mode to ensure readable text return luminance >= (isDarkMode ? 150 : 128) ? "black" : isDarkMode ? "var(--card-text-fallback)" : "white"; }; const findEmployeeById = (employees, id) => employees.find((e) => e.id === id); const EllipsesToolTip = React.memo(({ title, children, kiosk }) => { if (kiosk || !title) { return
{children}
; } return (
{children}
); }); EllipsesToolTip.displayName = "EllipsesToolTip"; const OwnerNameToolTip = ({ metadata, cardSettings }) => cardSettings?.ownr_nm && ( : null} kiosk={cardSettings.kiosk} > {metadata.ownr_ln || metadata.ownr_co_nm ? ( cardSettings.compact ? ( `${metadata.ownr_ln || ""} ${metadata.ownr_co_nm || ""}` ) : ( ) ) : (   )} ); const ModelInfoToolTip = ({ metadata, cardSettings }) => cardSettings?.model_info && ( {metadata.v_model_yr || metadata.v_make_desc || metadata.v_model_desc ? ( `${metadata.v_model_yr || ""} ${metadata.v_make_desc || ""} ${metadata.v_model_desc || ""}` ) : (   )} ); const InsuranceCompanyToolTip = ({ metadata, cardSettings }) => cardSettings?.ins_co_nm && ( {metadata.ins_co_nm ? metadata.ins_co_nm :  } ); const ClaimNumberToolTip = ({ metadata, cardSettings }) => cardSettings?.clm_no && ( {metadata.clm_no ? metadata.clm_no :  } ); const EmployeeAssignmentsToolTip = ({ metadata, cardSettings, employee_body, employee_prep, employee_refinish, employee_csr }) => cardSettings?.employeeassignments && ( {employee_body || metadata.labhrs.aggregate.sum.mod_lb_hrs ? ( `B: ${employee_body ? `${employee_body.first_name.substring(0, 3)} ${employee_body.last_name.charAt(0)}` : ""} ${metadata.labhrs.aggregate.sum.mod_lb_hrs || "?"}h` ) : (   )} {employee_prep ? ( `P: ${employee_prep ? `${employee_prep.first_name.substring(0, 3)} ${employee_prep.last_name.charAt(0)}` : ""}` ) : (   )} {employee_refinish || metadata.larhrs.aggregate.sum.mod_lb_hrs ? ( `R: ${employee_refinish ? `${employee_refinish.first_name.substring(0, 3)} ${employee_refinish.last_name.charAt(0)}` : ""} ${metadata.larhrs.aggregate.sum.mod_lb_hrs || "?"}h` ) : (   )} {employee_csr ? ( `C: ${employee_csr ? `${employee_csr.first_name} ${employee_csr.last_name}` : ""}` ) : (   )} ); const ActualInToolTip = ({ metadata, cardSettings }) => cardSettings?.actual_in && ( {metadata.actual_in ? ( {metadata.actual_in} ) : (   )} ); const EstimatorToolTip = ({ metadata, cardSettings }) => { return ( cardSettings?.estimator && ( {metadata.est_ct_fn && metadata.est_ct_ln ? ( E: {`${metadata.est_ct_fn} ${metadata.est_ct_ln}`} ) : (   )} ) ); }; const SubtotalTooltip = ({ metadata, cardSettings }) => { const dineroAmount = Dinero(metadata?.job_totals?.totals?.subtotal ?? Dinero()).toFormat(); return ( cardSettings?.subtotal && ( {dineroAmount} ) ); }; const ScheduledCompletionToolTip = ({ metadata, cardSettings, pastDueAlert }) => cardSettings?.scheduled_completion && ( {metadata.scheduled_completion ? ( {metadata.scheduled_completion} ) : (   )} ); const AltTransportToolTip = ({ metadata, cardSettings }) => cardSettings?.ats && ( {metadata.alt_transport ? metadata.alt_transport :  } ); const SubletsComponent = ({ metadata, cardSettings }) => cardSettings?.sublets && ( {metadata.subletLines ? ( ) : (   )} ); const ProductionNoteComponent = ({ metadata, cardSettings, card }) => cardSettings?.production_note && ( ); const PartsStatusComponent = ({ metadata, cardSettings }) => cardSettings?.partsstatus && ( {metadata.joblines_status ? :  } ); const TasksToolTip = ({ metadata, cardSettings, t }) => cardSettings?.tasks && ( {metadata.tasks_aggregate?.aggregate?.count ? ( `T: ${metadata.tasks_aggregate.aggregate.count}` ) : ( T: 0 )} ); export default function ProductionBoardCard({ technician, card, bodyshop, cardSettings }) { const { t } = useTranslation(); const { metadata } = card; 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; const completionDate = dayjs(metadata.scheduled_completion); if (dayjs().isSameOrAfter(completionDate, "day")) return "production-completion-past"; if (dayjs().add(1, "day").isSame(completionDate, "day")) return "production-completion-soon"; return null; }, [metadata?.scheduled_completion]); const totalHrs = useMemo(() => { return metadata?.labhrs && metadata?.larhrs ? metadata.labhrs.aggregate.sum.mod_lb_hrs + metadata.larhrs.aggregate.sum.mod_lb_hrs : 0; }, [metadata?.labhrs, metadata?.larhrs]); const bgColor = useMemo(() => cardColor(bodyshop.ssbuckets, totalHrs), [bodyshop.ssbuckets, totalHrs]); const contrastYIQ = useMemo(() => getContrastYIQ(bgColor), [bgColor]); const isBodyEmpty = useMemo(() => { return !( cardSettings?.ownr_nm || cardSettings?.model_info || cardSettings?.ins_co_nm || cardSettings?.clm_no || cardSettings?.employeeassignments || cardSettings?.actual_in || cardSettings?.scheduled_completion || cardSettings?.ats || cardSettings?.sublets || cardSettings?.production_note || cardSettings?.partsstatus || cardSettings?.estimator || cardSettings?.subtotal || cardSettings?.tasks ); }, [cardSettings]); const headerContent = (
{metadata?.suspended && } {metadata?.iouparent && ( )}
{metadata?.ro_number || t("general.labels.na")} {isBodyEmpty && (
)}
); const bodyContent = ( ); return ( } urlOverride={`${window.location.origin}/manage/jobs/${card.id}`} /> ) } > {isBodyEmpty ? headerContent : bodyContent} ); }