@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.
- package/algolia/algolia-loader.js +56 -0
- package/algolia/algolia-search.js +222 -0
- package/auth/teddy-auth-login.js +29 -0
- package/auth/teddy-auth-profile.js +58 -0
- package/auth/teddy-auth-register.js +52 -0
- package/auth/teddy-auth-reset.js +39 -0
- package/auth/teddy-auth.js +92 -0
- package/bantoa/bantoa-product.js +64 -0
- package/bantoa/bantoa-search.js +46 -0
- package/bantoa/bantoa-stylemix.js +43 -0
- package/bantoa/bantoa.js +21 -0
- package/cart/teddy-cart-controller.js +163 -0
- package/cart/teddy-cart-customer.js +86 -0
- package/cart/teddy-cart-discounts.js +55 -0
- package/cart/teddy-cart-promo-apply.js +24 -0
- package/cart/teddy-cart-promo-error.js +38 -0
- package/cart/teddy-cart-promo-loading.js +20 -0
- package/cart/teddy-cart-promo.js +96 -0
- package/components/mc-btn.js +38 -0
- package/components/mc-card-render.js +33 -0
- package/components/mc-cart-counter.js +14 -0
- package/components/mc-cart-error.js +35 -0
- package/components/mc-cart-quantity.js +43 -0
- package/components/mc-cart-remove.js +32 -0
- package/components/mc-copy.js +33 -0
- package/components/mc-element.js +84 -0
- package/components/mc-form-errors.js +35 -0
- package/components/mc-form-success.js +31 -0
- package/components/mc-form.js +223 -0
- package/components/mc-input-area.js +13 -0
- package/components/mc-input-checkbox-group.js +52 -0
- package/components/mc-input-checkbox.js +12 -0
- package/components/mc-input-password.js +39 -0
- package/components/mc-input-places.js +43 -0
- package/components/mc-input-quantity.js +43 -0
- package/components/mc-input-select.js +14 -0
- package/components/mc-input-text.js +12 -0
- package/components/mc-input.js +137 -0
- package/components/mc-loader.js +21 -0
- package/components/mc-modal.js +69 -0
- package/components/mc-password-eye.js +24 -0
- package/components/mc-password-tips.js +60 -0
- package/components/mc-qrcode.js +41 -0
- package/components/mc-range.js +108 -0
- package/components/mc-read-more.js +56 -0
- package/components/mc-recommended.js +50 -0
- package/components/mc-referrer.js +20 -0
- package/components/mc-splash-controller.js +32 -0
- package/components/mc-splash-link.js +65 -0
- package/components/mc-stoq.js +30 -0
- package/components/mc-swiper.js +333 -0
- package/components/mc-video.js +61 -0
- package/css/bootstrap-lg.css +2762 -0
- package/css/bootstrap-lg.min.css +1 -0
- package/css/bootstrap-md.css +2762 -0
- package/css/bootstrap-md.min.css +1 -0
- package/css/bootstrap-sm.css +2762 -0
- package/css/bootstrap-sm.min.css +1 -0
- package/css/bootstrap-xl.css +2790 -0
- package/css/bootstrap-xl.min.css +1 -0
- package/css/bootstrap-xxl.css +2762 -0
- package/css/bootstrap-xxl.min.css +1 -0
- package/css/bootstrap.css +9824 -0
- package/css/bootstrap.min.css +5 -0
- package/css/mc-form-errors.css +3 -0
- package/css/mc-loader.css +6 -0
- package/css/mc-password-eye.css +6 -0
- package/css/mc-password-tips.css +6 -0
- package/css/mc-read-more.css +14 -0
- package/css/mc-video.css +4 -0
- package/css/mc-wishlist-hero-btn.css +7 -0
- package/loader.js +110 -0
- package/loyalty/teddy-loyalty-create.js +40 -0
- package/loyalty/teddy-loyalty-redeem.js +38 -0
- package/loyalty/teddy-loyalty.js +214 -0
- package/package.json +20 -0
- package/res/mc-events.js +43 -0
- package/res/mc-shopify.js +439 -0
- package/res/mc-utils.js +119 -0
- package/res/mc-vue.js +9350 -0
- package/returns/teddy-return-iban.js +115 -0
- package/returns/teddy-return-list.js +165 -0
- package/returns/teddy-return-request.js +353 -0
- package/scripts/publish-store.js +62 -0
- package/test/auth-login-error.json +4 -0
- package/test/auth-login-success.json +13 -0
- package/test/auth-password-change-error.json +4 -0
- package/test/auth-password-change-success.json +3 -0
- package/test/auth-register-error.json +4 -0
- package/test/auth-register-success.json +12 -0
- package/test/auth-reset-error.json +4 -0
- package/test/auth-reset-success.json +3 -0
- package/test/loyalty-error.json +4 -0
- package/test/loyalty-noinfo.json +18 -0
- package/test/loyalty-redeem-error.json +4 -0
- package/test/loyalty-redeem-success.json +11 -0
- package/test/loyalty-success.json +143 -0
- package/test/returns-create-success.json +1 -0
- package/test/returns-get-success.json +35 -0
- package/test/returns-get-tracking.json +30 -0
- package/test/returns-list-empty.json +4 -0
- package/test/returns-list-success.json +59 -0
- package/test/returns-search-manual.json +67 -0
- package/test/returns-search-success.json +76 -0
- package/test/wishlist-error.json +4 -0
- package/test/wishlist-success.json +3 -0
- package/wishlist/teddy-wishlist-btn.js +55 -0
- package/wishlist/teddy-wishlist-clear.js +18 -0
- package/wishlist/teddy-wishlist-counter.js +35 -0
- package/wishlist/teddy-wishlist-item.js +46 -0
- package/wishlist/teddy-wishlist-page.js +59 -0
- package/wishlist/teddy-wishlist.js +131 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
await loadComponent('./components/mc-element.js', false);
|
|
2
|
+
await loadComponent('./res/mc-shopify.js', false);
|
|
3
|
+
|
|
4
|
+
class AlgoliaLoader extends McElement {
|
|
5
|
+
template;
|
|
6
|
+
|
|
7
|
+
connectedCallback() {
|
|
8
|
+
this.template = this.innerHTML;
|
|
9
|
+
if(window.lastAlgoliaResponse) this.onLoad({detail: window.lastAlgoliaResponse});
|
|
10
|
+
window.addEventListener('algolia-search-complete', this.onLoad.bind(this));
|
|
11
|
+
this.addEventListener('click', this.onClick.bind(this));
|
|
12
|
+
|
|
13
|
+
const observer = new IntersectionObserver((entries) => {
|
|
14
|
+
entries.forEach(entry => {
|
|
15
|
+
if(entry.isIntersecting) {
|
|
16
|
+
this.onClick();
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}, { rootMargin: '300px' });
|
|
20
|
+
|
|
21
|
+
observer.observe(this);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
onClick = (e) => {
|
|
25
|
+
e?.preventDefault();
|
|
26
|
+
window.dispatchEvent(new CustomEvent('algolia-load-more'));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
onLoad = (e) => {
|
|
30
|
+
const data = e.detail;
|
|
31
|
+
console.log('algolia-search-complete', data);
|
|
32
|
+
|
|
33
|
+
if(!data) {
|
|
34
|
+
console.log('AlgoliaLoader onLoad: no data'); return;
|
|
35
|
+
}
|
|
36
|
+
if(data.page == undefined) {
|
|
37
|
+
console.log('AlgoliaLoader onLoad: no page'); return;
|
|
38
|
+
}
|
|
39
|
+
if(data.page+1 >= data.nbPages) {
|
|
40
|
+
console.log('AlgoliaLoader onLoad: no more pages');
|
|
41
|
+
this.deactivate(); return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log('AlgoliaLoader onLoad: updating', data);
|
|
45
|
+
const shown = data.hitsPerPage * (data.page + 1);
|
|
46
|
+
const total = data.nbHits;
|
|
47
|
+
|
|
48
|
+
this.innerHTML = this.template.replace('${shown}', shown).replace('${total}', total);
|
|
49
|
+
this.activate();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!customElements.get('algolia-loader')) {
|
|
54
|
+
customElements.define('algolia-loader', AlgoliaLoader);
|
|
55
|
+
}
|
|
56
|
+
window.AlgoliaLoader = AlgoliaLoader;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
const {createApp} = await import('../res/mc-vue.js');
|
|
2
|
+
await loadComponent('./components/mc-element.js', false);
|
|
3
|
+
|
|
4
|
+
class AlgoliaSearch extends McElement {
|
|
5
|
+
connectedCallback() {
|
|
6
|
+
console.log('AlgoliaSearch init');
|
|
7
|
+
this.init();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
init = () => {
|
|
11
|
+
const cmp = this;
|
|
12
|
+
|
|
13
|
+
if(!cmp.dataset.apiKey || !cmp.dataset.appId) {
|
|
14
|
+
console.error('AlgoliaSearch: apiKey or appId not defined');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if(!cmp.dataset.productsIndex && !cmp.dataset.suggestionsIndex && !cmp.dataset.collectionsIndex) {
|
|
18
|
+
console.error('AlgoliaSearch: at least one of productsIndex, suggestionsIndex or collectionsIndex must be defined');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const app = createApp({
|
|
23
|
+
delimiters: ['${', '}'], // setta i delimitatori di vue, altrimenti se usiamo gli standard va in conflitto con liquid
|
|
24
|
+
data: () => {
|
|
25
|
+
return {
|
|
26
|
+
loading: false,
|
|
27
|
+
query: '',
|
|
28
|
+
products: [],
|
|
29
|
+
suggestions: [],
|
|
30
|
+
collections: [],
|
|
31
|
+
queryProductIndex: -1,
|
|
32
|
+
querySuggestionIndex: -1,
|
|
33
|
+
queryCollectionIndex: -1
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
methods: {
|
|
37
|
+
|
|
38
|
+
search() {
|
|
39
|
+
if (this.query.length < 3) {
|
|
40
|
+
this.loading = false;
|
|
41
|
+
this.products = [];
|
|
42
|
+
this.suggestions = [];
|
|
43
|
+
this.collections = [];
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.loading = true;
|
|
48
|
+
axios({
|
|
49
|
+
method: 'post',
|
|
50
|
+
url: `https://${cmp.dataset.appId}.algolia.net/1/indexes/*/queries`,
|
|
51
|
+
headers: {
|
|
52
|
+
"content-type": "application/json",
|
|
53
|
+
"x-algolia-api-key": cmp.dataset.apiKey,
|
|
54
|
+
"x-algolia-application-id": cmp.dataset.appId
|
|
55
|
+
},
|
|
56
|
+
data: this.getRequest()
|
|
57
|
+
}).then((response) => {
|
|
58
|
+
this.onSuccess(response);
|
|
59
|
+
}).catch((error) => {
|
|
60
|
+
this.onError(error);
|
|
61
|
+
}).finally(() => {
|
|
62
|
+
this.loading = false;
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
getRequest() {
|
|
67
|
+
const requests = [];
|
|
68
|
+
if(cmp.dataset.productsIndex === undefined || cmp.dataset.productsIndex.length == 0){
|
|
69
|
+
this.queryProductIndex = -1;
|
|
70
|
+
console.warn('AlgoliaSearch: productsIndex not defined, products search disabled');
|
|
71
|
+
}
|
|
72
|
+
if(cmp.dataset.suggestionsIndex === undefined || cmp.dataset.suggestionsIndex.length == 0){
|
|
73
|
+
this.querySuggestionIndex = -1;
|
|
74
|
+
console.warn('AlgoliaSearch: suggestionsIndex not defined, suggestions search disabled');
|
|
75
|
+
}
|
|
76
|
+
if(cmp.dataset.collectionsIndex === undefined || cmp.dataset.collectionsIndex.length == 0){
|
|
77
|
+
this.queryCollectionIndex = -1;
|
|
78
|
+
console.warn('AlgoliaSearch: collectionsIndex not defined, collections search disabled');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if(cmp.dataset.suggestionsIndex !== undefined) {
|
|
82
|
+
requests.push({
|
|
83
|
+
indexName: cmp.dataset.suggestionsIndex,
|
|
84
|
+
query: this.query,
|
|
85
|
+
distinct: true,
|
|
86
|
+
attributesToHighlight: [],
|
|
87
|
+
attributesToSnippet: [],
|
|
88
|
+
hitsPerPage: parseInt(cmp.dataset.suggestionsMax) || 4,
|
|
89
|
+
page: 0,
|
|
90
|
+
attributesToRetrieve: ["query"],
|
|
91
|
+
facets: ["*"]
|
|
92
|
+
});
|
|
93
|
+
this.querySuggestionIndex = requests.length - 1;
|
|
94
|
+
}
|
|
95
|
+
if(cmp.dataset.productsIndex !== undefined) {
|
|
96
|
+
requests.push({
|
|
97
|
+
indexName: cmp.dataset.productsIndex,
|
|
98
|
+
query: this.query,
|
|
99
|
+
attributesToRetrieve: ["handle"],
|
|
100
|
+
distinct: true,
|
|
101
|
+
attributesToHighlight: [],
|
|
102
|
+
attributesToSnippet: [],
|
|
103
|
+
hitsPerPage: parseInt(cmp.dataset.productsMax) || 4,
|
|
104
|
+
page: 0,
|
|
105
|
+
facets: ["*"]
|
|
106
|
+
});
|
|
107
|
+
this.queryProductIndex = requests.length - 1;
|
|
108
|
+
}
|
|
109
|
+
if(cmp.dataset.collectionsIndex !== undefined) {
|
|
110
|
+
requests.push({
|
|
111
|
+
indexName: cmp.dataset.collectionsIndex,
|
|
112
|
+
attributesToRetrieve: ["url", "path"],
|
|
113
|
+
query: this.query,
|
|
114
|
+
distinct: true,
|
|
115
|
+
attributesToHighlight: [],
|
|
116
|
+
attributesToSnippet: [],
|
|
117
|
+
hitsPerPage: parseInt(cmp.dataset.collectionsMax) || 4,
|
|
118
|
+
page: 0,
|
|
119
|
+
facets: ["*"]
|
|
120
|
+
});
|
|
121
|
+
this.queryCollectionIndex = requests.length - 1;
|
|
122
|
+
}
|
|
123
|
+
return {requests};
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
onSuccess(response) {
|
|
127
|
+
if(!response.data.results) {
|
|
128
|
+
this.onError('No results');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this.mapProducts(response);
|
|
133
|
+
this.mapSuggestions(response);
|
|
134
|
+
this.mapCollections(response);
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
mapProducts(response) {
|
|
138
|
+
if(this.queryProductIndex < 0) {
|
|
139
|
+
this.products = [];
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const hits = response.data.results[this.queryProductIndex]?.hits;
|
|
143
|
+
if(!hits) {
|
|
144
|
+
this.products = [];
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
this.products = hits.filter(hit => hit.handle != undefined && hit.handle != null);
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
mapSuggestions(response) {
|
|
151
|
+
if(this.querySuggestionIndex < 0) {
|
|
152
|
+
this.suggestions = [];
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const hits = response.data.results[this.querySuggestionIndex]?.hits;
|
|
156
|
+
if(!hits) {
|
|
157
|
+
this.suggestions = [];
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
this.suggestions = hits.map(hit => {
|
|
162
|
+
if(!hit.query) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
query: hit.query,
|
|
167
|
+
title: hit.query.replace(new RegExp(this.query, 'gi'), match => `<strong>${match}</strong>`)
|
|
168
|
+
};
|
|
169
|
+
}).filter(s => s != null);
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
mapCollections(response) {
|
|
173
|
+
if(this.queryCollectionIndex < 0) {
|
|
174
|
+
this.collections = [];
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const hits = response.data.results[this.queryCollectionIndex]?.hits;
|
|
178
|
+
if(!hits) {
|
|
179
|
+
this.collections = [];
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
this.collections = hits.map(hit => {
|
|
183
|
+
if(!hit.url || !hit.path) {
|
|
184
|
+
console.warn('AlgoliaSearch: collection hit without url or path', hit);
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
url: hit.url,
|
|
189
|
+
path: hit.path,
|
|
190
|
+
title: hit.path.replace(new RegExp(this.query, 'gi'), match => `<strong>${match}</strong>`)
|
|
191
|
+
};
|
|
192
|
+
}).filter(c => c != null);
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
onError(error) {
|
|
196
|
+
this.products = [];
|
|
197
|
+
this.suggestions = [];
|
|
198
|
+
this.collections = [];
|
|
199
|
+
console.error('AlgoliaSearch error', error);
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
suggest(suggestion) {
|
|
203
|
+
this.query = suggestion;
|
|
204
|
+
this.search();
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
computed: {
|
|
208
|
+
showResults() {
|
|
209
|
+
return this.products.length > 0 || this.suggestions.length > 0 || this.collections.length > 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
app.config.compilerOptions.isCustomElement = tag => tag.includes('-'); // per evitare che vue vada in conflitto con i custom element
|
|
215
|
+
app.mount(this);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (!customElements.get('algolia-search')) {
|
|
220
|
+
customElements.define('algolia-search', AlgoliaSearch);
|
|
221
|
+
}
|
|
222
|
+
window.AlgoliaSearch = AlgoliaSearch;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
await loadComponent('./auth/teddy-auth.js', false);
|
|
2
|
+
|
|
3
|
+
class TeddyAuthLogin extends TeddyAuth {
|
|
4
|
+
|
|
5
|
+
// formatto i dati per il payload sovrascrivendo il metodo getData
|
|
6
|
+
getData = () => {
|
|
7
|
+
const formData = new FormData(this.form);
|
|
8
|
+
|
|
9
|
+
this.data = {};
|
|
10
|
+
|
|
11
|
+
Array.from(formData.entries()).forEach(([key, value]) => {
|
|
12
|
+
this.data[key] = value;
|
|
13
|
+
});
|
|
14
|
+
this.data.sessionId = this.getSessionId();
|
|
15
|
+
this.data.mergeCart = true;
|
|
16
|
+
this.data.callingSystem = 6;
|
|
17
|
+
console.log('TeddyAuthLogin.getData', this.data);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
success = (response) => {
|
|
21
|
+
this.multipassSuccess(response);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!customElements.get('teddy-auth-login')) {
|
|
27
|
+
customElements.define('teddy-auth-login', TeddyAuthLogin);
|
|
28
|
+
}
|
|
29
|
+
window.TeddyAuthLogin = TeddyAuthLogin;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
await loadComponent('./auth/teddy-auth.js', false);
|
|
2
|
+
await loadComponent('./components/mc-form-success.js', false);
|
|
3
|
+
|
|
4
|
+
class TeddyAuthProfile extends TeddyAuth {
|
|
5
|
+
|
|
6
|
+
// formatto i dati per il payload sovrascrivendo il metodo getData
|
|
7
|
+
getData = () => {
|
|
8
|
+
const formData = new FormData(this.form);
|
|
9
|
+
|
|
10
|
+
this.data = {};
|
|
11
|
+
Array.from(formData.entries()).forEach(([key, value]) => {
|
|
12
|
+
if(key == 'birthday' && this.data?.dayOfBirth == undefined){
|
|
13
|
+
this.data.dayOfBirth = `${new Date(value).getDate()}`.padStart(2, '0');
|
|
14
|
+
this.data.monthOfBirth = `${(new Date(value).getMonth() + 1)}`.padStart(2, '0');
|
|
15
|
+
this.data.yearOfBirth = `${new Date(value).getFullYear()}`;
|
|
16
|
+
}
|
|
17
|
+
else if(key.includes('.')) {
|
|
18
|
+
const [parent, child] = key.split('.');
|
|
19
|
+
this.data[parent] = this.data[parent] || {};
|
|
20
|
+
this.data[parent][child] = value == 'true';
|
|
21
|
+
} else {
|
|
22
|
+
if(value === 'true') value = true;
|
|
23
|
+
if(value === 'false') value = false;
|
|
24
|
+
this.data[key] = value;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
this.data.preferences = this.data.preferences || {};
|
|
29
|
+
this.data.preferences.newsletter = this.data.preferences.newsletter || false;
|
|
30
|
+
this.data.preferences.sms = this.data.preferences.sms || false;
|
|
31
|
+
this.data.preferences.profiling = this.data.preferences.profiling || false;
|
|
32
|
+
|
|
33
|
+
this.data.callingSystem = 6;
|
|
34
|
+
this.data.sessionId = this.getSessionId();
|
|
35
|
+
console.log('TeddyAuthProfile.getData', this.data);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
success = (response) => {
|
|
39
|
+
const data = response.data;
|
|
40
|
+
if(!data.success){
|
|
41
|
+
this.error(data);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const success = this.querySelector('mc-form-success');
|
|
45
|
+
if(!success) return;
|
|
46
|
+
if(!theme.t.success.profile_updated) {
|
|
47
|
+
console.error('Profile updated message not found');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
success.showMessage(theme.t.success.profile_updated);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!customElements.get('teddy-auth-profile')) {
|
|
56
|
+
customElements.define('teddy-auth-profile', TeddyAuthProfile);
|
|
57
|
+
}
|
|
58
|
+
window.TeddyAuthProfile = TeddyAuthProfile;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
await loadComponent('./auth/teddy-auth.js', false);
|
|
2
|
+
|
|
3
|
+
class TeddyAuthRegister extends TeddyAuth {
|
|
4
|
+
|
|
5
|
+
// formatto i dati per il payload sovrascrivendo il metodo getData
|
|
6
|
+
getData = () => {
|
|
7
|
+
const formData = new FormData(this.form);
|
|
8
|
+
|
|
9
|
+
this.data = {};
|
|
10
|
+
|
|
11
|
+
Array.from(formData.entries()).forEach(([key, value]) => {
|
|
12
|
+
if(key == 'birthday' && this.data?.dayOfBirth == undefined){
|
|
13
|
+
this.data.dayOfBirth = `${new Date(value).getDate()}`.padStart(2, '0');
|
|
14
|
+
this.data.monthOfBirth = `${(new Date(value).getMonth() + 1)}`.padStart(2, '0');
|
|
15
|
+
this.data.yearOfBirth = `${new Date(value).getFullYear()}`;
|
|
16
|
+
}
|
|
17
|
+
else if (key == 'authSMSNotification' || key == 'authEmailNotification' || key == 'authDataProfiling') {
|
|
18
|
+
// Convert boolean values to string
|
|
19
|
+
this.data[key] = value == 1;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this.data[key] = value;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
if(this.data.authSMSNotification === undefined) {
|
|
26
|
+
this.data.authSMSNotification = false;
|
|
27
|
+
}
|
|
28
|
+
if(this.data.authEmailNotification === undefined) {
|
|
29
|
+
this.data.authEmailNotification = false;
|
|
30
|
+
}
|
|
31
|
+
if(this.data.authDataProfiling === undefined) {
|
|
32
|
+
this.data.authDataProfiling = false;
|
|
33
|
+
}
|
|
34
|
+
if(this.data.importantDate === undefined) {
|
|
35
|
+
this.data.importantDate = '';
|
|
36
|
+
}
|
|
37
|
+
this.data.requestLoyaltyCard = true;
|
|
38
|
+
this.data.sessionId = this.getSessionId();
|
|
39
|
+
this.data.callingSystem = 6;
|
|
40
|
+
console.log('TeddyAuthRegister.getData', this.data);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
success = (response) => {
|
|
44
|
+
this.multipassSuccess(response);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!customElements.get('teddy-auth-register')) {
|
|
50
|
+
customElements.define('teddy-auth-register', TeddyAuthRegister);
|
|
51
|
+
}
|
|
52
|
+
window.TeddyAuthRegister = TeddyAuthRegister;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
await loadComponent('./auth/teddy-auth.js', false);
|
|
2
|
+
await loadComponent('./components/mc-form-success.js', false);
|
|
3
|
+
|
|
4
|
+
class TeddyAuthReset extends TeddyAuth {
|
|
5
|
+
|
|
6
|
+
// formatto i dati per il payload sovrascrivendo il metodo getData
|
|
7
|
+
getData = () => {
|
|
8
|
+
const formData = new FormData(this.form);
|
|
9
|
+
|
|
10
|
+
this.data = {};
|
|
11
|
+
Array.from(formData.entries()).forEach(([key, value]) => {
|
|
12
|
+
this.data[key] = value;
|
|
13
|
+
});
|
|
14
|
+
this.data.callingSystem = "6";
|
|
15
|
+
this.data.sessionId = this.getSessionId();
|
|
16
|
+
console.log('TeddyAuthReset.getData', this.data);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
success = (response) => {
|
|
20
|
+
const data = response.data;
|
|
21
|
+
if(!data.success){
|
|
22
|
+
this.error(data);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const success = this.querySelector('mc-form-success');
|
|
26
|
+
if(!success) return;
|
|
27
|
+
if(!theme.t.success.password_changed) {
|
|
28
|
+
console.error('Password changed message not found');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
success.showMessage(theme.t.success.password_changed);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!customElements.get('teddy-auth-reset')) {
|
|
37
|
+
customElements.define('teddy-auth-reset', TeddyAuthReset);
|
|
38
|
+
}
|
|
39
|
+
window.TeddyAuthReset = TeddyAuthReset;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import '../res/mc-events.js';
|
|
2
|
+
await loadComponent('./components/mc-loader.js', false);
|
|
3
|
+
await loadComponent('./components/mc-form.js', false);
|
|
4
|
+
await loadComponent('./res/mc-utils.js', false);
|
|
5
|
+
await loadComponent('./res/mc-events.js', false);
|
|
6
|
+
|
|
7
|
+
class TeddyAuth extends McForm {
|
|
8
|
+
|
|
9
|
+
connectedCallback() {
|
|
10
|
+
this.init();
|
|
11
|
+
this.addEventListener(MCEVENTS.FORM_SUBMIT, this.onSubmit.bind(this));
|
|
12
|
+
this.addEventListener(MCEVENTS.FORM_COMPLETED, this.onComplete.bind(this));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
onSubmit = () => {
|
|
16
|
+
const loader = this.querySelector('mc-loader');
|
|
17
|
+
if(loader) {
|
|
18
|
+
loader.activate();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
onComplete = () => {
|
|
23
|
+
const loader = this.querySelector('mc-loader');
|
|
24
|
+
if(loader) {
|
|
25
|
+
loader.deactivate();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ottengo il sessionId dalla localStorage o lo genero se non esiste
|
|
30
|
+
getSessionId = () => {
|
|
31
|
+
return TeddyAuth.getSessionId();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ottengo il sessionId dalla localStorage o lo genero se non esiste
|
|
35
|
+
static getSessionId = () => {
|
|
36
|
+
if(localStorage.getItem('sessionId') === null) {
|
|
37
|
+
localStorage.setItem('sessionId', TeddyAuth.generateSessionId());
|
|
38
|
+
}
|
|
39
|
+
return localStorage.getItem('sessionId');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// genero un ID di sessione unico e sicuro
|
|
43
|
+
static generateSessionId = (length = 24) => {
|
|
44
|
+
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
45
|
+
let result = '';
|
|
46
|
+
const cryptoObj = window.crypto || window.msCrypto; // supporto IE11
|
|
47
|
+
|
|
48
|
+
if (cryptoObj && cryptoObj.getRandomValues) {
|
|
49
|
+
const randomValues = new Uint32Array(length);
|
|
50
|
+
cryptoObj.getRandomValues(randomValues);
|
|
51
|
+
for (let i = 0; i < length; i++) {
|
|
52
|
+
result += charset[randomValues[i] % charset.length];
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
// fallback meno sicuro
|
|
56
|
+
for (let i = 0; i < length; i++) {
|
|
57
|
+
result += charset[Math.floor(Math.random() * charset.length)];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
error = (e) => {
|
|
65
|
+
McShopify.customEvent(MCEVENTS.FORM_ERROR, e, this);
|
|
66
|
+
let message = theme.t.errors.generic || 'An error occurred';
|
|
67
|
+
if(!theme?.t?.errors?.idm) {
|
|
68
|
+
console.error('TeddyAuth: Missing theme.t.errors.idm translation');
|
|
69
|
+
this.errors.showError(message);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
message = theme.t.errors.idm[e.error?.code] || theme.t.errors.idm[e.status] || theme.t.errors.idm.default || message;
|
|
73
|
+
console.error("TeddyAuth.error", message, e);
|
|
74
|
+
this.errors.showError(message);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
multipassSuccess = (response) => {
|
|
78
|
+
const data = response.data;
|
|
79
|
+
console.log('TeddyAuth.multipassSuccess', data);
|
|
80
|
+
if(!data.success || data.error != undefined || !data.data?.multipassUrl) {
|
|
81
|
+
this.error(data);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
location.href = data.data.multipassUrl;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!customElements.get('teddy-auth')) {
|
|
90
|
+
customElements.define('teddy-auth', TeddyAuth);
|
|
91
|
+
}
|
|
92
|
+
window.TeddyAuth = TeddyAuth;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
await loadComponent('./res/mc-events.js', false);
|
|
2
|
+
await loadComponent('./components/mc-element.js', false);
|
|
3
|
+
|
|
4
|
+
class BantoaProduct extends McElement {
|
|
5
|
+
connectedCallback() {
|
|
6
|
+
console.log("BantoaProduct: Connected", this.id);
|
|
7
|
+
if(!this.dataset.sku) {
|
|
8
|
+
console.error("BantoaProduct: No SKU found in the element.");
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if(!this.dataset.position){
|
|
12
|
+
console.error("BantoaProduct: No position found in the element.");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if(window.isBantoaLoaded)
|
|
16
|
+
this.init();
|
|
17
|
+
window.addEventListener(MCEVENTS.BANTOA_LOADED, this.init.bind(this));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
checkExists = () => {
|
|
21
|
+
axios({
|
|
22
|
+
url: `https://api.bantoa.com/api/visual?apikey=${bantoaKey}&onlycheckexist=1&code=${this.dataset.sku}&tm=1751548151`,
|
|
23
|
+
method: 'get',
|
|
24
|
+
}).then(r => {
|
|
25
|
+
if(r.data.productexist == 'ok'){
|
|
26
|
+
this.classList.remove('d-none');
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
.catch(e => {
|
|
30
|
+
console.error("BantoaProduct: Error checking product existence", e);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
init = () => {
|
|
35
|
+
this.addEventListener('click', this.openViewer.bind(this));
|
|
36
|
+
this.checkExists();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
openViewer = () => {
|
|
40
|
+
if(!window.isBantoaLoaded) {
|
|
41
|
+
console.warn("BantoaProduct: Bantoa tracker is not loaded.");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const data = {
|
|
45
|
+
item: this.dataset.sku,
|
|
46
|
+
quality: '0.75',
|
|
47
|
+
max_results: 100,
|
|
48
|
+
min_results: 1,
|
|
49
|
+
position: this.dataset.position,
|
|
50
|
+
};
|
|
51
|
+
if(this.dataset.variant){
|
|
52
|
+
data.filter = {
|
|
53
|
+
sizes: this.dataset.variant
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
console.log("BantoaProduct: Opening viewer with data", data);
|
|
57
|
+
bnt_r_ai('visual', 'modal', data);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!customElements.get('bantoa-product')) {
|
|
62
|
+
customElements.define('bantoa-product', BantoaProduct);
|
|
63
|
+
}
|
|
64
|
+
window.BantoaProduct = BantoaProduct;
|
|
@@ -0,0 +1,46 @@
|
|
|
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 BantoaSearch extends McElement {
|
|
6
|
+
connectedCallback() {
|
|
7
|
+
if(!this.dataset.position){
|
|
8
|
+
console.error("BantoaSearch: No position found in the element.");
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
this.addEventListener('click', this.openViewer.bind(this));
|
|
12
|
+
const url = new URL(window.location.href);
|
|
13
|
+
if(url.searchParams.has("bantoa")){
|
|
14
|
+
this.openViewer(this);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
addParameterToUrl(){
|
|
19
|
+
const url = new URL(window.location.href);
|
|
20
|
+
url.searchParams.append("bantoa", "bantoa");
|
|
21
|
+
window.history.pushState({}, '', url)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
openViewer = () => {
|
|
25
|
+
if(!window.isBantoaLoaded) {
|
|
26
|
+
console.warn("BantoaSearch: Bantoa tracker is not loaded.");
|
|
27
|
+
window.addEventListener(MCEVENTS.BANTOA_LOADED, () => this.openViewer());
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
bnt_r_ai('visual', 'modal', {
|
|
31
|
+
quality: '0.75',
|
|
32
|
+
max_results: 100,
|
|
33
|
+
min_results: 1,
|
|
34
|
+
position: this.dataset.position,
|
|
35
|
+
});
|
|
36
|
+
const url = new URL(window.location.href);
|
|
37
|
+
if(!url.searchParams.has("bantoa")){
|
|
38
|
+
this.addParameterToUrl();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!customElements.get('bantoa-search')) {
|
|
44
|
+
customElements.define('bantoa-search', BantoaSearch);
|
|
45
|
+
}
|
|
46
|
+
window.BantoaSearch = BantoaSearch;
|