Revert "feat: enhance variant attribute handling across components for improved selection and display"
This reverts commit 56f602d876.
This commit is contained in:
@@ -12,7 +12,6 @@ import { findMenu } from '../../services/menu.utils';
|
|||||||
import { CheckoutService } from '../../services/checkout.service';
|
import { CheckoutService } from '../../services/checkout.service';
|
||||||
import { ToastService } from '../../services/toast.service';
|
import { ToastService } from '../../services/toast.service';
|
||||||
import { Category } from '../../services/tenant.interface';
|
import { Category } from '../../services/tenant.interface';
|
||||||
import { VariantAttributeValue } from '../../services/catalog/catalog.interface';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-store-layout',
|
selector: 'app-store-layout',
|
||||||
@@ -81,7 +80,7 @@ export class StoreLayoutComponent implements OnInit {
|
|||||||
if (selectedVariant) {
|
if (selectedVariant) {
|
||||||
attributes = Object.entries(selectedVariant.values).map(([label, value]) => ({
|
attributes = Object.entries(selectedVariant.values).map(([label, value]) => ({
|
||||||
label: this.formatAttributeLabel(label),
|
label: this.formatAttributeLabel(label),
|
||||||
value: this.variantAttributeLabel(value),
|
value: Array.isArray(value) ? value.join(', ') : value,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,14 +103,6 @@ export class StoreLayoutComponent implements OnInit {
|
|||||||
return label.charAt(0).toUpperCase() + label.slice(1);
|
return label.charAt(0).toUpperCase() + label.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private variantAttributeLabel(value: VariantAttributeValue): string {
|
|
||||||
if (typeof value === 'string') return value;
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
return value.map((item) => (typeof item === 'string' ? item : item.label)).join(', ');
|
|
||||||
}
|
|
||||||
return value.label;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected readonly currentYear = new Date().getFullYear();
|
protected readonly currentYear = new Date().getFullYear();
|
||||||
protected readonly tenant = this.tenantService.tenant;
|
protected readonly tenant = this.tenantService.tenant;
|
||||||
protected readonly user = this.authService.user;
|
protected readonly user = this.authService.user;
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { VariantAttributeValue } from '../catalog/catalog.interface';
|
|
||||||
|
|
||||||
export interface CartItemProduct {
|
export interface CartItemProduct {
|
||||||
nombre: string;
|
nombre: string;
|
||||||
imagen: string | null;
|
imagen: string | null;
|
||||||
@@ -10,7 +8,7 @@ export interface CartItemVariant {
|
|||||||
id: number;
|
id: number;
|
||||||
precio: string;
|
precio: string;
|
||||||
stock_tecnico: number | null;
|
stock_tecnico: number | null;
|
||||||
values: Record<string, VariantAttributeValue>;
|
values: Record<string, string | string[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CartItem {
|
export interface CartItem {
|
||||||
|
|||||||
@@ -47,17 +47,6 @@ export interface ProductAttribute {
|
|||||||
|
|
||||||
export type InventoryPolicy = 'tracked' | 'unlimited';
|
export type InventoryPolicy = 'tracked' | 'unlimited';
|
||||||
|
|
||||||
export interface VariantAttributeOptionValue {
|
|
||||||
value: string;
|
|
||||||
label: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type VariantAttributeValue =
|
|
||||||
| VariantAttributeOptionValue
|
|
||||||
| VariantAttributeOptionValue[]
|
|
||||||
| string
|
|
||||||
| string[];
|
|
||||||
|
|
||||||
export interface CatalogItemVariant {
|
export interface CatalogItemVariant {
|
||||||
id: number;
|
id: number;
|
||||||
descripcion?: string | null;
|
descripcion?: string | null;
|
||||||
@@ -70,7 +59,7 @@ export interface CatalogItemVariant {
|
|||||||
maximum_use_date?: string | null;
|
maximum_use_date?: string | null;
|
||||||
effective_minimum_use_date?: string | null;
|
effective_minimum_use_date?: string | null;
|
||||||
effective_maximum_use_date?: string | null;
|
effective_maximum_use_date?: string | null;
|
||||||
values: Record<string, VariantAttributeValue>;
|
values: Record<string, string | string[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectedCatalogItemVariant extends CatalogItemVariant {
|
export interface SelectedCatalogItemVariant extends CatalogItemVariant {
|
||||||
@@ -109,7 +98,7 @@ export interface CatalogFeaturedItemVariant {
|
|||||||
descripcion?: string | null;
|
descripcion?: string | null;
|
||||||
precio?: string;
|
precio?: string;
|
||||||
stock_tecnico: number | null;
|
stock_tecnico: number | null;
|
||||||
values: Record<string, VariantAttributeValue>;
|
values: Record<string, string | string[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CatalogFeaturedItem {
|
export interface CatalogFeaturedItem {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {
|
|||||||
InventoryPolicy,
|
InventoryPolicy,
|
||||||
ProductAttribute,
|
ProductAttribute,
|
||||||
ProductAttributeOption,
|
ProductAttributeOption,
|
||||||
VariantAttributeValue,
|
|
||||||
} from '../../../../core/services/catalog/catalog.interface';
|
} from '../../../../core/services/catalog/catalog.interface';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -199,7 +198,7 @@ export class ProductAttributeSelectorComponent {
|
|||||||
|
|
||||||
private getVariantAttributeValues(
|
private getVariantAttributeValues(
|
||||||
attribute: ProductAttribute,
|
attribute: ProductAttribute,
|
||||||
variantAttributes: Record<string, VariantAttributeValue>,
|
variantAttributes: Record<string, string | string[]>,
|
||||||
): string[] {
|
): string[] {
|
||||||
const normalizedCodigo = this.normalizeText(attribute.codigo);
|
const normalizedCodigo = this.normalizeText(attribute.codigo);
|
||||||
const normalizedNombre = this.normalizeText(attribute.nombre);
|
const normalizedNombre = this.normalizeText(attribute.nombre);
|
||||||
@@ -208,9 +207,7 @@ export class ProductAttributeSelectorComponent {
|
|||||||
const normalizedKey = this.normalizeText(key);
|
const normalizedKey = this.normalizeText(key);
|
||||||
|
|
||||||
if (normalizedKey === normalizedCodigo || normalizedKey === normalizedNombre) {
|
if (normalizedKey === normalizedCodigo || normalizedKey === normalizedNombre) {
|
||||||
return (Array.isArray(value) ? value : [value]).map((item) =>
|
return (Array.isArray(value) ? value : [value]).map((item) => this.normalizeText(item));
|
||||||
this.normalizeText(typeof item === 'string' ? item : item.value),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
[ngModel]="selectedValues()[selector.key]"
|
[ngModel]="selectedValues()[selector.key]"
|
||||||
(ngModelChange)="onVariantValueChange(selector.key, $event)"
|
(ngModelChange)="onVariantValueChange(selector.key, $event)"
|
||||||
>
|
>
|
||||||
@for (option of selector.options; track option.key) {
|
@for (option of selector.options; track option) {
|
||||||
<option [ngValue]="option.value">{{ option.label }}</option>
|
<option [ngValue]="option">{{ option }}</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,24 +136,6 @@ describe('ProductVerticalWithCartCardComponent', () => {
|
|||||||
expect(selectors?.querySelector('app-quantity-selector')).toBeNull();
|
expect(selectors?.querySelector('app-quantity-selector')).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses the variant value for selection and renders its label', async () => {
|
|
||||||
const fixture = await createComponent();
|
|
||||||
fixture.componentRef.setInput('variants', [
|
|
||||||
{
|
|
||||||
id: 10,
|
|
||||||
values: { event_date: { value: '2', label: '10/10/2026' } },
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const option = fixture.nativeElement.querySelector(
|
|
||||||
'.product-vertical-with-cart-card__variant-select option',
|
|
||||||
) as HTMLOptionElement;
|
|
||||||
|
|
||||||
expect(option.textContent?.trim()).toBe('10/10/2026');
|
|
||||||
expect((fixture.componentInstance as any).selectedValues()).toEqual({ event_date: '2' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('places all variant selectors together below price and quantity', async () => {
|
it('places all variant selectors together below price and quantity', async () => {
|
||||||
const fixture = await createComponent();
|
const fixture = await createComponent();
|
||||||
fixture.componentRef.setInput('variants', [
|
fixture.componentRef.setInput('variants', [
|
||||||
|
|||||||
@@ -13,27 +13,18 @@ import { FormsModule } from '@angular/forms';
|
|||||||
|
|
||||||
import { ButtonComponent } from '../button/button.component';
|
import { ButtonComponent } from '../button/button.component';
|
||||||
import { QuantitySelectorComponent } from '../quantity-selector/quantity-selector.component';
|
import { QuantitySelectorComponent } from '../quantity-selector/quantity-selector.component';
|
||||||
import { VariantAttributeValue } from '../../../core/services/catalog/catalog.interface';
|
|
||||||
|
|
||||||
type VariantSelectionValue = string | string[];
|
|
||||||
|
|
||||||
export interface VerticalCartVariant {
|
export interface VerticalCartVariant {
|
||||||
id: number;
|
id: number;
|
||||||
descripcion?: string | null;
|
descripcion?: string | null;
|
||||||
precio?: string | number;
|
precio?: string | number;
|
||||||
values: Record<string, VariantAttributeValue>;
|
values: Record<string, string>;
|
||||||
}
|
|
||||||
|
|
||||||
interface VariantSelectorOption {
|
|
||||||
key: string;
|
|
||||||
value: VariantSelectionValue;
|
|
||||||
label: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VariantSelector {
|
interface VariantSelector {
|
||||||
key: string;
|
key: string;
|
||||||
label: string;
|
label: string;
|
||||||
options: VariantSelectorOption[];
|
options: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -55,7 +46,7 @@ export class ProductVerticalWithCartCardComponent {
|
|||||||
readonly buy = output<{ quantity: number; variant: number | null }>();
|
readonly buy = output<{ quantity: number; variant: number | null }>();
|
||||||
readonly addToCart = output<{ quantity: number; variant: number | null }>();
|
readonly addToCart = output<{ quantity: number; variant: number | null }>();
|
||||||
|
|
||||||
protected readonly selectedValues = signal<Record<string, VariantSelectionValue>>({});
|
protected readonly selectedValues = signal<Record<string, string>>({});
|
||||||
|
|
||||||
protected readonly selectedVariantData = computed(() =>
|
protected readonly selectedVariantData = computed(() =>
|
||||||
this.variants().find((variant) => variant.id === this.selectedVariant()),
|
this.variants().find((variant) => variant.id === this.selectedVariant()),
|
||||||
@@ -76,7 +67,13 @@ export class ProductVerticalWithCartCardComponent {
|
|||||||
return keys.map((key) => ({
|
return keys.map((key) => ({
|
||||||
key,
|
key,
|
||||||
label: this.formatVariantLabel(key),
|
label: this.formatVariantLabel(key),
|
||||||
options: this.optionsFor(variants, key),
|
options: Array.from(
|
||||||
|
new Set(
|
||||||
|
variants
|
||||||
|
.map((variant) => variant.values[key])
|
||||||
|
.filter((value): value is string => Boolean(value)),
|
||||||
|
),
|
||||||
|
),
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -95,21 +92,17 @@ export class ProductVerticalWithCartCardComponent {
|
|||||||
|
|
||||||
const selected =
|
const selected =
|
||||||
variants.find((variant) => variant.id === this.selectedVariant()) ?? variants[0];
|
variants.find((variant) => variant.id === this.selectedVariant()) ?? variants[0];
|
||||||
this.selectedValues.set(this.selectionValues(selected.values));
|
this.selectedValues.set({ ...selected.values });
|
||||||
this.selectedVariant.set(selected.id);
|
this.selectedVariant.set(selected.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onVariantValueChange(key: string, value: VariantSelectionValue): void {
|
protected onVariantValueChange(key: string, value: string): void {
|
||||||
const values = { ...this.selectedValues(), [key]: value };
|
const values = { ...this.selectedValues(), [key]: value };
|
||||||
const selectors = this.variantSelectors();
|
const selectors = this.variantSelectors();
|
||||||
const matchingVariant = this.variants().find((variant) =>
|
const matchingVariant = this.variants().find((variant) =>
|
||||||
selectors.every(
|
selectors.every((selector) => variant.values[selector.key] === values[selector.key]),
|
||||||
(selector) =>
|
|
||||||
this.valueKey(this.selectionValue(variant.values[selector.key])) ===
|
|
||||||
this.valueKey(values[selector.key]),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.selectedValues.set(values);
|
this.selectedValues.set(values);
|
||||||
@@ -124,55 +117,6 @@ export class ProductVerticalWithCartCardComponent {
|
|||||||
this.buy.emit({ quantity: this.quantity(), variant: this.selectedVariant() });
|
this.buy.emit({ quantity: this.quantity(), variant: this.selectedVariant() });
|
||||||
}
|
}
|
||||||
|
|
||||||
private optionsFor(variants: VerticalCartVariant[], key: string): VariantSelectorOption[] {
|
|
||||||
const options = new Map<string, VariantSelectorOption>();
|
|
||||||
|
|
||||||
for (const variant of variants) {
|
|
||||||
const attributeValue = variant.values[key];
|
|
||||||
if (attributeValue === undefined) continue;
|
|
||||||
|
|
||||||
const value = this.selectionValue(attributeValue);
|
|
||||||
const optionKey = this.valueKey(value);
|
|
||||||
if (!options.has(optionKey)) {
|
|
||||||
options.set(optionKey, {
|
|
||||||
key: optionKey,
|
|
||||||
value,
|
|
||||||
label: this.selectionLabel(attributeValue),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.from(options.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
private selectionValues(
|
|
||||||
values: Record<string, VariantAttributeValue>,
|
|
||||||
): Record<string, VariantSelectionValue> {
|
|
||||||
return Object.fromEntries(
|
|
||||||
Object.entries(values).map(([key, value]) => [key, this.selectionValue(value)]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private selectionValue(value: VariantAttributeValue): VariantSelectionValue {
|
|
||||||
if (typeof value === 'string') return value;
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
return value.map((item) => (typeof item === 'string' ? item : item.value));
|
|
||||||
}
|
|
||||||
return value.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private selectionLabel(value: VariantAttributeValue): string {
|
|
||||||
if (typeof value === 'string') return value;
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
return value.map((item) => (typeof item === 'string' ? item : item.label)).join(', ');
|
|
||||||
}
|
|
||||||
return value.label;
|
|
||||||
}
|
|
||||||
|
|
||||||
private valueKey(value: VariantSelectionValue | undefined): string {
|
|
||||||
return JSON.stringify(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private formatVariantLabel(key: string): string {
|
private formatVariantLabel(key: string): string {
|
||||||
const label = key.replace(/[_-]+/g, ' ');
|
const label = key.replace(/[_-]+/g, ' ');
|
||||||
return label.charAt(0).toUpperCase() + label.slice(1);
|
return label.charAt(0).toUpperCase() + label.slice(1);
|
||||||
|
|||||||
@@ -38,22 +38,4 @@ describe('VariantSelectorComponent', () => {
|
|||||||
servicio: 'Cena',
|
servicio: 'Cena',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders labels while matching variants by value', async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [VariantSelectorComponent],
|
|
||||||
}).compileComponents();
|
|
||||||
const fixture = TestBed.createComponent(VariantSelectorComponent);
|
|
||||||
fixture.componentRef.setInput('variants', [
|
|
||||||
{
|
|
||||||
value: 1,
|
|
||||||
values: { event_date: { value: '2', label: '10/10/2026' } },
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const option = fixture.nativeElement.querySelector('option') as HTMLOptionElement;
|
|
||||||
expect(option.textContent?.trim()).toBe('10/10/2026');
|
|
||||||
expect((fixture.componentInstance as any).selectedValues()).toEqual({ event_date: '2' });
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,9 +9,8 @@ import {
|
|||||||
untracked,
|
untracked,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { VariantAttributeValue } from '../../../core/services/catalog/catalog.interface';
|
|
||||||
|
|
||||||
type VariantSelectionValue = string | string[];
|
export type VariantAttributeValue = string | string[];
|
||||||
|
|
||||||
export interface VariantSelectorVariant {
|
export interface VariantSelectorVariant {
|
||||||
value: unknown;
|
value: unknown;
|
||||||
@@ -21,7 +20,7 @@ export interface VariantSelectorVariant {
|
|||||||
interface VariantSelectorOption {
|
interface VariantSelectorOption {
|
||||||
key: string;
|
key: string;
|
||||||
label: string;
|
label: string;
|
||||||
value: VariantSelectionValue;
|
value: VariantAttributeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VariantSelectorGroup {
|
interface VariantSelectorGroup {
|
||||||
@@ -44,7 +43,7 @@ export class VariantSelectorComponent {
|
|||||||
readonly disabled = input(false);
|
readonly disabled = input(false);
|
||||||
readonly compact = input(false);
|
readonly compact = input(false);
|
||||||
|
|
||||||
protected readonly selectedValues = signal<Record<string, VariantSelectionValue>>({});
|
protected readonly selectedValues = signal<Record<string, VariantAttributeValue>>({});
|
||||||
protected readonly attributeKeys = computed(() =>
|
protected readonly attributeKeys = computed(() =>
|
||||||
Array.from(new Set(this.variants().flatMap((variant) => Object.keys(variant.values)))),
|
Array.from(new Set(this.variants().flatMap((variant) => Object.keys(variant.values)))),
|
||||||
);
|
);
|
||||||
@@ -57,10 +56,7 @@ export class VariantSelectorComponent {
|
|||||||
const previousKeys = keys.slice(0, index);
|
const previousKeys = keys.slice(0, index);
|
||||||
const compatibleVariants = variants.filter((variant) =>
|
const compatibleVariants = variants.filter((variant) =>
|
||||||
previousKeys.every((previousKey) =>
|
previousKeys.every((previousKey) =>
|
||||||
this.sameValue(
|
this.sameValue(variant.values[previousKey], selectedValues[previousKey]),
|
||||||
this.selectionValue(variant.values[previousKey]),
|
|
||||||
selectedValues[previousKey],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -86,13 +82,13 @@ export class VariantSelectorComponent {
|
|||||||
|
|
||||||
const selected =
|
const selected =
|
||||||
variants.find((variant) => Object.is(variant.value, selectedVariant)) ?? variants[0];
|
variants.find((variant) => Object.is(variant.value, selectedVariant)) ?? variants[0];
|
||||||
this.selectedValues.set(this.selectionValues(selected.values));
|
this.selectedValues.set({ ...selected.values });
|
||||||
if (!Object.is(selected.value, selectedVariant)) this.selectedVariant.set(selected.value);
|
if (!Object.is(selected.value, selectedVariant)) this.selectedVariant.set(selected.value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onValueChange(key: string, value: VariantSelectionValue): void {
|
protected onValueChange(key: string, value: VariantAttributeValue): void {
|
||||||
const variants = this.variants();
|
const variants = this.variants();
|
||||||
const keys = this.attributeKeys();
|
const keys = this.attributeKeys();
|
||||||
const changedIndex = keys.indexOf(key);
|
const changedIndex = keys.indexOf(key);
|
||||||
@@ -103,7 +99,7 @@ export class VariantSelectorComponent {
|
|||||||
const previousKeys = keys.slice(0, index);
|
const previousKeys = keys.slice(0, index);
|
||||||
const compatibleVariants = variants.filter((variant) =>
|
const compatibleVariants = variants.filter((variant) =>
|
||||||
previousKeys.every((previousKey) =>
|
previousKeys.every((previousKey) =>
|
||||||
this.sameValue(this.selectionValue(variant.values[previousKey]), values[previousKey]),
|
this.sameValue(variant.values[previousKey], values[previousKey]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const options = this.optionsFor(compatibleVariants, currentKey);
|
const options = this.optionsFor(compatibleVariants, currentKey);
|
||||||
@@ -117,7 +113,7 @@ export class VariantSelectorComponent {
|
|||||||
|
|
||||||
const matchingVariant = variants.find((variant) =>
|
const matchingVariant = variants.find((variant) =>
|
||||||
keys.every((attributeKey) =>
|
keys.every((attributeKey) =>
|
||||||
this.sameValue(this.selectionValue(variant.values[attributeKey]), values[attributeKey]),
|
this.sameValue(variant.values[attributeKey], values[attributeKey]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -129,19 +125,14 @@ export class VariantSelectorComponent {
|
|||||||
const options = new Map<string, VariantSelectorOption>();
|
const options = new Map<string, VariantSelectorOption>();
|
||||||
|
|
||||||
for (const variant of variants) {
|
for (const variant of variants) {
|
||||||
const attributeValue = variant.values[key];
|
const value = variant.values[key];
|
||||||
if (attributeValue === undefined) continue;
|
if (value === undefined || value === '') continue;
|
||||||
|
|
||||||
const value = this.selectionValue(attributeValue);
|
|
||||||
if (value === undefined || value === '' || (Array.isArray(value) && value.length === 0)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const optionKey = this.valueKey(value);
|
const optionKey = this.valueKey(value);
|
||||||
if (!options.has(optionKey)) {
|
if (!options.has(optionKey)) {
|
||||||
options.set(optionKey, {
|
options.set(optionKey, {
|
||||||
key: optionKey,
|
key: optionKey,
|
||||||
label: this.selectionLabel(attributeValue),
|
label: Array.isArray(value) ? value.join(', ') : value,
|
||||||
value,
|
value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -151,48 +142,18 @@ export class VariantSelectorComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private sameValue(
|
private sameValue(
|
||||||
left: VariantSelectionValue | undefined,
|
left: VariantAttributeValue | undefined,
|
||||||
right: VariantSelectionValue | undefined,
|
right: VariantAttributeValue | undefined,
|
||||||
): boolean {
|
): boolean {
|
||||||
return (
|
return (
|
||||||
left !== undefined && right !== undefined && this.valueKey(left) === this.valueKey(right)
|
left !== undefined && right !== undefined && this.valueKey(left) === this.valueKey(right)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private valueKey(value: VariantSelectionValue): string {
|
private valueKey(value: VariantAttributeValue): string {
|
||||||
return JSON.stringify(value);
|
return JSON.stringify(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private selectionValues(
|
|
||||||
values: Record<string, VariantAttributeValue>,
|
|
||||||
): Record<string, VariantSelectionValue> {
|
|
||||||
return Object.fromEntries(
|
|
||||||
Object.entries(values).flatMap(([key, value]) => {
|
|
||||||
const selectionValue = this.selectionValue(value);
|
|
||||||
return selectionValue === undefined ? [] : [[key, selectionValue]];
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private selectionValue(
|
|
||||||
value: VariantAttributeValue | undefined,
|
|
||||||
): VariantSelectionValue | undefined {
|
|
||||||
if (value === undefined) return undefined;
|
|
||||||
if (typeof value === 'string') return value;
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
return value.map((item) => (typeof item === 'string' ? item : item.value));
|
|
||||||
}
|
|
||||||
return value.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private selectionLabel(value: VariantAttributeValue): string {
|
|
||||||
if (typeof value === 'string') return value;
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
return value.map((item) => (typeof item === 'string' ? item : item.label)).join(', ');
|
|
||||||
}
|
|
||||||
return value.label;
|
|
||||||
}
|
|
||||||
|
|
||||||
private formatVariantLabel(key: string): string {
|
private formatVariantLabel(key: string): string {
|
||||||
const label = key.replace(/[_-]+/g, ' ');
|
const label = key.replace(/[_-]+/g, ' ');
|
||||||
return label.charAt(0).toUpperCase() + label.slice(1);
|
return label.charAt(0).toUpperCase() + label.slice(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user