import React, { useEffect, useMemo, useRef, useState } from "react";
import { Wine, Clock, Play, Pause, RotateCcw, Sparkles, Star } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
// Five‑Star Wine Timer — v3
// Premium + playful: glassy UI, gold accents, micro‑animations, confetti bubbles
// JOKE MENU: wine • wine • wine — all identical
// Logic: each tap on any wine adds +120s to countdown
export default function WineTimerApp() {
const [timeLeft, setTimeLeft] = useState(0); // seconds
const [isRunning, setIsRunning] = useState(false);
const [glasses, setGlasses] = useState(0);
const [toasts, setToasts] = useState([]); // ephemeral +2:00 badges
const [sessionActive, setSessionActive] = useState(false); // NEW: gate timer until session begins
const intervalRef = useRef(null);
// ===== Helpers =====
const formatted = useMemo(() => {
const m = Math.floor(timeLeft / 60).toString().padStart(2, "0");
const s = Math.floor(timeLeft % 60).toString().padStart(2, "0");
return `${m}:${s}`;
}, [timeLeft]);
// ===== Ticker =====
useEffect(() => {
if (!isRunning) return;
if (!sessionActive) {
// Safety: pause if session isn't active
setIsRunning(false);
return;
}
if (timeLeft <= 0) {
setIsRunning(false);
return;
}
intervalRef.current = setInterval(() => setTimeLeft((t) => (t > 0 ? t - 1 : 0)), 1000);
return () => intervalRef.current && clearInterval(intervalRef.current);
}, [isRunning, timeLeft, sessionActive]);
// ===== Actions =====
const addWine = () => {
setGlasses((g) => g + 1);
setTimeLeft((t) => t + 120);
const id = Math.random().toString(36).slice(2);
setToasts((old) => [...old, { id }]);
setTimeout(() => setToasts((old) => old.filter((x) => x.id !== id)), 1200);
};
const start = () => sessionActive && timeLeft > 0 && setIsRunning(true);
const pause = () => setIsRunning(false);
const reset = () => {
setIsRunning(false);
setTimeLeft(0);
setGlasses(0);
};
// Quick add: cardio tile adds +5:00
const addCardio = () => {
setTimeLeft((t) => t + 300);
const id = Math.random().toString(36).slice(2);
setToasts((old) => [...old, { id }]);
setTimeout(() => setToasts((old) => old.filter((x) => x.id !== id)), 1200);
};
// ===== UI Bits =====
const GoldFrame = ({ children, className = "" }) => (
<div className={`rounded-3xl p-[1px] bg-gradient-to-r from-amber-300 via-yellow-200 to-amber-400 ${className}`}>
<div className="rounded-3xl bg-zinc-950/60 backdrop-blur-xl border border-white/10">{children}</div>
</div>
);
const ControlButton = ({ onClick, disabled, icon: Icon, children, glow = "" }) => (
<button
onClick={onClick}
disabled={disabled}
className={`inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-semibold transition focus:outline-none focus:ring-2 focus:ring-amber-300 disabled:opacity-40 ${
glow || ""
}`}
style={{
background:
"radial-gradient(120% 120% at 50% 0%, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0.06) 60%, rgba(255,255,255,0.02) 100%)",
border: "1px solid rgba(255,255,255,0.12)",
}}
>
<Icon className="h-4 w-4" /> {children}
</button>
);
const MenuCard = ({ label }) => (
<motion.button
onClick={addWine}
whileTap={{ scale: 0.98 }}
whileHover={{ y: -2 }}
className="group relative overflow-hidden rounded-2xl border border-white/10 bg-white/5 p-4 text-left shadow-xl backdrop-blur-lg"
>
{/* shimmering highlight */}
<div className="pointer-events-none absolute -left-10 -top-20 h-40 w-64 rotate-12 bg-gradient-to-r from-white/20 via-white/5 to-transparent blur-2xl transition-opacity duration-500 group-hover:opacity-80" />
<div className="flex items-center gap-4">
<div className="relative">
<Wine className="h-9 w-9" />
<Sparkles className="absolute -right-1 -top-1 h-3 w-3 opacity-0 transition group-hover:opacity-100" />
</div>
<div>
<div className="font-serif text-lg font-semibold tracking-wide">{label}</div>
<div className="text-sm text-white/75">Sommelier’s Note: adds <span className="font-semibold">+2:00</span> 🍷</div>
</div>
<div className="ml-auto rounded-full border border-amber-300/40 bg-amber-300/10 px-3 py-1 text-xs text-amber-100">Tap to pour</div>
</div>
{/* faux wax seal */}
<div className="pointer-events-none absolute bottom-2 right-3 select-none rounded-full border border-rose-300/30 bg-rose-500/30 px-2 py-1 text-[10px] tracking-wider text-rose-50/90">CHEF’S PICK</div>
</motion.button>
);
// Animated wine bubbles (confetti vibes)
const Bubbles = () => (
<AnimatePresence>
{toasts.map((t) => (
<motion.div
key={t.id}
initial={{ opacity: 0, y: 12, scale: 0.9 }}
animate={{ opacity: 1, y: -18, scale: 1 }}
exit={{ opacity: 0, y: -36 }}
transition={{ duration: 0.7 }}
className="pointer-events-none absolute right-6 top-6 inline-flex items-center gap-2 rounded-full bg-white/10 px-3 py-1 text-sm"
>
<Clock className="h-4 w-4" /> +2:00
</motion.div>
))}
</AnimatePresence>
);
// Golden treadmill inline SVG
const TreadmillIcon = () => (
<svg viewBox="0 0 64 64" className="h-8 w-8" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stopColor="#FDE68A" />
<stop offset="50%" stopColor="#F59E0B" />
<stop offset="100%" stopColor="#FCD34D" />
</linearGradient>
</defs>
<path d="M10 50h36c4 0 6 2 6 6H8c0-4 2-6 2-6Z" fill="url(#g)" opacity="0.3" />
<rect x="8" y="44" width="40" height="4" rx="2" fill="url(#g)" />
<path d="M12 24h6l6 16h-6l-6-16Z" fill="url(#g)" />
<rect x="24" y="18" width="8" height="8" rx="1.5" fill="url(#g)" />
<rect x="34" y="16" width="4" height="18" rx="1.5" fill="url(#g)" />
</svg>
);
return (
<div className="min-h-screen w-full relative text-white">
{/* premium background */}
<div className="absolute inset-0 -z-10">
<div className="absolute inset-0 bg-[radial-gradient(80%_60%_at_50%_0%,rgba(255,214,165,0.12),transparent_60%)]" />
<div className="absolute inset-0 bg-gradient-to-br from-[#0a0a0a] via-[#0b0b0b] to-black" />
</div>
<div className="mx-auto max-w-4xl px-4 pb-24 pt-12">
{/* Header */}
<div className="mb-8 flex flex-wrap items-end justify-between gap-4">
<div>
<div className="flex items-center gap-2 text-amber-200">
<Star className="h-4 w-4" /> <Star className="h-4 w-4" /> <Star className="h-4 w-4" /> <Star className="h-4 w-4" /> <Star className="h-4 w-4" />
</div>
<h1 className="mt-2 font-serif text-4xl font-bold leading-tight tracking-tight">Maison du Pinot</h1>
<p className="mt-1 text-sm text-white/75">Tonight’s tasting menu: wine, wine, and… wine. All identical. Très chic.</p>
</div>
<motion.div
initial={{ rotate: -8, scale: 0.9 }}
animate={{ rotate: 0, scale: 1 }}
transition={{ type: "spring", stiffness: 220, damping: 14 }}
className="rounded-full border border-amber-200/20 bg-amber-200/10 p-3"
>
<Wine className="h-6 w-6" />
</motion.div>
</div>
{/* Session Gate & Timer */}
<GoldFrame>
<div className="relative grid grid-cols-1 gap-6 p-6 md:grid-cols-[1fr_auto] md:items-center">
<div>
<div className="text-[11px] uppercase tracking-[0.2em] text-white/70">Table Timer</div>
<div className="mt-1 flex items-baseline gap-3">
<div className="text-6xl font-black tabular-nums drop-shadow-sm">{formatted}</div>
<div className="rounded-full border border-amber-300/30 bg-amber-300/10 px-3 py-1 text-xs text-amber-50">{glasses} glass{glasses === 1 ? "" : "es"}</div>
</div>
{/* Session lock note */}
<div className="mt-3 flex items-center gap-2 text-xs text-white/70">
<div className={`h-2 w-2 rounded-full ${sessionActive ? "bg-emerald-400" : "bg-rose-400"}`} />
{sessionActive ? "Session is active — you can start the timer." : "Timer locked until session begins."}
</div>
</div>
<div className="flex flex-col items-stretch gap-2 md:items-end">
<ControlButton onClick={() => setSessionActive(true)} disabled={sessionActive} icon={Play} glow="hover:shadow-[0_0_30px_rgba(251,191,36,0.35)]">
Begin Session
</ControlButton>
<div className="flex gap-2">
<ControlButton onClick={start} disabled={!sessionActive || isRunning || timeLeft <= 0} icon={Play} glow="hover:shadow-[0_0_30px_rgba(16,185,129,0.25)]">
Start
</ControlButton>
<ControlButton onClick={pause} disabled={!isRunning} icon={Pause} glow="hover:shadow-[0_0_30px_rgba(245,158,11,0.25)]">
Pause
</ControlButton>
<ControlButton onClick={reset} disabled={false} icon={RotateCcw} glow="hover:shadow-[0_0_30px_rgba(244,63,94,0.25)]">
Reset
</ControlButton>
</div>
</div>
{/* floating +2:00 */}
<Bubbles />
</div>
</GoldFrame>
{/* Menu */}
<div className="mt-8 text-[11px] uppercase tracking-[0.25em] text-white/70">Chef’s Menu</div>
<div className="mt-3 grid grid-cols-1 gap-4 md:grid-cols-3">
<MenuCard label="Wine — House Red" />
<MenuCard label="Wine — House Red" />
<MenuCard label="Wine — House Red" />
</div>
{/* Little button underneath (as requested) */}
<div className="mt-6 grid grid-cols-1">
<button onClick={addCardio} className="group flex w-full items-center gap-4 rounded-2xl border border-amber-300/30 bg-amber-300/10 p-4 text-left shadow-md transition hover:bg-amber-300/15">
<div className="rounded-2xl bg-amber-300/10 p-2 ring-1 ring-amber-300/30">
<TreadmillIcon />
</div>
<div>
<div className="font-serif text-lg font-semibold text-amber-100">biscuts and chesse? cardio please</div>
<div className="text-sm text-amber-200/90">5.0 • 5 min walk</div>
</div>
<div className="ml-auto rounded-full border border-amber-300/40 bg-amber-300/10 px-3 py-1 text-xs text-amber-100 opacity-80 group-hover:opacity-100">+5:00</div>
</button>
</div>
<p className="mt-8 text-center text-sm text-white/70">Each glass adds <span className="font-semibold text-amber-200">2 minutes</span> to your countdown. Drink responsibly — even in pretend apps. 🍷</p>
</div>
</div>
);
}