"use client"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { Activity, BarChart3, BookOpen, Briefcase, FlaskConical, Gauge, LayoutDashboard, LogOut, Menu, Radio, Settings, ShieldAlert, TerminalSquare, X } from "lucide-react"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { useState } from "react"; import { api } from "@/lib/api"; import type { RiskStatus, SystemStatus } from "@/lib/types"; import { Badge, Button, Dot, cx } from "./ui"; const NAV = [ { href: "/", label: "Overview", icon: LayoutDashboard }, { href: "/market", label: "Market Explorer", icon: Activity }, { href: "/lab", label: "Strategy Lab", icon: FlaskConical }, { href: "/backtests", label: "Backtest Explorer", icon: BarChart3 }, { href: "/portfolio", label: "Portfolio Optimizer", icon: Briefcase }, { href: "/paper", label: "Paper Trading", icon: Radio }, { href: "/execution", label: "Execution Console", icon: TerminalSquare }, { href: "/risk", label: "Risk Center", icon: ShieldAlert }, { href: "/reports", label: "Research Reports", icon: BookOpen }, { href: "/settings", label: "Settings", icon: Settings }, ]; export function useSystemStatus() { return useQuery({ queryKey: ["system-status"], queryFn: () => api("/api/system/status"), refetchInterval: 15_000 }); } export function useRiskStatus() { return useQuery({ queryKey: ["risk-status"], queryFn: () => api("/api/risk/status"), refetchInterval: 15_000 }); } export function Shell({ children }: { children: React.ReactNode }) { const [open, setOpen] = useState(false); const pathname = usePathname(); const sys = useSystemStatus(); const risk = useRiskStatus(); const qc = useQueryClient(); const mode = sys.data?.mode ?? "offline"; const ks = risk.data?.kill_switch?.active; async function logout() { await api("/api/auth/logout", { method: "POST", headers: { Origin: window.location.origin } }); qc.clear(); // eslint-disable-next-line @next/next/no-location-assign-relative-destination -- full reload clears client state window.location.href = "/login"; } const nav = ( ); return (
{open && (
setOpen(false)}>
)}
{mode === "live" && (
LIVE TRADING ACTIVE — real orders can reach Kraken
)}
Kraken {sys.data?.kraken?.status ?? "…"} stream {sys.data?.stream ? (sys.data.stream.connected ? "live" : "down") : "n/a"} {ks !== undefined && kill switch {ks ? ACTIVE : "armed"}}
{ks && kill}
{children}
); } export function ModeBadge({ mode }: { mode: string }) { if (mode === "live") return LIVE; if (mode === "paper") return PAPER; return OFFLINE; }