From b0069a0c9e0eb3fd12f67b3007281a2df9963460 Mon Sep 17 00:00:00 2001 From: Jaume Garriga Maestre Date: Mon, 22 Jun 2026 22:49:51 +0200 Subject: [PATCH] =?UTF-8?q?feat(rutinas):=20panel=20de=20padres=20con=20ca?= =?UTF-8?q?t=C3=A1logo=20y=20selecci=C3=B3n=20de=20d=C3=ADas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit routines-tab permite definir rutinas en el catálogo y asignarlas a varios días marcando casillas, reutilizando emoji y color pickers. --- frontend/package-lock.json | 468 ++++++++++++++++++ frontend/src/app/core/models.ts | 25 +- frontend/src/app/core/parent-api.service.ts | 21 +- .../parents/routines-tab.component.ts | 141 +++++- 4 files changed, 624 insertions(+), 31 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c9caae1..fc0d2d0 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -14741,6 +14741,474 @@ } } }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, "node_modules/vite/node_modules/esbuild": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", diff --git a/frontend/src/app/core/models.ts b/frontend/src/app/core/models.ts index bd8f2d9..0bf6dd2 100644 --- a/frontend/src/app/core/models.ts +++ b/frontend/src/app/core/models.ts @@ -158,10 +158,22 @@ export interface WeeklyEntryView { coinsReward: number | null; } +/** Rutina del catálogo de la familia (definición reutilizable). */ +export interface RoutineTaskView { + id: number; + labelEs: string; + labelCa: string; + icon: string; + color: string; + coinsReward: number | null; +} + +/** Asignación de una rutina a un día; labels/icon/color derivan del catálogo. */ export interface RoutineView { id: number; childId: number; dayOfWeek: string; + routineTaskId: number; labelEs: string; labelCa: string; icon: string; @@ -245,13 +257,20 @@ export interface WeeklyEntryRequest { coinsReward?: number; } -export interface AfternoonRoutineRequest { - childId: number; - dayOfWeek: string; +/** Alta/edición de una rutina del catálogo (definición reutilizable). */ +export interface RoutineTaskRequest { labelEs: string; labelCa: string; icon: string; color: string; + coinsReward?: number; +} + +/** Asigna una rutina del catálogo a uno o varios días de una vez. */ +export interface AfternoonRoutineRequest { + childId: number; + routineTaskId: number; + daysOfWeek: string[]; orderIndex?: number; coinsReward?: number; } diff --git a/frontend/src/app/core/parent-api.service.ts b/frontend/src/app/core/parent-api.service.ts index f05c569..c325e37 100644 --- a/frontend/src/app/core/parent-api.service.ts +++ b/frontend/src/app/core/parent-api.service.ts @@ -14,6 +14,8 @@ import { MaterialView, RewardAdminView, RewardRequest, + RoutineTaskRequest, + RoutineTaskView, RoutineView, SettingsRequest, SpecialEventRequest, @@ -102,8 +104,9 @@ export class ParentApiService { listRoutines(childId: number): Observable { return this.http.get(`${this.base}/schedule/routines?childId=${childId}`); } - createRoutine(req: AfternoonRoutineRequest): Observable { - return this.http.post(`${this.base}/schedule/routines`, req); + /** Asigna una rutina del catálogo a varios días de una vez (devuelve las asignaciones creadas). */ + createRoutine(req: AfternoonRoutineRequest): Observable { + return this.http.post(`${this.base}/schedule/routines`, req); } deleteRoutine(id: number): Observable { return this.http.delete(`${this.base}/schedule/routines/${id}`); @@ -112,6 +115,20 @@ export class ParentApiService { return this.http.put(`${this.base}/schedule/routines/reorder`, { orderedIds }); } + // --- Catálogo de rutinas de tarde (reutilizables por familia) --- + listRoutineTasks(): Observable { + return this.http.get(`${this.base}/routine-tasks`); + } + createRoutineTask(req: RoutineTaskRequest): Observable { + return this.http.post(`${this.base}/routine-tasks`, req); + } + updateRoutineTask(id: number, req: RoutineTaskRequest): Observable { + return this.http.put(`${this.base}/routine-tasks/${id}`, req); + } + deleteRoutineTask(id: number): Observable { + return this.http.delete(`${this.base}/routine-tasks/${id}`); + } + // --- Eventos --- listEvents(childId: number): Observable { return this.http.get(`${this.base}/events?childId=${childId}`); diff --git a/frontend/src/app/features/parents/routines-tab.component.ts b/frontend/src/app/features/parents/routines-tab.component.ts index 16cd264..6290a73 100644 --- a/frontend/src/app/features/parents/routines-tab.component.ts +++ b/frontend/src/app/features/parents/routines-tab.component.ts @@ -2,7 +2,7 @@ import { Component, Input, computed, inject, signal } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { ParentApiService } from '../../core/parent-api.service'; import { I18nService } from '../../core/i18n.service'; -import { RoutineView } from '../../core/models'; +import { RoutineTaskView, RoutineView } from '../../core/models'; import { EmojiPickerComponent } from '../../shared/emoji-picker.component'; import { ColorPickerComponent } from '../../shared/color-picker.component'; @@ -16,29 +16,18 @@ const DAYS: { key: string; es: string; ca: string }[] = [ { key: 'SUNDAY', es: 'Domingo', ca: 'Diumenge' }, ]; -/** Pestaña Rutinas de tarde por día de la semana, de un niño. */ +/** + * Pestaña Rutinas de tarde. Dos pasos: (1) definir rutinas en el catálogo de la familia + * una sola vez; (2) asignar una rutina del catálogo a varios días del niño de golpe. + * Reutiliza el patrón de las mañanas (catálogo de actividades + asignación por día). + */ @Component({ selector: 'app-routines-tab', imports: [FormsModule, EmojiPickerComponent, ColorPickerComponent], template: ` +
-
- {{ i18n.t('tabRoutines') }}: - @for (d of days; track d.key) { - - } -
-
- -
-

