mirror of
https://github.com/ceratic/project_vollidioten_website.git
synced 2026-05-14 00:16:47 +02:00
Sets up the foundational structure for the Obsidian | RP Plattform. This includes configuring Vite as the build tool, integrating React for the UI, and establishing TypeScript for type safety. Also includes initial styling and placeholder data to define the application's core interfaces.
168 lines
6.2 KiB
TypeScript
168 lines
6.2 KiB
TypeScript
import React, { useState } from 'react';
|
|
import Layout from './components/Layout';
|
|
import Dashboard from './pages/Dashboard';
|
|
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 { MOCK_PLAYERS, MOCK_ORGS, MOCK_PROJECTS } from './constants';
|
|
import { Icons } from './components/IconSet';
|
|
|
|
function App() {
|
|
const [activeTab, setActiveTab] = useState('dashboard');
|
|
const [selectedPlayerId, setSelectedPlayerId] = useState<string | null>(null);
|
|
const [selectedCityId, setSelectedCityId] = useState<string | null>(null);
|
|
const [selectedProjectId, setSelectedProjectId] = useState<string | null>(null);
|
|
const [selectedOrgId, setSelectedOrgId] = useState<string | null>(null);
|
|
|
|
const handleNavigate = (tab: string) => {
|
|
setActiveTab(tab);
|
|
if (tab !== 'players') setSelectedPlayerId(null);
|
|
if (tab !== 'cities') setSelectedCityId(null);
|
|
if (tab !== 'projects') setSelectedProjectId(null);
|
|
if (tab !== 'organizations') setSelectedOrgId(null);
|
|
};
|
|
|
|
// Helper to jump to a player from another view
|
|
const navigateToPlayer = (id: string) => {
|
|
setSelectedPlayerId(id);
|
|
setActiveTab('players');
|
|
};
|
|
|
|
// Helper to jump to a project from another view
|
|
const navigateToProject = (id: string) => {
|
|
setSelectedProjectId(id);
|
|
setActiveTab('projects');
|
|
};
|
|
|
|
// Helper to jump to an org/city
|
|
const navigateToOrg = (id: string) => {
|
|
const org = MOCK_ORGS.find(o => o.id === id);
|
|
if (org?.type === 'City') {
|
|
setSelectedCityId(id);
|
|
setActiveTab('cities');
|
|
} else {
|
|
setSelectedOrgId(id);
|
|
setActiveTab('organizations');
|
|
}
|
|
};
|
|
|
|
const renderContent = () => {
|
|
if (activeTab === 'dashboard') return <Dashboard />;
|
|
|
|
if (activeTab === 'projects') {
|
|
if (selectedProjectId) {
|
|
const project = MOCK_PROJECTS.find(p => p.id === selectedProjectId);
|
|
if (project) return (
|
|
<ProjectProfile
|
|
project={project}
|
|
onBack={() => setSelectedProjectId(null)}
|
|
onSelectPlayer={navigateToPlayer}
|
|
onSelectOrg={navigateToOrg}
|
|
/>
|
|
);
|
|
}
|
|
return <Projects onSelectProject={setSelectedProjectId} />;
|
|
}
|
|
|
|
if (activeTab === 'organizations') {
|
|
if (selectedOrgId) {
|
|
const org = MOCK_ORGS.find(o => o.id === selectedOrgId);
|
|
if (org) return (
|
|
<CityProfile
|
|
city={org}
|
|
onBack={() => setSelectedOrgId(null)}
|
|
backLabel="Zurück zum Verzeichnis"
|
|
onSelectPlayer={navigateToPlayer}
|
|
onSelectProject={navigateToProject}
|
|
/>
|
|
);
|
|
}
|
|
return <Organizations onSelectOrg={setSelectedOrgId} />;
|
|
}
|
|
|
|
if (activeTab === 'setup') return <SetupGuide />;
|
|
|
|
if (activeTab === 'datapack') return <DatapackGenerator />;
|
|
|
|
if (activeTab === 'cities') {
|
|
if (selectedCityId) {
|
|
const city = MOCK_ORGS.find(o => o.id === selectedCityId);
|
|
if (city) return (
|
|
<CityProfile
|
|
city={city}
|
|
onBack={() => setSelectedCityId(null)}
|
|
backLabel="Zurück zu Städte"
|
|
onSelectPlayer={navigateToPlayer}
|
|
onSelectProject={navigateToProject}
|
|
/>
|
|
);
|
|
}
|
|
return <Cities onSelectCity={setSelectedCityId} />;
|
|
}
|
|
|
|
if (activeTab === 'players') {
|
|
if (selectedPlayerId) {
|
|
const player = MOCK_PLAYERS.find(p => p.uuid === selectedPlayerId);
|
|
if (player) return <PlayerProfile player={player} onBack={() => setSelectedPlayerId(null)} />;
|
|
}
|
|
|
|
return (
|
|
<div className="animate-in fade-in">
|
|
<div className="flex justify-between items-center mb-6">
|
|
<h2 className="text-2xl font-bold">Bürgerverzeichnis</h2>
|
|
<div className="relative">
|
|
<Icons.Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-textMuted" />
|
|
<input
|
|
type="text"
|
|
placeholder="Filtern nach Tag oder Name..."
|
|
className="bg-surfaceHighlight border border-border rounded-lg pl-10 pr-4 py-2 text-sm text-textMain focus:border-accentInfo focus:outline-none w-64 transition-colors"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
|
|
{MOCK_PLAYERS.map(player => (
|
|
<div
|
|
key={player.uuid}
|
|
onClick={() => setSelectedPlayerId(player.uuid)}
|
|
className="group bg-surface border border-border p-4 rounded-xl cursor-pointer hover:border-accentInfo/50 transition-all duration-200 hover:shadow-card"
|
|
>
|
|
<div className="flex items-center gap-4">
|
|
<div className="w-12 h-12 rounded-md flex items-center justify-center font-bold text-lg text-textMuted group-hover:text-textMain transition-colors">
|
|
<img src={"https://minotar.net/armor/bust/"+player.username+"/500.png"}></img>
|
|
</div>
|
|
<div>
|
|
<div className="font-semibold text-textMain group-hover:text-accentInfo transition-colors">{player.username}</div>
|
|
<div className="text-xs text-textMuted mt-1 flex gap-2">
|
|
{player.tags.slice(0, 2).map(t => <span key={t}>{t}</span>)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="flex flex-col items-center justify-center h-[50vh] text-textMuted">
|
|
<Icons.Box className="w-12 h-12 mb-4 opacity-20" />
|
|
<p>Modul <strong>{activeTab}</strong> wird derzeit gewartet.</p>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<Layout activeTab={activeTab} onNavigate={handleNavigate}>
|
|
{renderContent()}
|
|
</Layout>
|
|
);
|
|
}
|
|
|
|
export default App; |