116 lines
3.8 KiB
JavaScript
116 lines
3.8 KiB
JavaScript
import React, { useState, useEffect, useRef } from 'react';
|
||
import { FiSearch, FiX } from 'react-icons/fi';
|
||
import { searchMedia } from '../../services/pocketbaseService';
|
||
import SearchResults from './SearchResults';
|
||
|
||
const SearchBar = ({ onClose, mobileMode = false }) => {
|
||
const [query, setQuery] = useState('');
|
||
const [results, setResults] = useState([]);
|
||
const [isLoading, setIsLoading] = useState(false);
|
||
const inputRef = useRef(null);
|
||
|
||
// Фокус на инпут при монтировании
|
||
useEffect(() => {
|
||
const timer = setTimeout(() => {
|
||
if (inputRef.current) {
|
||
inputRef.current.focus();
|
||
}
|
||
}, 100);
|
||
return () => clearTimeout(timer);
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
const delayDebounceFn = setTimeout(() => {
|
||
if (query.length >= 2) {
|
||
setIsLoading(true);
|
||
searchMedia(query)
|
||
.then((data) => {
|
||
setResults(data);
|
||
setIsLoading(false);
|
||
})
|
||
.catch((error) => {
|
||
console.error('Search error:', error);
|
||
setIsLoading(false);
|
||
});
|
||
} else {
|
||
setResults([]);
|
||
}
|
||
}, 300);
|
||
|
||
return () => clearTimeout(delayDebounceFn);
|
||
}, [query]);
|
||
|
||
const handleInputChange = (e) => {
|
||
const value = e.target.value;
|
||
// Если это первый символ, делаем его заглавным
|
||
if (value.length === 1) {
|
||
setQuery(value.toUpperCase());
|
||
} else {
|
||
setQuery(value);
|
||
}
|
||
};
|
||
|
||
const handleResultClick = () => {
|
||
onClose(); // Закрываем поиск при клике на результат
|
||
};
|
||
|
||
return (
|
||
<div className="relative">
|
||
<div className="flex items-center gap-2">
|
||
<div className="relative flex-1">
|
||
<FiSearch className="absolute left-3 top-1/2 -translate-y-1/2 text-campfire-ash" />
|
||
<input
|
||
ref={inputRef}
|
||
type="text"
|
||
value={query}
|
||
onChange={handleInputChange}
|
||
placeholder="Че потерял?"
|
||
className="w-full pl-10 pr-4 py-2 bg-campfire-charcoal border border-campfire-ash/30 rounded-md text-campfire-light placeholder-campfire-ash focus:outline-none focus:ring-1 focus:ring-campfire-amber/100 focus:border-campfire-amber/50 transition-colors"
|
||
/>
|
||
{query && (
|
||
<button
|
||
onClick={() => setQuery('')}
|
||
className="absolute right-3 top-1/2 -translate-y-1/2 text-campfire-ash hover:text-campfire-light"
|
||
>
|
||
<FiX />
|
||
</button>
|
||
)}
|
||
</div>
|
||
<button
|
||
onClick={onClose}
|
||
className="px-4 py-2 text-campfire-light hover:text-campfire-amber transition-colors"
|
||
>
|
||
Отмена
|
||
</button>
|
||
</div>
|
||
|
||
{/* Search Results */}
|
||
{(query.length >= 2 || results.length > 0) && (
|
||
mobileMode ? (
|
||
<div className="mt-2 bg-campfire-charcoal/95 backdrop-blur-md border-b border-campfire-ash/30 shadow-lg rounded-lg">
|
||
<div className="container-custom mx-auto px-4 py-4">
|
||
{isLoading ? (
|
||
<div className="text-campfire-light text-center">Поиск...</div>
|
||
) : (
|
||
<SearchResults results={results} onResultClick={handleResultClick} />
|
||
)}
|
||
</div>
|
||
</div>
|
||
) : (
|
||
<div className="fixed left-0 right-0 top-[72px] bg-campfire-charcoal/95 backdrop-blur-md border-b border-campfire-ash/30 shadow-lg">
|
||
<div className="container-custom mx-auto px-4 py-4">
|
||
{isLoading ? (
|
||
<div className="text-campfire-light text-center">Поиск...</div>
|
||
) : (
|
||
<SearchResults results={results} onResultClick={handleResultClick} />
|
||
)}
|
||
</div>
|
||
</div>
|
||
)
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default SearchBar;
|