Appearance
Homepage + Header Design
Date: 2026-02-08 Status: Approved Scope: Homepage implementation + header search/city selector
Overview
Implement the homepage (index.vue) with three content sections (Hero + YMM, Categories, Recent Listings) and enhance the default layout header with search autocomplete and city selector.
API Endpoints Used
| Endpoint | Where |
|---|---|
GET /store/products/search?q=... | SearchBar autocomplete |
GET /store/categories?type=part | Categories grid on homepage |
GET /store/products?sort=date_desc&limit=8 | Recent listings on homepage |
GET /store/geo/regions + regions/{id}/cities | City selector in header |
GET /store/cars/makes, /models, /generations | YMM filter (existing) |
Reused Components
YmmSelect— Hero filterProductCard— Recent listingsuseGeoCascade— City selectoruseGeoStore— Persist selected city
1. Header Enhancement (default layout)
1.1 Search with Autocomplete
Desktop: UInput with search icon between Logo and navigation.
- Debounce 300ms, minimum 2 characters to trigger request
GET /store/products/search?q=...— dropdown with results (title, price, thumbnail)- Max 5 results in dropdown
- Enter with text →
/catalog?q=... - Click on result →
/product/:id - Escape or click outside → close dropdown
Mobile: Search icon in header, click expands full-width input.
FSD Architecture:
features/search/composables/useProductSearch.ts— debounced API call, returns reactive resultsfeatures/search/ui/SearchBar.vue— input + dropdown component
1.2 City Selector
- Button "Санкт-Петербург" with location pin icon (from
useGeoStore.locationLabel) - Click →
UModalwith region → city cascade (reuseuseGeoCascade) - Selected city persists in store + cookie
- MVP: city is display-only in header, filtering by city happens in catalog
2. Homepage — Hero Section
Content
h1: "Найдите запчасть для вашего авто" (i18n key)- YMM filter: Make → Model → Generation + "Подобрать" button
- Reuse
features/ymm-select/ui/YmmSelect.vue - Submit →
navigateTo('/catalog', { query: { make_id, model_id, generation_id } }) - Desktop: horizontal layout (3 selects + button in row)
- Mobile: vertical stack
- Reuse
Visual
- Background: subtle gradient or
bg-[var(--ui-bg-elevated)] - Centered content,
max-w-3xl - Padding:
py-16desktop,py-10mobile - Dark mode via semantic CSS variables
Architecture
- Inline in
index.vue— no separate widget needed - YMM component via FSD auto-import
3. Homepage — Categories Section
Data
GET /store/categories?type=partviauseAsyncData(SSR)- Show only root categories (
parent_id === null) - Schema:
categorySchema—id,name,slug,icon
Visual
- Section title: "Категории запчастей"
- Grid: desktop 3-5 columns, mobile 2 columns
- Card: icon (from
iconfield, fallback default) + name - Click →
/catalog?category_id=X - Hover effect, rounded corners, subtle border
- Dark mode:
bg-[var(--ui-bg-elevated)]+border-[var(--ui-border)]
Edge Cases
- 0 categories → hide section
- API error → hide section (don't block page)
4. Homepage — Recent Listings Section
Data
GET /store/products?sort=date_desc&limit=8viauseAsyncData(SSR)- Response type:
ApiListResponse<Product>
Visual
- Title: "Новые объявления" + "Смотреть все" link →
/catalog - Grid: desktop 4 columns, tablet 3, mobile 2
- Reuse
entities/product/ui/ProductCard.vue - Bottom: "Показать ещё" button →
/catalog(no infinite scroll on homepage)
States
- Loading: 4 skeleton cards (desktop), 2 (mobile) via
USkeleton - Empty: "Объявлений пока нет" + "Разместить первое" CTA
- Error: hide section silently
5. Files to Create/Modify
| File | Action | Description |
|---|---|---|
features/search/composables/useProductSearch.ts | Create | Debounced search via /store/products/search |
features/search/ui/SearchBar.vue | Create | Input + autocomplete dropdown |
app/layouts/default.vue | Modify | Add SearchBar + city selector |
app/pages/index.vue | Modify | Hero + YMM + categories + listings |
i18n/locales/ru.json | Modify | Add homepage i18n keys |
6. i18n Keys
json
{
"home": {
"hero": {
"title": "Найдите запчасть для вашего авто",
"submit": "Подобрать"
},
"categories": {
"title": "Категории запчастей"
},
"listings": {
"title": "Новые объявления",
"viewAll": "Смотреть все",
"showMore": "Показать ещё",
"empty": "Объявлений пока нет",
"emptyAction": "Разместить первое"
}
},
"search": {
"placeholder": "Поиск запчастей...",
"noResults": "Ничего не найдено",
"submit": "Найти"
}
}