Files
dumpsterChat/web/src/App.tsx
T
hobokenchicken 3f33859f4a feat: UI for server/channel creation, settings link, role management backend
Frontend:
- Settings link in header next to logout
- [+] button to create server (name + optional icon)
- [#] button to join server via invite code
- [+] button to create channel (name, type, category)
- Server name shown instead of UUID in channel list header
- /invites/:code route wired for JoinServer component

Backend:
- Wire role CRUD + member-role assignment routes (MANAGE_SERVER gated)
- Seed @everyone default role on server creation
2026-06-29 12:50:46 -04:00

119 lines
4.3 KiB
TypeScript

import { BrowserRouter, Routes, Route, Navigate, Link } from 'react-router-dom';
import { LoginForm } from './components/LoginForm.tsx';
import { Layout } from './components/Layout.tsx';
import { ChatArea } from './components/ChatArea.tsx';
import { UserSettings } from './components/UserSettings.tsx';
import { BotManager } from './components/BotManager.tsx';
import { CommandManager } from './components/CommandManager.tsx';
import { RoleManager } from './components/RoleManager.tsx';
import { JoinServer } from './components/JoinServer.tsx';
import { useAuthStore } from './stores/auth.ts';
function ProtectedRoute({ children }: { children: React.ReactNode }) {
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
return isAuthenticated ? <>{children}</> : <Navigate to="/login" replace />;
}
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/login" element={<LoginForm />} />
<Route
path="/settings"
element={
<ProtectedRoute>
<div className="h-full w-full flex flex-col bg-gb-bg">
<header className="flex items-center gap-4 px-4 py-2 border-b border-gb-bg-t bg-gb-bg-s">
<Link to="/" className="text-gb-fg-f hover:text-gb-aqua font-mono text-sm">
[BACK]
</Link>
<span className="text-gb-orange font-mono text-sm">SETTINGS</span>
</header>
<div className="flex-1 overflow-hidden">
<UserSettings />
</div>
</div>
</ProtectedRoute>
}
/>
<Route
path="/bots"
element={
<ProtectedRoute>
<div className="h-full w-full flex flex-col bg-gb-bg">
<header className="flex items-center gap-4 px-4 py-2 border-b border-gb-bg-t bg-gb-bg-s">
<Link to="/" className="text-gb-fg-f hover:text-gb-aqua font-mono text-sm">
[BACK]
</Link>
<span className="text-gb-orange font-mono text-sm">BOT MANAGER</span>
</header>
<div className="flex-1 overflow-hidden">
<BotManager />
</div>
</div>
</ProtectedRoute>
}
/>
<Route
path="/bots/:id/commands"
element={
<ProtectedRoute>
<div className="h-full w-full flex flex-col bg-gb-bg">
<header className="flex items-center gap-4 px-4 py-2 border-b border-gb-bg-t bg-gb-bg-s">
<Link to="/bots" className="text-gb-fg-f hover:text-gb-aqua font-mono text-sm">
[BACK]
</Link>
<span className="text-gb-orange font-mono text-sm">SLASH COMMANDS</span>
</header>
<div className="flex-1 overflow-hidden">
<CommandManager />
</div>
</div>
</ProtectedRoute>
}
/>
<Route
path="/servers/:serverId/roles"
element={
<ProtectedRoute>
<div className="h-full w-full flex flex-col bg-gb-bg">
<header className="flex items-center gap-4 px-4 py-2 border-b border-gb-bg-t bg-gb-bg-s">
<Link to="/" className="text-gb-fg-f hover:text-gb-aqua font-mono text-sm">
[BACK]
</Link>
<span className="text-gb-orange font-mono text-sm">ROLE MANAGER</span>
</header>
<div className="flex-1 overflow-hidden">
<RoleManager />
</div>
</div>
</ProtectedRoute>
}
/>
<Route
path="/invites/:code"
element={
<ProtectedRoute>
<JoinServer />
</ProtectedRoute>
}
/>
<Route
path="/"
element={
<ProtectedRoute>
<Layout />
</ProtectedRoute>
}
>
<Route index element={<ChatArea />} />
<Route path="channels/:channelId" element={<ChatArea />} />
</Route>
</Routes>
</BrowserRouter>
);
}
export default App;