2026-07-05 01:05:48 +04:00
|
|
|
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
|
|
|
|
import { DecimalPipe } from '@angular/common';
|
|
|
|
|
import { RouterLink } from '@angular/router';
|
2026-07-05 01:36:21 +04:00
|
|
|
import { Product } from '../../core/products/models/product-domain.model';
|
2026-07-05 01:05:48 +04:00
|
|
|
import { LangRoutePipe } from '../../pipes/lang-route.pipe';
|
2026-07-09 02:29:12 +04:00
|
|
|
import { TranslatePipe } from '../../i18n/translate.pipe';
|
2026-07-26 00:12:43 +04:00
|
|
|
import { cleanDescription, getBadgeClass, getDiscountedPrice, getMainImage, onImageError } from '../../utils/item.utils';
|
2026-07-05 01:05:48 +04:00
|
|
|
|
2026-07-19 22:04:13 +04:00
|
|
|
const STOCK_LABEL_KEYS: Record<string, string> = {
|
|
|
|
|
high: 'catalog.stockHigh',
|
|
|
|
|
medium: 'catalog.stockMedium',
|
|
|
|
|
low: 'catalog.stockLow',
|
|
|
|
|
out: 'catalog.stockOut'
|
|
|
|
|
};
|
|
|
|
|
|
2026-07-05 01:05:48 +04:00
|
|
|
export type ProductCardAppearance = 'standard' | 'compact';
|
|
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
|
selector: 'app-product-card',
|
|
|
|
|
standalone: true,
|
2026-07-09 02:29:12 +04:00
|
|
|
imports: [DecimalPipe, RouterLink, LangRoutePipe, TranslatePipe],
|
2026-07-05 01:05:48 +04:00
|
|
|
templateUrl: './product-card.component.html',
|
|
|
|
|
styleUrls: ['./product-card.component.scss'],
|
|
|
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
|
|
|
})
|
|
|
|
|
export class ProductCardComponent {
|
2026-07-05 01:36:21 +04:00
|
|
|
@Input({ required: true }) item!: Product;
|
2026-07-05 01:05:48 +04:00
|
|
|
@Input() title = '';
|
|
|
|
|
@Input() description = '';
|
2026-07-09 02:29:12 +04:00
|
|
|
@Input() addToCartLabel = '';
|
2026-07-05 01:05:48 +04:00
|
|
|
@Input() appearance: ProductCardAppearance = 'standard';
|
|
|
|
|
@Input() showDescription = false;
|
|
|
|
|
@Input() showStock = true;
|
|
|
|
|
@Input() showRating = true;
|
2026-07-09 00:55:50 +04:00
|
|
|
@Input() showDiscountBadge = true;
|
|
|
|
|
@Input() showFavoritePlaceholder = false;
|
|
|
|
|
@Input() showComparePlaceholder = false;
|
|
|
|
|
@Input() showQuickViewPlaceholder = false;
|
2026-07-09 01:13:54 +04:00
|
|
|
@Input() showFavoriteAction = false;
|
|
|
|
|
@Input() showCompareAction = false;
|
|
|
|
|
@Input() showShareAction = false;
|
|
|
|
|
@Input() isFavorite = false;
|
|
|
|
|
@Input() isCompared = false;
|
2026-07-05 01:05:48 +04:00
|
|
|
|
|
|
|
|
@Output() addToCart = new EventEmitter<{ itemID: number; event: Event }>();
|
|
|
|
|
@Output() preview = new EventEmitter<number>();
|
2026-07-05 01:36:21 +04:00
|
|
|
@Output() selected = new EventEmitter<{ itemID: number; event: Event }>();
|
2026-07-09 00:55:50 +04:00
|
|
|
@Output() favoritePlaceholder = new EventEmitter<number>();
|
|
|
|
|
@Output() comparePlaceholder = new EventEmitter<number>();
|
|
|
|
|
@Output() quickViewPlaceholder = new EventEmitter<number>();
|
2026-07-09 01:13:54 +04:00
|
|
|
@Output() favoriteToggled = new EventEmitter<number>();
|
|
|
|
|
@Output() compareToggled = new EventEmitter<number>();
|
|
|
|
|
@Output() shareRequested = new EventEmitter<number>();
|
2026-07-05 01:05:48 +04:00
|
|
|
|
|
|
|
|
readonly getMainImage = getMainImage;
|
|
|
|
|
readonly getDiscountedPrice = getDiscountedPrice;
|
|
|
|
|
readonly getBadgeClass = getBadgeClass;
|
2026-07-19 22:56:12 +04:00
|
|
|
readonly cleanDescription = cleanDescription;
|
2026-07-26 00:12:43 +04:00
|
|
|
readonly onImageError = onImageError;
|
2026-07-05 01:05:48 +04:00
|
|
|
|
|
|
|
|
onAddToCart(event: Event): void {
|
|
|
|
|
this.addToCart.emit({ itemID: this.item.itemID, event });
|
|
|
|
|
}
|
2026-07-05 01:36:21 +04:00
|
|
|
|
|
|
|
|
onSelected(event: Event): void {
|
|
|
|
|
this.selected.emit({ itemID: this.item.itemID, event });
|
|
|
|
|
}
|
2026-07-09 00:55:50 +04:00
|
|
|
|
|
|
|
|
onFavoritePlaceholder(event: Event): void {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
event.stopPropagation();
|
|
|
|
|
this.favoritePlaceholder.emit(this.item.itemID);
|
2026-07-09 01:13:54 +04:00
|
|
|
this.favoriteToggled.emit(this.item.itemID);
|
2026-07-09 00:55:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onComparePlaceholder(event: Event): void {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
event.stopPropagation();
|
|
|
|
|
this.comparePlaceholder.emit(this.item.itemID);
|
2026-07-09 01:13:54 +04:00
|
|
|
this.compareToggled.emit(this.item.itemID);
|
2026-07-09 00:55:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onQuickViewPlaceholder(event: Event): void {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
event.stopPropagation();
|
|
|
|
|
this.quickViewPlaceholder.emit(this.item.itemID);
|
|
|
|
|
}
|
2026-07-09 01:13:54 +04:00
|
|
|
|
|
|
|
|
onShare(event: Event): void {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
event.stopPropagation();
|
|
|
|
|
this.shareRequested.emit(this.item.itemID);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-19 22:04:13 +04:00
|
|
|
stockLabelKey(remainings: string): string {
|
|
|
|
|
return STOCK_LABEL_KEYS[remainings.toLowerCase()] ?? STOCK_LABEL_KEYS['high'];
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-09 01:13:54 +04:00
|
|
|
showFavoriteControl(): boolean {
|
|
|
|
|
return this.showFavoriteAction || this.showFavoritePlaceholder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
showCompareControl(): boolean {
|
|
|
|
|
return this.showCompareAction || this.showComparePlaceholder;
|
|
|
|
|
}
|
2026-07-05 01:05:48 +04:00
|
|
|
}
|