import { useEffect, useState, useRef } from 'react' import type { Article } from '@/types/nostr' import { objectCache } from '@/lib/objectCache' import { getSearchHistory } from '@/lib/searchHistory' import { Card, Button } from './ui' import { t } from '@/lib/i18n' interface SearchSuggestionsProps { query: string onSelect: (query: string) => void onClose: () => void } interface SuggestionItem { type: 'article' | 'author' | 'history' title: string query: string subtitle?: string timestamp?: number } const loadHistorySuggestions = async (): Promise => { try { const history = await getSearchHistory() return history.slice(0, 5).map((item) => ({ type: 'history' as const, title: item.query, query: item.query, timestamp: item.timestamp, })) } catch (error) { console.error('Error loading search history:', error) return [] } } const loadSuggestions = async (searchQuery: string): Promise => { try { const allArticles = (await objectCache.getAll('publication')) as Article[] const allAuthors = (await objectCache.getAll('author')) as Article[] const queryLower = searchQuery.toLowerCase() const articleSuggestions: SuggestionItem[] = allArticles .filter((article) => article.title.toLowerCase().includes(queryLower)) .slice(0, 5) .map((article) => ({ type: 'article' as const, title: article.title, query: article.title, subtitle: article.preview?.substring(0, 60), })) const authorSuggestions: SuggestionItem[] = allAuthors .filter((author) => { const name = extractAuthorName(author) return name.toLowerCase().includes(queryLower) }) .slice(0, 3) .map((author) => ({ type: 'author' as const, title: extractAuthorName(author), query: extractAuthorName(author), subtitle: author.description?.substring(0, 60), })) return [...articleSuggestions, ...authorSuggestions].slice(0, 8) } catch (error) { console.error('Error loading suggestions:', error) return [] } } function useSuggestionsLoader(query: string): { suggestions: SuggestionItem[]; loading: boolean } { const [suggestions, setSuggestions] = useState([]) const [loading, setLoading] = useState(false) useEffect(() => { const updateSuggestions = async (): Promise => { if (!query.trim()) { const historySuggestions = await loadHistorySuggestions() setSuggestions(historySuggestions) return } setLoading(true) try { const loadedSuggestions = await loadSuggestions(query) setSuggestions(loadedSuggestions) } finally { setLoading(false) } } void updateSuggestions() }, [query]) return { suggestions, loading } } function useClickOutsideHandler(containerRef: React.RefObject, onClose: () => void): void { useEffect(() => { const handleClickOutside = (e: MouseEvent): void => { if (containerRef.current && !containerRef.current.contains(e.target as Node)) { onClose() } } document.addEventListener('mousedown', handleClickOutside) return () => { document.removeEventListener('mousedown', handleClickOutside) } }, [containerRef, onClose]) } export function SearchSuggestions({ query, onSelect, onClose }: SearchSuggestionsProps): React.ReactElement | null { const containerRef = useRef(null) const { suggestions, loading } = useSuggestionsLoader(query) useClickOutsideHandler(containerRef, onClose) if (suggestions.length === 0 && !loading) { return null } return (
{loading && (

{t('common.loading')}

)} {!loading && suggestions.length > 0 && (
{suggestions.map((suggestion, index) => ( ))}
)}
) } function getSuggestionIcon(type: SuggestionItem['type']): React.ReactElement { if (type === 'article') { return ( ) } if (type === 'author') { return ( ) } return ( ) } function getSuggestionAriaLabel(type: SuggestionItem['type'], title: string): string { if (type === 'article') { return `${t('search.suggestion.article')}: ${title}` } if (type === 'author') { return `${t('search.suggestion.author')}: ${title}` } return `${t('search.suggestion.history')}: ${title}` } function SuggestionItemComponent({ suggestion, onSelect, }: { suggestion: SuggestionItem onSelect: (query: string) => void }): React.ReactElement { return ( ) } function extractAuthorName(author: Article): string { if (author.isPresentation) { return author.title } return author.title }