Files
ftb-project-management/apps/web/components/product/ProductCard.tsx
Script Generator 0099b23a86 style: 重做整体视觉系统(编辑设计 × 建筑精度)
- Fraunces 衬线 display + DM Sans body + JetBrains Mono 数字标签
- 暖米白主题(#f7f4ee)+ 蓝色强调色(#2563eb)
- 引入 lucide-react 图标库替代 emoji
- Sidebar 加入编号索引、Logo、用户区域、杂志风分组标题
- 产品列表页加入大号 display 标题、搜索、卡片悬浮动画
- 产品详情页面包屑、tab 编号、需求表格重做
- 状态徽章改为色点 + 文字,"已拒绝"用红色避免与"评审中"冲突
- 全局加入 grain 噪点纹理、入场交错动画

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-08 12:37:17 +08:00

67 lines
2.6 KiB
TypeScript

'use client';
import { Package } from 'lucide-react';
interface ProductWithCount {
id: string;
name: string;
description: string;
createdAt: string | Date;
_count?: { requirements: number; projects: number };
}
interface Props {
product: ProductWithCount;
index: number;
onClick: (id: string) => void;
}
export function ProductCard({ product, index, onClick }: Props) {
const reqCount = product._count?.requirements ?? 0;
const projCount = product._count?.projects ?? 0;
return (
<article
onClick={() => onClick(product.id)}
style={{ animationDelay: `${index * 60}ms` }}
className="group animate-fade-up relative cursor-pointer overflow-hidden rounded-xl border border-[var(--line)] bg-[var(--bg-elevated)] p-6 transition-all duration-300 hover:-translate-y-0.5 hover:border-[var(--ink)] hover:shadow-[0_12px_32px_-12px_rgba(26,24,20,0.18)]"
>
<div className="flex items-start justify-between">
<span className="font-mono text-[10px] tabular-nums uppercase tracking-[0.18em] text-[var(--ink-muted)]">
{String(index + 1).padStart(3, '0')}
</span>
<Package className="h-4 w-4 text-[var(--ink-muted)] transition-colors group-hover:text-[var(--accent)]" strokeWidth={1.75} />
</div>
<h3 className="mt-6 font-display text-[26px] font-medium leading-[1.15] tracking-tight text-[var(--ink)]">
{product.name}
</h3>
{product.description ? (
<p className="mt-2 line-clamp-2 text-[13px] leading-relaxed text-[var(--ink-soft)]">
{product.description}
</p>
) : (
<p className="mt-2 text-[13px] italic text-[var(--ink-muted)]"></p>
)}
<div className="mt-8 flex items-end justify-between border-t border-[var(--line-soft)] pt-4">
<div className="flex gap-6">
<div>
<p className="font-display text-2xl font-semibold tabular-nums text-[var(--ink)]">{reqCount}</p>
<p className="mt-0.5 font-mono text-[10px] uppercase tracking-[0.18em] text-[var(--ink-muted)]"></p>
</div>
<div className="h-10 w-px bg-[var(--line-soft)]" />
<div>
<p className="font-display text-2xl font-semibold tabular-nums text-[var(--ink)]">{projCount}</p>
<p className="mt-0.5 font-mono text-[10px] uppercase tracking-[0.18em] text-[var(--ink-muted)]"></p>
</div>
</div>
<span className="font-mono text-[11px] text-[var(--ink-muted)] opacity-0 transition-opacity group-hover:opacity-100">
</span>
</div>
</article>
);
}