11import { Component , OnDestroy , OnInit , inject } from '@angular/core' ;
22import { ActivatedRoute , Router } from '@angular/router' ;
3- import { Message } from 'primeng/api' ;
3+ import { ConfirmationService , Message , MessageService } from 'primeng/api' ;
44import { Subject , forkJoin , of , takeUntil } from 'rxjs' ;
55import { catchError } from 'rxjs/operators' ;
66import { ProjectsApiClient } from '../../../../core/api/clients/projects-api.client' ;
77import { TaskItemsApiClient } from '../../../../core/api/clients/task-items-api.client' ;
88import { ProjectDto , ProjectMemberDto } from '../../../../core/api/models/project.model' ;
99import { TaskItemDto } from '../../../../core/api/models/task-item.model' ;
1010import { TaskStatus } from '../../../../core/api/models/task-status.enum' ;
11+ import { AppRole } from '../../../../core/auth/models/app-role.model' ;
1112import { AuthService } from '../../../../core/auth/services/auth.service' ;
1213import { APP_ENVIRONMENT } from '../../../../core/config/app-environment.token' ;
1314import { AppPreferencesService } from '../../../../core/preferences/app-preferences.service' ;
@@ -27,6 +28,8 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy {
2728 private readonly projectsApiClient = inject ( ProjectsApiClient ) ;
2829 private readonly taskItemsApiClient = inject ( TaskItemsApiClient ) ;
2930 private readonly authService = inject ( AuthService ) ;
31+ private readonly confirmationService = inject ( ConfirmationService ) ;
32+ private readonly messageService = inject ( MessageService ) ;
3033 private readonly appEnvironment = inject ( APP_ENVIRONMENT ) ;
3134 private readonly preferencesService = inject ( AppPreferencesService ) ;
3235 private readonly router = inject ( Router ) ;
@@ -44,6 +47,7 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy {
4447 isPreviewMode = false ;
4548 previewDetail : string | null = null ;
4649 errors : Message [ ] = [ ] ;
50+ isProjectDeletePending = false ;
4751
4852 ngOnInit ( ) : void {
4953 this . loadProjects ( ) ;
@@ -130,6 +134,36 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy {
130134 void this . router . navigate ( [ '/tasks' ] ) ;
131135 }
132136
137+ canDeleteSelectedProject ( ) : boolean {
138+ const project = this . selectedProjectDetails ?? this . selectedProject ;
139+ if ( ! project ) {
140+ return false ;
141+ }
142+
143+ if ( this . authService . hasRole ( AppRole . Administrator ) ) {
144+ return true ;
145+ }
146+
147+ return this . authService . hasRole ( AppRole . ProjectManager ) && project . ownerUserId === this . authService . currentUserId ( ) ;
148+ }
149+
150+ deleteSelectedProject ( ) : void {
151+ const project = this . selectedProjectDetails ?? this . selectedProject ;
152+ if ( ! project || this . isProjectDeletePending || ! this . canDeleteSelectedProject ( ) ) {
153+ return ;
154+ }
155+
156+ this . confirmationService . confirm ( {
157+ header : 'Delete Project' ,
158+ message : `Delete project "${ project . name } "? This will remove related project data.` ,
159+ icon : 'pi pi-exclamation-triangle' ,
160+ acceptLabel : 'Delete' ,
161+ rejectLabel : 'Cancel' ,
162+ acceptButtonStyleClass : 'p-button-danger' ,
163+ accept : ( ) => this . executeProjectDeletion ( project )
164+ } ) ;
165+ }
166+
133167 getStatusName ( status : TaskStatus ) : string {
134168 switch ( status ) {
135169 case TaskStatus . Todo :
@@ -290,6 +324,58 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy {
290324 } ) ;
291325 }
292326
327+ private executeProjectDeletion ( project : ProjectDto ) : void {
328+ const previousProjects = [ ...this . projects ] ;
329+ const previousSelectedProjectId = this . selectedProjectId ;
330+ const previousSelectedDetails = this . selectedProjectDetails ;
331+ const previousMembers = [ ...this . projectMembers ] ;
332+ const previousRecentTasks = [ ...this . recentTasks ] ;
333+
334+ this . isProjectDeletePending = true ;
335+ this . projects = this . projects . filter ( ( entry ) => entry . id !== project . id ) ;
336+ this . selectedProjectDetails = null ;
337+ this . projectMembers = [ ] ;
338+ this . recentTasks = [ ] ;
339+
340+ const nextProjectId = this . projects [ 0 ] ?. id ?? null ;
341+ this . selectedProjectId = nextProjectId ;
342+ if ( nextProjectId ) {
343+ this . updateProjectQueryParam ( nextProjectId ) ;
344+ this . preferencesService . setLastSelectedProject ( ProjectDetailsComponent . PROJECT_SELECTION_CONTEXT , nextProjectId ) ;
345+ }
346+
347+ if ( this . isPreviewMode ) {
348+ this . isProjectDeletePending = false ;
349+ if ( nextProjectId ) {
350+ this . loadPreviewProjectData ( nextProjectId ) ;
351+ }
352+ this . messageService . add ( { severity : 'success' , summary : 'Deleted' , detail : 'Project deleted in preview mode.' } ) ;
353+ return ;
354+ }
355+
356+ this . projectsApiClient
357+ . delete ( project . id )
358+ . pipe ( takeUntil ( this . destroy$ ) )
359+ . subscribe ( {
360+ next : ( ) => {
361+ this . isProjectDeletePending = false ;
362+ if ( nextProjectId ) {
363+ this . loadProjectDetails ( nextProjectId ) ;
364+ }
365+ this . messageService . add ( { severity : 'success' , summary : 'Deleted' , detail : 'Project deleted successfully.' } ) ;
366+ } ,
367+ error : ( ) => {
368+ this . isProjectDeletePending = false ;
369+ this . projects = previousProjects ;
370+ this . selectedProjectId = previousSelectedProjectId ;
371+ this . selectedProjectDetails = previousSelectedDetails ;
372+ this . projectMembers = previousMembers ;
373+ this . recentTasks = previousRecentTasks ;
374+ this . messageService . add ( { severity : 'error' , summary : 'Delete Failed' , detail : 'Could not delete project.' } ) ;
375+ }
376+ } ) ;
377+ }
378+
293379 private loadPreviewProjects ( detail : string ) : void {
294380 this . isPreviewMode = true ;
295381 this . previewDetail = detail ;
0 commit comments