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:
68
frontend/src/app/features/home/board-view.component.ts
Normal file
68
frontend/src/app/features/home/board-view.component.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { Component, EventEmitter, Input, Output, inject } from '@angular/core';
|
||||
import { I18nService } from '../../core/i18n.service';
|
||||
import { TaskView } from '../../core/models';
|
||||
import { TaskCardComponent, ToggleEvent } from './task-card.component';
|
||||
|
||||
/** Vista TABLERO: dos columnas (cole / tarde) con las tareas del día. */
|
||||
@Component({
|
||||
selector: 'app-board-view',
|
||||
imports: [TaskCardComponent],
|
||||
template: `
|
||||
<div class="board">
|
||||
<section class="col">
|
||||
<h2 class="col__head">🎒 {{ i18n.t('school') }}</h2>
|
||||
@if (morning.length) {
|
||||
@for (task of morning; track task.id) {
|
||||
<app-task-card [task]="task" [ttsEnabled]="ttsEnabled" (toggle)="toggle.emit($event)" />
|
||||
}
|
||||
} @else {
|
||||
<div class="empty">🏖️ {{ i18n.t('noSchool') }}</div>
|
||||
}
|
||||
</section>
|
||||
|
||||
<section class="col">
|
||||
<h2 class="col__head">🌙 {{ i18n.t('afternoon') }}</h2>
|
||||
@for (task of afternoon; track task.id) {
|
||||
<app-task-card [task]="task" [ttsEnabled]="ttsEnabled" (toggle)="toggle.emit($event)" />
|
||||
}
|
||||
</section>
|
||||
</div>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
.board {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: var(--space-5);
|
||||
}
|
||||
@media (max-width: 760px) {
|
||||
.board { grid-template-columns: 1fr; }
|
||||
}
|
||||
.col { display: flex; flex-direction: column; gap: var(--space-3); }
|
||||
.col__head {
|
||||
margin: 0 0 var(--space-2);
|
||||
font-size: 1.4rem;
|
||||
color: var(--text-1);
|
||||
}
|
||||
.empty {
|
||||
padding: var(--space-6) var(--space-4);
|
||||
text-align: center;
|
||||
font-family: var(--font-display);
|
||||
font-weight: 700;
|
||||
font-size: 1.3rem;
|
||||
color: var(--text-2);
|
||||
background: var(--surface);
|
||||
border: 2px dashed var(--border-2);
|
||||
border-radius: var(--radius-card);
|
||||
}
|
||||
`,
|
||||
],
|
||||
})
|
||||
export class BoardViewComponent {
|
||||
@Input() morning: TaskView[] = [];
|
||||
@Input() afternoon: TaskView[] = [];
|
||||
@Input() ttsEnabled = true;
|
||||
@Output() toggle = new EventEmitter<ToggleEvent>();
|
||||
|
||||
protected readonly i18n = inject(I18nService);
|
||||
}
|
||||
Reference in New Issue
Block a user