feat(frontend): Oberfläche mit RRULE-Editor und Logo-Auswahl
- Vite, React 18, TypeScript und Tailwind mit dunklem Standard-Theme über CSS-Variablen, heller Modus umschaltbar und in localStorage gemerkt - Anmeldung, erzwungener Passwortwechsel, Layout mit Seitenleiste - API-Client mit stiller Token-Erneuerung, TanStack Query mit Fehler-Toasts - Seiten Recurrences (inkl. Detail-Drawer), Transactions, Merchants, Settings - Geführter RRULE-Editor mit Vorlagen, Expertenmodus, deutschem Klartext und Live-Vorschau der nächsten Termine vom preview-Endpunkt - Firmen-Kachelgrid mit Logo, Markenfarbe und Logo-Auswahldialog samt Upload - Beträge durchgängig in de-DE, Eingabe in beiden Schreibweisen - 49 Tests, tsc --noEmit und eslint sauber, Produktionsbundle baut Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
||||
import { Building2, type LucideIcon, Receipt, Repeat, Settings } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/cn";
|
||||
|
||||
interface NavEintrag {
|
||||
to: string;
|
||||
label: string;
|
||||
icon: LucideIcon;
|
||||
}
|
||||
|
||||
const NAVIGATION: NavEintrag[] = [
|
||||
{ to: "/recurrences", label: "Wiederkehrend", icon: Repeat },
|
||||
{ to: "/transactions", label: "Buchungen", icon: Receipt },
|
||||
{ to: "/merchants", label: "Firmen", icon: Building2 },
|
||||
{ to: "/settings", label: "Einstellungen", icon: Settings },
|
||||
];
|
||||
|
||||
export function Sidebar({ onNavigate }: { onNavigate?: () => void }) {
|
||||
return (
|
||||
<nav aria-label="Hauptnavigation" className="flex h-full flex-col gap-1 p-3">
|
||||
<div className="mb-4 flex items-center gap-2 px-2 py-1">
|
||||
<span
|
||||
aria-hidden
|
||||
className="flex h-8 w-8 items-center justify-center rounded-lg bg-accent text-sm font-bold text-accent-ink"
|
||||
>
|
||||
m
|
||||
</span>
|
||||
<span className="text-base font-semibold tracking-tight text-ink">moneyfy</span>
|
||||
</div>
|
||||
|
||||
{NAVIGATION.map(({ to, label, icon: Icon }) => (
|
||||
<NavLink
|
||||
key={to}
|
||||
to={to}
|
||||
onClick={onNavigate}
|
||||
className={({ isActive }) =>
|
||||
cn(
|
||||
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition",
|
||||
isActive ? "bg-accent/15 text-accent" : "text-muted hover:bg-raised hover:text-ink",
|
||||
)
|
||||
}
|
||||
>
|
||||
<Icon aria-hidden className="h-4 w-4 shrink-0" />
|
||||
{label}
|
||||
</NavLink>
|
||||
))}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user