feat(F-071): completed feature
This commit is contained in:
111
work/artifacts/F-071/implementer.md
Normal file
111
work/artifacts/F-071/implementer.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# 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 |
|
||||
Reference in New Issue
Block a user