Добавлены кнопки +/- для управления количеством витринных комплектов в корзине
Теперь витринные букеты можно увеличивать и уменьшать по экземплярам: UI изменения: - Заменен badge на полноценные кнопки +/- как у обычных товаров - Поле количества readonly с желтым фоном для визуального отличия - Кнопки используют тот же дизайн что и для обычных товаров Функционал увеличения (increaseShowcaseKitQty): - Блокирует еще один доступный экземпляр через API - Проверяет наличие свободных букетов на витрине - Показывает сообщение если нет доступных - Обновляет showcase_item_ids и qty в корзине Функционал уменьшения (decreaseShowcaseKitQty): - Снимает блокировку с последнего экземпляра из списка - При qty=1 полностью удаляет из корзины - Обновляет список витрины после изменения Все операции синхронизируются с сервером и Redis.
This commit is contained in:
@@ -901,14 +901,42 @@ function renderCart() {
|
|||||||
qtyControl.className = 'd-flex align-items-center';
|
qtyControl.className = 'd-flex align-items-center';
|
||||||
qtyControl.style.gap = '2px';
|
qtyControl.style.gap = '2px';
|
||||||
|
|
||||||
// СПЕЦИАЛЬНАЯ ЛОГИКА для витринных комплектов (только badge, без кнопок)
|
// СПЕЦИАЛЬНАЯ ЛОГИКА для витринных комплектов
|
||||||
if (isShowcaseKit) {
|
if (isShowcaseKit) {
|
||||||
const badge = document.createElement('span');
|
// Кнопка минус
|
||||||
badge.className = 'badge bg-warning text-dark';
|
const minusBtn = document.createElement('button');
|
||||||
badge.textContent = `${item.qty} шт (витрина)`;
|
minusBtn.className = 'btn btn-outline-secondary btn-sm';
|
||||||
badge.style.fontSize = '0.85rem';
|
minusBtn.innerHTML = '<i class="bi bi-dash-circle" style="font-size: 1.2em;"></i>';
|
||||||
badge.style.padding = '0.5rem 0.75rem';
|
minusBtn.onclick = async (e) => {
|
||||||
qtyControl.appendChild(badge);
|
e.preventDefault();
|
||||||
|
await decreaseShowcaseKitQty(cartKey);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Поле количества (только для отображения, readonly)
|
||||||
|
const qtyInput = document.createElement('input');
|
||||||
|
qtyInput.type = 'number';
|
||||||
|
qtyInput.className = 'qty-input form-control form-control-sm';
|
||||||
|
qtyInput.style.width = '60px';
|
||||||
|
qtyInput.style.textAlign = 'center';
|
||||||
|
qtyInput.style.padding = '0.375rem 0.25rem';
|
||||||
|
qtyInput.value = item.qty;
|
||||||
|
qtyInput.min = 1;
|
||||||
|
qtyInput.readOnly = true; // Только чтение - изменяем только через +/-
|
||||||
|
qtyInput.style.backgroundColor = '#fff3cd'; // Желтый фон как у витринных
|
||||||
|
|
||||||
|
// Кнопка плюс
|
||||||
|
const plusBtn = document.createElement('button');
|
||||||
|
plusBtn.className = 'btn btn-outline-secondary btn-sm';
|
||||||
|
plusBtn.innerHTML = '<i class="bi bi-plus-circle" style="font-size: 1.2em;"></i>';
|
||||||
|
plusBtn.onclick = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
await increaseShowcaseKitQty(cartKey);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Собираем контейнер
|
||||||
|
qtyControl.appendChild(minusBtn);
|
||||||
|
qtyControl.appendChild(qtyInput);
|
||||||
|
qtyControl.appendChild(plusBtn);
|
||||||
} else {
|
} else {
|
||||||
// ОБЫЧНАЯ ЛОГИКА для товаров и комплектов
|
// ОБЫЧНАЯ ЛОГИКА для товаров и комплектов
|
||||||
|
|
||||||
@@ -1029,6 +1057,109 @@ async function removeFromCart(cartKey) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Увеличивает количество витринного комплекта в корзине
|
||||||
|
* Добавляет еще один экземпляр через API (если есть доступные)
|
||||||
|
*/
|
||||||
|
async function increaseShowcaseKitQty(cartKey) {
|
||||||
|
const item = cart.get(cartKey);
|
||||||
|
if (!item || item.type !== 'showcase_kit') return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Пытаемся заблокировать еще 1 экземпляр
|
||||||
|
const response = await fetch(`/pos/api/showcase-kits/${item.id}/add-to-cart/`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-CSRFToken': getCookie('csrftoken'),
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ quantity: 1 })
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (!response.ok || !data.success) {
|
||||||
|
// Нет доступных экземпляров
|
||||||
|
alert(data.error || 'Нет доступных экземпляров этого букета на витрине');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Успешно заблокировали - обновляем корзину
|
||||||
|
const lockedItemIds = data.locked_item_ids || [];
|
||||||
|
item.qty += lockedItemIds.length;
|
||||||
|
item.showcase_item_ids = [...(item.showcase_item_ids || []), ...lockedItemIds];
|
||||||
|
|
||||||
|
renderCart();
|
||||||
|
saveCartToRedis();
|
||||||
|
|
||||||
|
// Обновляем список витрины
|
||||||
|
if (isShowcaseView) {
|
||||||
|
await loadShowcaseKits();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка при увеличении количества витринного комплекта:', error);
|
||||||
|
alert('Ошибка сервера. Попробуйте еще раз.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Уменьшает количество витринного комплекта в корзине
|
||||||
|
* Снимает блокировку с одного экземпляра (последнего в списке)
|
||||||
|
*/
|
||||||
|
async function decreaseShowcaseKitQty(cartKey) {
|
||||||
|
const item = cart.get(cartKey);
|
||||||
|
if (!item || item.type !== 'showcase_kit') return;
|
||||||
|
|
||||||
|
// Если количество = 1, удаляем полностью
|
||||||
|
if (item.qty <= 1) {
|
||||||
|
await removeFromCart(cartKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Снимаем блокировку с последнего экземпляра
|
||||||
|
const showcaseItemIds = item.showcase_item_ids || [];
|
||||||
|
if (showcaseItemIds.length === 0) {
|
||||||
|
// Нет ID - просто удаляем
|
||||||
|
await removeFromCart(cartKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Берем последний ID из списка
|
||||||
|
const itemIdToRelease = showcaseItemIds[showcaseItemIds.length - 1];
|
||||||
|
|
||||||
|
const response = await fetch(`/pos/api/showcase-kits/${item.id}/remove-from-cart/`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-CSRFToken': getCookie('csrftoken'),
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ showcase_item_ids: [itemIdToRelease] })
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error('Ошибка при снятии блокировки:', data.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обновляем корзину
|
||||||
|
item.qty -= 1;
|
||||||
|
item.showcase_item_ids = showcaseItemIds.filter(id => id !== itemIdToRelease);
|
||||||
|
|
||||||
|
renderCart();
|
||||||
|
saveCartToRedis();
|
||||||
|
|
||||||
|
// Обновляем список витрины
|
||||||
|
if (isShowcaseView) {
|
||||||
|
await loadShowcaseKits();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка при уменьшении количества витринного комплекта:', error);
|
||||||
|
alert('Ошибка сервера. Попробуйте еще раз.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function clearCart() {
|
async function clearCart() {
|
||||||
// Сбрасываем все свои блокировки витринных букетов
|
// Сбрасываем все свои блокировки витринных букетов
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user