mirror of
https://github.com/immissmandy/Kitchen.git
synced 2026-07-27 12:25:30 +02:00
feat: KitchenStock light UI, Gemma 31B AI, supermarket store filters & 130+ vegan products
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Camera, Barcode, Check, X, Sparkles, Plus } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
interface BarcodeScannerModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onProductScanned: (product: { name: string; size: number; unit: string; priceCents: number }) => void;
|
||||
}
|
||||
|
||||
const BARCODE_DATABASE: Record<string, { name: string; size: number; unit: string; priceCents: number }> = {
|
||||
'4008234567890': { name: 'Hafermilch Barista Bio (Oatly)', size: 1, unit: 'Liter', priceCents: 149 },
|
||||
'4012345678901': { name: 'Tofu Natur Bio (Taifun)', size: 200, unit: 'Gramm', priceCents: 199 },
|
||||
'4023456789012': { name: 'Spaghetti 500g (Barilla)', size: 500, unit: 'Gramm', priceCents: 189 },
|
||||
'4034567890123': { name: 'Bio Hefeflocken (Alnatura)', size: 200, unit: 'Gramm', priceCents: 299 },
|
||||
'4045678901234': { name: 'Strauchtomaten Bio', size: 500, unit: 'Gramm', priceCents: 229 },
|
||||
};
|
||||
|
||||
export function BarcodeScannerModal({ isOpen, onClose, onProductScanned }: BarcodeScannerModalProps) {
|
||||
const [barcodeInput, setBarcodeInput] = useState('');
|
||||
const [scanning, setScanning] = useState(false);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const handleSimulateScan = (code: string) => {
|
||||
setScanning(true);
|
||||
setTimeout(() => {
|
||||
setScanning(false);
|
||||
const match = BARCODE_DATABASE[code] || {
|
||||
name: `Gescanntes Bio-Produkt (${code.slice(-4)})`,
|
||||
size: 1,
|
||||
unit: 'Stück',
|
||||
priceCents: 199,
|
||||
};
|
||||
|
||||
onProductScanned(match);
|
||||
toast.success(`📷 Barcode gescannt: "${match.name}" erkannt! 🌱`);
|
||||
onClose();
|
||||
}, 800);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4 backdrop-blur-md">
|
||||
<div className="w-full max-w-md rounded-3xl border border-border/60 bg-card p-6 shadow-2xl space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-lg font-bold text-foreground flex items-center gap-2">
|
||||
<Camera className="h-5 w-5 text-emerald-500" />
|
||||
1-Klick Barcode Scanner
|
||||
</h2>
|
||||
<button onClick={onClose} className="rounded-full p-1 text-muted-foreground hover:bg-accent">
|
||||
<X className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Camera Scanner View Simulation */}
|
||||
<div className="relative overflow-hidden rounded-2xl bg-black p-8 text-center text-white space-y-4 border-2 border-emerald-500/50 shadow-inner">
|
||||
<div className="mx-auto flex h-20 w-20 items-center justify-center rounded-2xl bg-emerald-500/20 text-emerald-400 border border-emerald-500/40">
|
||||
<Barcode className={`h-12 w-12 ${scanning ? 'animate-pulse text-emerald-300' : ''}`} />
|
||||
</div>
|
||||
|
||||
<p className="text-xs font-semibold text-emerald-200">
|
||||
{scanning ? 'Barcode wird dekodiert...' : 'Halte die Kamera über den Barcode oder wähle unten ein Produkt'}
|
||||
</p>
|
||||
|
||||
<div className="absolute inset-x-0 top-1/2 border-b-2 border-rose-500/60 animate-pulse" />
|
||||
</div>
|
||||
|
||||
{/* Quick Scan Preset Buttons */}
|
||||
<div className="space-y-2">
|
||||
<label className="block text-xs font-bold text-muted-foreground uppercase">
|
||||
Direkt-Scan testen:
|
||||
</label>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<button
|
||||
onClick={() => handleSimulateScan('4008234567890')}
|
||||
className="flex items-center gap-2 rounded-xl border border-emerald-500/30 bg-emerald-500/10 p-2.5 text-xs font-bold text-emerald-700 dark:text-emerald-300 hover:bg-emerald-600 hover:text-white transition-all text-left"
|
||||
>
|
||||
<span>🥛 Hafermilch</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => handleSimulateScan('4012345678901')}
|
||||
className="flex items-center gap-2 rounded-xl border border-emerald-500/30 bg-emerald-500/10 p-2.5 text-xs font-bold text-emerald-700 dark:text-emerald-300 hover:bg-emerald-600 hover:text-white transition-all text-left"
|
||||
>
|
||||
<span>🧈 Taifun Tofu</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => handleSimulateScan('4023456789012')}
|
||||
className="flex items-center gap-2 rounded-xl border border-emerald-500/30 bg-emerald-500/10 p-2.5 text-xs font-bold text-emerald-700 dark:text-emerald-300 hover:bg-emerald-600 hover:text-white transition-all text-left"
|
||||
>
|
||||
<span>🍝 Spaghetti 500g</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => handleSimulateScan('4034567890123')}
|
||||
className="flex items-center gap-2 rounded-xl border border-emerald-500/30 bg-emerald-500/10 p-2.5 text-xs font-bold text-emerald-700 dark:text-emerald-300 hover:bg-emerald-600 hover:text-white transition-all text-left"
|
||||
>
|
||||
<span>🧀 Hefeflocken</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Manual Barcode Code Entry */}
|
||||
<form
|
||||
onSubmit={e => {
|
||||
e.preventDefault();
|
||||
if (barcodeInput.trim()) handleSimulateScan(barcodeInput.trim());
|
||||
}}
|
||||
className="flex gap-2"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
value={barcodeInput}
|
||||
onChange={e => setBarcodeInput(e.target.value)}
|
||||
placeholder="Barcode Nummer eingeben (z.B. 400823...)"
|
||||
className="flex-1 rounded-xl border border-input bg-background px-3.5 py-2.5 text-xs"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="rounded-xl bg-emerald-600 px-4 py-2.5 text-xs font-bold text-white hover:bg-emerald-500"
|
||||
>
|
||||
Scannen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user