From 14cf8af14bd9962be8a68d69789bdfaa8ccdddbf Mon Sep 17 00:00:00 2001
From: grey <pnh@thegreydiamond.de>
Date: Wed, 19 Mar 2025 20:45:05 +0100
Subject: [PATCH] restock mode

---
 static/pages/admin_products.js | 132 ++++++++++++++++++++++++++++++++-
 static/pages/product_select.js |   8 +-
 views/admin/products.eta       |  84 ++++++++++++++++++++-
 3 files changed, 214 insertions(+), 10 deletions(-)

diff --git a/static/pages/admin_products.js b/static/pages/admin_products.js
index e3dd290..00909f6 100644
--- a/static/pages/admin_products.js
+++ b/static/pages/admin_products.js
@@ -1,6 +1,26 @@
 let uploadFileInput = document.getElementById('imgUpload');
 let fileName = document.getElementById('fileName');
 let imgUploadForm = document.getElementById('imgUploadForm');
+let scannerField = document.getElementById('scannerField');
+let btn_restock = document.getElementById('btn_restock');
+
+let btn_save_2 = document.getElementById('btn_save_2');
+
+let form_gtin = document.getElementById('form_gtin');
+
+let modal_stage_1 = document.getElementById('modal-stage-1');
+let modal_stage_2 = document.getElementById('modal-stage-2');
+let modal_stage_3 = document.getElementById('modal-stage-3');
+
+let modal_stage_2_result = document.getElementById("stage-2-result");
+
+let modal_stage_2_amount = document.getElementById("stage-2-amount");
+
+let globalData;
+
+waitingForScan = false;
+let currentRestockProduct = null;
+
 
 function handleImagePresence(row) {
 	// Check if /api/v1/image?id=row&check returns true
@@ -55,6 +75,10 @@ function silentFormSubmit() {
 	};
 }
 
+function enableScanner() {
+	waitingForScan = true;
+	scannerField.focus();
+}
 
 uploadFileInput.addEventListener('change', function() {
 	fileName.innerHTML = this.files[0].name;
@@ -62,4 +86,110 @@ uploadFileInput.addEventListener('change', function() {
 	setTimeout(() => {
 		refreshTableByName('products');
 	}, 1000);
-});
\ No newline at end of file
+});
+
+scannerField.style.fontSize = '1px';
+scannerField.style.height = '1px';
+scannerField.style.width = '1px';
+scannerField.style.opacity = '0';
+scannerField.style.position = 'relative';
+
+// Make sure text fields is always centerd vertically
+window.addEventListener('scroll', function(event) {
+	if(!waitingForScan) {
+		return;
+	}
+	scannerField.y = document.documentElement.scrollTop + 20;
+	scannerField.style.top = document.documentElement.scrollTop + 20 + "px";
+});
+
+setInterval(() => {
+	if(!waitingForScan) {
+		return;
+	}
+	scannerField.focus();
+}, 1000);
+
+btn_restock.addEventListener('click', function() {
+	modal_stage_1.classList.remove('is-hidden');
+	modal_stage_2.classList.add('is-hidden');
+	modal_stage_3.classList.add('is-hidden');
+	waitingForScan = true;
+});
+// Handle barcode scanner input
+scannerField.addEventListener('keydown', async function(event) {
+	if(event.key != 'Enter') {
+		return;
+	}
+	let barcode = scannerField.value;
+	console.log('Barcode scanned:', barcode);
+	scannerField.value = "";
+	// createTemporaryNotification(`Barcode ${barcode} gescannt`, 'is-info');
+	
+
+	// Check if barcode is in the database
+	let product = globalData.find(p => p.gtin == barcode);
+	if(product) {
+		console.log('Product found:', product);
+		currentRestockProduct = product;
+		modal_stage_2_amount.innerHTML = "Aktuelle Menge: " + product.stock;
+		modal_stage_1.classList.add('is-hidden');
+		modal_stage_2.classList.remove('is-hidden');
+		modal_stage_3.classList.add('is-hidden');
+		createTemporaryNotification(`<i class="bi bi-upc-scan"></i> Barcode scan: GTIN ${barcode} gefunden`, 'is-success');
+	} else {
+		modal_stage_1.classList.add('is-hidden');
+		modal_stage_2.classList.add('is-hidden');
+		modal_stage_3.classList.remove('is-hidden');
+		form_gtin.value = barcode;
+	}
+	// modal_stage_2_result.innerHTML = product ? `<i class="bi bi-check"></i> Produkt gefunden: ${product.name}` : `<i class="bi bi-x"></i> Produkt nicht gefunden`;
+	waitingForScan = false;
+
+
+	// let product = globalData.find(p => p.gtin == barcode);
+	// if(product) {
+	// 	let event = new Event('click');
+	// 	createTemporaryNotification(`<i class="bi bi-upc-scan"></i> Barcode scan: GTIN ${barcode} gefunden`, 'is-success');
+	// 	document.getElementById(`product_${product.id}`).dispatchEvent(event);
+	// } else {
+	// 	createTemporaryNotification( `<i class="bi bi-upc-scan"></i> Barcode scan: GTIN ${barcode} nicht gefunden`, 'is-danger');
+	// }
+});
+
+function restock(amount) {
+	currentRestockProduct.stock += amount;
+	modal_stage_2_amount.innerHTML = "Aktuelle Menge: " + currentRestockProduct.stock;
+}
+
+function applyStock() {
+	let result = _api.patch('products', {
+		"id": currentRestockProduct.id,
+		"stock": currentRestockProduct.stock
+	})
+	if(result) {
+		createTemporaryNotification('Bestand erfolgreich aktualisiert', 'is-success');
+		modal_stage_2.classList.add('is-hidden');
+		modal_stage_1.classList.remove('is-hidden');
+		modal_stage_3.classList.add('is-hidden');
+		enableScanner();
+	} else {
+		createTemporaryNotification('Fehler beim Aktualisieren des Bestands', 'is-danger');
+	}
+
+
+}
+
+document.addEventListener('DOMContentLoaded', async function() {
+	let data = await returnTableDataByTableName('products');
+	console.info(`Found ${data.count} products`);
+	const result = data.result;
+	globalData = result;
+});
+
+// btn_save_2.addEventListener('click', async function() {
+// 	// Assume submission is valid
+// 	// Get the form data
+// 	// reload table
+// 	// close modal
+// });
\ No newline at end of file
diff --git a/static/pages/product_select.js b/static/pages/product_select.js
index b5daf2a..3825dc8 100644
--- a/static/pages/product_select.js
+++ b/static/pages/product_select.js
@@ -186,13 +186,7 @@ function confirmedCart() {
 	});
 }
 
