search engien
This commit is contained in:
@@ -1,27 +1 @@
|
||||
import { CatalogLayoutMode } from '../../products/models/catalog-experience.model';
|
||||
import { ProductSort } from '../../products/models/product-domain.model';
|
||||
import { SearchFilterState } from './search.model';
|
||||
|
||||
export interface SearchState {
|
||||
text: string;
|
||||
sort: ProductSort | 'discount';
|
||||
layout: CatalogLayoutMode;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
filters: SearchFilterState;
|
||||
}
|
||||
|
||||
export function createInitialSearchState(pageSize = 24): SearchState {
|
||||
return {
|
||||
text: '',
|
||||
sort: 'relevance',
|
||||
layout: 'grid',
|
||||
page: 1,
|
||||
pageSize,
|
||||
filters: {
|
||||
values: {},
|
||||
ranges: {},
|
||||
toggles: {},
|
||||
},
|
||||
};
|
||||
}
|
||||
export * from '../../../features/search/models/search-state.model';
|
||||
|
||||
@@ -1,76 +1 @@
|
||||
import { Product, ProductSort } from '../../products/models/product-domain.model';
|
||||
|
||||
export type SearchFilterType =
|
||||
| 'checkbox'
|
||||
| 'radio'
|
||||
| 'toggle'
|
||||
| 'range'
|
||||
| 'slider'
|
||||
| 'color'
|
||||
| 'size'
|
||||
| 'rating'
|
||||
| 'availability';
|
||||
|
||||
export interface SearchQuery {
|
||||
text: string;
|
||||
categoryIds: number[];
|
||||
subcategoryIds: string[];
|
||||
filters: SearchFilterState;
|
||||
sort: ProductSort | 'discount';
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
export interface SearchResult<TItem = Product> {
|
||||
query: SearchQuery;
|
||||
items: TItem[];
|
||||
total: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
export interface FilterOption {
|
||||
id: string;
|
||||
label: string;
|
||||
value: string;
|
||||
count?: number;
|
||||
colorHex?: string;
|
||||
availability?: 'in-stock' | 'low-stock' | 'out-of-stock';
|
||||
rating?: number;
|
||||
}
|
||||
|
||||
export interface FilterGroup {
|
||||
id: string;
|
||||
label: string;
|
||||
type: SearchFilterType;
|
||||
options: FilterOption[];
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface SortOption {
|
||||
id: ProductSort | 'discount';
|
||||
label: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface SearchSuggestion {
|
||||
id: string;
|
||||
text: string;
|
||||
kind: 'live' | 'recent' | 'popular';
|
||||
}
|
||||
|
||||
export interface SearchHistory {
|
||||
items: string[];
|
||||
recent: string[];
|
||||
popular: string[];
|
||||
}
|
||||
|
||||
export interface SearchFilterState {
|
||||
values: Record<string, string[]>;
|
||||
ranges: Record<string, { min?: number; max?: number }>;
|
||||
toggles: Record<string, boolean>;
|
||||
}
|
||||
export * from '../../../features/search/models/search.model';
|
||||
|
||||
@@ -1,76 +1 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SearchHistory } from '../models/search.model';
|
||||
|
||||
const STORAGE_KEY = 'marketplace.catalog.search.history';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class SearchHistoryService {
|
||||
private readonly maxSize = 10;
|
||||
|
||||
getHistory(): string[] {
|
||||
if (typeof window === 'undefined') {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const raw = localStorage.getItem(STORAGE_KEY);
|
||||
if (!raw) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const parsed = JSON.parse(raw);
|
||||
return Array.isArray(parsed)
|
||||
? parsed.filter((entry): entry is string => typeof entry === 'string' && entry.trim().length > 0)
|
||||
: [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
getSnapshot(popular: string[]): SearchHistory {
|
||||
const items = this.getHistory();
|
||||
return {
|
||||
items,
|
||||
recent: items.slice(0, 5),
|
||||
popular,
|
||||
};
|
||||
}
|
||||
|
||||
push(term: string, popular: string[]): SearchHistory {
|
||||
const normalized = term.trim();
|
||||
if (!normalized.length) {
|
||||
return this.getSnapshot(popular);
|
||||
}
|
||||
|
||||
const history = [normalized, ...this.getHistory().filter(entry => entry.toLowerCase() !== normalized.toLowerCase())]
|
||||
.slice(0, this.maxSize);
|
||||
|
||||
this.save(history);
|
||||
|
||||
return {
|
||||
items: history,
|
||||
recent: history.slice(0, 5),
|
||||
popular,
|
||||
};
|
||||
}
|
||||
|
||||
clear(popular: string[]): SearchHistory {
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.removeItem(STORAGE_KEY);
|
||||
}
|
||||
|
||||
return {
|
||||
items: [],
|
||||
recent: [],
|
||||
popular,
|
||||
};
|
||||
}
|
||||
|
||||
private save(history: string[]): void {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(history));
|
||||
}
|
||||
}
|
||||
export { SearchHistoryService } from '../../../features/search/services/search-history.service';
|
||||
|
||||
Reference in New Issue
Block a user