"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}
))}
)
}