# 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`. ### 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 `

`. ### 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 |