- Migrate from tailwindcss v3.3 to v4.1.18 - Replace @tailwind directives with @import 'tailwindcss' - Move custom colors to @theme block in globals.css - Convert custom utilities to @utility syntax - Update PostCSS config to use @tailwindcss/postcss - Remove autoprefixer (now built-in)
104 lines
4.5 KiB
TypeScript
104 lines
4.5 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
import { Sparkles, GlassWater, Dices, X } from 'lucide-react';
|
|
import { useI18n } from '@/i18n/I18nContext';
|
|
import Link from 'next/link';
|
|
|
|
interface Bottle {
|
|
id: string;
|
|
name: string;
|
|
distillery?: string;
|
|
status: 'sealed' | 'open' | 'sampled' | 'empty';
|
|
}
|
|
|
|
interface DramOfTheDayProps {
|
|
bottles: Bottle[];
|
|
}
|
|
|
|
export default function DramOfTheDay({ bottles }: DramOfTheDayProps) {
|
|
const { t } = useI18n();
|
|
const [suggestion, setSuggestion] = useState<Bottle | null>(null);
|
|
const [isRolling, setIsRolling] = useState(false);
|
|
|
|
const suggestDram = () => {
|
|
setIsRolling(true);
|
|
const openBottles = bottles.filter(b => b.status === 'open' || b.status === 'sampled');
|
|
|
|
if (openBottles.length === 0) {
|
|
alert(t('home.dramOfDay.noOpenBottles'));
|
|
setIsRolling(false);
|
|
return;
|
|
}
|
|
|
|
// Simulate a "roll" for 800ms
|
|
setTimeout(() => {
|
|
const randomBottle = openBottles[Math.floor(Math.random() * openBottles.length)];
|
|
setSuggestion(randomBottle);
|
|
setIsRolling(false);
|
|
}, 800);
|
|
};
|
|
|
|
return (
|
|
<div className="relative">
|
|
<button
|
|
onClick={suggestDram}
|
|
disabled={isRolling}
|
|
className="flex items-center gap-2 px-4 sm:px-6 py-2 sm:py-3 bg-orange-600 hover:bg-orange-700 text-white rounded-2xl font-bold uppercase tracking-widest text-[10px] sm:text-xs transition-all shadow-lg shadow-orange-950/20 active:scale-95 disabled:opacity-50"
|
|
>
|
|
{isRolling ? (
|
|
<Dices size={18} className="animate-spin" />
|
|
) : (
|
|
<Sparkles size={18} />
|
|
)}
|
|
{t('home.dramOfDay.button')}
|
|
</button>
|
|
|
|
{suggestion && (
|
|
<div className="fixed inset-0 z-100 flex items-center justify-center p-6 bg-zinc-950/80 backdrop-blur-xs animate-in fade-in duration-300">
|
|
<div className="bg-zinc-900 w-full max-w-sm rounded-[40px] p-8 shadow-2xl border border-orange-500/20 relative animate-in zoom-in-95 duration-300">
|
|
<button
|
|
onClick={() => setSuggestion(null)}
|
|
className="absolute top-6 right-6 text-zinc-500 hover:text-orange-600"
|
|
>
|
|
<X size={24} />
|
|
</button>
|
|
|
|
<div className="flex flex-col items-center text-center space-y-6">
|
|
<div className="w-20 h-20 bg-orange-900/30 rounded-3xl flex items-center justify-center text-orange-600">
|
|
<GlassWater size={40} strokeWidth={2.5} />
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<h3 className="text-[10px] font-bold uppercase tracking-[0.2em] text-orange-600">{t('home.dramOfDay.title')}</h3>
|
|
<h2 className="text-2xl font-bold text-zinc-50 leading-tight uppercase">
|
|
{suggestion.name}
|
|
</h2>
|
|
{suggestion.distillery && (
|
|
<p className="text-zinc-500 font-bold italic">{suggestion.distillery}</p>
|
|
)}
|
|
</div>
|
|
|
|
<div className="w-full pt-4">
|
|
<Link
|
|
href={`/bottles/${suggestion.id}`}
|
|
onClick={() => setSuggestion(null)}
|
|
className="block w-full py-4 bg-orange-600 text-white rounded-2xl font-bold uppercase tracking-widest text-xs hover:bg-orange-700 transition-all shadow-xl shadow-orange-950/20"
|
|
>
|
|
{t('home.dramOfDay.viewBottle')}
|
|
</Link>
|
|
<button
|
|
onClick={suggestDram}
|
|
className="w-full mt-3 py-2 text-zinc-500 hover:text-orange-600 text-[10px] font-bold uppercase tracking-widest transition-colors"
|
|
>
|
|
{t('home.dramOfDay.rollAgain')}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|