Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3774b119af | |||
| d15aad921a | |||
| 5eb66fbf34 | |||
| f67c97c1fd | |||
| 4456a0bfb4 | |||
| 3047f1cbcf | |||
| 0d607bba63 | |||
| e3fd23e884 |
134
src/app/page.tsx
134
src/app/page.tsx
@@ -5,37 +5,74 @@ import React, { useState, useMemo } from "react";
|
|||||||
import ReactLenis from "lenis/react";
|
import ReactLenis from "lenis/react";
|
||||||
import HeroSplitDualMedia from '@/components/sections/hero/HeroSplitDualMedia';
|
import HeroSplitDualMedia from '@/components/sections/hero/HeroSplitDualMedia';
|
||||||
|
|
||||||
// Move the random generation outside the component to ensure purity during render
|
// Helper to generate styles for floating elements (hearts, balloons, confetti)
|
||||||
const generateHeartStyles = () => {
|
const generateFloatingStyles = (count: number, type: 'heart' | 'balloon' | 'confetti', scaleMin: number, scaleMax: number, durationMin: number, durationMax: number, delayMin: number, delayMax: number) => {
|
||||||
return Array.from({ length: 30 }).map(() => ({
|
return Array.from({ length: count }).map((_, i) => ({
|
||||||
|
type,
|
||||||
left: `${Math.random() * 100}vw`,
|
left: `${Math.random() * 100}vw`,
|
||||||
animationDelay: `${Math.random() * 5}s`,
|
animationDelay: `${delayMin + Math.random() * (delayMax - delayMin)}s`,
|
||||||
animationDuration: `${5 + Math.random() * 5}s`,
|
animationDuration: `${durationMin + Math.random() * (durationMax - durationMin)}s`,
|
||||||
transform: `scale(${0.5 + Math.random()})`
|
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 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 (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-pink-100 bg-opacity-90 overflow-hidden">
|
<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">
|
<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">
|
<div className="absolute top-0 left-0 w-full h-full pointer-events-none">
|
||||||
{hearts}
|
<FloatingElements />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,8 +81,7 @@ const CelebrationOverlay = () => {
|
|||||||
|
|
||||||
export default function LandingPage() {
|
export default function LandingPage() {
|
||||||
const noMessages = [
|
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 [noClickCount, setNoClickCount] = useState(0);
|
||||||
const [showCelebration, setShowCelebration] = useState(false);
|
const [showCelebration, setShowCelebration] = useState(false);
|
||||||
|
|
||||||
@@ -57,36 +93,48 @@ export default function LandingPage() {
|
|||||||
setNoClickCount((prevCount) => prevCount + 1);
|
setNoClickCount((prevCount) => prevCount + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentDescription = noClickCount < 5
|
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?";
|
||||||
? "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 currentHeroDescription = noClickCount === 0
|
||||||
|
? initialProposalDescription
|
||||||
: noMessages[Math.min(noClickCount - 1, noMessages.length - 1)];
|
: noMessages[Math.min(noClickCount - 1, noMessages.length - 1)];
|
||||||
|
|
||||||
const buttons = noClickCount < 5
|
const buttons = noClickCount < 6
|
||||||
? [
|
? [
|
||||||
{ text: "Yes", onClick: handleYesClick },
|
{ text: "Yes", onClick: handleYesClick },
|
||||||
{ text: "No", onClick: handleNoClick }
|
{ 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 = `
|
const globalStyles = `
|
||||||
@keyframes heart-fall {
|
@keyframes floating {
|
||||||
0% { transform: translateY(-100vh) rotate(0deg) scale(0); opacity: 0; }
|
0% { transform: translateY(-100vh) scale(0) rotate(0deg); opacity: 0; }
|
||||||
10% { opacity: 1; }
|
10% { opacity: 1; transform: translateY(-80vh) scale(1) rotate(20deg); }
|
||||||
100% { transform: translateY(100vh) rotate(360deg) scale(1.5); opacity: 0; }
|
50% { opacity: 1; transform: translateY(0vh) scale(1.2) rotate(-20deg); }
|
||||||
|
100% { transform: translateY(100vh) scale(0) rotate(0deg); opacity: 0; }
|
||||||
}
|
}
|
||||||
@keyframes fade-in {
|
@keyframes fade-in {
|
||||||
from { opacity: 0; transform: translateY(20px); }
|
from { opacity: 0; transform: translateY(20px); }
|
||||||
to { opacity: 1; transform: translateY(0); }
|
to { opacity: 1; transform: translateY(0); }
|
||||||
}
|
}
|
||||||
.animate-heart-fall {
|
@keyframes ring-pop {
|
||||||
animation: heart-fall linear infinite;
|
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 {
|
.animate-fade-in {
|
||||||
animation: fade-in 1s ease-out forwards;
|
animation: fade-in 1s ease-out forwards;
|
||||||
}
|
}
|
||||||
|
.animate-ring-pop {
|
||||||
|
animation: ring-pop 0.8s ease-out forwards;
|
||||||
|
}
|
||||||
html, body, #__next {
|
html, body, #__next {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -116,22 +164,22 @@ export default function LandingPage() {
|
|||||||
<HeroSplitDualMedia
|
<HeroSplitDualMedia
|
||||||
background={{ variant: "plain" }}
|
background={{ variant: "plain" }}
|
||||||
title="Bisma, will you marry me?"
|
title="Bisma, will you marry me?"
|
||||||
description={currentDescription}
|
description={currentHeroDescription}
|
||||||
tag="A Lifetime Together"
|
tag="My Dearest Love"
|
||||||
buttons={buttons}
|
buttons={buttons}
|
||||||
mediaItems={[
|
mediaItems={[
|
||||||
{ imageSrc: '', imageAlt: '' },
|
{ imageSrc: 'https://imagedelivery.net/qN7d-a1E2_g_t-wwxG89gQ/cb330456-e41c-4384-a82f-2f8021c33c00/public?_wi=1', imageAlt: 'Diamond ring placeholder' },
|
||||||
{ imageSrc: '', imageAlt: '' },
|
{ imageSrc: 'https://imagedelivery.net/qN7d-a1E2_g_t-wwxG89gQ/cb330456-e41c-4384-a82f-2f8021c33c00/public?_wi=2', imageAlt: 'Diamond ring placeholder' },
|
||||||
]}
|
]}
|
||||||
mediaAnimation="none"
|
mediaAnimation="none"
|
||||||
rating={0}
|
rating={0}
|
||||||
ratingText=""
|
ratingText=""
|
||||||
containerClassName="p-8 max-w-3xl text-center"
|
containerClassName="p-8 max-w-3xl text-center"
|
||||||
titleClassName="text-5xl font-extrabold mb-4 text-pink-800"
|
titleClassName="text-5xl md:text-6xl lg:text-7xl font-extrabold mb-4 text-pink-800"
|
||||||
descriptionClassName="text-xl text-pink-700 mb-8"
|
descriptionClassName="text-xl md:text-2xl text-pink-700 mb-8"
|
||||||
buttonContainerClassName="flex justify-center gap-4"
|
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"
|
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"
|
tagClassName="text-pink-500 mb-2 font-medium"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user