Update src/app/page.tsx
This commit is contained in:
239
src/app/page.tsx
239
src/app/page.tsx
@@ -9,13 +9,16 @@ import TestimonialCardSix from '@/components/sections/testimonial/TestimonialCar
|
||||
import FeatureCardNine from '@/components/sections/feature/FeatureCardNine';
|
||||
import ContactSplitForm from '@/components/sections/contact/ContactSplitForm';
|
||||
import FooterLogoEmphasis from '@/components/sections/footer/FooterLogoEmphasis';
|
||||
import { Award, Sparkles, Users, Star } from "lucide-react";
|
||||
import { Award, Sparkles, Users, Star, ShoppingCart, Trash2, ArrowRight } from "lucide-react";
|
||||
import { useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function LandingPage() {
|
||||
const [formSubmitted, setFormSubmitted] = useState(false);
|
||||
const [filterCategory, setFilterCategory] = useState('all');
|
||||
const [reservation, setReservation] = useState(null);
|
||||
const [cart, setCart] = useState([]);
|
||||
const [showCart, setShowCart] = useState(false);
|
||||
|
||||
const handleFormSubmit = (data) => {
|
||||
console.log('Form submitted:', data);
|
||||
@@ -30,22 +33,97 @@ export default function LandingPage() {
|
||||
};
|
||||
|
||||
const allProducts = [
|
||||
// Pies Category
|
||||
{
|
||||
id: "bacon-egg", name: "Award-Winning Bacon & Egg", price: "Signature Pick", imageSrc: "http://img.b2bpic.net/free-photo/slice-roscon-de-reyes-epiphany-dessert_23-2148721499.jpg?_wi=1", imageAlt: "Bacon and egg pie with crispy golden pastry", category: "savory", onProductClick: () => console.log('Product clicked: Bacon & Egg')
|
||||
id: "bacon-egg", name: "Award-Winning Bacon & Egg", price: "$8.50", imageSrc: "http://img.b2bpic.net/free-photo/slice-roscon-de-reyes-epiphany-dessert_23-2148721499.jpg?_wi=1", imageAlt: "Bacon and egg pie with crispy golden pastry", category: "pies", onProductClick: () => console.log('Product clicked: Bacon & Egg'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "bacon-egg", name: "Award-Winning Bacon & Egg", price: "$8.50", quantity: qty })
|
||||
},
|
||||
{
|
||||
id: "beef-cheek", name: "Beef Cheek, Jalapeño & Cheddar", price: "Customer Favorite", imageSrc: "http://img.b2bpic.net/free-photo/bride-groom-salt-broken-piece-wedding-loaf_501050-105.jpg?_wi=1", imageAlt: "Beef cheek jalapeño and cheddar artisan pie", category: "savory", onProductClick: () => console.log('Product clicked: Beef Cheek')
|
||||
id: "beef-cheek", name: "Beef Cheek, Jalapeño & Cheddar", price: "$9.00", imageSrc: "http://img.b2bpic.net/free-photo/bride-groom-salt-broken-piece-wedding-loaf_501050-105.jpg?_wi=1", imageAlt: "Beef cheek jalapeño and cheddar artisan pie", category: "pies", onProductClick: () => console.log('Product clicked: Beef Cheek'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "beef-cheek", name: "Beef Cheek, Jalapeño & Cheddar", price: "$9.00", quantity: qty })
|
||||
},
|
||||
{
|
||||
id: "steak-cheese", name: "Steak & Cheese", price: "Best Seller", imageSrc: "http://img.b2bpic.net/free-photo/flat-lay-pumpkin-pie-thanksgiving_23-2148686219.jpg?_wi=1", imageAlt: "Steak and cheese pie with chunky beef and gravy", category: "savory", onProductClick: () => console.log('Product clicked: Steak & Cheese')
|
||||
id: "steak-cheese", name: "Steak & Cheese", price: "$8.75", imageSrc: "http://img.b2bpic.net/free-photo/flat-lay-pumpkin-pie-thanksgiving_23-2148686219.jpg?_wi=1", imageAlt: "Steak and cheese pie with chunky beef and gravy", category: "pies", onProductClick: () => console.log('Product clicked: Steak & Cheese'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "steak-cheese", name: "Steak & Cheese", price: "$8.75", quantity: qty })
|
||||
},
|
||||
// Sausage Rolls Category
|
||||
{
|
||||
id: "pork-sausage", name: "Pork Sausage Roll", price: "$5.50", imageSrc: "http://img.b2bpic.net/free-photo/slice-roscon-de-reyes-epiphany-dessert_23-2148721499.jpg?_wi=1", imageAlt: "Golden pork sausage roll", category: "sausage-rolls", onProductClick: () => console.log('Product clicked: Pork Sausage Roll'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "pork-sausage", name: "Pork Sausage Roll", price: "$5.50", quantity: qty })
|
||||
},
|
||||
{
|
||||
id: "sweet-selection", name: "Sweet Cabinet Selection", price: "Worth adding on", imageSrc: "http://img.b2bpic.net/free-photo/dessert-catering_1203-2828.jpg?_wi=1", imageAlt: "Assorted artisan donuts, croissants, and tarts", category: "sweet", onProductClick: () => console.log('Product clicked: Sweet Selection')
|
||||
id: "chorizo-cheese", name: "Chorizo & Cheese Roll", price: "$6.00", imageSrc: "http://img.b2bpic.net/free-photo/bride-groom-salt-broken-piece-wedding-loaf_501050-105.jpg?_wi=1", imageAlt: "Spicy chorizo and cheese sausage roll", category: "sausage-rolls", onProductClick: () => console.log('Product clicked: Chorizo & Cheese Roll'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "chorizo-cheese", name: "Chorizo & Cheese Roll", price: "$6.00", quantity: qty })
|
||||
},
|
||||
// Sweet Treats Category
|
||||
{
|
||||
id: "sweet-cabinet", name: "Sweet Cabinet Selection", price: "$4.50-7.00", imageSrc: "http://img.b2bpic.net/free-photo/dessert-catering_1203-2828.jpg?_wi=1", imageAlt: "Assorted artisan donuts, croissants, and tarts", category: "sweet-treats", onProductClick: () => console.log('Product clicked: Sweet Selection'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "sweet-cabinet", name: "Sweet Cabinet Selection", price: "$4.50-7.00", quantity: qty })
|
||||
},
|
||||
{
|
||||
id: "chocolate-eclair", name: "Chocolate Éclair", price: "$6.50", imageSrc: "http://img.b2bpic.net/free-photo/flat-lay-pumpkin-pie-thanksgiving_23-2148686219.jpg?_wi=1", imageAlt: "Classic chocolate éclair with premium filling", category: "sweet-treats", onProductClick: () => console.log('Product clicked: Chocolate Éclair'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "chocolate-eclair", name: "Chocolate Éclair", price: "$6.50", quantity: qty })
|
||||
},
|
||||
// Bread Category
|
||||
{
|
||||
id: "sourdough", name: "Artisan Sourdough", price: "$6.00", imageSrc: "http://img.b2bpic.net/free-photo/bride-groom-salt-broken-piece-wedding-loaf_501050-105.jpg?_wi=1", imageAlt: "Crusty artisan sourdough loaf", category: "bread", onProductClick: () => console.log('Product clicked: Sourdough'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "sourdough", name: "Artisan Sourdough", price: "$6.00", quantity: qty })
|
||||
},
|
||||
{
|
||||
id: "focaccia", name: "Rosemary Focaccia", price: "$5.50", imageSrc: "http://img.b2bpic.net/free-photo/slice-roscon-de-reyes-epiphany-dessert_23-2148721499.jpg?_wi=1", imageAlt: "Herb-infused focaccia with olive oil", category: "bread", onProductClick: () => console.log('Product clicked: Focaccia'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "focaccia", name: "Rosemary Focaccia", price: "$5.50", quantity: qty })
|
||||
},
|
||||
// Sandwiches Category
|
||||
{
|
||||
id: "roasted-veg", name: "Roasted Vegetable & Hummus", price: "$9.50", imageSrc: "http://img.b2bpic.net/free-photo/dessert-catering_1203-2828.jpg?_wi=1", imageAlt: "Fresh roasted vegetable sandwich", category: "sandwiches", onProductClick: () => console.log('Product clicked: Roasted Veg'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "roasted-veg", name: "Roasted Vegetable & Hummus", price: "$9.50", quantity: qty })
|
||||
},
|
||||
{
|
||||
id: "bacon-tomato", name: "Bacon & Tomato Club", price: "$11.00", imageSrc: "http://img.b2bpic.net/free-photo/flat-lay-pumpkin-pie-thanksgiving_23-2148686219.jpg?_wi=1", imageAlt: "Loaded bacon and tomato club sandwich", category: "sandwiches", onProductClick: () => console.log('Product clicked: Bacon Tomato'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "bacon-tomato", name: "Bacon & Tomato Club", price: "$11.00", quantity: qty })
|
||||
},
|
||||
// Coffee Category
|
||||
{
|
||||
id: "flat-white", name: "Flat White", price: "$5.00", imageSrc: "http://img.b2bpic.net/free-photo/medium-shot-woman-working-bakery_23-2150273180.jpg?_wi=1", imageAlt: "Smooth flat white coffee", category: "coffee", onProductClick: () => console.log('Product clicked: Flat White'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "flat-white", name: "Flat White", price: "$5.00", quantity: qty })
|
||||
},
|
||||
{
|
||||
id: "cappuccino", name: "Cappuccino", price: "$5.00", imageSrc: "http://img.b2bpic.net/free-photo/close-up-pastry-chef-preparing-food_23-2149038998.jpg?_wi=1", imageAlt: "Rich cappuccino with premium crema", category: "coffee", onProductClick: () => console.log('Product clicked: Cappuccino'),
|
||||
onQuantityChange: (qty) => handleAddToCart({ id: "cappuccino", name: "Cappuccino", price: "$5.00", quantity: qty })
|
||||
}
|
||||
];
|
||||
|
||||
const filteredProducts = filterCategory === 'all'
|
||||
? allProducts
|
||||
const handleAddToCart = (item) => {
|
||||
setCart(prevCart => {
|
||||
const existingItem = prevCart.find(cartItem => cartItem.id === item.id);
|
||||
if (existingItem) {
|
||||
return prevCart.map(cartItem =>
|
||||
cartItem.id === item.id
|
||||
? { ...cartItem, quantity: item.quantity }
|
||||
: cartItem
|
||||
);
|
||||
}
|
||||
return [...prevCart, item];
|
||||
});
|
||||
};
|
||||
|
||||
const handleRemoveFromCart = (itemId) => {
|
||||
setCart(prevCart => prevCart.filter(item => item.id !== itemId));
|
||||
};
|
||||
|
||||
const handleCheckout = () => {
|
||||
if (cart.length === 0) return;
|
||||
// Navigate to checkout page
|
||||
window.location.href = '/checkout';
|
||||
};
|
||||
|
||||
const cartTotal = cart.reduce((total, item) => {
|
||||
const price = parseFloat(item.price.replace('$', '').split('-')[0]);
|
||||
return total + (price * (item.quantity || 1));
|
||||
}, 0);
|
||||
|
||||
const filteredProducts = filterCategory === 'all'
|
||||
? allProducts
|
||||
: allProducts.filter(p => p.category === filterCategory);
|
||||
|
||||
return (
|
||||
@@ -65,12 +143,62 @@ export default function LandingPage() {
|
||||
<NavbarStyleApple
|
||||
brandName="Levain"
|
||||
navItems={[
|
||||
{ name: "Signature", id: "signature" },
|
||||
{ name: "Menu", id: "menu" },
|
||||
{ name: "Why Levain", id: "why-levain" },
|
||||
{ name: "Reviews", id: "reviews" },
|
||||
{ name: "Visit", id: "visit" }
|
||||
]}
|
||||
/>
|
||||
{/* Cart Indicator */}
|
||||
<div className="fixed top-20 right-4 z-40">
|
||||
<button
|
||||
onClick={() => setShowCart(!showCart)}
|
||||
className="relative bg-primary-cta text-white p-3 rounded-full shadow-lg hover:shadow-xl transition-all"
|
||||
aria-label="Shopping cart"
|
||||
>
|
||||
<ShoppingCart size={24} />
|
||||
{cart.length > 0 && (
|
||||
<span className="absolute -top-2 -right-2 bg-red-500 text-white text-xs rounded-full w-6 h-6 flex items-center justify-center">
|
||||
{cart.length}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
{showCart && cart.length > 0 && (
|
||||
<div className="absolute right-0 mt-2 w-72 bg-white dark:bg-gray-900 rounded-lg shadow-2xl p-4 border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="font-bold text-lg mb-4 text-foreground">Shopping Cart</h3>
|
||||
<div className="space-y-2 max-h-64 overflow-y-auto">
|
||||
{cart.map(item => (
|
||||
<div key={item.id} className="flex justify-between items-center p-2 bg-card rounded border border-gray-100 dark:border-gray-800">
|
||||
<div className="flex-1">
|
||||
<p className="font-medium text-sm text-foreground">{item.name}</p>
|
||||
<p className="text-xs text-gray-600 dark:text-gray-400">Qty: {item.quantity || 1} × {item.price}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => handleRemoveFromCart(item.id)}
|
||||
className="text-red-500 hover:text-red-700 transition-colors"
|
||||
aria-label={`Remove ${item.name} from cart`}
|
||||
>
|
||||
<Trash2 size={16} />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-4 pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||
<div className="flex justify-between items-center font-bold text-lg mb-4 text-foreground">
|
||||
<span>Total:</span>
|
||||
<span className="text-primary-cta">${cartTotal.toFixed(2)}</span>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleCheckout}
|
||||
className="w-full bg-primary-cta text-white py-2 rounded-lg font-semibold hover:opacity-90 transition-opacity flex items-center justify-center gap-2"
|
||||
aria-label="Proceed to checkout"
|
||||
>
|
||||
Checkout <ArrowRight size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="hero" data-section="hero">
|
||||
@@ -78,7 +206,7 @@ export default function LandingPage() {
|
||||
logoText="Auckland's most talked-about artisan bakery experience."
|
||||
description="Levain brings elevated bakery craft to everyday cravings — crisp golden pastry, generous fillings, sweet cabinet favourites, fast friendly service, and a reputation people happily drive across town for."
|
||||
buttons={[
|
||||
{ text: "Order Fresh Pies Now", href: "#signature" },
|
||||
{ text: "Order Fresh Pies Now", href: "#menu" },
|
||||
{ text: "See Hours & Location", href: "#visit" }
|
||||
]}
|
||||
imageSrc="http://img.b2bpic.net/free-photo/medium-shot-woman-working-bakery_23-2150273180.jpg?_wi=1"
|
||||
@@ -88,40 +216,56 @@ export default function LandingPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="signature" data-section="signature">
|
||||
<div className="mb-8 flex gap-4 justify-center">
|
||||
<div id="menu" data-section="menu">
|
||||
<div className="mb-8 flex gap-4 justify-center flex-wrap">
|
||||
<button
|
||||
onClick={() => setFilterCategory('all')}
|
||||
className={`px-4 py-2 rounded-full transition-all ${
|
||||
filterCategory === 'all'
|
||||
? 'bg-primary-cta text-white'
|
||||
: 'bg-card text-foreground border border-gray-300'
|
||||
}`}
|
||||
className={`px-4 py-2 rounded-full transition-all ${filterCategory === 'all' ? 'bg-primary-cta text-white' : 'bg-card text-foreground border border-gray-300 dark:border-gray-700'}`}
|
||||
aria-label="Show all products"
|
||||
>
|
||||
All Items
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilterCategory('savory')}
|
||||
className={`px-4 py-2 rounded-full transition-all ${
|
||||
filterCategory === 'savory'
|
||||
? 'bg-primary-cta text-white'
|
||||
: 'bg-card text-foreground border border-gray-300'
|
||||
}`}
|
||||
aria-label="Show savory products"
|
||||
onClick={() => setFilterCategory('pies')}
|
||||
className={`px-4 py-2 rounded-full transition-all ${filterCategory === 'pies' ? 'bg-primary-cta text-white' : 'bg-card text-foreground border border-gray-300 dark:border-gray-700'}`}
|
||||
aria-label="Show pies"
|
||||
>
|
||||
Savory
|
||||
Pies
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilterCategory('sweet')}
|
||||
className={`px-4 py-2 rounded-full transition-all ${
|
||||
filterCategory === 'sweet'
|
||||
? 'bg-primary-cta text-white'
|
||||
: 'bg-card text-foreground border border-gray-300'
|
||||
}`}
|
||||
aria-label="Show sweet products"
|
||||
onClick={() => setFilterCategory('sausage-rolls')}
|
||||
className={`px-4 py-2 rounded-full transition-all ${filterCategory === 'sausage-rolls' ? 'bg-primary-cta text-white' : 'bg-card text-foreground border border-gray-300 dark:border-gray-700'}`}
|
||||
aria-label="Show sausage rolls"
|
||||
>
|
||||
Sweet
|
||||
Sausage Rolls
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilterCategory('sweet-treats')}
|
||||
className={`px-4 py-2 rounded-full transition-all ${filterCategory === 'sweet-treats' ? 'bg-primary-cta text-white' : 'bg-card text-foreground border border-gray-300 dark:border-gray-700'}`}
|
||||
aria-label="Show sweet treats"
|
||||
>
|
||||
Sweet Treats
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilterCategory('bread')}
|
||||
className={`px-4 py-2 rounded-full transition-all ${filterCategory === 'bread' ? 'bg-primary-cta text-white' : 'bg-card text-foreground border border-gray-300 dark:border-gray-700'}`}
|
||||
aria-label="Show bread"
|
||||
>
|
||||
Bread
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilterCategory('sandwiches')}
|
||||
className={`px-4 py-2 rounded-full transition-all ${filterCategory === 'sandwiches' ? 'bg-primary-cta text-white' : 'bg-card text-foreground border border-gray-300 dark:border-gray-700'}`}
|
||||
aria-label="Show sandwiches"
|
||||
>
|
||||
Sandwiches
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilterCategory('coffee')}
|
||||
className={`px-4 py-2 rounded-full transition-all ${filterCategory === 'coffee' ? 'bg-primary-cta text-white' : 'bg-card text-foreground border border-gray-300 dark:border-gray-700'}`}
|
||||
aria-label="Show coffee"
|
||||
>
|
||||
Coffee
|
||||
</button>
|
||||
</div>
|
||||
<ProductCardThree
|
||||
@@ -134,7 +278,7 @@ export default function LandingPage() {
|
||||
gridVariant="two-columns-alternating-heights"
|
||||
animationType="slide-up"
|
||||
buttons={[
|
||||
{ text: "View Full Menu", href: "#signature" }
|
||||
{ text: "View Full Menu", href: "#menu" }
|
||||
]}
|
||||
products={filteredProducts}
|
||||
/>
|
||||
@@ -201,7 +345,7 @@ export default function LandingPage() {
|
||||
tag="Primary call to action"
|
||||
tagAnimation="blur-reveal"
|
||||
buttons={[
|
||||
{ text: "See Today's Favourites", href: "#signature" },
|
||||
{ text: "See Today's Favourites", href: "#menu" },
|
||||
{ text: "Get Directions", href: "#visit" }
|
||||
]}
|
||||
buttonAnimation="slide-up"
|
||||
@@ -265,27 +409,44 @@ export default function LandingPage() {
|
||||
{
|
||||
items: [
|
||||
{ label: "About", href: "#why-levain" },
|
||||
{ label: "Menu", href: "#signature" },
|
||||
{ label: "Menu", href: "#menu" },
|
||||
{ label: "Testimonials", href: "#reviews" }
|
||||
]
|
||||
},
|
||||
{
|
||||
items: [
|
||||
{ label: "Visit", href: "#visit" },
|
||||
{ label: "Instagram", href: "#" },
|
||||
{ label: "Instagram", href: "https://instagram.com" },
|
||||
{ label: "Contact", href: "#visit" }
|
||||
]
|
||||
},
|
||||
{
|
||||
items: [
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" },
|
||||
{ label: "Accessibility", href: "#" }
|
||||
{ label: "Privacy Policy", href: "/privacy" },
|
||||
{ label: "Terms of Service", href: "/terms" },
|
||||
{ label: "Accessibility", href: "/accessibility" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
ariaLabel="Levain bakery site footer"
|
||||
/>
|
||||
{/* Premium Footer CTA */}
|
||||
<div className="bg-gradient-to-r from-primary-cta to-accent text-white py-12 px-6 text-center mt-8">
|
||||
<h2 className="text-3xl font-bold mb-4">Join our community of Levain lovers.</h2>
|
||||
<p className="text-lg mb-6 opacity-95">Fresh, handcrafted pies delivered to your inbox. New flavors, special offers, and stories from our Auckland kitchen.</p>
|
||||
<div className="flex gap-4 justify-center flex-wrap">
|
||||
<input
|
||||
type="email"
|
||||
placeholder="Your email address"
|
||||
className="px-6 py-3 rounded-full text-foreground placeholder-gray-500 flex-1 max-w-sm focus:outline-none focus:ring-2 focus:ring-white"
|
||||
aria-label="Email for newsletter signup"
|
||||
/>
|
||||
<button className="px-8 py-3 bg-white text-primary-cta rounded-full font-semibold hover:opacity-90 transition-opacity" aria-label="Subscribe to newsletter">
|
||||
Subscribe
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-sm mt-6 opacity-75">We respect your inbox. Unsubscribe anytime.</p>
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user