ng-easycommerce-v18 0.0.4 → 0.0.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.
Files changed (25) hide show
  1. package/assets/ec-i18n/es.json +3 -0
  2. package/esm2022/lib/constants/core.constants.service.mjs +7 -1
  3. package/esm2022/lib/ec-components/cart-ec/cart-ec.component.mjs +4 -2
  4. package/esm2022/lib/ec-components/cart-ec/cart-item-ec/cart-item-ec.component.mjs +25 -1
  5. package/esm2022/lib/ec-components/filters-ec/filters-ec.component.mjs +19 -4
  6. package/esm2022/lib/ec-components/product-detail-ec/product-detail-ec.component.mjs +9 -2
  7. package/esm2022/lib/ec-components/product-ec/product-ec.component.mjs +3 -3
  8. package/esm2022/lib/ec-components/variants-ec/variants-ec.component.mjs +3 -3
  9. package/esm2022/lib/ec-components/widgets-ec/price-ec/price-ec.component.mjs +3 -3
  10. package/esm2022/lib/ec-directive/index.mjs +10 -0
  11. package/esm2022/lib/ec-directive/product-off.directive.mjs +119 -0
  12. package/esm2022/lib/ec-directive/product-stock.directive.mjs +72 -0
  13. package/esm2022/public-api.mjs +2 -2
  14. package/fesm2022/ng-easycommerce-v18.mjs +257 -13
  15. package/fesm2022/ng-easycommerce-v18.mjs.map +1 -1
  16. package/lib/constants/core.constants.service.d.ts +6 -0
  17. package/lib/ec-components/cart-ec/cart-ec.component.d.ts +2 -0
  18. package/lib/ec-components/cart-ec/cart-item-ec/cart-item-ec.component.d.ts +3 -0
  19. package/lib/ec-components/filters-ec/filters-ec.component.d.ts +10 -0
  20. package/lib/ec-components/product-detail-ec/product-detail-ec.component.d.ts +3 -0
  21. package/lib/ec-directive/index.d.ts +3 -0
  22. package/lib/ec-directive/product-off.directive.d.ts +28 -0
  23. package/lib/ec-directive/product-stock.directive.d.ts +18 -0
  24. package/package.json +1 -1
  25. package/public-api.d.ts +1 -0
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, makeEnvironmentProviders, inject, Injectable, PLATFORM_ID, RendererFactory2, afterNextRender, signal, EnvironmentInjector, runInInjectionContext, Component, CUSTOM_ELEMENTS_SCHEMA, Input, Pipe, EventEmitter, Output, forwardRef, afterRender, ViewChild, Injector } from '@angular/core';
2
+ import { InjectionToken, makeEnvironmentProviders, inject, Injectable, PLATFORM_ID, RendererFactory2, afterNextRender, signal, EnvironmentInjector, runInInjectionContext, Component, CUSTOM_ELEMENTS_SCHEMA, Input, Pipe, EventEmitter, Output, forwardRef, afterRender, ViewChild, Injector, Directive, Inject } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
4
  import { isPlatformBrowser, DOCUMENT, AsyncPipe, CommonModule, JsonPipe, UpperCasePipe, Location, TitleCasePipe } from '@angular/common';
5
5
  import { take, BehaviorSubject, shareReplay, map, catchError, of, filter, ReplaySubject, firstValueFrom, concatMap, switchMap, combineLatest, throwError } from 'rxjs';
@@ -218,6 +218,12 @@ class CoreConstantsService {
218
218
  * @returns
219
219
  */
220
220
  mediaUrl = (postMedia) => this.ASSETS_URL + (this.ASSETS_URL == this.apiConstants.API_URL ? 'media/' : '') + (postMedia ? postMedia : "image/");
221
+ /**
222
+ * Retorna la url donde se guarda las imagenes.
223
+ * @param postMedia
224
+ * @returns
225
+ */
226
+ mediaImageUrl = (postMedia) => this.ASSETS_URL + (this.ASSETS_URL == this.apiConstants.API_URL ? 'media/image' : '') + (postMedia ? postMedia : "image/");
221
227
  /**
222
228
  * Retorna la url del sitio.
223
229
  * @param postMedia
@@ -5983,11 +5989,11 @@ class PriceEcComponent {
5983
5989
  */
5984
5990
  saleprice;
5985
5991
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PriceEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5986
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: PriceEcComponent, isStandalone: true, selector: "app-price-ec", inputs: { price: "price", saleprice: "saleprice" }, ngImport: i0, template: "@if(saleprice){\r\n <!--With saleprice-->\r\n <div class=\"\">\r\n @if(price && price.split(' - ').length > 1){\r\n <div class=\"price text-center p-0 mx-0 mx-md-3\">\r\n <del class=\"text-center price\">\r\n {{ price.split(' - ')[0] | ecCurrencySymbol }}\r\n {{ price.split(' - ')[1] | ecCurrencySymbol }}\r\n </del>\r\n </div>\r\n }@else {\r\n <!--Simple Price Del-->\r\n <div class=\" text-center delete p-0 mx-0 mx-md-3\">\r\n <del class=\" text-center delete\">\r\n {{ price | ecCurrencySymbol }}</del>\r\n </div>\r\n }\r\n @if(saleprice && saleprice.split(' - ').length > 1){\r\n <div class=\"\">\r\n {{\r\n saleprice.split(' - ')[0] | ecCurrencySymbol\r\n }}\r\n {{\r\n saleprice.split(' - ')[1] | ecCurrencySymbol\r\n }}\r\n </div>\r\n } @else {\r\n <!--Simple saleprice-->\r\n <div class=\"text-center price p-0 mx-0 mx-md-3\">\r\n {{ saleprice | ecCurrencySymbol }}\r\n </div>\r\n }\r\n</div> \r\n}@else {\r\n <!--Only Price-->\r\n @if(price && price.split(' - ').length > 1){\r\n <div class=\"price\">\r\n {{ price.split(' - ')[0] | ecCurrencySymbol }} -\r\n {{ price.split(' - ')[1] | ecCurrencySymbol }}\r\n </div> \r\n } @else {\r\n <!--Simple price-->\r\n <div class=\"text-center price p-0 mx-0 mx-md-3\">\r\n {{ price | ecCurrencySymbol }}\r\n </div>\r\n }\r\n}", styles: [""], dependencies: [{ kind: "pipe", type: EcCurrencySymbolPipe, name: "ecCurrencySymbol" }] });
5992
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: PriceEcComponent, isStandalone: true, selector: "app-price-ec", inputs: { price: "price", saleprice: "saleprice" }, ngImport: i0, template: " <div class=\"price\">\r\n @if(saleprice){\r\n <!--With saleprice-->\r\n \r\n @if(price && price.split(' - ').length > 1){\r\n <div class=\"price-whithSaleprice\">\r\n <del class=\"\">\r\n {{ price.split(' - ')[0] | ecCurrencySymbol }}\r\n {{ price.split(' - ')[1] | ecCurrencySymbol }}\r\n </del>\r\n </div>\r\n }@else {\r\n <!--Simple Price Del-->\r\n <div class=\"price-simpleDel\">\r\n <del class=\"\">\r\n {{ price | ecCurrencySymbol }}</del>\r\n </div>\r\n }\r\n @if(saleprice && saleprice.split(' - ').length > 1){\r\n <div class=\"\">\r\n {{\r\n saleprice.split(' - ')[0] | ecCurrencySymbol\r\n }}\r\n {{\r\n saleprice.split(' - ')[1] | ecCurrencySymbol\r\n }}\r\n </div>\r\n } @else {\r\n <!--Simple saleprice-->\r\n <div class=\"price-simpleSaleprice\">\r\n {{ saleprice | ecCurrencySymbol }}\r\n </div>\r\n }\r\n\r\n}@else {\r\n <!--Only Price-->\r\n\r\n @if(price && price.split(' - ').length > 1){\r\n <div class=\"price-onlyPrice\">\r\n {{ price.split(' - ')[0] | ecCurrencySymbol }} -\r\n {{ price.split(' - ')[1] | ecCurrencySymbol }}\r\n </div> \r\n } @else {\r\n <!--Simple price-->\r\n <del>&nbsp;</del>\r\n <div class=\"price-simplePrice\">\r\n {{ price | ecCurrencySymbol }}\r\n </div>\r\n }\r\n}\r\n</div> ", styles: [""], dependencies: [{ kind: "pipe", type: EcCurrencySymbolPipe, name: "ecCurrencySymbol" }] });
5987
5993
  }
