Add routing

This commit is contained in:
Peter Stockings
2026-01-10 10:33:43 +11:00
parent 0c53496e9b
commit eb78a1b098
5 changed files with 35 additions and 29 deletions

View File

@@ -1,27 +1,21 @@
import { useState } from 'react';
import Sidebar, { type AppId } from './components/Sidebar';
import { Routes, Route, Navigate } from 'react-router-dom';
import Sidebar from './components/Sidebar';
import ImageApprox from './apps/ImageApprox/ImageApprox';
import SnakeAI from './apps/SnakeAI/SnakeAI';
import './App.css';
function App() {
const [currentApp, setCurrentApp] = useState<AppId>('image-approx');
const renderApp = () => {
switch (currentApp) {
case 'image-approx':
return <ImageApprox />;
case 'snake-ai':
return <SnakeAI />;
default:
return <div>App not found</div>;
}
};
return (
<div className="app-layout">
<Sidebar currentApp={currentApp} onAppChange={setCurrentApp} />
<main className="app-main">{renderApp()}</main>
<Sidebar />
<main className="app-main">
<Routes>
<Route path="/" element={<Navigate to="/image-approx" replace />} />
<Route path="/image-approx" element={<ImageApprox />} />
<Route path="/snake-ai" element={<SnakeAI />} />
<Route path="*" element={<div>App not found</div>} />
</Routes>
</main>
</div>
);
}

View File

@@ -1,9 +1,11 @@
import { NavLink } from 'react-router-dom';
import './Sidebar.css';
export type AppId = 'image-approx' | 'snake-ai';
export interface AppInfo {
id: AppId;
path: string;
name: string;
icon: string;
description: string;
@@ -12,24 +14,21 @@ export interface AppInfo {
export const APPS: AppInfo[] = [
{
id: 'image-approx',
path: '/image-approx',
name: 'Image Approximation',
icon: '🎨',
description: 'Evolve triangles to approximate images',
},
{
id: 'snake-ai',
path: '/snake-ai',
name: 'Neural Network Snake',
icon: '🐍',
description: 'Evolve neural networks to play Snake',
},
];
interface SidebarProps {
currentApp: AppId;
onAppChange: (appId: AppId) => void;
}
export default function Sidebar({ currentApp, onAppChange }: SidebarProps) {
export default function Sidebar() {
return (
<aside className="sidebar">
<div className="sidebar-header">
@@ -39,15 +38,15 @@ export default function Sidebar({ currentApp, onAppChange }: SidebarProps) {
<nav className="sidebar-nav">
{APPS.map((app) => (
<button
<NavLink
key={app.id}
className={`nav-item ${currentApp === app.id ? 'active' : ''}`}
onClick={() => onAppChange(app.id)}
to={app.path}
className={({ isActive }) => `nav-item ${isActive ? 'active' : ''}`}
title={app.description}
>
<span className="nav-icon">{app.icon}</span>
<span className="nav-name">{app.name}</span>
</button>
</NavLink>
))}
</nav>

View File

@@ -1,10 +1,13 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import './index.css'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>,
)