"use client" import { useState } from "react" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { MoreHorizontal, Eye, Download, Trash2 } from "lucide-react" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu" import { useRouter } from "next/navigation" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" export type EvaluationCardData = { id: string systemName: string provider: string modality: string // Added modality field completedDate: string applicableCategories: number completedCategories: number status: "strong" | "adequate" | "weak" | "insufficient" capabilityEval: { strong: number adequate: number weak: number insufficient: number strongCategories: string[] adequateCategories: string[] weakCategories: string[] insufficientCategories: string[] totalApplicable: number } riskEval: { strong: number adequate: number weak: number insufficient: number strongCategories: string[] adequateCategories: string[] weakCategories: string[] insufficientCategories: string[] totalApplicable: number } priorityAreas?: string[] priorityDetails?: Record< string, { yes: string[] negative: { text: string; status: "no" | "na"; reason?: string }[] } > } interface EvaluationCardProps { evaluation: EvaluationCardData onView: (id: string) => void onDelete: (id: string) => void } const getCompletenessColor = (score: number) => { if (score >= 85) return "bg-emerald-500 text-white" if (score >= 70) return "bg-blue-500 text-white" if (score >= 55) return "bg-amber-500 text-white" return "bg-red-500 text-white" } export function EvaluationCard({ evaluation, onView, onDelete }: EvaluationCardProps) { const [expandedAreas, setExpandedAreas] = useState>({}) const toggleArea = (area: string) => setExpandedAreas((p) => ({ ...p, [area]: !p[area] })) const router = useRouter() const modalityMap: Record = { "text-to-text": { label: "Text → Text", emoji: "📝" }, "text-to-image": { label: "Text → Image", emoji: "🖼️" }, multimodal: { label: "Multimodal", emoji: "🤖" }, "speech-to-text": { label: "Speech → Text", emoji: "🗣️" }, "speech-to-speech": { label: "Speech → Speech", emoji: "🔊" }, "image-to-text": { label: "Image → Text", emoji: "📷" }, code: { label: "Code", emoji: "💻" }, } const getUniqueCount = (lists: string[][]) => { const set = new Set() lists.forEach((list) => (list || []).forEach((item) => set.add(item))) return set.size } const capTotalComputed = getUniqueCount([ evaluation.capabilityEval.strongCategories, evaluation.capabilityEval.adequateCategories, evaluation.capabilityEval.weakCategories, evaluation.capabilityEval.insufficientCategories, ]) const riskTotalComputed = getUniqueCount([ evaluation.riskEval.strongCategories, evaluation.riskEval.adequateCategories, evaluation.riskEval.weakCategories, evaluation.riskEval.insufficientCategories, ]) const calculateCompletenessScore = () => { const weights = { strong: 4, adequate: 3, weak: 2, insufficient: 1 } const capTotal = capTotalComputed const riskTotal = riskTotalComputed if (capTotal === 0 && riskTotal === 0) { return "0.0" } let capScore = 0 if (capTotal > 0) { capScore = ((evaluation.capabilityEval.strong * weights.strong + evaluation.capabilityEval.adequate * weights.adequate + evaluation.capabilityEval.weak * weights.weak + evaluation.capabilityEval.insufficient * weights.insufficient) / (capTotal * 4)) * 100 } let riskScore = 0 if (riskTotal > 0) { riskScore = ((evaluation.riskEval.strong * weights.strong + evaluation.riskEval.adequate * weights.adequate + evaluation.riskEval.weak * weights.weak + evaluation.riskEval.insufficient * weights.insufficient) / (riskTotal * 4)) * 100 } const totalApplicable = capTotal + riskTotal const weightedScore = (capScore * capTotal + riskScore * riskTotal) / totalApplicable // Ensure we return a valid number return isNaN(weightedScore) ? "0.0" : weightedScore.toFixed(1) } const handleViewDetails = () => { router.push(`/evaluation/${evaluation.id}`) } const completenessScore = Number.parseFloat(calculateCompletenessScore()) return (
{evaluation.systemName}

{evaluation.provider}

{/* Pretty modality badge with emoji */} {(() => { const info = modalityMap[evaluation.modality] || { label: evaluation.modality } return ( {info.emoji ? {info.emoji} : null} {info.label} ) })()}
View Details Export Report onDelete(evaluation.id)} className="text-destructive"> Delete
Completeness
{completenessScore}%

Weighted average: (Strong×4 + Adequate×3 + Weak×2 + Insufficient×1) ÷ (Total×4) × 100
Capability: {evaluation.capabilityEval.totalApplicable} categories
Risk: {evaluation.riskEval.totalApplicable} categories

Date

{evaluation.completedDate}

Capability Eval ({evaluation.capabilityEval.totalApplicable} applicable)

{/* Vertical histogram bars for Capability */}
Strong

{evaluation.capabilityEval.strong}

{evaluation.capabilityEval.strongCategories.length > 0 ? evaluation.capabilityEval.strongCategories.join(", ") : "No categories"}

Adequate

{evaluation.capabilityEval.adequate}

{evaluation.capabilityEval.adequateCategories.length > 0 ? evaluation.capabilityEval.adequateCategories.join(", ") : "No categories"}

Weak

{evaluation.capabilityEval.weak}

{evaluation.capabilityEval.weakCategories.length > 0 ? evaluation.capabilityEval.weakCategories.join(", ") : "No categories"}

Insufficient

{evaluation.capabilityEval.insufficient}

{evaluation.capabilityEval.insufficientCategories.length > 0 ? evaluation.capabilityEval.insufficientCategories.join(", ") : "No categories"}

Risk Eval ({evaluation.riskEval.totalApplicable} applicable)

{/* Vertical histogram bars for Risk */}
Strong

{evaluation.riskEval.strong}

{evaluation.riskEval.strongCategories.length > 0 ? evaluation.riskEval.strongCategories.join(", ") : "No categories"}

Adequate

{evaluation.riskEval.adequate}

{evaluation.riskEval.adequateCategories.length > 0 ? evaluation.riskEval.adequateCategories.join(", ") : "No categories"}

Weak

{evaluation.riskEval.weak}

{evaluation.riskEval.weakCategories.length > 0 ? evaluation.riskEval.weakCategories.join(", ") : "No categories"}

Insufficient

{evaluation.riskEval.insufficient}

{evaluation.riskEval.insufficientCategories.length > 0 ? evaluation.riskEval.insufficientCategories.join(", ") : "No categories"}

{/* priorityAreas/details intentionally removed from summary card — shown on details page */} ) }