Mehrere EAN-Codes je Produkt und je Gruppe (mit Notiz) + Gruppen umbenennen
Barcodes:
- Neue Tabelle barcodes (code, note, product_id ODER group_id). Damit lassen sich
einem Produkt mehrere Codes geben und einer Gruppe beliebig viele Marken
zuordnen (z.B. alle Mehlmarken zu "Mehl"). Je Code eine Notiz wie
"Mehl bei Aldi".
- Lookup loest jetzt auch Alias-Codes auf; ist ein Code einer Gruppe zugeordnet,
liefert die API group_id/group_name zurueck. Beim Anlegen aus einem Scan wird
diese Gruppe automatisch gesetzt (Vorrang vor dem Kategorie-Rateversuch).
- Endpunkte: POST/DELETE /products/{id}/barcodes und /groups/{id}/barcodes.
- Web: wiederverwendbare BarcodeList-Komponente, eingebunden im Produktformular
und auf der Gruppen-Seite.
Gruppen:
- Namen lassen sich jetzt direkt in der Tabelle aendern (PATCH war vorhanden,
nur die Oberflaeche fehlte).
UI-Fix: Auswahlfelder in Tabellen richten sich nach ihrem Text statt nach der
Zellenbreite (Gruppen-/Benutzer-Dropdowns waren abgeschnitten).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,8 @@ export default function CheckIn() {
|
||||
const [barcode, setBarcode] = useState("");
|
||||
const [product, setProduct] = useState(null);
|
||||
const [suggestion, setSuggestion] = useState(null);
|
||||
// Gruppe, die diesem Code zugeordnet ist (z.B. alle Mehl-Marken in "Mehl").
|
||||
const [suggestionGroup, setSuggestionGroup] = useState({ id: "", name: "" });
|
||||
const [unknownBarcode, setUnknownBarcode] = useState(null);
|
||||
const [results, setResults] = useState([]);
|
||||
const [search, setSearch] = useState("");
|
||||
@@ -60,8 +62,10 @@ export default function CheckIn() {
|
||||
setInfo(`Produkt erkannt: ${res.existing_product.name}`);
|
||||
} else if (res.found && res.suggestion) {
|
||||
setSuggestion(res.suggestion);
|
||||
setSuggestionGroup({ id: res.group_id ? String(res.group_id) : "", name: res.group_name || "" });
|
||||
} else {
|
||||
setUnknownBarcode(barcode.trim());
|
||||
setSuggestionGroup({ id: res.group_id ? String(res.group_id) : "", name: res.group_name || "" });
|
||||
}
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
@@ -71,7 +75,9 @@ export default function CheckIn() {
|
||||
async function createFromSuggestion() {
|
||||
setError(null); setBusy(true);
|
||||
try {
|
||||
const payload = suggestionToProduct(suggestion, guessGroup(groups, suggestion));
|
||||
// Ist der Code einer Gruppe zugeordnet, hat das Vorrang vor dem Kategorie-Rateversuch.
|
||||
const groupId = suggestionGroup.id || guessGroup(groups, suggestion);
|
||||
const payload = suggestionToProduct(suggestion, groupId);
|
||||
const created = await api.createProduct(payload);
|
||||
selectProduct(created);
|
||||
setInfo(`Produkt "${created.name}" angelegt.`);
|
||||
@@ -163,7 +169,10 @@ export default function CheckIn() {
|
||||
{suggestion.brand ? `${suggestion.brand} · ` : ""}auf Open Food Facts gefunden
|
||||
{suggestion.quantity_text ? ` · ${suggestion.quantity_text}` : ""}
|
||||
</div>
|
||||
<div className="muted small">Noch nicht im Katalog.</div>
|
||||
<div className="muted small">
|
||||
Noch nicht im Katalog.
|
||||
{suggestionGroup.name && ` Gruppe: ${suggestionGroup.name}`}
|
||||
</div>
|
||||
</div>
|
||||
{isAdmin ? (
|
||||
<button className="btn primary" onClick={createFromSuggestion} disabled={busy}>
|
||||
|
||||
Reference in New Issue
Block a user