From 314e899394ead19126b5d34feb24aa8c5dd519ea Mon Sep 17 00:00:00 2001 From: Mazdak Gibran <141390141+mazdakgibran@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:37:03 +0500 Subject: [PATCH] setup user email setup user email, fixing bugs, pagination and added search filter for transaction logs --- .../authenticate/login/login.component.html | 8 +- src/app/authenticate/login/login.component.ts | 11 ++- src/app/models/user.ts | 14 +++ .../shared/pipes/transactionLogFilter.pipe.ts | 28 ++++++ .../services/transaction-log.service.ts | 67 +++++++++++--- .../sms-banking/sms-banking.component.html | 20 ----- .../transaction-logs.component.html | 53 ++++++++++- .../transaction-logs.component.ts | 89 ++++++++++++------- .../setup-user/setup-user.component.html | 4 +- .../setup-user/setup-user.component.ts | 4 +- .../third-party-registration.component.html | 7 +- .../user-permissions.component.html | 15 +--- .../user-permissions.component.ts | 5 +- src/assets/data/sideMenu.json | 7 ++ src/styles.scss | 2 +- 15 files changed, 239 insertions(+), 95 deletions(-) create mode 100644 src/app/shared/pipes/transactionLogFilter.pipe.ts diff --git a/src/app/authenticate/login/login.component.html b/src/app/authenticate/login/login.component.html index a2c6366..a543a1c 100644 --- a/src/app/authenticate/login/login.component.html +++ b/src/app/authenticate/login/login.component.html @@ -5,10 +5,10 @@
- + + +
diff --git a/src/app/authenticate/login/login.component.ts b/src/app/authenticate/login/login.component.ts index 6847685..c550208 100644 --- a/src/app/authenticate/login/login.component.ts +++ b/src/app/authenticate/login/login.component.ts @@ -13,10 +13,11 @@ import { directions, FormConstants, HiddenValues, supportedLanguages } from '../ import { environment } from '../../../environments/environment'; import { AuthenticationService } from '../../services/authenticate.service'; import { UserCredentials } from '../authenticate'; +import { NgSelectModule } from '@ng-select/ng-select'; @Component({ selector: 'app-login', - imports: [TranslateModule, ReactiveFormsModule, CommonModule, PasswordHideShowComponent], + imports: [TranslateModule, ReactiveFormsModule, CommonModule, PasswordHideShowComponent, NgSelectModule], templateUrl: './login.component.html', styleUrl: './login.component.scss' }) @@ -28,7 +29,11 @@ export class LoginComponent { currentLanguage = new FormControl(); passwordType: string = 'password'; direction: string = ''; - supportedLanguages = supportedLanguages; + languageOptions = [ + { label: 'English', value: supportedLanguages.ENGLISH }, + { label: 'Arabic', value: supportedLanguages.ARABIC } +]; + ucred: UserCredentials = new UserCredentials(); @ViewChild(PasswordHideShowComponent) passwordHideShow?: PasswordHideShowComponent; @@ -64,7 +69,7 @@ export class LoginComponent { initializeLanguage(): void { if (isPlatformBrowser(this.platformId)) { - const savedLanguage = this.storageService.getItem('language') || 'English'; + const savedLanguage = this.storageService.getItem('language') || supportedLanguages.ENGLISH;; this.storageService.setItem('language', savedLanguage); this.currentLanguage.setValue(savedLanguage) this.translateService.setDefaultLang(savedLanguage); diff --git a/src/app/models/user.ts b/src/app/models/user.ts index 6a18b8a..46ca9e1 100644 --- a/src/app/models/user.ts +++ b/src/app/models/user.ts @@ -12,3 +12,17 @@ export interface SetupUser { email: string; role: string; } + +export interface TransactionLog { + logId: number; + porOrgacode: string; + transactionID: string; + drMbmbkmsnumber: string; + crMbmbkmsnumber: string; + ppmPymdcode: string; + sgtGntrdate: string; + channelCode: string; + createdAt: string; +} + + diff --git a/src/app/shared/pipes/transactionLogFilter.pipe.ts b/src/app/shared/pipes/transactionLogFilter.pipe.ts new file mode 100644 index 0000000..4296ba3 --- /dev/null +++ b/src/app/shared/pipes/transactionLogFilter.pipe.ts @@ -0,0 +1,28 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { TransactionLog } from '../../models/user'; + +@Pipe({ + name: 'transactionLogFilter', + standalone: true +}) +export class TransactionLogFilterPipe implements PipeTransform { + transform(logs: TransactionLog[], searchText: string): TransactionLog[] { + if (!logs || !searchText) { + return logs; + } + + const search = searchText.toLowerCase(); + + return logs.filter(log => + log.logId?.toString().toLowerCase().includes(search) || + log.porOrgacode?.toLowerCase().includes(search) || + log.transactionID?.toLowerCase().includes(search) || + log.drMbmbkmsnumber?.toLowerCase().includes(search) || + log.crMbmbkmsnumber?.toLowerCase().includes(search) || + log.ppmPymdcode?.toLowerCase().includes(search) || + log.sgtGntrdate?.toLowerCase().includes(search) || + log.channelCode?.toLowerCase().includes(search) || + log.createdAt?.toLowerCase().includes(search) + ); + } +} \ No newline at end of file diff --git a/src/app/shared/services/transaction-log.service.ts b/src/app/shared/services/transaction-log.service.ts index a00a489..81ed177 100644 --- a/src/app/shared/services/transaction-log.service.ts +++ b/src/app/shared/services/transaction-log.service.ts @@ -1,24 +1,71 @@ import { Injectable } from '@angular/core'; -import { map, Observable } from 'rxjs'; +import { BehaviorSubject, map, Observable } from 'rxjs'; import { URIKey } from '../../utils/uri-enums'; import { HttpErrorResponse, HttpParams } from '@angular/common/http'; import { HttpURIService } from '../../app.http.uri.service'; +import { TransactionLog } from '../../models/user'; @Injectable({ providedIn: 'root' }) export class TransactionLogService { - constructor(private httpUriService: HttpURIService) { } + private logsSubject = new BehaviorSubject([]); + private currentPageSubject = new BehaviorSubject(1); + private totalCountSubject = new BehaviorSubject(0); + private itemsPerPageSubject = new BehaviorSubject(5); - getTransactionLogs(): Observable { + logs$ = this.logsSubject.asObservable(); + currentPage$ = this.currentPageSubject.asObservable(); + totalCount$ = this.totalCountSubject.asObservable(); + itemsPerPage$ = this.itemsPerPageSubject.asObservable(); + + constructor(private httpUriService: HttpURIService) {} + + loadLogs(): void { const params = new HttpParams(); - return this.httpUriService.requestGET(URIKey.TRANSACTION_LOGS, params).pipe(map((response: any) => { - if (!(response instanceof HttpErrorResponse)) { - return Array.isArray(response) ? response : []; - } - return []; - }) - ); + this.httpUriService + .requestGET(URIKey.TRANSACTION_LOGS, params) + .subscribe({ + next: (res) => { + const logs = Array.isArray(res) ? res : res?.data; + this.logsSubject.next(logs ?? []); + this.totalCountSubject.next(logs.length); + }, + error: (err) => console.error(err) + }); + } + + setItemsPerPage(itemsPerPage: number): void { + this.itemsPerPageSubject.next(itemsPerPage); + this.currentPageSubject.next(1); + } + + nextPage(): void { + const totalPages = this.getTotalPages(); + const currentPage = this.currentPageSubject.value; + if (currentPage < totalPages) { + this.currentPageSubject.next(currentPage + 1); + } + } + + previousPage(): void { + const currentPage = this.currentPageSubject.value; + if (currentPage > 1) { + this.currentPageSubject.next(currentPage - 1); + } + } + + goToPage(page: number): void { + const totalPages = this.getTotalPages(); + if (page > 0 && page <= totalPages) { + this.currentPageSubject.next(page); + } + } + + getTotalPages(): number { + const totalCount = this.totalCountSubject.value; + const itemsPerPage = this.itemsPerPageSubject.value; + return Math.ceil(totalCount / itemsPerPage); } } diff --git a/src/app/sms-banking/sms-banking.component.html b/src/app/sms-banking/sms-banking.component.html index fbd16fd..79d5a2c 100644 --- a/src/app/sms-banking/sms-banking.component.html +++ b/src/app/sms-banking/sms-banking.component.html @@ -139,26 +139,6 @@ - diff --git a/src/app/transaction-logs/transaction-logs.component.html b/src/app/transaction-logs/transaction-logs.component.html index defdfb3..4d66565 100644 --- a/src/app/transaction-logs/transaction-logs.component.html +++ b/src/app/transaction-logs/transaction-logs.component.html @@ -20,13 +20,30 @@
- {{'transactionLogs' | translate}} + {{'transactionLogs' | translate}} +
+ +
- + + + + + + + + + +
+

