Skip to content

Commit db1d07e

Browse files
authored
Merge pull request #1372 from w3bdesign/1371-look-into-cart-not-updating-after-add-to-cart
1371 look into cart not updating after add to cart
2 parents 0e9a4b4 + 1e67543 commit db1d07e

File tree

9 files changed

+314
-210
lines changed

9 files changed

+314
-210
lines changed

components/Cart/CartContents.vue

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
<template>
2-
<template v-if="data.cart?.contents?.nodes?.length">
2+
<div v-if="isLoading">
3+
<h2 class="mt-64 text-3xl text-center">Loading cart...</h2>
4+
</div>
5+
<div v-else-if="error">
6+
<h2 class="mt-64 text-3xl text-center text-red-500">Error loading cart. Please try again.</h2>
7+
</div>
8+
<div v-else-if="cartItems.length">
39
<h1 class="h-10 p-6 text-3xl font-bold text-center">Cart</h1>
410
<section class="mt-10">
511
<CartItem
6-
v-for="product in data.cart.contents.nodes"
7-
:key="product.id"
12+
v-for="product in cartItems"
13+
:key="product.key"
814
:product="product"
915
@remove="handleRemoveProduct"
1016
/>
1117
</section>
12-
<CommonButton link-to="/checkout" v-if="showCheckoutButton" center-button>
18+
<CommonButton link-to="/checkout" center-button>
1319
CHECKOUT
1420
</CommonButton>
15-
</template>
21+
</div>
1622
<h2 v-else class="mt-64 text-3xl text-center">Cart is currently empty</h2>
1723
</template>
1824

