fix(catalog): filter UX and tablet layout
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
</div>
|
||||
|
||||
@for (filter of definitions; track filter.id) {
|
||||
@if (filter.enabled) {
|
||||
@if (shouldRenderFilter(filter)) {
|
||||
<section class="filter-group">
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -30,6 +30,24 @@ export class CatalogFiltersPanelComponent {
|
||||
return this.collapsed()[filterId] ?? false;
|
||||
}
|
||||
|
||||
shouldRenderFilter(filter: FilterGroup): boolean {
|
||||
if (!filter.enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filter.type === 'range' || filter.type === 'slider') {
|
||||
const min = Number(filter.min ?? 0);
|
||||
const max = Number(filter.max ?? 0);
|
||||
return Number.isFinite(min) && Number.isFinite(max) && min < max;
|
||||
}
|
||||
|
||||
if (filter.type === 'toggle') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (filter.options?.length ?? 0) > 1;
|
||||
}
|
||||
|
||||
isSelected(filterId: string, optionValue: string): boolean {
|
||||
return (this.state.values[filterId] ?? []).includes(optionValue);
|
||||
}
|
||||
|
||||
@@ -84,6 +84,13 @@
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.catalog-products-section {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.catalog-left-panel {
|
||||
position: sticky;
|
||||
top: 16px;
|
||||
|
||||
@@ -120,6 +120,7 @@ export class CatalogContainerComponent {
|
||||
private dataSubscription?: Subscription;
|
||||
private readonly backendFetchSize = 200;
|
||||
private pendingScrollY: number | null = null;
|
||||
private restoringScrollFromUrlSync = false;
|
||||
private syncingUrl = false;
|
||||
|
||||
constructor() {
|
||||
@@ -522,14 +523,14 @@ export class CatalogContainerComponent {
|
||||
layoutLabelKey(layout: CatalogLayoutMode): string {
|
||||
switch (layout) {
|
||||
case 'grid':
|
||||
return 'catalog.layout.grid';
|
||||
return 'catalog.layoutGrid';
|
||||
case 'large-grid':
|
||||
return 'catalog.layout.largeGrid';
|
||||
return 'catalog.layoutLargeGrid';
|
||||
case 'compact-grid':
|
||||
return 'catalog.layout.compactGrid';
|
||||
return 'catalog.layoutCompactGrid';
|
||||
case 'list':
|
||||
default:
|
||||
return 'catalog.layout.list';
|
||||
return 'catalog.layoutList';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,12 +692,23 @@ export class CatalogContainerComponent {
|
||||
|
||||
private syncUrlFromState(): void {
|
||||
const queryParams = this.searchFacade.toQueryParams(this.toSearchState());
|
||||
const scrollY = typeof window !== 'undefined' ? window.scrollY : null;
|
||||
|
||||
this.syncingUrl = true;
|
||||
void this.router.navigate([], {
|
||||
relativeTo: this.route,
|
||||
queryParams,
|
||||
replaceUrl: true,
|
||||
}).finally(() => {
|
||||
if (scrollY != null && typeof window !== 'undefined') {
|
||||
this.restoringScrollFromUrlSync = true;
|
||||
const target = Math.max(0, scrollY);
|
||||
requestAnimationFrame(() => {
|
||||
window.scrollTo({ top: target, behavior: 'auto' });
|
||||
this.restoringScrollFromUrlSync = false;
|
||||
});
|
||||
}
|
||||
|
||||
this.syncingUrl = false;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user