Enhance transaction logs UI and fix translations

Improved the transaction logs component with better table UI, pagination, loading/error states, and date filtering. Updated SCSS for responsive design and visual enhancements. Fixed translation keys and placeholders in user management and constants. Adjusted login direction logic and commented out duplicate login check in authentication service.
dev-pending-20-01-2026
Naeem Ullah 6 days ago
parent 244ff1067a
commit 6e4f1c3c58

@ -87,13 +87,13 @@ export class LoginComponent {
this.storageService.setItem('direction', this.direction); this.storageService.setItem('direction', this.direction);
} }
else { else {
this.direction = directions.RTL; this.direction = directions.LTR;
this.storageService.setItem('direction', this.direction); this.storageService.setItem('direction', this.direction);
} }
if (typeof document !== 'undefined') { if (typeof document !== 'undefined') {
document.documentElement.setAttribute('dir', this.direction); document.documentElement.setAttribute('dir', this.direction);
document.documentElement.setAttribute('lang', document.documentElement.setAttribute('lang',
this.direction === directions.RTL ? 'ar' : 'en'); this.direction === directions.LTR ? 'ar' : 'en');
} }
} }

@ -4,9 +4,7 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<div <div class="d-sm-flex align-items-center justify-content-between navbar-header p-0"></div>
class="d-sm-flex align-items-center justify-content-between navbar-header p-0"
></div>
</div> </div>
</div> </div>
</div> </div>
@ -21,7 +19,7 @@
</div> </div>
<form [formGroup]="logsSearchForm"> <form [formGroup]="logsSearchForm">
<div class="row g-3 mb-3 "> <div class="row g-3 mb-3">
<div class="col-md-6"> <div class="col-md-6">
<label> <label>
{{ "fromDate" | translate }} {{ "fromDate" | translate }}
@ -40,7 +38,6 @@
*ngIf="logsSearchForm.get('fromDate')?.touched && logsSearchForm.get('fromDate')?.invalid"> *ngIf="logsSearchForm.get('fromDate')?.touched && logsSearchForm.get('fromDate')?.invalid">
{{ 'fieldRequired' | translate }} {{ 'fieldRequired' | translate }}
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
@ -87,43 +84,49 @@
<div class="col-xl-12 mt-4"> <div class="col-xl-12 mt-4">
<div class="card border"> <div class="card border">
<div class="card-body"> <div class="card-body">
<div <div class="card-header d-flex justify-content-between align-items-center font-edit-13-child">
class="card-header d-flex justify-content-between align-items-center font-edit-13-child" {{ "activityLogDetails" | translate }}
>
{{ "activityLogDetails" | translate }}
<div class="d-flex gap-2 align-items-center" *ngIf="allItems.length"> <div class="d-flex gap-2 align-items-center" *ngIf="allItems.length">
<div class="search-box"> <div class="search-box">
<input <input
type="text" type="text"
class="form-control form-control-sm" class="form-control form-control-sm"
placeholder="{{ 'search' | translate }}" placeholder="{{ 'search' | translate }}"
[(ngModel)]="searchText" [(ngModel)]="searchText"
(ngModelChange)="applySearch()" (ngModelChange)="applySearch()"
/> />
<i class="fas fa-search search-icon"></i> <i class="fas fa-search search-icon"></i>
</div> </div>
<div class="d-flex align-items-center gap-2"> <div class="d-flex align-items-center gap-2">
<i (click)="exportDataInExcel()" id="downloadReport" class="fa fa-download"></i> <button
</div> class="btn btn-sm btn-outline-success"
(click)="exportDataInExcel()"
<i class="materialdesignicons" (click)="toggleTableCard()"> [disabled]="!filteredItems.length"
<ng-container *ngIf="logsDataExpanded; else down"> title="Export to Excel"
<i class="dripicons-chevron-up float-end"></i> >
</ng-container> <i class="fa fa-download"></i>
</button>
</div>
<ng-template #down> <button
<i class="dripicons-chevron-down float-end"></i> class="btn btn-sm btn-outline-secondary"
</ng-template> (click)="toggleTableCard()"
</i> [title]="(logsDataExpanded ? 'collapse' : 'expand') | translate"
>
<i *ngIf="logsDataExpanded" class="dripicons-chevron-up"></i>
<i *ngIf="!logsDataExpanded" class="dripicons-chevron-down"></i>
</button>
</div>
</div> </div>
</div> </div>
</div>
<div class="card-body" *ngIf="logsDataExpanded"> <div class="card-body" *ngIf="logsDataExpanded">
<!-- NO RECORDS --> <!-- NO RECORDS -->
<div *ngIf="!filteredItems.length" class="text-center text-muted"> <div *ngIf="!filteredItems.length" class="text-center text-muted py-4">
{{ "noLoggingDetailsFound" | translate }} <i class="fas fa-search fa-2x mb-2 opacity-50"></i>
<p>{{ "noLoggingDetailsFound" | translate }}</p>
</div> </div>
<!-- TABLE --> <!-- TABLE -->
@ -152,43 +155,59 @@
</tbody> </tbody>
</table> </table>
<!-- FOOTER --> <!-- PAGINATION FOOTER -->
<div <div class="d-flex justify-content-between align-items-center mt-3 flex-wrap">
class="d-flex justify-content-between align-items-center mt-3" <!-- Items per page -->
> <div class="d-flex align-items-center gap-2 mb-2 mb-md-0">
<ng-select <span class="text-muted small">{{ "show" | translate }}</span>
[items]="pageSizeOptions" <div style="width: 120px;">
bindLabel="label" <ng-select
bindValue="value" class="form-select-sm"
[(ngModel)]="itemsPerPage" [items]="pageSizeOptions"
(change)="itemsPerPageChanged()" bindValue="value"
[searchable]="false" [(ngModel)]="itemsPerPage"
[clearable]="false"> (change)="itemsPerPageChanged()"
</ng-select> [searchable]="false"
[clearable]="false"
[dropdownPosition]="'top'"
>
<ng-template ng-option-tmp let-item="item">
{{ item.value }} {{ "entries" | translate }}
</ng-template>
<div class="text-muted"> <ng-template ng-label-tmp let-item="item">
{{ item.value }} {{ "entries" | translate }}
</ng-template>
</ng-select>
</div>
</div>
<!-- Page info -->
<div class="text-muted mb-2 mb-md-0">
{{ "page" | translate }} {{ currentPage }} {{ "page" | translate }} {{ currentPage }}
{{ "of" | translate }} {{ totalPages() }} ({{ {{ "of" | translate }} {{ totalPages() }}
filteredItems.length <span class="d-none d-md-inline">
}} ({{ filteredItems.length }} {{ "totalItems" | translate }})
{{ "totalItems" | translate }}) </span>
</div> </div>
<!-- Pagination buttons -->
<div class="btn-group"> <div class="btn-group">
<button <button
class="btn btn-primary" class="btn btn-outline-primary btn-sm"
(click)="previousPage()" (click)="previousPage()"
[disabled]="currentPage === 1" [disabled]="currentPage === 1"
> >
<i class="fas fa-chevron-left me-1"></i>
{{ "previous" | translate }} {{ "previous" | translate }}
</button> </button>
<button <button
class="btn btn-primary" class="btn btn-outline-primary btn-sm"
(click)="nextPage()" (click)="nextPage()"
[disabled]="currentPage >= totalPages()" [disabled]="currentPage >= totalPages()"
> >
{{ "next" | translate }} {{ "next" | translate }}
<i class="fas fa-chevron-right ms-1"></i>
</button> </button>
</div> </div>
</div> </div>
@ -198,4 +217,4 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>

