fix(mall): normalise group quantity and drop abandoned intents

Opening or joining a group now sets the activity SKU to quantity 1 instead of
accumulating, so a retry after a failed checkout - or a second click - can no
longer push the line to quantity 2 and then fail the quantity-1 intent with an
opaque error.

The stashed group intent is cleared when the checkout page unmounts without
submitting, and when its SKU is no longer in the cart, so an abandoned intent
cannot silently reprice a later order or keep the coupon picker hidden.
This commit is contained in:
2026-09-18 13:44:02 +00:00
parent d7fddf53ab
commit 4d8062f176
2 changed files with 14 additions and 0 deletions
+11
View File
@@ -117,6 +117,11 @@ async function loadCart(): Promise<void> {
items.value = snapshot.items;
addresses.value = list;
coupons.value = couponList;
// A stashed group intent only applies while its SKU is still in the cart.
const intent = groupIntent.value;
if (intent && !items.value.some((item) => item.sku_id === intent.sku_id)) {
groupIntent.value = null;
}
selectedAddressId.value =
list.find((address) => address.is_default)?.id ?? list[0]?.id ?? "";
if (items.value.length === 0) {
@@ -162,6 +167,12 @@ async function submitOrder(): Promise<void> {
}
onMounted(() => void loadCart());
// Leaving without submitting must not reprice a later order: the intent is
// consumed by a successful submit, which clears it before navigating to pay.
onBeforeUnmount(() => {
groupIntent.value = null;
});
</script>
<template>
+3
View File
@@ -54,6 +54,9 @@ async function start(activity: GroupBuyingActivityView, open: boolean): Promise<
workingId.value = activity.id;
try {
await $api.addCartItem(activity.sku_id, 1);
// The intent is quantity-1 only, so normalise in case the SKU was already in
// the cart or a previous attempt failed.
await $api.updateCartItem(activity.sku_id, 1);
await cart.refresh();
useState<GroupBuyIntent | null>("checkout-group-intent", () => null).value = {
activity_id: activity.id,