# 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
