'use client'; import { useState, useEffect, useRef } from 'react'; import { Package, Plus, X, Edit2, Trash2, Search, Image as ImageIcon, AlertTriangle } from 'lucide-react'; import { useToast } from '../components/ToastProvider'; import { useSession } from 'next-auth/react'; export default function ProductsPage() { const [products, setProducts] = useState([]); const [showForm, setShowForm] = useState(false); const [editingId, setEditingId] = useState(null); const [search, setSearch] = useState(''); const { toast, confirm } = useToast(); const { data: session } = useSession(); const permissions = (session?.user as any)?.permissions || []; const canEdit = permissions.includes('PURCHASING_MANAGE'); const canDelete = permissions.includes('DATA_DELETE'); const imageRef = useRef(null); const [form, setForm] = useState({ name: '', description: '', sku: '', purchasePrice: '', salePrice: '', stock: '', unit: 'Stk', category: '', trackStock: true }); const [imageFile, setImageFile] = useState(null); const [imagePreview, setImagePreview] = useState(null); useEffect(() => { fetchProducts(); }, []); const fetchProducts = async () => { const res = await fetch('/api/products'); if (res.ok) setProducts(await res.json()); }; const handleEdit = (p: any) => { setEditingId(p.id); setForm({ name: p.name, description: p.description || '', sku: p.sku || '', purchasePrice: p.purchasePrice.toString(), salePrice: p.salePrice.toString(), stock: p.stock.toString(), unit: p.unit, category: p.category || '', trackStock: p.trackStock !== false }); setImagePreview(p.imagePath); setImageFile(null); setShowForm(true); }; const handleNew = () => { setEditingId(null); setForm({ name: '', description: '', sku: '', purchasePrice: '', salePrice: '', stock: '', unit: 'Stk', category: '', trackStock: true }); setImagePreview(null); setImageFile(null); setShowForm(!showForm); }; const handleImageChange = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { setImageFile(file); setImagePreview(URL.createObjectURL(file)); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const fd = new FormData(); Object.entries(form).forEach(([k, v]) => fd.append(k, String(v))); if (editingId) { fd.append('id', editingId.toString()); fd.append('active', 'true'); } if (imageFile) fd.append('image', imageFile); const res = await fetch('/api/products', { method: editingId ? 'PUT' : 'POST', body: fd }); if (res.ok) { toast(editingId ? 'Produkt aktualisiert' : 'Produkt angelegt', 'success'); setShowForm(false); fetchProducts(); } else { const data = await res.json(); toast(data.error || 'Fehler', 'error'); } }; const handleDelete = async (p: any) => { const ok = await confirm({ title: 'Produkt löschen', message: `"${p.name}" wirklich löschen?`, danger: true }); if (!ok) return; const res = await fetch(`/api/products?id=${p.id}`, { method: 'DELETE' }); if (res.ok) { toast('Gelöscht', 'success'); fetchProducts(); } else toast('Fehler beim Löschen', 'error'); }; const filtered = products.filter(p => p.name.toLowerCase().includes(search.toLowerCase()) || (p.sku && p.sku.toLowerCase().includes(search.toLowerCase())) || (p.category && p.category.toLowerCase().includes(search.toLowerCase())) ); const availableStock = (p: any) => p.stock - p.reservedStock; return (

Produkte & Lager

Verwalte Artikel, Preise und Bestände.

setSearch(e.target.value)} className="pl-9 pr-4 py-2 border border-slate-300 rounded-xl text-sm outline-none focus-ring w-56" />
{canEdit && ( )}
{showForm && (

{editingId ? 'Produkt bearbeiten' : 'Neues Produkt'}

setForm({...form, name: e.target.value})} />
setForm({...form, sku: e.target.value})} />
setForm({...form, category: e.target.value})} />
setForm({...form, purchasePrice: e.target.value})} />
setForm({...form, salePrice: e.target.value})} />
setForm({...form, stock: e.target.value})} />