-function getCookie(name) {
-	let value = "; " + document.cookie;
-	let parts = value.split("; " + name + "=");
-	if(parts.length == 2) {
-		return parts.pop().split(";").shift();
-	}
-}
+
 
 // Handle barcode scanner
 // Force the cursor to the scanner field
diff --git a/views/admin/products.eta b/views/admin/products.eta
index e72bca6..acfddc8 100644
--- a/views/admin/products.eta
+++ b/views/admin/products.eta
@@ -1,11 +1,13 @@
 <%~ include("partials/base_head.eta", {"title": "Admin - Benutzer"}) %>
 <%~ include("partials/nav.eta") %>
-
+<input id="scannerField" type="text"/>
 <section class="section container" id="mainSelect">
 	<h1 class="title">Produktverwaltung</h1>
 	<p class="heading"><button class="js-modal-trigger button" data-target="modal-js-example">
 				Neues Produkt anlegen
-	</button></p>
+	</button><button class="js-modal-trigger button" data-target="modal-restock" id="btn_restock">
+				Lager nachfüllen
+	</button><br></p>
 
 		<input class="input" type="text"  data-searchTargetId="productTable" placeholder="Nach Produkt suchen.." />
 	<table class="table is-striped is-fullwidth is-hoverable" data-dataSource="products" id="productTable" data-pageSize="10">
@@ -148,6 +150,84 @@
 	<button class="modal-close is-large" aria-label="close"></button>
 	</div>
 
+<div id="modal-restock" class="modal">
+	<div class="modal-background"></div>
+
+	<div class="modal-content">
+		<div class="box" id="modal-stage-1">
+			<h2 class="title">Nachfüllen</h1>
+			<center><h1 class="title"><i class="bi bi-upc-scan"></i></h1></center>
+			Warten auf Scan....
+		</div>
+		<div class="box" id="modal-stage-2">
+			<h2 class="title">Scan erfolgreich - Produktmenge eingeben</h1>
+			<h3 class="subtitle" id="stage-2-amount">Aktuelle Menge: 0</h3>
+			<div class="buttons">
+				<button class="button is-info" onclick="restock(6)">+6</button>
+				<button class="button is-info" onclick="restock(10)">+10</button>
+				<button class="button is-info" onclick="restock(12)">+12</button>
+			</div>
+			<button class="button is-success" onclick="applyStock()">Änderungen speichern</button>
+			<div id="stage-2-result"></div>
+		</div>
+		<div class="box" id="modal-stage-3">
+			<h2 class="title">Scan erfolgreich - Produkt erstellen</h1>
+			<form data-targetTable="products">
+			<div class="field">
+				<label class="label">Bezeichner</label>
+				<div class="control has-icons-left">
+					<input class="input" type="text" placeholder="Schokolade" value="" name="name">
+					<span class="icon is-small is-left">
+					<i class="bi bi-file-earmark-person-fill"></i>
+					</span>
+				</div>
+			</div>
+
+			<div class="field">
+			<label class="label">GTIN</label>
+			<div class="control has-icons-left">
+				<input id="form_gtin" class="input" type="number" placeholder="" value="" name="gtin" readonly>
+				<span class="icon is-small is-left">
+				<i class="bi bi-upc"></i>
+				</span>
+			</div>
+			</div>
+
+			<div class="field">
+			<label class="label">Lagermenge</label>
+			<div class="control has-icons-left">
+				<input class="input" type="number" placeholder="" value="" name="stock">
+				<span class="icon is-small is-left">
+				<i class="bi bi-archive-fill"></i>
+				</span>
+			</div>
+			</div>
+
+			<div class="field">
+			<label class="label">Preis</label>
+			<div class="control has-icons-left">
+				<input class="input" type="number" placeholder="" value="" step=0.01 name="price">
+				<span class="icon is-small is-left">
+				<i class="bi bi-currency-euro"></i>
+				</span>
+			</div>
+			</div>
+			<div class="field is-grouped">
+			<div class="control">
+				<input type="submit" class="button is-link" value="Save" data-actionBtn="save" data-extTable="productTable" id="btn_save_2">
+			</div>
+			<!--<div class="control">
+				<button type="button" class="button is-link is-light" data-actionBtn="cancel">Cancel</button>
+			</div>-->
+			</div>
+		</form>
+			
+		</div>
+	</div>
+
+	<button class="modal-close is-large" aria-label="close"></button>
+</div>
+
 <script src="/static/pages/admin_products.js"></script>
 <%~ include("partials/footer.eta") %>
 <%~ include("partials/base_foot.eta") %>