Add reusable marketplace product card

This commit is contained in:
sdarbinyan
2026-07-05 01:05:48 +04:00
parent ae3512ad37
commit d7d73c2a10
7 changed files with 332 additions and 106 deletions

View File

@@ -9,53 +9,13 @@
@if (!error()) {
<div class="items-grid">
@for (item of items(); track trackByItemId($index, item)) {
<div class="item-card" (mouseenter)="onItemHover(item.itemID)">
<a [routerLink]="['/item', item.itemID] | langRoute" class="item-link">
<div class="item-image">
<img [src]="getMainImage(item)" [alt]="itemName(item)" loading="lazy" decoding="async" width="300" height="300" />
@if (item.discount > 0) {
<div class="discount-badge">-{{ item.discount }}%</div>
}
@if (item.badges && item.badges.length > 0) {
<div class="item-badges-overlay">
@for (badge of item.badges; track badge) {
<span class="item-badge" [class]="getBadgeClass(badge)">{{ badge }}</span>
}
</div>
}
</div>
<div class="item-details">
<h3 class="item-name">{{ itemName(item) }}</h3>
<div class="item-rating">
<span class="rating-stars">⭐ {{ item.rating }}</span>
<span class="rating-count">({{ item.callbacks?.length || 0 }})</span>
</div>
<div class="item-price">
@if (item.discount > 0) {
<span class="original-price">{{ item.price }} {{ item.currency }}</span>
<span class="discounted-price">{{ getDiscountedPrice(item) | number:'1.2-2' }} {{ item.currency }}</span>
} @else {
<span class="current-price">{{ item.price }} {{ item.currency }}</span>
}
</div>
<div class="item-stock">
<div class="stock-bar">
<span class="bar-segment" [class.filled]="item.remainings === 'high' || item.remainings === 'medium' || item.remainings === 'low'" [class.high]="item.remainings === 'high'" [class.medium]="item.remainings === 'medium'" [class.low]="item.remainings === 'low'"></span>
<span class="bar-segment" [class.filled]="item.remainings === 'high' || item.remainings === 'medium'" [class.high]="item.remainings === 'high'" [class.medium]="item.remainings === 'medium'"></span>
<span class="bar-segment" [class.filled]="item.remainings === 'high'" [class.high]="item.remainings === 'high'"></span>
</div>
</div>
</div>
</a>
<button class="add-to-cart-btn" (click)="addToCart(item.itemID, $event)" [attr.aria-label]="('category.addToCart' | translate) + ': ' + item.name">
{{ 'category.addToCart' | translate }}
</button>
</div>
<app-product-card
[item]="item"
[title]="itemName(item)"
[addToCartLabel]="'category.addToCart' | translate"
(addToCart)="addToCart($event.itemID, $event.event)"
(preview)="onItemHover($event)"
/>
}
@if (loading() && items().length > 0) {

View File

@@ -1,5 +1,4 @@
import { Component, OnInit, OnDestroy, signal, HostListener, ChangeDetectionStrategy, inject } from '@angular/core';
import { DecimalPipe } from '@angular/common';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { CartService } from '../../services';
import { PrefetchService } from '../../services/prefetch.service';
@@ -11,10 +10,11 @@ import { LangRoutePipe } from '../../pipes/lang-route.pipe';
import { TranslatePipe } from '../../i18n/translate.pipe';
import { SCROLL_THRESHOLD_PX, SCROLL_DEBOUNCE_MS, ITEMS_PER_PAGE } from '../../config/constants';
import { ProductFacade } from '../../facades/platform/product.facade';
import { ProductCardComponent } from '../../components/product-card/product-card.component';
@Component({
selector: 'app-category',
imports: [DecimalPipe, RouterLink, LangRoutePipe, TranslatePipe],
imports: [RouterLink, LangRoutePipe, TranslatePipe, ProductCardComponent],
templateUrl: './category.component.html',
styleUrls: ['./category.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush