changes
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import { Component, OnInit, OnDestroy, signal, ChangeDetectionStrategy, inject } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, signal, computed, ChangeDetectionStrategy, inject } from '@angular/core';
|
||||
import { DecimalPipe } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, RouterLink } from '@angular/router';
|
||||
import { ApiService, CartService, TelegramService, LanguageService, SeoService } from '../../services';
|
||||
import { AuthService } from '../../services/auth.service';
|
||||
import { Item, DescriptionField } from '../../models';
|
||||
import { Item, ItemDetail, DescriptionField } from '../../models';
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { environment } from '../../../environments/environment';
|
||||
@@ -27,6 +27,55 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
loading = signal(true);
|
||||
error = signal<string | null>(null);
|
||||
isnovo = environment.theme === 'novo';
|
||||
|
||||
// Variant selection
|
||||
selectedColour = signal<string | null>(null);
|
||||
selectedSize = signal<string | null>(null);
|
||||
|
||||
availableColours = computed(() => {
|
||||
const details = this.item()?.itemDetails;
|
||||
if (!details?.length) return [] as string[];
|
||||
const unique = [...new Set(details.map(d => d.colour || d.color).filter((c): c is string => !!c))];
|
||||
return unique;
|
||||
});
|
||||
|
||||
availableSizes = computed(() => {
|
||||
const details = this.item()?.itemDetails;
|
||||
if (!details?.length) return [] as string[];
|
||||
// If a colour is selected, only show sizes available for that colour
|
||||
const colour = this.selectedColour();
|
||||
const filtered = colour
|
||||
? details.filter(d => (d.colour || d.color) === colour)
|
||||
: details;
|
||||
const unique = [...new Set(filtered.map(d => d.size).filter((s): s is string => !!s))];
|
||||
return unique;
|
||||
});
|
||||
|
||||
selectedDetail = computed<ItemDetail | null>(() => {
|
||||
const details = this.item()?.itemDetails;
|
||||
if (!details?.length) return null;
|
||||
const colour = this.selectedColour();
|
||||
const size = this.selectedSize();
|
||||
return details.find(d =>
|
||||
(!colour || (d.colour || d.color) === colour) &&
|
||||
(!size || d.size === size)
|
||||
) ?? null;
|
||||
});
|
||||
|
||||
effectivePrice = computed(() => {
|
||||
const detail = this.selectedDetail();
|
||||
return detail?.price ?? this.item()?.price ?? 0;
|
||||
});
|
||||
|
||||
effectiveCurrency = computed(() => {
|
||||
const detail = this.selectedDetail();
|
||||
return detail?.currency ?? this.item()?.currency ?? '';
|
||||
});
|
||||
|
||||
effectiveRemaining = computed(() => {
|
||||
const detail = this.selectedDetail();
|
||||
return detail?.remaining ?? this.item()?.quantity ?? null;
|
||||
});
|
||||
|
||||
newReview = {
|
||||
rating: 0,
|
||||
@@ -75,6 +124,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
this.apiService.getItem(itemID).subscribe({
|
||||
next: (item) => {
|
||||
this.item.set(item);
|
||||
this.initVariantSelection(item);
|
||||
this.seoService.setItemMeta(item);
|
||||
this.loading.set(false);
|
||||
},
|
||||
@@ -86,6 +136,33 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
private initVariantSelection(item: Item): void {
|
||||
// Auto-select the first available colour and size from itemDetails
|
||||
const details = item.itemDetails;
|
||||
if (details?.length) {
|
||||
const firstColour = details[0].colour || details[0].color || null;
|
||||
this.selectedColour.set(firstColour);
|
||||
const firstSize = details[0].size || null;
|
||||
this.selectedSize.set(firstSize);
|
||||
} else {
|
||||
this.selectedColour.set(item.colour ?? null);
|
||||
this.selectedSize.set(item.size ?? null);
|
||||
}
|
||||
}
|
||||
|
||||
selectColour(colour: string): void {
|
||||
this.selectedColour.set(colour);
|
||||
// If current size is not available for the new colour, reset to first available
|
||||
const sizes = this.availableSizes();
|
||||
if (sizes.length && this.selectedSize() && !sizes.includes(this.selectedSize()!)) {
|
||||
this.selectedSize.set(sizes[0]);
|
||||
}
|
||||
}
|
||||
|
||||
selectSize(size: string): void {
|
||||
this.selectedSize.set(size);
|
||||
}
|
||||
|
||||
selectPhoto(index: number): void {
|
||||
this.selectedPhotoIndex.set(index);
|
||||
}
|
||||
@@ -93,14 +170,21 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
addToCart(): void {
|
||||
const currentItem = this.item();
|
||||
if (currentItem) {
|
||||
this.cartService.addItem(currentItem.itemID);
|
||||
this.cartService.addItem(currentItem.itemID, 1, {
|
||||
colour: this.selectedColour() ?? undefined,
|
||||
size: this.selectedSize() ?? undefined,
|
||||
price: this.effectivePrice(),
|
||||
currency: this.effectiveCurrency()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getDiscountedPrice(): number {
|
||||
const currentItem = this.item();
|
||||
if (!currentItem) return 0;
|
||||
return getDiscountedPrice(currentItem);
|
||||
const price = this.effectivePrice();
|
||||
const discount = currentItem.discount || 0;
|
||||
return discount > 0 ? price * (1 - discount / 100) : price;
|
||||
}
|
||||
|
||||
// BackOffice integration helpers
|
||||
@@ -115,8 +199,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
||||
getSimpleDescription(): string {
|
||||
const currentItem = this.item();
|
||||
if (!currentItem) return '';
|
||||
const lang = this.languageService.currentLanguage();
|
||||
return getTranslatedField(currentItem, 'simpleDescription', lang);
|
||||
return currentItem.simpleDescription || currentItem.description || '';
|
||||
}
|
||||
|
||||
hasDescriptionFields(): boolean {
|
||||
|
||||
Reference in New Issue
Block a user