@teddy-dev/frontend 1.0.1

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.
Files changed (112) hide show
  1. package/algolia/algolia-loader.js +56 -0
  2. package/algolia/algolia-search.js +222 -0
  3. package/auth/teddy-auth-login.js +29 -0
  4. package/auth/teddy-auth-profile.js +58 -0
  5. package/auth/teddy-auth-register.js +52 -0
  6. package/auth/teddy-auth-reset.js +39 -0
  7. package/auth/teddy-auth.js +92 -0
  8. package/bantoa/bantoa-product.js +64 -0
  9. package/bantoa/bantoa-search.js +46 -0
  10. package/bantoa/bantoa-stylemix.js +43 -0
  11. package/bantoa/bantoa.js +21 -0
  12. package/cart/teddy-cart-controller.js +163 -0
  13. package/cart/teddy-cart-customer.js +86 -0
  14. package/cart/teddy-cart-discounts.js +55 -0
  15. package/cart/teddy-cart-promo-apply.js +24 -0
  16. package/cart/teddy-cart-promo-error.js +38 -0
  17. package/cart/teddy-cart-promo-loading.js +20 -0
  18. package/cart/teddy-cart-promo.js +96 -0
  19. package/components/mc-btn.js +38 -0
  20. package/components/mc-card-render.js +33 -0
  21. package/components/mc-cart-counter.js +14 -0
  22. package/components/mc-cart-error.js +35 -0
  23. package/components/mc-cart-quantity.js +43 -0
  24. package/components/mc-cart-remove.js +32 -0
  25. package/components/mc-copy.js +33 -0
  26. package/components/mc-element.js +84 -0
  27. package/components/mc-form-errors.js +35 -0
  28. package/components/mc-form-success.js +31 -0
  29. package/components/mc-form.js +223 -0
  30. package/components/mc-input-area.js +13 -0
  31. package/components/mc-input-checkbox-group.js +52 -0
  32. package/components/mc-input-checkbox.js +12 -0
  33. package/components/mc-input-password.js +39 -0
  34. package/components/mc-input-places.js +43 -0
  35. package/components/mc-input-quantity.js +43 -0
  36. package/components/mc-input-select.js +14 -0
  37. package/components/mc-input-text.js +12 -0
  38. package/components/mc-input.js +137 -0
  39. package/components/mc-loader.js +21 -0
  40. package/components/mc-modal.js +69 -0
  41. package/components/mc-password-eye.js +24 -0
  42. package/components/mc-password-tips.js +60 -0
  43. package/components/mc-qrcode.js +41 -0
  44. package/components/mc-range.js +108 -0
  45. package/components/mc-read-more.js +56 -0
  46. package/components/mc-recommended.js +50 -0
  47. package/components/mc-referrer.js +20 -0
  48. package/components/mc-splash-controller.js +32 -0
  49. package/components/mc-splash-link.js +65 -0
  50. package/components/mc-stoq.js +30 -0
  51. package/components/mc-swiper.js +333 -0
  52. package/components/mc-video.js +61 -0
  53. package/css/bootstrap-lg.css +2762 -0
  54. package/css/bootstrap-lg.min.css +1 -0
  55. package/css/bootstrap-md.css +2762 -0
  56. package/css/bootstrap-md.min.css +1 -0
  57. package/css/bootstrap-sm.css +2762 -0
  58. package/css/bootstrap-sm.min.css +1 -0
  59. package/css/bootstrap-xl.css +2790 -0
  60. package/css/bootstrap-xl.min.css +1 -0
  61. package/css/bootstrap-xxl.css +2762 -0
  62. package/css/bootstrap-xxl.min.css +1 -0
  63. package/css/bootstrap.css +9824 -0
  64. package/css/bootstrap.min.css +5 -0
  65. package/css/mc-form-errors.css +3 -0
  66. package/css/mc-loader.css +6 -0
  67. package/css/mc-password-eye.css +6 -0
  68. package/css/mc-password-tips.css +6 -0
  69. package/css/mc-read-more.css +14 -0
  70. package/css/mc-video.css +4 -0
  71. package/css/mc-wishlist-hero-btn.css +7 -0
  72. package/loader.js +110 -0
  73. package/loyalty/teddy-loyalty-create.js +40 -0
  74. package/loyalty/teddy-loyalty-redeem.js +38 -0
  75. package/loyalty/teddy-loyalty.js +214 -0
  76. package/package.json +20 -0
  77. package/res/mc-events.js +43 -0
  78. package/res/mc-shopify.js +439 -0
  79. package/res/mc-utils.js +119 -0
  80. package/res/mc-vue.js +9350 -0
  81. package/returns/teddy-return-iban.js +115 -0
  82. package/returns/teddy-return-list.js +165 -0
  83. package/returns/teddy-return-request.js +353 -0
  84. package/scripts/publish-store.js +62 -0
  85. package/test/auth-login-error.json +4 -0
  86. package/test/auth-login-success.json +13 -0
  87. package/test/auth-password-change-error.json +4 -0
  88. package/test/auth-password-change-success.json +3 -0
  89. package/test/auth-register-error.json +4 -0
  90. package/test/auth-register-success.json +12 -0
  91. package/test/auth-reset-error.json +4 -0
  92. package/test/auth-reset-success.json +3 -0
  93. package/test/loyalty-error.json +4 -0
  94. package/test/loyalty-noinfo.json +18 -0
  95. package/test/loyalty-redeem-error.json +4 -0
  96. package/test/loyalty-redeem-success.json +11 -0
  97. package/test/loyalty-success.json +143 -0
  98. package/test/returns-create-success.json +1 -0
  99. package/test/returns-get-success.json +35 -0
  100. package/test/returns-get-tracking.json +30 -0
  101. package/test/returns-list-empty.json +4 -0
  102. package/test/returns-list-success.json +59 -0
  103. package/test/returns-search-manual.json +67 -0
  104. package/test/returns-search-success.json +76 -0
  105. package/test/wishlist-error.json +4 -0
  106. package/test/wishlist-success.json +3 -0
  107. package/wishlist/teddy-wishlist-btn.js +55 -0
  108. package/wishlist/teddy-wishlist-clear.js +18 -0
  109. package/wishlist/teddy-wishlist-counter.js +35 -0
  110. package/wishlist/teddy-wishlist-item.js +46 -0
  111. package/wishlist/teddy-wishlist-page.js +59 -0
  112. package/wishlist/teddy-wishlist.js +131 -0
