import { useState, useEffect } from 'react' import { Search as SearchIcon, ChevronLeft, ChevronRight, Download, X } from 'lucide-react' import { searchFurry, searchAnime, getFurryTags, getAnimeTags } from '../utils/api' import { hapticFeedback } from '../utils/telegram' import './Search.css' export default function Search({ user }) { const [mode, setMode] = useState(user.settings?.searchPreference || 'mixed') const [query, setQuery] = useState('') const [results, setResults] = useState([]) const [loading, setLoading] = useState(false) const [tagSuggestions, setTagSuggestions] = useState([]) const [currentIndex, setCurrentIndex] = useState(0) const [showViewer, setShowViewer] = useState(false) useEffect(() => { if (query.length > 1) { loadTagSuggestions() } else { setTagSuggestions([]) } }, [query, mode]) const loadTagSuggestions = async () => { try { let tags = [] if (mode === 'furry' || mode === 'mixed') { const furryTags = await getFurryTags(query) tags = [...tags, ...furryTags.map(t => ({ ...t, source: 'e621' }))] } if (mode === 'anime' || mode === 'mixed') { const animeTags = await getAnimeTags(query) tags = [...tags, ...animeTags.map(t => ({ ...t, source: 'gelbooru' }))] } // Убрать дубликаты const uniqueTags = tags.reduce((acc, tag) => { if (!acc.find(t => t.name === tag.name)) { acc.push(tag) } return acc }, []) setTagSuggestions(uniqueTags.slice(0, 10)) } catch (error) { console.error('Ошибка загрузки тегов:', error) } } const handleSearch = async (searchQuery = query) => { if (!searchQuery.trim()) return try { setLoading(true) hapticFeedback('light') setResults([]) let allResults = [] if (mode === 'furry' || mode === 'mixed') { const furryResults = await searchFurry(searchQuery, { limit: 30 }) allResults = [...allResults, ...furryResults] } if (mode === 'anime' || mode === 'mixed') { const animeResults = await searchAnime(searchQuery, { limit: 30 }) allResults = [...allResults, ...animeResults] } // Перемешать результаты если mixed режим if (mode === 'mixed') { allResults = allResults.sort(() => Math.random() - 0.5) } setResults(allResults) setTagSuggestions([]) if (allResults.length > 0) { hapticFeedback('success') } } catch (error) { console.error('Ошибка поиска:', error) hapticFeedback('error') } finally { setLoading(false) } } const handleTagClick = (tagName) => { setQuery(tagName) handleSearch(tagName) } const openViewer = (index) => { setCurrentIndex(index) setShowViewer(true) hapticFeedback('light') } const handleNext = () => { if (currentIndex < results.length - 1) { setCurrentIndex(currentIndex + 1) hapticFeedback('light') } } const handlePrev = () => { if (currentIndex > 0) { setCurrentIndex(currentIndex - 1) hapticFeedback('light') } } const handleDownload = async () => { const currentImage = results[currentIndex] if (!currentImage) return try { hapticFeedback('light') const response = await fetch(currentImage.url) const blob = await response.blob() const url = window.URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `nakama-${currentImage.id}.jpg` document.body.appendChild(a) a.click() document.body.removeChild(a) window.URL.revokeObjectURL(url) hapticFeedback('success') } catch (error) { console.error('Ошибка скачивания:', error) hapticFeedback('error') } } return (
{/* Хедер */}

Поиск

{/* Режимы поиска */}
{/* Строка поиска */}
setQuery(e.target.value)} onKeyPress={e => e.key === 'Enter' && handleSearch()} /> {query && ( )}
{/* Подсказки тегов */} {tagSuggestions.length > 0 && (
{tagSuggestions.map((tag, index) => ( ))}
)}
{/* Результаты */}
{loading ? (

Поиск...

) : results.length === 0 && query ? (

Ничего не найдено

Попробуйте другие теги
) : results.length === 0 ? (

Введите теги для поиска

Используйте e621 и gelbooru
) : (
{results.map((item, index) => (
openViewer(index)} > {`Result
{item.source} {item.rating}
))}
)}
{/* Просмотрщик изображений */} {showViewer && results[currentIndex] && (
setShowViewer(false)}>
{currentIndex + 1} / {results.length}
e.stopPropagation()}> Full view
{results[currentIndex].tags.slice(0, 5).map((tag, i) => ( {tag} ))}
Score: {results[currentIndex].score} Source: {results[currentIndex].source}
)}
) }