From 2d29184a857ff43fb7beda7f2fba964166c6d971 Mon Sep 17 00:00:00 2001
From: "thibault.capt" <thibault.capt@etu.hesge.ch>
Date: Wed, 19 Feb 2025 17:25:19 +0100
Subject: [PATCH] (feat): add local storage service

---
 .../frontend/src/app/app.component.html       |  2 +-
 .../frontend/src/app/app.component.ts         |  4 +-
 todo-workspace/frontend/src/app/app.config.ts | 11 +++--
 todo-workspace/frontend/src/app/app.routes.ts |  2 +-
 .../adapters/local-storage-todo.service.ts    | 44 +++++++++++++++++++
 .../features/todo-list/todo-list.component.ts |  3 +-
 6 files changed, 58 insertions(+), 8 deletions(-)
 create mode 100644 todo-workspace/frontend/src/app/core/adapters/local-storage-todo.service.ts

diff --git a/todo-workspace/frontend/src/app/app.component.html b/todo-workspace/frontend/src/app/app.component.html
index 25331c8..67e7bd4 100644
--- a/todo-workspace/frontend/src/app/app.component.html
+++ b/todo-workspace/frontend/src/app/app.component.html
@@ -1 +1 @@
-<app-todo-list />
+<router-outlet />
diff --git a/todo-workspace/frontend/src/app/app.component.ts b/todo-workspace/frontend/src/app/app.component.ts
index 4374dbb..62b4b87 100644
--- a/todo-workspace/frontend/src/app/app.component.ts
+++ b/todo-workspace/frontend/src/app/app.component.ts
@@ -1,11 +1,11 @@
 import { Component, inject } from '@angular/core';
-import TodoListComponent from '@features/todo-list/todo-list.component';
 import { FaIconLibrary } from '@fortawesome/angular-fontawesome';
 import { faIcons } from '@shared/fa-icons';
+import { RouterOutlet } from '@angular/router';
 
 @Component({
   selector: 'app-root',
-  imports: [TodoListComponent],
+  imports: [RouterOutlet],
   templateUrl: './app.component.html',
   styleUrl: './app.component.scss',
 })
diff --git a/todo-workspace/frontend/src/app/app.config.ts b/todo-workspace/frontend/src/app/app.config.ts
index 7a84a42..4553b08 100644
--- a/todo-workspace/frontend/src/app/app.config.ts
+++ b/todo-workspace/frontend/src/app/app.config.ts
@@ -4,15 +4,20 @@ import { provideRouter } from '@angular/router';
 import { routes } from './app.routes';
 import { provideHttpClient } from '@angular/common/http';
 import { TodoService } from '@core/ports/todo.service';
-import { InMemoryTodoService } from '@core/adapters/in-memory-todo.service';
-import { TodoBuilder } from '@core/models/builder/todo.builder';
+import { LocalStorageTodoService } from '@core/adapters/local-storage-todo.service';
 
 export const appConfig: ApplicationConfig = {
   providers: [
     provideZoneChangeDetection({ eventCoalescing: true }),
     provideRouter(routes),
     provideHttpClient(),
+
     {
+      provide: TodoService,
+      useFactory: () => new LocalStorageTodoService(),
+    },
+
+    /*{
       provide: TodoService,
       useFactory: () =>
         new InMemoryTodoService().withTodos([
@@ -20,6 +25,6 @@ export const appConfig: ApplicationConfig = {
           new TodoBuilder().withId(2).withName('Apprendre Java Spring Boot').complete().build(),
           new TodoBuilder().withId(3).withName('Apprendre PostgreSQL').uncomplete().build(),
         ]),
-    },
+    },*/
   ],
 };
diff --git a/todo-workspace/frontend/src/app/app.routes.ts b/todo-workspace/frontend/src/app/app.routes.ts
index dc39edb..cf124b5 100644
--- a/todo-workspace/frontend/src/app/app.routes.ts
+++ b/todo-workspace/frontend/src/app/app.routes.ts
@@ -1,3 +1,3 @@
 import { Routes } from '@angular/router';
 
-export const routes: Routes = [];
+export const routes: Routes = [{ path: '', loadComponent: () => import('./features/todo-list/todo-list.component') }];
diff --git a/todo-workspace/frontend/src/app/core/adapters/local-storage-todo.service.ts b/todo-workspace/frontend/src/app/core/adapters/local-storage-todo.service.ts
new file mode 100644
index 0000000..59a91f8
--- /dev/null
+++ b/todo-workspace/frontend/src/app/core/adapters/local-storage-todo.service.ts
@@ -0,0 +1,44 @@
+import { TodoService } from '@core/ports/todo.service';
+import { Observable, of } from 'rxjs';
+import { Todo, Todos } from '@core/models/todo';
+import { TodoBuilder } from '@core/models/builder/todo.builder';
+
+export class LocalStorageTodoService implements TodoService {
+  add(todoName: string): Observable<Todo> {
+    const todos = this.getTodos();
+    const newTodo = new TodoBuilder()
+      .withId(todos.length + 1)
+      .withName(todoName)
+      .uncomplete()
+      .build();
+    this.setTodos([...todos, newTodo]);
+    return of(newTodo);
+  }
+
+  getAll(): Observable<Todos> {
+    return of(this.getTodos());
+  }
+
+  remove(todoId: number): Observable<void> {
+    const todos = this.getTodos().filter((todo) => todo.id !== todoId);
+    this.setTodos(todos);
+    return of(void 0);
+  }
+
+  toggleCompleted(todoId: number): Observable<Todo> {
+    const todo = this.getTodos().find((todo) => todo.id === todoId)!;
+    todo.completed = !todo.completed;
+    const todos = this.getTodos().map((todo) => (todo.id === todoId ? { ...todo, completed: true } : todo));
+    this.setTodos(todos);
+    return of(todo);
+  }
+
+  private getTodos(): Todos {
+    const todos = localStorage.getItem('todos');
+    return todos ? JSON.parse(todos) : [];
+  }
+
+  private setTodos(todos: Todos): void {
+    localStorage.setItem('todos', JSON.stringify(todos));
+  }
+}
diff --git a/todo-workspace/frontend/src/app/features/todo-list/todo-list.component.ts b/todo-workspace/frontend/src/app/features/todo-list/todo-list.component.ts
index 3af9ca6..0fa3a40 100644
--- a/todo-workspace/frontend/src/app/features/todo-list/todo-list.component.ts
+++ b/todo-workspace/frontend/src/app/features/todo-list/todo-list.component.ts
@@ -1,4 +1,4 @@
-import { Component, inject } from '@angular/core';
+import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
 import { TodoService } from '@core/ports/todo.service';
 import { toSignal } from '@angular/core/rxjs-interop';
 import { BehaviorSubject, switchMap, tap } from 'rxjs';
@@ -12,6 +12,7 @@ import { TodoListItemComponent } from '@features/todo-list/components/todo-list-
   imports: [FormsModule, AddTodoFormComponent, TodoListItemComponent, TodoListItemComponent],
   templateUrl: './todo-list.component.html',
   styleUrl: './todo-list.component.scss',
+  changeDetection: ChangeDetectionStrategy.OnPush,
 })
 export default class TodoListComponent {
   private reload$$ = new BehaviorSubject<void>(void 0);
-- 
GitLab