Add src/app/checkout/page.tsx
This commit is contained in:
305
src/app/checkout/page.tsx
Normal file
305
src/app/checkout/page.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user