Files
einkaufsapp/web/html/js/views/scan-result.js

148 lines
5.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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();
});
}