ng-easycommerce-v18 0.3.21-beta.3 → 0.3.22-beta.2
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/README.md +7 -7
- package/esm2022/lib/classes/filters/filter.mjs +27 -2
- package/esm2022/lib/constants/api.constants.service.mjs +7 -1
- package/esm2022/lib/ec-components/blocks-ec/block-products-ec/block-products-ec.component.mjs +5 -3
- package/esm2022/lib/ec-components/checkout-ec/payment-ec/payment-ec.component.mjs +1 -5
- package/esm2022/lib/ec-components/checkout-ec/payment-ec/payment-methods/mp-redirect-ec/mp-redirect-ec.component.mjs +44 -53
- package/esm2022/lib/ec-components/header-ec/header-ec.component.mjs +32 -23
- package/esm2022/lib/ec-components/related-products-ec/related-products-ec.component.mjs +6 -4
- package/esm2022/lib/ec-components/widgets-ec/magnizoom-ec/magnizoom-ec.component.mjs +4 -2
- package/esm2022/lib/ec-components/widgets-ec/redsys-catch-ec/redsys-catch-ec.component.mjs +7 -17
- package/esm2022/lib/ec-services/analytics/facebook-pixel.service.mjs +4 -2
- package/esm2022/lib/ec-services/analytics/google-analytics.service.mjs +4 -2
- package/esm2022/lib/ec-services/analytics/gtm.service.mjs +90 -30
- package/esm2022/lib/ec-services/options.service.mjs +27 -3
- package/esm2022/lib/ec-services/parameters.service.mjs +41 -1
- package/fesm2022/ng-easycommerce-v18.mjs +445 -296
- package/fesm2022/ng-easycommerce-v18.mjs.map +1 -1
- package/lib/constants/api.constants.service.d.ts +4 -0
- package/lib/ec-components/checkout-ec/payment-ec/payment-methods/mp-redirect-ec/mp-redirect-ec.component.d.ts +0 -1
- package/lib/ec-services/analytics/gtm.service.d.ts +5 -0
- package/lib/ec-services/options.service.d.ts +4 -0
- package/lib/ec-services/parameters.service.d.ts +6 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, makeEnvironmentProviders, inject, Injectable, PLATFORM_ID, RendererFactory2, afterNextRender, signal, EnvironmentInjector, runInInjectionContext, Component, ChangeDetectorRef, HostListener, CUSTOM_ELEMENTS_SCHEMA, Input, Pipe, Injector, EventEmitter, Output, forwardRef, afterRender, ViewChild, Inject, computed,
|
|
2
|
+
import { InjectionToken, makeEnvironmentProviders, inject, Injectable, PLATFORM_ID, RendererFactory2, afterNextRender, signal, EnvironmentInjector, runInInjectionContext, Component, ChangeDetectorRef, HostListener, CUSTOM_ELEMENTS_SCHEMA, Input, Pipe, Injector, EventEmitter, Output, forwardRef, afterRender, ViewChild, Inject, computed, Renderer2, ChangeDetectionStrategy, Directive } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { DOCUMENT, isPlatformBrowser, AsyncPipe, CommonModule, TitleCasePipe, JsonPipe, UpperCasePipe, Location } from '@angular/common';
|
|
5
5
|
import { take, BehaviorSubject, shareReplay, map, catchError, of, filter, ReplaySubject, firstValueFrom, concatMap, throwError, switchMap, combineLatest } from 'rxjs';
|
|
@@ -123,6 +123,12 @@ class ApiConstantsService {
|
|
|
123
123
|
this._translate.use(locale.split('_')[0]);
|
|
124
124
|
this.LOCALE = locale;
|
|
125
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Indica si la aplicación está corriendo en producción.
|
|
128
|
+
*/
|
|
129
|
+
get IS_PRODUCTION() {
|
|
130
|
+
return this.environment.production === true;
|
|
131
|
+
}
|
|
126
132
|
//Storage key
|
|
127
133
|
LOCALE_KEY = 'LOCALE';
|
|
128
134
|
CHANNEL_KEY = 'CHANNEL';
|
|
@@ -533,6 +539,10 @@ class OptionsService {
|
|
|
533
539
|
* Maneja las peticiones a la API
|
|
534
540
|
*/
|
|
535
541
|
connection = inject(ConnectionService);
|
|
542
|
+
/**
|
|
543
|
+
* Platform ID para verificar si estamos en el navegador
|
|
544
|
+
*/
|
|
545
|
+
platformId = inject(PLATFORM_ID);
|
|
536
546
|
/**
|
|
537
547
|
* Constantes del core
|
|
538
548
|
*/
|
|
@@ -643,7 +653,26 @@ class OptionsService {
|
|
|
643
653
|
* @returns
|
|
644
654
|
*/
|
|
645
655
|
removeAccents(str) {
|
|
646
|
-
|
|
656
|
+
if (isPlatformBrowser(this.platformId) && typeof String.prototype.normalize === 'function') {
|
|
657
|
+
return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
658
|
+
}
|
|
659
|
+
// Fallback para SSR - remover acentos manualmente
|
|
660
|
+
return str.replace(/[àáâãäå]/g, 'a')
|
|
661
|
+
.replace(/[èéêë]/g, 'e')
|
|
662
|
+
.replace(/[ìíîï]/g, 'i')
|
|
663
|
+
.replace(/[òóôõö]/g, 'o')
|
|
664
|
+
.replace(/[ùúûü]/g, 'u')
|
|
665
|
+
.replace(/[ýÿ]/g, 'y')
|
|
666
|
+
.replace(/[ñ]/g, 'n')
|
|
667
|
+
.replace(/[ç]/g, 'c')
|
|
668
|
+
.replace(/[ÀÁÂÃÄÅ]/g, 'A')
|
|
669
|
+
.replace(/[ÈÉÊË]/g, 'E')
|
|
670
|
+
.replace(/[ÌÍÎÏ]/g, 'I')
|
|
671
|
+
.replace(/[ÒÓÔÕÖ]/g, 'O')
|
|
672
|
+
.replace(/[ÙÚÛÜ]/g, 'U')
|
|
673
|
+
.replace(/[ÝŸ]/g, 'Y')
|
|
674
|
+
.replace(/[Ñ]/g, 'N')
|
|
675
|
+
.replace(/[Ç]/g, 'C');
|
|
647
676
|
}
|
|
648
677
|
/**
|
|
649
678
|
* Realiza un mapeo de los datos para darle un formato mas entendible a la
|
|
@@ -824,172 +853,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
824
853
|
}]
|
|
825
854
|
}], ctorParameters: () => [] });
|
|
826
855
|
|
|
827
|
-
/**
|
|
828
|
-
* Servicio que maneja los parametros de la aplicación.
|
|
829
|
-
*/
|
|
830
|
-
class ParametersService {
|
|
831
|
-
/**
|
|
832
|
-
* Constantes de la API
|
|
833
|
-
*/
|
|
834
|
-
apiConstants = inject(ApiConstantsService);
|
|
835
|
-
/**
|
|
836
|
-
* Maneja las peticiones a la API
|
|
837
|
-
*/
|
|
838
|
-
connection = inject(ConnectionService);
|
|
839
|
-
//API URLS
|
|
840
|
-
/**
|
|
841
|
-
* Devuelve la URL para obtener todos los parametros.
|
|
842
|
-
* @returns
|
|
843
|
-
*/
|
|
844
|
-
getAllParametersAPI() { return `${this.apiConstants.SHOP_API_URL}${this.apiConstants.CHANNEL}/parameters`; }
|
|
845
|
-
//OBSERVABLES
|
|
846
|
-
/**
|
|
847
|
-
* Subject para manejar los cambios en los datos de los parametros
|
|
848
|
-
*/
|
|
849
|
-
parametersSubject = new BehaviorSubject(null);
|
|
850
|
-
parameters$ = this.parametersSubject.asObservable();
|
|
851
|
-
//METHODS
|
|
852
|
-
/**
|
|
853
|
-
* Obtiene los parámetros del backend.
|
|
854
|
-
* @returns
|
|
855
|
-
*/
|
|
856
|
-
getParameters() {
|
|
857
|
-
if (this.parametersSubject.getValue() === null) {
|
|
858
|
-
this.connection.get(this.getAllParametersAPI()).pipe(shareReplay(1), map((response) => {
|
|
859
|
-
this.parametersSubject.next(response);
|
|
860
|
-
return response;
|
|
861
|
-
}), catchError((error) => {
|
|
862
|
-
console.log(`Error: ${error}`);
|
|
863
|
-
this.parametersSubject.next([]);
|
|
864
|
-
return of([]);
|
|
865
|
-
})).subscribe();
|
|
866
|
-
}
|
|
867
|
-
return this.parameters$;
|
|
868
|
-
}
|
|
869
|
-
/**
|
|
870
|
-
* Comprueba si el código de un parámetro existe en la lista de parámetros.
|
|
871
|
-
* @param params Lista de parámetros
|
|
872
|
-
* @param code Código del parámetro a buscar
|
|
873
|
-
* @returns El objeto con los datos del parámetro encontrado, sino retorna `null`
|
|
874
|
-
*/
|
|
875
|
-
hasParams(params, code) { return params && params.find((param) => param.code?.toLowerCase().includes(code.toLowerCase())); }
|
|
876
|
-
constructor() { }
|
|
877
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ParametersService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
878
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ParametersService, providedIn: 'root' });
|
|
879
|
-
}
|
|
880
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ParametersService, decorators: [{
|
|
881
|
-
type: Injectable,
|
|
882
|
-
args: [{
|
|
883
|
-
providedIn: 'root'
|
|
884
|
-
}]
|
|
885
|
-
}], ctorParameters: () => [] });
|
|
886
|
-
|
|
887
|
-
/**
|
|
888
|
-
* Servicio que maneja los bloques como repositorio.
|
|
889
|
-
* @class BlocksRepositoryService
|
|
890
|
-
*/
|
|
891
|
-
class BlocksRepositoryService {
|
|
892
|
-
/**
|
|
893
|
-
* Constantes de la API
|
|
894
|
-
*/
|
|
895
|
-
apiConstants = inject(ApiConstantsService);
|
|
896
|
-
/**
|
|
897
|
-
* Menaja las conexiones con la API
|
|
898
|
-
*/
|
|
899
|
-
connection = inject(ConnectionService);
|
|
900
|
-
/**
|
|
901
|
-
* Subject para manejar los bloques recibidos.
|
|
902
|
-
*/
|
|
903
|
-
blocksSubject = new BehaviorSubject([]);
|
|
904
|
-
/**
|
|
905
|
-
* Observable de bloques.
|
|
906
|
-
*/
|
|
907
|
-
blocks$ = this.blocksSubject.asObservable();
|
|
908
|
-
//API URLS
|
|
909
|
-
/**
|
|
910
|
-
* Devuelve la url para obtener los bloques segun la sección.
|
|
911
|
-
* @param section
|
|
912
|
-
* @returns
|
|
913
|
-
*/
|
|
914
|
-
blocksAPI(section) { return `${this.apiConstants.CMS_URL}${this.apiConstants.CHANNEL}/blocks/section/${section}?locale=${this.apiConstants.LOCALE}`; }
|
|
915
|
-
/**
|
|
916
|
-
* Obtiene los bloques segun la seccion del Backend.
|
|
917
|
-
* @param section
|
|
918
|
-
* @returns Un observable de los bloques.
|
|
919
|
-
*/
|
|
920
|
-
getBlocks(section) {
|
|
921
|
-
//if(this.blocksSubject.getValue() != null){
|
|
922
|
-
this.connection.get(this.blocksAPI(section)).pipe(shareReplay(1), map((response) => {
|
|
923
|
-
//console.log(response)
|
|
924
|
-
this.blocksSubject.next(response.items);
|
|
925
|
-
return response;
|
|
926
|
-
})).subscribe();
|
|
927
|
-
//}
|
|
928
|
-
return this.blocks$;
|
|
929
|
-
}
|
|
930
|
-
/* private hasSectionBlocks = (section: string) => {
|
|
931
|
-
|
|
932
|
-
} */
|
|
933
|
-
appendBlock = (blocks, section) => {
|
|
934
|
-
const new_block = { section, blocks };
|
|
935
|
-
};
|
|
936
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksRepositoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
937
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksRepositoryService, providedIn: 'root' });
|
|
938
|
-
}
|
|
939
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksRepositoryService, decorators: [{
|
|
940
|
-
type: Injectable,
|
|
941
|
-
args: [{
|
|
942
|
-
providedIn: 'root'
|
|
943
|
-
}]
|
|
944
|
-
}] });
|
|
945
|
-
|
|
946
|
-
/**
|
|
947
|
-
* Servicio de tipo adapter para manejar los bloques.
|
|
948
|
-
* @class BlocksService
|
|
949
|
-
*/
|
|
950
|
-
class BlocksService {
|
|
951
|
-
/**
|
|
952
|
-
* Constantes de la API
|
|
953
|
-
*/
|
|
954
|
-
apiConstants = inject(ApiConstantsService);
|
|
955
|
-
/**
|
|
956
|
-
* Servicio de BlocksRepository.
|
|
957
|
-
*/
|
|
958
|
-
blocksRepositoryService = inject(BlocksRepositoryService);
|
|
959
|
-
/**
|
|
960
|
-
* Subject para manejar los bloques recibidos.
|
|
961
|
-
*/
|
|
962
|
-
blocksSubject = new BehaviorSubject([]);
|
|
963
|
-
/**
|
|
964
|
-
* Observable de bloques.
|
|
965
|
-
*/
|
|
966
|
-
blocks$ = this.blocksSubject.asObservable();
|
|
967
|
-
//API URLS
|
|
968
|
-
/**
|
|
969
|
-
* Devuelve la url para interactuar con el bloque de contacto.
|
|
970
|
-
* @returns
|
|
971
|
-
*/
|
|
972
|
-
contactFormResponseAPI() { return `${this.apiConstants.CMS_URL}${this.apiConstants.LOCALE}/contact-form/response`; }
|
|
973
|
-
//METHODS
|
|
974
|
-
/**
|
|
975
|
-
* Obtiene los bloques de una sección en especifico.
|
|
976
|
-
* @param section
|
|
977
|
-
* @returns Observable de los bloques.
|
|
978
|
-
*/
|
|
979
|
-
getBlocks(section) {
|
|
980
|
-
return this.blocksRepositoryService.getBlocks(section);
|
|
981
|
-
}
|
|
982
|
-
constructor() { }
|
|
983
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
984
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksService, providedIn: 'root' });
|
|
985
|
-
}
|
|
986
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksService, decorators: [{
|
|
987
|
-
type: Injectable,
|
|
988
|
-
args: [{
|
|
989
|
-
providedIn: 'root'
|
|
990
|
-
}]
|
|
991
|
-
}], ctorParameters: () => [] });
|
|
992
|
-
|
|
993
856
|
/**
|
|
994
857
|
* Servicio que se encarga de manejar el Analytics de Facebook.
|
|
995
858
|
* @class FacebookPixelService
|
|
@@ -1026,7 +889,9 @@ class FacebookPixelService {
|
|
|
1026
889
|
this.renderer.appendChild(this.document?.body, new_analityc_script);
|
|
1027
890
|
this.enabled = true;
|
|
1028
891
|
}
|
|
1029
|
-
|
|
892
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
893
|
+
setTimeout(() => this.callEvent('initialize'), 1000);
|
|
894
|
+
}
|
|
1030
895
|
}
|
|
1031
896
|
/**
|
|
1032
897
|
* Ejecuta el evento pasado por parametro.
|
|
@@ -1243,7 +1108,9 @@ class GoogleAnalyticsService {
|
|
|
1243
1108
|
this.renderer.appendChild(this.document?.head, declaration);
|
|
1244
1109
|
this.enabled = true;
|
|
1245
1110
|
}
|
|
1246
|
-
|
|
1111
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
1112
|
+
setTimeout(() => this.startListeningPageViews(gtm_id), 1000);
|
|
1113
|
+
}
|
|
1247
1114
|
}
|
|
1248
1115
|
/**
|
|
1249
1116
|
*
|
|
@@ -1516,16 +1383,29 @@ class GTMService {
|
|
|
1516
1383
|
this.document = inject(DOCUMENT);
|
|
1517
1384
|
}
|
|
1518
1385
|
}
|
|
1386
|
+
get isBrowser() {
|
|
1387
|
+
return isPlatformBrowser(this.platformId);
|
|
1388
|
+
}
|
|
1389
|
+
/** Acceso al window SSR-safe */
|
|
1390
|
+
get windowRef() {
|
|
1391
|
+
if (!this.isBrowser)
|
|
1392
|
+
return null;
|
|
1393
|
+
return window;
|
|
1394
|
+
}
|
|
1395
|
+
/** Acceso al document SSR-safe */
|
|
1396
|
+
get documentRef() {
|
|
1397
|
+
return this.isBrowser ? this.document : null;
|
|
1398
|
+
}
|
|
1519
1399
|
/**
|
|
1520
1400
|
* Obtiene el dataLayer del objecto window
|
|
1521
1401
|
* @returns
|
|
1522
1402
|
*/
|
|
1523
1403
|
getDataLayer() {
|
|
1524
|
-
const
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
return
|
|
1404
|
+
const win = this.windowRef;
|
|
1405
|
+
if (!win)
|
|
1406
|
+
return [];
|
|
1407
|
+
win.dataLayer = win.dataLayer || [];
|
|
1408
|
+
return win.dataLayer;
|
|
1529
1409
|
}
|
|
1530
1410
|
/**
|
|
1531
1411
|
* Agrega datos al dataLayer.
|
|
@@ -1533,6 +1413,8 @@ class GTMService {
|
|
|
1533
1413
|
*/
|
|
1534
1414
|
pushOnDataLayer(obj) {
|
|
1535
1415
|
const dataLayer = this.getDataLayer();
|
|
1416
|
+
if (!dataLayer.length && !this.isBrowser)
|
|
1417
|
+
return;
|
|
1536
1418
|
dataLayer.push(obj);
|
|
1537
1419
|
}
|
|
1538
1420
|
/**
|
|
@@ -1541,24 +1423,45 @@ class GTMService {
|
|
|
1541
1423
|
*/
|
|
1542
1424
|
addGtmToDom() {
|
|
1543
1425
|
return new Promise((resolve, reject) => {
|
|
1426
|
+
if (!this.isBrowser) {
|
|
1427
|
+
return resolve(false);
|
|
1428
|
+
}
|
|
1544
1429
|
if (this.isLoaded) {
|
|
1545
1430
|
return resolve(this.isLoaded);
|
|
1546
1431
|
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
return resolve(this.isLoaded = true);
|
|
1556
|
-
});
|
|
1557
|
-
gtmScript.addEventListener('error', () => {
|
|
1558
|
-
return reject(false);
|
|
1559
|
-
});
|
|
1560
|
-
this.document?.head.insertBefore(gtmScript, this.document.head.firstChild);
|
|
1432
|
+
const doc = this.documentRef;
|
|
1433
|
+
if (!doc) {
|
|
1434
|
+
return reject(false);
|
|
1435
|
+
}
|
|
1436
|
+
const existing = doc.getElementById('GTMscript');
|
|
1437
|
+
if (existing) {
|
|
1438
|
+
this.isLoaded = true;
|
|
1439
|
+
return resolve(true);
|
|
1561
1440
|
}
|
|
1441
|
+
this.pushOnDataLayer({
|
|
1442
|
+
'gtm.start': new Date().getTime(),
|
|
1443
|
+
event: 'gtm.js'
|
|
1444
|
+
});
|
|
1445
|
+
const gtmScript = doc.createElement('script');
|
|
1446
|
+
if (!gtmScript) {
|
|
1447
|
+
return reject(false);
|
|
1448
|
+
}
|
|
1449
|
+
gtmScript.id = 'GTMscript';
|
|
1450
|
+
gtmScript.async = true;
|
|
1451
|
+
gtmScript.src = this.applyGtmQueryParams(this.config['gtm_resource_path']
|
|
1452
|
+
? this.config['gtm_resource_path']
|
|
1453
|
+
: 'https://www.googletagmanager.com/gtm.js');
|
|
1454
|
+
gtmScript.addEventListener('load', () => {
|
|
1455
|
+
this.isLoaded = true;
|
|
1456
|
+
return resolve(true);
|
|
1457
|
+
});
|
|
1458
|
+
gtmScript.addEventListener('error', () => {
|
|
1459
|
+
this.isLoaded = false;
|
|
1460
|
+
return reject(false);
|
|
1461
|
+
});
|
|
1462
|
+
doc.head
|
|
1463
|
+
? doc.head.insertBefore(gtmScript, doc.head.firstChild)
|
|
1464
|
+
: doc.appendChild(gtmScript);
|
|
1562
1465
|
});
|
|
1563
1466
|
}
|
|
1564
1467
|
applyGtmQueryParams(url) {
|
|
@@ -1572,29 +1475,52 @@ class GTMService {
|
|
|
1572
1475
|
* @param config Configuraciones de Google Tag Manager
|
|
1573
1476
|
*/
|
|
1574
1477
|
initialize(config) {
|
|
1478
|
+
if (!this.isBrowser)
|
|
1479
|
+
return;
|
|
1480
|
+
if (this.isLoaded)
|
|
1481
|
+
return;
|
|
1575
1482
|
this.config = config || this.config;
|
|
1483
|
+
if (!config?.id)
|
|
1484
|
+
return;
|
|
1576
1485
|
this.addGtmToDom().then(() => {
|
|
1577
|
-
this.
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1486
|
+
this.isLoaded = true;
|
|
1487
|
+
this.enabled = true;
|
|
1488
|
+
this.router.events
|
|
1489
|
+
.pipe(filter(event => event instanceof NavigationEnd))
|
|
1490
|
+
.subscribe((event) => {
|
|
1491
|
+
const gtmTag = {
|
|
1492
|
+
event: 'page',
|
|
1493
|
+
pageName: event.urlAfterRedirects ?? event.url
|
|
1494
|
+
};
|
|
1495
|
+
this.pushTag(gtmTag);
|
|
1585
1496
|
});
|
|
1497
|
+
}).catch(() => {
|
|
1498
|
+
this.isLoaded = false;
|
|
1499
|
+
this.enabled = false;
|
|
1586
1500
|
});
|
|
1587
1501
|
}
|
|
1588
1502
|
pushTag(item) {
|
|
1589
1503
|
return new Promise((resolve, reject) => {
|
|
1504
|
+
if (!this.isBrowser) {
|
|
1505
|
+
return resolve();
|
|
1506
|
+
}
|
|
1507
|
+
if (!this.config?.id) {
|
|
1508
|
+
return resolve();
|
|
1509
|
+
}
|
|
1590
1510
|
if (!this.isLoaded) {
|
|
1591
1511
|
this.addGtmToDom().then(() => {
|
|
1512
|
+
this.isLoaded = true;
|
|
1513
|
+
this.enabled = true;
|
|
1592
1514
|
this.pushOnDataLayer(item);
|
|
1593
1515
|
return resolve();
|
|
1594
|
-
}).catch(
|
|
1516
|
+
}).catch(err => {
|
|
1517
|
+
return reject(err);
|
|
1518
|
+
});
|
|
1595
1519
|
}
|
|
1596
1520
|
else {
|
|
1597
|
-
this.
|
|
1521
|
+
if (this.enabled) {
|
|
1522
|
+
this.pushOnDataLayer(item);
|
|
1523
|
+
}
|
|
1598
1524
|
return resolve();
|
|
1599
1525
|
}
|
|
1600
1526
|
});
|
|
@@ -2056,6 +1982,211 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
2056
1982
|
}]
|
|
2057
1983
|
}], ctorParameters: () => [] });
|
|
2058
1984
|
|
|
1985
|
+
/**
|
|
1986
|
+
* Servicio que maneja los parametros de la aplicación.
|
|
1987
|
+
*/
|
|
1988
|
+
class ParametersService {
|
|
1989
|
+
/**
|
|
1990
|
+
* Constantes de la API
|
|
1991
|
+
*/
|
|
1992
|
+
apiConstants = inject(ApiConstantsService);
|
|
1993
|
+
/**
|
|
1994
|
+
* Maneja las peticiones a la API
|
|
1995
|
+
*/
|
|
1996
|
+
connection = inject(ConnectionService);
|
|
1997
|
+
/**
|
|
1998
|
+
* Servicio de Analytics
|
|
1999
|
+
*/
|
|
2000
|
+
analyticsService = inject(AnalyticsService);
|
|
2001
|
+
//API URLS
|
|
2002
|
+
/**
|
|
2003
|
+
* Devuelve la URL para obtener todos los parametros.
|
|
2004
|
+
* @returns
|
|
2005
|
+
*/
|
|
2006
|
+
getAllParametersAPI() { return `${this.apiConstants.SHOP_API_URL}${this.apiConstants.CHANNEL}/parameters`; }
|
|
2007
|
+
//OBSERVABLES
|
|
2008
|
+
/**
|
|
2009
|
+
* Subject para manejar los cambios en los datos de los parametros
|
|
2010
|
+
*/
|
|
2011
|
+
parametersSubject = new BehaviorSubject(null);
|
|
2012
|
+
parameters$ = this.parametersSubject.asObservable();
|
|
2013
|
+
//METHODS
|
|
2014
|
+
/**
|
|
2015
|
+
* Obtiene los parámetros del backend.
|
|
2016
|
+
* @returns
|
|
2017
|
+
*/
|
|
2018
|
+
getParameters() {
|
|
2019
|
+
if (this.parametersSubject.getValue() === null) {
|
|
2020
|
+
this.connection.get(this.getAllParametersAPI()).pipe(shareReplay(1), map((response) => {
|
|
2021
|
+
this.parametersSubject.next(response);
|
|
2022
|
+
this.initAnalyticsFromParams(response);
|
|
2023
|
+
return response;
|
|
2024
|
+
}), catchError((error) => {
|
|
2025
|
+
console.log(`Error: ${error}`);
|
|
2026
|
+
this.parametersSubject.next([]);
|
|
2027
|
+
return of([]);
|
|
2028
|
+
})).subscribe();
|
|
2029
|
+
}
|
|
2030
|
+
return this.parameters$;
|
|
2031
|
+
}
|
|
2032
|
+
/**
|
|
2033
|
+
* Comprueba si el código de un parámetro existe en la lista de parámetros.
|
|
2034
|
+
* @param params Lista de parámetros
|
|
2035
|
+
* @param code Código del parámetro a buscar
|
|
2036
|
+
* @returns El objeto con los datos del parámetro encontrado, sino retorna `null`
|
|
2037
|
+
*/
|
|
2038
|
+
hasParams(params, code) { return params && params.find((param) => param.code?.toLowerCase().includes(code.toLowerCase())); }
|
|
2039
|
+
findAnalyticsParam(params, service) {
|
|
2040
|
+
const channel = this.apiConstants.CHANNEL?.toLowerCase() ?? '';
|
|
2041
|
+
// Código específico por canal: facebook_nombrecanal_id
|
|
2042
|
+
const codeChannel = `${service}_${channel}_id`;
|
|
2043
|
+
// Código genérico: facebook_id
|
|
2044
|
+
const codeGeneric = `${service}_id`;
|
|
2045
|
+
const normalize = (code) => (code || '').toLowerCase();
|
|
2046
|
+
let param = params.find(p => normalize(p.code) === codeChannel);
|
|
2047
|
+
if (!param) {
|
|
2048
|
+
param = params.find(p => normalize(p.code) === codeGeneric);
|
|
2049
|
+
}
|
|
2050
|
+
return param;
|
|
2051
|
+
}
|
|
2052
|
+
initAnalyticsFromParams(params) {
|
|
2053
|
+
if (!params || !params.length)
|
|
2054
|
+
return;
|
|
2055
|
+
if (!this.apiConstants.IS_PRODUCTION)
|
|
2056
|
+
return;
|
|
2057
|
+
const facebook = this.findAnalyticsParam(params, 'facebook');
|
|
2058
|
+
const google = this.findAnalyticsParam(params, 'google');
|
|
2059
|
+
const gtm = this.findAnalyticsParam(params, 'gtm');
|
|
2060
|
+
const metricool = this.findAnalyticsParam(params, 'metricool');
|
|
2061
|
+
const doppler = this.findAnalyticsParam(params, 'doppler');
|
|
2062
|
+
if (facebook)
|
|
2063
|
+
this.analyticsService.initializeFacebook(facebook.value);
|
|
2064
|
+
if (google)
|
|
2065
|
+
this.analyticsService.initializeGoogle(google.value);
|
|
2066
|
+
if (gtm)
|
|
2067
|
+
this.analyticsService.initializeGTM(gtm.value);
|
|
2068
|
+
if (metricool)
|
|
2069
|
+
this.analyticsService.initializeMetricool(metricool.value);
|
|
2070
|
+
if (doppler)
|
|
2071
|
+
this.analyticsService.initializeDoppler(doppler.value);
|
|
2072
|
+
}
|
|
2073
|
+
constructor() { }
|
|
2074
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ParametersService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2075
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ParametersService, providedIn: 'root' });
|
|
2076
|
+
}
|
|
2077
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ParametersService, decorators: [{
|
|
2078
|
+
type: Injectable,
|
|
2079
|
+
args: [{
|
|
2080
|
+
providedIn: 'root'
|
|
2081
|
+
}]
|
|
2082
|
+
}], ctorParameters: () => [] });
|
|
2083
|
+
|
|
2084
|
+
/**
|
|
2085
|
+
* Servicio que maneja los bloques como repositorio.
|
|
2086
|
+
* @class BlocksRepositoryService
|
|
2087
|
+
*/
|
|
2088
|
+
class BlocksRepositoryService {
|
|
2089
|
+
/**
|
|
2090
|
+
* Constantes de la API
|
|
2091
|
+
*/
|
|
2092
|
+
apiConstants = inject(ApiConstantsService);
|
|
2093
|
+
/**
|
|
2094
|
+
* Menaja las conexiones con la API
|
|
2095
|
+
*/
|
|
2096
|
+
connection = inject(ConnectionService);
|
|
2097
|
+
/**
|
|
2098
|
+
* Subject para manejar los bloques recibidos.
|
|
2099
|
+
*/
|
|
2100
|
+
blocksSubject = new BehaviorSubject([]);
|
|
2101
|
+
/**
|
|
2102
|
+
* Observable de bloques.
|
|
2103
|
+
*/
|
|
2104
|
+
blocks$ = this.blocksSubject.asObservable();
|
|
2105
|
+
//API URLS
|
|
2106
|
+
/**
|
|
2107
|
+
* Devuelve la url para obtener los bloques segun la sección.
|
|
2108
|
+
* @param section
|
|
2109
|
+
* @returns
|
|
2110
|
+
*/
|
|
2111
|
+
blocksAPI(section) { return `${this.apiConstants.CMS_URL}${this.apiConstants.CHANNEL}/blocks/section/${section}?locale=${this.apiConstants.LOCALE}`; }
|
|
2112
|
+
/**
|
|
2113
|
+
* Obtiene los bloques segun la seccion del Backend.
|
|
2114
|
+
* @param section
|
|
2115
|
+
* @returns Un observable de los bloques.
|
|
2116
|
+
*/
|
|
2117
|
+
getBlocks(section) {
|
|
2118
|
+
//if(this.blocksSubject.getValue() != null){
|
|
2119
|
+
this.connection.get(this.blocksAPI(section)).pipe(shareReplay(1), map((response) => {
|
|
2120
|
+
//console.log(response)
|
|
2121
|
+
this.blocksSubject.next(response.items);
|
|
2122
|
+
return response;
|
|
2123
|
+
})).subscribe();
|
|
2124
|
+
//}
|
|
2125
|
+
return this.blocks$;
|
|
2126
|
+
}
|
|
2127
|
+
/* private hasSectionBlocks = (section: string) => {
|
|
2128
|
+
|
|
2129
|
+
} */
|
|
2130
|
+
appendBlock = (blocks, section) => {
|
|
2131
|
+
const new_block = { section, blocks };
|
|
2132
|
+
};
|
|
2133
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksRepositoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2134
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksRepositoryService, providedIn: 'root' });
|
|
2135
|
+
}
|
|
2136
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksRepositoryService, decorators: [{
|
|
2137
|
+
type: Injectable,
|
|
2138
|
+
args: [{
|
|
2139
|
+
providedIn: 'root'
|
|
2140
|
+
}]
|
|
2141
|
+
}] });
|
|
2142
|
+
|
|
2143
|
+
/**
|
|
2144
|
+
* Servicio de tipo adapter para manejar los bloques.
|
|
2145
|
+
* @class BlocksService
|
|
2146
|
+
*/
|
|
2147
|
+
class BlocksService {
|
|
2148
|
+
/**
|
|
2149
|
+
* Constantes de la API
|
|
2150
|
+
*/
|
|
2151
|
+
apiConstants = inject(ApiConstantsService);
|
|
2152
|
+
/**
|
|
2153
|
+
* Servicio de BlocksRepository.
|
|
2154
|
+
*/
|
|
2155
|
+
blocksRepositoryService = inject(BlocksRepositoryService);
|
|
2156
|
+
/**
|
|
2157
|
+
* Subject para manejar los bloques recibidos.
|
|
2158
|
+
*/
|
|
2159
|
+
blocksSubject = new BehaviorSubject([]);
|
|
2160
|
+
/**
|
|
2161
|
+
* Observable de bloques.
|
|
2162
|
+
*/
|
|
2163
|
+
blocks$ = this.blocksSubject.asObservable();
|
|
2164
|
+
//API URLS
|
|
2165
|
+
/**
|
|
2166
|
+
* Devuelve la url para interactuar con el bloque de contacto.
|
|
2167
|
+
* @returns
|
|
2168
|
+
*/
|
|
2169
|
+
contactFormResponseAPI() { return `${this.apiConstants.CMS_URL}${this.apiConstants.LOCALE}/contact-form/response`; }
|
|
2170
|
+
//METHODS
|
|
2171
|
+
/**
|
|
2172
|
+
* Obtiene los bloques de una sección en especifico.
|
|
2173
|
+
* @param section
|
|
2174
|
+
* @returns Observable de los bloques.
|
|
2175
|
+
*/
|
|
2176
|
+
getBlocks(section) {
|
|
2177
|
+
return this.blocksRepositoryService.getBlocks(section);
|
|
2178
|
+
}
|
|
2179
|
+
constructor() { }
|
|
2180
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2181
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksService, providedIn: 'root' });
|
|
2182
|
+
}
|
|
2183
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksService, decorators: [{
|
|
2184
|
+
type: Injectable,
|
|
2185
|
+
args: [{
|
|
2186
|
+
providedIn: 'root'
|
|
2187
|
+
}]
|
|
2188
|
+
}], ctorParameters: () => [] });
|
|
2189
|
+
|
|
2059
2190
|
/**
|
|
2060
2191
|
* Servicio para manejar los canales de la aplicación
|
|
2061
2192
|
* @class ChannelService
|
|
@@ -2644,6 +2775,31 @@ class User {
|
|
|
2644
2775
|
}
|
|
2645
2776
|
}
|
|
2646
2777
|
|
|
2778
|
+
/**
|
|
2779
|
+
* Función auxiliar para remover acentos de forma segura para SSR
|
|
2780
|
+
*/
|
|
2781
|
+
function safeRemoveAccents(str) {
|
|
2782
|
+
if (typeof window !== 'undefined' && typeof String.prototype.normalize === 'function') {
|
|
2783
|
+
return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
2784
|
+
}
|
|
2785
|
+
// Fallback para SSR - remover acentos manualmente
|
|
2786
|
+
return str.replace(/[àáâãäå]/g, 'a')
|
|
2787
|
+
.replace(/[èéêë]/g, 'e')
|
|
2788
|
+
.replace(/[ìíîï]/g, 'i')
|
|
2789
|
+
.replace(/[òóôõö]/g, 'o')
|
|
2790
|
+
.replace(/[ùúûü]/g, 'u')
|
|
2791
|
+
.replace(/[ýÿ]/g, 'y')
|
|
2792
|
+
.replace(/[ñ]/g, 'n')
|
|
2793
|
+
.replace(/[ç]/g, 'c')
|
|
2794
|
+
.replace(/[ÀÁÂÃÄÅ]/g, 'A')
|
|
2795
|
+
.replace(/[ÈÉÊË]/g, 'E')
|
|
2796
|
+
.replace(/[ÌÍÎÏ]/g, 'I')
|
|
2797
|
+
.replace(/[ÒÓÔÕÖ]/g, 'O')
|
|
2798
|
+
.replace(/[ÙÚÛÜ]/g, 'U')
|
|
2799
|
+
.replace(/[ÝŸ]/g, 'Y')
|
|
2800
|
+
.replace(/[Ñ]/g, 'N')
|
|
2801
|
+
.replace(/[Ç]/g, 'C');
|
|
2802
|
+
}
|
|
2647
2803
|
class Filter {
|
|
2648
2804
|
data = [];
|
|
2649
2805
|
multi = false;
|
|
@@ -2663,7 +2819,7 @@ class Filter {
|
|
|
2663
2819
|
throw new Error("Method not implemented.");
|
|
2664
2820
|
}
|
|
2665
2821
|
removeAccents = (str) => {
|
|
2666
|
-
return str
|
|
2822
|
+
return safeRemoveAccents(str);
|
|
2667
2823
|
};
|
|
2668
2824
|
setSelected(element, value) {
|
|
2669
2825
|
//console.log(element, value);
|
|
@@ -6218,17 +6374,21 @@ class HeaderEcComponent extends MenuEcComponent {
|
|
|
6218
6374
|
});
|
|
6219
6375
|
}
|
|
6220
6376
|
onWindowScroll() {
|
|
6221
|
-
|
|
6222
|
-
|
|
6377
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
6378
|
+
const scrollTop = window.scrollY;
|
|
6379
|
+
this.isScrolled = scrollTop > 80;
|
|
6380
|
+
}
|
|
6223
6381
|
}
|
|
6224
6382
|
isHomeFunction() {
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
if (
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6383
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
6384
|
+
const headerElement = document.querySelector('header');
|
|
6385
|
+
if (headerElement) {
|
|
6386
|
+
if (this.router.url !== '/home') {
|
|
6387
|
+
headerElement.classList.add('show-menu');
|
|
6388
|
+
}
|
|
6389
|
+
else {
|
|
6390
|
+
headerElement.classList.remove('show-menu');
|
|
6391
|
+
}
|
|
6232
6392
|
}
|
|
6233
6393
|
}
|
|
6234
6394
|
}
|
|
@@ -6252,26 +6412,30 @@ class HeaderEcComponent extends MenuEcComponent {
|
|
|
6252
6412
|
}
|
|
6253
6413
|
};
|
|
6254
6414
|
borrarInput(inputId) {
|
|
6255
|
-
if (
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
input.value = '';
|
|
6259
|
-
}
|
|
6260
|
-
}
|
|
6261
|
-
else {
|
|
6262
|
-
const inputs = ['searchInput1'];
|
|
6263
|
-
inputs.forEach((id) => {
|
|
6264
|
-
const input = document.getElementById(id);
|
|
6415
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
6416
|
+
if (inputId) {
|
|
6417
|
+
const input = document.getElementById(inputId);
|
|
6265
6418
|
if (input) {
|
|
6266
6419
|
input.value = '';
|
|
6267
6420
|
}
|
|
6268
|
-
}
|
|
6421
|
+
}
|
|
6422
|
+
else {
|
|
6423
|
+
const inputs = ['searchInput1'];
|
|
6424
|
+
inputs.forEach((id) => {
|
|
6425
|
+
const input = document.getElementById(id);
|
|
6426
|
+
if (input) {
|
|
6427
|
+
input.value = '';
|
|
6428
|
+
}
|
|
6429
|
+
});
|
|
6430
|
+
}
|
|
6269
6431
|
}
|
|
6270
6432
|
this.searchValue = '';
|
|
6271
6433
|
this.coreConstantsService.searchValue = '';
|
|
6272
6434
|
this.getCollectionSearch();
|
|
6273
6435
|
}
|
|
6274
6436
|
setupMobileMenu() {
|
|
6437
|
+
if (!isPlatformBrowser(this.platformId))
|
|
6438
|
+
return;
|
|
6275
6439
|
// console.log('setupMobileMenu called');
|
|
6276
6440
|
const menuMobile = document.querySelector('.menuMobile');
|
|
6277
6441
|
if (!(menuMobile instanceof HTMLElement))
|
|
@@ -6307,6 +6471,8 @@ class HeaderEcComponent extends MenuEcComponent {
|
|
|
6307
6471
|
});
|
|
6308
6472
|
}
|
|
6309
6473
|
setupSearchInputs() {
|
|
6474
|
+
if (!isPlatformBrowser(this.platformId))
|
|
6475
|
+
return;
|
|
6310
6476
|
const inputs = ['searchInput1', 'searchInput2'];
|
|
6311
6477
|
inputs.forEach(id => {
|
|
6312
6478
|
const input = document.getElementById(id);
|
|
@@ -7169,7 +7335,7 @@ class BlockProductsEcComponent extends BlockEcComponent {
|
|
|
7169
7335
|
* Permite personalización de las imágenes de las flechas mediante @Input.
|
|
7170
7336
|
*/
|
|
7171
7337
|
setupSwiperNavigation() {
|
|
7172
|
-
if (this.meta?.styles?.carrousel !== false) {
|
|
7338
|
+
if (this.meta?.styles?.carrousel !== false && isPlatformBrowser(this.platformId)) {
|
|
7173
7339
|
// Usar setTimeout para asegurar que el swiper esté inicializado
|
|
7174
7340
|
setTimeout(() => {
|
|
7175
7341
|
this.initializeSwiperWithCustomNavigation();
|
|
@@ -7181,6 +7347,8 @@ class BlockProductsEcComponent extends BlockEcComponent {
|
|
|
7181
7347
|
* Esta función puede ser movida al componente base para reutilización.
|
|
7182
7348
|
*/
|
|
7183
7349
|
initializeSwiperWithCustomNavigation() {
|
|
7350
|
+
if (!isPlatformBrowser(this.platformId))
|
|
7351
|
+
return;
|
|
7184
7352
|
const prevButton = document.getElementById(`${this.meta?.code}-prev`);
|
|
7185
7353
|
const nextButton = document.getElementById(`${this.meta?.code}-next`);
|
|
7186
7354
|
const swiperElement = document.getElementById(this.meta?.code);
|
|
@@ -7546,7 +7714,9 @@ class MagnizoomEcComponent {
|
|
|
7546
7714
|
this.image = this.document.createElement('img');
|
|
7547
7715
|
this.image.onload = () => {
|
|
7548
7716
|
this.lensSize = { width: this.image.width / 2, height: this.image.height / 2 };
|
|
7549
|
-
|
|
7717
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
7718
|
+
setTimeout(() => this.render());
|
|
7719
|
+
}
|
|
7550
7720
|
};
|
|
7551
7721
|
this.image.src = src;
|
|
7552
7722
|
}
|
|
@@ -7818,26 +7988,16 @@ class RedsysCatchEcComponent extends ComponentHelper {
|
|
|
7818
7988
|
}
|
|
7819
7989
|
/** Intenta cerrar la pestaña actual; si falla, ejecuta el callback de fallback. */
|
|
7820
7990
|
tryCloseSelf(onFail) {
|
|
7821
|
-
if (!isPlatformBrowser(this.platformId))
|
|
7822
|
-
onFail();
|
|
7823
|
-
|
|
7824
|
-
}
|
|
7825
|
-
// Fallback de seguridad: si después de ~800 ms la página sigue visible,
|
|
7826
|
-
// asumimos que window.close() fue ignorado.
|
|
7827
|
-
const fallback = setTimeout(() => {
|
|
7828
|
-
// Si la pestaña siguiera abierta, document.hidden suele ser false.
|
|
7829
|
-
if (!document.hidden) {
|
|
7830
|
-
onFail();
|
|
7831
|
-
}
|
|
7832
|
-
}, 800);
|
|
7991
|
+
if (!isPlatformBrowser(this.platformId))
|
|
7992
|
+
return onFail();
|
|
7993
|
+
let attempted = false;
|
|
7833
7994
|
try {
|
|
7834
7995
|
window.close();
|
|
7835
|
-
|
|
7996
|
+
attempted = true;
|
|
7836
7997
|
}
|
|
7837
|
-
catch {
|
|
7838
|
-
|
|
7998
|
+
catch { }
|
|
7999
|
+
if (!attempted)
|
|
7839
8000
|
onFail();
|
|
7840
|
-
}
|
|
7841
8001
|
}
|
|
7842
8002
|
/** Oculta header/footer para esta pantalla mínima. */
|
|
7843
8003
|
hideHeaderFooter() {
|
|
@@ -9834,7 +9994,6 @@ class MpRedirectEcComponent {
|
|
|
9834
9994
|
_toastService = inject(ToastService);
|
|
9835
9995
|
platformId = inject(PLATFORM_ID);
|
|
9836
9996
|
finished = false;
|
|
9837
|
-
ngZone = inject(NgZone);
|
|
9838
9997
|
method = null;
|
|
9839
9998
|
total_amount = 0;
|
|
9840
9999
|
allData;
|
|
@@ -9857,10 +10016,10 @@ class MpRedirectEcComponent {
|
|
|
9857
10016
|
this.windowRef = window;
|
|
9858
10017
|
if ('BroadcastChannel' in window) {
|
|
9859
10018
|
this.bc = new BroadcastChannel('mp_payment');
|
|
9860
|
-
this.bc.onmessage = (e) => this.
|
|
10019
|
+
this.bc.onmessage = (e) => this.onMpMessage(e?.data);
|
|
9861
10020
|
}
|
|
9862
|
-
window.addEventListener('storage',
|
|
9863
|
-
window.addEventListener('message',
|
|
10021
|
+
window.addEventListener('storage', this.onStorage);
|
|
10022
|
+
window.addEventListener('message', this.onWindowMessage);
|
|
9864
10023
|
}
|
|
9865
10024
|
this.getPreference();
|
|
9866
10025
|
}
|
|
@@ -9913,29 +10072,23 @@ class MpRedirectEcComponent {
|
|
|
9913
10072
|
}, 1000);
|
|
9914
10073
|
};
|
|
9915
10074
|
onWindowMessage = (event) => {
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
this.onMpMessage(data);
|
|
9919
|
-
});
|
|
10075
|
+
const data = event?.data;
|
|
10076
|
+
this.onMpMessage(data);
|
|
9920
10077
|
};
|
|
9921
10078
|
onStorage = (e) => {
|
|
9922
|
-
this.
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
|
|
9927
|
-
|
|
9928
|
-
}
|
|
9929
|
-
});
|
|
10079
|
+
if (!e.key || !this.sid)
|
|
10080
|
+
return;
|
|
10081
|
+
if (e.key === `mp:state:${this.sid}` && e.newValue) {
|
|
10082
|
+
const state = e.newValue;
|
|
10083
|
+
this.finishWithState(state);
|
|
10084
|
+
}
|
|
9930
10085
|
};
|
|
9931
10086
|
onMpMessage = (data) => {
|
|
9932
|
-
|
|
9933
|
-
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
this.finishWithState(data.state);
|
|
9938
|
-
});
|
|
10087
|
+
if (!data || data.type !== 'mp:state')
|
|
10088
|
+
return;
|
|
10089
|
+
if (data.sid !== this.sid)
|
|
10090
|
+
return;
|
|
10091
|
+
this.finishWithState(data.state);
|
|
9939
10092
|
};
|
|
9940
10093
|
checkLocalStorageOnce() {
|
|
9941
10094
|
if (!this.sid)
|
|
@@ -9946,34 +10099,32 @@ class MpRedirectEcComponent {
|
|
|
9946
10099
|
}
|
|
9947
10100
|
/** Cierra el flujo de pago con el estado final y notifica al padre. */
|
|
9948
10101
|
finishWithState(state) {
|
|
9949
|
-
this.
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
|
|
9959
|
-
|
|
9960
|
-
|
|
9961
|
-
|
|
9962
|
-
|
|
9963
|
-
|
|
9964
|
-
|
|
9965
|
-
|
|
9966
|
-
|
|
9967
|
-
|
|
9968
|
-
|
|
9969
|
-
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
}
|
|
9976
|
-
});
|
|
10102
|
+
if (this.finished)
|
|
10103
|
+
return;
|
|
10104
|
+
this.finished = true;
|
|
10105
|
+
if (this.pollTimer)
|
|
10106
|
+
clearInterval(this.pollTimer);
|
|
10107
|
+
this.pollTimer = null;
|
|
10108
|
+
localStorage.removeItem(`mp:state:${this.sid}`);
|
|
10109
|
+
localStorage.removeItem('mp:sid');
|
|
10110
|
+
localStorage.removeItem('state');
|
|
10111
|
+
try {
|
|
10112
|
+
this.ventana && !this.ventana.closed && this.ventana.close();
|
|
10113
|
+
}
|
|
10114
|
+
catch { }
|
|
10115
|
+
this.ventana = null;
|
|
10116
|
+
if (state === 'success' || state === 'pending') {
|
|
10117
|
+
this.phase = 'finalizing';
|
|
10118
|
+
this.ready.emit(true);
|
|
10119
|
+
}
|
|
10120
|
+
else if (state === 'failure' || state === 'cancel') {
|
|
10121
|
+
this.phase = 'idle';
|
|
10122
|
+
this._toastService.show(state === 'cancel' ? 'Se canceló el pago con Mercado Pago' : 'payment-error');
|
|
10123
|
+
}
|
|
10124
|
+
else {
|
|
10125
|
+
this.phase = 'idle';
|
|
10126
|
+
this._toastService.show('payment-error');
|
|
10127
|
+
}
|
|
9977
10128
|
}
|
|
9978
10129
|
genSid() {
|
|
9979
10130
|
return `mp_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
@@ -10339,10 +10490,6 @@ class PaymentEcComponent {
|
|
|
10339
10490
|
return true;
|
|
10340
10491
|
};
|
|
10341
10492
|
verifyValidate = ($event) => {
|
|
10342
|
-
if (!$event) {
|
|
10343
|
-
this.setLoading(false);
|
|
10344
|
-
return;
|
|
10345
|
-
}
|
|
10346
10493
|
this.setLoading(true);
|
|
10347
10494
|
setTimeout(() => this.emitResult(), 1000);
|
|
10348
10495
|
};
|
|
@@ -10876,9 +11023,11 @@ class RelatedProductsEcComponent extends BlockEcComponent {
|
|
|
10876
11023
|
this._relatedProductsSubject.next(relatedProducts);
|
|
10877
11024
|
res.map((products) => this._analyticsService.callEvent('view_item_list', { products: products.items, item_list_name: products.title || 'Related Products', item_list_id: products.id || 'related-products' }));
|
|
10878
11025
|
// Inicializar swiper después de que los datos estén disponibles
|
|
10879
|
-
|
|
10880
|
-
|
|
10881
|
-
|
|
11026
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
11027
|
+
setTimeout(() => {
|
|
11028
|
+
this.initSwiper();
|
|
11029
|
+
}, 100);
|
|
11030
|
+
}
|
|
10882
11031
|
});
|
|
10883
11032
|
}
|
|
10884
11033
|
initSwiper() {
|