Erste Produktivversion

This commit is contained in:
2026-08-08 20:31:58 +02:00
parent d8ded2816d
commit 7b21e2d1b4
110 changed files with 18170 additions and 644 deletions

View File

@@ -0,0 +1,110 @@
// Bestätigungsdialog nach einem Scan.
//
// Ersetzt das frühere prompt(): Dort ließ sich nur ein Name eingeben,
// und die Herkunft der Angaben war nicht erkennbar. Wenn Daten aus einer
// fremden Quelle vorbelegt werden, soll man sehen, woher sie stammen -
// und sie ändern können, bevor sie im eigenen Bestand landen.
"use strict";
import { el } from "../dom.js";
/**
* @param {object} lookup Antwort von /api/lists/{id}/barcode/{code}
* @returns {Promise<{name: string, quantity: string, unit: string, variant: string}|null>}
*/
export function confirmScan(lookup) {
return new Promise((resolve) => {
const known = lookup.found && lookup.source === "openfoodfacts";
const nameField = el("input", {
type: "text",
maxLength: 200,
value: lookup.name || "",
placeholder: "Wie heißt der Artikel?",
onkeydown: (ev) => { if (ev.key === "Enter") accept(); },
});
const countField = el("input.count", {
type: "text",
inputMode: "numeric",
value: lookup.count != null ? String(lookup.count) : "",
placeholder: "Anz.",
title: "Stückzahl",
});
const qtyField = el("input.qty", {
type: "text",
inputMode: "decimal",
value: lookup.pack_size != null
? String(lookup.pack_size).replace(".", ",") : "",
placeholder: "Gebinde",
title: "Packungsgröße",
});
const unitField = el("input.unit", {
type: "text",
maxLength: 32,
value: lookup.pack_unit || "",
placeholder: "Einheit",
});
const variantField = el("input.variant", {
type: "text",
maxLength: 200,
value: lookup.brand || "",
placeholder: "Eigenschaft",
});
function accept() {
const name = nameField.value.trim();
if (!name) {
nameField.focus();
return;
}
close({
name,
count: countField.value,
packSize: qtyField.value,
packUnit: unitField.value.trim(),
variant: variantField.value.trim(),
});
}
const dialog = el("div.modal", {},
el("div.modal-card", {},
el("h2", {}, known ? "Produkt gefunden" : "Neuer Artikel"),
el("p.sub", {}, `Strichcode ${lookup.barcode}`),
known
? el("p.source-note", {},
"Vorgeschlagen aus Open Food Facts",
lookup.package ? ` Packung: ${lookup.package}` : "",
". Bitte prüfen und bei Bedarf anpassen; übernommen wird, " +
"was hier steht.")
: el("p.lead", {},
"Zu diesem Code liegen keine Angaben vor. Trag den Namen ein " +
"beim nächsten Scan wird der Artikel dann sofort gefunden."),
el("label", {}, "Name"), nameField,
el("div.add-fields", {}, countField, qtyField, unitField, variantField),
el("div.menu-actions", {},
el("button.primary", { type: "button", onclick: accept }, "Hinzufügen"),
el("button", { type: "button", onclick: () => close(null) }, "Abbrechen"))
)
);
function close(result) {
dialog.remove();
window.removeEventListener("keydown", onKey);
document.body.classList.remove("modal-open");
resolve(result);
}
function onKey(ev) {
if (ev.key === "Escape") close(null);
}
window.addEventListener("keydown", onKey);
document.body.classList.add("modal-open");
document.body.append(dialog);
nameField.focus();
nameField.select();
});
}