Cart: trash/X/plus/minus/lock icons replaced with app-icon. Removed the standalone EmptyCartIconComponent entirely - it was a duplicate 80px shopping-cart glyph with no unique illustration, only ever used in one place; now app-icon name="cart" inline. Language/region selectors: dropdown chevrons (duplicated 3x with identical path data across two components) unified on chevronDown; region pin, locate (crosshair), and globe icons replaced. New mapPin/locate icons added to the registry. Items carousel: rating star and add-to-cart icons replaced. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
114 lines
3.6 KiB
TypeScript
114 lines
3.6 KiB
TypeScript
import { Component, OnInit, signal, ChangeDetectionStrategy, inject } from '@angular/core';
|
|
import { DecimalPipe } from '@angular/common';
|
|
import { RouterLink } from '@angular/router';
|
|
import { CarouselModule } from 'primeng/carousel';
|
|
import { ButtonModule } from 'primeng/button';
|
|
import { TagModule } from 'primeng/tag';
|
|
import { CartService } from '../../services';
|
|
import { Item } from '../../models';
|
|
import { getDiscountedPrice, getMainImage, getBadgeClass, getTranslatedField } from '../../utils/item.utils';
|
|
import { LanguageService } from '../../services/language.service';
|
|
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
|
import { TranslatePipe } from '../../i18n/translate.pipe';
|
|
import { ProductFacade } from '../../facades/platform/product.facade';
|
|
import { IconComponent } from '../../shared/ui/icon/icon.component';
|
|
|
|
@Component({
|
|
selector: 'app-items-carousel',
|
|
templateUrl: './items-carousel.component.html',
|
|
imports: [DecimalPipe, RouterLink, CarouselModule, ButtonModule, TagModule, LangRoutePipe, TranslatePipe, IconComponent],
|
|
styleUrls: ['./items-carousel.component.scss'],
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
})
|
|
export class ItemsCarouselComponent implements OnInit {
|
|
products = signal<Item[]>([]);
|
|
loading = signal(true);
|
|
private readonly productFacade = inject(ProductFacade);
|
|
|
|
responsiveOptions: { breakpoint: string; numVisible: number; numScroll: number }[] | undefined;
|
|
|
|
constructor(
|
|
private cartService: CartService
|
|
) {}
|
|
|
|
ngOnInit() {
|
|
this.productFacade.getFeaturedProducts({ count: 10 }).subscribe({
|
|
next: (result) => {
|
|
this.products.set(result.items);
|
|
this.loading.set(false);
|
|
},
|
|
error: () => {
|
|
this.loading.set(false);
|
|
}
|
|
});
|
|
|
|
this.responsiveOptions = [
|
|
{
|
|
breakpoint: '1400px',
|
|
numVisible: 5,
|
|
numScroll: 1
|
|
},
|
|
{
|
|
breakpoint: '1199px',
|
|
numVisible: 4,
|
|
numScroll: 1
|
|
},
|
|
{
|
|
breakpoint: '991px',
|
|
numVisible: 3,
|
|
numScroll: 1
|
|
},
|
|
{
|
|
breakpoint: '767px',
|
|
numVisible: 2,
|
|
numScroll: 1
|
|
},
|
|
{
|
|
breakpoint: '575px',
|
|
numVisible: 1,
|
|
numScroll: 1
|
|
}
|
|
];
|
|
}
|
|
|
|
getSeverity(remainings: string): 'success' | 'info' | 'warn' | 'danger' | 'secondary' | 'contrast' {
|
|
switch (remainings) {
|
|
case 'high':
|
|
return 'success';
|
|
case 'low':
|
|
return 'warn';
|
|
case 'out':
|
|
return 'danger';
|
|
default:
|
|
return 'success';
|
|
}
|
|
}
|
|
|
|
getInventoryStatus(remainings: string): string {
|
|
switch (remainings) {
|
|
case 'high':
|
|
return 'INSTOCK';
|
|
case 'low':
|
|
return 'LOWSTOCK';
|
|
case 'out':
|
|
return 'OUTOFSTOCK';
|
|
default:
|
|
return 'INSTOCK';
|
|
}
|
|
}
|
|
|
|
readonly getItemImage = getMainImage;
|
|
readonly getDiscountedPrice = getDiscountedPrice;
|
|
readonly getBadgeClass = getBadgeClass;
|
|
|
|
private langService = inject(LanguageService);
|
|
itemName(product: Item): string { return getTranslatedField(product, 'name', this.langService.currentLanguage()); }
|
|
|
|
addToCart(event: Event, item: Item): void {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
this.cartService.addItem(item.itemID, 1);
|
|
}
|
|
}
|
|
|