diff --git a/client/src/pages/os.tsx b/client/src/pages/os.tsx index 56dc4f5..53d0551 100644 --- a/client/src/pages/os.tsx +++ b/client/src/pages/os.tsx @@ -9,7 +9,11 @@ import { X, Minus, Square, Maximize2, Volume2, Wifi, Battery, ChevronUp, FolderOpen, Award, MessageCircle, Send, ExternalLink, User, LogOut, BarChart3, Loader2, - Presentation, Bell, Image, Monitor, Play, Pause, ChevronRight + Presentation, Bell, Image, Monitor, Play, Pause, ChevronRight, + Network, Activity, Code2, Radio, Newspaper, Gamepad2, + Users, Trophy, Calculator, StickyNote, Cpu, Camera, + Eye, Shield, Zap, Skull, Lock, Unlock, Server, Database, + TrendingUp, ArrowUp, ArrowDown, Hash } from "lucide-react"; interface WindowState { @@ -133,12 +137,22 @@ export default function AeThexOS() { }, [showScreensaver]); const apps: DesktopApp[] = [ - { id: "terminal", title: "Terminal", icon: , component: "terminal", defaultWidth: 700, defaultHeight: 450 }, + { id: "terminal", title: "Terminal", icon: , component: "terminal", defaultWidth: 750, defaultHeight: 500 }, { id: "passport", title: "Passport", icon: , component: "passport", defaultWidth: 500, defaultHeight: 600 }, { id: "files", title: "Projects", icon: , component: "files", defaultWidth: 700, defaultHeight: 500 }, + { id: "network", title: "Network", icon: , component: "network", defaultWidth: 700, defaultHeight: 550 }, + { id: "metrics", title: "Metrics", icon: , component: "metrics", defaultWidth: 750, defaultHeight: 550 }, + { id: "codeeditor", title: "Code", icon: , component: "codeeditor", defaultWidth: 700, defaultHeight: 500 }, + { id: "newsfeed", title: "News", icon: , component: "newsfeed", defaultWidth: 450, defaultHeight: 550 }, + { id: "arcade", title: "Arcade", icon: , component: "arcade", defaultWidth: 420, defaultHeight: 520 }, + { id: "profiles", title: "Profiles", icon: , component: "profiles", defaultWidth: 650, defaultHeight: 550 }, + { id: "leaderboard", title: "Leaderboard", icon: , component: "leaderboard", defaultWidth: 500, defaultHeight: 550 }, + { id: "calculator", title: "Calculator", icon: , component: "calculator", defaultWidth: 320, defaultHeight: 450 }, + { id: "notes", title: "Notes", icon: , component: "notes", defaultWidth: 400, defaultHeight: 450 }, + { id: "sysmonitor", title: "System", icon: , component: "sysmonitor", defaultWidth: 450, defaultHeight: 400 }, + { id: "webcam", title: "Aegis Cam", icon: , component: "webcam", defaultWidth: 500, defaultHeight: 450 }, { id: "achievements", title: "Achievements", icon: , component: "achievements", defaultWidth: 600, defaultHeight: 500 }, { id: "chat", title: "Chat", icon: , component: "chat", defaultWidth: 400, defaultHeight: 500 }, - { id: "manifesto", title: "Manifesto", icon: , component: "manifesto", defaultWidth: 600, defaultHeight: 500 }, { id: "music", title: "Ambient", icon: , component: "music", defaultWidth: 400, defaultHeight: 350 }, { id: "pitch", title: "Pitch Deck", icon: , component: "pitch", defaultWidth: 500, defaultHeight: 400 }, { id: "settings", title: "Settings", icon: , component: "settings", defaultWidth: 550, defaultHeight: 500 }, @@ -260,9 +274,19 @@ export default function AeThexOS() { case 'terminal': return ; case 'passport': return ; case 'files': return ; + case 'network': return ; + case 'metrics': return ; + case 'codeeditor': return ; + case 'newsfeed': return ; + case 'arcade': return ; + case 'profiles': return ; + case 'leaderboard': return ; + case 'calculator': return ; + case 'notes': return ; + case 'sysmonitor': return ; + case 'webcam': return ; case 'achievements': return ; case 'chat': return ; - case 'manifesto': return ; case 'music': return ; case 'pitch': return setLocation('/pitch')} />; case 'settings': return ; @@ -773,63 +797,349 @@ function Taskbar({ windows, activeWindowId, apps, time, showStartMenu, user, isA } function TerminalApp() { - const [history, setHistory] = useState(["AeThex Terminal v2.0.0", "Type 'help' for available commands.", ""]); + const ASCII_BANNER = [ + " _ _____ _____ _ _ _______ __", + " / \\ | ____|_ _| | | | ____\\ \\/ /", + " / _ \\ | _| | | | |_| | _| \\ / ", + " / ___ \\| |___ | | | _ | |___ / \\ ", + "/_/ \\_\\_____| |_| |_| |_|_____/_/\\_\\", + "", + ]; + const [history, setHistory] = useState([...ASCII_BANNER, "AeThex Terminal v3.0.0 - Secure Shell", "Type 'help' for available commands.", ""]); const [input, setInput] = useState(""); const [isLoading, setIsLoading] = useState(false); + const [commandHistory, setCommandHistory] = useState([]); + const [historyIndex, setHistoryIndex] = useState(-1); + const terminalRef = useRef(null); + const inputRef = useRef(null); - const runCommand = async (cmd: string): Promise => { - switch (cmd) { + useEffect(() => { + if (terminalRef.current) { + terminalRef.current.scrollTop = terminalRef.current.scrollHeight; + } + }, [history]); + + const delay = (ms: number) => new Promise(r => setTimeout(r, ms)); + + const typeEffect = async (lines: string[], setFn: React.Dispatch>) => { + for (const line of lines) { + setFn(prev => [...prev, line]); + await delay(50); + } + }; + + const progressBar = async (label: string, steps = 10) => { + for (let i = 0; i <= steps; i++) { + const pct = Math.round((i / steps) * 100); + const bar = '█'.repeat(i) + '░'.repeat(steps - i); + setHistory(prev => { + const newHist = [...prev]; + if (newHist.length > 0 && newHist[newHist.length - 1].startsWith(label)) { + newHist[newHist.length - 1] = `${label} [${bar}] ${pct}%`; + } else { + newHist.push(`${label} [${bar}] ${pct}%`); + } + return newHist; + }); + await delay(100); + } + }; + + const runCommand = async (cmd: string): Promise => { + const args = cmd.split(' '); + const baseCmd = args[0]; + + switch (baseCmd) { case 'help': - return ["Available commands:", " help - Show this message", " status - System status from server", " architects - List architects in network", " projects - List active projects", " whoami - Current user info", " clear - Clear terminal", " matrix - Enter the matrix", ""]; + await typeEffect([ + "╔═══════════════════════════════════════════╗", + "║ AETHEX TERMINAL COMMANDS ║", + "╠═══════════════════════════════════════════╣", + "║ status - System status from server ║", + "║ architects - List architects in network ║", + "║ projects - List active projects ║", + "║ scan - Scan network for nodes ║", + "║ analyze - Run security analysis ║", + "║ decrypt - Decrypt secure message ║", + "║ hack - ??? (try it) ║", + "║ fortune - Random architect wisdom ║", + "║ whoami - Current user info ║", + "║ neofetch - System information ║", + "║ matrix - Enter the matrix ║", + "║ clear - Clear terminal ║", + "║ tour - AeThex guided tour ║", + "╚═══════════════════════════════════════════╝", + "" + ], setHistory); + break; + case 'status': try { + setHistory(prev => [...prev, "Fetching system status..."]); + await delay(300); const res = await fetch('/api/metrics'); const data = await res.json(); - return ["SYSTEM STATUS", ` Total Architects: ${data.totalProfiles || 0}`, ` Total Projects: ${data.totalProjects || 0}`, ` Online Users: ${data.onlineUsers || 0}`, ` Verified Users: ${data.verifiedUsers || 0}`, ` Total XP: ${data.totalXP || 0}`, ""]; + await typeEffect([ + "┌─────────────────────────────────┐", + "│ SYSTEM STATUS │", + "├─────────────────────────────────┤", + `│ Architects: ${String(data.totalProfiles || 0).padEnd(18)}│`, + `│ Projects: ${String(data.totalProjects || 0).padEnd(18)}│`, + `│ Online: ${String(data.onlineUsers || 0).padEnd(18)}│`, + `│ Verified: ${String(data.verifiedUsers || 0).padEnd(18)}│`, + `│ Total XP: ${String(data.totalXP || 0).padEnd(18)}│`, + "└─────────────────────────────────┘", + "" + ], setHistory); } catch { - return ["Error fetching status", ""]; + setHistory(prev => [...prev, "ERROR: Failed to fetch status", ""]); } + break; + case 'architects': try { + setHistory(prev => [...prev, "Querying architect database..."]); + await delay(400); const res = await fetch('/api/os/architects'); const data = await res.json(); - if (!data.length) return ["No architects found in network.", ""]; - const lines = ["ARCHITECTS IN NETWORK:", ""]; + if (!data.length) { + setHistory(prev => [...prev, "No architects found in network.", ""]); + return; + } + const lines = ["", "ARCHITECTS IN NETWORK:", "─".repeat(40)]; data.forEach((a: any) => { - lines.push(` ${a.username || 'Unknown'} - Level ${a.level} (${a.xp} XP)${a.verified ? ' [VERIFIED]' : ''}`); + const status = a.verified ? '\x1b[32m●\x1b[0m' : '\x1b[33m○\x1b[0m'; + lines.push(` ${a.username || 'Unknown'} │ Lv.${a.level} │ ${a.xp} XP ${a.verified ? '[VERIFIED]' : ''}`); }); - lines.push(""); - return lines; + lines.push("─".repeat(40), ""); + await typeEffect(lines, setHistory); } catch { - return ["Error fetching architects", ""]; + setHistory(prev => [...prev, "ERROR: Database connection failed", ""]); } + break; + case 'projects': try { + setHistory(prev => [...prev, "Loading project registry..."]); + await delay(300); const res = await fetch('/api/os/projects'); const data = await res.json(); - if (!data.length) return ["No projects found.", ""]; - const lines = ["ACTIVE PROJECTS:", ""]; + if (!data.length) { + setHistory(prev => [...prev, "No projects found.", ""]); + return; + } + const lines = ["", "ACTIVE PROJECTS:", "─".repeat(50)]; data.forEach((p: any) => { - lines.push(` ${p.title} [${p.status || 'unknown'}]${p.engine ? ` - ${p.engine}` : ''}`); + const statusColor = p.status === 'active' ? '[ACTIVE]' : `[${(p.status || 'unknown').toUpperCase()}]`; + lines.push(` ► ${p.title} ${statusColor}${p.engine ? ` - ${p.engine}` : ''}`); }); - lines.push(""); - return lines; + lines.push("─".repeat(50), ""); + await typeEffect(lines, setHistory); } catch { - return ["Error fetching projects", ""]; + setHistory(prev => [...prev, "ERROR: Registry unavailable", ""]); } + break; + + case 'scan': + setHistory(prev => [...prev, "Initiating network scan..."]); + await delay(200); + await progressBar("SCANNING", 15); + await delay(300); + const nodes = Math.floor(Math.random() * 20) + 10; + await typeEffect([ + "", + `Scan complete. ${nodes} nodes discovered.`, + "", + " NODE-001 ─── AEGIS-CORE ─── [SECURE]", + " NODE-002 ─── CODEX-AUTH ─── [SECURE]", + " NODE-003 ─── AXIOM-DB ───── [SECURE]", + ` ... ${nodes - 3} additional nodes`, + "", + "All systems operational. No threats detected.", + "" + ], setHistory); + break; + + case 'analyze': + setHistory(prev => [...prev, "Running security analysis..."]); + await progressBar("ANALYZING", 20); + await delay(200); + await typeEffect([ + "", + "╔═══════════════════════════════════════╗", + "║ SECURITY ANALYSIS REPORT ║", + "╠═══════════════════════════════════════╣", + "║ Firewall Status: ██████████ 100% ║", + "║ Encryption Level: ██████████ AES ║", + "║ Intrusion Attempts: 0 BLOCKED ║", + "║ AEGIS Shield: ACTIVE ║", + "╚═══════════════════════════════════════╝", + "", + "System integrity: VERIFIED", + "" + ], setHistory); + break; + + case 'decrypt': + setHistory(prev => [...prev, "Decrypting secure message..."]); + await progressBar("DECRYPTING", 12); + await delay(500); + const messages = [ + "The future belongs to those who build it.", + "In the Metaverse, architects are gods.", + "AEGIS protects. CODEX certifies. AXIOM guides.", + "Welcome to the new reality, Architect.", + ]; + const msg = messages[Math.floor(Math.random() * messages.length)]; + await typeEffect([ + "", + "MESSAGE DECRYPTED:", + `"${msg}"`, + "" + ], setHistory); + break; + + case 'hack': + setHistory(prev => [...prev, "Initiating hack sequence..."]); + await delay(300); + const hackLines = []; + for (let i = 0; i < 8; i++) { + let line = ""; + for (let j = 0; j < 40; j++) { + line += String.fromCharCode(Math.floor(Math.random() * 26) + 65); + } + hackLines.push(line); + } + await typeEffect(hackLines, setHistory); + await delay(500); + await typeEffect([ + "", + "ACCESS DENIED", + "", + "Nice try, but AEGIS is watching.", + "This incident has been logged. 👁️", + "" + ], setHistory); + break; + + case 'fortune': + const fortunes = [ + "A great architect once said: 'First, solve the problem. Then, write the code.'", + "The Metaverse remembers those who build with purpose.", + "Your next commit will be legendary.", + "Trust in AEGIS, for it watches over all.", + "Level up, Architect. The network awaits your greatness.", + "In the digital realm, creativity is the ultimate currency.", + ]; + setHistory(prev => [...prev, "", `🔮 ${fortunes[Math.floor(Math.random() * fortunes.length)]}`, ""]); + break; + case 'whoami': - return ["architect@aethex-os", "Role: Metaverse Architect", ""]; + await typeEffect([ + "", + "╭──────────────────────────────────╮", + "│ USER: architect@aethex-os │", + "│ ROLE: Metaverse Architect │", + "│ CLEARANCE: LEVEL-7 │", + "│ STATUS: ACTIVE │", + "╰──────────────────────────────────╯", + "" + ], setHistory); + break; + + case 'neofetch': + await typeEffect([ + "", + " ▄▄▄ .▄▄ · ▄▄▄▄▄▄ .▄▄▄▄ ▄▄▄ .▐▄• ▄ ", + " ▐█ ▀█ ▐█ ▀. •██ █▌·▐█ ▀█ █▌•█▌ █▌█▌▪", + " ▄█▀▀█ ▄▀▀▀█▄ ▐█. ▐▀▀▀ ██▀ ▐█ ▐█▌ ·██· ", + " ██ ▪▄▌ ▐█▄▪▐█ ▐█▌·▐█▄▄▌██ ██▪▪▐█·█▌ ", + " ▀▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀▀ ▀▀▀ ▀▀ ▀▀▀ · ", + "───────────────────────────────────────────────", + " OS: AeThex OS v3.0.0", + " Kernel: AEGIS-CORE 2025.12", + " Shell: aethex-terminal", + " CPU: Quantum Neural Net @ ∞GHz", + " Memory: ∞ PB / ∞ PB", + " Uptime: Always", + "" + ], setHistory); + break; + case 'matrix': - return ["Wake up, Architect...", "The Matrix has you...", "Follow the white rabbit.", ""]; + await typeEffect([ + "", + "Wake up, Architect...", + "", + "The Matrix has you...", + "" + ], setHistory); + await delay(1000); + setHistory(prev => [...prev, "Follow the white rabbit.", "", "🐇", ""]); + break; + + case 'tour': + await typeEffect([ + "", + "════════════════════════════════════════════", + " WELCOME TO AETHEX ECOSYSTEM ", + "════════════════════════════════════════════", + "", + "► AXIOM - The foundational layer", + " Core principles and values that guide", + " everything we build in the Metaverse.", + "", + "► CODEX - The certification system", + " Earn credentials, level up, and prove", + " your expertise as a Metaverse Architect.", + "", + "► AEGIS - The security shield", + " Advanced protection layer keeping the", + " ecosystem safe from threats.", + "", + "Explore the OS apps to learn more!", + "" + ], setHistory); + break; + default: - return [`Command not found: ${cmd}`, "Type 'help' for available commands.", ""]; + setHistory(prev => [...prev, `Command not found: ${cmd}`, "Type 'help' for available commands.", ""]); + } + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'ArrowUp') { + e.preventDefault(); + if (commandHistory.length > 0) { + const newIndex = historyIndex < commandHistory.length - 1 ? historyIndex + 1 : historyIndex; + setHistoryIndex(newIndex); + setInput(commandHistory[commandHistory.length - 1 - newIndex] || ''); + } + } else if (e.key === 'ArrowDown') { + e.preventDefault(); + if (historyIndex > 0) { + const newIndex = historyIndex - 1; + setHistoryIndex(newIndex); + setInput(commandHistory[commandHistory.length - 1 - newIndex] || ''); + } else { + setHistoryIndex(-1); + setInput(''); + } + } else if (e.key === 'Tab') { + e.preventDefault(); + const cmds = ['help', 'status', 'architects', 'projects', 'scan', 'analyze', 'decrypt', 'hack', 'fortune', 'whoami', 'neofetch', 'matrix', 'clear', 'tour']; + const match = cmds.find(c => c.startsWith(input.toLowerCase())); + if (match) setInput(match); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const cmd = input.trim().toLowerCase(); + if (!cmd) return; setInput(""); + setHistoryIndex(-1); + setCommandHistory(prev => [...prev, cmd]); if (cmd === 'clear') { setHistory([]); @@ -838,19 +1148,32 @@ function TerminalApp() { setHistory(prev => [...prev, `$ ${input}`]); setIsLoading(true); - - const output = await runCommand(cmd); - setHistory(prev => [...prev, ...output]); + await runCommand(cmd); setIsLoading(false); }; return ( -
- {history.map((line, i) =>
{line}
)} +
inputRef.current?.focus()}> + {history.map((line, i) => ( +
+ {line} +
+ ))} {isLoading &&
Processing...
} -
+ $ - setInput(e.target.value)} className="flex-1 ml-2 bg-transparent outline-none text-green-400" autoFocus disabled={isLoading} data-testid="terminal-input" /> + setInput(e.target.value)} + onKeyDown={handleKeyDown} + className="flex-1 ml-2 bg-transparent outline-none text-green-400 caret-green-400" + autoFocus + disabled={isLoading} + data-testid="terminal-input" + autoComplete="off" + spellCheck={false} + />
); @@ -1232,10 +1555,759 @@ function SettingsApp({ wallpaper, setWallpaper, soundEnabled, setSoundEnabled }:
-
AeThex OS v2.0.0
+
AeThex OS v3.0.0
Build 2025.12.16
); } + +function NetworkMapApp() { + const { data: architects } = useQuery({ + queryKey: ['os-network-architects'], + queryFn: async () => { + const res = await fetch('/api/os/architects'); + return res.json(); + }, + }); + + const nodes = architects?.slice(0, 8) || []; + + return ( +
+
+ +

Network Map

+
+ +
+
+ + {nodes.map((_: any, i: number) => { + const angle = (i / nodes.length) * 2 * Math.PI; + const x1 = 50 + 35 * Math.cos(angle); + const y1 = 50 + 35 * Math.sin(angle); + return ( + + ); + })} + +
+ +
+ +
+ + {nodes.map((node: any, i: number) => { + const angle = (i / nodes.length) * 2 * Math.PI - Math.PI / 2; + const radius = 140; + const x = Math.cos(angle) * radius; + const y = Math.sin(angle) * radius; + return ( + +
+
+ +
+
{node.username}
+
Lv.{node.level}
+
+
+ ); + })} +
+ +
+ {nodes.length} nodes connected +
+
+ ); +} + +function MetricsDashboardApp() { + const { data: metrics, isLoading } = useQuery({ + queryKey: ['os-dashboard-metrics'], + queryFn: async () => { + const res = await fetch('/api/metrics'); + return res.json(); + }, + refetchInterval: 30000, + }); + + const [animatedValues, setAnimatedValues] = useState({ profiles: 0, projects: 0, xp: 0 }); + + useEffect(() => { + if (metrics) { + const duration = 1000; + const steps = 20; + const interval = duration / steps; + let step = 0; + const timer = setInterval(() => { + step++; + const progress = step / steps; + setAnimatedValues({ + profiles: Math.round(progress * (metrics.totalProfiles || 0)), + projects: Math.round(progress * (metrics.totalProjects || 0)), + xp: Math.round(progress * (metrics.totalXP || 0)), + }); + if (step >= steps) clearInterval(timer); + }, interval); + return () => clearInterval(timer); + } + }, [metrics]); + + if (isLoading) { + return ( +
+ +
+ ); + } + + return ( +
+
+ +

Live Metrics

+
+ +
+
+
Architects
+
{animatedValues.profiles}
+
+ +{Math.floor(Math.random() * 5) + 1} today +
+
+
+
Projects
+
{animatedValues.projects}
+
+ Active +
+
+
+
Total XP
+
{animatedValues.xp.toLocaleString()}
+
+
+
Online
+
{metrics?.onlineUsers || 0}
+
+
Live +
+
+
+ +
+
Network Activity
+
+ {Array.from({ length: 20 }).map((_, i) => { + const height = Math.random() * 80 + 20; + return ( + + ); + })} +
+
+
+ ); +} + +function CodeEditorApp() { + const sampleCode = `// AeThex Smart Contract +import { Aegis } from '@aethex/core'; + +interface Architect { + id: string; + level: number; + xp: number; + verified: boolean; +} + +class MetaverseRegistry { + private architects: Map; + + constructor() { + this.architects = new Map(); + Aegis.initialize(); + } + + async registerArchitect( + address: string, + credentials: Credential[] + ): Promise { + const architect: Architect = { + id: generateId(), + level: 1, + xp: 0, + verified: false + }; + + await Aegis.verify(architect); + this.architects.set(address, architect); + + return architect; + } +}`; + + return ( +
+
+
+ + registry.ts +
+
+
+
+          {sampleCode.split('\n').map((line, i) => (
+            
+ {i + 1} + {line || ' '} +
+ ))} +
+
+
+ TypeScript + UTF-8 + Ln 1, Col 1 +
+
+ ); +} + +function NewsFeedApp() { + const newsItems = [ + { time: '2 min ago', title: 'New architect joined the network', type: 'info' }, + { time: '15 min ago', title: 'Project "Genesis" reached milestone', type: 'success' }, + { time: '1 hour ago', title: 'AEGIS blocked 3 intrusion attempts', type: 'warning' }, + { time: '3 hours ago', title: 'Codex certification updated', type: 'info' }, + { time: '5 hours ago', title: 'Network expansion: 5 new nodes', type: 'success' }, + { time: '1 day ago', title: 'System maintenance completed', type: 'info' }, + ]; + + return ( +
+
+ +

News Feed

+
+
+ {newsItems.map((item, i) => ( + +
+
+
+
{item.title}
+
{item.time}
+
+
+ + ))} +
+
+ ); +} + +function ArcadeApp() { + const [snake, setSnake] = useState([{ x: 10, y: 10 }]); + const [food, setFood] = useState({ x: 15, y: 15 }); + const [direction, setDirection] = useState({ x: 1, y: 0 }); + const [gameOver, setGameOver] = useState(false); + const [score, setScore] = useState(0); + const [isPlaying, setIsPlaying] = useState(false); + + useEffect(() => { + if (!isPlaying || gameOver) return; + const interval = setInterval(() => { + setSnake(prev => { + const newHead = { x: prev[0].x + direction.x, y: prev[0].y + direction.y }; + if (newHead.x < 0 || newHead.x >= 20 || newHead.y < 0 || newHead.y >= 20) { + setGameOver(true); + setIsPlaying(false); + return prev; + } + if (prev.some(s => s.x === newHead.x && s.y === newHead.y)) { + setGameOver(true); + setIsPlaying(false); + return prev; + } + const newSnake = [newHead, ...prev]; + if (newHead.x === food.x && newHead.y === food.y) { + setScore(s => s + 10); + setFood({ x: Math.floor(Math.random() * 20), y: Math.floor(Math.random() * 20) }); + } else { + newSnake.pop(); + } + return newSnake; + }); + }, 150); + return () => clearInterval(interval); + }, [isPlaying, gameOver, direction, food]); + + useEffect(() => { + const handleKey = (e: KeyboardEvent) => { + if (!isPlaying) return; + switch (e.key) { + case 'ArrowUp': if (direction.y !== 1) setDirection({ x: 0, y: -1 }); break; + case 'ArrowDown': if (direction.y !== -1) setDirection({ x: 0, y: 1 }); break; + case 'ArrowLeft': if (direction.x !== 1) setDirection({ x: -1, y: 0 }); break; + case 'ArrowRight': if (direction.x !== -1) setDirection({ x: 1, y: 0 }); break; + } + }; + window.addEventListener('keydown', handleKey); + return () => window.removeEventListener('keydown', handleKey); + }, [isPlaying, direction]); + + const startGame = () => { + setSnake([{ x: 10, y: 10 }]); + setFood({ x: 15, y: 15 }); + setDirection({ x: 1, y: 0 }); + setGameOver(false); + setScore(0); + setIsPlaying(true); + }; + + return ( +
+
+ +

Cyber Snake

+
+ +
Score: {score}
+ +
+ {Array.from({ length: 400 }).map((_, i) => { + const x = i % 20; + const y = Math.floor(i / 20); + const isSnake = snake.some(s => s.x === x && s.y === y); + const isHead = snake[0]?.x === x && snake[0]?.y === y; + const isFood = food.x === x && food.y === y; + return ( +
+ ); + })} +
+ + {!isPlaying && ( + + )} + +
Use arrow keys to move
+
+ ); +} + +function ProfilesApp() { + const { data: profiles, isLoading } = useQuery({ + queryKey: ['os-profiles-list'], + queryFn: async () => { + const res = await fetch('/api/os/architects'); + return res.json(); + }, + }); + + if (isLoading) { + return ( +
+ +
+ ); + } + + return ( +
+
+ +

Architect Profiles

+
+
+ {profiles?.map((profile: any) => ( + +
+
+ +
+
+
{profile.username || 'Anonymous'}
+
Level {profile.level}
+
+
+
+ {profile.xp} XP + {profile.verified && Verified} +
+
+ ))} +
+
+ ); +} + +function LeaderboardApp() { + const { data: architects, isLoading } = useQuery({ + queryKey: ['os-leaderboard'], + queryFn: async () => { + const res = await fetch('/api/os/architects'); + const data = await res.json(); + return data.sort((a: any, b: any) => (b.xp || 0) - (a.xp || 0)); + }, + }); + + if (isLoading) { + return ( +
+ +
+ ); + } + + return ( +
+
+ +

Leaderboard

+
+
+ {architects?.map((architect: any, i: number) => { + const medal = i === 0 ? '🥇' : i === 1 ? '🥈' : i === 2 ? '🥉' : null; + return ( + +
+ {medal || {i + 1}} +
+
+ +
+
+
{architect.username || 'Anonymous'}
+
Level {architect.level}
+
+
+
{architect.xp || 0}
+
XP
+
+
+ ); + })} +
+
+ ); +} + +function CalculatorApp() { + const [display, setDisplay] = useState('0'); + const [prev, setPrev] = useState(null); + const [op, setOp] = useState(null); + const [newNumber, setNewNumber] = useState(true); + + const handleNumber = (n: string) => { + if (newNumber) { + setDisplay(n); + setNewNumber(false); + } else { + setDisplay(display === '0' ? n : display + n); + } + }; + + const handleOp = (operator: string) => { + setPrev(parseFloat(display)); + setOp(operator); + setNewNumber(true); + }; + + const calculate = () => { + if (prev === null || !op) return; + const current = parseFloat(display); + let result = 0; + switch (op) { + case '+': result = prev + current; break; + case '-': result = prev - current; break; + case '×': result = prev * current; break; + case '÷': result = current !== 0 ? prev / current : 0; break; + } + setDisplay(String(result)); + setPrev(null); + setOp(null); + setNewNumber(true); + }; + + const clear = () => { + setDisplay('0'); + setPrev(null); + setOp(null); + setNewNumber(true); + }; + + const buttons = ['C', '±', '%', '÷', '7', '8', '9', '×', '4', '5', '6', '-', '1', '2', '3', '+', '0', '.', '=']; + + return ( +
+
+
{display}
+
+
+ {buttons.map(btn => ( + + ))} +
+
+ ); +} + +function NotesApp() { + const [notes, setNotes] = useState(() => { + const saved = localStorage.getItem('aethex-notes'); + return saved || 'Welcome to AeThex Notes!\n\nStart typing here...'; + }); + + useEffect(() => { + localStorage.setItem('aethex-notes', notes); + }, [notes]); + + return ( +
+
+ + notes.txt +
+