141 lines
6.7 KiB
TypeScript
141 lines
6.7 KiB
TypeScript
'use client';
|
||
|
||
import { useCartStore } from '@/lib/cart-store';
|
||
import { useActionState, useEffect, startTransition } from 'react';
|
||
import Link from 'next/link';
|
||
import { submitOrderForm } from './actions';
|
||
import { ArrowLeft, CheckCircle2 } from 'lucide-react';
|
||
import { buttonClasses } from '@/components/ui/Button';
|
||
import { getRecaptchaToken } from '@/lib/getRecaptchaToken';
|
||
|
||
|
||
const initialState = { success: false, message: '' };
|
||
|
||
export default function ZamowieniePage() {
|
||
const { items, getTotal, clearCart } = useCartStore();
|
||
const [state, formAction, pending] = useActionState(submitOrderForm, initialState);
|
||
const total = getTotal();
|
||
|
||
useEffect(() => {
|
||
if (state.success) clearCart();
|
||
}, [state.success, clearCart]);
|
||
|
||
if (items.length === 0 && !state.success) {
|
||
return (
|
||
<main className="min-h-screen bg-slate-50 flex items-center justify-center">
|
||
<div className="text-center">
|
||
<p className="text-text-muted mb-4">Koszyk jest pusty.</p>
|
||
<Link href="/sklep" className={buttonClasses({ variant: 'primary', size: 'md' })}>
|
||
Wróć do sklepu
|
||
</Link>
|
||
</div>
|
||
</main>
|
||
);
|
||
}
|
||
|
||
if (state.success) {
|
||
return (
|
||
<main className="min-h-screen bg-slate-50 flex items-center justify-center py-16">
|
||
<div className="max-w-md mx-auto px-4 w-full">
|
||
<div className="bg-green-50 text-green-800 p-8 rounded-2xl border border-green-200 flex flex-col items-center text-center">
|
||
<CheckCircle2 className="w-16 h-16 text-green-500 mb-4" />
|
||
<h3 className="text-2xl font-bold font-heading mb-2">Zamówienie przyjęte!</h3>
|
||
<p className="text-green-700">{state.message}</p>
|
||
<Link href="/sklep" className="mt-6 px-6 py-2 bg-green-600 text-white rounded-lg font-semibold hover:bg-green-700 transition-colors">
|
||
Wróć do sklepu
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<main className="bg-slate-50 min-h-screen py-8">
|
||
<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
|
||
<Link href="/koszyk" className="inline-flex items-center gap-2 text-sm text-text-muted hover:text-accent mb-6">
|
||
<ArrowLeft className="size-4" /> Wróć do koszyka
|
||
</Link>
|
||
|
||
<h1 className="text-2xl font-bold text-primary font-heading mb-8">Złóż zamówienie</h1>
|
||
|
||
<div className="grid grid-cols-1 gap-6">
|
||
<div className="bg-white rounded-xl border border-border p-6">
|
||
<h2 className="text-base font-bold text-primary font-heading mb-4">Zamawiane produkty</h2>
|
||
<div className="flex flex-col gap-2">
|
||
{items.map((item) => (
|
||
<div key={item.id} className="flex justify-between text-sm">
|
||
<span className="text-text-muted">{item.name} × {item.quantity}</span>
|
||
<span className="font-semibold text-primary">{(item.price * item.quantity).toLocaleString('pl-PL')} zł</span>
|
||
</div>
|
||
))}
|
||
<div className="border-t border-border pt-2 mt-2 flex justify-between font-bold text-primary">
|
||
<span>Łącznie (urządzenia)</span>
|
||
<span>{total.toLocaleString('pl-PL')} zł</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<form onSubmit={async (e) => {
|
||
e.preventDefault();
|
||
const formData = new FormData(e.currentTarget);
|
||
const token = await getRecaptchaToken('submit');
|
||
if (token) {
|
||
formData.append('recaptchaToken', token);
|
||
}
|
||
startTransition(() => {
|
||
formAction(formData);
|
||
});
|
||
}} className="bg-white rounded-xl border border-border p-6 flex flex-col gap-4">
|
||
<h2 className="text-base font-bold text-primary font-heading">Twoje dane</h2>
|
||
<input type="hidden" name="products" value={JSON.stringify(items)} />
|
||
<input type="hidden" name="total" value={total} />
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||
<div>
|
||
<label className="text-xs font-medium text-primary mb-1 block">Imię i nazwisko *</label>
|
||
<input name="name" required className="w-full border border-border rounded-lg px-3 py-2.5 text-sm focus:border-accent outline-none" placeholder="Jan Kowalski" />
|
||
</div>
|
||
<div>
|
||
<label className="text-xs font-medium text-primary mb-1 block">Telefon *</label>
|
||
<input name="phone" required type="tel" className="w-full border border-border rounded-lg px-3 py-2.5 text-sm focus:border-accent outline-none" placeholder="+48 600 000 000" />
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="text-xs font-medium text-primary mb-1 block">Email *</label>
|
||
<input name="email" required type="email" className="w-full border border-border rounded-lg px-3 py-2.5 text-sm focus:border-accent outline-none" placeholder="[email protected]" />
|
||
</div>
|
||
|
||
<div>
|
||
<label className="text-xs font-medium text-primary mb-1 block">Adres dostawy / montażu</label>
|
||
<input name="address" className="w-full border border-border rounded-lg px-3 py-2.5 text-sm focus:border-accent outline-none" placeholder="ul. Przykładowa 1, 50-000 Wrocław" />
|
||
</div>
|
||
|
||
<div>
|
||
<label className="text-xs font-medium text-primary mb-1 block">Uwagi do zamówienia</label>
|
||
<textarea name="notes" rows={3} className="w-full border border-border rounded-lg px-3 py-2.5 text-sm focus:border-accent outline-none resize-none" placeholder="Np. preferowany termin montażu, piętro, specjalne wymagania..." />
|
||
</div>
|
||
|
||
<label className="flex items-start gap-3 cursor-pointer">
|
||
<input type="checkbox" name="consent" required className="mt-0.5 w-5 h-5 accent-accent shrink-0 cursor-pointer" />
|
||
<span className="text-xs text-text-muted">Wyrażam zgodę na przetwarzanie danych osobowych w celu realizacji zamówienia zgodnie z Polityką Prywatności. *</span>
|
||
</label>
|
||
|
||
{state.message && !state.success && (
|
||
<p className="text-sm text-red-500">{state.message}</p>
|
||
)}
|
||
|
||
<button type="submit" disabled={pending} className="btn btn-primary text-white font-bold w-full flex items-center justify-center gap-2">
|
||
{pending ? 'Wysyłanie...' : 'Wyślij zamówienie'}
|
||
</button>
|
||
|
||
<p className="text-xs text-text-muted text-center">
|
||
Po złożeniu zamówienia skontaktujemy się z Tobą telefonicznie w ciągu 24 godzin, aby potwierdzić szczegóły i ustalić termin montażu.
|
||
</p>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
);
|
||
}
|