chore: initialize Next.js project baseline

This commit is contained in:
2026-07-01 06:27:09 -07:00
commit 7f227c5f2a
53 changed files with 5894 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
import type { LucideIcon } from "lucide-react";
import { ArrowRight, CheckCircle2 } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
type ModuleMetric = {
label: string;
value: string;
detail: string;
};
type ModulePageProps = {
title: string;
eyebrow: string;
description: string;
icon: LucideIcon;
phase: "一期" | "二期预留" | "三期预留";
metrics: ModuleMetric[];
workflows: string[];
};
export function ModulePage({
title,
eyebrow,
icon: Icon,
phase,
metrics,
workflows,
}: ModulePageProps): React.ReactElement {
return (
<div className="mx-auto flex w-full max-w-7xl flex-col gap-6">
<section className="flex flex-col justify-between gap-4 border-b pb-5 lg:flex-row lg:items-end">
<div className="max-w-3xl">
<Badge variant={phase === "一期" ? "success" : "secondary"}>{phase}</Badge>
<div className="mt-4 flex items-center gap-3">
<span className="inline-flex size-11 items-center justify-center rounded-md bg-secondary text-primary">
<Icon className="size-5" aria-hidden="true" />
</span>
<div>
<p className="text-xs font-medium text-muted-foreground">{eyebrow}</p>
<h1 className="text-2xl font-semibold tracking-normal md:text-3xl">{title}</h1>
</div>
</div>
</div>
<div className="flex gap-2">
<Button variant="outline"></Button>
<Button>
<ArrowRight className="size-4" aria-hidden="true" />
</Button>
</div>
</section>
<section className="grid gap-4 md:grid-cols-3">
{metrics.map((metric) => (
<Card key={metric.label}>
<CardHeader className="p-4">
<CardDescription>{metric.label}</CardDescription>
<CardTitle className="text-2xl">{metric.value}</CardTitle>
</CardHeader>
<CardContent className="p-4 pt-0">
<p className="text-xs text-muted-foreground">{metric.detail}</p>
</CardContent>
</Card>
))}
</section>
<section>
<Card>
<CardHeader>
<CardTitle></CardTitle>
</CardHeader>
<CardContent>
<ol className="grid gap-3 md:grid-cols-2">
{workflows.map((workflow) => (
<li key={workflow} className="flex items-start gap-3 rounded-md border bg-secondary/30 p-3">
<CheckCircle2 className="mt-0.5 size-4 shrink-0 text-primary" aria-hidden="true" />
<span className="text-sm">{workflow}</span>
</li>
))}
</ol>
</CardContent>
</Card>
</section>
</div>
);
}