@@ -0,0 +1,43 @@
1
+ await loadComponent('./res/mc-events.js', false);
2
+ await loadComponent('./components/mc-element.js', false);
3
+ await loadComponent('./bantoa/bantoa.js', false);
4
+
5
+ class BantoaStylemix extends McElement {
6
+ connectedCallback() {
7
+ if(!this.dataset.position || !this.dataset.items){
8
+ console.error("BantoaStylemix: No position or items found in the element.");
9
+ return;
10
+ }
11
+ this.render();
12
+ }
13
+
14
+ render = () => {
15
+ if(!this.dataset.position || !this.dataset.items){
16
+ console.error("BantoaStylemix: No position or items found in the element.");
17
+ return;
18
+ }
19
+ if(!window.isBantoaLoaded) {
20
+ console.warn("BantoaSearch: Bantoa tracker is not loaded.");
21
+ window.addEventListener(MCEVENTS.BANTOA_LOADED, () => this.render());
22
+ return;
23
+ }
24
+ const settings = {
25
+ position: this.dataset.position,
26
+ items: this.dataset.items.split(','),
27
+ selector: this.getSelector(),
28
+ max_outfit: parseInt(this.dataset.maxOutfit) || 6,
29
+ min_outfit: parseInt(this.dataset.minOutfit) || 1,
30
+ layout: this.dataset.layout || 'moodboard',
31
+ filterOnlyCurrentSeason: this.dataset.filterOnlyCurrentSeason === 'true',
32
+ orderByCurrentSeason: this.dataset.orderByCurrentSeason === 'true',
33
+ type: this.dataset.type == 'both' ? ['ai', 'human'] : (this.dataset.type != undefined ? [this.dataset.type] : ['ai', 'human'])
34
+ };
35
+ console.log("BantoaStylemix: Rendering outfit with settings", settings);
36
+ bnt_r_ai('render', 'outfit', settings);
37
+ }
38
+ }
39
+
40
+ if (!customElements.get('bantoa-stylemix')) {
41
+ customElements.define('bantoa-stylemix', BantoaStylemix);
42
+ }
43
+ window.BantoaStylemix = BantoaStylemix;
@@ -0,0 +1,21 @@
1
+ await loadComponent('./res/mc-events.js', false);
2
+
3
+ class Bantoa {
4
+
5
+ init = (apikey) => {
6
+ window.bantoaKey = apikey;
7
+ const self = this;
8
+ !function(t,n,e,a,c,o,r,s){t.BantoaTrackerObject=c,t[c]=t[c]||function(){(t[c].q=t[c].q||[]).push(arguments)},
9
+ t[o]=t[o]||function(){(t[o].q=t[o].q||[]).push(arguments)},
10
+ r=n.createElement(e),s=n.getElementsByTagName(e)[0],r.async=1, r.onload=self.started, r.src=a,s.parentNode.insertBefore(r,s)}
11
+ (window,document,"script","https://www.bantoa.com/bantoa.tk.min.js?apikey="+apikey,"bnt_t","bnt_r_ai");
12
+ }
13
+
14
+ started = () => {
15
+ window.isBantoaLoaded = true;
16
+ McShopify.customEvent(MCEVENTS.BANTOA_LOADED);
17
+ console.log("Bantoa tracker initialized");
18
+ }
19
+ }
20
+ window.isBantoaLoaded = false;
21
+ window.Bantoa = Bantoa;
@@ -0,0 +1,163 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-element.js', false);
3
+ await loadComponent('./auth/teddy-auth.js', false);
4
+ await loadComponent('./res/mc-shopify.js', false);
5
+
6
+ class TeddyCartController extends McElement {
7
+ cartData;
8
+ cartLines = [];
9
+
10
+ // chiamata di associazione del carrello
11
+ associateCart = (customerId) => {
12
+ if(!customerId) {
13
+ throw new Error("TeddyCartController: No customer ID provided");
14
+ }
15
+ this.cartData = null;
16
+ this.cartLines = [];
17
+
18
+ const options = {
19
+ data: {
20
+ device: 'web'
21
+ }
22
+ };
23
+ if(theme.apis.cart.dev) {
24
+ options.method = 'GET';
25
+ options.url = `${Shopify.routes.root}?section_id=test-cart-response`;
26
+ } else {
27
+ options.method = 'POST';
28
+ options.url = theme.apis.cart.associate.replace('{userId}', customerId);
29
+ }
30
+ console.log("TeddyCartController: Associating cart with options:", options);
31
+ return axios(options).then(r => {
32
+ this.cartData = this.getData(r);
33
+ if(!this.cartData) {
34
+ throw new Error("TeddyCartController: No cart data found after association");
35
+ }
36
+ return this.cartData;
37
+ });
38
+ }
39
+
40
+ applyPromo = (data) => {
41
+ this.cartData = null;
42
+ this.cartLines = [];
43
+
44
+ const options = {
45
+ data: data
46
+ };
47
+ if(theme.apis.cart.dev) {
48
+ options.method = 'GET';
49
+ options.url = `${Shopify.routes.root}?section_id=test-cart-response`;
50
+ } else {
51
+ options.method = 'POST';
52
+ options.url = theme.apis.cart.apply;
53
+ options.headers = {
54
+ "Ocp-Apim-Subscription-Key": "0936a98c9baa4aa1a2787657e151b44a",
55
+ "Content-Type": "application/json"
56
+ }
57
+ }
58
+
59
+ return axios(options).then(r => {
60
+ this.cartData = this.getData(r);
61
+ if(!this.cartData) {
62
+ throw new Error("TeddyCartController: No cart data found after applying promo");
63
+ }
64
+ window.blackbox = this.cartData;
65
+ return this.cartData;
66
+ });
67
+ }
68
+
69
+ setAttributes = (attributes) => {
70
+ McShopify.updateCart({
71
+ data: {
72
+ attributes: {
73
+ _discounts: JSON.stringify(attributes)
74
+ }
75
+ }
76
+ });
77
+ }
78
+
79
+ setAttributes = (attributes) => {
80
+ if(!attributes) { console.error('TeddyCartController.updateCart: Devi passare almeno uno dei parametri form, formData o data'); return; }
81
+ if(typeof attributes !== 'object') { console.error('TeddyCartController.updateCart: Il parametro attributes deve essere un oggetto'); return; }
82
+
83
+ const config = {
84
+ url: `${Shopify.routes.root}cart/update.js`,
85
+ method: 'post',
86
+ data: {
87
+ attributes: {
88
+ _discounts: JSON.stringify(attributes)
89
+ }
90
+ }
91
+ };
92
+
93
+ return axios(config).then(r => {
94
+ if(r.data.items_changelog?.added?.length > 0){ //se ci sono elementi rimossi
95
+ McShopify.customEvent(MCEVENTS.CART_UPDATED, r.data);
96
+ McShopify.customEvent(MCEVENTS.CART_REMOVED, r.data);
97
+ }
98
+ if(r.data.items_changelog?.removed?.length > 0){ //se ci sono elementi aggiunti
99
+ McShopify.customEvent(MCEVENTS.CART_UPDATED, r.data);
100
+ McShopify.customEvent(MCEVENTS.CART_ADDED, r.data);
101
+ }
102
+ return r.data;
103
+ }).catch(e => {
104
+ McShopify.customEvent(MCEVENTS.CART_ERROR, e);
105
+ });
106
+ }
107
+
108
+ getAttributes = (data, sent) => {
109
+ console.log("TeddyCartController.getAttributes: Retrieving attributes", sent);
110
+ return {
111
+ session_id: TeddyAuth.getSessionId(),
112
+ actuals: {
113
+ coupon_code: sent.cart.promoCode,
114
+ gift_card_code: "",
115
+ gift_card_usage: 0,
116
+ fidelity_points: 0
117
+ },
118
+ shipping: {
119
+ isFreeShipping: data.cart.totals.freeShipping,
120
+ labels: []
121
+ },
122
+ cart_lines: data.cart.items.map(item => {
123
+ const skuItem = sent.cart.items.find(i => i.barcode === item.barcode);
124
+ return {
125
+ sku: skuItem.skuCode || "",
126
+ discount_price: [
127
+ {
128
+ qty: skuItem.quantity || 1,
129
+ unit_price: item.originalPrice,
130
+ discount_price: item.discount,
131
+ labels: item.appliedPromotions.map((d) => d.name) || [],
132
+ }
133
+ ]
134
+ };
135
+ })
136
+ };
137
+ }
138
+
139
+ // ottiene i dati del carrello dalla risposta dell'associazione e dell'applicazione della promo
140
+ getData = (response) => {
141
+ let data = response.data?.data || response.data;
142
+ if(theme.apis.cart.dev) {
143
+ const doc = McUtils.getDocument(data);
144
+ data = JSON.parse(doc.querySelector('div').textContent);
145
+ }
146
+ if(!response.data.success){
147
+ throw new Error("CartController: Error in cart data response", {
148
+ cause: data
149
+ });
150
+ }
151
+ if(!data || !data.cart?.items) {
152
+ throw new Error("CartController: No items found in cart data", {
153
+ cause: data
154
+ });
155
+ }
156
+ return data;
157
+ }
158
+
159
+ }
160
+ if (!customElements.get('teddy-cart-controller')) {
161
+ customElements.define('teddy-cart-controller', TeddyCartController);
162
+ }
163
+ window.TeddyCartController = TeddyCartController;
@@ -0,0 +1,86 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./res/mc-shopify.js', false);
3
+ await loadComponent('./cart/teddy-cart-controller.js', false);
4
+
5
+ class TeddyCartCustomer extends McElement {
6
+ static RETRY_LIMIT = 3;
7
+ retryCount = 0;
8
+
9
+ connectedCallback() {
10
+ this.init();
11
+ }
12
+
13
+ init = () => {
14
+ this.controller = document.createElement('teddy-cart-controller');
15
+ customElements.whenDefined('teddy-cart-controller').then(() => {
16
+ this.setLogged();
17
+ });
18
+ }
19
+
20
+ startAssociation = () => {
21
+ this.restrict();
22
+ this.controller.associateCart(this.dataset.logged)
23
+ .then(r => {
24
+ console.log("TeddyCartCustomer: Cart associated successfully", r);
25
+ return this.controller.findLines();
26
+ })
27
+ .then(r => {
28
+ console.log("TeddyCartCustomer: Lines found successfully", r);
29
+ return this.controller.clearCart();
30
+ })
31
+ .then(r => {
32
+ console.log("TeddyCartCustomer: Cart cleared successfully", r);
33
+ return this.controller.addAndUpdateCart();
34
+ })
35
+ .catch(e => {
36
+ if(this.retryCount > TeddyCartCustomer.RETRY_LIMIT) {
37
+ console.error("TeddyCartCustomer: Error associating cart after retries", e);
38
+ this.retryCount = 0;
39
+ return;
40
+ }
41
+ console.warn("TeddyCartCustomer: Retrying cart association", e);
42
+ this.retryCount++;
43
+ this.startAssociation();
44
+ })
45
+ .finally(() => {
46
+ this.release();
47
+ });
48
+ }
49
+
50
+ restrict = () => {
51
+ window.onbeforeunload = function (e) {
52
+ var message = theme.t.errors.logging_in,
53
+ e = e || window.event;
54
+ if (e) {
55
+ e.returnValue = message;
56
+ }
57
+ return message;
58
+ };
59
+ }
60
+
61
+ release = () => {
62
+ window.onbeforeunload = null;
63
+ }
64
+
65
+ // imposta il cliente loggato nel localStorage e lancia l'evento di login/logout
66
+ setLogged = () => {
67
+ if(this.dataset.logged) {
68
+ if(!localStorage.getItem('customer')) {
69
+ console.log('Customer logged in:', this.dataset.logged);
70
+ this.startAssociation();
71
+ McShopify.customEvent(MCEVENTS.LOGIN, {customer: this.dataset.logged});
72
+ }
73
+ localStorage.setItem('customer', this.dataset.logged);
74
+ } else {
75
+ if(localStorage.getItem('customer')) {
76
+ McShopify.customEvent(MCEVENTS.LOGOUT, {customer: localStorage.getItem('customer')});
77
+ }
78
+ localStorage.removeItem('customer');
79
+ }
80
+ }
81
+ }
82
+
83
+ if (!customElements.get('teddy-cart-customer')) {
84
+ customElements.define('teddy-cart-customer', TeddyCartCustomer);
85
+ }
86
+ window.TeddyCartCustomer = TeddyCartCustomer;
@@ -0,0 +1,55 @@
1
+ await loadComponent('./components/mc-element.js', false);
2
+ await loadComponent('./res/mc-events.js', false);
3
+ await loadComponent('./res/mc-utils.js', false);
4
+
5
+ class TeddyCartDiscounts extends McElement {
6
+ #wrapperTemplate;
7
+ #discountTemplate;
8
+
9
+ connectedCallback() {
10
+ this.#wrapperTemplate = this.querySelector('template[name="wrapper"]').innerHTML;
11
+ this.#discountTemplate = this.querySelector('template[name="discount"]').innerHTML;
12
+ this.innerHTML = '';
13
+
14
+ this.render();
15
+ window.addEventListener(MCEVENTS.PROMO_APPLIED, this.render.bind(this));
16
+ }
17
+
18
+ render = () => {
19
+ if(!window.blackbox){
20
+ console.warn('TeddyCartDiscounts: blackbox object not found');
21
+ this.innerHTML = '';
22
+ return;
23
+ }
24
+ console.log('TeddyCartDiscounts: rendering discounts', window.blackbox);
25
+ if(!blackbox.appliedPromotions || blackbox.appliedPromotions.length === 0){
26
+ this.innerHTML = '';
27
+ return;
28
+ }
29
+
30
+ this.innerHTML = this.#wrapperTemplate;
31
+ const listContainer = this.querySelector('[data-list]');
32
+ if(!listContainer){
33
+ console.warn('TeddyCartDiscounts: list container not found');
34
+ this.innerHTML = '';
35
+ return;
36
+ }
37
+
38
+ const promoList = [];
39
+ blackbox.appliedPromotions.forEach(promo => {
40
+ const discountHTML = this.#discountTemplate
41
+ .replace('{title}', promo.name)
42
+ .replace('{amount}', McUtils.money(promo.discount*100))
43
+ .replace('{automatic}', promo.automatic ? 'true' : 'false');
44
+ promoList.push(discountHTML);
45
+ });
46
+
47
+ listContainer.innerHTML = promoList.join('');
48
+ }
49
+
50
+ }
51
+
52
+ if (!customElements.get('teddy-cart-discounts')) {
53
+ customElements.define('teddy-cart-discounts', TeddyCartDiscounts);
54
+ }
55
+ window.TeddyCartDiscounts = TeddyCartDiscounts;
@@ -0,0 +1,24 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./res/mc-shopify.js', false);
3
+ await loadComponent('./auth/teddy-auth.js', false);
4
+ await loadComponent('./cart/teddy-cart-controller.js', false);
5
+ await loadComponent('./cart/teddy-cart-promo.js', false);
6
+
7
+ class TeddyCartPromoApply extends TeddyCartPromo {
8
+
9
+ connectedCallback() {
10
+ this.controller = document.createElement('teddy-cart-controller');
11
+ customElements.whenDefined('teddy-cart-controller').then(() => {
12
+ this.addEventListener('click', (e) => {
13
+ e.preventDefault();
14
+ this.startPromo();
15
+ });
16
+ });
17
+ }
18
+
19
+ }
20
+
21
+ if (!customElements.get('teddy-cart-promo-apply')) {
22
+ customElements.define('teddy-cart-promo-apply', TeddyCartPromoApply);
23
+ }
24
+ window.TeddyCartPromoApply = TeddyCartPromoApply;
@@ -0,0 +1,38 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-element.js', false);
3
+
4
+ class TeddyCartPromoError extends McElement {
5
+
6
+ connectedCallback() {
7
+ window.addEventListener(MCEVENTS.PROMO_ERROR, (e) => {
8
+ this.onError(e);
9
+ });
10
+ window.addEventListener(MCEVENTS.PROMO_APPLY, () => {
11
+ this.deactivate();
12
+ });
13
+ }
14
+
15
+ onError = (e) => {
16
+ if(!e?.detail){
17
+ console.warn('TeddyCartPromoError: No error details provided');
18
+ this.deactivate();
19
+ return;
20
+ }
21
+ if(!theme?.t?.errors?.bb) {
22
+ console.error('TeddyAuth: Missing theme.t.errors.bb translation');
23
+ this.activate();
24
+ return;
25
+ }
26
+
27
+ const error = e.detail;
28
+ console.log('TeddyCartPromoError: Promo error received', error);
29
+ this.innerText = theme.t.errors.bb[error.error?.message] || theme.t.errors.bb[error.status] || theme.t.errors.bb.default || theme.t.errors.generic || 'An error occurred';
30
+ this.activate();
31
+ }
32
+ }
33
+
34
+ if (!customElements.get('teddy-cart-promo-error')) {
35
+ customElements.define('teddy-cart-promo-error', TeddyCartPromoError);
36
+ }
37
+
38
+ window.TeddyCartPromoError = TeddyCartPromoError;
@@ -0,0 +1,20 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-loader.js', false);
3
+
4
+ class TeddyCartPromoLoading extends McLoader {
5
+
6
+ connectedCallback() {
7
+ window.addEventListener(MCEVENTS.PROMO_APPLY, () => {
8
+ this.activate();
9
+ });
10
+ window.addEventListener(MCEVENTS.PROMO_COMPLETED, () => {
11
+ this.deactivate();
12
+ });
13
+ }
14
+ }
15
+
16
+ if (!customElements.get('teddy-cart-promo-loading')) {
17
+ customElements.define('teddy-cart-promo-loading', TeddyCartPromoLoading);
18
+ }
19
+
20
+ window.TeddyCartPromoLoading = TeddyCartPromoLoading;
@@ -0,0 +1,96 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./res/mc-shopify.js', false);
3
+ await loadComponent('./auth/teddy-auth.js', false);
4
+ await loadComponent('./cart/teddy-cart-controller.js', false);
5
+
6
+ class TeddyCartPromo extends McElement {
7
+ static RETRY_LIMIT = 3;
8
+ retryCount = 0;
9
+ controller;
10
+
11
+ connectedCallback() {
12
+ this.controller = document.createElement('teddy-cart-controller');
13
+ customElements.whenDefined('teddy-cart-controller').then(() => {
14
+ this.startPromo();
15
+
16
+ window.addEventListener(MCEVENTS.CART_UPDATED, () => {
17
+ this.startPromo();
18
+ });
19
+ });
20
+ }
21
+
22
+ startPromo = () => {
23
+ McShopify.customEvent(MCEVENTS.PROMO_APPLY);
24
+ const data = this.getData();
25
+ this.controller.applyPromo(data)
26
+ .then(r => {
27
+ return this.controller.getAttributes(r, data);
28
+ })
29
+ .then(r => {
30
+ return this.controller.setAttributes(r);
31
+ })
32
+ .then(r => {
33
+ console.log('TeddyCartPromo: Promo applied successfully', r);
34
+ McShopify.customEvent(MCEVENTS.PROMO_APPLIED, r);
35
+ })
36
+ .catch(e => {
37
+ if(!e.cause?.error){
38
+ this.retry(e); return;
39
+ }
40
+
41
+ McShopify.customEvent(MCEVENTS.PROMO_ERROR, e.cause);
42
+ })
43
+ .finally(() => {
44
+ McShopify.customEvent(MCEVENTS.PROMO_COMPLETED);
45
+ });
46
+ }
47
+
48
+ retry = (e) => {
49
+ if(this.retryCount > TeddyCartPromo.RETRY_LIMIT) {
50
+ console.error("TeddyCartPromo: Error associating cart after retries", e);
51
+ this.retryCount = 0;
52
+ McShopify.customEvent(MCEVENTS.PROMO_ERROR, e);
53
+ return;
54
+ }
55
+ console.warn("TeddyCartPromo: Retrying cart association", e);
56
+ this.retryCount++;
57
+ this.startPromo();
58
+ }
59
+
60
+ getData = () => {
61
+ const form = this.querySelector('form') || document.getElementById(this.getAttribute('form')) || this.closest('teddy-cart-promo').querySelector('form');
62
+ if(!form) {
63
+ console.error("TeddyCartPromo: Form not found");
64
+ return;
65
+ }
66
+ const formdata = new FormData(form);
67
+ const data = McForm.formDataToObject(formdata);
68
+
69
+ this.data = {
70
+ callingSystem: 6,
71
+ sessionId: TeddyAuth.getSessionId(),
72
+ cart: {
73
+ items: []
74
+ }
75
+ };
76
+
77
+ if(!data.brand) { console.error("TeddyCartPromo: Brand not found"); return; }
78
+ if(!data.market) { console.error("TeddyCartPromo: Market not found"); return; }
79
+ if(!data.items || data.items.length === 0) { console.error("TeddyCartPromo: Items not found"); return; }
80
+
81
+ this.data.brand = data.brand;
82
+ this.data.market = data.market;
83
+ this.data.cart.items = data.items.map(item => {
84
+ return {...item, price: Number(item.price), quantity: Number(item.quantity)};
85
+ });
86
+ this.data.cart.loyaltyCardBarcode = data.loyaltyCardBarcode;
87
+ this.data.cart.promoCode = data.promoCode;
88
+ return this.data;
89
+ }
90
+
91
+ }
92
+
93
+ if (!customElements.get('teddy-cart-promo')) {
94
+ customElements.define('teddy-cart-promo', TeddyCartPromo);
95
+ }
96
+ window.TeddyCartPromo = TeddyCartPromo;
@@ -0,0 +1,38 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-element.js', false);
3
+
4
+ class McBtn extends McElement {
5
+
6
+ // oggetto di azioni possibili per il pulsante
7
+ actions = {
8
+ activate: () => this.target.activate(),
9
+ deactivate: () => this.target.deactivate(),
10
+ toggle: () => this.target.toggle()
11
+ }
12
+
13
+ connectedCallback() {
14
+ this.init();
15
+ }
16
+
17
+ init = () => {
18
+ this.target = this.target || document.querySelector(this.dataset.target);
19
+ if(!this.target) { console.error(`McBtn: Target element not found for selector ${this.dataset.target}`); return; }
20
+
21
+ // posso configurare il trigger e l'azione da eseguire
22
+ const trigger = this.dataset.trigger || 'click';
23
+ const action = this.dataset.action || 'toggle';
24
+
25
+ // attivo l'azione associata al trigger
26
+ this.addEventListener(trigger, this.actions[action]);
27
+
28
+ // se il target è un elemento custom, registro gli eventi di attivazione e disattivazione per attivare il pulsante
29
+ this.target.addEventListener(MCEVENTS.EL_ACTIVATED, this.activate.bind(this));
30
+ this.target.addEventListener(MCEVENTS.EL_DEACTIVATED, this.deactivate.bind(this));
31
+ }
32
+
33
+ }
34
+
35
+ if (!window.customElements.get('mc-btn')) {
36
+ window.customElements.define('mc-btn', McBtn);
37
+ }
38
+ window.McBtn = McBtn;
@@ -0,0 +1,33 @@
1
+ await loadComponent('./res/mc-shopify.js', false);
2
+
3
+ class McCardRender extends HTMLElement {
4
+
5
+ connectedCallback() {
6
+ if(!this.dataset.handle) {
7
+ console.error('McCardRender: Missing product handle in dataset.');
8
+ return;
9
+ }
10
+ this.render();
11
+ }
12
+
13
+ render = () => {
14
+ const section = this.dataset.section || 'helper-product-card';
15
+
16
+ McShopify.section({
17
+ path: `${Shopify.routes.root}products/${this.dataset.handle}`,
18
+ section_id: section,
19
+ onSuccess: (html) => {
20
+ this.innerHTML = html;
21
+ },
22
+ onError: (e) => {
23
+ console.error('McCardRender: Error fetching product card:', e);
24
+ }
25
+ });
26
+ }
27
+
28
+ }
29
+ if(!customElements.get('mc-card-render')){
30
+ customElements.define('mc-card-render', McCardRender);
31
+ }
32
+ window.McCardRender = McCardRender;
33
+ export default McCardRender;
@@ -0,0 +1,14 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-element.js', false);
3
+
4
+ class McCartCounter extends McElement {
5
+ connectedCallback() {
6
+ window.addEventListener(MCEVENTS.CART_UPDATED, this.reload.bind(this));
7
+ }
8
+ }
9
+
10
+ if(!customElements.get('mc-cart-counter')){
11
+ customElements.define('mc-cart-counter', McCartCounter);
12
+ }
13
+ window.McCartCounter = McCartCounter;
14
+ export default McCartCounter;
@@ -0,0 +1,35 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-element.js', false);
3
+ await loadComponent('./res/mc-shopify.js', false);
4
+
5
+ class McCartError extends McElement {
6
+
7
+ connectedCallback() {
8
+ setTimeout(() => {
9
+ window.addEventListener(MCEVENTS.CART_ERROR, this.onCartError.bind(this));
10
+ });
11
+ }
12
+
13
+ onCartError = (e) => {
14
+ const message = e.detail.response?.data?.message || e.detail.message;
15
+
16
+ const container = this.querySelector('[data-message]');
17
+ if(container) {
18
+ container.innerText = message;
19
+ }
20
+
21
+ const modal = bootstrap.Modal.getOrCreateInstance(this);
22
+ if(!modal) {
23
+ console.warn('McCartError: modal not found');
24
+ return;
25
+ }
26
+
27
+ modal.show();
28
+ }
29
+ }
30
+
31
+ if (!customElements.get('mc-cart-error')) {
32
+ customElements.define('mc-cart-error', McCartError);
33
+ }
34
+
35
+ window.McCartError = McCartError;