/* 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 — F&I Products & Service Contracts catalog (Sales & F&I).
// Manages window.jbProducts: service contracts, GAP, maintenance, tire & wheel,
// appearance, key/theft and other ancillary products. Edits here drive the
// product checklist in the Desking tool.
const fp$ = (n) => "$" + (Number(n) || 0).toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: 0 });
const FP_CAT_COLOR = {
"Service Contract": "var(--jb-blue)", "GAP": "var(--jb-green)", "Maintenance": "var(--jb-amber)",
"Tire & Wheel": "var(--jb-navy)", "Appearance Protection": "#7C3AED", "Key / Theft": "var(--jb-red)", "Other": "#64748B",
};
const FiProducts = ({ onClose, go }) => {
const [, force] = React.useReducer(n => n + 1, 0);
React.useEffect(() => window.jbProducts ? window.jbProducts.subscribe(force) : undefined, []);
const list = window.jbProducts ? window.jbProducts.list() : [];
const CATS = window.jbProducts ? window.jbProducts.CATEGORIES : [];
const [edit, setEdit] = React.useState(null);
const blank = { category: "Service Contract", name: "", provider: "", code: "", retail: 0, cost: 0, taxable: false, termMo: 0, active: true, notes: "" };
const totalRetail = list.filter(p => p.active).reduce((s, p) => s + p.retail, 0);
const avgMargin = (() => { const a = list.filter(p => p.active); return a.length ? a.reduce((s, p) => s + (p.retail - p.cost), 0) / a.length : 0; })();
const usedCats = CATS.filter(c => list.some(p => p.category === c));
return (
{}} onMax={() => {}} />
{[["Products", list.length, "var(--jb-navy)"], ["Active", list.filter(p => p.active).length, "var(--jb-green)"],
["Service Contracts", list.filter(p => p.category === "Service Contract").length, "var(--jb-blue)"],
["Avg. Margin", fp$(avgMargin), "var(--jb-amber)"]].map(([lab, val, c], i) => (
))}
Active menu retail total: {fp$(totalRetail)}
{usedCats.map(cat => (
{cat}
{["Product", "Provider", "Code", "Retail", "Cost", "Margin", "Tax", "Term", ""].map((h, i) => (
| = 3 && i <= 5 ? "right" : "left" }}>{h} |
))}
{list.filter(p => p.category === cat).map((p, i) => (
setEdit({ ...p })} style={{ borderTop: "1px solid var(--jb-border)", cursor: "pointer", opacity: p.active ? 1 : 0.5 }}>
| {p.name} |
{p.provider} |
{p.code} |
{fp$(p.retail)} |
{fp$(p.cost)} |
{fp$(p.retail - p.cost)} |
{p.taxable ? taxable : —} |
{p.termMo ? p.termMo + "mo" : "—"} |
{!p.active && inactive} |
))}
))}
{list.length === 0 &&
No products yet — click “+ Add Product”.
}
{edit && setEdit(null)}
onSave={(r) => { window.jbProducts.upsert(r); setEdit(null); window.k2bToast && window.k2bToast(`${r.name || "Product"} saved.`, "ok"); }}
onDelete={edit.id ? () => { window.jbProducts.remove(edit.id); setEdit(null); window.k2bToast && window.k2bToast("Product removed.", "warn"); } : null} />}
);
};
const ProductEditor = ({ rec, CATS, onClose, onSave, onDelete }) => {
const [r, setR] = React.useState({ ...rec });
const set = (k, v) => setR(p => ({ ...p, [k]: v }));
const margin = (+r.retail || 0) - (+r.cost || 0);
const valid = (r.name || "").trim().length > 0;
return (
{onDelete && Delete}
Cancel
valid ? onSave(r) : window.k2bToast && window.k2bToast("Product name is required.", "warn")}>Save
>}>
);
};
const FpFld = ({ label, k, type = "text", r, set }) => (
);
Object.assign(window, { FiProducts });