ng-easycommerce-v18 0.3.21-beta.2 → 0.3.22-beta.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.
@@ -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, NgZone, Renderer2, ChangeDetectionStrategy, Directive } 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, 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';
@@ -824,172 +830,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
824
830
  }]
825
831
  }], ctorParameters: () => [] });
826
832
 
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
833
  /**
994
834
  * Servicio que se encarga de manejar el Analytics de Facebook.
995
835
  * @class FacebookPixelService
@@ -1516,16 +1356,29 @@ class GTMService {
1516
1356
  this.document = inject(DOCUMENT);
1517
1357
  }
1518
1358
  }
1359
+ get isBrowser() {
1360
+ return isPlatformBrowser(this.platformId);
1361
+ }
1362
+ /** Acceso al window SSR-safe */
1363
+ get windowRef() {
1364
+ if (!this.isBrowser)
1365
+ return null;
1366
+ return window;
1367
+ }
1368
+ /** Acceso al document SSR-safe */
1369
+ get documentRef() {
1370
+ return this.isBrowser ? this.document : null;
1371
+ }
1519
1372
  /**
1520
1373
  * Obtiene el dataLayer del objecto window
1521
1374
  * @returns
1522
1375
  */
1523
1376
  getDataLayer() {
1524
- const window = this.window;
1525
- /* if(window)
1526
- window.dataLayer = window.dataLayer || [];
1527
- return window.dataLayer; */
1528
- return [];
1377
+ const win = this.windowRef;
1378
+ if (!win)
1379
+ return [];
1380
+ win.dataLayer = win.dataLayer || [];
1381
+ return win.dataLayer;
1529
1382
  }
1530
1383
  /**
1531
1384
  * Agrega datos al dataLayer.
@@ -1533,6 +1386,8 @@ class GTMService {
1533
1386
  */
1534
1387
  pushOnDataLayer(obj) {
1535
1388
  const dataLayer = this.getDataLayer();
1389
+ if (!dataLayer.length && !this.isBrowser)
1390
+ return;
1536
1391
  dataLayer.push(obj);
1537
1392
  }
1538
1393
  /**
@@ -1541,24 +1396,45 @@ class GTMService {
1541
1396
  */
