import { Component, EventEmitter, inject, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { MatTableDataSource } from '@angular/material/table'; import { AngularMaterialModule } from '../../shared/module/angular-material.module'; import { CommonModule } from '@angular/common'; import { CustomPaginator } from '../../shared/custom-paginator'; import { ExpeditedFee } from '../../core/models/service-provider/expedited-fee'; import { DeliveryType } from '../../core/models/delivery-type'; import { TimeZone } from '../../core/models/timezone'; import { finalize, Subject, takeUntil } from 'rxjs'; import { UserPreferences } from '../../core/models/user-preference'; import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service'; import { CommonService } from '../../core/services/common/common.service'; import { NotificationService } from '../../core/services/common/notification.service'; import { TimeFormatService } from '../../core/services/common/timeformat.service'; import { ExpeditedFeeService } from '../../core/services/service-provider/expedited-fee.service'; @Component({ selector: 'app-expedited-fee', imports: [AngularMaterialModule, CommonModule, ReactiveFormsModule], templateUrl: './expedited-fee.component.html', styleUrl: './expedited-fee.component.scss', providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }], }) export class ExpeditedFeeComponent implements OnInit, OnDestroy { @ViewChild(MatPaginator, { static: false }) set paginator(value: MatPaginator) { this.dataSource.paginator = value; } @ViewChild(MatSort, { static: false }) set sort(value: MatSort) { this.dataSource.sort = value; } displayedColumns: string[] = ['customerType', 'deliveryType', 'time', 'fee', 'effectiveDate', 'actions']; dataSource = new MatTableDataSource(); feeForm: FormGroup; isEditing = false; currentFeeId: number | null = null; isLoading = false; changeInProgress = false; showForm = false; showExpiredRecords = false; expeditedFees: ExpeditedFee[] = []; readOnlyFields: any = { lastChangedDate: null, lastChangedBy: null }; private destroy$ = new Subject(); @Input() isEditMode = false; @Input() spid: number = 0; @Input() userPreferences!: UserPreferences; @Output() hasExpeditedFees = new EventEmitter(); customerTypes = [ { value: 'PREPARER', label: 'Preparer' }, { value: 'SELFISSUER', label: 'Self issuer' } ]; deliveryTypes: DeliveryType[] = []; timeZones: TimeZone[] = []; private fb = inject(FormBuilder); private expeditedFeeService = inject(ExpeditedFeeService); private notificationService = inject(NotificationService); private errorHandler = inject(ApiErrorHandlerService); private commonService = inject(CommonService); private timeFormatHelper = inject(TimeFormatService); constructor() { this.feeForm = this.fb.group({ customerType: ['PREPARER', Validators.required], deliveryType: ['', Validators.required], startTime: [0, Validators.required], endTime: [0], timeZone: ['', Validators.required], fee: [0, [Validators.required, Validators.min(0)]], effectiveDate: ['', Validators.required] }, { validator: this.validateNumberRange }); } ngOnInit(): void { this.loadExpeditedFees(); this.loadLookupData(); } ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); } ngAfterViewInit() { this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; } private validateNumberRange(group: FormGroup): { [key: string]: any } | null { const start = +group.get('startTime')?.value; const end = +group.get('endTime')?.value; return start && end && start >= end ? { invalidRange: true } : null; } loadExpeditedFees(): void { this.isLoading = true; this.expeditedFeeService.getExpeditedFees(this.spid).pipe(finalize(() => { this.isLoading = false; })).subscribe({ next: (fees: ExpeditedFee[]) => { this.expeditedFees = fees; this.dataSource.data = this.expeditedFees; this.renderRecods(); }, error: (error: any) => { let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load expedited fees'); this.notificationService.showError(errorMessage); console.error('Error loading expedited fees:', error); } }); } toggleShowExpiredRecords(): void { this.showExpiredRecords = !this.showExpiredRecords; this.renderRecods(); } renderRecods(): void { if (this.showExpiredRecords) { this.dataSource.data = this.expeditedFees.filter(record => record.expired); } else { this.dataSource.data = this.expeditedFees.filter(record => !record.expired); } } loadLookupData(): void { this.loadDeliveryTypes(); this.loadTimeZones(); } loadTimeZones(): void { this.commonService.getTimezones() .pipe(takeUntil(this.destroy$)) .subscribe({ next: (timeZones) => { this.timeZones = timeZones; }, error: (error) => { console.error('Failed to load time zones', error); } }); } loadDeliveryTypes(): void { this.commonService.getDeliveryTypes() .pipe(takeUntil(this.destroy$)) .subscribe({ next: (deliveryTypes) => { this.deliveryTypes = deliveryTypes; }, error: (error) => { console.error('Failed to load delivery types', error); } }); } // applyFilter(event: Event): void { // const filterValue = (event.target as HTMLInputElement).value; // this.dataSource.filter = filterValue.trim().toLowerCase(); // if (this.dataSource.paginator) { // this.dataSource.paginator.firstPage(); // } // } addNewFee(): void { this.showForm = true; this.isEditing = false; this.currentFeeId = null; this.feeForm.reset({ customerType: 'PREPARER' }); this.feeForm.patchValue({ fee: 0 }); this.feeForm.get('customerType')?.enable(); this.feeForm.get('deliveryType')?.enable(); this.feeForm.get('startTime')?.enable(); this.feeForm.get('endTime')?.enable(); this.feeForm.get('timeZone')?.enable(); } editFee(fee: ExpeditedFee): void { this.showForm = true; this.isEditing = true; this.currentFeeId = fee.expeditedFeeId; this.feeForm.patchValue({ customerType: fee.customerType, deliveryType: fee.deliveryType, startTime: fee.startTime, endTime: fee.endTime, timeZone: fee.timeZone, fee: fee.fee, effectiveDate: fee.effectiveDate }); this.readOnlyFields.lastChangedDate = fee.dateCreated; this.readOnlyFields.lastChangedBy = fee.createdBy; this.feeForm.get('customerType')?.disable(); this.feeForm.get('deliveryType')?.disable(); this.feeForm.get('startTime')?.disable(); this.feeForm.get('endTime')?.disable(); this.feeForm.get('timeZone')?.disable(); } saveFee(): void { if (this.feeForm.invalid) { this.feeForm.markAllAsTouched(); return; } const feeData = this.feeForm.value; const saveObservable = this.isEditing && this.currentFeeId ? this.expeditedFeeService.updateExpeditedFee(this.currentFeeId, feeData) : this.expeditedFeeService.createExpeditedFee(this.spid, feeData); this.changeInProgress = true; saveObservable.pipe(finalize(() => { this.changeInProgress = false; })).subscribe({ next: () => { this.notificationService.showSuccess(`Expedited fee ${this.isEditing ? 'updated' : 'added'} successfully`); this.loadExpeditedFees(); this.cancelEdit(); }, error: (error) => { let errorMessage = this.errorHandler.handleApiError(error, `Failed to ${this.isEditing ? 'update' : 'add'} expedited fee`); this.notificationService.showError(errorMessage); console.error('Error saving expedited fee:', error); } }); } // deleteFee(feeId: string): void { // const dialogRef = this.dialog.open(ConfirmDialogComponent, { // width: '350px', // data: { // title: 'Confirm Delete', // message: 'Are you sure you want to delete this expedited fee?', // confirmText: 'Delete', // cancelText: 'Cancel' // } // }); // dialogRef.afterClosed().subscribe(result => { // if (result) { // this.expeditedFeeService.deleteExpeditedFee(feeId).subscribe({ // next: () => { // this.notificationService.showSuccess('Expedited fee deleted successfully'); // this.loadExpeditedFees(); // }, // error: (error) => { // this.notificationService.showError('Failed to delete expedited fee'); // console.error('Error deleting expedited fee:', error); // } // }); // } // }); // } cancelEdit(): void { this.showForm = false; this.isEditing = false; this.currentFeeId = null; this.feeForm.reset({ customerType: 'PREPARER' }); } getCustomerTypeLabel(value: string): string { const type = this.customerTypes.find(t => t.value === value); return type ? type.label : value; } getDeliveryLabel(value: string): string { const delivery = this.deliveryTypes.find(t => t.value === value); return delivery ? delivery.name : value; } getTimeLabel(startTime: string, endTime: string, timeZone: string): string { return this.timeFormatHelper.formatTimeRange(startTime, timeZone, endTime); } }