course creation

This commit is contained in:
OnlyPapy98
2025-12-19 18:00:50 +01:00
parent dde2e8aebf
commit 169b5ca412
39 changed files with 1250 additions and 2258 deletions

View File

@@ -150,7 +150,7 @@ export class AgentsPage {
this.tpeSvc
.list({ page: 1, perPage: 200, search: '', sortKey: 'imei', sortDir: 'asc' } as any)
.subscribe((res) => {
const tpes = res.data as TpeDevice[];
const tpes = res.content as TpeDevice[];
this.rebuildTpeMaps(tpes);
});
effect(() => {
@@ -175,8 +175,8 @@ export class AgentsPage {
this.loading.set(true);
this.api.list(params).subscribe({
next: (res) => {
this.rows.set(res.data);
this.total.set(res.meta.total);
this.rows.set(res.content);
this.total.set(res.pageable.total);
this.loading.set(false);
// Refresh TPE map to ensure we have latest data
this.refreshTpeMap();
@@ -193,7 +193,7 @@ export class AgentsPage {
this.tpeSvc
.list({ page: 1, perPage: 200, search: '', sortKey: 'imei', sortDir: 'asc' } as any)
.subscribe((res) => {
const tpes = res.data as TpeDevice[];
const tpes = res.content as TpeDevice[];
this.rebuildTpeMaps(tpes);
});
}

View File

@@ -16,7 +16,7 @@ import { ZardCardComponent } from '@shared/components/card/card.component';
import { ZardButtonComponent } from '@shared/components/button/button.component';
import { Course as CourseType } from 'src/app/core/interfaces/course';
import { SortDir } from '@shared/paging/paging';
import { CourseService } from 'src/app/core/services/course';
import { CourseApiResponse, CourseService } from 'src/app/core/services/course';
import { ResultatService } from 'src/app/core/services/resultat';
import { Resultat } from 'src/app/core/interfaces/resultat';
import { A11yModule } from '@angular/cdk/a11y';
@@ -77,23 +77,19 @@ export class Course {
key: 'type',
label: 'Type',
sortable: true,
cell: (c) => `<span class="font-medium">${c.type}</span>`,
cell: (c) => `<span class="font-medium">${c.discipline}</span>`,
},
{
key: 'dateDepartCourse',
label: 'Date et Heure Départ',
sortable: true,
cell: (c) =>
new Date(c.dateDepartCourse).toLocaleDateString('fr-FR', {
hour: '2-digit',
minute: '2-digit',
}),
cell: (c) => c.heureDepartPrevue
},
{
key: 'partants',
label: 'Partants',
cell: (c) =>
`<span>${c.partants}</span> <span class="text-xs text-red-500">(${
`<span>${c.nombrePartants}</span> <span class="text-xs text-red-500">(${
c.nonPartants?.length ?? 0
} NP)</span>`,
},
@@ -148,20 +144,24 @@ export class Course {
sortable: true,
cell: (c) => {
const colorMap: Record<string, string> = {
PROGRAMMEE: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300',
CREATED: 'bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-300',
VALIDATED: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300',
RUNNING: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
CLOSED: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300',
CANCELED: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300',
OUVERT: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300',
RESULTAT_PROVISOIRE: 'bg-cyan-100 text-purple-700 dark:bg-cyan-900/30 dark:text-cyan-300',
RESULTAT_OFFICIEL: 'bg-amber-100 text-purple-700 dark:bg-amber-900/30 dark:text-amber-300',
BROUILLON: 'bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-300',
VALIDE: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300',
REGLEE: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
FERME: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300',
ANNULEE: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300',
};
const labelMap: Record<string, string> = {
PROGRAMMEE: 'Programmée',
CREATED: 'Créée',
VALIDATED: 'Validée',
RUNNING: 'En cours',
CLOSED: 'Clôturée',
CANCELED: 'Annulée',
OUVERT: 'Ouvert',
RESULTAT_PROVISOIRE: 'Résultat provisoire',
RESULTAT_OFFICIEL: 'Résultat officiel',
BROUILLON: 'Brouillon',
VALIDE: 'Validé',
REGLEE: 'Réglée',
FERME: 'Fermé',
ANNULEE: 'Annulée'
};
return `<span class="px-2 py-1 rounded-full text-xs font-semibold ${colorMap[c.statut]}">${
labelMap[c.statut]
@@ -171,31 +171,13 @@ export class Course {
{
key: 'reunion.hippodrome.nom',
label: 'Hippodrome',
cell: (c) => (c.reunion?.hippodrome ? `${c.reunion.hippodrome.nom}` : '—'),
},
{
key: 'reunion.nom',
label: 'Réunion',
cell: (c) => c.reunion?.nom ?? '—',
cell: (c) => (c?.hippodrome ? `${c.hippodrome.nom}` : '—'),
},
{
key: 'distance',
label: 'Distance (m)',
sortable: true,
cell: (c) => c.distance.toLocaleString('fr-FR'),
},
{
key: 'createdAt',
label: 'Créée le',
cell: (c) =>
c.createdAt
? new Date(c.createdAt).toLocaleDateString('fr-FR', {
day: '2-digit',
month: 'short',
year: 'numeric',
})
: '—',
cell: (c) => c.distanceMetres.toLocaleString('fr-FR'),
},
];
@@ -224,14 +206,14 @@ export class Course {
this.loading.set(true);
this.api.list(params).subscribe({
next: (res) => {
this.rows.set(res.data);
this.total.set(res.meta.total);
this.totalRunning.set(res.meta['totalRunning'] ?? 0);
this.totalClosed.set(res.meta['totalClosed'] ?? 0);
this.totalByType.set(res.meta['totalByType'] ?? {});
this.rows.set(res.content);
this.total.set(res.totalElements);
this.totalRunning.set(0);
this.totalClosed.set(0);
this.totalByType.set({});
// Fetch resultats for all courses in parallel
const courseIds = res.data.map((c) => c.id);
const courseIds = res.content.map((c) => c.id);
if (courseIds.length > 0) {
const resultatRequests = courseIds.map((id) =>
this.resultatService.getByCourseId(id).pipe(catchError(() => of(undefined)))
@@ -305,7 +287,7 @@ export class Course {
const current = this.editingItem();
const req$ = current?.id
? this.api.update(current.id, payload)
: this.api.create(payload as Omit<CourseType, 'id'>);
: this.api.create(payload as Omit<CourseApiResponse, 'id'>);
req$.subscribe(() => {
this.closeModal();
@@ -412,7 +394,7 @@ export class Course {
return 3; // Default
};
const requiredHorses = getRequiredHorses(c.type);
const requiredHorses = 3;
// Collect all selected horses (flatten the places array)
const allHorses: number[] = places

View File

@@ -33,18 +33,6 @@
{{ averageByCountry() }}
</div>
</z-card>
<z-card class="text-center py-4">
<div class="text-sm text-gray-500 dark:text-gray-400">Réunions totales</div>
<div class="text-3xl font-bold text-purple-600 dark:text-purple-400 mt-1">
{{ totalReunions() }}
</div>
</z-card>
<z-card class="text-center py-4">
<div class="text-sm text-gray-500 dark:text-gray-400">Courses totales</div>
<div class="text-3xl font-bold text-pink-600 dark:text-pink-400 mt-1">
{{ totalCourses() }}
</div>
</z-card>
</div>
<app-search-bar placeholder="Rechercher (nom, ville, pays…)" (search)="onSearch($event)" />

View File

@@ -58,18 +58,6 @@ export class Hippodrome {
{ key: 'nom', label: 'Nom', sortable: true },
{ key: 'ville', label: 'Ville', sortable: true },
{ key: 'pays', label: 'Pays', sortable: true },
{
key: 'reunionCount',
label: 'Réunions',
sortable: true,
cell: (h) => (h.reunionCount ?? 0).toString(),
},
{
key: 'courseCount',
label: 'Courses',
sortable: true,
cell: (h) => (h.courseCount ?? 0).toString(),
},
{
key: 'capacite',
label: 'Capacité',
@@ -124,26 +112,20 @@ export class Hippodrome {
})
.subscribe({
next: (res) => {
this.rows.set(res.data);
const meta = res.meta ?? {};
this.total.set(meta['total'] ?? 0);
this.uniqueCities.set(meta['uniqueCities'] ?? 0);
this.uniqueCountries.set(meta['uniqueCountries'] ?? 0);
this.averageByCountry.set(meta['averageByCountry'] ?? 0);
this.totalReunions.set(meta['totalReunions'] ?? 0);
this.totalCourses.set(meta['totalCourses'] ?? 0);
const content = res.content;
this.rows.set(content);
this.total.set(res.pageable.total ?? 0);
this.uniqueCities.set(new Set(content.map(i=> i.ville)).size);
this.uniqueCountries.set(new Set(content.map(i=>i.pays)).size);
this.averageByCountry.set(0);
this.loading.set(false);
},
error: () => {
error: (err) => {
this.rows.set([]);
this.total.set(0);
this.uniqueCities.set(0);
this.uniqueCountries.set(0);
this.averageByCountry.set(0);
this.totalReunions.set(0);
this.totalCourses.set(0);
this.loading.set(false);
},
});

View File

@@ -127,7 +127,7 @@ export class LimitsPage implements OnInit {
}).pipe(
switchMap((res) => {
// Convert PagedResult to array for consistency
return of(res.data);
return of(res.content);
})
);
}
@@ -190,8 +190,8 @@ export class LimitsPage implements OnInit {
// Normal list with pagination
this.api.list(params).subscribe({
next: (res) => {
this.rows.set(res.data);
this.total.set(res.meta.total);
this.rows.set(res.content);
this.total.set(res.pageable.total);
this.loading.set(false);
},
error: () => {

View File

@@ -34,11 +34,11 @@
<span class="font-medium text-gray-900 dark:text-gray-100 truncate">
{{ c.nom }}
</span>
@if (c.type) {
@if (c.discipline) {
<span
class="inline-flex items-center px-2 py-0.5 rounded text-[10px] font-medium bg-indigo-50 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-300"
>
{{ c.type }}
{{ c.discipline }}
</span>
}
</div>
@@ -61,19 +61,15 @@
></path>
</svg>
{{
c.dateDepartCourse
? (c.dateDepartCourse | date : 'short' : undefined : 'fr-FR')
: '—'
c.heureDepartPrevue
}}
</span>
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
<span class="font-medium">
{{ c.reunion.hippodrome.nom }}
{{ c.nom }}
</span>
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
<span> Réunion {{ c.reunion.nom }} </span>
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
<span> Distance {{ c.distance | number : '1.0-0' }} m </span>
<span> Distance {{ c.distanceMetres | number : '1.0-0' }} m </span>
</div>
<div
class="flex flex-wrap items-center gap-2 text-[11px] text-gray-600 dark:text-gray-300"
@@ -93,19 +89,19 @@
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
></path>
</svg>
{{ c.partants }} partant{{ c.partants > 1 ? 's' : '' }}
{{ c.nombrePartants }} partant{{ c.nombrePartants > 1 ? 's' : '' }}
</span>
@if (c.nonPartants && c.nonPartants.length > 0) {
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
<span class="text-orange-600 dark:text-orange-400">
{{ c.nonPartants.length }} non-partant{{ c.nonPartants.length > 1 ? 's' : '' }}
</span>
} @if (c.condition) {
} @if (c.numero) {
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
<span class="italic">{{ c.condition }}</span>
} @if (c.particularite) {
<span class="italic">{{ c.numero }}</span>
} @if (c.discipline) {
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
<span class="text-blue-600 dark:text-blue-400">⭐ {{ c.particularite }}</span>
<span class="text-blue-600 dark:text-blue-400">⭐ {{ c.discipline }}</span>
}
</div>
</div>

View File

@@ -223,26 +223,21 @@ export class Main {
// Include PROGRAMMEE courses that are scheduled within the next 24 hours
if (statut === 'PROGRAMMEE') {
const d = c.dateDepartCourse ? new Date(c.dateDepartCourse) : null;
const d = c.heureDepartPrevue ? c.heureDepartPrevue : null;
if (!d) return false;
// Include if departure is in the past hour (just started) or within next 24 hours
return d >= oneHourAgo && d <= oneDayAhead;
return d ;
}
// Also include VALIDATED courses that are about to start (within next 24 hours)
if (statut === 'VALIDATED') {
const d = c.dateDepartCourse ? new Date(c.dateDepartCourse) : null;
const d = c.heureDepartPrevue ? c.heureDepartPrevue : null;
if (!d) return false;
return d >= now && d <= oneDayAhead;
return d;
}
return false;
})
.sort((a, b) => {
const da = a.dateDepartCourse ? new Date(a.dateDepartCourse).getTime() : 0;
const db = b.dateDepartCourse ? new Date(b.dateDepartCourse).getTime() : 0;
return da - db; // Sort by departure time ascending (earliest first)
})
.slice(0, 6);
this.liveCourses.set(live);

View File

@@ -1,132 +1,132 @@
import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { ActivatedRoute, RouterModule } from '@angular/router';
import { ZardCardComponent } from '@shared/components/card/card.component';
import { ReportService } from 'src/app/core/services/report';
import { CourseReportDetail, CourseReportDetailRow } from 'src/app/core/interfaces/report';
import { ZardButtonComponent } from '@shared/components/button/button.component';
// import { CommonModule } from '@angular/common';
// import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
// import { ActivatedRoute, RouterModule } from '@angular/router';
// import { ZardCardComponent } from '@shared/components/card/card.component';
// import { ReportService } from 'src/app/core/services/report';
// import { CourseReportDetail, CourseReportDetailRow } from 'src/app/core/interfaces/report';
// import { ZardButtonComponent } from '@shared/components/button/button.component';
@Component({
standalone: true,
selector: 'app-report-courses-detail',
templateUrl: './report-detail.html',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule, RouterModule, ZardCardComponent, ZardButtonComponent],
})
export class ReportCoursesDetailPage {
detail = signal<CourseReportDetail | undefined>(undefined);
editMode = signal(false);
editedRows = signal<CourseReportDetailRow[]>([]);
private originalRows = signal<CourseReportDetailRow[]>([]);
// @Component({
// standalone: true,
// selector: 'app-report-courses-detail',
// templateUrl: './report-detail.html',
// changeDetection: ChangeDetectionStrategy.OnPush,
// imports: [CommonModule, RouterModule, ZardCardComponent, ZardButtonComponent],
// })
// export class ReportCoursesDetailPage {
// detail = signal<CourseReportDetail | undefined>(undefined);
// editMode = signal(false);
// editedRows = signal<CourseReportDetailRow[]>([]);
// private originalRows = signal<CourseReportDetailRow[]>([]);
constructor(private route: ActivatedRoute, private api: ReportService) {
const id = this.route.snapshot.params['id'];
this.api.getDetail(id).subscribe((d) => {
this.detail.set(d);
this.editedRows.set(d?.rows ?? []);
this.originalRows.set(d?.rows ? d.rows.map((r) => ({ ...r })) : []);
});
}
// constructor(private route: ActivatedRoute, private api: ReportService) {
// const id = this.route.snapshot.params['id'];
// this.api.getDetail(id).subscribe((d) => {
// this.detail.set(d);
// this.editedRows.set(d?.rows ?? []);
// this.originalRows.set(d?.rows ? d.rows.map((r) => ({ ...r })) : []);
// });
// }
onValidate() {
const id = this.detail()?.summary.id;
if (!id) return;
// Persist edited rows then validate
this.api.modifyRows(id, this.editedRows()).subscribe(() => {
this.api.validate(id).subscribe((s) => {
if (this.detail()) this.detail.set({ summary: s!, rows: this.editedRows() });
// Commit current edits as the new baseline
this.originalRows.set(this.editedRows().map((r) => ({ ...r })));
this.editMode.set(false);
});
});
}
onConfirm() {
const id = this.detail()?.summary.id;
if (!id) return;
this.api.confirm(id).subscribe((s) => {
if (this.detail()) this.detail.set({ summary: s!, rows: this.editedRows() });
// Confirm also commits the current edits as baseline
this.originalRows.set(this.editedRows().map((r) => ({ ...r })));
this.editMode.set(false);
});
}
onReset() {
const id = this.detail()?.summary.id;
if (!id) return;
this.api.resetStatus(id).subscribe((s) => {
if (this.detail()) this.detail.set({ summary: s!, rows: this.detail()!.rows });
// Reset discards uncommitted edits
this.editedRows.set(this.originalRows().map((r) => ({ ...r })));
this.editMode.set(false);
});
}
// onValidate() {
// const id = this.detail()?.summary.id;
// if (!id) return;
// // Persist edited rows then validate
// this.api.modifyRows(id, this.editedRows()).subscribe(() => {
// this.api.validate(id).subscribe((s) => {
// if (this.detail()) this.detail.set({ summary: s!, rows: this.editedRows() });
// // Commit current edits as the new baseline
// this.originalRows.set(this.editedRows().map((r) => ({ ...r })));
// this.editMode.set(false);
// });
// });
// }
// onConfirm() {
// const id = this.detail()?.summary.id;
// if (!id) return;
// this.api.confirm(id).subscribe((s) => {
// if (this.detail()) this.detail.set({ summary: s!, rows: this.editedRows() });
// // Confirm also commits the current edits as baseline
// this.originalRows.set(this.editedRows().map((r) => ({ ...r })));
// this.editMode.set(false);
// });
// }
// onReset() {
// const id = this.detail()?.summary.id;
// if (!id) return;
// this.api.resetStatus(id).subscribe((s) => {
// if (this.detail()) this.detail.set({ summary: s!, rows: this.detail()!.rows });
// // Reset discards uncommitted edits
// this.editedRows.set(this.originalRows().map((r) => ({ ...r })));
// this.editMode.set(false);
// });
// }
onEditToggle() {
if (this.detail()?.summary.confirmed) return;
const currentlyEditing = this.editMode();
if (currentlyEditing) {
// Leaving edit mode without validation: revert to original snapshot
this.editedRows.set(this.originalRows().map((r) => ({ ...r })));
this.editMode.set(false);
} else {
this.editMode.set(true);
}
}
// onEditToggle() {
// if (this.detail()?.summary.confirmed) return;
// const currentlyEditing = this.editMode();
// if (currentlyEditing) {
// // Leaving edit mode without validation: revert to original snapshot
// this.editedRows.set(this.originalRows().map((r) => ({ ...r })));
// this.editMode.set(false);
// } else {
// this.editMode.set(true);
// }
// }
onChangeMontant(index: number, value: any) {
const v = Number(value);
this.editedRows.update((rows: CourseReportDetailRow[]) => {
const current = rows[index];
if (!current) return rows;
current.montant = Number.isFinite(v) ? v : current.montant;
return rows;
});
}
// onChangeMontant(index: number, value: any) {
// const v = Number(value);
// this.editedRows.update((rows: CourseReportDetailRow[]) => {
// const current = rows[index];
// if (!current) return rows;
// current.montant = Number.isFinite(v) ? v : current.montant;
// return rows;
// });
// }
onChangeNombre(index: number, value: any) {
const v = Number(value);
this.editedRows.update((rows: CourseReportDetailRow[]) => {
const current = rows[index];
if (!current) return rows;
current.nombre = Number.isFinite(v) ? v : current.nombre;
return rows;
});
}
// onChangeNombre(index: number, value: any) {
// const v = Number(value);
// this.editedRows.update((rows: CourseReportDetailRow[]) => {
// const current = rows[index];
// if (!current) return rows;
// current.nombre = Number.isFinite(v) ? v : current.nombre;
// return rows;
// });
// }
onToggleDistributed(index: number, value: any) {
const checked = !!value;
this.editedRows.update((rows: CourseReportDetailRow[]) => {
const current = rows[index];
if (!current) return rows;
current.distributed = checked;
return rows;
});
}
// onToggleDistributed(index: number, value: any) {
// const checked = !!value;
// this.editedRows.update((rows: CourseReportDetailRow[]) => {
// const current = rows[index];
// if (!current) return rows;
// current.distributed = checked;
// return rows;
// });
// }
onToggleExterne(index: number, value: any) {
const checked = !!value;
this.editedRows.update((rows: CourseReportDetailRow[]) => {
const current = rows[index];
if (!current) return rows;
current.externe = checked;
return rows;
});
}
// onToggleExterne(index: number, value: any) {
// const checked = !!value;
// this.editedRows.update((rows: CourseReportDetailRow[]) => {
// const current = rows[index];
// if (!current) return rows;
// current.externe = checked;
// return rows;
// });
// }
trackByRow(index: number, row: CourseReportDetailRow) {
return row.typeGain + '|' + row.typeJeu + '|' + index;
}
// trackByRow(index: number, row: CourseReportDetailRow) {
// return row.typeGain + '|' + row.typeJeu + '|' + index;
// }
isRowDirty(index: number): boolean {
const current = this.editedRows()[index];
const original = this.originalRows()[index];
if (!current || !original) return false;
return (
current.montant !== original.montant ||
current.nombre !== original.nombre ||
!!current.distributed !== !!original.distributed ||
!!current.externe !== !!original.externe
);
}
}
// isRowDirty(index: number): boolean {
// const current = this.editedRows()[index];
// const original = this.originalRows()[index];
// if (!current || !original) return false;
// return (
// current.montant !== original.montant ||
// current.nombre !== original.nombre ||
// !!current.distributed !== !!original.distributed ||
// !!current.externe !== !!original.externe
// );
// }
// }

View File

@@ -1,61 +1,61 @@
import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, signal, effect, untracked } from '@angular/core';
import { DataTable, SortState, TableColumn } from '@shared/components/data-table/data-table';
import { Paginator } from '@shared/components/paginator/paginator';
import { SearchBar } from '@shared/components/search-bar/search-bar';
import { ZardButtonComponent } from '@shared/components/button/button.component';
import { SortDir } from '@shared/paging/paging';
import { Router } from '@angular/router';
import { CourseReportSummary } from 'src/app/core/interfaces/report';
import { ReportService } from 'src/app/core/services/report';
// import { CommonModule } from '@angular/common';
// import { ChangeDetectionStrategy, Component, signal, effect, untracked } from '@angular/core';
// import { DataTable, SortState, TableColumn } from '@shared/components/data-table/data-table';
// import { Paginator } from '@shared/components/paginator/paginator';
// import { SearchBar } from '@shared/components/search-bar/search-bar';
// import { ZardButtonComponent } from '@shared/components/button/button.component';
// import { SortDir } from '@shared/paging/paging';
// import { Router } from '@angular/router';
// import { CourseReportSummary } from 'src/app/core/interfaces/report';
// import { ReportService } from 'src/app/core/services/report';
@Component({
standalone: true,
selector: 'app-report-courses-list',
templateUrl: './report-list.html',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule, DataTable, Paginator, SearchBar, ZardButtonComponent],
})
export class ReportCoursesListPage {
rows = signal<CourseReportSummary[]>([]);
total = signal(0);
page = signal(1);
perPage = signal(10);
search = signal('');
sort = signal<SortState>({ key: 'date', dir: 'desc' });
loading = signal(false);
// @Component({
// standalone: true,
// selector: 'app-report-courses-list',
// templateUrl: './report-list.html',
// changeDetection: ChangeDetectionStrategy.OnPush,
// imports: [CommonModule, DataTable, Paginator, SearchBar, ZardButtonComponent],
// })
// export class ReportCoursesListPage {
// rows = signal<CourseReportSummary[]>([]);
// total = signal(0);
// page = signal(1);
// perPage = signal(10);
// search = signal('');
// sort = signal<SortState>({ key: 'date', dir: 'desc' });
// loading = signal(false);
cols: TableColumn<CourseReportSummary>[] = [
{ key: 'course.dateDepartCourse', label: 'Date', sortable: true },
{ key: 'course.numero', label: 'Numéro', sortable: true },
{ key: 'course.nom', label: 'Nom', sortable: true },
{ key: 'course.type', label: 'Type', sortable: true },
{ key: 'course.reunion.hippodrome.nom', label: 'Lieu', sortable: true },
{ key: 'course.particularite', label: 'Particularité' },
{ key: 'statut', label: 'Statut', sortable: true },
];
// cols: TableColumn<CourseReportSummary>[] = [
// { key: 'course.dateDepartCourse', label: 'Date', sortable: true },
// { key: 'course.numero', label: 'Numéro', sortable: true },
// { key: 'course.nom', label: 'Nom', sortable: true },
// { key: 'course.type', label: 'Type', sortable: true },
// { key: 'course.reunion.hippodrome.nom', label: 'Lieu', sortable: true },
// { key: 'course.particularite', label: 'Particularité' },
// { key: 'statut', label: 'Statut', sortable: true },
// ];
constructor(private api: ReportService, private router: Router) {
effect(() => {
const params = { page: this.page(), perPage: this.perPage(), search: this.search(), sortKey: this.sort().key, sortDir: this.sort().dir as SortDir };
untracked(() => this.fetch(params));
});
}
// constructor(private api: ReportService, private router: Router) {
// effect(() => {
// const params = { page: this.page(), perPage: this.perPage(), search: this.search(), sortKey: this.sort().key, sortDir: this.sort().dir as SortDir };
// untracked(() => this.fetch(params));
// });
// }
fetch(params: { page: number; perPage: number; search: string; sortKey: string; sortDir: SortDir }) {
this.loading.set(true);
this.api.list(params).subscribe((res) => {
this.rows.set(res.data);
this.total.set(res.meta.total);
this.loading.set(false);
});
}
// fetch(params: { page: number; perPage: number; search: string; sortKey: string; sortDir: SortDir }) {
// this.loading.set(true);
// this.api.list(params).subscribe((res) => {
// this.rows.set(res.content);
// this.total.set(res.pageable.total);
// this.loading.set(false);
// });
// }
onSearch(q: string) { this.search.set(q); this.page.set(1); }
// onSearch(q: string) { this.search.set(q); this.page.set(1); }
open(row: CourseReportSummary) {
this.router.navigate(['/rapport-courses', row.id]);
}
}
// open(row: CourseReportSummary) {
// this.router.navigate(['/rapport-courses', row.id]);
// }
// }

View File

@@ -153,13 +153,13 @@ export class ReunionList {
this.loading.set(true);
this.api.list(params).subscribe({
next: (res) => {
this.rows.set(res.data);
this.total.set(res.meta.total);
const meta = res.meta;
this.rows.set(res.content);
this.total.set(res.pageable.total);
const meta = res.pageable;
this.upcomingReunions.set(res.meta['upcomingReunions'] ?? 0);
this.pastReunions.set(res.meta['pastReunions'] ?? 0);
this.uniqueHippodromes.set(res.meta['uniqueHippodromes'] ?? 0);
this.upcomingReunions.set(0);
this.pastReunions.set(0);
this.uniqueHippodromes.set(0);
this.loading.set(false);
},
error: () => {

View File

@@ -84,8 +84,8 @@ export class RolesPage {
this.loading.set(true);
this.api.list(params).subscribe({
next: (res) => {
this.rows.set(res.data);
this.total.set(res.meta.total);
this.rows.set(res.content);
this.total.set(res.pageable.total);
this.loading.set(false);
},
error: () => {

View File

@@ -191,8 +191,8 @@ export class TpePage implements OnInit {
this.total.set(res.length);
} else {
// List returns PagedResult
this.rows.set(res.data);
this.total.set(res.meta.total);
this.rows.set(res.content);
this.total.set(res.pageable.total);
}
this.loading.set(false);
},
@@ -281,8 +281,8 @@ export class TpePage implements OnInit {
// Normal list with pagination
this.api.list(params).subscribe({
next: (res) => {
this.rows.set(res.data);
this.total.set(res.meta.total);
this.rows.set(res.content);
this.total.set(res.pageable.total);
this.loading.set(false);
},
error: () => {

View File

@@ -79,7 +79,7 @@ export class UsersPage {
constructor(private api: UserService, private roleService: RoleService) {
this.roleService
.list({ page: 1, perPage: 100, search: '', sortKey: 'name', sortDir: 'asc' } as any)
.subscribe((res) => (res.data as Role[]).forEach((r) => this.roleMap.set(r.id, r.name)));
.subscribe((res) => (res.content as Role[]).forEach((r) => this.roleMap.set(r.id, r.name)));
effect(() => {
const params = {
page: this.page(),
@@ -102,8 +102,8 @@ export class UsersPage {
this.loading.set(true);
this.api.list(params).subscribe({
next: (res) => {
this.rows.set(res.data);
this.total.set(res.meta.total);
this.rows.set(res.content);
this.total.set(res.pageable.total);
this.loading.set(false);
},
error: () => {