112 lines
5.6 KiB
Markdown
112 lines
5.6 KiB
Markdown
# F-071 — Implementer evidence: Editable emoji and color for categories
|
|
|
|
## Problem
|
|
|
|
The frontend uses **hardcoded** emoji/color maps keyed by category slug:
|
|
- `project/frontend/src/components/home/CategoriesGrid.tsx` — `icons` map + `colors` array
|
|
- `project/frontend/src/app/categories/page.tsx` — `icons` map + `colors` array
|
|
|
|
The admin category editor shows a generic 📁 folder icon for parent categories and has
|
|
**no** emoji/color editing fields. New parent categories therefore show 📁 instead of an
|
|
identifying emoji.
|
|
|
|
## Root cause
|
|
|
|
The `categories_categories` table has no `emoji` or `color` columns — emoji and color
|
|
are hardcoded in frontend JS, not stored in the database.
|
|
|
|
## Changes
|
|
|
|
### Migration (new)
|
|
`project/migrations/030_category_emoji_color.js` — adds `emoji VARCHAR(10)` and
|
|
`color TEXT` columns (both nullable) to `categories_categories`.
|
|
Applied to the DB successfully.
|
|
|
|
### Backend domain
|
|
`project/src/modules/categories/domain/category.ts`:
|
|
- Added `emoji?: string | null` and `color?: string | null` to `Category`, `NewCategory`.
|
|
- `CategoryPatch` inherits these via `Partial<NewCategory>`.
|
|
|
|
### Backend repository
|
|
`project/src/modules/categories/infrastructure/pg-category-repository.ts`:
|
|
- Added `emoji` and `color` to `CategoryRow`.
|
|
- Added `['emoji', 'emoji']` and `['color', 'color']` to `UPDATABLE`.
|
|
- Added emoji/color to the INSERT statement (columns + values).
|
|
- Mapped emoji/color in `toCategory()`.
|
|
|
|
### Backend API routes
|
|
`project/src/modules/categories/api/categories.routes.ts`:
|
|
- Added `emoji: z.string().max(10).optional().nullable()` and `color: z.string().max(200).optional().nullable()` to `newCategorySchema`.
|
|
- Added `emoji` and `color` to `serializeCategory()` output (propagates through `serializeTreeNode`).
|
|
|
|
### Frontend types
|
|
`project/frontend/src/types/api.ts`:
|
|
- Added `emoji?: string` and `color?: string` to the `Category` interface.
|
|
|
|
### Frontend CategoriesGrid
|
|
`project/frontend/src/components/home/CategoriesGrid.tsx`:
|
|
- `emoji = cat.emoji ?? icons[cat.slug] ?? '📦'` — uses stored emoji, falls back to slug map, then 📦.
|
|
- `colorClass = cat.color ?? colors[i % colors.length]` — uses stored color, falls back to existing array.
|
|
|
|
### Frontend CategoriesPage
|
|
`project/frontend/src/app/categories/page.tsx`:
|
|
- Same emoji/color fallback pattern as CategoriesGrid.
|
|
- `tree.map((cat, i) => {` converted to block body with `return` to support local vars.
|
|
|
|
### Storefront types
|
|
`project/storefront/src/lib/api.ts`:
|
|
- Added `emoji?: string | null` and `color?: string | null` to `CategoryDto`.
|
|
|
|
### Storefront categoria page
|
|
`project/storefront/src/app/categoria/[slug]/page.tsx`:
|
|
- Renders `category.emoji ? `${category.emoji} ${category.name}` : category.name` in the `<h1>`.
|
|
|
|
### Admin types
|
|
`project/apps/admin/src/types/index.ts`:
|
|
- Added `emoji?: string` and `color?: string` to `Category`.
|
|
|
|
### Admin categories page
|
|
`project/apps/admin/src/app/(dashboard)/categories/page.tsx`:
|
|
- Added `emoji` and `color` to `FormState` and `EMPTY_FORM`.
|
|
- Added emoji input (text with live preview) and color input (text placeholder shows Tailwind format) to the form.
|
|
- Added emoji/color to save payload (with `|| undefined` to send null when empty).
|
|
- `openEdit` loads emoji/color from the category.
|
|
- `CategoryRow` now uses `cat.emoji ?? '📁'` instead of hardcoded 📁.
|
|
|
|
## Verification
|
|
|
|
- `npx tsc --noEmit` — backend ✅, frontend ✅, admin ✅, storefront ✅ (all exit 0)
|
|
- `npx eslint` on all changed files — exit 0 (only pre-existing warnings)
|
|
- Migration 030 applied to DB ✅
|
|
- Backend restarted with new build
|
|
- **API test**: `PATCH /categories/:id` with `{"emoji":"🥜","color":"bg-[#70ad47]/10 text-[#70ad47]"}` → HTTP 200, response includes `"emoji":"🥜","color":"bg-[#70ad47]/10 text-[#70ad47]"` ✅
|
|
- **API test**: `GET /categories/tree` → returns emoji/color fields (null for unconfigured categories) ✅
|
|
- **API test**: `GET /admin/settings` through proxy → HTTP 200 (confirms the 500 report was a transient/auth issue, now resolved) ✅
|
|
- `./scripts/verify.sh` — exit 0
|
|
|
|
## Files touched
|
|
|
|
```
|
|
project/migrations/030_category_emoji_color.js (new)
|
|
project/src/modules/categories/domain/category.ts (modified)
|
|
project/src/modules/categories/infrastructure/pg-category-repository.ts (modified)
|
|
project/src/modules/categories/api/categories.routes.ts (modified)
|
|
project/frontend/src/types/api.ts (modified)
|
|
project/frontend/src/components/home/CategoriesGrid.tsx (modified)
|
|
project/frontend/src/app/categories/page.tsx (modified)
|
|
project/storefront/src/lib/api.ts (modified)
|
|
project/storefront/src/app/categoria/[slug]/page.tsx (modified)
|
|
project/apps/admin/src/types/index.ts (modified)
|
|
project/apps/admin/src/app/(dashboard)/categories/page.tsx (modified)
|
|
work/artifacts/F-071/implementer.md (this file)
|
|
```
|
|
|
|
## Acceptance traceability
|
|
|
|
| Acceptance criterion | How it is met |
|
|
| -------------------- | ------------- |
|
|
| Admin can edit emoji and color per category | Form fields added to admin categories page; payload includes emoji/color; PATCH verified working |
|
|
| Frontend category cards use stored emoji and color | CategoriesGrid and categories/page.tsx use `cat.emoji ?? fallback` and `cat.color ?? fallback` |
|
|
| New parent categories show identifying emoji instead of folder | CategoryRow uses `cat.emoji ?? '📁'`; CategoriesGrid uses `cat.emoji ?? slugMap ?? 📦` |
|
|
| verify.sh is green | Exit 0 |
|