Refactor transaction logs UI and logic for clarity
Redesigned the transaction logs component to use a reactive form for date filtering, simplified the table and search logic, and improved pagination and export functionality. Updated SCSS for cleaner date input styling and adjusted i18n keys for new UI labels.mazdak/UX-transactionLogs
parent
9039567896
commit
cdec4e63ec
@ -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