"use client"; import { useMemo, useState } from "react"; import { Check, FileUp, MoreVertical, Plus, Search, UploadCloud, Wifi, WifiOff } from "lucide-react"; import LiquidGlass from "liquid-glass-react"; import { cn } from "@/lib/utils"; import { sourceFilters, type DashboardSource } from "@/components/dashboard/dashboardData"; import { PreviewBadge } from "@/components/dashboard/dashboardPrimitives"; import { MaterialTypeBadge } from "@/components/dashboard/SourceBlockedState"; import { getPublicDemoMode } from "@/lib/env"; import { hasLiveSession } from "@/lib/api/mode"; type SourcesPanelProps = { className?: string; selectedSourceId: string; selectedSourceIds?: string[]; documents?: DashboardSource[]; onSourceOpen: (sourceId: string) => void; onSourceToggle?: (sourceId: string) => void; onUploadClick?: () => void; }; export function SourcesPanel({ className, selectedSourceId, selectedSourceIds = [selectedSourceId], documents = [], onSourceOpen, onSourceToggle, onUploadClick, }: SourcesPanelProps) { const [activeFilter, setActiveFilter] = useState("All"); const [query, setQuery] = useState(""); const isLive = getPublicDemoMode() === "live" || hasLiveSession(); const liveBadge = isLive ? ( Connected to AI ) : ( Offline preview ); const visibleSources = useMemo( () => documents.filter((source) => { const filterMatches = activeFilter === "All" || source.type === activeFilter || (activeFilter === "Books" && source.type === "Book") || (activeFilter === "PYQs" && source.type === "PYQ") || (activeFilter === "Links" && source.type === "Link") || (activeFilter === "Images" && source.type === "Image"); const searchText = `${source.title} ${source.subtitle} ${source.type}`.toLowerCase(); return filterMatches && searchText.includes(query.trim().toLowerCase()); }), [activeFilter, query, documents], ); const pinnedSources = visibleSources.filter((source) => source.group === "Pinned"); const recentSources = visibleSources.filter((source) => source.group === "Recent"); const hasSources = visibleSources.length > 0; const selectedCount = selectedSourceIds.length; const sourceUsageLabel = selectedCount > 1 ? `Using ${selectedCount} sources` : selectedCount === 1 ? "Using 1 source" : "Choose sources for DocDoe"; return (

Sources {liveBadge}

{sourceUsageLabel}

{sourceFilters.filter(f => f !== "Images").map((tab) => ( ))}
{hasSources ? (
{pinnedSources.length > 0 && ( )}
) : (

No sources found

)}
); } function SourceGroup({ title, sources, selectedSourceId, selectedSourceIds, onSourceOpen, onSourceToggle, }: { title: string; sources: DashboardSource[]; selectedSourceId: string; selectedSourceIds: string[]; onSourceOpen: (sourceId: string) => void; onSourceToggle?: (sourceId: string) => void; }) { if (sources.length === 0) { return null; } return (

{title}

{sources.map((source) => ( onSourceOpen(source.id)} onToggle={() => onSourceToggle?.(source.id)} /> ))}
); } function SourcePanelRow({ source, isSelected, isIncluded, onOpen, onToggle, }: { source: DashboardSource; isSelected: boolean; isIncluded: boolean; onOpen: () => void; onToggle: () => void; }) { const Icon = source.icon; const statusLabel = source.status === "processing" || source.status === "uploaded" ? "Preparing" : source.status === "failed" ? "Could not read" : "Ready"; return (
{isSelected ? On : null} {statusLabel}
); }