hotschpotsh/Pottery-website/pages/Checkout.tsx

151 lines
8.8 KiB
TypeScript

import React, { useState } from 'react';
import { motion } from 'framer-motion';
import { Link, useNavigate } from 'react-router-dom';
import { useStore } from '../src/context/StoreContext';
const Checkout: React.FC = () => {
const { cart } = useStore();
const navigate = useNavigate();
const [formData, setFormData] = useState({
email: '',
firstName: '',
lastName: '',
address: '',
city: '',
postalCode: ''
});
const subtotal = cart.reduce((total, item) => total + (item.price * item.quantity), 0);
const shipping = subtotal > 150 ? 0 : 15;
const total = subtotal + shipping;
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const handleProceed = (e: React.FormEvent) => {
e.preventDefault();
const orderData = {
customer_email: formData.email,
customer_name: `${formData.firstName} ${formData.lastName}`,
shipping_address: {
address: formData.address,
city: formData.city,
postalCode: formData.postalCode
},
items: cart.map(item => ({
id: item.id,
title: item.title,
quantity: item.quantity,
price: item.price
})),
total_amount: total
};
navigate('/mock-payment', { state: { orderData } });
};
if (cart.length === 0) {
return (
<div className="min-h-screen pt-48 flex flex-col items-center justify-center text-text-main dark:text-white px-6">
<h2 className="font-display text-4xl mb-8">Your bag is empty</h2>
<Link to="/collections" className="text-xs uppercase tracking-widest underline underline-offset-8 hover:text-stone-500 transition-colors">
View Collections
</Link>
</div>
);
}
return (
<div className="bg-white dark:bg-stone-950 min-h-screen pt-32 pb-24">
<div className="max-w-[1400px] mx-auto px-6 md:px-12">
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="font-display text-5xl md:text-7xl font-light text-text-main dark:text-white mb-16"
>
Checkout
</motion.h1>
<form onSubmit={handleProceed} className="grid grid-cols-1 lg:grid-cols-12 gap-16 xl:gap-24">
{/* Order Summary Form */}
<div className="lg:col-span-7 space-y-12">
<section>
<h3 className="text-xs uppercase tracking-[0.3em] text-stone-400 mb-8 border-b border-stone-100 dark:border-stone-900 pb-4">Contact Information</h3>
<div className="grid grid-cols-1 gap-6">
<input
required
name="email"
type="email"
placeholder="Email Address"
value={formData.email}
onChange={handleInputChange}
className="w-full bg-stone-50 dark:bg-stone-900 border border-stone-200 dark:border-stone-800 p-4 text-sm focus:outline-none focus:border-stone-400 transition-colors"
/>
</div>
</section>
<section>
<h3 className="text-xs uppercase tracking-[0.3em] text-stone-400 mb-8 border-b border-stone-100 dark:border-stone-900 pb-4">Shipping Address</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<input required name="firstName" type="text" placeholder="First Name" value={formData.firstName} onChange={handleInputChange} className="w-full bg-stone-50 dark:bg-stone-900 border border-stone-200 dark:border-stone-800 p-4 text-sm focus:outline-none focus:border-stone-400" />
<input required name="lastName" type="text" placeholder="Last Name" value={formData.lastName} onChange={handleInputChange} className="w-full bg-stone-50 dark:bg-stone-900 border border-stone-200 dark:border-stone-800 p-4 text-sm focus:outline-none focus:border-stone-400" />
<div className="md:col-span-2">
<input required name="address" type="text" placeholder="Address" value={formData.address} onChange={handleInputChange} className="w-full bg-stone-50 dark:bg-stone-900 border border-stone-200 dark:border-stone-800 p-4 text-sm focus:outline-none focus:border-stone-400" />
</div>
<input required name="city" type="text" placeholder="City" value={formData.city} onChange={handleInputChange} className="w-full bg-stone-50 dark:bg-stone-900 border border-stone-200 dark:border-stone-800 p-4 text-sm focus:outline-none focus:border-stone-400" />
<input required name="postalCode" type="text" placeholder="Postal Code" value={formData.postalCode} onChange={handleInputChange} className="w-full bg-stone-50 dark:bg-stone-900 border border-stone-200 dark:border-stone-800 p-4 text-sm focus:outline-none focus:border-stone-400" />
</div>
</section>
<button type="submit" className="w-full bg-black dark:bg-white text-white dark:text-black py-5 uppercase tracking-[0.3em] text-xs font-bold hover:opacity-90 transition-opacity flex items-center justify-center gap-4 shadow-xl">
Proceed to Payment
<span className="material-symbols-outlined text-sm">arrow_forward</span>
</button>
</div>
{/* Cart Preview Sidebar */}
<div className="lg:col-span-5">
<div className="lg:sticky lg:top-32 bg-stone-50 dark:bg-stone-900/40 p-8 md:p-12 rounded-sm border border-stone-100 dark:border-stone-900">
<h3 className="text-xs uppercase tracking-[0.3em] text-stone-400 mb-8">In your bag</h3>
<div className="space-y-8 mb-12 max-h-96 overflow-y-auto pr-4 custom-scrollbar">
{cart.map((item) => (
<div key={item.id} className="flex gap-6">
<div className="w-20 aspect-[4/5] bg-stone-200 dark:bg-stone-800 flex-shrink-0 overflow-hidden">
<img src={item.image} alt={item.title} className="w-full h-full object-cover" />
</div>
<div className="flex-1 space-y-1">
<h4 className="font-display text-lg text-text-main dark:text-white">{item.title}</h4>
<p className="text-xs text-stone-500 uppercase tracking-widest">Qty: {item.quantity}</p>
<p className="text-sm font-light pt-2">${(item.price * item.quantity).toFixed(2)}</p>
</div>
</div>
))}
</div>
<div className="space-y-4 pt-8 border-t border-stone-200 dark:border-stone-800">
<div className="flex justify-between text-sm">
<span className="text-stone-500 font-light">Subtotal</span>
<span>${subtotal.toFixed(2)}</span>
</div>
<div className="flex justify-between text-sm">
<span className="text-stone-500 font-light">Shipping</span>
<span>{shipping === 0 ? 'Free' : `$${shipping.toFixed(2)}`}</span>
</div>
<div className="flex justify-between text-xl font-display pt-4">
<span>Total</span>
<span className="text-text-main dark:text-white">${total.toFixed(2)}</span>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
);
};
export default Checkout;