// Optimal Trade — Screens 3: Tracking, Activity (history), Operator Console
const { useState: useState3 } = React;
/* ============================== SHIPMENT TRACKING ============================== */
function Tracking({ app, params }) {
const w = app.world;
const c = (params && params.contract) || w.contracts.find(x => x.status === "transit") || w.contracts[0];
const stageIdx = w.shipStage;
const stages = SHIPMENT_STAGES;
const pct = Math.min(100, (stageIdx / (stages.length - 1)) * 100);
return (
} />
{/* summary */}
{c.goods}
{money(c.sym || "$", c.amount)}
{stages[stageIdx].label}
{/* progress bar */}
{/* timeline */}
{stages.map((st, i) => {
const done = i < stageIdx, active = i === stageIdx;
return (
{i < stages.length - 1 &&
}
{st.label}
{st.place}
{st.ts}
);
})}
{stageIdx < stages.length - 1 && (
)}
);
}
/* ============================== ACTIVITY / HISTORY ============================= */
function Activity({ app }) {
const w = app.world;
const [filter, setFilter] = useState3("all");
const tabs = [["all", "All"], ["invoice", "Payments"], ["topup", "Top ups"], ["convert", "Conversions"]];
const list = w.txs.filter(t => filter === "all" || t.type === filter);
const iconFor = { invoice: "ship", topup: "arrow-down-left", convert: "arrow-right-left" };
return (
} />
{tabs.map(([id, label]) => (
))}
{list.map(t => (
{t.amount < 0 ? "−" : "+"}{money(t.sym, Math.abs(t.amount), t.sym === "$" ? 0 : 0)}
} />
))}
{list.length === 0 &&
No transactions yet.
}
);
}
/* ============================== OPERATOR CONSOLE (desktop side panel) ========== */
function OperatorConsole({ app }) {
const w = app.world;
const stage = SHIPMENT_STAGES[w.shipStage];
const pending = w.contracts.filter(c => c.status === "pending");
return (
Operator Console
Demo payment & status control
Mock back-office. Actions here drive the live app on the left — advance shipments, approve or decline payments.
Active shipment
{stage.label}Stage {w.shipStage + 1} / {SHIPMENT_STAGES.length}
Pending payments ({pending.length})
{pending.length === 0 &&
No payments awaiting action.
}
{pending.map(c => (
{c.supplier}{c.id} · {money(c.sym || "$", c.amount)}
))}
);
}
Object.assign(window, { Tracking, Activity, OperatorConsole });