Add src/app/checkout/page.tsx

This commit is contained in:
2026-03-25 07:23:53 +00:00
parent 348f55c5ba
commit 484bffd95d

305
src/app/checkout/page.tsx Normal file
View File

@@ -0,0 +1,305 @@
"use client";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import ReactLenis from "lenis/react";
import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered';
import FooterBaseReveal from '@/components/sections/footer/FooterBaseReveal';
import Input from '@/components/form/Input';
import ButtonHoverBubble from '@/components/button/ButtonHoverBubble';
import { useState } from "react";
export default function CheckoutPage() {
const [shippingInfo, setShippingInfo] = useState({
fullName: "", address: "", city: "", state: "", zipCode: "", country: ""
});
const [paymentInfo, setPaymentInfo] = useState({
cardNumber: "", cardName: "", expiryDate: "", cvv: ""
});
const [orderConfirmed, setOrderConfirmed] = useState(false);
const handleShippingChange = (field: string, value: string) => {
setShippingInfo((prev) => ({ ...prev, [field]: value }));
};
const handlePaymentChange = (field: string, value: string) => {
setPaymentInfo((prev) => ({ ...prev, [field]: value }));
};
const handlePlaceOrder = async (e: React.FormEvent) => {
e.preventDefault();
// Simulate API call for order placement
console.log("Placing order with:", shippingInfo, paymentInfo);
// In a real app, you'd send this to an API endpoint
const response = await fetch('/api/checkout', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ shippingInfo, paymentInfo, items: [] }) // Add actual cart items
});
if (response.ok) {
setOrderConfirmed(true);
console.log("Order placed successfully!");
// Optionally clear cart or redirect
} else {
console.error("Order failed:", await response.json());
alert("Order placement failed. Please try again.");
}
};
// Dummy order summary data
const orderItems = [
{ id: "prod-1", name: "Luxury Velocity Runner", price: 12500, quantity: 1 },
{ id: "prod-4", name: "Aura X Wireless Earbuds", price: 8999, quantity: 1 }
];
const subtotal = orderItems.reduce((sum, item) => sum + item.price * item.quantity, 0);
const shippingCost = 500; // Example
const total = subtotal + shippingCost;
if (orderConfirmed) {
return (
<ThemeProvider
defaultButtonVariant="shift-hover"
defaultTextAnimation="reveal-blur"
borderRadius="rounded"
contentWidth="small"
sizing="mediumSizeLargeTitles"
background="blurBottom"
cardStyle="inset"
primaryButtonStyle="double-inset"
secondaryButtonStyle="layered"
headingFontWeight="medium"
>
<ReactLenis root>
<div id="nav" data-section="nav">
<NavbarStyleCentered
navItems={[
{ name: "Home", id: "/" },
{ name: "Shop", id: "/shop" },
{ name: "Categories", id: "/categories" },
{ name: "Wishlist", id: "/wishlist" },
{ name: "About", id: "/about" },
{ name: "Contact", id: "/contact" },
{ name: "Checkout", id: "/checkout" }
]}
button={{ text: "Admin Login", href: "/admin" }}
brandName="SHOEMOB"
/>
</div>
<main className="min-h-screen py-20 flex flex-col items-center justify-center text-center">
<h1 className="text-4xl font-bold mb-4">Order Confirmed!</h1>
<p className="text-xl mb-8">Thank you for your purchase. Your order has been successfully placed.</p>
<ButtonHoverBubble text="Continue Shopping" href="/shop" />
</main>
<div id="footer" data-section="footer">
<FooterBaseReveal
columns={[
{
title: "Shop", items: [
{ label: "Luxury Sneakers", href: "/shop?category=luxury-sneakers" }
]
}
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
);
}
return (
<ThemeProvider
defaultButtonVariant="shift-hover"
defaultTextAnimation="reveal-blur"
borderRadius="rounded"
contentWidth="small"
sizing="mediumSizeLargeTitles"
background="blurBottom"
cardStyle="inset"
primaryButtonStyle="double-inset"
secondaryButtonStyle="layered"
headingFontWeight="medium"
>
<ReactLenis root>
<div id="nav" data-section="nav">
<NavbarStyleCentered
navItems={[
{ name: "Home", id: "/" },
{ name: "Shop", id: "/shop" },
{ name: "Categories", id: "/categories" },
{ name: "Wishlist", id: "/wishlist" },
{ name: "About", id: "/about" },
{ name: "Contact", id: "/contact" },
{ name: "Checkout", id: "/checkout" } // Added checkout link
]}
button={{ text: "Admin Login", href: "/admin" }}
brandName="SHOEMOB"
/>
</div>
<main className="min-h-screen py-20 px-4 sm:px-6 lg:px-8">
<div className="max-w-4xl mx-auto">
<h1 className="text-4xl font-bold text-center mb-12">Checkout</h1>
<form onSubmit={handlePlaceOrder} className="grid md:grid-cols-2 gap-12">
{/* Shipping Information */}
<div className="bg-card p-8 rounded-lg shadow-lg">
<h2 className="text-2xl font-semibold mb-6">Shipping Information</h2>
<div className="grid grid-cols-1 gap-4">
<Input
value={shippingInfo.fullName}
onChange={(val) => handleShippingChange("fullName", val)}
placeholder="Full Name"
required
ariaLabel="Full Name"
/>
<Input
value={shippingInfo.address}
onChange={(val) => handleShippingChange("address", val)}
placeholder="Address"
required
ariaLabel="Address"
/>
<div className="grid grid-cols-2 gap-4">
<Input
value={shippingInfo.city}
onChange={(val) => handleShippingChange("city", val)}
placeholder="City"
required
ariaLabel="City"
/>
<Input
value={shippingInfo.state}
onChange={(val) => handleShippingChange("state", val)}
placeholder="State/Province"
required
ariaLabel="State/Province"
/>
</div>
<div className="grid grid-cols-2 gap-4">
<Input
value={shippingInfo.zipCode}
onChange={(val) => handleShippingChange("zipCode", val)}
placeholder="Zip Code"
required
ariaLabel="Zip Code"
/>
<Input
value={shippingInfo.country}
onChange={(val) => handleShippingChange("country", val)}
placeholder="Country"
required
ariaLabel="Country"
/>
</div>
</div>
</div>
{/* Order Summary & Payment */}
<div className="flex flex-col gap-12">
{/* Order Summary */}
<div className="bg-card p-8 rounded-lg shadow-lg">
<h2 className="text-2xl font-semibold mb-6">Order Summary</h2>
<div className="space-y-4">
{orderItems.map((item) => (
<div key={item.id} className="flex justify-between items-center text-foreground">
<span>{item.name} (x{item.quantity})</span>
<span>{(item.price * item.quantity).toLocaleString()}</span>
</div>
))}
<div className="pt-4 border-t border-accent/20">
<div className="flex justify-between text-foreground">
<span>Subtotal</span>
<span>{subtotal.toLocaleString()}</span>
</div>
<div className="flex justify-between text-foreground">
<span>Shipping</span>
<span>{shippingCost.toLocaleString()}</span>
</div>
<div className="flex justify-between font-bold text-xl mt-4 text-primary-cta">
<span>Total</span>
<span>{total.toLocaleString()}</span>
</div>
</div>
</div>
</div>
{/* Payment Information */}
<div className="bg-card p-8 rounded-lg shadow-lg">
<h2 className="text-2xl font-semibold mb-6">Payment Information</h2>
<div className="grid grid-cols-1 gap-4">
<Input
value={paymentInfo.cardName}
onChange={(val) => handlePaymentChange("cardName", val)}
placeholder="Name on Card"
required
ariaLabel="Name on Card"
/>
<Input
value={paymentInfo.cardNumber}
onChange={(val) => handlePaymentChange("cardNumber", val)}
placeholder="Card Number"
type="text"
inputMode="numeric"
pattern="[0-9]{13,16}" // Basic card number pattern
required
ariaLabel="Card Number"
/>
<div className="grid grid-cols-2 gap-4">
<Input
value={paymentInfo.expiryDate}
onChange={(val) => handlePaymentChange("expiryDate", val)}
placeholder="MM/YY"
type="text"
pattern="(0[1-9]|1[0-2])\/?([0-9]{2})" // MM/YY pattern
required
ariaLabel="Expiry Date"
/>
<Input
value={paymentInfo.cvv}
onChange={(val) => handlePaymentChange("cvv", val)}
placeholder="CVV"
type="text"
pattern="[0-9]{3,4}" // CVV pattern
required
ariaLabel="CVV"
/>
</div>
</div>
</div>
{/* Place Order Button */}
<div className="text-center">
<ButtonHoverBubble
text="Place Order"
type="submit"
className="w-full"
/>
</div>
</div>
</form>
</div>
</main>
<div id="footer" data-section="footer">
<FooterBaseReveal
columns={[
{
title: "Shop", items: [
{ label: "Luxury Sneakers", href: "/shop?category=luxury-sneakers" }
]
}
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
);
}