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>
71 lines
2.5 KiB
TypeScript
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;
|
|
}
|