feat: Permettre la personnalisation du logo et de la couleur principale de l'établissement

Les administrateurs peuvent désormais configurer l'identité visuelle
de leur établissement : upload d'un logo (PNG/JPG, redimensionné
automatiquement via Imagick) et choix d'une couleur principale
appliquée aux boutons et à la navigation.

La couleur est validée côté client et serveur pour garantir la
conformité WCAG AA (contraste ≥ 4.5:1 sur fond blanc). Les
personnalisations sont injectées dynamiquement via CSS variables
et visibles immédiatement après sauvegarde.
This commit is contained in:
2026-02-20 19:35:43 +01:00
parent cfbe96ccf8
commit 6fd084063f
67 changed files with 4584 additions and 29 deletions

View File

@@ -4,9 +4,11 @@
import { isAuthenticated, refreshToken, logout } from '$lib/auth/auth.svelte';
import RoleSwitcher from '$lib/components/organisms/RoleSwitcher/RoleSwitcher.svelte';
import { fetchRoles, resetRoleContext } from '$features/roles/roleContext.svelte';
import { fetchBranding, resetBranding, getLogoUrl } from '$features/branding/brandingStore.svelte';
let { children } = $props();
let isLoggingOut = $state(false);
let logoUrl = $derived(getLogoUrl());
// Load user roles on mount for multi-role context switching (FR5)
// Guard: only fetch if authenticated (or refresh succeeds), otherwise stay in demo mode
@@ -17,6 +19,7 @@
if (!refreshed) return;
}
fetchRoles();
fetchBranding();
});
});
@@ -24,6 +27,7 @@
isLoggingOut = true;
try {
resetRoleContext();
resetBranding();
await logout();
} finally {
isLoggingOut = false;
@@ -43,6 +47,9 @@
<header class="dashboard-header">
<div class="header-content">
<button class="logo-button" onclick={goHome}>
{#if logoUrl}
<img src={logoUrl} alt="Logo de l'établissement" class="header-logo" />
{/if}
<span class="logo-text">Classeo</span>
</button>
<nav class="header-nav">
@@ -98,12 +105,22 @@
}
.logo-button {
display: flex;
align-items: center;
gap: 0.5rem;
background: none;
border: none;
cursor: pointer;
padding: 0.5rem 0;
}
.header-logo {
height: 32px;
width: auto;
object-fit: contain;
border-radius: 0.25rem;
}
.logo-text {
font-size: 1.25rem;
font-weight: 700;