230 lines
7.0 KiB
JavaScript
230 lines
7.0 KiB
JavaScript
console.log('product_select.js loaded');
|
|
|
|
// Get containers
|
|
let mainSelectionDiv = document.getElementById('mainSelect');
|
|
let checkoutTable = document.getElementById('selectedProducts');
|
|
|
|
let sumField = document.getElementById('TableSum');
|
|
|
|
let toCheckoutButton = document.getElementById('checkout');
|
|
let confirmCartButton = document.getElementById('confirmCheckout');
|
|
|
|
let loadingModal = document.getElementById('loadingModal');
|
|
|
|
let scannerField = document.getElementById('scannerField');
|
|
|
|
const baseStruct = document.getElementById("baseStruct");
|
|
|
|
let globalData;
|
|
|
|
let shoppingCart = [];
|
|
|
|
toCheckoutButton.addEventListener('click', finalizeTransaction);
|
|
confirmCartButton.addEventListener('click', confirmedCart);
|
|
|
|
// Get user from url (and cookie)
|
|
let userFCookie = getCookie('user');
|
|
let userFUrl = new URLSearchParams(window.location.search).get('user');
|
|
|
|
if(userFCookie != userFUrl) {
|
|
createTemporaryNotification('Fehler: User nicht korrekt gesetzt!', 'is-danger');
|
|
window.location.href = '/user_select';
|
|
}
|
|
|
|
// On load
|
|
document.addEventListener('DOMContentLoaded', async function() {
|
|
let data = await returnTableDataByTableName('products');
|
|
console.info(`Found ${data.count} products`);
|
|
const result = data.result;
|
|
globalData = result;
|
|
|
|
|
|
for(let i = 0; i < result.length; i++) {
|
|
let product = result[i];
|
|
if(product.visible && product.stock > 0) {
|
|
let newDiv = baseStruct.cloneNode(true);
|
|
newDiv.id = `product_${product.id}`;
|
|
newDiv.style.display = 'block';
|
|
newDiv.querySelector('.product_name').innerText = product.name;
|
|
newDiv.querySelector('.product_description').innerText = product.description || "";
|
|
let price = parseFloat(product.price).toFixed(2);
|
|
|
|
newDiv.querySelector('.product_price').innerText = price + " €";
|
|
newDiv.querySelector('.product_ean').innerText = product.gtin;
|
|
newDiv.querySelector('.product_image').src = "/api/v1/image?id=" + product.id;
|
|
newDiv.querySelector('.product_image').alt = product.name;
|
|
|
|
newDiv.addEventListener('click', selectProductEvent);
|
|
mainSelectionDiv.appendChild(newDiv);
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
function canIAddProduct(product, shoppingCart) {
|
|
let stock = product.stock;
|
|
let count = shoppingCart.filter(p => p.id == product.id).length;
|
|
return count < stock;
|
|
}
|
|
|
|
function selectProductEvent(e) {
|
|
console.log('selectProductEvent', e);
|
|
let id = e.currentTarget.id.split('_')[1];
|
|
let product = globalData.find(p => p.id == id);
|
|
if(!canIAddProduct(product, shoppingCart)) {
|
|
createTemporaryNotification('Nicht genug Lagerbestand mehr vorhanden!', 'is-danger');
|
|
return;
|
|
}
|
|
let price = parseFloat(product.price).toFixed(2);
|
|
let row = checkoutTable.insertRow();
|
|
row.id = `product_${product.id}`;
|
|
let cell1 = row.insertCell(0); // Name
|
|
let cell2 = row.insertCell(1); // Price
|
|
let cell3 = row.insertCell(2); // Actions
|
|
|
|
shoppingCart.push(product);
|
|
|
|
cell1.innerText = product.name;
|
|
cell2.innerText = price + " €";
|
|
let deleteButton = document.createElement('button');
|
|
deleteButton.innerHTML = '<i class="bi bi-trash"></i>';
|
|
deleteButton.onclick = deleteProductEvent;
|
|
deleteButton.className = 'button is-danger';
|
|
deleteButton.style.color = 'white';
|
|
cell3.appendChild(deleteButton);
|
|
|
|
|
|
sumField.innerText = calculateSum(shoppingCart);
|
|
}
|
|
|
|
function calculateSum(cart) {
|
|
let sum = 0;
|
|
for(let i = 0; i < cart.length; i++) {
|
|
sum += parseFloat(cart[i].price);
|
|
}
|
|
return sum.toFixed(2) + " €";
|
|
}
|
|
|
|
function deleteProductEvent(e) {
|
|
let row = e.target.parentElement.parentElement;
|
|
// Check if icon was clicked instead of button
|
|
if(row.tagName != 'TR') {
|
|
row = e.target.parentElement.parentElement.parentElement;
|
|
}
|
|
let id = row.id.split('_')[1];
|
|
let product = shoppingCart.find(p => p.id == id);
|
|
let index = shoppingCart.indexOf(product);
|
|
shoppingCart.splice(index, 1);
|
|
row.remove();
|
|
sumField.innerText = calculateSum(shoppingCart);
|
|
}
|
|
|
|
function finalizeTransaction() {
|
|
if(shoppingCart.length == 0) {
|
|
return;
|
|
}
|
|
|
|
// Show confirmation dialog (id-> checkoutModal)
|
|
let modal = document.getElementById('checkoutModal');
|
|
modal.classList.add('is-active');
|
|
let modalContent = document.getElementById('modalContent');
|
|
|
|
// Grab table in modal
|
|
let modalTable = document.getElementById('selectedProductsModal');
|
|
modalTable.innerHTML = "";
|
|
for(let i = 0; i < shoppingCart.length; i++) {
|
|
let product = shoppingCart[i];
|
|
let row = modalTable.insertRow();
|
|
let cell1 = row.insertCell(0); // Name
|
|
let cell2 = row.insertCell(1); // Price
|
|
cell1.innerText = product.name;
|
|
cell2.innerText = parseFloat(product.price).toFixed(2) + " €";
|
|
}
|
|
|
|
let modalSum = document.getElementById('ModalSum');
|
|
modalSum.innerText = calculateSum(shoppingCart);
|
|
}
|
|
|
|
function confirmedCart() {
|
|
// Close modal
|
|
let modal = document.getElementById('checkoutModal');
|
|
modal.classList.remove('is-active');
|
|
|
|
// Show loading modal
|
|
loadingModal.classList.add('is-active');
|
|
|
|
// Send data to server
|
|
// alert('NYI: Send data to server. This demo ends here.');
|
|
|
|
let listOfIds = shoppingCart.map(p => p.id);
|
|
let data = {
|
|
products: listOfIds,
|
|
user_id: getCookie('user')
|
|
};
|
|
|
|
// Send data to server
|
|
fetch('/api/v1/transaction', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(data)
|
|
}).then(async (response) => {
|
|
let json = await response.json();
|
|
if(response.ok) {
|
|
createTemporaryNotification('<i class="bi bi-check-lg"></i> Erfolgreich abgeschlossen', 'is-success');
|
|
setTimeout(() => {
|
|
window.location.href = '/user_select';
|
|
}, 1000);
|
|
} else {
|
|
createTemporaryNotification('Fehler: ' + json.error, 'is-danger');
|
|
}
|
|
loadingModal.classList.remove('is-active');
|
|
}).catch((error) => {
|
|
createTemporaryNotification('Fehler: ' + error, 'is-danger');
|
|
loadingModal.classList.remove('is-active');
|
|
});
|
|
}
|
|
|
|
|
|
|
|
// Handle barcode scanner
|
|
// Force the cursor to the scanner field
|
|
scannerField.focus();
|
|
// Do so in an interval
|
|
setInterval(() => {
|
|
scannerField.focus();
|
|
}, 1000);
|
|
|
|
// Make it tiny
|
|
scannerField.style.fontSize = '1px';
|
|
scannerField.style.height = '1px';
|
|
scannerField.style.width = '1px';
|
|
scannerField.style.opacity = '0';
|
|
scannerField.style.position = 'relative';
|
|
|
|
// 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-link');
|
|
|
|
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');
|
|
}
|
|
});
|
|
|
|
// Make sure text fields is always centerd vertically
|
|
window.addEventListener('scroll', function(event) {
|
|
scannerField.y = document.documentElement.scrollTop + 20;
|
|
scannerField.style.top = document.documentElement.scrollTop + 20 + "px";
|
|
}); |