"use client"; import { useEffect, useMemo, useState } from "react"; import Link from "next/link"; import { loadExchange, type ExchangeListing } from "@/lib/exchangeState"; export default function ExchangeLedgerPage() { const [rows, setRows] = useState([]); const [ready, setReady] = useState(false); useEffect(() => { setRows(loadExchange()); setReady(true); }, []); const stats = useMemo(() => { const wts = rows.filter((r) => r.kind === "wts").length; const wtb = rows.filter((r) => r.kind === "wtb").length; const byCur = { BTC: 0, XMR: 0, USD: 0 } as Record; for (const r of rows) { byCur[r.currency] = (byCur[r.currency] ?? 0) + 1; } const newest = rows.length ? Math.max(...rows.map((r) => r.ts)) : 0; const oldest = rows.length ? Math.min(...rows.map((r) => r.ts)) : 0; return { wts, wtb, byCur, newest, oldest, n: rows.length }; }, [rows]); return (

Ledger view

Aggregates whatever is stored under cyberlux-exchange-v1 in this browser. No external analytics SDK — just local state, same source the board reads.

{!ready ? (

Loading ledger…

) : ( <>

Total rows

{stats.n}

WTS

{stats.wts}

WTB

{stats.wtb}

Newest post

{stats.newest ? new Date(stats.newest).toLocaleString() : "—"}

Currency tags

    {(["BTC", "XMR", "USD"] as const).map((c) => (
  • {c} {stats.byCur[c] ?? 0}
  • ))}
{stats.oldest && stats.newest ? (

Span: {new Date(stats.oldest).toLocaleDateString()} — {new Date(stats.newest).toLocaleDateString()}

) : null} )}

Board {" · "} Guidelines

); }