@ -24,11 +24,11 @@ export class AuthenticationService {
constructor(private buttonManagementService: ButtonManagementService, private httpService: HttpURIService, private router: Router, private credentialService: CredentialService, private i18nService: I18NService, private storageService: StorageService) { constructor(private buttonManagementService: ButtonManagementService, private httpService: HttpURIService, private router: Router, private credentialService: CredentialService, private i18nService: I18NService, private storageService: StorageService) {
} }
authenticate(uCreds: UserCredentials): Observable<any> { authenticate(uCreds: UserCredentials): Observable<any> {
const userJson = this.storageService.getItem('user'); // const userJson = this.storageService.getItem('user');
if (this.storageService.getItem('user') != null) { // if (this.storageService.getItem('user') != null) {
this.i18nService.error(ErrorMessages.ALREADY_LOGGED_IN, []); // this.i18nService.error(ErrorMessages.ALREADY_LOGGED_IN, []);
return new Observable(); // empty // return new Observable(); // empty
} // }
this.credentialService.setPorOrgacode(HiddenValues.POR_ORGACODE); this.credentialService.setPorOrgacode(HiddenValues.POR_ORGACODE);
this.credentialService.setUserId(uCreds.userId); this.credentialService.setUserId(uCreds.userId);

@ -3,9 +3,7 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<div <div class="d-sm-flex align-items-center justify-content-between navbar-header p-0"></div>
class="d-sm-flex align-items-center justify-content-between navbar-header p-0"
></div>
</div> </div>
</div> </div>
</div> </div>
@ -19,9 +17,7 @@
<div class="col-lg-12"> <div class="col-lg-12">
<div class="card-body mt-2 p-0"> <div class="card-body mt-2 p-0">
<div class="card mb-0 mt-2"> <div class="card mb-0 mt-2">
<div <div class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
class="card-header font-edit-13-child d-flex justify-content-between align-items-center"
>
{{ "transactionLogs" | translate }} {{ "transactionLogs" | translate }}
<div class="d-flex align-items-center gap-2"> <div class="d-flex align-items-center gap-2">
@ -32,169 +28,164 @@
[(ngModel)]="searchText" [(ngModel)]="searchText"
(ngModelChange)="onSearch($event)" (ngModelChange)="onSearch($event)"
placeholder="{{ 'search' | translate }}" placeholder="{{ 'search' | translate }}"
[disabled]="isLoading"
/> />
<i class="fas fa-search search-icon"></i> <i class="fas fa-search search-icon"></i>
</div> </div>
<div class="d-flex align-items-center gap-2"> <div class="d-flex align-items-center gap-2">
<i <button
class="btn btn-sm btn-outline-success"
(click)="exportDataInExcel()" (click)="exportDataInExcel()"
id="downloadReport" [disabled]="isLoading || transactionLog.length === 0"
class="fa fa-download" title="Export to Excel"
></i> >
<i class="fa fa-download"></i>
</button>
</div> </div>
<i <button
class="materialdesignicons" class="btn btn-sm btn-outline-secondary"
(click)="toggleTableCard()" (click)="toggleTableCard()"
[title]="(transactionDataExpanded ? 'collapse' : 'expand') | translate"
> >
<ng-container <i *ngIf="transactionDataExpanded" class="dripicons-chevron-up"></i>
*ngIf=" <i *ngIf="!transactionDataExpanded" class="dripicons-chevron-down"></i>
transactionDataExpanded; </button>
else collapsedIcon
"
>
<i class="dripicons-chevron-up float-end"></i>
</ng-container>
<ng-template #collapsedIcon>
<i class="dripicons-chevron-down float-end"></i>
</ng-template>
</i>
</div> </div>
</div> </div>
<div <div
class="card-body" class="card-body"
*ngIf=" *ngIf="transactionDataExpanded; else collapsedTable"
transactionDataExpanded && allItems.length;
else noRecordsFound
"
> >
<div *ngIf="isLoading" class="text-center text-muted"> <!-- Loading State -->
<p>{{ "loadingTransactionLogs" | translate }}</p> <div *ngIf="isLoading" class="text-center py-5">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p class="text-muted mt-2">{{ "loadingTransactionLogs" | translate }}</p>
</div> </div>
<div <!-- Error Message -->
*ngIf="!isLoading && transactionLog.length === 0" <div *ngIf="!isLoading && errorMessage" class="alert alert-danger alert-dismissible fade show" role="alert">
class="text-center text-muted" {{ errorMessage }}
> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close" (click)="errorMessage = ''"></button>
<p>{{ "noTransactionLogsFound" | translate }}</p>
</div> </div>
<div *ngIf="errorMessage" class="alert alert-danger"> <!-- No Data Found -->
{{ errorMessage }} <div *ngIf="!isLoading && !errorMessage && transactionLog.length === 0" class="text-center py-5 text-muted">
<i class="fas fa-database fa-3x mb-3 opacity-50"></i>
<h5>{{ "noTransactionLogsFound" | translate }}</h5>
</div> </div>
<div <!-- Data Table -->
*ngIf="!isLoading && transactionLog.length > 0" <div *ngIf="!isLoading && !errorMessage && transactionLog.length > 0" class="table-responsive">
class="table-responsive" <table class="table table-hover table-bordered mb-0">
>
<table class="table mb-0 border">
<thead class="table-light"> <thead class="table-light">
<tr> <tr>
<th>{{ "logID" | translate }}</th> <th scope="col">{{ "logID" | translate }}</th>
<th>{{ "organization" | translate }}</th> <th scope="col">{{ "organization" | translate }}</th>
<th>{{ "transactionID" | translate }}</th> <th scope="col">{{ "transactionID" | translate }}</th>
<th>{{ "drAccount" | translate }}</th> <th scope="col">{{ "drAccount" | translate }}</th>
<th>{{ "crAccount" | translate }}</th> <th scope="col">{{ "crAccount" | translate }}</th>
<th>{{ "drPcaGlacode" | translate }}</th> <th scope="col">{{ "drPcaGlacode" | translate }}</th>
<th>{{ "crPcaglacode" | translate }}</th> <th scope="col">{{ "crPcaglacode" | translate }}</th>
<th>{{ "transactionUri" | translate }}</th> <th scope="col">{{ "transactionUri" | translate }}</th>
<th>{{ "transactionCode" | translate }}</th> <th scope="col">{{ "transactionCode" | translate }}</th>
<th>{{ "paymentMode" | translate }}</th> <th scope="col">{{ "paymentMode" | translate }}</th>
<th>{{ "date" | translate }}</th> <th scope="col">{{ "date" | translate }}</th>
<th>{{ "channel" | translate }}</th> <th scope="col">{{ "channel" | translate }}</th>
<th>{{ "createdAt" | translate }}</th> <th scope="col">{{ "createdAt" | translate }}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr <tr *ngFor="let log of filteredItems | tableFilter: searchText: [
*ngFor=" 'logId',
let log of ( 'porOrgacode',
allItems 'transactionID',
| tableFilter 'drMbmbkmsnumber',
: searchText 'crMbmbkmsnumber',
: [ 'drPcaGlacode',
'logID', 'crPcaglacode',
'organization', 'transactionUri',
'transactionID', 'transactionCode',
'drAccount', 'ppmPymdcode',
'drPcaGlacode', 'sgtGntrdate',
'crPcaglacode', 'channelCode',
'crAccount', 'createdAt'
'transactionUri', ]">
'transactionCode', <td><code>{{ log.logId || '-' }}</code></td>
'paymentMode', <td>{{ log.porOrgacode || '-' }}</td>
'date', <td><strong>{{ log.transactionID || '-' }}</strong></td>
'channel', <td>{{ log.drMbmbkmsnumber || '-' }}</td>
'createdAt', <td>{{ log.crMbmbkmsnumber || '-' }}</td>
] <td>{{ log.drPcaGlacode || '-' }}</td>
).slice( <td>{{ log.crPcaglacode || '-' }}</td>
(currentPage - 1) * itemsPerPage, <td><small class="text-muted">{{ log.transactionUri || 'N/A' }}</small></td>
currentPage * itemsPerPage <td><span class="badge bg-secondary">{{ log.transactionCode || 'N/A' }}</span></td>
) <td>{{ log.ppmPymdcode || '-' }}</td>
" <td>{{ log.sgtGntrdate | date: 'MMM dd, yyyy' }}</td>
> <td>{{ log.channelCode || '-' }}</td>
<td>{{ log.logId }}</td> <td>{{ log.createdAt | date: 'MMM dd, yyyy HH:mm' }}</td>
<td>{{ log.porOrgacode }}</td>
<td>{{ log.transactionID }}</td>
<td>{{ log.drMbmbkmsnumber || "-" }}</td>
<td>{{ log.crMbmbkmsnumber || "-" }}</td>
<td>{{ log.drPcaGlacode || "-" }}</td>
<td>{{ log.crPcaglacode || "-" }}</td>
<td>{{ log.transactionUri || "N/A"}}</td>
<td>{{ log.transactionCode || "N/A"}}</td>
<td>{{ log.ppmPymdcode }}</td>
<td>
{{ log.sgtGntrdate | date: "MMM dd, yyyy" }}
</td>
<td>{{ log.channelCode }}</td>
<td>
{{
log.createdAt | date: "MMM dd, yyyy HH:mm"
}}
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div <!-- Pagination -->
class="d-flex justify-content-between align-items-center mt-3" <div class="d-flex justify-content-between align-items-center mt-3 flex-wrap">
> <!-- Items per page -->
<div class="form-group mb-0"> <div class="d-flex align-items-center gap-2 mb-2 mb-md-0">
<ng-select <span class="text-muted small">{{ "show" | translate }}</span>
class="form-select-sm" <div style="width: 120px;">
[items]="pageSizeOptions" <ng-select
bindLabel="label" class="form-select-sm"
bindValue="value" [items]="pageSizeOptions"
[(ngModel)]="itemsPerPage" bindValue="value"
(change)="itemsPerPageChanged()" [(ngModel)]="itemsPerPage"
[searchable]="false" (change)="itemsPerPageChanged()"
[clearable]="false" [searchable]="false"
[dropdownPosition]="'top'" [clearable]="false"
> [dropdownPosition]="'top'"
</ng-select> [disabled]="isLoading"
>
<ng-template ng-option-tmp let-item="item">
{{ item.value }} {{ "entries" | translate }}
</ng-template>
<ng-template ng-label-tmp let-item="item">
{{ item.value }} {{ "entries" | translate }}
</ng-template>
</ng-select>
</div>
</div> </div>
<div class="text-muted"> <!-- Page info -->
<div class="text-muted mb-2 mb-md-0">
{{ "page" | translate }} {{ currentPage }} {{ "page" | translate }} {{ currentPage }}
{{ "of" | translate }} {{ totalPages() }} ({{ {{ "of" | translate }} {{ totalPages() }}
totalCount <span class="d-none d-md-inline">
}} ({{ totalCount }} {{ "totalItems" | translate }})
{{ "totalItems" | translate }}) </span>
</div> </div>
<!-- Pagination buttons -->
<div class="btn-group"> <div class="btn-group">
<button <button
class="btn btn-primary waves-effect waves-light" class="btn btn-outline-primary btn-sm"
(click)="previousPage()" (click)="previousPage()"
[disabled]="currentPage === 1 || isLoading"
> >
<i class="fas fa-chevron-left me-1"></i>
{{ "previous" | translate }} {{ "previous" | translate }}
</button> </button>
<button <button
class="btn btn-primary waves-effect waves-light" class="btn btn-outline-primary btn-sm"
(click)="nextPage()" (click)="nextPage()"
[disabled]="currentPage === totalPages() || isLoading"
> >
{{ "next" | translate }} {{ "next" | translate }}
<i class="fas fa-chevron-right ms-1"></i>
</button> </button>
</div> </div>
</div> </div>
@ -211,11 +202,13 @@
</div> </div>
</div> </div>
</div> </div>
<ng-template #noRecordsFound>
<div <ng-template #collapsedTable>
*ngIf="!isLoading && allItems.length === 0" <div class="card-body text-center py-4 text-muted" *ngIf="!isLoading">
class="text-center text-muted mt-3" <i class="dripicons-chevron-down fa-2x mb-2"></i>
> <p>{{ "tableCollapsed" | translate }}</p>
<p>{{ "noTransactionLogsFound" | translate }}</p> <button class="btn btn-sm btn-outline-primary" (click)="toggleTableCard()">
{{ "showTable" | translate }}
</button>
</div> </div>
</ng-template> </ng-template>

@ -0,0 +1,125 @@
:host {
display: block;
}
.card-header {
background-color: #f8f9fa;
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
}
.search-box {
position: relative;
min-width: 200px;
.form-control {
padding-left: 2.5rem;
padding-right: 1rem;
}
.search-icon {
position: absolute;
left: 1rem;
top: 50%;
transform: translateY(-50%);
color: #6c757d;
pointer-events: none;
}
}
.table {
th {
font-weight: 600;
background-color: #f8f9fa;
border-bottom: 2px solid #dee2e6;
white-space: nowrap;
}
td {
vertical-align: middle;
}
}
.btn-group-sm > .btn {
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
}
.badge {
font-size: 0.75em;
}
.alert-info {
background-color: #e7f3ff;
border-color: #b3d7ff;
color: #004085;
.btn-close {
padding: 0.5rem;
}
}
.spinner-border {
width: 3rem;
height: 3rem;
}
// Responsive adjustments
@media (max-width: 768px) {
.card-header .d-flex {
flex-direction: column;
align-items: stretch !important;
gap: 0.75rem !important;
}
.search-box {
min-width: 100%;
}
.table-responsive {
font-size: 0.875rem;
}
.d-flex.justify-content-between {
flex-direction: column;
gap: 1rem;
> div {
width: 100%;
justify-content: center !important;
}
}
.btn-group {
width: 100%;
.btn {
flex: 1;
}
}
}
// Loading overlay
.text-center.py-5 {
min-height: 200px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
// Hover effects
.table-hover tbody tr:hover {
background-color: rgba(0, 123, 255, 0.05);
}
// Date filter styles
.form-control-sm {
min-width: 120px;
}
// Active state for filter buttons
.btn-outline-primary.active {
background-color: #0d6efd;
color: white;
border-color: #0d6efd;
}

@ -7,20 +7,19 @@ import { pageSizeOptions } from '../utils/app.constants';
import { NgSelectModule } from '@ng-select/ng-select'; import { NgSelectModule } from '@ng-select/ng-select';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { TableFilterPipe } from '../shared/pipes/table-filter.pipe'; import { TableFilterPipe } from '../shared/pipes/table-filter.pipe';
import {TransactionLog} from "../models/user" import { TransactionLog } from "../models/user";
import { URIKey } from '../utils/uri-enums'; import { URIKey } from '../utils/uri-enums';
import { HttpParams } from '@angular/common/http'; import { HttpParams } from '@angular/common/http';
import { HttpURIService } from '../app.http.uri.service'; import { HttpURIService } from '../app.http.uri.service';
import { formatDate } from '@angular/common';
@Component({ @Component({
selector: 'app-transaction-logs', selector: 'app-transaction-logs',
templateUrl: './transaction-logs.component.html', templateUrl: './transaction-logs.component.html',
imports: [CommonModule, TranslateModule, NgSelectModule, FormsModule, ReactiveFormsModule, TableFilterPipe ] styleUrls: ['./transaction-logs.component.scss'],
imports: [CommonModule, TranslateModule, NgSelectModule, FormsModule, ReactiveFormsModule, TableFilterPipe]
}) })
export class TransactionLogsComponent implements OnInit { export class TransactionLogsComponent implements OnInit {
onPageSizeChange(arg0: number) {
throw new Error('Method not implemented.');
}
currentPage: number = 1; currentPage: number = 1;
totalCount: number = 0; totalCount: number = 0;
renewalDataExpanded: boolean = true; renewalDataExpanded: boolean = true;
@ -32,75 +31,215 @@ throw new Error('Method not implemented.');
errorMessage: string = ''; errorMessage: string = '';
searchText: string = ''; searchText: string = '';
allItems: TransactionLog[] = []; allItems: TransactionLog[] = [];
transactionDataExpanded: boolean = true transactionDataExpanded: boolean = true;
// Date range properties
fromDate: string = '';
toDate: string = '';
maxDate: string = '';
showDateFilters: boolean = false;
constructor( constructor(
private excelExportService: ExcelExportService, private excelExportService: ExcelExportService,
private httpService: HttpURIService, private httpService: HttpURIService,
) {} ) {}
ngOnInit(): void { ngOnInit(): void {
// Set max date to today
this.maxDate = formatDate(new Date(), 'yyyy-MM-dd', 'en-US');
// Optionally set default date range (last 30 days)
const today = new Date();
const lastMonth = new Date();
lastMonth.setDate(today.getDate() - 30);
this.fromDate = formatDate(lastMonth, 'yyyy-MM-dd', 'en-US');
this.toDate = formatDate(today, 'yyyy-MM-dd', 'en-US');
this.loadTransactionLogs(); this.loadTransactionLogs();
} }
loadTransactionLogs(): void {
this.isLoading = true; loadTransactionLogs(): void {
const params = new HttpParams(); this.isLoading = true;
this.httpService this.errorMessage = '';
.requestGET<any>(URIKey.TRANSACTION_LOGS, params)
.subscribe({ // Build query parameters
next: (res) => { let params = new HttpParams();
const logs = Array.isArray(res) ? res : res?.data;
this.transactionLog = logs ?? []; // Add pagination parameters
this.allItems = [...this.transactionLog]; params = params.set('page', this.currentPage.toString());
this.totalCount = this.transactionLog.length; params = params.set('limit', this.itemsPerPage.toString());
this.updatePagedItems(); // Add date filters if provided
this.isLoading = false; if (this.fromDate) {
}, params = params.set('fromDate', this.fromDate);
error: (err) => { }
console.error('Error fetching logging details data:', err);
this.transactionLog = []; if (this.toDate) {
this.isLoading = false; params = params.set('toDate', this.toDate);
}
// Add search filter if provided
if (this.searchText && this.searchText.trim() !== '') {
params = params.set('search', this.searchText.trim());
}
this.httpService
.requestGET<any>(URIKey.TRANSACTION_LOGS, params)
.subscribe({
next: (res) => {
const logs = Array.isArray(res) ? res : res?.data;
this.transactionLog = logs ?? [];
this.allItems = [...this.transactionLog];
// Get total count from response
if (res?.total !== undefined) {
this.totalCount = res.total;
} else if (res?.pagination?.total !== undefined) {
this.totalCount = res.pagination.total;
} else if (res?.meta?.total !== undefined) {
this.totalCount = res.meta.total;
} else {
this.totalCount = this.transactionLog.length;
}
this.updatePagedItems();
this.isLoading = false;
},
error: (err) => {
console.error('Error fetching transaction logs:', err);
this.errorMessage = err.message || 'Failed to load transaction logs. Please try again.';
this.transactionLog = [];
this.allItems = [];
this.totalCount = 0;
this.pagedItems = [];
this.isLoading = false;
},
complete: () => {
this.isLoading = false;
}
});
}
// Date filter change handler
onDateFilterChange(): void {
// Validate date range
if (this.fromDate && this.toDate) {
const from = new Date(this.fromDate);
const to = new Date(this.toDate);
if (from > to) {
this.errorMessage = 'From date cannot be after To date';
return;
} }
}); }
}
// Reset to first page and reload
this.currentPage = 1;
this.loadTransactionLogs();
}
// Clear date filters
clearDateFilters(): void {
this.fromDate = '';
this.toDate = '';
this.currentPage = 1;
this.loadTransactionLogs();
}
// Toggle date filter visibility
toggleDateFilters(): void {
this.showDateFilters = !this.showDateFilters;
}
// Apply default date range (Last 7 days)
applyLast7Days(): void {
const today = new Date();
const lastWeek = new Date();
lastWeek.setDate(today.getDate() - 7);
this.fromDate = formatDate(lastWeek, 'yyyy-MM-dd', 'en-US');
this.toDate = formatDate(today, 'yyyy-MM-dd', 'en-US');
this.onDateFilterChange();
}
// Apply default date range (Last 30 days)
applyLast30Days(): void {
const today = new Date();
const lastMonth = new Date();
lastMonth.setDate(today.getDate() - 30);
this.fromDate = formatDate(lastMonth, 'yyyy-MM-dd', 'en-US');
this.toDate = formatDate(today, 'yyyy-MM-dd', 'en-US');
this.onDateFilterChange();
}
// Apply default date range (This month)
applyThisMonth(): void {
const today = new Date();
const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
this.fromDate = formatDate(firstDay, 'yyyy-MM-dd', 'en-US');
this.toDate = formatDate(today, 'yyyy-MM-dd', 'en-US');
this.onDateFilterChange();
}
toggleTableCard(): void { toggleTableCard(): void {
this.transactionDataExpanded = !this.transactionDataExpanded; this.transactionDataExpanded = !this.transactionDataExpanded;
} }
itemsPerPageChanged(): void { itemsPerPageChanged(): void {
this.currentPage = 1; this.currentPage = 1;
this.updatePagedItems(); this.loadTransactionLogs();
} }
onSearch(value: string): void { onSearch(value: string): void {
this.searchText = value; this.searchText = value;
} this.currentPage = 1;
// Debounce search to avoid too many API calls
clearTimeout((this as any).searchTimeout);
(this as any).searchTimeout = setTimeout(() => {
this.loadTransactionLogs();
}, 300);
}
totalPages(): number { totalPages(): number {
return Math.ceil(this.allItems.length / this.itemsPerPage); return Math.ceil(this.totalCount / this.itemsPerPage);
} }
previousPage(): void { previousPage(): void {
if (this.currentPage > 1) { if (this.currentPage > 1) {
this.currentPage--; this.currentPage--;
this.updatePagedItems(); this.loadTransactionLogs();
} }
} }
updatePagedItems(): void { updatePagedItems(): void {
// For client-side display with table filter pipe
const startIndex = (this.currentPage - 1) * this.itemsPerPage; const startIndex = (this.currentPage - 1) * this.itemsPerPage;
const endIndex = startIndex + this.itemsPerPage; const endIndex = startIndex + this.itemsPerPage;
// If using server-side pagination, use transactionLog directly
// If using client-side filtering with tableFilter pipe, this might not be needed
this.pagedItems = this.allItems.slice(startIndex, endIndex); this.pagedItems = this.allItems.slice(startIndex, endIndex);
} }
nextPage(): void { nextPage(): void {
if (this.currentPage < this.totalPages()) { if (this.currentPage < this.totalPages()) {
this.currentPage++; this.currentPage++;
this.updatePagedItems(); this.loadTransactionLogs();
} }
} }
exportDataInExcel() { exportDataInExcel(): void {
this.excelExportService.exportExcel(this.transactionLog, TRANSACTION_LOGS_FILE_NAME) // Export filtered data
const dataToExport = this.allItems.length > 0 ? this.allItems : this.transactionLog;
this.excelExportService.exportExcel(dataToExport, TRANSACTION_LOGS_FILE_NAME);
}
// Get filtered items for display (used in template)
get filteredItems(): TransactionLog[] {
return this.allItems;
} }
} }

@ -95,7 +95,7 @@
for="userFullname" for="userFullname"
class="text-nowrap mt-2" class="text-nowrap mt-2"
> >
{{ "name" | translate {{ "userFullname" | translate
}}<span class="mandatory">*</span> }}<span class="mandatory">*</span>
</label> </label>
<div <div
@ -107,9 +107,7 @@
formControlName="userFullname" formControlName="userFullname"
name="userFullname" name="userFullname"
maxlength="500" maxlength="500"
placeholder="{{ placeholder="{{ 'userFullname' | translate }}"
'Full Name' | translate
}}"
/> />
<div <div
@ -394,10 +392,10 @@
{{ "userID" | translate }} {{ "userID" | translate }}
</th> </th>
<th style="width: 25%"> <th style="width: 25%">
{{ "Name" | translate }} {{ "userFullname" | translate }}
</th> </th>
<th style="width: 25%"> <th style="width: 25%">
{{ "Email" | translate }} {{ "email" | translate }}
</th> </th>
<th style="width: 15%"> <th style="width: 15%">
{{ "Role" | translate }} {{ "Role" | translate }}
@ -481,6 +479,13 @@
[clearable]="false" [clearable]="false"
[dropdownPosition]="'top'" [dropdownPosition]="'top'"
> >
<ng-template ng-option-tmp let-item="item">
{{ item.value }} {{ "entries" | translate }}
</ng-template>
<ng-template ng-label-tmp let-item="item">
{{ item.value }} {{ "entries" | translate }}
</ng-template>
</ng-select> </ng-select>
</div> </div>

@ -5,9 +5,9 @@ export const CONSTANTS = {
}; };
export const pageSizeOptions = [ export const pageSizeOptions = [
{ value: 10, label: '10 items' }, { value: 10, label: '10' },
{ value: 20, label: '20 items' }, { value: 20, label: '20' },
{ value: 50, label: '50 items' }, { value: 50, label: '50' },
]; ];
export const toDateAfterFromDateValidator: ValidatorFn = ( export const toDateAfterFromDateValidator: ValidatorFn = (

@ -1,294 +1,299 @@
{ {
"logintoAccount":"تسجيل الدخول إلى حسابك", "logintoAccount": "تسجيل الدخول إلى حسابك",
"userName":"اسم المستخدم", "userName": "اسم المستخدم",
"userNamePlaceHolder":"ادخل اسم المستخدم", "userNamePlaceHolder": "ادخل اسم المستخدم",
"password":"كلمة المرور", "password": "كلمة المرور",
"passwordPlaceHolder":"أدخل كلمة المرور", "passwordPlaceHolder": "أدخل كلمة المرور",
"defaultPassword": "كلمة المرور الافتراضية", "defaultPassword": "كلمة المرور الافتراضية",
"rememberMe":"تذكرنى", "rememberMe": "تذكرنى",
"forgotPassword":"هل نسيت كلمة السر؟", "forgotPassword": "هل نسيت كلمة السر؟",
"passwordTooShort": "كلمة المرور قصيرة جدًا.", "passwordTooShort": "كلمة المرور قصيرة جدًا.",
"passwordsDoNotMatch": "كلمتا المرور غير متطابقتين.", "passwordsDoNotMatch": "كلمتا المرور غير متطابقتين.",
"login":"تسجيل الدخول", "login": "تسجيل الدخول",
"dashboardTitle":"لوحة القيادة", "dashboardTitle": "لوحة القيادة",
"passwordChangeRequired": "تغيير كلمة المرور مطلوب", "passwordChangeRequired": "تغيير كلمة المرور مطلوب",
"monthlyReqTitle":"الطلبات الشهرية", "monthlyReqTitle": "الطلبات الشهرية",
"monthlySmsTitle":"الرسائل القصيرة الشهرية", "monthlySmsTitle": "الرسائل القصيرة الشهرية",
"Dashboard":"لوحة القيادة", "Dashboard": "لوحة القيادة",
"UserManagement":"إدارةالمستخدم", "UserManagement": "إدارةالمستخدم",
"thirdPartyRegistration":"تسجيل الطرف الثالث", "thirdPartyRegistration": "تسجيل الطرف الثالث",
"setupUser":"مستخدم الإعداد", "setupUser": "مستخدم الإعداد",
"resetPassword":"إعادة تعيين كلمة مرور المستخدم", "resetPassword": "إعادة تعيين كلمة مرور المستخدم",
"changePassword":"غير كلمة السر", "changePassword": "غير كلمة السر",
"Logging":"تسجيل", "Logging": "تسجيل",
"loggerManager":"مدير المسجل", "loggerManager": "مدير المسجل",
"SMSBanking":"خدمة الرسائل المصرفية", "SMSBanking": "خدمة الرسائل المصرفية",
"smsLogger":"مسجل الرسائل", "smsLogger": "مسجل الرسائل",
"smsLoggerDetails": "تفاصيل سجل الرسائل القصيرة", "smsLoggerDetails": "تفاصيل سجل الرسائل القصيرة",
"smsGateway":"بوابة الرسائل", "smsGateway": "بوابة الرسائل",
"ibUnblockUser":"إلغاء حظر مستخدم IB", "ibUnblockUser": "إلغاء حظر مستخدم IB",
"ibSupport":"دعم IB", "ibSupport": "دعم IB",
"Permissions":"أذونات", "Permissions": "أذونات",
"permissions":"مدير الأذونات", "permissions": "مدير الأذونات",
"TodayTotalRequests":"إجمالي الطلبات اليوم", "TodayTotalRequests": "إجمالي الطلبات اليوم",
"TodayTotalSms":"مجموع الرسائل القصيرة اليوم", "TodayTotalSms": "مجموع الرسائل القصيرة اليوم",
"DescriptionUserPermission":"وصف", "DescriptionUserPermission": "وصف",
"PermissionsUserPermission":"أذونات", "PermissionsUserPermission": "أذونات",
"SaveUserPermission":"يحفظ", "SaveUserPermission": "يحفظ",
"UpdateUserPermission":"تحديث", "UpdateUserPermission": "تحديث",
"DeleteUserPermission":"حذف", "DeleteUserPermission": "حذف",
"ViewUserPermission":"رأي", "ViewUserPermission": "رأي",
"SelectUser":"اختر المستخدم", "SelectUser": "اختر المستخدم",
"SelectAUser":"حدد مستخدمًا", "SelectAUser": "حدد مستخدمًا",
"loggingTitle":"تسجيل", "loggingTitle": "تسجيل",
"IBChildTitle":"إلغاء حظر عن مستخدم", "IBChildTitle": "إلغاء حظر عن مستخدم",
"IBTitle":"تسجيل", "IBTitle": "تسجيل",
"loggingChildTitle":"مدير المسجل", "loggingChildTitle": "مدير المسجل",
"fromDate":"من التاريخ", "fromDate": "من التاريخ",
"custId": "قيمة هوية العميل", "custId": "قيمة هوية العميل",
"toDate":"حتي اليوم", "toDate": "حتي اليوم",
"findLogs":"البحث عن السجلات", "findLogs": "البحث عن السجلات",
"unBlockCustomer":"إلغاء حظر العميل", "unBlockCustomer": "إلغاء حظر العميل",
"unblockUserDetails": "إلغاء حظر تفاصيل المستخدم", "unblockUserDetails": "إلغاء حظر تفاصيل المستخدم",
"loggerManagerDetails": "تفاصيل مدير السجلات", "loggerManagerDetails": "تفاصيل مدير السجلات",
"fetchCustomer": "ابحث عن العملاء", "fetchCustomer": "ابحث عن العملاء",
"loggingID":"معرف", "loggingID": "معرف",
"firstName":"الاسم الأول", "firstName": "الاسم الأول",
"lastName": "اسم العائلة", "lastName": "اسم العائلة",
"cmpCuststatus":"حالة العميل", "cmpCuststatus": "حالة العميل",
"cmpCustlastlogin": "آخر تسجيل دخول للعميل", "cmpCustlastlogin": "آخر تسجيل دخول للعميل",
"accountNonLocked":"الحساب مغلق", "accountNonLocked": "الحساب مغلق",
"lockTime":"وقت القفل", "lockTime": "وقت القفل",
"accountno":"رقم الحساب", "accountno": "رقم الحساب",
"phoneno":"رقم الهاتف", "phoneno": "رقم الهاتف",
"loggingRequestUri":"طلب Uri", "loggingRequestUri": "طلب Uri",
"loggingResponseCode":"رمز الاستجابة", "loggingResponseCode": "رمز الاستجابة",
"loggingRemoteIP":"بعيد IP", "loggingRemoteIP": "بعيد IP",
"enterIdentityValue": "أدخل قيمة الهوية", "enterIdentityValue": "أدخل قيمة الهوية",
"loggingTimeTaken":"الوقت المستغرق", "loggingTimeTaken": "الوقت المستغرق",
"loggingDate":"تاريخ", "loggingDate": "تاريخ",
"loggingDateTime": "التاريخ والوقت", "loggingDateTime": "التاريخ والوقت",
"loggingMethod":"طريقة", "loggingMethod": "طريقة",
"DataAnalysis":"تحليل البيانات", "DataAnalysis": "تحليل البيانات",
"Analysis":"التحليلات", "Analysis": "التحليلات",
"smsBankingTitle":"خدمة الرسائل المصرفية", "smsBankingTitle": "خدمة الرسائل المصرفية",
"smsBankingChildTitle":"مسجل الرسائل", "smsBankingChildTitle": "مسجل الرسائل",
"smsTrackingID":"معرف تتبع", "smsTrackingID": "معرف تتبع",
"smsMessage":"رسالة", "smsMessage": "رسالة",
"smsNo":"رقم الهاتف", "smsNo": "رقم الهاتف",
"smsOrgaCode":"كود المنظمة", "smsOrgaCode": "كود المنظمة",
"smsDate":"تاريخ", "smsDate": "تاريخ",
"smsStatus":"حالة", "smsStatus": "حالة",
"viewThirdPartyAccounts":"عرض الحسابات", "viewThirdPartyAccounts": "عرض الحسابات",
"ThirdPartyID":"معرف الحفلة الثالثة", "ThirdPartyID": "معرف الحفلة الثالثة",
"name":"اسم", "name": "اسم",
"EnterThirdPartyName":"أدخل اسم الطرف الثالث", "EnterThirdPartyName": "أدخل اسم الطرف الثالث",
"Email":"البريد الإلكتروني", "email": "البريد الإلكتروني",
"invalidEmail": "أدخل بريدًا إلكترونيًا صالحًا يحتوي على @", "invalidEmail": "أدخل بريدًا إلكترونيًا صالحًا يحتوي على @",
"Address":"تبوك", "Address": "تبوك",
"phoneNumber":"رقم الهاتف", "phoneNumber": "رقم الهاتف",
"PhoneNumberPlaceHolder":"أدخل رقم الهاتف", "PhoneNumberPlaceHolder": "أدخل رقم الهاتف",
"regPhoneNo": "يجب أن يتكون رقم الهاتف من 10 أرقام", "regPhoneNo": "يجب أن يتكون رقم الهاتف من 10 أرقام",
"NewNoOfAccounts":"عدد جديد من الحسابات", "NewNoOfAccounts": "عدد جديد من الحسابات",
"EnterNewNumberOfAccounts":"أدخل عددًا جديدًا من الحسابات", "EnterNewNumberOfAccounts": "أدخل عددًا جديدًا من الحسابات",
"TotalNoOfAccounts":"العدد الإجمالي للحسابات", "TotalNoOfAccounts": "العدد الإجمالي للحسابات",
"gridSearch":"يبحث:", "gridSearch": "يبحث:",
"gridShow":"يعرض", "gridShow": "يعرض",
"gridEntries":"إدخالات", "gridEntries": "إدخالات",
"gridFilter":"منقي", "gridFilter": "منقي",
"gridNum10":"عشرة", "gridNum10": "عشرة",
"gridNum25":"خمسة وعشرون", "gridNum25": "خمسة وعشرون",
"gridNum50":"خمسون", "gridNum50": "خمسون",
"gridNum100":"مائة", "gridNum100": "مائة",
"userID":"معرف المستخدم", "userID": "معرف المستخدم",
"userId":"معرف المستخدم", "userId": "معرف المستخدم",
"userContactNumber":"أدخل رقم اتصال المستخدم", "userContactNumber": "أدخل رقم اتصال المستخدم",
"SelectHomeBranch":"حدد الفرع الرئيسي", "SelectHomeBranch": "حدد الفرع الرئيسي",
"SelectRole":"حدد الدور", "SelectRole": "حدد الدور",
"HomeBranch":"فرع المنزل", "HomeBranch": "فرع المنزل",
"Role":"دور", "Role": "دور",
"ResetPassword":"إعادة تعيين كلمة المرور", "ResetPassword": "إعادة تعيين كلمة المرور",
"enterNewPassword":"أدخل كلمة مرور جديدة", "enterNewPassword": "أدخل كلمة مرور جديدة",
"oldPassword":"كلمة المرور القديمة", "oldPassword": "كلمة المرور القديمة",
"newPasswordStatic":"كلمة السر الجديدة", "newPasswordStatic": "كلمة السر الجديدة",
"savePassword":"يحفظ", "savePassword": "يحفظ",
"passwordPattern":"يجب أن تكون كلمة المرور أكثر من 8 أحرف وتتضمن حرفًا كبيرًا وحرفًا صغيرًا ورقمًا وحرفًا خاصًا", "passwordPattern": "يجب أن تكون كلمة المرور أكثر من 8 أحرف وتتضمن حرفًا كبيرًا وحرفًا صغيرًا ورقمًا وحرفًا خاصًا",
"SMSGatewaySelect":"اختر صنف", "SMSGatewaySelect": "اختر صنف",
"selectIdentValueType": "حدد نوع قيمة الهوية", "selectIdentValueType": "حدد نوع قيمة الهوية",
"selectIdentityValue" : "رقم الهوية مطلوب", "selectIdentityValue": "رقم الهوية مطلوب",
"IdTypeSelect":"حدد تحديد النوع", "IdTypeSelect": "حدد تحديد النوع",
"SMSGatewaySyriatel":"سيريتل", "SMSGatewaySyriatel": "سيريتل",
"SMSGatewayTwillio":"تويليو", "SMSGatewayTwillio": "تويليو",
"SMSGatewayJazz":"جاز", "SMSGatewayJazz": "جاز",
"syriatelCredentials":"أوراق اعتماد سيريتل", "syriatelCredentials": "أوراق اعتماد سيريتل",
"twilioCredentials":"أوراق اعتماد تويليو", "twilioCredentials": "أوراق اعتماد تويليو",
"jazzCredentials":"أوراق اعتماد جاز", "jazzCredentials": "أوراق اعتماد جاز",
"accountSID":"الحساب SID", "accountSID": "الحساب SID",
"authToken":"رمز المصادقة", "authToken": "رمز المصادقة",
"fromNumber":"من الرقم", "fromNumber": "من الرقم",
"senderName":"اسم المرسل", "senderName": "اسم المرسل",
"senderNamePlaceHolder":"أدخل اسم المرسل", "senderNamePlaceHolder": "أدخل اسم المرسل",
"message": "رسالة", "message": "رسالة",
"template": "قالب", "template": "قالب",
"language":"اللغة", "language": "اللغة",
"notificationType": "نوع الإشعار", "notificationType": "نوع الإشعار",
"sinceLastDay":"منذ اليوم الماضي", "sinceLastDay": "منذ اليوم الماضي",
"TodayTotalErrorRequest":"طلب إجمالي الخطأ اليوم", "TodayTotalErrorRequest": "طلب إجمالي الخطأ اليوم",
"TodayTotalPendingSms":"مجموع الرسائل القصيرة المعلقة اليوم", "TodayTotalPendingSms": "مجموع الرسائل القصيرة المعلقة اليوم",
"selectTheDates":"الرجاء تحديد التواريخ", "selectTheDates": "الرجاء تحديد التواريخ",
"selectIdentValue":"الرجاء تحديد نوع الهوية", "selectIdentValue": "الرجاء تحديد نوع الهوية",
"noLogsFound":"لم يتم العثور على سجلات بين هذه التواريخ", "noLogsFound": "لم يتم العثور على سجلات بين هذه التواريخ",
"loginSuccess":"تم تسجيل الدخول بنجاح", "loginSuccess": "تم تسجيل الدخول بنجاح",
"passwordNotMatched":"كلمة السر غير متطابقة", "passwordNotMatched": "كلمة السر غير متطابقة",
"passwordPatternNotMatched":"نمط كلمة المرور غير مطابق", "passwordPatternNotMatched": "نمط كلمة المرور غير مطابق",
"successDeleted":"تم الحذف بنجاح", "successDeleted": "تم الحذف بنجاح",
"passwordNotSame":"لا يمكن أن تكون كلمة المرور هي نفسها كلمة المرور القديمة", "passwordNotSame": "لا يمكن أن تكون كلمة المرور هي نفسها كلمة المرور القديمة",
"SuccessSave":"تم الحفظ بنجاح", "SuccessSave": "تم الحفظ بنجاح",
"SuccessFind":"تجده بنجاح", "SuccessFind": "تجده بنجاح",
"customerAlreadyUnblocked": "العميل تم فتح حسابه مسبقًا", "customerAlreadyUnblocked": "العميل تم فتح حسابه مسبقًا",
"SuccessUpdate":"تم التحديث بنجاح", "SuccessUpdate": "تم التحديث بنجاح",
"UpdateFailed":"غير قادر على التحديث", "UpdateFailed": "غير قادر على التحديث",
"formInvalid":"النموذج غير صالح", "formInvalid": "النموذج غير صالح",
"ServerError":"خطأ في الخادم", "ServerError": "خطأ في الخادم",
"fieldsMissing":"الحقول المطلوبة مفقودة أو غير صالحة", "fieldsMissing": "الحقول المطلوبة مفقودة أو غير صالحة",
"selectAll":" اختر الكل " , "selectAll": " اختر الكل ",
"logoutSuccess":"تم تسجيل الخروج بنجاح", "logoutSuccess": "تم تسجيل الخروج بنجاح",
"smsGateWayChanged":"تم تغيير بوابة الرسائل القصيرة بنجاح", "smsGateWayChanged": "تم تغيير بوابة الرسائل القصيرة بنجاح",
"cnic_scnic": "CNIC / SCNIC", "cnic_scnic": "CNIC / SCNIC",
"poc": "POC", "poc": "POC",
"nicop": "S / NICOP", "nicop": "S / NICOP",
"passport": "جواز السفر", "passport": "جواز السفر",
"Next": "التالي", "Next": "التالي",
"ERR_APP_B_0001": "خطأ خادم داخلي", "ERR_APP_B_0001": "خطأ خادم داخلي",
"ERR_APP_B_0002": "خطأ اتصال محتمل مع الوحدة النمطية {{value1}}", "ERR_APP_B_0002": "خطأ اتصال محتمل مع الوحدة النمطية {{value1}}",
"ERR_APP_B_0003": "طلب غير صالح على وحدة {{value1}}", "ERR_APP_B_0003": "طلب غير صالح على وحدة {{value1}}",
"ERR_APP_B_0004": "انتهت الجلسة", "ERR_APP_B_0004": "انتهت الجلسة",
"ERR_APP_B_0005": "غير مصرح به: {{قيمة 1}}.", "ERR_APP_B_0005": "غير مصرح به: {{قيمة 1}}.",
"ERR_MDL_B_0001": "رمز الغرض موجود بالفعل", "ERR_MDL_B_0001": "رمز الغرض موجود بالفعل",
"feedbackSetup": "ردود الفعل الإعداد", "feedbackSetup": "ردود الفعل الإعداد",
"credentials": "أوراق اعتماد", "credentials": "أوراق اعتماد",
"credentialsTitle": "أوراق اعتماد ردود الفعل", "credentialsTitle": "أوراق اعتماد ردود الفعل",
"confirmPassword": "تأكيد كلمة المرور", "confirmPassword": "تأكيد كلمة المرور",
"passwordPlaceholder": "أدخل كلمة المرور", "passwordPlaceholder": "أدخل كلمة المرور",
"confirmPasswordPlaceholder": "أدخل تأكيد كلمة المرور", "confirmPasswordPlaceholder": "أدخل تأكيد كلمة المرور",
"newPasswordPlaceholder": "أدخل كلمة مرور جديدة", "newPasswordPlaceholder": "أدخل كلمة مرور جديدة",
"fieldRequired": "الخانة مطلوبة", "fieldRequired": "الخانة مطلوبة",
"emailLabel": "البريد الإلكتروني", "emailLabel": "البريد الإلكتروني",
"emailRequiredError": "البريد الإلكتروني مطلوب.", "emailRequiredError": "البريد الإلكتروني مطلوب.",
"invalidEmailFormatError": "تنسيق البريد الإلكتروني غير صالح.", "invalidEmailFormatError": "تنسيق البريد الإلكتروني غير صالح.",
"passNotMatch": "كلمة السر غير متطابقة", "passNotMatch": "كلمة السر غير متطابقة",
"POR_ORGACODE": "المصرف",
"POR_ORGACODE": "المصرف", "purposeSetup": "أضف غرض المعاملة",
"purposeSetup": "أضف غرض المعاملة", "purpcodeLabel": "كود الغرض",
"purpcodeLabel": "كود الغرض", "purpdescLabel": "وصف الغرض",
"purpdescLabel": "وصف الغرض", "purpcodePlaceholder": "أدخل رمز الغرض",
"purpcodePlaceholder": "أدخل رمز الغرض", "purpdescPlaceholder": "أدخل وصف الغرض",
"purpdescPlaceholder": "أدخل وصف الغرض", "transactionDetails": "تفاصيل المعاملة",
"transactionDetails": "تفاصيل المعاملة", "lengthExceed": " الطول تجاوز ",
"lengthExceed":" الطول تجاوز ", "transactionLogs": "سجلات المعاملات",
"transactionLogs": "سجلات المعاملات", "loadingTransactionLogs": "جاري تحميل سجلات المعاملات...",
"loadingTransactionLogs": "جاري تحميل سجلات المعاملات...", "noTransactionLogsFound": "لم يتم العثور على سجلات معاملات.",
"noTransactionLogsFound": "لم يتم العثور على سجلات معاملات.", "noThirdPartyRegFound": "لم يتم العثور على تفاصيل تسجيل الطرف الثالث",
"noThirdPartyRegFound":"لم يتم العثور على تفاصيل تسجيل الطرف الثالث", "logID": "معرف السجل",
"logID": "معرف السجل", "organization": "المنظمة",
"organization": "المنظمة", "transactionID": "معرف المعاملة",
"transactionID": "معرف المعاملة", "drAccount": "حساب المدين",
"drAccount": "حساب المدين", "crAccount": "حساب الدائن",
"crAccount": "حساب الدائن", "paymentMode": "وسيلة الدفع",
"paymentMode": "وسيلة الدفع", "channel": "القناة",
"channel": "القناة", "createdAt": "تم الإنشاء في",
"createdAt": "تم الإنشاء في", "refresh": "تحديث",
"refresh": "تحديث", "loading": "جاري التحميل",
"loading": "جاري التحميل", "invalidField": "ادخال غير صحيح",
"invalidField": "ادخال غير صحيح", "action": "اجراء",
"action": "اجراء", "confirmDelete": "هل أنت متأكد أنك تريد حذف؟",
"confirmDelete":"هل أنت متأكد أنك تريد حذف؟", "confirmSave": "هل أنت متأكد أنك تريد الحفظ؟",
"confirmSave":"هل أنت متأكد أنك تريد الحفظ؟", "2-stepAppPassword": "أدخل التحقق بخطوتين الذي تم إنشاؤه - كلمة مرور التطبيق",
"2-stepAppPassword": "أدخل التحقق بخطوتين الذي تم إنشاؤه - كلمة مرور التطبيق", "english": "إنجليزي",
"english": "إنجليزي", "arabic": "عربي",
"arabic": "عربي", "userNameRequired": "اسم المستخدم مطلوب",
"userNameRequired" : "اسم المستخدم مطلوب", "userNamePattterenError": "يُسمح فقط بالأحرف الصغيرة والأرقام",
"userNamePattterenError": "يُسمح فقط بالأحرف الصغيرة والأرقام", "PasswordRequired": "كلمة المرور مطلوبة",
"PasswordRequired": "كلمة المرور مطلوبة", "copyRightsReserved": "جميع الحقوق محفوظة © {{currentYearLong}} لشركة MFSYS Technologies.",
"copyRightsReserved": "جميع الحقوق محفوظة © {{currentYearLong}} لشركة MFSYS Technologies.", "versionAndBuildNumber": "الإصدار {{versionNumber}} البناء {{buildNumber}}",
"versionAndBuildNumber": "الإصدار {{versionNumber}} البناء {{buildNumber}}", "versionBuildDate": "+ تاريخ البناء {{date}}",
"versionBuildDate": "+ تاريخ البناء {{date}}", "dashboard": "لوحة القيادة",
"dashboard":"لوحة القيادة", "date": "تاريخ",
"date" : "تاريخ", "logout": "تسجيل الخروج",
"logout": "تسجيل الخروج", "save": "يحفظ",
"save": "يحفظ", "update": "تحديث",
"update": "تحديث", "cancel": "يلغي",
"cancel": "يلغي", "thirdPartyRegistrationDetails": "تفاصيل تسجيل الطرف الثالث",
"thirdPartyRegistrationDetails": "تفاصيل تسجيل الطرف الثالث", "SetupUserDetails": "إعداد تفاصيل المستخدم",
"SetupUserDetails": "إعداد تفاصيل المستخدم", "search": "يبحث",
"search": "يبحث", "thirdPartyNamePlaceholder": "أدخل اسم الطرف الثالث",
"thirdPartyNamePlaceholder": "أدخل اسم الطرف الثالث", "phoneNumberPlaceholder": "أدخل رقم الهاتف",
"phoneNumberPlaceholder": "أدخل رقم الهاتف", "newNoOfAccountsPlaceholder": "أدخل عدد الحسابات الجديد",
"newNoOfAccountsPlaceholder": "أدخل عدد الحسابات الجديد", "page": "صفحة",
"page": "صفحة", "of": "ل",
"of": "ل", "totalItems": "السجلات",
"totalItems": "السجلات", "record": "سِجِلّ",
"record": "سِجِلّ", "previous": "سابق",
"previous": "سابق", "next": "التالي",
"next": "التالي", "LOGIN_SUCCESSFULLY": "تم تسجيل الدخول بنجاح",
"LOGIN_SUCCESSFULLY":"تم تسجيل الدخول بنجاح", "RESET_PASSWORD_SUCCESS": "تمت إعادة تعيين كلمة المرور بنجاح",
"RESET_PASSWORD_SUCCESS": "تمت إعادة تعيين كلمة المرور بنجاح", "CHANGE_PASSWORD_SUCCESS": "تم تغيير كلمة المرور بنجاح",
"CHANGE_PASSWORD_SUCCESS": "تم تغيير كلمة المرور بنجاح", "ALREADY_LOGGED_IN": "المستخدم مسجل دخوله بالفعل",
"ALREADY_LOGGED_IN": "المستخدم مسجل دخوله بالفعل", "ACCESS_DENIED": "تم الرفض",
"ACCESS_DENIED" : "تم الرفض", "INTERNAL_SERVER_ERROR": "خطأ في الخادم الداخلي",
"INTERNAL_SERVER_ERROR": "خطأ في الخادم الداخلي", "CONNECTION_ERROR": "خطأ في الاتصال",
"CONNECTION_ERROR": "خطأ في الاتصال", "BAD_REQUEST": "اقتراح غير جيد",
"BAD_REQUEST": "اقتراح غير جيد", "FORBIDDEN_REQUEST": "طلب ممنوع",
"FORBIDDEN_REQUEST": "طلب ممنوع", "UNAUTHORIZED_REQUEST": "طلب غير مصرح به",
"UNAUTHORIZED_REQUEST": "طلب غير مصرح به", "edit": "يحرر",
"edit": "يحرر", "delete": "يمسح",
"delete": "يمسح", "deleteUser": "حذف حساب المستخدم",
"deleteUser": "حذف حساب المستخدم", "permissionManagement": "إدارة الأذونات",
"permissionManagement": "إدارة الأذونات", "userCode": "مستخدم",
"userCode": "مستخدم", "choose": "يختار",
"choose" : "يختار", "allow": "يسمح",
"allow": "يسمح", "toDateInvalidError": "يجب أن يكون تاريخ اليوم أكبر من أو يساوي تاريخ البداية",
"toDateInvalidError": "يجب أن يكون تاريخ اليوم أكبر من أو يساوي تاريخ البداية", "noLoggingDetailsFound": "لم يتم العثور على تفاصيل التسجيل",
"noLoggingDetailsFound": "لم يتم العثور على تفاصيل التسجيل", "noUserDetailsFound": "لم يتم العثور على تفاصيل المستخدم",
"noUserDetailsFound": "لم يتم العثور على تفاصيل المستخدم", "ERR_SEC_0001": "البريد الإلكتروني موجود بالفعل",
"ERR_SEC_0001": "البريد الإلكتروني موجود بالفعل", "ERR_SEC_0002": "اسم المستخدم موجود بالفعل",
"ERR_SEC_0002": "اسم المستخدم موجود بالفعل", "ERR_SEC_0003": "كلمة المرور القديمة غير صحيحة",
"ERR_SEC_0003": "كلمة المرور القديمة غير صحيحة", "ERR_SEC_0004": "اسم المستخدم أو كلمة المرور غير صحيحة",
"ERR_SEC_0004": "اسم المستخدم أو كلمة المرور غير صحيحة", "ERR_SEC_0005": "المستخدم غير موجود",
"ERR_SEC_0005": "المستخدم غير موجود", "ERR_SEC_0006": "كلمة المرور التي تم إدخالها غير صحيحة",
"ERR_SEC_0006": "كلمة المرور التي تم إدخالها غير صحيحة", "toDateGreaterThanToday": "يجب أن يكون التاريخ الحالي أقل من التاريخ الحالي",
"toDateGreaterThanToday": "يجب أن يكون التاريخ الحالي أقل من التاريخ الحالي", "fromDateGreaterThanToday": "يجب أن يكون تاريخ البدء أقل من التاريخ الحالي",
"fromDateGreaterThanToday": "يجب أن يكون تاريخ البدء أقل من التاريخ الحالي", "userIdMinLength": "يجب أن يكون معرف المستخدم مكوّنًا من 5 أحرف على الأقل",
"userIdMinLength": "يجب أن يكون معرف المستخدم مكوّنًا من 5 أحرف على الأقل", "nameMinLength": "يجب أن يكون الاسم مكوّنًا من 5 أحرف على الأقل",
"nameMinLength": "يجب أن يكون الاسم مكوّنًا من 5 أحرف على الأقل", "emptySpaceRestriction": "المسافات الفارغة غير مسموح بها",
"emptySpaceRestriction": "المسافات الفارغة غير مسموح بها", "USER_CREATED_SUCCESS": "تم إنشاء المستخدم",
"USER_CREATED_SUCCESS": "تم إنشاء المستخدم", "USER_DELETE_SUCCESS": "تم حذف المستخدم",
"USER_DELETE_SUCCESS": "تم حذف المستخدم", "SAVED_SUCCESSFULLY": "تم الحفظ بنجاح",
"SAVED_SUCCESSFULLY": "تم الحفظ بنجاح", "activityLogs": "سجلات النشاط",
"activityLogs": "سجلات النشاط", "activityLogDetails": "تفاصيل سجل النشاط",
"activityLogDetails": "تفاصيل سجل النشاط", "resetPasswordButton": "إعادة تعيين كلمة المرور",
"resetPasswordButton": "إعادة تعيين كلمة المرور", "dateTime": "التاريخ والوقت",
"dateTime": "التاريخ والوقت", "responseCode": "رمز الاستجابة",
"responseCode": "رمز الاستجابة", "remoteIp": "IP البعيد",
"remoteIp": "IP البعيد", "requestBody": "هيئة الطلب",
"requestBody": "هيئة الطلب", "requestUri": "طلب URI",
"requestUri": "طلب URI", "method": "طريقة",
"method": "طريقة", "id": "بطاقة تعريف",
"id": "بطاقة تعريف", "logId": "معرف السجل",
"porOrgacode": "رمز المنظمة",
"logId": "معرف السجل", "drMbmbkmsnumber": "رقم الحساب المدين",
"porOrgacode": "رمز المنظمة", "crMbmbkmsnumber": "رقم حساب الائتمان",
"drMbmbkmsnumber": "رقم الحساب المدين", "ppmPymdcode": "رمز الدفع",
"crMbmbkmsnumber": "رقم حساب الائتمان", "sgtGntrdate": "تاريخ المعاملة",
"ppmPymdcode": "رمز الدفع", "sgtGntrcreateat": "تاريخ الإنشاء",
"sgtGntrdate": "تاريخ المعاملة", "updatedAt": "تم التحديث في",
"sgtGntrcreateat": "تاريخ الإنشاء", "crPcaglacode": "حساب CR GL",
"updatedAt": "تم التحديث في", "drPcaGlacode": "حساب DR GL",
"crPcaglacode": "حساب CR GL", "transactionUri": "معرّف المعاملة",
"drPcaGlacode": "حساب DR GL", "transactionCode": "رمز المعاملة",
"transactionUri": "معرّف المعاملة", "channelCode": "رمز القناة",
"transactionCode": "رمز المعاملة", "userFullname": "الاسم الكامل",
"channelCode": "رمز القناة" "show": "عرض",
} "tableCollapsed": "الجدول مطوي",
"showTable": "عرض الجدول",
"collapse": "يطوي",
"expand": "توسيع",
"entries": "إدخالات"
}

@ -83,7 +83,6 @@
"ThirdPartyID":"Third Party ID", "ThirdPartyID":"Third Party ID",
"name":"Name", "name":"Name",
"EnterThirdPartyName":"Enter Third Party Name", "EnterThirdPartyName":"Enter Third Party Name",
"Email":"Email",
"email":"Email", "email":"Email",
"Address":"Address", "Address":"Address",
"phoneNumber":"Phone Number", "phoneNumber":"Phone Number",
@ -166,7 +165,6 @@
"ERR_APP_B_0004":"Session timed out", "ERR_APP_B_0004":"Session timed out",
"ERR_APP_B_0005":"Unauthorized: {{value1}}.", "ERR_APP_B_0005":"Unauthorized: {{value1}}.",
"ERR_MDL_B_0001": "Purpose Code already exists", "ERR_MDL_B_0001": "Purpose Code already exists",
"feedbackSetup": "Feedback Setup", "feedbackSetup": "Feedback Setup",
"credentials": "Credentials", "credentials": "Credentials",
"credentialsTitle": "Feedback Credentials Setup", "credentialsTitle": "Feedback Credentials Setup",
@ -292,6 +290,12 @@
"sgtGntrdate": "Transaction Date", "sgtGntrdate": "Transaction Date",
"sgtGntrcreateat": "Creation Date", "sgtGntrcreateat": "Creation Date",
"updatedAt": "Updated At", "updatedAt": "Updated At",
"channelCode": "Channel Code",
"channelCode": "Channel Code" "userFullname" : "Full Name",
"show": "Show",
"entries": "entries",
"tableCollapsed": "Table collapsed",
"showTable": "Show Table",
"collapse": "Collapse",
"expand": "Expand"
} }
Loading…
Cancel
Save