import { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Calendar as CalendarComponent } from "@/components/ui/calendar"; import { cn } from "@/lib/utils"; import { format } from "date-fns"; import { DateRange } from "@/types"; import { RetrievedSource } from "@/services/apiService"; import { storage, STORAGE_KEYS } from "@/lib/storage"; import { Search, ArrowUpDown, Calendar, FileText, ChevronDown, ChevronUp, ExternalLink } from "lucide-react"; interface SourcesModalProps { open: boolean; onOpenChange: (open: boolean) => void; } export const SourcesModal = ({ open, onOpenChange }: SourcesModalProps) => { const [searchTerm, setSearchTerm] = useState(""); const [selectedSource, setSelectedSource] = useState(""); const [selectedCategory, setSelectedCategory] = useState(""); const [date, setDate] = useState({ from: undefined, to: undefined, }); const [sortBy, setSortBy] = useState("date-desc"); const [sources, setSources] = useState([]); const [sourceTypes, setSourceTypes] = useState([]); const [categories, setCategories] = useState([]); // Load sources from storage useEffect(() => { if (open) { const storedSources = storage.get(STORAGE_KEYS.SOURCES) || []; setSources(storedSources); // Extract unique source types and categories const types = Array.from(new Set(storedSources.map(s => s.metadata?.source).filter(Boolean))); setSourceTypes(types as string[]); const cats = Array.from(new Set(storedSources.map(s => { // For this example, we'll use the first word of the content as a mock category const firstWord = s.content_snippet.split(' ')[0]; return firstWord.length > 3 ? firstWord : "General"; }))); setCategories(cats); } }, [open]); // Filter sources based on search term, source, category, and date const filteredSources = sources.filter(source => { const matchesSearch = !searchTerm || source.content_snippet.toLowerCase().includes(searchTerm.toLowerCase()) || (source.metadata?.source || "").toLowerCase().includes(searchTerm.toLowerCase()); const matchesSource = !selectedSource || selectedSource === "All" || source.metadata?.source === selectedSource; // Mock category matching based on first word of content const sourceCategory = source.content_snippet.split(' ')[0].length > 3 ? source.content_snippet.split(' ')[0] : "General"; const matchesCategory = !selectedCategory || selectedCategory === "All" || sourceCategory === selectedCategory; let matchesDate = true; if (date.from && source.metadata?.ruling_date) { matchesDate = matchesDate && new Date(source.metadata.ruling_date) >= date.from; } if (date.to && source.metadata?.ruling_date) { matchesDate = matchesDate && new Date(source.metadata.ruling_date) <= date.to; } return matchesSearch && matchesSource && matchesCategory && matchesDate; }); // Sort sources const sortedSources = [...filteredSources].sort((a, b) => { if (sortBy === "date-desc") { return new Date(b.metadata?.ruling_date || "").getTime() - new Date(a.metadata?.ruling_date || "").getTime(); } else if (sortBy === "date-asc") { return new Date(a.metadata?.ruling_date || "").getTime() - new Date(b.metadata?.ruling_date || "").getTime(); } else if (sortBy === "relevance-desc") { return b.content_snippet.length - a.content_snippet.length; } return 0; }); const resetFilters = () => { setSearchTerm(""); setSelectedSource(""); setSelectedCategory(""); setDate({ from: undefined, to: undefined }); }; const [expandedSources, setExpandedSources] = useState>({}); const toggleSource = (index: number) => { setExpandedSources(prev => ({ ...prev, [index]: !prev[index] })); }; return ( Knowledge Sources
setSearchTerm(e.target.value)} className="pl-10" />
{ if (value) setDate(value); }} className="p-3" />
{sortedSources.length > 0 ? ( sortedSources.map((source, index) => (

{source.metadata?.source || "Source"}

{source.metadata?.source || "Unknown Source"} {source.metadata?.ruling_date && ( <> {new Date(source.metadata.ruling_date).toLocaleDateString()} )}

{source.content_snippet}

{!expandedSources[index] && (
)}
{expandedSources[index] && (
)}
)) ) : (

No sources found

{sources.length > 0 ? "No sources match your current search criteria. Try adjusting your filters." : "Chat with Insight AI to get information with source citations."}

)}
); };