fix(frontend): navigation cohérente entre les pages authentifiées

Logo cliquable vers le tableau de bord (ev-brand-link) et fil d'Ariane
(ev-breadcrumb) sur les sous-pages, pour éviter les impasses de
navigation entre dashboard, liste des sites et détail de site.
This commit is contained in:
Johan LEROY
2026-09-17 15:58:50 +02:00
parent 5581cb1ef3
commit e22feac2c4
10 changed files with 95 additions and 17 deletions
@@ -1,14 +1,16 @@
<div class="dashboard">
<header class="dashboard__header">
<div class="dashboard__brand">
<ev-brand class="dashboard__logo" />
<a routerLink="/dashboard" class="ev-brand-link">
<ev-brand class="dashboard__logo" />
</a>
<div>
<h1>Vue d'ensemble</h1>
<p class="dashboard__subtitle">Consommation instantanée du parc</p>
</div>
</div>
<div class="dashboard__actions">
<a routerLink="/sites" class="dashboard__sites-link">Voir les sites</a>
<a routerLink="/sites" class="ev-link">Voir les sites</a>
<ev-button
class="logout-button"
variant="secondary"
@@ -40,16 +40,6 @@
gap: 1rem;
}
.dashboard__sites-link {
color: var(--color-primary);
font-weight: 600;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
h2 {
font-size: 1.1rem;
font-weight: 600;
@@ -1,5 +1,19 @@
<div class="site-detail-placeholder">
<nav class="ev-breadcrumb">
<a routerLink="/dashboard">Tableau de bord</a>
<span>/</span>
<a routerLink="/sites">Sites</a>
</nav>
<header class="site-detail-placeholder__header">
<a routerLink="/dashboard" class="ev-brand-link">
<ev-brand class="site-detail-placeholder__logo" />
</a>
<h1>Site {{ siteId }}</h1>
</header>
<ev-card>
<p>Détail du site {{ siteId }} : à venir (voir issue #51).</p>
<p>Le détail de ce site est à venir (voir issue #51).</p>
<a routerLink="/sites" class="ev-link">Retour aux sites</a>
</ev-card>
</div>
@@ -1,6 +1,28 @@
:host {
display: block;
color: var(--color-text);
padding: 2.5rem 2rem;
max-width: 640px;
margin: 0 auto;
}
.site-detail-placeholder__header {
display: flex;
align-items: center;
gap: 0.85rem;
margin-bottom: 1.5rem;
h1 {
margin: 0;
font-size: 1.5rem;
font-weight: 700;
}
}
.site-detail-placeholder__logo {
font-size: 1.3rem;
}
ev-card p {
margin: 0 0 0.75rem;
}
@@ -1,5 +1,5 @@
import { TestBed } from '@angular/core/testing';
import { ActivatedRoute, convertToParamMap } from '@angular/router';
import { ActivatedRoute, convertToParamMap, provideRouter } from '@angular/router';
import { SiteDetailPlaceholder } from './site-detail-placeholder';
describe('SiteDetailPlaceholder', () => {
@@ -7,6 +7,7 @@ describe('SiteDetailPlaceholder', () => {
TestBed.configureTestingModule({
imports: [SiteDetailPlaceholder],
providers: [
provideRouter([]),
{
provide: ActivatedRoute,
useValue: { snapshot: { paramMap: convertToParamMap({ siteId: 'SITE001' }) } },
@@ -1,11 +1,12 @@
import { Component, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { Card } from '../../../shared/components/ui/card/card';
import { Brand } from '../../../shared/components/ui/brand/brand';
@Component({
selector: 'app-site-detail-placeholder',
standalone: true,
imports: [Card],
imports: [RouterLink, Card, Brand],
templateUrl: './site-detail-placeholder.html',
styleUrl: './site-detail-placeholder.scss',
})
@@ -1,6 +1,12 @@
<div class="site-list">
<nav class="ev-breadcrumb">
<a routerLink="/dashboard">Tableau de bord</a>
</nav>
<header class="site-list__header">
<ev-brand class="site-list__logo" />
<a routerLink="/dashboard" class="ev-brand-link">
<ev-brand class="site-list__logo" />
</a>
<div>
<h1>Sites</h1>
<p class="site-list__subtitle">Vue d'ensemble du parc suivi</p>
+1
View File
@@ -1,6 +1,7 @@
@use 'styles/tokens';
@use 'styles/forms';
@use 'styles/auth-page';
@use 'styles/links';
body {
margin: 0;
+34
View File
@@ -0,0 +1,34 @@
.ev-link {
color: var(--color-primary);
font-weight: 600;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
.ev-breadcrumb {
display: flex;
align-items: center;
gap: 0.4rem;
font-size: 0.85rem;
color: var(--color-text-muted);
margin-bottom: 1.25rem;
a {
color: var(--color-text-muted);
text-decoration: none;
&:hover {
color: var(--color-primary);
text-decoration: underline;
}
}
}
.ev-brand-link {
display: inline-flex;
color: inherit;
text-decoration: none;
}
@@ -36,6 +36,13 @@ le fond dégradé et le centrage commun aux pages d'authentification (`login`, `
et à terme `forgot-password`/`reset-password`) : elle enveloppe la carte, pas de duplication du
fond par page.
Les classes de navigation partagées (`.ev-link`, `.ev-breadcrumb`, `.ev-brand-link`) sont dans
`apps/frontend/src/styles/_links.scss`, importées globalement. Convention pour toute page de la
zone authentifiée (derrière `authGuard`) : le logo (`<ev-brand>`) est enveloppé dans
`<a routerLink="/dashboard" class="ev-brand-link">` pour ramener au tableau de bord en un clic,
et un `<nav class="ev-breadcrumb">` liste le chemin de retour vers les pages parentes quand la
page n'est pas à la racine (voir `site-list`/`site-detail-placeholder` pour l'exemple).
## Composants partagés
Dans `apps/frontend/src/app/shared/components/ui/`, chacun standalone, à importer directement