feat: add frontend case list, detail, and creation pages (Phase 1F)

- Case list page (/cases) with search, status/type filters, status badges
- Case creation page (/cases/new) with reusable CaseForm component
- Case detail page (/cases/[id]) with tabs: Timeline, Deadlines, Documents, Parties
- CaseTimeline component for chronological case_events display
- PartyList component with inline party CRUD (add/delete)
- Updated sidebar navigation to route to /cases
This commit is contained in:
m
2026-03-25 13:50:20 +01:00
parent 0fac764211
commit 3a56d4cf11
7 changed files with 896 additions and 1 deletions

View File

@@ -0,0 +1,60 @@
"use client";
import type { CaseEvent } from "@/lib/types";
import { format } from "date-fns";
import { de } from "date-fns/locale";
const EVENT_ICONS: Record<string, string> = {
case_created: "bg-emerald-500",
status_changed: "bg-amber-500",
party_added: "bg-blue-500",
case_archived: "bg-neutral-400",
document_uploaded: "bg-violet-500",
deadline_created: "bg-red-500",
};
interface CaseTimelineProps {
events: CaseEvent[];
}
export function CaseTimeline({ events }: CaseTimelineProps) {
if (events.length === 0) {
return (
<p className="py-8 text-center text-sm text-neutral-400">
Keine Ereignisse vorhanden.
</p>
);
}
return (
<div className="relative space-y-0">
{events.map((event, i) => (
<div key={event.id} className="relative flex gap-3 pb-6">
{i < events.length - 1 && (
<div className="absolute left-[7px] top-4 h-full w-px bg-neutral-200" />
)}
<div
className={`mt-1 h-[15px] w-[15px] shrink-0 rounded-full border-2 border-white ${EVENT_ICONS[event.event_type ?? ""] ?? "bg-neutral-300"}`}
/>
<div className="min-w-0 flex-1">
<p className="text-sm font-medium text-neutral-900">
{event.title}
</p>
{event.description && (
<p className="mt-0.5 text-sm text-neutral-500">
{event.description}
</p>
)}
<p className="mt-1 text-xs text-neutral-400">
{format(
new Date(event.event_date ?? event.created_at),
"d. MMM yyyy, HH:mm",
{ locale: de },
)}
</p>
</div>
</div>
))}
</div>
);
}