/**
* 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 (
);
}
// 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 (
);
}