Server-side search in POS: instant search by name and SKU with debounce 300ms
This commit is contained in:
@@ -12,6 +12,8 @@ const cart = new Map();
|
||||
let currentPage = 1;
|
||||
let hasMoreItems = false;
|
||||
let isLoadingItems = false;
|
||||
let currentSearchQuery = ''; // Текущий поисковый запрос
|
||||
let searchDebounceTimer = null;
|
||||
|
||||
// Переменные для режима редактирования
|
||||
let isEditMode = false;
|
||||
@@ -60,6 +62,8 @@ function renderCategories() {
|
||||
allCard.onclick = async () => {
|
||||
currentCategoryId = null;
|
||||
isShowcaseView = false;
|
||||
currentSearchQuery = ''; // Сбрасываем поиск
|
||||
document.getElementById('searchInput').value = ''; // Очищаем поле поиска
|
||||
renderCategories();
|
||||
await loadItems(); // Загрузка через API
|
||||
};
|
||||
@@ -83,6 +87,8 @@ function renderCategories() {
|
||||
card.onclick = async () => {
|
||||
currentCategoryId = cat.id;
|
||||
isShowcaseView = false;
|
||||
currentSearchQuery = ''; // Сбрасываем поиск
|
||||
document.getElementById('searchInput').value = ''; // Очищаем поле поиска
|
||||
renderCategories();
|
||||
await loadItems(); // Загрузка через API
|
||||
};
|
||||
@@ -104,27 +110,26 @@ function renderCategories() {
|
||||
function renderProducts() {
|
||||
const grid = document.getElementById('productGrid');
|
||||
grid.innerHTML = '';
|
||||
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
|
||||
|
||||
let filtered;
|
||||
|
||||
// Если выбран режим витрины - показываем витринные комплекты
|
||||
if (isShowcaseView) {
|
||||
filtered = showcaseKits;
|
||||
|
||||
// Для витрины — клиентская фильтрация по поиску
|
||||
const searchTerm = document.getElementById('searchInput').value.toLowerCase().trim();
|
||||
if (searchTerm) {
|
||||
filtered = filtered.filter(item => {
|
||||
const name = (item.name || '').toLowerCase();
|
||||
const sku = (item.sku || '').toLowerCase();
|
||||
return name.includes(searchTerm) || sku.includes(searchTerm);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Обычный режим - ITEMS уже отфильтрованы по категории на сервере
|
||||
// Обычный режим - ITEMS уже отфильтрованы на сервере (категория + поиск)
|
||||
filtered = ITEMS;
|
||||
}
|
||||
|
||||
// Поиск — по названию или артикулу, по любой части, без регистра
|
||||
if (searchTerm) {
|
||||
const term = searchTerm.trim();
|
||||
filtered = filtered.filter(item => {
|
||||
const name = (item.name || '').toLowerCase();
|
||||
const sku = (item.sku || '').toLowerCase();
|
||||
return name.includes(term) || sku.includes(term);
|
||||
});
|
||||
}
|
||||
|
||||
filtered.forEach(item => {
|
||||
const col = document.createElement('div');
|
||||
@@ -272,6 +277,11 @@ async function loadItems(append = false) {
|
||||
params.append('category_id', currentCategoryId);
|
||||
}
|
||||
|
||||
// Добавляем поисковый запрос, если есть
|
||||
if (currentSearchQuery) {
|
||||
params.append('query', currentSearchQuery);
|
||||
}
|
||||
|
||||
const response = await fetch(`/pos/api/items/?${params}`);
|
||||
const data = await response.json();
|
||||
|
||||
@@ -932,11 +942,6 @@ document.getElementById('scheduleLater').onclick = async () => {
|
||||
alert('Функционал будет подключен позже: создание заказа на доставку/самовывоз.');
|
||||
};
|
||||
|
||||
// Search functionality - клиентская фильтрация
|
||||
document.getElementById('searchInput').addEventListener('input', () => {
|
||||
renderProducts(); // Просто перерисовываем с фильтрацией
|
||||
});
|
||||
|
||||
// Customer selection
|
||||
document.getElementById('customerSelectBtn').addEventListener('click', () => {
|
||||
alert('Функция выбора клиента будет реализована позже');
|
||||
@@ -1005,6 +1010,29 @@ function getCsrfToken() {
|
||||
return cookieValue;
|
||||
}
|
||||
|
||||
// Обработчик поиска с debounce
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
const query = e.target.value.trim();
|
||||
|
||||
// Отменяем предыдущий таймер
|
||||
if (searchDebounceTimer) {
|
||||
clearTimeout(searchDebounceTimer);
|
||||
}
|
||||
|
||||
// Для витрины — мгновенная клиентская фильтрация
|
||||
if (isShowcaseView) {
|
||||
renderProducts();
|
||||
return;
|
||||
}
|
||||
|
||||
// Для обычных товаров/комплектов — серверный поиск с debounce 300мс
|
||||
searchDebounceTimer = setTimeout(async () => {
|
||||
currentSearchQuery = query;
|
||||
await loadItems(); // Перезагрузка с серверным поиском
|
||||
}, 300);
|
||||
});
|
||||
|
||||
// Инициализация
|
||||
renderCategories();
|
||||
renderProducts(); // Сначала пустая сетка
|
||||
|
||||
Reference in New Issue
Block a user