From 8384c6598ec4958ac9f3056a3cfda94a9a60df32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20L=C3=B3pez?= Date: Fri, 20 Sep 2024 10:37:31 -0500 Subject: [PATCH] mi solucion --- src/app/app-routing.module.ts | 28 ++++- src/app/app.module.ts | 6 + .../components/footer/footer.component.html | 22 +++- src/app/components/footer/footer.component.ts | 19 ++- .../components/header/header.component.html | 2 +- src/app/interfaces/task.ts | 3 +- .../home/all-tasks/all-tasks.component.html | 20 ++++ .../home/all-tasks/all-tasks.component.ts | 56 +++++++++ .../complete-tasks.component.html | 19 +++ .../complete-tasks.component.ts | 46 ++++++++ src/app/pages/home/home.component.html | 32 +---- src/app/pages/home/home.component.ts | 49 ++++++-- .../pending-tasks.component.html | 19 +++ .../pending-tasks/pending-tasks.component.ts | 43 +++++++ src/app/services/todo-service.ts | 109 +++++++++++++++++- tsconfig.json | 2 +- 16 files changed, 421 insertions(+), 54 deletions(-) create mode 100644 src/app/pages/home/all-tasks/all-tasks.component.html create mode 100644 src/app/pages/home/all-tasks/all-tasks.component.ts create mode 100644 src/app/pages/home/complete-tasks/complete-tasks.component.html create mode 100644 src/app/pages/home/complete-tasks/complete-tasks.component.ts create mode 100644 src/app/pages/home/pending-tasks/pending-tasks.component.html create mode 100644 src/app/pages/home/pending-tasks/pending-tasks.component.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 00db1a2f..917ad62b 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -2,17 +2,37 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './pages/home/home.component'; +import { PendingTasksComponent } from './pages/home/pending-tasks/pending-tasks.component'; +import { CompleteTasksComponent } from './pages/home/complete-tasks/complete-tasks.component'; +import { AllTasksComponent } from './pages/home/all-tasks/all-tasks.component'; const routes: Routes = [ { path: '', component: HomeComponent, - pathMatch: 'full' - } + + children: [ + { + path: '', + + component: AllTasksComponent, // child route component that the router renders + }, + { + path: 'pending', + // child route path + component: PendingTasksComponent, // child route component that the router renders + }, + { + path: 'completed', + + component: CompleteTasksComponent, // another child route component that the router renders + }, + ], + }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], - exports: [RouterModule] + exports: [RouterModule], }) -export class AppRoutingModule { } +export class AppRoutingModule {} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2e56ce21..eb9a3d3b 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -7,6 +7,9 @@ import { HeaderComponent } from './components/header/header.component'; import { HomeComponent } from './pages/home/home.component'; import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { PendingTasksComponent } from './pages/home/pending-tasks/pending-tasks.component'; +import { CompleteTasksComponent } from './pages/home/complete-tasks/complete-tasks.component'; +import { AllTasksComponent } from './pages/home/all-tasks/all-tasks.component'; @NgModule({ declarations: [ @@ -20,6 +23,9 @@ import { CommonModule } from '@angular/common'; AppRoutingModule, HeaderComponent, FooterComponent, + PendingTasksComponent, + CompleteTasksComponent, + AllTasksComponent, CommonModule ], providers: [], diff --git a/src/app/components/footer/footer.component.html b/src/app/components/footer/footer.component.html index 52fbf7a9..f0aa667b 100644 --- a/src/app/components/footer/footer.component.html +++ b/src/app/components/footer/footer.component.html @@ -1,19 +1,29 @@ diff --git a/src/app/components/footer/footer.component.ts b/src/app/components/footer/footer.component.ts index db11e838..aadf8a8d 100644 --- a/src/app/components/footer/footer.component.ts +++ b/src/app/components/footer/footer.component.ts @@ -1,12 +1,27 @@ -import { Component } from '@angular/core'; +import { Component, Signal, computed, inject, input } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { TodoService } from 'src/app/services/todo-service'; +import { RouterLink, RouterLinkActive } from '@angular/router'; @Component({ selector: 'app-footer', standalone: true, - imports: [CommonModule], + imports: [CommonModule, RouterLink, RouterLinkActive], templateUrl: './footer.component.html', }) export class FooterComponent { + private todosSevice = inject(TodoService); + public numberOftasksCompleted: Signal = computed(() => this.todosSevice.todos().filter((task) => task.completed).length); + + + public totalElementsPending = input.required(); + + public pluralItem = computed(() => + this.totalElementsPending() > 1 ? 'items' : 'item' + ); + + public clearAllTasks(): void { + this.todosSevice.clearAllCompleteTasks(); + } } diff --git a/src/app/components/header/header.component.html b/src/app/components/header/header.component.html index 650e82ed..0c73b888 100644 --- a/src/app/components/header/header.component.html +++ b/src/app/components/header/header.component.html @@ -12,7 +12,7 @@

My Day

/> @if (formTask.controls.task.errors) { -

Este campo es requerido

+

Este campo es requerido

} diff --git a/src/app/interfaces/task.ts b/src/app/interfaces/task.ts index 245c8a6a..97ef68a1 100644 --- a/src/app/interfaces/task.ts +++ b/src/app/interfaces/task.ts @@ -1,5 +1,6 @@ export interface TaskTodo { id:string, title:string, - completed:boolean + completed:boolean, + edit:boolean } diff --git a/src/app/pages/home/all-tasks/all-tasks.component.html b/src/app/pages/home/all-tasks/all-tasks.component.html new file mode 100644 index 00000000..2ae11e60 --- /dev/null +++ b/src/app/pages/home/all-tasks/all-tasks.component.html @@ -0,0 +1,20 @@ +@for (task of tasks(); track task.id) { +
  • +
    + + + +
    + +
  • +} + diff --git a/src/app/pages/home/all-tasks/all-tasks.component.ts b/src/app/pages/home/all-tasks/all-tasks.component.ts new file mode 100644 index 00000000..f7edc7e5 --- /dev/null +++ b/src/app/pages/home/all-tasks/all-tasks.component.ts @@ -0,0 +1,56 @@ +import { CommonModule } from '@angular/common'; +import { Component, Signal, computed, inject, signal } from '@angular/core'; +import { TaskTodo } from 'src/app/interfaces/task'; +import { TodoService } from 'src/app/services/todo-service'; + +@Component({ + selector: 'app-all-tasks', + standalone: true, + imports: [CommonModule], + templateUrl: './all-tasks.component.html', + +}) +export class AllTasksComponent { + + private todoService = inject(TodoService); + + public inputEditValue = signal(''); + + public tasks: Signal = computed(() => this.todoService.todos()); + + public numberOftasksPending: Signal = computed( + () => this.todoService.todos().filter((task) => !task.completed).length + ); + + constructor() {} + + ngOnInit(): void {} + + public toogleTask(taskId: string): void { + this.todoService.toogleTask(taskId); + } + + public removeTask(taskId: string): void { + this.todoService.removeTask(taskId); + } + + public openEditMode(taskId: string) { + this.todoService.openEditModeByIdTask(taskId); + } + + public closeEditMode(taskId: string) { + this.todoService.closeEditModeByIdTask(taskId); + } + + public changeInputValue(event:Event){ + const newValue = (event.target as HTMLInputElement).value; + + this.inputEditValue.set(newValue); + } + + public editTask(taskId: string) { + + this.todoService.editTaskTitle(taskId, this.inputEditValue().trim()); + } + +} diff --git a/src/app/pages/home/complete-tasks/complete-tasks.component.html b/src/app/pages/home/complete-tasks/complete-tasks.component.html new file mode 100644 index 00000000..95681ac6 --- /dev/null +++ b/src/app/pages/home/complete-tasks/complete-tasks.component.html @@ -0,0 +1,19 @@ +@for (task of todosCompleted(); track task.id) { +
  • +
    + + + +
    + +
  • +} diff --git a/src/app/pages/home/complete-tasks/complete-tasks.component.ts b/src/app/pages/home/complete-tasks/complete-tasks.component.ts new file mode 100644 index 00000000..e7c892b2 --- /dev/null +++ b/src/app/pages/home/complete-tasks/complete-tasks.component.ts @@ -0,0 +1,46 @@ +import { CommonModule } from '@angular/common'; +import { Component, computed, inject, signal } from '@angular/core'; +import { TodoService } from 'src/app/services/todo-service'; + +@Component({ + selector: 'app-complete-tasks', + standalone: true, + imports: [CommonModule], + templateUrl: './complete-tasks.component.html', +}) +export class CompleteTasksComponent { + + + private todosService = inject(TodoService); + + public inputEditValue = signal(''); + + public todosCompleted = computed(() => this.todosService.todosCompleted()); + + public toogleTask(taskId: string): void { + this.todosService.toogleTask(taskId); + } + + public removeTask(taskId: string): void { + this.todosService.removeTask(taskId); + } + + public openEditMode(taskId: string) { + this.todosService.openEditModeByIdTask(taskId); + } + + public closeEditMode(taskId: string) { + this.todosService.closeEditModeByIdTask(taskId); + } + + public changeInputValue(event: Event) { + const newValue = (event.target as HTMLInputElement).value; + + this.inputEditValue.set(newValue); + } + + public editTask(taskId: string) { + this.todosService.editTaskTitle(taskId, this.inputEditValue().trim()); + } + +} diff --git a/src/app/pages/home/home.component.html b/src/app/pages/home/home.component.html index 41aa2046..6b226e35 100644 --- a/src/app/pages/home/home.component.html +++ b/src/app/pages/home/home.component.html @@ -7,41 +7,13 @@
      - - @for (task of tasks(); track task.id) { -
    • -
      - - - -
      - -
    • - } + - -
    - + } diff --git a/src/app/pages/home/home.component.ts b/src/app/pages/home/home.component.ts index 0ec882c6..863b19b4 100644 --- a/src/app/pages/home/home.component.ts +++ b/src/app/pages/home/home.component.ts @@ -1,25 +1,60 @@ import { CommonModule } from '@angular/common'; -import { Component, OnInit, Signal, WritableSignal, computed, inject, signal } from '@angular/core'; +import { + Component, + ElementRef, + EventEmitter, + OnInit, + Signal, + computed, + inject, + signal, +} from '@angular/core'; import { TaskTodo } from 'src/app/interfaces/task'; import { TodoService } from 'src/app/services/todo-service'; @Component({ selector: 'app-home', templateUrl: './home.component.html', +}) +export class HomeComponent implements OnInit { + private todoService = inject(TodoService); + public inputEditValue = signal(''); + public tasks: Signal = computed(() => this.todoService.todos()); -}) -export class HomeComponent implements OnInit { + public numberOftasksPending: Signal = computed( + () => this.todoService.todos().filter((task) => !task.completed).length + ); - private todoService = inject(TodoService); + constructor() {} - public tasks: Signal = computed(()=> this.todoService.todos()) + ngOnInit(): void {} - constructor() { } + public toogleTask(taskId: string): void { + this.todoService.toogleTask(taskId); + } - ngOnInit(): void { + public removeTask(taskId: string): void { + this.todoService.removeTask(taskId); + } + public openEditMode(taskId: string) { + this.todoService.openEditModeByIdTask(taskId); } + public closeEditMode(taskId: string) { + this.todoService.closeEditModeByIdTask(taskId); + } + + public changeInputValue(event:Event){ + const newValue = (event.target as HTMLInputElement).value; + + this.inputEditValue.set(newValue); + } + + public editTask(taskId: string) { + + this.todoService.editTaskTitle(taskId, this.inputEditValue().trim()); + } } diff --git a/src/app/pages/home/pending-tasks/pending-tasks.component.html b/src/app/pages/home/pending-tasks/pending-tasks.component.html new file mode 100644 index 00000000..6529b77d --- /dev/null +++ b/src/app/pages/home/pending-tasks/pending-tasks.component.html @@ -0,0 +1,19 @@ +@for (task of todosPending(); track task.id) { +
  • +
    + + + +
    + +
  • +} diff --git a/src/app/pages/home/pending-tasks/pending-tasks.component.ts b/src/app/pages/home/pending-tasks/pending-tasks.component.ts new file mode 100644 index 00000000..483b8035 --- /dev/null +++ b/src/app/pages/home/pending-tasks/pending-tasks.component.ts @@ -0,0 +1,43 @@ +import { CommonModule } from '@angular/common'; +import { Component, computed, inject, signal } from '@angular/core'; +import { TodoService } from 'src/app/services/todo-service'; + +@Component({ + selector: 'app-pending-tasks', + standalone: true, + imports: [CommonModule], + templateUrl: './pending-tasks.component.html', +}) +export class PendingTasksComponent { + private todosService = inject(TodoService); + + public inputEditValue = signal(''); + + public todosPending = computed(() => this.todosService.todosPending()); + + public toogleTask(taskId: string): void { + this.todosService.toogleTask(taskId); + } + + public removeTask(taskId: string): void { + this.todosService.removeTask(taskId); + } + + public openEditMode(taskId: string) { + this.todosService.openEditModeByIdTask(taskId); + } + + public closeEditMode(taskId: string) { + this.todosService.closeEditModeByIdTask(taskId); + } + + public changeInputValue(event: Event) { + const newValue = (event.target as HTMLInputElement).value; + + this.inputEditValue.set(newValue); + } + + public editTask(taskId: string) { + this.todosService.editTaskTitle(taskId, this.inputEditValue().trim()); + } +} diff --git a/src/app/services/todo-service.ts b/src/app/services/todo-service.ts index 2a476ce8..f0b0171b 100644 --- a/src/app/services/todo-service.ts +++ b/src/app/services/todo-service.ts @@ -4,6 +4,7 @@ import { WritableSignal, computed, signal, + effect, } from '@angular/core'; import { TaskTodo } from './../interfaces/task'; @@ -13,17 +14,121 @@ export class TodoService { public todos: Signal = computed(() => this.#todos()); - constructor() {} + + public todosPending: Signal = computed( + () => this.todos().filter((task) => !task.completed) + ); + + public todosCompleted: Signal = computed( + () => this.todos().filter((task) => task.completed) + ); + + constructor() { + this.getTodosLocalStorage(); + + effect(() => { + if (this.#todos().length > 0) { + localStorage.setItem('mydayapp-angular', JSON.stringify(this.#todos())); + } + }); + } + + private getTodosLocalStorage() { + if (!localStorage.getItem('mydayapp-angular')) return; + + const todosLocalStorage = JSON.parse( + localStorage.getItem('mydayapp-angular')! + ) as TaskTodo[]; + + this.#todos.set(todosLocalStorage); + } public addNewTask(titleTask: string) { - console.log(titleTask); this.#todos.set([ ...this.#todos(), { id: `${this.#todos().length + 1}`, completed: false, title: titleTask, + edit: false, }, ]); } + + public removeTask(taskId: string) { + const tasksWithoutRemoved: TaskTodo[] = this.#todos().filter( + (task) => task.id != taskId + ); + + this.#todos.set(tasksWithoutRemoved); + } + + public toogleTask(taskId: string) { + const indexTask = this.#todos().findIndex((task) => task.id == taskId); + + const todos = [...this.#todos()]; + + let taskUpdate = todos[indexTask]; + + taskUpdate = { + ...taskUpdate, + completed: !taskUpdate.completed, + }; + + todos.splice(indexTask, 1, taskUpdate); + + this.#todos.set(todos); + } + + public clearAllCompleteTasks() { + const pendingTasks = this.#todos().filter((task) => !task.completed); + this.#todos.set(pendingTasks); + } + + public openEditModeByIdTask(taskId: string) { + this.#todos.update((tasks) => + tasks.map((task) => ({ ...task, edit: false })) + ); + + const indexTask = this.#todos().findIndex((task) => task.id == taskId); + + const todos = [...this.#todos()]; + + let taskUpdate = todos[indexTask]; + + taskUpdate = { + ...taskUpdate, + edit: true, + }; + + todos.splice(indexTask, 1, taskUpdate); + + this.#todos.set(todos); + } + + public closeEditModeByIdTask(taskId: string) { + this.#todos.update((tasks) => + tasks.map((task) => ({ ...task, edit: false })) + ); + } + + public editTaskTitle(taskId: string, title:string) { + const indexTask = this.#todos().findIndex((task) => task.id == taskId); + + const todos = [...this.#todos()]; + + let taskUpdate = todos[indexTask]; + + taskUpdate = { + ...taskUpdate, + title:title, + edit: false, + }; + + console.log(taskUpdate); + + todos.splice(indexTask, 1, taskUpdate); + + this.#todos.set(todos); + } } diff --git a/tsconfig.json b/tsconfig.json index 1407cb6e..8e584f58 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,7 +16,7 @@ "experimentalDecorators": true, "moduleResolution": "node", "importHelpers": true, - "target": "ES2022", + "target": "ESNext", "module": "es2020", "lib": [ "es2020",