import { Component, OnInit, OnDestroy } from '@angular/core'; import { CommonModule } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; import { ExcelExportService } from '../shared/services/excel-export.service'; import { TRANSACTION_LOGS_FILE_NAME } from '../utils/app.constants'; import { pageSizeOptions } from '../utils/app.constants'; import { NgSelectModule } from '@ng-select/ng-select'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { TableFilterPipe } from '../shared/pipes/table-filter.pipe'; import { TransactionLog } from "../models/user"; import { URIKey } from '../utils/uri-enums'; import { HttpParams } from '@angular/common/http'; import { HttpURIService } from '../app.http.uri.service'; import { formatDate } from '@angular/common'; import { Subject } from 'rxjs'; import { takeUntil, debounceTime } from 'rxjs/operators'; @Component({ selector: 'app-transaction-logs', templateUrl: './transaction-logs.component.html', styleUrls: ['./transaction-logs.component.scss'], imports: [CommonModule, TranslateModule, NgSelectModule, FormsModule, ReactiveFormsModule, TableFilterPipe] }) export class TransactionLogsComponent implements OnInit, OnDestroy { currentPage: number = 1; totalCount: number = 0; renewalDataExpanded: boolean = true; pageSizeOptions = pageSizeOptions; itemsPerPage: number = 10; transactionLog: TransactionLog[] = []; isLoading = false; errorMessage: string = ''; searchText: string = ''; allItems: TransactionLog[] = []; transactionDataExpanded: boolean = true; // Date range properties fromDate: string = ''; toDate: string = ''; maxDate: string = ''; showDateFilters: boolean = false; // Search subject for debouncing private searchSubject = new Subject(); private destroy$ = new Subject(); constructor( private excelExportService: ExcelExportService, private httpService: HttpURIService, ) {} ngOnInit(): void { // Set max date to today 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 { this.destroy$.next(); this.destroy$.complete(); this.searchSubject.complete(); } private setupSearchDebounce(): void { this.searchSubject.pipe( takeUntil(this.destroy$), debounceTime(300) ).subscribe((searchValue: string) => { this.searchText = searchValue; this.currentPage = 1; this.loadTransactionLogs(); }); } loadTransactionLogs(): void { 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) { 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(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.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.isLoading = false; }, complete: () => { this.isLoading = false; } }); } private validateDateRange(): boolean { 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 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 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(); } // 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.loadTransactionLogs(); } onSearch(value: string): void { this.searchSubject.next(value); } totalPages(): number { if (this.totalCount === 0) return 1; return Math.ceil(this.totalCount / this.itemsPerPage); } previousPage(): void { if (this.currentPage > 1) { this.currentPage--; this.loadTransactionLogs(); } } nextPage(): void { if (this.currentPage < this.totalPages()) { this.currentPage++; this.loadTransactionLogs(); } } exportDataInExcel(): void { // Build export parameters let params = new HttpParams(); // 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(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 formatDateDisplay(dateString: string): string { if (!dateString) return ''; return formatDate(new Date(dateString), 'MMM dd, yyyy', 'en-US'); } // Check if date filter is active get isDateFilterActive(): boolean { return !!this.fromDate || !!this.toDate; } get pagedItems(): TransactionLog[] { const start = (this.currentPage - 1) * this.itemsPerPage; return this.allItems.slice(start, start + this.itemsPerPage); } }