From 45a40a39802ae3f92f27e60e5138497167c53ee7 Mon Sep 17 00:00:00 2001 From: Chneemann Date: Wed, 2 Apr 2025 20:32:23 +0200 Subject: [PATCH] feat: migrate subtask creation and toggle (check/uncheck) functionality to Django Rest --- .../components/add-task/add-task.component.ts | 20 ++--- .../components/board/task/task.component.ts | 4 +- src/app/interfaces/task.interface.ts | 6 +- src/app/services/api.service.ts | 15 ++++ src/app/services/toast-notification.servic.ts | 6 ++ .../task-overlay/task-overlay.component.html | 11 ++- .../task-overlay/task-overlay.component.ts | 82 +++++-------------- 7 files changed, 65 insertions(+), 79 deletions(-) diff --git a/src/app/components/add-task/add-task.component.ts b/src/app/components/add-task/add-task.component.ts index 867a901..e7dfeac 100644 --- a/src/app/components/add-task/add-task.component.ts +++ b/src/app/components/add-task/add-task.component.ts @@ -1,8 +1,7 @@ import { CommonModule } from '@angular/common'; -import { Component, HostListener, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { FormsModule, NgForm } from '@angular/forms'; import { AssignedComponent } from './assigned/assigned.component'; -import { FirebaseService } from '../../services/firebase.service'; import { Task } from '../../interfaces/task.interface'; import { OverlayService } from '../../services/overlay.service'; import { FormBtnComponent } from '../../shared/components/buttons/form-btn/form-btn.component'; @@ -38,7 +37,6 @@ export class AddTaskComponent implements OnInit { subtaskValue: string = ''; constructor( - public firebaseService: FirebaseService, private overlayService: OverlayService, private taskService: TaskService, private apiService: ApiService, @@ -57,7 +55,7 @@ export class AddTaskComponent implements OnInit { priority: this.taskService.getPriorities()[0], subtasks: [], subtasksTitle: [], - subtasksDone: [], + subtasksStatus: [], assigned: [], assignees: [], userData: [], @@ -97,7 +95,9 @@ export class AddTaskComponent implements OnInit { async loadEditTaskData() { if (this.overlayData) { const taskData = await firstValueFrom(this.getTaskData(this.overlayData)); - Object.assign(this.taskData, taskData); + if (taskData) { + this.taskData = { ...this.taskData, ...taskData }; + } } else if (this.overlayType === 'newTaskOverlay') { this.taskData.status = this.overlayData; } @@ -149,7 +149,7 @@ export class AddTaskComponent implements OnInit { */ addSubtask(subtaskName: string) { this.taskData.subtasksTitle.unshift(subtaskName); - this.taskData.subtasksDone.push(false); + this.taskData.subtasksStatus.push(false); this.saveTaskData(); } @@ -161,7 +161,7 @@ export class AddTaskComponent implements OnInit { const index = this.taskData.subtasksTitle.indexOf(subtaskName); if (index !== -1) { this.taskData.subtasksTitle.splice(index, 1); - this.taskData.subtasksDone.splice(index, 1); + this.taskData.subtasksStatus.splice(index, 1); this.saveTaskData(); } } @@ -270,7 +270,7 @@ export class AddTaskComponent implements OnInit { this.taskData.category = ''; this.taskData.assigned = []; this.taskData.subtasksTitle = []; - this.taskData.subtasksDone = []; + this.taskData.subtasksStatus = []; } /** @@ -298,9 +298,7 @@ export class AddTaskComponent implements OnInit { onSubmit(ngForm: NgForm) { if (ngForm.submitted && ngForm.form.valid) { - const { id, ...taskWithoutId } = this.taskData; - - this.apiService.saveNewTask(taskWithoutId).subscribe({ + this.apiService.saveNewTask(this.taskData).subscribe({ next: (response) => { this.toastNotificationService.createTaskSuccessToast(); this.updateNotifierService.notifyUpdate('task'); diff --git a/src/app/components/board/task/task.component.ts b/src/app/components/board/task/task.component.ts index 32aa3a1..1d4c1a0 100644 --- a/src/app/components/board/task/task.component.ts +++ b/src/app/components/board/task/task.component.ts @@ -132,7 +132,7 @@ export class TaskComponent { * @returns the number of completed subtasks */ completedSubtasks(): number { - return this.task.subtasks.filter((subtask) => subtask.done).length; + return this.task.subtasks.filter((subtask) => subtask.status).length; } /** @@ -141,7 +141,7 @@ export class TaskComponent { */ completedSubtasksPercent(): number { const completedSubtasksCount = this.task.subtasks.filter( - (subtask) => subtask.done + (subtask) => subtask.status ).length; return (completedSubtasksCount / this.task.subtasks.length) * 100; diff --git a/src/app/interfaces/task.interface.ts b/src/app/interfaces/task.interface.ts index c5b4694..281e2e3 100644 --- a/src/app/interfaces/task.interface.ts +++ b/src/app/interfaces/task.interface.ts @@ -9,7 +9,7 @@ export interface Task { priority: string; subtasks: Subtask[]; subtasksTitle: string[]; - subtasksDone: boolean[]; + subtasksStatus: boolean[]; assigned: string[]; assignees: Assignee[]; userData: UserSummary[]; @@ -18,9 +18,9 @@ export interface Task { } export interface Subtask { - id: number; + id: string; title: string; - done: boolean; + status: boolean; } export interface Assignee { diff --git a/src/app/services/api.service.ts b/src/app/services/api.service.ts index acfc6b0..07c9fa9 100644 --- a/src/app/services/api.service.ts +++ b/src/app/services/api.service.ts @@ -50,6 +50,21 @@ export class ApiService { }); } + updateSubtaskStatus( + taskId: string, + body: { + subtask_id: string; + subtask_title: string; + subtask_status: boolean; + } + ): Observable { + return this.request( + 'PATCH', + `/api/tasks/${taskId}/update_subtask/`, + body + ); + } + saveNewTask(task: Task): Observable { return this.request('POST', '/api/tasks/', task); } diff --git a/src/app/services/toast-notification.servic.ts b/src/app/services/toast-notification.servic.ts index 919617a..0bb1dee 100755 --- a/src/app/services/toast-notification.servic.ts +++ b/src/app/services/toast-notification.servic.ts @@ -35,6 +35,12 @@ export class ToastNotificationService { this.createInfoToast('Task successfully moved!', 'Task Moved'); } + // Subtask + + updateSubtaskSuccessToast(): void { + this.createSuccessToast('Subtask updated successfully!', 'Subtask Updated'); + } + // Contacts createContactSuccessToast(): void { diff --git a/src/app/shared/components/overlay/task-overlay/task-overlay.component.html b/src/app/shared/components/overlay/task-overlay/task-overlay.component.html index 8c8f83f..6f6bdf0 100644 --- a/src/app/shared/components/overlay/task-overlay/task-overlay.component.html +++ b/src/app/shared/components/overlay/task-overlay/task-overlay.component.html @@ -30,7 +30,7 @@

{{ "addTask.date" | translate }}:

- {{ timeConverter(task.date) }} + {{ task.date | date : "dd. MMM yyyy" }}

{{ "addTask.priority" | translate }}:

@@ -104,12 +104,17 @@
{ @@ -135,28 +123,31 @@ export class TaskOverlayComponent implements OnInit { this.closeDialog(); } - /** - * Toggles the status of a single subtask of a task. - * - * This function takes the task id, the index of the subtask, - * the array of subtask statuses, and the status of the subtask. - * It toggles the status of the subtask at the given index - * and updates the subtasksDone property of the task in the - * Firebase Realtime Database. - * - * @param taskId The task id of the task containing the subtask. - * @param index The index of the subtask. - * @param array The array of subtask statuses. - * @param status The status of the subtask at the given index. - */ toggleSubtaskStatus( taskId: string, - index: number, - array: boolean[], - status: boolean + subtaskId: string, + subtaskTitle: string, + currentStatus: boolean ) { - status ? (array[index] = false) : (array[index] = true); - this.firebaseService.updateSubTask(taskId, array); + const body = { + subtask_id: subtaskId, + subtask_title: subtaskTitle, + subtask_status: !currentStatus, + }; + this.apiService.updateSubtaskStatus(taskId, body).subscribe( + (response) => { + this.task?.subtasks.forEach((subtask) => { + if (subtask.id === subtaskId) { + subtask.status = !currentStatus; + } + }); + this.toastNotificationService.updateSubtaskSuccessToast(); + this.updateNotifierService.notifyUpdate('task'); + }, + (error) => { + console.error('Error updating subtask:', error); + } + ); } /** @@ -170,33 +161,4 @@ export class TaskOverlayComponent implements OnInit { capitalizeFirstLetter(data: string) { return data.charAt(0).toUpperCase() + data.slice(1); } - - /** - * Converts a date string to a human-readable format. - * - * @param dateString - The date string to convert. - * @returns A string representing the date in the format "MMM. DD, YYYY". - */ - timeConverter(dateString: string) { - var a = new Date(dateString); - var months = [ - 'Jan.', - 'Feb.', - 'Mar.', - 'Apr.', - 'May.', - 'Jun.', - 'Jul.', - 'Aug.', - 'Sep.', - 'Oct.', - 'Nov.', - 'Dec.', - ]; - var year = a.getFullYear(); - var month = months[a.getMonth()]; - var date = a.getDate(); - var time = month + ' ' + date + ', ' + year; - return time; - } }