feat(product-ticket-selector): enhance variant selection logic and update test cases for improved accuracy
This commit is contained in:
@@ -28,12 +28,18 @@
|
|||||||
class="form-select variant-selector__select"
|
class="form-select variant-selector__select"
|
||||||
[attr.aria-label]="selector.label"
|
[attr.aria-label]="selector.label"
|
||||||
[disabled]="rowDisabled(row)"
|
[disabled]="rowDisabled(row)"
|
||||||
[value]="selectedOptionKey(row, selector.key)"
|
|
||||||
(change)="onSelectionKeyChange(row.id, selector, $any($event.target).value)"
|
(change)="onSelectionKeyChange(row.id, selector, $any($event.target).value)"
|
||||||
>
|
>
|
||||||
<option value="" disabled>Seleccioná {{ selector.label }}</option>
|
<option value="" disabled [selected]="selectedOptionKey(row, selector.key) === ''">
|
||||||
|
Seleccioná {{ selector.label }}
|
||||||
|
</option>
|
||||||
@for (option of selector.options; track $index) {
|
@for (option of selector.options; track $index) {
|
||||||
<option [value]="optionKey(option)">{{ optionLabel(option) }}</option>
|
<option
|
||||||
|
[value]="optionKey(option)"
|
||||||
|
[selected]="optionKey(option) === selectedOptionKey(row, selector.key)"
|
||||||
|
>
|
||||||
|
{{ optionLabel(option) }}
|
||||||
|
</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -228,17 +228,20 @@ describe('ProductTicketSelectorComponent', () => {
|
|||||||
{
|
{
|
||||||
key: 'sector',
|
key: 'sector',
|
||||||
label: 'Sector',
|
label: 'Sector',
|
||||||
options: [{ value: 'a', label: 'Sector A' }],
|
options: [
|
||||||
|
{ value: 'a', label: 'Sector A' },
|
||||||
|
{ value: 'b', label: 'Sector B' },
|
||||||
|
],
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
{ key: 'seat', label: 'Seat', options: ['1'], enabled: true },
|
{ key: 'seat', label: 'Seat', options: ['1', '2'], enabled: true },
|
||||||
],
|
],
|
||||||
selected_values: { sector: 'a', seat: '1' },
|
selected_values: { sector: 'b', seat: '2' },
|
||||||
resolved_variant: {
|
resolved_variant: {
|
||||||
id: 401,
|
id: 401,
|
||||||
precio: '10000.00',
|
precio: '10000.00',
|
||||||
stock_tecnico: 1,
|
stock_tecnico: 1,
|
||||||
values: { sector: { value: 'a', label: 'Sector A' }, seat: '1' },
|
values: { sector: { value: 'b', label: 'Sector B' }, seat: '2' },
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
@@ -267,22 +270,22 @@ describe('ProductTicketSelectorComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(catalogService.getVariantOptions).toHaveBeenCalledWith(7, {
|
expect(catalogService.getVariantOptions).toHaveBeenCalledWith(7, {
|
||||||
selected_values: { sector: 'a', seat: '1' },
|
selected_values: {},
|
||||||
cart_item_id: 25,
|
cart_item_id: 25,
|
||||||
});
|
});
|
||||||
expect(fixture.componentInstance['rows']()[0]).toMatchObject({
|
expect(fixture.componentInstance['rows']()[0]).toMatchObject({
|
||||||
variantId: 401,
|
variantId: 401,
|
||||||
reservedVariantId: 401,
|
reservedVariantId: 401,
|
||||||
cartItemId: 25,
|
cartItemId: 25,
|
||||||
selectedValues: { sector: 'a', seat: '1' },
|
selectedValues: { sector: 'b', seat: '2' },
|
||||||
status: 'reserved',
|
status: 'reserved',
|
||||||
});
|
});
|
||||||
expect(cartService.addItem).not.toHaveBeenCalled();
|
expect(cartService.addItem).not.toHaveBeenCalled();
|
||||||
expect(cartService.updateItemVariant).not.toHaveBeenCalled();
|
expect(cartService.updateItemVariant).not.toHaveBeenCalled();
|
||||||
const selects = Array.from<HTMLSelectElement>(fixture.nativeElement.querySelectorAll('select'));
|
const selects = Array.from<HTMLSelectElement>(fixture.nativeElement.querySelectorAll('select'));
|
||||||
expect(selects.map((select) => select.selectedOptions[0]?.textContent?.trim())).toEqual([
|
expect(selects.map((select) => select.selectedOptions[0]?.textContent?.trim())).toEqual([
|
||||||
'Sector A',
|
'Sector B',
|
||||||
'1',
|
'2',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { CartService } from '../../../core/services/cart/cart.service';
|
import { CartService } from '../../../core/services/cart/cart.service';
|
||||||
import { CartItem, CartItemVariantValue } from '../../../core/services/cart/cart.interface';
|
import { CartItem } from '../../../core/services/cart/cart.interface';
|
||||||
import { ModalService } from '../../../core/services/modal.service';
|
import { ModalService } from '../../../core/services/modal.service';
|
||||||
import { ToastService } from '../../../core/services/toast.service';
|
import { ToastService } from '../../../core/services/toast.service';
|
||||||
import {
|
import {
|
||||||
@@ -455,19 +455,14 @@ export class ProductTicketSelectorComponent {
|
|||||||
private createCartRow(item: CartItem, id = this.nextRowId++): TicketSelectionRow | null {
|
private createCartRow(item: CartItem, id = this.nextRowId++): TicketSelectionRow | null {
|
||||||
if (item.variant_id === null) return null;
|
if (item.variant_id === null) return null;
|
||||||
|
|
||||||
const variant = item.variant;
|
|
||||||
if (!variant || variant.id !== item.variant_id) return null;
|
|
||||||
|
|
||||||
const selectedValues = this.normalizeCartValues(variant.values);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
variantId: item.variant_id,
|
variantId: item.variant_id,
|
||||||
reservedVariantId: item.variant_id,
|
reservedVariantId: item.variant_id,
|
||||||
cartItemId: item.id,
|
cartItemId: item.id,
|
||||||
selectedValues,
|
selectedValues: {},
|
||||||
selectors: [],
|
selectors: [],
|
||||||
reservedSelectedValues: selectedValues,
|
reservedSelectedValues: {},
|
||||||
reservedSelectors: [],
|
reservedSelectors: [],
|
||||||
status: 'checking',
|
status: 'checking',
|
||||||
error: null,
|
error: null,
|
||||||
@@ -495,11 +490,7 @@ export class ProductTicketSelectorComponent {
|
|||||||
|
|
||||||
if (!cartRow) return [];
|
if (!cartRow) return [];
|
||||||
|
|
||||||
if (
|
if (existingRow && existingRow.reservedVariantId === cartRow.reservedVariantId) {
|
||||||
existingRow &&
|
|
||||||
existingRow.reservedVariantId === cartRow.reservedVariantId &&
|
|
||||||
this.sameSelectedValues(existingRow.selectedValues, cartRow.selectedValues)
|
|
||||||
) {
|
|
||||||
return [existingRow];
|
return [existingRow];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,21 +534,6 @@ export class ProductTicketSelectorComponent {
|
|||||||
this.rows.set(rows);
|
this.rows.set(rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
private normalizeCartValues(
|
|
||||||
values: Record<string, CartItemVariantValue>,
|
|
||||||
): Record<string, string | string[]> {
|
|
||||||
return Object.fromEntries(
|
|
||||||
Object.entries(values).map(([key, value]) => [key, this.normalizeValue(value)]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private sameSelectedValues(
|
|
||||||
left: Record<string, string | string[]>,
|
|
||||||
right: Record<string, string | string[]>,
|
|
||||||
): boolean {
|
|
||||||
return JSON.stringify(left) === JSON.stringify(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
private findRow(rowId: number): TicketSelectionRow | undefined {
|
private findRow(rowId: number): TicketSelectionRow | undefined {
|
||||||
return this.rows().find((row) => row.id === rowId);
|
return this.rows().find((row) => row.id === rowId);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user