1542
1397
  addGtmToDom() {
1543
1398
  return new Promise((resolve, reject) => {
1399
+ if (!this.isBrowser) {
1400
+ return resolve(false);
1401
+ }
1544
1402
  if (this.isLoaded) {
1545
1403
  return resolve(this.isLoaded);
1546
1404
  }
1547
- //const doc = this.browserGlobals.documentRef();
1548
- this.pushOnDataLayer({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
1549
- const gtmScript = this.document?.createElement('script'); //doc.createElement('script');
1550
- if (gtmScript) {
1551
- gtmScript.id = 'GTMscript';
1552
- gtmScript.async = true;
1553
- gtmScript.src = this.applyGtmQueryParams(this.config["gtm_resource_path"] ? this.config["gtm_resource_path"] : 'https://www.googletagmanager.com/gtm.js');
1554
- gtmScript.addEventListener('load', () => {
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);
1405
+ const doc = this.documentRef;
1406
+ if (!doc) {
1407
+ return reject(false);
1408
+ }
1409
+ const existing = doc.getElementById('GTMscript');
1410
+ if (existing) {
1411
+ this.isLoaded = true;
1412
+ return resolve(true);
1561
1413
  }
1414
+ this.pushOnDataLayer({
1415
+ 'gtm.start': new Date().getTime(),
1416
+ event: 'gtm.js'
1417
+ });
1418
+ const gtmScript = doc.createElement('script');
1419
+ if (!gtmScript) {
1420
+ return reject(false);
1421
+ }
1422
+ gtmScript.id = 'GTMscript';
1423
+ gtmScript.async = true;
1424
+ gtmScript.src = this.applyGtmQueryParams(this.config['gtm_resource_path']
1425
+ ? this.config['gtm_resource_path']
1426
+ : 'https://www.googletagmanager.com/gtm.js');
1427
+ gtmScript.addEventListener('load', () => {
1428
+ this.isLoaded = true;
1429
+ return resolve(true);
1430
+ });
1431
+ gtmScript.addEventListener('error', () => {
1432
+ this.isLoaded = false;
1433
+ return reject(false);
1434
+ });
1435
+ doc.head
1436
+ ? doc.head.insertBefore(gtmScript, doc.head.firstChild)
1437
+ : doc.appendChild(gtmScript);
1562
1438
  });
1563
1439
  }
1564
1440
  applyGtmQueryParams(url) {
@@ -1572,29 +1448,52 @@ class GTMService {
1572
1448
  * @param config Configuraciones de Google Tag Manager
1573
1449
  */
1574
1450
  initialize(config) {
1451
+ if (!this.isBrowser)
1452
+ return;
1453
+ if (this.isLoaded)
1454
+ return;
1575
1455
  this.config = config || this.config;
1456
+ if (!config?.id)
1457
+ return;
1576
1458
  this.addGtmToDom().then(() => {
1577
- this.router.events.forEach(item => {
1578
- if (item instanceof NavigationEnd) {
1579
- const gtmTag = {
1580
- event: 'page',
1581
- pageName: item.url
1582
- };
1583
- this.pushTag(gtmTag);
1584
- }
1459
+ this.isLoaded = true;
1460
+ this.enabled = true;
1461
+ this.router.events
1462
+ .pipe(filter(event => event instanceof NavigationEnd))
1463
+ .subscribe((event) => {
1464
+ const gtmTag = {
1465
+ event: 'page',
1466
+ pageName: event.urlAfterRedirects ?? event.url
1467
+ };
1468
+ this.pushTag(gtmTag);
1585
1469
  });
1470
+ }).catch(() => {
1471
+ this.isLoaded = false;
1472
+ this.enabled = false;
1586
1473
  });
1587
1474
  }
1588
1475
  pushTag(item) {
1589
1476
  return new Promise((resolve, reject) => {
1477
+ if (!this.isBrowser) {
1478
+ return resolve();
1479
+ }
1480
+ if (!this.config?.id) {
1481
+ return resolve();
1482
+ }
1590
1483
  if (!this.isLoaded) {
1591
1484
  this.addGtmToDom().then(() => {
1485
+ this.isLoaded = true;
1486
+ this.enabled = true;
1592
1487
  this.pushOnDataLayer(item);
1593
1488
  return resolve();
1594
- }).catch(() => reject());
1489
+ }).catch(err => {
1490
+ return reject(err);
1491
+ });
1595
1492
  }
1596
1493
  else {
1597
- this.pushOnDataLayer(item);
1494
+ if (this.enabled) {
1495
+ this.pushOnDataLayer(item);
1496
+ }
1598
1497
  return resolve();
1599
1498
  }
1600
1499
  });
@@ -2056,6 +1955,211 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
2056
1955
  }]
2057
1956
  }], ctorParameters: () => [] });
2058
1957
 
1958
+ /**
1959
+ * Servicio que maneja los parametros de la aplicación.
1960
+ */
1961
+ class ParametersService {
1962
+ /**
1963
+ * Constantes de la API
1964
+ */
1965
+ apiConstants = inject(ApiConstantsService);
1966
+ /**
1967
+ * Maneja las peticiones a la API
1968
+ */
1969
+ connection = inject(ConnectionService);
1970
+ /**
1971
+ * Servicio de Analytics
1972
+ */
1973
+ analyticsService = inject(AnalyticsService);
1974
+ //API URLS
1975
+ /**
1976
+ * Devuelve la URL para obtener todos los parametros.
1977
+ * @returns
1978
+ */
1979
+ getAllParametersAPI() { return `${this.apiConstants.SHOP_API_URL}${this.apiConstants.CHANNEL}/parameters`; }
1980
+ //OBSERVABLES
1981
+ /**
1982
+ * Subject para manejar los cambios en los datos de los parametros
1983
+ */
1984
+ parametersSubject = new BehaviorSubject(null);
1985
+ parameters$ = this.parametersSubject.asObservable();
1986
+ //METHODS
1987
+ /**
1988
+ * Obtiene los parámetros del backend.
1989
+ * @returns
1990
+ */
1991
+ getParameters() {
1992
+ if (this.parametersSubject.getValue() === null) {
1993
+ this.connection.get(this.getAllParametersAPI()).pipe(shareReplay(1), map((response) => {
1994
+ this.parametersSubject.next(response);
1995
+ this.initAnalyticsFromParams(response);
1996
+ return response;
1997
+ }), catchError((error) => {
1998
+ console.log(`Error: ${error}`);
1999
+ this.parametersSubject.next([]);
2000
+ return of([]);
2001
+ })).subscribe();
2002
+ }
2003
+ return this.parameters$;
2004
+ }
2005
+ /**
2006
+ * Comprueba si el código de un parámetro existe en la lista de parámetros.
2007
+ * @param params Lista de parámetros
2008
+ * @param code Código del parámetro a buscar
2009
+ * @returns El objeto con los datos del parámetro encontrado, sino retorna `null`
2010
+ */
2011
+ hasParams(params, code) { return params && params.find((param) => param.code?.toLowerCase().includes(code.toLowerCase())); }
2012
+ findAnalyticsParam(params, service) {
2013
+ const channel = this.apiConstants.CHANNEL?.toLowerCase() ?? '';
2014
+ // Código específico por canal: facebook_nombrecanal_id
2015
+ const codeChannel = `${service}_${channel}_id`;
2016
+ // Código genérico: facebook_id
2017
+ const codeGeneric = `${service}_id`;
2018
+ const normalize = (code) => (code || '').toLowerCase();
2019
+ let param = params.find(p => normalize(p.code) === codeChannel);
2020
+ if (!param) {
2021
+ param = params.find(p => normalize(p.code) === codeGeneric);
2022
+ }
2023
+ return param;
2024
+ }
2025
+ initAnalyticsFromParams(params) {
2026
+ if (!params || !params.length)
2027
+ return;
2028
+ if (!this.apiConstants.IS_PRODUCTION)
2029
+ return;
2030
+ const facebook = this.findAnalyticsParam(params, 'facebook');
2031
+ const google = this.findAnalyticsParam(params, 'google');
2032
+ const gtm = this.findAnalyticsParam(params, 'gtm');
2033
+ const metricool = this.findAnalyticsParam(params, 'metricool');
2034
+ const doppler = this.findAnalyticsParam(params, 'doppler');
2035
+ if (facebook)
2036
+ this.analyticsService.initializeFacebook(facebook.value);
2037
+ if (google)
2038
+ this.analyticsService.initializeGoogle(google.value);
2039
+ if (gtm)
2040
+ this.analyticsService.initializeGTM(gtm.value);
2041
+ if (metricool)
2042
+ this.analyticsService.initializeMetricool(metricool.value);
2043
+ if (doppler)
2044
+ this.analyticsService.initializeDoppler(doppler.value);
2045
+ }
2046
+ constructor() { }
2047
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ParametersService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2048
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ParametersService, providedIn: 'root' });
2049
+ }
2050
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ParametersService, decorators: [{
2051
+ type: Injectable,
2052
+ args: [{
2053
+ providedIn: 'root'
2054
+ }]
2055
+ }], ctorParameters: () => [] });
2056
+
2057
+ /**
2058
+ * Servicio que maneja los bloques como repositorio.
2059
+ * @class BlocksRepositoryService
2060
+ */
2061
+ class BlocksRepositoryService {
2062
+ /**
2063
+ * Constantes de la API
2064
+ */
2065
+ apiConstants = inject(ApiConstantsService);
2066
+ /**
2067
+ * Menaja las conexiones con la API
2068
+ */
2069
+ connection = inject(ConnectionService);
2070
+ /**
2071
+ * Subject para manejar los bloques recibidos.
2072
+ */
2073
+ blocksSubject = new BehaviorSubject([]);
2074
+ /**
2075
+ * Observable de bloques.
2076
+ */
2077
+ blocks$ = this.blocksSubject.asObservable();
2078
+ //API URLS
2079
+ /**
2080
+ * Devuelve la url para obtener los bloques segun la sección.
2081
+ * @param section
2082
+ * @returns
2083
+ */
2084
+ blocksAPI(section) { return `${this.apiConstants.CMS_URL}${this.apiConstants.CHANNEL}/blocks/section/${section}?locale=${this.apiConstants.LOCALE}`; }
2085
+ /**
2086
+ * Obtiene los bloques segun la seccion del Backend.
2087
+ * @param section
2088
+ * @returns Un observable de los bloques.
2089
+ */
2090
+ getBlocks(section) {
2091
+ //if(this.blocksSubject.getValue() != null){
2092
+ this.connection.get(this.blocksAPI(section)).pipe(shareReplay(1), map((response) => {
2093
+ //console.log(response)
2094
+ this.blocksSubject.next(response.items);
2095
+ return response;
2096
+ })).subscribe();
2097
+ //}
2098
+ return this.blocks$;
2099
+ }
2100
+ /* private hasSectionBlocks = (section: string) => {
2101
+
2102
+ } */
2103
+ appendBlock = (blocks, section) => {
2104
+ const new_block = { section, blocks };
2105
+ };
2106
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksRepositoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2107
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksRepositoryService, providedIn: 'root' });
2108
+ }
2109
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksRepositoryService, decorators: [{
2110
+ type: Injectable,
2111
+ args: [{
2112
+ providedIn: 'root'
2113
+ }]
2114
+ }] });
2115
+
2116
+ /**
2117
+ * Servicio de tipo adapter para manejar los bloques.
2118
+ * @class BlocksService
2119
+ */
2120
+ class BlocksService {
2121
+ /**
2122
+ * Constantes de la API
2123
+ */
2124
+ apiConstants = inject(ApiConstantsService);
2125
+ /**
2126
+ * Servicio de BlocksRepository.
2127
+ */
2128
+ blocksRepositoryService = inject(BlocksRepositoryService);
2129
+ /**
2130
+ * Subject para manejar los bloques recibidos.
2131
+ */
2132
+ blocksSubject = new BehaviorSubject([]);
2133
+ /**
2134
+ * Observable de bloques.
2135
+ */
2136
+ blocks$ = this.blocksSubject.asObservable();
2137
+ //API URLS
2138
+ /**
2139
+ * Devuelve la url para interactuar con el bloque de contacto.
2140
+ * @returns
2141
+ */
2142
+ contactFormResponseAPI() { return `${this.apiConstants.CMS_URL}${this.apiConstants.LOCALE}/contact-form/response`; }
2143
+ //METHODS
2144
+ /**
2145
+ * Obtiene los bloques de una sección en especifico.
2146
+ * @param section
2147
+ * @returns Observable de los bloques.
2148
+ */
2149
+ getBlocks(section) {
2150
+ return this.blocksRepositoryService.getBlocks(section);
2151
+ }
2152
+ constructor() { }
2153
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2154
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksService, providedIn: 'root' });
2155
+ }
2156
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BlocksService, decorators: [{
2157
+ type: Injectable,
2158
+ args: [{
2159
+ providedIn: 'root'
2160
+ }]
2161
+ }], ctorParameters: () => [] });
2162
+
2059
2163
  /**
2060
2164
  * Servicio para manejar los canales de la aplicación
2061
2165
  * @class ChannelService
@@ -7818,26 +7922,16 @@ class RedsysCatchEcComponent extends ComponentHelper {
7818
7922
  }
7819
7923
  /** Intenta cerrar la pestaña actual; si falla, ejecuta el callback de fallback. */