Nueva rutina

+

Catálogo de rutinas

@@ -57,10 +46,71 @@ const DAYS: { key: string; es: string; ca: string }[] = [
- + + +
+ @for (t of catalog(); track t.id) { +
+ {{ t.icon }} + {{ i18n.label(t.labelEs, t.labelCa) }} + +
+ } @empty { +

{{ i18n.t('none') }}

+ } +
+
+

Asignar a días

+
+ + +
+
+ @for (d of days; track d.key) { + + } +
+ +
+ + +
+
+ {{ i18n.t('tabRoutines') }}: + @for (d of days; track d.key) { + + } +
@for (r of routinesForDay(); track r.id; let i = $index; let last = $last) {
@@ -103,32 +153,36 @@ export class RoutinesTabComponent { protected readonly days = DAYS; protected readonly day = signal('MONDAY'); + protected readonly catalog = signal([]); protected readonly routines = signal([]); protected readonly routinesForDay = computed(() => this.routines().filter((r) => r.dayOfWeek === this.day()), ); + // Estado del formulario del catálogo. protected readonly routineIcons = ['🎒', '🥪', '📝', '🎹', '🍽️', '🛁', '🦷', '📚', '🧹', '🐕', '🛏️', '🎨', '⚽', '🧺']; protected icon = ''; protected labelEs = ''; protected labelCa = ''; protected color = '#A78BD0'; + // Estado del formulario de asignación. + protected selectedTaskId: number | null = null; + protected readonly selectedDays = signal([]); + private reload(): void { + this.api.listRoutineTasks().subscribe((l) => this.catalog.set(l)); this.api.listRoutines(this._childId).subscribe((l) => this.routines.set(l)); } - add(): void { - const order = this.routinesForDay().length; + // --- Catálogo --- + addToCatalog(): void { this.api - .createRoutine({ - childId: this._childId, - dayOfWeek: this.day(), + .createRoutineTask({ labelEs: this.labelEs, labelCa: this.labelCa, icon: this.icon, color: this.color, - orderIndex: order, }) .subscribe(() => { this.labelEs = this.labelCa = this.icon = ''; @@ -136,6 +190,41 @@ export class RoutinesTabComponent { }); } + removeFromCatalog(t: RoutineTaskView): void { + this.api.deleteRoutineTask(t.id).subscribe(() => this.reload()); + } + + // --- Asignación multi-día --- + isSelected(dayKey: string): boolean { + return this.selectedDays().includes(dayKey); + } + + toggleSelectedDay(dayKey: string): void { + const current = this.selectedDays(); + this.selectedDays.set( + current.includes(dayKey) ? current.filter((d) => d !== dayKey) : [...current, dayKey], + ); + } + + assign(): void { + if (this.selectedTaskId === null || this.selectedDays().length === 0) { + return; + } + const order = this.routinesForDay().length; + this.api + .createRoutine({ + childId: this._childId, + routineTaskId: this.selectedTaskId, + daysOfWeek: this.selectedDays(), + orderIndex: order, + }) + .subscribe(() => { + this.selectedTaskId = null; + this.selectedDays.set([]); + this.reload(); + }); + } + /** Mueve una rutina del día arriba (-1) o abajo (+1) y persiste el nuevo orden. */ move(index: number, delta: number): void { const list = [...this.routinesForDay()];