feat(catalog): implement sprint 10 advanced search experience
Some checks failed
Architecture Governance / architecture (push) Has been cancelled

This commit is contained in:
sdarbinyan
2026-07-09 00:55:50 +04:00
parent 3ef0bd711d
commit 1a8f916942
40 changed files with 1917 additions and 70 deletions

View File

@@ -0,0 +1,86 @@
import { Product, ProductListResult, ProductSort } from './product-domain.model';
export type CatalogLayoutMode = 'grid' | 'large-grid' | 'compact-grid' | 'list';
export type CatalogNavigationMode = 'default' | 'left-category-navigation' | 'mega-category-layout' | 'top-category-carousel';
export interface SearchCriteria {
keyword?: string;
categoryIDs?: number[];
subcategoryIDs?: string[];
minPrice?: number;
maxPrice?: number;
availability?: Array<'in-stock' | 'low-stock' | 'out-of-stock'>;
rating?: number[];
brand?: string[];
discountOnly?: boolean;
newOnly?: boolean;
color?: string[];
size?: string[];
attributes?: Record<string, string[]>;
sort?: ProductSort | 'discount';
page?: number;
pageSize?: number;
}
export type FilterValueType = 'multi-select' | 'range' | 'toggle';
export interface FilterOption {
id: string;
label: string;
value: string;
count?: number;
}
export interface FilterDefinition {
id: string;
label: string;
type: FilterValueType;
options?: FilterOption[];
min?: number;
max?: number;
step?: number;
enabled?: boolean;
}
export interface SortDefinition {
id: ProductSort | 'discount';
label: string;
enabled?: boolean;
}
export interface CatalogView {
layout: CatalogLayoutMode;
navigationMode: CatalogNavigationMode;
showBreadcrumbs: boolean;
showCategoryBanner: boolean;
showSubcategoryChips: boolean;
showRatings: boolean;
showDiscounts: boolean;
showAvailability: boolean;
}
export interface SearchResult {
criteria: SearchCriteria;
items: Product[];
total: number;
page: number;
pageSize: number;
summary: string;
}
export function toSearchResult(result: ProductListResult, criteria: SearchCriteria): SearchResult {
const pageSize = Math.max(1, criteria.pageSize ?? result.count ?? 24);
const page = Math.max(1, criteria.page ?? Math.floor((result.skip ?? 0) / pageSize) + 1);
const keyword = (criteria.keyword ?? '').trim();
return {
criteria,
items: result.items,
total: result.total,
page,
pageSize,
summary: keyword.length > 0
? `Results for "${keyword}" (${result.total})`
: `Products found: ${result.total}`
};
}