feat: implement compare functionality, checkout flow, and add 30 blog posts
This commit is contained in:
+86
-28
@@ -1,39 +1,97 @@
|
||||
import { Metadata } from 'next';
|
||||
import { HeroSection } from '@/components/sections/HeroSection';
|
||||
import { CartItems } from '@/components/shop/CartItems';
|
||||
import { CartSummary } from '@/components/shop/CartSummary';
|
||||
'use client';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Twój Koszyk | AirProject',
|
||||
description: 'Przejrzyj swoje zamówienie na klimatyzatory i usługi montażu przed finalizacją zakupów.',
|
||||
alternates: {
|
||||
canonical: '/koszyk',
|
||||
}
|
||||
};
|
||||
import { useCartStore } from '@/lib/cart-store';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { Trash2, Plus, Minus, ShoppingBag, ArrowRight } from 'lucide-react';
|
||||
|
||||
export default function KoszykPage() {
|
||||
return (
|
||||
<main className="bg-slate-50 min-h-screen">
|
||||
<HeroSection
|
||||
eyebrow="Sklep"
|
||||
title="Twój koszyk"
|
||||
subtitle="Zanim przejdziesz do płatności, sprawdź szczegóły swojego zamówienia. Możesz łatwo zmienić liczbę urządzeń lub dodać profesjonalny montaż dla wybranych pozycji."
|
||||
ctaText="Wróc do sklepu"
|
||||
ctaLink="/sklep"
|
||||
backgroundImage="https://images.unsplash.com/photo-1556740714-a8395b3bf30f?w=1600&q=80"
|
||||
/>
|
||||
const { items, removeItem, updateQuantity, getTotal, clearCart } = useCartStore();
|
||||
const total = getTotal();
|
||||
|
||||
<section className="py-16 md:py-24 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-12 items-start">
|
||||
<div className="lg:col-span-2">
|
||||
<h2 className="text-2xl font-bold text-primary font-heading mb-8">Lista produktów</h2>
|
||||
<CartItems />
|
||||
if (items.length === 0) {
|
||||
return (
|
||||
<main className="min-h-screen bg-slate-50 flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<ShoppingBag className="size-16 text-border mx-auto mb-4" />
|
||||
<h1 className="text-2xl font-bold text-primary font-heading mb-2">Koszyk jest pusty</h1>
|
||||
<p className="text-text-muted mb-6">Dodaj produkty ze sklepu aby złożyć zamówienie.</p>
|
||||
<Link href="/sklep">
|
||||
<button className="btn btn-primary text-white font-bold">Przejdź do sklepu</button>
|
||||
</Link>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="bg-slate-50 min-h-screen py-8">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-2xl font-bold text-primary font-heading mb-8">Twój koszyk</h1>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
{/* Lista produktów */}
|
||||
<div className="lg:col-span-2 flex flex-col gap-4">
|
||||
{items.map((item) => (
|
||||
<div key={item.id} className="bg-white rounded-xl border border-border p-4 flex gap-4 items-center">
|
||||
<div className="relative size-20 bg-slate-50 rounded-lg shrink-0">
|
||||
<Image src={item.image} alt={item.name} fill className="object-contain p-2" unoptimized={item.image.startsWith('http')} />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-xs text-accent font-semibold">{item.brand}</p>
|
||||
<p className="text-sm font-semibold text-primary font-heading leading-snug line-clamp-2">{item.name}</p>
|
||||
<p className="text-base font-bold text-primary mt-1">{item.price.toLocaleString('pl-PL')} zł</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
<button onClick={() => updateQuantity(item.id, item.quantity - 1)} className="size-7 rounded-lg border border-border flex items-center justify-center text-primary hover:border-accent hover:text-accent transition-colors">
|
||||
<Minus className="size-3.5" />
|
||||
</button>
|
||||
<span className="text-sm font-bold text-primary w-6 text-center">{item.quantity}</span>
|
||||
<button onClick={() => updateQuantity(item.id, item.quantity + 1)} className="size-7 rounded-lg border border-border flex items-center justify-center text-primary hover:border-accent hover:text-accent transition-colors">
|
||||
<Plus className="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-base font-bold text-primary shrink-0 w-24 text-right">
|
||||
{(item.price * item.quantity).toLocaleString('pl-PL')} zł
|
||||
</p>
|
||||
<button onClick={() => removeItem(item.id)} className="text-text-muted hover:text-red-500 transition-colors shrink-0">
|
||||
<Trash2 className="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Podsumowanie */}
|
||||
<div className="lg:col-span-1">
|
||||
<CartSummary />
|
||||
<div className="bg-white rounded-xl border border-border p-6 sticky top-24">
|
||||
<h2 className="text-base font-bold text-primary font-heading mb-4">Podsumowanie</h2>
|
||||
<div className="flex justify-between text-sm text-text-muted mb-2">
|
||||
<span>Produkty ({items.reduce((s, i) => s + i.quantity, 0)} szt.)</span>
|
||||
<span>{total.toLocaleString('pl-PL')} zł</span>
|
||||
</div>
|
||||
<div className="flex justify-between text-sm text-text-muted mb-4">
|
||||
<span>Montaż</span>
|
||||
<span className="text-accent font-medium">wycena telefoniczna</span>
|
||||
</div>
|
||||
<div className="border-t border-border pt-4 mb-6">
|
||||
<div className="flex justify-between font-bold text-primary">
|
||||
<span>Razem (urządzenia)</span>
|
||||
<span>{total.toLocaleString('pl-PL')} zł</span>
|
||||
</div>
|
||||
<p className="text-xs text-text-muted mt-1">+ koszt montażu ustalany indywidualnie</p>
|
||||
</div>
|
||||
<Link href="/zamowienie" className="block">
|
||||
<button className="btn btn-primary text-white font-bold w-full flex items-center justify-center gap-2">
|
||||
Złóż zamówienie <ArrowRight className="size-4" />
|
||||
</button>
|
||||
</Link>
|
||||
<button onClick={clearCart} className="w-full text-xs text-text-muted hover:text-primary transition-colors mt-3">
|
||||
Wyczyść koszyk
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user