feat: optimize layout for mobile devices (Pixel 9 Pro)
This commit is contained in:
@@ -29,8 +29,8 @@ export default async function BottlePage({ params }: { params: { id: string } })
|
|||||||
.order('created_at', { ascending: false });
|
.order('created_at', { ascending: false });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="min-h-screen bg-zinc-50 dark:bg-black p-6 md:p-12 lg:p-24">
|
<main className="min-h-screen bg-zinc-50 dark:bg-black p-4 md:p-12 lg:p-24">
|
||||||
<div className="max-w-4xl mx-auto space-y-12">
|
<div className="max-w-4xl mx-auto space-y-6 md:space-y-12">
|
||||||
{/* Back Button */}
|
{/* Back Button */}
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/"
|
||||||
@@ -52,10 +52,10 @@ export default async function BottlePage({ params }: { params: { id: string } })
|
|||||||
|
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-4xl font-black text-zinc-900 dark:text-white tracking-tight leading-tight">
|
<h1 className="text-2xl md:text-4xl font-black text-zinc-900 dark:text-white tracking-tighter leading-tight">
|
||||||
{bottle.name}
|
{bottle.name}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-xl text-amber-600 font-bold mt-1 uppercase tracking-widest">{bottle.distillery}</p>
|
<p className="text-sm md:text-xl text-amber-600 font-bold mt-1 uppercase tracking-widest">{bottle.distillery}</p>
|
||||||
|
|
||||||
{bottle.whiskybase_id && (
|
{bottle.whiskybase_id && (
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export default function Home() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="flex min-h-screen flex-col items-center gap-12 p-6 md:p-24 bg-zinc-50 dark:bg-black">
|
<main className="flex min-h-screen flex-col items-center gap-6 md:gap-12 p-4 md:p-24 bg-zinc-50 dark:bg-black">
|
||||||
<div className="z-10 max-w-5xl w-full flex flex-col items-center gap-8">
|
<div className="z-10 max-w-5xl w-full flex flex-col items-center gap-8">
|
||||||
<header className="w-full flex justify-between items-center">
|
<header className="w-full flex justify-between items-center">
|
||||||
<h1 className="text-4xl font-black text-zinc-900 dark:text-white tracking-tighter">
|
<h1 className="text-4xl font-black text-zinc-900 dark:text-white tracking-tighter">
|
||||||
|
|||||||
@@ -59,10 +59,10 @@ function BottleCard({ bottle }: BottleCardProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-5 space-y-4">
|
<div className="p-3 md:p-5 space-y-3 md:space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex justify-between items-start mb-1">
|
<div className="flex justify-between items-start mb-1">
|
||||||
<p className="text-[10px] font-black text-amber-600 uppercase tracking-[0.2em] leading-none">{bottle.distillery}</p>
|
<p className="text-[9px] md:text-[10px] font-black text-amber-600 uppercase tracking-[0.2em] leading-none">{bottle.distillery}</p>
|
||||||
{(bottle.is_whisky === false || (bottle.confidence && bottle.confidence < 70)) && (
|
{(bottle.is_whisky === false || (bottle.confidence && bottle.confidence < 70)) && (
|
||||||
<div className="flex items-center gap-1 text-[8px] font-black bg-red-500 text-white px-1.5 py-0.5 rounded-full animate-pulse">
|
<div className="flex items-center gap-1 text-[8px] font-black bg-red-500 text-white px-1.5 py-0.5 rounded-full animate-pulse">
|
||||||
<AlertCircle size={8} />
|
<AlertCircle size={8} />
|
||||||
@@ -70,24 +70,24 @@ function BottleCard({ bottle }: BottleCardProps) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<h3 className={`font-black text-xl leading-tight group-hover:text-amber-600 transition-colors line-clamp-2 min-h-[3.5rem] flex items-center ${bottle.is_whisky === false ? 'text-red-600 dark:text-red-400' : 'text-zinc-900 dark:text-zinc-100'
|
<h3 className={`font-black text-lg md:text-xl leading-tight group-hover:text-amber-600 transition-colors line-clamp-2 min-h-[3rem] md:min-h-[3.5rem] flex items-center ${bottle.is_whisky === false ? 'text-red-600 dark:text-red-400' : 'text-zinc-900 dark:text-zinc-100'
|
||||||
}`}>
|
}`}>
|
||||||
{bottle.name || 'Unbekannte Flasche'}
|
{bottle.name || 'Unbekannte Flasche'}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-1.5 md:gap-2">
|
||||||
<span className="px-2.5 py-1 bg-zinc-100 dark:bg-zinc-800 text-zinc-600 dark:text-zinc-400 text-[10px] font-black uppercase tracking-widest rounded-lg border border-zinc-200/50 dark:border-zinc-700/50">
|
<span className="px-2 py-0.5 md:px-2.5 md:py-1 bg-zinc-100 dark:bg-zinc-800 text-zinc-600 dark:text-zinc-400 text-[9px] md:text-[10px] font-black uppercase tracking-widest rounded-lg border border-zinc-200/50 dark:border-zinc-700/50">
|
||||||
{bottle.category}
|
{bottle.category}
|
||||||
</span>
|
</span>
|
||||||
<span className="px-2.5 py-1 bg-amber-50 dark:bg-amber-900/20 text-amber-700 dark:text-amber-400 text-[10px] font-black uppercase tracking-widest rounded-lg border border-amber-200/50 dark:border-amber-800/20">
|
<span className="px-2 py-0.5 md:px-2.5 md:py-1 bg-amber-50 dark:bg-amber-900/20 text-amber-700 dark:text-amber-400 text-[9px] md:text-[10px] font-black uppercase tracking-widest rounded-lg border border-amber-200/50 dark:border-amber-800/20">
|
||||||
{bottle.abv}% VOL
|
{bottle.abv}% VOL
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pt-2 flex items-center gap-2 text-[10px] font-bold text-zinc-400 uppercase tracking-wider border-t border-zinc-100 dark:border-zinc-800">
|
<div className="pt-1 md:pt-2 flex items-center gap-2 text-[9px] md:text-[10px] font-bold text-zinc-400 uppercase tracking-wider border-t border-zinc-100 dark:border-zinc-800">
|
||||||
<Calendar size={12} className="text-zinc-300" />
|
<Calendar size={10} className="text-zinc-300" />
|
||||||
<span className="opacity-70 text-[9px]">Hinzugefügt am</span>
|
<span className="opacity-70 text-[8px] md:text-[9px]">Hinzugefügt am</span>
|
||||||
<span className="text-zinc-500 dark:text-zinc-300">{new Date(bottle.created_at).toLocaleDateString('de-DE')}</span>
|
<span className="text-zinc-500 dark:text-zinc-300">{new Date(bottle.created_at).toLocaleDateString('de-DE')}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -187,14 +187,14 @@ export default function BottleGrid({ bottles }: BottleGridProps) {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-6">
|
||||||
{/* Category Filter */}
|
{/* Category Filter */}
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<span className="text-[10px] font-black uppercase tracking-widest text-zinc-400 px-1">Kategorie</span>
|
<span className="text-[10px] font-black uppercase tracking-widest text-zinc-400 px-1">Kategorie</span>
|
||||||
<div className="flex gap-2 overflow-x-auto pb-2 scrollbar-hide">
|
<div className="flex gap-2 overflow-x-auto -mx-4 px-4 pb-2 scrollbar-hide touch-pan-x">
|
||||||
<button
|
<button
|
||||||
onClick={() => setSelectedCategory(null)}
|
onClick={() => setSelectedCategory(null)}
|
||||||
className={`px-4 py-2 rounded-xl text-xs font-bold whitespace-nowrap transition-all border ${selectedCategory === null
|
className={`px-3 py-1.5 md:px-4 md:py-2 rounded-xl text-[10px] md:text-xs font-bold whitespace-nowrap transition-all border ${selectedCategory === null
|
||||||
? 'bg-amber-600 border-amber-600 text-white shadow-lg shadow-amber-600/20'
|
? 'bg-amber-600 border-amber-600 text-white shadow-lg shadow-amber-600/20'
|
||||||
: 'bg-white dark:bg-zinc-900 border-zinc-200 dark:border-zinc-800 text-zinc-600 dark:text-zinc-400'
|
: 'bg-white dark:bg-zinc-900 border-zinc-200 dark:border-zinc-800 text-zinc-600 dark:text-zinc-400'
|
||||||
}`}
|
}`}
|
||||||
@@ -205,7 +205,7 @@ export default function BottleGrid({ bottles }: BottleGridProps) {
|
|||||||
<button
|
<button
|
||||||
key={cat}
|
key={cat}
|
||||||
onClick={() => setSelectedCategory(cat)}
|
onClick={() => setSelectedCategory(cat)}
|
||||||
className={`px-4 py-2 rounded-xl text-xs font-bold whitespace-nowrap transition-all border ${selectedCategory === cat
|
className={`px-3 py-1.5 md:px-4 md:py-2 rounded-xl text-[10px] md:text-xs font-bold whitespace-nowrap transition-all border ${selectedCategory === cat
|
||||||
? 'bg-amber-600 border-amber-600 text-white shadow-lg shadow-amber-600/20'
|
? 'bg-amber-600 border-amber-600 text-white shadow-lg shadow-amber-600/20'
|
||||||
: 'bg-white dark:bg-zinc-900 border-zinc-200 dark:border-zinc-800 text-zinc-600 dark:text-zinc-400'
|
: 'bg-white dark:bg-zinc-900 border-zinc-200 dark:border-zinc-800 text-zinc-600 dark:text-zinc-400'
|
||||||
}`}
|
}`}
|
||||||
@@ -219,10 +219,10 @@ export default function BottleGrid({ bottles }: BottleGridProps) {
|
|||||||
{/* Distillery Filter */}
|
{/* Distillery Filter */}
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<span className="text-[10px] font-black uppercase tracking-widest text-zinc-400 px-1">Distillery</span>
|
<span className="text-[10px] font-black uppercase tracking-widest text-zinc-400 px-1">Distillery</span>
|
||||||
<div className="flex gap-2 overflow-x-auto pb-2 scrollbar-hide">
|
<div className="flex gap-2 overflow-x-auto -mx-4 px-4 pb-2 scrollbar-hide touch-pan-x">
|
||||||
<button
|
<button
|
||||||
onClick={() => setSelectedDistillery(null)}
|
onClick={() => setSelectedDistillery(null)}
|
||||||
className={`px-4 py-2 rounded-xl text-xs font-bold whitespace-nowrap transition-all border ${selectedDistillery === null
|
className={`px-3 py-1.5 md:px-4 md:py-2 rounded-xl text-[10px] md:text-xs font-bold whitespace-nowrap transition-all border ${selectedDistillery === null
|
||||||
? 'bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 border-zinc-900 dark:border-white'
|
? 'bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 border-zinc-900 dark:border-white'
|
||||||
: 'bg-white dark:bg-zinc-900 border-zinc-200 dark:border-zinc-800 text-zinc-600 dark:text-zinc-400'
|
: 'bg-white dark:bg-zinc-900 border-zinc-200 dark:border-zinc-800 text-zinc-600 dark:text-zinc-400'
|
||||||
}`}
|
}`}
|
||||||
@@ -233,7 +233,7 @@ export default function BottleGrid({ bottles }: BottleGridProps) {
|
|||||||
<button
|
<button
|
||||||
key={dist}
|
key={dist}
|
||||||
onClick={() => setSelectedDistillery(dist)}
|
onClick={() => setSelectedDistillery(dist)}
|
||||||
className={`px-4 py-2 rounded-xl text-xs font-bold whitespace-nowrap transition-all border ${selectedDistillery === dist
|
className={`px-3 py-1.5 md:px-4 md:py-2 rounded-xl text-[10px] md:text-xs font-bold whitespace-nowrap transition-all border ${selectedDistillery === dist
|
||||||
? 'bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 border-zinc-900 dark:border-white'
|
? 'bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 border-zinc-900 dark:border-white'
|
||||||
: 'bg-white dark:bg-zinc-900 border-zinc-200 dark:border-zinc-800 text-zinc-600 dark:text-zinc-400'
|
: 'bg-white dark:bg-zinc-900 border-zinc-200 dark:border-zinc-800 text-zinc-600 dark:text-zinc-400'
|
||||||
}`}
|
}`}
|
||||||
@@ -247,12 +247,12 @@ export default function BottleGrid({ bottles }: BottleGridProps) {
|
|||||||
{/* Status Filter */}
|
{/* Status Filter */}
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<span className="text-[10px] font-black uppercase tracking-widest text-zinc-400 px-1">Status</span>
|
<span className="text-[10px] font-black uppercase tracking-widest text-zinc-400 px-1">Status</span>
|
||||||
<div className="flex gap-2 overflow-x-auto pb-2 scrollbar-hide">
|
<div className="flex gap-2 overflow-x-auto -mx-4 px-4 pb-2 scrollbar-hide touch-pan-x">
|
||||||
{['sealed', 'open', 'sampled', 'empty'].map((status) => (
|
{['sealed', 'open', 'sampled', 'empty'].map((status) => (
|
||||||
<button
|
<button
|
||||||
key={status}
|
key={status}
|
||||||
onClick={() => setSelectedStatus(selectedStatus === status ? null : status)}
|
onClick={() => setSelectedStatus(selectedStatus === status ? null : status)}
|
||||||
className={`px-4 py-2 rounded-xl text-xs font-bold whitespace-nowrap transition-all border ${selectedStatus === status
|
className={`px-3 py-1.5 md:px-4 md:py-2 rounded-xl text-[10px] md:text-xs font-bold whitespace-nowrap transition-all border ${selectedStatus === status
|
||||||
? status === 'open' ? 'bg-amber-500 border-amber-500 text-white' : status === 'sampled' ? 'bg-purple-500 border-purple-500 text-white' : status === 'empty' ? 'bg-zinc-500 border-zinc-500 text-white' : 'bg-blue-600 border-blue-600 text-white'
|
? status === 'open' ? 'bg-amber-500 border-amber-500 text-white' : status === 'sampled' ? 'bg-purple-500 border-purple-500 text-white' : status === 'empty' ? 'bg-zinc-500 border-zinc-500 text-white' : 'bg-blue-600 border-blue-600 text-white'
|
||||||
: 'bg-white dark:bg-zinc-900 border-zinc-200 dark:border-zinc-800 text-zinc-600 dark:text-zinc-400'
|
: 'bg-white dark:bg-zinc-900 border-zinc-200 dark:border-zinc-800 text-zinc-600 dark:text-zinc-400'
|
||||||
}`}
|
}`}
|
||||||
|
|||||||
@@ -158,8 +158,8 @@ export default function CameraCapture({ onImageCaptured, onAnalysisComplete, onS
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center gap-6 w-full max-w-md mx-auto p-6 bg-white dark:bg-zinc-900 rounded-3xl shadow-2xl border border-zinc-200 dark:border-zinc-800 transition-all hover:shadow-whisky-amber/20">
|
<div className="flex flex-col items-center gap-4 md:gap-6 w-full max-w-md mx-auto p-4 md:p-6 bg-white dark:bg-zinc-900 rounded-3xl shadow-2xl border border-zinc-200 dark:border-zinc-800 transition-all hover:shadow-whisky-amber/20">
|
||||||
<h2 className="text-2xl font-bold text-zinc-800 dark:text-zinc-100 italic">Magic Shot</h2>
|
<h2 className="text-xl md:text-2xl font-bold text-zinc-800 dark:text-zinc-100 italic">Magic Shot</h2>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="relative group cursor-pointer w-full aspect-square rounded-2xl border-2 border-dashed border-zinc-300 dark:border-zinc-700 overflow-hidden flex items-center justify-center bg-zinc-50 dark:bg-zinc-800/50 hover:border-amber-500 transition-colors"
|
className="relative group cursor-pointer w-full aspect-square rounded-2xl border-2 border-dashed border-zinc-300 dark:border-zinc-700 overflow-hidden flex items-center justify-center bg-zinc-50 dark:bg-zinc-800/50 hover:border-amber-500 transition-colors"
|
||||||
@@ -273,10 +273,10 @@ export default function CameraCapture({ onImageCaptured, onAnalysisComplete, onS
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{analysisResult && (
|
{analysisResult && (
|
||||||
<div className="p-4 bg-zinc-50 dark:bg-zinc-800/50 rounded-2xl border border-zinc-200 dark:border-zinc-700">
|
<div className="p-3 md:p-4 bg-zinc-50 dark:bg-zinc-800/50 rounded-2xl border border-zinc-200 dark:border-zinc-700">
|
||||||
<div className="flex items-center gap-2 mb-3 text-amber-600 dark:text-amber-500">
|
<div className="flex items-center gap-2 mb-2 md:mb-3 text-amber-600 dark:text-amber-500">
|
||||||
<Sparkles size={18} />
|
<Sparkles size={18} />
|
||||||
<span className="font-bold text-sm uppercase tracking-wider">Ergebnisse</span>
|
<span className="font-bold text-[10px] md:text-sm uppercase tracking-wider">Ergebnisse</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="flex justify-between text-sm">
|
<div className="flex justify-between text-sm">
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ CREATE TABLE IF NOT EXISTS bottles (
|
|||||||
category TEXT, -- Single Malt, Bourbon, etc.
|
category TEXT, -- Single Malt, Bourbon, etc.
|
||||||
abv DECIMAL,
|
abv DECIMAL,
|
||||||
age INTEGER,
|
age INTEGER,
|
||||||
status TEXT DEFAULT 'sealed' CHECK (status IN ('sealed', 'open', 'empty')),
|
status TEXT DEFAULT 'sealed' CHECK (status IN ('sealed', 'open', 'sampled', 'empty')),
|
||||||
whiskybase_id TEXT,
|
whiskybase_id TEXT,
|
||||||
image_url TEXT,
|
image_url TEXT,
|
||||||
is_whisky BOOLEAN DEFAULT true,
|
is_whisky BOOLEAN DEFAULT true,
|
||||||
|
|||||||
Reference in New Issue
Block a user