148 lines
5.2 KiB
JavaScript
148 lines
5.2 KiB
JavaScript
// 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, formatQuantity } from "../dom.js";
|
||
|
||
/**
|
||
* @param {object} lookup Antwort von /api/lists/{id}/barcode/{code}
|
||
* @param {object} context
|
||
* @param {Array} context.markets Märkte der Liste
|
||
* @param {Array} context.categories Warengruppen der Liste
|
||
* @param {string|null} context.market Vorauswahl aus der Eingabezeile
|
||
* @param {string|null} context.category dito
|
||
* @returns {Promise<{name, count, packSize, packUnit, variant,
|
||
* marketId, categoryId}|null>}
|
||
*/
|
||
export function confirmScan(lookup, context = {}) {
|
||
return new Promise((resolve) => {
|
||
const known = lookup.found && lookup.source === "openfoodfacts";
|
||
const markets = context.markets || [];
|
||
const categories = context.categories || [];
|
||
|
||
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",
|
||
// formatQuantity statt roher Zeichenkette: Die API liefert
|
||
// "200.000", und "200,000" im Feld sieht nach zweihunderttausend
|
||
// aus.
|
||
value: lookup.pack_size != null ? formatQuantity(lookup.pack_size) : "",
|
||
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",
|
||
});
|
||
|
||
// Warengruppe und Markt wie in der Eingabezeile - der gescannte
|
||
// Artikel soll ohne Nacharbeit an der richtigen Stelle landen.
|
||
// Vorbelegt mit dem, was im Formular schon ausgewählt war.
|
||
const categoryField = categories.length
|
||
? el("select.category-select", { title: "Warengruppe" },
|
||
el("option", { value: "" }, "— Vorgabe des Artikels —"),
|
||
categories.map((c) => el("option", { value: c.id }, c.name)))
|
||
: null;
|
||
if (categoryField && context.category
|
||
&& categories.some((c) => c.id === context.category)) {
|
||
categoryField.value = context.category;
|
||
}
|
||
|
||
const marketField = markets.length
|
||
? el("select.market-select", { title: "Markt" },
|
||
el("option", { value: "" }, "— Vorgabe des Artikels —"),
|
||
markets.map((m) => el("option", { value: m.id }, m.name)))
|
||
: null;
|
||
if (marketField && context.market
|
||
&& markets.some((m) => m.id === context.market)) {
|
||
marketField.value = context.market;
|
||
}
|
||
|
||
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(),
|
||
marketId: marketField ? marketField.value || null : null,
|
||
categoryId: categoryField ? categoryField.value || null : null,
|
||
});
|
||
}
|
||
|
||
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),
|
||
categoryField ? el("div.add-select", {}, categoryField) : null,
|
||
marketField ? el("div.add-select", {}, marketField) : null,
|
||
|
||
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();
|
||
});
|
||
}
|