5988
5994
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PriceEcComponent, decorators: [{
5989
5995
  type: Component,
5990
- args: [{ selector: 'app-price-ec', standalone: true, imports: [EcCurrencySymbolPipe], template: "@if(saleprice){\r\n <!--With saleprice-->\r\n <div class=\"\">\r\n @if(price && price.split(' - ').length > 1){\r\n <div class=\"price text-center p-0 mx-0 mx-md-3\">\r\n <del class=\"text-center price\">\r\n {{ price.split(' - ')[0] | ecCurrencySymbol }}\r\n {{ price.split(' - ')[1] | ecCurrencySymbol }}\r\n </del>\r\n </div>\r\n }@else {\r\n <!--Simple Price Del-->\r\n <div class=\" text-center delete p-0 mx-0 mx-md-3\">\r\n <del class=\" text-center delete\">\r\n {{ price | ecCurrencySymbol }}</del>\r\n </div>\r\n }\r\n @if(saleprice && saleprice.split(' - ').length > 1){\r\n <div class=\"\">\r\n {{\r\n saleprice.split(' - ')[0] | ecCurrencySymbol\r\n }}\r\n {{\r\n saleprice.split(' - ')[1] | ecCurrencySymbol\r\n }}\r\n </div>\r\n } @else {\r\n <!--Simple saleprice-->\r\n <div class=\"text-center price p-0 mx-0 mx-md-3\">\r\n {{ saleprice | ecCurrencySymbol }}\r\n </div>\r\n }\r\n</div> \r\n}@else {\r\n <!--Only Price-->\r\n @if(price && price.split(' - ').length > 1){\r\n <div class=\"price\">\r\n {{ price.split(' - ')[0] | ecCurrencySymbol }} -\r\n {{ price.split(' - ')[1] | ecCurrencySymbol }}\r\n </div> \r\n } @else {\r\n <!--Simple price-->\r\n <div class=\"text-center price p-0 mx-0 mx-md-3\">\r\n {{ price | ecCurrencySymbol }}\r\n </div>\r\n }\r\n}" }]
5996
+ args: [{ selector: 'app-price-ec', standalone: true, imports: [EcCurrencySymbolPipe], template: " <div class=\"price\">\r\n @if(saleprice){\r\n <!--With saleprice-->\r\n \r\n @if(price && price.split(' - ').length > 1){\r\n <div class=\"price-whithSaleprice\">\r\n <del class=\"\">\r\n {{ price.split(' - ')[0] | ecCurrencySymbol }}\r\n {{ price.split(' - ')[1] | ecCurrencySymbol }}\r\n </del>\r\n </div>\r\n }@else {\r\n <!--Simple Price Del-->\r\n <div class=\"price-simpleDel\">\r\n <del class=\"\">\r\n {{ price | ecCurrencySymbol }}</del>\r\n </div>\r\n }\r\n @if(saleprice && saleprice.split(' - ').length > 1){\r\n <div class=\"\">\r\n {{\r\n saleprice.split(' - ')[0] | ecCurrencySymbol\r\n }}\r\n {{\r\n saleprice.split(' - ')[1] | ecCurrencySymbol\r\n }}\r\n </div>\r\n } @else {\r\n <!--Simple saleprice-->\r\n <div class=\"price-simpleSaleprice\">\r\n {{ saleprice | ecCurrencySymbol }}\r\n </div>\r\n }\r\n\r\n}@else {\r\n <!--Only Price-->\r\n\r\n @if(price && price.split(' - ').length > 1){\r\n <div class=\"price-onlyPrice\">\r\n {{ price.split(' - ')[0] | ecCurrencySymbol }} -\r\n {{ price.split(' - ')[1] | ecCurrencySymbol }}\r\n </div> \r\n } @else {\r\n <!--Simple price-->\r\n <del>&nbsp;</del>\r\n <div class=\"price-simplePrice\">\r\n {{ price | ecCurrencySymbol }}\r\n </div>\r\n }\r\n}\r\n</div> " }]
5991
5997
  }], propDecorators: { price: [{
5992
5998
  type: Input
5993
5999
  }], saleprice: [{
@@ -6034,11 +6040,11 @@ class ProductEcComponent {
6034
6040
  return this.product.saleprice && this.product.saleprice !== this.product.price;
6035
6041
  }
6036
6042
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: ProductEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6037
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", 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\">\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 @if (shouldShowPrice) {\r\n <app-price-ec [price]=\"product.price\" [saleprice]=\"product.saleprice\" class=\"\" />\r\n }@else {\r\n <p class=\"noPrice mb-1 mt-2 pt-1\"></p>\r\n }\r\n\r\n <!-- Nombre del producto -->\r\n <h6 class=\"my-0\">{{ product.name | titlecase }}</h6>\r\n\r\n <p class=\"sku mt-2\" [innerHTML]=\"product.shortdetails\"></p>\r\n\r\n <div class=\"fixBottom mt-1\">\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\" [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 }\r\n <!-- Cuando tiene marca especial y el tipo no es 'standard' -->\r\n @if(product?.special_mark?.[0]?.type !== 'standard'){\r\n @for (item of product.special_mark; track $index) {\r\n <!-- Caso 1: Agotado o Disponible muy pronto -->\r\n @if (item.type === 'out_of_stock' || item.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>{{ item.name | uppercase }}</span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n </button>}\r\n <!-- Caso 2: Contacto por WhatsApp -->\r\n @if (item.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(item.whatsappContact)\">\r\n @if(isCollection){\r\n <span>{{ item.name | uppercase }}</span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n\r\n </button>\r\n }\r\n <!-- Caso 3: Solicitar m\u00E1s informaci\u00F3n -->\r\n @if (item.type === 'more_info') {\r\n <button *ngIf=\"\" class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n\r\n @if(isCollection){\r\n <span>{{ item.name | uppercase }}</span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n </button>\r\n }\r\n\r\n }\r\n }\r\n\r\n <!-- </ng-container>\r\n <ng-template #noStock>\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n <ng-container *ngIf=\"isCollection; else normalText\">\r\n <span>{{(\"out-of-stock-short\" | translate) | uppercase}}</span>\r\n </ng-container>\r\n <ng-template #normalText>\r\n {{(\"out-of-stock-short\" | translate) | uppercase}}\r\n </ng-template>\r\n </button>\r\n </ng-template> -->\r\n </div>\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"] }, { 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" }] });
6043
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", 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\">\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 }@else {\r\n <p class=\"noPrice\"></p>\r\n }\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\" [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 }\r\n <!-- Cuando tiene marca especial y el tipo no es 'standard' -->\r\n @if(product.special_mark?.[0]?.type !== 'standard'){\r\n @for (item of product.special_mark; track $index) {\r\n <!-- Caso 1: Agotado o Disponible muy pronto -->\r\n @if (item.type === 'out_of_stock' || item.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>{{ item.name | uppercase }} </span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n </button>}\r\n <!-- Caso 2: Contacto por WhatsApp -->\r\n @if (item.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(item.whatsappContact)\">\r\n @if(isCollection){\r\n <span>{{ item.name | uppercase }}</span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n\r\n </button>\r\n }\r\n <!-- Caso 3: Solicitar m\u00E1s informaci\u00F3n -->\r\n @if (item.type === 'more_info') {\r\n <button *ngIf=\"\" class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n @if(isCollection){\r\n <span>{{ item.name | uppercase }}</span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n </button>\r\n }\r\n\r\n }\r\n }\r\n\r\n <!-- </ng-container>\r\n <ng-template #noStock>\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n <ng-container *ngIf=\"isCollection; else normalText\">\r\n <span>{{(\"out-of-stock-short\" | translate) | uppercase}}</span>\r\n </ng-container>\r\n <ng-template #normalText>\r\n {{(\"out-of-stock-short\" | translate) | uppercase}}\r\n </ng-template>\r\n </button>\r\n </ng-template> -->\r\n </div>\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"] }, { 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" }] });
6038
6044
  }
