feat: app completa recordaLexia (fases 1-5)
App web familiar de rutinas visuales para niños con TDAH: muestra cada día el material del cole y las rutinas de tarde, con gamificación por monedas y tienda de recompensas. Multi-niño y bilingüe ES/CA. Uso doméstico/homelab. Backend (Spring Boot 3.5 / Java 21 / Gradle): - Dominio por capas, PostgreSQL + Liquibase, datos semilla. - API REST con DTOs: /today, toggle con monedas y bonos de bloque/día, monedero, tienda/canje, ajustes y CRUD del panel de padres. - Seguridad ligera por PIN (BCrypt + sesion en memoria), sin Keycloak. - Tests JUnit: generacion del dia, monedas/bonos con reversion, canje, seguridad. Frontend (Angular 19, standalone + signals): - Perfiles, Home (Tablero y Foco), Tienda y panel de padres (5 pestañas). - Tipografia OpenDyslexic conmutable (accesibilidad), i18n ES/CA, TTS y sonido. - Tokens de diseño fieles al handoff (paleta, animaciones, monedas voladoras). Empaquetado: - Docker multi-stage + docker-compose (PostgreSQL + backend + Nginx). - Decisiones de arquitectura documentadas en docs/adr.
This commit is contained in:
31
docs/adr/0001-spring-boot-3x.md
Normal file
31
docs/adr/0001-spring-boot-3x.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# ADR 0001 — Fijar Spring Boot 3.5.x (no Spring Boot 4)
|
||||
|
||||
- **Estado:** aceptada
|
||||
- **Fecha:** 2026-06-21
|
||||
- **Fase:** 1 (esqueleto)
|
||||
|
||||
## Contexto
|
||||
|
||||
Al generar el backend con Spring Initializr, la versión por defecto ofrecida es
|
||||
**Spring Boot 4.1.0** (arrastra Spring Framework 7 y un layout de *starters*
|
||||
modular nuevo: `spring-boot-starter-webmvc`, starters de test por módulo).
|
||||
|
||||
El contrato del proyecto (CLAUDE.md y prompt director) fija explícitamente
|
||||
**Spring Boot 3.x / Java 21**.
|
||||
|
||||
## Decisión
|
||||
|
||||
Se fija el backend a **Spring Boot 3.5.15** (última 3.x disponible en Initializr),
|
||||
con `spring-boot-starter-web`, `liquibase-core` y `spring-boot-starter-test`.
|
||||
|
||||
## Motivación
|
||||
|
||||
- Cumplir el stack contratado sin introducir un salto de versión mayor no aprobado.
|
||||
- Boot 4 / Spring 7 es muy reciente; el ecosistema y los ejemplos del equipo
|
||||
siguen sobre 3.x.
|
||||
|
||||
## Consecuencias
|
||||
|
||||
- Cuando se quiera adoptar Boot 4 deberá hacerse mediante un ADR propio que
|
||||
contemple la migración de starters y `jakarta`.
|
||||
- El wrapper de Gradle queda fijado por Initializr; no se requiere Gradle en host.
|
||||
39
docs/adr/0002-tipografia-opendyslexic.md
Normal file
39
docs/adr/0002-tipografia-opendyslexic.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# ADR 0002 — OpenDyslexic como tipografía por defecto (conmutable)
|
||||
|
||||
- **Estado:** aceptada
|
||||
- **Fecha:** 2026-06-21
|
||||
- **Fase:** 1 (esqueleto / preparación de tipografías)
|
||||
|
||||
## Contexto
|
||||
|
||||
El handoff de diseño fija como tokens tipográficos **Fredoka** (títulos/labels) y
|
||||
**Nunito** (texto). Para una app dirigida a peques con TDAH (y con vocación de
|
||||
lectura accesible) se solicita usar **OpenDyslexic**, fuente diseñada para mejorar
|
||||
la legibilidad. Esto entra en tensión con los tokens fijos del handoff, por lo que
|
||||
se decide cómo conviven.
|
||||
|
||||
## Decisión
|
||||
|
||||
1. **OpenDyslexic es la tipografía por defecto y se aplica a TODO el texto**
|
||||
(títulos, etiquetas y cuerpo).
|
||||
2. **Es una preferencia conmutable por niño, activada de serie.** Al desactivarla,
|
||||
la UI cae a las tipografías de marca del handoff (Fredoka/Nunito).
|
||||
3. **Las tres familias se empaquetan en local** vía `@fontsource` (sin CDN): la
|
||||
app funciona en un kiosko sin internet garantizado.
|
||||
|
||||
## Implementación
|
||||
|
||||
- Fichero único de tokens `frontend/src/styles/_theme.scss`: define
|
||||
`--font-display` y `--font-body`, que por defecto apuntan a OpenDyslexic.
|
||||
- Interruptor: atributo `data-dyslexia-font` en `<html>`. Con valor `off`, los
|
||||
tokens caen a las familias de marca. Se inicializa a `on` en `index.html`.
|
||||
- `FontPreferenceService` aplica/persiste la preferencia (hoy en `localStorage`).
|
||||
|
||||
## Consecuencias
|
||||
|
||||
- La UI nunca referencia una familia concreta, solo `var(--font-display/-body)`:
|
||||
el cambio de tipografía no toca componentes.
|
||||
- **Pendiente Fase 5:** la preferencia se conectará a los ajustes por niño del
|
||||
backend, sustituyendo el almacenamiento en `localStorage`.
|
||||
- Se cargan solo los subsets `latin` y `latin-ext` (suficientes para ES/CA) para
|
||||
no inflar el bundle.
|
||||
51
docs/adr/0003-dominio-y-seguridad-fase2.md
Normal file
51
docs/adr/0003-dominio-y-seguridad-fase2.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# ADR 0003 — Decisiones de dominio y seguridad (Fase 2 backend)
|
||||
|
||||
- **Estado:** aceptada
|
||||
- **Fecha:** 2026-06-21
|
||||
- **Fase:** 2 (dominio + API + seguridad)
|
||||
|
||||
## Contexto
|
||||
|
||||
El contrato de backend deja varias decisiones "a tu criterio". Se documentan aquí
|
||||
las tomadas al implementar el dominio, la lógica de negocio y la seguridad.
|
||||
|
||||
## Decisiones
|
||||
|
||||
1. **i18n por columnas embebidas** `label_es` / `label_ca` (no tabla de
|
||||
traducciones). Encaja con el shape de los DTOs y simplifica las consultas.
|
||||
|
||||
2. **Capas, sin hexagonal completa.** Entidad JPA como modelo de dominio (con
|
||||
comportamiento donde aporta: monedero en `Child`, marcado en `DailyTask`), DTOs
|
||||
tipo `record` en el borde. **Nunca se exponen entidades**.
|
||||
|
||||
3. **Mañana vs. tarde.** La mañana se modela con `Activity` (catálogo) +
|
||||
`WeeklyTemplateEntry` (asignación por día). La tarde con `AfternoonRoutine`
|
||||
directa por día. Se evita una FK polimórfica.
|
||||
|
||||
4. **Eventos = banner, no tareas.** Los `SpecialEvent` (examen/deberes) se muestran
|
||||
en el banner informativo del día (`specialEvents[]`), NO se materializan como
|
||||
`DailyTask` marcables (coherente con el prototipo). El enum `TaskOrigin.EVENT`
|
||||
queda disponible por si se decide lo contrario más adelante.
|
||||
|
||||
5. **Bonos reconciliables.** El bono de bloque y el de día se modelan como
|
||||
transacciones de monedas con el mismo motivo: +importe al otorgar, -importe al
|
||||
revertir. "Suma neta > 0" indica bono activo. Hace el marcar/desmarcar robusto
|
||||
ante cualquier secuencia.
|
||||
|
||||
6. **Seguridad ligera.** PIN de padres con hash BCrypt; al validarlo se abre una
|
||||
sesión en memoria identificada por un valor opaco (cabecera `X-Parent-Session`).
|
||||
`/api/parents/**` exige rol PARENT; el resto (kiosko del niño) es abierto. Todo
|
||||
encapsulado en el paquete `security` para poder sustituirlo por Keycloak.
|
||||
|
||||
7. **Semilla por `DataSeeder`** (ApplicationRunner, solo si la BD está vacía), no
|
||||
por Liquibase. Más mantenible y tipado. Desactivable con
|
||||
`recordalexia.seed.enabled=false` (lo usan los tests).
|
||||
|
||||
8. **Tests sobre H2** (modo PostgreSQL) con Liquibase. Se valorará Testcontainers
|
||||
en una iteración posterior para fidelidad total con PostgreSQL.
|
||||
|
||||
## Consecuencias
|
||||
|
||||
- Los textos visibles siempre viajan en ES y CA; el frontend elige idioma.
|
||||
- Cambiar a Keycloak no afecta a controladores ni servicios de negocio.
|
||||
- La zona horaria del negocio (Europe/Madrid) se centraliza en un `Clock` inyectable.
|
||||
Reference in New Issue
Block a user