<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your Cart | Seed Vault</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/lucide@latest"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Inter:wght@400;600&display=swap');
h1, h2, h3 { font-family: 'Playfair Display', serif; }
body { font-family: 'Inter', sans-serif; }
</style>
</head>
<body class="bg-stone-50 text-stone-800">
<!-- Navigation -->
<nav class="bg-white border-b border-stone-200 sticky top-0 z-50">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16 items-center">
<div class="flex items-center">
<a href="/" class="text-2xl font-bold text-emerald-800 flex items-center gap-2">
<i data-lucide="sprout"></i>
<span class="hidden sm:inline">Seed Vault</span>
</a>
</div>
<div class="flex items-center gap-4">
<a href="/" class="text-stone-600 hover:text-emerald-700">Continue Shopping</a>
<a href="/cart" class="p-2 text-stone-600 hover:text-emerald-700 relative">
<i data-lucide="shopping-cart"></i>
<span class="absolute top-0 right-0 bg-emerald-600 text-white text-[10px] rounded-full h-4 w-4 flex items-center justify-center">{{ cart_count }}</span>
</a>
</div>
</div>
</div>
</nav>
<main class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div class="flex justify-between items-center mb-8">
<h1 class="text-4xl font-bold text-stone-900">Your Shopping Cart</h1>
{% if cart_items %}
<form action="/cart/clear" method="POST" onsubmit="return confirm('Are you sure you want to clear your cart?');">
<button type="submit" class="text-sm text-red-600 hover:text-red-700 font-medium">
Clear Cart
</button>
</form>
{% endif %}
</div>
{% if cart_items %}
<div class="bg-white rounded-2xl shadow-sm border border-stone-200 overflow-hidden">
<ul class="divide-y divide-stone-200">
{% for item in cart_items %}
<li class="p-6 flex items-center gap-6">
<div class="w-24 h-24 flex-shrink-0 rounded-lg overflow-hidden bg-stone-100">
<img src="{{ item.product.image }}" alt="{{ item.product.name }}" class="w-full h-full object-cover">
</div>
<div class="flex-1">
<h3 class="text-lg font-bold text-stone-900">{{ item.product.name }}</h3>
<p class="text-stone-500 text-sm">{{ item.product.category }}</p>
<p class="text-stone-900 font-semibold mt-1">${{ "%.2f"|format(item.product.price) }}</p>
</div>
<div class="flex items-center gap-6">
<!-- Quantity Controls -->
<div class="flex items-center border border-stone-200 rounded-lg overflow-hidden">
<form action="/cart/update/{{ item.product.id }}" method="POST" class="flex items-center">
<input type="hidden" name="quantity" id="qty-{{ item.product.id }}" value="{{ item.quantity }}">
<button type="submit" name="action" value="decrement" onclick="updateQty('{{ item.product.id }}', -1)" class="p-2 text-stone-500 hover:bg-stone-100 transition">
<i data-lucide="minus" class="w-4 h-4"></i>
</button>
<span class="px-4 py-2 text-sm font-medium border-x border-stone-200">{{ item.quantity }}</span>
<button type="submit" name="action" value="increment" onclick="updateQty('{{ item.product.id }}', 1)" class="p-2 text-stone-500 hover:bg-stone-100 transition">
<i data-lucide="plus" class="w-4 h-4"></i>
</button>
</form>
</div>
<div class="text-right min-w-[80px]">
<p class="text-stone-900 font-bold">${{ "%.2f"|format(item.item_total) }}</p>
</div>
<button onclick="removeFromCart('{{ item.product.id }}')" class="p-2 text-stone-400 hover:text-red-600 transition">
<i data-lucide="trash-2" class="w-5 h-5"></i>
</button>
</div>
</li>
{% endfor %}
</ul>
<div class="p-6 bg-stone-50 border-t border-stone-200">
<div class="flex justify-between items-center">
<span class="text-lg font-medium text-stone-600">Subtotal</span>
<span class="text-2xl font-bold text-stone-900">${{ "%.2f"|format(total_price) }}</span>
</div>
<div class="mt-8 flex gap-4">
<a href="/" class="flex-1 text-center bg-stone-200 hover:bg-stone-300 text-stone-800 font-bold py-4 rounded-xl transition">
Continue Shopping
</a>
<a href="/checkout" class="flex-[2] text-center bg-emerald-700 hover:bg-emerald-800 text-white font-bold py-4 rounded-xl transition shadow-lg shadow-emerald-900/20">
Proceed to Checkout
</a>
</div>
</div>
</div>
{% else %}
<div class="text-center py-20 bg-white rounded-2xl border border-dashed border-stone-300">
<i data-lucide="shopping-cart" class="w-16 h-16 text-stone-300 mx-auto mb-4"></i>
<h2 class="text-2xl font-bold text-stone-900">Your cart is empty</h2>
<p class="text-stone-500 mt-2 mb-8">Looks like you haven't found anything special yet.</p>
<a href="/" class="inline-block bg-emerald-700 text-white px-8 py-3 rounded-full font-semibold hover:bg-emerald-800 transition">
Start Shopping
</a>
</div>
{% endif %}
</main>
<footer class="bg-stone-900 text-stone-400 py-12 mt-24">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<div class="flex justify-center items-center gap-2 text-white text-xl font-bold mb-6">
<i data-lucide="sprout"></i>
<span>Seed Vault</span>
</div>
<p class="mb-6">Nurturing food sovereignty, one seed at a time.</p>
<div class="border-t border-stone-800 pt-8 text-sm">
© 2026 The Artisanal Seed Vault. All rights reserved.
</div>
</div>
</footer>
<!-- Toast Notification -->
<div id="toast" class="fixed bottom-5 right-5 bg-emerald-800 text-white px-6 py-3 rounded-lg shadow-lg transform translate-y-20 opacity-0 transition-all duration-300 z-[100] flex items-center gap-3">
<i data-lucide="check-circle" class="w-5 h-5 text-emerald-400"></i>
<span id="toast-message">Added to cart!</span>
</div>
<script>
lucide.createIcons();
function updateQty(productId, delta) {
const input = document.getElementById(`qty-${productId}`);
let currentVal = parseInt(input.value);
input.value = Math.max(0, currentVal + delta);
}
function showToast(message, type = 'success') {
const toast = document.getElementById('toast');
const toastMsg = document.getElementById('toast-message');
if (type === 'error') {
toast.classList.remove('bg-emerald-800');
toast.classList.add('bg-red-800');
} else {
toast.classList.remove('bg-red-800');
toast.classList.add('bg-emerald-800');
}
toastMsg.innerText = message;
toast.classList.remove('translate-y-20', 'opacity-0');
toast.classList.add('translate-y-0', 'opacity-100');
setTimeout(() => {
toast.classList.add('translate-y-20', 'opacity-0');
toast.classList.remove('translate-y-0', 'opacity-100');
}, 3000);
}
async function removeFromCart(productId) {
try {
const response = await fetch(`/cart/remove/${productId}`, { method: 'POST' });
if (response.ok) {
showToast('Removed from cart!', 'success');
setTimeout(() => {
window.location.reload();
}, 500);
} else {
showToast('Error removing item', 'error');
}
} catch (error) {
console.error('Error removing from cart:', error);
showToast('Error removing item', 'error');
}
}
</script>
</body>
</html>