import { useEffect, useMemo, useState } from 'react'; import { Link } from 'react-router-dom'; import { api } from '../../api/client.js'; const emptyForm = { name: '', car_model_id: '', description: '', markup_type: 'none', markup_value: 0, sort_order: 0 }; export default function Packages() { const [packages, setPackages] = useState([]); const [models, setModels] = useState([]); const [form, setForm] = useState(emptyForm); const [editingId, setEditingId] = useState(null); const [error, setError] = useState(''); const [brandFilter, setBrandFilter] = useState('all'); const [modelFilter, setModelFilter] = useState('all'); const load = () => { api.get('/packages').then(setPackages); api.get('/models').then(setModels); }; useEffect(load, []); const modelById = useMemo(() => new Map(models.map((m) => [m.id, m])), [models]); const brandOptions = useMemo(() => { const seen = new Map(); models.forEach((m) => { if (!seen.has(m.brand_id)) seen.set(m.brand_id, m.brand_name); }); return Array.from(seen, ([id, name]) => ({ id, name })).sort((a, b) => a.name.localeCompare(b.name)); }, [models]); const modelOptions = useMemo( () => models .filter((m) => brandFilter === 'all' || String(m.brand_id) === brandFilter) .sort((a, b) => a.name.localeCompare(b.name)), [models, brandFilter] ); const handleBrandFilterChange = (value) => { setBrandFilter(value); setModelFilter('all'); }; const filteredPackages = useMemo( () => packages.filter((pkg) => { const model = modelById.get(pkg.car_model_id); if (brandFilter !== 'all' && String(model?.brand_id) !== brandFilter) return false; if (modelFilter !== 'all' && String(pkg.car_model_id) !== modelFilter) return false; return true; }), [packages, modelById, brandFilter, modelFilter] ); const startEdit = (pkg) => { setEditingId(pkg.id); setForm({ name: pkg.name, car_model_id: pkg.car_model_id, description: pkg.description || '', markup_type: pkg.markup_type || 'none', markup_value: pkg.markup_value || 0, sort_order: pkg.sort_order, }); }; const resetForm = () => { setEditingId(null); setForm(emptyForm); }; const handleSubmit = async (e) => { e.preventDefault(); setError(''); const payload = { ...form, car_model_id: Number(form.car_model_id), markup_value: Number(form.markup_value) }; try { if (editingId) { await api.put(`/packages/${editingId}`, payload); } else { await api.post('/packages', payload); } resetForm(); load(); } catch (err) { setError(err.message); } }; const handleDelete = async (id) => { if (!confirm('Paket inkl. aller Produkte wirklich löschen?')) return; await api.delete(`/packages/${id}`); load(); }; return (

Pakete

{(brandFilter !== 'all' || modelFilter !== 'all') && ( )} {filteredPackages.length} von {packages.length}
{filteredPackages.map((pkg) => ( ))} {filteredPackages.length === 0 && ( )}
Marke / Modell Paket Aufschlag Aktionen
{pkg.brand_name} {pkg.model_name} {pkg.name} {pkg.markup_type === 'fixed' && `+${pkg.markup_value} €`} {pkg.markup_type === 'percent' && `+${pkg.markup_value} %`} {(!pkg.markup_type || pkg.markup_type === 'none') && '–'} Produkte Upgrades
{packages.length === 0 ? 'Noch keine Pakete angelegt.' : 'Keine Pakete für diesen Filter.'}

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

setForm({ ...form, name: e.target.value })} className="w-full rounded-md border border-neutral-300 bg-white px-3 py-2 text-sm dark:border-neutral-700 dark:bg-neutral-900" />

Jede Zeile erscheint als eigener Stichpunkt zusammen mit den Bauteilen.