7820
7924
  tryCloseSelf(onFail) {
7821
- if (!isPlatformBrowser(this.platformId)) {
7822
- onFail();
7823
- return;
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);
7925
+ if (!isPlatformBrowser(this.platformId))
7926
+ return onFail();
7927
+ let attempted = false;
7833
7928
  try {
7834
7929
  window.close();
7835
- // Si window.close() lanza excepción, limpiamos el timeout y hacemos fallback inmediato.
7930
+ attempted = true;
7836
7931
  }
7837
- catch {
7838
- clearTimeout(fallback);
7932
+ catch { }
7933
+ if (!attempted)
7839
7934
  onFail();
7840
- }
7841
7935
  }
7842
7936
  /** Oculta header/footer para esta pantalla mínima. */
7843
7937
  hideHeaderFooter() {
@@ -9834,7 +9928,6 @@ class MpRedirectEcComponent {
9834
9928
  _toastService = inject(ToastService);
9835
9929
  platformId = inject(PLATFORM_ID);
9836
9930
  finished = false;
9837
- ngZone = inject(NgZone);
9838
9931
  method = null;
9839
9932
  total_amount = 0;
9840
9933
  allData;
@@ -9857,10 +9950,10 @@ class MpRedirectEcComponent {
9857
9950
  this.windowRef = window;
9858
9951
  if ('BroadcastChannel' in window) {
9859
9952
  this.bc = new BroadcastChannel('mp_payment');
9860
- this.bc.onmessage = (e) => this.ngZone.run(() => this.onMpMessage(e?.data));
9953
+ this.bc.onmessage = (e) => this.onMpMessage(e?.data);
9861
9954
  }
9862
- window.addEventListener('storage', (e) => this.ngZone.run(() => this.onStorage(e)));
9863
- window.addEventListener('message', (e) => this.ngZone.run(() => this.onWindowMessage(e)));
9955
+ window.addEventListener('storage', this.onStorage);
9956
+ window.addEventListener('message', this.onWindowMessage);
9864
9957
  }
9865
9958
  this.getPreference();
9866
9959
  }
@@ -9913,29 +10006,23 @@ class MpRedirectEcComponent {
9913
10006
  }, 1000);