@@ -21,56 +27,43 @@
2127
* Vue.js component for handling the logic of removing a product from the cart and updating the cart state.
2228
*
2329
* @module CartContents
24-
* @param {Object} props - Object containing the component's properties.
25-
* @param {Boolean} props.showCheckoutButton - Determines whether the checkout button should be shown or not.
2630
* @returns {Object} The Vue.js component object.
2731
*/
28-
import GET_CART_QUERY from "@/apollo/queries/GET_CART_QUERY.gql";
29-
import UPDATE_CART_MUTATION from "@/apollo/mutations/UPDATE_CART_MUTATION.gql";
30-
32+
import { computed, ref, onMounted } from 'vue';
3133
import { useCart } from "@/store/useCart";
34+
import CommonButton from '@/components/common/CommonButton.vue';
3235
3336
const cart = useCart();
37+
const isLoading = ref(true);
38+
const error = ref(null);
3439
35-
defineProps({
36-
showCheckoutButton: { type: Boolean, required: false, default: false },
37-
});
38-
39-
const { data } = await useAsyncQuery(GET_CART_QUERY);
40+
const cartItems = computed(() => cart.cart);
4041
4142
/**
4243
* Handles the removal of a product.
4344
*
44-
* @param {Object} product - The product to be removed.
45+
* @param {string} key - The key of the product to be removed.
4546
*/
46-
const handleRemoveProduct = (product) => {
47-
const updatedItems = [];
48-
49-
const { key } = product;
50-
51-
updatedItems.push({
52-
key,
53-
quantity: 0,
54-
});
55-
56-
const variables = {
57-
input: {
58-
items: updatedItems,
59-
},
60-
};
61-
62-
cart.removeProductFromCart(product);
63-
64-
const { mutate, onDone, onError } = useMutation(UPDATE_CART_MUTATION, {
65-
variables,
66-
});
67-
68-
mutate(variables);
69-
70-
onDone(() => {
71-
document.location = "/cart";
72-
});
47+
const handleRemoveProduct = async (key) => {
48+
try {
49+
await cart.removeProductFromCart(key);
50+
} catch (error) {
51+
console.error('Error removing product from cart:', error);
52+
// Optionally, you can add a user-friendly notification here
53+
// without exposing the error details
54+
}
7355
};
56+
57+
onMounted(async () => {
58+
try {
59+
await cart.refetch();
60+
} catch (err) {
61+
console.error('Error fetching cart:', err);
62+
error.value = err;
63+
} finally {
64+
isLoading.value = false;
65+
}
66+
});
7467
</script>
7568

7669
<style scoped>

components/Cart/CartItem.vue

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
</div>
1616
<div class="item">
1717
<span class="block mt-2 font-extrabold">Name: <br /></span>
18-
<span class="item-content">{{ product.product.node.name }}</span>
18+
<span class="item-content">{{ product.product.name }}</span>
1919
</div>
2020
<div class="item">
2121
<span class="block mt-2 font-extrabold">Quantity: <br /></span>
@@ -25,7 +25,7 @@
2525
</div>
2626
<div class="item">
2727
<span class="block mt-2 font-extrabold">Subtotal: <br /></span>
28-
<span class="item-content">{{ formatPrice(`${product.total}`) }}</span>
28+
<span class="item-content">{{ formatPrice(product.total) }}</span>
2929
</div>
3030
</div>
3131
</template>
@@ -37,13 +37,16 @@
3737
* @component CartItem
3838
*
3939
* @prop {Object} product - The product object containing information about the product.
40-
* @prop {string} product.name - The name of the product.
40+
* @prop {Object} product.product - The product details.
41+
* @prop {string} product.product.name - The name of the product.
4142
* @prop {number} product.quantity - The quantity of the product.
42-
* @prop {number} product.total - The subtotal of the product.
43+
* @prop {string} product.total - The subtotal of the product.
44+
* @prop {string} product.key - The unique key for the cart item.
4345
*
4446
* @emits CartItem#remove - Emitted when the remove button is clicked.
4547
*/
4648
49+
import { ref } from 'vue';
4750
import { formatPrice } from "@/utils/functions";
4851
4952
const isRemoving = ref(false);
@@ -58,10 +61,11 @@ const props = defineProps({
5861
const emit = defineEmits(["remove"]);
5962
6063
/**
61-
* Emits a "remove" event with the `product` prop as the payload.
64+
* Emits a "remove" event with the product's key as the payload.
6265
*/
6366
const emitRemove = () => {
64-
emit("remove", props.product);
67+
isRemoving.value = true;
68+
emit("remove", props.product.key);
6569
};
6670
</script>
6771

components/Layout/LayoutCart.vue

Lines changed: 26 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
<template>
2-
<div v-if="remoteError">
3-
<span class="text-xl text-red-500"
4-
>Error fetching cart. Please refresh the page.</span
5-
>
6-
</div>
7-
<div v-else class="mt-4 lg:mt-0">
8-
<NuxtLink to="/cart">
2+
<div class="mt-4 lg:mt-0">
3+
<div v-if="isLoading">
4+
<span class="text-xl text-gray-500">Loading cart...</span>
5+
</div>
6+
<div v-else-if="error">
7+
<span class="text-xl text-red-500">
8+
Error fetching cart. Please refresh the page.
9+
</span>
10+
</div>
11+
<NuxtLink v-else to="/cart">
912
<transition name="cart">
1013
<span
11-
v-if="cartLength && !loading"
14+
v-if="cartLength > 0"
1215
class="text-xl text-white no-underline lg:text-black is-active"
1316
>
1417
<span class="hidden lg:block">
@@ -29,14 +32,14 @@
2932
</span>
3033
</transition>
3134
<transition name="cart">
32-
<div v-if="cartLength && !loading">
35+
<div v-if="cartLength > 0">
3336
<span
3437
class="absolute w-6 h-6 pb-2 ml-16 -mt-12 text-center text-black bg-white lg:text-white lg:bg-black rounded-full lg:ml-14"
3538
>
3639
{{ cartLength }}
3740
</span>
3841
<span class="text-white lg:text-black">
39-
Total: {{ formatPrice(`${subTotal}`) }}
42+
Total: {{ formatPrice(cartSubtotal) }}
4043
</span>
4144
</div>
4245
</transition>
@@ -45,62 +48,24 @@
4548
</template>
4649

4750
<script setup>
48-
import { ref, onBeforeMount, computed, watch } from "vue";
49-
50-
import GET_CART_QUERY from "@/apollo/queries/GET_CART_QUERY.gql";
51-
import { getCookie } from "@/utils/functions";
51+
import { ref, computed, onMounted } from "vue";
5252
import { useCart } from "@/store/useCart";
53+
import { formatPrice } from "@/utils/functions";
5354
5455
const cart = useCart();
55-
const cartChanged = ref(false);
56-
const loading = ref(true);
57-
const remoteError = ref(false);
58-
59-
const { data, error, pending, execute } = useAsyncQuery(GET_CART_QUERY, {
60-
fetchPolicy: "cache-and-network",
61-
});
62-
63-
const cartContents = computed(() => data.value?.cart?.contents?.nodes || []);
64-
const cartLength = computed(() =>
65-
cartContents.value.reduce((total, product) => total + product.quantity, 0)
66-
);
67-
const subTotal = computed(() =>
68-
cartContents.value.reduce(
69-
(total, product) => total + Number(product.total.replace(/[^0-9.-]+/g, "")),
70-
0
71-
)
72-
);
73-
74-
// Watch for changes in the cart quantity and set a flag if it changes
75-
watch(cartLength, (newLength, oldLength) => {
76-
if (newLength !== oldLength) {
77-
cartChanged.value = true;
78-
}
79-
});
80-
81-
// Execute the query initially
82-
onBeforeMount(() => {
83-
execute();
84-
});
56+
const isLoading = ref(true);
57+
const error = ref(null);
8558
86-
// When the component is mounted, stop the loading state
87-
loading.value = false;
59+
const cartLength = computed(() => cart.cartQuantity);
60+
const cartSubtotal = computed(() => cart.cartSubtotal);
8861
89-
// Watch for the cartChanged flag and execute the query when it changes
90-
watch(cartChanged, (newValue) => {
91-
if (
92-
newValue &&
93-
process.client &&
94-
!pending.value &&
95-
getCookie("woo-session")
96-
) {
97-
execute();
98-
cartChanged.value = false; // Reset the flag after executing the query
62+
onMounted(async () => {
63+
try {
64+
await cart.refetch();
65+
} catch (err) {
66+
error.value = err;
67+
} finally {
68+
isLoading.value = false;
9969
}
10070
});
101-
102-
// Watch for errors from the Apollo query
103-
watch(error, (newError) => {
104-
remoteError.value = !!newError;
105-
});
10671
</script>

components/Products/ProductsSingleProduct.vue

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,14 @@
5454
@common-button-click="addProductToCart(data.product)"
5555
:is-loading="isLoading"
5656
>
57-
ADD TO CART</CommonButton
58-
>
57+
ADD TO CART
58+
</CommonButton>
5959
</div>
6060
</div>
6161
</div>
6262
</div>
6363
</section>
64+
<Toast ref="toast" />
6465
</template>
6566
</template>
6667

@@ -75,13 +76,13 @@
7576
* @prop {string} slug - The slug of the product to display.
7677
*/
7778
78-
import { ref, watch } from "vue";
79+
import { ref, watch, computed } from "vue";
7980
8081
import GET_SINGLE_PRODUCT_QUERY from "@/apollo/queries/GET_SINGLE_PRODUCT_QUERY.gql";
81-
import ADD_TO_CART_MUTATION from "@/apollo/mutations/ADD_TO_CART_MUTATION.gql";
8282
8383
import ProductImage from "@/components/Products/ProductImage.vue";
8484
import ProductPrice from "@/components/Products/ProductPrice.vue";
85+
import Toast from "@/components/common/Toast.vue";
8586
8687
import { stripHTML, filteredVariantName } from "@/utils/functions";
8788
@@ -92,6 +93,7 @@ const cart = useCart();
9293
const isLoading = computed(() => cart.loading);
9394
9495
const selectedVariation = ref(); // TODO Pass this value to addProductToCart()
96+
const toast = ref(null);
9597
9698
const props = defineProps({
9799
id: { type: String, required: true },
@@ -119,12 +121,12 @@ watch(
119121
* @return {Promise<void>} A Promise that resolves when the product has been successfully added to the cart.
120122
*/
121123
const addProductToCart = async (product) => {
122-
await cart.addToCart(product);
123-
124-
watchEffect(() => {
125-
if (isLoading.value === false) {
126-
window.location.reload();
127-
}
128-
});
124+
try {
125+
await cart.addToCart(product);
126+
toast.value.show();
127+
} catch (error) {
128+
console.error('Error adding product to cart:', error);
129+
// You might want to show an error message to the user here
130+
}
129131
};
130132
</script>

0 commit comments

Comments
 (0)