feat(catalog): implement sprint 10 advanced search experience
Some checks failed
Architecture Governance / architecture (push) Has been cancelled

This commit is contained in:
sdarbinyan
2026-07-09 00:55:50 +04:00
parent 3ef0bd711d
commit 1a8f916942
40 changed files with 1917 additions and 70 deletions

View File

@@ -2,9 +2,27 @@
<a [routerLink]="['/product', item.itemID] | langRoute" class="product-link" (click)="onSelected($event)">
<div class="product-image">
<img [src]="getMainImage(item)" [alt]="title || item.name" loading="lazy" decoding="async" width="300" height="300" />
@if (item.discount > 0) {
@if (showDiscountBadge && item.discount > 0) {
<div class="discount-badge">-{{ item.discount }}%</div>
}
@if (showStock && item.remainings) {
<span class="stock-badge" [class.out]="item.remainings === 'out'">{{ item.remainings }}</span>
}
@if (showFavoritePlaceholder || showComparePlaceholder || showQuickViewPlaceholder) {
<div class="product-actions-overlay">
@if (showFavoritePlaceholder) {
<button type="button" (click)="onFavoritePlaceholder($event)">Fav</button>
}
@if (showComparePlaceholder) {
<button type="button" (click)="onComparePlaceholder($event)">Compare</button>
}
@if (showQuickViewPlaceholder) {
<button type="button" (click)="onQuickViewPlaceholder($event)">Quick</button>
}
</div>
}
@if (item.badges && item.badges.length > 0) {
<div class="product-badges-overlay">
@for (badge of item.badges; track badge) {

View File

@@ -60,6 +60,48 @@
z-index: 1;
}
.stock-badge {
position: absolute;
right: 12px;
bottom: 12px;
z-index: 1;
min-height: 22px;
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: 999px;
background: rgba(22, 163, 74, 0.9);
color: #fff;
font-size: 0.72rem;
font-weight: 700;
text-transform: capitalize;
}
.stock-badge.out {
background: rgba(239, 68, 68, 0.9);
}
.product-actions-overlay {
position: absolute;
right: 12px;
top: 44px;
z-index: 2;
display: grid;
gap: 6px;
}
.product-actions-overlay button {
min-height: 24px;
border: 1px solid rgba(30, 60, 56, 0.15);
border-radius: 999px;
background: rgba(255, 255, 255, 0.9);
color: #1e3c38;
font-size: 0.72rem;
font-weight: 700;
padding: 0 8px;
cursor: pointer;
}
.product-badges-overlay {
position: absolute;
left: 10px;

View File

@@ -24,10 +24,17 @@ export class ProductCardComponent {
@Input() showDescription = false;
@Input() showStock = true;
@Input() showRating = true;
@Input() showDiscountBadge = true;
@Input() showFavoritePlaceholder = false;
@Input() showComparePlaceholder = false;
@Input() showQuickViewPlaceholder = false;
@Output() addToCart = new EventEmitter<{ itemID: number; event: Event }>();
@Output() preview = new EventEmitter<number>();
@Output() selected = new EventEmitter<{ itemID: number; event: Event }>();
@Output() favoritePlaceholder = new EventEmitter<number>();
@Output() comparePlaceholder = new EventEmitter<number>();
@Output() quickViewPlaceholder = new EventEmitter<number>();
readonly getMainImage = getMainImage;
readonly getDiscountedPrice = getDiscountedPrice;
@@ -40,4 +47,22 @@ export class ProductCardComponent {
onSelected(event: Event): void {
this.selected.emit({ itemID: this.item.itemID, event });
}
onFavoritePlaceholder(event: Event): void {
event.preventDefault();
event.stopPropagation();
this.favoritePlaceholder.emit(this.item.itemID);
}
onComparePlaceholder(event: Event): void {
event.preventDefault();
event.stopPropagation();
this.comparePlaceholder.emit(this.item.itemID);
}
onQuickViewPlaceholder(event: Event): void {
event.preventDefault();
event.stopPropagation();
this.quickViewPlaceholder.emit(this.item.itemID);
}
}