Merge branch 'mazdak/UX-transactionLogs' into PRE-PRODUCTION-2026
commit
16be190777
@ -1,139 +1,29 @@
|
|||||||
// Date filter section
|
.date-input-wrapper {
|
||||||
.date-filter-section {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
|
|
||||||
.date-input-group {
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.form-control {
|
input[type="date"] {
|
||||||
padding-right: 2.5rem;
|
cursor: pointer;
|
||||||
}
|
padding-right: 35px;
|
||||||
|
|
||||||
.date-icon {
|
&::-webkit-calendar-picker-indicator {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0.75rem;
|
left: 0;
|
||||||
top: 50%;
|
top: 0;
|
||||||
transform: translateY(-50%);
|
width: 100%;
|
||||||
color: #6c757d;
|
height: 100%;
|
||||||
}
|
margin: 0;
|
||||||
}
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
.quick-filter-btn {
|
opacity: 0;
|
||||||
&.active {
|
|
||||||
background-color: var(--bs-primary);
|
|
||||||
color: white;
|
|
||||||
border-color: var(--bs-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Table styling
|
|
||||||
.table-responsive {
|
|
||||||
min-height: 400px;
|
|
||||||
|
|
||||||
table {
|
|
||||||
font-size: 0.875rem;
|
|
||||||
|
|
||||||
th {
|
|
||||||
font-weight: 600;
|
|
||||||
white-space: nowrap;
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
}
|
|
||||||
|
|
||||||
td {
|
|
||||||
vertical-align: middle;
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
padding: 0.2rem 0.4rem;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge {
|
|
||||||
font-size: 0.7rem;
|
|
||||||
padding: 0.25rem 0.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loading spinner
|
|
||||||
.spinner-border {
|
|
||||||
width: 3rem;
|
|
||||||
height: 3rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search box
|
.calendar-icon {
|
||||||
.search-box {
|
|
||||||
position: relative;
|
|
||||||
min-width: 200px;
|
|
||||||
|
|
||||||
.search-icon {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0.75rem;
|
right: 10px;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
color: #6c757d;
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
color: #6c757d;
|
||||||
|
|
||||||
.form-control {
|
|
||||||
padding-right: 2.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Active filter badge
|
|
||||||
.active-filter-badge {
|
|
||||||
animation: fadeIn 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-10px);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mobile responsive adjustments
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.date-filter-section {
|
|
||||||
.btn-group {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
flex: 1;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
padding: 0.375rem 0.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-responsive {
|
|
||||||
overflow-x: auto;
|
|
||||||
|
|
||||||
table {
|
|
||||||
min-width: 1200px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box {
|
|
||||||
min-width: 150px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dark mode support (if needed)
|
|
||||||
[data-bs-theme="dark"] {
|
|
||||||
.table-light {
|
|
||||||
background-color: #2d333b !important;
|
|
||||||
color: #adb5bd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box .search-icon {
|
|
||||||
color: #adb5bd;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,340 +1,171 @@
|
|||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule, DatePipe } from '@angular/common';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { ExcelExportService } from '../shared/services/excel-export.service';
|
import { ExcelExportService } from '../shared/services/excel-export.service';
|
||||||
import { TRANSACTION_LOGS_FILE_NAME } from '../utils/app.constants';
|
import { toDateAfterFromDateValidator, TRANSACTION_LOGS_FILE_NAME } from '../utils/app.constants';
|
||||||
import { pageSizeOptions } from '../utils/app.constants';
|
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 { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } 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';
|
|
||||||
import { Subject } from 'rxjs';
|
|
||||||
import { takeUntil, debounceTime } from 'rxjs/operators';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-transaction-logs',
|
selector: 'app-transaction-logs',
|
||||||
templateUrl: './transaction-logs.component.html',
|
templateUrl: './transaction-logs.component.html',
|
||||||
styleUrls: ['./transaction-logs.component.scss'],
|
styleUrls: ['./transaction-logs.component.scss'],
|
||||||
imports: [CommonModule, TranslateModule, NgSelectModule, FormsModule, ReactiveFormsModule, TableFilterPipe]
|
imports: [
|
||||||
})
|
TranslateModule,
|
||||||
export class TransactionLogsComponent implements OnInit, OnDestroy {
|
FormsModule,
|
||||||
currentPage: number = 1;
|
NgSelectModule,
|
||||||
totalCount: number = 0;
|
CommonModule,
|
||||||
renewalDataExpanded: boolean = true;
|
ReactiveFormsModule,
|
||||||
|
TableFilterPipe
|
||||||
|
],
|
||||||
|
providers: [DatePipe]})
|
||||||
|
export class TransactionLogsComponent implements OnInit {
|
||||||
|
logsSearchForm!: FormGroup;
|
||||||
|
|
||||||
pageSizeOptions = pageSizeOptions;
|
pageSizeOptions = pageSizeOptions;
|
||||||
itemsPerPage: number = 10;
|
itemsPerPage = 10;
|
||||||
transactionLog: TransactionLog[] = [];
|
currentPage = 1;
|
||||||
isLoading = false;
|
maxDate: string;
|
||||||
errorMessage: string = '';
|
searchText = '';
|
||||||
searchText: string = '';
|
|
||||||
allItems: TransactionLog[] = [];
|
|
||||||
transactionDataExpanded: boolean = true;
|
|
||||||
|
|
||||||
// Date range properties
|
logsDataExpanded = true;
|
||||||
fromDate: string = '';
|
isLoading = false;
|
||||||
toDate: string = '';
|
|
||||||
maxDate: string = '';
|
|
||||||
showDateFilters: boolean = false;
|
|
||||||
|
|
||||||
// Search subject for debouncing
|
/** DATA LAYERS (do not mix these) */
|
||||||
private searchSubject = new Subject<string>();
|
allItems: TransactionLog[] = []; // raw API data
|
||||||
private destroy$ = new Subject<void>();
|
filteredItems: TransactionLog[] = []; // after search
|
||||||
|
pagedItems: TransactionLog[] = []; // table view
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private excelExportService: ExcelExportService,
|
private fb: FormBuilder,
|
||||||
private httpService: HttpURIService,
|
private httpService: HttpURIService,
|
||||||
) {}
|
private datePipe: DatePipe,
|
||||||
|
private excelExportService: ExcelExportService,
|
||||||
ngOnInit(): void {
|
) {
|
||||||
// Set max date to today
|
this.maxDate = new Date().toISOString().split('T')[0];
|
||||||
this.maxDate = formatDate(new Date(), 'yyyy-MM-dd', 'en-US');
|
|
||||||
|
|
||||||
// Set default date range (last 7 days)
|
|
||||||
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');
|
|
||||||
|
|
||||||
// Set up search debouncing
|
|
||||||
this.setupSearchDebounce();
|
|
||||||
|
|
||||||
this.loadTransactionLogs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnInit(): void {
|
||||||
this.destroy$.next();
|
this.logsSearchForm = this.fb.group(
|
||||||
this.destroy$.complete();
|
{
|
||||||
this.searchSubject.complete();
|
fromDate: ['', Validators.required],
|
||||||
|
toDate: ['', Validators.required],
|
||||||
|
},
|
||||||
|
{ validators: toDateAfterFromDateValidator },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupSearchDebounce(): void {
|
getlogsData(): void {
|
||||||
this.searchSubject.pipe(
|
if (this.logsSearchForm.invalid) return;
|
||||||
takeUntil(this.destroy$),
|
|
||||||
debounceTime(300)
|
|
||||||
).subscribe((searchValue: string) => {
|
|
||||||
this.searchText = searchValue;
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.loadTransactionLogs();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
loadTransactionLogs(): void {
|
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.errorMessage = '';
|
|
||||||
|
|
||||||
// Validate date range before making API call
|
|
||||||
if (!this.validateDateRange()) {
|
|
||||||
this.isLoading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build query parameters
|
|
||||||
let params = new HttpParams();
|
|
||||||
|
|
||||||
// Add pagination parameters
|
|
||||||
params = params.set('page', this.currentPage.toString());
|
|
||||||
params = params.set('limit', this.itemsPerPage.toString());
|
|
||||||
|
|
||||||
// Add date filters if provided
|
|
||||||
if (this.fromDate) {
|
|
||||||
params = params.set('fromDate', this.fromDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.toDate) {
|
const { fromDate, toDate } = this.logsSearchForm.value;
|
||||||
params = params.set('toDate', this.toDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add search filter if provided
|
const params = new HttpParams()
|
||||||
if (this.searchText && this.searchText.trim() !== '') {
|
.set('fromDate', this.datePipe.transform(fromDate, 'dd-MM-yyyy')!)
|
||||||
params = params.set('search', this.searchText.trim());
|
.set('toDate', this.datePipe.transform(toDate, 'dd-MM-yyyy')!);
|
||||||
}
|
|
||||||
|
|
||||||
this.httpService
|
this.httpService
|
||||||
.requestGET<any>(URIKey.TRANSACTION_LOGS, params)
|
.requestGET<TransactionLog[]>(URIKey.TRANSACTION_LOGS, params)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: (res) => {
|
next: (response) => {
|
||||||
const logs = Array.isArray(res) ? res : res?.data;
|
this.allItems = response ?? [];
|
||||||
this.transactionLog = logs ?? [];
|
this.filteredItems = [...this.allItems];
|
||||||
this.allItems = [...this.transactionLog];
|
this.currentPage = 1;
|
||||||
|
this.updatePagedItems();
|
||||||
// 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.isLoading = false;
|
this.isLoading = false;
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: () => {
|
||||||
console.error('Error fetching transaction logs:', err);
|
|
||||||
this.errorMessage = err.message || 'Failed to load transaction logs. Please try again.';
|
|
||||||
this.transactionLog = [];
|
|
||||||
this.allItems = [];
|
this.allItems = [];
|
||||||
this.totalCount = 0;
|
this.filteredItems = [];
|
||||||
|
this.pagedItems = [];
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
},
|
},
|
||||||
complete: () => {
|
|
||||||
this.isLoading = false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private validateDateRange(): boolean {
|
/** SEARCH — filters DATA, not DOM */
|
||||||
if (this.fromDate && this.toDate) {
|
applySearch(): void {
|
||||||
const from = new Date(this.fromDate);
|
const value = this.searchText.toLowerCase().trim();
|
||||||
const to = new Date(this.toDate);
|
|
||||||
|
|
||||||
if (from > to) {
|
|
||||||
this.errorMessage = 'From date cannot be after To date';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optional: Validate date range is not too wide
|
|
||||||
const diffTime = Math.abs(to.getTime() - from.getTime());
|
|
||||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
||||||
|
|
||||||
if (diffDays > 365) {
|
|
||||||
this.errorMessage = 'Date range cannot exceed 1 year';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Date filter change handler
|
|
||||||
onDateFilterChange(): void {
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.loadTransactionLogs();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear date filters
|
|
||||||
clearDateFilters(): void {
|
|
||||||
this.fromDate = '';
|
|
||||||
this.toDate = '';
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.loadTransactionLogs();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle date filter visibility
|
if (!value) {
|
||||||
toggleDateFilters(): void {
|
this.filteredItems = [...this.allItems];
|
||||||
this.showDateFilters = !this.showDateFilters;
|
} else {
|
||||||
}
|
this.filteredItems = this.allItems.filter((item) =>
|
||||||
|
[
|
||||||
// Apply default date range (Last 7 days)
|
'logId',
|
||||||
applyLast7Days(): void {
|
'porOrgacode',
|
||||||
const today = new Date();
|
'transactionID',
|
||||||
const lastWeek = new Date();
|
'drMbmbkmsnumber',
|
||||||
lastWeek.setDate(today.getDate() - 7);
|
'crMbmbkmsnumber',
|
||||||
|
'crPcaglacode',
|
||||||
this.fromDate = formatDate(lastWeek, 'yyyy-MM-dd', 'en-US');
|
'drPcaGlacode',
|
||||||
this.toDate = formatDate(today, 'yyyy-MM-dd', 'en-US');
|
'amount',
|
||||||
this.onDateFilterChange();
|
'paymentMode',
|
||||||
}
|
'ppmPymdcode',
|
||||||
|
'sgtGntrdate',
|
||||||
// Apply default date range (Last 30 days)
|
'channelCode',
|
||||||
applyLast30Days(): void {
|
'createdAt',
|
||||||
const today = new Date();
|
'transactionUri',
|
||||||
const lastMonth = new Date();
|
'transactionCode',
|
||||||
lastMonth.setDate(today.getDate() - 30);
|
].some((key) =>
|
||||||
|
String((item as any)[key] ?? '')
|
||||||
this.fromDate = formatDate(lastMonth, 'yyyy-MM-dd', 'en-US');
|
.toLowerCase()
|
||||||
this.toDate = formatDate(today, 'yyyy-MM-dd', 'en-US');
|
.includes(value),
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply date range (Last 3 months)
|
|
||||||
applyLast3Months(): void {
|
|
||||||
const today = new Date();
|
|
||||||
const threeMonthsAgo = new Date();
|
|
||||||
threeMonthsAgo.setMonth(today.getMonth() - 3);
|
|
||||||
|
|
||||||
this.fromDate = formatDate(threeMonthsAgo, 'yyyy-MM-dd', 'en-US');
|
|
||||||
this.toDate = formatDate(today, 'yyyy-MM-dd', 'en-US');
|
|
||||||
this.onDateFilterChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleTableCard(): void {
|
|
||||||
this.transactionDataExpanded = !this.transactionDataExpanded;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
itemsPerPageChanged(): void {
|
|
||||||
this.currentPage = 1;
|
this.currentPage = 1;
|
||||||
this.loadTransactionLogs();
|
this.updatePagedItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearch(value: string): void {
|
updatePagedItems(): void {
|
||||||
this.searchSubject.next(value);
|
const start = (this.currentPage - 1) * this.itemsPerPage;
|
||||||
|
const end = start + this.itemsPerPage;
|
||||||
|
this.pagedItems = this.filteredItems.slice(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
totalPages(): number {
|
totalPages(): number {
|
||||||
if (this.totalCount === 0) return 1;
|
return Math.ceil(this.filteredItems.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.loadTransactionLogs();
|
this.updatePagedItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nextPage(): void {
|
nextPage(): void {
|
||||||
if (this.currentPage < this.totalPages()) {
|
if (this.currentPage < this.totalPages()) {
|
||||||
this.currentPage++;
|
this.currentPage++;
|
||||||
this.loadTransactionLogs();
|
this.updatePagedItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exportDataInExcel(): void {
|
itemsPerPageChanged(): void {
|
||||||
// Build export parameters
|
this.currentPage = 1;
|
||||||
let params = new HttpParams();
|
this.updatePagedItems();
|
||||||
|
|
||||||
// Include date filters in export if they are set
|
|
||||||
if (this.fromDate) {
|
|
||||||
params = params.set('fromDate', this.fromDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.toDate) {
|
|
||||||
params = params.set('toDate', this.toDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.searchText && this.searchText.trim() !== '') {
|
|
||||||
params = params.set('search', this.searchText.trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
// For large exports, you might want to fetch all data without pagination
|
|
||||||
params = params.set('limit', '10000'); // Adjust as needed
|
|
||||||
|
|
||||||
this.httpService
|
|
||||||
.requestGET<any>(URIKey.TRANSACTION_LOGS, params)
|
|
||||||
.subscribe({
|
|
||||||
next: (res) => {
|
|
||||||
const logs = Array.isArray(res) ? res : res?.data;
|
|
||||||
const dataToExport = logs ?? [];
|
|
||||||
|
|
||||||
if (dataToExport.length === 0) {
|
|
||||||
this.errorMessage = 'No data to export';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate filename with date range if applicable
|
|
||||||
let fileName = TRANSACTION_LOGS_FILE_NAME;
|
|
||||||
if (this.fromDate || this.toDate) {
|
|
||||||
const from = this.fromDate ? formatDate(new Date(this.fromDate), 'dd-MMM-yyyy', 'en-US') : 'All';
|
|
||||||
const to = this.toDate ? formatDate(new Date(this.toDate), 'dd-MMM-yyyy', 'en-US') : 'All';
|
|
||||||
fileName = `TransactionLogs_${from}_to_${to}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.excelExportService.exportExcel(dataToExport, fileName);
|
|
||||||
},
|
|
||||||
error: (err) => {
|
|
||||||
console.error('Error exporting data:', err);
|
|
||||||
this.errorMessage = 'Failed to export data. Please try again.';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get filtered items for display (used in template)
|
|
||||||
get filteredItems(): TransactionLog[] {
|
|
||||||
return this.allItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format date for display
|
toggleTableCard(): void {
|
||||||
formatDateDisplay(dateString: string): string {
|
this.logsDataExpanded = !this.logsDataExpanded;
|
||||||
if (!dateString) return '';
|
|
||||||
return formatDate(new Date(dateString), 'MMM dd, yyyy', 'en-US');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if date filter is active
|
exportDataInExcel(): void {
|
||||||
get isDateFilterActive(): boolean {
|
this.excelExportService.exportExcel(
|
||||||
return !!this.fromDate || !!this.toDate;
|
this.allItems,
|
||||||
|
TRANSACTION_LOGS_FILE_NAME,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get pagedItems(): TransactionLog[] {
|
|
||||||
const start = (this.currentPage - 1) * this.itemsPerPage;
|
|
||||||
return this.allItems.slice(start, start + this.itemsPerPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue