Merge version_5 into main #5
@@ -21,9 +21,11 @@ const sourceSans3 = Source_Sans_3({
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Essence & Aura | Premium Luxury Perfumes & Cosmetics", description: "Discover curated luxury fragrances with interactive animated product experiences. Premium perfumes and cosmetics for the discerning connoisseur.", keywords: "luxury perfume, fragrance, cosmetics, premium scent, perfume shop, interactive shopping", openGraph: {
|
||||
title: "Essence & Aura | Discover Your Signature Scent", description: "Experience premium luxury fragrances with immersive interactive animations", type: "website", siteName: "Essence & Aura"},
|
||||
title: "Essence & Aura | Discover Your Signature Scent", description: "Experience premium luxury fragrances with immersive interactive animations", type: "website", siteName: "Essence & Aura"
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image", title: "Essence & Aura | Premium Fragrances", description: "Luxury perfumes with interactive product experiences"},
|
||||
card: "summary_large_image", title: "Essence & Aura | Premium Fragrances", description: "Luxury perfumes with interactive product experiences"
|
||||
},
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
||||
180
src/app/page.tsx
180
src/app/page.tsx
@@ -10,8 +10,39 @@ import FaqBase from '@/components/sections/faq/FaqBase';
|
||||
import ContactSplitForm from '@/components/sections/contact/ContactSplitForm';
|
||||
import FooterSimple from '@/components/sections/footer/FooterSimple';
|
||||
import { Sparkles, Heart, Gem, Star, HelpCircle, ShoppingBag } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
|
||||
export default function LandingPage() {
|
||||
const [activeProductId, setActiveProductId] = useState<string | null>(null);
|
||||
const [showSprayAnimation, setShowSprayAnimation] = useState(false);
|
||||
|
||||
const products = [
|
||||
{
|
||||
id: "perfume-1", name: "Midnight Blossom", price: "$185", variant: "100ml • Floral • 3 Scent Notes", imageSrc: "http://img.b2bpic.net/free-photo/closeup-shot-beautifully-shaped-glass-bottles-filled-with-perfume_181624-28370.jpg?_wi=2", imageAlt: "Midnight Blossom Fragrance"
|
||||
},
|
||||
{
|
||||
id: "perfume-2", name: "Crystal Noir", price: "$210", variant: "100ml • Oriental • Premium Edition", imageSrc: "http://img.b2bpic.net/free-photo/close-up-variety-cosmetic-products-desk-isolated_574295-5284.jpg?_wi=2", imageAlt: "Crystal Noir Fragrance"
|
||||
},
|
||||
{
|
||||
id: "perfume-3", name: "Amber Essence", price: "$165", variant: "75ml • Woody • Signature Collection", imageSrc: "http://img.b2bpic.net/free-photo/ecofriendly-beauty-product_23-2150669115.jpg?_wi=2", imageAlt: "Amber Essence Fragrance"
|
||||
},
|
||||
{
|
||||
id: "perfume-4", name: "Rose Garden", price: "$195", variant: "100ml • Fruity Floral • Limited Release", imageSrc: "http://img.b2bpic.net/free-photo/containers-liquid-soap-shampoo-with-dispenser-is-sold-supermarket_169016-50305.jpg?_wi=3", imageAlt: "Rose Garden Fragrance"
|
||||
},
|
||||
{
|
||||
id: "perfume-5", name: "Ocean Wave", price: "$175", variant: "100ml • Fresh Citrus • Summer Collection", imageSrc: "http://img.b2bpic.net/free-photo/containers-liquid-soap-shampoo-with-dispenser-is-sold-supermarket_169016-50305.jpg?_wi=4", imageAlt: "Ocean Wave Fragrance"
|
||||
},
|
||||
{
|
||||
id: "perfume-6", name: "Vanilla Luxe", price: "$200", variant: "100ml • Gourmand • Exclusive Blend", imageSrc: "http://img.b2bpic.net/free-photo/elegant-vegan-alcohol-arrangement_23-2149337695.jpg?_wi=2", imageAlt: "Vanilla Luxe Fragrance"
|
||||
}
|
||||
];
|
||||
|
||||
const handleProductClick = (productId: string) => {
|
||||
setActiveProductId(productId);
|
||||
setShowSprayAnimation(true);
|
||||
setTimeout(() => setShowSprayAnimation(false), 2000);
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="shift-hover"
|
||||
@@ -67,43 +98,118 @@ export default function LandingPage() {
|
||||
</div>
|
||||
|
||||
<div id="products" data-section="products">
|
||||
<ProductCardFour
|
||||
products={[
|
||||
{
|
||||
id: "perfume-1", name: "Midnight Blossom", price: "$185", variant: "100ml • Floral • 3 Scent Notes", imageSrc: "http://img.b2bpic.net/free-photo/closeup-shot-beautifully-shaped-glass-bottles-filled-with-perfume_181624-28370.jpg?_wi=2", imageAlt: "Midnight Blossom Fragrance"
|
||||
},
|
||||
{
|
||||
id: "perfume-2", name: "Crystal Noir", price: "$210", variant: "100ml • Oriental • Premium Edition", imageSrc: "http://img.b2bpic.net/free-photo/close-up-variety-cosmetic-products-desk-isolated_574295-5284.jpg?_wi=2", imageAlt: "Crystal Noir Fragrance"
|
||||
},
|
||||
{
|
||||
id: "perfume-3", name: "Amber Essence", price: "$165", variant: "75ml • Woody • Signature Collection", imageSrc: "http://img.b2bpic.net/free-photo/ecofriendly-beauty-product_23-2150669115.jpg?_wi=2", imageAlt: "Amber Essence Fragrance"
|
||||
},
|
||||
{
|
||||
id: "perfume-4", name: "Rose Garden", price: "$195", variant: "100ml • Fruity Floral • Limited Release", imageSrc: "http://img.b2bpic.net/free-photo/containers-liquid-soap-shampoo-with-dispenser-is-sold-supermarket_169016-50305.jpg?_wi=3", imageAlt: "Rose Garden Fragrance"
|
||||
},
|
||||
{
|
||||
id: "perfume-5", name: "Ocean Wave", price: "$175", variant: "100ml • Fresh Citrus • Summer Collection", imageSrc: "http://img.b2bpic.net/free-photo/containers-liquid-soap-shampoo-with-dispenser-is-sold-supermarket_169016-50305.jpg?_wi=4", imageAlt: "Ocean Wave Fragrance"
|
||||
},
|
||||
{
|
||||
id: "perfume-6", name: "Vanilla Luxe", price: "$200", variant: "100ml • Gourmand • Exclusive Blend", imageSrc: "http://img.b2bpic.net/free-photo/elegant-vegan-alcohol-arrangement_23-2149337695.jpg?_wi=2", imageAlt: "Vanilla Luxe Fragrance"
|
||||
}
|
||||
]}
|
||||
title="Premium Fragrance Collection"
|
||||
description="Sourced from master perfumers worldwide, authenticity guaranteed. Handpicked luxury perfumes and cosmetics for the discerning connoisseur. Click to explore interactive product animations"
|
||||
tag="Featured Selection"
|
||||
tagIcon={Heart}
|
||||
tagAnimation="slide-up"
|
||||
buttons={[
|
||||
{ text: "View All Products", href: "#" },
|
||||
{ text: "Shop Collection", href: "#" }
|
||||
]}
|
||||
buttonAnimation="slide-up"
|
||||
gridVariant="uniform-all-items-equal"
|
||||
animationType="slide-up"
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={false}
|
||||
carouselMode="buttons"
|
||||
/>
|
||||
<div className="relative">
|
||||
<ProductCardFour
|
||||
products={products.map(product => ({
|
||||
...product,
|
||||
onProductClick: () => handleProductClick(product.id)
|
||||
}))}
|
||||
title="Premium Fragrance Collection"
|
||||
description="Sourced from master perfumers worldwide, authenticity guaranteed. Handpicked luxury perfumes and cosmetics for the discerning connoisseur. Click to explore interactive product animations"
|
||||
tag="Featured Selection"
|
||||
tagIcon={Heart}
|
||||
tagAnimation="slide-up"
|
||||
buttons={[
|
||||
{ text: "View All Products", href: "#" },
|
||||
{ text: "Shop Collection", href: "#" }
|
||||
]}
|
||||
buttonAnimation="slide-up"
|
||||
gridVariant="uniform-all-items-equal"
|
||||
animationType="slide-up"
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={false}
|
||||
carouselMode="buttons"
|
||||
/>
|
||||
|
||||
{activeProductId && showSprayAnimation && (
|
||||
<div className="fixed inset-0 pointer-events-none z-50 flex items-center justify-center">
|
||||
<div className="relative w-96 h-96">
|
||||
{/* Product rotates leftward */}
|
||||
<div className="absolute inset-0 animate-spin-slow" style={{
|
||||
animationDuration: '2s',
|
||||
animationDirection: 'reverse',
|
||||
transformOrigin: 'center',
|
||||
}}>
|
||||
<img
|
||||
src={products.find(p => p.id === activeProductId)?.imageSrc}
|
||||
alt="Product"
|
||||
className="w-full h-full object-cover rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Spray particles animation */}
|
||||
<div className="absolute inset-0 overflow-hidden rounded-lg">
|
||||
{Array.from({ length: 12 }).map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="absolute w-2 h-2 bg-gradient-to-b from-white to-transparent rounded-full"
|
||||
style={{
|
||||
left: `${Math.random() * 100}%`,
|
||||
top: `-10px`,
|
||||
animation: `fall ${1 + Math.random() * 1}s ease-out forwards`,
|
||||
animationDelay: `${Math.random() * 0.5}s`,
|
||||
opacity: 0.7,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Product information reveal overlay */}
|
||||
<div
|
||||
className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent rounded-lg flex flex-col justify-end p-6 text-white"
|
||||
style={{
|
||||
animation: 'fadeIn 1.2s ease-in forwards',
|
||||
animationDelay: '0.5s',
|
||||
}}
|
||||
>
|
||||
<div className="opacity-0 animate-fadeInUp" style={{ animationDelay: '0.8s' }}>
|
||||
<h3 className="text-2xl font-bold mb-2">
|
||||
{products.find(p => p.id === activeProductId)?.name}
|
||||
</h3>
|
||||
<p className="text-sm mb-2">
|
||||
{products.find(p => p.id === activeProductId)?.variant}
|
||||
</p>
|
||||
<p className="text-xl font-semibold">
|
||||
{products.find(p => p.id === activeProductId)?.price}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>{`
|
||||
@keyframes spin-slow {
|
||||
from { transform: rotateY(0deg); }
|
||||
to { transform: rotateY(-180deg); }
|
||||
}
|
||||
@keyframes fall {
|
||||
to {
|
||||
transform: translateY(100px) translateX(${Math.random() * 40 - 20}px);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
to { opacity: 1; }
|
||||
}
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
.animate-spin-slow {
|
||||
animation: spin-slow 2s reverse;
|
||||
}
|
||||
.animate-fadeInUp {
|
||||
animation: fadeInUp 1s ease-out forwards;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="about" data-section="about">
|
||||
|
||||
Reference in New Issue
Block a user