import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, signal, ViewChild } from '@angular/core'; import { DataTable, TableColumn } from '@shared/components/data-table/data-table'; import { ZardButtonComponent } from '@shared/components/button/button.component'; import { ZardPaginationModule } from '@shared/components/pagination/pagination.module'; import { ListParams, PagedResult } from '@shared/paging/paging'; import { ResultatApiResponse, ResultatStatut } from 'src/app/core/interfaces/resultat'; import { ResultatService } from 'src/app/core/services/resultat'; import { Depouillement, ResultatCourse } from 'src/app/core/services/depouillement'; import { Course } from 'src/app/core/interfaces/course'; import { toast } from 'ngx-sonner'; @Component({ standalone: true, selector: 'app-rapport', templateUrl: './rapport.html', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, DataTable, ZardButtonComponent, ZardPaginationModule], }) export class Rapport { rows = signal([]); loading = signal(false); sending = signal>(new Map()); // Pagination state page = signal(1); perPage = signal(10); totalPages = signal(1); totalElements = signal(0); @ViewChild(DataTable) table?: DataTable; cols: TableColumn[] = [ { key: 'courseNumero', label: 'N°' }, { key: 'hippodromeNom', label: 'Hippodrome' }, { key: 'courseNom', label: 'Course' }, { key: 'ordreArrivee', label: "Ordre d'arrivée", cell: (r) => String(r.ordreArrivee ?? '').replace(/,/g, ' - ') }, { key: 'statut', label: 'Statut', cell: (r)=>(r.statut.toString().toLowerCase().replace("_", " ")) }, { key: 'datePublication', label: 'Date pub.', cell: (r) => r.datePublication ?? r.createdAt ?? '—' }, { key: 'dateValidation', label: 'Date validation' }, ]; constructor(private api: ResultatService, private depouillement: Depouillement) { // initial load this.fetch(); } private fetchPage(params?: Partial) { this.loading.set(true); const p: ListParams = { page: this.page(), size: this.perPage(), ...(params || {}) }; this.api.listRawPaged(p).subscribe({ next: (res: PagedResult) => { const filtered = (res?.content || []).filter((r) => !!(r.ordreArrivee && String(r.ordreArrivee).trim())); this.rows.set(filtered); // normalize paging meta this.totalPages.set(res.totalPages ?? 1); this.totalElements.set(res.totalElements ?? (filtered.length || 0)); // ensure local page is in sync with backend response if (res.pageable?.pageNumber) this.page.set(res.pageable.pageNumber); this.loading.set(false); }, error: (err) => { console.error('Error fetching paged reports:', err); this.rows.set([]); this.loading.set(false); }, }); } fetch() { this.fetchPage(); } onPageChange(nextPage: number) { this.page.set(nextPage); this.fetchPage(); } onPerPageChange(size: number) { this.perPage.set(size); this.page.set(1); this.fetchPage(); } // wrapper for template change event to avoid $event typing issues onPerPageChangeEvent(e: Event) { const v = (e.target as HTMLSelectElement)?.value; const size = Number(v) || 10; this.onPerPageChange(size); } openReport(row: ResultatApiResponse) { try { // Open a per-result report URL in a new tab. Adjust path if your server uses another route. const url = `/resultat/${row.id}`; window.open(url, '_blank'); } catch (err) { console.error('Failed to open report for', row, err); } } isSending(id: string | number) { return !!this.sending().get(String(id)); } private setSending(id: string | number, v: boolean) { const map = new Map(this.sending()); map.set(String(id), v); this.sending.set(map); } sendToDepouillement(row: ResultatApiResponse) { if (!row || !row.id) return; const id = String(row.id); if (this.isSending(id)) return; // already sending this.setSending(id, true); // Build a minimal ResultatCourse payload using available fields. const course = { id: String((row as any).courseId ?? '') }; const payload: Omit = { course, statut: (row.statut as any) ?? (0 as any), ordreArrivee: String(row.ordreArrivee ?? ''), datePublication: row.datePublication ?? row.createdAt, }; this.depouillement.sendResultat(payload).subscribe({ next: (res) => { // After successful depouillement, update the resultat statut to PROVISOIRE const updateId = String((res && (res as any).id) ?? row.id); this.api.update(updateId, { statut: ResultatStatut.PROVISOIRE }).subscribe({ next: (updated) => { // Update the local rows to reflect the new statut this.rows.set( this.rows().map((r) => (String(r.id) === String(updateId) ? { ...r, statut: ResultatStatut.PROVISOIRE } : r)) ); toast.success('Résultat envoyé au dépouillement et statut mis à jour.'); this.setSending(id, false); }, error: (err) => { console.error('Error updating resultat statut after depouillement:', err); toast.error('Échec de la mise à jour du statut du résultat.'); this.setSending(id, false); }, }); }, error: (err) => { console.error('Error sending to depouillement:', err); this.setSending(id, false); }, }); } }