Create update quantity component for changing cart item quantity

This commit is contained in:
marzban-dev
2025-03-18 16:49:20 +03:30
parent 9919dd2555
commit 84151aac4a
@@ -0,0 +1,87 @@
<script lang="ts" setup>
// import
import useGetProduct from "~/composables/api/product/useGetProduct";
import useAddCartItem from "~/composables/api/orders/useAddCartItem";
import type { ProductVariantProvideType } from "~/pages/product/[id].vue";
// provide / inject
const { selectedVariant } = inject(
"productVariant"
) as ProductVariantProvideType;
// state
const route = useRoute();
const id = route.params.id as string | undefined;
const { refetch: refetchProduct } = useGetProduct(id);
const { mutateAsync: addCartItem, isPending: isAddCartItemPending } = useAddCartItem();
const timer = ref<NodeJS.Timeout | null>(null);
const quantity = ref(1);
// methods
const onInput = (e: any) => {
const value = Number(e.target.value);
if (value > 0 && value <= selectedVariant.value!.in_stock) {
quantity.value = value;
} else {
quantity.value = 1;
}
};
watch(
() => quantity.value,
(newValue) => {
if (timer.value) clearTimeout(timer.value);
timer.value = setTimeout(async () => {
await addCartItem({ id: selectedVariant.value!.id, quantity: newValue });
await refetchProduct();
}, 350);
}
);
watch(selectedVariant, (newValue) => {
quantity.value = newValue!.cart_quantity;
});
// lifecycle
onMounted(() => {
quantity.value = selectedVariant.value!.cart_quantity;
});
</script>
<template>
<NumberFieldRoot
class="rounded-full border-slate-200 border-[1.5px] flex items-center bg-white gap-4 p-4"
v-model="quantity"
:min="1"
:max="selectedVariant!.in_stock"
>
<NumberFieldIncrement class="cursor-pointer">
<Icon name="ci:plus" class="**:stroke-slate-500 size-5" />
</NumberFieldIncrement>
<div class="relative">
<div
:class="isAddCartItemPending ? 'opacity-100' : 'opacity-0'"
class="w-[40px] h-[25px] flex-center transition-all absolute bg-white"
>
<Icon :name="'svg-spinners:180-ring-with-bg'" class="size-[25px]" />
</div>
<NumberFieldInput
@input="onInput"
:class="!isAddCartItemPending ? 'opacity-100' : 'opacity-0'"
class="transition-all field-sizing-content w-[40px] h-[25px] bg-transparent text-center outline-none typo-label-md text-black"
/>
</div>
<NumberFieldDecrement class="cursor-pointer">
<Icon name="ci:minus" class="**:stroke-slate-500 size-5" />
</NumberFieldDecrement>
</NumberFieldRoot>
</template>