Files
0pt/lib/order-client.ts
adminandClaude Opus 4.8 56e117a6d6 feat: buy everything + monitor everything in UI (client order ledger)
lib/order-client: createOrder records each order to a localStorage ledger; portal dashboard + admin queue merge it with /api/orders; order tracker falls back to it. Wired all buy paths: configurator, beskriv (custom services), and one-click catalog Beställ. Makes buy->monitor work in the browser now; becomes server-truth when Postgres is connected. tsc 0, build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 02:10:12 +02:00

71 lines
2.5 KiB
TypeScript

"use client";
// Client-side order ledger. Every buy path writes here; every monitoring surface
// reads it merged with /api/orders. This makes buy → monitor work in the browser
// before the database is provisioned; once POSTGRES_URL is set the API is the
// source of truth and this becomes a local cache.
export interface LocalOrder {
order_id: string;
flow: string;
status: string;
total_ore: number;
deposit_ore: number;
balance_ore: number;
config?: Record<string, unknown>;
created_at: string;
}
const KEY = "0pt-orders";
export function getLocalOrders(): LocalOrder[] {
if (typeof window === "undefined") return [];
try { return JSON.parse(localStorage.getItem(KEY) || "[]"); } catch { return []; }
}
export function saveLocalOrder(o: LocalOrder): void {
if (typeof window === "undefined") return;
const all = getLocalOrders().filter((x) => x.order_id !== o.order_id);
all.unshift(o);
localStorage.setItem(KEY, JSON.stringify(all.slice(0, 200)));
}
export function getLocalOrder(id: string): LocalOrder | null {
return getLocalOrders().find((o) => o.order_id === id) ?? null;
}
export function setLocalStatus(id: string, status: string): void {
if (typeof window === "undefined") return;
const all = getLocalOrders();
const o = all.find((x) => x.order_id === id);
if (o) { o.status = status; localStorage.setItem(KEY, JSON.stringify(all)); }
}
/** Merge server orders with local ones (server wins on conflict). */
export function mergeOrders<T extends { order_id: string }>(server: T[]): (T | LocalOrder)[] {
const ids = new Set(server.map((s) => s.order_id));
return [...server, ...getLocalOrders().filter((l) => !ids.has(l.order_id))];
}
/** Create an order via the API and record it locally. Returns the id (or null). */
export async function createOrder(flow: string, config: Record<string, unknown>): Promise<string | null> {
try {
const res = await fetch("/api/orders", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ flow, config }),
});
const o = await res.json();
if (o?.order_id) {
const total = o.total_ore ?? 0;
const deposit = o.deposit_ore ?? Math.round(total / 2);
saveLocalOrder({
order_id: o.order_id, flow, status: "draft",
total_ore: total, deposit_ore: deposit, balance_ore: total - deposit,
config, created_at: new Date().toISOString(),
});
return o.order_id;
}
} catch {}
return null;
}