From 3f5aa2af2a8bca16b7854edeaecec5c0b28a7a6b Mon Sep 17 00:00:00 2001 From: sdarbinyan Date: Sun, 5 Jul 2026 01:10:56 +0400 Subject: [PATCH] Polish marketplace search states --- src/app/i18n/en.ts | 1 + src/app/i18n/hy.ts | 1 + src/app/i18n/ru.ts | 1 + src/app/i18n/translations.ts | 1 + src/app/pages/search/search.component.html | 16 ++++++++++-- src/app/pages/search/search.component.ts | 29 +++++++++++++++++++--- 6 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/app/i18n/en.ts b/src/app/i18n/en.ts index 60bfc76..866afda 100644 --- a/src/app/i18n/en.ts +++ b/src/app/i18n/en.ts @@ -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: { diff --git a/src/app/i18n/hy.ts b/src/app/i18n/hy.ts index 7b507c1..fc97da6 100644 --- a/src/app/i18n/hy.ts +++ b/src/app/i18n/hy.ts @@ -131,6 +131,7 @@ export const hy: Translations = { loadingMore: 'Բեռնում...', allLoaded: 'Բոլոր արդյունքները բեռնված են', emptyState: 'Մուտքագրեք հարցում որոնման համար', + minLength: 'Որոնման համար մուտքագրեք առնվազն {{count}} նիշ', of: '-ից', }, category: { diff --git a/src/app/i18n/ru.ts b/src/app/i18n/ru.ts index d101b91..ea5673f 100644 --- a/src/app/i18n/ru.ts +++ b/src/app/i18n/ru.ts @@ -131,6 +131,7 @@ export const ru: Translations = { loadingMore: 'Загрузка...', allLoaded: 'Все результаты загружены', emptyState: 'Введите запрос для поиска товаров', + minLength: 'Введите минимум {{count}} символа для поиска', of: 'из', }, category: { diff --git a/src/app/i18n/translations.ts b/src/app/i18n/translations.ts index b02b479..39c2203 100644 --- a/src/app/i18n/translations.ts +++ b/src/app/i18n/translations.ts @@ -129,6 +129,7 @@ export interface Translations { loadingMore: string; allLoaded: string; emptyState: string; + minLength: string; of: string; }; category: { diff --git a/src/app/pages/search/search.component.html b/src/app/pages/search/search.component.html index 80f898a..3c0124b 100644 --- a/src/app/pages/search/search.component.html +++ b/src/app/pages/search/search.component.html @@ -39,11 +39,23 @@ } - @if (!loading() && searchQuery && items().length === 0 && !error()) { + @if (isQueryTooShort()) { +
+
+ + + + +
+

{{ 'search.minLength' | translate:{ count: minSearchLength } }}

+
+ } + + @if (!loading() && searchQuery && !isQueryTooShort() && items().length === 0 && !error()) {
- +
diff --git a/src/app/pages/search/search.component.ts b/src/app/pages/search/search.component.ts index 637536d..1c44469 100644 --- a/src/app/pages/search/search.component.ts +++ b/src/app/pages/search/search.component.ts @@ -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([]); 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; @HostListener('window:scroll')