/
Cooolprogrammers
/
web-nodejs-labs
Обзор
Документация
Войти
/
Cooolprogrammers
/
web-nodejs-labs
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
public/lab9/task3/script.js
384 строки
14 KB
darkvoid6@mail.ru
ЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫ
18 дек 2025, 07:59
18 дек 2025, 07:59
f2c4f06
Код
Авторство
О чём код?
const API_BASE = '/api/lab9'; // Ключ для localStorage const CART_STORAGE_KEY = 'lab9_shopping_cart'; // Форматирование цены: Копейки -> Рубли const formatPrice = (cents) => { return (cents / 100).toLocaleString('ru-RU', { style: 'currency', currency: 'RUB' }); }; // Корзина let cart = {}; let availableProducts = []; // Загрузка корзины из localStorage function loadCart() { const savedCart = localStorage.getItem(CART_STORAGE_KEY); if (savedCart) { cart = JSON.parse(savedCart); } updateCartDisplay(); } // Сохранение корзины в localStorage function saveCart() { localStorage.setItem(CART_STORAGE_KEY, JSON.stringify(cart)); updateCartDisplay(); } // Обновление отображения корзины function updateCartDisplay() { const cartItemsCount = document.getElementById('cartItemsCount'); const cartTotalPrice = document.getElementById('cartTotalPrice'); const cartContent = document.getElementById('cartContent'); const checkoutSection = document.getElementById('checkoutSection'); // Подсчет общего количества и стоимости let totalItems = 0; let totalPrice = 0; Object.values(cart).forEach(item => { totalItems += item.quantity; totalPrice += item.price * item.quantity; }); // Обновление счетчика и общей стоимости cartItemsCount.textContent = totalItems; cartTotalPrice.textContent = formatPrice(totalPrice); // Отображение содержимого корзины if (totalItems === 0) { cartContent.innerHTML = ` <div class="empty-cart-message"> <h3>Корзина пуста</h3> <p>Добавьте товары из списка ниже</p> </div> `; checkoutSection.style.display = 'none'; } else { renderCartItems(); checkoutSection.style.display = 'block'; } } // Отображение товаров в корзине function renderCartItems() { const cartContent = document.getElementById('cartContent'); const cartItemsHTML = Object.values(cart).map(item => ` <div class="cart-item" data-product-id="${item.id}"> <div class="cart-item-info"> <div class="cart-item-title">${item.title}</div> <div class="cart-item-details"> <span class="cart-item-price">${formatPrice(item.price)}</span> <span class="cart-item-id">ID: ${item.id}</span> </div> </div> <div class="cart-item-controls"> <div class="quantity-controls"> <button class="quantity-btn" onclick="changeQuantity(${item.id}, -1)" ${item.quantity <= 1 ? 'disabled' : ''}>-</button> <span class="quantity-display">${item.quantity}</span> <button class="quantity-btn" onclick="changeQuantity(${item.id}, 1)" ${item.quantity >= 5 ? 'disabled' : ''}>+</button> </div> <div class="item-total"> ${formatPrice(item.price * item.quantity)} </div> <button class="remove-from-cart" onclick="removeFromCart(${item.id})"> Удалить </button> </div> </div> `).join(''); cartContent.innerHTML = ` <div class="cart-items"> ${cartItemsHTML} </div> `; } // Изменение количества товара в корзине function changeQuantity(productId, delta) { if (cart[productId]) { const newQuantity = cart[productId].quantity + delta; if (newQuantity >= 1 && newQuantity <= 5) { cart[productId].quantity = newQuantity; saveCart(); } } } // Удаление товара из корзины function removeFromCart(productId) { if (confirm('Удалить товар из корзины?')) { delete cart[productId]; saveCart(); } } // Очистка корзины document.getElementById('clearCartBtn').addEventListener('click', function() { if (Object.keys(cart).length === 0) { showMessage('Корзина уже пуста', 'error'); return; } if (confirm('Очистить всю корзину?')) { cart = {}; saveCart(); showMessage('Корзина очищена', 'success'); } }); // Добавление товара в корзину function addToCart(product) { if (cart[product.id]) { if (cart[product.id].quantity >= 5) { showMessage('Максимальное количество товара в корзине - 5', 'error'); return; } cart[product.id].quantity += 1; } else { cart[product.id] = { id: product.id, title: product.title, price: product.price, quantity: 1 }; } saveCart(); showMessage(`Товар "${product.title}" добавлен в корзину`, 'success'); } // Загрузка доступных товаров async function loadAvailableProducts(searchTerm = '') { try { let url = `${API_BASE}/products`; if (searchTerm) { url = `${API_BASE}/task1/products?q=${encodeURIComponent(searchTerm)}`; } const response = await fetch(url); if (!response.ok) { throw new Error('Ошибка загрузки товаров'); } availableProducts = await response.json(); renderAvailableProducts(); } catch (error) { document.getElementById('availableProducts').innerHTML = `<div class="error-message">${error.message}</div>`; } } // Отображение доступных товаров function renderAvailableProducts() { const availableProductsContainer = document.getElementById('availableProducts'); if (availableProducts.length === 0) { availableProductsContainer.innerHTML = '<div class="loading">Товары не найдены</div>'; return; } const productsHTML = availableProducts.map(product => { const inCart = cart[product.id]; const cartQuantity = inCart ? inCart.quantity : 0; const canAddMore = cartQuantity < 5; return ` <div class="available-product"> <div class="available-product-info"> <div class="available-product-title">${product.title}</div> <div class="available-product-details"> <span class="product-price">${formatPrice(product.price)}</span> <span class="product-amount">В наличии: ${product.amount} шт.</span> <span class="product-id">ID: ${product.id}</span> </div> </div> <div class="available-product-actions"> <button class="add-to-cart-btn" onclick="addToCart(${JSON.stringify(product).replace(/"/g, '"')})" ${!canAddMore ? 'disabled' : ''}> ${inCart ? `В корзине: ${cartQuantity}` : 'В корзину'} </button> </div> </div> `; }).join(''); availableProductsContainer.innerHTML = productsHTML; } // Проверка наличия товаров document.getElementById('checkOrderBtn').addEventListener('click', async function() { const checkResult = document.getElementById('checkResult'); // Преобразуем корзину в формат для API const items = Object.values(cart).map(item => ({ productId: item.id, quantity: item.quantity })); try { const response = await fetch(`${API_BASE}/order/check`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ items }) }); const result = await response.json(); if (response.ok) { checkResult.innerHTML = ` <div class="availability-result availability-success"> <h4>✅ Проверка пройдена</h4> <p>${result.message}</p> <p>Все товары доступны в нужном количестве.</p> </div> `; } else { let unavailableHTML = ''; if (result.unavailableItems && result.unavailableItems.length > 0) { unavailableHTML = ` <div class="unavailable-items"> <h5>Проблемные товары:</h5> ${result.unavailableItems.map(item => ` <div class="unavailable-item"> <strong>${item.productTitle || `Товар ID: ${item.productId}`}</strong><br> Запрошено: ${item.requested} шт., Доступно: ${item.available} шт.<br> <em>${item.reason}</em> </div> `).join('')} </div> `; } checkResult.innerHTML = ` <div class="availability-result availability-error"> <h4>❌ Проблемы с заказом</h4> <p>${result.message}</p> ${unavailableHTML} </div> `; } } catch (error) { checkResult.innerHTML = ` <div class="availability-result availability-error"> <h4>❌ Ошибка проверки</h4> <p>${error.message}</p> </div> `; } }); // Оформление покупки document.getElementById('purchaseBtn').addEventListener('click', async function() { const checkResult = document.getElementById('checkResult'); // Преобразуем корзину в формат для API const items = Object.values(cart).map(item => ({ productId: item.id, quantity: item.quantity })); try { const response = await fetch(`${API_BASE}/order/purchase`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ items }) }); const result = await response.json(); if (response.ok) { checkResult.innerHTML = ` <div class="availability-result availability-success"> <h4>✅ Покупка оформлена!</h4> <p>${result.message}</p> <p>Заказ успешно обработан. Товары списаны со склада.</p> </div> `; // Очищаем корзину после успешной покупки cart = {}; saveCart(); // Обновляем список доступных товаров loadAvailableProducts(); } else { checkResult.innerHTML = ` <div class="availability-result availability-error"> <h4>❌ Ошибка оформления</h4> <p>${result.message}</p> ${result.errors ? ` <div class="unavailable-items"> <h5>Ошибки:</h5> ${result.errors.map(error => ` <div class="unavailable-item">${error}</div> `).join('')} </div> ` : ''} </div> `; } } catch (error) { checkResult.innerHTML = ` <div class="availability-result availability-error"> <h4>❌ Ошибка оформления</h4> <p>${error.message}</p> </div> `; } }); // Поиск товаров document.getElementById('searchProductsBtn').addEventListener('click', function() { const searchTerm = document.getElementById('productsSearch').value.trim(); loadAvailableProducts(searchTerm); }); // Поиск при нажатии Enter document.getElementById('productsSearch').addEventListener('keypress', function(e) { if (e.key === 'Enter') { const searchTerm = this.value.trim(); loadAvailableProducts(searchTerm); } }); // Показать сообщение function showMessage(message, type) { const messageDiv = document.createElement('div'); messageDiv.className = type === 'success' ? 'success-message' : 'error-message'; messageDiv.textContent = message; const content = document.querySelector('.task-content'); content.insertBefore(messageDiv, content.firstChild); setTimeout(() => { messageDiv.remove(); }, 5000); } // Инициализация при загрузке страницы document.addEventListener('DOMContentLoaded', function() { // Загружаем корзину и товары loadCart(); loadAvailableProducts(); // Обновляем счетчик корзины каждые 2 секунды (на случай изменений из других вкладок) setInterval(loadCart, 2000); });