course creation
This commit is contained in:
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import { ZardCardComponent } from '@shared/components/card/card.component';
|
||||
import { ZardButtonComponent } from '@shared/components/button/button.component';
|
||||
import { Course as CourseType } from 'src/app/core/interfaces/course';
|
||||
import { SortDir } from '@shared/paging/paging';
|
||||
import { CourseService } from 'src/app/core/services/course';
|
||||
import { CourseApiResponse, CourseService } from 'src/app/core/services/course';
|
||||
import { ResultatService } from 'src/app/core/services/resultat';
|
||||
import { Resultat } from 'src/app/core/interfaces/resultat';
|
||||
import { A11yModule } from '@angular/cdk/a11y';
|
||||
@@ -77,23 +77,19 @@ export class Course {
|
||||
key: 'type',
|
||||
label: 'Type',
|
||||
sortable: true,
|
||||
cell: (c) => `<span class="font-medium">${c.type}</span>`,
|
||||
cell: (c) => `<span class="font-medium">${c.discipline}</span>`,
|
||||
},
|
||||
{
|
||||
key: 'dateDepartCourse',
|
||||
label: 'Date et Heure Départ',
|
||||
sortable: true,
|
||||
cell: (c) =>
|
||||
new Date(c.dateDepartCourse).toLocaleDateString('fr-FR', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
}),
|
||||
cell: (c) => c.heureDepartPrevue
|
||||
},
|
||||
{
|
||||
key: 'partants',
|
||||
label: 'Partants',
|
||||
cell: (c) =>
|
||||
`<span>${c.partants}</span> <span class="text-xs text-red-500">(${
|
||||
`<span>${c.nombrePartants}</span> <span class="text-xs text-red-500">(${
|
||||
c.nonPartants?.length ?? 0
|
||||
} NP)</span>`,
|
||||
},
|
||||
@@ -148,20 +144,24 @@ export class Course {
|
||||
sortable: true,
|
||||
cell: (c) => {
|
||||
const colorMap: Record<string, string> = {
|
||||
PROGRAMMEE: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300',
|
||||
CREATED: 'bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-300',
|
||||
VALIDATED: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300',
|
||||
RUNNING: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
|
||||
CLOSED: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300',
|
||||
CANCELED: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300',
|
||||
OUVERT: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300',
|
||||
RESULTAT_PROVISOIRE: 'bg-cyan-100 text-purple-700 dark:bg-cyan-900/30 dark:text-cyan-300',
|
||||
RESULTAT_OFFICIEL: 'bg-amber-100 text-purple-700 dark:bg-amber-900/30 dark:text-amber-300',
|
||||
BROUILLON: 'bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-300',
|
||||
VALIDE: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300',
|
||||
REGLEE: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
|
||||
FERME: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300',
|
||||
ANNULEE: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300',
|
||||
};
|
||||
const labelMap: Record<string, string> = {
|
||||
PROGRAMMEE: 'Programmée',
|
||||
CREATED: 'Créée',
|
||||
VALIDATED: 'Validée',
|
||||
RUNNING: 'En cours',
|
||||
CLOSED: 'Clôturée',
|
||||
CANCELED: 'Annulée',
|
||||
OUVERT: 'Ouvert',
|
||||
RESULTAT_PROVISOIRE: 'Résultat provisoire',
|
||||
RESULTAT_OFFICIEL: 'Résultat officiel',
|
||||
BROUILLON: 'Brouillon',
|
||||
VALIDE: 'Validé',
|
||||
REGLEE: 'Réglée',
|
||||
FERME: 'Fermé',
|
||||
ANNULEE: 'Annulée'
|
||||
};
|
||||
return `<span class="px-2 py-1 rounded-full text-xs font-semibold ${colorMap[c.statut]}">${
|
||||
labelMap[c.statut]
|
||||
@@ -171,31 +171,13 @@ export class Course {
|
||||
{
|
||||
key: 'reunion.hippodrome.nom',
|
||||
label: 'Hippodrome',
|
||||
cell: (c) => (c.reunion?.hippodrome ? `${c.reunion.hippodrome.nom}` : '—'),
|
||||
},
|
||||
{
|
||||
key: 'reunion.nom',
|
||||
label: 'Réunion',
|
||||
cell: (c) => c.reunion?.nom ?? '—',
|
||||
cell: (c) => (c?.hippodrome ? `${c.hippodrome.nom}` : '—'),
|
||||
},
|
||||
{
|
||||
key: 'distance',
|
||||
label: 'Distance (m)',
|
||||
sortable: true,
|
||||
cell: (c) => c.distance.toLocaleString('fr-FR'),
|
||||
},
|
||||
|
||||
{
|
||||
key: 'createdAt',
|
||||
label: 'Créée le',
|
||||
cell: (c) =>
|
||||
c.createdAt
|
||||
? new Date(c.createdAt).toLocaleDateString('fr-FR', {
|
||||
day: '2-digit',
|
||||
month: 'short',
|
||||
year: 'numeric',
|
||||
})
|
||||
: '—',
|
||||
cell: (c) => c.distanceMetres.toLocaleString('fr-FR'),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -224,14 +206,14 @@ export class Course {
|
||||
this.loading.set(true);
|
||||
this.api.list(params).subscribe({
|
||||
next: (res) => {
|
||||
this.rows.set(res.data);
|
||||
this.total.set(res.meta.total);
|
||||
this.totalRunning.set(res.meta['totalRunning'] ?? 0);
|
||||
this.totalClosed.set(res.meta['totalClosed'] ?? 0);
|
||||
this.totalByType.set(res.meta['totalByType'] ?? {});
|
||||
this.rows.set(res.content);
|
||||
this.total.set(res.totalElements);
|
||||
this.totalRunning.set(0);
|
||||
this.totalClosed.set(0);
|
||||
this.totalByType.set({});
|
||||
|
||||
// Fetch resultats for all courses in parallel
|
||||
const courseIds = res.data.map((c) => c.id);
|
||||
const courseIds = res.content.map((c) => c.id);
|
||||
if (courseIds.length > 0) {
|
||||
const resultatRequests = courseIds.map((id) =>
|
||||
this.resultatService.getByCourseId(id).pipe(catchError(() => of(undefined)))
|
||||
@@ -305,7 +287,7 @@ export class Course {
|
||||
const current = this.editingItem();
|
||||
const req$ = current?.id
|
||||
? this.api.update(current.id, payload)
|
||||
: this.api.create(payload as Omit<CourseType, 'id'>);
|
||||
: this.api.create(payload as Omit<CourseApiResponse, 'id'>);
|
||||
|
||||
req$.subscribe(() => {
|
||||
this.closeModal();
|
||||
@@ -412,7 +394,7 @@ export class Course {
|
||||
return 3; // Default
|
||||
};
|
||||
|
||||
const requiredHorses = getRequiredHorses(c.type);
|
||||
const requiredHorses = 3;
|
||||
|
||||
// Collect all selected horses (flatten the places array)
|
||||
const allHorses: number[] = places
|
||||
|
||||
@@ -33,18 +33,6 @@
|
||||
{{ averageByCountry() }}
|
||||
</div>
|
||||
</z-card>
|
||||
<z-card class="text-center py-4">
|
||||
<div class="text-sm text-gray-500 dark:text-gray-400">Réunions totales</div>
|
||||
<div class="text-3xl font-bold text-purple-600 dark:text-purple-400 mt-1">
|
||||
{{ totalReunions() }}
|
||||
</div>
|
||||
</z-card>
|
||||
<z-card class="text-center py-4">
|
||||
<div class="text-sm text-gray-500 dark:text-gray-400">Courses totales</div>
|
||||
<div class="text-3xl font-bold text-pink-600 dark:text-pink-400 mt-1">
|
||||
{{ totalCourses() }}
|
||||
</div>
|
||||
</z-card>
|
||||
</div>
|
||||
|
||||
<app-search-bar placeholder="Rechercher (nom, ville, pays…)" (search)="onSearch($event)" />
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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: () => {
|
||||
|
||||
@@ -34,11 +34,11 @@
|
||||
<span class="font-medium text-gray-900 dark:text-gray-100 truncate">
|
||||
{{ c.nom }}
|
||||
</span>
|
||||
@if (c.type) {
|
||||
@if (c.discipline) {
|
||||
<span
|
||||
class="inline-flex items-center px-2 py-0.5 rounded text-[10px] font-medium bg-indigo-50 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-300"
|
||||
>
|
||||
{{ c.type }}
|
||||
{{ c.discipline }}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
@@ -61,19 +61,15 @@
|
||||
></path>
|
||||
</svg>
|
||||
{{
|
||||
c.dateDepartCourse
|
||||
? (c.dateDepartCourse | date : 'short' : undefined : 'fr-FR')
|
||||
: '—'
|
||||
c.heureDepartPrevue
|
||||
}}
|
||||
</span>
|
||||
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
|
||||
<span class="font-medium">
|
||||
{{ c.reunion.hippodrome.nom }}
|
||||
{{ c.nom }}
|
||||
</span>
|
||||
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
|
||||
<span> Réunion {{ c.reunion.nom }} </span>
|
||||
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
|
||||
<span> Distance {{ c.distance | number : '1.0-0' }} m </span>
|
||||
<span> Distance {{ c.distanceMetres | number : '1.0-0' }} m </span>
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-wrap items-center gap-2 text-[11px] text-gray-600 dark:text-gray-300"
|
||||
@@ -93,19 +89,19 @@
|
||||
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
|
||||
></path>
|
||||
</svg>
|
||||
{{ c.partants }} partant{{ c.partants > 1 ? 's' : '' }}
|
||||
{{ c.nombrePartants }} partant{{ c.nombrePartants > 1 ? 's' : '' }}
|
||||
</span>
|
||||
@if (c.nonPartants && c.nonPartants.length > 0) {
|
||||
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
|
||||
<span class="text-orange-600 dark:text-orange-400">
|
||||
{{ c.nonPartants.length }} non-partant{{ c.nonPartants.length > 1 ? 's' : '' }}
|
||||
</span>
|
||||
} @if (c.condition) {
|
||||
} @if (c.numero) {
|
||||
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
|
||||
<span class="italic">{{ c.condition }}</span>
|
||||
} @if (c.particularite) {
|
||||
<span class="italic">{{ c.numero }}</span>
|
||||
} @if (c.discipline) {
|
||||
<span class="h-1 w-1 rounded-full bg-gray-400"></span>
|
||||
<span class="text-blue-600 dark:text-blue-400">⭐ {{ c.particularite }}</span>
|
||||
<span class="text-blue-600 dark:text-blue-400">⭐ {{ c.discipline }}</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -1,132 +1,132 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
|
||||
import { ActivatedRoute, RouterModule } from '@angular/router';
|
||||
import { ZardCardComponent } from '@shared/components/card/card.component';
|
||||
import { ReportService } from 'src/app/core/services/report';
|
||||
import { CourseReportDetail, CourseReportDetailRow } from 'src/app/core/interfaces/report';
|
||||
import { ZardButtonComponent } from '@shared/components/button/button.component';
|
||||
// import { CommonModule } from '@angular/common';
|
||||
// import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
|
||||
// import { ActivatedRoute, RouterModule } from '@angular/router';
|
||||
// import { ZardCardComponent } from '@shared/components/card/card.component';
|
||||
// import { ReportService } from 'src/app/core/services/report';
|
||||
// import { CourseReportDetail, CourseReportDetailRow } from 'src/app/core/interfaces/report';
|
||||
// import { ZardButtonComponent } from '@shared/components/button/button.component';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-report-courses-detail',
|
||||
templateUrl: './report-detail.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [CommonModule, RouterModule, ZardCardComponent, ZardButtonComponent],
|
||||
})
|
||||
export class ReportCoursesDetailPage {
|
||||
detail = signal<CourseReportDetail | undefined>(undefined);
|
||||
editMode = signal(false);
|
||||
editedRows = signal<CourseReportDetailRow[]>([]);
|
||||
private originalRows = signal<CourseReportDetailRow[]>([]);
|
||||
// @Component({
|
||||
// standalone: true,
|
||||
// selector: 'app-report-courses-detail',
|
||||
// templateUrl: './report-detail.html',
|
||||
// changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
// imports: [CommonModule, RouterModule, ZardCardComponent, ZardButtonComponent],
|
||||
// })
|
||||
// export class ReportCoursesDetailPage {
|
||||
// detail = signal<CourseReportDetail | undefined>(undefined);
|
||||
// editMode = signal(false);
|
||||
// editedRows = signal<CourseReportDetailRow[]>([]);
|
||||
// private originalRows = signal<CourseReportDetailRow[]>([]);
|
||||
|
||||
constructor(private route: ActivatedRoute, private api: ReportService) {
|
||||
const id = this.route.snapshot.params['id'];
|
||||
this.api.getDetail(id).subscribe((d) => {
|
||||
this.detail.set(d);
|
||||
this.editedRows.set(d?.rows ?? []);
|
||||
this.originalRows.set(d?.rows ? d.rows.map((r) => ({ ...r })) : []);
|
||||
});
|
||||
}
|
||||
// constructor(private route: ActivatedRoute, private api: ReportService) {
|
||||
// const id = this.route.snapshot.params['id'];
|
||||
// this.api.getDetail(id).subscribe((d) => {
|
||||
// this.detail.set(d);
|
||||
// this.editedRows.set(d?.rows ?? []);
|
||||
// this.originalRows.set(d?.rows ? d.rows.map((r) => ({ ...r })) : []);
|
||||
// });
|
||||
// }
|
||||
|
||||
onValidate() {
|
||||
const id = this.detail()?.summary.id;
|
||||
if (!id) return;
|
||||
// Persist edited rows then validate
|
||||
this.api.modifyRows(id, this.editedRows()).subscribe(() => {
|
||||
this.api.validate(id).subscribe((s) => {
|
||||
if (this.detail()) this.detail.set({ summary: s!, rows: this.editedRows() });
|
||||
// Commit current edits as the new baseline
|
||||
this.originalRows.set(this.editedRows().map((r) => ({ ...r })));
|
||||
this.editMode.set(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
onConfirm() {
|
||||
const id = this.detail()?.summary.id;
|
||||
if (!id) return;
|
||||
this.api.confirm(id).subscribe((s) => {
|
||||
if (this.detail()) this.detail.set({ summary: s!, rows: this.editedRows() });
|
||||
// Confirm also commits the current edits as baseline
|
||||
this.originalRows.set(this.editedRows().map((r) => ({ ...r })));
|
||||
this.editMode.set(false);
|
||||
});
|
||||
}
|
||||
onReset() {
|
||||
const id = this.detail()?.summary.id;
|
||||
if (!id) return;
|
||||
this.api.resetStatus(id).subscribe((s) => {
|
||||
if (this.detail()) this.detail.set({ summary: s!, rows: this.detail()!.rows });
|
||||
// Reset discards uncommitted edits
|
||||
this.editedRows.set(this.originalRows().map((r) => ({ ...r })));
|
||||
this.editMode.set(false);
|
||||
});
|
||||
}
|
||||
// onValidate() {
|
||||
// const id = this.detail()?.summary.id;
|
||||
// if (!id) return;
|
||||
// // Persist edited rows then validate
|
||||
// this.api.modifyRows(id, this.editedRows()).subscribe(() => {
|
||||
// this.api.validate(id).subscribe((s) => {
|
||||
// if (this.detail()) this.detail.set({ summary: s!, rows: this.editedRows() });
|
||||
// // Commit current edits as the new baseline
|
||||
// this.originalRows.set(this.editedRows().map((r) => ({ ...r })));
|
||||
// this.editMode.set(false);
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// onConfirm() {
|
||||
// const id = this.detail()?.summary.id;
|
||||
// if (!id) return;
|
||||
// this.api.confirm(id).subscribe((s) => {
|
||||
// if (this.detail()) this.detail.set({ summary: s!, rows: this.editedRows() });
|
||||
// // Confirm also commits the current edits as baseline
|
||||
// this.originalRows.set(this.editedRows().map((r) => ({ ...r })));
|
||||
// this.editMode.set(false);
|
||||
// });
|
||||
// }
|
||||
// onReset() {
|
||||
// const id = this.detail()?.summary.id;
|
||||
// if (!id) return;
|
||||
// this.api.resetStatus(id).subscribe((s) => {
|
||||
// if (this.detail()) this.detail.set({ summary: s!, rows: this.detail()!.rows });
|
||||
// // Reset discards uncommitted edits
|
||||
// this.editedRows.set(this.originalRows().map((r) => ({ ...r })));
|
||||
// this.editMode.set(false);
|
||||
// });
|
||||
// }
|
||||
|
||||
onEditToggle() {
|
||||
if (this.detail()?.summary.confirmed) return;
|
||||
const currentlyEditing = this.editMode();
|
||||
if (currentlyEditing) {
|
||||
// Leaving edit mode without validation: revert to original snapshot
|
||||
this.editedRows.set(this.originalRows().map((r) => ({ ...r })));
|
||||
this.editMode.set(false);
|
||||
} else {
|
||||
this.editMode.set(true);
|
||||
}
|
||||
}
|
||||
// onEditToggle() {
|
||||
// if (this.detail()?.summary.confirmed) return;
|
||||
// const currentlyEditing = this.editMode();
|
||||
// if (currentlyEditing) {
|
||||
// // Leaving edit mode without validation: revert to original snapshot
|
||||
// this.editedRows.set(this.originalRows().map((r) => ({ ...r })));
|
||||
// this.editMode.set(false);
|
||||
// } else {
|
||||
// this.editMode.set(true);
|
||||
// }
|
||||
// }
|
||||
|
||||
onChangeMontant(index: number, value: any) {
|
||||
const v = Number(value);
|
||||
this.editedRows.update((rows: CourseReportDetailRow[]) => {
|
||||
const current = rows[index];
|
||||
if (!current) return rows;
|
||||
current.montant = Number.isFinite(v) ? v : current.montant;
|
||||
return rows;
|
||||
});
|
||||
}
|
||||
// onChangeMontant(index: number, value: any) {
|
||||
// const v = Number(value);
|
||||
// this.editedRows.update((rows: CourseReportDetailRow[]) => {
|
||||
// const current = rows[index];
|
||||
// if (!current) return rows;
|
||||
// current.montant = Number.isFinite(v) ? v : current.montant;
|
||||
// return rows;
|
||||
// });
|
||||
// }
|
||||
|
||||
onChangeNombre(index: number, value: any) {
|
||||
const v = Number(value);
|
||||
this.editedRows.update((rows: CourseReportDetailRow[]) => {
|
||||
const current = rows[index];
|
||||
if (!current) return rows;
|
||||
current.nombre = Number.isFinite(v) ? v : current.nombre;
|
||||
return rows;
|
||||
});
|
||||
}
|
||||
// onChangeNombre(index: number, value: any) {
|
||||
// const v = Number(value);
|
||||
// this.editedRows.update((rows: CourseReportDetailRow[]) => {
|
||||
// const current = rows[index];
|
||||
// if (!current) return rows;
|
||||
// current.nombre = Number.isFinite(v) ? v : current.nombre;
|
||||
// return rows;
|
||||
// });
|
||||
// }
|
||||
|
||||
onToggleDistributed(index: number, value: any) {
|
||||
const checked = !!value;
|
||||
this.editedRows.update((rows: CourseReportDetailRow[]) => {
|
||||
const current = rows[index];
|
||||
if (!current) return rows;
|
||||
current.distributed = checked;
|
||||
return rows;
|
||||
});
|
||||
}
|
||||
// onToggleDistributed(index: number, value: any) {
|
||||
// const checked = !!value;
|
||||
// this.editedRows.update((rows: CourseReportDetailRow[]) => {
|
||||
// const current = rows[index];
|
||||
// if (!current) return rows;
|
||||
// current.distributed = checked;
|
||||
// return rows;
|
||||
// });
|
||||
// }
|
||||
|
||||
onToggleExterne(index: number, value: any) {
|
||||
const checked = !!value;
|
||||
this.editedRows.update((rows: CourseReportDetailRow[]) => {
|
||||
const current = rows[index];
|
||||
if (!current) return rows;
|
||||
current.externe = checked;
|
||||
return rows;
|
||||
});
|
||||
}
|
||||
// onToggleExterne(index: number, value: any) {
|
||||
// const checked = !!value;
|
||||
// this.editedRows.update((rows: CourseReportDetailRow[]) => {
|
||||
// const current = rows[index];
|
||||
// if (!current) return rows;
|
||||
// current.externe = checked;
|
||||
// return rows;
|
||||
// });
|
||||
// }
|
||||
|
||||
trackByRow(index: number, row: CourseReportDetailRow) {
|
||||
return row.typeGain + '|' + row.typeJeu + '|' + index;
|
||||
}
|
||||
// trackByRow(index: number, row: CourseReportDetailRow) {
|
||||
// return row.typeGain + '|' + row.typeJeu + '|' + index;
|
||||
// }
|
||||
|
||||
isRowDirty(index: number): boolean {
|
||||
const current = this.editedRows()[index];
|
||||
const original = this.originalRows()[index];
|
||||
if (!current || !original) return false;
|
||||
return (
|
||||
current.montant !== original.montant ||
|
||||
current.nombre !== original.nombre ||
|
||||
!!current.distributed !== !!original.distributed ||
|
||||
!!current.externe !== !!original.externe
|
||||
);
|
||||
}
|
||||
}
|
||||
// isRowDirty(index: number): boolean {
|
||||
// const current = this.editedRows()[index];
|
||||
// const original = this.originalRows()[index];
|
||||
// if (!current || !original) return false;
|
||||
// return (
|
||||
// current.montant !== original.montant ||
|
||||
// current.nombre !== original.nombre ||
|
||||
// !!current.distributed !== !!original.distributed ||
|
||||
// !!current.externe !== !!original.externe
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,61 +1,61 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, Component, signal, effect, untracked } from '@angular/core';
|
||||
import { DataTable, SortState, TableColumn } from '@shared/components/data-table/data-table';
|
||||
import { Paginator } from '@shared/components/paginator/paginator';
|
||||
import { SearchBar } from '@shared/components/search-bar/search-bar';
|
||||
import { ZardButtonComponent } from '@shared/components/button/button.component';
|
||||
import { SortDir } from '@shared/paging/paging';
|
||||
import { Router } from '@angular/router';
|
||||
import { CourseReportSummary } from 'src/app/core/interfaces/report';
|
||||
import { ReportService } from 'src/app/core/services/report';
|
||||
// import { CommonModule } from '@angular/common';
|
||||
// import { ChangeDetectionStrategy, Component, signal, effect, untracked } from '@angular/core';
|
||||
// import { DataTable, SortState, TableColumn } from '@shared/components/data-table/data-table';
|
||||
// import { Paginator } from '@shared/components/paginator/paginator';
|
||||
// import { SearchBar } from '@shared/components/search-bar/search-bar';
|
||||
// import { ZardButtonComponent } from '@shared/components/button/button.component';
|
||||
// import { SortDir } from '@shared/paging/paging';
|
||||
// import { Router } from '@angular/router';
|
||||
// import { CourseReportSummary } from 'src/app/core/interfaces/report';
|
||||
// import { ReportService } from 'src/app/core/services/report';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-report-courses-list',
|
||||
templateUrl: './report-list.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [CommonModule, DataTable, Paginator, SearchBar, ZardButtonComponent],
|
||||
})
|
||||
export class ReportCoursesListPage {
|
||||
rows = signal<CourseReportSummary[]>([]);
|
||||
total = signal(0);
|
||||
page = signal(1);
|
||||
perPage = signal(10);
|
||||
search = signal('');
|
||||
sort = signal<SortState>({ key: 'date', dir: 'desc' });
|
||||
loading = signal(false);
|
||||
// @Component({
|
||||
// standalone: true,
|
||||
// selector: 'app-report-courses-list',
|
||||
// templateUrl: './report-list.html',
|
||||
// changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
// imports: [CommonModule, DataTable, Paginator, SearchBar, ZardButtonComponent],
|
||||
// })
|
||||
// export class ReportCoursesListPage {
|
||||
// rows = signal<CourseReportSummary[]>([]);
|
||||
// total = signal(0);
|
||||
// page = signal(1);
|
||||
// perPage = signal(10);
|
||||
// search = signal('');
|
||||
// sort = signal<SortState>({ key: 'date', dir: 'desc' });
|
||||
// loading = signal(false);
|
||||
|
||||
cols: TableColumn<CourseReportSummary>[] = [
|
||||
{ key: 'course.dateDepartCourse', label: 'Date', sortable: true },
|
||||
{ key: 'course.numero', label: 'Numéro', sortable: true },
|
||||
{ key: 'course.nom', label: 'Nom', sortable: true },
|
||||
{ key: 'course.type', label: 'Type', sortable: true },
|
||||
{ key: 'course.reunion.hippodrome.nom', label: 'Lieu', sortable: true },
|
||||
{ key: 'course.particularite', label: 'Particularité' },
|
||||
{ key: 'statut', label: 'Statut', sortable: true },
|
||||
];
|
||||
// cols: TableColumn<CourseReportSummary>[] = [
|
||||
// { key: 'course.dateDepartCourse', label: 'Date', sortable: true },
|
||||
// { key: 'course.numero', label: 'Numéro', sortable: true },
|
||||
// { key: 'course.nom', label: 'Nom', sortable: true },
|
||||
// { key: 'course.type', label: 'Type', sortable: true },
|
||||
// { key: 'course.reunion.hippodrome.nom', label: 'Lieu', sortable: true },
|
||||
// { key: 'course.particularite', label: 'Particularité' },
|
||||
// { key: 'statut', label: 'Statut', sortable: true },
|
||||
// ];
|
||||
|
||||
constructor(private api: ReportService, private router: Router) {
|
||||
effect(() => {
|
||||
const params = { page: this.page(), perPage: this.perPage(), search: this.search(), sortKey: this.sort().key, sortDir: this.sort().dir as SortDir };
|
||||
untracked(() => this.fetch(params));
|
||||
});
|
||||
}
|
||||
// constructor(private api: ReportService, private router: Router) {
|
||||
// effect(() => {
|
||||
// const params = { page: this.page(), perPage: this.perPage(), search: this.search(), sortKey: this.sort().key, sortDir: this.sort().dir as SortDir };
|
||||
// untracked(() => this.fetch(params));
|
||||
// });
|
||||
// }
|
||||
|
||||
fetch(params: { page: number; perPage: number; search: string; sortKey: string; sortDir: SortDir }) {
|
||||
this.loading.set(true);
|
||||
this.api.list(params).subscribe((res) => {
|
||||
this.rows.set(res.data);
|
||||
this.total.set(res.meta.total);
|
||||
this.loading.set(false);
|
||||
});
|
||||
}
|
||||
// fetch(params: { page: number; perPage: number; search: string; sortKey: string; sortDir: SortDir }) {
|
||||
// this.loading.set(true);
|
||||
// this.api.list(params).subscribe((res) => {
|
||||
// this.rows.set(res.content);
|
||||
// this.total.set(res.pageable.total);
|
||||
// this.loading.set(false);
|
||||
// });
|
||||
// }
|
||||
|
||||
onSearch(q: string) { this.search.set(q); this.page.set(1); }
|
||||
// onSearch(q: string) { this.search.set(q); this.page.set(1); }
|
||||
|
||||
open(row: CourseReportSummary) {
|
||||
this.router.navigate(['/rapport-courses', row.id]);
|
||||
}
|
||||
}
|
||||
// open(row: CourseReportSummary) {
|
||||
// this.router.navigate(['/rapport-courses', row.id]);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
@@ -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: () => {
|
||||
|
||||
@@ -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: () => {
|
||||
|
||||
@@ -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: () => {
|
||||
|
||||
@@ -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: () => {
|
||||
|
||||
Reference in New Issue
Block a user