feat: add inline quantity adjustment controls to POS product and purchase forms

This commit is contained in:
Yoga Pangestu 2026-06-13 12:14:45 +07:00
parent 0131115f1b
commit f84ebbd955
2 changed files with 62 additions and 7 deletions

View File

@ -179,6 +179,17 @@ function getVariantPrice(variant: ProductVariantItem): ProductPriceItem | undefi
return variant.prices.find((price) => price.type === form.price_type);
}
function getCartItem(variantId: number): OrderCartItem | undefined {
return cart.value.find((item) => item.product_variant_id === variantId);
}
async function decreaseVariantQty(variantId: number) {
const index = cart.value.findIndex((item) => item.product_variant_id === variantId);
if (index !== -1) {
await adjustQuantity(index, -1);
}
}
function lineSubtotal(item: OrderCartItem): number {
const quantity = Number(item.quantity) || 0;
@ -374,9 +385,12 @@ function submit() {
Belum ada varian
</p>
<div v-for="variant in product.variants" :key="variant.id"
class="flex items-center gap-2.5 px-3 py-2.5 transition-colors"
:class="getVariantPrice(variant) ? 'cursor-pointer hover:bg-muted/30' : 'opacity-60'"
@click="getVariantPrice(variant) && addToCart(product, variant)">
class="flex items-center gap-2.5 px-3 py-2.5 transition-all duration-200"
:class="[
getVariantPrice(variant) ? 'cursor-pointer hover:bg-muted/30' : 'opacity-60',
getCartItem(variant.id) ? 'border-2 border-primary bg-primary/5 rounded-md mx-1 my-0.5' : ''
]"
@click="getVariantPrice(variant) && !getCartItem(variant.id) && addToCart(product, variant)">
<PosCatalogVariantThumb :items="variant.images" />
<div class="min-w-0 flex-1">
<p class="truncate text-sm font-medium">
@ -391,7 +405,20 @@ function submit() {
<span v-else>-</span>
</p>
</div>
<Button type="button" variant="outline" size="icon-sm" class="shrink-0"
<div v-if="getCartItem(variant.id)" class="flex items-center gap-1.5 shrink-0">
<Button type="button" variant="outline" size="icon-sm"
@click.stop="decreaseVariantQty(variant.id)">
<Minus class="size-3.5" />
</Button>
<span class="text-xs font-semibold min-w-[1.25rem] text-center tabular-nums">
{{ getCartItem(variant.id)!.quantity }}
</span>
<Button type="button" variant="outline" size="icon-sm"
@click.stop="addToCart(product, variant)">
<Plus class="size-3.5" />
</Button>
</div>
<Button v-else type="button" variant="outline" size="icon-sm" class="shrink-0"
:disabled="!getVariantPrice(variant)" @click.stop="addToCart(product, variant)">
<Plus class="size-3.5" />
</Button>

View File

@ -156,6 +156,17 @@ const discountAmount = computed(() => Number(parseRupiah(form.discount)) || 0);
const total = computed(() => Math.max(subtotal.value - discountAmount.value, 0));
function getCartItem(priceId: number): PurchaseCartItem | undefined {
return cart.value.find((item) => item.raw_material_price_id === priceId);
}
async function decreasePriceQty(priceId: number) {
const index = cart.value.findIndex((item) => item.raw_material_price_id === priceId);
if (index !== -1) {
await adjustQuantity(index, -1);
}
}
function lineSubtotal(item: PurchaseCartItem): number {
const quantity = Number(item.quantity) || 0;
@ -358,8 +369,12 @@ function submit() {
Belum ada varian
</p>
<div v-for="price in rawMaterial.prices" :key="price.id"
class="flex cursor-pointer items-center gap-2.5 px-3 py-2.5 transition-colors hover:bg-muted/30"
@click="addToCart(rawMaterial, price)">
class="flex items-center gap-2.5 px-3 py-2.5 transition-all duration-200"
:class="[
'cursor-pointer hover:bg-muted/30',
getCartItem(price.id) ? 'border-2 border-primary bg-primary/5 rounded-md mx-1 my-0.5' : ''
]"
@click="!getCartItem(price.id) && addToCart(rawMaterial, price)">
<PosCatalogVariantThumb :items="price.images" />
<div class="min-w-0 flex-1">
<p class="truncate text-sm font-medium">
@ -369,7 +384,20 @@ function submit() {
{{ price.price_formatted }}
</p>
</div>
<Button type="button" variant="outline" size="icon-sm" class="shrink-0"
<div v-if="getCartItem(price.id)" class="flex items-center gap-1.5 shrink-0">
<Button type="button" variant="outline" size="icon-sm"
@click.stop="decreasePriceQty(price.id)">
<Minus class="size-3.5" />
</Button>
<span class="text-xs font-semibold min-w-[1.25rem] text-center tabular-nums">
{{ getCartItem(price.id)!.quantity }}
</span>
<Button type="button" variant="outline" size="icon-sm"
@click.stop="addToCart(rawMaterial, price)">
<Plus class="size-3.5" />
</Button>
</div>
<Button v-else type="button" variant="outline" size="icon-sm" class="shrink-0"
@click.stop="addToCart(rawMaterial, price)">
<Plus class="size-3.5" />
</Button>