cart.astro raw
1 ---
2 import Base from '../layouts/Base.astro';
3 ---
4 <Base title="Количка">
5 <section class="section">
6 <div class="container">
7 <h1 data-i18n="cartTitle">Количка</h1>
8 <div id="cart-contents"></div>
9 <div id="cart-summary" class="cart-summary" style="display:none">
10 <div class="cart-total">
11 <span data-i18n="cartTotal">Общо: </span>
12 <span id="cart-total-amount"> 0.00 EUR</span>
13 </div>
14 <a href="/checkout" class="btn btn-primary btn-lg" style="margin-top:1rem" data-i18n="toCheckout">Към плащане</a>
15 </div>
16 <div id="cart-empty" style="display:none">
17 <p data-i18n="cartEmpty">Количката е празна.</p>
18 <a href="/shop" class="btn btn-outline" data-i18n="shopNow">Разгледайте продуктите</a>
19 </div>
20 </div>
21 </section>
22 </Base>
23
24 <script>
25 import { getCart, setQty, removeItem, formatLv, escapeHtml } from '../lib/cart-client';
26 import { currentLang } from '../lib/i18n';
27
28 function renderCart() {
29 const cart = getCart();
30 const container = document.getElementById('cart-contents')!;
31 const summary = document.getElementById('cart-summary')!;
32 const empty = document.getElementById('cart-empty')!;
33 const lang = currentLang();
34
35 if (cart.length === 0) {
36 container.innerHTML = '';
37 summary.style.display = 'none';
38 empty.style.display = 'block';
39 return;
40 }
41
42 empty.style.display = 'none';
43 summary.style.display = 'block';
44
45 let total = 0;
46 container.innerHTML = `<div class="cart-items">${cart.map((item, i) => {
47 total += item.price_cents * item.qty;
48 const displayName = lang === 'en' && item.name_en ? item.name_en : item.name;
49 const unitLabel = lang === 'en' ? 'g' : 'г';
50 return `<div class="cart-item">
51 <img src="${escapeHtml(item.image)}" alt="${escapeHtml(displayName)}" width="80" height="80" />
52 <div class="cart-item-info">
53 <h3>${escapeHtml(displayName)}</h3>
54 <p>${formatLv(item.price_cents)} / ${item.unit_size}${unitLabel}</p>
55 </div>
56 <div class="cart-item-qty">
57 <button class="qty-btn" data-i="${i}" data-dir="-1">-</button>
58 <span>${item.qty} бр.</span>
59 <button class="qty-btn" data-i="${i}" data-dir="1" ${item.qty >= item.stock ? 'disabled' : ''}>+</button>
60 </div>
61 <div class="cart-item-total">${formatLv(item.price_cents * item.qty)}</div>
62 <button class="cart-item-remove" data-i="${i}">×</button>
63 </div>`;
64 }).join('')}</div>`;
65
66 document.getElementById('cart-total-amount')!.textContent = formatLv(total);
67
68 document.querySelectorAll('.qty-btn').forEach(el => {
69 const btn = el as HTMLButtonElement;
70 btn.addEventListener('click', () => {
71 const i = parseInt(btn.dataset.i!);
72 const cart = getCart();
73 setQty(i, cart[i].qty + parseInt(btn.dataset.dir!));
74 renderCart();
75 });
76 });
77 document.querySelectorAll('.cart-item-remove').forEach(el => {
78 const btn = el as HTMLButtonElement;
79 btn.addEventListener('click', () => {
80 removeItem(parseInt(btn.dataset.i!));
81 renderCart();
82 });
83 });
84 }
85 renderCart();
86 window.addEventListener('lang-changed', renderCart);
87 </script>
88
89 <style is:global>
90 #cart-contents { margin-top: 1rem; }
91 .qty-btn:disabled { opacity: 0.35; cursor: not-allowed; }
92 .cart-item-remove {
93 background: none;
94 border: none;
95 font-size: 1.2rem;
96 color: #999;
97 cursor: pointer;
98 padding: 0 4px;
99 line-height: 1;
100 flex-shrink: 0;
101 }
102 .cart-item-remove:hover { color: #c0392b; }
103 </style>
104