2025-05-30 18:00:52 +02:00
|
|
|
// static/js/cart.js
|
|
|
|
|
|
|
|
import { getAuthHeaders, handleApiError } from './utils.js';
|
|
|
|
|
2025-05-25 16:25:22 +02:00
|
|
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
|
|
try {
|
|
|
|
const token = localStorage.getItem('token');
|
|
|
|
if (!token) {
|
|
|
|
window.location.href = '/login.html';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const response = await fetch('/api/cart', {
|
2025-05-30 18:00:52 +02:00
|
|
|
headers: getAuthHeaders()
|
2025-05-25 16:25:22 +02:00
|
|
|
});
|
2025-05-30 18:00:52 +02:00
|
|
|
|
2025-05-25 16:25:22 +02:00
|
|
|
if (!response.ok) throw new Error('Błąd ładowania koszyka');
|
|
|
|
const cartItems = await response.json();
|
2025-05-30 18:00:52 +02:00
|
|
|
renderCart(cartItems);
|
2025-05-25 16:25:22 +02:00
|
|
|
|
2025-05-30 18:00:52 +02:00
|
|
|
} catch (error) {
|
|
|
|
handleApiError(error, 'Nie udało się załadować koszyka');
|
|
|
|
}
|
|
|
|
});
|
2025-05-30 15:40:23 +02:00
|
|
|
|
2025-05-30 18:00:52 +02:00
|
|
|
function renderCart(cartItems) {
|
|
|
|
const container = document.getElementById('cart-items');
|
|
|
|
container.innerHTML = '';
|
|
|
|
|
|
|
|
if (cartItems.length === 0) {
|
|
|
|
container.innerHTML = '<p class="text-center">Twój koszyk jest pusty</p>';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let totalCartValue = 0;
|
|
|
|
|
|
|
|
cartItems.forEach(item => {
|
|
|
|
const price = parseFloat(item.cena);
|
|
|
|
const itemTotal = price * item.quantity;
|
|
|
|
totalCartValue += itemTotal;
|
|
|
|
|
|
|
|
const itemHTML = `
|
|
|
|
<div class="col-12 mb-4 cart-item">
|
|
|
|
<div class="card dark-card">
|
|
|
|
<div class="row g-0">
|
|
|
|
<div class="col-md-4 text-center p-3 cart-item-image">
|
|
|
|
<img src="${item.obraz_url}"
|
|
|
|
class="img-fluid rounded"
|
|
|
|
alt="${item.tytul}"
|
|
|
|
style="max-height: 200px;">
|
|
|
|
</div>
|
|
|
|
<div class="col-md-8 cart-item-details">
|
|
|
|
<div class="card-body h-100 d-flex flex-column">
|
|
|
|
<div>
|
|
|
|
<h5 class="card-title cart-item-title">${item.tytul}</h5>
|
|
|
|
<p class="card-text cart-item-author">${item.autor}</p>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="d-flex flex-wrap gap-3 mb-2 cart-item-info mt-auto">
|
|
|
|
<div class="d-flex flex-column flex-grow-1">
|
|
|
|
<span class="fw-bold cart-item-price">Cena jednostkowa</span>
|
|
|
|
<span class="fs-5">${price.toFixed(2)} PLN</span>
|
2025-05-30 15:40:23 +02:00
|
|
|
</div>
|
|
|
|
|
2025-05-30 18:00:52 +02:00
|
|
|
<div class="d-flex flex-column">
|
|
|
|
<span class="fw-bold">Ilość</span>
|
|
|
|
<div class="d-flex align-items-center gap-2">
|
|
|
|
<span class="fs-5 badge bg-dark rounded-pill">${item.quantity}</span>
|
2025-05-30 15:40:23 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2025-05-30 18:00:52 +02:00
|
|
|
<div class="d-flex flex-column">
|
|
|
|
<span class="fw-bold cart-item-total">Suma</span>
|
|
|
|
<span class="fs-5 text-warning">${itemTotal.toFixed(2)} PLN</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="mt-3">
|
|
|
|
<div class="btn-group w-100" role="group">
|
|
|
|
<button class="btn btn-sm btn-outline-secondary decrease-quantity flex-grow-1"
|
|
|
|
data-book-id="${item.book_id}">
|
|
|
|
<i class="bi bi-dash"></i> Zmniejsz ilość
|
|
|
|
</button>
|
|
|
|
<button class="btn btn-sm btn-outline-danger remove-from-cart cart-remove-btn flex-grow-1"
|
|
|
|
data-book-id="${item.book_id}">
|
|
|
|
<i class="bi bi-trash"></i> Usuń
|
|
|
|
</button>
|
2025-05-30 15:40:23 +02:00
|
|
|
</div>
|
2025-05-25 16:25:22 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-05-30 15:40:23 +02:00
|
|
|
</div>
|
|
|
|
`;
|
2025-05-30 18:00:52 +02:00
|
|
|
container.insertAdjacentHTML('beforeend', itemHTML);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Suma całkowita
|
|
|
|
const totalHTML = `
|
|
|
|
<div class="col-12 mt-4">
|
|
|
|
<div class="card dark-card p-4">
|
|
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
|
|
<h2 class="mb-0">Suma całkowita</h2>
|
|
|
|
<h2 class="mb-0 total-cart-value">${totalCartValue.toFixed(2)} PLN</h2>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
`;
|
|
|
|
container.insertAdjacentHTML('beforeend', totalHTML);
|
|
|
|
|
|
|
|
// Obsługa przycisków
|
|
|
|
document.querySelectorAll('.decrease-quantity').forEach(button => {
|
|
|
|
button.addEventListener('click', function() {
|
|
|
|
const bookId = this.dataset.bookId;
|
|
|
|
updateCartItemQuantity(bookId, 'decrease');
|
2025-05-30 15:40:23 +02:00
|
|
|
});
|
2025-05-30 18:00:52 +02:00
|
|
|
});
|
2025-05-30 15:40:23 +02:00
|
|
|
|
2025-05-30 18:00:52 +02:00
|
|
|
document.querySelectorAll('.remove-from-cart').forEach(button => {
|
|
|
|
button.addEventListener('click', function() {
|
|
|
|
const bookId = this.dataset.bookId;
|
|
|
|
updateCartItemQuantity(bookId, 'remove');
|
2025-05-30 15:40:23 +02:00
|
|
|
});
|
2025-05-30 18:00:52 +02:00
|
|
|
});
|
2025-05-30 15:40:23 +02:00
|
|
|
|
2025-05-30 18:00:52 +02:00
|
|
|
// Finalizacja zamówienia
|
|
|
|
document.getElementById('checkoutBtn')?.addEventListener('click', handleCheckout);
|
|
|
|
}
|
2025-05-25 16:54:16 +02:00
|
|
|
|
2025-05-30 15:40:23 +02:00
|
|
|
async function updateCartItemQuantity(bookId, action) {
|
|
|
|
try {
|
|
|
|
const token = localStorage.getItem('token');
|
|
|
|
if (!token) {
|
|
|
|
window.location.href = '/login.html';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2025-05-30 18:00:52 +02:00
|
|
|
let method, endpoint;
|
2025-05-30 15:40:23 +02:00
|
|
|
if (action === 'decrease') {
|
|
|
|
endpoint = `/api/decrease-cart-item/${bookId}`;
|
|
|
|
method = 'POST';
|
2025-05-30 18:00:52 +02:00
|
|
|
} else {
|
2025-05-30 15:40:23 +02:00
|
|
|
endpoint = `/api/remove-from-cart/${bookId}`;
|
|
|
|
method = 'DELETE';
|
|
|
|
}
|
|
|
|
|
|
|
|
const response = await fetch(endpoint, {
|
2025-05-30 18:00:52 +02:00
|
|
|
method,
|
|
|
|
headers: getAuthHeaders()
|
2025-05-30 15:40:23 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
if (!response.ok) throw new Error('Błąd aktualizacji koszyka');
|
|
|
|
location.reload();
|
|
|
|
} catch (error) {
|
2025-05-30 18:00:52 +02:00
|
|
|
handleApiError(error);
|
2025-05-30 15:40:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-30 18:00:52 +02:00
|
|
|
async function handleCheckout() {
|
2025-05-25 16:54:16 +02:00
|
|
|
try {
|
|
|
|
const token = localStorage.getItem('token');
|
|
|
|
if (!token) {
|
|
|
|
window.location.href = '/login.html';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2025-05-30 18:00:52 +02:00
|
|
|
// Pobierz zawartość koszyka
|
2025-05-25 16:54:16 +02:00
|
|
|
const cartResponse = await fetch('/api/cart', {
|
2025-05-30 18:00:52 +02:00
|
|
|
headers: getAuthHeaders()
|
2025-05-25 16:54:16 +02:00
|
|
|
});
|
2025-05-30 18:00:52 +02:00
|
|
|
if (!cartResponse.ok) throw new Error('Błąd pobierania koszyka');
|
2025-05-25 16:54:16 +02:00
|
|
|
const cartItems = await cartResponse.json();
|
|
|
|
|
|
|
|
// Wyślij zamówienie
|
|
|
|
const response = await fetch('/api/checkout', {
|
|
|
|
method: 'POST',
|
2025-05-30 18:00:52 +02:00
|
|
|
headers: getAuthHeaders(),
|
|
|
|
body: JSON.stringify({
|
|
|
|
items: cartItems.map(item => ({
|
|
|
|
book_id: item.book_id,
|
|
|
|
quantity: item.quantity
|
|
|
|
})),
|
|
|
|
total: cartItems.reduce((sum, item) =>
|
|
|
|
sum + (parseFloat(item.cena) * item.quantity), 0)
|
|
|
|
})
|
2025-05-25 16:54:16 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
if (!response.ok) throw new Error('Błąd podczas składania zamówienia');
|
|
|
|
window.location.href = '/thankyou.html';
|
|
|
|
} catch (error) {
|
2025-05-30 18:00:52 +02:00
|
|
|
handleApiError(error, 'Nie udało się złożyć zamówienia');
|
2025-05-25 16:54:16 +02:00
|
|
|
}
|
2025-05-30 18:00:52 +02:00
|
|
|
}
|