Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1fb7758e17 | |||
| 96bff63066 | |||
| b7b936fc38 | |||
| 7687a9b6f9 | |||
| 03c1c55d3a | |||
| 57b6b4b3e0 | |||
| 59fbc4cbff | |||
| 76a45761c1 | |||
| 8eb9436899 |
146
src/app/cart/page.tsx
Normal file
146
src/app/cart/page.tsx
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||||
|
import NavbarLayoutFloatingOverlay from "@/components/navbar/NavbarLayoutFloatingOverlay/NavbarLayoutFloatingOverlay";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { ShoppingCart, Trash2, Minus, Plus } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
interface CartItem {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
price: string;
|
||||||
|
quantity: number;
|
||||||
|
imageSrc: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function CartPage() {
|
||||||
|
const [cartItems, setCartItems] = useState<CartItem[]>([
|
||||||
|
{
|
||||||
|
id: "1", name: "Classic Rainbow Lollipops", price: "$12.99", quantity: 2,
|
||||||
|
imageSrc: "http://img.b2bpic.net/free-photo/valentines-day-postcard-with-red-lollipops-white-background_1268-31406.jpg?_wi=2"},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const handleQuantityChange = (id: string, newQuantity: number) => {
|
||||||
|
if (newQuantity < 1) return;
|
||||||
|
setCartItems(cartItems.map(item =>
|
||||||
|
item.id === id ? { ...item, quantity: newQuantity } : item
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemove = (id: string) => {
|
||||||
|
setCartItems(cartItems.filter(item => item.id !== id));
|
||||||
|
};
|
||||||
|
|
||||||
|
const calculateTotal = () => {
|
||||||
|
return cartItems.reduce((total, item) => {
|
||||||
|
const price = parseFloat(item.price.replace("$", ""));
|
||||||
|
return total + (price * item.quantity);
|
||||||
|
}, 0).toFixed(2);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider
|
||||||
|
defaultButtonVariant="icon-arrow"
|
||||||
|
defaultTextAnimation="background-highlight"
|
||||||
|
borderRadius="pill"
|
||||||
|
contentWidth="smallMedium"
|
||||||
|
sizing="largeSmallSizeLargeTitles"
|
||||||
|
background="circleGradient"
|
||||||
|
cardStyle="gradient-bordered"
|
||||||
|
primaryButtonStyle="diagonal-gradient"
|
||||||
|
secondaryButtonStyle="layered"
|
||||||
|
headingFontWeight="normal"
|
||||||
|
>
|
||||||
|
<div id="nav" data-section="nav">
|
||||||
|
<NavbarLayoutFloatingOverlay
|
||||||
|
brandName="Sweet Baby C's"
|
||||||
|
navItems={[
|
||||||
|
{ name: "Home", id: "/" },
|
||||||
|
{ name: "Our Story", id: "about" },
|
||||||
|
{ name: "Products", id: "products" },
|
||||||
|
{ name: "Reviews", id: "testimonials" },
|
||||||
|
{ name: "FAQ", id: "faq" },
|
||||||
|
]}
|
||||||
|
button={{ text: "Continue Shopping", href: "/" }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="min-h-screen py-20 px-4 md:px-8">
|
||||||
|
<div className="max-w-4xl mx-auto">
|
||||||
|
<div className="flex items-center gap-3 mb-8">
|
||||||
|
<ShoppingCart className="w-8 h-8" />
|
||||||
|
<h1 className="text-4xl font-bold">Shopping Cart</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{cartItems.length === 0 ? (
|
||||||
|
<div className="text-center py-12">
|
||||||
|
<p className="text-xl mb-6">Your cart is empty</p>
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="inline-block px-6 py-3 bg-[var(--primary-cta)] text-[var(--primary-cta-text)] rounded-full font-semibold hover:opacity-90 transition-opacity"
|
||||||
|
>
|
||||||
|
Continue Shopping
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className="space-y-4 mb-8">
|
||||||
|
{cartItems.map((item) => (
|
||||||
|
<div
|
||||||
|
key={item.id}
|
||||||
|
className="flex gap-4 p-4 bg-[var(--card)] rounded-lg border border-[var(--accent)]"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={item.imageSrc}
|
||||||
|
alt={item.name}
|
||||||
|
className="w-24 h-24 object-cover rounded-lg"
|
||||||
|
/>
|
||||||
|
<div className="flex-1">
|
||||||
|
<h3 className="font-semibold mb-2">{item.name}</h3>
|
||||||
|
<p className="text-lg font-bold mb-4">{item.price}</p>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<button
|
||||||
|
onClick={() => handleQuantityChange(item.id, item.quantity - 1)}
|
||||||
|
className="p-1 rounded hover:bg-[var(--background-accent)] transition-colors"
|
||||||
|
aria-label="Decrease quantity"
|
||||||
|
>
|
||||||
|
<Minus className="w-4 h-4" />
|
||||||
|
</button>
|
||||||
|
<span className="w-8 text-center font-semibold">{item.quantity}</span>
|
||||||
|
<button
|
||||||
|
onClick={() => handleQuantityChange(item.id, item.quantity + 1)}
|
||||||
|
className="p-1 rounded hover:bg-[var(--background-accent)] transition-colors"
|
||||||
|
aria-label="Increase quantity"
|
||||||
|
>
|
||||||
|
<Plus className="w-4 h-4" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={() => handleRemove(item.id)}
|
||||||
|
className="p-2 rounded hover:bg-red-100 text-red-600 transition-colors self-start"
|
||||||
|
aria-label="Remove item"
|
||||||
|
>
|
||||||
|
<Trash2 className="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-[var(--card)] rounded-lg p-6 border border-[var(--accent)]">
|
||||||
|
<div className="flex justify-between items-center mb-6">
|
||||||
|
<span className="text-xl font-semibold">Total:</span>
|
||||||
|
<span className="text-3xl font-bold text-[var(--primary-cta)]">${calculateTotal()}</span>
|
||||||
|
</div>
|
||||||
|
<button className="w-full py-3 bg-[var(--primary-cta)] text-[var(--primary-cta-text)] rounded-full font-semibold hover:opacity-90 transition-opacity">
|
||||||
|
Proceed to Checkout
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,58 +1,22 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Lato } from "next/font/google";
|
|
||||||
import { Halant } from "next/font/google";
|
|
||||||
import { Inter } from "next/font/google";
|
import { Inter } from "next/font/google";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import { ServiceWrapper } from "@/components/ServiceWrapper";
|
import "./styles/variables.css";
|
||||||
import Tag from "@/tag/Tag";
|
import "./styles/base.css";
|
||||||
|
|
||||||
const lato = Lato({
|
const inter = Inter({ subsets: ["latin"] });
|
||||||
variable: "--font-lato", subsets: ["latin"],
|
|
||||||
weight: ["100", "300", "400", "700", "900"],
|
|
||||||
});
|
|
||||||
|
|
||||||
const halant = Halant({
|
|
||||||
variable: "--font-halant", subsets: ["latin"],
|
|
||||||
weight: ["300", "400", "500", "600", "700"],
|
|
||||||
});
|
|
||||||
|
|
||||||
const inter = Inter({
|
|
||||||
variable: "--font-inter", subsets: ["latin"],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Sweet Baby C's - Premium Lollipops & Popsicles", description: "Discover extra sweet, always lickable premium lollipops and popsicles made with natural ingredients. Shop handcrafted candies at Sweet Baby C's today.", keywords: "lollipops, popsicles, premium candy, gourmet sweets, artisan confectionery", metadataBase: new URL("https://sweetbabycs.com"),
|
title: "Sweet Baby C's - Premium Lollipops & Popsicles", description: "Discover handcrafted premium lollipops and popsicles made with natural ingredients."};
|
||||||
alternates: {
|
|
||||||
canonical: "https://sweetbabycs.com"},
|
|
||||||
openGraph: {
|
|
||||||
title: "Sweet Baby C's - Premium Lollipops & Popsicles", description: "Extra sweet, always lickable. Premium handcrafted treats made with natural ingredients.", url: "https://sweetbabycs.com", siteName: "Sweet Baby C's", type: "website", images: [
|
|
||||||
{
|
|
||||||
url: "http://img.b2bpic.net/free-photo/close-up-candycane-lollipop-colorful-sweets-background_53876-31923.jpg", alt: "Sweet Baby C's lollipops and popsicles"},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
twitter: {
|
|
||||||
card: "summary_large_image", title: "Sweet Baby C's - Premium Lollipops & Popsicles", description: "Extra sweet, always lickable. Premium handcrafted treats.", images: ["http://img.b2bpic.net/free-photo/close-up-candycane-lollipop-colorful-sweets-background_53876-31923.jpg"],
|
|
||||||
},
|
|
||||||
robots: {
|
|
||||||
index: true,
|
|
||||||
follow: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" suppressHydrationWarning>
|
<html lang="en">
|
||||||
<ServiceWrapper>
|
<body className={inter.className}>{children}
|
||||||
<body
|
|
||||||
className={`${lato.variable} ${halant.variable} ${inter.variable} antialiased`}
|
|
||||||
>
|
|
||||||
<Tag />
|
|
||||||
{children}
|
|
||||||
|
|
||||||
<script
|
<script
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: `
|
__html: `
|
||||||
@@ -1420,7 +1384,6 @@ export default function RootLayout({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</body>
|
</body>
|
||||||
</ServiceWrapper>
|
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import SocialProofOne from "@/components/sections/socialProof/SocialProofOne";
|
|||||||
import TestimonialCardFive from "@/components/sections/testimonial/TestimonialCardFive";
|
import TestimonialCardFive from "@/components/sections/testimonial/TestimonialCardFive";
|
||||||
import FaqDouble from "@/components/sections/faq/FaqDouble";
|
import FaqDouble from "@/components/sections/faq/FaqDouble";
|
||||||
import FooterLogoEmphasis from "@/components/sections/footer/FooterLogoEmphasis";
|
import FooterLogoEmphasis from "@/components/sections/footer/FooterLogoEmphasis";
|
||||||
import { Sparkles, Heart, Zap, Users, Star, HelpCircle } from "lucide-react";
|
import { Sparkles, Heart, Zap, Users, Star, HelpCircle, ShoppingCart } from "lucide-react";
|
||||||
|
|
||||||
export default function LandingPage() {
|
export default function LandingPage() {
|
||||||
return (
|
return (
|
||||||
@@ -35,7 +35,7 @@ export default function LandingPage() {
|
|||||||
{ name: "Reviews", id: "testimonials" },
|
{ name: "Reviews", id: "testimonials" },
|
||||||
{ name: "FAQ", id: "faq" },
|
{ name: "FAQ", id: "faq" },
|
||||||
]}
|
]}
|
||||||
button={{ text: "Order Now", href: "#products" }}
|
button={{ text: "Shop Now", href: "#products" }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -98,17 +98,17 @@ export default function LandingPage() {
|
|||||||
tagAnimation="slide-up"
|
tagAnimation="slide-up"
|
||||||
products={[
|
products={[
|
||||||
{
|
{
|
||||||
id: "1", name: "Classic Rainbow Lollipops", price: "$12.99", imageSrc: "http://img.b2bpic.net/free-photo/valentines-day-postcard-with-red-lollipops-white-background_1268-31406.jpg", imageAlt: "Classic rainbow lollipop", initialQuantity: 1,
|
id: "1", name: "Classic Rainbow Lollipops", price: "$12.99", imageSrc: "http://img.b2bpic.net/free-photo/valentines-day-postcard-with-red-lollipops-white-background_1268-31406.jpg?_wi=1", imageAlt: "Classic rainbow lollipop", initialQuantity: 1,
|
||||||
},
|
onProductClick: () => window.location.href = "/cart"},
|
||||||
{
|
{
|
||||||
id: "2", name: "Tropical Popsicles Mix", price: "$14.99", imageSrc: "http://img.b2bpic.net/free-vector/realistic-summer-background_23-2148965901.jpg", imageAlt: "Tropical popsicle collection", initialQuantity: 1,
|
id: "2", name: "Tropical Popsicles Mix", price: "$14.99", imageSrc: "http://img.b2bpic.net/free-vector/realistic-summer-background_23-2148965901.jpg", imageAlt: "Tropical popsicle collection", initialQuantity: 1,
|
||||||
},
|
onProductClick: () => window.location.href = "/cart"},
|
||||||
{
|
{
|
||||||
id: "3", name: "Berry Burst Lollipops", price: "$13.99", imageSrc: "http://img.b2bpic.net/free-photo/top-view-colored-icicle-with-marmalade-form-raspberries-blackberries-blue-background_141793-11426.jpg", imageAlt: "Berry flavored lollipops", initialQuantity: 1,
|
id: "3", name: "Berry Burst Lollipops", price: "$13.99", imageSrc: "http://img.b2bpic.net/free-photo/top-view-colored-icicle-with-marmalade-form-raspberries-blackberries-blue-background_141793-11426.jpg", imageAlt: "Berry flavored lollipops", initialQuantity: 1,
|
||||||
},
|
onProductClick: () => window.location.href = "/cart"},
|
||||||
{
|
{
|
||||||
id: "4", name: "Citrus Sunshine Popsicles", price: "$15.99", imageSrc: "http://img.b2bpic.net/free-photo/top-view-yummy-popsicles-with-mint-orange_23-2148763611.jpg", imageAlt: "Citrus popsicle assortment", initialQuantity: 1,
|
id: "4", name: "Citrus Sunshine Popsicles", price: "$15.99", imageSrc: "http://img.b2bpic.net/free-photo/top-view-yummy-popsicles-with-mint-orange_23-2148763611.jpg", imageAlt: "Citrus popsicle assortment", initialQuantity: 1,
|
||||||
},
|
onProductClick: () => window.location.href = "/cart"},
|
||||||
]}
|
]}
|
||||||
gridVariant="four-items-2x2-equal-grid"
|
gridVariant="four-items-2x2-equal-grid"
|
||||||
animationType="slide-up"
|
animationType="slide-up"
|
||||||
|
|||||||
Reference in New Issue
Block a user