From f0ea3e963a19e8e4609e0725e80ca7a575be1e39 Mon Sep 17 00:00:00 2001 From: DaX Date: Sun, 6 Jul 2025 02:55:08 +0200 Subject: [PATCH] Add sale countdown timer expiring next Sunday - Created SaleCountdown component with real-time countdown - Displays days, hours, minutes, seconds until sale ends - Responsive design with fire emoji and urgency messaging - Auto-calculates next Sunday at 23:59:59 - Positioned prominently above filament table --- app/page.tsx | 3 + scripts/pre-commit.sh | 6 ++ src/components/SaleCountdown.tsx | 99 ++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 src/components/SaleCountdown.tsx diff --git a/app/page.tsx b/app/page.tsx index 81dc8a3..bce225c 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react'; import { FilamentTableV2 } from '../src/components/FilamentTableV2'; +import { SaleCountdown } from '../src/components/SaleCountdown'; import { Filament } from '../src/types/filament'; import { filamentService } from '../src/services/api'; import { trackEvent } from '../src/components/MatomoAnalytics'; @@ -174,6 +175,8 @@ export default function Home() { + + ({ days: 0, hours: 0, minutes: 0, seconds: 0 }); + const [mounted, setMounted] = useState(false); + + useEffect(() => { + setMounted(true); + }, []); + + useEffect(() => { + if (!mounted) return; + + const calculateTimeLeft = (): TimeLeft => { + // Get next Sunday at 23:59:59 + const now = new Date(); + const nextSunday = new Date(); + const daysUntilSunday = (7 - now.getDay()) % 7; + const targetDay = daysUntilSunday === 0 ? 7 : daysUntilSunday; // If today is Sunday, target next Sunday + + nextSunday.setDate(now.getDate() + targetDay); + nextSunday.setHours(23, 59, 59, 999); + + const difference = nextSunday.getTime() - now.getTime(); + + if (difference > 0) { + return { + days: Math.floor(difference / (1000 * 60 * 60 * 24)), + hours: Math.floor((difference / (1000 * 60 * 60)) % 24), + minutes: Math.floor((difference / 1000 / 60) % 60), + seconds: Math.floor((difference / 1000) % 60) + }; + } + + return { days: 0, hours: 0, minutes: 0, seconds: 0 }; + }; + + const timer = setInterval(() => { + setTimeLeft(calculateTimeLeft()); + }, 1000); + + // Initial calculation + setTimeLeft(calculateTimeLeft()); + + return () => clearInterval(timer); + }, [mounted]); + + if (!mounted) { + return
; // Placeholder to prevent hydration mismatch + } + + const isActive = timeLeft.days > 0 || timeLeft.hours > 0 || timeLeft.minutes > 0 || timeLeft.seconds > 0; + + if (!isActive) return null; + + return ( +
+
+

đŸ”„ AKCIJA SE ZAVRĆ AVA!

+

Popust od 5% vaĆŸi joĆĄ:

+ +
+
+
{timeLeft.days}
+
dana
+
+ +
+
{timeLeft.hours.toString().padStart(2, '0')}
+
sati
+
+ +
+
{timeLeft.minutes.toString().padStart(2, '0')}
+
min
+
+ +
+
{timeLeft.seconds.toString().padStart(2, '0')}
+
sek
+
+
+ +

+ Poruči sada i uơtedi na Bambu Lab filamentima! +

+
+
+ ); +} \ No newline at end of file