import { Component, OnDestroy, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { CustomSelectComponent } from '../../components/custom-select/custom-select'; import { SolicitacaoLinhaDto, SolicitacoesLinhasService } from '../../services/solicitacoes-linhas.service'; import { buildPageNumbers, clampPage, computePageEnd, computePageStart, computeTotalPages } from '../../utils/pagination.util'; @Component({ selector: 'app-solicitacoes-linhas', standalone: true, imports: [CommonModule, FormsModule, CustomSelectComponent], templateUrl: './solicitacoes-linhas.html', styleUrls: ['./solicitacoes-linhas.scss'], }) export class SolicitacoesLinhas implements OnInit, OnDestroy { items: SolicitacaoLinhaDto[] = []; loading = false; errorMsg = ''; page = 1; pageSize = 20; pageSizeOptions = [10, 20, 50, 100]; total = 0; search = ''; private searchTimer: ReturnType | null = null; constructor(private readonly solicitacoesService: SolicitacoesLinhasService) {} ngOnInit(): void { this.fetch(1); } ngOnDestroy(): void { if (this.searchTimer) { clearTimeout(this.searchTimer); this.searchTimer = null; } } refresh(): void { this.fetch(); } onSearchChange(): void { if (this.searchTimer) { clearTimeout(this.searchTimer); } this.searchTimer = setTimeout(() => { this.page = 1; this.fetch(); }, 300); } clearSearch(): void { this.search = ''; this.page = 1; this.fetch(); } onPageSizeChange(): void { this.page = 1; this.fetch(); } goToPage(pageNumber: number): void { this.page = clampPage(pageNumber, this.totalPages); this.fetch(); } get totalPages(): number { return computeTotalPages(this.total || 0, this.pageSize); } get pageNumbers(): number[] { return buildPageNumbers(this.page, this.totalPages); } get pageStart(): number { return computePageStart(this.total || 0, this.page, this.pageSize); } get pageEnd(): number { return computePageEnd(this.total || 0, this.page, this.pageSize); } private parseDate(value?: string | null): Date | null { if (!value) return null; const d = new Date(value); return Number.isNaN(d.getTime()) ? null : d; } formatDateTime(value?: string | null): string { const d = this.parseDate(value); if (!d) return '-'; return d.toLocaleString('pt-BR'); } formatDate(value?: string | null): string { const d = this.parseDate(value); if (!d) return '-'; return d.toLocaleDateString('pt-BR'); } formatTime(value?: string | null): string { const d = this.parseDate(value); if (!d) return '--:--'; return d.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' }); } formatFranquiaValor(value?: number | null): string { if (value === null || value === undefined) return '-'; return new Intl.NumberFormat('pt-BR', { maximumFractionDigits: 2 }).format(value); } formatFranquia(value?: number | null): string { const formatted = this.formatFranquiaValor(value); return formatted === '-' ? '-' : `${formatted} GB`; } tipoLabel(value?: string | null): string { const v = (value ?? '').toString().trim().toUpperCase(); if (v === 'ALTERACAO_FRANQUIA') return 'Alteração de franquia'; if (v === 'BLOQUEIO') return 'Bloqueio'; return v || '-'; } tipoBadgeClass(value?: string | null): string { const v = (value ?? '').toString().trim().toUpperCase(); if (v === 'ALTERACAO_FRANQUIA') return 'type-badge type-badge--franquia'; if (v === 'BLOQUEIO') return 'type-badge type-badge--bloqueio'; return 'type-badge type-badge--default'; } trackBySolicitacao(_: number, item: SolicitacaoLinhaDto): string { return item.id; } descricao(item: SolicitacaoLinhaDto): string { const tipo = (item.tipoSolicitacao ?? '').toString().trim().toUpperCase(); const linha = (item.linha ?? '').toString().trim(); if (tipo === 'ALTERACAO_FRANQUIA') { return `Mudanca de franquia de ${this.formatFranquiaValor(item.franquiaLineAtual)} para ${this.formatFranquiaValor(item.franquiaLineNova)}`; } if (tipo === 'BLOQUEIO') { return `Bloqueio da linha ${linha || '-'}`; } return (item.mensagem ?? '').toString().trim() || '-'; } private fetch(goToPage?: number): void { if (goToPage) this.page = goToPage; this.loading = true; this.errorMsg = ''; this.solicitacoesService .list({ page: this.page, pageSize: this.pageSize, search: this.search?.trim() || undefined, }) .subscribe({ next: (res) => { this.items = res.items || []; this.total = res.total || 0; this.page = res.page || this.page; this.pageSize = res.pageSize || this.pageSize; this.loading = false; }, error: () => { this.loading = false; this.errorMsg = 'Não foi possível carregar as solicitações.'; }, }); } }