This commit is contained in:
2026-07-02 22:13:33 +02:00
parent b343ad8a38
commit ba6c35f76d
30 changed files with 2752 additions and 2 deletions
+109
View File
@@ -0,0 +1,109 @@
import React, { useEffect, useState, useCallback } from "react";
import { api } from "./api";
import ProjectsTab from "./components/ProjectsTab.jsx";
import PeopleTab from "./components/PeopleTab.jsx";
import TimelineTab from "./components/TimelineTab.jsx";
import CapacityTab from "./components/CapacityTab.jsx";
const NAV = [
{ key: "timeline", index: "01", label: "Zeitachse" },
{ key: "capacity", index: "02", label: "Kapazitaet" },
{ key: "projects", index: "03", label: "Projekte & Aufgaben" },
{ key: "people", index: "04", label: "Team" }
];
export default function App() {
const [view, setView] = useState("timeline");
const [people, setPeople] = useState([]);
const [projects, setProjects] = useState([]);
const [tasks, setTasks] = useState([]);
const [absences, setAbsences] = useState([]);
const [loading, setLoading] = useState(true);
const [loadError, setLoadError] = useState(null);
const reloadAll = useCallback(async () => {
try {
const [p, pr, t, a] = await Promise.all([
api.people.list(),
api.projects.list(),
api.tasks.list(),
api.absences.list()
]);
setPeople(p);
setProjects(pr);
setTasks(t);
setAbsences(a);
setLoadError(null);
} catch (err) {
setLoadError(err.message);
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
reloadAll();
}, [reloadAll]);
const currentYear = new Date().getFullYear();
return (
<div className="app-shell">
<aside className="sidebar">
<div className="brand">
<span className="brand-mark">Jahresplan</span>
<span className="brand-sub">Planung &amp; Kapazitaet {currentYear}</span>
</div>
<ul className="nav-list">
{NAV.map((item) => (
<li key={item.key}>
<button
className={`nav-item ${view === item.key ? "active" : ""}`}
onClick={() => setView(item.key)}
>
<span className="nav-index">{item.index}</span>
{item.label}
</button>
</li>
))}
</ul>
<div className="sidebar-foot">
{people.length} Personen &middot; {projects.length} Projekte
<br />
{tasks.length} Aufgaben insgesamt
</div>
</aside>
<main className="main">
{loadError && (
<div className="panel" style={{ borderColor: "var(--danger)" }}>
<p className="error-text" style={{ margin: 0 }}>
Daten konnten nicht geladen werden: {loadError}
</p>
</div>
)}
{!loading && view === "timeline" && (
<TimelineTab projects={projects} tasks={tasks} people={people} />
)}
{!loading && view === "capacity" && (
<CapacityTab people={people} />
)}
{!loading && view === "projects" && (
<ProjectsTab
projects={projects}
tasks={tasks}
people={people}
onChange={reloadAll}
/>
)}
{!loading && view === "people" && (
<PeopleTab people={people} absences={absences} onChange={reloadAll} />
)}
</main>
</div>
);
}