diff --git a/src/app/core/layout/store-layout/store-layout.component.ts b/src/app/core/layout/store-layout/store-layout.component.ts index cb4ef29..1ef34aa 100644 --- a/src/app/core/layout/store-layout/store-layout.component.ts +++ b/src/app/core/layout/store-layout/store-layout.component.ts @@ -69,10 +69,7 @@ export class StoreLayoutComponent implements OnInit { }); } - const variants = (item.product?.variants ?? []).map((variant) => ({ - value: variant.id, - values: variant.values, - })); + const variants = item.product?.variants ?? []; const selectedVariant = item.product?.variants?.find( (variant) => variant.id === item.variant_id, ); diff --git a/src/app/core/services/catalog/catalog.interface.ts b/src/app/core/services/catalog/catalog.interface.ts index 3cb9e14..637a779 100644 --- a/src/app/core/services/catalog/catalog.interface.ts +++ b/src/app/core/services/catalog/catalog.interface.ts @@ -71,7 +71,7 @@ export interface CatalogItemVariant { maximum_use_date?: string | null; effective_minimum_use_date?: string | null; effective_maximum_use_date?: string | null; - values: Record; + values: Record; } export interface SelectedCatalogItemVariant extends CatalogItemVariant { diff --git a/src/app/features/componentes-test/pages/reutilizables-test-page/reutilizables-test-page.component.html b/src/app/features/componentes-test/pages/reutilizables-test-page/reutilizables-test-page.component.html index d7ecc6e..002c96e 100644 --- a/src/app/features/componentes-test/pages/reutilizables-test-page/reutilizables-test-page.component.html +++ b/src/app/features/componentes-test/pages/reutilizables-test-page/reutilizables-test-page.component.html @@ -771,7 +771,7 @@ [description]="testTicketSelectorProduct.description" [price]="testTicketSelectorProduct.price" [imageUrl]="testTicketSelectorProduct.imageUrl" - [variants]="testTicketSelectorVariants" + [variants]="testTicketSelectorProduct.variants" (buy)="onTicketBuy($event)" /> diff --git a/src/app/features/componentes-test/pages/reutilizables-test-page/reutilizables-test-page.component.ts b/src/app/features/componentes-test/pages/reutilizables-test-page/reutilizables-test-page.component.ts index 2aa13d8..594d44f 100644 --- a/src/app/features/componentes-test/pages/reutilizables-test-page/reutilizables-test-page.component.ts +++ b/src/app/features/componentes-test/pages/reutilizables-test-page/reutilizables-test-page.component.ts @@ -211,9 +211,9 @@ export class ReutilizablesTestPageComponent { 'Acceso total al predio. No incluye acceso a estacionamiento. Niños menores de 5 años ingresan gratis.', price: 10000, variants: [ - { value: '10-oct-manana', values: { fecha: '10 de Octubre', turno: 'Mañana' } }, - { value: '10-oct-tarde', values: { fecha: '10 de Octubre', turno: 'Tarde' } }, - { value: '11-oct-tarde', values: { fecha: '11 de Octubre', turno: 'Tarde' } }, + { id: '10-oct-manana', values: { fecha: '10 de Octubre', turno: 'Mañana' } }, + { id: '10-oct-tarde', values: { fecha: '10 de Octubre', turno: 'Tarde' } }, + { id: '11-oct-tarde', values: { fecha: '11 de Octubre', turno: 'Tarde' } }, ], }; @@ -342,15 +342,6 @@ export class ReutilizablesTestPageComponent { ], }; - protected readonly testTicketSelectorVariants = this.testTicketSelectorProduct.variants.map( - (variant) => ({ - value: variant.id, - precio: variant.precio, - stock_tecnico: variant.stock_tecnico, - values: variant.values, - }), - ); - protected readonly cartMockItems: CartItemMock[] = [ { imageUrl: null, diff --git a/src/app/shared/components/cart/cart.component.spec.ts b/src/app/shared/components/cart/cart.component.spec.ts index 0909875..091c8b5 100644 --- a/src/app/shared/components/cart/cart.component.spec.ts +++ b/src/app/shared/components/cart/cart.component.spec.ts @@ -449,8 +449,8 @@ describe('CartComponent', () => { quantity: 2, variantId: 20, variants: [ - { value: 20, values: { servicio: 'Almuerzo' } }, - { value: 21, values: { servicio: 'Cena' } }, + { id: 20, values: { servicio: 'Almuerzo' } }, + { id: 21, values: { servicio: 'Cena' } }, ], }, ]); diff --git a/src/app/shared/components/product-list/product-list.component.html b/src/app/shared/components/product-list/product-list.component.html index ccc74fa..8f10cba 100644 --- a/src/app/shared/components/product-list/product-list.component.html +++ b/src/app/shared/components/product-list/product-list.component.html @@ -12,7 +12,7 @@ [title]="item.nombre" [description]="item.descripcion ?? ''" [price]="price(item)" - [variants]="variantsFor(item)" + [variants]="item.variants ?? []" (buy)="emitRowBuy(item, $event)" (addToCart)="emitRowCart(item, $event)" /> @@ -33,7 +33,7 @@ [description]="item.descripcion ?? ''" [price]="price(item)" [imageUrl]="loadImages() ? (item.image ?? null) : null" - [variants]="variantsFor(item)" + [variants]="item.variants ?? []" [disabled]="loading()" (buy)="emitTicketBuy(item, $event)" /> diff --git a/src/app/shared/components/product-list/product-list.component.spec.ts b/src/app/shared/components/product-list/product-list.component.spec.ts index c24e280..0dd7ad7 100644 --- a/src/app/shared/components/product-list/product-list.component.spec.ts +++ b/src/app/shared/components/product-list/product-list.component.spec.ts @@ -226,7 +226,23 @@ describe('ProductListComponent', () => { id: 401, precio: '10000.00', stock_tecnico: 1, - values: { tipo: 'VIP', sector: 'A', fila: '3', asiento: '12' }, + values: { + tipo: { value: 'vip', label: 'VIP' }, + sector: { value: 'a', label: 'Sector A' }, + fila: { value: '3', label: 'Fila 3' }, + asiento: { value: '12', label: 'Asiento 12' }, + }, + }, + { + id: 402, + precio: '12000.00', + stock_tecnico: 1, + values: { + tipo: { value: 'vip', label: 'VIP' }, + sector: { value: 'a', label: 'Sector A' }, + fila: { value: '3', label: 'Fila 3' }, + asiento: { value: '13', label: 'Asiento 13' }, + }, }, ], }; @@ -241,13 +257,19 @@ describe('ProductListComponent', () => { expect(element.querySelectorAll('app-product-ticket-selector')).toHaveLength(1); expect(element.querySelectorAll('.variant-selector__select')).toHaveLength(4); + (element.querySelector('.ticket-selector__add-row-button') as HTMLButtonElement).click(); + fixture.detectChanges(); + + expect(element.querySelectorAll('.ticket-selector__row')).toHaveLength(2); + expect(element.querySelectorAll('.variant-selector__select')).toHaveLength(8); + (element.querySelector('.ticket-selector__actions .btn-primary') as HTMLButtonElement).click(); expect(buySpy).toHaveBeenCalledWith({ product: ticket, - quantity: 1, + quantity: 2, variant: 401, - variantIds: [401], + variantIds: [401, 402], directPurchase: true, }); }); diff --git a/src/app/shared/components/product-list/product-list.component.ts b/src/app/shared/components/product-list/product-list.component.ts index 7f2f14c..c5b1027 100644 --- a/src/app/shared/components/product-list/product-list.component.ts +++ b/src/app/shared/components/product-list/product-list.component.ts @@ -21,10 +21,7 @@ import { import { CarouselComponent } from '../carousel/carousel.component'; import { PaginatorComponent } from '../paginator/paginator.component'; import { ProductColumnWithImageComponent } from '../product-column-with-image/product-column-with-image.component'; -import { - ProductRowCardComponent, - Variant as RowVariant, -} from '../product-row-card/product-row-card.component'; +import { ProductRowCardComponent } from '../product-row-card/product-row-card.component'; import { ProductVerticalWithCartCardComponent } from '../product-vertical-with-cart-card/product-vertical-with-cart-card.component'; import { ProductTicketSelectorComponent } from '../product-ticket-selector/product-ticket-selector.component'; @@ -108,16 +105,6 @@ export class ProductListComponent { return Number.isFinite(price) ? price : 0; } - protected variantsFor(item: ProductListItem): RowVariant[] { - return (item.variants ?? []).map((variant) => ({ - value: variant.id, - descripcion: variant.descripcion, - precio: variant.precio, - stock_tecnico: variant.stock_tecnico, - values: variant.values, - })); - } - protected emitRowCart( product: ProductListItem, event: { quantity: number; variant: unknown }, diff --git a/src/app/shared/components/product-row-card/product-row-card.component.ts b/src/app/shared/components/product-row-card/product-row-card.component.ts index 240d2df..8b659db 100644 --- a/src/app/shared/components/product-row-card/product-row-card.component.ts +++ b/src/app/shared/components/product-row-card/product-row-card.component.ts @@ -37,7 +37,7 @@ export class ProductRowCardComponent { readonly addToCart = output<{ quantity: number; variant: unknown }>(); protected readonly selectedVariantData = computed(() => - this.variants().find((variant) => Object.is(variant.value, this.selectedVariant())), + this.variants().find((variant) => Object.is(variant.id, this.selectedVariant())), ); protected readonly effectiveDescription = computed( () => this.selectedVariantData()?.descripcion ?? this.description(), diff --git a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.scss b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.scss index 724f404..bb607c1 100644 --- a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.scss +++ b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.scss @@ -32,7 +32,7 @@ &__price { flex: 0 0 auto; - font-size: 16px; + font-size: 25px; font-weight: 400; strong { diff --git a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.ts b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.ts index ebd5761..db9fc8c 100644 --- a/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.ts +++ b/src/app/shared/components/product-ticket-selector/product-ticket-selector.component.ts @@ -98,7 +98,7 @@ export class ProductTicketSelectorComponent { ); return this.selectableVariants().filter( - (variant) => !selectedByOtherRows.has(variant.value as number), + (variant) => !selectedByOtherRows.has(variant.id as number), ); } diff --git a/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.html b/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.html index b6e3baa..970ff1c 100644 --- a/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.html +++ b/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.html @@ -21,10 +21,7 @@
- +
} diff --git a/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.spec.ts b/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.spec.ts index ea0b626..c0aa867 100644 --- a/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.spec.ts +++ b/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.spec.ts @@ -1,4 +1,4 @@ -import { TestBed, getTestBed } from '@angular/core/testing'; +import { TestBed, getTestBed } from '@angular/core/testing'; import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing'; import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest'; @@ -17,7 +17,7 @@ describe('ProductVerticalWithCartCardComponent', () => { TestBed.resetTestingModule(); }); - async function createComponent(description = 'Pancho con aderezo a elección.') { + async function createComponent(description = 'Pancho con aderezo a elección.') { await TestBed.configureTestingModule({ imports: [ProductVerticalWithCartCardComponent], }).compileComponents(); @@ -40,7 +40,7 @@ describe('ProductVerticalWithCartCardComponent', () => { ); expect( element.querySelector('.product-vertical-with-cart-card__description')?.textContent, - ).toContain('Pancho con aderezo a elección.'); + ).toContain('Pancho con aderezo a elección.'); expect( element.querySelector('.product-vertical-with-cart-card__price')?.textContent?.trim(), ).toBe('$ 11.500'); @@ -130,16 +130,14 @@ describe('ProductVerticalWithCartCardComponent', () => { expect(summary?.querySelector('.product-vertical-with-cart-card__price')).not.toBeNull(); expect(summary?.querySelector('app-quantity-selector')).not.toBeNull(); - expect( - selectors?.querySelectorAll('.variant-selector__select'), - ).toHaveLength(1); + expect(selectors?.querySelectorAll('.variant-selector__select')).toHaveLength(1); expect(selectors?.querySelector('app-quantity-selector')).toBeNull(); }); it('places all variant selectors together below price and quantity', async () => { const fixture = await createComponent(); fixture.componentRef.setInput('variants', [ - { id: 20, values: { fecha: '10 de octubre', turno: 'Mañana' } }, + { id: 20, values: { fecha: '10 de octubre', turno: 'Mañana' } }, { id: 21, values: { fecha: '10 de octubre', turno: 'Tarde' } }, ]); fixture.detectChanges(); @@ -181,7 +179,7 @@ describe('ProductVerticalWithCartCardComponent', () => { }); it('prioritizes the selected variant description and price', async () => { - const fixture = await createComponent('Descripción general'); + const fixture = await createComponent('Descripción general'); fixture.componentRef.setInput('variants', [ { id: 40, @@ -206,9 +204,7 @@ describe('ProductVerticalWithCartCardComponent', () => { element.querySelector('.product-vertical-with-cart-card__price')?.textContent?.trim(), ).toBe('$ 10.000'); - const select = element.querySelector( - '.variant-selector__select', - ) as HTMLSelectElement; + const select = element.querySelector('.variant-selector__select') as HTMLSelectElement; select.value = select.options[1].value; select.dispatchEvent(new Event('change')); fixture.detectChanges(); diff --git a/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.ts b/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.ts index 0ceed82..88d5ae7 100644 --- a/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.ts +++ b/src/app/shared/components/product-vertical-with-cart-card/product-vertical-with-cart-card.component.ts @@ -1,11 +1,4 @@ -import { - ChangeDetectionStrategy, - Component, - computed, - input, - model, - output, -} from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, input, model, output } from '@angular/core'; import { ButtonComponent } from '../button/button.component'; import { QuantitySelectorComponent } from '../quantity-selector/quantity-selector.component'; @@ -14,11 +7,9 @@ import { VariantSelectorVariant, } from '../variant-selector/variant-selector.component'; -export interface VerticalCartVariant { - id: number; +export interface VerticalCartVariant extends VariantSelectorVariant { descripcion?: string | null; precio?: string | number; - values: Record; } @Component({ @@ -52,10 +43,7 @@ export class ProductVerticalWithCartCardComponent { return Number.isFinite(variantPrice) ? variantPrice : this.price(); }); protected readonly formattedPrice = computed(() => this.formatCurrency(this.effectivePrice())); - protected readonly selectorVariants = computed(() => - this.variants().map((variant) => ({ value: variant.id, values: variant.values })), - ); - protected readonly hasVariants = computed(() => this.selectorVariants().length > 0); + protected readonly hasVariants = computed(() => this.variants().length > 0); protected onAddToCart(): void { this.addToCart.emit({ quantity: this.quantity(), variant: this.selectedVariant() }); diff --git a/src/app/shared/components/variant-selector/variant-selector.component.spec.ts b/src/app/shared/components/variant-selector/variant-selector.component.spec.ts index ee14425..c56478d 100644 --- a/src/app/shared/components/variant-selector/variant-selector.component.spec.ts +++ b/src/app/shared/components/variant-selector/variant-selector.component.spec.ts @@ -22,9 +22,9 @@ describe('VariantSelectorComponent', () => { }).compileComponents(); const fixture = TestBed.createComponent(VariantSelectorComponent); fixture.componentRef.setInput('variants', [ - { value: 1, values: { alojamiento: 'Carpa', servicio: 'Almuerzo' } }, - { value: 2, values: { alojamiento: 'Carpa', servicio: 'Cena' } }, - { value: 3, values: { alojamiento: 'Hotel', servicio: 'Cena' } }, + { id: 1, values: { alojamiento: 'Carpa', servicio: 'Almuerzo' } }, + { id: 2, values: { alojamiento: 'Carpa', servicio: 'Cena' } }, + { id: 3, values: { alojamiento: 'Hotel', servicio: 'Cena' } }, ]); fixture.componentRef.setInput('selectedVariant', 1); fixture.detectChanges(); @@ -46,14 +46,14 @@ describe('VariantSelectorComponent', () => { const fixture = TestBed.createComponent(VariantSelectorComponent); fixture.componentRef.setInput('variants', [ { - value: 1, + id: 1, values: { color: { value: 'red', label: 'Rojo' }, talle: { value: 's', label: 'Small' }, }, }, { - value: 2, + id: 2, values: { color: { value: 'red', label: 'Rojo' }, talle: { value: 'm', label: 'Medium' }, diff --git a/src/app/shared/components/variant-selector/variant-selector.component.ts b/src/app/shared/components/variant-selector/variant-selector.component.ts index 324e035..a0fc2f1 100644 --- a/src/app/shared/components/variant-selector/variant-selector.component.ts +++ b/src/app/shared/components/variant-selector/variant-selector.component.ts @@ -19,7 +19,7 @@ export type VariantAttributeScalar = string | VariantAttributeOption; export type VariantAttributeValue = VariantAttributeScalar | VariantAttributeScalar[]; export interface VariantSelectorVariant { - value: unknown; + id: unknown; values: Record; } @@ -91,9 +91,9 @@ export class VariantSelectorComponent { } const selected = - variants.find((variant) => Object.is(variant.value, selectedVariant)) ?? variants[0]; + variants.find((variant) => Object.is(variant.id, selectedVariant)) ?? variants[0]; this.selectedValues.set({ ...selected.values }); - if (!Object.is(selected.value, selectedVariant)) this.selectedVariant.set(selected.value); + if (!Object.is(selected.id, selectedVariant)) this.selectedVariant.set(selected.id); }); }); } @@ -128,7 +128,7 @@ export class VariantSelectorComponent { ); this.selectedValues.set(values); - this.selectedVariant.set(matchingVariant?.value ?? null); + this.selectedVariant.set(matchingVariant?.id ?? null); } private optionsFor(variants: VariantSelectorVariant[], key: string): VariantSelectorOption[] {