diff --git a/src/app/core/services/todo.service.ts b/src/app/core/services/todo.service.ts index 5ce413c..3a5f89b 100644 --- a/src/app/core/services/todo.service.ts +++ b/src/app/core/services/todo.service.ts @@ -5,21 +5,15 @@ import { Todo, TodoCreate } from '../models/todo.model'; @Injectable({ providedIn: 'root' }) export class TodoApiService { - // TODO 1.1: Créer un signal privé pour stocker la liste de tâches. - // Initialisez-le avec le tableau de données fourni dans les commentaires. - /* - [ - { id: 1, title: 'Apprendre les signaux Angular', completed: true }, - { id: 2, title: 'Créer un service en mémoire', completed: false }, - { id: 3, title: 'Préparer la transition vers HttpClient', completed: false }, - ] - */ - private readonly todos = signal([]); + private readonly todos = signal([ + { id: 1, title: 'Apprendre les signaux Angular', completed: true }, + { id: 2, title: 'Créer un service en mémoire', completed: false }, + { id: 3, title: 'Préparer la transition vers HttpClient', completed: false }, + ]); private nextId = 4; - // TODO 1.2: Exposer le signal `todos` en tant que propriété publique `todos$` - // en lecture seule en utilisant `.asReadonly()`. + // C'est la source de vérité pour les données. Les composants s'y connecteront. public readonly todos$: Signal = this.todos.asReadonly(); // Cette méthode sert uniquement à SIMULER un appel réseau pour le chargement initial. @@ -31,23 +25,27 @@ export class TodoApiService { } createTodo(todoData: TodoCreate): Observable { - // TODO 1.3: Implémenter la logique de création. - // 1. Créez un objet `newTodo` avec un nouvel `id`, et les données de `todoData`. - // 2. Mettez à jour le signal `todos` avec `.update()`. - // 3. Retournez le `newTodo` dans un `Observable` avec un `delay` de 300ms. - const newTodo: Todo = { id: 0, title: '', completed: false }; // A MODIFIER - return of(newTodo); // A MODIFIER + const newTodo: Todo = { + id: this.nextId++, + title: todoData.title, + completed: todoData.completed, + }; + this.todos.update(currentTodos => [...currentTodos, newTodo]); + console.log(`SERVICE: Tâche "${newTodo.title}" créée.`); + return of(newTodo).pipe(delay(300)); } toggleTodo(id: number): void { - // TODO 1.4: Implémenter la logique de bascule (toggle). - // Utilisez `this.todos.update()` et la méthode `.map()` pour inverser - // l'état `completed` de la tâche correspondante. + this.todos.update(currentTodos => + currentTodos.map(todo => + todo.id === id ? { ...todo, completed: !todo.completed } : todo + ) + ); + console.log(`SERVICE: Tâche ID ${id} basculée.`); } deleteTodo(id: number): void { - // TODO 1.4 (suite): Implémenter la logique de suppression. - // Utilisez `this.todos.update()` et la méthode `.filter()` pour - // supprimer la tâche correspondante. + this.todos.update(currentTodos => currentTodos.filter(todo => todo.id !== id)); + console.log(`SERVICE: Tâche ID ${id} supprimée.`); } } diff --git a/src/app/features/todo/todo-form/todo-form.component.html b/src/app/features/todo/todo-form/todo-form.component.html index 380a675..33c46f5 100644 --- a/src/app/features/todo/todo-form/todo-form.component.html +++ b/src/app/features/todo/todo-form/todo-form.component.html @@ -4,10 +4,10 @@ Annuler -
+
- + @if (todoForm.get('title')?.invalid && todoForm.get('title')?.touched) { Le titre est requis (2 caractères min). } @@ -15,14 +15,18 @@
- +
+ + @if (todoForm.get('completed')?.invalid && todoForm.get('completed')?.touched) { + Ce champ est requis. + }
@if (isSaving()) { - Enregistrement... + Chargement ... } @else {