Add ability to add transaction items using barcode scanner

This commit is contained in:
2023-11-05 23:10:54 +00:00
parent eae1833e2b
commit 929eddd9e8
9 changed files with 145 additions and 38 deletions

View File

@ -13,6 +13,10 @@ export default class ModalController extends Controller {
if (!this.element.open) {
return;
}
if (event.type === "turbo:submit-end" && (event.detail.formSubmission.method === 0 || !event.detail.success)) {
// Don't close modal if form method was GET or submission failed
return;
}
event.preventDefault();

View File

@ -1,7 +1,26 @@
import { Controller } from "/lib/hotwired/stimulus/dist/stimulus.js";
export default class TransactionItemFormController extends Controller {
static targets = ["option", "price", "quantity"];
static targets = ["barcodeButton", "barcodeData", "barcodeFormat", "barcodeFormField", "brand", "option", "price", "quantity"];
#scanning = false;
#scanIntervalId;
#stream;
connect() {
if ('BarcodeDetector' in globalThis) {
this.barcodeFormFieldTarget.hidden = false;
if (this.barcodeDataTarget.value) {
this.brandTarget.autofocus = false;
}
}
}
disconnect() {
this.barcodeFormFieldTarget.hidden = true;
this.brandTarget.autofocus = true;
this.stopScanning();
}
filterNames(event) {
for (const option of this.optionTargets) {
@ -36,4 +55,54 @@ export default class TransactionItemFormController extends Controller {
}
}
}
async scanBarcode(event) {
event?.preventDefault();
if (this.#scanning) {
return;
}
this.#scanning = true;
this.barcodeDataTarget.value = "";
this.barcodeFormatTarget.value = "";
this.#stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } });
const video = document.createElement("video");
video.srcObject = this.#stream;
await video.play();
const detector = new BarcodeDetector();
this.#scanIntervalId = setInterval(async () => {
const barcodes = await detector.detect(video);
if (barcodes.length === 0) {
return;
}
const barcode = barcodes[0];
this.barcodeDataTarget.value = barcode.rawValue;
this.barcodeFormatTarget.value = barcode.format;
this.stopScanning();
const form = this.element.closest("form");
for (const element of form.elements) {
element.disabled = !element.name.startsWith("barcode");
}
form.requestSubmit(this.barcodeButtonTarget);
}, 250);
}
stopScanning() {
if (this.#scanning) {
this.#stream?.getTracks()
.forEach(track => track.stop());
clearInterval(this.#scanIntervalId);
this.#scanning = false;
}
}
}