import { Component, EventEmitter, inject, Input, Output, SimpleChanges, ViewChild } from '@angular/core'; import { AngularMaterialModule } from '../../shared/module/angular-material.module'; import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { NavigationService } from '../../core/services/common/navigation.service'; import { UserPreferencesService } from '../../core/services/user-preference.service'; import { MatTableDataSource } from '@angular/material/table'; import { NotificationService } from '../../core/services/common/notification.service'; import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service'; import { UserPreferences } from '../../core/models/user-preference'; import { MatSort } from '@angular/material/sort'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { HolderService as HolderService } from '../../core/services/holder/holder.service'; import { HolderService as CarnetApplicationHolderService } from '../../core/services/carnet/holder.service'; import { CustomPaginator } from '../../shared/custom-paginator'; import { BasicDetail } from '../../core/models/holder/basic-detail'; import { HolderFilter } from '../../core/models/holder/holder-filter'; import { ConfirmDialogComponent } from '../../shared/components/confirm-dialog/confirm-dialog.component'; import { MatDialog } from '@angular/material/dialog'; import { StorageService } from '../../core/services/common/storage.service'; import { finalize } from 'rxjs'; @Component({ selector: 'app-holder-search', imports: [AngularMaterialModule, ReactiveFormsModule, CommonModule], templateUrl: './search-holder.component.html', styleUrl: './search-holder.component.scss', providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }], }) export class SearchHolderComponent { private _paginator!: MatPaginator; @ViewChild(MatPaginator, { static: false }) set paginator(value: MatPaginator) { this._paginator = value; this.dataSource.paginator = value; } get paginator(): MatPaginator { return this._paginator; } @ViewChild(MatSort, { static: false }) set sort(value: MatSort) { this.dataSource.sort = value; } @Input() isViewMode = false; @Input() headerid: number = 0; @Input() selectedHolderId: number = 0; @Input() applicationName: string = ''; @Output() holderSelectionCompleted = new EventEmitter(); showInactiveHolders: boolean = false; holders: BasicDetail[] = [] isLoading: boolean = false; changeInProgress: boolean = false; userPreferences: UserPreferences; searchForm: FormGroup; private fb = inject(FormBuilder); private holderService = inject(HolderService); private navigationService = inject(NavigationService); private carnetHolderService = inject(CarnetApplicationHolderService); private errorHandler = inject(ApiErrorHandlerService); private notificationService = inject(NotificationService); private storageService = inject(StorageService); private dialog = inject(MatDialog); dataSource = new MatTableDataSource([]); ngAfterViewInit() { // This is different from other pages to show the item selected in the table. //this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; } displayedColumns: string[] = ['holderName', 'dbaName', 'address', 'uscibMember', 'holderType', 'actions']; constructor( userPrefenceService: UserPreferencesService ) { this.userPreferences = userPrefenceService.getPreferences(); this.searchForm = this.createSearchForm(); } createSearchForm(): FormGroup { return this.fb.group({ holderName: [''] }); } ngOnInit(): void { this.searchHolders(); } ngOnChanges(changes: SimpleChanges): void { if (changes['selectedHolderId'] && this.paginator) { if (this.selectedHolderId && this.dataSource.data.length) { this.goToItemPage(this.selectedHolderId); } } } onSearch(): void { this.searchHolders(); } saveHolderSelection(): void { this.changeInProgress = true; const saveObservable = this.carnetHolderService.saveApplicationHolder(this.headerid, this.selectedHolderId ? Number(this.selectedHolderId) : 0); saveObservable.pipe(finalize(() => { this.changeInProgress = false; })).subscribe({ next: (basicData: any) => { this.notificationService.showSuccess(`Holder updated successfully`); this.holderSelectionCompleted.emit(true); }, error: (error: any) => { let errorMessage = this.errorHandler.handleApiError(error, `Failed to update holder details`); this.notificationService.showError(errorMessage); console.error('Error saving holder details:', error); } }); } toggleShowInactiveHolders(): void { this.showInactiveHolders = !this.showInactiveHolders; this.renderHolders(); } searchHolders(): void { this.isLoading = true; const filterData: HolderFilter = this.searchForm.value; this.holderService.getHolders(filterData).pipe(finalize(() => { this.isLoading = false; })).subscribe({ next: (holders: BasicDetail[]) => { this.dataSource.data = this.holders = holders; this.renderHolders() }, error: (error: any) => { let errorMessage = this.errorHandler.handleApiError(error, 'Failed to search holders'); this.notificationService.showError(errorMessage); console.error('Error loading holders:', error); } }); } renderHolders() { if (this.showInactiveHolders) { this.dataSource.data = this.holders; } else { this.dataSource.data = this.holders.filter((holder: any) => !holder?.isInactive); } } addNewHolder(): void { if (this.headerid) { let currentApplicationDetails = { headerid: this.headerid, applicationName: this.applicationName } this.storageService.set("currentapplication", currentApplicationDetails); } this.navigationService.navigate(["add-holder"]) } onEdit(id: string) { if (this.headerid) { let currentApplicationDetails = { headerid: this.headerid, applicationName: this.applicationName } this.storageService.set("currentapplication", currentApplicationDetails); } this.navigationService.navigate(['edit-holder', id]); } inactivateHolder(holderid: number): void { const dialogRef = this.dialog.open(ConfirmDialogComponent, { width: '350px', data: { title: 'Confirm Inactivation', message: 'Are you sure you want to inactivate this holder?', confirmText: 'Yes', cancelText: 'Cancel' } }); dialogRef.afterClosed().subscribe(result => { if (result) { this.holderService.inactivateHolder(holderid).subscribe({ next: () => { this.notificationService.showSuccess('Holder inactivated successfully'); this.searchHolders(); }, error: (error) => { let errorMessage = this.errorHandler.handleApiError(error, 'Failed to inactivate holder'); this.notificationService.showError(errorMessage); console.error('Error inactivating holder:', error); } }); } }); } reactivateHolder(holderid: number): void { const dialogRef = this.dialog.open(ConfirmDialogComponent, { width: '350px', data: { title: 'Confirm Reactivation', message: 'Are you sure you want to reactivate this holder?', confirmText: 'Yes', cancelText: 'Cancel' } }); dialogRef.afterClosed().subscribe(result => { if (result) { this.holderService.reactivateHolder(holderid).subscribe({ next: () => { this.notificationService.showSuccess('Holder reactivated successfully'); this.searchHolders(); }, error: (error) => { let errorMessage = this.errorHandler.handleApiError(error, 'Failed to reactivate holder'); this.notificationService.showError(errorMessage); console.error('Error reactivating holder:', error); } }); } }); } onClearSearch(): void { this.searchForm.reset(); this.searchHolders(); } onHolderSelection(holder: any): void { this.selectedHolderId = holder.holderid; } getAddressLabel(holder: BasicDetail): string { const parts = [ holder.address1, holder.address2, holder.city, holder.state, holder.zip, holder.country ]; // Filter out any empty, null, or undefined parts and then join them. return parts.filter(part => part).join(', '); } goToItemPage(holderid: number): void { const itemIndex = this.dataSource.data.findIndex(dataItem => dataItem.holderid === holderid); if (itemIndex > -1 && this.paginator) { const targetPageIndex = Math.floor(itemIndex / this.paginator.pageSize); this.paginator.pageIndex = targetPageIndex; this.dataSource.paginator = this.paginator; } } }