Files
pmu-plateforme-jeux-admin-plr/src/app/dashboard/pages/rapport/rapport.ts
2025-12-31 14:53:40 +01:00

155 lines
5.8 KiB
TypeScript

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<ResultatApiResponse[]>([]);
loading = signal(false);
sending = signal<Map<string, boolean>>(new Map());
// Pagination state
page = signal<number>(1);
perPage = signal<number>(10);
totalPages = signal<number>(1);
totalElements = signal<number>(0);
@ViewChild(DataTable) table?: DataTable<ResultatApiResponse>;
cols: TableColumn<ResultatApiResponse>[] = [
{ 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<ListParams>) {
this.loading.set(true);
const p: ListParams = { page: this.page(), size: this.perPage(), ...(params || {}) };
this.api.listRawPaged(p).subscribe({
next: (res: PagedResult<ResultatApiResponse>) => {
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<ResultatCourse, "id"> = {
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);
},
});
}
}