diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index ec79263..65404b5 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -8,11 +8,16 @@ import { NotFoundComponent } from './shared/components/not-found/not-found.compo import { UserSettingsComponent } from './user-settings/user-settings.component'; import { RegisterComponent } from './register/register.component'; import { ForgotPasswordComponent } from './forgot-password/forgot-password.component'; +import { ParamTableComponent } from './param/table/param-table.component'; +import { ManageTableRecordComponent } from './param/manage-table-record/manage-table-record.component'; +import { ManageParamRecordComponent } from './param/manage-param-record/manage-param-record.component'; export const routes: Routes = [ { path: 'login', component: LoginComponent }, { path: 'register', component: RegisterComponent }, { path: 'forgot-password', component: ForgotPasswordComponent }, + { path: 'table-record', component: ManageTableRecordComponent }, + { path: 'param-record/:id', component: ManageParamRecordComponent }, { path: 'usersettings', component: UserSettingsComponent, canActivate: [AuthGuard] }, { path: 'home', component: HomeComponent, canActivate: [AuthGuard] }, { path: 'service-provider/:id', component: EditServiceProviderComponent, canActivate: [AuthGuard] }, diff --git a/src/app/common/secured-header/secured-header.component.html b/src/app/common/secured-header/secured-header.component.html index 02de989..5438891 100644 --- a/src/app/common/secured-header/secured-header.component.html +++ b/src/app/common/secured-header/secured-header.component.html @@ -8,6 +8,7 @@ Home Users Regions + Parameters
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Type{{ client.PARAMTYPE }}Description{{ client.PARAMDESC || '--'}}Value{{ client.PARAMVALUE }}Additional Value 1{{ client.ADDLPARAMVALUE1 || '--' }}Additional Value 2{{ client.ADDLPARAMVALUE2 || '--'}}Additional Value 3{{ client.ADDLPARAMVALUE3 || '--' }}Additional Value 4{{ client.ADDLPARAMVALUE4 || '--' }}Additional Value 5{{ client.ADDLPARAMVALUE5 || '--'}}Actions +
+ + + + + + + +
+
+ info + No records found matching your criteria +
+ + + + +
+
+
+

{{ !isParamRecord ? 'Add New Table' : isEditing ? 'Edit Param' : 'Add New Param' }} +

