initial
This commit is contained in:
@@ -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 & 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 · {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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user