2026-01-18 18:57:06 +04:00
|
|
|
<div class="search-container">
|
|
|
|
|
<div class="search-header">
|
2026-02-26 23:09:20 +04:00
|
|
|
<h1>{{ 'search.title' | translate }}</h1>
|
2026-01-18 18:57:06 +04:00
|
|
|
<div class="search-box">
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
[(ngModel)]="searchQuery"
|
|
|
|
|
(input)="onSearchInput(searchQuery)"
|
2026-02-26 23:09:20 +04:00
|
|
|
[placeholder]="'search.placeholder' | translate"
|
2026-01-18 18:57:06 +04:00
|
|
|
class="search-input"
|
|
|
|
|
autofocus
|
|
|
|
|
/>
|
2026-02-14 02:34:11 +04:00
|
|
|
<span class="search-icon">
|
|
|
|
|
<svg width="22" height="22" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
|
|
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4ZM2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12Z" fill="#697777" />
|
|
|
|
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.2929 18.2929C18.6834 17.9024 19.3166 17.9024 19.7071 18.2929L25.7071 24.2929C26.0976 24.6834 26.0976 25.3166 25.7071 25.7071C25.3166 26.0976 24.6834 26.0976 24.2929 25.7071L18.2929 19.7071C17.9024 19.3166 17.9024 18.6834 18.2929 18.2929Z" fill="#697777" />
|
|
|
|
|
</svg>
|
|
|
|
|
</span>
|
2026-01-18 18:57:06 +04:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
@if (searchQuery && items().length > 0) {
|
|
|
|
|
<div class="results-count">
|
2026-02-26 23:09:20 +04:00
|
|
|
{{ 'search.resultsCount' | translate }} {{ items().length }}@if (totalResults() > items().length) { {{ 'search.of' | translate }} {{ totalResults() }} }
|
2026-01-18 18:57:06 +04:00
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@if (loading() && items().length === 0) {
|
|
|
|
|
<div class="loading-initial">
|
|
|
|
|
<div class="spinner"></div>
|
2026-02-26 23:09:20 +04:00
|
|
|
<p>{{ 'search.searching' | translate }}</p>
|
2026-01-18 18:57:06 +04:00
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@if (error()) {
|
|
|
|
|
<div class="error">
|
|
|
|
|
<p>{{ error() }}</p>
|
2026-02-26 23:09:20 +04:00
|
|
|
<button (click)="performSearch(searchQuery)">{{ 'search.retry' | translate }}</button>
|
2026-01-18 18:57:06 +04:00
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@if (!loading() && searchQuery && items().length === 0 && !error()) {
|
|
|
|
|
<div class="no-results">
|
2026-02-14 02:34:11 +04:00
|
|
|
<div class="no-results-icon">
|
|
|
|
|
<svg width="48" height="48" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
|
|
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4ZZ2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12Z" fill="#a1b4b5" />
|
|
|
|
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.2929 18.2929C18.6834 17.9024 19.3166 17.9024 19.7071 18.2929L25.7071 24.2929C26.0976 24.6834 26.0976 25.3166 25.7071 25.7071C25.3166 26.0976 24.6834 26.0976 24.2929 25.7071L18.2929 19.7071C17.9024 19.3166 17.9024 18.6834 18.2929 18.2929Z" fill="#a1b4b5" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
2026-02-26 23:09:20 +04:00
|
|
|
<h2>{{ 'search.noResults' | translate }}</h2>
|
|
|
|
|
<p>{{ 'search.noResultsFor' | translate:{ query: searchQuery } }}</p>
|
|
|
|
|
<p class="hint">{{ 'search.noResultsHint' | translate }}</p>
|
2026-01-18 18:57:06 +04:00
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@if (items().length > 0) {
|
|
|
|
|
<div class="items-grid">
|
|
|
|
|
@for (item of items(); track trackByItemId($index, item)) {
|
|
|
|
|
<div class="item-card">
|
2026-02-26 22:23:08 +04:00
|
|
|
<a [routerLink]="['/item', item.itemID] | langRoute" class="item-link">
|
2026-01-18 18:57:06 +04:00
|
|
|
<div class="item-image">
|
|
|
|
|
<img [src]="getMainImage(item)" [alt]="item.name" loading="lazy" decoding="async" width="300" height="300" />
|
|
|
|
|
@if (item.discount > 0) {
|
|
|
|
|
<div class="discount-badge">-{{ item.discount }}%</div>
|
|
|
|
|
}
|
2026-02-20 10:44:03 +04:00
|
|
|
@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>
|
|
|
|
|
}
|
2026-01-18 18:57:06 +04:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="item-details">
|
|
|
|
|
<h3 class="item-name">{{ item.name }}</h3>
|
|
|
|
|
|
2026-02-20 10:44:03 +04:00
|
|
|
@if (item.simpleDescription) {
|
|
|
|
|
<p class="item-simple-desc">{{ item.simpleDescription }}</p>
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-18 18:57:06 +04:00
|
|
|
<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>
|
|
|
|
|
|
|
|
|
|
@if (item.remainings) {
|
|
|
|
|
<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)">
|
2026-02-26 23:09:20 +04:00
|
|
|
{{ 'search.addToCart' | translate }}
|
2026-01-18 18:57:06 +04:00
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
@if (loading() && items().length > 0) {
|
|
|
|
|
<div class="loading-more">
|
|
|
|
|
<div class="spinner"></div>
|
2026-02-26 23:09:20 +04:00
|
|
|
<p>{{ 'search.loadingMore' | translate }}</p>
|
2026-01-18 18:57:06 +04:00
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@if (!hasMore() && items().length > 0) {
|
|
|
|
|
<div class="no-more">
|
2026-02-26 23:09:20 +04:00
|
|
|
<p>{{ 'search.allLoaded' | translate }}</p>
|
2026-01-18 18:57:06 +04:00
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@if (!searchQuery) {
|
|
|
|
|
<div class="empty-state">
|
2026-02-14 18:38:25 +04:00
|
|
|
<div class="empty-state-icon">
|
|
|
|
|
<svg width="56" height="56" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
|
|
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4ZM2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12Z" fill="#d3dad9" />
|
|
|
|
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.2929 18.2929C18.6834 17.9024 19.3166 17.9024 19.7071 18.2929L25.7071 24.2929C26.0976 24.6834 26.0976 25.3166 25.7071 25.7071C25.3166 26.0976 24.6834 26.0976 24.2929 25.7071L18.2929 19.7071C17.9024 19.3166 17.9024 18.6834 18.2929 18.2929Z" fill="#d3dad9" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
2026-02-26 23:09:20 +04:00
|
|
|
<p>{{ 'search.emptyState' | translate }}</p>
|
2026-01-18 18:57:06 +04:00
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
</div>
|