From d60fe7e7ec84113bba33cc67651acb9a7136aca9 Mon Sep 17 00:00:00 2001 From: HydrallHarsh Date: Wed, 22 Oct 2025 17:28:41 +0530 Subject: [PATCH] feat: add user detail dialog and integrate with admin users component --- .../admin-users/admin-users.component.ts | 59 +++++++++++- .../components/admin-users/admin-users.html | 11 +++ .../interfaces/interfaces.ts | 8 ++ .../user-detail-dialog.component.scss | 24 +++++ .../user-detail-dialog.component.ts | 89 +++++++++++++++++++ .../user-detail-dialog.html | 36 ++++++++ 6 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 apps/client/src/app/components/user-detail-dialog/interfaces/interfaces.ts create mode 100644 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.scss create mode 100644 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.ts create mode 100644 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html diff --git a/apps/client/src/app/components/admin-users/admin-users.component.ts b/apps/client/src/app/components/admin-users/admin-users.component.ts index 84b82d111..c2bf62d21 100644 --- a/apps/client/src/app/components/admin-users/admin-users.component.ts +++ b/apps/client/src/app/components/admin-users/admin-users.component.ts @@ -19,6 +19,7 @@ import { ViewChild } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; +import { MatDialog } from '@angular/material/dialog'; import { MatMenuModule } from '@angular/material/menu'; import { MatPaginator, @@ -26,6 +27,7 @@ import { PageEvent } from '@angular/material/paginator'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { ActivatedRoute, Router } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { differenceInSeconds, @@ -37,8 +39,10 @@ import { contractOutline, ellipsisHorizontal, keyOutline, + personOutline, trashOutline } from 'ionicons/icons'; +import { DeviceDetectorService } from 'ngx-device-detector'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -49,6 +53,8 @@ import { AdminService } from '../../services/admin.service'; import { DataService } from '../../services/data.service'; import { ImpersonationStorageService } from '../../services/impersonation-storage.service'; import { UserService } from '../../services/user/user.service'; +import { UserDetailDialogParams } from '../user-detail-dialog/interfaces/interfaces'; +import { GfUserDetailDialogComponent } from '../user-detail-dialog/user-detail-dialog.component'; @Component({ imports: [ @@ -72,7 +78,9 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit { public dataSource = new MatTableDataSource(); public defaultDateFormat: string; public displayedColumns: string[] = []; + public deviceType: string; public getEmojiFlag = getEmojiFlag; + public hasImpersonationId: boolean; public hasPermissionForSubscription: boolean; public hasPermissionToImpersonateAllUsers: boolean; public info: InfoItem; @@ -87,6 +95,10 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit { private adminService: AdminService, private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private deviceService: DeviceDetectorService, + private dialog: MatDialog, + private route: ActivatedRoute, + private router: Router, private impersonationStorageService: ImpersonationStorageService, private notificationService: NotificationService, private tokenStorageService: TokenStorageService, @@ -138,13 +150,58 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit { } }); - addIcons({ contractOutline, ellipsisHorizontal, keyOutline, trashOutline }); + addIcons({ + contractOutline, + ellipsisHorizontal, + personOutline, + keyOutline, + trashOutline + }); + + this.deviceType = this.deviceService.getDeviceInfo().deviceType; + this.hasImpersonationId = !!this.impersonationStorageService.getId(); + this.route.queryParams + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((params) => { + if (params['userId'] && params['userDetailDialog']) { + this.openUserDetailDialog(params['userId']); + } + }); } public ngOnInit() { this.fetchUsers(); } + public onOpenUserDetailDialog(userId: string) { + this.router.navigate([], { + queryParams: { userId, userDetailDialog: true } + }); + } + private openUserDetailDialog(userId: string) { + // Find the user data from the current dataSource + const userData = this.dataSource.data.find((user) => user.id === userId); + + const dialogRef = this.dialog.open(GfUserDetailDialogComponent, { + autoFocus: false, + data: { + userId: userId, + deviceType: this.deviceType, + hasImpersonationId: this.hasImpersonationId, + userData: userData // Pass the user data + } as UserDetailDialogParams, + height: this.deviceType === 'mobile' ? '80vh' : '60vh', + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + }); + + dialogRef + .afterClosed() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + this.fetchUsers(); // Refresh the users list + this.router.navigate(['.'], { relativeTo: this.route }); // Clear query params + }); + } public formatDistanceToNow(aDateString: string) { if (aDateString) { const distanceString = formatDistanceToNowStrict(parseISO(aDateString), { diff --git a/apps/client/src/app/components/admin-users/admin-users.html b/apps/client/src/app/components/admin-users/admin-users.html index 4e58abf08..23a371a89 100644 --- a/apps/client/src/app/components/admin-users/admin-users.html +++ b/apps/client/src/app/components/admin-users/admin-users.html @@ -216,6 +216,15 @@ + @if (hasPermissionToImpersonateAllUsers) {