Convierte recordaLexia de una sola familia a multi-familia, con cuentas propias y persistencia de preferencias. Backend: - Tenant Family (email único + contraseña BCrypt + PIN + prefs de cuenta); family_id en child/activity/material_item/reward; aislamiento por familia (acceso cruzado responde 404). - Auth propia (sin Keycloak): registro/login email+contraseña, sesiones de familia persistidas en BD (sobreviven a reinicios), panel de padres tras PIN. - Liquibase 002-multitenant; seeder crea una familia demo. - Tests de aislamiento entre familias, registro/login y gate del panel. Frontend: - Login, registro y pantalla de cuenta; guards (sesion + PIN) e interceptor de sesion global; perfiles scopeados a la familia. Preferencias: - OpenDyslexic persistida por nino (child.dyslexiaFont) y default de cuenta. Decisiones en docs/adr/0004.
268 lines
5.1 KiB
TypeScript
268 lines
5.1 KiB
TypeScript
// Modelos TypeScript alineados con los DTOs del backend (es.asepeyo.recordalexia.web.dto).
|
|
// Mantener en sincronía con el backend, en especial TodayResponse.
|
|
|
|
export type ViewMode = 'BOARD' | 'FOCUS';
|
|
export type Language = 'ES' | 'CA';
|
|
|
|
/** Resumen de perfil para la pantalla de selección. */
|
|
export interface ChildSummary {
|
|
id: number;
|
|
name: string;
|
|
mascot: string;
|
|
accentColor: string;
|
|
age: number;
|
|
coins: number;
|
|
viewMode: ViewMode;
|
|
language: Language;
|
|
}
|
|
|
|
/** Datos del niño embebidos en /today. */
|
|
export interface ChildInfo {
|
|
id: number;
|
|
name: string;
|
|
mascot: string;
|
|
accentColor: string;
|
|
viewMode: ViewMode;
|
|
language: Language;
|
|
soundEnabled: boolean;
|
|
ttsEnabled: boolean;
|
|
dyslexiaFont: boolean;
|
|
}
|
|
|
|
/** Tarea del día (mañana o tarde). Lleva texto ES y CA. */
|
|
export interface TaskView {
|
|
id: number;
|
|
labelEs: string;
|
|
labelCa: string;
|
|
icon: string;
|
|
color: string;
|
|
done: boolean;
|
|
coinsReward: number;
|
|
orderIndex: number;
|
|
}
|
|
|
|
/** Evento del día (examen/deberes) para el banner. */
|
|
export interface EventView {
|
|
id: number;
|
|
type: 'EXAM' | 'HOMEWORK';
|
|
titleEs: string;
|
|
titleCa: string;
|
|
icon: string;
|
|
color: string;
|
|
}
|
|
|
|
export interface ProgressView {
|
|
morningDone: number;
|
|
morningTotal: number;
|
|
afternoonDone: number;
|
|
afternoonTotal: number;
|
|
totalDone: number;
|
|
total: number;
|
|
}
|
|
|
|
export interface WalletInfo {
|
|
coins: number;
|
|
}
|
|
|
|
export interface TimerInfo {
|
|
departureTime: string | null;
|
|
minutesUntilDeparture: number | null;
|
|
}
|
|
|
|
/** Payload completo de GET /api/children/{id}/today. */
|
|
export interface TodayResponse {
|
|
child: ChildInfo;
|
|
morning: TaskView[];
|
|
afternoon: TaskView[];
|
|
specialEvents: EventView[];
|
|
progress: ProgressView;
|
|
wallet: WalletInfo;
|
|
timer: TimerInfo;
|
|
}
|
|
|
|
/** Resultado de marcar/desmarcar una tarea. */
|
|
export interface ToggleResult {
|
|
taskId: number;
|
|
done: boolean;
|
|
coinsEarned: number;
|
|
newBalance: number;
|
|
progress: ProgressView;
|
|
}
|
|
|
|
/** Ajustes editables del niño (todos opcionales). */
|
|
export interface SettingsRequest {
|
|
viewMode?: ViewMode;
|
|
soundEnabled?: boolean;
|
|
ttsEnabled?: boolean;
|
|
language?: Language;
|
|
dyslexiaFont?: boolean;
|
|
departureTime?: string;
|
|
}
|
|
|
|
/** Premio visible en la tienda (Fase 5). */
|
|
export interface RewardView {
|
|
id: number;
|
|
labelEs: string;
|
|
labelCa: string;
|
|
icon: string;
|
|
color: string;
|
|
cost: number;
|
|
affordable: boolean;
|
|
missing: number;
|
|
}
|
|
|
|
export interface RedeemResult {
|
|
rewardId: number;
|
|
cost: number;
|
|
newBalance: number;
|
|
}
|
|
|
|
// ----- Panel de padres: vistas de lectura -----
|
|
export interface RewardAdminView {
|
|
id: number;
|
|
labelEs: string;
|
|
labelCa: string;
|
|
icon: string;
|
|
color: string;
|
|
cost: number;
|
|
active: boolean;
|
|
}
|
|
|
|
export interface MaterialView {
|
|
id: number;
|
|
labelEs: string;
|
|
labelCa: string;
|
|
icon: string;
|
|
color: string;
|
|
category: string | null;
|
|
}
|
|
|
|
export interface ActivityView {
|
|
id: number;
|
|
labelEs: string;
|
|
labelCa: string;
|
|
icon: string;
|
|
color: string;
|
|
materialIds: number[];
|
|
}
|
|
|
|
export interface WeeklyEntryView {
|
|
id: number;
|
|
childId: number;
|
|
dayOfWeek: string;
|
|
activityId: number;
|
|
activityLabelEs: string;
|
|
icon: string;
|
|
color: string;
|
|
orderIndex: number;
|
|
coinsReward: number | null;
|
|
}
|
|
|
|
export interface RoutineView {
|
|
id: number;
|
|
childId: number;
|
|
dayOfWeek: string;
|
|
labelEs: string;
|
|
labelCa: string;
|
|
icon: string;
|
|
color: string;
|
|
orderIndex: number;
|
|
coinsReward: number | null;
|
|
}
|
|
|
|
export interface EventAdminView {
|
|
id: number;
|
|
childId: number;
|
|
date: string;
|
|
type: 'EXAM' | 'HOMEWORK';
|
|
titleEs: string;
|
|
titleCa: string;
|
|
icon: string;
|
|
color: string;
|
|
}
|
|
|
|
export interface GamificationView {
|
|
coinsPerTask: number;
|
|
coinsPerBlock: number;
|
|
coinsPerDay: number;
|
|
}
|
|
|
|
// ----- Auth / cuenta de familia -----
|
|
export interface MeResponse {
|
|
familyId: number;
|
|
email: string;
|
|
name: string;
|
|
uiLanguage: string;
|
|
defaultDyslexiaFont: boolean;
|
|
}
|
|
|
|
// ----- Panel de padres: peticiones -----
|
|
export interface ChildRequest {
|
|
name?: string;
|
|
mascot?: string;
|
|
accentColor?: string;
|
|
age?: number;
|
|
departureTime?: string;
|
|
coins?: number;
|
|
}
|
|
|
|
export interface GamificationRequest {
|
|
coinsPerTask?: number;
|
|
coinsPerBlock?: number;
|
|
coinsPerDay?: number;
|
|
}
|
|
|
|
export interface RewardRequest {
|
|
labelEs: string;
|
|
labelCa: string;
|
|
icon: string;
|
|
color: string;
|
|
cost: number;
|
|
active?: boolean;
|
|
}
|
|
|
|
export interface MaterialRequest {
|
|
labelEs: string;
|
|
labelCa: string;
|
|
icon: string;
|
|
color: string;
|
|
category?: string;
|
|
}
|
|
|
|
export interface ActivityRequest {
|
|
labelEs: string;
|
|
labelCa: string;
|
|
icon: string;
|
|
color: string;
|
|
materialIds: number[];
|
|
}
|
|
|
|
export interface WeeklyEntryRequest {
|
|
childId: number;
|
|
dayOfWeek: string;
|
|
activityId: number;
|
|
orderIndex?: number;
|
|
coinsReward?: number;
|
|
}
|
|
|
|
export interface AfternoonRoutineRequest {
|
|
childId: number;
|
|
dayOfWeek: string;
|
|
labelEs: string;
|
|
labelCa: string;
|
|
icon: string;
|
|
color: string;
|
|
orderIndex?: number;
|
|
coinsReward?: number;
|
|
}
|
|
|
|
export interface SpecialEventRequest {
|
|
childId: number;
|
|
date: string;
|
|
type: 'EXAM' | 'HOMEWORK';
|
|
titleEs: string;
|
|
titleCa: string;
|
|
icon: string;
|
|
color: string;
|
|
}
|