Добавлено получение истории поиска с автодополнением в компоненте Header. Обновлены обработчики ввода для управления отображением истории и плейсхолдера. Внедрен запрос для получения последних поисковых запросов. Обновлены стили и логика отображения в компоненте Header.
This commit is contained in:
93
src/components/SearchHistoryDropdown.tsx
Normal file
93
src/components/SearchHistoryDropdown.tsx
Normal file
@ -0,0 +1,93 @@
|
||||
import React from 'react';
|
||||
import { PartsSearchHistoryItem } from '@/lib/graphql/search-history';
|
||||
|
||||
interface SearchHistoryDropdownProps {
|
||||
isVisible: boolean;
|
||||
historyItems: PartsSearchHistoryItem[];
|
||||
onItemClick: (searchQuery: string) => void;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const SearchHistoryDropdown: React.FC<SearchHistoryDropdownProps> = ({
|
||||
isVisible,
|
||||
historyItems,
|
||||
onItemClick,
|
||||
loading = false
|
||||
}) => {
|
||||
if (!isVisible) return null;
|
||||
|
||||
// Фильтруем уникальные запросы
|
||||
const uniqueQueries = Array.from(
|
||||
new Map(
|
||||
historyItems.map(item => [item.searchQuery.toLowerCase(), item])
|
||||
).values()
|
||||
);
|
||||
|
||||
const getSearchTypeLabel = (type: string) => {
|
||||
switch (type) {
|
||||
case 'VIN':
|
||||
return 'VIN';
|
||||
case 'PLATE':
|
||||
return 'Госномер';
|
||||
case 'OEM':
|
||||
case 'ARTICLE':
|
||||
return 'Артикул';
|
||||
default:
|
||||
return 'Поиск';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="absolute top-full left-0 right-0 bg-white border border-gray-200 rounded-lg shadow-lg mt-2 z-50 max-h-60 overflow-y-auto">
|
||||
{loading ? (
|
||||
<div className="p-4 text-center text-gray-500">
|
||||
<div className="flex items-center justify-center">
|
||||
<svg className="animate-spin w-4 h-4 mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
Загрузка истории...
|
||||
</div>
|
||||
</div>
|
||||
) : uniqueQueries.length > 0 ? (
|
||||
<>
|
||||
<div className="p-3 border-b border-gray-100">
|
||||
<h3 className="text-xs font-medium text-gray-500 uppercase tracking-wide">
|
||||
Последние запросы
|
||||
</h3>
|
||||
</div>
|
||||
{uniqueQueries.map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
onClick={() => onItemClick(item.searchQuery)}
|
||||
className="w-full text-left p-3 hover:bg-gray-50 border-b border-gray-100 last:border-b-0 transition-colors cursor-pointer"
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm font-medium text-gray-900 truncate">
|
||||
{item.searchQuery}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500">
|
||||
{getSearchTypeLabel(item.searchType)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="ml-2 flex-shrink-0">
|
||||
<svg className="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
<div className="p-4 text-center text-gray-500">
|
||||
<p className="text-sm">История поиска пуста</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchHistoryDropdown;
|
Reference in New Issue
Block a user