feat: modernize main list pages from tables to card-based rows

New shared ListItemCard component: icon avatar, title/subtitle, trailing
badges/actions, chevron affordance when linked to a detail page. Applied
to the 9 primary data-list pages (Bienenstaende, Voelker, Koeniginnen,
Honigchargen, Aufgaben, Lager, Produkte, Inventar, Wiederkehrende
Aufgaben), replacing the plain HTML tables with the same rounded-card
list aesthetic already used elsewhere in the app (inspections,
treatments, varroa, etc.), for a consistent look across the whole
product. Admin/settings tables (Benutzer, Webhooks, Audit-Log, Import)
intentionally left as tables per user's scoping choice.
This commit is contained in:
Nick Szaunig committed 2026-08-25 23:49:31 +02:00
1 parent faefd47e4b
commit c586bff18f
10 files changed
+242 -362

No files matched your search

@@ -0,0 +1,56 @@
import { ReactNode } from "react";
import Link from "next/link";
import { ChevronRight, type LucideIcon } from "lucide-react";
import { Card, CardContent } from "@/components/ui/card";
interface ListItemCardProps {
href?: string;
icon: LucideIcon;
gradient?: string;
title: ReactNode;
subtitle?: ReactNode;
trailing?: ReactNode;
className?: string;
}
export function ListItemCard({
href,
icon: Icon,
gradient = "var(--gradient-honey)",
title,
subtitle,
trailing,
className,
}: ListItemCardProps) {
const body = (
<Card interactive={Boolean(href)} className={className}>
<CardContent className="flex items-center gap-3">
<div
className="flex size-10 shrink-0 items-center justify-center rounded-xl text-white shadow-[var(--shadow-soft)]"
style={{ background: gradient }}
>
<Icon className="size-5" />
</div>
<div className="min-w-0 flex-1">
<p className="truncate font-medium">{title}</p>
{subtitle ? (
<p className="truncate text-sm text-muted-foreground">{subtitle}</p>
) : null}
</div>
{trailing ? <div className="flex shrink-0 items-center gap-2">{trailing}</div> : null}
{href ? (
<ChevronRight className="size-4 shrink-0 text-muted-foreground/60" />
) : null}
</CardContent>
</Card>
);
if (href) {
return (
<Link href={href} className="block">
{body}
</Link>
);
}
return body;
}