Files
webdev-pipeline/app/dashboard/page.tsx

107 lines
3.9 KiB
TypeScript

import {
dashboardKpis,
pipelineHealth,
reviewQueue,
} from "@/lib/dashboard-model";
import { LeadFunnelBoard } from "@/components/lead-funnel-board";
export default function DashboardPage() {
return (
<main className="px-4 py-5 sm:px-6 lg:px-8">
<div className="mx-auto flex w-full max-w-7xl flex-col gap-6">
<header className="flex flex-col gap-3 border-b pb-5 lg:flex-row lg:items-end lg:justify-between">
<div>
<p className="text-sm font-medium text-muted-foreground">
Interner Arbeitsbereich
</p>
<h1 className="mt-2 text-3xl font-semibold tracking-normal">
Pipeline-Übersicht
</h1>
<p className="mt-2 max-w-2xl text-sm leading-6 text-muted-foreground">
Recherche, Audit-Freigabe und Outreach bleiben eng gekoppelt:
wenige gute Leads, manuelle Prüfung, kein automatischer Versand.
</p>
</div>
<p className="text-sm font-medium text-muted-foreground">MVP intern</p>
</header>
<section className="grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
{dashboardKpis.map((kpi) => (
<article
className="rounded-lg border bg-card p-4 text-card-foreground"
key={kpi.label}
>
<p className="text-sm text-muted-foreground">{kpi.label}</p>
<p className="mt-3 text-3xl font-semibold tracking-normal">
{kpi.value}
</p>
<p className="mt-2 text-sm leading-5 text-muted-foreground">
{kpi.detail}
</p>
</article>
))}
</section>
<LeadFunnelBoard />
<section className="grid gap-3 lg:grid-cols-[1.45fr_0.55fr]">
<div className="rounded-lg border bg-card text-card-foreground">
<div className="border-b p-4">
<h2 className="text-base font-semibold tracking-normal">
Nächste Review-Schritte
</h2>
<p className="mt-1 text-sm leading-6 text-muted-foreground">
Alles bleibt an manuelle Freigabe gekoppelt.
</p>
</div>
<div className="divide-y">
{reviewQueue.map((item) => (
<article
className="grid gap-2 p-4 sm:grid-cols-[1fr_auto]"
key={`${item.title}-${item.company}`}
>
<div>
<h3 className="text-sm font-medium">{item.title}</h3>
<p className="mt-1 text-sm text-muted-foreground">
{item.company}
</p>
</div>
<p className="max-w-sm text-sm leading-6 text-muted-foreground sm:text-right">
{item.detail}
</p>
</article>
))}
</div>
</div>
<div className="rounded-lg border bg-card p-4 text-card-foreground">
<h2 className="text-base font-semibold tracking-normal">
Betriebsmodus
</h2>
<div className="mt-4 grid gap-3">
{pipelineHealth.map((item) => {
const Icon = item.icon;
return (
<div
className="flex items-center justify-between gap-3 rounded-lg border bg-background p-3"
key={item.label}
>
<span className="inline-flex items-center gap-2 text-sm font-medium">
<Icon className="size-4 text-muted-foreground" />
{item.label}
</span>
<span className="text-right text-sm text-muted-foreground">
{item.value}
</span>
</div>
);
})}
</div>
</div>
</section>
</div>
</main>
);
}