Merge version_1 into main #1

Merged
bender merged 5 commits from version_1 into main 2026-02-23 15:11:08 +00:00
5 changed files with 240 additions and 470 deletions

View File

@@ -7,59 +7,47 @@ import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import { useBlogPosts } from "@/hooks/useBlogPosts";
export default function BlogPage() {
const { posts, isLoading } = useBlogPosts();
const { posts, isLoading } = useBlogPosts();
const navItems = [
{ name: "Home", id: "/" },
{ name: "Blog", id: "/blog" },
{ name: "Shop", id: "/shop" },
];
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="background-highlight"
borderRadius="pill"
contentWidth="medium"
sizing="mediumLargeSizeLargeTitles"
background="grid"
cardStyle="gradient-mesh"
primaryButtonStyle="double-inset"
secondaryButtonStyle="layered"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="nav" data-section="nav">
<NavbarStyleFullscreen
navItems={[
{ name: "Home", id: "/" },
{ name: "Hero", id: "hero-section" },
{ name: "About", id: "about-section" },
{ name: "Feature", id: "features-section" },
{ name: "Product", id: "products-section" },
{ name: "Testimonial", id: "testimonials-section" },
{ name: "Faq", id: "faq-section" },
{ name: "Contact", id: "contact-section" }
]}
brandName="Warm Stone Bakery"
bottomLeftText="Global Community"
bottomRightText="hello@warmstonebakery.com"
topBarClassName=""
/>
</div>
{isLoading ? (
<div className="w-content-width mx-auto py-20 text-center">
<p className="text-foreground">Loading posts...</p>
</div>
) : (
<div id="blog" data-section="blog">
<BlogCardOne
blogs={posts}
title="Latest Articles"
description="Stay updated with our latest insights"
textboxLayout="default"
useInvertedBackground={false}
carouselMode="buttons"
animationType="slide-up"
/>
</div>
)}
</ReactLenis>
</ThemeProvider>
);
}
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="entrance-slide"
borderRadius="rounded"
contentWidth="medium"
sizing="medium"
background="circleGradient"
cardStyle="glass-elevated"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="normal"
>
<ReactLenis root>
<div id="nav" data-section="nav">
<NavbarStyleFullscreen navItems={navItems} />
</div>
<div className="min-h-screen bg-gray-50 py-12 px-4">
<div className="max-w-7xl mx-auto">
<h1 className="text-4xl font-bold text-gray-900 mb-8">Our Blog</h1>
{isLoading ? (
<div className="text-center text-gray-600">Loading blog posts...</div>
) : posts && posts.length > 0 ? (
<BlogCardOne
posts={posts}
title="Latest Articles"
description="Discover insights and stories from our artisanal bakery"
/>
) : (
<div className="text-center text-gray-600">No blog posts available yet.</div>
)}
</div>
</div>
</ReactLenis>
</ThemeProvider>
);
}

View File

