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: `
@if (loading()) {
} @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'
);
},
});
}
}