9914
10007
  };
9915
10008
  onWindowMessage = (event) => {
9916
- this.ngZone.run(() => {
9917
- const data = event?.data;
9918
- this.onMpMessage(data);
9919
- });
10009
+ const data = event?.data;
10010
+ this.onMpMessage(data);
9920
10011
  };
9921
10012
  onStorage = (e) => {
9922
- this.ngZone.run(() => {
9923
- if (!e.key || !this.sid)
9924
- return;
9925
- if (e.key === `mp:state:${this.sid}` && e.newValue) {
9926
- const state = e.newValue;
9927
- this.finishWithState(state);
9928
- }
9929
- });
10013
+ if (!e.key || !this.sid)
10014
+ return;
10015
+ if (e.key === `mp:state:${this.sid}` && e.newValue) {
10016
+ const state = e.newValue;
10017
+ this.finishWithState(state);
10018
+ }
9930
10019
  };
9931
10020
  onMpMessage = (data) => {
9932
- this.ngZone.run(() => {
9933
- if (!data || data.type !== 'mp:state')
9934
- return;
9935
- if (data.sid !== this.sid)
9936
- return;
9937
- this.finishWithState(data.state);
9938
- });
10021
+ if (!data || data.type !== 'mp:state')
10022
+ return;
10023
+ if (data.sid !== this.sid)
10024
+ return;
10025
+ this.finishWithState(data.state);
9939
10026
  };
