"Add onAddProduct method in PosDepartmentStepMobile2Addons.vue for double-click quantity increment, apply custom styles for selected products in PosDepartmentStepMobile2CategoryProduct.vue, and enhance product interaction logic with conditional classes and cursor pointers"

This commit is contained in:
Jeppe Bundgaard
2025-11-06 09:06:30 +01:00
parent 2cbe709c35
commit b3e3ddce25
2 changed files with 65 additions and 6 deletions
@@ -42,6 +42,55 @@ const getLabel = (addon: Addon) => {
//return `${addon.name} / ${SessionUser.functions.currency.toLocal(addon.price)}`;
}
/**
* When double-clicking on the product, it will add 1 to the quantity
*/
const doubleClickTimeout = 500; // milliseconds
const doubleClickTimers = ref<{ [key: string]: number | null }>({});
/**
* Function to add a product to the add-ons list
* @param addon
*/
const onAddProduct = (addon: Addon) => {
// Check if the product was just added
if (doubleClickTimers.value[addon.id]) {
console.warn("Double-click detected for product " + addon.id, addon);
clearTimeout(doubleClickTimers.value[addon.id]);
doubleClickTimers.value[addon.id] = null;
// Check if the product can have more quantity
if (addon.quantity >= addon.max && addon.max !== -1) {
console.warn("Max quantity reached for product " + addon.id, addon);
return;
}
addon.quantity = addon.quantity + 1;
emit('update:addons', [...props.addons])
// Set the timeout again to allow for the next double-click
doubleClickTimers.value[addon.id] = window.setTimeout(() => {
doubleClickTimers.value[addon.id] = null;
}, doubleClickTimeout);
return;
}
console.warn("Single click detected for product " + addon.id, addon);
// If the product is already has a quantity, set it to 0
if (addon.quantity > 0) {
addon.quantity = 0;
emit('update:addons', [...props.addons])
return;
}
addon.quantity = (addon.min > 0 ? addon.min : 1);
// Set a timeout to handle double-clicks.
// If the product max is reached, it will not be added.
if (addon.quantity >= addon.max && addon.max !== -1) {
console.warn("Max quantity reached for product " + addon.id, addon);
emit('update:addons', [...props.addons])
return;
}
doubleClickTimers.value[addon.id] = window.setTimeout(() => {
doubleClickTimers.value[addon.id] = null;
}, doubleClickTimeout);
emit('update:addons', [...props.addons])
}
</script>
@@ -55,7 +104,7 @@ const getLabel = (addon: Addon) => {
:price="addon.price"
:label="getLabel(addon)"
:piktogram="addon.product.piktogram"
@addProduct="addon.quantity = (addon.min > 0 ? addon.min : 1); emit('update:addons', [...props.addons])"
@addProduct="onAddProduct(addon)"
:customButton="addon.quantity > 0">
<span class="custom-select-quantity-container">
<ControlSelectAmount
@@ -180,7 +229,7 @@ const getLabel = (addon: Addon) => {
}
.custom-label {
/* Add-ons */
padding-bottom: 24px;
width: 60px;
height: 16px;
@@ -61,14 +61,14 @@ const imageStyleCompact = {
</script>
<template>
<div style="border-bottom: 1px solid #E5E5E5; padding: 10px 0;">
<div class="columns is-vcentered is-mobile">
<div class="column is-narrow">
<div style="border-bottom: 1px solid #E5E5E5; padding: 10px 0;" class="mb-1">
<div class="columns is-vcentered is-mobile" :class="props.customButton ? 'has-quantity' : ''">
<div class="column is-narrow" @click="onClick" style="cursor: pointer;">
<img :src="getPicture(props.piktogram)" :alt="props.label" class="product-image"
:style="props.compact ? imageStyleCompact : imageSize"
style="border-radius: 8px; object-fit: contain;" />
</div>
<div class="column">
<div class="column" @click="onClick" style="cursor: pointer;">
<template v-if="!props.compact">
<h1 class="title is-6">{{ props.label }}</h1>
<h2 class="subtitle is-6">{{ SessionUser.functions.currency.toLocal(props.price) }}</h2>
@@ -135,4 +135,14 @@ const imageStyleCompact = {
padding: 0px;
gap: 0px;
}
.has-quantity {
border-radius: 10px;
background-color: #5173d4;
}
.has-quantity .column .title {
color: #FFFFFF;
}
.has-quantity .column .subtitle {
color: rgba(255, 255, 255, 0.6);
}
</style>