Liste : jour de semaine dans l'en-tête + bouton dédié d'ajout par journée
Retour d'usage : avec plusieurs journées ouvertes, viser le bouton principal d'ajout en traversant la liste faisait dériver la date ciblée (le survol pilote la journée affichée sur la carte). - En-tête de journée réorganisé : jour de la semaine avant la date (ex. « Lundi 15/09/2026 »), nombre de trajets à la suite, puis un bouton dédié « + » à l'extrémité droite (infobulle « Ajouter un trajet sur cette journée »). - Le bouton « + » ouvre la création avec la date de SA journée, indépendamment de la date affichée sur la carte (Output ajouterSurJournee -> conteneur fixe lun. 21 sept. 2026 12:54:31 CEST avant ouverture via ouvrirCreationSur). stopPropagation pour ne pas déclencher le repliage/dépliage au clic. - Style : fond bleu IAD / texte blanc par défaut, survol orange (cohérent avec les autres boutons d'action). - Locale française enregistrée (registerLocaleData(localeFr) + LOCALE_ID 'fr-FR' dans app.config.ts) pour l'affichage du jour de la semaine. Specs : requirements.md (exigence 12, critères 6 et 24) et design.md (TrajetListComponent, locale) mis à jour.
This commit is contained in:
@@ -252,13 +252,15 @@ src/
|
||||
- Bouton "Export PDF annuel"
|
||||
|
||||
**`TrajetListComponent`**
|
||||
- Affiche TOUS les trajets du mois, regroupés par journée : chaque groupe/jour a un **en-tête repliable** (date, nombre de trajets) ; par défaut tout est replié sauf le dernier jour du mois ayant des trajets.
|
||||
- Affiche TOUS les trajets du mois, regroupés par journée : chaque groupe/jour a un **en-tête repliable** (jour de la semaine avant la date, ex. « Lundi 15/09/2026 », puis nombre de trajets) ; par défaut tout est replié sauf le dernier jour du mois ayant des trajets.
|
||||
- **Bouton dédié « + » à droite de l'en-tête** (`Output ajouterSurJournee: string`) : ouvre le formulaire de création avec la date de CETTE journée, sans dépendre de la journée affichée sur la Carte (pilotée par le survol) — évite qu'un déplacement de souris à travers plusieurs journées ouvertes ne fasse dériver la date visée en se dirigeant vers le bouton principal d'ajout. Le conteneur fixe `date` sur cette valeur avant d'ouvrir la création (`ouvrirCreationSur`).
|
||||
- Ligne par trajet (triée par `Position` croissante au sein du jour) : colonne dédiée **A/R** en début de ligne pour les allers/retours, commentaire (si présent), adresses (taille réduite), distance effective
|
||||
- Actions par trajet : modifier (→ `TrajetFormComponent` pré-rempli en < 500 ms), supprimer (→ dialog de confirmation), **insérer après** (→ `TrajetFormComponent` en mode insertion avec `adresseDepart` = point de fin du trajet courant — son arrivée, ou son **départ** si le trajet est un aller/retour —, la **date de la journée** du trajet, `positionApres` = Position du trajet courant)
|
||||
- Si le trajet n'est pas le dernier de la journée : action **insérer avant le suivant** disponible, pré-remplissant l'adresse de départ avec le point de fin du trajet courant (départ si aller/retour) et l'adresse d'arrivée avec le départ du trajet suivant, en calculant la position d'insertion `(P_courant + P_suivant) / 2`
|
||||
- Méthode publique `ouvrirJour(dateIso)` : déplie une journée donnée (appelée par le conteneur après ajout/insertion pour rendre le trajet visible) ; `ouvrirToutesLesJournees()` déplie tous les groupes ; `aDesJourneesFermees()` conditionne l'affichage du bouton « Ouvrir toutes les journées »
|
||||
- `@Input jourAffiche` : la journée affichée sur la Carte ; le groupe correspondant est mis en surbrillance (`estJourAffiche`)
|
||||
- **Glisser-déposer** (drag & drop) limité à chaque journée : un `cdkDropList` par jour, listes **non connectées** entre elles (pas de déplacement inter-journées) → recalcul des positions du jour puis `PATCH /api/trajets/reordonner`
|
||||
- **Locale** : `registerLocaleData(localeFr)` et `LOCALE_ID: 'fr-FR'` enregistrés dans `app.config.ts`, nécessaires pour que le pipe `date` (format `EEEE`, jour de la semaine) affiche les noms en français.
|
||||
- Rafraîchissement du résumé mensuel en < 1 000 ms après modification/suppression/insertion
|
||||
|
||||
**`CarteTrajetsComponent`**
|
||||
|
||||
@@ -294,7 +294,7 @@ L'application est composée d'un frontend Angular/TypeScript et d'un backend C#.
|
||||
3. WHEN l'utilisateur sélectionne une année, THE Frontend SHALL afficher les douze mois de cette année et mettre en surbrillance les mois comportant au moins un Trajet, avec le même code couleur que la journée mise en avant dans la liste (cohérence visuelle).
|
||||
4. THE Frontend SHALL empêcher la sélection de tout mois postérieur au mois courant (aucun mois futur sélectionnable).
|
||||
5. WHEN l'utilisateur sélectionne un mois, THE Frontend SHALL afficher la liste de TOUS les Trajets de ce mois, regroupés par journée et triés par date croissante puis par Position croissante au sein de chaque journée.
|
||||
6. THE Frontend SHALL afficher chaque journée de la liste mensuelle comme un groupe repliable ; par défaut toutes les journées sont repliées et, au changement de mois, seule la dernière journée comportant des Trajets est dépliée.
|
||||
6. THE Frontend SHALL afficher chaque journée de la liste mensuelle comme un groupe repliable, avec un en-tête indiquant le jour de la semaine avant la date (ex. « Lundi 15/09/2026 ») suivi du nombre de Trajets de la journée ; par défaut toutes les journées sont repliées et, au changement de mois, seule la dernière journée comportant des Trajets est dépliée.
|
||||
7. THE Frontend SHALL afficher la liste mensuelle des Trajets comme zone principale, avec défilement vertical (scroll) lorsque le nombre de Trajets dépasse la hauteur visible, tandis que le Sélecteur_Temporel, la navigation par jour, le Panneau_Totaux et la Carte restent visibles.
|
||||
8. THE Frontend SHALL afficher un Panneau_Totaux toujours visible contenant : le total kilométrique du jour ciblé sur la Carte, le total kilométrique du mois sélectionné, et le Total_Annuel_Partiel de l'année sélectionnée.
|
||||
9. THE Panneau_Totaux SHALL calculer le Total_Annuel_Partiel en cumulant uniquement les Trajets de l'année sélectionnée jusqu'au mois sélectionné inclus, sans inclure les mois postérieurs au mois sélectionné.
|
||||
@@ -312,6 +312,7 @@ L'application est composée d'un frontend Angular/TypeScript et d'un backend C#.
|
||||
21. THE Panneau_Totaux SHALL calculer le total du jour, le total du mois et le Total_Annuel_Partiel uniquement à partir des Trajets associés au Véhicule sélectionné.
|
||||
22. WHEN l'utilisateur change de Véhicule sélectionné, THE Frontend SHALL mettre à jour la liste mensuelle des Trajets, le Panneau_Totaux et la Carte dans un délai de 1000 ms sans rechargement complet de la page.
|
||||
23. WHEN un Trajet est créé ou modifié avec une date appartenant à un mois différent du mois affiché, THE Frontend SHALL se repositionner automatiquement sur le mois de ce Trajet, cibler sa journée sur la Carte, et déplier le groupe de cette journée dans la liste afin que le Trajet ajouté soit visible.
|
||||
24. THE Frontend SHALL afficher, à l'extrémité droite de l'en-tête de chaque journée, un bouton dédié « Ajouter un trajet sur cette journée » qui ouvre le formulaire de création avec la date de CETTE journée pré-remplie, indépendamment de la journée actuellement affichée sur la Carte (afin d'éviter qu'un survol traversant plusieurs journées ouvertes ne fasse dériver la date visée par l'utilisateur).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import { ApplicationConfig, provideZonelessChangeDetection } from '@angular/core';
|
||||
import { ApplicationConfig, LOCALE_ID, provideZonelessChangeDetection } from '@angular/core';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { provideHttpClient, withInterceptors } from '@angular/common/http';
|
||||
import { registerLocaleData } from '@angular/common';
|
||||
import localeFr from '@angular/common/locales/fr';
|
||||
|
||||
import { routes } from './app.routes';
|
||||
import { authInterceptor } from './core/interceptors/auth.interceptor';
|
||||
import { timeoutInterceptor } from './core/interceptors/timeout.interceptor';
|
||||
|
||||
// Locale française : nécessaire pour que le pipe `date` (ex. 'EEEE' → jour de la
|
||||
// semaine) affiche les noms en français plutôt qu'en anglais par défaut.
|
||||
registerLocaleData(localeFr);
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
// Détection de changement SANS zone.js (zoneless). L'état affiché est exposé via
|
||||
@@ -19,6 +25,7 @@ export const appConfig: ApplicationConfig = {
|
||||
// - timeoutInterceptor : timeout 10s + gestion des erreurs réseau (Exigence 1.9).
|
||||
// authInterceptor est placé AVANT timeoutInterceptor pour injecter le Bearer
|
||||
// avant le contrôle de timeout.
|
||||
provideHttpClient(withInterceptors([authInterceptor, timeoutInterceptor]))
|
||||
provideHttpClient(withInterceptors([authInterceptor, timeoutInterceptor])),
|
||||
{ provide: LOCALE_ID, useValue: 'fr-FR' }
|
||||
]
|
||||
};
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
(insertBetween)="onInsert($event)"
|
||||
(changed)="onListeChangee()"
|
||||
(survol)="onSurvolTrajet($event)"
|
||||
(ajouterSurJournee)="ouvrirCreationSur($event)"
|
||||
></app-trajet-list>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -212,6 +212,19 @@ export class ConsultationJourComponent implements OnInit, OnDestroy {
|
||||
this.formulaire.set({ type: 'create' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Ouvre le formulaire de création avec la date FIXÉE sur `dateIso` (bouton « + » de
|
||||
* l'en-tête d'une journée). Cale `date` avant l'ouverture, afin que la date par
|
||||
* défaut du formulaire soit celle voulue, indépendamment d'un éventuel survol en
|
||||
* cours (qui pilote aussi `date`, mais un clic explicite doit primer).
|
||||
*/
|
||||
ouvrirCreationSur(dateIso: string): void {
|
||||
if (dateIso) {
|
||||
this.date.set(dateIso);
|
||||
}
|
||||
this.formulaire.set({ type: 'create' });
|
||||
}
|
||||
|
||||
/** Ouvre le formulaire en mode édition (Output `edit` de la liste). */
|
||||
onEdit(trajet: Trajet): void {
|
||||
this.formulaire.set({ type: 'edit', trajet });
|
||||
|
||||
@@ -7,17 +7,31 @@
|
||||
[class.jour--affiche]="estJourAffiche(groupe)"
|
||||
aria-label="Trajets d'une journée"
|
||||
>
|
||||
<!-- En-tête repliable : chevron + date + nombre de trajets. -->
|
||||
<button
|
||||
type="button"
|
||||
class="jour__entete"
|
||||
[attr.aria-expanded]="estOuvert(groupe)"
|
||||
(click)="basculerJour(groupe)"
|
||||
>
|
||||
<span class="jour__chevron" aria-hidden="true">{{ estOuvert(groupe) ? '▾' : '▸' }}</span>
|
||||
<span class="jour__date">{{ groupe.date | date: 'dd/MM/yyyy' }}</span>
|
||||
<span class="jour__compteur">{{ groupe.trajets.length }} trajet{{ groupe.trajets.length > 1 ? 's' : '' }}</span>
|
||||
</button>
|
||||
<!-- En-tête repliable : chevron + jour de semaine + date + nombre de trajets,
|
||||
puis un bouton « + » dédié pour ajouter un trajet SUR CETTE JOURNÉE (indépendant
|
||||
de la date affichée sur la carte, pilotée par le survol : viser le bouton
|
||||
principal d'ajout en traversant plusieurs journées ouvertes ferait dériver la
|
||||
date ciblée). -->
|
||||
<div class="jour__entete" [attr.aria-expanded]="estOuvert(groupe)">
|
||||
<button
|
||||
type="button"
|
||||
class="jour__entete-bouton"
|
||||
(click)="basculerJour(groupe)"
|
||||
>
|
||||
<span class="jour__chevron" aria-hidden="true">{{ estOuvert(groupe) ? '▾' : '▸' }}</span>
|
||||
<span class="jour__date">{{ groupe.date | date: 'EEEE dd/MM/yyyy' }}</span>
|
||||
<span class="jour__compteur">{{ groupe.trajets.length }} trajet{{ groupe.trajets.length > 1 ? 's' : '' }}</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="jour__ajouter"
|
||||
title="Ajouter un trajet sur cette journée"
|
||||
aria-label="Ajouter un trajet sur cette journée"
|
||||
(click)="ajouterSur(groupe, $event)"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@if (estOuvert(groupe)) {
|
||||
<ul
|
||||
|
||||
@@ -10,30 +10,65 @@
|
||||
.jour {
|
||||
padding: 0.5rem 0;
|
||||
|
||||
// Conteneur de l'en-tête : le bouton de repliage (zone cliquable principale) et,
|
||||
// à droite, le bouton dédié « + » (ajouter un trajet sur cette journée).
|
||||
&__entete {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
margin: 0 0 0.4rem;
|
||||
padding: 0.4rem 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
color: #334155;
|
||||
background: #f1f5f9;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&__entete-bouton {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
padding: 0.4rem 0.5rem;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
border-radius: 6px 0 0 6px;
|
||||
|
||||
&:hover {
|
||||
background: #e9eef4;
|
||||
}
|
||||
}
|
||||
|
||||
// Bouton dédié : ajouter un trajet SUR CETTE JOURNÉE, indépendant de la date de
|
||||
// la carte (pilotée par le survol). Toujours visible, à droite de l'en-tête.
|
||||
&__ajouter {
|
||||
flex: 0 0 auto;
|
||||
width: 2rem;
|
||||
margin: 0.25rem 0.25rem 0.25rem 0;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
background: var(--couleur-bleu, #1976d2);
|
||||
color: #fff;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: var(--couleur-orange, #f28c28);
|
||||
}
|
||||
}
|
||||
|
||||
// Journée affichée sur la carte : en-tête accentué (bleu) pour la repérer.
|
||||
&--affiche &__entete {
|
||||
background: #e3f0ff;
|
||||
@@ -42,6 +77,7 @@
|
||||
box-shadow: inset 3px 0 0 #1976d2;
|
||||
}
|
||||
|
||||
|
||||
&__chevron {
|
||||
flex: 0 0 auto;
|
||||
color: #64748b;
|
||||
|
||||
@@ -121,6 +121,14 @@ export class TrajetListComponent {
|
||||
/** Émis pour insérer un trajet entre le courant et le suivant (Exigence 11.3/11.4). */
|
||||
@Output() insertBetween = new EventEmitter<TrajetInsertionContext>();
|
||||
|
||||
/**
|
||||
* Émis pour ajouter un Trajet sur une journée précise (date ISO `yyyy-MM-dd`), via
|
||||
* le bouton « + » de l'en-tête de journée. Évite de dépendre de la date affichée sur
|
||||
* la carte (pilotée par le survol), qui peut avoir dérivé pendant le déplacement de
|
||||
* la souris vers le bouton.
|
||||
*/
|
||||
@Output() ajouterSurJournee = new EventEmitter<string>();
|
||||
|
||||
/**
|
||||
* Émis lorsque la liste a changé (suppression, réordonnancement) et que le
|
||||
* conteneur doit recharger la journée / le résumé mensuel (Exigences 5.7, 11.6).
|
||||
@@ -244,6 +252,15 @@ export class TrajetListComponent {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Demande l'ajout d'un Trajet sur cette journée (bouton « + » de l'en-tête). Empêche
|
||||
* la propagation du clic vers le bouton de repliage (l'en-tête est elle-même cliquable).
|
||||
*/
|
||||
ajouterSur(groupe: GroupeJour, event: MouseEvent): void {
|
||||
event.stopPropagation();
|
||||
this.ajouterSurJournee.emit(groupe.date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Déplie explicitement la journée `dateIso` (`yyyy-MM-dd`), sans toucher aux autres.
|
||||
* Appelé par le conteneur après l'ajout/insertion d'un trajet pour rendre la journée
|
||||
|
||||
Reference in New Issue
Block a user