Files
octopus/myproject/pos/static/pos/js/terminal.js

265 lines
8.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// POS Terminal JavaScript
const CATEGORIES = JSON.parse(document.getElementById('categoriesData').textContent);
const PRODUCTS = JSON.parse(document.getElementById('productsData').textContent);
// Отладка: проверить количество загруженных товаров
console.log('Загружено категорий:', CATEGORIES.length);
console.log('Загружено товаров:', PRODUCTS.length);
console.log('Товары:', PRODUCTS);
let currentCategoryId = null;
const cart = new Map(); // productId -> {id, name, price, qty}
function formatMoney(v) {
return (Number(v)).toFixed(2);
}
function renderCategories() {
const grid = document.getElementById('categoryGrid');
grid.innerHTML = '';
// Кнопка "Все"
const allCol = document.createElement('div');
allCol.className = 'col-6 col-sm-4 col-md-3 col-lg-2';
const allCard = document.createElement('div');
allCard.className = 'card category-card' + (currentCategoryId === null ? ' active' : '');
allCard.onclick = () => {
currentCategoryId = null;
renderCategories();
renderProducts();
};
const allBody = document.createElement('div');
allBody.className = 'card-body';
const allName = document.createElement('div');
allName.className = 'category-name';
allName.textContent = 'Все товары';
allBody.appendChild(allName);
allCard.appendChild(allBody);
allCol.appendChild(allCard);
grid.appendChild(allCol);
// Категории
CATEGORIES.forEach(cat => {
const col = document.createElement('div');
col.className = 'col-6 col-sm-4 col-md-3 col-lg-2';
const card = document.createElement('div');
card.className = 'card category-card' + (currentCategoryId === cat.id ? ' active' : '');
card.onclick = () => {
currentCategoryId = cat.id;
renderCategories();
renderProducts();
};
const body = document.createElement('div');
body.className = 'card-body';
const name = document.createElement('div');
name.className = 'category-name';
name.textContent = cat.name;
body.appendChild(name);
card.appendChild(body);
col.appendChild(card);
grid.appendChild(col);
});
}
function renderProducts() {
const grid = document.getElementById('productGrid');
grid.innerHTML = '';
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
let filtered = currentCategoryId
? PRODUCTS.filter(p => (p.category_ids || []).includes(currentCategoryId))
: PRODUCTS;
if (searchTerm) {
filtered = filtered.filter(p => p.name.toLowerCase().includes(searchTerm));
}
filtered.forEach(p => {
const col = document.createElement('div');
col.className = 'col-6 col-sm-4 col-md-3 col-lg-2';
const card = document.createElement('div');
card.className = 'card product-card';
card.onclick = () => addToCart(p);
const body = document.createElement('div');
body.className = 'card-body';
// Изображение товара
const imageDiv = document.createElement('div');
imageDiv.className = 'product-image';
if (p.image) {
const img = document.createElement('img');
img.src = p.image;
img.alt = p.name;
imageDiv.appendChild(img);
} else {
imageDiv.innerHTML = '<i class="bi bi-image"></i>';
}
// Информация о товаре
const info = document.createElement('div');
info.className = 'product-info';
const name = document.createElement('div');
name.className = 'product-name';
name.textContent = p.name;
const stock = document.createElement('div');
stock.className = 'product-stock';
stock.textContent = p.in_stock ? 'В наличии' : 'Под заказ';
if (!p.in_stock) {
stock.style.color = '#dc3545';
}
const sku = document.createElement('div');
sku.className = 'product-sku';
const skuText = document.createElement('span');
skuText.textContent = p.sku || 'н/д';
const priceSpan = document.createElement('span');
priceSpan.className = 'product-price';
priceSpan.textContent = `${formatMoney(p.price)}`;
sku.appendChild(skuText);
sku.appendChild(priceSpan);
info.appendChild(name);
info.appendChild(stock);
info.appendChild(sku);
body.appendChild(imageDiv);
body.appendChild(info);
card.appendChild(body);
col.appendChild(card);
grid.appendChild(col);
});
}
function addToCart(p) {
if (!cart.has(p.id)) {
cart.set(p.id, { id: p.id, name: p.name, price: Number(p.price), qty: 1 });
} else {
cart.get(p.id).qty += 1;
}
renderCart();
}
function updateQty(id, delta) {
if (!cart.has(id)) return;
const item = cart.get(id);
item.qty += delta;
if (item.qty <= 0) cart.delete(id);
renderCart();
}
function renderCart() {
const list = document.getElementById('cartList');
list.innerHTML = '';
let total = 0;
if (cart.size === 0) {
list.innerHTML = '<p class="text-muted text-center py-4 small">Корзина пуста</p>';
document.getElementById('cartTotal').textContent = '0.00';
return;
}
cart.forEach(item => {
const row = document.createElement('div');
row.className = 'mb-2 pb-2 border-bottom';
const nameRow = document.createElement('div');
nameRow.className = 'd-flex justify-content-between align-items-start mb-1';
nameRow.innerHTML = `
<div class="fw-semibold small">${item.name}</div>
<button class="btn btn-sm btn-link text-danger p-0 ms-2" onclick="event.stopPropagation(); removeFromCart(${item.id});">
<i class="bi bi-x"></i>
</button>
`;
const controlsRow = document.createElement('div');
controlsRow.className = 'd-flex justify-content-between align-items-center';
const controls = document.createElement('div');
controls.className = 'btn-group btn-group-sm';
const minus = document.createElement('button');
minus.className = 'btn btn-outline-secondary';
minus.innerHTML = '<i class="bi bi-dash"></i>';
minus.onclick = (e) => { e.stopPropagation(); updateQty(item.id, -1); };
const qtySpan = document.createElement('button');
qtySpan.className = 'btn btn-outline-secondary disabled';
qtySpan.textContent = item.qty;
const plus = document.createElement('button');
plus.className = 'btn btn-outline-secondary';
plus.innerHTML = '<i class="bi bi-plus"></i>';
plus.onclick = (e) => { e.stopPropagation(); updateQty(item.id, +1); };
controls.appendChild(minus);
controls.appendChild(qtySpan);
controls.appendChild(plus);
const priceDiv = document.createElement('div');
priceDiv.className = 'text-end small';
priceDiv.innerHTML = `<strong>${formatMoney(item.price * item.qty)}</strong>`;
controlsRow.appendChild(controls);
controlsRow.appendChild(priceDiv);
row.appendChild(nameRow);
row.appendChild(controlsRow);
list.appendChild(row);
total += item.qty * item.price;
});
document.getElementById('cartTotal').textContent = formatMoney(total);
}
function removeFromCart(id) {
cart.delete(id);
renderCart();
}
function clearCart() {
cart.clear();
renderCart();
}
document.getElementById('clearCart').onclick = clearCart;
// Заглушки для функционала (будет реализовано позже)
document.getElementById('checkoutNow').onclick = async () => {
alert('Функционал будет подключен позже: создание заказа и списание со склада.');
};
document.getElementById('scheduleLater').onclick = async () => {
alert('Функционал будет подключен позже: создание заказа на доставку/самовывоз.');
};
// Search functionality
document.getElementById('searchInput').addEventListener('input', () => {
renderProducts();
});
// Customer selection
document.getElementById('customerSelectBtn').addEventListener('click', () => {
alert('Функция выбора клиента будет реализована позже');
});
// Инициализация
renderCategories();
renderProducts();
renderCart();
// Установить фокус на строку поиска
document.getElementById('searchInput').focus();