gw-customer-accounts 1.2.6 → 1.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/wishlist-button.js +14 -14
- package/package.json +1 -1
- package/src/scripts/components/wishlist-button.js +322 -313
package/dist/wishlist-button.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import{G as s,a
|
|
2
|
-
|
|
3
|
-
${this.iconEl}
|
|
4
|
-
${this.filledIconEl}
|
|
5
|
-
</button>
|
|
6
|
-
`:this.shadowRoot.innerHTML=`
|
|
7
|
-
<button class="wishlist-button" part="button">
|
|
8
|
-
<span class="icon-container" part="icon-container">
|
|
1
|
+
import{G as s,a}from"./assets/index-DI2a6rRk.js";customElements.whenDefined("gw-customer-accounts").then(()=>{class c extends HTMLElement{constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}set variantId(t){this.setAttribute("variant-id",t)}get variantId(){return this.getAttribute("variant-id")}get productId(){return this.getAttribute("product-id")}connectedCallback(){this.renderButton(),this.button=this.shadowRoot.querySelector("button"),this.loader=this.shadowRoot.querySelector("[data-loader]"),this.addEventListener("click",t=>this._handleFavoriteButtonClick(t)),this._activateButton(this._isProductInFavorites()),document.addEventListener("variant:change",({detail:{productId:t,variant:e}})=>{t!==this.productId||!e||(this.variantId=e.id)}),s.app.addEventListener(a.CUSTOM_EVENTS.FAVORITES_STORAGE_UPDATED,()=>{this._activateButton(this._isProductInFavorites())})}log(t){const e="[GW_WISHLIST_BUTTON] Product ID: "+this.productId;console.log(e,t)}renderButton(){if(this.iconEl=this._createIcon("icon"),this.filledIconEl=this._createIcon("filled-icon"),this.hasAttribute("icon-only")){this.shadowRoot.innerHTML=`
|
|
2
|
+
<button class="wishlist-button wishlist-button--icon-only" part="button">
|
|
9
3
|
${this.iconEl}
|
|
10
4
|
${this.filledIconEl}
|
|
11
|
-
</
|
|
12
|
-
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
</button>
|
|
6
|
+
`;return}this.shadowRoot.innerHTML=`
|
|
7
|
+
<button class="wishlist-button" part="button">
|
|
8
|
+
<span class="icon-container" part="icon-container">
|
|
9
|
+
${this.iconEl}
|
|
10
|
+
${this.filledIconEl}
|
|
11
|
+
</span>
|
|
12
|
+
<span class="" data-button-label></span>
|
|
13
|
+
<span class="loader" data-loader></span>
|
|
14
|
+
</button>
|
|
15
|
+
`}_createIcon(t){if(!t)return"";const e=this.querySelector(`template[name="${t}"]`);if(!e)return"";const o=e.content.cloneNode(!0).querySelector("svg");return this.log(o),o.setAttribute("part",t),o.setAttribute("data-button-icon",""),o.setAttribute("hidden",""),o.outerHTML}_getVariantId(){const e=new URLSearchParams(window.location.search).get("variant");return e||this.variantId}async _handleFavoriteButtonClick(t){if(t.preventDefault(),t.stopPropagation(),this.button.disabled=!0,this.button.setAttribute("aria-disabled","true"),this.setAttribute("processing",""),this.loader&&(this.loader.hidden=!1),this.hasAttribute("saved")){this._activateButton(!1);try{const e=await this._removeFromFavorites();if(e.error)throw new Error(e.error);const r=e.products;if(!r)throw new Error("Product not found");s.dashboard._removeFavoriteItem(s.parseVariantId(r.id)),s.app.updateFavoriteItemsStorage({removeIds:[s.parseVariantId(r.id)]});const o=s.customerFirstName?`${s.customerFirstName}'s`:"Your";s.notify(`
|
|
16
16
|
<span>Product removed from ${o} favorites</span>
|
|
17
17
|
<a href="#my-favorites" class="gw-notification__link">View</a>
|
|
18
18
|
`)}catch(e){console.error(e),this._activateButton(!0),s.notify("An error occurred. Please try again later.")}}else{this._activateButton(!0);try{const e=await this._addToFavorites();if(e.error)throw new Error(e.error);const r=e.products;if(!r)throw new Error("Product not found");s.app.updateFavoriteItemsStorage({addIds:[s.parseVariantId(r.id)]}),s.dashboard._renderSingleFavoriteItem(r);const o=s.customerFirstName?`${s.customerFirstName}'s`:"Your";s.notify(`
|
|
19
19
|
<span>Added to ${o} favorites</span>
|
|
20
20
|
<a href="#my-favorites" class="gw-notification__link">View</a>
|
|
21
|
-
`),document.dispatchEvent(new CustomEvent("wishlist:add",{detail:{product:{id:this.productData.id,title:this.productData.title},variant:this.currentVariant}}))}catch(e){console.error(e),this._activateButton(!1),s.notify("An error occurred. Please try again later.")}}this.loader&&(this.loader.hidden=!0),this.button.disabled=!1,this.button.removeAttribute("aria-disabled"),this.removeAttribute("Processing")}get productData(){if(!this._productData){const t=this.querySelector("[data-product-data]");this._productData=JSON.parse(t.textContent)}return this._productData}get productVariants(){var t;return((t=this.productData.variants)==null?void 0:t.nodes)||[]}get currentVariant(){return this.productVariants.find(t=>t.id==this.variantId)}async _addToFavorites(){if(!s.hasCustomer){const e=this.querySelector("[data-product-data]"),r=JSON.parse(e.textContent),o=localStorage.getItem(
|
|
21
|
+
`),document.dispatchEvent(new CustomEvent("wishlist:add",{detail:{product:{id:this.productData.id,title:this.productData.title},variant:this.currentVariant}}))}catch(e){console.error(e),this._activateButton(!1),s.notify("An error occurred. Please try again later.")}}this.loader&&(this.loader.hidden=!0),this.button.disabled=!1,this.button.removeAttribute("aria-disabled"),this.removeAttribute("Processing")}get productData(){if(!this._productData){const t=this.querySelector("[data-product-data]");this._productData=JSON.parse(t.textContent)}return this._productData}get productVariants(){var t;return((t=this.productData.variants)==null?void 0:t.nodes)||[]}get currentVariant(){return this.productVariants.find(t=>t.id==this.variantId)}async _addToFavorites(){if(!s.hasCustomer){const e=this.querySelector("[data-product-data]"),r=JSON.parse(e.textContent),o=localStorage.getItem(a.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS)||"[]",i=JSON.parse(o).filter(d=>d.id!==r.id);return i.push(r),localStorage.setItem(a.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS,JSON.stringify(i)),{success:!0,products:r}}const t=await s.request(a.ENDPOINTS.FAVORITES.ADD,{prodID:this.productId,varID:this.variantId||this._getVariantId()});if(t.error)throw new Error(t.error);return t}async _removeFromFavorites(){if(!s.hasCustomer){const e=this.querySelector("[data-product-data]"),r=JSON.parse(e.textContent),o=localStorage.getItem(a.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS)||"[]",i=JSON.parse(o).filter(d=>d.id!==r.id);return localStorage.setItem(a.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS,JSON.stringify(i)),{success:!0,products:r}}const t=await s.request(a.ENDPOINTS.FAVORITES.REMOVE,{prodID:this.productId});if(t.error)throw new Error(t.error);return t}_activateButton(t){var n,i;const e=this.shadowRoot.querySelectorAll("[data-button-icon]"),r=this.shadowRoot.querySelector("[data-button-label]"),o={inactive:((n=s.componentData.wishlist)==null?void 0:n.addToWishlistLabel)||"Add to wishlist",active:((i=s.componentData.wishlist)==null?void 0:i.addedToWishlistLabel)||"Added to wishlist"};e.length&&e.forEach(d=>d.removeAttribute("hidden")),this.loader&&this.loader.setAttribute("hidden",""),t?(this.setAttribute("saved",""),this.button.setAttribute("aria-label",o.active),r&&(r.textContent=o.active)):(this.removeAttribute("saved"),this.button.setAttribute("aria-label",o.inactive),r&&(r.textContent=o.inactive))}_isProductInFavorites(){if(!s.hasCustomer){const r=localStorage.getItem(a.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS);return(r?JSON.parse(r):[]).some(n=>n.id===this.productId)}const t=sessionStorage.getItem(a.STORAGE_KEYS.WISHLIST_PRODUCT_IDS);return(t?JSON.parse(t):[]).includes(this.productId)}}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{customElements.define("gw-wishlist-button",c)}):customElements.define("gw-wishlist-button",c)});
|
package/package.json
CHANGED
|
@@ -2,382 +2,391 @@ import { GWUtils } from '../utils';
|
|
|
2
2
|
import { GWCA } from '../utils/constants';
|
|
3
3
|
|
|
4
4
|
customElements.whenDefined('gw-customer-accounts').then(() => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
this.shadow = this.attachShadow({ mode: 'open' });
|
|
11
|
-
this.isIconOnly = this.hasAttribute('icon-only');
|
|
12
|
-
|
|
13
|
-
const iconTemplate = this.querySelector('template[name="icon"]');
|
|
14
|
-
this.iconEl = this._createIcon(iconTemplate, 'icon');
|
|
15
|
-
|
|
16
|
-
const filledIconTemplate = this.querySelector(
|
|
17
|
-
'template[name="filled-icon"]'
|
|
18
|
-
);
|
|
19
|
-
this.filledIconEl = this._createIcon(filledIconTemplate, 'filled-icon');
|
|
20
|
-
|
|
21
|
-
if (this.hasAttribute('icon-only')) {
|
|
22
|
-
this.shadowRoot.innerHTML = `
|
|
23
|
-
<button class="wishlist-button wishlist-button--icon-only" part="button">
|
|
24
|
-
${this.iconEl}
|
|
25
|
-
${this.filledIconEl}
|
|
26
|
-
</button>
|
|
27
|
-
`;
|
|
28
|
-
} else {
|
|
29
|
-
this.shadowRoot.innerHTML = `
|
|
30
|
-
<button class="wishlist-button" part="button">
|
|
31
|
-
<span class="icon-container" part="icon-container">
|
|
32
|
-
${this.iconEl}
|
|
33
|
-
${this.filledIconEl}
|
|
34
|
-
</span>
|
|
35
|
-
<span class="" data-button-label></span>
|
|
36
|
-
<span class="loader" data-loader></span>
|
|
37
|
-
</button>
|
|
38
|
-
`;
|
|
39
|
-
}
|
|
5
|
+
class GWWishlistButton extends HTMLElement {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this.shadow = this.attachShadow({ mode: 'open' });
|
|
9
|
+
}
|
|
40
10
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
inactive:
|
|
45
|
-
GWUtils.componentData.wishlist?.addToWishlistLabel ||
|
|
46
|
-
'Add to wishlist',
|
|
47
|
-
active:
|
|
48
|
-
GWUtils.componentData.wishlist?.addedToWishlistLabel ||
|
|
49
|
-
'Added to wishlist',
|
|
50
|
-
};
|
|
11
|
+
set variantId(value) {
|
|
12
|
+
this.setAttribute('variant-id', value);
|
|
13
|
+
}
|
|
51
14
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.buttonIcon =
|
|
56
|
-
this.shadowRoot.querySelectorAll('[data-button-icon]');
|
|
57
|
-
}
|
|
15
|
+
get variantId() {
|
|
16
|
+
return this.getAttribute('variant-id');
|
|
17
|
+
}
|
|
58
18
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
19
|
+
get productId() {
|
|
20
|
+
return this.getAttribute('product-id');
|
|
21
|
+
}
|
|
62
22
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
23
|
+
connectedCallback() {
|
|
24
|
+
this.renderButton();
|
|
66
25
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
this.addEventListener('click', (e) =>
|
|
70
|
-
this._handleFavoriteButtonClick(e)
|
|
71
|
-
);
|
|
26
|
+
this.button = this.shadowRoot.querySelector('button');
|
|
27
|
+
this.loader = this.shadowRoot.querySelector('[data-loader]');
|
|
72
28
|
|
|
73
|
-
|
|
74
|
-
|
|
29
|
+
// Add the event listener for the button click
|
|
30
|
+
this.addEventListener('click', (e) => this._handleFavoriteButtonClick(e));
|
|
75
31
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
({ detail: { productId, variant } }) => {
|
|
79
|
-
if (productId !== this.productId || !variant) return;
|
|
32
|
+
// Display initial state of the button
|
|
33
|
+
this._activateButton(this._isProductInFavorites());
|
|
80
34
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
)
|
|
35
|
+
document.addEventListener(
|
|
36
|
+
'variant:change',
|
|
37
|
+
({ detail: { productId, variant } }) => {
|
|
38
|
+
if (productId !== this.productId || !variant) return;
|
|
84
39
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
() => {
|
|
89
|
-
this._activateButton(this._isProductInFavorites());
|
|
90
|
-
}
|
|
91
|
-
);
|
|
92
|
-
}
|
|
40
|
+
this.variantId = variant.id;
|
|
41
|
+
}
|
|
42
|
+
);
|
|
93
43
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
44
|
+
// Listen for the wishlist initialization event
|
|
45
|
+
GWUtils.app.addEventListener(
|
|
46
|
+
GWCA.CUSTOM_EVENTS.FAVORITES_STORAGE_UPDATED,
|
|
47
|
+
() => {
|
|
48
|
+
this._activateButton(this._isProductInFavorites());
|
|
97
49
|
}
|
|
50
|
+
);
|
|
51
|
+
}
|
|
98
52
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
svgEl.setAttribute('part', partName);
|
|
102
|
-
svgEl.setAttribute('data-button-icon', '');
|
|
103
|
-
svgEl.setAttribute('hidden', '');
|
|
104
|
-
return svgEl.outerHTML;
|
|
105
|
-
}
|
|
53
|
+
log(log) {
|
|
54
|
+
const logKey = '[GW_WISHLIST_BUTTON] ' + 'Product ID: ' + this.productId;
|
|
106
55
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
* @returns {number} The variant ID.
|
|
110
|
-
*/
|
|
111
|
-
_getVariantId() {
|
|
112
|
-
const params = new URLSearchParams(window.location.search);
|
|
113
|
-
const variantIdFromUrl = params.get('variant');
|
|
56
|
+
console.log(logKey, log);
|
|
57
|
+
}
|
|
114
58
|
|
|
115
|
-
|
|
59
|
+
renderButton() {
|
|
60
|
+
this.iconEl = this._createIcon('icon');
|
|
61
|
+
this.filledIconEl = this._createIcon('filled-icon');
|
|
116
62
|
|
|
117
|
-
|
|
63
|
+
// If icon-only attribute is present, render the button with only the icon
|
|
64
|
+
if (this.hasAttribute('icon-only')) {
|
|
65
|
+
this.shadowRoot.innerHTML = `
|
|
66
|
+
<button class="wishlist-button wishlist-button--icon-only" part="button">
|
|
67
|
+
${this.iconEl}
|
|
68
|
+
${this.filledIconEl}
|
|
69
|
+
</button>
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
return;
|
|
118
73
|
}
|
|
119
74
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
75
|
+
// Render the button with the icon and label
|
|
76
|
+
this.shadowRoot.innerHTML = `
|
|
77
|
+
<button class="wishlist-button" part="button">
|
|
78
|
+
<span class="icon-container" part="icon-container">
|
|
79
|
+
${this.iconEl}
|
|
80
|
+
${this.filledIconEl}
|
|
81
|
+
</span>
|
|
82
|
+
<span class="" data-button-label></span>
|
|
83
|
+
<span class="loader" data-loader></span>
|
|
84
|
+
</button>
|
|
85
|
+
`;
|
|
86
|
+
}
|
|
123
87
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
88
|
+
_createIcon(iconType) {
|
|
89
|
+
if (!iconType) return '';
|
|
90
|
+
const templateEl = this.querySelector(`template[name="${iconType}"]`);
|
|
91
|
+
if (!templateEl) return '';
|
|
92
|
+
|
|
93
|
+
const clone = templateEl.content.cloneNode(true);
|
|
94
|
+
const svgEl = clone.querySelector('svg');
|
|
95
|
+
this.log(svgEl);
|
|
96
|
+
svgEl.setAttribute('part', iconType);
|
|
97
|
+
svgEl.setAttribute('data-button-icon', '');
|
|
98
|
+
svgEl.setAttribute('hidden', '');
|
|
99
|
+
return svgEl.outerHTML;
|
|
100
|
+
}
|
|
127
101
|
|
|
128
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Gets the variant ID from the URL if it exists.
|
|
104
|
+
* @returns {number} The variant ID.
|
|
105
|
+
*/
|
|
106
|
+
_getVariantId() {
|
|
107
|
+
const params = new URLSearchParams(window.location.search);
|
|
108
|
+
const variantIdFromUrl = params.get('variant');
|
|
129
109
|
|
|
130
|
-
|
|
131
|
-
// Activate the button to prevent multiple clicks
|
|
132
|
-
this._activateButton(true);
|
|
110
|
+
if (!variantIdFromUrl) return this.variantId;
|
|
133
111
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
112
|
+
return variantIdFromUrl;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async _handleFavoriteButtonClick(event) {
|
|
116
|
+
event.preventDefault();
|
|
117
|
+
event.stopPropagation();
|
|
137
118
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
119
|
+
this.button.disabled = true;
|
|
120
|
+
this.button.setAttribute('aria-disabled', 'true');
|
|
121
|
+
this.setAttribute('processing', '');
|
|
141
122
|
|
|
142
|
-
|
|
143
|
-
if (!favoritedProduct) {
|
|
144
|
-
throw new Error('Product not found');
|
|
145
|
-
}
|
|
123
|
+
if (this.loader) this.loader.hidden = false;
|
|
146
124
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
});
|
|
125
|
+
if (!this.hasAttribute('saved')) {
|
|
126
|
+
// Activate the button to prevent multiple clicks
|
|
127
|
+
this._activateButton(true);
|
|
151
128
|
|
|
152
|
-
|
|
153
|
-
|
|
129
|
+
try {
|
|
130
|
+
// Add the product to the favorites list
|
|
131
|
+
const favResponse = await this._addToFavorites();
|
|
154
132
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
133
|
+
if (favResponse.error) {
|
|
134
|
+
throw new Error(favResponse.error);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const favoritedProduct = favResponse.products;
|
|
138
|
+
if (!favoritedProduct) {
|
|
139
|
+
throw new Error('Product not found');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Add the favorited product id to the storage and reinitialize all wishlist buttons
|
|
143
|
+
GWUtils.app.updateFavoriteItemsStorage({
|
|
144
|
+
addIds: [GWUtils.parseVariantId(favoritedProduct.id)],
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Render the favorited product to the customer's dashboard
|
|
148
|
+
GWUtils.dashboard._renderSingleFavoriteItem(favoritedProduct);
|
|
149
|
+
|
|
150
|
+
// Notify the customer
|
|
151
|
+
const customerFirstName = GWUtils.customerFirstName
|
|
152
|
+
? `${GWUtils.customerFirstName}'s`
|
|
153
|
+
: 'Your';
|
|
154
|
+
GWUtils.notify(`
|
|
160
155
|
<span>Added to ${customerFirstName} favorites</span>
|
|
161
156
|
<a href="#my-favorites" class="gw-notification__link">View</a>
|
|
162
157
|
`);
|
|
163
158
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
},
|
|
172
|
-
variant: this.currentVariant,
|
|
159
|
+
// Dispatch event
|
|
160
|
+
document.dispatchEvent(
|
|
161
|
+
new CustomEvent('wishlist:add', {
|
|
162
|
+
detail: {
|
|
163
|
+
product: {
|
|
164
|
+
id: this.productData.id,
|
|
165
|
+
title: this.productData.title,
|
|
173
166
|
},
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
} else {
|
|
167
|
+
variant: this.currentVariant,
|
|
168
|
+
},
|
|
169
|
+
})
|
|
170
|
+
);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error(error);
|
|
182
173
|
this._activateButton(false);
|
|
174
|
+
GWUtils.notify('An error occurred. Please try again later.');
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
this._activateButton(false);
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
// Remove the product from the favorites list
|
|
181
|
+
const removeFavResponse = await this._removeFromFavorites();
|
|
183
182
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const customerFirstName = GWUtils.customerFirstName
|
|
209
|
-
? `${GWUtils.customerFirstName}'s`
|
|
210
|
-
: 'Your';
|
|
211
|
-
GWUtils.notify(`
|
|
183
|
+
if (removeFavResponse.error) {
|
|
184
|
+
throw new Error(removeFavResponse.error);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const unfavoritedProduct = removeFavResponse.products;
|
|
188
|
+
if (!unfavoritedProduct) {
|
|
189
|
+
throw new Error('Product not found');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Remove the favorited product from carousel and drawer
|
|
193
|
+
GWUtils.dashboard._removeFavoriteItem(
|
|
194
|
+
GWUtils.parseVariantId(unfavoritedProduct.id)
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
// Reinitialize all wishlist buttons
|
|
198
|
+
GWUtils.app.updateFavoriteItemsStorage({
|
|
199
|
+
removeIds: [GWUtils.parseVariantId(unfavoritedProduct.id)],
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Notify the user
|
|
203
|
+
const customerFirstName = GWUtils.customerFirstName
|
|
204
|
+
? `${GWUtils.customerFirstName}'s`
|
|
205
|
+
: 'Your';
|
|
206
|
+
GWUtils.notify(`
|
|
212
207
|
<span>Product removed from ${customerFirstName} favorites</span>
|
|
213
208
|
<a href="#my-favorites" class="gw-notification__link">View</a>
|
|
214
209
|
`);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
210
|
+
} catch (error) {
|
|
211
|
+
console.error(error);
|
|
212
|
+
this._activateButton(true);
|
|
213
|
+
GWUtils.notify('An error occurred. Please try again later.');
|
|
220
214
|
}
|
|
221
|
-
|
|
222
|
-
if (this.loader) this.loader.hidden = true;
|
|
223
|
-
this.button.disabled = false;
|
|
224
|
-
this.button.removeAttribute('aria-disabled');
|
|
225
|
-
this.removeAttribute('Processing');
|
|
226
215
|
}
|
|
227
216
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
217
|
+
if (this.loader) this.loader.hidden = true;
|
|
218
|
+
this.button.disabled = false;
|
|
219
|
+
this.button.removeAttribute('aria-disabled');
|
|
220
|
+
this.removeAttribute('Processing');
|
|
221
|
+
}
|
|
234
222
|
|
|
235
|
-
|
|
223
|
+
// TODO: Update methods to use this getter
|
|
224
|
+
get productData() {
|
|
225
|
+
if (!this._productData) {
|
|
226
|
+
const productDataElement = this.querySelector('[data-product-data]');
|
|
227
|
+
this._productData = JSON.parse(productDataElement.textContent);
|
|
236
228
|
}
|
|
237
229
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return this.productData.variants?.nodes || [];
|
|
241
|
-
}
|
|
230
|
+
return this._productData;
|
|
231
|
+
}
|
|
242
232
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
233
|
+
// TODO: Update methods to use this getter
|
|
234
|
+
get productVariants() {
|
|
235
|
+
return this.productData.variants?.nodes || [];
|
|
236
|
+
}
|
|
248
237
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if (!GWUtils.hasCustomer) {
|
|
255
|
-
const productDataElement = this.querySelector('[data-product-data]');
|
|
256
|
-
const parsedProductData = JSON.parse(productDataElement.textContent);
|
|
257
|
-
|
|
258
|
-
const stored =
|
|
259
|
-
localStorage.getItem(GWCA.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS) ||
|
|
260
|
-
'[]';
|
|
261
|
-
const items = JSON.parse(stored);
|
|
262
|
-
|
|
263
|
-
const updatedItems = items.filter(
|
|
264
|
-
(item) => item.id !== parsedProductData.id
|
|
265
|
-
);
|
|
266
|
-
updatedItems.push(parsedProductData);
|
|
238
|
+
get currentVariant() {
|
|
239
|
+
return this.productVariants.find(
|
|
240
|
+
(variant) => variant.id == this.variantId
|
|
241
|
+
);
|
|
242
|
+
}
|
|
267
243
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
244
|
+
/**
|
|
245
|
+
* Adds the product to the favorites list.
|
|
246
|
+
* @returns {Promise<void>}
|
|
247
|
+
*/
|
|
248
|
+
async _addToFavorites() {
|
|
249
|
+
if (!GWUtils.hasCustomer) {
|
|
250
|
+
const productDataElement = this.querySelector('[data-product-data]');
|
|
251
|
+
const parsedProductData = JSON.parse(productDataElement.textContent);
|
|
252
|
+
|
|
253
|
+
const stored =
|
|
254
|
+
localStorage.getItem(GWCA.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS) ||
|
|
255
|
+
'[]';
|
|
256
|
+
const items = JSON.parse(stored);
|
|
257
|
+
|
|
258
|
+
const updatedItems = items.filter(
|
|
259
|
+
(item) => item.id !== parsedProductData.id
|
|
260
|
+
);
|
|
261
|
+
updatedItems.push(parsedProductData);
|
|
272
262
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
263
|
+
localStorage.setItem(
|
|
264
|
+
GWCA.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS,
|
|
265
|
+
JSON.stringify(updatedItems)
|
|
266
|
+
);
|
|
278
267
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
268
|
+
return {
|
|
269
|
+
success: true,
|
|
270
|
+
products: parsedProductData,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
283
273
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
274
|
+
const response = await GWUtils.request(GWCA.ENDPOINTS.FAVORITES.ADD, {
|
|
275
|
+
prodID: this.productId,
|
|
276
|
+
varID: this.variantId || this._getVariantId(),
|
|
277
|
+
});
|
|
287
278
|
|
|
288
|
-
|
|
279
|
+
if (response.error) {
|
|
280
|
+
throw new Error(response.error);
|
|
289
281
|
}
|
|
290
282
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
* @returns {Promise<void>}
|
|
294
|
-
*/
|
|
295
|
-
async _removeFromFavorites() {
|
|
296
|
-
if (!GWUtils.hasCustomer) {
|
|
297
|
-
const productData = this.querySelector('[data-product-data]');
|
|
298
|
-
const parsedProductData = JSON.parse(productData.textContent);
|
|
299
|
-
|
|
300
|
-
const stored =
|
|
301
|
-
localStorage.getItem(GWCA.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS) ||
|
|
302
|
-
'[]';
|
|
303
|
-
const items = JSON.parse(stored);
|
|
304
|
-
|
|
305
|
-
const updatedItems = items.filter(
|
|
306
|
-
(item) => item.id !== parsedProductData.id
|
|
307
|
-
);
|
|
308
|
-
localStorage.setItem(
|
|
309
|
-
GWCA.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS,
|
|
310
|
-
JSON.stringify(updatedItems)
|
|
311
|
-
);
|
|
312
|
-
|
|
313
|
-
return {
|
|
314
|
-
success: true,
|
|
315
|
-
products: parsedProductData,
|
|
316
|
-
};
|
|
317
|
-
}
|
|
283
|
+
return response;
|
|
284
|
+
}
|
|
318
285
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
286
|
+
/**
|
|
287
|
+
* Removes the product from the favorites list.
|
|
288
|
+
* @returns {Promise<void>}
|
|
289
|
+
*/
|
|
290
|
+
async _removeFromFavorites() {
|
|
291
|
+
if (!GWUtils.hasCustomer) {
|
|
292
|
+
const productData = this.querySelector('[data-product-data]');
|
|
293
|
+
const parsedProductData = JSON.parse(productData.textContent);
|
|
294
|
+
|
|
295
|
+
const stored =
|
|
296
|
+
localStorage.getItem(GWCA.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS) ||
|
|
297
|
+
'[]';
|
|
298
|
+
const items = JSON.parse(stored);
|
|
299
|
+
|
|
300
|
+
const updatedItems = items.filter(
|
|
301
|
+
(item) => item.id !== parsedProductData.id
|
|
302
|
+
);
|
|
303
|
+
localStorage.setItem(
|
|
304
|
+
GWCA.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS,
|
|
305
|
+
JSON.stringify(updatedItems)
|
|
324
306
|
);
|
|
325
307
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
return response;
|
|
308
|
+
return {
|
|
309
|
+
success: true,
|
|
310
|
+
products: parsedProductData,
|
|
311
|
+
};
|
|
331
312
|
}
|
|
332
313
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
if (this.buttonIcon.length)
|
|
340
|
-
this.buttonIcon.forEach((icon) => icon.removeAttribute('hidden'));
|
|
341
|
-
if (this.loader) this.loader.setAttribute('hidden', '');
|
|
342
|
-
|
|
343
|
-
if (isProductInFavorites) {
|
|
344
|
-
this.setAttribute('saved', '');
|
|
345
|
-
this.button.setAttribute('aria-label', this.labels.active);
|
|
346
|
-
if (this.buttonLabel)
|
|
347
|
-
this.buttonLabel.textContent = this.labels.active;
|
|
348
|
-
} else {
|
|
349
|
-
this.removeAttribute('saved');
|
|
350
|
-
this.button.setAttribute('aria-label', this.labels.inactive);
|
|
351
|
-
if (this.buttonLabel)
|
|
352
|
-
this.buttonLabel.textContent = this.labels.inactive;
|
|
353
|
-
}
|
|
314
|
+
const response = await GWUtils.request(GWCA.ENDPOINTS.FAVORITES.REMOVE, {
|
|
315
|
+
prodID: this.productId,
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
if (response.error) {
|
|
319
|
+
throw new Error(response.error);
|
|
354
320
|
}
|
|
355
321
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
* @returns {boolean} True if the product is in the favorites list, otherwise false.
|
|
359
|
-
*/
|
|
360
|
-
_isProductInFavorites() {
|
|
361
|
-
if (!GWUtils.hasCustomer) {
|
|
362
|
-
const tempWishlistItemsStorage = localStorage.getItem(
|
|
363
|
-
GWCA.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS
|
|
364
|
-
);
|
|
365
|
-
const tempWishlistItems = tempWishlistItemsStorage
|
|
366
|
-
? JSON.parse(tempWishlistItemsStorage)
|
|
367
|
-
: [];
|
|
322
|
+
return response;
|
|
323
|
+
}
|
|
368
324
|
|
|
369
|
-
|
|
370
|
-
|
|
325
|
+
/**
|
|
326
|
+
* Activates the button based on whether the product is in the favorites list.
|
|
327
|
+
* @param {boolean} isProductInFavorites - True if the product is in the favorites list, otherwise false.
|
|
328
|
+
* @returns {void}
|
|
329
|
+
*/
|
|
330
|
+
_activateButton(isProductInFavorites) {
|
|
331
|
+
const buttonIcon = this.shadowRoot.querySelectorAll('[data-button-icon]');
|
|
332
|
+
const buttonLabel = this.shadowRoot.querySelector('[data-button-label]');
|
|
333
|
+
|
|
334
|
+
const labels = {
|
|
335
|
+
inactive:
|
|
336
|
+
GWUtils.componentData.wishlist?.addToWishlistLabel ||
|
|
337
|
+
'Add to wishlist',
|
|
338
|
+
active:
|
|
339
|
+
GWUtils.componentData.wishlist?.addedToWishlistLabel ||
|
|
340
|
+
'Added to wishlist',
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
if (buttonIcon.length)
|
|
344
|
+
buttonIcon.forEach((icon) => icon.removeAttribute('hidden'));
|
|
345
|
+
if (this.loader) this.loader.setAttribute('hidden', '');
|
|
346
|
+
|
|
347
|
+
if (isProductInFavorites) {
|
|
348
|
+
this.setAttribute('saved', '');
|
|
349
|
+
this.button.setAttribute('aria-label', labels.active);
|
|
350
|
+
if (buttonLabel) buttonLabel.textContent = labels.active;
|
|
351
|
+
} else {
|
|
352
|
+
this.removeAttribute('saved');
|
|
353
|
+
this.button.setAttribute('aria-label', labels.inactive);
|
|
354
|
+
if (buttonLabel) buttonLabel.textContent = labels.inactive;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
371
357
|
|
|
372
|
-
|
|
373
|
-
|
|
358
|
+
/**
|
|
359
|
+
* Checks if the product is in the favorites list.
|
|
360
|
+
* @returns {boolean} True if the product is in the favorites list, otherwise false.
|
|
361
|
+
*/
|
|
362
|
+
_isProductInFavorites() {
|
|
363
|
+
if (!GWUtils.hasCustomer) {
|
|
364
|
+
const tempWishlistItemsStorage = localStorage.getItem(
|
|
365
|
+
GWCA.STORAGE_KEYS.TEMP_WISHLIST_PRODUCTS
|
|
374
366
|
);
|
|
375
|
-
const
|
|
376
|
-
? JSON.parse(
|
|
367
|
+
const tempWishlistItems = tempWishlistItemsStorage
|
|
368
|
+
? JSON.parse(tempWishlistItemsStorage)
|
|
377
369
|
: [];
|
|
378
370
|
|
|
379
|
-
return
|
|
371
|
+
return tempWishlistItems.some((item) => item.id === this.productId);
|
|
380
372
|
}
|
|
373
|
+
|
|
374
|
+
const wishlistItemsStorage = sessionStorage.getItem(
|
|
375
|
+
GWCA.STORAGE_KEYS.WISHLIST_PRODUCT_IDS
|
|
376
|
+
);
|
|
377
|
+
const wishlistItems = wishlistItemsStorage
|
|
378
|
+
? JSON.parse(wishlistItemsStorage)
|
|
379
|
+
: [];
|
|
380
|
+
|
|
381
|
+
return wishlistItems.includes(this.productId);
|
|
381
382
|
}
|
|
382
|
-
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (document.readyState === 'loading') {
|
|
386
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
387
|
+
customElements.define('gw-wishlist-button', GWWishlistButton);
|
|
388
|
+
});
|
|
389
|
+
} else {
|
|
390
|
+
customElements.define('gw-wishlist-button', GWWishlistButton);
|
|
391
|
+
}
|
|
383
392
|
});
|