9940
10027
  checkLocalStorageOnce() {
9941
10028
  if (!this.sid)
@@ -9946,34 +10033,32 @@ class MpRedirectEcComponent {
9946
10033
  }
9947
10034
  /** Cierra el flujo de pago con el estado final y notifica al padre. */
9948
10035
  finishWithState(state) {
9949
- this.ngZone.run(() => {
9950
- if (this.finished)
9951
- return;
9952
- this.finished = true;
9953
- if (this.pollTimer)
9954
- clearInterval(this.pollTimer);
9955
- this.pollTimer = null;
9956
- localStorage.removeItem(`mp:state:${this.sid}`);
9957
- localStorage.removeItem('mp:sid');
9958
- localStorage.removeItem('state');
9959
- try {
9960
- this.ventana && !this.ventana.closed && this.ventana.close();
9961
- }
9962
- catch { }
9963
- this.ventana = null;
9964
- if (state === 'success' || state === 'pending') {
9965
- this.phase = 'finalizing';
9966
- this.ready.emit(true);
9967
- }
9968
- else if (state === 'failure' || state === 'cancel') {
9969
- this.phase = 'idle';
9970
- this._toastService.show(state === 'cancel' ? 'Se canceló el pago con Mercado Pago' : 'payment-error');
9971
- }
9972
- else {
9973
- this.phase = 'idle';
9974
- this._toastService.show('payment-error');
9975
- }
9976
- });
10036
+ if (this.finished)
10037
+ return;
10038
+ this.finished = true;
10039
+ if (this.pollTimer)
10040
+ clearInterval(this.pollTimer);
10041
+ this.pollTimer = null;
10042
+ localStorage.removeItem(`mp:state:${this.sid}`);
10043
+ localStorage.removeItem('mp:sid');
10044
+ localStorage.removeItem('state');
10045
+ try {
10046
+ this.ventana && !this.ventana.closed && this.ventana.close();
10047
+ }
10048
+ catch { }
10049
+ this.ventana = null;
10050
+ if (state === 'success' || state === 'pending') {
10051
+ this.phase = 'finalizing';
10052
+ this.ready.emit(true);
10053
+ }
10054
+ else if (state === 'failure' || state === 'cancel') {
10055
+ this.phase = 'idle';
10056
+ this._toastService.show(state === 'cancel' ? 'Se canceló el pago con Mercado Pago' : 'payment-error');
10057
+ }
10058
+ else {
10059
+ this.phase = 'idle';
10060
+ this._toastService.show('payment-error');
10061
+ }
9977
10062
  }
9978
10063
  genSid() {
9979
10064
  return `mp_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
@@ -10339,11 +10424,6 @@ class PaymentEcComponent {
10339
10424
  return true;
10340
10425
  };
10341
10426
  verifyValidate = ($event) => {
10342
- console.log('[PAYMENT] verifyValidate llamado con:', $event);
10343
- if (!$event) {
10344
- this.setLoading(false);
10345
- return;
10346
- }
10347
10427
  this.setLoading(true);
10348
10428
  setTimeout(() => this.emitResult(), 1000);
10349
10429
  };