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:
@@ -1,14 +1,16 @@
|
|||||||
<div class="dashboard">
|
<div class="dashboard">
|
||||||
<header class="dashboard__header">
|
<header class="dashboard__header">
|
||||||
<div class="dashboard__brand">
|
<div class="dashboard__brand">
|
||||||
|
<a routerLink="/dashboard" class="ev-brand-link">
|
||||||
<ev-brand class="dashboard__logo" />
|
<ev-brand class="dashboard__logo" />
|
||||||
|
</a>
|
||||||
<div>
|
<div>
|
||||||
<h1>Vue d'ensemble</h1>
|
<h1>Vue d'ensemble</h1>
|
||||||
<p class="dashboard__subtitle">Consommation instantanée du parc</p>
|
<p class="dashboard__subtitle">Consommation instantanée du parc</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dashboard__actions">
|
<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
|
<ev-button
|
||||||
class="logout-button"
|
class="logout-button"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
|
|||||||
@@ -40,16 +40,6 @@
|
|||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard__sites-link {
|
|
||||||
color: var(--color-primary);
|
|
||||||
font-weight: 600;
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|||||||
+15
-1
@@ -1,5 +1,19 @@
|
|||||||
<div class="site-detail-placeholder">
|
<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>
|
<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>
|
</ev-card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+22
@@ -1,6 +1,28 @@
|
|||||||
:host {
|
:host {
|
||||||
display: block;
|
display: block;
|
||||||
|
color: var(--color-text);
|
||||||
padding: 2.5rem 2rem;
|
padding: 2.5rem 2rem;
|
||||||
max-width: 640px;
|
max-width: 640px;
|
||||||
margin: 0 auto;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
+2
-1
@@ -1,5 +1,5 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
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';
|
import { SiteDetailPlaceholder } from './site-detail-placeholder';
|
||||||
|
|
||||||
describe('SiteDetailPlaceholder', () => {
|
describe('SiteDetailPlaceholder', () => {
|
||||||
@@ -7,6 +7,7 @@ describe('SiteDetailPlaceholder', () => {
|
|||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [SiteDetailPlaceholder],
|
imports: [SiteDetailPlaceholder],
|
||||||
providers: [
|
providers: [
|
||||||
|
provideRouter([]),
|
||||||
{
|
{
|
||||||
provide: ActivatedRoute,
|
provide: ActivatedRoute,
|
||||||
useValue: { snapshot: { paramMap: convertToParamMap({ siteId: 'SITE001' }) } },
|
useValue: { snapshot: { paramMap: convertToParamMap({ siteId: 'SITE001' }) } },
|
||||||
|
|||||||
+3
-2
@@ -1,11 +1,12 @@
|
|||||||
import { Component, inject } from '@angular/core';
|
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 { Card } from '../../../shared/components/ui/card/card';
|
||||||
|
import { Brand } from '../../../shared/components/ui/brand/brand';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-site-detail-placeholder',
|
selector: 'app-site-detail-placeholder',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [Card],
|
imports: [RouterLink, Card, Brand],
|
||||||
templateUrl: './site-detail-placeholder.html',
|
templateUrl: './site-detail-placeholder.html',
|
||||||
styleUrl: './site-detail-placeholder.scss',
|
styleUrl: './site-detail-placeholder.scss',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
<div class="site-list">
|
<div class="site-list">
|
||||||
|
<nav class="ev-breadcrumb">
|
||||||
|
<a routerLink="/dashboard">Tableau de bord</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
<header class="site-list__header">
|
<header class="site-list__header">
|
||||||
|
<a routerLink="/dashboard" class="ev-brand-link">
|
||||||
<ev-brand class="site-list__logo" />
|
<ev-brand class="site-list__logo" />
|
||||||
|
</a>
|
||||||
<div>
|
<div>
|
||||||
<h1>Sites</h1>
|
<h1>Sites</h1>
|
||||||
<p class="site-list__subtitle">Vue d'ensemble du parc suivi</p>
|
<p class="site-list__subtitle">Vue d'ensemble du parc suivi</p>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
@use 'styles/tokens';
|
@use 'styles/tokens';
|
||||||
@use 'styles/forms';
|
@use 'styles/forms';
|
||||||
@use 'styles/auth-page';
|
@use 'styles/auth-page';
|
||||||
|
@use 'styles/links';
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
@@ -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
|
et à terme `forgot-password`/`reset-password`) : elle enveloppe la carte, pas de duplication du
|
||||||
fond par page.
|
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
|
## Composants partagés
|
||||||
|
|
||||||
Dans `apps/frontend/src/app/shared/components/ui/`, chacun standalone, à importer directement
|
Dans `apps/frontend/src/app/shared/components/ui/`, chacun standalone, à importer directement
|
||||||
|
|||||||
Reference in New Issue
Block a user