import React, { useState, useCallback, useEffect, useRef } from 'react'; import { Search, X, Book, ChevronRight, Loader2 } from 'lucide-react'; import { searchBible, SearchResult, SearchResponse } from '../services/api'; import { useNavigate } from 'react-router-dom'; interface SearchComponentProps { formatBookName: (bookName: string) => string; getBookUrlName: (bookName: string) => string; books?: string[]; selectedVersion?: string; onVersionChange?: (version: string) => void; onClose?: () => void; isModal?: boolean; } const SearchComponent: React.FC = ({ formatBookName, getBookUrlName, books = [], selectedVersion: initialVersion, onVersionChange, onClose, isModal = false }) => { // Default to ESV if no version is selected, otherwise use the current version const defaultVersion = initialVersion || 'esv'; const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(''); const [hasSearched, setHasSearched] = useState(false); const [selectedBook, setSelectedBook] = useState(''); const [selectedVersion, setSelectedVersion] = useState(defaultVersion); const searchTimeoutRef = useRef(); const navigate = useNavigate(); // Debounced search function const debouncedSearch = useCallback(async (searchQuery: string, bookFilter?: string) => { if (searchQuery.trim().length < 2) { setResults([]); setHasSearched(false); return; } setLoading(true); setError(''); try { const searchOptions = { ...(bookFilter && { book: bookFilter }), limit: 50, context: true, version: selectedVersion }; const response: SearchResponse = await searchBible(searchQuery, searchOptions); setResults(response.results); setHasSearched(true); } catch (err) { console.error('Search error:', err); setError('Search failed. Please try again.'); setResults([]); } finally { setLoading(false); } }, [selectedVersion]); // Handle search input changes useEffect(() => { if (searchTimeoutRef.current) { clearTimeout(searchTimeoutRef.current); } searchTimeoutRef.current = setTimeout(() => { debouncedSearch(query, selectedBook); }, 300); return () => { if (searchTimeoutRef.current) { clearTimeout(searchTimeoutRef.current); } }; }, [query, selectedBook, debouncedSearch]); // Handle result click const handleResultClick = (result: SearchResult) => { const urlBookName = getBookUrlName(formatBookName(result.book)); // Navigate to chapter with verse hash to scroll directly to the verse // Include the version in the URL to ensure we navigate to the correct translation const url = `/version/${selectedVersion}/book/${urlBookName}/chapter/${result.chapter}#verse-${result.verse}`; navigate(url); if (onClose) onClose(); }; // Highlight search terms in text const highlightText = (text: string, searchQuery: string) => { if (!searchQuery) return text; const words = searchQuery.toLowerCase().split(/\s+/); let highlightedText = text; words.forEach(word => { const regex = new RegExp(`(${word})`, 'gi'); highlightedText = highlightedText.replace(regex, '$1'); }); return highlightedText; }; const containerClasses = isModal ? "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50" : "w-full max-w-4xl mx-auto"; const contentClasses = isModal ? "bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-4xl max-h-[90vh] overflow-hidden" : "bg-white dark:bg-gray-800 rounded-lg shadow-lg"; return (
{/* Header */}

Search Bible

{isModal && onClose && ( )}
{/* Search Input */}
setQuery(e.target.value)} placeholder="Search for verses, words, or phrases..." className="w-full pl-10 pr-4 py-3 text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" autoFocus /> {loading && ( )}
{/* Version Selector */}
{/* Results */}
{error && (
{error}
)} {!loading && !error && hasSearched && results.length === 0 && (

No results found for "{query}"

Try different keywords or check your spelling

)} {!loading && !error && !hasSearched && query.length === 0 && (

Enter a search term to find verses

Search for words, phrases, or topics across the entire Bible

)} {results.length > 0 && (
{results.map((result, index) => (
handleResultClick(result)} className="p-4 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors" > {/* Reference */}
{formatBookName(result.book)} Chapter {result.chapter} Verse {result.verse}
{/* Verse Text */}
{/* Context */} {result.context && result.context.length > 0 && (

Context:

{result.context.map((contextVerse, idx) => (
{contextVerse.verse} {contextVerse.verse === result.verse ? : contextVerse.text }
))}
)}
))}
)}
{/* Footer */} {results.length > 0 && (
Found {results.length} result{results.length !== 1 ? 's' : ''} for "{query}" in {selectedVersion.toUpperCase()} Bible
)}
); }; export default SearchComponent;