|
|
|
|
@@ -4,6 +4,43 @@ import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
|
|
|
|
|
import SiteBackgroundSlot from "@/components/ui/SiteBackgroundSlot";
|
|
|
|
|
import { Outlet } from 'react-router-dom';
|
|
|
|
|
import { StyleProvider } from "@/components/ui/StyleProvider";
|
|
|
|
|
import { useState, useEffect } from 'react';
|
|
|
|
|
import { Timer } from 'lucide-react';
|
|
|
|
|
import Button from '@/components/ui/Button';
|
|
|
|
|
|
|
|
|
|
function FloatingDiscount() {
|
|
|
|
|
const [timeLeft, setTimeLeft] = useState(300);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (timeLeft <= 0) return;
|
|
|
|
|
const timer = setInterval(() => setTimeLeft(t => t - 1), 1000);
|
|
|
|
|
return () => clearInterval(timer);
|
|
|
|
|
}, [timeLeft]);
|
|
|
|
|
|
|
|
|
|
const mins = Math.floor(timeLeft / 60);
|
|
|
|
|
const secs = timeLeft % 60;
|
|
|
|
|
|
|
|
|
|
if (timeLeft <= 0) return null;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="fixed bottom-6 left-1/2 -translate-x-1/2 z-50 animate-in slide-in-from-bottom-10 fade-in duration-500">
|
|
|
|
|
<div className="relative p-[2px] rounded-full overflow-hidden shadow-2xl">
|
|
|
|
|
<div className="absolute top-1/2 left-1/2 aspect-square w-[300%] -translate-x-1/2 -translate-y-1/2 bg-[conic-gradient(from_0deg,transparent_0_340deg,white_360deg)] animate-[spin_2s_linear_infinite]" />
|
|
|
|
|
<div className="relative bg-primary-cta text-primary-cta-text px-4 py-2 md:px-6 md:py-3 rounded-full flex items-center gap-3 md:gap-4 whitespace-nowrap">
|
|
|
|
|
<div className="flex items-center gap-2 font-medium text-sm md:text-base">
|
|
|
|
|
<Timer className="w-4 h-4 md:w-5 md:h-5" />
|
|
|
|
|
<span className="hidden sm:inline bg-gradient-to-r from-white via-white/50 to-white bg-[length:200%_auto] animate-shimmer bg-clip-text text-transparent">Claim 20% Off Today!</span>
|
|
|
|
|
<span className="sm:hidden bg-gradient-to-r from-white via-white/50 to-white bg-[length:200%_auto] animate-shimmer bg-clip-text text-transparent">20% Off!</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="bg-background/20 px-2 py-1 md:px-3 md:py-1 rounded-md font-mono font-bold tracking-wider text-sm md:text-base">
|
|
|
|
|
{mins}:{secs.toString().padStart(2, '0')}
|
|
|
|
|
</div>
|
|
|
|
|
<button className="bg-white text-primary-cta px-3 py-1 md:px-4 md:py-1.5 rounded-full text-xs md:text-sm font-semibold hover:bg-white/90 transition-colors">Opt In</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function Layout() {
|
|
|
|
|
const navItems = [
|
|
|
|
|
@@ -52,6 +89,7 @@ export default function Layout() {
|
|
|
|
|
<main className="flex-grow">
|
|
|
|
|
<Outlet />
|
|
|
|
|
</main>
|
|
|
|
|
<FloatingDiscount />
|
|
|
|
|
<SectionErrorBoundary name="footer">
|
|
|
|
|
<FooterBasic
|
|
|
|
|
columns={[
|
|
|
|
|
|