diff --git a/app/globals.css b/app/globals.css index 6d33e08..9350a78 100644 --- a/app/globals.css +++ b/app/globals.css @@ -61,4 +61,90 @@ .animate-fadeIn { animation: fadeIn 0.2s ease-out; } + + /* Animations pour le Hero Section */ + @keyframes float { + 0%, 100% { transform: translateY(0px) rotate(0deg); } + 25% { transform: translateY(-20px) rotate(5deg); } + 50% { transform: translateY(-10px) rotate(-5deg); } + 75% { transform: translateY(-15px) rotate(3deg); } + } + + @keyframes floatSlow { + 0%, 100% { transform: translateY(0px) translateX(0px) rotate(0deg); } + 33% { transform: translateY(-30px) translateX(10px) rotate(10deg); } + 66% { transform: translateY(-15px) translateX(-10px) rotate(-10deg); } + } + + @keyframes pulse { + 0%, 100% { opacity: 0.3; transform: scale(1); } + 50% { opacity: 0.5; transform: scale(1.05); } + } + + @keyframes steam { + 0% { opacity: 0.6; transform: translateY(0px) translateX(0px) scale(1); } + 50% { opacity: 0.3; transform: translateY(-30px) translateX(10px) scale(1.2); } + 100% { opacity: 0; transform: translateY(-60px) translateX(-10px) scale(1.5); } + } + + .float-animation { + animation: float 6s ease-in-out infinite; + } + + .float-slow { + animation: floatSlow 8s ease-in-out infinite; + } + + .pulse-animation { + animation: pulse 4s ease-in-out infinite; + } + + .steam-1 { + animation: steam 3s ease-out infinite; + animation-delay: 0s; + } + + .steam-2 { + animation: steam 3s ease-out infinite; + animation-delay: 1s; + } + + .steam-3 { + animation: steam 3s ease-out infinite; + animation-delay: 2s; + } + + /* Animation de descente douce du haut vers le bas sans rotation */ + @keyframes fallDown { + 0% { + transform: translateY(-100vh) translateX(0px); + opacity: 0; + } + 10% { + opacity: 0.5; + } + 20% { + transform: translateY(-60vh) translateX(15px); + } + 40% { + transform: translateY(-20vh) translateX(-10px); + } + 60% { + transform: translateY(20vh) translateX(20px); + } + 80% { + transform: translateY(60vh) translateX(-15px); + } + 90% { + opacity: 0.5; + } + 100% { + transform: translateY(100vh) translateX(0px); + opacity: 0; + } + } + + .animate-float-gentle { + animation: fallDown 15s linear infinite; + } } diff --git a/app/page.tsx b/app/page.tsx index 83b8021..785763f 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,76 +1,135 @@ -import type { Metadata } from "next"; +'use client'; + import Link from "next/link"; import Image from "next/image"; import Button from "@/components/Button"; - -export const metadata: Metadata = { - title: "Thé Tip Top - Grand Jeu Concours 10ème Anniversaire", - description: "Célébrez nos 10 ans ! 100% de tickets gagnants. Participez au jeu-concours et gagnez des lots exceptionnels.", -}; +import CountdownTimer from "@/components/CountdownTimer"; +import GamePeriod from "@/components/GamePeriod"; +import GrandPrize from "@/components/GrandPrize"; +import AboutContest from "@/components/AboutContest"; export default function HomePage() { return ( -
- {/* Hero Section - Bannière principale */} -
-
-
+
+ {/* Background avec icônes de thé */} +
+ {/* Fond dégradé beige clair */} +
+ + {/* Icônes de thé dispersées avec animation de descente - 35 icônes */} +
+ {/* Ligne 1 - 5 icons */} + + + + + + + {/* Ligne 2 - 5 icons */} + + + + + + + {/* Ligne 3 - 5 icons */} + + + + + + + {/* Ligne 4 - 5 icons */} + + + + + + + {/* Ligne 5 - 5 icons */} + + + + + + + {/* Ligne 6 - 5 icons */} + + + + + + + {/* Ligne 7 - 5 icons */} + + + + +
+ {/* Overlay lumineux pour harmoniser */} +
+
+ + {/* Hero Section - Bannière principale */} +
+
-

- Un code, un gain garanti ! +

+ Jeu Concours Thé Tip Top
+ Nice

-

- Célébrez l'ouverture de notre 10e boutique avec notre grand jeu-concours. -
- 100% des participants gagnent un magnifique lot ! +

+ À l'occasion de l'ouverture de notre 10ème boutique de thé premium à Nice,
+ participez à notre concours et gagnez des thés et accessoires exclusifs !

-
+
- - - - -
- - {/* Stats badges */} -
-
- - - - 100% sécurisé -
-
- - - - 100% gagnants -
-
- - - - - 500 000 codes -
+ {/* Game Period & Countdown Section */} +
+
+
+ {/* Countdown Timer */} + + + {/* Game Period Cards */} + + + {/* Grand Prize Banner */} + +
+
+
+ + {/* About Contest Section */} + + {/* How to Participate Section */} -
+

@@ -134,7 +193,7 @@ export default function HomePage() {

{/* Prizes Section */} -
+

@@ -244,44 +303,6 @@ export default function HomePage() {

- {/* Stats Section */} -
-
-
-
-
-
100%
-
Gagnants garantis
-
-
-
500k
-
Codes disponibles
-
-
-
10
-
Boutiques en France
-
-
-
360€
-
Gain en jeu
-
-
- -
-
- - - - Jeu-concours certifié et contrôlé par un huissier de justice. Vos données sont protégées conformément au RGPD. -
-

- Thés 100% bio et artisanaux. -

-
-
-
-
-
); } diff --git a/components/AboutContest.tsx b/components/AboutContest.tsx new file mode 100644 index 0000000..7766296 --- /dev/null +++ b/components/AboutContest.tsx @@ -0,0 +1,130 @@ +'use client'; + +import Image from 'next/image'; +import Link from 'next/link'; +import Button from './Button'; + +interface AboutContestProps { + title?: string; + description?: string; + imageUrl?: string; +} + +export default function AboutContest({ + title = "Jeu Concours Thé Tip Top - Boutique de Thé Premium à Nice", + description, + imageUrl = "/images/tea-collection.jpg", +}: AboutContestProps) { + const defaultDescription = ` + Bienvenue dans notre grand jeu-concours Thé Tip Top organisé à l'occasion de l'ouverture de notre 10ème boutique de thé premium à Nice. + Nous vous offrons la chance de gagner des produits exceptionnels : thés bio, accessoires exclusifs et bien plus encore. + + Participez facilement en quelques clics et tentez votre chance parmi nos lots prestigieux. + Avec 100% de tickets gagnants, chaque participation vous offre la garantie de repartir avec un cadeau ! + `; + + return ( +
+
+
+
+ {/* Texte */} +
+

+ {title} +

+ +
+ {(description || defaultDescription).split('\n').filter(p => p.trim()).map((paragraph, index) => ( +

+ {paragraph.trim()} +

+ ))} +
+ + {/* Points clés */} +
+
+ + + + + 100% de gagnants : Chaque ticket acheté à 49€ vous fait gagner un lot + +
+ +
+ + + + + Résultat immédiat : Découvrez instantanément votre lot en ligne + +
+ +
+ + + + + Thés bio et artisanaux : Tous nos produits sont de qualité premium + +
+
+ + + + +
+ + {/* Image */} +
+
+ {/* Fallback avec illustration CSS si l'image n'existe pas */} +
+ {/* Motif décoratif */} +
+
+
+ + {/* Icône de thé */} +
+
🍵
+
+ + {/* Badges décoratifs */} +
+ 10 ans +
+
+ Premium Bio +
+
+ + {/* Note: Vous pouvez remplacer le div ci-dessus par une vraie image : + Collection de thés Thé Tip Top + */} +
+
+
+
+
+
+ ); +} diff --git a/components/Button.tsx b/components/Button.tsx index 55955c0..e819b0f 100644 --- a/components/Button.tsx +++ b/components/Button.tsx @@ -27,15 +27,15 @@ const Button = forwardRef( const variants = { primary: - "bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500", + "bg-[#d4a574] text-white hover:bg-[#c4956a] focus:ring-[#d4a574] shadow-md hover:shadow-lg", secondary: - "bg-secondary-500 text-white hover:bg-secondary-600 focus:ring-secondary-500", + "bg-white text-[#5a5a4e] hover:bg-[#d4a574] hover:text-white focus:ring-[#d4a574] border border-[#e5e4dc] shadow-sm", outline: - "border-2 border-primary-600 text-primary-600 hover:bg-primary-50 focus:ring-primary-500", + "border-2 border-[#d4a574] text-[#d4a574] hover:bg-[#d4a574] hover:text-white focus:ring-[#d4a574] shadow-sm", danger: - "bg-red-600 text-white hover:bg-red-700 focus:ring-red-500", + "bg-red-600 text-white hover:bg-red-700 focus:ring-red-500 shadow-md", success: - "bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500", + "bg-[#1a4d2e] text-white hover:bg-[#2d5a3d] focus:ring-[#1a4d2e] shadow-md hover:shadow-lg", }; const sizes = { diff --git a/components/CountdownTimer.tsx b/components/CountdownTimer.tsx new file mode 100644 index 0000000..231b2b6 --- /dev/null +++ b/components/CountdownTimer.tsx @@ -0,0 +1,111 @@ +'use client'; + +import { useEffect, useState } from 'react'; + +interface CountdownTimerProps { + endDate: Date; + title?: string; +} + +export default function CountdownTimer({ endDate, title = "Période de jeu" }: CountdownTimerProps) { + const [timeLeft, setTimeLeft] = useState({ + days: 0, + hours: 0, + minutes: 0, + seconds: 0, + }); + const [progress, setProgress] = useState(0); + + useEffect(() => { + const calculateTimeLeft = () => { + const now = new Date().getTime(); + const end = endDate.getTime(); + const difference = end - now; + + if (difference > 0) { + const days = Math.floor(difference / (1000 * 60 * 60 * 24)); + const hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + const minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((difference % (1000 * 60)) / 1000); + + setTimeLeft({ days, hours, minutes, seconds }); + + // Calcul du pourcentage écoulé (exemple: 30 jours de concours) + const totalDuration = 30 * 24 * 60 * 60 * 1000; // 30 jours en ms + const elapsed = totalDuration - difference; + const progressPercent = Math.min(Math.max((elapsed / totalDuration) * 100, 0), 100); + setProgress(progressPercent); + } else { + setTimeLeft({ days: 0, hours: 0, minutes: 0, seconds: 0 }); + setProgress(100); + } + }; + + calculateTimeLeft(); + const timer = setInterval(calculateTimeLeft, 1000); + + return () => clearInterval(timer); + }, [endDate]); + + return ( +
+
+

{title}

+

Utilisez vos tickets pour jouer et gagner des lots !

+
+ + {/* Compteur principal */} +
+
+
+ + {timeLeft.days} + + + jour{timeLeft.days !== 1 ? 's' : ''} + +
+
restants
+
+ + {/* Détails temps */} +
+
+
+
{String(timeLeft.hours).padStart(2, '0')}
+
heures
+
+
+
:
+
+
+
{String(timeLeft.minutes).padStart(2, '0')}
+
minutes
+
+
+
:
+
+
+
{String(timeLeft.seconds).padStart(2, '0')}
+
secondes
+
+
+
+ + {/* Barre de progression */} +
+
+
+
+
+ Début du concours + {Math.round(progress)}% écoulé +
+
+
+
+ ); +} diff --git a/components/Footer.tsx b/components/Footer.tsx index c4f12b7..d3464ed 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -8,17 +8,16 @@ export default function Footer() { const currentYear = new Date().getFullYear(); return ( -