import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, inject, signal, } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatToolbarModule } from '@angular/material/toolbar'; import { MatTooltipModule } from '@angular/material/tooltip'; import { RouterModule } from '@angular/router'; import { CommentResponse, CommentsService, TaskResponse, TasksService, User, UsersService, } from '@org/shared/api'; import { ToastService } from '@org/shared/toast'; import { catchError, finalize, forkJoin, of } from 'rxjs'; import { AddTaskDialogComponent } from './add-task-dialog.component'; import { TaskCardComponent } from './task-card.component'; @Component({ selector: 'lib-task-list', imports: [ CommonModule, RouterModule, MatProgressSpinnerModule, MatToolbarModule, MatIconModule, MatButtonModule, MatTooltipModule, TaskCardComponent, ], changeDetection: ChangeDetectionStrategy.OnPush, template: `
Tasks @if (loading()) {

Loading tasks...

} @else if (tasks().length === 0) {
assignment

No Tasks Found

There are currently no tasks in the system.

} @else {
@for (task of tasks(); track task.tasks.id) { }
}
`, styles: [ ` .fab { position: fixed; bottom: 2rem; right: 2rem; z-index: 100; } .page-container { max-width: 1200px; margin: 0 auto; } .page-header { margin-bottom: 1.5rem; border-radius: var(--mat-sys-corner-small); box-shadow: var(--mat-sys-level1); } .spacer { flex: 1 1 auto; } .loading-container { display: flex; flex-direction: column; align-items: center; margin: 3rem 0; gap: 1rem; } .empty-state { display: flex; flex-direction: column; align-items: center; background-color: var(--mat-sys-surface-container-low); border-radius: var(--mat-sys-corner-small); padding: 3rem 1.5rem; margin: 1.5rem 0; text-align: center; box-shadow: var(--mat-sys-level1); } .empty-icon { font-size: 3rem; height: 3rem; width: 3rem; color: var(--mat-sys-outline); margin-bottom: 1rem; } .task-container { margin: 1rem 0; } @media (max-width: 768px) { .page-container { padding: 0 0.5rem 5rem 0.5rem; } } `, ], }) export class TaskListComponent { private readonly tasksService = inject(TasksService); private readonly usersService = inject(UsersService); private readonly commentsService = inject(CommentsService); private readonly toastService = inject(ToastService); private readonly dialog = inject(MatDialog); readonly tasks = signal([]); readonly users = signal([]); readonly comments = signal([]); readonly loading = signal(true); readonly addingComment = signal(false); constructor() { this.loadData(); } loadData() { this.loading.set(true); forkJoin({ users: this.usersService.getUsers(), tasks: this.tasksService.getTasks(), comments: this.commentsService.getComments(), }) .pipe( catchError((error) => { console.error('Error loading data:', error); this.toastService.show( 'Failed to load data. Please try again.', 'error' ); return of({ users: [], tasks: [], comments: [] }); }), finalize(() => this.loading.set(false)) ) .subscribe({ next: (data) => { this.users.set(data.users); this.tasks.set(data.tasks); this.comments.set(data.comments); }, }); } openAddTaskDialog() { const dialogRef = this.dialog.open(AddTaskDialogComponent, { width: '400px', enterAnimationDuration: '220ms', exitAnimationDuration: '180ms', autoFocus: true, restoreFocus: true, disableClose: false, }); dialogRef.afterClosed().subscribe((result) => { if (result) { this.loadData(); } }); } // Methods moved to child components addComment(data: { taskId: number; content: string; userId: number }) { this.addingComment.set(true); const comment = { content: data.content, taskId: data.taskId, userId: data.userId, }; this.commentsService .createComment(comment) .pipe(finalize(() => this.addingComment.set(false))) .subscribe({ next: (newComment) => { this.comments.update((comments) => [...comments, newComment]); this.toastService.show('Comment added successfully!'); }, error: (error) => { console.error('Error adding comment:', error); this.toastService.show( 'Failed to add comment! Please try again.', 'error' ); }, }); } }