/** * ProjectCard - Enterprise SaaS Style (Linear/Notion inspired) * * Visual Design: * - Modern typography with Microsoft YaHei optimization * - Soft shadows and generous spacing * - Clean section headers with decorative accents * - Traffic light system for FAI values */ import { ProjectData } from '@/types/project'; import { getRiskBadgeClass, formatDate, getDisplayValue, parseFAIValue, getFAIColorClass, getCardVisualState, formatExcelDate } from '@/lib/projectUtils'; import { Target, FlaskConical, CheckCircle2 } from 'lucide-react'; interface ProjectCardProps { project: ProjectData; } export default function ProjectCard({ project }: ProjectCardProps) { const { no, identity, milestones, details } = project; // Get visual state based on currentNode const visualState = getCardVisualState(milestones.currentNode); return (
{/* Card Header */}

{getDisplayValue(identity.projectName, 'N/A')}

{getDisplayValue(identity.productName, 'N/A')} NO. {getDisplayValue(no, 'N/A')}

{/* Status Badge - Only show if valid currentNode */} {visualState.showBadge && ( {visualState.badgeLabel} )}
{/* Section 1: 项目基本信息 */}

项目基本信息

{/* Section 2: 内部节点 */}

内部节点

{/* Timeline Visual - CSS Grid for Perfect Alignment */}
{/* The Grey Line - Perfectly centered start-to-end */}
{/* The Nodes - Grid System (5 equal columns) */}
{/* Status Indicators Grid */}
} label="当前阶段" value={milestones.currentStage} /> } label="试模次数" value={milestones.trialCount} /> } label="T1尺寸达标" value={milestones.t1SizeQualified} /> {/* FAI Fields with Traffic Light Logic */} {/* Status is now shown in header badge */}
{/* Section 3: 项目推进细节 - Executive View */}

项目推进细节

{/* Date Display with formatExcelDate */} 更新时间: {formatExcelDate(details.detailDate)}
{/* The Content Block - Executive View Typography (Premium Bold) */}

{getDisplayValue(details.detailProgress, '无详细内容')}

); } // Helper component for info fields in Section 1 function InfoField({ label, value, highlight = false }: { label: string; value: string; highlight?: boolean; }) { return (
{label}
{getDisplayValue(value, '-')}
); } // Helper component for timeline nodes in Section 2 function TimelineNode({ label, date }: { label: string; date: string }) { return (
{label}
{date}
); } // Helper component for status fields in Section 2 function StatusField({ icon, label, value }: { icon?: React.ReactNode; label: string; value: string; }) { return (
{icon && {icon}}
{label}
{getDisplayValue(value, '-')}
); } // Helper component for FAI fields with traffic light logic function FAIField({ label, value }: { label: string; value: string; }) { const displayValue = parseFAIValue(value); const colorClass = getFAIColorClass(value); return (
{label}
{displayValue}
); }