Files
mercadodevida/work/artifacts/F-071/architect.md
2026-08-19 19:04:41 +02:00

3.8 KiB

F-071 — Architecture: Editable emoji and color for categories

Problem

The frontend uses hardcoded emoji/color maps keyed by category slug:

  • project/frontend/src/components/home/CategoriesGrid.tsxicons map + colors array
  • project/frontend/src/app/categories/page.tsxicons map + colors array

The admin category editor (project/apps/admin/src/app/(dashboard)/categories/page.tsx) shows a generic 📁 folder icon for parent categories and has no emoji/color fields. New parent categories therefore show the folder instead of an identifying emoji.

Design

1. Database schema (migration 030)

ALTER TABLE categories_categories
  ADD COLUMN emoji    VARCHAR(10) NULL DEFAULT NULL,
  ADD COLUMN color    TEXT        NULL DEFAULT NULL;
  • emoji VARCHAR(10): a single emoji unicode character (with potential variation selectors). Nullable so existing categories are unaffected.
  • color TEXT: stores a Tailwind gradient class string, e.g. from-[#70ad47] to-[#40916C]. Nullable. Storing the class string keeps it simple and consistent with the existing categories/page.tsx colors array format.

Both columns are nullable with NULL default → zero-downtime, no data migration needed for existing rows.

2. Backend domain

project/src/modules/categories/domain/category.ts:

  • Add emoji?: string | null and color?: string | null to Category, NewCategory, CategoryPatch.

3. Backend repository

project/src/modules/categories/infrastructure/pg-category-repository.ts:

  • Add emoji: string | null and color: string | null to CategoryRow.
  • Add ['emoji', 'emoji'] and ['color', 'color'] to UPDATABLE.
  • Add emoji/color to the INSERT statement.
  • Map emoji/color in toCategory().

4. Backend API routes

project/src/modules/categories/api/categories.routes.ts:

  • Add emoji: z.string().max(10).optional().nullable() and color: z.string().max(200).optional().nullable() to newCategorySchema.
  • Add emoji and color to serializeCategory() output.

5. Frontend types

project/frontend/src/types/api.ts:

  • Add emoji?: string and color?: string to the Category interface.

6. Frontend — CategoriesGrid + CategoriesPage

  • Replace hardcoded icons[cat.slug] ?? '📦' with cat.emoji ?? fallbackIcons[cat.slug] ?? '📦'.
  • Replace hardcoded colors[i % colors.length] gradient with cat.color ?? colors[i % colors.length] — keeps existing visual behavior for categories without stored color.

7. Admin — types + form

project/apps/admin/src/types/index.ts:

  • Add emoji?: string and color?: string to Category.

project/apps/admin/src/app/(dashboard)/categories/page.tsx:

  • Add emoji and color to FormState.
  • Add emoji input (text) and color input (text input for Tailwind class, with placeholder examples) to the form UI.
  • Include emoji/color in the save payload.
  • In CategoryRow, replace the hardcoded 📁 with cat.emoji ?? '📁'.

8. Storefront

project/storefront/src/lib/api.ts:

  • Add emoji?: string | null and color?: string | null to CategoryDto.

project/storefront/src/app/categoria/[slug]/page.tsx:

  • Optionally render the emoji in the header if present.

Data flow

Admin form → PATCH /api/categories/:id → backend serializes → DB stores
            GET /categories/tree       → backend returns emoji+color → frontend renders

Risks

  • Low: All new columns are nullable; existing categories keep working.
  • The color field stores a CSS class string, not a sanitized color value. Admin input is validated by z.string().max(200). A malicious class value is a cosmetic (not security) concern — it's rendered via className which React sanitizes against script injection.
  • Backward compatibility: emoji and color default to null → UI falls back to hardcoded maps.