Добавлено получение истории поиска с автодополнением в компоненте Header. Обновлены обработчики ввода для управления отображением истории и плейсхолдера. Внедрен запрос для получения последних поисковых запросов. Обновлены стили и логика отображения в компоненте Header.
This commit is contained in:
@ -9,6 +9,8 @@ import { FIND_LAXIMO_VEHICLE, DOC_FIND_OEM, FIND_LAXIMO_VEHICLE_BY_PLATE_GLOBAL,
|
||||
import { LaximoVehicleSearchResult, LaximoDocFindOEMResult, LaximoVehiclesByPartResult } from '@/types/laximo';
|
||||
import Link from "next/link";
|
||||
import CartButton from './CartButton';
|
||||
import SearchHistoryDropdown from './SearchHistoryDropdown';
|
||||
import { GET_RECENT_SEARCH_QUERIES, PartsSearchHistoryItem } from '@/lib/graphql/search-history';
|
||||
|
||||
interface HeaderProps {
|
||||
onOpenAuthModal?: () => void;
|
||||
@ -25,9 +27,14 @@ const Header: React.FC<HeaderProps> = ({ onOpenAuthModal = () => console.log('Au
|
||||
const [vehiclesByPartResults, setVehiclesByPartResults] = useState<LaximoVehiclesByPartResult | null>(null);
|
||||
const [searchType, setSearchType] = useState<'vin' | 'oem' | 'plate' | 'text'>('text');
|
||||
const [oemSearchMode, setOemSearchMode] = useState<'parts' | 'vehicles'>('parts');
|
||||
const [showSearchHistory, setShowSearchHistory] = useState(false);
|
||||
const [searchHistoryItems, setSearchHistoryItems] = useState<PartsSearchHistoryItem[]>([]);
|
||||
const [inputFocused, setInputFocused] = useState(false);
|
||||
const [showPlaceholder, setShowPlaceholder] = useState(true);
|
||||
const router = useRouter();
|
||||
const searchFormRef = useRef<HTMLFormElement>(null);
|
||||
const searchDropdownRef = useRef<HTMLDivElement>(null);
|
||||
const searchInputRef = useRef<HTMLInputElement>(null);
|
||||
const isClient = useIsClient();
|
||||
|
||||
// Эффект для восстановления поискового запроса из URL
|
||||
@ -111,11 +118,28 @@ const Header: React.FC<HeaderProps> = ({ onOpenAuthModal = () => console.log('Au
|
||||
}
|
||||
});
|
||||
|
||||
// Запрос для получения истории поиска
|
||||
const [getSearchHistory, { loading: historyLoading }] = useLazyQuery(GET_RECENT_SEARCH_QUERIES, {
|
||||
onCompleted: (data) => {
|
||||
setSearchHistoryItems(data.partsSearchHistory?.items || []);
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('❌ Ошибка загрузки истории поиска:', error);
|
||||
setSearchHistoryItems([]);
|
||||
}
|
||||
});
|
||||
|
||||
// Закрытие результатов при клике вне области
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (searchDropdownRef.current && !searchDropdownRef.current.contains(event.target as Node)) {
|
||||
setShowResults(false);
|
||||
setShowSearchHistory(false);
|
||||
setInputFocused(false);
|
||||
// Показываем placeholder обратно только если поле пустое
|
||||
if (searchQuery.trim() === '') {
|
||||
setShowPlaceholder(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -356,6 +380,54 @@ const Header: React.FC<HeaderProps> = ({ onOpenAuthModal = () => console.log('Au
|
||||
router.push(url);
|
||||
};
|
||||
|
||||
// Обработчик фокуса на поле ввода
|
||||
const handleInputFocus = () => {
|
||||
setInputFocused(true);
|
||||
setShowResults(false);
|
||||
setShowPlaceholder(false);
|
||||
if (searchQuery.trim() === '') {
|
||||
setShowSearchHistory(true);
|
||||
getSearchHistory({ variables: { limit: 5 } });
|
||||
}
|
||||
};
|
||||
|
||||
// Обработчик изменения значения поля ввода
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
setSearchQuery(value);
|
||||
|
||||
// Управляем placeholder в зависимости от наличия текста
|
||||
if (value.trim() === '') {
|
||||
setShowPlaceholder(false); // Скрываем placeholder пока в фокусе
|
||||
setShowSearchHistory(true);
|
||||
setShowResults(false);
|
||||
getSearchHistory({ variables: { limit: 5 } });
|
||||
} else {
|
||||
setShowPlaceholder(false); // Скрываем placeholder когда есть текст
|
||||
setShowSearchHistory(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Обработчик потери фокуса
|
||||
const handleInputBlur = () => {
|
||||
// Показываем placeholder обратно только если поле пустое
|
||||
if (searchQuery.trim() === '') {
|
||||
setShowPlaceholder(true);
|
||||
}
|
||||
};
|
||||
|
||||
// Обработчик клика по элементу истории
|
||||
const handleHistoryItemClick = (searchQuery: string) => {
|
||||
setSearchQuery(searchQuery);
|
||||
setShowSearchHistory(false);
|
||||
setInputFocused(false);
|
||||
setShowPlaceholder(false); // Скрываем placeholder так как теперь есть текст
|
||||
// Фокусируем поле ввода для возможности редактирования
|
||||
if (searchInputRef.current) {
|
||||
searchInputRef.current.focus();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* <section className="top_head">
|
||||
@ -421,7 +493,7 @@ const Header: React.FC<HeaderProps> = ({ onOpenAuthModal = () => console.log('Au
|
||||
</svg></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="searcj w-form" style={{ position: 'relative' }}>
|
||||
<div className="searcj w-form" style={{ position: 'relative' }} ref={searchDropdownRef}>
|
||||
<form
|
||||
id="custom-search-form"
|
||||
name="custom-search-form"
|
||||
@ -444,23 +516,33 @@ const Header: React.FC<HeaderProps> = ({ onOpenAuthModal = () => console.log('Au
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
ref={searchInputRef}
|
||||
className="text-field w-input"
|
||||
maxLength={256}
|
||||
name="customSearch"
|
||||
data-custom-input="true"
|
||||
placeholder="Введите код запчасти, VIN номер или госномер автомобиля"
|
||||
placeholder={showPlaceholder ? "Введите код запчасти, VIN номер или госномер автомобиля" : ""}
|
||||
type="text"
|
||||
id="customSearchInput"
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
onChange={handleInputChange}
|
||||
onFocus={handleInputFocus}
|
||||
onBlur={handleInputBlur}
|
||||
disabled={isSearching}
|
||||
/>
|
||||
</form>
|
||||
|
||||
{/* История поиска */}
|
||||
<SearchHistoryDropdown
|
||||
isVisible={showSearchHistory && !showResults}
|
||||
historyItems={searchHistoryItems}
|
||||
onItemClick={handleHistoryItemClick}
|
||||
loading={historyLoading}
|
||||
/>
|
||||
|
||||
{/* Результаты поиска VIN */}
|
||||
{showResults && searchResults.length > 0 && (searchType === 'vin' || searchType === 'plate') && (
|
||||
<div
|
||||
ref={searchDropdownRef}
|
||||
className="absolute top-full left-0 right-0 bg-white border border-gray-200 rounded-lg shadow-lg mt-2 z-50 max-h-80 overflow-y-auto"
|
||||
>
|
||||
<div className="p-3 border-b border-gray-100">
|
||||
|
Reference in New Issue
Block a user