mirror of
https://github.com/ceratic/project_vollidioten_website.git
synced 2026-05-14 00:16:47 +02:00
154 lines
5.3 KiB
TypeScript
154 lines
5.3 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import { Routes, Route, useNavigate, useLocation } from 'react-router-dom';
|
|
import Layout from './components/Layout';
|
|
import Dashboard from './pages/Dashboard';
|
|
import Players from './pages/Players';
|
|
import PlayerProfile from './pages/PlayerProfile';
|
|
import SetupGuide from './pages/SetupGuide';
|
|
import Projects from './pages/Projects';
|
|
import Organizations from './pages/Organizations';
|
|
import Cities from './pages/Cities';
|
|
import CityProfile from './pages/CityProfile';
|
|
import ProjectProfile from './pages/ProjectProfile';
|
|
import DatapackGenerator from './pages/DatapackGenerator';
|
|
import DatabaseManager from './pages/DatabaseManager';
|
|
import LinkPlayer from './pages/LinkPlayer';
|
|
import AdminPage from './pages/Admin';
|
|
import { dbService } from './services/DatabaseService';
|
|
import { authService } from './services/AuthService';
|
|
import { DiscordUser } from './types';
|
|
|
|
function App() {
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
|
|
// Auth state
|
|
const [user, setUser] = useState<DiscordUser | null>(null);
|
|
const [authChecked, setAuthChecked] = useState(false);
|
|
|
|
// State for data from DB (Async)
|
|
const [players, setPlayers] = useState(dbService.getPlayers());
|
|
const [orgs, setOrgs] = useState(dbService.getOrgs());
|
|
const [projects, setProjects] = useState(dbService.getProjects());
|
|
|
|
// Subscribe to DB updates (when fetch completes or edits happen)
|
|
useEffect(() => {
|
|
const unsub = dbService.subscribe(() => {
|
|
setPlayers([...dbService.getPlayers()]);
|
|
setOrgs([...dbService.getOrgs()]);
|
|
setProjects([...dbService.getProjects()]);
|
|
});
|
|
return unsub;
|
|
}, []);
|
|
|
|
// Subscribe to auth updates
|
|
useEffect(() => {
|
|
const unsub = authService.subscribe((currentUser) => {
|
|
setUser(currentUser);
|
|
setAuthChecked(true);
|
|
|
|
// If user is logged in but not linked, redirect to link page
|
|
if (currentUser && !currentUser.linkedPlayerUuid) {
|
|
navigate('/link-player');
|
|
} else if (currentUser && currentUser.linkedPlayerUuid) {
|
|
// User is fully authenticated, redirect from link page if needed
|
|
if (location.pathname === '/link-player') {
|
|
navigate('/');
|
|
}
|
|
}
|
|
});
|
|
return unsub;
|
|
}, [navigate, location.pathname]);
|
|
|
|
const navigateToPlayer = (id: string) => {
|
|
navigate(`/players/${id}`);
|
|
};
|
|
|
|
const navigateToProject = (id: string) => {
|
|
navigate(`/projects/${id}`);
|
|
};
|
|
|
|
const navigateToOrg = (id: string) => {
|
|
const org = orgs.find(o => o.id === id);
|
|
if (org?.type === 'City') {
|
|
navigate(`/cities/${id}`);
|
|
} else {
|
|
navigate(`/organizations/${id}`);
|
|
}
|
|
};
|
|
|
|
const handleNavigate = (path: string) => {
|
|
navigate(path);
|
|
};
|
|
|
|
// Determine active tab from current path
|
|
const getActiveTab = () => {
|
|
const path = location.pathname;
|
|
if (path === '/') return 'dashboard';
|
|
if (path.startsWith('/players')) return 'players';
|
|
if (path.startsWith('/cities')) return 'cities';
|
|
if (path.startsWith('/projects')) return 'projects';
|
|
if (path.startsWith('/organizations')) return 'organizations';
|
|
if (path.startsWith('/admin')) return 'admin';
|
|
if (path === '/setup') return 'setup';
|
|
if (path === '/datapack') return 'datapack';
|
|
if (path === '/link-player') return 'link-player';
|
|
return 'dashboard';
|
|
};
|
|
|
|
const activeTab = getActiveTab();
|
|
|
|
return (
|
|
<Layout activeTab={activeTab} onNavigate={handleNavigate}>
|
|
<Routes>
|
|
{/* Auth Route */}
|
|
<Route path="/link-player" element={<LinkPlayer />} />
|
|
|
|
{/* Main Routes */}
|
|
<Route path="/" element={<Dashboard />} />
|
|
<Route path="/setup" element={<SetupGuide />} />
|
|
<Route path="/datapack" element={<DatapackGenerator />} />
|
|
|
|
{/* Player Routes */}
|
|
<Route path="/players" element={<Players onSelectPlayer={navigateToPlayer} />} />
|
|
<Route path="/players/:id" element={<PlayerProfile />} />
|
|
|
|
{/* City Routes */}
|
|
<Route path="/cities" element={<Cities onSelectCity={(id) => navigateToOrg(id)} />} />
|
|
<Route path="/cities/:id" element={<CityProfile />} />
|
|
|
|
{/* Organization Routes */}
|
|
<Route path="/organizations" element={<Organizations onSelectOrg={(id) => navigateToOrg(id)} />} />
|
|
<Route path="/organizations/:id" element={<CityProfile />} />
|
|
|
|
{/* Project Routes */}
|
|
<Route path="/projects" element={<Projects onSelectProject={(id) => navigateToProject(id)} />} />
|
|
<Route path="/projects/:id" element={<ProjectProfile
|
|
onBack={() => navigate('/projects')}
|
|
onSelectPlayer={navigateToPlayer}
|
|
onSelectOrg={navigateToOrg}
|
|
/>} />
|
|
|
|
{/* Admin Routes */}
|
|
<Route path="/admin" element={<AdminPage onBack={() => navigate('/')} />} />
|
|
|
|
{/* Fallback */}
|
|
<Route path="*" element={
|
|
<div className="flex flex-col items-center justify-center h-[50vh] text-textMuted">
|
|
<div className="text-6xl mb-4">404</div>
|
|
<p>Seite nicht gefunden</p>
|
|
<button
|
|
onClick={() => navigate('/')}
|
|
className="mt-4 text-accentInfo hover:underline"
|
|
>
|
|
Zurück zur Startseite
|
|
</button>
|
|
</div>
|
|
} />
|
|
</Routes>
|
|
</Layout>
|
|
);
|
|
}
|
|
|
|
export default App;
|