"use client" import { useState } from "react" import { cn } from "@/lib/utils" import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { ScrollArea } from "@/components/ui/scroll-area" import { ExternalLink, ChevronDown, ChevronRight, Globe, BookOpen, FileText, Newspaper, GraduationCap, LinkIcon, Filter } from "lucide-react" import type { Source } from "./types" interface SourcePanelProps { sources: Source[] isOpen: boolean onToggle: () => void className?: string variant?: "panel" | "inline" | "minimal" maxHeight?: string } interface SourceCardProps { source: Source index: number variant?: "detailed" | "compact" onView: (source: Source) => void } function getSourceIcon(category: string) { switch (category.toLowerCase()) { case "academic": return case "news": return case "documentation": return case "blog": return default: return } } function getCategoryColor(category: string) { switch (category.toLowerCase()) { case "academic": return "bg-blue-100 text-blue-800 border-blue-200" case "news": return "bg-red-100 text-red-800 border-red-200" case "documentation": return "bg-green-100 text-green-800 border-green-200" case "blog": return "bg-purple-100 text-purple-800 border-purple-200" default: return "bg-gray-100 text-gray-800 border-gray-200" } } function SourceCard({ source, index, variant = "detailed", onView }: SourceCardProps) { const handleClick = () => { window.open(source.url, '_blank', 'noopener,noreferrer') onView(source) } if (variant === "compact") { return (
{index + 1}
{getSourceIcon(source.category)} {source.source_name}

{source.title}

) } return (
{index + 1}
{getSourceIcon(source.category)} {source.category} {source.source_name}

{source.excerpt}

) } export function SourcePanel({ sources, isOpen, onToggle, className, variant = "panel", maxHeight = "400px" }: SourcePanelProps) { const [viewedSources, setViewedSources] = useState>(new Set()) const [filterCategory, setFilterCategory] = useState("all") if (variant === "inline") { return (
Sources {sources.length}
{isOpen && (
{sources.slice(0, 3).map((source, index) => ( setViewedSources(prev => new Set(prev).add(source.url))} /> ))} {sources.length > 3 && ( )}
)}
) } if (variant === "minimal") { return (
Sources: {sources.slice(0, 5).map((source, index) => ( ))} {sources.length > 5 && ( +{sources.length - 5} more )}
) } // Panel variant (default) const categories = Array.from(new Set(sources.map(s => s.category))) const filteredSources = filterCategory === "all" ? sources : sources.filter(s => s.category === filterCategory) return (
Sources {sources.length}
{categories.length > 1 && (
{categories.map(category => ( ))}
)}
{isOpen && (
{filteredSources.map((source, index) => ( setViewedSources(prev => new Set(prev).add(source.url))} /> ))}
)}
) } interface SourceSummaryProps { sources: Source[] className?: string } export function SourceSummary({ sources, className }: SourceSummaryProps) { if (!sources || sources.length === 0) return null const categories = Array.from(new Set(sources.map(s => s.category))) const sourcesByCategory = categories.map(category => ({ category, count: sources.filter(s => s.category === category).length, sources: sources.filter(s => s.category === category) })) return (
Based on {sources.length} sources {sourcesByCategory.map(({ category, count }) => ( {getSourceIcon(category)} {count} {category} ))}
) }