import React, { useState } from 'react'; import { useDebounce } from 'use-debounce'; import { useSearchMessages, useSearchSessions, type SearchResult, type SessionSearchResult, } from './hooks/useSearch'; import { formatDate, formatTime } from '@/lib/date-utils'; import { Button } from './ui/button'; import { Badge } from './ui/badge'; import { Input } from './ui/input'; import { Dialog, DialogContent } from './ui/dialog'; import { ScrollArea } from './ui/scroll-area'; import { Search, MessageSquare, Clock, User, Bot, Settings, X, ChevronRight, AlertTriangle, RefreshCw, } from 'lucide-react'; import { cn } from '@/lib/utils'; import { Alert, AlertDescription } from './ui/alert'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; interface SearchPanelProps { isOpen: boolean; onClose: () => void; onNavigateToSession: (sessionId: string, messageIndex?: number) => void; variant?: 'inline' | 'modal' | 'popover'; } type SearchMode = 'messages' | 'sessions'; export default function SearchPanel({ isOpen, onClose, onNavigateToSession, variant = 'modal', }: SearchPanelProps) { const [searchQuery, setSearchQuery] = useState(''); const [debouncedQuery] = useDebounce(searchQuery, 300); const [searchMode, setSearchMode] = useState('messages'); const [roleFilter, setRoleFilter] = useState('all'); const [sessionFilter, setSessionFilter] = useState(''); // Use TanStack Query hooks for search const { data: messageData, isLoading: messageLoading, error: messageError, } = useSearchMessages( debouncedQuery, sessionFilter || undefined, 20, isOpen && searchMode === 'messages' ); const { data: sessionData, isLoading: sessionLoading, error: sessionError, } = useSearchSessions(debouncedQuery, isOpen && searchMode === 'sessions'); // Derive state from query results const messageResults = messageData?.results || []; const sessionResults = sessionData?.results || []; const isLoading = searchMode === 'messages' ? messageLoading : sessionLoading; const error = searchMode === 'messages' ? messageError : sessionError; const total = searchMode === 'messages' ? messageData?.total || 0 : sessionData?.total || 0; const handleResultClick = (result: SearchResult) => { onNavigateToSession(result.sessionId, result.messageIndex); onClose(); }; const handleSessionResultClick = (sessionResult: SessionSearchResult) => { onNavigateToSession(sessionResult.sessionId, sessionResult.firstMatch.messageIndex); onClose(); }; const getRoleIcon = (role: string) => { switch (role) { case 'user': return ; case 'assistant': return ; case 'system': return ; default: return ; } }; const getRoleColor = (role: string) => { switch (role) { case 'user': return 'bg-blue-100 text-blue-800'; case 'assistant': return 'bg-green-100 text-green-800'; case 'system': return 'bg-yellow-100 text-yellow-800'; default: return 'bg-gray-100 text-gray-800'; } }; const highlightText = (text: string, query: string) => { if (!query) return text; const regex = new RegExp(`(${query})`, 'gi'); const parts = text.split(regex); return parts.map((part, index) => regex.test(part) ? ( {part} ) : ( part ) ); }; const content = (
{/* Search Input - moved to top for better UX */}
setSearchQuery(e.target.value)} className="pl-10" />
{/* Search Mode Toggle */}
{/* Filters for message search */} {searchMode === 'messages' && (
setSessionFilter(e.target.value)} className="flex-1 text-sm" />
)}
{/* Results */}
{error && (
{error?.message || 'Search failed'}
)}
{isLoading ? (
Searching...
) : ( <> {/* Results Summary */} {searchQuery && (
{total > 0 ? ( <> Found {total}{' '} {searchMode === 'messages' ? 'messages' : 'sessions'}{' '} matching "{searchQuery}" ) : ( <> No{' '} {searchMode === 'messages' ? 'messages' : 'sessions'}{' '} found matching "{searchQuery}" )}
)} {/* Message Results */} {searchMode === 'messages' && messageResults.length > 0 && (
{messageResults.map((result, index) => (
handleResultClick(result)} >
{getRoleIcon(result.message.role)} {result.message.role} Session: {result.sessionId.slice(0, 8)} ...
{highlightText(result.context, searchQuery)}
))}
)} {/* Session Results */} {searchMode === 'sessions' && sessionResults.length > 0 && (
{sessionResults.map((sessionResult, index) => (
handleSessionResultClick(sessionResult) } >
{sessionResult.sessionId.slice(0, 12)} ... {sessionResult.matchCount} matches
{sessionResult.metadata.messageCount} messages • Created{' '} {formatDate(sessionResult.metadata.createdAt)} • Last active{' '} {formatTime( sessionResult.metadata.lastActivity )}
{highlightText( sessionResult.firstMatch.context, searchQuery )}
))}
)} {/* No Results */} {searchQuery && !isLoading && (searchMode === 'messages' ? messageResults.length === 0 : sessionResults.length === 0) && (

No{' '} {searchMode === 'messages' ? 'messages' : 'sessions'}{' '} found matching your search.

Try adjusting your search terms or filters.

)} {/* Empty State */} {!searchQuery && (

Start typing to search through your conversations.

)} )}
); if (variant === 'inline') { return
{content}
; } if (variant === 'popover') { if (!isOpen) return null; return ( <> {/* Backdrop */}
{/* Popover panel */}

Search Chats

{content}
); } return ( !open && onClose()}> {content} ); }