import { useState, useEffect } from "react"; import { Link, useLocation } from "react-router-dom"; import { useAuth } from "@/contexts/AuthContext"; import { useArmTheme } from "@/contexts/ArmThemeContext"; import NotificationBell from "@/components/notifications/NotificationBell"; import { AIChatButton } from "@/components/ai"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { User, Settings, LogOut, Sparkles, UserCircle, Menu, BookOpen, Shield, X, } from "lucide-react"; // ─── Brand styles (injected once) ──────────────────────────────────────────── const AX_STYLES = ` @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;700;900&family=Share+Tech+Mono&display=swap'); @keyframes ax-flicker { 0%,100%{opacity:1} 92%{opacity:1} 93%{opacity:0.82} 94%{opacity:1} 96%{opacity:0.9} 97%{opacity:1} } @keyframes ax-glitch { 0%,89%,100%{transform:translateX(0) skewX(0)} 90%{transform:translateX(-3px) skewX(-1deg)} 91%{transform:translateX(3px) skewX(1deg)} 92%{transform:translateX(0) skewX(0)} } @keyframes ax-blink { 0%,50%{opacity:1} 51%,100%{opacity:0} } @keyframes ax-sweep { 0%{left:-100%} 100%{left:200%} } @keyframes ax-pulse-glow { 0%,100%{box-shadow:0 0 8px rgba(0,255,255,0.08),inset 0 0 8px rgba(0,255,255,0.02)} 50%{box-shadow:0 0 24px rgba(0,255,255,0.2),inset 0 0 16px rgba(0,255,255,0.05)} } @keyframes ax-fade-up { from{opacity:0;transform:translateY(10px)} to{opacity:1;transform:translateY(0)} } .ax-flicker { animation: ax-flicker 12s infinite; } .ax-orbitron { font-family: 'Orbitron', monospace !important; } .ax-mono { font-family: 'Share Tech Mono', monospace !important; } .ax-glitch { animation: ax-glitch 9s infinite; font-family: 'Orbitron', monospace !important; } .ax-card-sweep { position: relative; overflow: hidden; } .ax-card-sweep::after { content: ''; position: absolute; top: 0; left: -100%; width: 50%; height: 100%; background: linear-gradient(90deg, transparent, rgba(0,255,255,0.05), transparent); animation: ax-sweep 5s infinite; pointer-events: none; } .ax-pulse { animation: ax-pulse-glow 4s infinite; } .ax-fade-up { animation: ax-fade-up 0.4s ease both; } .ax-corner-bracket { position: relative; } .ax-corner-bracket::before, .ax-corner-bracket::after { content: ''; position: absolute; width: 16px; height: 16px; } .ax-corner-bracket::before { top: -1px; left: -1px; border-top: 2px solid rgba(0,255,255,0.6); border-left: 2px solid rgba(0,255,255,0.6); } .ax-corner-bracket::after { bottom: -1px; right: -1px; border-bottom: 2px solid rgba(0,255,255,0.6); border-right: 2px solid rgba(0,255,255,0.6); } .ax-clip { clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 8px 100%, 0 calc(100% - 8px)); } body::before { content: ''; position: fixed; inset: 0; background: repeating-linear-gradient( 0deg, transparent, transparent 2px, rgba(0,255,255,0.015) 2px, rgba(0,255,255,0.015) 4px ); pointer-events: none; z-index: 9990; } body::after { content: ''; position: fixed; inset: 0; background-image: linear-gradient(rgba(0,255,255,0.025) 1px, transparent 1px), linear-gradient(90deg, rgba(0,255,255,0.025) 1px, transparent 1px); background-size: 50px 50px; pointer-events: none; z-index: 9989; } `; // ─── SysBar ─────────────────────────────────────────────────────────────────── const APP_VERSION = import.meta.env.VITE_APP_VERSION || "0.1.0"; type SysStatus = "ok" | "degraded" | "outage" | "unknown"; function SysBar() { const [time, setTime] = useState(""); const [latency, setLatency] = useState(null); const [status, setStatus] = useState("unknown"); const [node, setNode] = useState("vps.aethex.tech"); // Live clock useEffect(() => { const tick = () => setTime(new Date().toLocaleTimeString("en-US", { hour12: false })); tick(); const id = setInterval(tick, 1000); return () => clearInterval(id); }, []); // Ping /api/health every 30s — measures real round-trip latency useEffect(() => { const ping = async () => { const t0 = performance.now(); try { const res = await fetch("/api/health", { cache: "no-store" }); const ms = Math.round(performance.now() - t0); setLatency(ms); if (!res.ok) { setStatus("outage"); } else { const body = await res.json().catch(() => ({})); const host: string = body?.host ?? ""; if (host) setNode(new URL(host).hostname.replace("www.", "")); setStatus(ms > 800 ? "degraded" : "ok"); } } catch { setLatency(null); setStatus("outage"); } }; ping(); const id = setInterval(ping, 30_000); return () => clearInterval(id); }, []); const dotColor = status === "ok" ? "#00ff41" : status === "degraded" ? "#facc15" : status === "outage" ? "#f87171" : "rgba(0,255,255,0.3)"; return (
AeThex.OS v{APP_VERSION} // Forge Terminal node: {node} {latency !== null ? `${latency}ms` : "…"} {time}
); } // ─── HexLogo ────────────────────────────────────────────────────────────────── function HexLogo({ size = 30 }: { size?: number }) { return ( Æ ); } // ─── NavLink helper ─────────────────────────────────────────────────────────── function NavLink({ to, children }: { to: string; children: React.ReactNode }) { return ( (e.currentTarget.style.color = "#00ffff")} onMouseLeave={e => (e.currentTarget.style.color = "rgba(0,255,255,0.45)")} > {children} ); } // ─── Layout ─────────────────────────────────────────────────────────────────── interface LayoutProps { children: React.ReactNode; hideFooter?: boolean; } const FOOTER_LINKS = { Platform: [ { name: "Home", href: "/" }, { name: "Realms", href: "/realms" }, { name: "Developer Platform", href: "/dev-platform" }, { name: "Dashboard", href: "/dashboard" }, ], Community: [ { name: "Explore", href: "/engage" }, { name: "Teams", href: "/teams" }, { name: "Squads", href: "/squads" }, { name: "Opportunities", href: "/opportunities" }, ], Resources: [ { name: "Docs", href: "/docs" }, { name: "API Reference", href: "/dev-platform/api-reference" }, { name: "Quick Start", href: "/dev-platform/quick-start" }, { name: "Roadmap", href: "/roadmap" }, ], Legal: [ { name: "About", href: "/about" }, { name: "Contact", href: "/contact" }, { name: "Blog", href: "/blog" }, ], }; export default function CodeLayout({ children, hideFooter }: LayoutProps) { const location = useLocation(); const { user, profile, roles, signOut, loading } = useAuth(); const isPrivileged = Array.isArray(roles) && roles.some(r => ["owner", "admin", "founder"].includes(r.toLowerCase())); const isInternal = Array.isArray(roles) && roles.some(r => ["owner", "admin", "founder", "staff"].includes(r.toLowerCase())); useArmTheme(); // keep context alive for downstream consumers const [mobileOpen, setMobileOpen] = useState(false); const publicNavLinks = [ { name: "Realms", href: "/realms" }, { name: "Dev Platform", href: "/dev-platform" }, { name: "Docs", href: "/docs" }, { name: "About", href: "/about" }, ]; const userNavLinks = [ { name: "Dashboard", href: "/dashboard" }, { name: "Realms", href: "/realms" }, { name: "Teams", href: "/teams" }, { name: "Dev Platform", href: "/dev-platform" }, { name: "Engage", href: "/engage" }, ]; const navLinks = user ? userNavLinks : publicNavLinks; // Inject global brand styles once useEffect(() => { const existing = document.getElementById("ax-forge-styles"); if (!existing) { const el = document.createElement("style"); el.id = "ax-forge-styles"; el.textContent = AX_STYLES; document.head.appendChild(el); } }, []); const passportHref = profile?.username ? `/passport/${profile.username}` : "/passport/me"; const userInitials = (profile?.full_name || profile?.username || "U") .split(" ").map((n: string) => n[0]).join("").toUpperCase(); return (
{/* ── Navigation ──────────────────────────────────────────────────────── */}
{/* TrinityBar */}
{/* Logo */} AETHEX {/* Desktop nav links */} {/* Auth */}
{!loading && ( <> {user ? (
{profile ? (
{profile.full_name || profile.username}
{/* User items */} Dashboard My Profile AeThex Passport Settings {/* Internal section — staff/admin/owner only */} {isInternal && ( <>
Internal
{isPrivileged && ( Admin )} Internal Docs )} signOut()} > Sign out
) : ( )}
) : (
Sign In { e.currentTarget.style.background = "rgba(0,255,255,0.12)"; e.currentTarget.style.boxShadow = "0 0 16px rgba(0,255,255,0.2)"; }} onMouseLeave={e => { e.currentTarget.style.background = "rgba(0,255,255,0.04)"; e.currentTarget.style.boxShadow = "none"; }} > Join AeThex →
)} )} {/* Mobile hamburger */}
{/* Mobile menu */} {mobileOpen && (
{navLinks.map((item) => ( setMobileOpen(false)} className="ax-mono" style={{ fontSize: 11, letterSpacing: 2, textTransform: "uppercase", color: "rgba(0,255,255,0.5)", textDecoration: "none", padding: "8px 0", borderBottom: "1px solid rgba(0,255,255,0.06)", }} > {item.name} ))} {!user && ( setMobileOpen(false)} className="ax-mono" style={{ marginTop: 4, fontSize: 11, letterSpacing: 2, textTransform: "uppercase", border: "1px solid rgba(0,255,255,0.4)", color: "#00ffff", padding: "12px 16px", textDecoration: "none", textAlign: "center", }} > Join AeThex → )}
)}
{/* ── Content ─────────────────────────────────────────────────────────── */}
{children}
{/* ── Footer ──────────────────────────────────────────────────────────── */} {!hideFooter && (
{/* TrinityBar */}
{/* Brand column */}
AETHEX

The integration layer connecting all metaverse platforms. Six specialized realms. One ecosystem.

Queen Creek, Arizona
info@aethex.biz

{/* Link columns */} {Object.entries(FOOTER_LINKS).map(([section, links]) => (

{section}

{links.map((link) => ( (e.currentTarget.style.color = "rgba(0,255,255,0.7)")} onMouseLeave={e => (e.currentTarget.style.color = "rgba(0,255,255,0.3)")} > {link.name} ))}
))}
{/* Bottom bar */}
© 2026 AeThex Corporation. All rights reserved. AeThex.OS v3.7.1 // aethex.dev
)}
); }