Compare commits
2 Commits
fix1407
...
074eb120b4
Author | SHA1 | Date | |
---|---|---|---|
074eb120b4 | |||
4dfc081214 |
92
package-lock.json
generated
92
package-lock.json
generated
@ -16,6 +16,7 @@
|
|||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"graphql": "^16.11.0",
|
"graphql": "^16.11.0",
|
||||||
"next": "15.3.3",
|
"next": "15.3.3",
|
||||||
|
"node-fetch": "^3.3.2",
|
||||||
"qrcode": "^1.5.4",
|
"qrcode": "^1.5.4",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
@ -1540,6 +1541,15 @@
|
|||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/data-uri-to-buffer": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/decamelize": {
|
"node_modules/decamelize": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||||
@ -1602,6 +1612,29 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fetch-blob": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "paypal",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"node-domexception": "^1.0.0",
|
||||||
|
"web-streams-polyfill": "^3.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20 || >= 14.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/find-up": {
|
"node_modules/find-up": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||||
@ -1615,6 +1648,18 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/formdata-polyfill": {
|
||||||
|
"version": "4.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||||
|
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fetch-blob": "^3.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fraction.js": {
|
"node_modules/fraction.js": {
|
||||||
"version": "4.3.7",
|
"version": "4.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
||||||
@ -2140,6 +2185,44 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-domexception": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||||
|
"deprecated": "Use your platform's native DOMException instead",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"data-uri-to-buffer": "^4.0.0",
|
||||||
|
"fetch-blob": "^3.1.4",
|
||||||
|
"formdata-polyfill": "^4.0.10"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/node-fetch"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-releases": {
|
"node_modules/node-releases": {
|
||||||
"version": "2.0.19",
|
"version": "2.0.19",
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
|
||||||
@ -2690,6 +2773,15 @@
|
|||||||
"uuid": "dist/esm/bin/uuid"
|
"uuid": "dist/esm/bin/uuid"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/web-streams-polyfill": {
|
||||||
|
"version": "3.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||||
|
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/which-module": {
|
"node_modules/which-module": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"graphql": "^16.11.0",
|
"graphql": "^16.11.0",
|
||||||
"next": "15.3.3",
|
"next": "15.3.3",
|
||||||
|
"node-fetch": "^3.3.2",
|
||||||
"qrcode": "^1.5.4",
|
"qrcode": "^1.5.4",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
@ -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 { LaximoVehicleSearchResult, LaximoDocFindOEMResult, LaximoVehiclesByPartResult } from '@/types/laximo';
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import CartButton from './CartButton';
|
import CartButton from './CartButton';
|
||||||
|
import SearchHistoryDropdown from './SearchHistoryDropdown';
|
||||||
|
import { GET_RECENT_SEARCH_QUERIES, PartsSearchHistoryItem } from '@/lib/graphql/search-history';
|
||||||
|
|
||||||
interface HeaderProps {
|
interface HeaderProps {
|
||||||
onOpenAuthModal?: () => void;
|
onOpenAuthModal?: () => void;
|
||||||
@ -25,9 +27,14 @@ const Header: React.FC<HeaderProps> = ({ onOpenAuthModal = () => console.log('Au
|
|||||||
const [vehiclesByPartResults, setVehiclesByPartResults] = useState<LaximoVehiclesByPartResult | null>(null);
|
const [vehiclesByPartResults, setVehiclesByPartResults] = useState<LaximoVehiclesByPartResult | null>(null);
|
||||||
const [searchType, setSearchType] = useState<'vin' | 'oem' | 'plate' | 'text'>('text');
|
const [searchType, setSearchType] = useState<'vin' | 'oem' | 'plate' | 'text'>('text');
|
||||||
const [oemSearchMode, setOemSearchMode] = useState<'parts' | 'vehicles'>('parts');
|
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 router = useRouter();
|
||||||
const searchFormRef = useRef<HTMLFormElement>(null);
|
const searchFormRef = useRef<HTMLFormElement>(null);
|
||||||
const searchDropdownRef = useRef<HTMLDivElement>(null);
|
const searchDropdownRef = useRef<HTMLDivElement>(null);
|
||||||
|
const searchInputRef = useRef<HTMLInputElement>(null);
|
||||||
const isClient = useIsClient();
|
const isClient = useIsClient();
|
||||||
|
|
||||||
// Эффект для восстановления поискового запроса из URL
|
// Эффект для восстановления поискового запроса из 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(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
if (searchDropdownRef.current && !searchDropdownRef.current.contains(event.target as Node)) {
|
if (searchDropdownRef.current && !searchDropdownRef.current.contains(event.target as Node)) {
|
||||||
setShowResults(false);
|
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);
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* <section className="top_head">
|
{/* <section className="top_head">
|
||||||
@ -421,7 +493,7 @@ const Header: React.FC<HeaderProps> = ({ onOpenAuthModal = () => console.log('Au
|
|||||||
</svg></div>
|
</svg></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="searcj w-form" style={{ position: 'relative' }}>
|
<div className="searcj w-form" style={{ position: 'relative' }} ref={searchDropdownRef}>
|
||||||
<form
|
<form
|
||||||
id="custom-search-form"
|
id="custom-search-form"
|
||||||
name="custom-search-form"
|
name="custom-search-form"
|
||||||
@ -444,23 +516,33 @@ const Header: React.FC<HeaderProps> = ({ onOpenAuthModal = () => console.log('Au
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
|
ref={searchInputRef}
|
||||||
className="text-field w-input"
|
className="text-field w-input"
|
||||||
maxLength={256}
|
maxLength={256}
|
||||||
name="customSearch"
|
name="customSearch"
|
||||||
data-custom-input="true"
|
data-custom-input="true"
|
||||||
placeholder="Введите код запчасти, VIN номер или госномер автомобиля"
|
placeholder={showPlaceholder ? "Введите код запчасти, VIN номер или госномер автомобиля" : ""}
|
||||||
type="text"
|
type="text"
|
||||||
id="customSearchInput"
|
id="customSearchInput"
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
onChange={handleInputChange}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
|
onBlur={handleInputBlur}
|
||||||
disabled={isSearching}
|
disabled={isSearching}
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
{/* История поиска */}
|
||||||
|
<SearchHistoryDropdown
|
||||||
|
isVisible={showSearchHistory && !showResults}
|
||||||
|
historyItems={searchHistoryItems}
|
||||||
|
onItemClick={handleHistoryItemClick}
|
||||||
|
loading={historyLoading}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Результаты поиска VIN */}
|
{/* Результаты поиска VIN */}
|
||||||
{showResults && searchResults.length > 0 && (searchType === 'vin' || searchType === 'plate') && (
|
{showResults && searchResults.length > 0 && (searchType === 'vin' || searchType === 'plate') && (
|
||||||
<div
|
<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"
|
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">
|
<div className="p-3 border-b border-gray-100">
|
||||||
|
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;
|
@ -24,6 +24,20 @@ export const GET_PARTS_SEARCH_HISTORY = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
// Запрос для получения последних поисковых запросов для автодополнения
|
||||||
|
export const GET_RECENT_SEARCH_QUERIES = gql`
|
||||||
|
query GetRecentSearchQueries($limit: Int = 5) {
|
||||||
|
partsSearchHistory(limit: $limit, offset: 0) {
|
||||||
|
items {
|
||||||
|
id
|
||||||
|
searchQuery
|
||||||
|
searchType
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const DELETE_SEARCH_HISTORY_ITEM = gql`
|
export const DELETE_SEARCH_HISTORY_ITEM = gql`
|
||||||
mutation DeletePartsSearchHistoryItem($id: ID!) {
|
mutation DeletePartsSearchHistoryItem($id: ID!) {
|
||||||
deletePartsSearchHistoryItem(id: $id)
|
deletePartsSearchHistoryItem(id: $id)
|
||||||
|
Reference in New Issue
Block a user