// §3.10 Volume Tracker — Upload, MVC Commitment, Analytics function VolumeTracker({ user, perms }) { const [tab, setTab] = useState("overview"); const [showUpload, setShowUpload] = useState(false); const tabs = [ { id: "overview", label: "Overview" }, { id: "commitment", label: "MVC Commitment", count: Object.keys(MVC).length }, { id: "rebatepace", label: "Rebate Pace" }, { id: "data", label: "Volume Records" }, ]; return (
| Terminal | {months.map(m =>{m.slice(5)} | )}
|---|---|
| {tc} | {months.map(m => { const row = tRows.find(r => r.period === m); const idx = row ? row.teu / avg : 1; // Color: <1 cool, >1 warm let bg; if (idx < 0.9) bg = `oklch(70% 0.05 230 / ${0.4 + (0.9 - idx) * 4})`; else if (idx > 1.05) bg = `oklch(70% 0.13 35 / ${0.3 + (idx - 1) * 3})`; else bg = "var(--paper-2)"; return (
{idx > 0.85 && idx < 1.15 ? "" : Math.round(idx * 100)}
|
);
})}
| Terminal | Contract MVC | YTD Actual | Pace vs MVC | YTD Pace (Annualised) | Gap to MVC | Risk | Shortfall Cost | Focal |
|---|---|---|---|---|---|---|---|---|
|
{r.name}
{r.region}
|
{fmt.num(r.mvc, 0)} | {fmt.num(r.ytd, 0)} | {fmt.num(r.pace, 0)} | {r.gap > 0 ? "+" : ""}{fmt.num(r.gap, 0)} |
{r.risk === "On Track" && |
0 ? "var(--red)" : null }}> {r.shortfall > 0 ? fmt.usd(r.shortfall) : "—"} | {r.focal} |
| Period | Terminal | Equipment | Cargo | Move Type | Actual TEU | Actual Moves | Source | Uploaded |
|---|---|---|---|---|---|---|---|---|
| {v.period} |
{v.terminalName}
{v.terminal}
|
{EQUIPMENT[i % EQUIPMENT.length]} | {CARGO_TYPES[i % CARGO_TYPES.length]} | {MOVE_TYPES[i % MOVE_TYPES.length]} | {fmt.num(v.teu, 0)} | {fmt.num(v.moves, 0)} | 2025-05-08 · D. Park |
| Terminal | Period | Equipment | Cargo | Move | TEU | Moves | Result |
|---|---|---|---|---|---|---|---|
| {s.terminal} | {s.period} | {s.eq} | {s.cargo} | {s.move} | {fmt.num(s.teu, 0)} | {fmt.num(s.moves, 0)} | {s.status === "ok" && ✓ Valid} {s.status === "dup" && ✕ Duplicate combination} {s.status === "future" && ✕ Future period not allowed} |