Merge version_3 into main #6
136
src/app/page.tsx
136
src/app/page.tsx
@@ -5,37 +5,74 @@ import React, { useState, useMemo } from "react";
|
||||
import ReactLenis from "lenis/react";
|
||||
import HeroSplitDualMedia from '@/components/sections/hero/HeroSplitDualMedia';
|
||||
|
||||
// Move the random generation outside the component to ensure purity during render
|
||||
const generateHeartStyles = () => {
|
||||
return Array.from({ length: 30 }).map(() => ({
|
||||
// Helper to generate styles for floating elements (hearts, balloons, confetti)
|
||||
const generateFloatingStyles = (count: number, type: 'heart' | 'balloon' | 'confetti', scaleMin: number, scaleMax: number, durationMin: number, durationMax: number, delayMin: number, delayMax: number) => {
|
||||
return Array.from({ length: count }).map((_, i) => ({
|
||||
type,
|
||||
left: `${Math.random() * 100}vw`,
|
||||
animationDelay: `${Math.random() * 5}s`,
|
||||
animationDuration: `${5 + Math.random() * 5}s`,
|
||||
transform: `scale(${0.5 + Math.random()})`
|
||||
animationDelay: `${delayMin + Math.random() * (delayMax - delayMin)}s`,
|
||||
animationDuration: `${durationMin + Math.random() * (durationMax - durationMin)}s`,
|
||||
transform: `scale(${scaleMin + Math.random() * (scaleMax - scaleMin)})`,
|
||||
zIndex: Math.floor(Math.random() * 10) + 1, // Random z-index for depth
|
||||
}));
|
||||
};
|
||||
|
||||
const initialHeartStyles = generateHeartStyles(); // Generate once when module loads
|
||||
const getEmojiForType = (type: 'heart' | 'balloon' | 'confetti') => {
|
||||
if (type === 'heart') return '❤️';
|
||||
if (type === 'balloon') return '🎈';
|
||||
const confettiEmojis = ['✨', '🥳', '🎉'];
|
||||
return confettiEmojis[Math.floor(Math.random() * confettiEmojis.length)];
|
||||
};
|
||||
|
||||
const initialFloatingElements = {
|
||||
hearts: generateFloatingStyles(50, 'heart', 0.5, 1.5, 5, 10, 0, 5),
|
||||
balloons: generateFloatingStyles(30, 'balloon', 0.8, 1.2, 7, 12, 0, 7),
|
||||
confetti: generateFloatingStyles(100, 'confetti', 0.3, 0.8, 3, 7, 0, 4),
|
||||
};
|
||||
|
||||
const FloatingElements = () => {
|
||||
const elements = useMemo(() => {
|
||||
return [
|
||||
...initialFloatingElements.hearts,
|
||||
...initialFloatingElements.balloons,
|
||||
...initialFloatingElements.confetti,
|
||||
];
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{elements.map((style, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="absolute opacity-0 animate-floating"
|
||||
style={{
|
||||
left: style.left,
|
||||
animationDelay: style.animationDelay,
|
||||
animationDuration: style.animationDuration,
|
||||
transform: style.transform,
|
||||
zIndex: style.zIndex,
|
||||
fontSize: style.type === 'heart' ? '2rem' : (style.type === 'balloon' ? '2.5rem' : '1.5rem')
|
||||
}}
|
||||
>
|
||||
{getEmojiForType(style.type)}
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const CelebrationOverlay = () => {
|
||||
const heartStyles = useMemo(() => initialHeartStyles, []); // Reference the pre-generated styles
|
||||
|
||||
const hearts = heartStyles.map((style, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="absolute text-pink-500 text-3xl opacity-0 animate-heart-fall"
|
||||
style={style}
|
||||
>
|
||||
❤️
|
||||
</div>
|
||||
));
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-pink-100 bg-opacity-90 overflow-hidden">
|
||||
<div className="relative text-center text-pink-700 text-5xl font-bold p-8 animate-fade-in">
|
||||
I Love You Bisma ❤️
|
||||
<img
|
||||
src="https://imagedelivery.net/qN7d-a1E2_g_t-wwxG89gQ/cb330456-e41c-4384-a82f-2f8021c33c00/public" // Placeholder engagement ring
|
||||
alt="USA-style engagement ring"
|
||||
className="mx-auto mb-8 w-48 h-48 object-contain animate-ring-pop"
|
||||
/>
|
||||
I love you Bisma ❤️
|
||||
<div className="absolute top-0 left-0 w-full h-full pointer-events-none">
|
||||
{hearts}
|
||||
<FloatingElements />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,8 +81,7 @@ const CelebrationOverlay = () => {
|
||||
|
||||
export default function LandingPage() {
|
||||
const noMessages = [
|
||||
"Are you sure, Bisma? Think about our future... 🫠", "Please reconsider, my love. My heart aches at the thought. 💔", "Don't say no! We're meant to be. This isn't a game. 😭", "Just one more chance... Say yes! 🙏", "My world stops without you. Please, Bisma. Yes? ✨"
|
||||
];
|
||||
"Please kar lo na 🥺", "Main tum se bohat pyar karta hoon ❤️", "Ab to yes kar do na 🥹", "Please Bisma, maan jao na ❤️", "Mere liye yes kar do 💕", "Last time bol raha hoon, yes kar do ❤️"];
|
||||
const [noClickCount, setNoClickCount] = useState(0);
|
||||
const [showCelebration, setShowCelebration] = useState(false);
|
||||
|
||||
@@ -57,36 +93,48 @@ export default function LandingPage() {
|
||||
setNoClickCount((prevCount) => prevCount + 1);
|
||||
};
|
||||
|
||||
const currentDescription = noClickCount < 5
|
||||
? "My dearest Bisma, from the moment I met you, my world changed. Every day with you is a joy, an adventure, and a blessing. You are the most beautiful, kind, and brilliant person I know. My love for you grows with each passing moment, and I can't imagine a future without you by my side. Let's start our forever now."
|
||||
const initialProposalDescription = "You are the most beautiful, kind, and brilliant person I know. My love for you grows with each passing moment, and I can't imagine a future without you by my side. Will you make me the happiest man alive?";
|
||||
|
||||
const currentHeroDescription = noClickCount === 0
|
||||
? initialProposalDescription
|
||||
: noMessages[Math.min(noClickCount - 1, noMessages.length - 1)];
|
||||
|
||||
const buttons = noClickCount < 5
|
||||
const buttons = noClickCount < 6
|
||||
? [
|
||||
{ text: "Yes", onClick: handleYesClick },
|
||||
{ text: "No", onClick: handleNoClick }
|
||||
]
|
||||
: [
|
||||
{ text: "Yes ❤️", onClick: handleYesClick }, { text: "Yes ❤️", onClick: handleYesClick }
|
||||
{ text: "Yes ❤️", onClick: handleYesClick },
|
||||
{ text: "Yes ❤️", onClick: handleYesClick }
|
||||
];
|
||||
|
||||
// Tailwind keyframes for hearts and fade-in
|
||||
// Tailwind keyframes for floating elements and fade-in
|
||||
const globalStyles = `
|
||||
@keyframes heart-fall {
|
||||
0% { transform: translateY(-100vh) rotate(0deg) scale(0); opacity: 0; }
|
||||
10% { opacity: 1; }
|
||||
100% { transform: translateY(100vh) rotate(360deg) scale(1.5); opacity: 0; }
|
||||
@keyframes floating {
|
||||
0% { transform: translateY(-100vh) scale(0) rotate(0deg); opacity: 0; }
|
||||
10% { opacity: 1; transform: translateY(-80vh) scale(1) rotate(20deg); }
|
||||
50% { opacity: 1; transform: translateY(0vh) scale(1.2) rotate(-20deg); }
|
||||
100% { transform: translateY(100vh) scale(0) rotate(0deg); opacity: 0; }
|
||||
}
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; transform: translateY(20px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
.animate-heart-fall {
|
||||
animation: heart-fall linear infinite;
|
||||
@keyframes ring-pop {
|
||||
0% { transform: scale(0); opacity: 0; }
|
||||
50% { transform: scale(1.2); opacity: 1; }
|
||||
100% { transform: scale(1); opacity: 1; }
|
||||
}
|
||||
.animate-floating {
|
||||
animation: floating linear infinite;
|
||||
}
|
||||
.animate-fade-in {
|
||||
animation: fade-in 1s ease-out forwards;
|
||||
}
|
||||
.animate-ring-pop {
|
||||
animation: ring-pop 0.8s ease-out forwards;
|
||||
}
|
||||
html, body, #__next {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
@@ -116,26 +164,26 @@ export default function LandingPage() {
|
||||
<HeroSplitDualMedia
|
||||
background={{ variant: "plain" }}
|
||||
title="Bisma, will you marry me?"
|
||||
description={currentDescription}
|
||||
tag="A Lifetime Together"
|
||||
description={currentHeroDescription}
|
||||
tag="My Dearest Love"
|
||||
buttons={buttons}
|
||||
mediaItems={[
|
||||
{ imageSrc: '', imageAlt: '' },
|
||||
{ imageSrc: '', imageAlt: '' },
|
||||
{ imageSrc: 'https://imagedelivery.net/qN7d-a1E2_g_t-wwxG89gQ/cb330456-e41c-4384-a82f-2f8021c33c00/public', imageAlt: 'Diamond ring placeholder' },
|
||||
{ imageSrc: 'https://imagedelivery.net/qN7d-a1E2_g_t-wwxG89gQ/cb330456-e41c-4384-a82f-2f8021c33c00/public', imageAlt: 'Diamond ring placeholder' },
|
||||
]}
|
||||
mediaAnimation="none"
|
||||
rating={0}
|
||||
ratingText=""
|
||||
containerClassName="p-8 max-w-3xl text-center"
|
||||
titleClassName="text-5xl font-extrabold mb-4 text-pink-800"
|
||||
descriptionClassName="text-xl text-pink-700 mb-8"
|
||||
buttonContainerClassName="flex justify-center gap-4"
|
||||
buttonClassName="bg-pink-600 hover:bg-pink-700 text-white font-bold py-3 px-6 rounded-full shadow-lg transition duration-300 ease-in-out"
|
||||
tagClassName="text-pink-500 mb-2"
|
||||
titleClassName="text-5xl md:text-6xl lg:text-7xl font-extrabold mb-4 text-pink-800"
|
||||
descriptionClassName="text-xl md:text-2xl text-pink-700 mb-8"
|
||||
buttonContainerClassName="flex justify-center gap-4 mt-8"
|
||||
buttonClassName="bg-pink-600 hover:bg-pink-700 text-white font-bold py-3 px-6 rounded-full shadow-lg transition duration-300 ease-in-out text-lg"
|
||||
tagClassName="text-pink-500 mb-2 font-medium"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</ReactLenis>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user