"use client"; import { useState, useEffect, useRef, useCallback } from "react"; import Link from "next/link"; import ThemedLayout from "@/components/layouts/ThemedLayout"; import { useAccount } from "@/contexts/AccountContext"; type Msg = { id: string; from: string; text: string; ts: number }; export default function MessagesPage() { const { user, hydrated } = useAccount(); const handle = user?.username ?? null; const [msgs, setMsgs] = useState([]); const [input, setInput] = useState(""); const [ready, setReady] = useState(false); const endRef = useRef(null); const fetchMessages = useCallback(async () => { try { const res = await fetch("/api/messages?channel=global"); const data = await res.json(); if (data.ok && data.messages) { setMsgs(data.messages); } setReady(true); } catch (e) { // ignore } }, []); useEffect(() => { if (!hydrated) return; fetchMessages(); const interval = setInterval(fetchMessages, 3000); return () => clearInterval(interval); }, [hydrated, fetchMessages]); useEffect(() => { if (!ready) return; endRef.current?.scrollIntoView({ behavior: "smooth" }); }, [msgs, ready]); const send = async () => { const text = input.trim(); if (!text) return; setInput(""); const optimisticMsg: Msg = { id: "temp-" + Date.now(), from: handle ?? "anon", text, ts: Date.now() }; setMsgs((p) => [...p, optimisticMsg]); try { await fetch("/api/messages", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ from: handle ?? "anon", text, channel: "global" }), }); fetchMessages(); } catch (e) { // ignore } }; const ts = (n: number) => new Date(n).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }); return (

GLOBAL COMMS

{handle ? ( <>Channel: @{handle} · synced across network ) : ( <> Sign in {" "} to persist messages to your handle )}

{!ready ? (
Loading…
) : msgs.length === 0 ? (
No messages yet. Be the first!
) : ( msgs.map((m) => { const mine = m.from === handle || (m.from === "anon" && !handle); return (
@{m.from} {ts(m.ts)}
{m.text}
); }) )}
setInput(e.target.value)} onKeyDown={(e) => e.key === "Enter" && send()} placeholder={ready ? "Message the network…" : "Loading…"} disabled={!ready} className="flex-1 rounded-xl border border-white/10 bg-transparent px-4 py-3 text-sm focus:border-neon-cyan/40 focus:outline-none disabled:opacity-50" maxLength={500} />
Global synced storage
Real-time transport
Encrypted at rest
Forum (persisted threads) → Barter board Dashboard
); } function Sections({ children }: { children: React.ReactNode }) { return ( {children} ); }