+
+ +
+ + Param Type + + + Param Type is required + + + Maximum 10 characters allowed + + + + + {{!isParamRecord ? 'Table Description' : 'Param Description'}} + + + {{!isParamRecord ? 'Table Description' : 'Param Description'}} is required + + + Maximum 100 characters allowed + + + + +
+ +
+ + + Param Value + + + Param Value is required + + + Maximum 20 characters allowed + + + + + Additional Param Value 1 + + + Maximum 20 characters allowed + + +
+ +
+ + + Additional Param Value 2 + + + Maximum 20 characters allowed + + + + + Additional Param Value 3 + + + Maximum 20 characters allowed + + +
+ +
+ + + Additional Param Value 4 + + + Maximum 20 characters allowed + + + + + Additional Param Value 5 + + + Maximum 20 characters allowed + + +
+ + +
+
+
+ +
+ +
+ {{paramReadOnlyFields.lastChangedBy || 'N/A'}} +
+
+ +
+ +
+ {{paramReadOnlyFields.isInactive === true ? 'Yes' : 'No' }} +
+
+
+
+ + +
+ +
+ {{(paramReadOnlyFields.lastChangedDate | date:'mediumDate':'UTC') || 'N/A'}} +
+
+ + +
+ +
+ {{(paramReadOnlyFields.inactivatedDate | date:'mediumDate':'UTC') || 'N/A'}} +
+
+
+
+
+ +
+ + +
+
+
+ + \ No newline at end of file diff --git a/src/app/param/table/param-table.component.scss b/src/app/param/table/param-table.component.scss new file mode 100644 index 0000000..1ed7268 --- /dev/null +++ b/src/app/param/table/param-table.component.scss @@ -0,0 +1,174 @@ +.page-header { + margin: 0.5rem 0px; + color: var(--mat-sys-primary); + font-weight: 500; +} + +.actions-bar { + clear: both; + margin-bottom: -16px; + + mat-slide-toggle { + transform: scale(0.8); + margin-left: -1rem; + } + + button { + float: right; + } + + .icon-text { + padding-left: 10px !important; + font-size: 18px !important; + } +} + +.form-container { + background-color: white; + padding: 24px; + border-radius: 8px; + margin-top: 16px; + + .form-header { + margin-bottom: 24px; + + h3 { + margin: 0; + color: var(--mat-sys-primary); + font-weight: 500; + } + } + + form { + display: flex; + flex-direction: column; + gap: 16px; + + .form-row { + display: flex; + gap: 16px; + + mat-form-field { + flex: 1; + } + + .small-field { + max-width: 120px; + } + } + + .form-actions { + display: flex; + justify-content: flex-end; + gap: 16px; + margin-top: 16px; + } + + .readonly-section { + padding-top: 0.5rem; + border-top: 1px solid #eee; + + .readonly-fields { + display: flex; + gap: 2rem; + + .field-column { + flex: 1; + display: flex; + flex-direction: column; + gap: 1.5rem; + } + } + + .readonly-field { + label { + display: block; + font-size: 0.875rem; + color: #666; + margin-bottom: 0.25rem; + } + + .readonly-value { + padding: 0.25rem; + font-size: 0.9375rem; + display: flex; + align-items: center; + } + } + } + } +} + + +.results-section { + position: relative; + overflow: auto; + border-radius: 8px; + + .loading-shade { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(255, 255, 255, 0.7); + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + } + + mat-table { + width: 100%; + + mat-icon { + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + transform: scale(1.1); + } + } + + .mat-column-actions { + width: 180px; + text-align: center; + } + + .mat-column-defaultContact { + width: 80px; + text-align: center; + } + } + + .no-data-message { + text-align: center; + padding: 0.9rem; + color: rgba(0, 0, 0, 0.54); + + mat-icon { + font-size: 1rem; + width: 1rem; + height: 1rem; + margin-bottom: -3px; + } + } + + mat-paginator { + border-top: 1px solid rgba(0, 0, 0, 0.12); + border-radius: 0 0 8px 8px; + padding-top: 4px; + } +} + +.search-bar { + display: flex; + width: 100%; + margin-top: 10px; + + + .full-width { + flex: 1; + width: 100%; + } +} \ No newline at end of file diff --git a/src/app/param/table/param-table.component.ts b/src/app/param/table/param-table.component.ts new file mode 100644 index 0000000..0bb65e8 --- /dev/null +++ b/src/app/param/table/param-table.component.ts @@ -0,0 +1,280 @@ +import { Component, inject, Input, ViewChild } from '@angular/core'; +import { AngularMaterialModule } from '../../shared/module/angular-material.module'; +import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; +import { CommonModule } from '@angular/common'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { UserPreferences } from '../../core/models/user-preference'; +import { UserPreferencesService } from '../../core/services/user-preference.service'; +import { MatTableDataSource } from '@angular/material/table'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { NavigationService } from '../../core/services/common/navigation.service'; +import { ActivatedRoute } from '@angular/router'; +import { ParamService } from '../../core/services/param/param.service'; +import { ParamTableForm, ParamValue, ParamValueForm } from '../../core/models/param/paramValue'; +import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service'; +import { NotificationService } from '../../core/services/common/notification.service'; +import { TABLE_MODE } from '../../core/models/param/types'; + +@Component({ + selector: 'app-param-table', + imports: [AngularMaterialModule, ReactiveFormsModule, CommonModule, MatSlideToggleModule], + templateUrl: './param-table.component.html', + styleUrl: './param-table.component.scss' +}) +export class ParamTableComponent { + @ViewChild(MatPaginator) paginator!: MatPaginator; + @ViewChild(MatSort) sort!: MatSort; + + @Input() table_mode: TABLE_MODE = 'TABLE-RECORD' + @Input() paramHeading: string = 'Table Records'; + + isLoading: boolean = false; + userPreferences: UserPreferences; + paramType: string | null = null; + paramData: any = []; + showInactiveData: boolean = false; + isEditing: boolean = false; + showForm: boolean = false; + currentParamid: number | null = null; + + paramReadOnlyFields: any = { + lastChangedDate: null, + lastChangedBy: null, + isInactive: null, + inactivatedDate: null + }; + + private paramService = inject(ParamService); + private errorHandler = inject(ApiErrorHandlerService); + private notificationService = inject(NotificationService); + + dataSource = new MatTableDataSource([]); + paramForm: FormGroup; + + ngAfterViewInit() { + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + this.dataSource.data = this.paramData; + } + + displayedColumns: string[] = ['ParamType', 'ParamDesc', 'paramvalue', 'addlparamvalue1', 'addlparamvalue2', 'addlparamvalue3', + 'addlparamvalue4', 'addlparamvalue5', 'actions']; + + formControls: any = {}; + + getForm(): void { + if (this.table_mode === 'PARAM-RECORD') { + this.formControls = { + paramType: ['', [Validators.required, Validators.maxLength(10)]], + paramValue: ['', [Validators.required, Validators.maxLength(20)]], + paramDescription: ['', [Validators.required, Validators.maxLength(100)]], + Additional_Param_Value1: ['', [Validators.maxLength(20)]], + Additional_Param_Value2: ['', [Validators.maxLength(20)]], + Additional_Param_Value3: ['', [Validators.maxLength(20)]], + Additional_Param_Value4: ['', [Validators.maxLength(20)]], + Additional_Param_Value5: ['', [Validators.maxLength(20)]], + }; + } + else { + this.formControls = { + paramDescription: ['', [Validators.required, Validators.maxLength(100)]], + } + } + } + + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.dataSource.filter = filterValue.trim().toLowerCase(); + } + + get isParamRecord(): boolean { + return this.table_mode === 'PARAM-RECORD'; + } + + constructor( + private userPrefenceService: UserPreferencesService, + private navigationService: NavigationService, + private fb: FormBuilder, + ) { + this.userPreferences = this.userPrefenceService.getPreferences(); + this.getForm(); + this.paramForm = this.fb.group(this.formControls); + } + + cancelEdit(): void { + this.showForm = false; + this.isEditing = false; + this.currentParamid = null; + this.paramForm.reset(); + } + + private route = inject(ActivatedRoute); + + ngOnInit(): void { + this.paramType = this.route.snapshot.paramMap.get('id'); + this.getParamValues(); + } + + getParamValues(): void { + + this.isLoading = true; + + const P_PARAMTYPE: string = this.paramType ? this.paramType : '000'; + + this.paramService.getParamValues(P_PARAMTYPE).subscribe({ + next: (paramData: ParamValue[]) => { + this.paramData = paramData + this.renderParamData() + this.isLoading = false; + }, + error: (error: any) => { + let errorMessage = this.errorHandler.handleApiError(error, 'Failed to search preparers'); + this.notificationService.showError(errorMessage); + this.isLoading = false; + console.error('Error loading preparers:', error); + } + }); + } + + renderParamData() { + + if (this.showInactiveData && this.table_mode === 'PARAM-RECORD') { + this.dataSource.data = this.paramData.filter((data: any) => data?.INACTIVECODEFLAG === 'Y'); + } + else if (!this.showInactiveData && this.table_mode === 'PARAM-RECORD') { + this.dataSource.data = this.paramData.filter((data: any) => data?.INACTIVECODEFLAG === 'N' || data?.INACTIVECODEFLAG === null); + } + else { + this.dataSource.data = this.paramData; + } + } + + toggleShowInactiveData(): void { + this.showInactiveData = !this.showInactiveData; + this.renderParamData(); + } + + onRecordClick(id: string, paramDesc: string): void { + this.navigationService.navigate(['param-record', id], { queryParams: { param: paramDesc } }); + } + + addNewParam(): void { + this.getForm(); + this.paramForm = this.fb.group(this.formControls); + this.showForm = true; + this.isEditing = false; + this.currentParamid = null; + this.paramForm.reset(); + this.paramForm.get('paramType')?.setValue(this.paramType); + } + + onEditParam(param: any): void { + this.getForm(); + this.paramForm = this.fb.group(this.formControls); + + this.showForm = true; + this.isEditing = true; + this.currentParamid = param.PARAMID; + this.paramForm.patchValue({ + paramType: param.PARAMTYPE, + paramValue: param.PARAMVALUE, + paramDescription: param.PARAMDESC, + Additional_Param_Value1: param.ADDLPARAMVALUE1, + Additional_Param_Value2: param.ADDLPARAMVALUE2, + Additional_Param_Value3: param.ADDLPARAMVALUE3, + Additional_Param_Value4: param.ADDLPARAMVALUE4, + Additional_Param_Value5: param.ADDLPARAMVALUE5 + }); + + this.paramForm.get('paramType')?.setValue(this.paramType); + + this.paramReadOnlyFields.lastChangedDate = param.LASTUPDATEDDATE ?? param.DATECREATED; + this.paramReadOnlyFields.lastChangedBy = param.LASTUPDATEDBY ?? param.CREATEDBY; + this.paramReadOnlyFields.isInactive = param.INACTIVECODEFLAG === 'N' || !param.INACTIVECODEFLAG ? 'No' : 'Yes'; + this.paramReadOnlyFields.inactivatedDate = param.INACTIVEDATE; + } + + saveRecord(): void { + if (this.paramForm.invalid) { + this.paramForm.markAllAsTouched(); + return; + } + + let paramData: ParamTableForm | ParamValueForm; + + if (this.table_mode === 'TABLE-RECORD') { + paramData = { + P_TABLEFULLDESC: this.paramForm.value.paramDescription, + } as ParamTableForm; + } else { + paramData = { + P_PARAMTYPE: this.paramForm.value.paramType, + ...(this.isEditing && { P_PARAMID: this.currentParamid ?? 0 }), + P_PARAMDESC: this.paramForm.value.paramDescription, + P_PARAMVALUE: this.paramForm.value.paramValue, + P_ADDLPARAMVALUE1: this.paramForm.value.Additional_Param_Value1, + P_ADDLPARAMVALUE2: this.paramForm.value.Additional_Param_Value2, + P_ADDLPARAMVALUE3: this.paramForm.value.Additional_Param_Value3, + P_ADDLPARAMVALUE4: this.paramForm.value.Additional_Param_Value4, + P_ADDLPARAMVALUE5: this.paramForm.value.Additional_Param_Value5, + P_SORTSEQ: 1 + } as ParamValueForm; + } + + const saveObservable = this.table_mode === 'TABLE-RECORD' ? + this.paramService.CreateTableRecord(paramData as ParamTableForm) + : + this.isEditing + ? this.paramService.UpdateParamRecord(paramData as ParamValueForm) + : this.paramService.CreateParamRecord(paramData as ParamValueForm); + + saveObservable.subscribe({ + next: () => { + this.notificationService.showSuccess(`Record ${this.isEditing && (this.table_mode !== 'TABLE-RECORD') ? 'updated' : 'added'} successfully`); + this.getParamValues(); + if (this.table_mode === 'PARAM-RECORD') { + this.cancelEdit(); + } + }, + error: (error) => { + let errorMessage = this.errorHandler.handleApiError(error, `Failed to ${this.isEditing && (this.table_mode !== 'TABLE-RECORD') ? 'update' : 'add'} Record`); + this.notificationService.showError(errorMessage); + console.error('Error saving Record:', error); + } + }); + } + + InActivateParamRecord(PARAMID: number): void { + this.paramService.InActivateParamRecord(PARAMID).subscribe( + { + next: (data: any) => { + this.notificationService.showSuccess(`Param Inactivated successfully`); + this.getParamValues(); + }, + error: (error: any) => { + let errorMessage = this.errorHandler.handleApiError(error, `Failed to Inactivate Param`); + this.notificationService.showError(errorMessage); + console.error('Error Inactivating Param:', error); + } + } + ); + } + + ReActivateParamRecord(PARAMID: number): void { + this.paramService.ReActivateParamRecord(PARAMID).subscribe( + { + next: (data: any) => { + this.notificationService.showSuccess(`Param Reactivated successfully`); + this.getParamValues(); + }, + error: (error: any) => { + let errorMessage = this.errorHandler.handleApiError(error, `Failed to Reactivate Param`); + this.notificationService.showError(errorMessage); + console.error('Error Reactivating Param:', error); + } + } + ); + } + +}