Enhance addon handling with quantity controls and unselecting
Added support for managing addon quantities including increment, decrement, and conditional status toggling. Improved UX by allowing product unselection and refined expandable product details behavior. These changes enhance flexibility and clarity in addon operations.
This commit is contained in:
@@ -3,6 +3,8 @@ import { ref, defineProps, defineEmits } from 'vue';
|
||||
import { Colors } from "@/ThemeConfig.vue";
|
||||
import { showPopper, popperBoxProductAddonHtml, removePopperIfOpen } from "@/components/displays/PopperDefault.vue";
|
||||
|
||||
const expandIcon = ref(null);
|
||||
|
||||
const emit = defineEmits(['add-to-cart']);
|
||||
|
||||
const props = defineProps({
|
||||
@@ -15,6 +17,10 @@ const props = defineProps({
|
||||
isSelected: Boolean,
|
||||
selectedAddons: Array,
|
||||
toggleProductAddon: Function,
|
||||
getProductAddonQuantity: Function,
|
||||
addProductAddon: Function,
|
||||
subtractProductAddon: Function,
|
||||
unselect: Function
|
||||
});
|
||||
|
||||
const isAddonSelected = (productId, addonId) => {
|
||||
@@ -44,6 +50,13 @@ const emitAddToCart = (id) => {
|
||||
emit('add-to-cart', id);
|
||||
};
|
||||
|
||||
const toggleIsSelected = () => {
|
||||
if (props.isSelected)
|
||||
{
|
||||
props.unselect()
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
@@ -68,37 +81,52 @@ const emitAddToCart = (id) => {
|
||||
<!-- Expandable product details -->
|
||||
<div v-if="isSelected" class="column is-12-desktop">
|
||||
<!-- Addons -->
|
||||
<div class="buttons is-centered mt-3 mb-0 pl-6" v-if="addons.length > 0">
|
||||
<button
|
||||
class="button is-small is-fullwidth"
|
||||
<div class="buttons has-addons is-centered mt-3 mb-0 pl-6" v-if="addons.length > 0">
|
||||
<div
|
||||
class="buttons has-addons is-small is-fullwidth is-flex-wrap-nowrap"
|
||||
v-for="addon in addons"
|
||||
:key="addon.id"
|
||||
:class="{ 'is-link': isAddonSelected(props.id, addon.option_id), 'is-light': !isAddonSelected(props.id, addon.option_id) }"
|
||||
@click="toggleProductAddon(props.id, addon.option_id)"
|
||||
@mouseenter="showAddonPopper(addon, $event.target)"
|
||||
@mouseleave="hideAddonPopper(addon, $event.target)"
|
||||
>
|
||||
<!-- Addon ( + ) -->
|
||||
<span class="icon is-small" style="margin-right: auto; margin-left: 1rem;">
|
||||
<i class="fas fa-plus fa-xs"></i>
|
||||
</span>
|
||||
<!-- Addon name -->
|
||||
<span style="font-size: 0.7rem;">
|
||||
{{ addon.name }}
|
||||
</span>
|
||||
<!-- Price separator -->
|
||||
<span style="font-size: 0.7rem;">
|
||||
/
|
||||
</span>
|
||||
<!-- Addon price -->
|
||||
<span style="font-size: 0.7rem;">
|
||||
{{ getAddonPrice(addon.id) }} Kr.
|
||||
</span>
|
||||
<button
|
||||
class="button is-small"
|
||||
@click="addProductAddon(
|
||||
props.id,
|
||||
addon.option_id
|
||||
)"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-plus"></i>
|
||||
</span>
|
||||
</button>
|
||||
<!-- quantity (if any), Addon name, price -->
|
||||
<button
|
||||
class="button is-small"
|
||||
:class="{ 'is-link': isAddonSelected(props.id, addon.option_id), 'is-light': !isAddonSelected(props.id, addon.option_id) }"
|
||||
@click="toggleProductAddon(props.id, addon.option_id)"
|
||||
@mouseenter="showAddonPopper(addon, $event.target)"
|
||||
@mouseleave="hideAddonPopper(addon, $event.target)"
|
||||
>
|
||||
<template v-if="isAddonSelected(props.id, addon.option_id)">
|
||||
{{ getProductAddonQuantity(props.id, addon.option_id) }} x
|
||||
</template>
|
||||
{{ addon.name }} / {{ getAddonPrice(addon.id) }} Kr.
|
||||
</button>
|
||||
<!-- Addon ( - ) -->
|
||||
<span class="icon is-small" style="margin-left: auto; margin-right: 1rem;">
|
||||
<i class="fas fa-minus fa-xs"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="button is-small"
|
||||
:disabled="!isAddonSelected(props.id, addon.option_id)"
|
||||
@click="subtractProductAddon(
|
||||
props.id,
|
||||
addon.option_id
|
||||
)"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-minus"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- White space, to accommodate the design requirements -->
|
||||
<p> </p>
|
||||
@@ -117,12 +145,18 @@ const emitAddToCart = (id) => {
|
||||
</div>
|
||||
<!-- Expander -->
|
||||
<div class="column is-12-desktop">
|
||||
<p class="has-text-centered pl-6">
|
||||
<p
|
||||
class="has-text-centered pl-6"
|
||||
@click="toggleIsSelected"
|
||||
@mouseover="expandIcon.classList.add('has-text-link')"
|
||||
@mouseleave="expandIcon.classList.remove('has-text-link')"
|
||||
>
|
||||
<span class="icon is-small" style="color: #c7c7c7;">
|
||||
<i
|
||||
class="fas fa-angle-down fa-lg"
|
||||
:class="{ 'fa-rotate-180': isSelected }"
|
||||
aria-hidden="true"
|
||||
ref="expandIcon"
|
||||
></i>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
@@ -184,14 +184,15 @@ const isProductAddonTrue = (productId, addonId) => {
|
||||
return productAddons.value.find((productAddon) => productAddon.product_id === productId && productAddon.addon_id === addonId && productAddon.status === true) !== undefined;
|
||||
};
|
||||
// Set the product addon
|
||||
const setProductAddon = (productId, addonId, status) => {
|
||||
const setProductAddon = (productId, addonId, status, quantity = 1) => {
|
||||
// Set the product addon status
|
||||
const productAddon = productAddons.value.find((productAddon) => productAddon.product_id === productId && productAddon.addon_id === addonId);
|
||||
if (productAddon === undefined) {
|
||||
productAddons.value.push({
|
||||
product_id: productId,
|
||||
addon_id: addonId,
|
||||
status: status
|
||||
quantity: status ? quantity : 0,
|
||||
status: quantity === 0 ? false : status
|
||||
});
|
||||
} else {
|
||||
productAddon.status = status;
|
||||
@@ -208,12 +209,42 @@ const addAddonsToOrderMiddleware = async (product_id, quantity = 1, related_item
|
||||
// If the product addons are set, add them to the order (If the product is added)
|
||||
var product_addons = productAddons.value.filter((productAddon) => productAddon.product_id === product_id && productAddon.status === true);
|
||||
for (let i = 0; i < product_addons.length; i++) {
|
||||
// Get the addons quantity (If the addon quantity is 0, use the product quantity, otherwise multiply the addon quantity with the product quantity)
|
||||
let addon_quantity = product_addons[i].quantity === 0 ? quantity : product_addons[i].quantity * quantity;
|
||||
// Get the products addon, and show the fake create order item
|
||||
showFakeCreateOrderItem(product_addons[i].addon_id, quantity, 0, related_item_id);
|
||||
showFakeCreateOrderItem(
|
||||
product_addons[i].addon_id,
|
||||
addon_quantity,
|
||||
0,
|
||||
related_item_id
|
||||
);
|
||||
}
|
||||
// Add the addons to the order
|
||||
for (let i = 0; i < product_addons.length; i++) {
|
||||
await createOrderItem(getOrderId(), product_addons[i].addon_id, quantity, related_item_id);
|
||||
let addon_quantity = product_addons[i].quantity === 0 ? quantity : product_addons[i].quantity * quantity;
|
||||
await createOrderItem(
|
||||
getOrderId(),
|
||||
product_addons[i].addon_id,
|
||||
addon_quantity,
|
||||
related_item_id
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const getProductAddonQuantity = (productId, addonId) => {
|
||||
// Get the product addon quantity (If the product addon is not set, return 0)
|
||||
const productAddon = productAddons.value.find((productAddon) => productAddon.product_id === productId && productAddon.addon_id === addonId);
|
||||
return productAddon === undefined ? 0 : productAddon.quantity;
|
||||
};
|
||||
|
||||
const setProductAddonQuantity = (productId, addonId, quantity) => {
|
||||
console.log(productId, addonId, quantity);
|
||||
// If the quantity is 0, set the product addon status to false
|
||||
if (quantity === 0 || quantity < 0) {
|
||||
setProductAddon(productId, addonId, false, 0);
|
||||
} else {
|
||||
// Set the product addon quantity
|
||||
setProductAddon(productId, addonId, true, quantity);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -287,6 +318,43 @@ const selectProduct = (productId) => {
|
||||
const getAddonPrice = (productId, addonId) => {
|
||||
return products.value.find((product) => product.id === productId).addons.find((addon) => addon.option_id === addonId).price;
|
||||
};
|
||||
|
||||
const addProductAddon = (productId, addonId) => {
|
||||
const product = products.value.find((product) => product.id === productId);
|
||||
const addon = product.addons.find((addon) => addon.option_id === addonId);
|
||||
const productAddon = productAddons.value.find((productAddon) => productAddon.product_id === productId && productAddon.addon_id === addonId);
|
||||
if (productAddon === undefined) {
|
||||
productAddons.value.push({
|
||||
product_id: productId,
|
||||
addon_id: addonId,
|
||||
quantity: 1,
|
||||
status: true
|
||||
});
|
||||
} else {
|
||||
productAddon.quantity += 1;
|
||||
productAddon.status = true;
|
||||
}
|
||||
};
|
||||
|
||||
const subtractProductAddon = (productId, addonId) => {
|
||||
const productAddon = productAddons.value.find((productAddon) => productAddon.product_id === productId && productAddon.addon_id === addonId);
|
||||
if (productAddon !== undefined) {
|
||||
if (productAddon.quantity > 0) {
|
||||
productAddon.quantity -= 1;
|
||||
}
|
||||
// If the quantity is 0, set the product addon status to false
|
||||
if (productAddon.quantity === 0) {
|
||||
productAddon.status = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const unselectProduct = () => {
|
||||
// Wait for the selection from the click to be done
|
||||
setTimeout(() => {
|
||||
selectedProduct.value = null;
|
||||
}, 100);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -446,8 +514,12 @@ const getAddonPrice = (productId, addonId) => {
|
||||
:isSelected="selectedProduct === product.id"
|
||||
:selectedAddons="productAddons"
|
||||
:toggleProductAddon="toggleProductAddon"
|
||||
@click="selectProduct(parseInt(product.id))"
|
||||
:getProductAddonQuantity="getProductAddonQuantity"
|
||||
:addProductAddon="addProductAddon"
|
||||
:subtractProductAddon="subtractProductAddon"
|
||||
@click="!isProductSelected(product.id) ? selectProduct(product.id) : void 0"
|
||||
@addToCart="addProductWithAddonsToOrder(product.id)"
|
||||
:unselect="unselectProduct"
|
||||
/>
|
||||
</WhiteBox>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user