6039
6045
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: ProductEcComponent, decorators: [{
6040
6046
  type: Component,
6041
- args: [{ selector: 'app-product-ec', standalone: true, imports: [CommonModule, PriceEcComponent, RouterLink, TranslateModule], template: "<a [routerLink]=\"['/product', product.id]\" class=\"text-decoration-none\">\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 @if (shouldShowPrice) {\r\n <app-price-ec [price]=\"product.price\" [saleprice]=\"product.saleprice\" class=\"\" />\r\n }@else {\r\n <p class=\"noPrice mb-1 mt-2 pt-1\"></p>\r\n }\r\n\r\n <!-- Nombre del producto -->\r\n <h6 class=\"my-0\">{{ product.name | titlecase }}</h6>\r\n\r\n <p class=\"sku mt-2\" [innerHTML]=\"product.shortdetails\"></p>\r\n\r\n <div class=\"fixBottom mt-1\">\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\" [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 }\r\n <!-- Cuando tiene marca especial y el tipo no es 'standard' -->\r\n @if(product?.special_mark?.[0]?.type !== 'standard'){\r\n @for (item of product.special_mark; track $index) {\r\n <!-- Caso 1: Agotado o Disponible muy pronto -->\r\n @if (item.type === 'out_of_stock' || item.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>{{ item.name | uppercase }}</span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n </button>}\r\n <!-- Caso 2: Contacto por WhatsApp -->\r\n @if (item.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(item.whatsappContact)\">\r\n @if(isCollection){\r\n <span>{{ item.name | uppercase }}</span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n\r\n </button>\r\n }\r\n <!-- Caso 3: Solicitar m\u00E1s informaci\u00F3n -->\r\n @if (item.type === 'more_info') {\r\n <button *ngIf=\"\" class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n\r\n @if(isCollection){\r\n <span>{{ item.name | uppercase }}</span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n </button>\r\n }\r\n\r\n }\r\n }\r\n\r\n <!-- </ng-container>\r\n <ng-template #noStock>\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n <ng-container *ngIf=\"isCollection; else normalText\">\r\n <span>{{(\"out-of-stock-short\" | translate) | uppercase}}</span>\r\n </ng-container>\r\n <ng-template #normalText>\r\n {{(\"out-of-stock-short\" | translate) | uppercase}}\r\n </ng-template>\r\n </button>\r\n </ng-template> -->\r\n </div>\r\n</a>" }]
6047
+ args: [{ selector: 'app-product-ec', standalone: true, imports: [CommonModule, PriceEcComponent, RouterLink, TranslateModule], template: "<a [routerLink]=\"['/product', product.id]\" class=\"text-decoration-none\">\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 }@else {\r\n <p class=\"noPrice\"></p>\r\n }\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\" [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 }\r\n <!-- Cuando tiene marca especial y el tipo no es 'standard' -->\r\n @if(product.special_mark?.[0]?.type !== 'standard'){\r\n @for (item of product.special_mark; track $index) {\r\n <!-- Caso 1: Agotado o Disponible muy pronto -->\r\n @if (item.type === 'out_of_stock' || item.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>{{ item.name | uppercase }} </span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n </button>}\r\n <!-- Caso 2: Contacto por WhatsApp -->\r\n @if (item.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(item.whatsappContact)\">\r\n @if(isCollection){\r\n <span>{{ item.name | uppercase }}</span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n\r\n </button>\r\n }\r\n <!-- Caso 3: Solicitar m\u00E1s informaci\u00F3n -->\r\n @if (item.type === 'more_info') {\r\n <button *ngIf=\"\" class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n @if(isCollection){\r\n <span>{{ item.name | uppercase }}</span>\r\n }@else {\r\n {{ item.name | uppercase }}\r\n }\r\n </button>\r\n }\r\n\r\n }\r\n }\r\n\r\n <!-- </ng-container>\r\n <ng-template #noStock>\r\n <button class=\"btn\" [ngClass]=\"isCollection ? 'px-2 w-100 d-sm-block' : 'py-2 px-4'\">\r\n <ng-container *ngIf=\"isCollection; else normalText\">\r\n <span>{{(\"out-of-stock-short\" | translate) | uppercase}}</span>\r\n </ng-container>\r\n <ng-template #normalText>\r\n {{(\"out-of-stock-short\" | translate) | uppercase}}\r\n </ng-template>\r\n </button>\r\n </ng-template> -->\r\n </div>\r\n</a>" }]
6042
6048
  }], propDecorators: { product: [{
6043
6049
  type: Input,
6044
6050
  args: [{
@@ -7168,9 +7174,12 @@ class FiltersEcComponent {
7168
7174
  filters = [];
7169
7175
  filter$ = this._filtersService.filters$;
7170
7176
  setSelect;
7177
+ rangeMinRef;
7178
+ rangeMaxRef;
7179
+ priceGapPercentage = 0.1;
7171
7180
  constructor() {
7172
7181
  this.filter$.subscribe(res => {
7173
- this.filters = this._filtersService.getSpecificFilters(['attributes', 'categories', 'dynamics']);
7182
+ this.filters = this._filtersService.getSpecificFilters(['attributes', 'categories', 'price_range', 'dynamics']);
7174
7183
  });
7175
7184
  }
7176
7185
  getSpecificFilter(type) {
@@ -7196,6 +7205,12 @@ class FiltersEcComponent {
7196
7205
  * - Mínimo: redondea hacia abajo.
7197
7206
  * - Máximo: redondea hacia arriba.
7198
7207
  */
7208
+ onRangeChange(event, type, filter) {
7209
+ const input = event.target;
7210
+ let value = parseInt(input.value, 10);
7211
+ value = this.roundToNearest(value, 5, type, filter);
7212
+ this.updateFilterPrices(type, value, filter, this.priceGapPercentage);
7213
+ }
7199
7214
  roundToNearest(value, step, type, filter) {
7200
7215
  let rounded = Math.round(value / step) * step;
7201
7216
  if (type === 'max' && rounded < filter.maxPrice) {
@@ -7279,13 +7294,19 @@ class FiltersEcComponent {
7279
7294
  return true;
7280
7295
  };
7281
7296
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: FiltersEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7282
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.0", type: FiltersEcComponent, isStandalone: true, selector: "lib-filters-ec", inputs: { setSelect: "setSelect" }, ngImport: i0, template: "<p>filters-ec works!</p>\r\n", styles: [""] });
7297
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.0", type: FiltersEcComponent, isStandalone: true, selector: "lib-filters-ec", inputs: { setSelect: "setSelect" }, viewQueries: [{ propertyName: "rangeMinRef", first: true, predicate: ["rangeMin"], descendants: true }, { propertyName: "rangeMaxRef", first: true, predicate: ["rangeMax"], descendants: true }], ngImport: i0, template: "<p>filters-ec works!</p>\r\n", styles: [""] });
7283
7298
  }
7284
7299
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: FiltersEcComponent, decorators: [{
7285
7300
  type: Component,
7286
7301
  args: [{ selector: 'lib-filters-ec', standalone: true, imports: [], template: "<p>filters-ec works!</p>\r\n" }]
7287
7302
  }], ctorParameters: () => [], propDecorators: { setSelect: [{
7288
7303
  type: Input
7304
+ }], rangeMinRef: [{
7305
+ type: ViewChild,
7306
+ args: ['rangeMin']
7307
+ }], rangeMaxRef: [{
7308
+ type: ViewChild,
7309
+ args: ['rangeMax']
7289
7310
  }] } });
7290
7311
 
7291
7312
  class ProductDetailEcComponent {
@@ -7307,6 +7328,8 @@ class ProductDetailEcComponent {
7307
7328
  code = '';
7308
7329
  showFormContact = false;
7309
7330
  showReviews = false;
7331
+ reset = false;
7332
+ success = false;
7310
7333
  quantity = signal(1);
7311
7334
  parameters$ = this.parametersService.getParameters();
7312
7335
  hasParams = this.parametersService.hasParams;
@@ -7335,8 +7358,9 @@ class ProductDetailEcComponent {
7335
7358
  const currentUrl = this._consts.url() + this._location.path(true); // `true` incluye el query string
7336
7359
  this._meta.updateTag({ property: 'og:title', content: product.name || '' });
7337
7360
  this._meta.updateTag({ property: 'og:description', content: descripcionLimpia || '' });
7338
- this._meta.updateTag({ property: 'og:image', content: this._consts.mediaUrl(Array.isArray(product.picturesdefault) ? product.picturesdefault[0] : product.picturesdefault) || '' });
7361
+ this._meta.updateTag({ property: 'og:image', content: this._consts.mediaImageUrl(Array.isArray(product.picturesdefault) ? product.picturesdefault[0] : product.picturesdefault) || '' });
7339
7362
  this._meta.updateTag({ property: 'og:url', content: currentUrl });
7363
+ this._meta.updateTag({ property: 'og:type', content: 'product' });
7340
7364
  }
7341
7365
  sanitizedHtml(html) {
7342
7366
  return this._domSanitizer.bypassSecurityTrustHtml(html);
@@ -7379,6 +7403,10 @@ class ProductDetailEcComponent {
7379
7403
  }
7380
7404
  }, 500);
7381
7405
  }
7406
+ resetForm = () => {
7407
+ this.reset = !this.reset;
7408
+ this.success = true;
7409
+ };
7382
7410
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: ProductDetailEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7383
7411
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.0", type: ProductDetailEcComponent, isStandalone: true, selector: "app-product-detail-ec", ngImport: i0, template: "", styles: [""] });
7384
7412
  }
@@ -7394,11 +7422,11 @@ class VariantsEcComponent {
7394
7422
  this._productDetailsService.setOption(optionCode, optionValue);
7395
7423
  }
7396
7424
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: VariantsEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7397
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: VariantsEcComponent, isStandalone: true, selector: "app-variants-ec", ngImport: i0, template: "@if(options$ | async; as options){\r\n @if(options && options.length){\r\n @for(option of options; track $index){\r\n @switch (option.type) {\r\n @case ('color') {\r\n <h5>Colores disponibles</h5>\r\n <div class=\"row w-100 mx-auto pb-3 mb-3\">\r\n @for(value of option.values; track $index; let x = $index){\r\n <a role=\"button\" [title]=\"value.description\" (click)=\"setOption(option.code, value.name)\"\r\n [class]=\"'item m-1 circle ' + (value.selected ? 'shadow' : '')\" [id]=\"x + value.name\"\r\n [style.background]=\"'#' + value.name\" [style.box-shadow]=\"(value.selected ? '0px 0px 0px 2px #000' : 'none')\">\r\n </a>\r\n }\r\n </div>\r\n }\r\n @case ('size') {\r\n\r\n }\r\n @default {\r\n\r\n }\r\n }\r\n }\r\n } @else {\r\n <p>loading</p>\r\n }\r\n}\r\n\r\n<!-- <div *ngIf=\"(options$ | async) as options\">\r\n <div *ngIf=\"options && options.length; else loading\">\r\n <div *ngFor=\"let option of options; let i = index\">\r\n\r\n <div [ngSwitch]=\"option.type\">\r\n <div *ngSwitchCase=\"'color'\">\r\n <h5>Colores disponibles</h5>\r\n <div class=\"row w-100 mx-auto pb-3 mb-3\">\r\n <a *ngFor=\"let value of option.values; let x = index\" role=\"button\"\r\n (click)=\"setOption(option.code, value.name)\" [class]=\"'item m-1 ' + (value.selected ? 'shadow' : '')\"\r\n [id]=\"x + value.name\"\r\n [style.background]=\"'#' + value.name\"\r\n [style.box-shadow]=\"(value.selected ? '0px 0px 0px 2px #000' : 'none')\">\r\n </a>\r\n </div>\r\n </div>\r\n <div *ngSwitchCase=\"'size'\">\r\n <h5>Talles displonibles</h5>\r\n <div class=\"row w-100 mx-auto pb-3\">\r\n <a *ngFor=\"let value of option.values; let x = index\" role=\"buttom\"\r\n (click)=\"setOption(option.code, value.name)\"\r\n [id]=\"x + value.name\"\r\n [class]=\"'btn item m-1 ' + (value.selected ? 'selected-size' : 'unselected-size')\">\r\n {{ value.name }}\r\n </a>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<ng-template #loading>\r\n <div class=\"loading-container\">\r\n <div id=\"loading\"></div>\r\n </div>\r\n</ng-template> -->", styles: [".circle{width:32px;height:32px;border-radius:50%}.shadow{border:1px solid #000}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }] });
7425
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: VariantsEcComponent, isStandalone: true, selector: "app-variants-ec", ngImport: i0, template: "@if(options$ | async; as options){\r\n@if(options && options.length){\r\n@for(option of options; track $index){\r\n@switch (option.type) {\r\n@case ('color') {\r\n<h5>Colores disponibles</h5>\r\n<div class=\"row w-100 mx-auto pb-3 mb-3\">\r\n @for(value of option.values; track $index; let x = $index){\r\n <a role=\"button\" [title]=\"value.description\" (click)=\"setOption(option.code, value.name)\"\r\n [class]=\"'item m-1 circle ' + (value.selected ? 'shadow' : '')\" [id]=\"x + value.name\"\r\n [style.background]=\"'#' + value.name\" [style.box-shadow]=\"(value.selected ? '0px 0px 0px 2px #000' : 'none')\">\r\n </a>\r\n }\r\n</div>\r\n}\r\n@case ('size') {\r\n<h5>Talles displonibles</h5>\r\n<div class=\"row w-100 mx-auto pb-3\">\r\n @for(value of option.values; track $index; let x = $index){\r\n <a role=\"buttom\" (click)=\"setOption(option.code, value.name)\" [id]=\"x + value.name\"\r\n [class]=\"'btn item m-1 ' + (value.selected ? 'selected-size' : 'unselected-size')\">\r\n {{ value.name }}\r\n </a>\r\n }\r\n\r\n</div>\r\n}\r\n@default {\r\n\r\n}\r\n}\r\n}\r\n}\r\n}\r\n", styles: [".circle{width:32px;height:32px;border-radius:50%}.shadow{border:1px solid #000}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }] });
7398
7426
  }
7399
7427
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: VariantsEcComponent, decorators: [{
7400
7428
  type: Component,
7401
- args: [{ selector: 'app-variants-ec', standalone: true, imports: [AsyncPipe], template: "@if(options$ | async; as options){\r\n @if(options && options.length){\r\n @for(option of options; track $index){\r\n @switch (option.type) {\r\n @case ('color') {\r\n <h5>Colores disponibles</h5>\r\n <div class=\"row w-100 mx-auto pb-3 mb-3\">\r\n @for(value of option.values; track $index; let x = $index){\r\n <a role=\"button\" [title]=\"value.description\" (click)=\"setOption(option.code, value.name)\"\r\n [class]=\"'item m-1 circle ' + (value.selected ? 'shadow' : '')\" [id]=\"x + value.name\"\r\n [style.background]=\"'#' + value.name\" [style.box-shadow]=\"(value.selected ? '0px 0px 0px 2px #000' : 'none')\">\r\n </a>\r\n }\r\n </div>\r\n }\r\n @case ('size') {\r\n\r\n }\r\n @default {\r\n\r\n }\r\n }\r\n }\r\n } @else {\r\n <p>loading</p>\r\n }\r\n}\r\n\r\n<!-- <div *ngIf=\"(options$ | async) as options\">\r\n <div *ngIf=\"options && options.length; else loading\">\r\n <div *ngFor=\"let option of options; let i = index\">\r\n\r\n <div [ngSwitch]=\"option.type\">\r\n <div *ngSwitchCase=\"'color'\">\r\n <h5>Colores disponibles</h5>\r\n <div class=\"row w-100 mx-auto pb-3 mb-3\">\r\n <a *ngFor=\"let value of option.values; let x = index\" role=\"button\"\r\n (click)=\"setOption(option.code, value.name)\" [class]=\"'item m-1 ' + (value.selected ? 'shadow' : '')\"\r\n [id]=\"x + value.name\"\r\n [style.background]=\"'#' + value.name\"\r\n [style.box-shadow]=\"(value.selected ? '0px 0px 0px 2px #000' : 'none')\">\r\n </a>\r\n </div>\r\n </div>\r\n <div *ngSwitchCase=\"'size'\">\r\n <h5>Talles displonibles</h5>\r\n <div class=\"row w-100 mx-auto pb-3\">\r\n <a *ngFor=\"let value of option.values; let x = index\" role=\"buttom\"\r\n (click)=\"setOption(option.code, value.name)\"\r\n [id]=\"x + value.name\"\r\n [class]=\"'btn item m-1 ' + (value.selected ? 'selected-size' : 'unselected-size')\">\r\n {{ value.name }}\r\n </a>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<ng-template #loading>\r\n <div class=\"loading-container\">\r\n <div id=\"loading\"></div>\r\n </div>\r\n</ng-template> -->", styles: [".circle{width:32px;height:32px;border-radius:50%}.shadow{border:1px solid #000}\n"] }]
7429
+ args: [{ selector: 'app-variants-ec', standalone: true, imports: [AsyncPipe], template: "@if(options$ | async; as options){\r\n@if(options && options.length){\r\n@for(option of options; track $index){\r\n@switch (option.type) {\r\n@case ('color') {\r\n<h5>Colores disponibles</h5>\r\n<div class=\"row w-100 mx-auto pb-3 mb-3\">\r\n @for(value of option.values; track $index; let x = $index){\r\n <a role=\"button\" [title]=\"value.description\" (click)=\"setOption(option.code, value.name)\"\r\n [class]=\"'item m-1 circle ' + (value.selected ? 'shadow' : '')\" [id]=\"x + value.name\"\r\n [style.background]=\"'#' + value.name\" [style.box-shadow]=\"(value.selected ? '0px 0px 0px 2px #000' : 'none')\">\r\n </a>\r\n }\r\n</div>\r\n}\r\n@case ('size') {\r\n<h5>Talles displonibles</h5>\r\n<div class=\"row w-100 mx-auto pb-3\">\r\n @for(value of option.values; track $index; let x = $index){\r\n <a role=\"buttom\" (click)=\"setOption(option.code, value.name)\" [id]=\"x + value.name\"\r\n [class]=\"'btn item m-1 ' + (value.selected ? 'selected-size' : 'unselected-size')\">\r\n {{ value.name }}\r\n </a>\r\n }\r\n\r\n</div>\r\n}\r\n@default {\r\n\r\n}\r\n}\r\n}\r\n}\r\n}\r\n", styles: [".circle{width:32px;height:32px;border-radius:50%}.shadow{border:1px solid #000}\n"] }]
7402
7430
  }] });
7403
7431
 
7404
7432
  class BreadcrumbEcComponent {
@@ -7428,6 +7456,8 @@ class CartEcComponent {
7428
7456
  totalPromotionAmount$ = this._cartService.getTotalPromotionAmount();
7429
7457
  taxesAmount$ = this._cartService.getTaxesAmount();
7430
7458
  totalAmount$ = this._cartService.getTotalAmount();
7459
+ _authService = inject(AuthService);
7460
+ isAuthenticated$ = this._authService.isAuthenticated();
7431
7461
  removeCoupon() {
7432
7462
  this._cartService.removeCoupon();
7433
7463
  }
@@ -7448,6 +7478,7 @@ class CartItemEcComponent {
7448
7478
  mediaUrl = this._constants.mediaUrl();
7449
7479
  quantity = 0;
7450
7480
  variantsToShow = ['TALLE', 'COLOR'];
7481
+ updateStock = false;
7451
7482
  ngOnInit() {
7452
7483
  this.quantity = this.item.quantity;
7453
7484
  console.log(this.item, this.mediaUrl);
@@ -7512,6 +7543,29 @@ class CartItemEcComponent {
7512
7543
  return null;
7513
7544
  }
7514
7545
  }
7546
+ createDiscountMessage(saleprice, price) {
7547
+ if (isNaN(saleprice) || isNaN(price) || saleprice >= price || saleprice <= 0 || price <= 0) {
7548
+ return '';
7549
+ }
7550
+ let discountPercentage = Math.round(((price - saleprice) / price) * 100);
7551
+ let discountMessage = `${discountPercentage}% OFF`;
7552
+ return discountMessage;
7553
+ }
7554
+ checkStock(product) {
7555
+ for (const variant of product.product.variants) {
7556
+ if (product.variant_id === variant.code) {
7557
+ if (variant.stock === 0) {
7558
+ this.updateStock = true;
7559
+ return '0';
7560
+ }
7561
+ else if (product.quantity > variant.stock) {
7562
+ this.updateStock = true;
7563
+ return variant.stock;
7564
+ }
7565
+ }
7566
+ }
7567
+ return false; // Solo se ejecuta si no se cumple la condición
7568
+ }
7515
7569
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: CartItemEcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7516
7570
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", 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-2\">\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-8\">\r\n <div class=\"info d-flex flex-column align-items-start\">\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=\"input-group mb-3\">\r\n <button (click)=\"less(item.product.variants[0]?.stock)\" class=\"btn btn-outline-secondary\" 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=\"\" aria-label=\"Example text with button addon\"\r\n aria-describedby=\"button-addon1\" [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\" type=\"button\" id=\"button-addon1\">\r\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\r\n </button>\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"] }] });
7517
7571
  }
@@ -8640,16 +8694,206 @@ const authInterceptor = (req, next) => {
8640
8694
  return next(req);
8641
8695
  };
8642
8696
 
8697
+ class ProductStockDirective {
8698
+ templateRef;
8699
+ viewContainer;
8700
+ productDirective = null;
8701
+ ecProductStockElse;
8702
+ set ecProductStock(product) {
8703
+ this.productDirective = product;
8704
+ this.viewContainer.clear();
8705
+ if (this.validateStock()) {
8706
+ if (this.ecProductStockElse) {
8707
+ this.viewContainer.createEmbeddedView(this.ecProductStockElse);
8708
+ }
8709
+ else {
8710
+ console.error('falta definir el template de agotado');
8711
+ }
8712
+ }
8713
+ else {
8714
+ this.viewContainer.createEmbeddedView(this.templateRef);
8715
+ }
8716
+ }
8717
+ constructor(templateRef, viewContainer) {
8718
+ this.templateRef = templateRef;
8719
+ this.viewContainer = viewContainer;
8720
+ }
8721
+ ngOnInit() { }
8722
+ ngOnDestroy() { }
8723
+ ngOnChanges() { }
8724
+ validateStock = () => {
8725
+ if (!this.productDirective || this.productDirective.special_mark == undefined || this.productDirective.variants == undefined) {
8726
+ setTimeout(() => {
8727
+ this.validateStock();
8728
+ }, 1000);
8729
+ return false; // Ensure a boolean is returned
8730
+ }
8731
+ else {
8732
+ return this.checkValuesForStock();
8733
+ }
8734
+ };
8735
+ checkValuesForStock = () => {
8736
+ let existMark = false;
8737
+ // Check special_mark
8738
+ if (this.productDirective?.special_mark) {
8739
+ this.productDirective.special_mark.forEach(special_mark => {
8740
+ if (special_mark.type === 'out_of_stock') {
8741
+ existMark = true;
8742
+ }
8743
+ });
8744
+ }
8745
+ // Check variants
8746
+ if (!existMark && this.productDirective) {
8747
+ existMark = !!(this.productDirective.variant_id
8748
+ ? this.productDirective.variants?.find(v => v.code === this.productDirective?.variant_id && v.stock > 0) === undefined
8749
+ : this.productDirective.variants?.find(v => v.stock > 0) === undefined);
8750
+ }
8751
+ return existMark;
8752
+ };
8753
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: ProductStockDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
8754
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.0", type: ProductStockDirective, selector: "[ecProductStock]", inputs: { ecProductStockElse: "ecProductStockElse", ecProductStock: "ecProductStock" }, usesOnChanges: true, ngImport: i0 });
8755
+ }
8756
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: ProductStockDirective, decorators: [{
8757
+ type: Directive,
8758
+ args: [{
8759
+ selector: "[ecProductStock]"
8760
+ }]
8761
+ }], ctorParameters: () => [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }], propDecorators: { ecProductStockElse: [{
8762
+ type: Input
8763
+ }], ecProductStock: [{
8764
+ type: Input
8765
+ }] } });
8766
+
8767
+ class ParamsContext {
8768
+ }
8769
+ class ProductOffDirective {
8770
+ document;
8771
+ elementRef;
8772
+ renderer;
8773
+ product;
8774
+ classStr = "";
8775
+ customMessageStr = "{discount}% OFF";
8776
+ set ecProductOff(value) {
8777
+ this.product = value;
8778
+ }
8779
+ set classStrSpacing(value) {
8780
+ this.classStr = value;
8781
+ }
8782
+ set customMessage(value) {
8783
+ this.customMessageStr = value;
8784
+ }
8785
+ constructor(document, elementRef, renderer) {
8786
+ this.document = document;
8787
+ this.elementRef = elementRef;
8788
+ this.renderer = renderer;
8789
+ }
8790
+ ngOnInit() { }
8791
+ hasDiscount = (product) => {
8792
+ if (!product.saleprice) {
8793
+ return null;
8794
+ }
8795
+ if (typeof product.price === 'string' && product.price.includes("-") &&
8796
+ typeof product.saleprice === 'string' && product.saleprice.includes("-")) {
8797
+ let prices = product.price.split('-');
8798
+ let saleprices = product.saleprice.split('-');
8799
+ let saleBf = this.generateDiscount(prices[1]?.trim(), saleprices[1]?.trim());
8800
+ let saleLt = this.generateDiscount(prices[0]?.trim(), saleprices[0]?.trim());
8801
+ if (!saleBf && !saleLt) {
8802
+ return null;
8803
+ }
8804
+ if (saleBf && saleLt && saleBf === saleLt) {
8805
+ return `${saleBf}`;
8806
+ }
8807
+ if (saleBf && !saleLt) {
8808
+ return `${saleBf}`;
8809
+ }
8810
+ if (!saleBf && saleLt) {
8811
+ return `${saleLt}`;
8812
+ }
8813
+ return `${saleBf} - ${saleLt}`;
8814
+ }
8815
+ else {
8816
+ if (parseInt(product.price) > parseInt(product.saleprice)) {
8817
+ return this.generateDiscount(product.price, product.saleprice)?.toString() || null;
8818
+ }
8819
+ }
8820
+ return null; // Ensure a return value in all code paths
8821
+ };
8822
+ generateDiscount = (price, saleprice) => {
8823
+ if (parseFloat(price) > parseFloat(saleprice)) {
8824
+ let result = ((parseFloat(price) - parseFloat(saleprice)) /
8825
+ parseFloat(price)) *
8826
+ 100;
8827
+ if (Number.isNaN(result)) {
8828
+ return null;
8829
+ }
8830
+ else
8831
+ return Math.round(result); //Math.floor(result);
8832
+ }
8833
+ return null;
8834
+ };
8835
+ ngOnChanges(changes) {
8836
+ if (this.product.price) {
8837
+ let discount = this.hasDiscount(this.product);
8838
+ this.elementRef.nativeElement.childNodes.forEach((node) => {
8839
+ this.renderer.removeChild(this.elementRef.nativeElement, node);
8840
+ });
8841
+ if (discount) {
8842
+ this.renderer.appendChild(this.elementRef.nativeElement, this.createImage(discount));
8843
+ }
8844
+ // else {
8845
+ // this.renderer.removeChild(this.elementRef.nativeElement.parentElement, this.elementRef.nativeElement);
8846
+ // }
8847
+ }
8848
+ }
8849
+ createImage = (discount) => {
8850
+ let popover = this.renderer.createElement("a");
8851
+ this.customMessageStr = this.customMessageStr.replace('{discount}', discount);
8852
+ this.renderer.setProperty(popover, "innerHTML", this.customMessageStr);
8853
+ this.classStr?.split(" ").forEach((cl) => {
8854
+ try {
8855
+ this.renderer.addClass(popover, cl);
8856
+ }
8857
+ catch (error) {
8858
+ console.log('add class directive -> ', error);
8859
+ }
8860
+ });
8861
+ return popover;
8862
+ };
8863
+ ngOnDestroy() { }
8864
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: ProductOffDirective, deps: [{ token: DOCUMENT }, { token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
8865
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.0", type: ProductOffDirective, selector: "[ecProductOff]", inputs: { ecProductOff: "ecProductOff", classStrSpacing: "classStrSpacing", customMessage: "customMessage" }, usesOnChanges: true, ngImport: i0 });
8866
+ }
8867
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: ProductOffDirective, decorators: [{
8868
+ type: Directive,
8869
+ args: [{
8870
+ selector: "[ecProductOff]",
8871
+ }]
8872
+ }], ctorParameters: () => [{ type: Document, decorators: [{
8873
+ type: Inject,
8874
+ args: [DOCUMENT]
8875
+ }] }, { type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { ecProductOff: [{
8876
+ type: Input
8877
+ }], classStrSpacing: [{
8878
+ type: Input
8879
+ }], customMessage: [{
8880
+ type: Input
8881
+ }] } });
8882
+
8883
+ //Directives base
8884
+ const directives = [
8885
+ ProductOffDirective,
8886
+ ProductStockDirective,
8887
+ ];
8888
+
8643
8889
  /*
8644
8890
  * Public API Surface of ng-easycommerce
8645
8891
  */
8646
8892
  //Components
8647
- // Directives
8648
- //export * from './lib/ec-directive/index';
8649
8893
 
8650
8894
  /**
8651
8895
  * Generated bundle index. Do not edit.
8652
8896
  */
8653
8897
 
8654
- 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, CoreConstantsService, CouponEcComponent, CurrencyService, DopplerService, ENVIRONMENT_TOKEN, EcCurrencySymbolPipe, FacebookPixelService, 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, PaymentService, PriceEcComponent, ProductDetailEcComponent, ProductDetailService, ProductEcComponent, ProductsService, ReCaptchaEcComponent, ReCaptchaService, RegisterFormEcComponent, RegisterWholesalerFormEcComponent, ShipmentService, SidebarEcComponent, SuccessEcComponent, TestService, ToastService, VariantsEcComponent, authGuard, authInterceptor, provideEnvironment };
8898
+ 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, CoreConstantsService, CouponEcComponent, CurrencyService, DopplerService, ENVIRONMENT_TOKEN, EcCurrencySymbolPipe, FacebookPixelService, 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, PaymentService, PriceEcComponent, ProductDetailEcComponent, ProductDetailService, ProductEcComponent, ProductOffDirective, ProductStockDirective, ProductsService, ReCaptchaEcComponent, ReCaptchaService, RegisterFormEcComponent, RegisterWholesalerFormEcComponent, ShipmentService, SidebarEcComponent, SuccessEcComponent, TestService, ToastService, VariantsEcComponent, authGuard, authInterceptor, directives, provideEnvironment };
8655
8899
  //# sourceMappingURL=ng-easycommerce-v18.mjs.map