Polish marketplace search states
This commit is contained in:
@@ -131,6 +131,7 @@ export const en: Translations = {
|
||||
loadingMore: 'Loading...',
|
||||
allLoaded: 'All results loaded',
|
||||
emptyState: 'Enter a query to search for products',
|
||||
minLength: 'Enter at least {{count}} characters to search',
|
||||
of: 'of',
|
||||
},
|
||||
category: {
|
||||
|
||||
@@ -131,6 +131,7 @@ export const hy: Translations = {
|
||||
loadingMore: 'Բեռնում...',
|
||||
allLoaded: 'Բոլոր արդյունքները բեռնված են',
|
||||
emptyState: 'Մուտքագրեք հարցում որոնման համար',
|
||||
minLength: 'Որոնման համար մուտքագրեք առնվազն {{count}} նիշ',
|
||||
of: '-ից',
|
||||
},
|
||||
category: {
|
||||
|
||||
@@ -131,6 +131,7 @@ export const ru: Translations = {
|
||||
loadingMore: 'Загрузка...',
|
||||
allLoaded: 'Все результаты загружены',
|
||||
emptyState: 'Введите запрос для поиска товаров',
|
||||
minLength: 'Введите минимум {{count}} символа для поиска',
|
||||
of: 'из',
|
||||
},
|
||||
category: {
|
||||
|
||||
@@ -129,6 +129,7 @@ export interface Translations {
|
||||
loadingMore: string;
|
||||
allLoaded: string;
|
||||
emptyState: string;
|
||||
minLength: string;
|
||||
of: string;
|
||||
};
|
||||
category: {
|
||||
|
||||
@@ -39,11 +39,23 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (!loading() && searchQuery && items().length === 0 && !error()) {
|
||||
@if (isQueryTooShort()) {
|
||||
<div class="empty-state">
|
||||
<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>
|
||||
<p>{{ 'search.minLength' | translate:{ count: minSearchLength } }}</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (!loading() && searchQuery && !isQueryTooShort() && items().length === 0 && !error()) {
|
||||
<div class="no-results">
|
||||
<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="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="#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>
|
||||
|
||||
@@ -21,6 +21,7 @@ import { ProductCardComponent } from '../../components/product-card/product-card
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class SearchComponent implements OnDestroy {
|
||||
readonly minSearchLength = 3;
|
||||
searchQuery = '';
|
||||
items = signal<Item[]>([]);
|
||||
loading = signal(false);
|
||||
@@ -60,17 +61,23 @@ export class SearchComponent implements OnDestroy {
|
||||
|
||||
onSearchInput(query: string): void {
|
||||
this.searchQuery = query;
|
||||
this.error.set(null);
|
||||
|
||||
if (this.isQueryTooShort()) {
|
||||
this.resetSearchState();
|
||||
return;
|
||||
}
|
||||
|
||||
this.searchSubject.next(query);
|
||||
}
|
||||
|
||||
performSearch(query: string): void {
|
||||
if (!query.trim()) {
|
||||
this.items.set([]);
|
||||
this.hasMore.set(false);
|
||||
this.totalResults.set(0);
|
||||
this.resetSearchState();
|
||||
return;
|
||||
}
|
||||
|
||||
this.error.set(null);
|
||||
this.items.set([]);
|
||||
this.skip = 0;
|
||||
this.hasMore.set(true);
|
||||
@@ -84,7 +91,7 @@ export class SearchComponent implements OnDestroy {
|
||||
this.loading.set(true);
|
||||
this.isLoadingMore = true;
|
||||
|
||||
this.productFacade.searchProducts({ search: this.searchQuery, count: this.count, skip: this.skip }).subscribe({
|
||||
this.productFacade.searchProducts({ search: this.searchQuery.trim(), count: this.count, skip: this.skip }).subscribe({
|
||||
next: (response) => {
|
||||
// Update total results (only on first load)
|
||||
if (this.skip === 0) {
|
||||
@@ -114,6 +121,20 @@ export class SearchComponent implements OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
private resetSearchState(): void {
|
||||
this.items.set([]);
|
||||
this.loading.set(false);
|
||||
this.hasMore.set(false);
|
||||
this.totalResults.set(0);
|
||||
this.skip = 0;
|
||||
this.isLoadingMore = false;
|
||||
}
|
||||
|
||||
isQueryTooShort(): boolean {
|
||||
const length = this.searchQuery.trim().length;
|
||||
return length > 0 && length < this.minSearchLength;
|
||||
}
|
||||
|
||||
private scrollTimeout?: ReturnType<typeof setTimeout>;
|
||||
|
||||
@HostListener('window:scroll')
|
||||
|
||||
Reference in New Issue
Block a user