/
Cooolprogrammers
/
web-nodejs-labs
Обзор
Документация
Войти
/
Cooolprogrammers
/
web-nodejs-labs
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
public/lab11/task3/script.js
221 строка
7 KB
darkvoid6@mail.ru
ЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫ
18 дек 2025, 07:59
18 дек 2025, 07:59
f2c4f06
Код
Авторство
О чём код?
const API_AUTH = '/api/lab11'; const API_SHOP = '/api/lab10'; let currentUser = null; // ========================================== // 1. AUTH & INIT // ========================================== function initApp() { const token = localStorage.getItem('token'); const userJson = localStorage.getItem('user'); if (token && userJson) { currentUser = JSON.parse(userJson); updateHeaderUI(true); } else { updateHeaderUI(false); } } function updateHeaderUI(isLoggedIn) { const infoEl = document.getElementById('userInfo'); const btn = document.getElementById('authBtn'); if (isLoggedIn) { const role = currentUser.role === 'admin' ? '<span class="role-badge">ADMIN</span>' : ''; infoEl.innerHTML = `${currentUser.login} ${role}`; btn.textContent = 'Выйти'; btn.onclick = logout; } else { infoEl.textContent = 'Гость'; btn.textContent = 'Войти'; btn.onclick = openLoginModal; } } async function login(e) { e.preventDefault(); const formData = new FormData(e.target); const body = Object.fromEntries(formData); try { const res = await fetch(`${API_AUTH}/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); if (res.ok) { const data = await res.json(); localStorage.setItem('token', data.token); localStorage.setItem('user', JSON.stringify(data.user)); location.reload(); } else { alert('Неверный логин или пароль'); } } catch (err) { alert('Ошибка сети'); } } function logout() { localStorage.removeItem('token'); localStorage.removeItem('user'); location.reload(); } // Универсальная функция запроса (добавляет токен) async function apiCall(url, method, body = null) { const token = localStorage.getItem('token'); const headers = { 'Content-Type': 'application/json' }; if (token) { headers['Authorization'] = `Bearer ${token}`; } const options = { method, headers }; if (body) options.body = JSON.stringify(body); const res = await fetch(url, options); // Если 401 - токен протух if (res.status === 401 && token) { logout(); // Авто-выход return { ok: false, status: 401 }; } const data = await res.json(); return { ok: res.ok, status: res.status, data }; } // ========================================== // 2. SHOP LOGIC // ========================================== async function loadProducts() { const container = document.getElementById('productsContainer'); if (!container) return; // Мы не на странице магазина const res = await apiCall(`${API_SHOP}/products?limit=12`, 'GET'); if (!res.ok) { container.innerHTML = 'Ошибка загрузки'; return; } container.innerHTML = res.data.data.map(p => ` <div class="card"> <div class="card-img">📦</div> <div class="card-body"> <div style="font-size:0.8rem; color:#888; text-transform:uppercase">${p.category_name || 'Разное'}</div> <h3 class="card-title">${p.title}</h3> <div class="card-price">${(p.price / 100).toLocaleString()} ₽</div> </div> <div class="card-footer"> <button class="btn btn-primary" onclick="addToCart(${p.id}, '${p.title}', ${p.price})"> В корзину </button> </div> </div> `).join(''); } // ========================================== // 3. CART LOGIC (Local Storage) // ========================================== function getCart() { return JSON.parse(localStorage.getItem('lab11_cart') || '{}'); } function addToCart(id, title, price) { const cart = getCart(); if (!cart[id]) cart[id] = { id, title, price, quantity: 0 }; cart[id].quantity++; localStorage.setItem('lab11_cart', JSON.stringify(cart)); updateCartUI(); // Анимация кнопки корзины const btn = document.getElementById('cartToggle'); btn.style.transform = "scale(1.1)"; setTimeout(() => btn.style.transform = "scale(1)", 200); } function updateCartUI() { const cart = getCart(); const items = Object.values(cart); const count = items.reduce((sum, i) => sum + i.quantity, 0); const total = items.reduce((sum, i) => sum + (i.price * i.quantity), 0); const countBadge = document.getElementById('cartCount'); if (countBadge) countBadge.textContent = count; const list = document.getElementById('cartItems'); if (list) { if (items.length === 0) list.innerHTML = '<div style="text-align:center; color:#999">Корзина пуста</div>'; else { list.innerHTML = items.map(i => ` <div class="cart-item"> <div> <div style="font-weight:bold">${i.title}</div> <div style="font-size:0.85em; color:#666">${i.quantity} x ${(i.price / 100).toLocaleString()}</div> </div> <div style="font-weight:bold; color:#2563eb">${(i.price * i.quantity / 100).toLocaleString()} ₽</div> </div> `).join(''); } document.getElementById('cartTotal').textContent = (total / 100).toLocaleString() + ' ₽'; } } // ========================================== // 4. CHECKOUT (PROTECTED ACTION) // ========================================== async function checkout() { const cart = getCart(); const items = Object.values(cart).map(i => ({ id: i.id, quantity: i.quantity })); if (items.length === 0) { alert('Корзина пуста'); return; } // ПРОВЕРКА АВТОРИЗАЦИИ ПЕРЕД ПОКУПКОЙ if (!currentUser) { // Гость -> Открыть модалку openLoginModal(); return; } if (!confirm('Подтвердить покупку?')) return; // Авторизован -> Отправляем запрос с токеном const res = await apiCall(`${API_SHOP}/checkout`, 'POST', { items }); if (res.ok) { alert(`✅ Заказ №${res.data.orderId} успешно оформлен!`); localStorage.removeItem('lab11_cart'); updateCartUI(); document.getElementById('cartPanel').classList.add('hidden'); } else { alert(`Ошибка: ${res.data.message || res.data.error}`); } } // ========================================== // 5. MODALS // ========================================== function openLoginModal() { document.getElementById('loginModal').classList.remove('hidden'); } function closeLoginModal() { document.getElementById('loginModal').classList.add('hidden'); } const loginForm = document.getElementById('loginForm'); if (loginForm) loginForm.addEventListener('submit', login);