feat: implement ROMs management UI (Phase 8)

Backend (Phase 8.1):
- Add ROMs endpoints: GET, GET/:id, PUT/:id/game, DELETE
- Add metadata search endpoint using IGDB/RAWG/TGDB
- Implement RomsController with ROM CRUD logic
- Add 12 comprehensive ROM endpoint tests
- Configure Vitest to run tests sequentially (threads: false)
- Auto-apply Prisma migrations in test setup

Frontend (Phase 8.2 + 8.3):
- Create ROM types: RomFile, Artwork, EnrichedGame
- Extend API client with roms and metadata namespaces
- Implement 5 custom hooks with TanStack Query
- Create ScanDialog, MetadataSearchDialog, RomCard components
- Rewrite roms.tsx page with table and all actions
- Add 37 comprehensive component and page tests

All 122 tests passing: 63 backend + 59 frontend
Lint: 0 errors, only unused directive warnings
This commit is contained in:
2026-02-12 19:52:59 +01:00
parent 630ebe0dc8
commit 571ac97f00
22 changed files with 2221 additions and 4 deletions

View File

@@ -0,0 +1,73 @@
## Plan: Fase 8 - Integración ROMs + Metadata (UI completa)
Implementar UI completa para gestionar ROMs: tabla con scan de directorios, búsqueda de metadata en IGDB/RAWG/TheGamesDB, vinculación con juegos, y visualización de artwork. Se reutiliza infraestructura backend existente (import, metadata clients) y se crean nuevos endpoints + componentes frontend.
**Sub-Fases: 3**
---
### **Fase 8.1: Backend ROMs API endpoints + Controller**
- **Objetivo:** Endpoints REST para listar ROMs, búsqueda de metadata, vincular ROM a juego
- **Archivos/Funciones a crear/modificar:**
- `backend/src/controllers/romsController.ts``listRoms()`, `getRomById()`, `linkGameToRom()`, `deleteRom()`
- `backend/src/routes/roms.ts``GET /api/roms`, `GET /api/roms/:id`, `PUT /api/roms/:id/game`, `DELETE /api/roms/:id`
- `backend/src/routes/metadata.ts``GET /api/metadata/search?q=query` (orquesta metadataService)
- **Tests a escribir:**
- `backend/tests/routes/roms.spec.ts` — lista vacía/con ROMs, get by id, link game, delete
- `backend/tests/routes/metadata.spec.ts` — búsqueda con results, sin results, mixed sources
- **Steps:**
1. Write tests (failing) — casos para CRUD + search
2. Implement romsController + routes
3. Run tests → pass
4. Lint + format
---
### **Fase 8.2: Frontend Types + API client + Custom Hooks**
- **Objetivo:** Tipos, cliente HTTP extendido, custom hooks con TanStack Query
- **Archivos/Funciones a crear/modificar:**
- `frontend/src/types/rom.ts``RomFile`, `Artwork`, `EnrichedGame`
- `frontend/src/lib/api.ts` — extender con `api.roms.*` y `api.metadata.*` namespaces
- `frontend/src/hooks/useRoms.ts``useRoms()`, `useScanDirectory()`, `useEnrichMetadata()`, `useLinkGameToRom()`
- **Tests a escribir:**
- Skipped por ahora (cubiertos en 8.3 con integration tests de páginas)
- **Steps:**
1. Create ROM types (RomFile, Artwork templates from Prisma schema)
2. Extend api.ts with roms and metadata namespaces
3. Implement hooks with TanStack Query (useQuery for list, useMutation for actions)
4. Format
---
### **Fase 8.3: Frontend Components + ROMs Page**
- **Objetivo:** Componentes UI para ROMs y tabla interactiva
- **Archivos/Funciones a crear/modificar:**
- `frontend/src/components/roms/ScanDialog.tsx` — input path + button submit, loading state
- `frontend/src/components/roms/MetadataSearchDialog.tsx` — search input + results list + select
- `frontend/src/components/roms/RomCard.tsx` — card display (simple card con info ROM)
- `frontend/src/routes/roms.tsx` — reescribir con tabla, botones (scan, link, delete), dialogs
- **Tests a escribir:**
- `frontend/tests/routes/roms.spec.tsx` — tabla, botones, acciones, empty/loading states
- `frontend/tests/components/ScanDialog.spec.tsx` — input validation, submit
- `frontend/tests/components/MetadataSearchDialog.spec.tsx` — search results display
- **Steps:**
1. Write tests (failing) para página y componentes
2. Crear componentes (ScanDialog, MetadataSearchDialog, RomCard, roms.tsx page)
3. Tests → pass
4. Format + lint
---
### **Open Questions**
1. ¿Agregar endpoint `GET /api/artwork/:gameId` (P1) o mantenerlo para Fase 9?
- **Respuesta:** Mantener para Fase 9 (artwork.ts). Fase 8 usa URLs directas de IGDB/RAWG.
2. ¿Cachear artwork localmente o usar proxy directo desde IGDB/RAWG?
- **Respuesta:** URLs directas de APIs (simples para Fase 8). Caché en Fase 9.
3. ¿Permitir batch scan (múltiples directorios) en Fase 8?
- **Respuesta:** No, un directorio por operación.