import { useEffect, useState } from 'react'; import { useLocation } from 'wouter'; import { useQuery, useMutation } from '@tanstack/react-query'; import { SearchInput } from '@/components/SearchInput'; import { SearchResults } from '@/components/SearchResults'; import { FollowUpInput } from '@/components/FollowUpInput'; import { Button } from '@/components/ui/button'; import { ArrowLeft } from 'lucide-react'; import { motion, AnimatePresence } from 'framer-motion'; import { SourceList } from '@/components/SourceList'; export function Search() { const [location, setLocation] = useLocation(); const [sessionId, setSessionId] = useState(null); const [currentResults, setCurrentResults] = useState(null); const [originalQuery, setOriginalQuery] = useState(null); const [isFollowUp, setIsFollowUp] = useState(false); const [followUpQuery, setFollowUpQuery] = useState(null); // Extract query from URL, handling both initial load and subsequent navigation const getQueryFromUrl = () => { const searchParams = new URLSearchParams(window.location.search); return searchParams.get('q') || ''; }; const [searchQuery, setSearchQuery] = useState(getQueryFromUrl); const [refetchCounter, setRefetchCounter] = useState(0); const { data, isLoading, error } = useQuery({ queryKey: ['search', searchQuery, refetchCounter], queryFn: async () => { if (!searchQuery) return null; const response = await fetch(`/api/search?q=${encodeURIComponent(searchQuery)}`); if (!response.ok) throw new Error('Search failed'); const result = await response.json(); console.log('Search API Response:', JSON.stringify(result, null, 2)); if (result.sessionId) { setSessionId(result.sessionId); setCurrentResults(result); if (!originalQuery) { setOriginalQuery(searchQuery); } setIsFollowUp(false); } return result; }, enabled: !!searchQuery, }); // Follow-up mutation const followUpMutation = useMutation({ mutationFn: async (followUpQuery: string) => { if (!sessionId) { const response = await fetch(`/api/search?q=${encodeURIComponent(followUpQuery)}`); if (!response.ok) throw new Error('Search failed'); const result = await response.json(); console.log('New Search API Response:', JSON.stringify(result, null, 2)); if (result.sessionId) { setSessionId(result.sessionId); setOriginalQuery(searchQuery); setIsFollowUp(false); } return result; } const response = await fetch('/api/follow-up', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ sessionId, query: followUpQuery, }), }); if (!response.ok) { if (response.status === 404) { const newResponse = await fetch(`/api/search?q=${encodeURIComponent(followUpQuery)}`); if (!newResponse.ok) throw new Error('Search failed'); const result = await newResponse.json(); console.log('Fallback Search API Response:', JSON.stringify(result, null, 2)); if (result.sessionId) { setSessionId(result.sessionId); setOriginalQuery(searchQuery); setIsFollowUp(false); } return result; } throw new Error('Follow-up failed'); } const result = await response.json(); console.log('Follow-up API Response:', JSON.stringify(result, null, 2)); return result; }, onSuccess: (result) => { setCurrentResults(result); setIsFollowUp(true); }, }); const handleSearch = async (newQuery: string) => { if (newQuery === searchQuery) { // If it's the same query, increment the refetch counter to trigger a new search setRefetchCounter(c => c + 1); } else { setSessionId(null); // Clear session on new search setOriginalQuery(null); // Clear original query setIsFollowUp(false); // Reset follow-up state setSearchQuery(newQuery); } // Update URL without triggering a page reload const newUrl = `/search?q=${encodeURIComponent(newQuery)}`; window.history.pushState({}, '', newUrl); }; const handleFollowUp = async (newFollowUpQuery: string) => { setFollowUpQuery(newFollowUpQuery); await followUpMutation.mutateAsync(newFollowUpQuery); }; // Automatically start search when component mounts or URL changes useEffect(() => { const query = getQueryFromUrl(); if (query && query !== searchQuery) { setSessionId(null); // Clear session on URL change setOriginalQuery(null); // Clear original query setIsFollowUp(false); // Reset follow-up state setSearchQuery(query); } }, [location]); // Use currentResults if available, otherwise fall back to data from useQuery const displayResults = currentResults || data; return (
{displayResults && !isLoading && !followUpMutation.isPending && ( )}
); }