@@ -9,23 +9,23 @@ const outfit = Outfit({
});
export const metadata: Metadata = {
title: "Artisan Bakery | Fresh Baked Goods Made with Love", description: "Discover handcrafted pastries and breads made with passion and traditional techniques. Experience the warmth of our artisanal bakery in the heart of the community.", keywords: ["artisan bakery", "handcrafted pastries", "fresh bread", "local bakery", "traditional baking"],
title: "Artisan Bakery | Fresh Baked Goods Made with Love", description: "Discover handcrafted pastries and breads made with passion and traditional techniques. Experience the warmth of our cozy bakery.", keywords: "artisan bakery, fresh baked goods, pastries, sourdough, handcrafted bread", openGraph: {
title: "Artisan Bakery | Fresh Baked Goods Made with Love", description: "Discover handcrafted pastries and breads made with passion and traditional techniques.", type: "website"},
};
export default function RootLayout({
children,
}: Readonly<{
}: {
children: React.ReactNode;
}>) {
}) {
return (
<html lang="en" suppressHydrationWarning>
<ServiceWrapper>
<body
className={`${outfit.variable} antialiased`}
>
<html lang="en" className={outfit.variable}>
<body className="bg-white text-gray-900">
<ServiceWrapper>
<Tag />
{children}
</ServiceWrapper>
<script
dangerouslySetInnerHTML={{
__html: `
@@ -1393,7 +1393,6 @@ export default function RootLayout({
}}
/>
</body>
</ServiceWrapper>
</html>
);
}
}

View File

@@ -1,53 +1,40 @@
"use client";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarStyleFullscreen from '@/components/navbar/NavbarStyleFullscreen/NavbarStyleFullscreen';
import HeroOverlay from '@/components/sections/hero/HeroOverlay';
import MediaAbout from '@/components/sections/about/MediaAbout';
import FeatureCardMedia from '@/components/sections/feature/FeatureCardMedia';
import ProductCardOne from '@/components/sections/product/ProductCardOne';
import TestimonialCardOne from '@/components/sections/testimonial/TestimonialCardOne';
import FaqBase from '@/components/sections/faq/FaqBase';
import ContactSplitForm from '@/components/sections/contact/ContactSplitForm';
import FooterMedia from '@/components/sections/footer/FooterMedia';
import { Sparkles, Clock, Star } from 'lucide-react';
import NavbarStyleFullscreen from "@/components/navbar/NavbarStyleFullscreen/NavbarStyleFullscreen";
import HeroOverlay from "@/components/sections/hero/HeroOverlay";
import MediaAbout from "@/components/sections/about/MediaAbout";
import FeatureCardMedia from "@/components/sections/feature/FeatureCardMedia";
import ProductCardOne from "@/components/sections/product/ProductCardOne";
import TestimonialCardOne from "@/components/sections/testimonial/TestimonialCardOne";
import FaqBase from "@/components/sections/faq/FaqBase";
import ContactSplitForm from "@/components/sections/contact/ContactSplitForm";
import FooterMedia from "@/components/sections/footer/FooterMedia";
import { Sparkles, Clock, Star } from "lucide-react";
const assetMap: { [key: string]: string } = {
"hero-section-backgroundImage": "https://img.b2bpic.net/free-photo/front-view-delicious-thanksgiving-meal_23-2148629567.jpg", "about-section-imageSrc": "https://img.b2bpic.net/free-photo/female-glazing-dough-with-mum-wooden-table-top-view_176474-5458.jpg", "features-section-localIngredients": "https://img.b2bpic.net/free-photo/organic-foods-fresh-organic-food-local-farmers-market-farmers-markets-are-traditional-way-selling-agricultural-products_1391-373.jpg", "features-section-traditionalTechniques": "https://img.b2bpic.net/free-photo/painting-inspiration-supplies-placed-ready-be-painted-canvas_482257-115978.jpg", "features-section-dailyFreshness": "https://img.b2bpic.net/free-photo/cup-milky-cappuccino-with-cookie-blue-table_114579-4248.jpg", "products-section-croissant": "https://img.b2bpic.net/free-photo/wooden-cutting-board-with-powdered-cacao-cookie_114579-52662.jpg", "products-section-sourdough": "https://img.b2bpic.net/free-photo/close-up-fresh-bread-wooden-board_23-2148613571.jpg", "products-section-chocolateChip": "https://img.b2bpic.net/free-photo/plate-with-fresh-cookies-from-oven_23-2148837150.jpg", "products-section-blueberryMuffin": "https://img.b2bpic.net/free-photo/muffins-with-black-currant_661915-152.jpg", "testimonials-section-testimonial1-image": "https://img.b2bpic.net/free-photo/beautiful-girls-buys-buns-bakery_1157-24661.jpg", "testimonials-section-testimonial2-image": "https://img.b2bpic.net/free-photo/high-angle-parents-teaching-girl-cook_23-2148542888.jpg", "testimonials-section-testimonial3-image": "https://img.b2bpic.net/free-photo/tea-time-cafe_1098-14163.jpg", "testimonials-section-testimonial4-image": "https://img.b2bpic.net/free-photo/smiling-girl-with-curly-hair-listening-music-sitting-restaurant_651396-865.jpg", "contact-section-imageSrc": "https://img.b2bpic.net/free-photo/welcome-open-sign-hanging_23-2149168995.jpg", "footer-section-backgroundImage": "https://img.b2bpic.net/free-photo/bakery-atmospheric-photo_1321-4640.jpg"};
export default function Home() {
const navItems = [
{ name: "Home", id: "/" },
{ name: "Blog", id: "/blog" },
{ name: "Shop", id: "/shop" },
];
function getAssetUrl(id: string): string {
return assetMap[id] || "/placeholders/placeholder1.webp";
}
export default function LandingPage() {
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="background-highlight"
borderRadius="pill"
defaultTextAnimation="entrance-slide"
borderRadius="rounded"
contentWidth="medium"
sizing="mediumLargeSizeLargeTitles"
background="grid"
cardStyle="gradient-mesh"
primaryButtonStyle="double-inset"
secondaryButtonStyle="layered"
headingFontWeight="bold"
sizing="medium"
background="circleGradient"
cardStyle="glass-elevated"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="normal"
>
<NavbarStyleFullscreen
navItems={[
{ name: "Hero", id: "hero-section" },
{ name: "About", id: "about-section" },
{ name: "Feature", id: "features-section" },
{ name: "Product", id: "products-section" },
{ name: "Testimonial", id: "testimonials-section" },
{ name: "Faq", id: "faq-section" },
{ name: "Contact", id: "contact-section" }
]}
brandName="Warm Stone Bakery"
bottomLeftText="Global Community"
bottomRightText="hello@warmstonebakery.com"
topBarClassName=""
/>
<div id="nav" data-section="nav">
<NavbarStyleFullscreen navItems={navItems} />
</div>
<div id="hero-section" data-section="hero-section">
<HeroOverlay
@@ -58,11 +45,11 @@ export default function LandingPage() {
tagAnimation="slide-up"
buttons={[
{ text: "View Our Menu", href: "#products-section" },
{ text: "Visit Us", href: "#contact-section" }
{ text: "Visit Us", href: "#contact-section" },
]}
buttonAnimation="blur-reveal"
imageSrc={getAssetUrl("hero-section-backgroundImage")}
imageAlt="Cozy bakery interior with fresh pastries on display"
imageSrc="https://img.b2bpic.net/free-photo/front-view-delicious-thanksgiving-meal_23-2148629567.jpg"
imageAlt="bakery interior warm lighting fresh bread cozy atmosphere"
textPosition="bottom-left"
showDimOverlay={true}
showBlur={true}
@@ -79,11 +66,11 @@ export default function LandingPage() {
tagAnimation="slide-up"
buttons={[
{ text: "Explore Our Products", href: "#products-section" },
{ text: "Visit Our Bakery", href: "#contact-section" }
{ text: "Visit Our Bakery", href: "#contact-section" },
]}
buttonAnimation="blur-reveal"
imageSrc={getAssetUrl("about-section-imageSrc")}
imageAlt="Artisan bakers working in our cozy bakery kitchen with fresh bread and pastries"
imageSrc="https://img.b2bpic.net/free-photo/female-glazing-dough-with-mum-wooden-table-top-view_176474-5458.jpg"
imageAlt="baker kneading dough rustic kitchen artisan baking wooden surfaces"
useInvertedBackground={true}
ariaLabel="About our bakery section"
/>
@@ -98,17 +85,11 @@ export default function LandingPage() {
useInvertedBackground={true}
features={[
{
id: "feature-1", title: "Locally Sourced Ingredients", description: "We partner with local farms and suppliers to bring you the freshest, highest-quality ingredients for our baked goods.", tag: "Fresh & Local", imageSrc: getAssetUrl("features-section-localIngredients"),
imageAlt: "Farmers market produce and fresh ingredients"
},
id: "feature-1", title: "Locally Sourced Ingredients", description: "We partner with local farms and suppliers to bring you the freshest, highest-quality ingredients for our baked goods.", tag: "Fresh & Local", imageSrc: "https://img.b2bpic.net/free-photo/organic-foods-fresh-organic-food-local-farmers-market-farmers-markets-are-traditional-way-selling-agricultural-products_1391-373.jpg", imageAlt: "farmers market local ingredients fresh produce organic foods"},
{
id: "feature-2", title: "Traditional Techniques", description: "Our bakers use time-tested methods passed down through generations to create authentic flavors and textures.", tag: "Time-Honored", imageSrc: getAssetUrl("features-section-traditionalTechniques"),
imageAlt: "Baker kneading dough with traditional tools"
},
id: "feature-2", title: "Traditional Techniques", description: "Our bakers use time-tested methods passed down through generations to create authentic flavors and textures.", tag: "Time-Honored", imageSrc: "https://img.b2bpic.net/free-photo/painting-inspiration-supplies-placed-ready-be-painted-canvas_482257-115978.jpg", imageAlt: "traditional baking wooden rolling pin clay pot artisan techniques"},
{
id: "feature-3", title: "Daily Freshness", description: "Each item is baked fresh daily, ensuring peak flavor and quality when you enjoy it at home or in our cozy shop.", tag: "Made Fresh Daily", imageSrc: getAssetUrl("features-section-dailyFreshness"),
imageAlt: "Freshly baked bread and pastries displayed"
}
id: "feature-3", title: "Daily Freshness", description: "Each item is baked fresh daily, ensuring peak flavor and quality when you enjoy it at home or in our cozy shop.", tag: "Made Fresh Daily", imageSrc: "https://img.b2bpic.net/free-photo/cup-milky-cappuccino-with-cookie-blue-table_114579-4248.jpg", imageAlt: "fresh baked goods croissants rustic tray daily freshness"},
]}
/>
</div>
@@ -120,24 +101,16 @@ export default function LandingPage() {
gridVariant="bento-grid"
animationType="slide-up"
textboxLayout="default"
useInvertedBackground={false}
useInvertedBackground={true}
products={[
{
id: "croissant", name: "Butter Croissant", price: "$3.50", imageSrc: getAssetUrl("products-section-croissant"),
imageAlt: "Delicious butter croissant with golden layers"
},
id: "croissant", name: "Butter Croissant", price: "$3.50", imageSrc: "https://img.b2bpic.net/free-photo/wooden-cutting-board-with-powdered-cacao-cookie_114579-52662.jpg", imageAlt: "croissant buttery pastry flaky layers wooden surface"},
{
id: "sourdough", name: "Sourdough Bread", price: "$5.00", imageSrc: getAssetUrl("products-section-sourdough"),
imageAlt: "Freshly baked sourdough loaf with rustic crust"
},
id: "sourdough", name: "Sourdough Bread", price: "$5.00", imageSrc: "https://img.b2bpic.net/free-photo/close-up-fresh-bread-wooden-board_23-2148613571.jpg", imageAlt: "sourdough bread artisan bread crusty exterior soft interior"},
{
id: "chocolate-chip", name: "Chocolate Chip Cookie", price: "$2.50", imageSrc: getAssetUrl("products-section-chocolateChip"),
imageAlt: "Warm chocolate chip cookie with gooey center"
},
id: "chocolate-chip", name: "Chocolate Chip Cookie", price: "$2.50", imageSrc: "https://img.b2bpic.net/free-photo/plate-with-fresh-cookies-from-oven_23-2148837150.jpg", imageAlt: "chocolate chip cookies warm baked goods wooden board homemade treats"},
{
id: "blueberry-muffin", name: "Blueberry Muffin", price: "$3.00", imageSrc: getAssetUrl("products-section-blueberryMuffin"),
imageAlt: "Soft blueberry muffin with fresh berries on top"
}
id: "blueberry-muffin", name: "Blueberry Muffin", price: "$3.00", imageSrc: "https://img.b2bpic.net/free-photo/muffins-with-black-currant_661915-152.jpg", imageAlt: "blueberry muffins fresh baked goods ceramic plate fruit muffins"},
]}
/>
</div>
@@ -147,24 +120,16 @@ export default function LandingPage() {
testimonials={[
{
id: "testimonial-1", name: "Sarah Johnson", role: "Local Food Blogger", company: "Bite & Sip", rating: 5,
imageSrc: getAssetUrl("testimonials-section-testimonial1-image"),
imageAlt: "Sarah Johnson, local food blogger, enjoying a fresh croissant"
},
imageSrc: "https://img.b2bpic.net/free-photo/beautiful-girls-buys-buns-bakery_1157-24661.jpg", imageAlt: "customer enjoying pastry cozy bakery happy customer fresh baked goods"},
{
id: "testimonial-2", name: "Michael Torres", role: "Community Chef", company: "Urban Kitchen", rating: 5,
imageSrc: getAssetUrl("testimonials-section-testimonial2-image"),
imageAlt: "Michael Torres, community chef, savoring a slice of homemade sourdough"
},
imageSrc: "https://img.b2bpic.net/free-photo/high-angle-parents-teaching-girl-cook_23-2148542888.jpg", imageAlt: "family bakery visit children with pastries local community happy family"},
{
id: "testimonial-3", name: "Emma Richardson", role: "Artisan Bread Enthusiast", company: "The Bread Collective", rating: 5,
imageSrc: getAssetUrl("testimonials-section-testimonial3-image"),
imageAlt: "Emma Richardson, artisan bread enthusiast, holding a warm baguette"
},
imageSrc: "https://img.b2bpic.net/free-photo/tea-time-cafe_1098-14163.jpg", imageAlt: "elderly customer warm croissant cozy seating retired customer"},
{
id: "testimonial-4", name: "David Chen", role: "Local Business Owner", company: "Cozy Corner Café", rating: 5,
imageSrc: getAssetUrl("testimonials-section-testimonial4-image"),
imageAlt: "David Chen, local business owner, sharing a pastry with his family"
}
imageSrc: "https://img.b2bpic.net/free-photo/smiling-girl-with-curly-hair-listening-music-sitting-restaurant_651396-865.jpg", imageAlt: "young professional coffee and pastry rustic table workplace cafe"},
]}
gridVariant="uniform-all-items-equal"
animationType="slide-up"
@@ -173,9 +138,7 @@ export default function LandingPage() {
tag="Customer Favorites"
tagIcon={Star}
tagAnimation="blur-reveal"
buttons={[
{ text: "View All Reviews", href: "#" }
]}
buttons={[{ text: "View All Reviews", href: "#" }]}
buttonAnimation="opacity"
textboxLayout="default"
useInvertedBackground={true}
@@ -188,20 +151,15 @@ export default function LandingPage() {
description="Find answers to common questions about our artisanal baked goods, ordering process, and bakery experience."
faqs={[
{
id: "faq-1", title: "What makes your baked goods special?", content: "Our baked goods are crafted using traditional methods and high-quality ingredients sourced from local farms. Each item is made fresh daily with care and attention to detail."
},
id: "faq-1", title: "What makes your baked goods special?", content: "Our baked goods are crafted using traditional methods and high-quality ingredients sourced from local farms. Each item is made fresh daily with care and attention to detail."},
{
id: "faq-2", title: "How do I place an order?", content: "You can place orders online through our website or by calling us directly. We also offer custom orders for special occasions and events."
},
id: "faq-2", title: "How do I place an order?", content: "You can place orders online through our website or by calling us directly. We also offer custom orders for special occasions and events."},
{
id: "faq-3", title: "Do you offer gluten-free options?", content: "Yes, we have a selection of gluten-free breads and pastries available. Please inform us of any allergies when placing your order."
},
id: "faq-3", title: "Do you offer gluten-free options?", content: "Yes, we have a selection of gluten-free breads and pastries available. Please inform us of any allergies when placing your order."},
{
id: "faq-4", title: "What are your hours of operation?", content: "We're open Tuesday through Sunday from 7:00 AM to 6:00 PM. Closed on Mondays for fresh ingredient preparation."
},
id: "faq-4", title: "What are your hours of operation?", content: "We're open Tuesday through Sunday from 7:00 AM to 6:00 PM. Closed on Mondays for fresh ingredient preparation."},
{
id: "faq-5", title: "Can I customize my order?", content: "Absolutely! We love creating custom cakes, pastries, and breads for birthdays, weddings, and corporate events. Contact us for more details."
}
id: "faq-5", title: "Can I customize my order?", content: "Absolutely! We love creating custom cakes, pastries, and breads for birthdays, weddings, and corporate events. Contact us for more details."},
]}
faqsAnimation="slide-up"
textboxLayout="inline-image"
@@ -211,7 +169,7 @@ export default function LandingPage() {
tagAnimation="slide-up"
buttons={[
{ text: "View All Products", href: "#products-section" },
{ text: "Contact Us", href: "#contact-section" }
{ text: "Contact Us", href: "#contact-section" },
]}
buttonAnimation="slide-up"
/>
@@ -224,61 +182,48 @@ export default function LandingPage() {
inputs={[
{ name: "name", type: "text", placeholder: "Your Name", required: true },
{ name: "email", type: "email", placeholder: "Your Email", required: true },
{ name: "phone", type: "tel", placeholder: "Your Phone Number" }
{ name: "phone", type: "tel", placeholder: "Your Phone Number" },
]}
textarea={{
name: "message", placeholder: "Your Message", rows: 4,
required: true
}}
textarea={{ name: "message", placeholder: "Your Message", rows: 4, required: true }}
useInvertedBackground={true}
imageSrc={getAssetUrl("contact-section-imageSrc")}
imageAlt="Cozy bakery interior with warm lighting and fresh pastries displayed on wooden shelves"
imageSrc="https://img.b2bpic.net/free-photo/welcome-open-sign-hanging_23-2149168995.jpg"
imageAlt="bakery storefront inviting window handwritten sign warm atmosphere"
mediaAnimation="slide-up"
mediaPosition="right"
buttonText="Send Your Sweet Message"
ariaLabel="Contact section"
className="py-16"
containerClassName="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"
contentClassName="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center"
formCardClassName="bg-white rounded-2xl shadow-lg p-8"
titleClassName="text-3xl md:text-4xl font-bold text-gray-900 mb-4"
descriptionClassName="text-lg text-gray-600 mb-6"
buttonClassName="bg-amber-600 hover:bg-amber-700 text-white font-semibold py-3 px-6 rounded-lg transition duration-300 ease-in-out transform hover:scale-105"
buttonTextClassName="flex items-center justify-center"
mediaWrapperClassName="relative overflow-hidden rounded-2xl"
mediaClassName="w-full h-full object-cover"
/>
</div>
<div id="footer-section" data-section="footer-section">
<FooterMedia
imageSrc={getAssetUrl("footer-section-backgroundImage")}
imageAlt="Cozy bakery interior with wooden shelves and fresh pastries"
imageSrc="https://img.b2bpic.net/free-photo/bakery-atmospheric-photo_1321-4640.jpg"
imageAlt="bakery counter rustic setup warm lighting baked goods display"
columns={[
{
title: "Explore", items: [
{ label: "Our Story", href: "#about-section" },
{ label: "Fresh Products", href: "#products-section" },
{ label: "Baking Classes", href: "#faq-section" },
{ label: "Seasonal Specials", href: "#features-section" }
]
{ label: "Seasonal Specials", href: "#features-section" },
],
},
{
title: "Support", items: [
{ label: "Contact Us", href: "#contact-section" },
{ label: "FAQs", href: "#faq-section" },
{ label: "Delivery Info", href: "#faq-section" },
{ label: "Return Policy", href: "#faq-section" }
]
{ label: "Return Policy", href: "#faq-section" },
],
},
{
title: "Connect", items: [
{ label: "Instagram", href: "#" },
{ label: "Facebook", href: "#" },
{ label: "Newsletter", href: "#" },
{ label: "Blog", href: "#" }
]
}
{ label: "Blog", href: "#" },
],
},
]}
logoText="Sweet Crumb Bakery"
copyrightText="© 2025 Sweet Crumb Bakery | Crafting joy, one bite at a time"
@@ -287,4 +232,4 @@ export default function LandingPage() {
</div>
</ThemeProvider>
);
}
}

View File

@@ -8,206 +8,74 @@ import NavbarStyleFullscreen from "@/components/navbar/NavbarStyleFullscreen/Nav
import ProductDetailCard from "@/components/ecommerce/productDetail/ProductDetailCard";
import ProductCart from "@/components/ecommerce/cart/ProductCart";
import { useProductDetail } from "@/hooks/useProductDetail";
import { useCart } from "@/hooks/useCart";
import { useCheckout } from "@/hooks/useCheckout";
interface ProductPageProps {
params: Promise<{ id: string }>;
}
function ProductDetailContent({ id }: { id: string }) {
const router = useRouter();
const { product, isLoading, error } = useProductDetail(id);
export default function ProductPage({ params }: ProductPageProps) {
const handleAddToCart = useCallback(() => {
console.log("Product added to cart:", product);
}, [product]);
if (isLoading) {
return <div className="text-center py-12">Loading product details...</div>;
}
if (error || !product) {
return (
<Suspense fallback={null}>
<ProductPageContent params={params} />
</Suspense>
);
}
function ProductPageContent({ params }: ProductPageProps) {
const { id } = use(params);
const router = useRouter();
const {
product,
isLoading,
images,
meta,
variants,
quantityVariant,
selectedQuantity,
createCartItem,
} = useProductDetail(id);
const {
items: cartItems,
isOpen: cartOpen,
setIsOpen: setCartOpen,
addItem,
updateQuantity,
removeItem,
total: cartTotal,
getCheckoutItems,
} = useCart();
const { buyNow, checkout, isLoading: isCheckoutLoading } = useCheckout();
const handleAddToCart = useCallback(() => {
const item = createCartItem();
if (item) {
addItem(item);
}
}, [createCartItem, addItem]);
const handleBuyNow = useCallback(() => {
if (product) {
buyNow(product, selectedQuantity);
}
}, [product, selectedQuantity, buyNow]);
const handleCheckout = useCallback(async () => {
if (cartItems.length === 0) return;
const currentUrl = new URL(window.location.href);
currentUrl.searchParams.set("success", "true");
await checkout(getCheckoutItems(), { successUrl: currentUrl.toString() });
}, [cartItems, checkout, getCheckoutItems]);
if (isLoading) {
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="background-highlight"
borderRadius="pill"
contentWidth="medium"
sizing="mediumLargeSizeLargeTitles"
background="grid"
cardStyle="gradient-mesh"
primaryButtonStyle="double-inset"
secondaryButtonStyle="layered"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="navbar" data-section="navbar">
<NavbarStyleFullscreen
navItems={[{"name":"Home","id":"/"},{"name":"Hero","id":"hero-section"},{"name":"About","id":"about-section"},{"name":"Feature","id":"features-section"},{"name":"Product","id":"products-section"},{"name":"Testimonial","id":"testimonials-section"},{"name":"Faq","id":"faq-section"},{"name":"Contact","id":"contact-section"},{"name":"Shop","id":"/shop"}]}
brandName="Warm Stone Bakery"
bottomLeftText="Global Community"
bottomRightText="hello@warmstonebakery.com"
topBarClassName=""
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
/>
</div>
<main className="min-h-screen flex items-center justify-center pt-20">
<p className="text-foreground">Loading product...</p>
</main>
</ReactLenis>
</ThemeProvider>
);
}
if (!product) {
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="background-highlight"
borderRadius="pill"
contentWidth="medium"
sizing="mediumLargeSizeLargeTitles"
background="grid"
cardStyle="gradient-mesh"
primaryButtonStyle="double-inset"
secondaryButtonStyle="layered"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="navbar" data-section="navbar">
<NavbarStyleFullscreen
navItems={[{"name":"Home","id":"/"},{"name":"Hero","id":"hero-section"},{"name":"About","id":"about-section"},{"name":"Feature","id":"features-section"},{"name":"Product","id":"products-section"},{"name":"Testimonial","id":"testimonials-section"},{"name":"Faq","id":"faq-section"},{"name":"Contact","id":"contact-section"},{"name":"Shop","id":"/shop"}]}
brandName="Warm Stone Bakery"
bottomLeftText="Global Community"
bottomRightText="hello@warmstonebakery.com"
topBarClassName=""
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
/>
</div>
<main className="min-h-screen flex items-center justify-center pt-20">
<div className="text-center">
<p className="text-foreground mb-4">Product not found</p>
<button
onClick={() => router.push("/shop")}
className="primary-button px-6 py-2 rounded-theme text-primary-cta-text"
>
Back to Shop
</button>
</div>
</main>
</ReactLenis>
</ThemeProvider>
);
}
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="background-highlight"
borderRadius="pill"
contentWidth="medium"
sizing="mediumLargeSizeLargeTitles"
background="grid"
cardStyle="gradient-mesh"
primaryButtonStyle="double-inset"
secondaryButtonStyle="layered"
headingFontWeight="bold"
<div className="text-center py-12">
<p className="text-red-600">Product not found</p>
<button
onClick={() => router.push("/shop")}
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded"
>
<ReactLenis root>
<div id="navbar" data-section="navbar">
<NavbarStyleFullscreen
navItems={[{"name":"Home","id":"/"},{"name":"Hero","id":"hero-section"},{"name":"About","id":"about-section"},{"name":"Feature","id":"features-section"},{"name":"Product","id":"products-section"},{"name":"Testimonial","id":"testimonials-section"},{"name":"Faq","id":"faq-section"},{"name":"Contact","id":"contact-section"},{"name":"Shop","id":"/shop"}]}
brandName="Warm Stone Bakery"
bottomLeftText="Global Community"
bottomRightText="hello@warmstonebakery.com"
topBarClassName=""
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
/>
</div>
<div id="productDetailCard" data-section="productDetailCard">
<ProductDetailCard
layout="page"
name={product.name}
price={product.price}
salePrice={meta.salePrice}
rating={product.rating || 0}
description={product.description}
images={images}
variants={variants.length > 0 ? variants : undefined}
quantity={quantityVariant}
ribbon={meta.ribbon}
inventoryStatus={meta.inventoryStatus}
inventoryQuantity={meta.inventoryQuantity}
sku={meta.sku}
buttons={[
{ text: "Add To Cart", onClick: handleAddToCart },
{ text: "Buy Now", onClick: handleBuyNow },
]}
/>
</div>
<div id="productCart" data-section="productCart">
<ProductCart
isOpen={cartOpen}
onClose={() => setCartOpen(false)}
items={cartItems}
onQuantityChange={updateQuantity}
onRemove={removeItem}
total={`$${cartTotal}`}
buttons={[
{
text: isCheckoutLoading ? "Processing..." : "Check Out", onClick: handleCheckout,
},
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
Back to Shop
</button>
</div>
);
}
}
return (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 py-12 px-4">
<ProductDetailCard product={product} onAddToCart={handleAddToCart} />
<ProductCart product={product} onAddToCart={handleAddToCart} />
</div>
);
}
export default function ProductDetailPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = use(params);
const navItems = [
{ name: "Home", id: "/" },
{ name: "Blog", id: "/blog" },
{ name: "Shop", id: "/shop" },
];
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="entrance-slide"
borderRadius="rounded"
contentWidth="medium"
sizing="medium"
background="circleGradient"
cardStyle="glass-elevated"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="normal"
>
<ReactLenis root>
<div id="nav" data-section="nav">
<NavbarStyleFullscreen navItems={navItems} />
</div>
<Suspense fallback={<div className="text-center py-12">Loading...</div>}>
<ProductDetailContent id={id} />
</Suspense>
</ReactLenis>
</ThemeProvider>
);
}

View File

@@ -8,93 +8,63 @@ import ProductCatalog from "@/components/ecommerce/productCatalog/ProductCatalog
import { useProductCatalog } from "@/hooks/useProductCatalog";
function ShopPageContent() {
const {
products,
isLoading,
search,
setSearch,
filters,
cartOpen,
setCartOpen,
} = useProductCatalog({ basePath: "/shop" });
const {
products,
isLoading,
search,
setSearch,
category,
setCategory,
sort,
setSort,
filters,
categories,
} = useProductCatalog();
if (isLoading) {
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="background-highlight"
borderRadius="pill"
contentWidth="medium"
sizing="mediumLargeSizeLargeTitles"
background="grid"
cardStyle="gradient-mesh"
primaryButtonStyle="double-inset"
secondaryButtonStyle="layered"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="navbar" data-section="navbar">
<NavbarStyleFullscreen
navItems={[{"name":"Home","id":"/"},{"name":"Hero","id":"hero-section"},{"name":"About","id":"about-section"},{"name":"Feature","id":"features-section"},{"name":"Product","id":"products-section"},{"name":"Testimonial","id":"testimonials-section"},{"name":"Faq","id":"faq-section"},{"name":"Contact","id":"contact-section"},{"name":"Shop","id":"/shop"}]}
brandName="Warm Stone Bakery"
bottomLeftText="Global Community"
bottomRightText="hello@warmstonebakery.com"
topBarClassName=""
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
/>
</div>
<main className="min-h-screen flex items-center justify-center pt-20">
<p className="text-foreground">Loading products...</p>
</main>
</ReactLenis>
</ThemeProvider>
);
}
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="background-highlight"
borderRadius="pill"
contentWidth="medium"
sizing="mediumLargeSizeLargeTitles"
background="grid"
cardStyle="gradient-mesh"
primaryButtonStyle="double-inset"
secondaryButtonStyle="layered"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="navbar" data-section="navbar">
<NavbarStyleFullscreen
navItems={[{"name":"Home","id":"/"},{"name":"Hero","id":"hero-section"},{"name":"About","id":"about-section"},{"name":"Feature","id":"features-section"},{"name":"Product","id":"products-section"},{"name":"Testimonial","id":"testimonials-section"},{"name":"Faq","id":"faq-section"},{"name":"Contact","id":"contact-section"},{"name":"Shop","id":"/shop"}]}
brandName="Warm Stone Bakery"
bottomLeftText="Global Community"
bottomRightText="hello@warmstonebakery.com"
topBarClassName=""
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
/>
</div>
<div id="productCatalog" data-section="productCatalog">
<ProductCatalog
layout="page"
products={products}
searchValue={search}
onSearchChange={setSearch}
searchPlaceholder="Search products..."
filters={filters}
emptyMessage="No products found"
/>
</div>
</ReactLenis>
</ThemeProvider>
);
return (
<ProductCatalog
products={products}
isLoading={isLoading}
search={search}
setSearch={setSearch}
category={category}
setCategory={setCategory}
sort={sort}
setSort={setSort}
filters={filters}
categories={categories}
/>
);
}
export default function ShopPage() {
return (
<Suspense>
<ShopPageContent />
const navItems = [
{ name: "Home", id: "/" },
{ name: "Blog", id: "/blog" },
{ name: "Shop", id: "/shop" },
];
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="entrance-slide"
borderRadius="rounded"
contentWidth="medium"
sizing="medium"
background="circleGradient"
cardStyle="glass-elevated"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="normal"
>
<ReactLenis root>
<div id="nav" data-section="nav">
<NavbarStyleFullscreen navItems={navItems} />
</div>
<Suspense fallback={<div className="text-center py-12">Loading shop...</div>}>
<ShopPageContent />
</Suspense>
);
}
</ReactLenis>
</ThemeProvider>
);
}