Add interactive citizen page with sidebar, display settings, and adaptive CSS

Major rework of the citizen-facing page:
- Chart + sidebar layout (auth/vote/countdown in right sidebar)
- DisplaySettings component (font size, chart density, color palettes)
- Adaptive CSS with clamp() throughout, responsive breakpoints at 480/768/1024
- Baseline charts zoomed on first tier for small consumption detail
- Marginal price chart with dual Y-axes (foyers left, €/m³ right)
- Key metrics banner (5 columns: recettes, palier, prix palier, prix médian, mon prix)
- Client-side p0/impacts computation, draggable median price bar
- Household dots toggle, vote overlay curves
- Auth returns volume_m3, vote captures submitted_at
- Cleaned header nav (removed Accueil/Super Admin for public visitors)
- Terminology: foyer for bills, électeur for votes
- 600m³ added to impact reference volumes
- Realistic seed votes (50 votes, 3 profiles)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-02-23 21:00:22 +01:00
parent 6caea1b809
commit 5dc42af33e
19 changed files with 2109 additions and 416 deletions

View File

@@ -3,19 +3,26 @@
<header class="app-header">
<div class="container header-inner">
<NuxtLink to="/" class="logo">SejeteralO</NuxtLink>
<nav class="header-nav">
<NuxtLink to="/">Accueil</NuxtLink>
<template v-if="authStore.isAuthenticated">
<NuxtLink v-if="authStore.isSuperAdmin" to="/admin">Super Admin</NuxtLink>
<div class="header-right">
<template v-if="authStore.isAuthenticated && authStore.isAdmin">
<NuxtLink
v-else-if="authStore.isAdmin && authStore.communeSlug"
v-if="authStore.isSuperAdmin"
to="/admin"
class="header-link"
>
Administration
</NuxtLink>
<NuxtLink
v-else-if="authStore.communeSlug"
:to="`/admin/communes/${authStore.communeSlug}`"
class="header-link"
>
Gestion commune
</NuxtLink>
<button class="btn btn-secondary btn-sm" @click="logout">Déconnexion</button>
<button class="btn btn-secondary btn-sm" @click="logout">Deconnexion</button>
</template>
</nav>
<DisplaySettings />
</div>
</div>
</header>
<main class="app-main container">
@@ -23,7 +30,7 @@
</main>
<footer class="app-footer">
<div class="container">
SejeteralO Outil de démocratie participative pour la tarification de l'eau
SejeteralO Outil de democratie participative pour la tarification de l'eau
</div>
</footer>
</div>
@@ -50,6 +57,9 @@ function logout() {
background: var(--color-surface);
border-bottom: 1px solid var(--color-border);
padding: 0.75rem 0;
position: sticky;
top: 0;
z-index: 40;
}
.header-inner {
@@ -59,21 +69,25 @@ function logout() {
}
.logo {
font-size: 1.25rem;
font-size: clamp(1.05rem, 3vw, 1.25rem);
font-weight: 700;
color: var(--color-primary);
}
.logo:hover { text-decoration: none; }
.logo:hover {
text-decoration: none;
}
.header-nav {
.header-right {
display: flex;
align-items: center;
gap: 1.5rem;
gap: clamp(0.5rem, 2vw, 1rem);
}
.header-link {
font-size: clamp(0.75rem, 2vw, 0.85rem);
white-space: nowrap;
color: var(--color-text-muted);
}
.header-link:hover { color: var(--color-primary); text-decoration: none; }
.btn-sm {
padding: 0.25rem 0.75rem;
font-size: 0.8rem;
@@ -81,8 +95,8 @@ function logout() {
.app-main {
flex: 1;
padding-top: 2rem;
padding-bottom: 2rem;
padding-top: clamp(1rem, 3vw, 2rem);
padding-bottom: clamp(1rem, 3vw, 2rem);
}
.app-footer {