Add cart button to header with item count
Add a cart button in the header (right of language switcher) that displays the number of items in parentheses when cart is not empty. Button opens the cart drawer on click and count updates dynamically when items are added/removed. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
b3940bba08
commit
957cf79e45
3 changed files with 76 additions and 2 deletions
|
|
@ -43,14 +43,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-left,
|
.header-left {
|
||||||
.header-right {
|
|
||||||
width: 90px;
|
width: 90px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.header-center {
|
.header-center {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
@ -75,4 +81,39 @@
|
||||||
color: var(--color-txt);
|
color: var(--color-txt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-cart-btn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--color-txt);
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-cart-count {
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:empty)::before {
|
||||||
|
content: '(';
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:empty)::after {
|
||||||
|
content: ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
const checkoutBtn = document.querySelector('[data-cart-checkout]');
|
const checkoutBtn = document.querySelector('[data-cart-checkout]');
|
||||||
const closeButtons = document.querySelectorAll('[data-cart-close]');
|
const closeButtons = document.querySelectorAll('[data-cart-close]');
|
||||||
const totalDisplay = document.querySelector('[data-cart-total]');
|
const totalDisplay = document.querySelector('[data-cart-total]');
|
||||||
|
const headerCartBtn = document.querySelector('[data-cart-open]');
|
||||||
|
const headerCartCount = document.querySelector('[data-cart-count]');
|
||||||
|
|
||||||
// Get translated text
|
// Get translated text
|
||||||
const removeText = drawer.dataset.textRemove || 'Remove';
|
const removeText = drawer.dataset.textRemove || 'Remove';
|
||||||
|
|
@ -38,6 +40,11 @@
|
||||||
btn.addEventListener('click', closeDrawer);
|
btn.addEventListener('click', closeDrawer);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Open drawer from header button
|
||||||
|
if (headerCartBtn) {
|
||||||
|
headerCartBtn.addEventListener('click', openDrawer);
|
||||||
|
}
|
||||||
|
|
||||||
// Checkout button
|
// Checkout button
|
||||||
checkoutBtn.addEventListener('click', () => {
|
checkoutBtn.addEventListener('click', () => {
|
||||||
if (currentCart?.checkoutUrl) {
|
if (currentCart?.checkoutUrl) {
|
||||||
|
|
@ -81,6 +88,24 @@
|
||||||
}).format(amount);
|
}).format(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateCartCount() {
|
||||||
|
if (!currentCart || !currentCart.lines || currentCart.lines.edges.length === 0) {
|
||||||
|
if (headerCartCount) {
|
||||||
|
headerCartCount.textContent = '';
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate total quantity
|
||||||
|
const totalQty = currentCart.lines.edges.reduce((sum, edge) => {
|
||||||
|
return sum + edge.node.quantity;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
if (headerCartCount) {
|
||||||
|
headerCartCount.textContent = totalQty > 0 ? totalQty : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function renderCart() {
|
function renderCart() {
|
||||||
if (!currentCart || !currentCart.lines || currentCart.lines.edges.length === 0) {
|
if (!currentCart || !currentCart.lines || currentCart.lines.edges.length === 0) {
|
||||||
emptyState.classList.remove('hidden');
|
emptyState.classList.remove('hidden');
|
||||||
|
|
@ -89,6 +114,7 @@
|
||||||
if (totalDisplay) {
|
if (totalDisplay) {
|
||||||
totalDisplay.textContent = '0,00 €';
|
totalDisplay.textContent = '0,00 €';
|
||||||
}
|
}
|
||||||
|
updateCartCount();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,6 +129,9 @@
|
||||||
totalDisplay.textContent = formatPrice(total, currency);
|
totalDisplay.textContent = formatPrice(total, currency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update header cart count
|
||||||
|
updateCartCount();
|
||||||
|
|
||||||
// Render cart items
|
// Render cart items
|
||||||
itemsContainer.innerHTML = currentCart.lines.edges.map(edge => {
|
itemsContainer.innerHTML = currentCart.lines.edges.map(edge => {
|
||||||
const item = edge.node;
|
const item = edge.node;
|
||||||
|
|
|
||||||
|
|
@ -47,5 +47,9 @@
|
||||||
</li>
|
</li>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<button class="header-cart-btn" data-cart-open aria-label="<?= t('cart') ?>">
|
||||||
|
<?= t('cart') ?> <span class="header-cart-count" data-cart-count></span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue