diff --git a/client/components/ResearchWidget.tsx b/client/components/ResearchWidget.tsx new file mode 100644 index 00000000..274aaa51 --- /dev/null +++ b/client/components/ResearchWidget.tsx @@ -0,0 +1,176 @@ +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { BookMarked, ExternalLink, CheckCircle, Clock, AlertCircle } from "lucide-react"; + +export interface ResearchTrack { + id: string; + title: string; + description?: string; + status: "active" | "paused" | "completed" | "on_hold"; + category?: string; + progress?: number; + whitepaper_url?: string; + publications?: number; + team_members?: number; + start_date?: string; +} + +interface ResearchWidgetProps { + tracks: ResearchTrack[]; + title?: string; + description?: string; + onViewDetails?: (trackId: string) => void; + accentColor?: "yellow" | "blue" | "purple"; +} + +const colorMap = { + yellow: { + bg: "bg-gradient-to-br from-yellow-950/40 to-yellow-900/20", + border: "border-yellow-500/20", + }, + blue: { + bg: "bg-gradient-to-br from-blue-950/40 to-blue-900/20", + border: "border-blue-500/20", + }, + purple: { + bg: "bg-gradient-to-br from-purple-950/40 to-purple-900/20", + border: "border-purple-500/20", + }, +}; + +const statusMap = { + active: { label: "Active", color: "bg-green-600/50 text-green-100", icon: CheckCircle }, + paused: { label: "Paused", color: "bg-yellow-600/50 text-yellow-100", icon: Clock }, + completed: { label: "Completed", color: "bg-blue-600/50 text-blue-100", icon: CheckCircle }, + on_hold: { label: "On Hold", color: "bg-red-600/50 text-red-100", icon: AlertCircle }, +}; + +export function ResearchWidget({ + tracks, + title = "Active Research Tracks", + description = "Current research initiatives and whitepapers", + onViewDetails, + accentColor = "yellow", +}: ResearchWidgetProps) { + const colors = colorMap[accentColor]; + const activeCount = tracks.filter(t => t.status === "active").length; + const completedCount = tracks.filter(t => t.status === "completed").length; + + return ( + + + + + {title} + + {description} + + + {tracks.length === 0 ? ( +
+ +

No active research tracks

+
+ ) : ( +
+ {/* Stats */} +
+
+

Total

+

{tracks.length}

+
+
+

Active

+

{activeCount}

+
+
+

Completed

+

{completedCount}

+
+
+ + {/* Tracks List */} +
+ {tracks.map((track) => { + const statusInfo = statusMap[track.status]; + const StatusIcon = statusInfo.icon; + + return ( +
onViewDetails?.(track.id)} + > + {/* Header */} +
+
+

{track.title}

+ {track.category && ( +

{track.category}

+ )} +
+ + + {statusInfo.label} + +
+ + {/* Description */} + {track.description && ( +

{track.description}

+ )} + + {/* Meta */} +
+ {track.progress !== undefined && ( + {track.progress}% complete + )} + {track.publications && track.publications > 0 && ( + 📄 {track.publications} publications + )} + {track.team_members && track.team_members > 0 && ( + 👥 {track.team_members} members + )} +
+ + {/* Actions */} +
+ {track.whitepaper_url && ( + + )} + +
+
+ ); + })} +
+
+ )} +
+
+ ); +} + +export default ResearchWidget;