{{'loadingTransactionLogs' | translate}}

@@ -56,7 +73,12 @@ - + {{ log.logId }} {{ log.porOrgacode }} {{ log.transactionID }} @@ -69,6 +91,31 @@ + +
+
+ + +
+ +
+ {{ 'page' | translate }} {{ currentPage }} {{ 'of' | translate }} {{ getTotalPages() }} ({{ totalCount }} {{ 'totalItems' | translate }}) +
+ +
+ + +
+
diff --git a/src/app/transaction-logs/transaction-logs.component.ts b/src/app/transaction-logs/transaction-logs.component.ts index 1b4f450..902073d 100644 --- a/src/app/transaction-logs/transaction-logs.component.ts +++ b/src/app/transaction-logs/transaction-logs.component.ts @@ -4,62 +4,83 @@ import { CommonModule } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; import { ExcelExportService } from '../shared/services/excel-export.service'; import { TRANSACTION_LOGS_FILE_NAME } from '../utils/app.constants'; - -interface TransactionLog { - logId: number; - porOrgacode: string; - drMbmbkmsnumber: string; - crMbmbkmsnumber: string; - crPcaglacode: string; - drPcaGlacode: string; - ppmPymdcode: string; - sgtGntrdate: string; - sgtGntrcreateat: string; - channelCode: string; - transactionID: string; - createdAt: string; - updatedAt: string; -} +import { pageSizeOptions } from '../utils/app.constants'; +import { NgSelectModule } from '@ng-select/ng-select'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { TransactionLogFilterPipe } from '../shared/pipes/transactionLogFilter.pipe'; +import {TransactionLog} from "../models/user" @Component({ selector: 'app-transaction-logs', templateUrl: './transaction-logs.component.html', providers: [TransactionLogService], - imports:[CommonModule, TranslateModule] + imports: [CommonModule, TranslateModule, NgSelectModule, FormsModule, ReactiveFormsModule, TransactionLogFilterPipe, ] }) export class TransactionLogsComponent implements OnInit { - + currentPage: number = 1; + totalCount: number = 0; + renewalDataExpanded: boolean = true; + pageSizeOptions = pageSizeOptions; + itemsPerPage: number = 5; logs: TransactionLog[] = []; isLoading = false; errorMessage: string = ''; + searchText: string = ''; constructor( private transactionLogService: TransactionLogService, private excelExportService: ExcelExportService ) {} - ngOnInit(): void { - this.loadLogs(); + get logs$(){ + return this.transactionLogService.logs$; } + ngOnInit(): void { + this.transactionLogService.loadLogs(); - loadLogs() { - this.isLoading = true; - this.errorMessage = ''; - - this.transactionLogService.getTransactionLogs().subscribe({ - next: (res) => { - this.logs = res; - this.isLoading = false; - }, - error: (err) => { - console.error('Failed to load transaction logs', err); - this.errorMessage = 'Failed to load transaction logs. Please try again.'; - this.isLoading = false; - } + this.transactionLogService.logs$.subscribe((logs: TransactionLog[]) => { + this.logs = logs; }); + + this.transactionLogService.currentPage$.subscribe((page) => { + this.currentPage = page; + }); + + this.transactionLogService.totalCount$.subscribe((count) => { + this.totalCount = count; + }); + + this.transactionLogService.itemsPerPage$.subscribe((size) => { + this.itemsPerPage = size; + }); + } + + onSearch(value: string): void { + this.searchText = value; +} + + get paginatedLogs(): TransactionLog[] { + const start = (this.currentPage - 1) * this.itemsPerPage; + const end = start + this.itemsPerPage; + return this.logs.slice(start, end); } exportDataInExcel(){ this.excelExportService.exportExcel(this.logs, TRANSACTION_LOGS_FILE_NAME) } + getTotalPages(): number { + return this.transactionLogService.getTotalPages(); + } + onPageSizeChange(pageSize: number): void { + this.transactionLogService.setItemsPerPage(pageSize); + } + + nextPage(): void { + this.transactionLogService.nextPage(); + } + + previousPage(): void { + this.transactionLogService.previousPage(); + } + } \ No newline at end of file diff --git a/src/app/user-management/setup-user/setup-user.component.html b/src/app/user-management/setup-user/setup-user.component.html index ad2e749..5564195 100644 --- a/src/app/user-management/setup-user/setup-user.component.html +++ b/src/app/user-management/setup-user/setup-user.component.html @@ -126,13 +126,13 @@ -
+
- {{ 'fieldRequired' | translate }} + {{ 'fieldRequired' | translate }}
diff --git a/src/app/user-management/setup-user/setup-user.component.ts b/src/app/user-management/setup-user/setup-user.component.ts index befccb4..a411383 100644 --- a/src/app/user-management/setup-user/setup-user.component.ts +++ b/src/app/user-management/setup-user/setup-user.component.ts @@ -81,7 +81,7 @@ export class SetupUserComponent implements OnInit { const newUser : SetupUser = { userId: this.userForm.value.userId, userFullname: this.userForm.value.userFullname, - email: `${this.userForm.value.userId}@dummy.com`, + email: this.userForm.value.email, role: this.userForm.value.userRole, porOrgacode: this.storageService.getItem('POR_ORGACODE'), password: this.userForm.value.defaultPassword @@ -138,7 +138,7 @@ ngOnInit(): void { userFullname: ['', [Validators.required, Validators.maxLength(500)]], defaultPassword: ['', Validators.required], email: ['', [Validators.required, Validators.email]], - userRole: ['', Validators.required] + userRole: [null, Validators.required] }); this.userService.loadUsers(); diff --git a/src/app/user-management/third-party-registration/third-party-registration.component.html b/src/app/user-management/third-party-registration/third-party-registration.component.html index d1b352d..f64df10 100644 --- a/src/app/user-management/third-party-registration/third-party-registration.component.html +++ b/src/app/user-management/third-party-registration/third-party-registration.component.html @@ -282,9 +282,10 @@
- - + + +
diff --git a/src/app/user-permissions/user-permissions.component.html b/src/app/user-permissions/user-permissions.component.html index 40440f4..536512d 100644 --- a/src/app/user-permissions/user-permissions.component.html +++ b/src/app/user-permissions/user-permissions.component.html @@ -12,17 +12,10 @@
- + + +
diff --git a/src/app/user-permissions/user-permissions.component.ts b/src/app/user-permissions/user-permissions.component.ts index 0efc51a..8af7d0a 100644 --- a/src/app/user-permissions/user-permissions.component.ts +++ b/src/app/user-permissions/user-permissions.component.ts @@ -10,10 +10,11 @@ import { URIKey } from '../utils/uri-enums'; import { HttpErrorResponse, HttpParams } from '@angular/common/http'; import { FormConstants, HiddenValues, SuccessMessages } from '../utils/enums'; import { CommonModule } from '@angular/common'; +import { NgSelectModule } from '@ng-select/ng-select'; @Component({ selector: 'app-user-permissions', - imports: [TranslateModule, ReactiveFormsModule, CommonModule], + imports: [TranslateModule, ReactiveFormsModule, CommonModule, TranslateModule, NgSelectModule], templateUrl: './user-permissions.component.html', styleUrl: './user-permissions.component.scss' }) @@ -27,7 +28,7 @@ export class UserPermissionsComponent { constructor(private credentialService: CredentialService, private fb: FormBuilder, private httpService: HttpURIService, private i18nService: I18NService) { this.permission = this.fb.group({ allocation: [''], - userCode: [''], + userCode: [null], userRole: [''], }); diff --git a/src/assets/data/sideMenu.json b/src/assets/data/sideMenu.json index ac2ab5c..c1a3f6d 100644 --- a/src/assets/data/sideMenu.json +++ b/src/assets/data/sideMenu.json @@ -103,6 +103,13 @@ "checked": false, "expanded": false, "children": [] + }, + { + "name": "transactionLogs", + "route": "/home/transactionLogs", + "checked": false, + "expanded": false, + "children": [] } ] }, diff --git a/src/styles.scss b/src/styles.scss index e3fc20b..c67a1a1 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -166,7 +166,7 @@ ng-select.form-select-sm { border: none !important; } .ng-select .ng-select-container{ - width: 98% !important; + width: 100% !important; } #downloadReport {