ng-easycommerce-v18 0.3.14-beta.4 → 0.3.14-beta.6
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 +20 -0
- package/esm2022/lib/constants/core.constants.service.mjs +2 -2
- package/esm2022/lib/ec-components/abstractions-components/menu-ec.component.mjs +17 -1
- package/esm2022/lib/ec-components/auth-ec/login-form-ec/login-form-ec.component.mjs +5 -1
- package/esm2022/lib/ec-components/auth-ec/register-form-ec/register-form-ec.component.mjs +5 -1
- package/esm2022/lib/ec-components/cart-ec/cart-item-ec/cart-item-ec.component.mjs +6 -2
- package/esm2022/lib/ec-components/checkout-ec/payment-ec/payment-methods/mp-redirect-ec/mp-redirect-ec.component.mjs +141 -75
- package/esm2022/lib/ec-components/filters-ec/filters-ec.component.mjs +30 -5
- package/esm2022/lib/ec-components/header-ec/header-ec.component.mjs +23 -3
- package/esm2022/lib/ec-components/product-detail-ec/product-detail-ec.component.mjs +11 -10
- package/esm2022/lib/ec-components/product-ec/product-ec.component.mjs +95 -5
- package/esm2022/lib/ec-components/stores-ec/stores-ec.component.mjs +21 -6
- package/esm2022/lib/ec-components/widgets-ec/decidir-ec/decidir-ec.component.mjs +3 -1
- package/esm2022/lib/ec-components/widgets-ec/index.mjs +2 -1
- package/esm2022/lib/ec-components/widgets-ec/redsys-catch-ec/redsys-catch-ec.component.mjs +193 -0
- package/esm2022/lib/ec-services/analytics/google-analytics.service.mjs +4 -2
- package/esm2022/lib/ec-services/analytics/gtm.service.mjs +6 -3
- package/esm2022/lib/ec-services/analytics/metricool-pixel.service.mjs +4 -2
- package/esm2022/lib/interfaces/filter.mjs +1 -1
- package/esm2022/lib/interfaces/options.mjs +1 -1
- package/fesm2022/ng-easycommerce-v18.mjs +559 -124
- package/fesm2022/ng-easycommerce-v18.mjs.map +1 -1
- package/lib/ec-components/abstractions-components/menu-ec.component.d.ts +12 -0
- package/lib/ec-components/auth-ec/login-form-ec/login-form-ec.component.d.ts +2 -0
- package/lib/ec-components/auth-ec/register-form-ec/register-form-ec.component.d.ts +2 -0
- package/lib/ec-components/cart-ec/cart-item-ec/cart-item-ec.component.d.ts +5 -0
- package/lib/ec-components/checkout-ec/payment-ec/payment-methods/mp-redirect-ec/mp-redirect-ec.component.d.ts +38 -16
- package/lib/ec-components/filters-ec/filters-ec.component.d.ts +12 -4
- package/lib/ec-components/header-ec/header-ec.component.d.ts +5 -1
- package/lib/ec-components/product-ec/product-ec.component.d.ts +10 -1
- package/lib/ec-components/stores-ec/stores-ec.component.d.ts +2 -1
- package/lib/ec-components/widgets-ec/index.d.ts +1 -0
- package/lib/ec-components/widgets-ec/redsys-catch-ec/redsys-catch-ec.component.d.ts +47 -0
- package/lib/ec-services/analytics/google-analytics.service.d.ts +1 -1
- package/lib/ec-services/analytics/gtm.service.d.ts +1 -1
- package/lib/interfaces/filter.d.ts +1 -0
- package/lib/interfaces/options.d.ts +2 -0
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ import { ToastrService } from 'ngx-toastr';
|
|
|
14
14
|
import moment from 'moment';
|
|
15
15
|
import { StorageMap } from '@ngx-pwa/local-storage';
|
|
16
16
|
import * as i1$3 from '@angular/forms';
|
|
17
|
-
import { Validators, FormBuilder, NG_VALUE_ACCESSOR, ReactiveFormsModule
|
|
17
|
+
import { Validators, FormsModule, FormBuilder, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
|
|
18
18
|
import { register } from 'swiper/element/bundle';
|
|
19
19
|
import { register as register$1 } from 'swiper/element';
|
|
20
20
|
import * as i1$4 from '@angular/platform-browser';
|
|
@@ -295,7 +295,7 @@ class CoreConstantsService {
|
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
297
|
// Para SSR, intentar construir desde el document si está disponible
|
|
298
|
-
if (this.document?.location) {
|
|
298
|
+
if (isPlatformBrowser(this.platformId) && this.document?.location) {
|
|
299
299
|
return `${this.document.location.protocol}//${this.document.location.host}`;
|
|
300
300
|
}
|
|
301
301
|
// Intentar obtener desde environment
|
|
@@ -1253,7 +1253,9 @@ class GoogleAnalyticsService {
|
|
|
1253
1253
|
* @param gtm_id id provisto por Google Tag Manager.
|
|
1254
1254
|
*/
|
|
1255
1255
|
initialize(gtm_id) {
|
|
1256
|
-
if (!
|
|
1256
|
+
if (!isPlatformBrowser(this.platformId))
|
|
1257
|
+
return;
|
|
1258
|
+
if (!this.document?.getElementById('google_tag_manager')) {
|
|
1257
1259
|
console.log('hay elemento');
|
|
1258
1260
|
const declaration = this.renderer.createElement('script');
|
|
1259
1261
|
declaration.async = true;
|
|
@@ -1568,9 +1570,12 @@ class GTMService {
|
|
|
1568
1570
|
if (this.isLoaded) {
|
|
1569
1571
|
return resolve(this.isLoaded);
|
|
1570
1572
|
}
|
|
1573
|
+
if (!isPlatformBrowser(this.platformId) || !this.document) {
|
|
1574
|
+
return reject(false);
|
|
1575
|
+
}
|
|
1571
1576
|
//const doc = this.browserGlobals.documentRef();
|
|
1572
1577
|
this.pushOnDataLayer({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
|
|
1573
|
-
const gtmScript = this.document
|
|
1578
|
+
const gtmScript = this.document.createElement('script'); //doc.createElement('script');
|
|
1574
1579
|
if (gtmScript) {
|
|
1575
1580
|
gtmScript.id = 'GTMscript';
|
|
1576
1581
|
gtmScript.async = true;
|
|
@@ -1581,7 +1586,7 @@ class GTMService {
|
|
|
1581
1586
|
gtmScript.addEventListener('error', () => {
|
|
1582
1587
|
return reject(false);
|
|
1583
1588
|
});
|
|
1584
|
-
this.document
|
|
1589
|
+
this.document.head.insertBefore(gtmScript, this.document.head.firstChild);
|
|
1585
1590
|
}
|
|
1586
1591
|
});
|
|
1587
1592
|
}
|
|
@@ -1982,6 +1987,8 @@ class MetricoolPixelService {
|
|
|
1982
1987
|
* @param pixel_hash hash provisto por Metricool Pixel.
|
|
1983
1988
|
*/
|
|
1984
1989
|
initialize = (pixel_hash) => {
|
|
1990
|
+
if (!isPlatformBrowser(this.platformId) || !this.document)
|
|
1991
|
+
return;
|
|
1985
1992
|
let new_analityc_script = this.renderer.createElement('script');
|
|
1986
1993
|
new_analityc_script.type = 'text/javascript';
|
|
1987
1994
|
new_analityc_script.text = `
|
|
@@ -1995,7 +2002,7 @@ class MetricoolPixelService {
|
|
|
1995
2002
|
beTracker.t({ hash: "${pixel_hash}" })
|
|
1996
2003
|
});
|
|
1997
2004
|
`;
|
|
1998
|
-
this.renderer.appendChild(this.document
|
|
2005
|
+
this.renderer.appendChild(this.document.body, new_analityc_script);
|
|
1999
2006
|
};
|
|
2000
2007
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MetricoolPixelService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2001
2008
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MetricoolPixelService, providedIn: 'root' });
|
|
@@ -6057,6 +6064,22 @@ class MenuEcComponent {
|
|
|
6057
6064
|
hasVisibleProperty(category) {
|
|
6058
6065
|
return category.isVisible === true;
|
|
6059
6066
|
}
|
|
6067
|
+
filterVisibleTree(list) {
|
|
6068
|
+
return (list ?? [])
|
|
6069
|
+
.filter((n) => n?.isVisible === true)
|
|
6070
|
+
.map(n => ({ ...n, children: this.filterVisibleTree(n.children) }));
|
|
6071
|
+
}
|
|
6072
|
+
// Exponé streams ya filtrados
|
|
6073
|
+
categoriesVisible$ = this.categories$.pipe(map((list) => this.filterVisibleTree(list)));
|
|
6074
|
+
sectionsVisible$ = this.sections$.pipe(map((list) => this.filterVisibleTree(list)));
|
|
6075
|
+
attributesVisible$ = this.attributes$.pipe(map((list) => this.filterVisibleTree(list)));
|
|
6076
|
+
// Helpers de conveniencia opcionales
|
|
6077
|
+
getVisibleChildren(node) {
|
|
6078
|
+
return this.filterVisibleTree(node?.children);
|
|
6079
|
+
}
|
|
6080
|
+
hasVisibleChildren(node) {
|
|
6081
|
+
return this.getVisibleChildren(node).length > 0;
|
|
6082
|
+
}
|
|
6060
6083
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MenuEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6061
6084
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: MenuEcComponent, isStandalone: true, selector: "lib-footer-ec", ngImport: i0, template: '<p>Menu and Footer Helper Component</p>', isInline: true });
|
|
6062
6085
|
}
|
|
@@ -6203,6 +6226,11 @@ class HeaderEcComponent extends MenuEcComponent {
|
|
|
6203
6226
|
hidePrices = false;
|
|
6204
6227
|
__authService = inject(AuthService);
|
|
6205
6228
|
_channelService = inject(ChannelService);
|
|
6229
|
+
changeDetector = inject(ChangeDetectorRef);
|
|
6230
|
+
appRouter = inject(Router);
|
|
6231
|
+
platformId = inject(PLATFORM_ID);
|
|
6232
|
+
// Observable del estado de autenticación
|
|
6233
|
+
logged$;
|
|
6206
6234
|
isAuthenticated$ = this.__authService.isAuthenticated();
|
|
6207
6235
|
constructor() {
|
|
6208
6236
|
super();
|
|
@@ -6216,11 +6244,26 @@ class HeaderEcComponent extends MenuEcComponent {
|
|
|
6216
6244
|
coreConstantsService = inject(CoreConstantsService);
|
|
6217
6245
|
router = inject(Router);
|
|
6218
6246
|
cdr = inject(ChangeDetectorRef); // Inyectamos ChangeDetectorRef para forzar la actualización
|
|
6219
|
-
platformId = inject(PLATFORM_ID);
|
|
6220
6247
|
ngOnInit() {
|
|
6221
6248
|
this.channel = this.coreConstantsService.getChannel();
|
|
6222
6249
|
this.onWindowScroll();
|
|
6223
6250
|
this.detectRouteChange(); // Llamamos a la función que detecta el cambio de ruta
|
|
6251
|
+
// Usar el Observable del AuthService
|
|
6252
|
+
this.logged$ = this.__authService.loggedIn$;
|
|
6253
|
+
// Suscribirse al Observable y forzar detección de cambios cuando sea necesario
|
|
6254
|
+
this.logged$.subscribe(isLoggedIn => {
|
|
6255
|
+
this.changeDetector.detectChanges();
|
|
6256
|
+
});
|
|
6257
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
6258
|
+
this.appRouter.events.subscribe(evt => {
|
|
6259
|
+
if (evt instanceof NavigationEnd) {
|
|
6260
|
+
// Forzar detección de cambios después de navegación
|
|
6261
|
+
setTimeout(() => {
|
|
6262
|
+
this.changeDetector.detectChanges();
|
|
6263
|
+
}, 100);
|
|
6264
|
+
}
|
|
6265
|
+
});
|
|
6266
|
+
}
|
|
6224
6267
|
}
|
|
6225
6268
|
ngAfterViewInit() {
|
|
6226
6269
|
this.setupMobileMenu(); // Inicializamos el menú móvil
|
|
@@ -6934,6 +6977,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
6934
6977
|
class ProductEcComponent {
|
|
6935
6978
|
injector = inject(Injector);
|
|
6936
6979
|
routerService = inject(Router);
|
|
6980
|
+
_cartService = inject(CartService);
|
|
6981
|
+
_toastService = inject(ToastService);
|
|
6982
|
+
isAddingToCart = signal(false);
|
|
6983
|
+
quantity = signal(1);
|
|
6937
6984
|
/**
|
|
6938
6985
|
* Navega al detalle del producto y sube al inicio de la página
|
|
6939
6986
|
* @param productId ID del producto
|
|
@@ -7006,12 +7053,97 @@ class ProductEcComponent {
|
|
|
7006
7053
|
const discount = ((originalPrice - salePrice) / originalPrice) * 100;
|
|
7007
7054
|
return Math.round(discount);
|
|
7008
7055
|
}
|
|
7056
|
+
plus(stock, multipleQuantity) {
|
|
7057
|
+
console.log('Aumentando cantidad');
|
|
7058
|
+
const current = Number(this.quantity()); // <-- fuerza a número
|
|
7059
|
+
if (multipleQuantity && multipleQuantity > 0) {
|
|
7060
|
+
stock
|
|
7061
|
+
? (current < stock
|
|
7062
|
+
? this.quantity.set(current + multipleQuantity)
|
|
7063
|
+
: this._toastService.show('out-of-stock-actually'))
|
|
7064
|
+
: this.quantity.set(current + multipleQuantity);
|
|
7065
|
+
}
|
|
7066
|
+
else {
|
|
7067
|
+
stock
|
|
7068
|
+
? (current < stock
|
|
7069
|
+
? this.quantity.set(current + 1)
|
|
7070
|
+
: this._toastService.show('out-of-stock-actually'))
|
|
7071
|
+
: this.quantity.set(current + 1);
|
|
7072
|
+
}
|
|
7073
|
+
}
|
|
7074
|
+
less(multipleQuantity) {
|
|
7075
|
+
console.log('Disminuyendo cantidad');
|
|
7076
|
+
const current = Number(this.quantity()); // <-- fuerza a número
|
|
7077
|
+
if (multipleQuantity && multipleQuantity > 0) {
|
|
7078
|
+
current > multipleQuantity
|
|
7079
|
+
? this.quantity.set(current - multipleQuantity)
|
|
7080
|
+
: null;
|
|
7081
|
+
}
|
|
7082
|
+
else {
|
|
7083
|
+
current > 1 ? this.quantity.set(current - 1) : null;
|
|
7084
|
+
}
|
|
7085
|
+
}
|
|
7086
|
+
addToCart() {
|
|
7087
|
+
console.log('Añadiendo al carrito');
|
|
7088
|
+
if (this.isAddingToCart() || this.quantity() <= 0)
|
|
7089
|
+
return;
|
|
7090
|
+
// Verificar que tenemos el producto y sus variantes
|
|
7091
|
+
if (!this.product || !this.product.variants || this.product.variants.length === 0) {
|
|
7092
|
+
this._toastService.show('cant-buy');
|
|
7093
|
+
return;
|
|
7094
|
+
}
|
|
7095
|
+
// Verificar stock
|
|
7096
|
+
const firstVariant = this.product.variants[0];
|
|
7097
|
+
if (!firstVariant.stock || firstVariant.stock <= 0) {
|
|
7098
|
+
this._toastService.show('out-of-stock');
|
|
7099
|
+
return;
|
|
7100
|
+
}
|
|
7101
|
+
// Verificar que no se supere el stock disponible
|
|
7102
|
+
if (this.quantity() > firstVariant.stock) {
|
|
7103
|
+
this._toastService.show('out-of-stock-actually');
|
|
7104
|
+
return;
|
|
7105
|
+
}
|
|
7106
|
+
this.isAddingToCart.set(true);
|
|
7107
|
+
try {
|
|
7108
|
+
// Agregar al carrito usando CartService directamente
|
|
7109
|
+
this._cartService.addToCart(this.product, this.quantity(), firstVariant.code);
|
|
7110
|
+
console.log('Producto agregado al carrito exitosamente');
|
|
7111
|
+
// Resetear cantidad a 1 después de agregar al carrito
|
|
7112
|
+
this.quantity.set(1);
|
|
7113
|
+
}
|
|
7114
|
+
catch (error) {
|
|
7115
|
+
console.error('Error al agregar al carrito:', error);
|
|
7116
|
+
this._toastService.show('cant-buy');
|
|
7117
|
+
}
|
|
7118
|
+
setTimeout(() => {
|
|
7119
|
+
this.isAddingToCart.set(false);
|
|
7120
|
+
}, 2000);
|
|
7121
|
+
}
|
|
7122
|
+
checkStock(stock) {
|
|
7123
|
+
if (this.quantity() >= stock)
|
|
7124
|
+
this.quantity.set(stock);
|
|
7125
|
+
}
|
|
7126
|
+
onQuantityChange(event) {
|
|
7127
|
+
const target = event.target;
|
|
7128
|
+
const value = +target.value;
|
|
7129
|
+
// Validar que el valor sea mayor a 0
|
|
7130
|
+
if (value > 0) {
|
|
7131
|
+
this.quantity.set(value);
|
|
7132
|
+
// Validar contra el stock disponible
|
|
7133
|
+
const maxStock = this.product?.variants?.[0]?.stock || this.product?.stock || 0;
|
|
7134
|
+
this.checkStock(maxStock);
|
|
7135
|
+
}
|
|
7136
|
+
else {
|
|
7137
|
+
// Si el valor es 0 o negativo, resetear a 1
|
|
7138
|
+
this.quantity.set(1);
|
|
7139
|
+
}
|
|
7140
|
+
}
|
|
7009
7141
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7010
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ProductEcComponent, isStandalone: true, selector: "app-product-ec", inputs: { product: "product", isProductBox: "isProductBox", isCollection: "isCollection" }, outputs: { loaded: "loaded" }, ngImport: i0, template: "<a [routerLink]=\"['/product', product.id]\" class=\"text-decoration-none producto\">\r\n <!-- Marca especial y descuento -->\r\n <!-- <div *ngIf=\"product.saleprice || (product.special_mark && product.special_mark !== null && product.special_mark !== undefined && product.special_mark.length >0)\"\r\n class=\"marcas\">\r\n <div *ecProductStock=\"product\" [ecProductMini]=\"product.special_mark\"></div>\r\n <ng-container *ngIf=\"shouldShowPrice\">\r\n <div *ecProductStock=\"product\" [ngClass]=\"{'tag-dsc float-right': product.saleprice}\"\r\n [ecProductOff]=\"product\">\r\n </div>\r\n </ng-container>\r\n </div> -->\r\n\r\n <!-- Imagen del producto -->\r\n <div class=\"foto\">\r\n @if(product.picturesdefault){\r\n @if (product.picturesdefault && product.picturesdefault.length > 1 ) {\r\n <img [src]=\"mediaUrl + product.picturesdefault[0]\" alt=\"Imagen principal\" class=\"w-100 pic01\" />\r\n <img [src]=\"mediaUrl + product.picturesdefault[1]\" alt=\"Imagen secundaria\" class=\"w-100 pic02\" />\r\n } @else {\r\n <img [src]=\"mediaUrl + product.picturesdefault[0]\" alt=\"Imagen principal\" class=\"w-100 pic01\" />\r\n }\r\n }\r\n </div>\r\n <!-- Precio -->\r\n\r\n\r\n <!-- Nombre del producto -->\r\n <h6 class=\"title\">{{ product.name | titlecase }}</h6>\r\n\r\n <div class=\"sku\" [innerHTML]=\"product.shortdetails\"></div>\r\n\r\n @if (shouldShowPrice) {\r\n <app-price-ec [price]=\"product.price\" [saleprice]=\"product.saleprice\" class=\"\" />\r\n }\r\n @if(!hidePrices){\r\n @if(!showPricesOnlyToLoggedUsers || isAuthenticated$){\r\n\r\n <div class=\"fixBottom\">\r\n\r\n <!-- Bot\u00F3n de acciones -->\r\n <!-- <ng-container *ecProductStock=\"product; else noStock\"> -->\r\n <!-- Cuando no tiene marca especial o es de tipo 'standard' -->\r\n @if (!product.special_mark || product.special_mark.length === 0 || product.special_mark[0]?.type ===\r\n 'standard') {\r\n <button class=\"btn standard\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n <ng-container *ngIf=\"isCollection; else normalText\">\r\n <span> {{(\"buy\" | translate) | uppercase}} </span>\r\n </ng-container>\r\n <ng-template #normalText>\r\n {{(\"buy\" | translate) | uppercase}}\r\n </ng-template>\r\n </button>\r\n }@else {\r\n <!-- Caso 1: Agotado o Disponible muy pronto -->\r\n @if (product.special_mark[0]?.type === 'out_of_stock' || product.special_mark[0]?.type === 'coming_soon') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0].name | uppercase }} </span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n </button>}\r\n <!-- Caso 2: Contacto por WhatsApp -->\r\n @if (product.special_mark[0].type === 'whatsapp_contact') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\"\r\n (click)=\"openWhatsApp(product.special_mark[0]?.whatsappContact)\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0]?.name | uppercase }}</span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n\r\n </button>\r\n }\r\n <!-- Caso 3: Solicitar m\u00E1s informaci\u00F3n -->\r\n @if (product.special_mark[0]?.type === 'more_info') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0]?.name | uppercase }}</span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n </button>\r\n }\r\n }\r\n </div>\r\n }}\r\n</a>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1.TitleCasePipe, name: "titlecase" }, { kind: "component", type: PriceEcComponent, selector: "app-price-ec", inputs: ["price", "saleprice", "basePrice", "taxeAmount", "taxes", "priceSize", "showTaxLegendOnly", "disableTaxInfo", "customPriceTemplate", "customSalePriceTemplate", "customSimplePriceTemplate", "customSimpleSalePriceTemplate", "customTaxTemplate", "customOnlyTaxLabelTemplate"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
|
|
7142
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ProductEcComponent, isStandalone: true, selector: "app-product-ec", inputs: { product: "product", isProductBox: "isProductBox", isCollection: "isCollection" }, outputs: { loaded: "loaded" }, ngImport: i0, template: "<a [routerLink]=\"['/product', product.id]\" class=\"text-decoration-none producto\">\r\n <!-- Marca especial y descuento -->\r\n <!-- <div *ngIf=\"product.saleprice || (product.special_mark && product.special_mark !== null && product.special_mark !== undefined && product.special_mark.length >0)\"\r\n class=\"marcas\">\r\n <div *ecProductStock=\"product\" [ecProductMini]=\"product.special_mark\"></div>\r\n <ng-container *ngIf=\"shouldShowPrice\">\r\n <div *ecProductStock=\"product\" [ngClass]=\"{'tag-dsc float-right': product.saleprice}\"\r\n [ecProductOff]=\"product\">\r\n </div>\r\n </ng-container>\r\n </div> -->\r\n\r\n <!-- Imagen del producto -->\r\n <div class=\"foto\">\r\n @if(product.picturesdefault){\r\n @if (product.picturesdefault && product.picturesdefault.length > 1 ) {\r\n <img [src]=\"mediaUrl + product.picturesdefault[0]\" alt=\"Imagen principal\" class=\"w-100 pic01\" />\r\n <img [src]=\"mediaUrl + product.picturesdefault[1]\" alt=\"Imagen secundaria\" class=\"w-100 pic02\" />\r\n } @else {\r\n <img [src]=\"mediaUrl + product.picturesdefault[0]\" alt=\"Imagen principal\" class=\"w-100 pic01\" />\r\n }\r\n }\r\n </div>\r\n <!-- Precio -->\r\n\r\n\r\n <!-- Nombre del producto -->\r\n <h6 class=\"title\">{{ product.name | titlecase }}</h6>\r\n\r\n <div class=\"sku\" [innerHTML]=\"product.shortdetails\"></div>\r\n\r\n @if (shouldShowPrice) {\r\n <app-price-ec [price]=\"product.price\" [saleprice]=\"product.saleprice\" class=\"\" />\r\n }\r\n @if(!hidePrices){\r\n @if(!showPricesOnlyToLoggedUsers || isAuthenticated$){\r\n\r\n <div class=\"fixBottom\">\r\n\r\n <!-- Bot\u00F3n de acciones -->\r\n <!-- <ng-container *ecProductStock=\"product; else noStock\"> -->\r\n <!-- Cuando no tiene marca especial o es de tipo 'standard' -->\r\n @if (!product.special_mark || product.special_mark.length === 0 || product.special_mark[0]?.type ===\r\n 'standard') {\r\n <button class=\"btn standard\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n <ng-container *ngIf=\"isCollection; else normalText\">\r\n <span> {{(\"buy\" | translate) | uppercase}} </span>\r\n </ng-container>\r\n <ng-template #normalText>\r\n {{(\"buy\" | translate) | uppercase}}\r\n </ng-template>\r\n </button>\r\n }@else {\r\n <!-- Caso 1: Agotado o Disponible muy pronto -->\r\n @if (product.special_mark[0]?.type === 'out_of_stock' || product.special_mark[0]?.type === 'coming_soon') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0].name | uppercase }} </span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n </button>}\r\n <!-- Caso 2: Contacto por WhatsApp -->\r\n @if (product.special_mark[0].type === 'whatsapp_contact') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\"\r\n (click)=\"openWhatsApp(product.special_mark[0]?.whatsappContact)\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0]?.name | uppercase }}</span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n\r\n </button>\r\n }\r\n <!-- Caso 3: Solicitar m\u00E1s informaci\u00F3n -->\r\n @if (product.special_mark[0]?.type === 'more_info') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0]?.name | uppercase }}</span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n </button>\r\n }\r\n }\r\n </div>\r\n }}\r\n</a>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1.TitleCasePipe, name: "titlecase" }, { kind: "component", type: PriceEcComponent, selector: "app-price-ec", inputs: ["price", "saleprice", "basePrice", "taxeAmount", "taxes", "priceSize", "showTaxLegendOnly", "disableTaxInfo", "customPriceTemplate", "customSalePriceTemplate", "customSimplePriceTemplate", "customSimpleSalePriceTemplate", "customTaxTemplate", "customOnlyTaxLabelTemplate"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: FormsModule }] });
|
|
7011
7143
|
}
|
|
7012
7144
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ProductEcComponent, decorators: [{
|
|
7013
7145
|
type: Component,
|
|
7014
|
-
args: [{ selector: 'app-product-ec', standalone: true, imports: [CommonModule, PriceEcComponent, RouterLink, TranslateModule], template: "<a [routerLink]=\"['/product', product.id]\" class=\"text-decoration-none producto\">\r\n <!-- Marca especial y descuento -->\r\n <!-- <div *ngIf=\"product.saleprice || (product.special_mark && product.special_mark !== null && product.special_mark !== undefined && product.special_mark.length >0)\"\r\n class=\"marcas\">\r\n <div *ecProductStock=\"product\" [ecProductMini]=\"product.special_mark\"></div>\r\n <ng-container *ngIf=\"shouldShowPrice\">\r\n <div *ecProductStock=\"product\" [ngClass]=\"{'tag-dsc float-right': product.saleprice}\"\r\n [ecProductOff]=\"product\">\r\n </div>\r\n </ng-container>\r\n </div> -->\r\n\r\n <!-- Imagen del producto -->\r\n <div class=\"foto\">\r\n @if(product.picturesdefault){\r\n @if (product.picturesdefault && product.picturesdefault.length > 1 ) {\r\n <img [src]=\"mediaUrl + product.picturesdefault[0]\" alt=\"Imagen principal\" class=\"w-100 pic01\" />\r\n <img [src]=\"mediaUrl + product.picturesdefault[1]\" alt=\"Imagen secundaria\" class=\"w-100 pic02\" />\r\n } @else {\r\n <img [src]=\"mediaUrl + product.picturesdefault[0]\" alt=\"Imagen principal\" class=\"w-100 pic01\" />\r\n }\r\n }\r\n </div>\r\n <!-- Precio -->\r\n\r\n\r\n <!-- Nombre del producto -->\r\n <h6 class=\"title\">{{ product.name | titlecase }}</h6>\r\n\r\n <div class=\"sku\" [innerHTML]=\"product.shortdetails\"></div>\r\n\r\n @if (shouldShowPrice) {\r\n <app-price-ec [price]=\"product.price\" [saleprice]=\"product.saleprice\" class=\"\" />\r\n }\r\n @if(!hidePrices){\r\n @if(!showPricesOnlyToLoggedUsers || isAuthenticated$){\r\n\r\n <div class=\"fixBottom\">\r\n\r\n <!-- Bot\u00F3n de acciones -->\r\n <!-- <ng-container *ecProductStock=\"product; else noStock\"> -->\r\n <!-- Cuando no tiene marca especial o es de tipo 'standard' -->\r\n @if (!product.special_mark || product.special_mark.length === 0 || product.special_mark[0]?.type ===\r\n 'standard') {\r\n <button class=\"btn standard\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n <ng-container *ngIf=\"isCollection; else normalText\">\r\n <span> {{(\"buy\" | translate) | uppercase}} </span>\r\n </ng-container>\r\n <ng-template #normalText>\r\n {{(\"buy\" | translate) | uppercase}}\r\n </ng-template>\r\n </button>\r\n }@else {\r\n <!-- Caso 1: Agotado o Disponible muy pronto -->\r\n @if (product.special_mark[0]?.type === 'out_of_stock' || product.special_mark[0]?.type === 'coming_soon') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0].name | uppercase }} </span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n </button>}\r\n <!-- Caso 2: Contacto por WhatsApp -->\r\n @if (product.special_mark[0].type === 'whatsapp_contact') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\"\r\n (click)=\"openWhatsApp(product.special_mark[0]?.whatsappContact)\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0]?.name | uppercase }}</span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n\r\n </button>\r\n }\r\n <!-- Caso 3: Solicitar m\u00E1s informaci\u00F3n -->\r\n @if (product.special_mark[0]?.type === 'more_info') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0]?.name | uppercase }}</span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n </button>\r\n }\r\n }\r\n </div>\r\n }}\r\n</a>" }]
|
|
7146
|
+
args: [{ selector: 'app-product-ec', standalone: true, imports: [CommonModule, PriceEcComponent, RouterLink, TranslateModule, FormsModule], template: "<a [routerLink]=\"['/product', product.id]\" class=\"text-decoration-none producto\">\r\n <!-- Marca especial y descuento -->\r\n <!-- <div *ngIf=\"product.saleprice || (product.special_mark && product.special_mark !== null && product.special_mark !== undefined && product.special_mark.length >0)\"\r\n class=\"marcas\">\r\n <div *ecProductStock=\"product\" [ecProductMini]=\"product.special_mark\"></div>\r\n <ng-container *ngIf=\"shouldShowPrice\">\r\n <div *ecProductStock=\"product\" [ngClass]=\"{'tag-dsc float-right': product.saleprice}\"\r\n [ecProductOff]=\"product\">\r\n </div>\r\n </ng-container>\r\n </div> -->\r\n\r\n <!-- Imagen del producto -->\r\n <div class=\"foto\">\r\n @if(product.picturesdefault){\r\n @if (product.picturesdefault && product.picturesdefault.length > 1 ) {\r\n <img [src]=\"mediaUrl + product.picturesdefault[0]\" alt=\"Imagen principal\" class=\"w-100 pic01\" />\r\n <img [src]=\"mediaUrl + product.picturesdefault[1]\" alt=\"Imagen secundaria\" class=\"w-100 pic02\" />\r\n } @else {\r\n <img [src]=\"mediaUrl + product.picturesdefault[0]\" alt=\"Imagen principal\" class=\"w-100 pic01\" />\r\n }\r\n }\r\n </div>\r\n <!-- Precio -->\r\n\r\n\r\n <!-- Nombre del producto -->\r\n <h6 class=\"title\">{{ product.name | titlecase }}</h6>\r\n\r\n <div class=\"sku\" [innerHTML]=\"product.shortdetails\"></div>\r\n\r\n @if (shouldShowPrice) {\r\n <app-price-ec [price]=\"product.price\" [saleprice]=\"product.saleprice\" class=\"\" />\r\n }\r\n @if(!hidePrices){\r\n @if(!showPricesOnlyToLoggedUsers || isAuthenticated$){\r\n\r\n <div class=\"fixBottom\">\r\n\r\n <!-- Bot\u00F3n de acciones -->\r\n <!-- <ng-container *ecProductStock=\"product; else noStock\"> -->\r\n <!-- Cuando no tiene marca especial o es de tipo 'standard' -->\r\n @if (!product.special_mark || product.special_mark.length === 0 || product.special_mark[0]?.type ===\r\n 'standard') {\r\n <button class=\"btn standard\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n <ng-container *ngIf=\"isCollection; else normalText\">\r\n <span> {{(\"buy\" | translate) | uppercase}} </span>\r\n </ng-container>\r\n <ng-template #normalText>\r\n {{(\"buy\" | translate) | uppercase}}\r\n </ng-template>\r\n </button>\r\n }@else {\r\n <!-- Caso 1: Agotado o Disponible muy pronto -->\r\n @if (product.special_mark[0]?.type === 'out_of_stock' || product.special_mark[0]?.type === 'coming_soon') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0].name | uppercase }} </span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n </button>}\r\n <!-- Caso 2: Contacto por WhatsApp -->\r\n @if (product.special_mark[0].type === 'whatsapp_contact') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\"\r\n (click)=\"openWhatsApp(product.special_mark[0]?.whatsappContact)\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0]?.name | uppercase }}</span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n\r\n </button>\r\n }\r\n <!-- Caso 3: Solicitar m\u00E1s informaci\u00F3n -->\r\n @if (product.special_mark[0]?.type === 'more_info') {\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n @if(isCollection){\r\n <span>{{ product.special_mark[0]?.name | uppercase }}</span>\r\n }@else {\r\n {{ product.special_mark[0]?.name | uppercase }}\r\n }\r\n </button>\r\n }\r\n }\r\n </div>\r\n }}\r\n</a>" }]
|
|
7015
7147
|
}], ctorParameters: () => [], propDecorators: { product: [{
|
|
7016
7148
|
type: Input,
|
|
7017
7149
|
args: [{
|
|
@@ -7589,6 +7721,212 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
7589
7721
|
args: ['mainCanvas', { static: true }]
|
|
7590
7722
|
}] } });
|
|
7591
7723
|
|
|
7724
|
+
class ComponentHelper {
|
|
7725
|
+
constructor() {
|
|
7726
|
+
this.ecOnConstruct();
|
|
7727
|
+
}
|
|
7728
|
+
ecOnInit = (params = {}) => {
|
|
7729
|
+
};
|
|
7730
|
+
ecOnConstruct = (params = {}) => {
|
|
7731
|
+
};
|
|
7732
|
+
hasParams = (params, searched) => {
|
|
7733
|
+
if (!params || !searched)
|
|
7734
|
+
return false;
|
|
7735
|
+
const q = searched.trim().toLowerCase();
|
|
7736
|
+
return params.some(p => {
|
|
7737
|
+
const code = p?.['code']?.toString().toLowerCase() ?? '';
|
|
7738
|
+
// Primero chequeo exacto, y si no, parcial
|
|
7739
|
+
return code === q || code.includes(q);
|
|
7740
|
+
});
|
|
7741
|
+
};
|
|
7742
|
+
navigateOnRouter(router, url) {
|
|
7743
|
+
router.navigateByUrl(`/${url}`);
|
|
7744
|
+
}
|
|
7745
|
+
}
|
|
7746
|
+
|
|
7747
|
+
/**
|
|
7748
|
+
* Catch genérico para redirecciones de pagos.
|
|
7749
|
+
* - Normaliza el estado recibido por params/query.
|
|
7750
|
+
* - Informa el resultado al opener (postMessage), BroadcastChannel y localStorage.
|
|
7751
|
+
* - Intenta cerrarse; si el cierre falla, redirige según el estado.
|
|
7752
|
+
*/
|
|
7753
|
+
class RedsysCatchEcComponent extends ComponentHelper {
|
|
7754
|
+
activedRoute;
|
|
7755
|
+
router;
|
|
7756
|
+
checkoutService;
|
|
7757
|
+
renderer;
|
|
7758
|
+
elementRef;
|
|
7759
|
+
document;
|
|
7760
|
+
platformId;
|
|
7761
|
+
message = '';
|
|
7762
|
+
subscription = null;
|
|
7763
|
+
sid = '';
|
|
7764
|
+
bc;
|
|
7765
|
+
constructor(activedRoute, router, checkoutService, renderer, elementRef, document, platformId) {
|
|
7766
|
+
super();
|
|
7767
|
+
this.activedRoute = activedRoute;
|
|
7768
|
+
this.router = router;
|
|
7769
|
+
this.checkoutService = checkoutService;
|
|
7770
|
+
this.renderer = renderer;
|
|
7771
|
+
this.elementRef = elementRef;
|
|
7772
|
+
this.document = document;
|
|
7773
|
+
this.platformId = platformId;
|
|
7774
|
+
this.hideHeaderFooter();
|
|
7775
|
+
this.ecOnConstruct();
|
|
7776
|
+
}
|
|
7777
|
+
ngOnInit() {
|
|
7778
|
+
if (isPlatformBrowser(this.platformId) && 'BroadcastChannel' in window) {
|
|
7779
|
+
this.bc = new BroadcastChannel('mp_payment');
|
|
7780
|
+
}
|
|
7781
|
+
this.subscription = combineLatest([this.activedRoute.params, this.activedRoute.queryParams])
|
|
7782
|
+
.subscribe(([routeParams, q]) => {
|
|
7783
|
+
let stateStr = routeParams['state'];
|
|
7784
|
+
if (stateStr === 'statuspayment')
|
|
7785
|
+
stateStr = q['status'];
|
|
7786
|
+
const statusParam = (stateStr || q['status'] || q['state'] || '').toString();
|
|
7787
|
+
const state = this.normalizeState(statusParam);
|
|
7788
|
+
this.sid = (q['sid'] || (isPlatformBrowser(this.platformId) ? localStorage.getItem('mp:sid') : '') || '').toString();
|
|
7789
|
+
this.storeTotalAmount(q);
|
|
7790
|
+
this.setStateInLocal('Su pago fue procesado con éxito.', state);
|
|
7791
|
+
this.signalState(state);
|
|
7792
|
+
this.tryCloseSelf(() => {
|
|
7793
|
+
const target = (state === 'success' || state === 'pending')
|
|
7794
|
+
? ['/checkout/order_success']
|
|
7795
|
+
: ['/checkout'];
|
|
7796
|
+
setTimeout(() => this.router.navigate(target), 4500);
|
|
7797
|
+
});
|
|
7798
|
+
});
|
|
7799
|
+
this.ecOnInit();
|
|
7800
|
+
}
|
|
7801
|
+
ngOnDestroy() {
|
|
7802
|
+
this.subscription?.unsubscribe();
|
|
7803
|
+
this.bc?.close();
|
|
7804
|
+
this.showHeaderFooter();
|
|
7805
|
+
}
|
|
7806
|
+
/** Guarda total_amount si viene desde el PSP. */
|
|
7807
|
+
storeTotalAmount(queryParams) {
|
|
7808
|
+
const totalAmount = queryParams['total_amount'];
|
|
7809
|
+
if (totalAmount && isPlatformBrowser(this.platformId)) {
|
|
7810
|
+
localStorage.setItem('total_amount', totalAmount);
|
|
7811
|
+
}
|
|
7812
|
+
}
|
|
7813
|
+
/** Setea mensaje y estado en storages. */
|
|
7814
|
+
setStateInLocal = (mensaje, state) => {
|
|
7815
|
+
this.message = mensaje;
|
|
7816
|
+
if (!isPlatformBrowser(this.platformId))
|
|
7817
|
+
return;
|
|
7818
|
+
try {
|
|
7819
|
+
localStorage.setItem('state', state);
|
|
7820
|
+
}
|
|
7821
|
+
catch { }
|
|
7822
|
+
try {
|
|
7823
|
+
sessionStorage.setItem('modalnews', 'false');
|
|
7824
|
+
}
|
|
7825
|
+
catch { }
|
|
7826
|
+
};
|
|
7827
|
+
/** Normaliza estados heterogéneos de distintos gateways. */
|
|
7828
|
+
normalizeState(raw) {
|
|
7829
|
+
const v = (raw || '').toLowerCase();
|
|
7830
|
+
if (v === '200' || v === 'ok' || v === 'success')
|
|
7831
|
+
return 'success';
|
|
7832
|
+
if (v === 'pending')
|
|
7833
|
+
return 'pending';
|
|
7834
|
+
if (v === 'cancel')
|
|
7835
|
+
return 'cancel';
|
|
7836
|
+
return 'failure'; // failure, 0, error, rejected, chargeback, desconocidos
|
|
7837
|
+
}
|
|
7838
|
+
/**
|
|
7839
|
+
* Informa el resultado: postMessage al opener, BroadcastChannel y localStorage
|
|
7840
|
+
* (este último permite polling en la pestaña madre).
|
|
7841
|
+
*/
|
|
7842
|
+
signalState(state) {
|
|
7843
|
+
if (!isPlatformBrowser(this.platformId))
|
|
7844
|
+
return;
|
|
7845
|
+
const sid = this.sid || localStorage.getItem('mp:sid') || '';
|
|
7846
|
+
const payload = { type: 'mp:state', sid, state };
|
|
7847
|
+
try {
|
|
7848
|
+
window.opener && window.opener.postMessage(payload, '*');
|
|
7849
|
+
}
|
|
7850
|
+
catch { }
|
|
7851
|
+
try {
|
|
7852
|
+
this.bc?.postMessage(payload);
|
|
7853
|
+
}
|
|
7854
|
+
catch { }
|
|
7855
|
+
try {
|
|
7856
|
+
localStorage.setItem(`mp:state:${sid}`, state);
|
|
7857
|
+
}
|
|
7858
|
+
catch { }
|
|
7859
|
+
try {
|
|
7860
|
+
localStorage.setItem('state', state);
|
|
7861
|
+
}
|
|
7862
|
+
catch { }
|
|
7863
|
+
}
|
|
7864
|
+
/** Intenta cerrar la pestaña actual; si falla, ejecuta el callback de fallback. */
|
|
7865
|
+
tryCloseSelf(onFail) {
|
|
7866
|
+
if (!isPlatformBrowser(this.platformId))
|
|
7867
|
+
return onFail();
|
|
7868
|
+
let attempted = false;
|
|
7869
|
+
try {
|
|
7870
|
+
window.close();
|
|
7871
|
+
attempted = true;
|
|
7872
|
+
}
|
|
7873
|
+
catch { }
|
|
7874
|
+
if (!attempted)
|
|
7875
|
+
onFail();
|
|
7876
|
+
}
|
|
7877
|
+
/** Oculta header/footer para esta pantalla mínima. */
|
|
7878
|
+
hideHeaderFooter() {
|
|
7879
|
+
if (!isPlatformBrowser(this.platformId) || !this.document)
|
|
7880
|
+
return;
|
|
7881
|
+
const header = this.document.querySelector('header');
|
|
7882
|
+
const footer = this.document.querySelector('footer');
|
|
7883
|
+
if (header)
|
|
7884
|
+
this.renderer.setStyle(header, 'display', 'none');
|
|
7885
|
+
if (footer)
|
|
7886
|
+
this.renderer.setStyle(footer, 'display', 'none');
|
|
7887
|
+
}
|
|
7888
|
+
/** Restaura header/footer al salir. */
|
|
7889
|
+
showHeaderFooter() {
|
|
7890
|
+
if (!isPlatformBrowser(this.platformId) || !this.document)
|
|
7891
|
+
return;
|
|
7892
|
+
const header = this.document.querySelector('header');
|
|
7893
|
+
const footer = this.document.querySelector('footer');
|
|
7894
|
+
if (header)
|
|
7895
|
+
this.renderer.removeStyle(header, 'display');
|
|
7896
|
+
if (footer)
|
|
7897
|
+
this.renderer.removeStyle(footer, 'display');
|
|
7898
|
+
}
|
|
7899
|
+
setStateInSession(mensaje, state) {
|
|
7900
|
+
this.message = mensaje;
|
|
7901
|
+
if (!isPlatformBrowser(this.platformId))
|
|
7902
|
+
return;
|
|
7903
|
+
try {
|
|
7904
|
+
sessionStorage.setItem('state', state);
|
|
7905
|
+
}
|
|
7906
|
+
catch { }
|
|
7907
|
+
try {
|
|
7908
|
+
localStorage.setItem('state', state);
|
|
7909
|
+
}
|
|
7910
|
+
catch { }
|
|
7911
|
+
try {
|
|
7912
|
+
sessionStorage.setItem('modalnews', 'false');
|
|
7913
|
+
}
|
|
7914
|
+
catch { }
|
|
7915
|
+
}
|
|
7916
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedsysCatchEcComponent, deps: [{ token: i2.ActivatedRoute }, { token: i2.Router }, { token: CheckoutService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: DOCUMENT }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
7917
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: RedsysCatchEcComponent, isStandalone: true, selector: "app-redsys-catch-ec", usesInheritance: true, ngImport: i0, template: "<div id=\"container\">\r\n <div class=\"row\">\r\n <div class=\"col align-self-center\">\r\n <h4 class=\"titpage center-block text-center font-nexa font-lg my-3\">{{ message | uppercase }}</h4>\r\n </div>\r\n </div>\r\n <div class=\"row\">\r\n <div class=\"col align-self-center\">\r\n <h5 class=\"center-block text-center font-nexa my-3\">Redirigiendo en segundos...</h5>\r\n <br>\r\n <div class=\"d-flex flex-column jusitfy-content-center align-items-center\">\r\n <app-loading-full-ec></app-loading-full-ec>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".loader{border:16px solid #f3f3f3;border-top:16px solid #dc3545;border-radius:50%;width:50px;height:50px;animation:spin 2s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.flex-container{display:flex;justify-content:center;align-items:center;height:80vh;width:100%}.flex-container>div{width:90%;height:100px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "component", type: LoadingFullEcComponent, selector: "app-loading-full-ec" }] });
|
|
7918
|
+
}
|
|
7919
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedsysCatchEcComponent, decorators: [{
|
|
7920
|
+
type: Component,
|
|
7921
|
+
args: [{ selector: 'app-redsys-catch-ec', standalone: true, imports: [CommonModule, LoadingFullEcComponent], template: "<div id=\"container\">\r\n <div class=\"row\">\r\n <div class=\"col align-self-center\">\r\n <h4 class=\"titpage center-block text-center font-nexa font-lg my-3\">{{ message | uppercase }}</h4>\r\n </div>\r\n </div>\r\n <div class=\"row\">\r\n <div class=\"col align-self-center\">\r\n <h5 class=\"center-block text-center font-nexa my-3\">Redirigiendo en segundos...</h5>\r\n <br>\r\n <div class=\"d-flex flex-column jusitfy-content-center align-items-center\">\r\n <app-loading-full-ec></app-loading-full-ec>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".loader{border:16px solid #f3f3f3;border-top:16px solid #dc3545;border-radius:50%;width:50px;height:50px;animation:spin 2s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.flex-container{display:flex;justify-content:center;align-items:center;height:80vh;width:100%}.flex-container>div{width:90%;height:100px}\n"] }]
|
|
7922
|
+
}], ctorParameters: () => [{ type: i2.ActivatedRoute }, { type: i2.Router }, { type: CheckoutService }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: Document, decorators: [{
|
|
7923
|
+
type: Inject,
|
|
7924
|
+
args: [DOCUMENT]
|
|
7925
|
+
}] }, { type: undefined, decorators: [{
|
|
7926
|
+
type: Inject,
|
|
7927
|
+
args: [PLATFORM_ID]
|
|
7928
|
+
}] }] });
|
|
7929
|
+
|
|
7592
7930
|
// export * from './rating-ec/rating-ec.component';
|
|
7593
7931
|
|
|
7594
7932
|
class BlockFormContactEcComponent extends BlockEcComponent {
|
|
@@ -7864,6 +8202,7 @@ class LoginFormEcComponent {
|
|
|
7864
8202
|
_formBuilder = inject(FormBuilder);
|
|
7865
8203
|
_toastService = inject(ToastService);
|
|
7866
8204
|
_router = inject(Router);
|
|
8205
|
+
showPassword = false;
|
|
7867
8206
|
/**
|
|
7868
8207
|
* Parametro para indicar si tras loguear
|
|
7869
8208
|
* debe redireccionar o no.
|
|
@@ -7952,6 +8291,9 @@ class LoginFormEcComponent {
|
|
|
7952
8291
|
? resolverFunction()
|
|
7953
8292
|
: this._router.navigateByUrl(this.redirectTo);
|
|
7954
8293
|
}
|
|
8294
|
+
togglePassword() {
|
|
8295
|
+
this.showPassword = !this.showPassword;
|
|
8296
|
+
}
|
|
7955
8297
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LoginFormEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7956
8298
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LoginFormEcComponent, isStandalone: true, selector: "app-login-form-ec", inputs: { redirect: "redirect", redirectTo: "redirectTo", inCart: "inCart" }, outputs: { ready: "ready" }, ngImport: i0, template: "<div class=\"d-flex flex-column position-relative\">\r\n <h1 class=\"right-line ff-ubuntu-light mb-4\"><span>Ingresar</span></h1>\r\n <p class=\"ff-ubuntu-light font-sm pr-4 mb-4\">\r\n Si ya est\u00E1s registrado. Ingresa en tu cuenta con tu email y la\r\n contrase\u00F1a adecuada.\r\n </p>\r\n <div class=\"w-md-50 w-100 text-center\">\r\n <form [formGroup]=\"loginForm()\" (submit)=\"login($event)\">\r\n <input class=\"form-control mb-4 radius-0\" type=\"email\" formControlName=\"username\"\r\n placeholder=\"Correo Electr\u00F3nico\">\r\n <input class=\"form-control mb-4 radius-0\" type=\"password\" formControlName=\"password\"\r\n placeholder=\"Contrase\u00F1a\">\r\n\r\n <div class=\"row d-flex flex-column\">\r\n <div class=\"col-12 mb-4\">\r\n <button type=\"submit\"\r\n class=\"bg-gray border-0 px-4 py-2 color-white ff-ubuntu-light\">INGRESAR</button>\r\n </div>\r\n <div class=\"col-12 d-flex justify-content-center align-items-center\">\r\n <a [routerLink]=\"'/auth/forgot-password'\" class=\"font-md ff-ubuntu-light\">\r\n \u00BFOlvid\u00F3 su contrase\u00F1a?\r\n </a>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n @if(loading){\r\n <app-loading-section-ec></app-loading-section-ec>\r\n }\r\n</div>", styles: [""], dependencies: [{ kind: "component", type: LoadingSectionEcComponent, selector: "app-loading-section-ec" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
|
|
7957
8299
|
}
|
|
@@ -8051,6 +8393,7 @@ class RegisterFormEcComponent {
|
|
|
8051
8393
|
_analyticsService = inject(AnalyticsService);
|
|
8052
8394
|
_formBuilder = inject(FormBuilder);
|
|
8053
8395
|
channelConfigService = inject(ChannelService);
|
|
8396
|
+
showPassword = false;
|
|
8054
8397
|
/**
|
|
8055
8398
|
* Indica si debe redireccionar o se queda en la misma pantalla
|
|
8056
8399
|
*/
|
|
@@ -8166,6 +8509,9 @@ class RegisterFormEcComponent {
|
|
|
8166
8509
|
this.register_loading = false;
|
|
8167
8510
|
}
|
|
8168
8511
|
}
|
|
8512
|
+
togglePassword() {
|
|
8513
|
+
this.showPassword = !this.showPassword;
|
|
8514
|
+
}
|
|
8169
8515
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RegisterFormEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8170
8516
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: RegisterFormEcComponent, isStandalone: true, selector: "app-register-form-ec", inputs: { redirect: "redirect" }, outputs: { ready: "ready" }, ngImport: i0, template: "<div class=\"w-100 pl-md-5 position-relative\" id=\"register\">\r\n <div class=\"py-2\">\r\n <h5>CREAR CUENTA</h5>\r\n </div>\r\n <form id=\"registro\" [formGroup]=\"registerForm\" (submit)=\"register($event)\">\r\n <div class=\"form-group\">\r\n <label for=\"\" class=\"form-label\">NOMBRE</label>\r\n <input formControlName=\"firstName\" class=\"form-control rounded-0\" type=\"text\" placeholder=\"Nombre\">\r\n </div>\r\n <div class=\"form-group\">\r\n <label for=\"\" class=\"form-label\">APELLIDO</label>\r\n <input formControlName=\"lastName\" class=\"form-control rounded-0\" type=\"text\" placeholder=\"Apellido\">\r\n </div>\r\n <div class=\"form-group\">\r\n <label for=\"\" class=\"\">CORREO ELECTRONICO</label>\r\n <input formControlName=\"email\" email required class=\"form-control rounded-0\" type=\"email\"\r\n placeholder=\"Correo electr\u00F3nico\">\r\n </div>\r\n <div class=\"form-group\">\r\n <label for=\"\" class=\"form-label\">CONTRASE\u00D1A</label>\r\n <input formControlName=\"plainPassword\" required class=\"form-control rounded-0\" type=\"password\"\r\n placeholder=\"Contrase\u00F1a\">\r\n </div>\r\n <div class=\"form-group\">\r\n <label for=\"\" class=\"form-label\">REPETIR CONTRASE\u00D1A</label>\r\n <input formControlName=\"plainPassword2\" required class=\"form-control rounded-0\" type=\"password\"\r\n placeholder=\"Repetir contrase\u00F1a\">\r\n </div>\r\n\r\n <div class=\"custom-control d-flex flex-row form-check custom-checkbox mr-sm-2 mt-4 mb-2\">\r\n <input type=\"checkbox\" formControlName=\"terms\" required class=\"custom-control-input form-check-input\" name=\"Color2\"\r\n id=\"Color2\">\r\n <label class=\"custom-control-label ff-ubuntu-light font-sm form-check-label\" for=\"Color2\"> He\r\n le\u00EDdo y acepto las pol\u00EDticas de privacidad y los t\u00E9rminos y\r\n condiciones</label>\r\n </div>\r\n\r\n <div class=\"custom-control d-flex flex-row form-check custom-checkbox mr-sm-2 mb-4\">\r\n <input type=\"checkbox\" formControlName=\"newsletter\" class=\"custom-control-input form-check-input\" name=\"Color3\" id=\"Color3\">\r\n <label class=\"custom-control-label form-check-label ff-ubuntu-light font-sm\" for=\"Color3\">\r\n Suscripci\u00F3n al Newsletter</label>\r\n </div>\r\n\r\n <div class=\"row\">\r\n <div class=\"col-12\">\r\n <button [disabled]=\"registerForm.invalid\" type=\"submit\"\r\n class=\"btn btn-primary px-5 py-2 h-fit\">CREAR</button>\r\n </div>\r\n </div>\r\n </form>\r\n @if(loading){\r\n <app-loading-section-ec />\r\n }\r\n \r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.CheckboxRequiredValidator, selector: "input[type=checkbox][required][formControlName],input[type=checkbox][required][formControl],input[type=checkbox][required][ngModel]" }, { kind: "directive", type: i1$3.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: LoadingSectionEcComponent, selector: "app-loading-section-ec" }] });
|
|
8171
8517
|
}
|
|
@@ -8320,29 +8666,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
8320
8666
|
type: Output
|
|
8321
8667
|
}] } });
|
|
8322
8668
|
|
|
8323
|
-
class ComponentHelper {
|
|
8324
|
-
constructor() {
|
|
8325
|
-
this.ecOnConstruct();
|
|
8326
|
-
}
|
|
8327
|
-
ecOnInit = (params = {}) => {
|
|
8328
|
-
};
|
|
8329
|
-
ecOnConstruct = (params = {}) => {
|
|
8330
|
-
};
|
|
8331
|
-
hasParams = (params, searched) => {
|
|
8332
|
-
if (!params || !searched)
|
|
8333
|
-
return false;
|
|
8334
|
-
const q = searched.trim().toLowerCase();
|
|
8335
|
-
return params.some(p => {
|
|
8336
|
-
const code = p?.['code']?.toString().toLowerCase() ?? '';
|
|
8337
|
-
// Primero chequeo exacto, y si no, parcial
|
|
8338
|
-
return code === q || code.includes(q);
|
|
8339
|
-
});
|
|
8340
|
-
};
|
|
8341
|
-
navigateOnRouter(router, url) {
|
|
8342
|
-
router.navigateByUrl(`/${url}`);
|
|
8343
|
-
}
|
|
8344
|
-
}
|
|
8345
|
-
|
|
8346
8669
|
class PasswordResetEcComponent extends ComponentHelper {
|
|
8347
8670
|
authService;
|
|
8348
8671
|
toastr;
|
|
@@ -8484,6 +8807,8 @@ class FiltersEcComponent {
|
|
|
8484
8807
|
console.error('Filter or selected element is undefined:', { filter, selected });
|
|
8485
8808
|
return;
|
|
8486
8809
|
}
|
|
8810
|
+
if (selected.isVisible !== true)
|
|
8811
|
+
return;
|
|
8487
8812
|
if (typeof filter.setSelected !== 'function') {
|
|
8488
8813
|
console.error('filter.setSelected is not a function. Filter might not be an instance of the expected class:', filter);
|
|
8489
8814
|
return;
|
|
@@ -8553,13 +8878,36 @@ class FiltersEcComponent {
|
|
|
8553
8878
|
}) ?? false;
|
|
8554
8879
|
}
|
|
8555
8880
|
/**
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8881
|
+
* Verifica si una categoría tiene la propiedad isVisible y está marcada como visible
|
|
8882
|
+
* @param category - La categoría a verificar
|
|
8883
|
+
* @returns true si la categoría es visible, false en caso contrario
|
|
8884
|
+
*/
|
|
8560
8885
|
hasVisibleProperty(category) {
|
|
8561
8886
|
return category.isVisible === true;
|
|
8562
8887
|
}
|
|
8888
|
+
/** Lista visible (filtra recursivo por isVisible) */
|
|
8889
|
+
getVisibleData(filter) {
|
|
8890
|
+
if (!filter)
|
|
8891
|
+
return [];
|
|
8892
|
+
return this.filterVisibleTree(filter.data);
|
|
8893
|
+
}
|
|
8894
|
+
/** Children visibles de un nodo */
|
|
8895
|
+
getVisibleChildren(node) {
|
|
8896
|
+
return this.filterVisibleTree(node?.children ?? []);
|
|
8897
|
+
}
|
|
8898
|
+
/** Tiene hijos visibles? */
|
|
8899
|
+
hasVisibleChildren(node) {
|
|
8900
|
+
return this.getVisibleChildren(node).length > 0;
|
|
8901
|
+
}
|
|
8902
|
+
/** Utilidad recursiva */
|
|
8903
|
+
filterVisibleTree(list = []) {
|
|
8904
|
+
return (list ?? [])
|
|
8905
|
+
.filter(n => n.isVisible === true)
|
|
8906
|
+
.map(n => ({
|
|
8907
|
+
...n,
|
|
8908
|
+
children: this.filterVisibleTree(n.children ?? [])
|
|
8909
|
+
}));
|
|
8910
|
+
}
|
|
8563
8911
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FiltersEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8564
8912
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: FiltersEcComponent, isStandalone: true, selector: "lib-filters-ec", inputs: { setSelect: "setSelect" }, ngImport: i0, template: "<p>filters-ec works!</p>\r\n", styles: [""] });
|
|
8565
8913
|
}
|
|
@@ -8711,9 +9059,8 @@ class ProductDetailEcComponent {
|
|
|
8711
9059
|
this._meta.updateTag({ property: 'og:type', content: 'product' });
|
|
8712
9060
|
}
|
|
8713
9061
|
decodeHtml(html) {
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
return txt.value;
|
|
9062
|
+
// Usar he.decode en lugar de document para compatibilidad SSR
|
|
9063
|
+
return he.decode(html);
|
|
8717
9064
|
}
|
|
8718
9065
|
sanitizedHtml(html) {
|
|
8719
9066
|
const decodedHtml = this.decodeHtml(html);
|
|
@@ -8762,12 +9109,14 @@ class ProductDetailEcComponent {
|
|
|
8762
9109
|
}
|
|
8763
9110
|
goToSection(section) {
|
|
8764
9111
|
this.showFormContact = true;
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
element
|
|
8769
|
-
|
|
8770
|
-
|
|
9112
|
+
if (typeof document !== 'undefined') {
|
|
9113
|
+
setTimeout(() => {
|
|
9114
|
+
const element = document.getElementById(section);
|
|
9115
|
+
if (element) {
|
|
9116
|
+
element.scrollIntoView({ behavior: 'smooth' });
|
|
9117
|
+
}
|
|
9118
|
+
}, 500);
|
|
9119
|
+
}
|
|
8771
9120
|
}
|
|
8772
9121
|
resetForm = () => {
|
|
8773
9122
|
this.reset = !this.reset;
|
|
@@ -8943,6 +9292,7 @@ class CartItemEcComponent {
|
|
|
8943
9292
|
_cartService = inject(CartService);
|
|
8944
9293
|
_toastService = inject(ToastService);
|
|
8945
9294
|
_constants = inject(CoreConstantsService);
|
|
9295
|
+
parametersService = inject(ParametersService);
|
|
8946
9296
|
mediaUrl = this._constants.mediaUrl();
|
|
8947
9297
|
quantity = 0;
|
|
8948
9298
|
variantsToShow = ['TALLA', 'COLOR'];
|
|
@@ -9029,6 +9379,9 @@ class CartItemEcComponent {
|
|
|
9029
9379
|
}
|
|
9030
9380
|
return false; // Solo se ejecuta si no se cumple la condición
|
|
9031
9381
|
}
|
|
9382
|
+
// PARAMETROS
|
|
9383
|
+
parameters$ = this.parametersService.getParameters();
|
|
9384
|
+
hasParams = this.parametersService.hasParams;
|
|
9032
9385
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CartItemEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9033
9386
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CartItemEcComponent, isStandalone: true, selector: "app-cart-item-ec", inputs: { item: "item", inSidebar: "inSidebar" }, ngImport: i0, template: "@if(!inSidebar){\r\n<p>cart-item-ec works!</p>\r\n}@else{\r\n\r\n<div class=\"row\">\r\n <div class=\"col-3\">\r\n @let product= item.product;\r\n @if(item.variant_id && product.variants.length>0){\r\n <img [src]=\"mediaUrl + product.variants[0].images[0]\" alt=\"\" class=\"img-fluid\">\r\n }@else{\r\n <img [src]=\"mediaUrl + product.picturesdefault[0]\" alt=\"\" class=\"img-fluid\">\r\n }\r\n </div>\r\n <div class=\"col-7\">\r\n <div class=\"info d-flex flex-column align-items-start\">\r\n @if (item.product.special_mark?.length > 0 || item.product.saleprice) {\r\n <div class=\"marcas\">\r\n <img [src]=\"mediaUrl + (item.product.special_mark?.[0]?.images[0] || '')\" alt=\"\">\r\n\r\n @if (item.product.saleprice) {\r\n <div class=\"tag-dsc\">\r\n {{\r\n createDiscountMessage(item.product.saleprice,\r\n item.product.price)\r\n }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n <a class=\"title text-dark text-decoration-none m-0 p-0 h6 mb-0\"\r\n [routerLink]=\"['/product', item.variant_id]\">{{\r\n item.product.name | titlecase\r\n }}</a>\r\n <div class=\"qty1\">\r\n <span>{{ item.product.id}}</span>\r\n </div>\r\n <div class=\"price h6 fw-bold mb-0 pb-0\">{{ item.product.price | ecCurrencySymbol\r\n }}</div>\r\n @if(getVariants(item); as options){\r\n <div class=\"d-flex align-items-center p-0\">\r\n @for(option of options; track $index){\r\n <span class=\"me-1\"> {{option.name | titlecase}}:</span>\r\n @if(option.name == 'COLOR'){\r\n <div class=\"p-2 rounded\" [style.background]=\"'#' + option.value\"></div>\r\n }@else{\r\n <b>{{option.value}}</b>\r\n }\r\n }\r\n </div>\r\n }\r\n <div class=\"campoCantidad mt-2\">\r\n <div class=\"numero\">\r\n <button (click)=\"less(item.product.variants[0]?.stock)\" class=\"btn btn-outline-secondary\"\r\n type=\"button\" id=\"button-addon1\">\r\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\r\n </button>\r\n <input type=\"text\" class=\"form-control text-center\" placeholder=\"\"\r\n aria-label=\"Example text with button addon\" aria-describedby=\"button-addon1\"\r\n [value]=\"item.quantity\" min=\"1\" step=\"1\" [(ngModel)]=\"quantity\"\r\n (change)=\"updateQuantity(item.product.variants[0]?.stock)\">\r\n <button (click)=\"plus(item.product.variants[0]?.stock)\" class=\"btn btn-outline-secondary\"\r\n type=\"button\" id=\"button-addon1\">\r\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"col-2\">\r\n <a (click)=\"deleteCartItem()\" class=\"btn botBorrar\"><i class=\"fa fa-trash\" aria-hidden=\"true\"></i></a>\r\n </div>\r\n</div>\r\n\r\n\r\n\r\n\r\n\r\n}", styles: [""], dependencies: [{ kind: "pipe", type: TitleCasePipe, name: "titlecase" }, { kind: "pipe", type: EcCurrencySymbolPipe, name: "ecCurrencySymbol" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
9034
9387
|
}
|
|
@@ -9540,108 +9893,174 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
9540
9893
|
class MpRedirectEcComponent {
|
|
9541
9894
|
_paymentService = inject(PaymentService);
|
|
9542
9895
|
_toastService = inject(ToastService);
|
|
9896
|
+
platformId = inject(PLATFORM_ID);
|
|
9897
|
+
finished = false;
|
|
9543
9898
|
method = null;
|
|
9544
9899
|
total_amount = 0;
|
|
9545
9900
|
allData;
|
|
9546
9901
|
ready = new EventEmitter();
|
|
9547
9902
|
preference;
|
|
9548
|
-
loading = false;
|
|
9549
9903
|
url;
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9904
|
+
// Fases de UI
|
|
9905
|
+
phase = 'idle';
|
|
9906
|
+
get isIdle() { return this.phase === 'idle'; }
|
|
9907
|
+
get isPaying() { return this.phase === 'paying'; }
|
|
9908
|
+
get isFinalizing() { return this.phase === 'finalizing'; }
|
|
9909
|
+
ventana = null;
|
|
9910
|
+
windowRef;
|
|
9911
|
+
sid = '';
|
|
9912
|
+
bc;
|
|
9913
|
+
pollTimer;
|
|
9914
|
+
pollStartedAt = 0;
|
|
9915
|
+
ngOnInit() {
|
|
9556
9916
|
if (isPlatformBrowser(this.platformId)) {
|
|
9557
|
-
this.
|
|
9558
|
-
|
|
9917
|
+
this.windowRef = window;
|
|
9918
|
+
if ('BroadcastChannel' in window) {
|
|
9919
|
+
this.bc = new BroadcastChannel('mp_payment');
|
|
9920
|
+
this.bc.onmessage = (e) => this.onMpMessage(e?.data);
|
|
9921
|
+
}
|
|
9922
|
+
window.addEventListener('storage', this.onStorage);
|
|
9923
|
+
window.addEventListener('message', this.onWindowMessage);
|
|
9559
9924
|
}
|
|
9560
|
-
}
|
|
9561
|
-
ngOnInit() {
|
|
9562
9925
|
this.getPreference();
|
|
9563
9926
|
}
|
|
9927
|
+
ngOnDestroy() {
|
|
9928
|
+
if (!isPlatformBrowser(this.platformId))
|
|
9929
|
+
return;
|
|
9930
|
+
this.bc?.close();
|
|
9931
|
+
window.removeEventListener('storage', this.onStorage);
|
|
9932
|
+
window.removeEventListener('message', this.onWindowMessage);
|
|
9933
|
+
if (this.pollTimer)
|
|
9934
|
+
clearInterval(this.pollTimer);
|
|
9935
|
+
}
|
|
9936
|
+
/** Cancela manualmente el pago y finaliza el flujo con estado "cancel". */
|
|
9564
9937
|
clickClose = () => {
|
|
9565
|
-
|
|
9566
|
-
|
|
9938
|
+
if (this.finished)
|
|
9939
|
+
return;
|
|
9940
|
+
this.finishWithState('cancel');
|
|
9567
9941
|
};
|
|
9942
|
+
/**
|
|
9943
|
+
* Inicia el pago abriendo `init_point` en una ventana/pestaña nueva.
|
|
9944
|
+
* Genera un SID y lo persiste para casar la respuesta del catch.
|
|
9945
|
+
* Si el popup es bloqueado, hace fallback navegando en la misma pestaña.
|
|
9946
|
+
*/
|
|
9568
9947
|
iniciar = () => {
|
|
9569
|
-
this.
|
|
9570
|
-
|
|
9571
|
-
this.
|
|
9572
|
-
this.
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
this.
|
|
9578
|
-
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
this.
|
|
9589
|
-
this.
|
|
9590
|
-
|
|
9591
|
-
}
|
|
9592
|
-
if (state == 'failure') {
|
|
9593
|
-
this.ventana?.close();
|
|
9594
|
-
this.processError('');
|
|
9595
|
-
return;
|
|
9596
|
-
}
|
|
9597
|
-
if (state == 'cancel') {
|
|
9598
|
-
this.ventana?.close();
|
|
9599
|
-
this.processError('Se cancelo el pago con mercado pago');
|
|
9948
|
+
if (!isPlatformBrowser(this.platformId) || !this.windowRef || !this.url)
|
|
9949
|
+
return;
|
|
9950
|
+
this.phase = 'paying';
|
|
9951
|
+
this.sid = this.genSid();
|
|
9952
|
+
const url = new URL(this.url);
|
|
9953
|
+
localStorage.setItem('mp:sid', this.sid);
|
|
9954
|
+
this.ventana = this.windowRef.open(this.url, '_blank');
|
|
9955
|
+
// popup bloqueado → fallback a navegación en misma pestaña
|
|
9956
|
+
if (!this.ventana || this.ventana.closed) {
|
|
9957
|
+
this.windowRef.location.href = this.url;
|
|
9958
|
+
return;
|
|
9959
|
+
}
|
|
9960
|
+
// polling de último recurso (hasta 10 minutos)
|
|
9961
|
+
this.pollStartedAt = Date.now();
|
|
9962
|
+
if (this.pollTimer)
|
|
9963
|
+
clearInterval(this.pollTimer);
|
|
9964
|
+
this.pollTimer = setInterval(() => {
|
|
9965
|
+
if (Date.now() - this.pollStartedAt > 10 * 60 * 1000) {
|
|
9966
|
+
clearInterval(this.pollTimer);
|
|
9967
|
+
this.pollTimer = null;
|
|
9968
|
+
this.phase = 'idle';
|
|
9969
|
+
this.processError('Tiempo de espera agotado al procesar el pago.');
|
|
9600
9970
|
return;
|
|
9601
9971
|
}
|
|
9602
|
-
this.
|
|
9603
|
-
|
|
9972
|
+
this.checkLocalStorageOnce();
|
|
9973
|
+
}, 1000);
|
|
9974
|
+
};
|
|
9975
|
+
onWindowMessage = (event) => {
|
|
9976
|
+
const data = event?.data;
|
|
9977
|
+
this.onMpMessage(data);
|
|
9978
|
+
};
|
|
9979
|
+
onStorage = (e) => {
|
|
9980
|
+
if (!e.key || !this.sid)
|
|
9604
9981
|
return;
|
|
9982
|
+
if (e.key === `mp:state:${this.sid}` && e.newValue) {
|
|
9983
|
+
const state = e.newValue;
|
|
9984
|
+
this.finishWithState(state);
|
|
9605
9985
|
}
|
|
9606
|
-
setTimeout(() => {
|
|
9607
|
-
this.callState();
|
|
9608
|
-
}, 5000);
|
|
9609
9986
|
};
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9987
|
+
onMpMessage = (data) => {
|
|
9988
|
+
if (!data || data.type !== 'mp:state')
|
|
9989
|
+
return;
|
|
9990
|
+
if (data.sid !== this.sid)
|
|
9991
|
+
return;
|
|
9992
|
+
this.finishWithState(data.state);
|
|
9993
|
+
};
|
|
9994
|
+
checkLocalStorageOnce() {
|
|
9995
|
+
if (!this.sid)
|
|
9996
|
+
return;
|
|
9997
|
+
const state = localStorage.getItem(`mp:state:${this.sid}`);
|
|
9998
|
+
if (state)
|
|
9999
|
+
this.finishWithState(state);
|
|
10000
|
+
}
|
|
10001
|
+
/** Cierra el flujo de pago con el estado final y notifica al padre. */
|
|
10002
|
+
finishWithState(state) {
|
|
10003
|
+
if (this.finished)
|
|
10004
|
+
return;
|
|
10005
|
+
this.finished = true;
|
|
10006
|
+
if (this.pollTimer)
|
|
10007
|
+
clearInterval(this.pollTimer);
|
|
10008
|
+
this.pollTimer = null;
|
|
10009
|
+
localStorage.removeItem(`mp:state:${this.sid}`);
|
|
10010
|
+
localStorage.removeItem('mp:sid');
|
|
10011
|
+
localStorage.removeItem('state');
|
|
10012
|
+
try {
|
|
10013
|
+
this.ventana && !this.ventana.closed && this.ventana.close();
|
|
10014
|
+
}
|
|
10015
|
+
catch { }
|
|
10016
|
+
this.ventana = null;
|
|
10017
|
+
if (state === 'success' || state === 'pending') {
|
|
10018
|
+
this.phase = 'finalizing';
|
|
10019
|
+
this.ready.emit(true);
|
|
10020
|
+
}
|
|
10021
|
+
else if (state === 'failure' || state === 'cancel') {
|
|
10022
|
+
this.phase = 'idle';
|
|
10023
|
+
this._toastService.show(state === 'cancel' ? 'Se canceló el pago con Mercado Pago' : 'payment-error');
|
|
10024
|
+
}
|
|
10025
|
+
else {
|
|
10026
|
+
this.phase = 'idle';
|
|
10027
|
+
this._toastService.show('payment-error');
|
|
10028
|
+
}
|
|
10029
|
+
}
|
|
10030
|
+
genSid() {
|
|
10031
|
+
return `mp_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
10032
|
+
}
|
|
10033
|
+
processError = (msg) => {
|
|
10034
|
+
this._toastService.show(msg || 'payment-error');
|
|
9613
10035
|
};
|
|
10036
|
+
/** Limpia posibles residuos de estado en storages. */
|
|
9614
10037
|
clearStorageState = () => {
|
|
9615
|
-
|
|
9616
|
-
|
|
10038
|
+
if (!isPlatformBrowser(this.platformId))
|
|
10039
|
+
return;
|
|
10040
|
+
localStorage.removeItem('state');
|
|
10041
|
+
const sid = localStorage.getItem('mp:sid');
|
|
10042
|
+
if (sid)
|
|
10043
|
+
localStorage.removeItem(`mp:state:${sid}`);
|
|
10044
|
+
};
|
|
10045
|
+
/** Obtiene la preferencia e inicializa `url` (init_point). */
|
|
10046
|
+
getPreference = () => {
|
|
10047
|
+
this._paymentService.getPreference(this.allData).then((res) => {
|
|
10048
|
+
this.preference = res;
|
|
10049
|
+
this.url = this.preference?.init_point;
|
|
10050
|
+
this.renderMP(this.preference);
|
|
10051
|
+
}, () => this.setError('operation-error'));
|
|
9617
10052
|
};
|
|
9618
|
-
getPreference = () => this._paymentService.getPreference(this.allData).then(res => {
|
|
9619
|
-
this.preference = res;
|
|
9620
|
-
this.url = this.preference.init_point;
|
|
9621
|
-
this.renderMP(this.preference);
|
|
9622
|
-
}, err => this.setError('operation-error'));
|
|
9623
10053
|
setError = (message) => {
|
|
9624
10054
|
//this.error = message;
|
|
9625
10055
|
};
|
|
9626
|
-
renderMP = (
|
|
9627
|
-
this.window?.addEventListener("message", (event) => {
|
|
9628
|
-
if (event.origin !== 'https://www.mercadopago.com.ar' || !event.data.type) {
|
|
9629
|
-
return;
|
|
9630
|
-
}
|
|
9631
|
-
let dataType = event.data.type;
|
|
9632
|
-
if (dataType === 'submit') {
|
|
9633
|
-
const paymentData = event.data.value;
|
|
9634
|
-
return;
|
|
9635
|
-
}
|
|
9636
|
-
});
|
|
9637
|
-
};
|
|
10056
|
+
renderMP = (_pref) => { };
|
|
9638
10057
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MpRedirectEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9639
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: MpRedirectEcComponent, isStandalone: true, selector: "app-mp-redirect-ec", inputs: { method: "method", total_amount: "total_amount", allData: "allData" }, outputs: { ready: "ready" }, ngImport: i0, template: "<div class=\"text-center\">\r\n\t@if(url){\r\n\
|
|
10058
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: MpRedirectEcComponent, isStandalone: true, selector: "app-mp-redirect-ec", inputs: { method: "method", total_amount: "total_amount", allData: "allData" }, outputs: { ready: "ready" }, ngImport: i0, template: "<div class=\"text-center\">\r\n\t@if(url) {\r\n\r\n\t@if(isIdle) {\r\n\t<button (click)=\"iniciar()\" class=\"btn btn-outline-primary rounded-0 comprar mt-3\">Pagar</button>\r\n\t}\r\n\r\n\t@if(isPaying) {\r\n\t<div class=\"d-flex flex-column jusitfy-content-center align-items-center mt-2\">\r\n\t\t<h3>Procesando el pago por Mercado Pago</h3>\r\n\t\t<h5>Record\u00E1 tocar \u201CVolver al sitio\u201D en Mercado Pago para finalizar.</h5>\r\n\t\t<app-loading-full-ec></app-loading-full-ec>\r\n\t</div>\r\n\r\n\t<div class=\"container-fluid\">\r\n\t\t<div class=\"row\">\r\n\t\t\t<div class=\"col-5\">\r\n\t\t\t\t<hr>\r\n\t\t\t</div>\r\n\t\t\t<div class=\"col-2 text-center\"><label>o</label></div>\r\n\t\t\t<div class=\"col-5\">\r\n\t\t\t\t<hr>\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t</div>\r\n\r\n\t<div class=\"d-flex flex-column justify-content-center align-items-center mt-2\">\r\n\t\t<button (click)=\"clickClose()\" class=\"btn btn-outline-secondary\">Cancelar pago</button>\r\n\t</div>\r\n\t}\r\n\r\n\t@if(isFinalizing) {\r\n\t<div class=\"d-flex flex-column jusitfy-content-center align-items-center mt-2\">\r\n\t\t<h3>Confirmando pago y redirigiendo\u2026</h3>\r\n\t\t<h5>No cierres ni recargues esta p\u00E1gina.</h5>\r\n\t\t<app-loading-full-ec></app-loading-full-ec>\r\n\t</div>\r\n\t}\r\n\r\n\t} @else {\r\n\t<div class=\"d-flex flex-column justify-content-center align-items-center mt-2\">\r\n\t\t<app-loading-full-ec></app-loading-full-ec>\r\n\t</div>\r\n\t}\r\n</div>", styles: [""], dependencies: [{ kind: "component", type: LoadingFullEcComponent, selector: "app-loading-full-ec" }] });
|
|
9640
10059
|
}
|
|
9641
10060
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MpRedirectEcComponent, decorators: [{
|
|
9642
10061
|
type: Component,
|
|
9643
|
-
args: [{ selector: 'app-mp-redirect-ec', standalone: true, imports: [LoadingFullEcComponent], template: "<div class=\"text-center\">\r\n\t@if(url){\r\n\
|
|
9644
|
-
}],
|
|
10062
|
+
args: [{ selector: 'app-mp-redirect-ec', standalone: true, imports: [LoadingFullEcComponent], template: "<div class=\"text-center\">\r\n\t@if(url) {\r\n\r\n\t@if(isIdle) {\r\n\t<button (click)=\"iniciar()\" class=\"btn btn-outline-primary rounded-0 comprar mt-3\">Pagar</button>\r\n\t}\r\n\r\n\t@if(isPaying) {\r\n\t<div class=\"d-flex flex-column jusitfy-content-center align-items-center mt-2\">\r\n\t\t<h3>Procesando el pago por Mercado Pago</h3>\r\n\t\t<h5>Record\u00E1 tocar \u201CVolver al sitio\u201D en Mercado Pago para finalizar.</h5>\r\n\t\t<app-loading-full-ec></app-loading-full-ec>\r\n\t</div>\r\n\r\n\t<div class=\"container-fluid\">\r\n\t\t<div class=\"row\">\r\n\t\t\t<div class=\"col-5\">\r\n\t\t\t\t<hr>\r\n\t\t\t</div>\r\n\t\t\t<div class=\"col-2 text-center\"><label>o</label></div>\r\n\t\t\t<div class=\"col-5\">\r\n\t\t\t\t<hr>\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t</div>\r\n\r\n\t<div class=\"d-flex flex-column justify-content-center align-items-center mt-2\">\r\n\t\t<button (click)=\"clickClose()\" class=\"btn btn-outline-secondary\">Cancelar pago</button>\r\n\t</div>\r\n\t}\r\n\r\n\t@if(isFinalizing) {\r\n\t<div class=\"d-flex flex-column jusitfy-content-center align-items-center mt-2\">\r\n\t\t<h3>Confirmando pago y redirigiendo\u2026</h3>\r\n\t\t<h5>No cierres ni recargues esta p\u00E1gina.</h5>\r\n\t\t<app-loading-full-ec></app-loading-full-ec>\r\n\t</div>\r\n\t}\r\n\r\n\t} @else {\r\n\t<div class=\"d-flex flex-column justify-content-center align-items-center mt-2\">\r\n\t\t<app-loading-full-ec></app-loading-full-ec>\r\n\t</div>\r\n\t}\r\n</div>" }]
|
|
10063
|
+
}], propDecorators: { method: [{
|
|
9645
10064
|
type: Input
|
|
9646
10065
|
}], total_amount: [{
|
|
9647
10066
|
type: Input
|
|
@@ -9880,6 +10299,8 @@ class DecidirEcComponent extends ComponentHelper {
|
|
|
9880
10299
|
});
|
|
9881
10300
|
};
|
|
9882
10301
|
resizeIframe = (obj) => {
|
|
10302
|
+
if (typeof document === 'undefined' || !obj.contentWindow || !obj.contentWindow.document)
|
|
10303
|
+
return;
|
|
9883
10304
|
obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
|
|
9884
10305
|
obj.style.width = obj.contentWindow.document.body.scrollWidth + 'px';
|
|
9885
10306
|
};
|
|
@@ -11193,6 +11614,7 @@ class StoresEcComponent extends ComponentHelper {
|
|
|
11193
11614
|
storesService;
|
|
11194
11615
|
consts;
|
|
11195
11616
|
sanitizer;
|
|
11617
|
+
platformId;
|
|
11196
11618
|
stores = new BehaviorSubject([]);
|
|
11197
11619
|
filterStores = null;
|
|
11198
11620
|
storesAll = null;
|
|
@@ -11205,11 +11627,12 @@ class StoresEcComponent extends ComponentHelper {
|
|
|
11205
11627
|
markers = [];
|
|
11206
11628
|
locations = [];
|
|
11207
11629
|
ultimoElementoSeleccionado = null;
|
|
11208
|
-
constructor(storesService, consts, sanitizer) {
|
|
11630
|
+
constructor(storesService, consts, sanitizer, platformId) {
|
|
11209
11631
|
super();
|
|
11210
11632
|
this.storesService = storesService;
|
|
11211
11633
|
this.consts = consts;
|
|
11212
11634
|
this.sanitizer = sanitizer;
|
|
11635
|
+
this.platformId = platformId;
|
|
11213
11636
|
this.urlmap = this.sanitizer.bypassSecurityTrustResourceUrl('https://www.google.com/maps/embed?pb=!1m10!1m8!1m3!1d13137.519688957545!2d-58.3888163!3d-34.5945533!3m2!1i1024!2i768!4f13.1!5e0!3m2!1ses-419!2sar!4v1523889204148');
|
|
11214
11637
|
this.storesService.stores
|
|
11215
11638
|
.pipe(filter$1((stores) => Array.isArray(stores) && stores.length > 0))
|
|
@@ -11282,6 +11705,8 @@ class StoresEcComponent extends ComponentHelper {
|
|
|
11282
11705
|
return true;
|
|
11283
11706
|
};
|
|
11284
11707
|
initMap() {
|
|
11708
|
+
if (!isPlatformBrowser(this.platformId))
|
|
11709
|
+
return;
|
|
11285
11710
|
this.storesService.stores.pipe(skipWhile(stores => !stores || stores.length === 0) // Omitir valores vacíos
|
|
11286
11711
|
).subscribe((res) => {
|
|
11287
11712
|
// this.stores.next(res ?? []); // Eliminado para no sobrescribir el listado principal
|
|
@@ -11302,7 +11727,10 @@ class StoresEcComponent extends ComponentHelper {
|
|
|
11302
11727
|
});
|
|
11303
11728
|
const center = bounds.getCenter();
|
|
11304
11729
|
const style = [{ "elementType": "geometry", "stylers": [{ "color": "#212121" }] }, { "elementType": "labels.icon", "stylers": [{ "visibility": "off" }] }, { "elementType": "labels.text.fill", "stylers": [{ "color": "#757575" }] }, { "elementType": "labels.text.stroke", "stylers": [{ "color": "#212121" }] }, { "featureType": "administrative", "elementType": "geometry", "stylers": [{ "color": "#757575" }] }, { "featureType": "administrative.country", "elementType": "labels.text.fill", "stylers": [{ "color": "#9e9e9e" }] }, { "featureType": "administrative.locality", "elementType": "labels.text.fill", "stylers": [{ "color": "#bdbdbd" }] }, { "featureType": "poi", "elementType": "labels.text.fill", "stylers": [{ "color": "#757575" }] }, { "featureType": "poi.business", "stylers": [{ "visibility": "off" }] }, { "featureType": "poi.park", "elementType": "geometry", "stylers": [{ "color": "#181818" }] }, { "featureType": "poi.park", "elementType": "labels.text.fill", "stylers": [{ "color": "#616161" }] }, { "featureType": "poi.park", "elementType": "labels.text.stroke", "stylers": [{ "color": "#1b1b1b" }] }, { "featureType": "road", "elementType": "geometry.fill", "stylers": [{ "color": "#2c2c2c" }] }, { "featureType": "road", "elementType": "labels.icon", "stylers": [{ "visibility": "off" }] }, { "featureType": "road", "elementType": "labels.text.fill", "stylers": [{ "color": "#8a8a8a" }] }, { "featureType": "road.arterial", "elementType": "geometry", "stylers": [{ "color": "#373737" }] }, { "featureType": "road.arterial", "elementType": "labels", "stylers": [{ "visibility": "off" }] }, { "featureType": "road.highway", "elementType": "geometry", "stylers": [{ "color": "#3c3c3c" }] }, { "featureType": "road.highway", "elementType": "labels", "stylers": [{ "visibility": "off" }] }, { "featureType": "road.highway.controlled_access", "elementType": "geometry", "stylers": [{ "color": "#4e4e4e" }] }, { "featureType": "road.local", "stylers": [{ "visibility": "off" }] }, { "featureType": "road.local", "elementType": "labels.text.fill", "stylers": [{ "color": "#616161" }] }, { "featureType": "transit", "stylers": [{ "visibility": "off" }] }, { "featureType": "transit", "elementType": "labels.text.fill", "stylers": [{ "color": "#757575" }] }, { "featureType": "water", "elementType": "geometry", "stylers": [{ "color": "#000000" }] }, { "featureType": "water", "elementType": "labels.text.fill", "stylers": [{ "color": "#3d3d3d" }] }];
|
|
11305
|
-
|
|
11730
|
+
const mapElement = document.getElementById('map');
|
|
11731
|
+
if (!mapElement)
|
|
11732
|
+
return;
|
|
11733
|
+
this.map = new google.maps.Map(mapElement, {
|
|
11306
11734
|
zoom: 12,
|
|
11307
11735
|
center: center, // Centrar el mapa en el centro calculado
|
|
11308
11736
|
styles: style // Aplica los estilos personalizados
|
|
@@ -11320,6 +11748,8 @@ class StoresEcComponent extends ComponentHelper {
|
|
|
11320
11748
|
marker.set('id', location.id); // Associate marker with its ID
|
|
11321
11749
|
this.markers.push(marker);
|
|
11322
11750
|
marker.addListener('click', () => {
|
|
11751
|
+
if (typeof document === 'undefined')
|
|
11752
|
+
return;
|
|
11323
11753
|
const elemento = document.getElementById(location.id);
|
|
11324
11754
|
const contenedor = document.getElementById('home');
|
|
11325
11755
|
if (elemento && contenedor) {
|
|
@@ -11347,6 +11777,8 @@ class StoresEcComponent extends ComponentHelper {
|
|
|
11347
11777
|
});
|
|
11348
11778
|
}
|
|
11349
11779
|
showStoreOnMap(storeCode) {
|
|
11780
|
+
if (!isPlatformBrowser(this.platformId))
|
|
11781
|
+
return;
|
|
11350
11782
|
this.stopBounce();
|
|
11351
11783
|
const marker = this.markers.find(m => m.get('id') === storeCode);
|
|
11352
11784
|
const elemento = document.getElementById(storeCode);
|
|
@@ -11368,13 +11800,16 @@ class StoresEcComponent extends ComponentHelper {
|
|
|
11368
11800
|
marker.setAnimation(null);
|
|
11369
11801
|
});
|
|
11370
11802
|
}
|
|
11371
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StoresEcComponent, deps: [{ token: StoresService }, { token: CoreConstantsService }, { token: i1$4.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
|
|
11803
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StoresEcComponent, deps: [{ token: StoresService }, { token: CoreConstantsService }, { token: i1$4.DomSanitizer }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
11372
11804
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StoresEcComponent, isStandalone: true, selector: "app-store-ec", usesInheritance: true, ngImport: i0, template: "<!-- <div class=\"row w-100 mx-auto my-4 px-3 bb-s bt-md-s py-1\">\r\n <strong>{{ 'stores' | translate }}</strong>\r\n</div>\r\n@if(stores){\r\n<div class=\"row\">\r\n <div class=\"col-12 col-md-3 order-1 order-md-1\">\r\n <div class=\"row\">\r\n <div class=\"form-group w-100\">\r\n <select (change)=\"selectChange($event.target.value)\" class=\"rounded-0 form-control form-control-sm\"\r\n id=\"exampleFormControlSelect1\">\r\n <option selected [value]=\"''\">Seleccione provincia</option>\r\n <option [value]=\"item.code\" *ngFor=\"let item of getProvices(stores)\"> {{item.name}}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"col-12 col-md-3 order-3 order-md-2\">\r\n <div class=\"container-fluid scrolleable\" *ngIf=\"filterStores && filterStores.length\">\r\n <div class=\"row mb-1\" *ngFor=\"let store of filterStores; let i = index\">\r\n <div class=\"col-12\">\r\n <h6 class=\"\"><strong>{{ store.name }}</strong></h6>\r\n <label>{{ store.address }}</label>\r\n <label>{{ store.phone }}</label>\r\n <div [innerHtml]=\"store.note\"></div>\r\n <div class=\"text-right\">\r\n\r\n <a *ngIf=\"store.urlMap\" (click)=\"updateMap (store.urlMap)\" class=\"custom-a\">Ver mapa</a>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"col-12 col-md-6 order-2 order-md-3 my-4 mt-md-0\">\r\n\r\n <iframe id=\"map-iframe\" [src]=\"urlmap\" frameborder=\"0\"></iframe>\r\n </div>\r\n</div>\r\n}@else {\r\n<div class=\"d-flex flex-row justify-content-center my-5 align-items-center alto-total\">\r\n <h5 class=\"text-center\">{{ 'no-stores' | translate }}</h5>\r\n</div>\r\n}\r\n\r\n\r\n\r\n<ng-template #loading>\r\n <div class=\"container\">\r\n <div class=\"row\">\r\n <div class=\"col-12 align-items-center\">\r\n <div class=\"d-flex flex-column justify-content-center align-items-center my-5\">\r\n <app-loading-full-ec></app-loading-full-ec>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template> -->", styles: [".scrolleable{height:70vh;overflow:auto}@media screen and (max-width: 768px){.scrolleable{height:auto}}.background-white{background-color:#fff}.alto-total{height:60vh}.custom-a{color:#000}#map-iframe{width:100%;border:0;height:100%}@media screen and (max-width: 425px){#map-iframe{height:400px}}\n"], dependencies: [{ kind: "ngmodule", type: TranslateModule }] });
|
|
11373
11805
|
}
|
|
11374
11806
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StoresEcComponent, decorators: [{
|
|
11375
11807
|
type: Component,
|
|
11376
11808
|
args: [{ selector: 'app-store-ec', standalone: true, imports: [TranslateModule], template: "<!-- <div class=\"row w-100 mx-auto my-4 px-3 bb-s bt-md-s py-1\">\r\n <strong>{{ 'stores' | translate }}</strong>\r\n</div>\r\n@if(stores){\r\n<div class=\"row\">\r\n <div class=\"col-12 col-md-3 order-1 order-md-1\">\r\n <div class=\"row\">\r\n <div class=\"form-group w-100\">\r\n <select (change)=\"selectChange($event.target.value)\" class=\"rounded-0 form-control form-control-sm\"\r\n id=\"exampleFormControlSelect1\">\r\n <option selected [value]=\"''\">Seleccione provincia</option>\r\n <option [value]=\"item.code\" *ngFor=\"let item of getProvices(stores)\"> {{item.name}}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"col-12 col-md-3 order-3 order-md-2\">\r\n <div class=\"container-fluid scrolleable\" *ngIf=\"filterStores && filterStores.length\">\r\n <div class=\"row mb-1\" *ngFor=\"let store of filterStores; let i = index\">\r\n <div class=\"col-12\">\r\n <h6 class=\"\"><strong>{{ store.name }}</strong></h6>\r\n <label>{{ store.address }}</label>\r\n <label>{{ store.phone }}</label>\r\n <div [innerHtml]=\"store.note\"></div>\r\n <div class=\"text-right\">\r\n\r\n <a *ngIf=\"store.urlMap\" (click)=\"updateMap (store.urlMap)\" class=\"custom-a\">Ver mapa</a>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"col-12 col-md-6 order-2 order-md-3 my-4 mt-md-0\">\r\n\r\n <iframe id=\"map-iframe\" [src]=\"urlmap\" frameborder=\"0\"></iframe>\r\n </div>\r\n</div>\r\n}@else {\r\n<div class=\"d-flex flex-row justify-content-center my-5 align-items-center alto-total\">\r\n <h5 class=\"text-center\">{{ 'no-stores' | translate }}</h5>\r\n</div>\r\n}\r\n\r\n\r\n\r\n<ng-template #loading>\r\n <div class=\"container\">\r\n <div class=\"row\">\r\n <div class=\"col-12 align-items-center\">\r\n <div class=\"d-flex flex-column justify-content-center align-items-center my-5\">\r\n <app-loading-full-ec></app-loading-full-ec>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template> -->", styles: [".scrolleable{height:70vh;overflow:auto}@media screen and (max-width: 768px){.scrolleable{height:auto}}.background-white{background-color:#fff}.alto-total{height:60vh}.custom-a{color:#000}#map-iframe{width:100%;border:0;height:100%}@media screen and (max-width: 425px){#map-iframe{height:400px}}\n"] }]
|
|
11377
|
-
}], ctorParameters: () => [{ type: StoresService }, { type: CoreConstantsService }, { type: i1$4.DomSanitizer }
|
|
11809
|
+
}], ctorParameters: () => [{ type: StoresService }, { type: CoreConstantsService }, { type: i1$4.DomSanitizer }, { type: Object, decorators: [{
|
|
11810
|
+
type: Inject,
|
|
11811
|
+
args: [PLATFORM_ID]
|
|
11812
|
+
}] }] });
|
|
11378
11813
|
|
|
11379
11814
|
class PriceRangeFilterComponent {
|
|
11380
11815
|
_filtersService = inject(FiltersService);
|
|
@@ -11761,5 +12196,5 @@ const directives = [
|
|
|
11761
12196
|
* Generated bundle index. Do not edit.
|
|
11762
12197
|
*/
|
|
11763
12198
|
|
|
11764
|
-
export { AccountEcComponent, AddressingService, AnalyticsService, AuthEcComponent, AuthService, AuthStorageService, BlockBannerBoxEcComponent, BlockBannerFullEcComponent, BlockFormContactEcComponent, BlockHtmlEcComponent, BlockNewsletterEcComponent, BlockProductsEcComponent, BlocksEcComponent, BlocksRepositoryService, BlocksService, BreadcrumbEcComponent, CartEcComponent, CartItemEcComponent, CartService, ChannelService, CheckoutEcComponent, CheckoutService, CollectionEcComponent, ConfirmAccountEcComponent, ContactEcComponent, CoreConstantsService, CouponEcComponent, CurrencyService, DopplerService, ENVIRONMENT_TOKEN, EcCurrencySymbolPipe, EcSafeHtmlPipe, FacebookPixelService, FaqsEcComponent, FiltersEcComponent, FiltersService, FiltersSortEcComponent, FooterEcComponent, ForgotPasswordEcComponent, FormService, GTMService, GoogleAnalyticsService, HeaderEcComponent, HomeEcComponent, LoadingFullEcComponent, LoadingInlineEcComponent, LoadingSectionEcComponent, LocalStorageService, LoginFormEcComponent, MagnizoomEcComponent, MetricoolPixelService, NgxLocalStorageService, OptionsService, OrderEcComponent, OrderUtilityService, OrdersListEcComponent, OrdersService, PaginationService, ParametersService, ParamsContext, PasswordResetEcComponent, PaymentService, PriceEcComponent, PriceRangeFilterComponent, ProductDetailEcComponent, ProductDetailService, ProductEcComponent, ProductOffDirective, ProductStockDirective, ProductsService, ReCaptchaEcComponent, ReCaptchaService, RegisterFormEcComponent, RegisterWholesalerFormEcComponent, RelatedProductsEcComponent, ReviewsEcComponent, ReviewsFormEcComponent, SectionContainerEcComponent, ShareEcComponent, ShipmentService, SidebarEcComponent, StoresEcComponent, SuccessEcComponent, TestService, ToastService, VariantsEcComponent, authGuard, authInterceptor, directives, provideEnvironment };
|
|
12199
|
+
export { AccountEcComponent, AddressingService, AnalyticsService, AuthEcComponent, AuthService, AuthStorageService, BlockBannerBoxEcComponent, BlockBannerFullEcComponent, BlockFormContactEcComponent, BlockHtmlEcComponent, BlockNewsletterEcComponent, BlockProductsEcComponent, BlocksEcComponent, BlocksRepositoryService, BlocksService, BreadcrumbEcComponent, CartEcComponent, CartItemEcComponent, CartService, ChannelService, CheckoutEcComponent, CheckoutService, CollectionEcComponent, ConfirmAccountEcComponent, ContactEcComponent, CoreConstantsService, CouponEcComponent, CurrencyService, DopplerService, ENVIRONMENT_TOKEN, EcCurrencySymbolPipe, EcSafeHtmlPipe, FacebookPixelService, FaqsEcComponent, FiltersEcComponent, FiltersService, FiltersSortEcComponent, FooterEcComponent, ForgotPasswordEcComponent, FormService, GTMService, GoogleAnalyticsService, HeaderEcComponent, HomeEcComponent, LoadingFullEcComponent, LoadingInlineEcComponent, LoadingSectionEcComponent, LocalStorageService, LoginFormEcComponent, MagnizoomEcComponent, MetricoolPixelService, NgxLocalStorageService, OptionsService, OrderEcComponent, OrderUtilityService, OrdersListEcComponent, OrdersService, PaginationService, ParametersService, ParamsContext, PasswordResetEcComponent, PaymentService, PriceEcComponent, PriceRangeFilterComponent, ProductDetailEcComponent, ProductDetailService, ProductEcComponent, ProductOffDirective, ProductStockDirective, ProductsService, ReCaptchaEcComponent, ReCaptchaService, RedsysCatchEcComponent, RegisterFormEcComponent, RegisterWholesalerFormEcComponent, RelatedProductsEcComponent, ReviewsEcComponent, ReviewsFormEcComponent, SectionContainerEcComponent, ShareEcComponent, ShipmentService, SidebarEcComponent, StoresEcComponent, SuccessEcComponent, TestService, ToastService, VariantsEcComponent, authGuard, authInterceptor, directives, provideEnvironment };
|
|
11765
12200
|
//# sourceMappingURL=ng-easycommerce-v18.mjs.map
|