# Catalog Module Report ## Scope Sprint 5 added a Catalog Module on the frozen platform architecture. No backend APIs, authentication, payment, or bootstrap contracts were changed. The catalog uses existing domain boundaries: - Category data: `CategoryFacade` -> `CategoryService` -> Category Repository -> existing `GET /category` - Product data: `ProductFacade` -> `ProductDataService` -> Product Provider -> existing product/category item endpoints ## Implemented Module ### Catalog Container - `src/app/features/website/catalog/containers/catalog-container.component.ts` - `src/app/features/website/catalog/containers/catalog-container.component.html` - `src/app/features/website/catalog/containers/catalog-container.component.scss` Responsibilities implemented: - Reads the route category id. - Requests category data through `CategoryFacade` only. - Requests product data through `ProductFacade` only. - Determines whether the current category has child categories. - Renders category grid when child categories exist. - Renders product grid when no child categories exist. - Supports root catalog entry with root categories. - Handles loading, empty, and error states. - Cancels prior category/product data subscriptions when the route changes. No `HttpClient`, backend DTO, auth, payment, bootstrap, or tenant-specific logic is used in the container. ### Category Grid - `src/app/features/website/catalog/components/category-grid/category-grid.component.ts` - `src/app/features/website/catalog/components/category-grid/category-grid.component.html` - `src/app/features/website/catalog/components/category-grid/category-grid.component.scss` Reusable category grid implemented with: - Input: `Category[]` - Output: selected `Category` - Responsive grid layout - Domain model only - No data fetching - No backend DTOs ### Product Grid - `src/app/features/website/catalog/components/product-grid/product-grid.component.ts` - `src/app/features/website/catalog/components/product-grid/product-grid.component.html` - `src/app/features/website/catalog/components/product-grid/product-grid.component.scss` Reusable product grid implemented with: - Input: `Product[]` - Output: selected `Product` - Output: add-to-cart payload - Output: product preview id - Responsive grid layout - Uses existing reusable product card - No `HttpClient` - No backend DTOs ### Product Card Compatibility - `src/app/components/product-card/product-card.component.ts` - `src/app/components/product-card/product-card.component.html` Updated the reusable product card to depend on the Product Domain type and added an explicit selected output. The product card remains input/output-only and does not use services, storage, `HttpClient`, or environment configuration. It displays image, title, price, discount, badges, and stock. ### Catalog State - `src/app/features/website/catalog/models/catalog-state.model.ts` Prepared future state architecture for: - Category - Search - Sort - Price range - Attributes - Pagination - Filters Backend filtering was intentionally not implemented in this sprint. ## Navigation Updated routes in `src/app/app.routes.ts`: - `/catalog` - `/catalog/:id` Both routes load the same catalog container. Legacy category URLs redirect to the catalog route: - `/category/:id` -> `/catalog/:id` - `/category/:id/items` -> `/catalog/:id` Home category links now point to `/catalog/:id`. ## Unlimited Category Depth Unlimited nesting is supported by the Category Domain tree utilities from Sprint 4. The catalog container does not assume a fixed depth. For any category id, it asks `CategoryFacade.getChildren(categoryId)`: - if children exist, it renders the category grid - if no children exist, it loads the product grid This same decision repeats for every category route depth. ## Localization Added catalog translations in: - `src/app/i18n/en.ts` - `src/app/i18n/ru.ts` - `src/app/i18n/hy.ts` - `src/app/i18n/translations.ts` ## Validation Completed checks: - Unlimited category depth is supported through facade child lookup and recursive category domain tree utilities. - Product grid is reusable and consumes `Product[]`. - Category grid is reusable and consumes `Category[]`. - Catalog components use domain models only. - Catalog data requests go through facades only. - DTOs remain isolated outside the catalog module. - Catalog module has no `HttpClient` usage. - Product card has no services, storage, `HttpClient`, or environment usage. - Authentication was not modified. - Payment was not modified. - Bootstrap contracts were not modified. - Backend APIs were not modified. Build validation passed: ```bash npm run build ``` ## Stop Point Catalog Module implementation is complete for Sprint 5. Stop here for approval before starting the next module or any Builder/Backoffice work. ## Sprint 10.2 Catalog UX Polish Sprint 10.2 improves catalog UX and responsiveness without changing facades, business logic, bootstrap flow, runtime architecture, routing, authentication, or payment. ### Empty State Behavior Two separate states are now rendered in the catalog container: - Empty category state (`rawProducts.length === 0`): - hides filter/sort/layout/result controls - shows dedicated empty category component with icon, category context, friendly message, and "Browse Categories" action - Filtered empty state (`rawProducts.length > 0 && products.length === 0`): - shows "no filter match" message - provides "Clear Filters" action - keeps filter access available (sidebar on desktop, drawer trigger on tablet/mobile) ### Mobile Filter Drawer - Desktop keeps visible sticky sidebar filters. - Tablet and mobile switch to a drawer-based filter UI. - Drawer includes filter groups, Reset, and Apply actions. - Apply closes the drawer. - Accessibility: - drawer uses dialog semantics (`role="dialog"`, `aria-modal="true"`) - focus trap is enabled while drawer is open - `Esc` closes the drawer ### Mobile Sort - Desktop keeps dropdown sort control. - Tablet keeps compact dropdown with drawer-based filters. - Mobile opens a bottom-sheet sort modal. - Supported mobile sort options: - Recommended - Newest - Price Low -> High - Price High -> Low - Rating - Popularity ### Responsive Grid Modes and Toolbar - Grid selector uses icon buttons and keeps active-state highlighting. - Mobile sticky toolbar added with quick actions: - Filters - Sort - Grid cycle - Grid cycle rotates through supported layouts while preserving existing layout architecture. ### Responsive Spacing and Overflow Catalog spacing and controls were polished for desktop/tablet/mobile: - filter/input/button spacing - sort/reset row behavior (single row on desktop, stacked naturally on mobile) - card and grid spacing - search block spacing - drawer/sheet interaction surfaces - horizontal overflow prevention ## Sprint UI Polish (Visual Only) This sprint applies visual and responsive UX polish only. No facade contracts, business logic, API contracts, runtime/bootstrap architecture, or widget contracts were changed. ### Desktop Layout - Catalog products section uses a cleaner two-column structure with consistent spacing tokens (8/12/16/24/32). - Filters panel remains sticky on desktop and uses collapsible sections with smooth expand/collapse animation. - Product cards keep consistent image height/aspect ratio and improved vertical rhythm between image/title/rating/price/actions. - Product action controls are vertical floating circles in the image top-right zone with fixed spacing and no overlap. ### Tablet Layout - Sidebar filters transition into drawer interaction for better content width. - Sort and layout controls retain consistent sizing and spacing. - Grid/list results avoid horizontal overflow and preserve button/input containment. ### Mobile Layout - Permanent sidebar is hidden. - Sticky toolbar provides three entry points: Filters, Sort, Grid. - Filters open in drawer form with scrollable content and fixed bottom actions. - Sort and Grid open bottom-sheet style dialogs. - Focus states and keyboard dismissal (`Esc`) are preserved for all overlays. ### Grid Types - `grid` - `large-grid` - `compact-grid` - `list` All grid switch icons are normalized in size and selected state is visually highlighted. ### Filter Drawer and Sections - Filter groups (Price, Availability, Rating, Brand, etc.) are collapsible. - Range inputs are stacked vertically (`From`, `To`) with full-width controls and 12px+ spacing. - Slider remains below price inputs for predictable scan order. ### Product Card Anatomy - Image area: square ratio, `object-fit: contain`, padded image content. - Status elements (discount/stock/badges) positioned to avoid action collisions. - Actions: top-right vertical controls with equal circular dimensions. - Content: title, optional description, rating, pricing, stock indicator, CTA. ### Animations - Card hover: subtle elevation + `translateY(-2px)`. - Button/selector transitions: ~180-200ms. - Filter group expand/collapse: smooth height/opacity transition. - Drawer and sheet overlays: subtle slide/fade entrance. ### Empty and Loading States - Empty results state keeps friendly message and action while hiding non-essential catalog controls when no products are rendered. - Skeletons for cards/results keep stable heights to reduce layout shift. ### Accessibility Notes - Added/standardized visible `:focus-visible` outlines for interactive elements. - Product quick action controls now expose aria labels. - Modal/drawer interactions continue to use dialog semantics and focus trap. ### Localization and Accessibility - New strings for empty states, drawer/sheet UI, and toolbar were added to all languages: - `src/app/i18n/en.ts` - `src/app/i18n/ru.ts` - `src/app/i18n/hy.ts` - `src/app/i18n/translations.ts` - No hardcoded catalog UX strings were introduced for Sprint 10.2 additions. ## Sprint 11 Search & Discovery Engine Sprint 11 introduces a reusable, backend-driven Search and Discovery architecture while preserving platform boundaries and existing domain models. ### Search Domain Models Core search models were added under: - `src/app/core/search/models/search.model.ts` - `src/app/core/search/models/search-state.model.ts` Model coverage includes: - `SearchQuery` - `SearchResult` - `FilterGroup` - `FilterOption` - `SortOption` - `SearchSuggestion` - `SearchHistory` - `SearchState` ### Search Entry Point - `src/app/facades/platform/search.facade.ts` `SearchFacade` is now the search orchestration entry point for the catalog UX and provides: - backend catalog loading bridge for search query payloads - metadata-driven sort option generation - metadata-driven dynamic filter group generation - live suggestions generation - in-memory filter metadata memoization - reusable filtering, sorting, and pagination helpers - query param serialization/deserialization for URL synchronization ### History Service - `src/app/core/search/services/search-history.service.ts` Search history moved to a reusable core service with: - recent search tracking - popular search support - clear/reset support ### Catalog UI Integration Catalog UI now consumes Search domain metadata and state: - `src/app/features/website/catalog/containers/catalog-container.component.ts` - `src/app/features/website/catalog/components/search-box/search-box.component.ts` - `src/app/features/website/catalog/components/filters-panel/filters-panel.component.ts` - `src/app/features/website/catalog/components/sorting-control/sorting-control.component.ts` Implemented behaviors: - live suggestions - recent + popular searches - keyboard navigation in search box (up/down/enter/escape) - clear search action - dynamic filters for checkbox, radio, toggle, range, slider, color, size, rating, availability - URL query synchronization with `SearchState` - page reload restore from query params ### Validation Completed validation for Sprint 11 integration: - `npm run build` passes successfully - facades remain the UI data boundary - no authentication changes - no payment changes - no bootstrap/runtime contract changes