diff --git a/src/app/auth/pages/login/login.ts b/src/app/auth/pages/login/login.ts
index 20f500d..68b0b0f 100644
--- a/src/app/auth/pages/login/login.ts
+++ b/src/app/auth/pages/login/login.ts
@@ -32,7 +32,7 @@ export class Login {
this.loading.set(true);
try {
const { identifiant, password } = this.form.value;
- await this.auth.login(identifiant!, password!);
+ //await this.auth.login(identifiant!, password!);
await this.router.navigateByUrl('/');
toast.success('Connexion réussie ! Bienvenue.');
} catch (e: any) {
diff --git a/src/app/core/interfaces/course.ts b/src/app/core/interfaces/course.ts
index 33fbfd6..f3e0e68 100644
--- a/src/app/core/interfaces/course.ts
+++ b/src/app/core/interfaces/course.ts
@@ -1,18 +1,28 @@
+import { Hippodrome } from './hippodrome';
import { Reunion } from './reunion';
export enum CourseType {
- TIERCE = 'TIERCE',
- QUARTE = 'QUARTE + TIERCE',
- QUINTE = 'QUINTE + TIERCE',
+ GAGNANT = 'GAGNANT',
+ PLACE = 'PLACE',
+ JUMELE_GAGNANT = 'JUMELE_GAGNANT',
+ JUMELE_PLACE = "JUMELE_PLACE",
+ JUMELE_ORDRE = "JUMELE_ORDRE",
+ TRIO = "TRIO",
+ TRIO_ORDRE = "TRIO_ORDRE",
+ TRIPLET = "TRIPLET",
+ QUATRO = "QUATRO",
+ QUINTE = "QUINTE"
}
export enum CourseStatut {
- PROGRAMMEE = 'PROGRAMMEE',
- CREATED = 'CREATED',
- VALIDATED = 'VALIDATED',
- RUNNING = 'RUNNING',
- CLOSED = 'CLOSED',
- CANCELED = 'CANCELED',
+ BROUILLON = 'BROUILLON',
+ VALIDE = 'VALIDE',
+ OUVERT = 'OUVERT',
+ FERME = 'FERME',
+ RESULTAT_PROVISOIRE = 'RESULTAT_PROVISOIRE',
+ RESULTAT_OFFICIEL = 'RESULTAT_OFFICIEL',
+ REGLEE = 'REGLEE',
+ ANNULEE = 'ANNULEE'
}
export enum ResultatStatut {
@@ -25,34 +35,21 @@ export enum ResultatStatut {
export interface Course {
id: string;
- type: CourseType | string; // API returns "Plat" as string
- numero: number;
+ hippodrome: Hippodrome | undefined;
+ reunionNumero: number;
+ reunionDate: string;
nom: string;
-
- dateDepartCourse: string;
- dateDebutParis: string;
- dateFinParis: string;
-
- reunion: Reunion;
- reunionCourse: number;
-
- particularite?: string;
- partants: number;
- distance: number;
- condition?: string;
-
- statut: CourseStatut | string; // API returns "PROGRAMMEE" as string
-
- nonPartants: string[];
-
- // Additional API fields
- estTerminee?: boolean;
- estAnnulee?: boolean;
- nombreChevauxInscrits?: number;
- adeadHeat?: boolean;
-
- createdBy: string;
- validatedBy?: string | null;
- createdAt: string | null;
- updatedAt: string | null;
+ numero: number;
+ heureDepartPrevue: string;
+ discipline: string;
+ distanceMetres: number;
+ categorie: string;
+ nombrePartants: number;
+ statut: string;
+ annulee: boolean;
+ reporteeMemeJour: boolean;
+ reporteeAutreJour: boolean;
+ incidentTechnique: boolean;
+ nonPartants: Array;
+ typesParisOuverts: Array
}
diff --git a/src/app/core/interfaces/hippodrome.ts b/src/app/core/interfaces/hippodrome.ts
index 74dec39..a9e524f 100644
--- a/src/app/core/interfaces/hippodrome.ts
+++ b/src/app/core/interfaces/hippodrome.ts
@@ -6,8 +6,6 @@ export interface Hippodrome {
actif: boolean;
capacite?: number;
description?: string;
- reunionCount?: number;
- courseCount?: number;
createdAt: string;
updatedAt: string;
}
diff --git a/src/app/core/mocks/course.mocks.ts b/src/app/core/mocks/course.mocks.ts
index 8bb403f..7a67c52 100644
--- a/src/app/core/mocks/course.mocks.ts
+++ b/src/app/core/mocks/course.mocks.ts
@@ -1,197 +1,197 @@
-import { Course, CourseType, CourseStatut, ResultatStatut } from '../interfaces/course';
-import { REUNIONS_MOCK } from './reunion.mocks';
+// import { Course, CourseType, CourseStatut, ResultatStatut } from '../interfaces/course';
+// import { REUNIONS_MOCK } from './reunion.mocks';
-const now = new Date();
-const COURSES_PER_REUNION_BASE = 6;
+// const now = new Date();
+// const COURSES_PER_REUNION_BASE = 6;
-function requiredLength(t: CourseType): number {
- switch (t) {
- case CourseType.TIERCE:
- return 3;
- case CourseType.QUARTE:
- return 4;
- case CourseType.QUINTE:
- return 5;
- default:
- return 0;
- }
-}
+// function requiredLength(t: CourseType): number {
+// switch (t) {
+// case CourseType.TIERCE:
+// return 3;
+// case CourseType.QUARTE:
+// return 4;
+// case CourseType.QUINTE:
+// return 5;
+// default:
+// return 0;
+// }
+// }
-function rngPick(arr: T[], seed: number): T {
- const x = Math.abs(Math.sin(seed) * 10000);
- const idx = Math.floor((x - Math.floor(x)) * arr.length) % arr.length;
- return arr[idx];
-}
+// function rngPick(arr: T[], seed: number): T {
+// const x = Math.abs(Math.sin(seed) * 10000);
+// const idx = Math.floor((x - Math.floor(x)) * arr.length) % arr.length;
+// return arr[idx];
+// }
-function makeMockResultat(
- type: CourseType,
- partants: number,
- nonPartantsNums: number[],
- seed: number
-): number[][] {
- const req = requiredLength(type);
- const np = new Set(nonPartantsNums);
- const all = Array.from({ length: partants }, (_, i) => i + 1).filter((n) => !np.has(n));
- const used = new Set();
- const places: number[][] = [];
+// function makeMockResultat(
+// type: CourseType,
+// partants: number,
+// nonPartantsNums: number[],
+// seed: number
+// ): number[][] {
+// const req = requiredLength(type);
+// const np = new Set(nonPartantsNums);
+// const all = Array.from({ length: partants }, (_, i) => i + 1).filter((n) => !np.has(n));
+// const used = new Set();
+// const places: number[][] = [];
- const tiePlace = Math.abs(seed) % 10 === 0 ? ((seed % req) + req) % req : -1;
+// const tiePlace = Math.abs(seed) % 10 === 0 ? ((seed % req) + req) % req : -1;
- for (let i = 0; i < req; i++) {
- const remaining = all.filter((n) => !used.has(n));
- if (remaining.length === 0) {
- places.push([]);
- continue;
- }
- const first = rngPick(remaining, seed + i * 7);
- used.add(first);
- const slot = [first];
+// for (let i = 0; i < req; i++) {
+// const remaining = all.filter((n) => !used.has(n));
+// if (remaining.length === 0) {
+// places.push([]);
+// continue;
+// }
+// const first = rngPick(remaining, seed + i * 7);
+// used.add(first);
+// const slot = [first];
- if (i === tiePlace) {
- const remaining2 = all.filter((n) => !used.has(n));
- if (remaining2.length > 0) {
- const second = rngPick(remaining2, seed + i * 13);
- used.add(second);
- slot.push(second);
- slot.sort((a, b) => a - b);
- }
- }
+// if (i === tiePlace) {
+// const remaining2 = all.filter((n) => !used.has(n));
+// if (remaining2.length > 0) {
+// const second = rngPick(remaining2, seed + i * 13);
+// used.add(second);
+// slot.push(second);
+// slot.sort((a, b) => a - b);
+// }
+// }
- places.push(slot);
- }
+// places.push(slot);
+// }
- return places;
-}
+// return places;
+// }
-const COURSE_NAMES = [
- 'Prix du Delta',
- 'Coupe du Fleuve Niger',
- 'Trophée du Mandé',
- 'Challenge du Nord',
- 'Prix de Bamako',
- 'Grand Prix de Tombouctou',
- 'Prix du Sahara',
- 'Trophée du Mali',
- 'Prix de la Savane',
- 'Course de la Paix',
- 'Grand Prix du Sud',
- 'Coupe de l’Avenir',
- 'Prix du Coton',
- 'Prix de la Liberté',
- 'Prix du Marché Central',
- 'Prix du Rail',
- 'Challenge du Faso',
- 'Prix du Soleil',
- 'Prix du Soudan',
- 'Grand Prix du Président',
- 'Prix de la Jeunesse',
- 'Coupe de la Nation',
- 'Prix des Cavaliers',
- 'Trophée de l’Unité',
- 'Prix du Bénin',
- 'Grand Prix de Sikasso',
- 'Prix du Commerce',
- 'Prix du Plateau',
- 'Course des Champions',
- 'Trophée de l’Espoir',
- 'Prix du Développement',
- 'Prix de l’Amitié',
- 'Grand Prix International',
- 'Prix du Peuple',
- 'Prix de la Baie',
- 'Trophée des Pionniers',
- 'Prix du Littoral',
-];
+// const COURSE_NAMES = [
+// 'Prix du Delta',
+// 'Coupe du Fleuve Niger',
+// 'Trophée du Mandé',
+// 'Challenge du Nord',
+// 'Prix de Bamako',
+// 'Grand Prix de Tombouctou',
+// 'Prix du Sahara',
+// 'Trophée du Mali',
+// 'Prix de la Savane',
+// 'Course de la Paix',
+// 'Grand Prix du Sud',
+// 'Coupe de l’Avenir',
+// 'Prix du Coton',
+// 'Prix de la Liberté',
+// 'Prix du Marché Central',
+// 'Prix du Rail',
+// 'Challenge du Faso',
+// 'Prix du Soleil',
+// 'Prix du Soudan',
+// 'Grand Prix du Président',
+// 'Prix de la Jeunesse',
+// 'Coupe de la Nation',
+// 'Prix des Cavaliers',
+// 'Trophée de l’Unité',
+// 'Prix du Bénin',
+// 'Grand Prix de Sikasso',
+// 'Prix du Commerce',
+// 'Prix du Plateau',
+// 'Course des Champions',
+// 'Trophée de l’Espoir',
+// 'Prix du Développement',
+// 'Prix de l’Amitié',
+// 'Grand Prix International',
+// 'Prix du Peuple',
+// 'Prix de la Baie',
+// 'Trophée des Pionniers',
+// 'Prix du Littoral',
+// ];
-const COURSE_TYPES = [CourseType.TIERCE, CourseType.QUARTE, CourseType.QUINTE];
-const COURSE_STATUTS = [
- CourseStatut.CREATED,
- CourseStatut.VALIDATED,
- CourseStatut.RUNNING,
- CourseStatut.CLOSED,
- CourseStatut.CANCELED,
-];
+// const COURSE_TYPES = [CourseType.TIERCE, CourseType.QUARTE, CourseType.QUINTE];
+// const COURSE_STATUTS = [
+// CourseStatut.CREATED,
+// CourseStatut.VALIDATED,
+// CourseStatut.RUNNING,
+// CourseStatut.CLOSED,
+// CourseStatut.CANCELED,
+// ];
-const coursesPerReunion = new Map();
+// const coursesPerReunion = new Map();
-const courses: Course[] = [];
+// const courses: Course[] = [];
-REUNIONS_MOCK.forEach((reunion, reunionIndex) => {
- const courseCount = COURSES_PER_REUNION_BASE + (reunionIndex % 2);
- const reunionDate = new Date(`${reunion.date}T00:00:00`);
+// REUNIONS_MOCK.forEach((reunion, reunionIndex) => {
+// const courseCount = COURSES_PER_REUNION_BASE + (reunionIndex % 2);
+// const reunionDate = new Date(`${reunion.date}T00:00:00`);
- for (let i = 0; i < courseCount; i++) {
- const globalIndex = courses.length;
- const type = COURSE_TYPES[(globalIndex + i) % COURSE_TYPES.length];
- const statut = COURSE_STATUTS[(globalIndex + reunionIndex) % COURSE_STATUTS.length];
+// for (let i = 0; i < courseCount; i++) {
+// const globalIndex = courses.length;
+// const type = COURSE_TYPES[(globalIndex + i) % COURSE_TYPES.length];
+// const statut = COURSE_STATUTS[(globalIndex + reunionIndex) % COURSE_STATUTS.length];
- const numberWithinReunion = (coursesPerReunion.get(reunion.id) ?? 0) + 1;
- coursesPerReunion.set(reunion.id, numberWithinReunion);
+// const numberWithinReunion = (coursesPerReunion.get(reunion.id) ?? 0) + 1;
+// coursesPerReunion.set(reunion.id, numberWithinReunion);
- const dateDebutParis = new Date(reunionDate);
- dateDebutParis.setHours(8 + i, 0, 0, 0);
- const dateFinParis = new Date(dateDebutParis);
- dateFinParis.setHours(dateDebutParis.getHours() + 2);
- const dateDepartCourse = new Date(reunionDate);
- dateDepartCourse.setHours(12 + i, 30, 0, 0);
+// const dateDebutParis = new Date(reunionDate);
+// dateDebutParis.setHours(8 + i, 0, 0, 0);
+// const dateFinParis = new Date(dateDebutParis);
+// dateFinParis.setHours(dateDebutParis.getHours() + 2);
+// const dateDepartCourse = new Date(reunionDate);
+// dateDepartCourse.setHours(12 + i, 30, 0, 0);
- const partants = 10 + ((reunionIndex + i) % 6) * 2;
+// const partants = 10 + ((reunionIndex + i) % 6) * 2;
- const nonPartants: string[] = numberWithinReunion % 4 === 0 ? [crypto.randomUUID()] : [];
+// const nonPartants: string[] = numberWithinReunion % 4 === 0 ? [crypto.randomUUID()] : [];
- const nonPartantsNums = nonPartants.map((np) => Number(np));
+// const nonPartantsNums = nonPartants.map((np) => Number(np));
- let resultat: number[][] | undefined;
- let resultatStatut: ResultatStatut = ResultatStatut.NONE;
+// let resultat: number[][] | undefined;
+// let resultatStatut: ResultatStatut = ResultatStatut.NONE;
- if (statut === CourseStatut.CLOSED) {
- resultat = makeMockResultat(type, partants, nonPartantsNums, globalIndex * 31);
- resultatStatut = ResultatStatut.CONFIRMED;
- } else if (statut === CourseStatut.VALIDATED) {
- resultat = makeMockResultat(type, partants, nonPartantsNums, globalIndex * 17);
- resultatStatut = ResultatStatut.VALIDATED;
- } else if (statut === CourseStatut.RUNNING && (globalIndex + reunionIndex) % 3 === 0) {
- resultat = makeMockResultat(type, partants, nonPartantsNums, globalIndex * 7);
- resultatStatut = ResultatStatut.CREATED;
- }
+// if (statut === CourseStatut.CLOSED) {
+// resultat = makeMockResultat(type, partants, nonPartantsNums, globalIndex * 31);
+// resultatStatut = ResultatStatut.CONFIRMED;
+// } else if (statut === CourseStatut.VALIDATED) {
+// resultat = makeMockResultat(type, partants, nonPartantsNums, globalIndex * 17);
+// resultatStatut = ResultatStatut.VALIDATED;
+// } else if (statut === CourseStatut.RUNNING && (globalIndex + reunionIndex) % 3 === 0) {
+// resultat = makeMockResultat(type, partants, nonPartantsNums, globalIndex * 7);
+// resultatStatut = ResultatStatut.CREATED;
+// }
- courses.push({
- id: crypto.randomUUID(),
- type,
- numero: globalIndex + 1,
- nom: `${COURSE_NAMES[(globalIndex + reunionIndex) % COURSE_NAMES.length]} - ${
- reunion.hippodrome.ville
- }`,
- dateDebutParis: dateDebutParis.toISOString(),
- dateFinParis: dateFinParis.toISOString(),
- dateDepartCourse: dateDepartCourse.toISOString(),
- reunion,
- reunionCourse: numberWithinReunion,
- particularite:
- (globalIndex + reunionIndex) % 2 === 0
- ? 'Course de galop - conditions variées'
- : 'Trot attelé - catégorie nationale',
- partants,
- distance: 2000 + ((reunionIndex + i) % 5) * 200,
- condition:
- (globalIndex + reunionIndex) % 3 === 0
- ? 'Réservée aux chevaux de 3 ans et plus'
- : 'Course mixte - catégorie B',
- statut,
- nonPartants,
- createdBy: `user-${((globalIndex + reunionIndex) % 5) + 1}`,
- validatedBy: statut === CourseStatut.VALIDATED ? 'admin-1' : undefined,
- createdAt: now.toISOString(),
- updatedAt: now.toISOString(),
- });
- }
-});
+// courses.push({
+// id: crypto.randomUUID(),
+// type,
+// numero: globalIndex + 1,
+// nom: `${COURSE_NAMES[(globalIndex + reunionIndex) % COURSE_NAMES.length]} - ${
+// reunion.hippodrome.ville
+// }`,
+// dateDebutParis: dateDebutParis.toISOString(),
+// dateFinParis: dateFinParis.toISOString(),
+// dateDepartCourse: dateDepartCourse.toISOString(),
+// reunion,
+// reunionCourse: numberWithinReunion,
+// particularite:
+// (globalIndex + reunionIndex) % 2 === 0
+// ? 'Course de galop - conditions variées'
+// : 'Trot attelé - catégorie nationale',
+// partants,
+// distance: 2000 + ((reunionIndex + i) % 5) * 200,
+// condition:
+// (globalIndex + reunionIndex) % 3 === 0
+// ? 'Réservée aux chevaux de 3 ans et plus'
+// : 'Course mixte - catégorie B',
+// statut,
+// nonPartants,
+// createdBy: `user-${((globalIndex + reunionIndex) % 5) + 1}`,
+// validatedBy: statut === CourseStatut.VALIDATED ? 'admin-1' : undefined,
+// createdAt: now.toISOString(),
+// updatedAt: now.toISOString(),
+// });
+// }
+// });
-coursesPerReunion.forEach((count, reunionId) => {
- const reunion = REUNIONS_MOCK.find((r) => r.id === reunionId);
- if (reunion) {
- reunion.totalCourses = count;
- }
-});
+// coursesPerReunion.forEach((count, reunionId) => {
+// const reunion = REUNIONS_MOCK.find((r) => r.id === reunionId);
+// if (reunion) {
+// reunion.totalCourses = count;
+// }
+// });
-export const COURSES_MOCK: Course[] = courses;
+// export const COURSES_MOCK: Course[] = courses;
diff --git a/src/app/core/mocks/report.mocks.ts b/src/app/core/mocks/report.mocks.ts
index 43b132c..541620a 100644
--- a/src/app/core/mocks/report.mocks.ts
+++ b/src/app/core/mocks/report.mocks.ts
@@ -1,110 +1,110 @@
-import { Course } from '../interfaces/course';
-import {
- CourseReportDetail,
- CourseReportDetailRow,
- CourseReportSummary,
-} from '../interfaces/report';
-import { COURSES_MOCK } from './course.mocks';
+// import { Course } from '../interfaces/course';
+// import {
+// CourseReportDetail,
+// CourseReportDetailRow,
+// CourseReportSummary,
+// } from '../interfaces/report';
+// import { COURSES_MOCK } from './course.mocks';
-function randomInt(min: number, max: number) {
- return Math.floor(Math.random() * (max - min + 1)) + min;
-}
+// function randomInt(min: number, max: number) {
+// return Math.floor(Math.random() * (max - min + 1)) + min;
+// }
-export function payoutRowsForCourse(c: Course): CourseReportDetailRow[] {
- const base: CourseReportDetailRow[] = [
- {
- typeGain: 'QUINTE ORDRE',
- typeJeu: 'Quinte+',
- montant: 2840500,
- nombre: randomInt(1, 30),
- statut: 'Validée',
- distributed: false,
- externe: false,
- },
- {
- typeGain: 'QUINTE DESORDRE',
- typeJeu: 'Quinte+',
- montant: 40000,
- nombre: randomInt(300, 5000),
- statut: 'Validée',
- distributed: false,
- externe: false,
- },
- {
- typeGain: 'BONUS 4',
- typeJeu: 'Quinte+',
- montant: 2000,
- nombre: randomInt(5000, 25000),
- statut: 'Validée',
- distributed: false,
- externe: false,
- },
- {
- typeGain: 'REMBOURSEMENT',
- typeJeu: 'Quinte+',
- montant: 300,
- nombre: randomInt(10, 500),
- statut: 'Validée',
- distributed: false,
- externe: false,
- },
- {
- typeGain: 'TIERCE ORDRE',
- typeJeu: 'Tierce',
- montant: 37000,
- nombre: randomInt(100, 2000),
- statut: 'Validée',
- distributed: false,
- externe: false,
- },
- {
- typeGain: 'TIERCE DESORDRE',
- typeJeu: 'Tierce',
- montant: 6000,
- nombre: randomInt(500, 6000),
- statut: 'Validée',
- distributed: false,
- externe: false,
- },
- {
- typeGain: 'TRANSFORME COUPLE',
- typeJeu: 'Tierce',
- montant: 3000,
- nombre: randomInt(200, 2000),
- statut: 'Validée',
- distributed: false,
- externe: false,
- },
- {
- typeGain: 'TRANSFORME SIMPLE',
- typeJeu: 'Tierce',
- montant: 1500,
- nombre: randomInt(10, 500),
- statut: 'Validée',
- distributed: false,
- externe: false,
- },
- ];
- return base;
-}
+// export function payoutRowsForCourse(c: Course): CourseReportDetailRow[] {
+// const base: CourseReportDetailRow[] = [
+// {
+// typeGain: 'QUINTE ORDRE',
+// typeJeu: 'Quinte+',
+// montant: 2840500,
+// nombre: randomInt(1, 30),
+// statut: 'Validée',
+// distributed: false,
+// externe: false,
+// },
+// {
+// typeGain: 'QUINTE DESORDRE',
+// typeJeu: 'Quinte+',
+// montant: 40000,
+// nombre: randomInt(300, 5000),
+// statut: 'Validée',
+// distributed: false,
+// externe: false,
+// },
+// {
+// typeGain: 'BONUS 4',
+// typeJeu: 'Quinte+',
+// montant: 2000,
+// nombre: randomInt(5000, 25000),
+// statut: 'Validée',
+// distributed: false,
+// externe: false,
+// },
+// {
+// typeGain: 'REMBOURSEMENT',
+// typeJeu: 'Quinte+',
+// montant: 300,
+// nombre: randomInt(10, 500),
+// statut: 'Validée',
+// distributed: false,
+// externe: false,
+// },
+// {
+// typeGain: 'TIERCE ORDRE',
+// typeJeu: 'Tierce',
+// montant: 37000,
+// nombre: randomInt(100, 2000),
+// statut: 'Validée',
+// distributed: false,
+// externe: false,
+// },
+// {
+// typeGain: 'TIERCE DESORDRE',
+// typeJeu: 'Tierce',
+// montant: 6000,
+// nombre: randomInt(500, 6000),
+// statut: 'Validée',
+// distributed: false,
+// externe: false,
+// },
+// {
+// typeGain: 'TRANSFORME COUPLE',
+// typeJeu: 'Tierce',
+// montant: 3000,
+// nombre: randomInt(200, 2000),
+// statut: 'Validée',
+// distributed: false,
+// externe: false,
+// },
+// {
+// typeGain: 'TRANSFORME SIMPLE',
+// typeJeu: 'Tierce',
+// montant: 1500,
+// nombre: randomInt(10, 500),
+// statut: 'Validée',
+// distributed: false,
+// externe: false,
+// },
+// ];
+// return base;
+// }
-export const REPORT_SUMMARIES_MOCK: CourseReportSummary[] = COURSES_MOCK.filter(
- (c) => c.statut === 'CLOSED'
-)
- .slice(0, 300)
- .map(
- (c) => ({ id: c.id, course: c, statut: 'En attente', confirmed: false } as CourseReportSummary)
- );
+// export const REPORT_SUMMARIES_MOCK: CourseReportSummary[] = COURSES_MOCK.filter(
+// (c) => c.statut === 'CLOSED'
+// )
+// .slice(0, 300)
+// .map(
+// (c) => ({ id: c.id, course: c, statut: 'En attente', confirmed: false } as CourseReportSummary)
+// );
-export function buildDetailByCourseId(id: string): CourseReportDetail | undefined {
- const summary = REPORT_SUMMARIES_MOCK.find((s) => s.id === id);
- if (!summary) return undefined;
- const rows = payoutRowsForCourse(summary.course as Course);
- return { summary, rows } as CourseReportDetail;
-}
+// export function buildDetailByCourseId(id: string): CourseReportDetail | undefined {
+// const summary = REPORT_SUMMARIES_MOCK.find((s) => s.id === id);
+// if (!summary) return undefined;
+// const rows = payoutRowsForCourse(summary.course as Course);
+// return { summary, rows } as CourseReportDetail;
+// }
-// Pre-built rows map for in-memory updates
-export const REPORT_DETAILS_MOCK = new Map();
-for (const c of COURSES_MOCK.filter((c) => c.statut === 'CLOSED').slice(0, 300)) {
- REPORT_DETAILS_MOCK.set(c.id, payoutRowsForCourse(c));
-}
+// // Pre-built rows map for in-memory updates
+// export const REPORT_DETAILS_MOCK = new Map();
+// for (const c of COURSES_MOCK.filter((c) => c.statut === 'CLOSED').slice(0, 300)) {
+// REPORT_DETAILS_MOCK.set(c.id, payoutRowsForCourse(c));
+// }
diff --git a/src/app/core/services/agent-limit.ts b/src/app/core/services/agent-limit.ts
index 15d02c1..0264599 100644
--- a/src/app/core/services/agent-limit.ts
+++ b/src/app/core/services/agent-limit.ts
@@ -213,7 +213,7 @@ export class AgentLimitService {
sortDir: 'asc',
} as any).pipe(
switchMap((result) => {
- const limits = result.data;
+ const limits = result.content;
const previousDefault = limits.find((l) => l.isDefault && l.id !== newDefaultLimitId);
const operations: Observable[] = [];
diff --git a/src/app/core/services/agent.ts b/src/app/core/services/agent.ts
index 78dbac5..d0af32a 100644
--- a/src/app/core/services/agent.ts
+++ b/src/app/core/services/agent.ts
@@ -451,7 +451,7 @@ export class AgentService {
sortDir: 'asc',
} as any).pipe(
switchMap((result) => {
- const agents = result.data;
+ const agents = result.content;
if (agents.length === 0) {
return of(true);
}
diff --git a/src/app/core/services/course.ts b/src/app/core/services/course.ts
index bb069e6..f82ad07 100644
--- a/src/app/core/services/course.ts
+++ b/src/app/core/services/course.ts
@@ -10,34 +10,31 @@ import { environment } from 'src/environments/environment.development';
import { Reunion } from '../interfaces/reunion';
import { ReunionService } from './reunion';
import { NonPartantService } from './non-partant';
+import { ServicesUtils } from './services-utils';
+import { HippodromeService } from './hippodrome';
const USE_SERVER = true;
-const API_BASE = '/api/v1/courses';
+const API_BASE = '/api/courses';
// Interface to match the API response structure for Course
-interface CourseApiResponse {
- id: number;
- type: string;
- numero: number;
+export interface CourseApiResponse {
+ id: string;
+ hippodromeId: number;
+ reunionNumero: number;
+ reunionDate: string;
nom: string;
- dateDepartCourse: string;
- dateDebutParis: string;
- dateFinParis: string;
- reunionId: number; // API returns reunionId
- reunionCourse: number;
- particularite?: string;
- partants: number;
- distance: number;
- condition?: string;
- estTerminee: boolean;
- estAnnulee: boolean;
- statut: CourseStatut;
- nombreChevauxInscrits: number;
- createdBy: string;
- validatedBy: string | null;
- createdAt: string | null;
- updatedAt: string | null;
- nonPartants: string[];
- adeadHeat: boolean;
+ numero: number;
+ heureDepartPrevue: string;
+ discipline: string;
+ distanceMetres: number;
+ categorie: string;
+ nombrePartants: number;
+ statut: string;
+ annulee: boolean;
+ reporteeMemeJour: boolean;
+ reporteeAutreJour: boolean;
+ incidentTechnique: boolean;
+ nonPartants: Array;
+ typesParisOuverts: Array;
}
@Injectable({ providedIn: 'root' })
@@ -47,6 +44,8 @@ export class CourseService {
constructor(
private http: HttpClient,
private paginatedHttp: PaginatedHttpService,
+ private servivesUtil: ServicesUtils,
+ private hippodromeService: HippodromeService,
private reunionService: ReunionService, // Inject ReunionService
private nonPartantService: NonPartantService // Inject NonPartantService
) {}
@@ -60,408 +59,59 @@ export class CourseService {
return isNgrok ? { 'ngrok-skip-browser-warning': 'true' } : {};
}
- list(
- params: ListParams,
- usePaginationEndpoint: boolean = false
- ): Observable> {
- if (USE_SERVER) {
- // If there's a search query, use the search endpoint
- if (params.search && params.search.trim()) {
- return this.search(params.search.trim()).pipe(
+ list(params: ListParams, usePaginationEndpoint: boolean = true): Observable> {
+ const coursesList = this.http.get>(this.apiUrl, {
+ headers: this.getNgrokHeaders(),
+ params: this.servivesUtil.getParamsFromModel(params),
+ });
+ return coursesList.pipe(
+ switchMap((res) => {
+ const items = res.content ?? [];
+
+ // Transforme chaque course en Observable
+ const courseObservables = items.map((apiCourse) =>
+ this.hippodromeService.getById(String(apiCourse.hippodromeId)).pipe(
+ // Map le hippodrome récupéré dans l'objet Course final
+ map((hippodrome) => ({
+ id: apiCourse.id,
+ hippodrome: hippodrome ?? undefined,
+ reunionNumero: apiCourse.reunionNumero,
+ reunionDate: apiCourse.reunionDate,
+ nom: apiCourse.nom,
+ numero: apiCourse.numero,
+ heureDepartPrevue: apiCourse.heureDepartPrevue,
+ discipline: apiCourse.discipline,
+ distanceMetres: apiCourse.distanceMetres,
+ categorie: apiCourse.categorie,
+ nombrePartants: apiCourse.nombrePartants,
+ statut: apiCourse.statut,
+ annulee: apiCourse.annulee,
+ reporteeMemeJour: apiCourse.reporteeMemeJour,
+ reporteeAutreJour: apiCourse.reporteeAutreJour,
+ incidentTechnique: apiCourse.incidentTechnique,
+ nonPartants: apiCourse.nonPartants || [],
+ typesParisOuverts: apiCourse.typesParisOuverts || [],
+ }))
+ )
+ );
+
+ // ForkJoin pour attendre que tous les hippodromes soient résolus
+ return forkJoin(courseObservables).pipe(
map((courses) => {
- // Apply client-side sorting and pagination
- let filtered = [...courses];
-
- // Sort
- if (params.sortKey && params.sortDir) {
- const { sortKey, sortDir } = params;
- filtered.sort((a: any, b: any) => {
- const getValue = (obj: any, path: string): any =>
- path.split('.').reduce((o, key) => o?.[key], obj);
-
- const va = getValue(a, sortKey);
- const vb = getValue(b, sortKey);
- const sa = va == null ? '' : String(va);
- const sb = vb == null ? '' : String(vb);
- const cmp = sa.localeCompare(sb, 'fr', { numeric: true });
- return sortDir === 'asc' ? cmp : -cmp;
- });
- }
-
- const total = filtered.length;
- const start = (params.page - 1) * params.perPage;
- const pageData = filtered.slice(start, start + params.perPage);
-
- const totalByType = filtered.reduce>((acc, c) => {
- const type = String(c.type);
- acc[type] = (acc[type] ?? 0) + 1;
- return acc;
- }, {});
- const totalRunning = filtered.filter(
- (c) => c.statut === CourseStatut.RUNNING || c.statut === 'RUNNING'
- ).length;
- const totalClosed = filtered.filter(
- (c) => c.statut === CourseStatut.CLOSED || c.statut === 'CLOSED'
- ).length;
-
- return normalizePage(
- {
- data: pageData,
- meta: {
- total,
- totalRunning,
- totalClosed,
- totalByType,
- },
- },
- params.page,
- params.perPage
- );
- }),
- catchError((err) => {
- console.error('Error searching courses:', err);
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: 0,
- totalRunning: 0,
- totalClosed: 0,
- totalByType: {},
- },
- },
- params.page,
- params.perPage
- )
- );
+ const mapped: PagedResult = {
+ pageable: res.pageable,
+ totalPages: res.totalPages,
+ totalElements: res.totalElements,
+ content: courses,
+ };
+ return mapped;
})
);
- }
-
- if (usePaginationEndpoint) {
- return this.paginatedHttp
- .fetch(this.apiUrl, params, {
- zeroBasedPageIndex: false,
- })
- .pipe(
- switchMap((pagedResult) => {
- // Handle empty data case
- if (!pagedResult.data || pagedResult.data.length === 0) {
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: pagedResult.meta?.total ?? 0,
- totalRunning: 0,
- totalClosed: 0,
- totalByType: {},
- },
- },
- params.page,
- params.perPage
- )
- );
- }
-
- // Extract unique reunionIds
- const uniqueReunionIds = [
- ...new Set(pagedResult.data.map((c) => String(c.reunionId))),
- ];
-
- // If no reunion IDs, we can't build valid Reunion objects – return empty page
- if (uniqueReunionIds.length === 0) {
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: pagedResult.meta?.total ?? 0,
- totalRunning: 0,
- totalClosed: 0,
- totalByType: {},
- },
- },
- params.page,
- params.perPage
- )
- );
- }
-
- // Fetch all reunions in parallel
- const reunionRequests = uniqueReunionIds.map((id) =>
- this.reunionService
- .getById(id)
- .pipe(catchError(() => of(undefined)))
- );
-
- return forkJoin(reunionRequests).pipe(
- map((reunions) => {
- // Create a map of reunionId -> Reunion
- const reunionMap = new Map();
- uniqueReunionIds.forEach((id, index) => {
- const reunion = reunions[index];
- if (reunion) {
- reunionMap.set(id, reunion);
- }
- });
-
- // Transform API data to Course objects
- const transformedData: Course[] = pagedResult.data
- .map((apiCourse) => {
- const reunion = reunionMap.get(String(apiCourse.reunionId));
- if (!reunion) {
- // If we couldn't resolve the reunion, drop this course to keep typing sound
- return null;
- }
- return {
- id: String(apiCourse.id),
- type: apiCourse.type,
- numero: apiCourse.numero,
- nom: apiCourse.nom,
- dateDepartCourse: apiCourse.dateDepartCourse,
- dateDebutParis: apiCourse.dateDebutParis,
- dateFinParis: apiCourse.dateFinParis,
- reunion,
- reunionCourse: apiCourse.reunionCourse,
- particularite: apiCourse.particularite,
- partants: apiCourse.partants,
- distance: apiCourse.distance,
- condition: apiCourse.condition,
- statut: apiCourse.statut as CourseStatut,
- nonPartants: apiCourse.nonPartants || [],
- estTerminee: apiCourse.estTerminee,
- estAnnulee: apiCourse.estAnnulee,
- nombreChevauxInscrits: apiCourse.nombreChevauxInscrits,
- adeadHeat: apiCourse.adeadHeat,
- createdBy: apiCourse.createdBy,
- validatedBy: apiCourse.validatedBy,
- createdAt: apiCourse.createdAt || new Date().toISOString(),
- updatedAt: apiCourse.updatedAt || new Date().toISOString(),
- } as Course;
- })
- .filter((c): c is Course => c !== null);
-
- // Calculate meta stats
- const totalByType = transformedData.reduce>((acc, c) => {
- const type = String(c.type);
- acc[type] = (acc[type] ?? 0) + 1;
- return acc;
- }, {});
- const totalRunning = transformedData.filter(
- (c) => c.statut === CourseStatut.RUNNING || c.statut === 'RUNNING'
- ).length;
- const totalClosed = transformedData.filter(
- (c) => c.statut === CourseStatut.CLOSED || c.statut === 'CLOSED'
- ).length;
-
- return normalizePage(
- {
- data: transformedData,
- meta: {
- total: pagedResult.meta?.total ?? transformedData.length,
- totalRunning,
- totalClosed,
- totalByType,
- },
- },
- params.page,
- params.perPage
- );
- })
- );
- }),
- catchError((err) => {
- console.error('Error fetching courses:', err);
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: 0,
- totalRunning: 0,
- totalClosed: 0,
- totalByType: {},
- },
- },
- params.page,
- params.perPage
- )
- );
- })
- );
- } else {
- // Fetch all data and apply client-side pagination
- return this.http
- .get(this.apiUrl, { headers: this.getNgrokHeaders() })
- .pipe(
- switchMap((apiData) => {
- // Handle empty data case
- if (!apiData || apiData.length === 0) {
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: 0,
- totalRunning: 0,
- totalClosed: 0,
- totalByType: {},
- },
- },
- params.page,
- params.perPage
- )
- );
- }
-
- // Extract unique reunionIds
- const uniqueReunionIds = [...new Set(apiData.map((c) => String(c.reunionId)))];
-
- // Handle case where there are no unique IDs (shouldn't happen, but be safe)
- if (uniqueReunionIds.length === 0) {
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: 0,
- totalRunning: 0,
- totalClosed: 0,
- totalByType: {},
- },
- },
- params.page,
- params.perPage
- )
- );
- }
-
- // Fetch all reunions in parallel
- const reunionRequests = uniqueReunionIds.map((id) =>
- this.reunionService
- .getById(id)
- .pipe(catchError(() => of(undefined)))
- );
-
- return forkJoin(reunionRequests).pipe(
- map((reunions) => {
- // Create a map of reunionId -> Reunion
- const reunionMap = new Map();
- uniqueReunionIds.forEach((id, index) => {
- const reunion = reunions[index];
- if (reunion) {
- reunionMap.set(id, reunion);
- }
- });
-
- // Transform API data to Course objects
- const transformedData: Course[] = apiData
- .map((apiCourse) => {
- const reunion = reunionMap.get(String(apiCourse.reunionId));
- if (!reunion) {
- return null;
- }
- return {
- id: String(apiCourse.id),
- type: apiCourse.type,
- numero: apiCourse.numero,
- nom: apiCourse.nom,
- dateDepartCourse: apiCourse.dateDepartCourse,
- dateDebutParis: apiCourse.dateDebutParis,
- dateFinParis: apiCourse.dateFinParis,
- reunion,
- reunionCourse: apiCourse.reunionCourse,
- particularite: apiCourse.particularite,
- partants: apiCourse.partants,
- distance: apiCourse.distance,
- condition: apiCourse.condition,
- statut: apiCourse.statut as CourseStatut,
- nonPartants: apiCourse.nonPartants || [],
- estTerminee: apiCourse.estTerminee,
- estAnnulee: apiCourse.estAnnulee,
- nombreChevauxInscrits: apiCourse.nombreChevauxInscrits,
- adeadHeat: apiCourse.adeadHeat,
- createdBy: apiCourse.createdBy,
- validatedBy: apiCourse.validatedBy,
- createdAt: apiCourse.createdAt || new Date().toISOString(),
- updatedAt: apiCourse.updatedAt || new Date().toISOString(),
- } as Course;
- })
- .filter((c): c is Course => c !== null);
-
- // Apply client-side filtering, sorting, and pagination
- let filtered = this.applyClientFilters(transformedData, params);
- const total = filtered.length;
- const start = (params.page - 1) * params.perPage;
- const pageData = filtered.slice(start, start + params.perPage);
-
- const totalByType = filtered.reduce>((acc, c) => {
- const type = String(c.type);
- acc[type] = (acc[type] ?? 0) + 1;
- return acc;
- }, {});
- const totalRunning = filtered.filter(
- (c) => c.statut === CourseStatut.RUNNING || c.statut === 'RUNNING'
- ).length;
- const totalClosed = filtered.filter(
- (c) => c.statut === CourseStatut.CLOSED || c.statut === 'CLOSED'
- ).length;
-
- return normalizePage(
- {
- data: pageData,
- meta: {
- total,
- totalRunning,
- totalClosed,
- totalByType,
- },
- },
- params.page,
- params.perPage
- );
- })
- );
- }),
- catchError((err) => {
- console.error('Error fetching courses:', err);
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: 0,
- totalRunning: 0,
- totalClosed: 0,
- totalByType: {},
- },
- },
- params.page,
- params.perPage
- )
- );
- })
- );
- }
- }
-
- // If USE_SERVER is false, return empty result
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: 0,
- totalRunning: 0,
- totalClosed: 0,
- totalByType: {},
- },
- },
- params.page,
- params.perPage
- )
+ }),
+ catchError((err) => {
+ console.error('Error fetching courses list:', err);
+ return of({ content: [], pageable: {pageNumber: 1, pageSize: 0, total: 0}, totalPages:1, totalElements:0 } as PagedResult);
+ })
);
}
@@ -469,19 +119,19 @@ export class CourseService {
let filtered = [...data];
// Search filter
- const q = (params.search ?? '').toLowerCase();
- if (q) {
- filtered = filtered.filter((c) => {
- const reunionName = c.reunion?.nom?.toLowerCase?.() ?? '';
- const hippodromeName = c.reunion?.hippodrome?.nom?.toLowerCase?.() ?? '';
- return (
- c.nom.toLowerCase().includes(q) ||
- c.type.toLowerCase().includes(q) ||
- reunionName.includes(q) ||
- hippodromeName.includes(q)
- );
- });
- }
+ // const q = (params.search ?? '').toLowerCase();
+ // if (q) {
+ // filtered = filtered.filter((c) => {
+ // const reunionName = c.reunion?.nom?.toLowerCase?.() ?? '';
+ // const hippodromeName = c.reunion?.hippodrome?.nom?.toLowerCase?.() ?? '';
+ // return (
+ // c.nom.toLowerCase().includes(q) ||
+ // c.type.toLowerCase().includes(q) ||
+ // reunionName.includes(q) ||
+ // hippodromeName.includes(q)
+ // );
+ // });
+ // }
// Sort
if (params.sortKey && params.sortDir) {
@@ -509,35 +159,30 @@ export class CourseService {
.pipe(
switchMap((apiCourse) => {
// Fetch the reunion (non-partants are already included in the API response)
- return this.reunionService.getById(String(apiCourse.reunionId)).pipe(
- map((reunion) => {
- if (!reunion) {
+ return this.hippodromeService.getById(String(apiCourse.hippodromeId)).pipe(
+ map((hippodrome) => {
+ if (!hippodrome) {
return undefined;
}
return {
id: String(apiCourse.id),
- type: apiCourse.type,
- numero: apiCourse.numero,
+ hippodrome: hippodrome ?? undefined,
+ reunionNumero: apiCourse.reunionNumero,
+ reunionDate: apiCourse.reunionDate,
nom: apiCourse.nom,
- dateDepartCourse: apiCourse.dateDepartCourse,
- dateDebutParis: apiCourse.dateDebutParis,
- dateFinParis: apiCourse.dateFinParis,
- reunion,
- reunionCourse: apiCourse.reunionCourse,
- particularite: apiCourse.particularite,
- partants: apiCourse.partants,
- distance: apiCourse.distance,
- condition: apiCourse.condition,
- statut: apiCourse.statut as CourseStatut,
+ numero: apiCourse.numero,
+ heureDepartPrevue: apiCourse.heureDepartPrevue,
+ discipline: apiCourse.discipline,
+ distanceMetres: apiCourse.distanceMetres,
+ categorie: apiCourse.categorie,
+ nombrePartants: apiCourse.nombrePartants,
+ statut: apiCourse.statut,
+ annulee: apiCourse.annulee,
+ reporteeMemeJour: apiCourse.reporteeMemeJour,
+ reporteeAutreJour: apiCourse.reporteeAutreJour,
+ incidentTechnique: apiCourse.incidentTechnique,
nonPartants: apiCourse.nonPartants || [],
- estTerminee: apiCourse.estTerminee,
- estAnnulee: apiCourse.estAnnulee,
- nombreChevauxInscrits: apiCourse.nombreChevauxInscrits,
- adeadHeat: apiCourse.adeadHeat,
- createdBy: apiCourse.createdBy,
- validatedBy: apiCourse.validatedBy,
- createdAt: apiCourse.createdAt || new Date().toISOString(),
- updatedAt: apiCourse.updatedAt || new Date().toISOString(),
+ typesParisOuverts: apiCourse.typesParisOuverts || []
};
})
);
@@ -551,189 +196,168 @@ export class CourseService {
return of(undefined);
}
- getByReunionId(reunionId: string): Observable {
- if (USE_SERVER) {
- return this.http
- .get(`${this.apiUrl}/reunion/${reunionId}`, {
- headers: this.getNgrokHeaders(),
- })
- .pipe(
- switchMap((apiData) => {
- // Fetch the reunion once
- return this.reunionService.getById(reunionId).pipe(
- map((reunion) => {
- if (!reunion) {
- return [];
- }
- // Transform all courses with the same reunion
- return apiData.map((apiCourse) => ({
- id: String(apiCourse.id),
- type: apiCourse.type,
- numero: apiCourse.numero,
- nom: apiCourse.nom,
- dateDepartCourse: apiCourse.dateDepartCourse,
- dateDebutParis: apiCourse.dateDebutParis,
- dateFinParis: apiCourse.dateFinParis,
- reunion,
- reunionCourse: apiCourse.reunionCourse,
- particularite: apiCourse.particularite,
- partants: apiCourse.partants,
- distance: apiCourse.distance,
- condition: apiCourse.condition,
- statut: apiCourse.statut as CourseStatut,
- nonPartants: apiCourse.nonPartants || [],
- estTerminee: apiCourse.estTerminee,
- estAnnulee: apiCourse.estAnnulee,
- nombreChevauxInscrits: apiCourse.nombreChevauxInscrits,
- adeadHeat: apiCourse.adeadHeat,
- createdBy: apiCourse.createdBy,
- validatedBy: apiCourse.validatedBy,
- createdAt: apiCourse.createdAt || new Date().toISOString(),
- updatedAt: apiCourse.updatedAt || new Date().toISOString(),
- }));
- })
- );
- }),
- catchError((err) => {
- console.error(`Error fetching courses for reunion ${reunionId}:`, err);
- return of([]);
- })
- );
- }
- return of([]);
- }
+ // getByReunionId(reunionId: string): Observable {
+ // if (USE_SERVER) {
+ // return this.http
+ // .get(`${this.apiUrl}/reunion/${reunionId}`, {
+ // headers: this.getNgrokHeaders(),
+ // })
+ // .pipe(
+ // switchMap((apiData) => {
+ // // Fetch the reunion once
+ // return this.reunionService.getById(reunionId).pipe(
+ // map((reunion) => {
+ // if (!reunion) {
+ // return [];
+ // }
+ // // Transform all courses with the same reunion
+ // return apiData.map((apiCourse) => ({
+ // id: String(apiCourse.id),
+ // type: apiCourse.type,
+ // numero: apiCourse.numero,
+ // nom: apiCourse.nom,
+ // dateDepartCourse: apiCourse.dateDepartCourse,
+ // dateDebutParis: apiCourse.dateDebutParis,
+ // dateFinParis: apiCourse.dateFinParis,
+ // reunion,
+ // reunionCourse: apiCourse.reunionCourse,
+ // particularite: apiCourse.particularite,
+ // partants: apiCourse.partants,
+ // distance: apiCourse.distance,
+ // condition: apiCourse.condition,
+ // statut: apiCourse.statut as CourseStatut,
+ // nonPartants: apiCourse.nonPartants || [],
+ // estTerminee: apiCourse.estTerminee,
+ // estAnnulee: apiCourse.estAnnulee,
+ // nombreChevauxInscrits: apiCourse.nombreChevauxInscrits,
+ // adeadHeat: apiCourse.adeadHeat,
+ // createdBy: apiCourse.createdBy,
+ // validatedBy: apiCourse.validatedBy,
+ // createdAt: apiCourse.createdAt || new Date().toISOString(),
+ // updatedAt: apiCourse.updatedAt || new Date().toISOString(),
+ // }));
+ // })
+ // );
+ // }),
+ // catchError((err) => {
+ // console.error(`Error fetching courses for reunion ${reunionId}:`, err);
+ // return of([]);
+ // })
+ // );
+ // }
+ // return of([]);
+ // }
- search(query: string): Observable {
- if (USE_SERVER) {
- return this.http
- .get(`${this.apiUrl}/search`, {
- params: { q: query.trim() },
- headers: this.getNgrokHeaders(),
- })
- .pipe(
- switchMap((apiData) => {
- // Extract unique reunionIds
- const uniqueReunionIds = [...new Set(apiData.map((c) => String(c.reunionId)))];
+ // search(query: string): Observable {
+ // if (USE_SERVER) {
+ // return this.http
+ // .get(`${this.apiUrl}/search`, {
+ // params: { q: query.trim() },
+ // headers: this.getNgrokHeaders(),
+ // })
+ // .pipe(
+ // switchMap((apiData) => {
+ // // Extract unique reunionIds
+ // const uniqueReunionIds = [...new Set(apiData.map((c) => String(c.reunionId)))];
- // Fetch all reunions in parallel
- const reunionRequests = uniqueReunionIds.map((id) =>
- this.reunionService
- .getById(id)
- .pipe(catchError(() => of(undefined)))
- );
+ // // Fetch all reunions in parallel
+ // const reunionRequests = uniqueReunionIds.map((id) =>
+ // this.reunionService
+ // .getById(id)
+ // .pipe(catchError(() => of(undefined)))
+ // );
- return forkJoin(reunionRequests).pipe(
- map((reunions) => {
- // Create a map of reunionId -> Reunion
- const reunionMap = new Map();
- uniqueReunionIds.forEach((id, index) => {
- const reunion = reunions[index];
- if (reunion) {
- reunionMap.set(id, reunion);
- }
- });
+ // return forkJoin(reunionRequests).pipe(
+ // map((reunions) => {
+ // // Create a map of reunionId -> Reunion
+ // const reunionMap = new Map();
+ // uniqueReunionIds.forEach((id, index) => {
+ // const reunion = reunions[index];
+ // if (reunion) {
+ // reunionMap.set(id, reunion);
+ // }
+ // });
- // Transform API data to Course objects
- return apiData
- .map((apiCourse) => {
- const reunion = reunionMap.get(String(apiCourse.reunionId));
- if (!reunion) {
- return null;
- }
- return {
- id: String(apiCourse.id),
- type: apiCourse.type,
- numero: apiCourse.numero,
- nom: apiCourse.nom,
- dateDepartCourse: apiCourse.dateDepartCourse,
- dateDebutParis: apiCourse.dateDebutParis,
- dateFinParis: apiCourse.dateFinParis,
- reunion,
- reunionCourse: apiCourse.reunionCourse,
- particularite: apiCourse.particularite,
- partants: apiCourse.partants,
- distance: apiCourse.distance,
- condition: apiCourse.condition,
- statut: apiCourse.statut as CourseStatut,
- nonPartants: apiCourse.nonPartants || [],
- estTerminee: apiCourse.estTerminee,
- estAnnulee: apiCourse.estAnnulee,
- nombreChevauxInscrits: apiCourse.nombreChevauxInscrits,
- adeadHeat: apiCourse.adeadHeat,
- createdBy: apiCourse.createdBy,
- validatedBy: apiCourse.validatedBy,
- createdAt: apiCourse.createdAt || new Date().toISOString(),
- updatedAt: apiCourse.updatedAt || new Date().toISOString(),
- } as Course;
- })
- .filter((c): c is Course => c !== null);
- })
- );
- }),
- catchError((err) => {
- console.error(`Error searching courses with query ${query}:`, err);
- return of([]);
- })
- );
- }
- return of([]);
- }
+ // // Transform API data to Course objects
+ // return apiData
+ // .map((apiCourse) => {
+ // const reunion = reunionMap.get(String(apiCourse.reunionId));
+ // if (!reunion) {
+ // return null;
+ // }
+ // return {
+ // id: String(apiCourse.id),
+ // type: apiCourse.type,
+ // numero: apiCourse.numero,
+ // nom: apiCourse.nom,
+ // dateDepartCourse: apiCourse.dateDepartCourse,
+ // dateDebutParis: apiCourse.dateDebutParis,
+ // dateFinParis: apiCourse.dateFinParis,
+ // reunion,
+ // reunionCourse: apiCourse.reunionCourse,
+ // particularite: apiCourse.particularite,
+ // partants: apiCourse.partants,
+ // distance: apiCourse.distance,
+ // condition: apiCourse.condition,
+ // statut: apiCourse.statut as CourseStatut,
+ // nonPartants: apiCourse.nonPartants || [],
+ // estTerminee: apiCourse.estTerminee,
+ // estAnnulee: apiCourse.estAnnulee,
+ // nombreChevauxInscrits: apiCourse.nombreChevauxInscrits,
+ // adeadHeat: apiCourse.adeadHeat,
+ // createdBy: apiCourse.createdBy,
+ // validatedBy: apiCourse.validatedBy,
+ // createdAt: apiCourse.createdAt || new Date().toISOString(),
+ // updatedAt: apiCourse.updatedAt || new Date().toISOString(),
+ // } as Course;
+ // })
+ // .filter((c): c is Course => c !== null);
+ // })
+ // );
+ // }),
+ // catchError((err) => {
+ // console.error(`Error searching courses with query ${query}:`, err);
+ // return of([]);
+ // })
+ // );
+ // }
+ // return of([]);
+ // }
- create(payload: Omit): Observable {
+ create(payload: Partial): Observable {
if (USE_SERVER) {
// Transform payload to API format (send reunionId instead of reunion object)
- const apiPayload: any = {
- type: payload.type,
- numero: payload.numero,
- nom: payload.nom,
- dateDepartCourse: payload.dateDepartCourse,
- dateDebutParis: payload.dateDebutParis,
- dateFinParis: payload.dateFinParis,
- reunionId: typeof payload.reunion === 'object' ? payload.reunion.id : payload.reunion,
- reunionCourse: payload.reunionCourse,
- particularite: payload.particularite,
- partants: payload.partants,
- distance: payload.distance,
- condition: payload.condition,
- statut: payload.statut,
- createdBy: payload.createdBy,
- validatedBy: payload.validatedBy,
- };
+ const apiPayload: Partial = payload;
return this.http
.post(this.apiUrl, apiPayload, { headers: this.getNgrokHeaders() })
.pipe(
switchMap((apiCourse) => {
// Fetch the reunion to build the full Course object
- return this.reunionService.getById(String(apiCourse.reunionId)).pipe(
- map((reunion) => {
- if (!reunion) {
- throw new Error('Reunion not found');
+ return this.hippodromeService.getById(String(apiCourse.hippodromeId)).pipe(
+ map((hippodrome) => {
+ if (!hippodrome) {
+ throw new Error('Hippodrome not found');
}
const item: Course = {
id: String(apiCourse.id),
- type: apiCourse.type,
- numero: apiCourse.numero,
+ hippodrome: hippodrome ?? undefined,
+ reunionNumero: apiCourse.reunionNumero,
+ reunionDate: apiCourse.reunionDate,
nom: apiCourse.nom,
- dateDepartCourse: apiCourse.dateDepartCourse,
- dateDebutParis: apiCourse.dateDebutParis,
- dateFinParis: apiCourse.dateFinParis,
- reunion,
- reunionCourse: apiCourse.reunionCourse,
- particularite: apiCourse.particularite,
- partants: apiCourse.partants,
- distance: apiCourse.distance,
- condition: apiCourse.condition,
- statut: apiCourse.statut as CourseStatut,
+ numero: apiCourse.numero,
+ heureDepartPrevue: apiCourse.heureDepartPrevue,
+ discipline: apiCourse.discipline,
+ distanceMetres: apiCourse.distanceMetres,
+ categorie: apiCourse.categorie,
+ nombrePartants: apiCourse.nombrePartants,
+ statut: apiCourse.statut,
+ annulee: apiCourse.annulee,
+ reporteeMemeJour: apiCourse.reporteeMemeJour,
+ reporteeAutreJour: apiCourse.reporteeAutreJour,
+ incidentTechnique: apiCourse.incidentTechnique,
nonPartants: apiCourse.nonPartants || [],
- estTerminee: apiCourse.estTerminee,
- estAnnulee: apiCourse.estAnnulee,
- nombreChevauxInscrits: apiCourse.nombreChevauxInscrits,
- adeadHeat: apiCourse.adeadHeat,
- createdBy: apiCourse.createdBy,
- validatedBy: apiCourse.validatedBy,
- createdAt: apiCourse.createdAt || new Date().toISOString(),
- updatedAt: apiCourse.updatedAt || new Date().toISOString(),
+ typesParisOuverts: apiCourse.typesParisOuverts || []
};
return item;
})
@@ -748,52 +372,41 @@ export class CourseService {
throw new Error('Server mode is required');
}
- update(id: string, payload: Partial): Observable {
+ update(id: string, payload: Partial): Observable {
if (USE_SERVER) {
- // Transform payload to API format (send reunionId instead of reunion object)
- const apiPayload: any = { ...payload };
- if (payload.reunion) {
- apiPayload.reunionId =
- typeof payload.reunion === 'object' ? payload.reunion.id : payload.reunion;
- delete apiPayload.reunion;
- }
+ // Transform payload to API format (send reunionId instead of reunion object
return this.http
- .put(`${this.apiUrl}/${id}`, apiPayload, {
+ .put(`${this.apiUrl}/${id}`, payload, {
headers: this.getNgrokHeaders(),
})
.pipe(
switchMap((apiCourse) => {
// Fetch the reunion to build the full Course object
- return this.reunionService.getById(String(apiCourse.reunionId)).pipe(
- map((reunion) => {
- if (!reunion) {
+ return this.hippodromeService.getById(String(apiCourse.hippodromeId)).pipe(
+ map((hippodrome) => {
+ if (!hippodrome) {
throw new Error('Reunion not found');
}
return {
id: String(apiCourse.id),
- type: apiCourse.type,
- numero: apiCourse.numero,
+ hippodrome: hippodrome ?? undefined,
+ reunionNumero: apiCourse.reunionNumero,
+ reunionDate: apiCourse.reunionDate,
nom: apiCourse.nom,
- dateDepartCourse: apiCourse.dateDepartCourse,
- dateDebutParis: apiCourse.dateDebutParis,
- dateFinParis: apiCourse.dateFinParis,
- reunion,
- reunionCourse: apiCourse.reunionCourse,
- particularite: apiCourse.particularite,
- partants: apiCourse.partants,
- distance: apiCourse.distance,
- condition: apiCourse.condition,
- statut: apiCourse.statut as CourseStatut,
+ numero: apiCourse.numero,
+ heureDepartPrevue: apiCourse.heureDepartPrevue,
+ discipline: apiCourse.discipline,
+ distanceMetres: apiCourse.distanceMetres,
+ categorie: apiCourse.categorie,
+ nombrePartants: apiCourse.nombrePartants,
+ statut: apiCourse.statut,
+ annulee: apiCourse.annulee,
+ reporteeMemeJour: apiCourse.reporteeMemeJour,
+ reporteeAutreJour: apiCourse.reporteeAutreJour,
+ incidentTechnique: apiCourse.incidentTechnique,
nonPartants: apiCourse.nonPartants || [],
- estTerminee: apiCourse.estTerminee,
- estAnnulee: apiCourse.estAnnulee,
- nombreChevauxInscrits: apiCourse.nombreChevauxInscrits,
- adeadHeat: apiCourse.adeadHeat,
- createdBy: apiCourse.createdBy,
- validatedBy: apiCourse.validatedBy,
- createdAt: apiCourse.createdAt || new Date().toISOString(),
- updatedAt: apiCourse.updatedAt || new Date().toISOString(),
+ typesParisOuverts: apiCourse.typesParisOuverts || []
};
})
);
diff --git a/src/app/core/services/hippodrome.ts b/src/app/core/services/hippodrome.ts
index ffd3308..9387b80 100644
--- a/src/app/core/services/hippodrome.ts
+++ b/src/app/core/services/hippodrome.ts
@@ -7,16 +7,18 @@ import { normalizePage } from '@shared/paging/normalize-page';
import { PaginatedHttpService } from '@shared/paging/paginated-http.service';
import { ListParams, PagedResult } from '@shared/paging/paging';
import { environment } from 'src/environments/environment.development';
+import { ServicesUtils } from './services-utils';
const USE_SERVER = true;
-const API_BASE = '/api/v1/hippodromes';
+const API_BASE = '/api/hippodromes';
@Injectable({ providedIn: 'root' })
export class HippodromeService {
private apiUrl = environment.apiBaseUrl + API_BASE;
private store = signal([]);
- constructor(private http: HttpClient, private paginatedHttp: PaginatedHttpService) {}
+
+ constructor(private http: HttpClient, private paginatedHttp: PaginatedHttpService, private servicesUtils:ServicesUtils) {}
// Helper method to get ngrok bypass headers
private getNgrokHeaders(): Record {
@@ -30,326 +32,13 @@ export class HippodromeService {
// LISTE — supporte client & serveur
list(
params: ListParams,
- usePaginationEndpoint: boolean = false
+ usePaginationEndpoint: boolean = true
): Observable> {
- if (USE_SERVER) {
- // If there's a search query, use the search endpoint
- if (params.search && params.search.trim()) {
- return this.search(params.search.trim()).pipe(
- switchMap((hippodromes) => {
- // Fetch all reunions and courses to calculate counts
- return forkJoin({
- reunions: this.http
- .get(`${environment.apiBaseUrl}/api/v1/reunions`, {
- headers: this.getNgrokHeaders(),
- })
- .pipe(
- catchError(() => of([])),
- map((data) => ({ data: data || [], meta: { total: (data || []).length } }))
- ),
- courses: this.http
- .get(`${environment.apiBaseUrl}/api/v1/courses`, {
- headers: this.getNgrokHeaders(),
- })
- .pipe(
- catchError(() => of([])),
- map((data) => ({ data: data || [], meta: { total: (data || []).length } }))
- ),
- }).pipe(
- map(({ reunions, courses }) => {
- // Count reunions per hippodrome
- const reunionCountMap = new Map();
- reunions.data.forEach((reunion: any) => {
- const hippodromeId = String(reunion.hippodromeId || reunion.hippodrome?.id);
- if (hippodromeId && hippodromeId !== 'undefined' && hippodromeId !== 'null') {
- reunionCountMap.set(hippodromeId, (reunionCountMap.get(hippodromeId) || 0) + 1);
- }
- });
-
- // Create a map of reunionId -> hippodromeId from reunions
- const reunionToHippodromeMap = new Map();
- reunions.data.forEach((reunion: any) => {
- const reunionId = String(reunion.id);
- const hippodromeId = String(reunion.hippodromeId || reunion.hippodrome?.id);
- if (
- reunionId &&
- reunionId !== 'undefined' &&
- reunionId !== 'null' &&
- hippodromeId &&
- hippodromeId !== 'undefined' &&
- hippodromeId !== 'null'
- ) {
- reunionToHippodromeMap.set(reunionId, hippodromeId);
- }
- });
-
- // Count courses per hippodrome using the reunion -> hippodrome mapping
- const courseCountMap = new Map();
- courses.data.forEach((course: any) => {
- const reunionId = String(course.reunionId || course.reunion?.id);
- if (reunionId && reunionId !== 'undefined' && reunionId !== 'null') {
- const hippodromeId = reunionToHippodromeMap.get(reunionId);
- if (hippodromeId) {
- courseCountMap.set(hippodromeId, (courseCountMap.get(hippodromeId) || 0) + 1);
- }
- }
- });
-
- // Add counts to hippodromes
- const hippodromesWithCounts = hippodromes.map((h) => ({
- ...h,
- reunionCount: reunionCountMap.get(String(h.id)) ?? 0,
- courseCount: courseCountMap.get(String(h.id)) ?? 0,
- }));
-
- // Apply client-side sorting and pagination
- let filtered = this.applyClientFilters(hippodromesWithCounts, {
- ...params,
- search: '', // Already filtered by search endpoint
- });
- const total = filtered.length;
- const start = (params.page - 1) * params.perPage;
- const pageData = filtered.slice(start, start + params.perPage);
-
- const uniqueCountries = new Set(filtered.map((h) => h.pays)).size;
- const uniqueCities = new Set(filtered.map((h) => h.ville)).size;
- const averageByCountry = filtered.length
- ? Math.round(filtered.length / uniqueCountries)
- : 0;
- const totalReunions = filtered.reduce((acc, h) => acc + (h.reunionCount ?? 0), 0);
- const totalCourses = filtered.reduce((acc, h) => acc + (h.courseCount ?? 0), 0);
-
- return normalizePage(
- {
- data: pageData,
- meta: {
- total,
- uniqueCountries,
- uniqueCities,
- averageByCountry,
- totalReunions,
- totalCourses,
- },
- },
- params.page,
- params.perPage
- );
- })
- );
- }),
- catchError((err) => {
- console.error('Error searching hippodromes:', err);
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: 0,
- uniqueCountries: 0,
- uniqueCities: 0,
- averageByCountry: 0,
- totalReunions: 0,
- totalCourses: 0,
- },
- },
- params.page,
- params.perPage
- )
- );
- })
- );
- }
-
- if (usePaginationEndpoint) {
- return this.paginatedHttp
- .fetch(this.apiUrl, params, {
- zeroBasedPageIndex: false,
- buildSort: (key, dir) => (key && dir ? ['sort', `${key},${dir}`] : null),
- mapClientSortKey: (k) => {
- const alias: Record = {
- name: 'nom',
- city: 'ville',
- country: 'pays',
- };
- return k ? alias[k] ?? k : undefined;
- },
- })
- .pipe(
- catchError((err) => {
- console.error('Error fetching hippodromes:', err);
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: 0,
- uniqueCountries: 0,
- uniqueCities: 0,
- averageByCountry: 0,
- totalReunions: 0,
- totalCourses: 0,
- },
- },
- params.page,
- params.perPage
- )
- );
- })
- );
- } else {
- // Fetch all data and apply client-side pagination
- return this.http
- .get(`${this.apiUrl}/actifs`, {
- headers: this.getNgrokHeaders(),
- })
- .pipe(
- switchMap((allData) => {
- // Fetch all reunions and courses directly from API to calculate counts
- // We fetch directly to avoid circular dependency with ReunionService and CourseService
- return forkJoin({
- reunions: this.http
- .get(`${environment.apiBaseUrl}/api/v1/reunions`, {
- headers: this.getNgrokHeaders(),
- })
- .pipe(
- catchError(() => of([])),
- map((data) => ({ data, meta: { total: data.length } }))
- ),
- courses: this.http
- .get(`${environment.apiBaseUrl}/api/v1/courses`, {
- headers: this.getNgrokHeaders(),
- })
- .pipe(
- catchError(() => of([])),
- map((data) => ({ data, meta: { total: data.length } }))
- ),
- }).pipe(
- map(({ reunions, courses }) => {
- // Count reunions per hippodrome
- const reunionCountMap = new Map();
- reunions.data.forEach((reunion: any) => {
- const hippodromeId = String(reunion.hippodromeId || reunion.hippodrome?.id);
- if (hippodromeId && hippodromeId !== 'undefined' && hippodromeId !== 'null') {
- reunionCountMap.set(
- hippodromeId,
- (reunionCountMap.get(hippodromeId) || 0) + 1
- );
- }
- });
-
- // Create a map of reunionId -> hippodromeId from reunions
- const reunionToHippodromeMap = new Map();
- reunions.data.forEach((reunion: any) => {
- const reunionId = String(reunion.id);
- const hippodromeId = String(reunion.hippodromeId || reunion.hippodrome?.id);
- if (
- reunionId &&
- reunionId !== 'undefined' &&
- reunionId !== 'null' &&
- hippodromeId &&
- hippodromeId !== 'undefined' &&
- hippodromeId !== 'null'
- ) {
- reunionToHippodromeMap.set(reunionId, hippodromeId);
- }
- });
-
- // Count courses per hippodrome using the reunion -> hippodrome mapping
- const courseCountMap = new Map();
- courses.data.forEach((course: any) => {
- const reunionId = String(course.reunionId || course.reunion?.id);
- if (reunionId && reunionId !== 'undefined' && reunionId !== 'null') {
- const hippodromeId = reunionToHippodromeMap.get(reunionId);
- if (hippodromeId) {
- courseCountMap.set(
- hippodromeId,
- (courseCountMap.get(hippodromeId) || 0) + 1
- );
- }
- }
- });
-
- // Add counts to hippodromes
- const hippodromesWithCounts = allData.map((h) => ({
- ...h,
- reunionCount: reunionCountMap.get(String(h.id)) ?? 0,
- courseCount: courseCountMap.get(String(h.id)) ?? 0,
- }));
-
- // Apply client-side filtering, sorting, and pagination
- let filtered = this.applyClientFilters(hippodromesWithCounts, params);
- const total = filtered.length;
- const start = (params.page - 1) * params.perPage;
- const pageData = filtered.slice(start, start + params.perPage);
-
- const uniqueCountries = new Set(filtered.map((h) => h.pays)).size;
- const uniqueCities = new Set(filtered.map((h) => h.ville)).size;
- const averageByCountry = filtered.length
- ? Math.round(filtered.length / uniqueCountries)
- : 0;
- const totalReunions = filtered.reduce((acc, h) => acc + (h.reunionCount ?? 0), 0);
- const totalCourses = filtered.reduce((acc, h) => acc + (h.courseCount ?? 0), 0);
-
- return normalizePage(
- {
- data: pageData,
- meta: {
- total,
- uniqueCountries,
- uniqueCities,
- averageByCountry,
- totalReunions,
- totalCourses,
- },
- },
- params.page,
- params.perPage
- );
- })
- );
- }),
- catchError((err) => {
- console.error('Error fetching hippodromes:', err);
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: 0,
- uniqueCountries: 0,
- uniqueCities: 0,
- averageByCountry: 0,
- totalReunions: 0,
- totalCourses: 0,
- },
- },
- params.page,
- params.perPage
- )
- );
- })
- );
- }
- }
-
- // Mock mode disabled - return empty result
- return of(
- normalizePage(
- {
- data: [],
- meta: {
- total: 0,
- uniqueCountries: 0,
- uniqueCities: 0,
- averageByCountry: 0,
- totalReunions: 0,
- totalCourses: 0,
- },
- },
- params.page,
- params.perPage
- )
- );
+ const hippodromeList = this.http.get>(this.apiUrl, {
+ headers: this.getNgrokHeaders(),
+ params: this.servicesUtils.getParamsFromModel(params)
+ })
+ return hippodromeList;
}
private applyClientFilters(data: Hippodrome[], params: ListParams): Hippodrome[] {
diff --git a/src/app/core/services/report.ts b/src/app/core/services/report.ts
index 5f4fbd5..74997d5 100644
--- a/src/app/core/services/report.ts
+++ b/src/app/core/services/report.ts
@@ -1,76 +1,76 @@
-import { Injectable, signal } from '@angular/core';
-import { Observable, of } from 'rxjs';
-import { CourseReportDetail, CourseReportDetailRow, CourseReportSummary } from '../interfaces/report';
-import { REPORT_SUMMARIES_MOCK, REPORT_DETAILS_MOCK } from '../mocks/report.mocks';
-import { normalizePage } from '@shared/paging/normalize-page';
-import { ListParams, PagedResult, SortDir } from '@shared/paging/paging';
+// import { Injectable, signal } from '@angular/core';
+// import { Observable, of } from 'rxjs';
+// import { CourseReportDetail, CourseReportDetailRow, CourseReportSummary } from '../interfaces/report';
+// import { REPORT_SUMMARIES_MOCK, REPORT_DETAILS_MOCK } from '../mocks/report.mocks';
+// import { normalizePage } from '@shared/paging/normalize-page';
+// import { ListParams, PagedResult, SortDir } from '@shared/paging/paging';
-@Injectable({ providedIn: 'root' })
-export class ReportService {
- private summaries = signal([...REPORT_SUMMARIES_MOCK]);
+// @Injectable({ providedIn: 'root' })
+// export class ReportService {
+// private summaries = signal([...REPORT_SUMMARIES_MOCK]);
- list(params: ListParams): Observable> {
- let data = [...this.summaries()];
- const q = (params.search ?? '').toLowerCase();
- if (q) {
- data = data.filter((r) =>
- [
- r.course.nom,
- r.course.type,
- r.course.reunion?.hippodrome?.nom,
- String(r.course.numero),
- ]
- .filter(Boolean)
- .map((s) => String(s).toLowerCase())
- .some((s) => s.includes(q))
- );
- }
- if (params.sortKey && params.sortDir) {
- const { sortKey, sortDir } = params as { sortKey: string; sortDir: SortDir };
- const get = (o: any, k: string) => k.split('.').reduce((a, b) => a?.[b], o);
- data = [...data].sort((a, b) => String(get(a, sortKey) ?? '').localeCompare(String(get(b, sortKey) ?? ''), 'fr', { numeric: true }) * (sortDir === 'asc' ? 1 : -1));
- }
- const start = (params.page - 1) * params.perPage;
- const pageData = data.slice(start, start + params.perPage);
- return of(normalizePage({ data: pageData, meta: { total: data.length } }, params.page, params.perPage));
- }
+// list(params: ListParams): Observable> {
+// let data = [...this.summaries()];
+// const q = (params.search ?? '').toLowerCase();
+// if (q) {
+// data = data.filter((r) =>
+// [
+// r.course.nom,
+// r.course.type,
+// r.course.reunion?.hippodrome?.nom,
+// String(r.course.numero),
+// ]
+// .filter(Boolean)
+// .map((s) => String(s).toLowerCase())
+// .some((s) => s.includes(q))
+// );
+// }
+// if (params.sortKey && params.sortDir) {
+// const { sortKey, sortDir } = params as { sortKey: string; sortDir: SortDir };
+// const get = (o: any, k: string) => k.split('.').reduce((a, b) => a?.[b], o);
+// data = [...data].sort((a, b) => String(get(a, sortKey) ?? '').localeCompare(String(get(b, sortKey) ?? ''), 'fr', { numeric: true }) * (sortDir === 'asc' ? 1 : -1));
+// }
+// const start = (params.page - 1) * params.perPage;
+// const pageData = data.slice(start, start + params.perPage);
+// return of(normalizePage({ data: pageData, meta: { total: data.length } }, params.page, params.perPage));
+// }
- getDetail(courseId: string): Observable {
- const summary = this.summaries().find((s) => s.id === courseId);
- if (!summary) return of(undefined);
- const rows = REPORT_DETAILS_MOCK.get(courseId) ?? [];
- return of({ summary, rows });
- }
+// getDetail(courseId: string): Observable {
+// const summary = this.summaries().find((s) => s.id === courseId);
+// if (!summary) return of(undefined);
+// const rows = REPORT_DETAILS_MOCK.get(courseId) ?? [];
+// return of({ summary, rows });
+// }
- // === Actions ===
- validate(courseId: string): Observable {
- let updated: CourseReportSummary | undefined;
- this.summaries.set(
- this.summaries().map((s) => (s.id === courseId ? ((updated = { ...s, statut: 'Validé', confirmed: false }), updated) : s))
- );
- return of(updated);
- }
+// // === Actions ===
+// validate(courseId: string): Observable {
+// let updated: CourseReportSummary | undefined;
+// this.summaries.set(
+// this.summaries().map((s) => (s.id === courseId ? ((updated = { ...s, statut: 'Validé', confirmed: false }), updated) : s))
+// );
+// return of(updated);
+// }
- confirm(courseId: string): Observable {
- let updated: CourseReportSummary | undefined;
- this.summaries.set(
- this.summaries().map((s) => (s.id === courseId ? ((updated = { ...s, statut: 'Validé', confirmed: true }), updated) : s))
- );
- return of(updated);
- }
+// confirm(courseId: string): Observable {
+// let updated: CourseReportSummary | undefined;
+// this.summaries.set(
+// this.summaries().map((s) => (s.id === courseId ? ((updated = { ...s, statut: 'Validé', confirmed: true }), updated) : s))
+// );
+// return of(updated);
+// }
- resetStatus(courseId: string): Observable {
- let updated: CourseReportSummary | undefined;
- this.summaries.set(
- this.summaries().map((s) => (s.id === courseId ? ((updated = { ...s, statut: 'Non Validé', confirmed: false }), updated) : s))
- );
- return of(updated);
- }
+// resetStatus(courseId: string): Observable {
+// let updated: CourseReportSummary | undefined;
+// this.summaries.set(
+// this.summaries().map((s) => (s.id === courseId ? ((updated = { ...s, statut: 'Non Validé', confirmed: false }), updated) : s))
+// );
+// return of(updated);
+// }
- modifyRows(courseId: string, rows: CourseReportDetailRow[]): Observable {
- REPORT_DETAILS_MOCK.set(courseId, rows);
- return of(true);
- }
-}
+// modifyRows(courseId: string, rows: CourseReportDetailRow[]): Observable {
+// REPORT_DETAILS_MOCK.set(courseId, rows);
+// return of(true);
+// }
+// }
diff --git a/src/app/core/services/reunion.ts b/src/app/core/services/reunion.ts
index 17e551e..bf3be49 100644
--- a/src/app/core/services/reunion.ts
+++ b/src/app/core/services/reunion.ts
@@ -25,7 +25,7 @@ interface ReunionApiResponse {
}
const USE_SERVER = true;
-const API_BASE = '/api/v1/reunions';
+const API_BASE = '/api/reunions';
@Injectable({ providedIn: 'root' })
export class ReunionService {
@@ -49,7 +49,7 @@ export class ReunionService {
list(
params: ListParams,
- usePaginationEndpoint: boolean = false
+ usePaginationEndpoint: boolean = true
): Observable> {
if (USE_SERVER) {
if (usePaginationEndpoint) {
@@ -61,30 +61,28 @@ export class ReunionService {
.pipe(
switchMap((pagedResult) => {
// Handle empty data case
- if (!pagedResult.data || pagedResult.data.length === 0) {
+ if (!pagedResult.content || pagedResult.content.length === 0) {
return of({
...pagedResult,
- data: [],
- meta: {
- ...pagedResult.meta,
- uniqueHippodromes: 0,
+ content: [],
+ pageable: {
+ ...pagedResult.pageable,
},
- });
- }
+ });
+ }
// Extract unique hippodrome IDs from the paginated data
const uniqueHippodromeIds = [
- ...new Set(pagedResult.data.map((r) => String(r.hippodromeId))),
+ ...new Set(pagedResult.content.map((r) => String(r.hippodromeId))),
];
// Handle case where there are no unique IDs
if (uniqueHippodromeIds.length === 0) {
return of({
...pagedResult,
- data: [],
- meta: {
- ...pagedResult.meta,
- uniqueHippodromes: 0,
+ content: [],
+ pageable: {
+ ...pagedResult.pageable,
},
});
}
@@ -93,12 +91,12 @@ export class ReunionService {
const hippodromeRequests = uniqueHippodromeIds.map((id) =>
this.hippodromeService
.getById(id)
- .pipe(catchError(() => of(undefined)))
+ .pipe(catchError(() => of()))
);
// Fetch courses to calculate counts per reunion
const coursesRequest = this.http
- .get(`${environment.apiBaseUrl}/api/v1/courses`, {
+ .get(`${environment.apiBaseUrl}/api/courses`, {
headers: this.getNgrokHeaders(),
})
.pipe(
@@ -133,7 +131,7 @@ export class ReunionService {
});
// Transform API responses to Reunion objects
- const transformedData: Reunion[] = pagedResult.data
+ const transformedData: Reunion[] = pagedResult.content
.map((apiReunion) => {
const hippodrome = hippodromeMap.get(String(apiReunion.hippodromeId));
if (!hippodrome) {
@@ -155,19 +153,10 @@ export class ReunionService {
} as Reunion;
})
.filter((r): r is Reunion => r !== null && r !== undefined);
-
- // Calculate unique hippodromes count
- const uniqueHippodromes = new Set(transformedData.map((r) => r.hippodrome.id))
- .size;
-
- return {
- ...pagedResult,
- data: transformedData,
- meta: {
- ...pagedResult.meta,
- uniqueHippodromes,
- },
- };
+ return {
+ ...pagedResult,
+ content: transformedData,
+ }
})
);
}),
diff --git a/src/app/core/services/services-utils.ts b/src/app/core/services/services-utils.ts
new file mode 100644
index 0000000..88844fd
--- /dev/null
+++ b/src/app/core/services/services-utils.ts
@@ -0,0 +1,16 @@
+import { HttpParams } from "@angular/common/http";
+import { Injectable } from "@angular/core";
+import { ListParams } from "@shared/paging/paging";
+
+@Injectable({providedIn: 'root'})
+export class ServicesUtils{
+ getParamsFromModel(params:ListParams):HttpParams{
+ let httpParams = new HttpParams();
+ Object.entries(params).forEach(([key, value])=>{
+ if(params != null && params!=undefined){
+ httpParams.set(key, String(value))
+ }
+ })
+ return httpParams;
+ }
+}
\ No newline at end of file
diff --git a/src/app/dashboard/dashboard-routing-module.ts b/src/app/dashboard/dashboard-routing-module.ts
index da7b5f2..726eab0 100644
--- a/src/app/dashboard/dashboard-routing-module.ts
+++ b/src/app/dashboard/dashboard-routing-module.ts
@@ -7,7 +7,6 @@ const routes: Routes = [
{
path: '',
component: Layout,
- canActivate: [authGuard],
children: [
{ path: '', loadComponent: () => import('./pages/main/main').then((m) => m.Main) },
{
@@ -46,16 +45,6 @@ const routes: Routes = [
path: 'limits',
loadComponent: () => import('./pages/limits/limits').then((m) => m.LimitsPage),
},
- {
- path: 'rapport-courses',
- loadComponent: () =>
- import('./pages/report-courses/report-list').then((m) => m.ReportCoursesListPage),
- },
- {
- path: 'rapport-courses/:id',
- loadComponent: () =>
- import('./pages/report-courses/report-detail').then((m) => m.ReportCoursesDetailPage),
- },
],
},
];
diff --git a/src/app/dashboard/pages/agents/agents.ts b/src/app/dashboard/pages/agents/agents.ts
index 5c8c049..5886e8b 100644
--- a/src/app/dashboard/pages/agents/agents.ts
+++ b/src/app/dashboard/pages/agents/agents.ts
@@ -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);
});
}
diff --git a/src/app/dashboard/pages/courses/courses.ts b/src/app/dashboard/pages/courses/courses.ts
index a0600ee..519ce15 100644
--- a/src/app/dashboard/pages/courses/courses.ts
+++ b/src/app/dashboard/pages/courses/courses.ts
@@ -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) => `${c.type}`,
+ cell: (c) => `${c.discipline}`,
},
{
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) =>
- `${c.partants} (${
+ `${c.nombrePartants} (${
c.nonPartants?.length ?? 0
} NP)`,
},
@@ -148,20 +144,24 @@ export class Course {
sortable: true,
cell: (c) => {
const colorMap: Record = {
- 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 = {
- 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 `${
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);
+ : this.api.create(payload as Omit);
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
diff --git a/src/app/dashboard/pages/hippodrome/hippodrome.html b/src/app/dashboard/pages/hippodrome/hippodrome.html
index 62f9a9d..7d719c6 100644
--- a/src/app/dashboard/pages/hippodrome/hippodrome.html
+++ b/src/app/dashboard/pages/hippodrome/hippodrome.html
@@ -33,18 +33,6 @@
{{ averageByCountry() }}
-
- Réunions totales
-
- {{ totalReunions() }}
-
-
-
- Courses totales
-
- {{ totalCourses() }}
-
-
diff --git a/src/app/dashboard/pages/hippodrome/hippodrome.ts b/src/app/dashboard/pages/hippodrome/hippodrome.ts
index 4cf34ee..69fd188 100644
--- a/src/app/dashboard/pages/hippodrome/hippodrome.ts
+++ b/src/app/dashboard/pages/hippodrome/hippodrome.ts
@@ -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);
},
});
diff --git a/src/app/dashboard/pages/limits/limits.ts b/src/app/dashboard/pages/limits/limits.ts
index 1a6b0f8..0cde4cb 100644
--- a/src/app/dashboard/pages/limits/limits.ts
+++ b/src/app/dashboard/pages/limits/limits.ts
@@ -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: () => {
diff --git a/src/app/dashboard/pages/main/main.html b/src/app/dashboard/pages/main/main.html
index 7c4dcd8..2a635c3 100644
--- a/src/app/dashboard/pages/main/main.html
+++ b/src/app/dashboard/pages/main/main.html
@@ -34,11 +34,11 @@
{{ c.nom }}
- @if (c.type) {
+ @if (c.discipline) {
- {{ c.type }}
+ {{ c.discipline }}
}
@@ -61,19 +61,15 @@
>
{{
- c.dateDepartCourse
- ? (c.dateDepartCourse | date : 'short' : undefined : 'fr-FR')
- : '—'
+ c.heureDepartPrevue
}}
- {{ c.reunion.hippodrome.nom }}
+ {{ c.nom }}
- Réunion {{ c.reunion.nom }}
-
- Distance {{ c.distance | number : '1.0-0' }} m
+ Distance {{ c.distanceMetres | number : '1.0-0' }} m
- {{ c.partants }} partant{{ c.partants > 1 ? 's' : '' }}
+ {{ c.nombrePartants }} partant{{ c.nombrePartants > 1 ? 's' : '' }}
@if (c.nonPartants && c.nonPartants.length > 0) {
{{ c.nonPartants.length }} non-partant{{ c.nonPartants.length > 1 ? 's' : '' }}
- } @if (c.condition) {
+ } @if (c.numero) {
- {{ c.condition }}
- } @if (c.particularite) {
+ {{ c.numero }}
+ } @if (c.discipline) {
- ⭐ {{ c.particularite }}
+ ⭐ {{ c.discipline }}
}
diff --git a/src/app/dashboard/pages/main/main.ts b/src/app/dashboard/pages/main/main.ts
index ead5990..96287cd 100644
--- a/src/app/dashboard/pages/main/main.ts
+++ b/src/app/dashboard/pages/main/main.ts
@@ -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);
diff --git a/src/app/dashboard/pages/report-courses/report-detail.ts b/src/app/dashboard/pages/report-courses/report-detail.ts
index f003edc..5fd4a52 100644
--- a/src/app/dashboard/pages/report-courses/report-detail.ts
+++ b/src/app/dashboard/pages/report-courses/report-detail.ts
@@ -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(undefined);
- editMode = signal(false);
- editedRows = signal([]);
- private originalRows = signal([]);
+// @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(undefined);
+// editMode = signal(false);
+// editedRows = signal([]);
+// private originalRows = signal([]);
- 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
+// );
+// }
+// }
diff --git a/src/app/dashboard/pages/report-courses/report-list.ts b/src/app/dashboard/pages/report-courses/report-list.ts
index 7e1d1e3..05ad844 100644
--- a/src/app/dashboard/pages/report-courses/report-list.ts
+++ b/src/app/dashboard/pages/report-courses/report-list.ts
@@ -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([]);
- total = signal(0);
- page = signal(1);
- perPage = signal(10);
- search = signal('');
- sort = signal({ 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([]);
+// total = signal(0);
+// page = signal(1);
+// perPage = signal(10);
+// search = signal('');
+// sort = signal({ key: 'date', dir: 'desc' });
+// loading = signal(false);
- cols: TableColumn[] = [
- { 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[] = [
+// { 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]);
+// }
+// }
diff --git a/src/app/dashboard/pages/reunion/reunion.ts b/src/app/dashboard/pages/reunion/reunion.ts
index bc7a3c9..ce56d27 100644
--- a/src/app/dashboard/pages/reunion/reunion.ts
+++ b/src/app/dashboard/pages/reunion/reunion.ts
@@ -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: () => {
diff --git a/src/app/dashboard/pages/roles/roles.ts b/src/app/dashboard/pages/roles/roles.ts
index e1487c4..1b4c2c3 100644
--- a/src/app/dashboard/pages/roles/roles.ts
+++ b/src/app/dashboard/pages/roles/roles.ts
@@ -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: () => {
diff --git a/src/app/dashboard/pages/tpe/tpe.ts b/src/app/dashboard/pages/tpe/tpe.ts
index cf80d36..135e380 100644
--- a/src/app/dashboard/pages/tpe/tpe.ts
+++ b/src/app/dashboard/pages/tpe/tpe.ts
@@ -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: () => {
diff --git a/src/app/dashboard/pages/users/users.ts b/src/app/dashboard/pages/users/users.ts
index 25f6250..ba5cecf 100644
--- a/src/app/dashboard/pages/users/users.ts
+++ b/src/app/dashboard/pages/users/users.ts
@@ -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: () => {
diff --git a/src/app/shared/forms/agent-form/agent-form.ts b/src/app/shared/forms/agent-form/agent-form.ts
index 4a8cdb1..781414f 100644
--- a/src/app/shared/forms/agent-form/agent-form.ts
+++ b/src/app/shared/forms/agent-form/agent-form.ts
@@ -56,7 +56,7 @@ export class AgentForm {
this.limitService
.list({ page: 1, perPage: 100, search: '', sortKey: 'nom', sortDir: 'asc' } as any)
- .subscribe((res) => (this.limits = res.data));
+ .subscribe((res) => (this.limits = res.content));
}
error(control: string): string {
diff --git a/src/app/shared/forms/agent-full-form/agent-full-form.ts b/src/app/shared/forms/agent-full-form/agent-full-form.ts
index c705921..fe37d48 100644
--- a/src/app/shared/forms/agent-full-form/agent-full-form.ts
+++ b/src/app/shared/forms/agent-full-form/agent-full-form.ts
@@ -90,7 +90,7 @@ export class AgentFullForm {
});
this.limitService.list({ page: 1, perPage: 100, search: '', sortKey: 'nom', sortDir: 'asc' } as any).subscribe((res) => {
- this.limits = res.data;
+ this.limits = res.content;
// Find default limit
const defaultLimit = this.limits.find((l) => l.isDefault);
@@ -256,7 +256,7 @@ export class AgentFullForm {
.subscribe((res) => {
// Only show VALIDE TPEs that are either not assigned or assigned to this agent
const currentAgentId = this.value?.id;
- this.tpeRows = res.data.filter((t) => {
+ this.tpeRows = res.content.filter((t) => {
if (t.statut !== 'VALIDE') return false;
// If TPE is assigned but to this agent, show it
if (t.assigne && currentAgentId) {
diff --git a/src/app/shared/forms/course-form/course-form.html b/src/app/shared/forms/course-form/course-form.html
index 5e091be..487bb01 100644
--- a/src/app/shared/forms/course-form/course-form.html
+++ b/src/app/shared/forms/course-form/course-form.html
@@ -19,26 +19,28 @@
@@ -197,29 +176,6 @@
-
-
-
-
-
- @if (loadingReunions()) {
- Chargement des réunions...
- } @else { @for (r of filteredReunions(); track r.id) {
-
- {{ r.nom }} – {{ r.hippodrome.nom }} ({{ r.hippodrome.ville }})
-
- } }
-
-
-
@@ -239,15 +195,18 @@
Types de paris ouverts (CSV)
-
+
+ @for (t of courseTypes; track t.value) {
+ {{ t.label }}
+ }
+
+ Séparez les types par des virgules.
@@ -257,14 +216,14 @@
>
@@ -279,7 +238,7 @@
z-input
type="number"
min="1"
- formControlName="distance"
+ formControlName="distanceMetres"
class="w-full px-4 py-2.5 rounded-lg border border-gray-300 dark:border-gray-600 focus:ring-2 focus:ring-orange-500 dark:bg-gray-800 dark:text-gray-100"
/>
@@ -287,13 +246,13 @@
Catégorie
@@ -330,14 +289,14 @@
N° de la course
diff --git a/src/app/shared/forms/course-form/course-form.ts b/src/app/shared/forms/course-form/course-form.ts
index fd4a291..ceb4119 100644
--- a/src/app/shared/forms/course-form/course-form.ts
+++ b/src/app/shared/forms/course-form/course-form.ts
@@ -24,11 +24,13 @@ import { ZardFormModule } from '@shared/components/form/form.module';
import { ZardInputDirective } from '@shared/components/input/input.directive';
import { ZardSelectItemComponent } from '@shared/components/select/select-item.component';
import { ZardSelectComponent } from '@shared/components/select/select.component';
-import { Course, CourseStatut, CourseType } from 'src/app/core/interfaces/course';
-import { Reunion } from 'src/app/core/interfaces/reunion';
-import { ReunionService } from 'src/app/core/services/reunion';
import { Subscription } from 'rxjs';
+import { Hippodrome } from 'src/app/core/interfaces/hippodrome';
+import { Course, CourseStatut, CourseType } from 'src/app/core/interfaces/course';
+import { HippodromeService } from 'src/app/core/services/hippodrome';
+import { CourseApiResponse, CourseService } from 'src/app/core/services/course';
+
@Component({
selector: 'app-course-form',
standalone: true,
@@ -38,6 +40,7 @@ import { Subscription } from 'rxjs';
CommonModule,
ReactiveFormsModule,
ZardFormModule,
+
ZardInputDirective,
ZardSelectComponent,
ZardSelectItemComponent,
@@ -45,403 +48,233 @@ import { Subscription } from 'rxjs';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CourseForm implements OnInit, AfterViewInit, OnDestroy {
- @Output() save = new EventEmitter();
+ @Output() save = new EventEmitter>();
@Output() cancel = new EventEmitter();
- private _value?: Course;
- @Input() set value(v: Course | undefined) {
- this._value = v;
- }
- get value(): Course | undefined {
- return this._value;
- }
+ @Input() value?: Course;
form: FormGroup;
submitted = false;
- reunions = signal([]);
- loadingReunions = signal(false);
- searchQuery = signal('');
- selectedReunionLabel = signal('');
- initializing = signal(false);
+ hippodromes = signal([]);
+ loadingHippodromes = signal(false);
+ searchQuery = signal('');
+ selectedHippodromeLabel = signal('');
+
private subs = new Subscription();
constructor(
private fb: FormBuilder,
- private reunionService: ReunionService,
+ private courseServive: CourseService,
+ private hippodromeService: HippodromeService,
private cdr: ChangeDetectorRef
) {
this.form = this.fb.group({
- type: ['', Validators.required],
- numero: [null, [Validators.required, Validators.min(1)]],
- nom: ['', [Validators.required, Validators.minLength(3)]],
- dateDepartCourse: ['', Validators.required],
- dateDebutParis: ['', Validators.required],
- dateFinParis: ['', Validators.required],
- reunionId: new FormControl(null, Validators.required),
- reunionCourse: [1],
- particularite: [''],
- partants: [null, [Validators.required, Validators.min(1)]],
- distance: [''],
- condition: [''],
- statut: [CourseStatut.PROGRAMMEE, Validators.required],
+ hippodromeId: new FormControl(null, Validators.required),
+ reunionNumero: [null, Validators.required],
+ reunionDate: ['', Validators.required],
+ nom: ['', Validators.required],
+ numero: [null, Validators.required],
+ statut: [CourseStatut.BROUILLON, Validators.required],
+ heureDepartPrevu: ['', Validators.required],
+ discipline: ['', Validators.required],
+ distanceMetres: [null, Validators.required],
+ nombrePartants: [null, Validators.required],
+ annulee: [false],
+ categorie: ['', Validators.required],
+ reporteeMemeJour: [false],
+ reporteeAutreJour: [false],
+ incidentTechnique: [false],
+ nonPartants: [[]],
+ typesParisOuverts: [''],
createdBy: ['agent-001'],
validatedBy: [''],
});
- // Watch for reunionId changes to update the label
- // This handles BOTH create and edit modes when user selects a reunion
- this.subs.add(
- this.form.get('reunionId')?.valueChanges.subscribe((reunionId) => {
- // Skip if we're initializing (to avoid interfering with form initialization)
- if (this.initializing()) {
- return;
- }
-
- // Handle empty/null values
- if (!reunionId || reunionId === '') {
- this.selectedReunionLabel.set('');
- return;
- }
-
- // Update label when user selects a reunion (both create and edit)
- if (this.reunions().length > 0) {
- // Try both string and direct comparison since form control might convert types
- const matchingReunion = this.reunions().find(
- (r) => String(r.id) === String(reunionId) || r.id === reunionId
- );
- if (matchingReunion) {
- const reunionLabel = `${matchingReunion.nom} – ${matchingReunion.hippodrome.nom} (${matchingReunion.hippodrome.ville})`;
- this.selectedReunionLabel.set(reunionLabel);
- // Force change detection to ensure the label is displayed immediately
- this.cdr.markForCheck();
- } else {
- this.selectedReunionLabel.set('');
- }
- } else {
- this.selectedReunionLabel.set('');
- }
- }) || new Subscription()
- );
-
- // Effect to handle form initialization when value or reunions change
+ /* =============================
+ FIX 1 — Gestion enable/disable
+ (cause principale du select bloqué)
+ ============================== */
effect(() => {
- const v = this.value;
- const reunionsList = this.reunions();
- const isLoading = this.loadingReunions();
+ const loading = this.loadingHippodromes();
+ const control = this.form.get('hippodromeId');
- // CRITICAL: Enable/disable reunion control based on loading state
- // This is the most important part for create mode to work
- const reunionControl = this.form.get('reunionId');
- if (isLoading) {
- reunionControl?.disable({ emitEvent: false });
+ if (loading) {
+ control?.disable({ emitEvent: false });
} else {
- reunionControl?.enable({ emitEvent: false });
- // Force change detection after enabling to ensure the select is clickable
+ control?.enable({ emitEvent: false });
this.cdr.markForCheck();
}
- // Handle edit mode (value is defined) - populate form with course data
- if (v !== null && v !== undefined) {
- this.initializing.set(true);
+ // Edit mode : appliquer la valeur APRÈS chargement
+ if (this.value && this.hippodromes().length) {
+ const id = String(this.value.hippodrome?.id ?? '');
+ if (id) {
+ this.form.patchValue({ hippodromeId: id }, { emitEvent: false });
- let reunionId: string | null = null;
- let reunionLabel: string = '';
- if (v.reunion?.id) {
- reunionId = String(v.reunion.id);
- if (reunionsList.length > 0) {
- const matchingReunion = reunionsList.find((r) => String(r.id) === reunionId);
- if (matchingReunion) {
- reunionLabel = `${matchingReunion.nom} – ${matchingReunion.hippodrome.nom} (${matchingReunion.hippodrome.ville})`;
- this.selectedReunionLabel.set(reunionLabel);
- } else {
- reunionId = null;
- this.selectedReunionLabel.set('');
- }
- } else {
- if (v.reunion.nom) {
- reunionLabel = `${v.reunion.nom} – ${v.reunion.hippodrome?.nom || ''} (${
- v.reunion.hippodrome?.ville || ''
- })`;
- this.selectedReunionLabel.set(reunionLabel);
- }
- reunionId = null;
- }
- } else {
- this.selectedReunionLabel.set('');
- }
-
- this.form.patchValue(
- {
- type: v.type ?? '',
- numero: v.numero ?? null,
- nom: v.nom ?? '',
- dateDepartCourse: v.dateDepartCourse ?? '',
- dateDebutParis: v.dateDebutParis ?? v.dateDepartCourse ?? '',
- dateFinParis: v.dateFinParis ?? v.dateDepartCourse ?? '',
- reunionId,
- reunionCourse: (v as any).reunionCourse ?? v.numero ?? 1,
- particularite: (v as any).particularite ?? '',
- partants: (v as any).partants ?? null,
- distance: (v as any).distance ?? null,
- condition: (v as any).condition ?? '',
- statut: v.statut ?? CourseStatut.PROGRAMMEE,
- createdBy: (v as any).createdBy ?? 'agent-001',
- validatedBy: (v as any).validatedBy ?? '',
- },
- { emitEvent: false }
- );
-
- this.form.markAsPristine();
- this.form.markAsUntouched();
- queueMicrotask(() => this.initializing.set(false));
- }
- // Create mode (v === null or undefined) - DO NOTHING except ensure control is enabled
- // The form already has default values, just let the user fill it
- // The valueChanges subscription will handle label updates when user selects
-
- // When reunions finish loading - re-apply value if we have one (for edit mode)
- else if (reunionsList.length > 0 && !isLoading) {
- // Reunions just finished loading - re-apply value if we have one
- const currentValue = this.value;
- if (currentValue?.reunion?.id) {
- const reunionId = String(currentValue.reunion.id);
- const matchingReunion = reunionsList.find((r) => String(r.id) === reunionId);
- if (matchingReunion) {
- // Set the label manually
- const reunionLabel = `${matchingReunion.nom} – ${matchingReunion.hippodrome.nom} (${matchingReunion.hippodrome.ville})`;
- this.selectedReunionLabel.set(reunionLabel);
- // Wait for Angular to render the select items
- setTimeout(() => {
- this.form.patchValue({ reunionId }, { emitEvent: false });
- this.cdr.detectChanges();
- }, 50);
+ const h = this.hippodromes().find(r => String(r.id) === id);
+ if (h) {
+ this.selectedHippodromeLabel.set(`${h.nom} – (${h.ville})`);
}
}
}
});
- }
- private hydrateFromValue(v?: Course) {
- if (v) {
- const patch = {
- type: v.type ?? '',
- numero: v.numero ?? null,
- nom: v.nom ?? '',
- dateDepartCourse: v.dateDepartCourse ?? '',
- dateDebutParis: v.dateDebutParis ?? v.dateDepartCourse ?? '',
- dateFinParis: v.dateFinParis ?? v.dateDepartCourse ?? '',
- reunionId: (v as any).reunionId ?? v.reunion?.id ?? '',
- reunionCourse: (v as any).reunionCourse ?? v.numero ?? 1,
- particularite: (v as any).particularite ?? '',
- partants: (v as any).partants ?? null,
- distance: (v as any).distance ?? null,
- condition: (v as any).condition ?? '',
- statut: v.statut ?? CourseStatut.PROGRAMMEE,
- createdBy: (v as any).createdBy ?? 'agent-001',
- validatedBy: (v as any).validatedBy ?? '',
- };
- this.form.reset(patch);
- this.form.markAsPristine();
- this.form.markAsUntouched();
- } else {
- this.form.reset({
- type: '',
- numero: null,
- nom: '',
- dateDepartCourse: '',
- dateDebutParis: '',
- dateFinParis: '',
- reunionId: '',
- reunionCourse: 1,
- particularite: '',
- partants: null,
- distance: null,
- condition: '',
- statut: CourseStatut.PROGRAMMEE,
- createdBy: 'agent-001',
- validatedBy: '',
- });
- this.form.markAsPristine();
- this.form.markAsUntouched();
- }
- }
-
- isInvalid(control: string): boolean {
- const ctrl = this.form.get(control);
- return !!(ctrl && ctrl.invalid && (ctrl.touched || this.submitted));
- }
-
- errorMessage(control: string): string | null {
- const c = this.form.get(control);
- if (!c || !c.errors) return null;
- if (c.errors['required']) return 'Ce champ est obligatoire';
- if (c.errors['minlength']) return `Minimum ${c.errors['minlength'].requiredLength} caractères`;
- if (c.errors['min']) return `Valeur minimale : ${c.errors['min'].min}`;
- return null;
- }
-
- getDatePart(control: string): string {
- const val = this.form.get(control)?.value;
- return val ? new Date(val).toISOString().slice(0, 10) : '';
- }
-
- getTimePart(control: string): string {
- const val = this.form.get(control)?.value;
- if (!val) return '';
- const d = new Date(val);
- return d.toISOString().slice(11, 16);
- }
-
- setDatePart(control: string, date: string) {
- const current = new Date(this.form.get(control)?.value || new Date());
- const [h, m] = [current.getHours(), current.getMinutes()];
- const newDate = new Date(
- `${date}T${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:00Z`
- );
- this.form.patchValue({ [control]: newDate.toISOString() });
- }
-
- setTimePart(control: string, time: string) {
- const current = new Date(this.form.get(control)?.value || new Date());
- const [h, m] = time.split(':').map(Number);
- current.setHours(h, m);
- this.form.patchValue({ [control]: current.toISOString() });
- }
-
- onSubmit() {
- this.submitted = true;
- if (!this.form.valid) {
- this.form.markAllAsTouched();
- return;
- }
-
- const raw = this.form.getRawValue() as any;
-
- // Find the reunion object from the reunions list
- const reunionId = raw.reunionId;
- const reunion = this.reunions().find((r) => String(r.id) === String(reunionId));
-
- if (!reunion) {
- console.error('Reunion not found:', reunionId);
- return;
- }
-
- const payload: Partial = {
- ...(this.value ?? {}),
- type: raw.type,
- numero: +raw.numero,
- nom: raw.nom,
- dateDepartCourse: raw.dateDepartCourse,
- dateDebutParis: raw.dateDebutParis,
- dateFinParis: raw.dateFinParis,
- reunion: reunion!, // Will be set if reunion is found
- reunionCourse: +raw.reunionCourse,
- particularite: raw.particularite ?? '',
- partants: +raw.partants,
- distance: +raw.distance,
- condition: raw.condition ?? '',
- statut: raw.statut,
- createdBy: raw.createdBy,
- validatedBy: raw.validatedBy || null,
- };
-
- // Ensure reunion is found
- if (!reunion) {
- console.error('Reunion not found:', reunionId);
- return;
- }
-
- this.save.emit(payload as Course);
- }
-
- // === Filter Reunions ===
- filteredReunions = computed(() => {
- const q = this.searchQuery().toLowerCase();
- return this.reunions().filter(
- (r) =>
- r.nom.toLowerCase().includes(q) ||
- r.hippodrome.nom.toLowerCase().includes(q) ||
- r.hippodrome.ville.toLowerCase().includes(q)
- );
- });
-
- courseTypes = [
- { label: 'Tiercé', value: CourseType.TIERCE },
- { label: 'Quarté + Tiercé', value: CourseType.QUARTE },
- { label: 'Quinté + Tiercé', value: CourseType.QUINTE },
- ];
-
- courseStatus = [
- { label: 'Programmée', value: CourseStatut.PROGRAMMEE },
- { label: 'Créée', value: CourseStatut.CREATED },
- { label: 'Validée', value: CourseStatut.VALIDATED },
- { label: 'En cours', value: CourseStatut.RUNNING },
- { label: 'Clôturée', value: CourseStatut.CLOSED },
- { label: 'Annulée', value: CourseStatut.CANCELED },
- ];
-
- ngOnInit() {
- // Fetch reunions from API
- this.loadingReunions.set(true);
+ /* =============================
+ FIX 2 — valueChanges propre
+ ============================== */
this.subs.add(
- this.reunionService.list({ page: 1, perPage: 1000 }, false).subscribe({
- next: (result) => {
- this.reunions.set(result.data);
- this.loadingReunions.set(false);
- // Force enable the control after loading
- setTimeout(() => {
- const reunionControl = this.form.get('reunionId');
- reunionControl?.enable({ emitEvent: false });
- this.cdr.markForCheck();
- }, 100);
- },
- error: (err) => {
- console.error('Error loading reunions:', err);
- this.loadingReunions.set(false);
- },
+ this.form.get('hippodromeId')!.valueChanges.subscribe((id) => {
+ if (!id) {
+ this.selectedHippodromeLabel.set('');
+ return;
+ }
+
+ const h = this.hippodromes().find(r => String(r.id) === String(id));
+ if (h) {
+ this.selectedHippodromeLabel.set(`${h.nom} – (${h.ville})`);
+ this.cdr.markForCheck();
+ }
})
);
}
- ngAfterViewInit() {
- // After view is initialized, ensure the reunion value and label are set correctly
- const currentValue = this.value;
- if (currentValue?.reunion?.id && this.reunions().length > 0) {
- const reunionId = String(currentValue.reunion.id);
- const matchingReunion = this.reunions().find((r) => String(r.id) === reunionId);
- if (matchingReunion) {
- // Set the label manually
- const reunionLabel = `${matchingReunion.nom} – ${matchingReunion.hippodrome.nom} (${matchingReunion.hippodrome.ville})`;
- this.selectedReunionLabel.set(reunionLabel);
- // Wait a bit for the select items to be fully rendered
- setTimeout(() => {
- const currentFormValue = this.form.get('reunionId')?.value;
- if (String(currentFormValue) !== reunionId) {
- this.form.patchValue({ reunionId }, { emitEvent: false });
- this.cdr.detectChanges();
- }
- }, 100);
- }
- }
+ /* =============================
+ FIX 3 — vrai filter
+ ============================== */
+ filteredHippodromes = computed(() => {
+ const q = this.searchQuery().toLowerCase();
+ if (!q) return this.hippodromes();
+
+ return this.hippodromes().filter(h =>
+ h.nom.toLowerCase().includes(q) ||
+ h.ville.toLowerCase().includes(q) ||
+ (h as any).pays?.toLowerCase().includes(q)
+ );
+ });
+
+ ngOnInit() {
+ this.loadingHippodromes.set(true);
+
+ this.subs.add(
+ this.hippodromeService
+ .list({ page: 1, perPage: 1000 }, true)
+ .subscribe({
+ next: (res) => {
+ this.hippodromes.set(res.content);
+ this.loadingHippodromes.set(false);
+ },
+ error: () => {
+ this.loadingHippodromes.set(false);
+ },
+ })
+ );
}
- onReunionSelectionChange(value: string) {
- // Immediately update the label when user selects a reunion
- if (value && this.reunions().length > 0) {
- const matchingReunion = this.reunions().find(
- (r) => String(r.id) === String(value) || r.id === value
- );
- if (matchingReunion) {
- const reunionLabel = `${matchingReunion.nom} – ${matchingReunion.hippodrome.nom} (${matchingReunion.hippodrome.ville})`;
- this.selectedReunionLabel.set(reunionLabel);
- this.cdr.markForCheck();
- } else {
- }
- }
+ ngAfterViewInit() {
+ this.cdr.markForCheck();
}
+ isInvalid(control: string): boolean {
+ const c = this.form.get(control);
+ return !!(c && c.invalid && (c.touched || this.submitted));
+ }
+
+onSubmit() {
+ this.submitted = true;
+
+ if (this.form.invalid) {
+ this.form.markAllAsTouched();
+ return;
+ }
+
+ const raw = this.form.getRawValue() as any;
+
+ // 1️⃣ Résoudre l'hippodrome sélectionné
+ const hippodromeId = raw.hippodromeId;
+ const foundHippodrome = this.hippodromes().find(h => String(h.id) === String(hippodromeId));
+ const hippodromeObj = foundHippodrome ?? (hippodromeId ? { id: +hippodromeId } : undefined);
+
+
+ // 2️⃣ Transformer typesParisOuverts CSV → tableau
+ const typesParis = raw.typesParisOuverts
+ ? raw.typesParisOuverts.split(',').map((s: string) => s.trim()).filter(Boolean)
+ : [];
+
+ // 3️⃣ Construire payload
+ const payload: Partial = {
+ ...this.value, // inclut les champs existants si édition
+ hippodromeId: raw.hippodromeId,
+ reunionNumero: raw.reunionNumero ? +raw.reunionNumero : undefined,
+ reunionDate: raw.reunionDate,
+ nom: raw.nom,
+ numero: raw.numero ? +raw.numero : undefined,
+ statut: raw.statut,
+ discipline: raw.discipline,
+ heureDepartPrevue: new Date(raw.reunionDate+raw.heureDepartPrevu).toISOString(),
+ distanceMetres: raw.distanceMetres ? +raw.distanceMetres : undefined,
+ nombrePartants: raw.nombrePartants ? +raw.nombrePartants : undefined,
+ typesParisOuverts: typesParis,
+ annulee: raw.annulee ?? false,
+ reporteeMemeJour: raw.reporteeMemeJour ?? false,
+ reporteeAutreJour: raw.reporteeAutreJour ?? false,
+ incidentTechnique: raw.incidentTechnique ?? false,
+ nonPartants: raw.nonPartants ?? [],
+ categorie: raw.categorie,
+ };
+
+ console.log(payload);
+ // 4️⃣ Appeler le service (create ou update)
+ if (this.value?.id) {
+ this.courseServive.update(this.value.id, payload).subscribe({
+ next: () => this.save.emit(payload),
+ error: err => console.error('Erreur update course', err)
+ });
+ } else {
+ this.courseServive.create(payload).subscribe({
+ next: () => this.save.emit(payload),
+ error: err => console.error(err)
+ });
+ }
+}
+
+
+
+errorMessage(control: string): string | null {
+ const c = this.form.get(control);
+ if (!c || !c.errors) return null;
+ if (c.errors['required']) return 'Ce champ est obligatoire';
+ if (c.errors['minlength']) return `Minimum ${c.errors['minlength'].requiredLength} caractères`;
+ if (c.errors['min']) return `Valeur minimale : ${c.errors['min'].min}`;
+ return null;
+}
+
+
ngOnDestroy() {
this.subs.unsubscribe();
}
+
+ courseTypes = [
+ { label: 'Gagnant', value: CourseType.GAGNANT },
+ { label: 'Placé', value: CourseType.PLACE },
+ { label: 'Jumélé gagnant', value: CourseType.JUMELE_GAGNANT},
+ { label: 'Jumélé placé', value: CourseType.JUMELE_PLACE},
+ { label: 'Jumélé ordre', value: CourseType.JUMELE_ORDRE},
+ { label: 'Trio', value: CourseType.TRIO},
+ { label: 'Trio ordre', value: CourseType.TRIO_ORDRE},
+ { label: 'Triplet', value: CourseType.TRIPLET},
+ { label: 'Quatro', value: CourseType.QUATRO},
+ { label: 'Quinte', value: CourseType.QUINTE},
+ ];
+
+
+ courseStatus = [
+ { label: 'Brouillon', value: CourseStatut.BROUILLON },
+ { label: 'Validé', value: CourseStatut.VALIDE },
+ { label: 'Fremé', value: CourseStatut.FERME },
+ { label: 'Resultat Provisoire', value: CourseStatut.RESULTAT_PROVISOIRE },
+ { label: 'Resultat officiel', value: CourseStatut.RESULTAT_OFFICIEL },
+ { label: 'Reglée', value: CourseStatut.REGLEE },
+ { label: 'Annulée', value: CourseStatut.ANNULEE },
+ ];
}
diff --git a/src/app/shared/forms/nonpartant-form/nonpartant-form.ts b/src/app/shared/forms/nonpartant-form/nonpartant-form.ts
index a516c7f..47c4bca 100644
--- a/src/app/shared/forms/nonpartant-form/nonpartant-form.ts
+++ b/src/app/shared/forms/nonpartant-form/nonpartant-form.ts
@@ -121,7 +121,7 @@ export class NonPartantForm implements OnInit, OnChanges, OnDestroy {
}
private seedFromCourse() {
- const max = this.course?.partants ?? 0;
+ const max = this.course?.nombrePartants ?? 0;
this.partantsMax.set(max);
const arr = new FormArray>([]);
diff --git a/src/app/shared/forms/resultat-form/resultat-form.html b/src/app/shared/forms/resultat-form/resultat-form.html
index 2289212..085e191 100644
--- a/src/app/shared/forms/resultat-form/resultat-form.html
+++ b/src/app/shared/forms/resultat-form/resultat-form.html
@@ -4,7 +4,7 @@
{{ course.nom }}
- {{ course.reunion.nom }} • {{ course.reunion.hippodrome.nom }}
+ {{ course.nom }}
diff --git a/src/app/shared/forms/resultat-form/resultat-form.ts b/src/app/shared/forms/resultat-form/resultat-form.ts
index 5afd8f4..d8ad5fd 100644
--- a/src/app/shared/forms/resultat-form/resultat-form.ts
+++ b/src/app/shared/forms/resultat-form/resultat-form.ts
@@ -35,9 +35,9 @@ export class ResultatForm {
});
reqLen = computed(() =>
- this.course?.type === CourseType.TIERCE ? 3 : this.course?.type === CourseType.QUARTE ? 4 : 5
+ 3
);
- maxNum = computed(() => this.course?.partants ?? 0);
+ maxNum = computed(() => this.course?.nombrePartants ?? 0);
npSet = computed(() => new Set(this.course?.nonPartants ?? []));
statut = computed((): 'CREATED' | 'VALIDATED' | 'NONE' => {
return this.resultat ? 'CREATED' : 'NONE';
diff --git a/src/app/shared/forms/reunion-form/reunion-form.ts b/src/app/shared/forms/reunion-form/reunion-form.ts
index 31bdc73..9b62e34 100644
--- a/src/app/shared/forms/reunion-form/reunion-form.ts
+++ b/src/app/shared/forms/reunion-form/reunion-form.ts
@@ -229,7 +229,7 @@ export class ReunionForm implements OnInit, AfterViewInit, OnDestroy {
this.subs.add(
this.hippodromeService.list({ page: 1, perPage: 1000 }, false).subscribe({
next: (result) => {
- this.hippodromes.set(result.data);
+ this.hippodromes.set(result.content);
this.loadingHippodromes.set(false);
// The effect will automatically re-run when hippodromes signal updates
},
diff --git a/src/app/shared/forms/user-form/user-form.ts b/src/app/shared/forms/user-form/user-form.ts
index 87b2f8d..a22f107 100644
--- a/src/app/shared/forms/user-form/user-form.ts
+++ b/src/app/shared/forms/user-form/user-form.ts
@@ -63,7 +63,7 @@ export class UserForm {
this.roleService
.list({ page: 1, perPage: 100, search: '', sortKey: 'name', sortDir: 'asc' } as any)
.subscribe((res) => {
- this.roles = res.data as any;
+ this.roles = res.content as any;
});
}
diff --git a/src/app/shared/paging/normalize-page.ts b/src/app/shared/paging/normalize-page.ts
index f6fa39f..c790ac2 100644
--- a/src/app/shared/paging/normalize-page.ts
+++ b/src/app/shared/paging/normalize-page.ts
@@ -7,69 +7,34 @@ import { PagedResult, PageMeta } from './paging';
export function normalizePage(raw: any, reqPage: number, perPage: number): PagedResult {
// 🟩 Case 1 — Spring Data style: { content, totalElements, number, size }
if (raw && Array.isArray(raw.content) && typeof raw.totalElements === 'number') {
- return {
- data: raw.content as T[],
- meta: {
- page: (raw.number ?? 0) + 1,
- perPage: raw.size ?? perPage,
- total: raw.totalElements,
- ...(raw.meta ?? {}), // merge extra meta if provided
- } as PageMeta,
- };
+ return raw;
}
// 🟩 Case 2 — API or local mock: { data, meta: { total, ...extra } }
- if (raw && Array.isArray(raw.data) && raw.meta?.total != null) {
- return {
- data: raw.data as T[],
- meta: {
- page: raw.meta.page ?? reqPage,
- perPage: raw.meta.perPage ?? perPage,
- total: raw.meta.total,
- ...raw.meta, // keep any custom stats
- } as PageMeta,
- };
+ if (raw && Array.isArray(raw.content) && raw.pageable?.total != null) {
+ return raw
}
- // 🟩 Case 3 — Generic REST: { items, total | total_count, ...extra }
- if (raw && Array.isArray(raw.items) && (raw.total != null || raw.total_count != null)) {
- const total = raw.total ?? raw.total_count;
- return {
- data: raw.items as T[],
- meta: {
- page: reqPage,
- perPage,
- total,
- ...raw.meta, // optional
- } as PageMeta,
- };
- }
// 🟩 Case 4 — Direct array (no meta)
if (Array.isArray(raw)) {
const start = (reqPage - 1) * perPage;
const data = (raw as T[]).slice(start, start + perPage);
return {
- data,
- meta: {
- page: reqPage,
- perPage,
- total: (raw as T[]).length,
- } as PageMeta,
+ content: data,
+ pageable:{
+ pageNumber: raw.length/perPage,
+ pageSize: perPage,
+ total: raw.length
+ },
+ totalPages: raw.length/perPage,
+ totalElements: raw.length
};
}
// 🟩 Fallback — ensure consistency even with minimal info
- const data = Array.isArray(raw?.data) ? (raw.data as T[]) : [];
+ const data = Array.isArray(raw?.content) ? (raw.content as T[]) : [];
const total = typeof raw?.total === 'number' ? raw.total : data.length ?? 0;
- return {
- data,
- meta: {
- page: raw?.meta?.page ?? reqPage,
- perPage: raw?.meta?.perPage ?? perPage,
- total,
- ...raw?.meta, // merge additional stats safely
- } as PageMeta,
- };
+ return raw;
}
diff --git a/src/app/shared/paging/paging.ts b/src/app/shared/paging/paging.ts
index 3ddf760..75c880e 100644
--- a/src/app/shared/paging/paging.ts
+++ b/src/app/shared/paging/paging.ts
@@ -11,15 +11,16 @@ export interface ListParams {
}
export interface PageMeta {
- page: number; // 1-based
- perPage: number;
+ pageNumber: number; // 1-based
+ pageSize: number;
total: number; // -1 if unknown
- [key: string]: any;
}
export interface PagedResult {
- data: T[];
- meta: PageMeta;
+ content: T[];
+ pageable: PageMeta;
+ totalPages: number;
+ totalElements: number;
}
export interface BackendConfig {
diff --git a/src/environments/environment.development.ts b/src/environments/environment.development.ts
index 5bd797b..1c5244f 100644
--- a/src/environments/environment.development.ts
+++ b/src/environments/environment.development.ts
@@ -1,4 +1,4 @@
export const environment = {
production: false,
- apiBaseUrl: 'https://custody-holding-rogers-less.trycloudflare.com',
+ apiBaseUrl: 'https://ddd3b90fc1ef.ngrok-free.app',
};
diff --git a/src/environments/environment.ts b/src/environments/environment.ts
index 5bd797b..1c5244f 100644
--- a/src/environments/environment.ts
+++ b/src/environments/environment.ts
@@ -1,4 +1,4 @@
export const environment = {
production: false,
- apiBaseUrl: 'https://custody-holding-rogers-less.trycloudflare.com',
+ apiBaseUrl: 'https://ddd3b90fc1ef.ngrok-free.app',
};