import { Component, inject, signal, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Router, RouterLink } from '@angular/router'; import { FormsModule } from '@angular/forms'; import { NzTableModule, NzTableFilterList } from 'ng-zorro-antd/table'; import { NzButtonModule } from 'ng-zorro-antd/button'; import { NzInputModule } from 'ng-zorro-antd/input'; import { NzTagModule } from 'ng-zorro-antd/tag'; import { NzIconModule } from 'ng-zorro-antd/icon'; import { NzEmptyModule } from 'ng-zorro-antd/empty'; import { NzSpinModule } from 'ng-zorro-antd/spin'; import { NzToolTipModule } from 'ng-zorro-antd/tooltip'; import { NzPaginationModule } from 'ng-zorro-antd/pagination'; import { NzDatePickerModule } from 'ng-zorro-antd/date-picker'; import { NzDropDownModule } from 'ng-zorro-antd/dropdown'; import { ApiService } from '../../../core/services/api.service'; import { AuthService } from '../../../core/services/auth.service'; import { Message, MessageListParams } from '../../../core/models'; import { RelativeTimePipe } from '../../../shared/pipes/relative-time.pipe'; @Component({ selector: 'app-message-list', standalone: true, imports: [ CommonModule, FormsModule, RouterLink, NzTableModule, NzButtonModule, NzInputModule, NzTagModule, NzIconModule, NzEmptyModule, NzSpinModule, NzToolTipModule, NzPaginationModule, NzDatePickerModule, NzDropDownModule, RelativeTimePipe, ], templateUrl: './message-list.component.html', styleUrl: './message-list.component.scss' }) export class MessageListComponent implements OnInit { private apiService = inject(ApiService); private authService = inject(AuthService); private router = inject(Router); messages = signal([]); loading = signal(false); // Pagination currentPage = signal(1); pageSize = 50; totalCount = signal(0); // Filters searchText = ''; appliedSearchText = ''; priorityFilter: string[] = []; channelFilter: string[] = []; senderFilter: string[] = []; dateRange: [Date, Date] | null = null; dateFilterVisible = false; // Filter options priorityFilters: NzTableFilterList = [ { text: 'Low', value: '0' }, { text: 'Normal', value: '1' }, { text: 'High', value: '2' }, ]; channelFilters = signal([]); senderFilters = signal([]); ngOnInit(): void { this.loadChannels(); this.loadSenders(); this.loadMessages(); } loadChannels(): void { const userId = this.authService.getUserId(); if (!userId) return; this.apiService.getChannels(userId, 'all_any').subscribe({ next: (response) => { this.channelFilters.set( response.channels.map(ch => ({ text: ch.display_name, value: ch.channel_id, })) ); } }); } loadSenders(): void { this.apiService.getSenderNames().subscribe({ next: (response) => { this.senderFilters.set( response.sender_names.map(s => ({ text: s.name, value: s.name, })) ); } }); } loadMessages(): void { this.loading.set(true); const params: MessageListParams = { page_size: this.pageSize, trimmed: true, }; if (this.appliedSearchText) { params.search = this.appliedSearchText; } if (this.priorityFilter.length > 0) { params.priority = this.priorityFilter.map(p => parseInt(p, 10)); } if (this.channelFilter.length > 0) { params.channel_id = this.channelFilter; } if (this.senderFilter.length > 0) { params.sender = this.senderFilter; } if (this.dateRange) { params.after = this.dateRange[0].toISOString(); params.before = this.dateRange[1].toISOString(); } // Use page-index based pagination: $1 = page 1, $2 = page 2, etc. const page = this.currentPage(); if (page > 1) { params.next_page_token = `$${page}`; } this.apiService.getMessages(params).subscribe({ next: (response) => { this.messages.set(response.messages); this.totalCount.set(response.total_count); this.loading.set(false); }, error: () => { this.loading.set(false); } }); } applyFilters(): void { this.appliedSearchText = this.searchText; this.currentPage.set(1); this.loadMessages(); } onPriorityFilterChange(filters: string[] | null): void { this.priorityFilter = filters ?? []; this.currentPage.set(1); this.loadMessages(); } onChannelFilterChange(filters: string[] | null): void { this.channelFilter = filters ?? []; this.currentPage.set(1); this.loadMessages(); } onSenderFilterChange(filters: string[] | null): void { this.senderFilter = filters ?? []; this.currentPage.set(1); this.loadMessages(); } clearSearch(): void { this.searchText = ''; this.appliedSearchText = ''; this.currentPage.set(1); this.loadMessages(); } clearChannelFilter(): void { this.channelFilter = []; this.currentPage.set(1); this.loadMessages(); } removeChannelFilter(channel: string): void { this.channelFilter = this.channelFilter.filter(c => c !== channel); this.currentPage.set(1); this.loadMessages(); } clearSenderFilter(): void { this.senderFilter = []; this.currentPage.set(1); this.loadMessages(); } removeSenderFilter(sender: string): void { this.senderFilter = this.senderFilter.filter(s => s !== sender); this.currentPage.set(1); this.loadMessages(); } clearPriorityFilter(): void { this.priorityFilter = []; this.currentPage.set(1); this.loadMessages(); } onDateRangeChange(dates: [Date, Date] | null): void { this.dateRange = dates; if (dates) { this.dateFilterVisible = false; } this.currentPage.set(1); this.loadMessages(); } clearDateRange(): void { this.dateRange = null; this.currentPage.set(1); this.loadMessages(); } clearAllFilters(): void { this.searchText = ''; this.appliedSearchText = ''; this.channelFilter = []; this.senderFilter = []; this.priorityFilter = []; this.dateRange = null; this.currentPage.set(1); this.loadMessages(); } hasActiveFilters(): boolean { return !!this.appliedSearchText || this.channelFilter.length > 0 || this.senderFilter.length > 0 || this.priorityFilter.length > 0 || !!this.dateRange; } getChannelDisplayName(channelId: string): string { const filters = this.channelFilters(); const channel = filters.find(f => f.value === channelId); return channel?.text?.toString() ?? channelId; } getDateRangeDisplay(): string { if (!this.dateRange) return ''; const format = (d: Date) => d.toLocaleDateString(); return `${format(this.dateRange[0])} - ${format(this.dateRange[1])}`; } goToPage(page: number): void { this.currentPage.set(page); this.loadMessages(); } viewMessage(message: Message): void { this.router.navigate(['/messages', message.message_id]); } getPriorityLabel(priority: number): string { switch (priority) { case 0: return 'Low'; case 1: return 'Normal'; case 2: return 'High'; default: return 'Unknown'; } } getPriorityColor(priority: number): string { switch (priority) { case 0: return 'default'; case 1: return 'blue'; case 2: return 'red'; default: return 'default'; } } }