Add guest checkout and admin login link

- Add guest checkout flow: customers can now complete orders without creating an account
  - New /checkout page with login or guest options
  - Guest form collects: full name, email, phone, address
  - Orders track guest info via guestName and guestPhone fields
- Update cart message to reflect guest option
- Add "Admin login" link to customer login page for clear navigation
- Update checkout API to accept and store guest information

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Andymick
2026-07-16 20:10:42 +01:00
co-authored by Claude Haiku 4.5
parent 39f54dedee
commit 8edb5e1f5b
5 changed files with 275 additions and 25 deletions
+5 -25
View File
@@ -7,8 +7,6 @@ import Price from '@/components/Price';
export default function CartPage() {
const [mounted, setMounted] = useState(false);
const [checkingOut, setCheckingOut] = useState(false);
const [checkoutError, setCheckoutError] = useState<string | null>(null);
const items = useCart((s) => s.items);
const removeItem = useCart((s) => s.removeItem);
const setQuantity = useCart((s) => s.setQuantity);
@@ -17,24 +15,8 @@ export default function CartPage() {
useEffect(() => setMounted(true), []);
const handleCheckout = async () => {
setCheckingOut(true);
setCheckoutError(null);
try {
const res = await fetch('/api/checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items }),
});
const data = await res.json();
if (!res.ok || !data.url) {
throw new Error(data.error ?? 'Something went wrong starting checkout.');
}
window.location.href = data.url;
} catch (err) {
setCheckoutError(err instanceof Error ? err.message : 'Something went wrong.');
setCheckingOut(false);
}
const handleCheckout = () => {
window.location.href = '/checkout';
};
if (!mounted) return null; // avoid a hydration mismatch on first paint
@@ -180,16 +162,14 @@ export default function CartPage() {
<div className="w-full max-w-xs">
<div className="mb-4 rounded border border-splash-blue/40 bg-splash-blue/5 px-3 py-2 text-xs text-muted">
Your cart will be saved. You&apos;ll need to log in again to complete your order.
Your cart will be saved. You can log in or continue as a guest to complete your order.
</div>
<button
onClick={handleCheckout}
disabled={checkingOut}
className="w-full bg-clay px-6 py-3 text-sm font-medium text-paper transition-colors hover:bg-clay-dark disabled:opacity-60"
className="w-full bg-clay px-6 py-3 text-sm font-medium text-paper transition-colors hover:bg-clay-dark"
>
{checkingOut ? 'Redirecting to checkout…' : 'Checkout'}
Checkout
</button>
{checkoutError && <p className="mt-2 text-center text-xs text-splash-pink">{checkoutError}</p>}
<p className="mt-2 text-center text-xs text-muted">You&apos;ll enter payment details on the next step.</p>
<p className="mt-1 text-center text-xs text-muted">
By placing an order you agree to our{' '}