/* eslint-disable */ /* © 2026 K2B NETWORK SOLUTIONS LLC. All rights reserved. Proprietary and confidential. Unauthorized copying, distribution, or use of this file, via any medium, is strictly prohibited. Original work product. */ // JBREWS DMS — GM Fleet (Sales & F&I). // Fleet customer book: types (Small Business, Dealer Fleet, Large Fleet, // Government, Rental), GM Fleet Account Number (FAN), incentive eligibility, // and YTD purchasing. FAN compliance is surfaced because non-small-business // fleet sales require a FAN on file to claim National Fleet incentives. // Backed by window.jbFleet. const flMoney = (n) => "$" + (Number(n) || 0).toLocaleString("en-US", { maximumFractionDigits: 0 }); const FL_TYPE_COLOR = { "Small Business": "#5A6472", "Dealer Fleet": "var(--jb-blue,#1B66A8)", "Large Fleet": "var(--jb-navy,#11337A)", "Government": "#1456A0", "Rental": "#9A6700", }; const Fleet = ({ onClose, go }) => { const [, force] = React.useReducer(n => n + 1, 0); React.useEffect(() => window.jbFleet ? window.jbFleet.subscribe(force) : undefined, []); const list = window.jbFleet ? window.jbFleet.list() : []; const TYPES = window.jbFleet ? window.jbFleet.TYPES : []; const INCS = window.jbFleet ? window.jbFleet.INCENTIVES : []; const [edit, setEdit] = React.useState(null); const [filter, setFilter] = React.useState("All"); const blank = { name: "", type: "Dealer Fleet", fan: "", contact: "", phone: "", email: "", arAcct: "", incentives: [], ytdUnits: 0, ytdSpend: 0, fanRequired: true, active: true, notes: "" }; const filtered = filter === "All" ? list : list.filter(f => f.type === filter); const nonCompliant = list.filter(f => !window.jbFleet.fanCompliant(f)); const ytdUnits = list.reduce((s, f) => s + f.ytdUnits, 0); const ytdSpend = list.reduce((s, f) => s + f.ytdSpend, 0); return (
{}} onMax={() => {}} />
{[["Fleet Accounts", list.length, "var(--jb-navy)"], ["YTD Units", ytdUnits, "var(--jb-blue)"], ["YTD Fleet Spend", flMoney(ytdSpend), "var(--jb-green)"], ["Missing FAN", nonCompliant.length, nonCompliant.length ? "var(--jb-red)" : "var(--jb-green)"]].map(([lab, val, c], i) => (
{lab}
{val}
))}
{nonCompliant.length > 0 && (
⚠ {nonCompliant.length} fleet account{nonCompliant.length !== 1 ? "s" : ""} require a Fleet Account Number (FAN) to claim National Fleet incentives: {nonCompliant.map(f => f.name).join(", ")}.
)}
Filter {["All", ...TYPES].map(t => ( ))}
{["Account", "Type", "FAN", "Incentives", "YTD Units", "YTD Spend", "A/R", ""].map((h, i) => ( ))} {filtered.map((f, i) => { const compliant = window.jbFleet.fanCompliant(f); return ( setEdit({ ...f })} style={{ background: i % 2 ? "var(--jb-surface-2)" : "#fff", cursor: "pointer", opacity: f.active ? 1 : 0.5 }}> ); })} {filtered.length === 0 && }
{h}
{f.name}
{f.contact}{f.phone ? " · " + f.phone : ""}
{f.type} {f.fan ? {f.fan} : {compliant ? "n/a" : "⚠ required"}} {f.incentives.map(code => {code})} {f.ytdUnits} {flMoney(f.ytdSpend)} {f.arAcct || "—"} edit ›
No fleet accounts in this view.
Small Business customers don't qualify for a FAN. Dealer/Large Fleet, Government and Rental accounts need a FAN on file to claim National Fleet incentives at delivery.
{edit && setEdit(null)} onSave={(r) => { window.jbFleet.upsert(r); setEdit(null); window.k2bToast && window.k2bToast(`${r.name} saved.`, "ok"); }} onDelete={edit.id ? () => { window.jbFleet.remove(edit.id); setEdit(null); window.k2bToast && window.k2bToast("Fleet account removed.", "warn"); } : null} />}
); }; const FleetEditor = ({ rec, TYPES, INCS, onClose, onSave, onDelete }) => { const [r, setR] = React.useState({ ...rec }); const set = (k, v) => setR(p => ({ ...p, [k]: v })); const toggleInc = (code) => setR(p => { const a = p.incentives || []; return { ...p, incentives: a.includes(code) ? a.filter(x => x !== code) : [...a, code] }; }); const fanRequired = r.type !== "Small Business"; const valid = (r.name || "").trim().length > 0; const save = () => valid ? onSave({ ...r, fanRequired }) : window.k2bToast && window.k2bToast("Account name is required.", "warn"); return ( {onDelete && Delete} Cancel Save }>
Incentive Eligibility
{INCS.map(o => { const on = (r.incentives || []).includes(o.code); return ( ); })}