Initial MUH app implementation

This commit is contained in:
2026-03-12 11:43:27 +01:00
commit fb8e3c8ef6
69 changed files with 8387 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
import { NavLink, Outlet, useLocation, useNavigate } from "react-router-dom";
import { useSession } from "../lib/session";
const NAV_ITEMS = [
{ to: "/home", label: "Start" },
{ to: "/samples/new", label: "Neue Probe" },
{ to: "/admin", label: "Verwaltung" },
{ to: "/portal", label: "Portal" },
];
const PAGE_TITLES: Record<string, string> = {
"/home": "Startseite",
"/samples/new": "Neuanlage einer Probe",
"/admin": "Verwaltung",
"/portal": "MUH-Portal",
};
function resolvePageTitle(pathname: string) {
if (pathname.includes("/anamnesis")) {
return "Anamnese";
}
if (pathname.includes("/antibiogram")) {
return "Antibiogramm";
}
if (pathname.includes("/therapy")) {
return "Therapieempfehlung";
}
if (pathname.includes("/registration")) {
return "Probe bearbeiten";
}
return PAGE_TITLES[pathname] ?? "MUH App";
}
export default function AppShell() {
const { user, setUser } = useSession();
const location = useLocation();
const navigate = useNavigate();
return (
<div className="app-shell">
<aside className="sidebar">
<div className="sidebar__brand">
<div className="sidebar__logo">MUH</div>
</div>
<nav className="sidebar__nav">
{NAV_ITEMS.map((item) => (
<NavLink
key={item.to}
to={item.to}
className={({ isActive }) => `nav-link ${isActive ? "is-active" : ""}`}
>
{item.label}
</NavLink>
))}
</nav>
<div className="sidebar__footer">
<div className="user-chip user-chip--stacked">
<span>{user?.displayName}</span>
<small>{user?.code}</small>
</div>
<button
type="button"
className="ghost-button"
onClick={() => {
setUser(null);
navigate("/");
}}
>
Abmelden
</button>
</div>
</aside>
<div className="shell-main">
<header className="topbar">
<div className="topbar__headline">
<h2>{resolvePageTitle(location.pathname)}</h2>
</div>
<div className="topbar__actions">
<button type="button" className="accent-button" onClick={() => navigate("/samples/new")}>
Neuanlage
</button>
</div>
</header>
<main className="content-area">
<Outlet />
</main>
</div>
</div>
);
}