-
-
{{ trajet.date | date: 'dd/MM/yyyy' }}
- @if (trajet.commentaire) {
+ @if (trajet.commentaire) {
+
- }
-
+
+ }
{{ trajet.adresseDepart }}
→
@@ -110,6 +120,7 @@
}
+ }
}
}
diff --git a/frontend/src/app/features/trajet-list/trajet-list.component.scss b/frontend/src/app/features/trajet-list/trajet-list.component.scss
index e2b68e5..f35b1d5 100644
--- a/frontend/src/app/features/trajet-list/trajet-list.component.scss
+++ b/frontend/src/app/features/trajet-list/trajet-list.component.scss
@@ -11,17 +11,44 @@
padding: 0.5rem 0;
&__entete {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ width: 100%;
margin: 0 0 0.4rem;
- padding: 0.35rem 0.5rem;
+ padding: 0.4rem 0.5rem;
font-size: 0.85rem;
font-weight: 700;
color: #334155;
background: #f1f5f9;
+ border: 1px solid #e2e8f0;
border-radius: 6px;
- text-transform: none;
+ text-align: left;
+ cursor: pointer;
position: sticky;
top: 0;
z-index: 1;
+
+ &:hover {
+ background: #e9eef4;
+ }
+ }
+
+ &__chevron {
+ flex: 0 0 auto;
+ color: #64748b;
+ font-size: 0.75rem;
+ }
+
+ &__date {
+ flex: 1 1 auto;
+ }
+
+ &__compteur {
+ flex: 0 0 auto;
+ font-weight: 500;
+ font-size: 0.75rem;
+ color: #64748b;
}
& + .jour {
@@ -81,11 +108,6 @@
font-style: italic;
line-height: 1.3;
word-break: break-word;
- // Séparateur visuel discret entre la date et le commentaire.
- &::before {
- content: '— ';
- color: #cbd5e1;
- }
}
&__adresses {
diff --git a/frontend/src/app/features/trajet-list/trajet-list.component.ts b/frontend/src/app/features/trajet-list/trajet-list.component.ts
index ce18b5a..635e07b 100644
--- a/frontend/src/app/features/trajet-list/trajet-list.component.ts
+++ b/frontend/src/app/features/trajet-list/trajet-list.component.ts
@@ -96,6 +96,7 @@ export class TrajetListComponent {
@Input() set trajets(valeur: Trajet[] | null) {
this._trajets = valeur ?? [];
this.trajetsSource.set([...this._trajets]);
+ this.reinitialiserRepliageSiMoisChange();
}
get trajets(): Trajet[] {
return this._trajets;
@@ -132,6 +133,16 @@ export class TrajetListComponent {
/** Source brute des trajets du mois (mise à jour à chaque changement d'entrée). */
private readonly trajetsSource = signal([]);
+ /**
+ * Dates (`yyyy-MM-dd`) des journées dépliées. Par défaut toutes les journées
+ * sont repliées ; au changement de mois, seule la dernière journée comportant
+ * des trajets est dépliée.
+ */
+ private readonly joursOuverts = signal>(new Set());
+
+ /** Préfixe `yyyy-MM` du mois actuellement affiché, pour détecter un changement de mois. */
+ private moisAffiche: string | null = null;
+
/**
* Trajets regroupés par journée, source d'affichage. Les groupes sont triés par
* date croissante ; à l'intérieur d'un groupe, les trajets sont triés par position
@@ -171,6 +182,54 @@ export class TrajetListComponent {
/** True pendant l'appel de suppression / réordonnancement (désactive les actions). */
readonly operationEnCours = signal(false);
+ // --- Repliage par journée ---
+
+ /**
+ * Recalcule l'état de repliage quand le mois affiché change (nouvel ensemble de
+ * trajets appartenant à un autre mois). Toutes les journées sont repliées, sauf la
+ * dernière journée comportant des trajets qui est dépliée. Les mises à jour au sein
+ * du même mois (ajout / suppression / réordonnancement) conservent l'état courant.
+ */
+ private reinitialiserRepliageSiMoisChange(): void {
+ const dates = this.trajetsSource()
+ .map((t) => (t.date ?? '').slice(0, 10))
+ .filter((d) => d.length === 10)
+ .sort();
+ const moisCourant = dates.length > 0 ? dates[0].slice(0, 7) : null;
+
+ if (moisCourant === this.moisAffiche) {
+ // Même mois : purge les dates disparues, conserve le reste de l'état.
+ const presentes = new Set(dates);
+ const conserves = new Set(
+ [...this.joursOuverts()].filter((d) => presentes.has(d))
+ );
+ this.joursOuverts.set(conserves);
+ return;
+ }
+
+ this.moisAffiche = moisCourant;
+ const dernierJour = dates.length > 0 ? dates[dates.length - 1] : null;
+ this.joursOuverts.set(dernierJour ? new Set([dernierJour]) : new Set());
+ }
+
+ /** Vrai si la journée est dépliée (ses trajets sont visibles). */
+ estOuvert(groupe: GroupeJour): boolean {
+ return this.joursOuverts().has(groupe.date);
+ }
+
+ /** Bascule le repliage d'une journée (déplie / replie). */
+ basculerJour(groupe: GroupeJour): void {
+ this.joursOuverts.update((ouverts) => {
+ const suivant = new Set(ouverts);
+ if (suivant.has(groupe.date)) {
+ suivant.delete(groupe.date);
+ } else {
+ suivant.add(groupe.date);
+ }
+ return suivant;
+ });
+ }
+
// --- Helpers d'affichage ---
/** Vrai si le trajet est le dernier DE SA JOURNÉE (pas d'« insérer avant le suivant »). */