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:
49
frontend/src/app/features/home/wallet.component.ts
Normal file
49
frontend/src/app/features/home/wallet.component.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { Component, ElementRef, Input, inject, signal } from '@angular/core';
|
||||
|
||||
/** Monedero: pill con 🪙 y el saldo. Hace walletBump cuando se le pide (al ganar). */
|
||||
@Component({
|
||||
selector: 'app-wallet',
|
||||
imports: [],
|
||||
template: `
|
||||
<span class="wallet" [class.wallet--bump]="bumping()">
|
||||
<span class="wallet__coin">🪙</span>
|
||||
<span class="wallet__amount">{{ coins }}</span>
|
||||
</span>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
.wallet {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 9px 18px;
|
||||
border-radius: var(--radius-pill);
|
||||
background: var(--coin-bg);
|
||||
color: var(--coin-text);
|
||||
font-family: var(--font-display);
|
||||
font-weight: 700;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
.wallet--bump { animation: walletBump 0.45s ease; }
|
||||
`,
|
||||
],
|
||||
})
|
||||
export class WalletComponent {
|
||||
@Input({ required: true }) coins = 0;
|
||||
|
||||
protected readonly bumping = signal(false);
|
||||
private readonly el = inject(ElementRef<HTMLElement>);
|
||||
|
||||
/** Rectángulo del monedero: destino de las monedas voladoras. */
|
||||
getRect(): DOMRect {
|
||||
return (this.el.nativeElement as HTMLElement).getBoundingClientRect();
|
||||
}
|
||||
|
||||
/** Dispara la animación de "rebote" del monedero. */
|
||||
bump(): void {
|
||||
this.bumping.set(false);
|
||||
// Reinicia la animación en el siguiente frame.
|
||||
requestAnimationFrame(() => this.bumping.set(true));
|
||||
setTimeout(() => this.bumping.set(false), 500);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user