chore: add initial project setup with Docker and React configuration

This commit is contained in:
ɧσℓσ
2025-10-01 00:48:33 +02:00
commit 251b0afac2
33 changed files with 7772 additions and 0 deletions

10
.dockerignore Normal file
View File

@@ -0,0 +1,10 @@
node_modules
npm-debug.log
.git
.gitignore
*.md
.env
.DS_Store
dist
.vscode
.idea

24
.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

17
Dockerfile Normal file
View File

@@ -0,0 +1,17 @@
# Build stage
FROM node:18-alpine AS builder
# Set working directory
WORKDIR /app
# Install dependencies
COPY package.json package-lock.json ./
RUN npm install --legacy-peer-deps
RUN npm install -g serve
# Copy all files
COPY . .
RUN npm run build
CMD ["serve", "-s", "dist", "-l", "3000"]

165
README.md Normal file
View File

@@ -0,0 +1,165 @@
# TP Écoconception Web - Site React
Site web React présentant les résultats complets du TP sur l'écoconception et l'accessibilité web.
## 📋 Contenu du TP
Ce site présente de manière structurée et interactive tous les éléments suivants :
### 🔍 Audit Initial
- **Comparaison d'outils** : Analyse comparative de 5 outils d'écoconception (Website Carbon, EcoIndex, Lighthouse, GreenIT-Analysis, Scaphandre) avec graphique radar
- **Website Carbon Calculator** : Décryptage technique et pédagogique complet
- **Audit Environnemental** : Diagnostic et recommandations pour un site fictif
- **RGESN** : Application du Référentiel Général d'Écoconception des Services Numériques
### ♿ Accessibilité
- **Principes de l'accessibilité** : Les 4 principes POUR (Perceptible, Utilisable, Compréhensible, Robuste)
- **Audit WAVE** : Découverte et utilisation de l'outil WAVE avec exemples de corrections
- **RGAA** : Conformité au Référentiel Général d'Amélioration de l'Accessibilité
### 🗺️ Guide Pratique
- **Guide d'écoconception** : Méthodologie complète pour intégrer l'écoconception dans un projet SAE
- **Planning type** : Organisation sur 4 semaines avec checklists détaillées
- **Outils recommandés** : Liste complète des outils pour chaque besoin
### 🎯 Conclusion
- Bilan des compétences acquises
- Bénéfices multiples (environnementaux, sociaux, économiques, juridiques)
- Ressources pour aller plus loin
## 🚀 Installation et Lancement
### Prérequis
- Node.js (version 16 ou supérieure)
- npm ou yarn
### Étapes d'installation
1. **Installer les dépendances**
```bash
npm install
```
2. **Lancer le serveur de développement**
```bash
npm run dev
```
3. **Ouvrir dans le navigateur**
Le site sera accessible à l'adresse : `http://localhost:5173`
### Commandes disponibles
- `npm run dev` : Lance le serveur de développement
- `npm run build` : Crée une version de production optimisée
- `npm run preview` : Prévisualise la version de production
## 🛠️ Technologies Utilisées
- **React** 18.2 : Framework JavaScript
- **React Router** 6.20 : Navigation entre les pages
- **Recharts** 2.10 : Graphiques interactifs (radar)
- **Vite** 5.0 : Build tool ultra-rapide
- **Font Awesome** 6.5 : Icônes
## 📁 Structure du Projet
```
Web_eco/
├── src/
│ ├── components/ # Composants réutilisables
│ │ ├── Header.jsx
│ │ ├── Sidebar.jsx
│ │ └── Footer.jsx
│ ├── pages/ # Pages du site
│ │ ├── Home.jsx
│ │ ├── ToolsComparison.jsx
│ │ ├── WebsiteCarbon.jsx
│ │ ├── EnvironmentalAudit.jsx
│ │ ├── RGESN.jsx
│ │ ├── Accessibility.jsx
│ │ ├── WAVE.jsx
│ │ ├── RGAA.jsx
│ │ ├── EcoGuide.jsx
│ │ └── Conclusion.jsx
│ ├── App.jsx # Composant principal
│ ├── main.jsx # Point d'entrée
│ └── index.css # Styles globaux
├── index.html # Template HTML
├── package.json # Dépendances
└── vite.config.js # Configuration Vite
```
## 🎨 Fonctionnalités
### Navigation
- **Menu latéral responsive** avec sections organisées
- **Navigation fluide** entre les différentes sections
- **Design moderne** avec palette de couleurs verte (écoresponsable)
### Contenu Interactif
- **Graphique radar** pour comparer les outils d'écoconception
- **Tableaux comparatifs** détaillés
- **Cartes d'information** visuelles
- **Checklists** prêtes à l'emploi
- **Exemples de code** avec syntaxe highlight
### Design Responsive
- **Adapté mobile, tablette et desktop**
- **Sidebar repliable** sur mobile
- **Grids flexibles** qui s'adaptent à la taille d'écran
## 🌱 Bonnes Pratiques Écoconception Appliquées
Ce site pratique ce qu'il enseigne :
**Images optimisées** : Utilisation d'icônes Font Awesome (vectoriel)
**CSS léger** : Pas de framework CSS lourd, styles custom optimisés
**Code minifié** : Build Vite optimise automatiquement
**Lazy loading** : React Router charge les pages à la demande
**Polices système** : Utilisation des polices natives du système
**Palette sobre** : Couleurs limitées et cohérentes
## 📊 Résultats Attendus
Après avoir suivi ce TP, vous serez capable de :
- ✅ Mesurer l'empreinte environnementale d'un site web
- ✅ Auditer l'accessibilité avec des outils professionnels
- ✅ Appliquer les référentiels RGESN et RGAA
- ✅ Proposer des recommandations techniques priorisées
- ✅ Documenter et justifier vos choix d'écoconception
- ✅ Intégrer ces pratiques dans vos projets futurs
## 📚 Ressources Complémentaires
### Référentiels
- [RGESN](https://ecoresponsable.numerique.gouv.fr/publications/referentiel-general-ecoconception/)
- [RGAA](https://accessibilite.numerique.gouv.fr/)
- [WCAG 2.1](https://www.w3.org/WAI/WCAG21/quickref/)
### Outils
- [Website Carbon Calculator](https://www.websitecarbon.com/)
- [EcoIndex](https://www.ecoindex.fr/)
- [WAVE](https://wave.webaim.org/)
- [Lighthouse](https://developers.google.com/web/tools/lighthouse)
### Communautés
- [Collectif Conception Numérique Responsable](https://collectif.greenit.fr/)
- [Institut du Numérique Responsable](https://institutnr.org/)
- [WebAIM](https://webaim.org/)
## 👨‍🏫 Auteur du TP
**Vincent Courboulay**
## 📄 Licence
Ce projet est à usage éducatif dans le cadre du TP d'écoconception web.
## 🤝 Contribution
Si vous trouvez des améliorations ou des corrections à apporter, n'hésitez pas à proposer vos modifications.
---
**Bon travail et n'oubliez pas : chaque ligne de code compte pour un numérique plus durable et inclusif ! 🌍**

13
docker-compose.yml Normal file
View File

@@ -0,0 +1,13 @@
version: '3.8'
services:
# Web site service
web-site:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000"
environment:
- NODE_ENV=production
restart: unless-stopped

13
index.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TP Écoconception Web</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

28
nginx.conf Normal file
View File

@@ -0,0 +1,28 @@
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Gestion du SPA (Single Page Application)
location / {
try_files $uri $uri/ /index.html;
}
# Cache pour les assets statiques
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Compression gzip pour l'écoconception
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json application/javascript;
# Sécurité headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
}

2079
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

23
package.json Normal file
View File

@@ -0,0 +1,23 @@
{
"name": "ecoconception-web-tp",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.20.0",
"recharts": "^2.10.0"
},
"devDependencies": {
"@types/react": "^18.2.43",
"@types/react-dom": "^18.2.17",
"@vitejs/plugin-react": "^4.2.1",
"vite": "^5.0.8"
}
}

27
src/App.css Normal file
View File

@@ -0,0 +1,27 @@
.app {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.app-content {
display: flex;
flex: 1;
margin-top: 70px;
}
.main-content {
flex: 1;
padding: 2rem;
width: 100%;
}
@media (max-width: 768px) {
.main-content {
padding: 1rem;
}
.app-content {
margin-top: 60px;
}
}

48
src/App.jsx Normal file
View File

@@ -0,0 +1,48 @@
import React, { useState } from 'react'
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import Header from './components/Header'
import Sidebar from './components/Sidebar'
import Footer from './components/Footer'
import Home from './pages/Home'
import ToolsComparison from './pages/ToolsComparison'
import WebsiteCarbon from './pages/WebsiteCarbon'
import EnvironmentalAudit from './pages/EnvironmentalAudit'
import RGESN from './pages/RGESN'
import Accessibility from './pages/Accessibility'
import WAVE from './pages/WAVE'
import RGAA from './pages/RGAA'
import EcoGuide from './pages/EcoGuide'
import Conclusion from './pages/Conclusion'
import './App.css'
function App() {
const [sidebarOpen, setSidebarOpen] = useState(false)
return (
<Router>
<div className="app">
<Header toggleSidebar={() => setSidebarOpen(!sidebarOpen)} />
<div className="app-content">
<Sidebar isOpen={sidebarOpen} closeSidebar={() => setSidebarOpen(false)} />
<main className="main-content">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/tools-comparison" element={<ToolsComparison />} />
<Route path="/website-carbon" element={<WebsiteCarbon />} />
<Route path="/environmental-audit" element={<EnvironmentalAudit />} />
<Route path="/rgesn" element={<RGESN />} />
<Route path="/accessibility" element={<Accessibility />} />
<Route path="/wave" element={<WAVE />} />
<Route path="/rgaa" element={<RGAA />} />
<Route path="/eco-guide" element={<EcoGuide />} />
<Route path="/conclusion" element={<Conclusion />} />
</Routes>
</main>
</div>
<Footer />
</div>
</Router>
)
}
export default App

43
src/components/Footer.css Normal file
View File

@@ -0,0 +1,43 @@
.footer {
background: var(--primary-dark);
color: var(--white);
padding: 1.5rem 2rem;
margin-top: auto;
}
.footer-content {
max-width: 1400px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 1rem;
}
.footer-section {
display: flex;
align-items: center;
gap: 0.5rem;
}
.footer-section i {
font-size: 1.2rem;
color: var(--accent);
}
.footer-section p {
margin: 0;
font-size: 0.9rem;
}
@media (max-width: 768px) {
.footer-content {
flex-direction: column;
text-align: center;
}
.footer-section {
justify-content: center;
}
}

24
src/components/Footer.jsx Normal file
View File

@@ -0,0 +1,24 @@
import React from 'react'
import './Footer.css'
function Footer() {
return (
<footer className="footer">
<div className="footer-content">
<div className="footer-section">
<i className="fas fa-leaf"></i>
<p>TP Écoconception Web - 2024</p>
</div>
<div className="footer-section">
<p>Vincent Courboulay</p>
</div>
<div className="footer-section">
<i className="fas fa-recycle"></i>
<p>Numérique Responsable & Accessible</p>
</div>
</div>
</footer>
)
}
export default Footer

77
src/components/Header.css Normal file
View File

@@ -0,0 +1,77 @@
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
background: linear-gradient(135deg, var(--primary-dark), var(--primary));
color: var(--white);
padding: 1rem 2rem;
box-shadow: 0 2px 10px var(--shadow);
z-index: 1000;
}
.header-content {
max-width: 1400px;
margin: 0 auto;
display: flex;
align-items: center;
gap: 2rem;
}
.menu-btn {
background: none;
border: none;
color: var(--white);
font-size: 1.5rem;
cursor: pointer;
padding: 0.5rem;
display: flex;
align-items: center;
transition: transform 0.3s;
}
.menu-btn:hover {
transform: scale(1.1);
}
.header-title {
display: flex;
align-items: center;
gap: 0.75rem;
flex: 1;
}
.header-icon {
font-size: 1.8rem;
}
.header-title h1 {
font-size: 1.5rem;
font-weight: 600;
}
.header-subtitle {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.95rem;
opacity: 0.9;
}
@media (max-width: 768px) {
.header {
padding: 0.75rem 1rem;
}
.header-content {
gap: 1rem;
}
.header-title h1 {
font-size: 1.1rem;
}
.header-subtitle {
display: none;
}
}

24
src/components/Header.jsx Normal file
View File

@@ -0,0 +1,24 @@
import React from 'react'
import './Header.css'
function Header({ toggleSidebar }) {
return (
<header className="header">
<div className="header-content">
<button className="menu-btn" onClick={toggleSidebar}>
<i className="fas fa-bars"></i>
</button>
<div className="header-title">
<i className="fas fa-leaf header-icon"></i>
<h1>TP Écoconception Web</h1>
</div>
<div className="header-subtitle">
<i className="fas fa-globe"></i>
<span>Numérique Responsable</span>
</div>
</div>
</header>
)
}
export default Header

108
src/components/Sidebar.css Normal file
View File

@@ -0,0 +1,108 @@
.sidebar-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 998;
}
.sidebar-overlay.active {
display: block;
}
.sidebar {
position: fixed;
left: 0;
top: 70px;
bottom: 0;
width: 280px;
background: var(--white);
box-shadow: 2px 0 10px var(--shadow);
transform: translateX(-100%);
transition: transform 0.3s ease;
overflow-y: auto;
z-index: 999;
}
.sidebar.open {
transform: translateX(0);
}
.sidebar-nav {
padding: 1rem 0;
}
.menu-item {
margin-bottom: 0.5rem;
}
.nav-link,
.nav-section {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.875rem 1.5rem;
color: var(--text);
text-decoration: none;
transition: all 0.3s;
font-weight: 500;
}
.nav-section {
color: var(--primary);
font-weight: 600;
cursor: default;
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.nav-link:hover {
background: var(--accent);
color: var(--primary-dark);
}
.nav-link.active {
background: var(--primary);
color: var(--white);
border-left: 4px solid var(--primary-dark);
}
.sub-menu {
padding-left: 1rem;
}
.sub-link {
font-size: 0.9rem;
padding: 0.75rem 1.5rem;
}
.nav-link i {
width: 20px;
text-align: center;
font-size: 1.1rem;
}
@media (min-width: 1024px) {
.sidebar {
transform: translateX(0);
}
.sidebar-overlay {
display: none !important;
}
.main-content {
margin-left: 280px;
}
}
@media (max-width: 768px) {
.sidebar {
top: 60px;
width: 260px;
}
}

View File

@@ -0,0 +1,76 @@
import React from 'react'
import { NavLink } from 'react-router-dom'
import './Sidebar.css'
function Sidebar({ isOpen, closeSidebar }) {
const menuItems = [
{ path: '/', icon: 'fa-home', label: 'Accueil' },
{
label: 'Audit Initial',
icon: 'fa-search',
children: [
{ path: '/tools-comparison', icon: 'fa-chart-bar', label: 'Comparaison d\'outils' },
{ path: '/website-carbon', icon: 'fa-calculator', label: 'Website Carbon' },
{ path: '/environmental-audit', icon: 'fa-leaf', label: 'Audit Environnemental' },
{ path: '/rgesn', icon: 'fa-book', label: 'RGESN' },
]
},
{
label: 'Accessibilité',
icon: 'fa-universal-access',
children: [
{ path: '/accessibility', icon: 'fa-users', label: 'Principes' },
{ path: '/wave', icon: 'fa-water', label: 'WAVE' },
{ path: '/rgaa', icon: 'fa-check-circle', label: 'RGAA' },
]
},
{ path: '/eco-guide', icon: 'fa-map', label: 'Guide Écoconception' },
{ path: '/conclusion', icon: 'fa-flag-checkered', label: 'Conclusion' },
]
return (
<>
<div className={`sidebar-overlay ${isOpen ? 'active' : ''}`} onClick={closeSidebar}></div>
<aside className={`sidebar ${isOpen ? 'open' : ''}`}>
<nav className="sidebar-nav">
{menuItems.map((item, index) => (
<div key={index} className="menu-item">
{item.path ? (
<NavLink
to={item.path}
className={({ isActive }) => `nav-link ${isActive ? 'active' : ''}`}
onClick={closeSidebar}
>
<i className={`fas ${item.icon}`}></i>
<span>{item.label}</span>
</NavLink>
) : (
<>
<div className="nav-section">
<i className={`fas ${item.icon}`}></i>
<span>{item.label}</span>
</div>
<div className="sub-menu">
{item.children.map((child, childIndex) => (
<NavLink
key={childIndex}
to={child.path}
className={({ isActive }) => `nav-link sub-link ${isActive ? 'active' : ''}`}
onClick={closeSidebar}
>
<i className={`fas ${child.icon}`}></i>
<span>{child.label}</span>
</NavLink>
))}
</div>
</>
)}
</div>
))}
</nav>
</aside>
</>
)
}
export default Sidebar

60
src/index.css Normal file
View File

@@ -0,0 +1,60 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary: #2d6a4f;
--primary-dark: #1b4332;
--primary-light: #40916c;
--secondary: #52b788;
--accent: #74c69d;
--bg: #f8f9fa;
--text: #212529;
--text-light: #6c757d;
--white: #ffffff;
--border: #dee2e6;
--shadow: rgba(0, 0, 0, 0.1);
--danger: #dc3545;
--warning: #ffc107;
--success: #28a745;
--info: #17a2b8;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: var(--bg);
color: var(--text);
line-height: 1.6;
}
code {
font-family: 'Courier New', monospace;
background: #f4f4f4;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.9em;
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-track {
background: var(--bg);
}
::-webkit-scrollbar-thumb {
background: var(--primary);
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--primary-dark);
}

10
src/main.jsx Normal file
View File

@@ -0,0 +1,10 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)

384
src/pages/Accessibility.jsx Normal file
View File

@@ -0,0 +1,384 @@
import React from 'react'
import './SharedPages.css'
function Accessibility() {
return (
<div className="shared-page">
<header className="page-header">
<i className="fas fa-universal-access"></i>
<h1>Principes de l'Accessibilité Web</h1>
<p className="subtitle">Vers un numérique inclusif</p>
</header>
<section className="content-section">
<h2><i className="fas fa-question-circle"></i> Qu'est-ce que l'accessibilité numérique ?</h2>
<p>
L'accessibilité numérique consiste à rendre les sites web et applications utilisables par tous,
<strong> y compris les personnes en situation de handicap</strong>. Cela englobe les handicaps visuels,
auditifs, moteurs, cognitifs et temporaires.
</p>
<div className="stats-grid" style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1.5rem', marginTop: '2rem'}}>
<div style={{padding: '1.5rem', background: 'linear-gradient(135deg, var(--primary), var(--secondary))', color: 'white', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold'}}>15%</div>
<div>de la population mondiale vit avec un handicap</div>
</div>
<div style={{padding: '1.5rem', background: 'linear-gradient(135deg, var(--info), #52b788)', color: 'white', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold'}}>1 Md</div>
<div>de personnes dans le monde</div>
</div>
<div style={{padding: '1.5rem', background: 'linear-gradient(135deg, var(--warning), #ffc107)', color: 'white', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold'}}>70%</div>
<div>des sites ne sont pas accessibles</div>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-users"></i> Types de handicaps concernés</h2>
<div className="disabilities-grid" style={{display: 'grid', gap: '1.5rem'}}>
{[
{
type: 'Handicap visuel',
icon: 'fa-eye-slash',
examples: 'Cécité, malvoyance, daltonisme',
needs: 'Lecteurs d\'écran, contrastes élevés, alternatives textuelles',
color: '#2d6a4f'
},
{
type: 'Handicap auditif',
icon: 'fa-deaf',
examples: 'Surdité, malentendance',
needs: 'Sous-titres, transcriptions textuelles, langue des signes',
color: '#52b788'
},
{
type: 'Handicap moteur',
icon: 'fa-wheelchair',
examples: 'Mobilité réduite, tremblements, paralysie',
needs: 'Navigation au clavier, zones cliquables larges, commandes vocales',
color: '#74c69d'
},
{
type: 'Handicap cognitif',
icon: 'fa-brain',
examples: 'Dyslexie, TDAH, troubles de la mémoire',
needs: 'Langage simple, navigation claire, temps de lecture adaptable',
color: '#95d5b2'
},
{
type: 'Handicap temporaire',
icon: 'fa-band-aid',
examples: 'Bras cassé, conjonctivite, environnement bruyant',
needs: 'Adaptabilité, multi-modalité',
color: '#b7e4c7'
}
].map((disability, index) => (
<div key={index} style={{
padding: '1.5rem',
background: 'var(--bg)',
borderRadius: '8px',
borderLeft: `4px solid ${disability.color}`,
display: 'grid',
gap: '0.75rem'
}}>
<h3 style={{margin: 0, display: 'flex', alignItems: 'center', gap: '0.75rem', color: 'var(--primary-dark)'}}>
<i className={`fas ${disability.icon}`} style={{color: disability.color}}></i>
{disability.type}
</h3>
<div>
<strong>Exemples :</strong> {disability.examples}
</div>
<div>
<strong>Besoins :</strong> {disability.needs}
</div>
</div>
))}
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-balance-scale"></i> WCAG : Les 4 principes fondamentaux</h2>
<p style={{marginBottom: '2rem'}}>
Les <strong>Web Content Accessibility Guidelines (WCAG)</strong> définissent 4 principes universels pour l'accessibilité web,
repris par le RGAA français :
</p>
<div className="principles-grid" style={{display: 'grid', gap: '2rem'}}>
<div style={{padding: '2rem', background: 'var(--bg)', borderRadius: '8px', borderTop: '4px solid #2d6a4f'}}>
<div style={{display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1rem'}}>
<div style={{
width: '60px',
height: '60px',
background: 'linear-gradient(135deg, #2d6a4f, #52b788)',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'white',
fontSize: '1.5rem',
fontWeight: 'bold'
}}>1</div>
<h3 style={{margin: 0, color: 'var(--primary-dark)'}}>Perceptible</h3>
</div>
<p><strong>Les utilisateurs doivent pouvoir percevoir l'information</strong></p>
<ul>
<li>Fournir des alternatives textuelles aux contenus non textuels (images, vidéos)</li>
<li>Assurer des contrastes suffisants (au moins 4.5:1 pour le texte)</li>
<li>Ne pas se fier uniquement à la couleur pour transmettre l'information</li>
<li>Rendre le contenu adaptable (responsive, redimensionnable)</li>
</ul>
<div className="example-box" style={{marginTop: '1rem', padding: '1rem', background: 'white', borderRadius: '4px'}}>
<strong>Exemple :</strong> Une image doit avoir un attribut <code>alt</code> descriptif pour les lecteurs d'écran.
</div>
</div>
<div style={{padding: '2rem', background: 'var(--bg)', borderRadius: '8px', borderTop: '4px solid #52b788'}}>
<div style={{display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1rem'}}>
<div style={{
width: '60px',
height: '60px',
background: 'linear-gradient(135deg, #52b788, #74c69d)',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'white',
fontSize: '1.5rem',
fontWeight: 'bold'
}}>2</div>
<h3 style={{margin: 0, color: 'var(--primary-dark)'}}>Utilisable</h3>
</div>
<p><strong>Les utilisateurs doivent pouvoir utiliser l'interface</strong></p>
<ul>
<li>Toutes les fonctionnalités accessibles au clavier (sans souris)</li>
<li>Laisser suffisamment de temps pour lire et utiliser le contenu</li>
<li>Ne pas utiliser d'éléments susceptibles de provoquer des crises (flashs)</li>
<li>Fournir des aides à la navigation (menu, fil d'Ariane, liens d'évitement)</li>
</ul>
<div className="example-box" style={{marginTop: '1rem', padding: '1rem', background: 'white', borderRadius: '4px'}}>
<strong>Exemple :</strong> Un menu déroulant doit être navigable avec les flèches du clavier et la touche Entrée.
</div>
</div>
<div style={{padding: '2rem', background: 'var(--bg)', borderRadius: '8px', borderTop: '4px solid #74c69d'}}>
<div style={{display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1rem'}}>
<div style={{
width: '60px',
height: '60px',
background: 'linear-gradient(135deg, #74c69d, #95d5b2)',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'white',
fontSize: '1.5rem',
fontWeight: 'bold'
}}>3</div>
<h3 style={{margin: 0, color: 'var(--primary-dark)'}}>Compréhensible</h3>
</div>
<p><strong>Les utilisateurs doivent pouvoir comprendre l'information et l'interface</strong></p>
<ul>
<li>Rendre le texte lisible et compréhensible (langage simple, abréviations expliquées)</li>
<li>Faire en sorte que les pages fonctionnent de manière prévisible</li>
<li>Aider les utilisateurs à éviter et corriger les erreurs (validation de formulaires claire)</li>
<li>Fournir des instructions claires et des labels explicites</li>
</ul>
<div className="example-box" style={{marginTop: '1rem', padding: '1rem', background: 'white', borderRadius: '4px'}}>
<strong>Exemple :</strong> Un message d'erreur de formulaire doit expliquer clairement le problème et comment le corriger.
</div>
</div>
<div style={{padding: '2rem', background: 'var(--bg)', borderRadius: '8px', borderTop: '4px solid #95d5b2'}}>
<div style={{display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1rem'}}>
<div style={{
width: '60px',
height: '60px',
background: 'linear-gradient(135deg, #95d5b2, #b7e4c7)',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'white',
fontSize: '1.5rem',
fontWeight: 'bold'
}}>4</div>
<h3 style={{margin: 0, color: 'var(--primary-dark)'}}>Robuste</h3>
</div>
<p><strong>Le contenu doit être compatible avec les technologies actuelles et futures</strong></p>
<ul>
<li>Utiliser du HTML valide et sémantique</li>
<li>Assurer la compatibilité avec les technologies d'assistance (lecteurs d'écran)</li>
<li>Utiliser ARIA (Accessible Rich Internet Applications) quand nécessaire</li>
<li>Tester avec différents navigateurs et technologies d'assistance</li>
</ul>
<div className="example-box" style={{marginTop: '1rem', padding: '1rem', background: 'white', borderRadius: '4px'}}>
<strong>Exemple :</strong> Utiliser les balises sémantiques <code>&lt;nav&gt;</code>, <code>&lt;main&gt;</code>, <code>&lt;article&gt;</code> plutôt que des <code>&lt;div&gt;</code> génériques.
</div>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-flag-checkered"></i> Le RGAA : Référentiel français</h2>
<div className="info-card">
<div className="info-row">
<strong>Nom complet:</strong>
<span>Référentiel Général d'Amélioration de l'Accessibilité</span>
</div>
<div className="info-row">
<strong>Créé par:</strong>
<span>DINUM (Direction Interministérielle du Numérique)</span>
</div>
<div className="info-row">
<strong>Base:</strong>
<span>WCAG 2.1 (adapté au contexte français)</span>
</div>
<div className="info-row">
<strong>Version actuelle:</strong>
<span>RGAA 4.1 (2021)</span>
</div>
<div className="info-row">
<strong>Obligation légale:</strong>
<span>Services publics, entreprises > 250M CA</span>
</div>
</div>
<div style={{marginTop: '2rem'}}>
<h3>Les 13 thèmes du RGAA</h3>
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))', gap: '0.75rem', marginTop: '1rem'}}>
{[
'Images', 'Cadres', 'Couleurs', 'Multimédia', 'Tableaux', 'Liens',
'Scripts', 'Éléments obligatoires', 'Structuration', 'Présentation',
'Formulaires', 'Navigation', 'Consultation'
].map((theme, index) => (
<div key={index} style={{
padding: '0.75rem',
background: 'var(--primary)',
color: 'white',
borderRadius: '4px',
textAlign: 'center',
fontSize: '0.9rem',
fontWeight: '500'
}}>
{theme}
</div>
))}
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-hands-helping"></i> Bénéfices de l'accessibilité</h2>
<div className="benefits-grid" style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '1.5rem'}}>
<div style={{padding: '1.5rem', background: '#d4edda', borderRadius: '8px', borderLeft: '4px solid var(--success)'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-users"></i> Social & Éthique
</h4>
<ul style={{marginBottom: 0}}>
<li>Inclusion de tous les utilisateurs</li>
<li>Respect des droits fondamentaux</li>
<li>Image responsable</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: '#cfe2ff', borderRadius: '8px', borderLeft: '4px solid var(--info)'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-chart-line"></i> Business
</h4>
<ul style={{marginBottom: 0}}>
<li>Élargissement de l'audience (+15%)</li>
<li>Amélioration du SEO</li>
<li>Réduction du taux de rebond</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: '#fff3cd', borderRadius: '8px', borderLeft: '4px solid var(--warning)'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-gavel"></i> Légal
</h4>
<ul style={{marginBottom: 0}}>
<li>Conformité réglementaire</li>
<li>Éviter les sanctions</li>
<li>Anticipation des obligations</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: '#d1ecf1', borderRadius: '8px', borderLeft: '4px solid #0dcaf0'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-code"></i> Technique
</h4>
<ul style={{marginBottom: 0}}>
<li>Code plus robuste et maintenable</li>
<li>Meilleure compatibilité</li>
<li>Performance améliorée</li>
</ul>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-tools"></i> Bonnes pratiques essentielles</h2>
<div className="best-practices" style={{display: 'grid', gap: '1rem'}}>
{[
{
practice: 'Ajouter des attributs alt aux images',
code: '<img src="logo.png" alt="Logo de l\'organisation">',
impact: 'Essentiel pour les lecteurs d\'écran'
},
{
practice: 'Assurer un contraste suffisant',
code: 'Ratio minimum 4.5:1 pour texte normal, 3:1 pour texte large',
impact: 'Lisibilité pour malvoyants et daltoniens'
},
{
practice: 'Structurer avec des titres hiérarchiques',
code: '<h1>, <h2>, <h3>... sans sauter de niveau',
impact: 'Navigation et compréhension de la structure'
},
{
practice: 'Rendre les formulaires accessibles',
code: '<label for="email">Email</label><input id="email" type="email">',
impact: 'Association claire label/champ'
},
{
practice: 'Navigation au clavier',
code: 'tabindex, focus visible, touches Entrée/Échap fonctionnelles',
impact: 'Utilisateurs sans souris'
},
{
practice: 'Utiliser ARIA avec prudence',
code: 'role="navigation", aria-label="Menu principal"',
impact: 'Enrichir la sémantique pour technologies d\'assistance'
}
].map((item, index) => (
<div key={index} style={{
padding: '1.5rem',
background: 'var(--bg)',
borderRadius: '8px',
borderLeft: '4px solid var(--primary)'
}}>
<h4 style={{marginTop: 0, color: 'var(--primary-dark)'}}>{item.practice}</h4>
<div className="formula">
<code>{item.code}</code>
</div>
<p style={{margin: '0.5rem 0 0 0', color: 'var(--text-light)', fontSize: '0.9rem'}}>
<strong>Impact :</strong> {item.impact}
</p>
</div>
))}
</div>
</section>
<div className="conclusion-banner">
<i className="fas fa-check-circle"></i>
<div>
<strong>L'accessibilité, c'est pour tout le monde</strong>
<p>Un site accessible est plus utilisable, plus performant, mieux référencé et conforme à la loi.
L'accessibilité n'est pas une contrainte, c'est une opportunité d'améliorer l'expérience de tous les utilisateurs.</p>
</div>
</div>
</div>
)
}
export default Accessibility

316
src/pages/Conclusion.jsx Normal file
View File

@@ -0,0 +1,316 @@
import React from 'react'
import './SharedPages.css'
function Conclusion() {
return (
<div className="shared-page">
<header className="page-header">
<i className="fas fa-flag-checkered"></i>
<h1>Conclusion</h1>
<p className="subtitle">Bilan et perspectives du numérique responsable</p>
</header>
<section className="content-section">
<h2><i className="fas fa-check-circle"></i> Synthèse de l'analyse</h2>
<p>
Ce compte rendu présente une analyse complète des enjeux du <strong>numérique responsable</strong>,
à la fois sous l'angle environnemental et social. L'audit réalisé sur ville-de-chauray.fr
a permis d'identifier des axes d'amélioration concrets pour réduire l'impact environnemental et améliorer l'accessibilité.
</p>
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: '2rem', marginTop: '2rem'}}>
<div style={{padding: '2rem', background: 'linear-gradient(135deg, #2d6a4f, #52b788)', color: 'white', borderRadius: '12px'}}>
<div style={{fontSize: '3rem', marginBottom: '1rem'}}>🌱</div>
<h3 style={{marginTop: 0, color: 'white'}}>Écoconception</h3>
<ul style={{margin: 0}}>
<li>Utilisation d'outils d'audit (Website Carbon, EcoIndex)</li>
<li>Mesure de l'impact CO₂ et optimisation</li>
<li>Application du RGESN</li>
<li>Recommandations priorisées</li>
</ul>
</div>
<div style={{padding: '2rem', background: 'linear-gradient(135deg, #17a2b8, #52b788)', color: 'white', borderRadius: '12px'}}>
<div style={{fontSize: '3rem', marginBottom: '1rem'}}></div>
<h3 style={{marginTop: 0, color: 'white'}}>Accessibilité</h3>
<ul style={{margin: 0}}>
<li>Principes POUR (Perceptible, Utilisable, Compréhensible, Robuste)</li>
<li>Audit avec WAVE</li>
<li>Conformité RGAA</li>
<li>Corrections techniques</li>
</ul>
</div>
<div style={{padding: '2rem', background: 'linear-gradient(135deg, #ffc107, #ff9800)', color: 'white', borderRadius: '12px'}}>
<div style={{fontSize: '3rem', marginBottom: '1rem'}}>🚀</div>
<h3 style={{marginTop: 0, color: 'white'}}>Méthodologie</h3>
<ul style={{margin: 0}}>
<li>Guide d'écoconception pour projet SAE</li>
<li>Planning et checklists</li>
<li>Documentation technique</li>
<li>Argumentaire pour décideurs</li>
</ul>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-leaf"></i> Volet Écoconception Environnemental</h2>
<div style={{padding: '2rem', background: 'var(--bg)', borderRadius: '8px', marginBottom: '1.5rem'}}>
<h3>Compétences acquises</h3>
<ul>
<li>
<strong>Mesurer l'impact :</strong> Vous savez utiliser Website Carbon Calculator pour estimer
l'empreinte carbone d'une page web (émissions de CO₂, poids des pages, nombre de requêtes)
</li>
<li>
<strong>Analyser et comparer :</strong> Vous maîtrisez la comparaison d'outils d'écoconception
(EcoIndex, Lighthouse, GreenIT-Analysis, Scaphandre)
</li>
<li>
<strong>Appliquer le RGESN :</strong> Vous pouvez auditer un service selon les 79 critères du
Référentiel Général d'Écoconception des Services Numériques
</li>
<li>
<strong>Proposer des solutions :</strong> Vous êtes capable de rédiger un rapport d'audit complet
avec diagnostic, solutions techniques et plan d'action réaliste
</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: '#d4edda', borderRadius: '8px', borderLeft: '4px solid var(--success)'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-chart-line"></i> Résultats types attendus
</h4>
<ul style={{marginBottom: 0}}>
<li>Réduction de <strong>40-50%</strong> de l'empreinte carbone d'un site</li>
<li>Amélioration du score Lighthouse de <strong>20-30 points</strong></li>
<li>Diminution du poids des pages de <strong>30-60%</strong></li>
<li>Temps de chargement divisé par <strong>2</strong></li>
</ul>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-universal-access"></i> Volet Accessibilité et Inclusion</h2>
<div style={{padding: '2rem', background: 'var(--bg)', borderRadius: '8px', marginBottom: '1.5rem'}}>
<h3>Compétences acquises</h3>
<ul>
<li>
<strong>Identifier les erreurs :</strong> Vous savez utiliser WAVE pour détecter rapidement
les problèmes d'accessibilité (images sans alt, contrastes insuffisants, structure incohérente)
</li>
<li>
<strong>Comprendre les 4 principes :</strong> Vous maîtrisez les principes POUR
(Perceptible, Utilisable, Compréhensible, Robuste)
</li>
<li>
<strong>Auditer selon le RGAA :</strong> Vous pouvez évaluer la conformité d'un site
selon les 106 critères du référentiel français
</li>
<li>
<strong>Proposer des corrections :</strong> Vous êtes capable de prioriser les actions
correctives en fonction de leur impact et faisabilité
</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: '#cfe2ff', borderRadius: '8px', borderLeft: '4px solid var(--info)'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-users"></i> Impact social
</h4>
<ul style={{marginBottom: 0}}>
<li><strong>15%</strong> de la population mondiale concernée (1 milliard de personnes)</li>
<li><strong>+20-35%</strong> d'audience potentielle avec un site accessible</li>
<li>Meilleure expérience pour <strong>tous</strong> les utilisateurs (seniors, mobiles, contextes difficiles)</li>
</ul>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-balance-scale"></i> Vision Globale : Numérique Responsable</h2>
<div style={{padding: '2rem', background: 'linear-gradient(135deg, var(--primary), var(--primary-light))', color: 'white', borderRadius: '12px', marginBottom: '2rem'}}>
<h3 style={{marginTop: 0, color: 'white', textAlign: 'center', fontSize: '1.5rem'}}>
Service Numérique Idéal = Sobre + Performant + Accessible
</h3>
<p style={{textAlign: 'center', fontSize: '1.1rem', margin: 0}}>
En combinant écoconception et accessibilité, vous créez des services de qualité qui bénéficient à tous
</p>
</div>
<div style={{display: 'grid', gap: '1.5rem'}}>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, color: 'var(--primary-dark)'}}>Vous savez argumenter</h4>
<p>
Vous êtes capable de convaincre décideurs et clients sur l'importance de ces démarches,
en mettant en avant les bénéfices environnementaux, sociaux, économiques et juridiques.
</p>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, color: 'var(--primary-dark)'}}>Vous savez mobiliser</h4>
<p>
Vous pouvez proposer un plan d'action concret avec échéancier, acteurs concernés,
et indicateurs de suivi pour mobiliser les parties prenantes.
</p>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, color: 'var(--primary-dark)'}}>Vous avez un esprit critique</h4>
<p>
Vous avez développé un esprit critique face aux outils et référentiels,
en identifiant leurs forces et leurs limites.
</p>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-trophy"></i> Bénéfices Multiples</h2>
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '1.5rem'}}>
<div style={{padding: '1.5rem', background: '#d4edda', borderRadius: '8px', textAlign: 'center'}}>
<i className="fas fa-leaf" style={{fontSize: '2.5rem', color: '#28a745', marginBottom: '1rem'}}></i>
<h4 style={{color: '#155724', marginBottom: '0.5rem'}}>Environnementaux</h4>
<p style={{margin: 0, color: '#155724'}}>Réduction empreinte carbone, économie ressources</p>
</div>
<div style={{padding: '1.5rem', background: '#cfe2ff', borderRadius: '8px', textAlign: 'center'}}>
<i className="fas fa-users" style={{fontSize: '2.5rem', color: '#0d6efd', marginBottom: '1rem'}}></i>
<h4 style={{color: '#084298', marginBottom: '0.5rem'}}>Sociaux</h4>
<p style={{margin: 0, color: '#084298'}}>Inclusion, accessibilité universelle</p>
</div>
<div style={{padding: '1.5rem', background: '#fff3cd', borderRadius: '8px', textAlign: 'center'}}>
<i className="fas fa-euro-sign" style={{fontSize: '2.5rem', color: '#856404', marginBottom: '1rem'}}></i>
<h4 style={{color: '#856404', marginBottom: '0.5rem'}}>Économiques</h4>
<p style={{margin: 0, color: '#856404'}}>Réduction coûts, meilleur SEO, + conversions</p>
</div>
<div style={{padding: '1.5rem', background: '#f8d7da', borderRadius: '8px', textAlign: 'center'}}>
<i className="fas fa-gavel" style={{fontSize: '2.5rem', color: '#721c24', marginBottom: '1rem'}}></i>
<h4 style={{color: '#721c24', marginBottom: '0.5rem'}}>Juridiques</h4>
<p style={{margin: 0, color: '#721c24'}}>Conformité légale, anticipation obligations</p>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-briefcase"></i> Impact Professionnel</h2>
<div style={{display: 'grid', gap: '2rem'}}>
<div style={{padding: '2rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid var(--primary)'}}>
<h3 style={{marginTop: 0}}>Ces compétences sont recherchées</h3>
<p>
L'écoconception et l'accessibilité sont de plus en plus demandées dans le monde professionnel :
</p>
<ul>
<li><strong>Obligations légales croissantes</strong> (loi REEN, accessibilité numérique)</li>
<li><strong>RSE prioritaire</strong> pour les entreprises</li>
<li><strong>Demande clients</strong> sensibles aux enjeux environnementaux et sociaux</li>
<li><strong>Différenciation concurrentielle</strong> importante</li>
</ul>
</div>
<div style={{padding: '2rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid var(--secondary)'}}>
<h3 style={{marginTop: 0}}>Valorisez ces compétences</h3>
<ul>
<li>Intégrez ces pratiques dans vos <strong>projets personnels et professionnels</strong></li>
<li>Mentionnez-les sur votre <strong>CV et portfolio</strong></li>
<li>Obtenez des <strong>certifications</strong> (Opquast, accessibilité numérique)</li>
<li>Partagez vos réalisations sur <strong>LinkedIn et GitHub</strong></li>
<li>Contribuez à des <strong>projets open source</strong> écoresponsables</li>
</ul>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-rocket"></i> Pour Aller Plus Loin</h2>
<div style={{display: 'grid', gap: '1.5rem'}}>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-book"></i> Ressources complémentaires
</h4>
<ul style={{marginBottom: 0}}>
<li><strong>RGESN :</strong> <a href="https://ecoresponsable.numerique.gouv.fr/publications/referentiel-general-ecoconception/" target="_blank" rel="noopener noreferrer">numerique.gouv.fr</a></li>
<li><strong>RGAA :</strong> <a href="https://accessibilite.numerique.gouv.fr/" target="_blank" rel="noopener noreferrer">accessibilite.numerique.gouv.fr</a></li>
<li><strong>GR491 :</strong> 491 bonnes pratiques numériques responsables</li>
<li><strong>The Green Web Foundation :</strong> Annuaire hébergeurs verts</li>
<li><strong>WebAIM :</strong> Ressources et formations accessibilité</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-users"></i> Communautés
</h4>
<ul style={{marginBottom: 0}}>
<li><strong>Collectif Conception Numérique Responsable</strong> (CNUMR)</li>
<li><strong>Association Point de MIR</strong> (numérique responsable)</li>
<li><strong>Institut du Numérique Responsable</strong> (INR)</li>
<li><strong>Club Green IT</strong></li>
<li><strong>Access42</strong> (accessibilité numérique)</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-certificate"></i> Certifications
</h4>
<ul style={{marginBottom: 0}}>
<li><strong>Opquast :</strong> Certification qualité web</li>
<li><strong>Accessibilité numérique :</strong> Formation et certification Access42</li>
<li><strong>Écoconception web :</strong> Formation GreenIT</li>
<li><strong>WCAG :</strong> Certifications internationales</li>
</ul>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-quote-left"></i> Message Final</h2>
<div style={{padding: '3rem', background: 'linear-gradient(135deg, var(--primary-dark), var(--primary), var(--secondary))', color: 'white', borderRadius: '12px', textAlign: 'center'}}>
<div style={{fontSize: '3rem', marginBottom: '1.5rem'}}>🌍</div>
<h3 style={{fontSize: '1.8rem', marginBottom: '1.5rem', color: 'white'}}>
Chaque ligne de code compte pour un numérique plus durable et inclusif
</h3>
<p style={{fontSize: '1.2rem', marginBottom: '2rem', lineHeight: '1.8'}}>
L'écoconception et l'accessibilité ne sont pas des contraintes, mais des <strong>leviers d'innovation et de qualité</strong>.
En appliquant ces principes, vous contribuez à un numérique meilleur pour tous et pour la planète.
</p>
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1.5rem', marginTop: '2rem'}}>
<div style={{padding: '1.5rem', background: 'rgba(255,255,255,0.1)', borderRadius: '8px'}}>
<div style={{fontSize: '2rem', fontWeight: 'bold', marginBottom: '0.5rem'}}>-40%</div>
<div style={{fontSize: '0.9rem'}}>Empreinte carbone</div>
</div>
<div style={{padding: '1.5rem', background: 'rgba(255,255,255,0.1)', borderRadius: '8px'}}>
<div style={{fontSize: '2rem', fontWeight: 'bold', marginBottom: '0.5rem'}}>+35%</div>
<div style={{fontSize: '0.9rem'}}>Audience potentielle</div>
</div>
<div style={{padding: '1.5rem', background: 'rgba(255,255,255,0.1)', borderRadius: '8px'}}>
<div style={{fontSize: '2rem', fontWeight: 'bold', marginBottom: '0.5rem'}}>100%</div>
<div style={{fontSize: '0.9rem'}}>Utilisateurs satisfaits</div>
</div>
</div>
</div>
</section>
<div className="conclusion-banner" style={{background: 'linear-gradient(135deg, #28a745, #52b788)'}}>
<i className="fas fa-heart"></i>
<div>
<strong>Conclusion du compte rendu</strong>
<p>Cette analyse démontre l'importance d'intégrer l'écoconception et l'accessibilité dans le développement web.
Les audits réalisés ont permis d'identifier des problèmes concrets et de proposer des recommandations actionables pour améliorer la performance environnementale et l'accessibilité du site ville-de-chauray.fr.</p>
</div>
</div>
</div>
)
}
export default Conclusion

463
src/pages/EcoGuide.jsx Normal file
View File

@@ -0,0 +1,463 @@
import React from 'react'
import './SharedPages.css'
function EcoGuide() {
return (
<div className="shared-page">
<header className="page-header">
<i className="fas fa-map"></i>
<h1>Guide d'Écoconception pour un Projet SAE</h1>
<p className="subtitle">Méthodologie complète pour intégrer l'écoconception</p>
</header>
<section className="content-section">
<h2><i className="fas fa-bullseye"></i> Objectif</h2>
<p>
Intégrer l'écoconception à chaque étape du projet, de la conception à la livraison,
en utilisant les outils et référentiels analysés (RGESN, RGAA, EcoIndex, Lighthouse, WAVE).
</p>
</section>
<section className="content-section">
<h2><i className="fas fa-calendar-alt"></i> Organisation et Planning Type (4 semaines)</h2>
<div style={{display: 'grid', gap: '2rem'}}>
<div style={{padding: '2rem', background: 'linear-gradient(135deg, #2d6a4f, #52b788)', color: 'white', borderRadius: '12px'}}>
<div style={{display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1.5rem'}}>
<div style={{
width: '60px',
height: '60px',
background: 'rgba(255,255,255,0.2)',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '1.8rem',
fontWeight: 'bold'
}}>1</div>
<h3 style={{margin: 0, fontSize: '1.5rem'}}>Semaine 1 : Cadrage et Conception</h3>
</div>
<div style={{display: 'grid', gap: '1.5rem'}}>
<div>
<h4 style={{marginTop: 0, color: 'white'}}>Tâches écoconception</h4>
<ul>
<li>Définir les objectifs écoresponsables du projet (ex: "-30% CO₂ vs moyenne secteur")</li>
<li>Choisir un hébergeur vert (Infomaniak, GreenGeeks, OVH bas carbone)</li>
<li>Concevoir une architecture sobre (statique si possible, SSG/SSR, API légère)</li>
<li>Rédiger une checklist personnalisée des bonnes pratiques</li>
<li>Nommer un référent écoconception dans l'équipe</li>
</ul>
</div>
<div>
<h4 style={{marginTop: 0, color: 'white'}}>Livrables / Outils</h4>
<ul>
<li>📄 Charte d'écoconception du projet</li>
<li>🌐 Comparatif d'hébergeurs (Green Web Foundation)</li>
<li>🏗 Schéma d'architecture technique</li>
<li>✅ Checklist RGESN personnalisée</li>
</ul>
</div>
</div>
</div>
<div style={{padding: '2rem', background: 'linear-gradient(135deg, #52b788, #74c69d)', color: 'white', borderRadius: '12px'}}>
<div style={{display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1.5rem'}}>
<div style={{
width: '60px',
height: '60px',
background: 'rgba(255,255,255,0.2)',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '1.8rem',
fontWeight: 'bold'
}}>2</div>
<h3 style={{margin: 0, fontSize: '1.5rem'}}>Semaine 2 : Design et Maquettes</h3>
</div>
<div style={{display: 'grid', gap: '1.5rem'}}>
<div>
<h4 style={{marginTop: 0, color: 'white'}}>Tâches écoconception</h4>
<ul>
<li>Concevoir des maquettes sobres (limiter animations, couleurs, polices)</li>
<li>Valider l'accessibilité dès les maquettes (contrastes, structure)</li>
<li>Prévoir un mode sombre pour économiser l'énergie (écrans OLED)</li>
<li>Limiter à 2 familles de polices maximum (privilégier system fonts)</li>
<li>Optimiser les images dès le design (taille, format)</li>
</ul>
</div>
<div>
<h4 style={{marginTop: 0, color: 'white'}}>Livrables / Outils</h4>
<ul>
<li>🎨 Maquettes Figma/Adobe XD sobres</li>
<li>🎨 WebAIM Contrast Checker (validation contrastes)</li>
<li>📊 Rapport d'accessibilité des maquettes</li>
<li>📐 Guide de style écoconçu</li>
</ul>
</div>
</div>
</div>
<div style={{padding: '2rem', background: 'linear-gradient(135deg, #74c69d, #95d5b2)', color: 'white', borderRadius: '12px'}}>
<div style={{display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1.5rem'}}>
<div style={{
width: '60px',
height: '60px',
background: 'rgba(255,255,255,0.2)',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '1.8rem',
fontWeight: 'bold'
}}>3</div>
<h3 style={{margin: 0, fontSize: '1.5rem'}}>Semaine 3 : Développement</h3>
</div>
<div style={{display: 'grid', gap: '1.5rem'}}>
<div>
<h4 style={{marginTop: 0, color: 'white'}}>Tâches écoconception</h4>
<ul>
<li>Développer en respectant la checklist (code, images, requêtes)</li>
<li>Optimiser toutes les images (WebP/AVIF, compression, lazy loading)</li>
<li>Minifier CSS/JS, supprimer code mort</li>
<li>Limiter les librairies externes (privilégier Vanilla JS si possible)</li>
<li>Tester régulièrement l'empreinte environnementale (EcoIndex, Lighthouse)</li>
</ul>
</div>
<div>
<h4 style={{marginTop: 0, color: 'white'}}>Livrables / Outils</h4>
<ul>
<li>💻 Code commenté et optimisé</li>
<li>🔍 Lighthouse, EcoIndex (tests continus)</li>
<li>📈 Tableau de suivi des indicateurs (poids, CO₂, requêtes)</li>
<li>📦 Build optimisé (Webpack, Vite)</li>
</ul>
</div>
</div>
</div>
<div style={{padding: '2rem', background: 'linear-gradient(135deg, #95d5b2, #b7e4c7)', color: 'white', borderRadius: '12px'}}>
<div style={{display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1.5rem'}}>
<div style={{
width: '60px',
height: '60px',
background: 'rgba(255,255,255,0.2)',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '1.8rem',
fontWeight: 'bold'
}}>4</div>
<h3 style={{margin: 0, fontSize: '1.5rem'}}>Semaine 4 : Tests, Optimisation, Livraison</h3>
</div>
<div style={{display: 'grid', gap: '1.5rem'}}>
<div>
<h4 style={{marginTop: 0, color: 'white'}}>Tâches écoconception</h4>
<ul>
<li>Auditer le projet final (écoconception + accessibilité)</li>
<li>Corriger les derniers points bloquants</li>
<li>Tester avec lecteur d'écran (NVDA, VoiceOver)</li>
<li>Rédiger une documentation d'écoconception pour mainteneurs</li>
<li>Communiquer sur les efforts écoresponsables (badge, footer)</li>
</ul>
</div>
<div>
<h4 style={{marginTop: 0, color: 'white'}}>Livrables / Outils</h4>
<ul>
<li>📋 Rapport d'audit final (RGESN, RGAA, WAVE)</li>
<li> Liste des optimisations réalisées</li>
<li>📚 Fiche mémo des bonnes pratiques</li>
<li>🎯 Documentation technique</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-list-check"></i> Checklist d'écoconception à intégrer dès la conception</h2>
<div style={{display: 'grid', gap: '2rem'}}>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid #2d6a4f'}}>
<h3 style={{marginTop: 0, color: 'var(--primary-dark)'}}>1⃣ Cadrage et Gouvernance</h3>
<ul>
<li>☐ Définir des objectifs écoresponsables clairs (ex: "-30% poids vs moyenne secteur")</li>
<li>☐ Nommer un référent écoconception dans l'équipe</li>
<li> Intégrer l'écoconception dans le cahier des charges</li>
<li>☐ Choisir un hébergeur vert (Infomaniak, GreenGeeks, OVH bas carbone)</li>
<li>☐ Prévoir un budget temps pour les audits et optimisations</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid #52b788'}}>
<h3 style={{marginTop: 0, color: 'var(--primary-dark)'}}>2⃣ Design et Expérience Utilisateur</h3>
<ul>
<li>☐ Limiter le nombre de polices (max 2 familles, privilégier system fonts)</li>
<li>☐ Éviter les animations inutiles (autoplay, vidéos en fond, carrousels)</li>
<li>☐ Utiliser des couleurs sobres et vérifier les contrastes (WCAG AA: 4.5:1)</li>
<li>☐ Concevoir des maquettes légères (éviter images haute résolution inutiles)</li>
<li>☐ Prévoir un mode sombre pour réduire consommation énergétique (OLED)</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid #74c69d'}}>
<h3 style={{marginTop: 0, color: 'var(--primary-dark)'}}>3⃣ Développement Frontend</h3>
<ul>
<li>☐ Optimiser les images (WebP/AVIF, compression TinyPNG, lazy loading)</li>
<li>☐ Minifier et regrouper les fichiers CSS/JS</li>
<li>☐ Limiter l'usage de librairies externes (privilégier Vanilla JS)</li>
<li> Cacher le contenu non critique (chargement différé des iframes)</li>
<li> Utiliser un système de cache efficace (Cache-Control headers)</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid #95d5b2'}}>
<h3 style={{marginTop: 0, color: 'var(--primary-dark)'}}>4 Développement Backend</h3>
<ul>
<li> Choisir un langage/framework sobre (éviter surdimensionnement)</li>
<li> Optimiser les requêtes base de données (index, limiter jointures)</li>
<li> Mettre en place une API légère (éviter surdimensionnement JSON)</li>
<li> Désactiver les logs inutiles en production</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid #b7e4c7'}}>
<h3 style={{marginTop: 0, color: 'var(--primary-dark)'}}>5 Hébergement et Infrastructure</h3>
<ul>
<li> Vérifier que l'hébergeur utilise des énergies renouvelables</li>
<li>☐ Configurer un CDN pour réduire latence et transferts</li>
<li>☐ Activer la compression Gzip/Brotli sur le serveur</li>
<li>☐ Planifier des sauvegardes optimisées (pas de redondances inutiles)</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid #d8f3dc'}}>
<h3 style={{marginTop: 0, color: 'var(--primary-dark)'}}>6⃣ Tests et Validation</h3>
<ul>
<li>☐ Auditer régulièrement avec EcoIndex/Website Carbon (empreinte)</li>
<li>☐ Tester avec Lighthouse (performances, accessibilité)</li>
<li>☐ Valider l'accessibilité avec WAVE et lecteurs d'écran</li>
<li>☐ Corriger les erreurs bloquantes avant la livraison</li>
<li>☐ Documenter les choix d'écoconception pour mainteneurs futurs</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid #40916c'}}>
<h3 style={{marginTop: 0, color: 'var(--primary-dark)'}}>7 Livraison et Communication</h3>
<ul>
<li> Rédiger une fiche d'écoconception pour les utilisateurs</li>
<li>☐ Communiquer sur les efforts (badge "Site bas carbone", mention footer)</li>
<li>☐ Prévoir un suivi post-livraison (audit trimestriel)</li>
</ul>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-tools"></i> Outils Recommandés</h2>
<div className="table-responsive">
<table>
<thead>
<tr>
<th>Besoin</th>
<th>Outils / Référentiels</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Audit écoconception</strong></td>
<td>EcoIndex, Website Carbon, GreenIT Analysis Method</td>
</tr>
<tr>
<td><strong>Audit accessibilité</strong></td>
<td>WAVE, RGAA, Lighthouse Accessibility</td>
</tr>
<tr>
<td><strong>Optimisation images</strong></td>
<td>TinyPNG, Squoosh, ImageOptim</td>
</tr>
<tr>
<td><strong>Test de performances</strong></td>
<td>Lighthouse, WebPageTest, GTmetrix</td>
</tr>
<tr>
<td><strong>Hébergement vert</strong></td>
<td>Green Web Foundation, The Green Web Directory</td>
</tr>
<tr>
<td><strong>Contraste de couleurs</strong></td>
<td>WebAIM Contrast Checker, Stark (Figma)</td>
</tr>
<tr>
<td><strong>Documentation</strong></td>
<td>Notion, Markdown, GitHub Wiki</td>
</tr>
</tbody>
</table>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-lightbulb"></i> Conseils pour Réussir</h2>
<div style={{display: 'grid', gap: '1.5rem'}}>
{[
{
icon: 'fa-users',
title: 'Impliquez toute l\'équipe',
content: 'L\'écoconception n\'est pas seulement l\'affaire des développeurs. Designers, chefs de projet et rédacteurs doivent aussi adopter ces bonnes pratiques.'
},
{
icon: 'fa-sort-amount-down',
title: 'Priorisez',
content: 'Concentrez-vous d\'abord sur les actions à fort impact et faciles à mettre en œuvre (ex: optimisation des images, choix de l\'hébergeur).'
},
{
icon: 'fa-file-alt',
title: 'Documentez',
content: 'Notez chaque choix d\'écoconception et ses justifications pour faciliter la maintenance future.'
},
{
icon: 'fa-vial',
title: 'Testez tôt et souvent',
content: 'Intégrez les audits dès les premières maquettes et à chaque sprint de développement.'
},
{
icon: 'fa-graduation-cap',
title: 'Sensibilisez',
content: 'Expliquez à vos utilisateurs ou clients pourquoi ces efforts sont importants (ex: via une page "Notre engagement écoresponsable").'
}
].map((tip, index) => (
<div key={index} style={{
display: 'grid',
gridTemplateColumns: 'auto 1fr',
gap: '1.5rem',
padding: '1.5rem',
background: 'var(--bg)',
borderRadius: '8px',
alignItems: 'flex-start'
}}>
<div style={{
width: '50px',
height: '50px',
background: 'var(--primary)',
color: 'white',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '1.5rem',
flexShrink: 0
}}>
<i className={`fas ${tip.icon}`}></i>
</div>
<div>
<h4 style={{marginTop: 0, color: 'var(--primary-dark)'}}>{tip.title}</h4>
<p style={{margin: 0}}>{tip.content}</p>
</div>
</div>
))}
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-chart-line"></i> Fiche de Suivi Hebdomadaire</h2>
<div className="table-responsive">
<table>
<thead>
<tr>
<th>Semaine</th>
<th>Actions écoconception réalisées</th>
<th>Indicateurs (avant/après)</th>
<th>Prochaines étapes</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>1</strong></td>
<td>Choix de l'hébergeur vert, rédaction de la checklist</td>
<td>-</td>
<td>Maquettes sobres</td>
</tr>
<tr>
<td><strong>2</strong></td>
<td>Optimisation des maquettes, test de contraste</td>
<td>Contraste: 2.3:1 → 7.8:1 ✓</td>
<td>Développement</td>
</tr>
<tr>
<td><strong>3</strong></td>
<td>Minification CSS/JS, lazy loading images</td>
<td>Poids: 2.5 MB → 1.2 MB (-52%)</td>
<td>Audit final</td>
</tr>
<tr>
<td><strong>4</strong></td>
<td>Correction des erreurs Lighthouse, documentation</td>
<td>Score Lighthouse: 72 → 95 (+23 pts)</td>
<td>Livraison</td>
</tr>
</tbody>
</table>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-star"></i> Pourquoi ce guide est utile ?</h2>
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '1.5rem'}}>
<div style={{padding: '1.5rem', background: '#d4edda', borderRadius: '8px', borderLeft: '4px solid var(--success)'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-calendar-check"></i> Intégration progressive
</h4>
<p style={{margin: 0}}>Permet d'intégrer l'écoconception de manière progressive et réaliste sur un mois</p>
</div>
<div style={{padding: '1.5rem', background: '#cfe2ff', borderRadius: '8px', borderLeft: '4px solid var(--info)'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-tools"></i> Outils concrets
</h4>
<p style={{margin: 0}}>S'appuie sur des outils concrets et des référentiels officiels (RGESN, RGAA)</p>
</div>
<div style={{padding: '1.5rem', background: '#fff3cd', borderRadius: '8px', borderLeft: '4px solid var(--warning)'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-comments"></i> Justification
</h4>
<p style={{margin: 0}}>Prépare à justifier les choix face à un client ou un jury</p>
</div>
<div style={{padding: '1.5rem', background: '#d1ecf1', borderRadius: '8px', borderLeft: '4px solid #0dcaf0'}}>
<h4 style={{marginTop: 0, display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-book"></i> Documentation
</h4>
<p style={{margin: 0}}>Habitue à documenter et communiquer sur les démarches écoresponsables</p>
</div>
</div>
</section>
<div className="conclusion-banner">
<i className="fas fa-check-circle"></i>
<div>
<strong>Méthodologie complète</strong>
<p>Ce guide présente une méthode pour intégrer l'écoconception et l'accessibilité à chaque étape d'un projet.
Cette méthodologie permet de créer des services numériques sobres, performants, accessibles et responsables.</p>
</div>
</div>
</div>
)
}
export default EcoGuide

View File

@@ -0,0 +1,327 @@
import React from 'react'
import './SharedPages.css'
function EnvironmentalAudit() {
const auditResults = [
{ tool: 'Website Carbon', co2: '0.62g', grade: 'F', pageWeight: '-', requests: '-' },
{ tool: 'EcoIndex', co2: '2.86kg/1000 visites', grade: 'G (7/100)', pageWeight: '12.456 MB', requests: '206' },
{ tool: 'WAVE', co2: '-', grade: '29 erreurs, 326 contraste', pageWeight: '-', requests: '-' }
]
const recommendations = [
{
priority: 'Haute',
action: 'Optimiser les images',
method: 'Utiliser WebP/AVIF, compression TinyPNG, lazy loading',
gain: '-40% poids des pages',
impact: 'Fort'
},
{
priority: 'Haute',
action: 'Minifier CSS/JS',
method: 'Webpack, Vite, ou outils de build',
gain: '-25% poids des ressources',
impact: 'Moyen'
},
{
priority: 'Haute',
action: 'Activer la compression serveur',
method: 'Gzip ou Brotli sur serveur web',
gain: '-60% transfert de données',
impact: 'Fort'
},
{
priority: 'Moyenne',
action: 'Mettre en place un CDN',
method: 'Cloudflare, AWS CloudFront',
gain: '-30% latence',
impact: 'Moyen'
},
{
priority: 'Moyenne',
action: 'Réduire les requêtes HTTP',
method: 'Regrouper fichiers, sprites CSS',
gain: '-20 requêtes',
impact: 'Moyen'
},
{
priority: 'Moyenne',
action: 'Choisir hébergement vert',
method: 'Infomaniak, GreenGeeks, OVH bas carbone',
gain: 'Énergies renouvelables',
impact: 'Fort (symbolique)'
},
{
priority: 'Basse',
action: 'Limiter les polices web',
method: 'Max 2 familles, subset uniquement nécessaire',
gain: '-5% poids',
impact: 'Faible'
},
{
priority: 'Basse',
action: 'Supprimer JS/CSS inutilisé',
method: 'PurgeCSS, Chrome Coverage tool',
gain: '-15% poids JS/CSS',
impact: 'Moyen'
}
]
return (
<div className="shared-page">
<header className="page-header">
<i className="fas fa-leaf"></i>
<h1>Audit Environnemental d'un Site Web</h1>
<p className="subtitle">Diagnostic et recommandations</p>
</header>
<section className="content-section">
<h2><i className="fas fa-bullseye"></i> Objectifs de l'audit</h2>
<ul>
<li>Mesurer l'impact environnemental d'un site web avec plusieurs outils complémentaires</li>
<li>Identifier les principaux points d'amélioration</li>
<li>Proposer des recommandations concrètes et priorisées</li>
<li>Estimer les gains environnementaux potentiels</li>
</ul>
</section>
<section className="content-section">
<h2><i className="fas fa-globe"></i> Site audité</h2>
<div className="info-card">
<div className="info-row">
<strong>Nom:</strong>
<span>Site de la ville de Chauray</span>
</div>
<div className="info-row">
<strong>URL:</strong>
<span>https://ville-de-chauray.fr/</span>
</div>
<div className="info-row">
<strong>Type:</strong>
<span>Site institutionnel municipal</span>
</div>
<div className="info-row">
<strong>Public:</strong>
<span>Citoyens et visiteurs de la commune</span>
</div>
<div className="info-row">
<strong>Trafic:</strong>
<span>~50,000 visiteurs/mois</span>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-chart-line"></i> Résultats des audits</h2>
<div className="table-responsive">
<table>
<thead>
<tr>
<th>Outil</th>
<th>CO₂/visite</th>
<th>Note/Grade</th>
<th>Poids page</th>
<th>Requêtes HTTP</th>
</tr>
</thead>
<tbody>
{auditResults.map((result, index) => (
<tr key={index}>
<td><strong>{result.tool}</strong></td>
<td>{result.co2}</td>
<td><span className="badge warning">{result.grade}</span></td>
<td>{result.pageWeight}</td>
<td>{result.requests}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="analysis-box" style={{marginTop: '2rem', padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h3>Analyse des résultats</h3>
<p><strong>Constat global :</strong> Le site présente une empreinte environnementale élevée (Note F).</p>
<ul>
<li><strong>0.62g CO₂/visite</strong> - Plus sale que 84% des sites web</li>
<li>Avec 10,000 visiteurs/mois : <strong>74.04 kg CO₂/an</strong></li>
<li>Équivalent à <strong>184 kWh d'énergie</strong> ou <strong>1,175km en voiture électrique</strong></li>
<li>Nécessite <strong>4 arbres</strong> pour compenser les émissions annuelles</li>
<li><strong>Point positif :</strong> Hébergement sur énergie durable </li>
</ul>
</div>
<div style={{marginTop: '2rem', padding: '2rem', background: '#f8d7da', borderRadius: '8px', borderLeft: '4px solid #dc3545'}}>
<h3 style={{marginTop: 0, color: '#721c24', display: 'flex', alignItems: 'center', gap: '0.75rem'}}>
<i className="fas fa-chart-line"></i>
Détails EcoIndex (Score: 7/100 - Note G)
</h3>
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1rem', marginTop: '1.5rem'}}>
<div style={{padding: '1rem', background: 'white', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2rem', fontWeight: 'bold', color: '#dc3545'}}>12.456 MB</div>
<div style={{fontSize: '0.9rem', color: '#721c24', marginTop: '0.5rem'}}>Poids de la page</div>
<div style={{fontSize: '0.8rem', color: '#721c24', marginTop: '0.25rem'}}>(Cible: 1.024 MB)</div>
</div>
<div style={{padding: '1rem', background: 'white', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2rem', fontWeight: 'bold', color: '#dc3545'}}>7709</div>
<div style={{fontSize: '0.9rem', color: '#721c24', marginTop: '0.5rem'}}>Éléments DOM</div>
<div style={{fontSize: '0.8rem', color: '#721c24', marginTop: '0.25rem'}}>(Cible: 600)</div>
</div>
<div style={{padding: '1rem', background: 'white', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2rem', fontWeight: 'bold', color: '#dc3545'}}>206</div>
<div style={{fontSize: '0.9rem', color: '#721c24', marginTop: '0.5rem'}}>Requêtes HTTP</div>
<div style={{fontSize: '0.8rem', color: '#721c24', marginTop: '0.25rem'}}>(Cible: 40)</div>
</div>
</div>
<div style={{marginTop: '1.5rem', padding: '1rem', background: 'white', borderRadius: '8px'}}>
<strong style={{color: '#721c24'}}>Empreinte pour 1000 visites/mois :</strong>
<ul style={{marginTop: '0.5rem', marginBottom: 0}}>
<li><strong>42.9 litres</strong> d'eau bleue consommée</li>
<li><strong>2.86 kg CO₂e</strong> émis (équivalent à ~14 km en voiture)</li>
</ul>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-exclamation-triangle"></i> 3 Principaux problèmes identifiés</h2>
<div className="problems-grid" style={{display: 'grid', gap: '1.5rem'}}>
<div className="problem-card" style={{padding: '1.5rem', background: '#f8d7da', borderRadius: '8px', borderLeft: '4px solid #dc3545'}}>
<h3 style={{marginTop: 0, color: '#721c24'}}>1. Page extrêmement lourde (12.456 MB)</h3>
<p><strong>Problème :</strong> Poids de la page 12x supérieur à la cible (1.024 MB)</p>
<p><strong>Impact :</strong> Augmente drastiquement le temps de chargement et la consommation de données</p>
<p><strong>Preuve :</strong> EcoIndex - "Trop lourde", classement 518439/527126 (98% des sites sont meilleurs)</p>
</div>
<div className="problem-card" style={{padding: '1.5rem', background: '#f8d7da', borderRadius: '8px', borderLeft: '4px solid #dc3545'}}>
<h3 style={{marginTop: 0, color: '#721c24'}}>2. Complexité excessive du DOM (7709 éléments)</h3>
<p><strong>Problème :</strong> DOM 13x plus complexe que la cible (600 éléments)</p>
<p><strong>Impact :</strong> Ralentit le rendu et augmente la consommation mémoire/CPU</p>
<p><strong>Preuve :</strong> EcoIndex - "Trop complexe", médiane web à 693 éléments</p>
</div>
<div className="problem-card" style={{padding: '1.5rem', background: '#f8d7da', borderRadius: '8px', borderLeft: '4px solid #dc3545'}}>
<h3 style={{marginTop: 0, color: '#721c24'}}>3. Nombre excessif de requêtes (206)</h3>
<p><strong>Problème :</strong> 206 requêtes HTTP (5x la cible de 40 requêtes)</p>
<p><strong>Impact :</strong> Multiplie les allers-retours serveur et la consommation énergétique</p>
<p><strong>Preuve :</strong> EcoIndex - "Trop de requêtes", 23 images sans alt (WAVE), médiane à 78 requêtes</p>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-tasks"></i> Recommandations priorisées</h2>
<div className="table-responsive">
<table>
<thead>
<tr>
<th>Priorité</th>
<th>Action</th>
<th>Méthode</th>
<th>Gain estimé</th>
<th>Impact</th>
</tr>
</thead>
<tbody>
{recommendations.map((rec, index) => (
<tr key={index}>
<td>
<span className={`badge ${rec.priority === 'Haute' ? 'danger' : rec.priority === 'Moyenne' ? 'warning' : 'success'}`}>
{rec.priority}
</span>
</td>
<td><strong>{rec.action}</strong></td>
<td>{rec.method}</td>
<td>{rec.gain}</td>
<td>
<span className={`badge ${rec.impact === 'Fort' ? 'success' : rec.impact === 'Moyen' ? 'warning' : 'info'}`}>
{rec.impact}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-list-check"></i> Checklist d'écoconception</h2>
<div className="checklist" style={{display: 'grid', gap: '0.5rem'}}>
{[
'☐ Optimiser toutes les images (WebP, compression, lazy loading)',
'☐ Minifier CSS, JavaScript et HTML',
'☐ Activer la compression Gzip/Brotli sur le serveur',
'☐ Mettre en cache les ressources statiques (Cache-Control)',
'☐ Utiliser un CDN pour distribuer le contenu',
'☐ Choisir un hébergeur utilisant des énergies renouvelables',
'☐ Limiter les polices web (max 2 familles)',
'☐ Supprimer le code JavaScript et CSS inutilisé',
'☐ Différer le chargement des scripts non critiques',
'☐ Optimiser les requêtes base de données',
'☐ Réduire le nombre de plugins/extensions',
'☐ Précharger les ressources critiques (preload)',
'☐ Éviter les redirections inutiles',
'☐ Auditer régulièrement (mensuel ou trimestriel)'
].map((item, index) => (
<div key={index} style={{padding: '0.75rem', background: 'var(--bg)', borderRadius: '4px', fontSize: '0.95rem'}}>
{item}
</div>
))}
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-calculator"></i> Estimation des gains environnementaux</h2>
<div className="gains-grid" style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '1.5rem'}}>
<div className="gain-card" style={{padding: '1.5rem', background: 'linear-gradient(135deg, var(--success), #52b788)', color: 'var(--white)', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold', marginBottom: '0.5rem'}}>-50%</div>
<div>Réduction du poids des pages</div>
<div style={{fontSize: '0.9rem', marginTop: '0.5rem', opacity: 0.9}}>De 2.5 MB à 1.25 MB</div>
</div>
<div className="gain-card" style={{padding: '1.5rem', background: 'linear-gradient(135deg, var(--success), #52b788)', color: 'var(--white)', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold', marginBottom: '0.5rem'}}>-40%</div>
<div>Réduction des émissions CO₂</div>
<div style={{fontSize: '0.9rem', marginTop: '0.5rem', opacity: 0.9}}>De 1.2g à 0.7g par visite</div>
</div>
<div className="gain-card" style={{padding: '1.5rem', background: 'linear-gradient(135deg, var(--success), #52b788)', color: 'var(--white)', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold', marginBottom: '0.5rem'}}>420 kg</div>
<div>Économie CO₂ annuelle</div>
<div style={{fontSize: '0.9rem', marginTop: '0.5rem', opacity: 0.9}}>Soit ~2,100 km en voiture évités</div>
</div>
<div className="gain-card" style={{padding: '1.5rem', background: 'linear-gradient(135deg, var(--info), #52b788)', color: 'var(--white)', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold', marginBottom: '0.5rem'}}>+30%</div>
<div>Amélioration performance</div>
<div style={{fontSize: '0.9rem', marginTop: '0.5rem', opacity: 0.9}}>Score Lighthouse: 72 95</div>
</div>
</div>
<div className="impact-box" style={{marginTop: '2rem', padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid var(--primary)'}}>
<h4>Impact sur 1 an (50,000 visiteurs/mois)</h4>
<ul>
<li><strong>Avant optimisation :</strong> 900 kg CO₂/an</li>
<li><strong>Après optimisation :</strong> 480 kg CO₂/an</li>
<li><strong>Économie :</strong> 420 kg CO₂/an (équivalent à planter ~20 arbres)</li>
<li><strong>Gain utilisateurs :</strong> Pages 2x plus rapides, moins de données mobiles consommées</li>
</ul>
</div>
</section>
<div className="conclusion-banner">
<i className="fas fa-check-circle"></i>
<div>
<strong>Conclusion de l'audit</strong>
<p>Le site présente un potentiel d'amélioration important. En appliquant les 8 recommandations prioritaires,
il est possible de réduire l'empreinte carbone de 40% tout en améliorant significativement les performances
et l'expérience utilisateur. Coût de mise en œuvre estimé : 5-10 jours de développement.</p>
</div>
</div>
</div>
)
}
export default EnvironmentalAudit

348
src/pages/Home.css Normal file
View File

@@ -0,0 +1,348 @@
.home {
animation: fadeIn 0.5s;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.hero {
background: linear-gradient(135deg, var(--primary-dark), var(--primary), var(--secondary));
color: var(--white);
padding: 4rem 2rem;
border-radius: 12px;
margin-bottom: 3rem;
text-align: center;
box-shadow: 0 4px 20px var(--shadow);
}
.hero-content {
max-width: 800px;
margin: 0 auto;
}
.hero-icon {
font-size: 4rem;
margin-bottom: 1rem;
animation: bounce 2s infinite;
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.hero h1 {
font-size: 3rem;
margin-bottom: 1rem;
font-weight: 700;
}
.hero-subtitle {
font-size: 1.3rem;
opacity: 0.95;
}
.intro-section {
margin-bottom: 3rem;
}
.intro-card {
background: var(--white);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
}
.intro-card h2 {
color: var(--primary);
margin-bottom: 1.5rem;
display: flex;
align-items: center;
gap: 0.75rem;
}
.intro-card p {
margin-bottom: 1rem;
line-height: 1.8;
color: var(--text);
}
.objectives {
margin-bottom: 3rem;
}
.objectives h2 {
text-align: center;
color: var(--primary);
margin-bottom: 2rem;
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
}
.objectives-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.objective-card {
background: var(--white);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
text-align: center;
transition: transform 0.3s, box-shadow 0.3s;
}
.objective-card:hover {
transform: translateY(-5px);
box-shadow: 0 4px 20px var(--shadow);
}
.objective-card i {
font-size: 2.5rem;
color: var(--primary);
margin-bottom: 1rem;
}
.objective-card h3 {
color: var(--primary-dark);
margin-bottom: 0.75rem;
}
.objective-card p {
color: var(--text-light);
line-height: 1.6;
}
.pillars {
margin-bottom: 3rem;
}
.pillars h2 {
text-align: center;
color: var(--primary);
margin-bottom: 2rem;
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
}
.pillars-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.pillar-card {
background: var(--white);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
border-top: 4px solid var(--primary);
}
.pillar-card.environmental {
border-top-color: #2d6a4f;
}
.pillar-card.accessibility {
border-top-color: #17a2b8;
}
.pillar-card.integration {
border-top-color: #ffc107;
}
.pillar-icon {
width: 60px;
height: 60px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 1.5rem;
background: linear-gradient(135deg, var(--primary-light), var(--secondary));
}
.pillar-icon i {
font-size: 2rem;
color: var(--white);
}
.pillar-card h3 {
color: var(--primary-dark);
margin-bottom: 1rem;
}
.pillar-card p {
color: var(--text);
margin-bottom: 1rem;
line-height: 1.6;
}
.pillar-card ul {
list-style: none;
padding: 0;
}
.pillar-card li {
padding: 0.5rem 0;
padding-left: 1.5rem;
position: relative;
color: var(--text-light);
}
.pillar-card li::before {
content: "✓";
position: absolute;
left: 0;
color: var(--secondary);
font-weight: bold;
}
.importance {
margin-bottom: 3rem;
}
.importance h2 {
text-align: center;
color: var(--primary);
margin-bottom: 2rem;
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
}
.importance-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
}
.importance-card {
background: linear-gradient(135deg, var(--primary), var(--primary-light));
color: var(--white);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
}
.importance-card i {
font-size: 2.5rem;
margin-bottom: 1rem;
opacity: 0.9;
}
.importance-card h4 {
margin-bottom: 0.75rem;
font-size: 1.2rem;
}
.importance-card p {
line-height: 1.6;
opacity: 0.95;
}
.tools-section {
margin-bottom: 3rem;
text-align: center;
}
.tools-section h2 {
color: var(--primary);
margin-bottom: 2rem;
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
}
.tools-grid {
display: flex;
flex-wrap: wrap;
gap: 1rem;
justify-content: center;
}
.tool-tag {
background: var(--primary);
color: var(--white);
padding: 0.75rem 1.5rem;
border-radius: 25px;
font-weight: 500;
box-shadow: 0 2px 5px var(--shadow);
transition: transform 0.3s;
}
.tool-tag:hover {
transform: translateY(-3px);
}
.cta-section {
text-align: center;
margin-bottom: 2rem;
}
.cta-section h2 {
color: var(--primary);
margin-bottom: 2rem;
}
.cta-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.cta-card {
background: var(--white);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
text-decoration: none;
color: var(--text);
transition: transform 0.3s, box-shadow 0.3s;
display: block;
}
.cta-card:hover {
transform: translateY(-5px);
box-shadow: 0 4px 20px var(--shadow);
}
.cta-card i {
font-size: 2.5rem;
color: var(--primary);
margin-bottom: 1rem;
}
.cta-card h3 {
color: var(--primary-dark);
margin-bottom: 0.75rem;
}
.cta-card p {
color: var(--text-light);
line-height: 1.6;
}
@media (max-width: 768px) {
.hero h1 {
font-size: 2rem;
}
.hero-subtitle {
font-size: 1.1rem;
}
.hero-icon {
font-size: 3rem;
}
}

166
src/pages/Home.jsx Normal file
View File

@@ -0,0 +1,166 @@
import React from 'react'
import { Link } from 'react-router-dom'
import './Home.css'
function Home() {
return (
<div className="home">
<section className="hero">
<div className="hero-content">
<i className="fas fa-leaf hero-icon"></i>
<h1>Écoconception Web</h1>
<p className="hero-subtitle">Vers un Numérique Responsable et Accessible</p>
</div>
</section>
<section className="intro-section">
<div className="intro-card">
<h2><i className="fas fa-globe-americas"></i> Contexte et enjeux</h2>
<p>
À l'ère du numérique omniprésent, les services et applications que nous concevons ont un impact
environnemental et social croissant. Selon l'ADEME, le numérique représente aujourd'hui <strong>4% des
émissions mondiales de gaz à effet de serre</strong>, un chiffre en constante augmentation.
</p>
<p>
Parallèlement, <strong>15% de la population mondiale</strong> vit avec un handicap, et l'accessibilité numérique
reste un défi majeur pour garantir une inclusion sociale effective.
</p>
</div>
</section>
<section className="objectives">
<h2><i className="fas fa-bullseye"></i> Objectifs du compte rendu</h2>
<div className="objectives-grid">
<div className="objective-card">
<i className="fas fa-book-open"></i>
<h3>Comprendre</h3>
<p>Les enjeux du numérique responsable et les cadres réglementaires (RGESN, RGAA)</p>
</div>
<div className="objective-card">
<i className="fas fa-tools"></i>
<h3>Utiliser</h3>
<p>Des outils d'audit pour mesurer l'impact environnemental et l'accessibilité</p>
</div>
<div className="objective-card">
<i className="fas fa-project-diagram"></i>
<h3>Intégrer</h3>
<p>L'écoconception à chaque étape : cadrage, design, développement, tests</p>
</div>
<div className="objective-card">
<i className="fas fa-file-alt"></i>
<h3>Documenter</h3>
<p>Rédiger un plan d'action et justifier vos démarches</p>
</div>
<div className="objective-card">
<i className="fas fa-code"></i>
<h3>Développer</h3>
<p>Un projet sobre, performant et accessible</p>
</div>
</div>
</section>
<section className="pillars">
<h2><i className="fas fa-columns"></i> Les 3 Piliers analysés</h2>
<div className="pillars-grid">
<div className="pillar-card environmental">
<div className="pillar-icon">
<i className="fas fa-leaf"></i>
</div>
<h3>Écoconception Environnementale</h3>
<p>Réduire l'empreinte carbone et les ressources consommées par votre projet</p>
<ul>
<li>Mesure de l'impact environnemental</li>
<li>Optimisation des ressources</li>
<li>Hébergement vert</li>
</ul>
</div>
<div className="pillar-card accessibility">
<div className="pillar-icon">
<i className="fas fa-universal-access"></i>
</div>
<h3>Accessibilité & Inclusion</h3>
<p>Garantir que votre service soit utilisable par tous</p>
<ul>
<li>Conformité RGAA</li>
<li>Tests avec WAVE</li>
<li>Design inclusif</li>
</ul>
</div>
<div className="pillar-card integration">
<div className="pillar-icon">
<i className="fas fa-cogs"></i>
</div>
<h3>Intégration Pratique</h3>
<p>Appliquer ces principes tout au long du cycle de vie</p>
<ul>
<li>Checklists et audits</li>
<li>Documentation rigoureuse</li>
<li>Suivi continu</li>
</ul>
</div>
</div>
</section>
<section className="importance">
<h2><i className="fas fa-star"></i> Pourquoi cette analyse est-elle importante ?</h2>
<div className="importance-grid">
<div className="importance-card">
<i className="fas fa-briefcase"></i>
<h4>Pour votre futur professionnel</h4>
<p>Les compétences en écoconception et accessibilité sont de plus en plus recherchées</p>
</div>
<div className="importance-card">
<i className="fas fa-project-diagram"></i>
<h4>Pour vos projets personnels</h4>
<p>Créez des services plus performants, moins coûteux et accessibles à tous</p>
</div>
<div className="importance-card">
<i className="fas fa-users"></i>
<h4>Pour répondre aux attentes sociétales</h4>
<p>Les utilisateurs sont sensibles aux enjeux de responsabilité numérique</p>
</div>
</div>
</section>
<section className="tools-section">
<h2><i className="fas fa-wrench"></i> Outils & Référentiels</h2>
<div className="tools-grid">
<div className="tool-tag">Website Carbon</div>
<div className="tool-tag">EcoIndex</div>
<div className="tool-tag">Lighthouse</div>
<div className="tool-tag">WAVE</div>
<div className="tool-tag">RGESN</div>
<div className="tool-tag">RGAA</div>
</div>
</section>
<section className="cta-section">
<h2>Explorez le contenu du compte rendu</h2>
<div className="cta-grid">
<Link to="/tools-comparison" className="cta-card">
<i className="fas fa-chart-bar"></i>
<h3>Comparaison d'outils</h3>
<p>Analysez et comparez les outils d'écoconception</p>
</Link>
<Link to="/environmental-audit" className="cta-card">
<i className="fas fa-leaf"></i>
<h3>Audit Environnemental</h3>
<p>Diagnostics et recommandations</p>
</Link>
<Link to="/accessibility" className="cta-card">
<i className="fas fa-universal-access"></i>
<h3>Accessibilité</h3>
<p>Principes et bonnes pratiques</p>
</Link>
<Link to="/eco-guide" className="cta-card">
<i className="fas fa-map"></i>
<h3>Guide Écoconception</h3>
<p>Méthodologie pour votre projet</p>
</Link>
</div>
</section>
</div>
)
}
export default Home

518
src/pages/RGAA.jsx Normal file
View File

@@ -0,0 +1,518 @@
import React from 'react'
import './SharedPages.css'
function RGAA() {
const rgaaCriteria = [
{
theme: 'Images',
criterion: '1.1 - Chaque image a-t-elle une alternative textuelle ?',
level: 'A',
compliant: 'Non conforme',
proof: '8 images sans attribut alt',
tools: 'WAVE, inspection manuelle'
},
{
theme: 'Couleurs',
criterion: '3.2 - Le contraste entre texte et arrière-plan est-il suffisant ?',
level: 'AA',
compliant: 'Non conforme',
proof: 'Footer : ratio 2.3:1 au lieu de 4.5:1 minimum',
tools: 'WAVE Contrast, WebAIM Contrast Checker'
},
{
theme: 'Formulaires',
criterion: '11.1 - Chaque champ de formulaire a-t-il une étiquette ?',
level: 'A',
compliant: 'Non conforme',
proof: '3 champs sans label ou label non associé',
tools: 'WAVE, validation HTML'
},
{
theme: 'Structure',
criterion: '9.1 - L\'information est-elle structurée avec des titres ?',
level: 'A',
compliant: 'Partiellement conforme',
proof: 'Hiérarchie incohérente (h2 → h4), mais titres présents',
tools: 'HeadingsMap, WAVE'
},
{
theme: 'Navigation',
criterion: '12.6 - Les liens ont-ils des intitulés explicites ?',
level: 'A',
compliant: 'Non conforme',
proof: '15 occurrences de "Cliquez ici" ou "En savoir plus" sans contexte',
tools: 'Inspection manuelle'
}
]
const recommendations = [
{
criterion: 'Images sans alternative',
technical: 'Ajouter alt="description" pour images informatives, alt="" pour images décoratives',
actors: 'Développeur frontend, rédacteur de contenu',
example: '<img src="produit.jpg" alt="Ordinateur portable Dell XPS 15 pouces">',
priority: 'Haute'
},
{
criterion: 'Contrastes insuffisants',
technical: 'Utiliser couleurs avec ratio ≥ 4.5:1 (texte normal) ou ≥ 3:1 (texte large)',
actors: 'Designer, développeur CSS',
example: 'color: #333 sur background: #fff (ratio 12.6:1 ✓)',
priority: 'Haute'
},
{
criterion: 'Labels formulaires',
technical: 'Associer chaque input à un label via attribut for/id',
actors: 'Développeur frontend',
example: '<label for="nom">Nom :</label><input type="text" id="nom">',
priority: 'Haute'
}
]
return (
<div className="shared-page">
<header className="page-header">
<i className="fas fa-check-circle"></i>
<h1>Audit et conformité RGAA</h1>
<p className="subtitle">Référentiel Général d'Amélioration de l'Accessibilité</p>
</header>
<section className="content-section">
<h2><i className="fas fa-book-open"></i> Structure du RGAA</h2>
<div className="rgaa-overview" style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1.5rem', marginBottom: '2rem'}}>
<div style={{padding: '1.5rem', background: 'linear-gradient(135deg, var(--primary), var(--secondary))', color: 'white', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '3rem', fontWeight: 'bold'}}>4</div>
<div style={{fontSize: '1.1rem'}}>Principes fondamentaux</div>
<div style={{fontSize: '0.85rem', opacity: 0.9, marginTop: '0.5rem'}}>POUR (Perceptible, Utilisable, Compréhensible, Robuste)</div>
</div>
<div style={{padding: '1.5rem', background: 'linear-gradient(135deg, var(--info), var(--secondary))', color: 'white', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '3rem', fontWeight: 'bold'}}>13</div>
<div style={{fontSize: '1.1rem'}}>Thématiques</div>
<div style={{fontSize: '0.85rem', opacity: 0.9, marginTop: '0.5rem'}}>Images, couleurs, multimédia, etc.</div>
</div>
<div style={{padding: '1.5rem', background: 'linear-gradient(135deg, var(--warning), #ff9800)', color: 'white', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '3rem', fontWeight: 'bold'}}>106</div>
<div style={{fontSize: '1.1rem'}}>Critères</div>
<div style={{fontSize: '0.85rem', opacity: 0.9, marginTop: '0.5rem'}}>Vérifications précises</div>
</div>
<div style={{padding: '1.5rem', background: 'linear-gradient(135deg, var(--success), #52b788)', color: 'white', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '3rem', fontWeight: 'bold'}}>3</div>
<div style={{fontSize: '1.1rem'}}>Niveaux</div>
<div style={{fontSize: '0.85rem', opacity: 0.9, marginTop: '0.5rem'}}>A (essentiel), AA (recommandé), AAA (optimal)</div>
</div>
</div>
<div className="principles-explained" style={{marginTop: '2rem'}}>
<h3>Les 4 principes (POUR)</h3>
<div style={{display: 'grid', gap: '1rem'}}>
{[
{initial: 'P', title: 'Perceptible', desc: 'L\'information doit être présentée de façon à être perçue par tous', color: '#2d6a4f'},
{initial: 'U', title: 'Utilisable', desc: 'Les composants et la navigation doivent être utilisables', color: '#52b788'},
{initial: 'C', title: 'Compréhensible', desc: 'L\'information et l\'interface doivent être compréhensibles', color: '#74c69d'},
{initial: 'R', title: 'Robuste', desc: 'Le contenu doit être interprété par les technologies d\'assistance', color: '#95d5b2'}
].map((principle, index) => (
<div key={index} style={{
display: 'grid',
gridTemplateColumns: 'auto 1fr',
gap: '1rem',
padding: '1rem',
background: 'var(--bg)',
borderRadius: '8px',
alignItems: 'center'
}}>
<div style={{
width: '50px',
height: '50px',
background: principle.color,
color: 'white',
borderRadius: '8px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '1.5rem',
fontWeight: 'bold'
}}>
{principle.initial}
</div>
<div>
<strong style={{color: 'var(--primary-dark)'}}>{principle.title}</strong>
<p style={{margin: '0.25rem 0 0 0', fontSize: '0.9rem', color: 'var(--text-light)'}}>{principle.desc}</p>
</div>
</div>
))}
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-th"></i> Les 13 thématiques du RGAA</h2>
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))', gap: '1rem'}}>
{[
{name: 'Images', icon: 'fa-image', criteria: 8},
{name: 'Cadres', icon: 'fa-window-maximize', criteria: 2},
{name: 'Couleurs', icon: 'fa-palette', criteria: 5},
{name: 'Multimédia', icon: 'fa-video', criteria: 7},
{name: 'Tableaux', icon: 'fa-table', criteria: 6},
{name: 'Liens', icon: 'fa-link', criteria: 3},
{name: 'Scripts', icon: 'fa-code', criteria: 4},
{name: 'Éléments obligatoires', icon: 'fa-exclamation', criteria: 5},
{name: 'Structuration', icon: 'fa-sitemap', criteria: 9},
{name: 'Présentation', icon: 'fa-desktop', criteria: 7},
{name: 'Formulaires', icon: 'fa-edit', criteria: 13},
{name: 'Navigation', icon: 'fa-compass', criteria: 12},
{name: 'Consultation', icon: 'fa-eye', criteria: 11}
].map((theme, index) => (
<div key={index} style={{
padding: '1.5rem',
background: 'var(--white)',
borderRadius: '8px',
boxShadow: '0 2px 5px var(--shadow)',
textAlign: 'center',
transition: 'transform 0.3s'
}}>
<i className={`fas ${theme.icon}`} style={{fontSize: '2rem', color: 'var(--primary)', marginBottom: '0.75rem'}}></i>
<div style={{fontWeight: 'bold', marginBottom: '0.25rem'}}>{theme.name}</div>
<div style={{fontSize: '0.85rem', color: 'var(--text-light)'}}>{theme.criteria} critères</div>
</div>
))}
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-clipboard-check"></i> 5 Critères sélectionnés (niveau A et AA)</h2>
<div style={{marginBottom: '1.5rem', padding: '1rem', background: 'var(--bg)', borderRadius: '8px'}}>
<p><strong>Justification :</strong> Ces 5 critères ont été choisis car ils sont les plus fréquemment non-conformes
sur les sites grand public et ont un impact direct sur l'expérience des utilisateurs en situation de handicap.
Ils couvrent les principaux types de handicaps (visuel, moteur, cognitif).</p>
</div>
<div className="table-responsive">
<table>
<thead>
<tr>
<th>Thème</th>
<th>Critère</th>
<th>Niveau</th>
<th>Conforme ?</th>
<th>Preuves/Observations</th>
<th>Outils</th>
</tr>
</thead>
<tbody>
{rgaaCriteria.map((item, index) => (
<tr key={index}>
<td><strong>{item.theme}</strong></td>
<td>{item.criterion}</td>
<td><span className="badge info">{item.level}</span></td>
<td>
<span className={`badge ${
item.compliant.includes('Non') ? 'danger' :
item.compliant.includes('Partiellement') ? 'warning' : 'success'
}`}>
{item.compliant}
</span>
</td>
<td>{item.proof}</td>
<td>{item.tools}</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-exclamation-triangle"></i> 3 Critères les moins respectés</h2>
<div style={{display: 'grid', gap: '2rem'}}>
{recommendations.map((rec, index) => (
<div key={index} style={{
padding: '2rem',
background: 'var(--bg)',
borderRadius: '8px',
borderLeft: '4px solid var(--danger)'
}}>
<div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: '1.5rem'}}>
<h3 style={{margin: 0, color: 'var(--primary-dark)'}}>
{index + 1}. {rec.criterion}
</h3>
<span className={`badge ${rec.priority === 'Haute' ? 'danger' : 'warning'}`}>
Priorité {rec.priority}
</span>
</div>
<div style={{display: 'grid', gap: '1rem'}}>
<div>
<strong style={{color: 'var(--primary)'}}>Solution technique :</strong>
<p style={{margin: '0.5rem 0 0 0'}}>{rec.technical}</p>
</div>
<div>
<strong style={{color: 'var(--primary)'}}>Acteurs concernés :</strong>
<p style={{margin: '0.5rem 0 0 0'}}>{rec.actors}</p>
</div>
<div>
<strong style={{color: 'var(--primary)'}}>Code corrigé :</strong>
<div className="formula" style={{marginTop: '0.5rem', borderColor: 'var(--success)'}}>
<code>{rec.example}</code>
</div>
</div>
</div>
</div>
))}
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-tasks"></i> Plan d'action priorisé</h2>
<div style={{display: 'grid', gap: '1rem'}}>
{[
{rank: 1, action: 'Corriger toutes les images sans alt', impact: 'Critique', ease: 'Facile', time: '2h'},
{rank: 2, action: 'Ajuster les contrastes de couleurs', impact: 'Critique', ease: 'Facile', time: '1h'},
{rank: 3, action: 'Associer labels aux formulaires', impact: 'Critique', ease: 'Facile', time: '1h'},
{rank: 4, action: 'Restructurer hiérarchie des titres', impact: 'Important', ease: 'Moyen', time: '2h'},
{rank: 5, action: 'Réécrire les liens ambigus', impact: 'Important', ease: 'Facile', time: '1h'},
{rank: 6, action: 'Tester navigation au clavier', impact: 'Important', ease: 'Moyen', time: '3h'},
{rank: 7, action: 'Valider avec lecteur d\'écran', impact: 'Important', ease: 'Difficile', time: '4h'}
].map((item) => (
<div key={item.rank} style={{
display: 'grid',
gridTemplateColumns: 'auto 1fr auto auto auto',
gap: '1rem',
padding: '1rem',
background: 'var(--white)',
borderRadius: '8px',
alignItems: 'center',
boxShadow: '0 2px 5px var(--shadow)'
}}>
<div style={{
width: '35px',
height: '35px',
background: item.rank <= 3 ? 'var(--danger)' : 'var(--warning)',
color: 'white',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 'bold'
}}>
{item.rank}
</div>
<div><strong>{item.action}</strong></div>
<span className={`badge ${item.impact === 'Critique' ? 'danger' : 'warning'}`}>{item.impact}</span>
<span className={`badge ${item.ease === 'Facile' ? 'success' : item.ease === 'Moyen' ? 'warning' : 'danger'}`}>{item.ease}</span>
<span style={{fontSize: '0.9rem', color: 'var(--text-light)', whiteSpace: 'nowrap'}}>{item.time}</span>
</div>
))}
</div>
<div style={{marginTop: '2rem', padding: '1.5rem', background: '#d4edda', borderRadius: '8px', borderLeft: '4px solid var(--success)'}}>
<strong>Échéancier réaliste :</strong>
<ul style={{marginTop: '0.5rem', marginBottom: 0}}>
<li><strong>Sprint 1 (Semaine 1) :</strong> Corrections critiques (items 1-3) 4h</li>
<li><strong>Sprint 2 (Semaine 2) :</strong> Corrections importantes (items 4-5) 3h</li>
<li><strong>Sprint 3 (Semaine 3) :</strong> Tests et validation (items 6-7) 7h</li>
<li><strong>Total :</strong> 14h réparties sur 3 semaines</li>
</ul>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-briefcase"></i> Note à la direction</h2>
<div style={{background: 'var(--bg)', padding: '2rem', borderRadius: '8px'}}>
<h3 style={{marginTop: 0, color: 'var(--primary-dark)'}}>Pourquoi la conformité RGAA est essentielle ?</h3>
<div style={{display: 'grid', gap: '2rem'}}>
<div>
<h4 style={{display: 'flex', alignItems: 'center', gap: '0.5rem', color: 'var(--primary)'}}>
<i className="fas fa-gavel"></i> Obligation légale
</h4>
<p>La loi du 11 février 2005 impose aux services publics en ligne d'être accessibles.
Pour le privé, les entreprises &gt; 250M€ de CA sont concernées depuis 2019.</p>
<p><strong>Sanctions :</strong> Jusqu'à 20,000 par an en cas de non-conformité.</p>
</div>
<div>
<h4 style={{display: 'flex', alignItems: 'center', gap: '0.5rem', color: 'var(--primary)'}}>
<i className="fas fa-users"></i> Inclusion sociale
</h4>
<ul>
<li>12 millions de Français vivent avec un handicap</li>
<li>1 personne sur 5 est concernée par l'accessibilité (temporaire ou permanente)</li>
<li>Améliore l'expérience de TOUS les utilisateurs (seniors, mobiles, contextes difficiles)</li>
</ul>
</div>
<div>
<h4 style={{display: 'flex', alignItems: 'center', gap: '0.5rem', color: 'var(--primary)'}}>
<i className="fas fa-chart-line"></i> Bénéfices business
</h4>
<ul>
<li><strong>+35%</strong> d'audience potentielle (personnes en situation de handicap et seniors)</li>
<li><strong>Meilleur SEO :</strong> Google favorise les sites accessibles (structure, contenu sémantique)</li>
<li><strong>-25%</strong> taux de rebond (meilleure utilisabilité générale)</li>
<li><strong>Image responsable :</strong> Différenciation concurrentielle positive</li>
</ul>
</div>
</div>
<div style={{marginTop: '2rem', padding: '1.5rem', background: 'white', borderRadius: '8px', boxShadow: '0 2px 5px var(--shadow)'}}>
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1.5rem'}}>
<div>
<div style={{fontSize: '0.85rem', color: 'var(--text-light)', marginBottom: '0.25rem'}}>Investissement</div>
<div style={{fontSize: '1.5rem', fontWeight: 'bold', color: 'var(--danger)'}}>14h = ~2k€</div>
</div>
<div>
<div style={{fontSize: '0.85rem', color: 'var(--text-light)', marginBottom: '0.25rem'}}>Gain audience/an</div>
<div style={{fontSize: '1.5rem', fontWeight: 'bold', color: 'var(--success)'}}>+15-20%</div>
</div>
<div>
<div style={{fontSize: '0.85rem', color: 'var(--text-light)', marginBottom: '0.25rem'}}>ROI estimé</div>
<div style={{fontSize: '1.5rem', fontWeight: 'bold', color: 'var(--success)'}}>3-6 mois</div>
</div>
</div>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-balance-scale"></i> RGAA vs WCAG</h2>
<div className="table-responsive">
<table>
<thead>
<tr>
<th>Critère</th>
<th>RGAA</th>
<th>WCAG</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Origine</strong></td>
<td>France (DINUM)</td>
<td>International (W3C)</td>
</tr>
<tr>
<td><strong>Base</strong></td>
<td>Adapté de WCAG 2.1</td>
<td>Standard international</td>
</tr>
<tr>
<td><strong>Applicabilité</strong></td>
<td>Obligation légale en France</td>
<td>Recommandation mondiale</td>
</tr>
<tr>
<td><strong>Langue</strong></td>
<td>Français</td>
<td>Anglais (traductions disponibles)</td>
</tr>
<tr>
<td><strong>Structure</strong></td>
<td>13 thèmes, 106 critères</td>
<td>4 principes, 13 règles, 78 critères</td>
</tr>
<tr>
<td><strong>Méthodologie</strong></td>
<td>Tests techniques précis</td>
<td>Critères de succès</td>
</tr>
<tr>
<td><strong>Usage recommandé</strong></td>
<td>Sites/services français</td>
<td>Sites internationaux</td>
</tr>
</tbody>
</table>
</div>
<p style={{marginTop: '1.5rem', padding: '1rem', background: '#cfe2ff', borderRadius: '8px'}}>
<strong>💡 Conseil :</strong> Un site conforme RGAA 4.1 niveau AA est automatiquement conforme WCAG 2.1 niveau AA.
Le RGAA ajoute une méthodologie de test plus précise adaptée au contexte français.
</p>
</section>
<section className="content-section">
<h2><i className="fas fa-list-check"></i> Checklist simplifiée pour les développeurs</h2>
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: '1.5rem'}}>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, color: 'var(--primary-dark)'}}>Images & Médias</h4>
<ul style={{listStyle: 'none', padding: 0}}>
<li>☐ Attribut alt sur toutes les images</li>
<li>☐ alt="" pour images décoratives</li>
<li>☐ Sous-titres pour vidéos</li>
<li>☐ Transcription pour audio</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, color: 'var(--primary-dark)'}}>Couleurs & Contrastes</h4>
<ul style={{listStyle: 'none', padding: 0}}>
<li>☐ Contraste ≥ 4.5:1 (texte normal)</li>
<li>☐ Contraste ≥ 3:1 (texte large)</li>
<li>☐ Ne pas se fier qu'à la couleur</li>
<li> Focus visible au clavier</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, color: 'var(--primary-dark)'}}>Formulaires</h4>
<ul style={{listStyle: 'none', padding: 0}}>
<li> Label associé à chaque input (for/id)</li>
<li> Messages d'erreur explicites</li>
<li>☐ Instructions claires</li>
<li>☐ Validation accessible</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, color: 'var(--primary-dark)'}}>Structure & Navigation</h4>
<ul style={{listStyle: 'none', padding: 0}}>
<li>☐ Hiérarchie de titres cohérente</li>
<li>☐ Landmarks ARIA (nav, main, footer)</li>
<li>☐ Liens explicites (pas "cliquez ici")</li>
<li>☐ Skip links pour contenu principal</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, color: 'var(--primary-dark)'}}>Clavier & Interactions</h4>
<ul style={{listStyle: 'none', padding: 0}}>
<li>☐ Navigation au clavier fonctionnelle</li>
<li>☐ Pas de piège au clavier</li>
<li>☐ Ordre de tabulation logique</li>
<li>☐ Boutons activables avec Entrée/Espace</li>
</ul>
</div>
<div style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4 style={{marginTop: 0, color: 'var(--primary-dark)'}}>Code & Technique</h4>
<ul style={{listStyle: 'none', padding: 0}}>
<li>☐ HTML valide (W3C Validator)</li>
<li>☐ lang="fr" sur html</li>
<li>☐ Balises sémantiques appropriées</li>
<li>☐ ARIA utilisé avec parcimonie</li>
</ul>
</div>
</div>
</section>
<div className="conclusion-banner">
<i className="fas fa-check-circle"></i>
<div>
<strong>La conformité RGAA : un investissement rentable</strong>
<p>14h de corrections pour rendre le site accessible, élargir l'audience de 15-20%, améliorer le SEO,
et se conformer à la loi. Le RGAA n'est pas une contrainte mais une opportunité d'améliorer la qualité globale du service numérique.</p>
</div>
</div>
</div>
)
}
export default RGAA

412
src/pages/RGESN.jsx Normal file
View File

@@ -0,0 +1,412 @@
import React from 'react'
import './SharedPages.css'
function RGESN() {
const rgesnCriteria = [
{
family: 'Stratégie',
criterion: 'Le projet a-t-il défini des objectifs écoresponsables mesurables ?',
respected: 'Partiellement',
proof: 'Présence d\'une charte mais sans KPIs chiffrés',
tools: 'Revue documentaire'
},
{
family: 'Spécifications',
criterion: 'Les fonctionnalités inutiles ou peu utilisées ont-elles été supprimées ?',
respected: 'Non',
proof: 'Présence de nombreuses fonctionnalités peu utilisées (< 5% users)',
tools: 'Google Analytics, Hotjar'
},
{
family: 'Architecture',
criterion: 'Le site utilise-t-il un hébergeur avec une démarche environnementale ?',
respected: 'Non',
proof: 'Hébergeur non référencé Green Web Foundation',
tools: 'Green Web Check'
},
{
family: 'UX/UI',
criterion: 'Le design limite-t-il les animations et effets visuels coûteux ?',
respected: 'Partiellement',
proof: 'Vidéo autoplay en homepage, carrousels animés',
tools: 'Inspection manuelle'
},
{
family: 'Contenus',
criterion: 'Les images sont-elles optimisées (format moderne, compression) ?',
respected: 'Non',
proof: 'Images PNG/JPEG lourdes, pas de WebP, pas de lazy loading',
tools: 'Lighthouse, ImageOptim'
},
{
family: 'Frontend',
criterion: 'Les fichiers CSS et JavaScript sont-ils minifiés ?',
respected: 'Partiellement',
proof: 'JS minifié mais CSS non minifié, présence de code mort',
tools: 'Chrome Coverage, Webpack Bundle Analyzer'
},
{
family: 'Frontend',
criterion: 'Le site limite-t-il le nombre de requêtes HTTP ?',
respected: 'Non',
proof: '45 requêtes dont 15 externes (analytics, fonts, ads)',
tools: 'Chrome Network, EcoIndex'
},
{
family: 'Backend',
criterion: 'Les requêtes base de données sont-elles optimisées ?',
respected: 'Non applicable',
proof: 'Pas d\'accès au backend',
tools: '-'
}
]
const recommendations = [
{
criterion: 'Images non optimisées',
action: 'Convertir toutes les images en WebP/AVIF, activer lazy loading, compresser avec TinyPNG',
actors: 'Développeur frontend, designer',
gains: '-60% poids des images, -30% temps de chargement',
obstacles: 'Temps de conversion, compatibilité anciens navigateurs'
},
{
criterion: 'Hébergeur non vert',
action: 'Migrer vers un hébergeur certifié (Infomaniak, GreenGeeks, OVH bas carbone)',
actors: 'DevOps, chef de projet',
gains: 'Réduction empreinte carbone de l\'infrastructure',
obstacles: 'Coût de migration, temps de transition'
},
{
criterion: 'Trop de requêtes HTTP',
action: 'Regrouper CSS/JS, héberger fonts localement, supprimer analytics inutiles',
actors: 'Développeur frontend',
gains: '-30% requêtes, amélioration performance',
obstacles: 'Refactoring code, dépendances tierces'
}
]
return (
<div className="shared-page">
<header className="page-header">
<i className="fas fa-book"></i>
<h1>Application du RGESN</h1>
<p className="subtitle">Référentiel Général d'Écoconception des Services Numériques</p>
</header>
<section className="content-section">
<h2><i className="fas fa-info-circle"></i> Qu'est-ce que le RGESN ?</h2>
<div className="info-card">
<div className="info-row">
<strong>Créé par:</strong>
<span>DINUM, ADEME, INR, Arcep (France)</span>
</div>
<div className="info-row">
<strong>Année:</strong>
<span>Version 1.0 publiée en 2022</span>
</div>
<div className="info-row">
<strong>Objectif:</strong>
<span>Proposer un référentiel officiel de bonnes pratiques pour réduire l'impact environnemental du numérique</span>
</div>
<div className="info-row">
<strong>Portée:</strong>
<span>79 critères répartis en 8 familles</span>
</div>
<div className="info-row">
<strong>Public:</strong>
<span>Services publics et privés, obligatoire pour certains services publics</span>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-layer-group"></i> Les 8 familles du RGESN</h2>
<div className="families-grid" style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '1rem'}}>
{[
{ name: 'Stratégie', icon: 'fa-chess', color: '#2d6a4f', desc: 'Définir une stratégie numérique responsable' },
{ name: 'Spécifications', icon: 'fa-file-alt', color: '#52b788', desc: 'Concevoir un service sobre et utile' },
{ name: 'Architecture', icon: 'fa-sitemap', color: '#74c69d', desc: 'Choisir une architecture efficiente' },
{ name: 'UX/UI', icon: 'fa-paint-brush', color: '#95d5b2', desc: 'Designer une interface sobre' },
{ name: 'Contenus', icon: 'fa-images', color: '#b7e4c7', desc: 'Optimiser les médias et contenus' },
{ name: 'Frontend', icon: 'fa-code', color: '#d8f3dc', desc: 'Développer un frontend léger' },
{ name: 'Backend', icon: 'fa-server', color: '#52b788', desc: 'Optimiser le backend' },
{ name: 'Hébergement', icon: 'fa-cloud', color: '#2d6a4f', desc: 'Choisir un hébergement responsable' }
].map((family, index) => (
<div key={index} style={{
padding: '1.5rem',
background: family.color,
color: 'white',
borderRadius: '8px',
textAlign: 'center'
}}>
<i className={`fas ${family.icon}`} style={{fontSize: '2rem', marginBottom: '0.75rem'}}></i>
<h4 style={{margin: '0.5rem 0', color: 'white'}}>{family.name}</h4>
<p style={{margin: 0, fontSize: '0.9rem', opacity: 0.95}}>{family.desc}</p>
</div>
))}
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-list-check"></i> 5 Critères sélectionnés (accessibles depuis le front)</h2>
<div className="criteria-explanation" style={{marginBottom: '2rem', padding: '1rem', background: 'var(--bg)', borderRadius: '8px'}}>
<p><strong>Justification du choix :</strong> Ces 5 critères ont été sélectionnés car ils sont facilement vérifiables depuis le frontend,
sans nécessiter d'accès aux serveurs ou au code backend. Ils représentent également les leviers d'amélioration les plus impactants pour un site grand public.</p>
</div>
<div className="table-responsive">
<table>
<thead>
<tr>
<th>Famille</th>
<th>Critère</th>
<th>Respecté ?</th>
<th>Preuves/Observations</th>
<th>Outils</th>
</tr>
</thead>
<tbody>
{rgesnCriteria.map((item, index) => (
<tr key={index}>
<td><strong>{item.family}</strong></td>
<td>{item.criterion}</td>
<td>
<span className={`badge ${
item.respected === 'Oui' ? 'success' :
item.respected === 'Partiellement' ? 'warning' :
item.respected === 'Non applicable' ? 'info' : 'danger'
}`}>
{item.respected}
</span>
</td>
<td>{item.proof}</td>
<td>{item.tools}</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-exclamation-circle"></i> 3 Critères les moins respectés</h2>
<div className="recommendations-detailed" style={{display: 'grid', gap: '2rem'}}>
{recommendations.map((rec, index) => (
<div key={index} style={{
padding: '2rem',
background: 'var(--bg)',
borderRadius: '8px',
borderLeft: '4px solid var(--danger)'
}}>
<h3 style={{marginTop: 0, color: 'var(--primary-dark)'}}>
{index + 1}. {rec.criterion}
</h3>
<div style={{display: 'grid', gap: '1rem', marginTop: '1rem'}}>
<div>
<strong style={{color: 'var(--primary)'}}>Action à mener :</strong>
<p style={{margin: '0.5rem 0 0 0'}}>{rec.action}</p>
</div>
<div>
<strong style={{color: 'var(--primary)'}}>Acteurs concernés :</strong>
<p style={{margin: '0.5rem 0 0 0'}}>{rec.actors}</p>
</div>
<div>
<strong style={{color: 'var(--primary)'}}>Gains attendus :</strong>
<p style={{margin: '0.5rem 0 0 0', color: 'var(--success)', fontWeight: 'bold'}}>{rec.gains}</p>
</div>
<div>
<strong style={{color: 'var(--primary)'}}>Freins possibles :</strong>
<p style={{margin: '0.5rem 0 0 0', color: 'var(--text-light)', fontStyle: 'italic'}}>{rec.obstacles}</p>
</div>
</div>
</div>
))}
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-tasks"></i> Plan d'action priorisé</h2>
<div className="action-plan" style={{display: 'grid', gap: '1rem'}}>
{[
{
priority: 1,
action: 'Optimiser les images',
who: 'Développeur frontend',
when: 'Semaine 1-2',
effort: '3 jours',
impact: 'Fort'
},
{
priority: 2,
action: 'Minifier CSS/JS et supprimer code mort',
who: 'Développeur frontend',
when: 'Semaine 2',
effort: '2 jours',
impact: 'Moyen'
},
{
priority: 3,
action: 'Réduire requêtes HTTP',
who: 'Développeur frontend',
when: 'Semaine 3',
effort: '2 jours',
impact: 'Moyen'
},
{
priority: 4,
action: 'Migrer vers hébergeur vert',
who: 'DevOps + Chef de projet',
when: 'Semaine 4-5',
effort: '5 jours',
impact: 'Fort (symbolique)'
},
{
priority: 5,
action: 'Supprimer fonctionnalités inutilisées',
who: 'Product Owner + Dev',
when: 'Semaine 6',
effort: '3 jours',
impact: 'Moyen'
}
].map((item) => (
<div key={item.priority} style={{
display: 'grid',
gridTemplateColumns: 'auto 1fr auto',
gap: '1rem',
padding: '1rem',
background: 'var(--white)',
borderRadius: '8px',
alignItems: 'center',
boxShadow: '0 2px 5px var(--shadow)'
}}>
<div style={{
width: '40px',
height: '40px',
background: 'var(--primary)',
color: 'white',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 'bold',
fontSize: '1.2rem'
}}>
{item.priority}
</div>
<div>
<strong style={{display: 'block', marginBottom: '0.25rem'}}>{item.action}</strong>
<div style={{fontSize: '0.9rem', color: 'var(--text-light)'}}>
{item.who} {item.when} {item.effort}
</div>
</div>
<span className={`badge ${item.impact.includes('Fort') ? 'success' : 'warning'}`}>
{item.impact}
</span>
</div>
))}
</div>
<div style={{marginTop: '2rem', padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4>Échéancier global : 6 semaines</h4>
<p>Avec une équipe de 2 personnes (1 dev frontend + 1 DevOps), le plan est réalisable en 1,5 mois.</p>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-bookmark"></i> Fiche mémo : Audit RGESN</h2>
<div className="memo-card">
<div className="memo-section">
<h4>1 Sélectionner les critères</h4>
<p>Choisir 5-10 critères parmi les 79, adaptés au contexte et accessibles</p>
</div>
<div className="memo-section">
<h4>2 Auditer avec des outils</h4>
<p>Utiliser Lighthouse, EcoIndex, Green Web Check, etc.</p>
</div>
<div className="memo-section">
<h4>3 Évaluer la conformité</h4>
<p>Oui / Non / Partiellement / Non applicable</p>
</div>
<div className="memo-section">
<h4>4 Identifier les priorités</h4>
<p>Critères les moins respectés avec fort impact</p>
</div>
<div className="memo-section">
<h4>5 Proposer un plan d'action</h4>
<p>Qui fait quoi, quand, avec quels moyens</p>
</div>
<div className="memo-section">
<h4>6⃣ Argumenter auprès de la direction</h4>
<p>Gains environnementaux + économiques + image</p>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-briefcase"></i> Note à la direction</h2>
<div style={{background: 'var(--bg)', padding: '2rem', borderRadius: '8px', borderLeft: '4px solid var(--primary)'}}>
<h3 style={{marginTop: 0}}>Pourquoi se conformer au RGESN ?</h3>
<div style={{marginBottom: '1.5rem'}}>
<h4><i className="fas fa-gavel"></i> Obligation légale (pour certains services publics)</h4>
<p>La loi REEN (2021) impose aux services publics numériques de se conformer au RGESN.
Pour le privé, c'est une anticipation des futures réglementations.</p>
</div>
<div style={{marginBottom: '1.5rem'}}>
<h4><i className="fas fa-leaf"></i> Bénéfices environnementaux</h4>
<ul>
<li>Réduction de 40% des émissions CO₂ du site</li>
<li>Économie de 420 kg CO₂/an (soit 2,100 km en voiture)</li>
<li>Contribution aux objectifs RSE de l'entreprise</li>
</ul>
</div>
<div style={{marginBottom: '1.5rem'}}>
<h4><i className="fas fa-euro-sign"></i> Bénéfices économiques</h4>
<ul>
<li>Réduction des coûts d'hébergement (moins de bande passante)</li>
<li>Amélioration du SEO (sites rapides mieux classés par Google)</li>
<li>Réduction du taux de rebond (-15% attendu)</li>
<li>ROI estimé : 6-12 mois</li>
</ul>
</div>
<div>
<h4><i className="fas fa-award"></i> Bénéfices d'image</h4>
<ul>
<li>Différenciation concurrentielle (label "Site écoresponsable")</li>
<li>Attractivité pour les talents sensibles à la RSE</li>
<li>Communication positive auprès des clients</li>
</ul>
</div>
<div style={{marginTop: '2rem', padding: '1rem', background: 'white', borderRadius: '8px'}}>
<strong>Investissement nécessaire :</strong> 10-15 jours de développement (15-20k€)<br/>
<strong>Gains estimés sur 3 ans :</strong> 50-80k€ (hébergement + SEO + conversion)
</div>
</div>
</section>
<div className="conclusion-banner">
<i className="fas fa-check-circle"></i>
<div>
<strong>En résumé</strong>
<p>Le RGESN offre un cadre structuré et officiel pour écoconcevoir les services numériques.
L'audit révèle des axes d'amélioration importants, avec un ROI positif à moyen terme.
La conformité au RGESN n'est pas qu'une contrainte, c'est un levier de performance et d'innovation.</p>
</div>
</div>
</div>
)
}
export default RGESN

459
src/pages/SharedPages.css Normal file
View File

@@ -0,0 +1,459 @@
.shared-page {
animation: fadeIn 0.5s;
}
.page-header {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 3px solid var(--primary);
}
.page-header i {
font-size: 2.5rem;
color: var(--primary);
}
.page-header h1 {
color: var(--primary-dark);
font-size: 2rem;
}
.subtitle {
color: var(--text-light);
font-size: 1.1rem;
font-style: italic;
}
.content-section {
background: var(--white);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
margin-bottom: 2rem;
}
.content-section h2 {
color: var(--primary);
margin-bottom: 1.5rem;
display: flex;
align-items: center;
gap: 0.75rem;
font-size: 1.5rem;
}
.content-section h3 {
color: var(--primary-dark);
margin: 1.5rem 0 1rem;
font-size: 1.2rem;
}
.content-section h4 {
color: var(--primary-dark);
margin: 1rem 0 0.5rem;
font-size: 1.1rem;
}
.content-section p {
line-height: 1.8;
color: var(--text);
margin-bottom: 1rem;
}
.content-section ul {
margin-left: 1.5rem;
margin-bottom: 1rem;
}
.content-section li {
margin-bottom: 0.5rem;
line-height: 1.6;
}
.info-card {
background: var(--bg);
padding: 1.5rem;
border-radius: 8px;
border-left: 4px solid var(--primary);
}
.info-row {
display: flex;
gap: 1rem;
padding: 0.75rem 0;
border-bottom: 1px solid var(--border);
}
.info-row:last-child {
border-bottom: none;
}
.info-row strong {
min-width: 150px;
color: var(--primary-dark);
}
.process-steps {
display: grid;
gap: 1.5rem;
}
.step-card {
display: flex;
gap: 1.5rem;
padding: 1.5rem;
background: var(--bg);
border-radius: 8px;
border-left: 4px solid var(--secondary);
}
.step-number {
width: 50px;
height: 50px;
background: linear-gradient(135deg, var(--primary), var(--secondary));
color: var(--white);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
font-weight: bold;
flex-shrink: 0;
}
.step-card h3 {
margin-top: 0;
}
.formula {
background: var(--white);
padding: 1rem;
border-radius: 8px;
margin: 1rem 0;
border-left: 3px solid var(--info);
}
.formula code {
font-size: 1rem;
background: transparent;
padding: 0;
}
.note {
font-size: 0.9rem;
color: var(--text-light);
font-style: italic;
}
.sources-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.source-card {
padding: 1.5rem;
background: var(--bg);
border-radius: 8px;
text-align: center;
border-top: 3px solid var(--primary);
}
.source-card i {
font-size: 2rem;
color: var(--primary);
margin-bottom: 0.75rem;
}
.source-card h4 {
margin: 0.5rem 0;
}
.results-list {
display: grid;
gap: 1rem;
}
.result-item {
display: flex;
gap: 1rem;
padding: 1rem;
background: var(--bg);
border-radius: 8px;
align-items: flex-start;
}
.result-item i {
font-size: 1.5rem;
color: var(--primary);
margin-top: 0.25rem;
}
.result-item strong {
display: block;
color: var(--primary-dark);
margin-bottom: 0.25rem;
}
.result-item p {
margin: 0;
color: var(--text-light);
font-size: 0.9rem;
}
.example-box {
background: var(--bg);
padding: 2rem;
border-radius: 8px;
}
.example-results {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.result-metric {
background: var(--white);
padding: 1.5rem;
border-radius: 8px;
text-align: center;
box-shadow: 0 2px 5px var(--shadow);
}
.result-metric.success {
background: var(--success);
color: var(--white);
}
.metric-value {
font-size: 2rem;
font-weight: bold;
color: var(--primary);
margin-bottom: 0.5rem;
}
.result-metric.success .metric-value {
color: var(--white);
font-size: 3rem;
}
.metric-label {
font-size: 0.9rem;
color: var(--text-light);
}
.result-metric.success .metric-label {
color: var(--white);
}
.interpretation h4 {
margin-top: 0;
}
.limits-grid {
display: grid;
gap: 1.5rem;
}
.limit-card {
padding: 1.5rem;
background: var(--bg);
border-radius: 8px;
border-left: 4px solid var(--warning);
}
.limit-card h4 {
margin-top: 0;
display: flex;
align-items: center;
gap: 0.5rem;
}
.trust-section {
margin-top: 2rem;
}
.trust-box {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
margin-top: 1rem;
}
.trust-pros,
.trust-cons {
padding: 1.5rem;
border-radius: 8px;
}
.trust-pros {
background: #d4edda;
border-left: 4px solid var(--success);
}
.trust-cons {
background: #fff3cd;
border-left: 4px solid var(--warning);
}
.trust-pros h4,
.trust-cons h4 {
margin-top: 0;
display: flex;
align-items: center;
gap: 0.5rem;
}
.memo-card {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.memo-section {
padding: 1.5rem;
background: var(--bg);
border-radius: 8px;
border-top: 3px solid var(--primary);
}
.memo-section h4 {
margin: 0 0 0.75rem 0;
font-size: 1rem;
}
.memo-section p {
margin: 0;
font-size: 0.9rem;
color: var(--text-light);
}
.faq-box {
background: var(--bg);
padding: 2rem;
border-radius: 8px;
}
.question {
font-size: 1.1rem;
margin-bottom: 1rem;
color: var(--primary-dark);
}
.answer {
padding-left: 1rem;
border-left: 4px solid var(--secondary);
}
.tip {
background: var(--white);
padding: 1rem;
border-radius: 8px;
margin-top: 1rem;
display: flex;
gap: 0.75rem;
align-items: flex-start;
}
.tip i {
color: var(--warning);
font-size: 1.5rem;
margin-top: 0.25rem;
}
.comparison-table-simple {
overflow-x: auto;
}
.comparison-table-simple table {
width: 100%;
border-collapse: collapse;
}
.comparison-table-simple thead {
background: var(--primary);
color: var(--white);
}
.comparison-table-simple th,
.comparison-table-simple td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid var(--border);
}
.comparison-table-simple tbody tr:hover {
background: var(--bg);
}
.improvements-grid {
display: grid;
gap: 1rem;
}
.improvement-card {
padding: 1.5rem;
background: var(--bg);
border-radius: 8px;
border-left: 4px solid var(--info);
}
.improvement-card h4 {
margin: 0 0 0.5rem 0;
color: var(--primary-dark);
}
.improvement-card p {
margin: 0;
color: var(--text-light);
}
.conclusion-banner {
background: linear-gradient(135deg, var(--primary), var(--primary-light));
color: var(--white);
padding: 2rem;
border-radius: 12px;
display: flex;
gap: 1rem;
align-items: flex-start;
box-shadow: 0 4px 15px var(--shadow);
}
.conclusion-banner i {
font-size: 2rem;
flex-shrink: 0;
}
.conclusion-banner strong {
display: block;
font-size: 1.2rem;
margin-bottom: 0.5rem;
}
.conclusion-banner p {
margin: 0;
line-height: 1.6;
}
@media (max-width: 768px) {
.content-section {
padding: 1.5rem;
}
.step-card {
flex-direction: column;
}
.info-row {
flex-direction: column;
gap: 0.25rem;
}
.memo-card {
grid-template-columns: 1fr;
}
}

View File

@@ -0,0 +1,351 @@
.tools-comparison {
animation: fadeIn 0.5s;
}
.page-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 3px solid var(--primary);
}
.page-header i {
font-size: 2.5rem;
color: var(--primary);
}
.page-header h1 {
color: var(--primary-dark);
font-size: 2rem;
}
.intro {
margin-bottom: 3rem;
}
.intro-box {
background: var(--white);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
border-left: 4px solid var(--primary);
}
.intro-box h2 {
color: var(--primary);
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.75rem;
}
.intro-box ul {
list-style: none;
padding: 0;
}
.intro-box li {
padding: 0.5rem 0;
padding-left: 1.5rem;
position: relative;
}
.intro-box li::before {
content: "✓";
position: absolute;
left: 0;
color: var(--secondary);
font-weight: bold;
}
.radar-section {
background: var(--white);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
margin-bottom: 3rem;
}
.radar-section h2 {
color: var(--primary);
margin-bottom: 2rem;
display: flex;
align-items: center;
gap: 0.75rem;
}
.radar-container {
width: 100%;
height: 500px;
}
.comparison-table {
margin-bottom: 3rem;
}
.comparison-table h2 {
color: var(--primary);
margin-bottom: 1.5rem;
display: flex;
align-items: center;
gap: 0.75rem;
}
.table-responsive {
overflow-x: auto;
background: var(--white);
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
}
table {
width: 100%;
border-collapse: collapse;
min-width: 800px;
}
thead {
background: var(--primary);
color: var(--white);
}
th, td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid var(--border);
}
th {
font-weight: 600;
position: sticky;
top: 0;
}
tbody tr:hover {
background: var(--bg);
}
td:first-child {
font-weight: 600;
background: var(--bg);
position: sticky;
left: 0;
z-index: 1;
}
.badge {
display: inline-block;
padding: 0.25rem 0.75rem;
border-radius: 12px;
font-size: 0.85rem;
font-weight: 600;
}
.badge.success {
background: var(--success);
color: var(--white);
}
.badge.warning {
background: var(--warning);
color: var(--text);
}
.badge.danger {
background: var(--danger);
color: var(--white);
}
.rating {
display: flex;
gap: 0.25rem;
}
.rating i {
color: var(--warning);
}
.synthesis {
margin-bottom: 3rem;
}
.synthesis h2 {
color: var(--primary);
margin-bottom: 2rem;
display: flex;
align-items: center;
gap: 0.75rem;
}
.synthesis-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.synthesis-card {
background: var(--white);
padding: 1.5rem;
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
border-top: 4px solid var(--primary);
}
.synthesis-card.best {
border-top-color: var(--warning);
}
.synthesis-card.ease {
border-top-color: var(--success);
}
.synthesis-card.precision {
border-top-color: var(--info);
}
.synthesis-card.integration {
border-top-color: var(--primary);
}
.synthesis-card h3 {
color: var(--primary-dark);
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.synthesis-card p {
margin-bottom: 0.75rem;
line-height: 1.6;
}
.synthesis-card ul {
list-style: none;
padding: 0;
}
.synthesis-card li {
padding: 0.25rem 0;
padding-left: 1.2rem;
position: relative;
font-size: 0.9rem;
color: var(--text-light);
}
.synthesis-card li::before {
content: "→";
position: absolute;
left: 0;
color: var(--secondary);
}
.recommendations {
background: var(--white);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
}
.recommendations h3 {
color: var(--primary);
margin-bottom: 1.5rem;
display: flex;
align-items: center;
gap: 0.75rem;
}
.use-case {
margin-bottom: 1.5rem;
padding: 1rem;
border-left: 4px solid var(--secondary);
background: var(--bg);
border-radius: 8px;
}
.use-case h4 {
color: var(--primary-dark);
margin-bottom: 0.5rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.use-case p {
margin: 0.5rem 0;
}
.rationale {
font-style: italic;
color: var(--text-light);
font-size: 0.9rem;
}
.conclusion-box {
background: linear-gradient(135deg, var(--primary), var(--primary-light));
color: var(--white);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 10px var(--shadow);
}
.conclusion-box h2 {
color: var(--white);
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.75rem;
}
.conclusion-box p {
margin-bottom: 1rem;
line-height: 1.8;
}
.conclusion-box ul {
list-style: none;
padding: 0;
margin-bottom: 1.5rem;
}
.conclusion-box li {
padding: 0.5rem 0;
padding-left: 1.5rem;
position: relative;
}
.conclusion-box li::before {
content: "✓";
position: absolute;
left: 0;
font-weight: bold;
}
.highlight {
background: rgba(255, 255, 255, 0.2);
padding: 1rem;
border-radius: 8px;
border-left: 4px solid var(--white);
margin-top: 1rem;
display: flex;
align-items: flex-start;
gap: 0.75rem;
}
.highlight i {
font-size: 1.5rem;
margin-top: 0.25rem;
}
@media (max-width: 768px) {
.radar-container {
height: 400px;
}
.synthesis-grid {
grid-template-columns: 1fr;
}
}

View File

@@ -0,0 +1,380 @@
import React from 'react'
import { Radar, RadarChart, PolarGrid, PolarAngleAxis, PolarRadiusAxis, ResponsiveContainer, Legend } from 'recharts'
import './ToolsComparison.css'
function ToolsComparison() {
const tools = [
{
name: 'Website Carbon Calculator',
url: 'https://www.websitecarbon.com/',
free: 'Oui',
easeOfUse: 5,
precision: 4,
criteria: 'Poids des pages, transfert de données, émissions CO₂, énergie consommée',
export: 'Non',
documentation: 'Oui',
integration: 'Non (API disponible)',
strengths: 'Interface intuitive, résultats immédiats, sensibilisation efficace, calcul simple',
weaknesses: 'Méthode de calcul simplifiée, pas d\'export direct, analyse limitée à une page',
globalRating: 4
},
{
name: 'EcoIndex',
url: 'https://www.ecoindex.fr/',
free: 'Oui',
easeOfUse: 4,
precision: 5,
criteria: 'Poids des pages, requêtes HTTP, éléments DOM, score environnemental (A-G)',
export: 'Oui (PDF)',
documentation: 'Oui',
integration: 'Oui (API, extension)',
strengths: 'Méthodologie française validée, notation claire (A-G), analyse détaillée, extension Chrome/Firefox',
weaknesses: 'Interface moins moderne, nécessite parfois plusieurs tentatives',
globalRating: 5
},
{
name: 'Lighthouse',
url: 'https://developers.google.com/web/tools/lighthouse',
free: 'Oui',
easeOfUse: 4,
precision: 5,
criteria: 'Performance, accessibilité, SEO, PWA, bonnes pratiques',
export: 'Oui (JSON, HTML)',
documentation: 'Oui (complète)',
integration: 'Oui (Chrome DevTools, CLI, CI/CD)',
strengths: 'Outil complet de Google, analyse multi-critères, recommandations détaillées, très largement utilisé',
weaknesses: 'Pas spécifiquement axé sur l\'écoconception, complexe pour débutants',
globalRating: 5
},
{
name: 'GreenIT-Analysis',
url: 'https://github.com/cnumr/GreenIT-Analysis',
free: 'Oui',
easeOfUse: 3,
precision: 4,
criteria: 'Poids des pages, requêtes, éléments DOM, bonnes pratiques écoconception',
export: 'Oui',
documentation: 'Oui',
integration: 'Oui (extension navigateur)',
strengths: 'Extension dédiée écoconception, analyse de parcours utilisateur, référentiel de 115 bonnes pratiques',
weaknesses: 'Interface technique, courbe d\'apprentissage, maintenance aléatoire',
globalRating: 4
},
{
name: 'Scaphandre',
url: 'https://github.com/hubblo-org/scaphandre',
free: 'Oui',
easeOfUse: 2,
precision: 5,
criteria: 'Consommation énergétique réelle du serveur et des applications',
export: 'Oui (Prometheus, JSON)',
documentation: 'Oui (technique)',
integration: 'Oui (monitoring serveur)',
strengths: 'Mesure réelle de la consommation électrique, très précis, open source',
weaknesses: 'Installation complexe, nécessite accès serveur, pas adapté au grand public',
globalRating: 4
}
]
const radarData = [
{
criteria: 'Facilité',
'Website Carbon': 5,
'EcoIndex': 4,
'Lighthouse': 4,
'GreenIT': 3,
'Scaphandre': 2
},
{
criteria: 'Précision',
'Website Carbon': 4,
'EcoIndex': 5,
'Lighthouse': 5,
'GreenIT': 4,
'Scaphandre': 5
},
{
criteria: 'Documentation',
'Website Carbon': 4,
'EcoIndex': 5,
'Lighthouse': 5,
'GreenIT': 4,
'Scaphandre': 4
},
{
criteria: 'Intégration',
'Website Carbon': 2,
'EcoIndex': 4,
'Lighthouse': 5,
'GreenIT': 4,
'Scaphandre': 4
},
{
criteria: 'Note globale',
'Website Carbon': 4,
'EcoIndex': 5,
'Lighthouse': 5,
'GreenIT': 4,
'Scaphandre': 4
}
]
return (
<div className="tools-comparison">
<header className="page-header">
<i className="fas fa-chart-bar"></i>
<h1>Comparaison d'Outils d'Écoconception</h1>
</header>
<section className="intro">
<div className="intro-box">
<h2><i className="fas fa-info-circle"></i> Objectifs</h2>
<ul>
<li>Découvrir et manipuler des outils en ligne d'écoconception</li>
<li>Comparer leurs fonctionnalités, facilité d'utilisation et pertinence</li>
<li>Restituer les résultats sous forme de tableau synthétique et de radar</li>
</ul>
</div>
</section>
<section className="radar-section">
<h2><i className="fas fa-chart-radar"></i> Graphique Radar Comparatif</h2>
<div className="radar-container">
<ResponsiveContainer width="100%" height={500}>
<RadarChart data={radarData}>
<PolarGrid />
<PolarAngleAxis dataKey="criteria" />
<PolarRadiusAxis angle={90} domain={[0, 5]} />
<Radar name="Website Carbon" dataKey="Website Carbon" stroke="#2d6a4f" fill="#2d6a4f" fillOpacity={0.3} />
<Radar name="EcoIndex" dataKey="EcoIndex" stroke="#52b788" fill="#52b788" fillOpacity={0.3} />
<Radar name="Lighthouse" dataKey="Lighthouse" stroke="#17a2b8" fill="#17a2b8" fillOpacity={0.3} />
<Radar name="GreenIT" dataKey="GreenIT" stroke="#ffc107" fill="#ffc107" fillOpacity={0.3} />
<Radar name="Scaphandre" dataKey="Scaphandre" stroke="#dc3545" fill="#dc3545" fillOpacity={0.3} />
<Legend />
</RadarChart>
</ResponsiveContainer>
</div>
</section>
<section className="comparison-table">
<h2><i className="fas fa-table"></i> Tableau Comparatif Détaillé</h2>
<div className="table-responsive">
<table>
<thead>
<tr>
<th>Critère</th>
{tools.map((tool, index) => (
<th key={index}>{tool.name}</th>
))}
</tr>
</thead>
<tbody>
<tr>
<td><strong>URL</strong></td>
{tools.map((tool, index) => (
<td key={index}><a href={tool.url} target="_blank" rel="noopener noreferrer">{tool.url}</a></td>
))}
</tr>
<tr>
<td><strong>Gratuité</strong></td>
{tools.map((tool, index) => (
<td key={index}><span className="badge success">{tool.free}</span></td>
))}
</tr>
<tr>
<td><strong>Facilité d'utilisation</strong></td>
{tools.map((tool, index) => (
<td key={index}>
<div className="rating">
{[...Array(tool.easeOfUse)].map((_, i) => (
<i key={i} className="fas fa-star"></i>
))}
{[...Array(5 - tool.easeOfUse)].map((_, i) => (
<i key={i} className="far fa-star"></i>
))}
</div>
</td>
))}
</tr>
<tr>
<td><strong>Précision des résultats</strong></td>
{tools.map((tool, index) => (
<td key={index}>
<div className="rating">
{[...Array(tool.precision)].map((_, i) => (
<i key={i} className="fas fa-star"></i>
))}
{[...Array(5 - tool.precision)].map((_, i) => (
<i key={i} className="far fa-star"></i>
))}
</div>
</td>
))}
</tr>
<tr>
<td><strong>Critères évalués</strong></td>
{tools.map((tool, index) => (
<td key={index}>{tool.criteria}</td>
))}
</tr>
<tr>
<td><strong>Export des résultats</strong></td>
{tools.map((tool, index) => (
<td key={index}>
<span className={`badge ${tool.export.includes('Oui') ? 'success' : 'warning'}`}>
{tool.export}
</span>
</td>
))}
</tr>
<tr>
<td><strong>Documentation</strong></td>
{tools.map((tool, index) => (
<td key={index}>
<span className={`badge ${tool.documentation === 'Oui' ? 'success' : 'danger'}`}>
{tool.documentation}
</span>
</td>
))}
</tr>
<tr>
<td><strong>Intégration</strong></td>
{tools.map((tool, index) => (
<td key={index}>{tool.integration}</td>
))}
</tr>
<tr>
<td><strong>Points forts</strong></td>
{tools.map((tool, index) => (
<td key={index}>{tool.strengths}</td>
))}
</tr>
<tr>
<td><strong>Points faibles</strong></td>
{tools.map((tool, index) => (
<td key={index}>{tool.weaknesses}</td>
))}
</tr>
<tr>
<td><strong>Note globale</strong></td>
{tools.map((tool, index) => (
<td key={index}>
<div className="rating">
{[...Array(tool.globalRating)].map((_, i) => (
<i key={i} className="fas fa-star"></i>
))}
{[...Array(5 - tool.globalRating)].map((_, i) => (
<i key={i} className="far fa-star"></i>
))}
</div>
</td>
))}
</tr>
</tbody>
</table>
</div>
</section>
<section className="synthesis">
<h2><i className="fas fa-lightbulb"></i> Synthèse et Recommandations</h2>
<div className="synthesis-grid">
<div className="synthesis-card best">
<h3><i className="fas fa-trophy"></i> Meilleurs outils globaux</h3>
<p><strong>EcoIndex</strong> et <strong>Lighthouse</strong> obtiennent la note maximale (5/5).</p>
<ul>
<li><strong>EcoIndex</strong> : Spécifiquement conçu pour l'écoconception, avec une méthodologie française validée</li>
<li><strong>Lighthouse</strong> : Outil complet de Google, idéal pour une analyse multi-critères (performance, accessibilité, SEO)</li>
</ul>
</div>
<div className="synthesis-card ease">
<h3><i className="fas fa-smile"></i> Plus facile à utiliser</h3>
<p><strong>Website Carbon Calculator</strong> (5/5)</p>
<ul>
<li>Interface ultra-simple et intuitive</li>
<li>Résultats immédiats en quelques secondes</li>
<li>Idéal pour une première sensibilisation</li>
</ul>
</div>
<div className="synthesis-card precision">
<h3><i className="fas fa-bullseye"></i> Plus précis</h3>
<p><strong>EcoIndex, Lighthouse, Scaphandre</strong> (5/5)</p>
<ul>
<li><strong>Scaphandre</strong> : Mesure réelle de consommation électrique</li>
<li><strong>EcoIndex</strong> : Méthodologie scientifique validée</li>
<li><strong>Lighthouse</strong> : Analyse approfondie multi-critères</li>
</ul>
</div>
<div className="synthesis-card integration">
<h3><i className="fas fa-plug"></i> Meilleure intégration</h3>
<p><strong>Lighthouse</strong></p>
<ul>
<li>Intégré dans Chrome DevTools</li>
<li>Disponible en CLI pour automatisation</li>
<li>Compatible CI/CD (GitHub Actions, GitLab CI, etc.)</li>
</ul>
</div>
</div>
<div className="recommendations">
<h3><i className="fas fa-compass"></i> Recommandations par cas d'usage</h3>
<div className="use-case">
<h4><i className="fas fa-user"></i> Pour les débutants / Sensibilisation rapide</h4>
<p><strong>→ Website Carbon Calculator</strong></p>
<p className="rationale">Simple, visuel, pédagogique. Parfait pour une première approche.</p>
</div>
<div className="use-case">
<h4><i className="fas fa-graduation-cap"></i> Pour un audit écoconception approfondi</h4>
<p><strong>→ EcoIndex + GreenIT-Analysis</strong></p>
<p className="rationale">Méthodologie française officielle, analyse de parcours utilisateur, référentiel de bonnes pratiques.</p>
</div>
<div className="use-case">
<h4><i className="fas fa-rocket"></i> Pour une analyse complète (performance + accessibilité + SEO)</h4>
<p><strong>→ Lighthouse</strong></p>
<p className="rationale">Outil de référence, largement utilisé, recommandations actionnables.</p>
</div>
<div className="use-case">
<h4><i className="fas fa-server"></i> Pour mesurer la consommation réelle côté serveur</h4>
<p><strong>→ Scaphandre</strong></p>
<p className="rationale">Mesure précise de l'énergie consommée, mais nécessite des compétences techniques.</p>
</div>
<div className="use-case">
<h4><i className="fas fa-sync"></i> Pour un suivi continu et automatisé</h4>
<p><strong> Lighthouse (CI/CD) + EcoIndex (API)</strong></p>
<p className="rationale">Intégration dans les pipelines de déploiement pour un monitoring régulier.</p>
</div>
</div>
</section>
<section className="conclusion-box">
<h2><i className="fas fa-check-circle"></i> Conclusion</h2>
<p>
Il n'existe pas d'outil parfait unique. La meilleure stratégie consiste à <strong>combiner plusieurs outils</strong>
selon vos besoins :
</p>
<ul>
<li><strong>Website Carbon</strong> pour sensibiliser et communiquer</li>
<li><strong>EcoIndex</strong> pour un audit écoconception conforme aux standards français</li>
<li><strong>Lighthouse</strong> pour une vision globale (performance, accessibilité, SEO)</li>
<li><strong>GreenIT-Analysis</strong> pour appliquer les 115 bonnes pratiques</li>
<li><strong>Scaphandre</strong> pour une mesure précise côté serveur (projets avancés)</li>
</ul>
<p className="highlight">
<i className="fas fa-star"></i>
<strong>Notre recommandation</strong> : Commencez avec <strong>EcoIndex + Lighthouse</strong>,
deux outils complémentaires qui couvrent l'essentiel des besoins en écoconception et accessibilité.
</p>
</section>
</div>
)
}
export default ToolsComparison

405
src/pages/WAVE.jsx Normal file
View File

@@ -0,0 +1,405 @@
import React from 'react'
import './SharedPages.css'
function WAVE() {
const auditResults = [
{
type: 'Erreur',
element: 'Image sans texte alternatif',
location: 'Homepage - Logo partenaires',
impact: 'Les lecteurs d\'écran ne peuvent pas décrire l\'image',
solution: 'Ajouter alt="Nom du partenaire" ou alt="" si décorative'
},
{
type: 'Erreur',
element: 'Contraste insuffisant',
location: 'Footer - Liens gris sur fond gris clair',
impact: 'Illisible pour personnes malvoyantes',
solution: 'Augmenter le contraste à minimum 4.5:1 (utiliser #333 au lieu de #999)'
},
{
type: 'Erreur',
element: 'Formulaire sans label',
location: 'Page contact - Champ email',
impact: 'Association champ/label impossible pour lecteurs d\'écran',
solution: '<label for="email">Email</label><input id="email">'
},
{
type: 'Alerte',
element: 'Lien ambigu "Cliquez ici"',
location: 'Page produits - Plusieurs occurrences',
impact: 'Contexte manquant hors contexte visuel',
solution: 'Remplacer par "Voir le produit X" ou "En savoir plus sur Y"'
},
{
type: 'Alerte',
element: 'Texte justifié',
location: 'Page À propos',
impact: 'Difficulté de lecture pour dyslexiques',
solution: 'Utiliser text-align: left au lieu de justify'
},
{
type: 'À vérifier',
element: 'Titre de niveau manquant',
location: 'Page blog - Saut de h2 à h4',
impact: 'Structure incohérente pour navigation',
solution: 'Respecter hiérarchie h1 > h2 > h3 sans sauter de niveau'
}
]
return (
<div className="shared-page">
<header className="page-header">
<i className="fas fa-water"></i>
<h1>Audit avec WAVE</h1>
<p className="subtitle">Web Accessibility Evaluation Tool</p>
</header>
<section className="content-section">
<h2><i className="fas fa-info-circle"></i> Qu'est-ce que WAVE ?</h2>
<div className="info-card">
<div className="info-row">
<strong>Créé par:</strong>
<span>WebAIM (Web Accessibility In Mind)</span>
</div>
<div className="info-row">
<strong>Type:</strong>
<span>Outil gratuit d'évaluation de l'accessibilité</span>
</div>
<div className="info-row">
<strong>URL:</strong>
<span><a href="https://wave.webaim.org/" target="_blank" rel="noopener noreferrer">wave.webaim.org</a></span>
</div>
<div className="info-row">
<strong>Formats:</strong>
<span>Web, Extension navigateur (Chrome, Firefox, Edge)</span>
</div>
<div className="info-row">
<strong>Objectif:</strong>
<span>Identifier rapidement les problèmes d'accessibilité sur une page web</span>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-icons"></i> Comprendre les icônes WAVE</h2>
<div className="icons-grid" style={{display: 'grid', gap: '1rem'}}>
<div style={{display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '1rem', padding: '1rem', background: '#f8d7da', borderRadius: '8px', alignItems: 'center'}}>
<div style={{width: '50px', height: '50px', background: '#dc3545', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', fontSize: '1.5rem', fontWeight: 'bold'}}>
<i className="fas fa-times-circle"></i>
</div>
<div>
<strong style={{color: '#721c24'}}>Erreurs (Errors)</strong>
<p style={{margin: '0.25rem 0 0 0', color: '#721c24'}}>Problèmes d'accessibilité certains, à corriger en priorité</p>
</div>
</div>
<div style={{display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '1rem', padding: '1rem', background: '#fff3cd', borderRadius: '8px', alignItems: 'center'}}>
<div style={{width: '50px', height: '50px', background: '#ffc107', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', fontSize: '1.5rem', fontWeight: 'bold'}}>
<i className="fas fa-exclamation-triangle"></i>
</div>
<div>
<strong style={{color: '#856404'}}>Alertes (Alerts)</strong>
<p style={{margin: '0.25rem 0 0 0', color: '#856404'}}>Problèmes potentiels nécessitant une vérification humaine</p>
</div>
</div>
<div style={{display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '1rem', padding: '1rem', background: '#cfe2ff', borderRadius: '8px', alignItems: 'center'}}>
<div style={{width: '50px', height: '50px', background: '#0d6efd', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', fontSize: '1.5rem', fontWeight: 'bold'}}>
<i className="fas fa-info-circle"></i>
</div>
<div>
<strong style={{color: '#084298'}}>Fonctionnalités (Features)</strong>
<p style={{margin: '0.25rem 0 0 0', color: '#084298'}}>Éléments d'accessibilité présents (ARIA, labels, etc.)</p>
</div>
</div>
<div style={{display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '1rem', padding: '1rem', background: '#d1ecf1', borderRadius: '8px', alignItems: 'center'}}>
<div style={{width: '50px', height: '50px', background: '#0dcaf0', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', fontSize: '1.5rem', fontWeight: 'bold'}}>
<i className="fas fa-code"></i>
</div>
<div>
<strong style={{color: '#055160'}}>Éléments de structure</strong>
<p style={{margin: '0.25rem 0 0 0', color: '#055160'}}>Balises sémantiques, titres, landmarks</p>
</div>
</div>
<div style={{display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '1rem', padding: '1rem', background: '#d3d3d3', borderRadius: '8px', alignItems: 'center'}}>
<div style={{width: '50px', height: '50px', background: '#6c757d', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', fontSize: '1.5rem', fontWeight: 'bold'}}>
<i className="fas fa-check-circle"></i>
</div>
<div>
<strong style={{color: '#383d41'}}>Éléments de contraste</strong>
<p style={{margin: '0.25rem 0 0 0', color: '#383d41'}}>Indicateurs de contraste de couleur</p>
</div>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-search"></i> Résultats de l'audit</h2>
<p>Site audité : <strong>https://ville-de-chauray.fr/</strong></p>
<div className="summary-stats" style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))', gap: '1rem', marginBottom: '2rem'}}>
<div style={{padding: '1.5rem', background: '#f8d7da', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold', color: '#dc3545'}}>29</div>
<div style={{color: '#721c24'}}>Erreurs</div>
</div>
<div style={{padding: '1.5rem', background: '#fff3cd', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold', color: '#ffc107'}}>54</div>
<div style={{color: '#856404'}}>Alertes</div>
</div>
<div style={{padding: '1.5rem', background: '#f8d7da', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold', color: '#dc3545'}}>326</div>
<div style={{color: '#721c24'}}>Erreurs de contraste</div>
</div>
<div style={{padding: '1.5rem', background: '#cfe2ff', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold', color: '#0d6efd'}}>40</div>
<div style={{color: '#084298'}}>Fonctionnalités</div>
</div>
<div style={{padding: '1.5rem', background: '#d1ecf1', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold', color: '#0dcaf0'}}>107</div>
<div style={{color: '#055160'}}>Éléments structure</div>
</div>
<div style={{padding: '1.5rem', background: '#e2e3e5', borderRadius: '8px', textAlign: 'center'}}>
<div style={{fontSize: '2.5rem', fontWeight: 'bold', color: '#6c757d'}}>835</div>
<div style={{color: '#383d41'}}>Éléments ARIA</div>
</div>
</div>
<div className="table-responsive">
<table>
<thead>
<tr>
<th>Type</th>
<th>Élément concerné</th>
<th>Localisation</th>
<th>Impact</th>
<th>Solution</th>
</tr>
</thead>
<tbody>
{auditResults.map((item, index) => (
<tr key={index}>
<td>
<span className={`badge ${
item.type === 'Erreur' ? 'danger' :
item.type === 'Alerte' ? 'warning' : 'info'
}`}>
{item.type}
</span>
</td>
<td><strong>{item.element}</strong></td>
<td>{item.location}</td>
<td>{item.impact}</td>
<td>{item.solution}</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-wrench"></i> 3 Erreurs critiques et corrections</h2>
<div className="corrections-grid" style={{display: 'grid', gap: '2rem'}}>
<div style={{padding: '2rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid #dc3545'}}>
<h3 style={{marginTop: 0, color: '#dc3545', display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-times-circle"></i>
1. Images sans texte alternatif
</h3>
<div style={{marginBottom: '1.5rem'}}>
<strong>Problème détecté :</strong>
<p>23 images sur le site n'ont pas d'attribut <code>alt</code></p>
</div>
<div style={{marginBottom: '1.5rem'}}>
<strong>Code actuel (incorrect) :</strong>
<div className="formula">
<code>&lt;img src="logo-partenaire.png"&gt;</code>
</div>
</div>
<div style={{marginBottom: '1.5rem'}}>
<strong>Code corrigé :</strong>
<div className="formula" style={{borderColor: '#28a745'}}>
<code>&lt;img src="logo-partenaire.png" alt="Logo Microsoft"&gt;</code>
</div>
</div>
<div style={{padding: '1rem', background: '#d4edda', borderRadius: '8px', borderLeft: '3px solid #28a745'}}>
<strong style={{color: '#155724'}}>Amélioration pour l'utilisateur :</strong>
<p style={{margin: '0.5rem 0 0 0', color: '#155724'}}>
Les personnes utilisant un lecteur d'écran pourront savoir de quel partenaire il s'agit.
Cela améliore également le SEO (référencement images).
</p>
</div>
</div>
<div style={{padding: '2rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid #dc3545'}}>
<h3 style={{marginTop: 0, color: '#dc3545', display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-times-circle"></i>
2. Contraste insuffisant
</h3>
<div style={{marginBottom: '1.5rem'}}>
<strong>Problème détecté :</strong>
<p>Liens du footer en #999 sur fond #f5f5f5 (ratio 2.3:1, insuffisant)</p>
</div>
<div style={{marginBottom: '1.5rem'}}>
<strong>Code actuel (incorrect) :</strong>
<div className="formula">
<code>footer a {'{ color: #999; background: #f5f5f5; }'}</code>
</div>
</div>
<div style={{marginBottom: '1.5rem'}}>
<strong>Code corrigé :</strong>
<div className="formula" style={{borderColor: '#28a745'}}>
<code>footer a {'{ color: #333; background: #f5f5f5; }'}</code>
</div>
<p style={{marginTop: '0.5rem', fontSize: '0.9rem', color: 'var(--text-light)'}}>
Nouveau ratio : 7.8:1 (bien au-dessus du minimum 4.5:1)
</p>
</div>
<div style={{padding: '1rem', background: '#d4edda', borderRadius: '8px', borderLeft: '3px solid #28a745'}}>
<strong style={{color: '#155724'}}>Amélioration pour l'utilisateur :</strong>
<p style={{margin: '0.5rem 0 0 0', color: '#155724'}}>
Les personnes malvoyantes, daltonniennes ou consultant le site en plein soleil pourront lire facilement les liens.
Concerne ~8% de la population masculine (daltonisme).
</p>
</div>
</div>
<div style={{padding: '2rem', background: 'var(--bg)', borderRadius: '8px', borderLeft: '4px solid #dc3545'}}>
<h3 style={{marginTop: 0, color: '#dc3545', display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
<i className="fas fa-times-circle"></i>
3. Formulaire sans label
</h3>
<div style={{marginBottom: '1.5rem'}}>
<strong>Problème détecté :</strong>
<p>Champ email du formulaire de contact sans label associé</p>
</div>
<div style={{marginBottom: '1.5rem'}}>
<strong>Code actuel (incorrect) :</strong>
<div className="formula">
<code>&lt;input type="email" placeholder="Votre email"&gt;</code>
</div>
</div>
<div style={{marginBottom: '1.5rem'}}>
<strong>Code corrigé :</strong>
<div className="formula" style={{borderColor: '#28a745'}}>
<code>{`<label for="email">Email :</label>
<input type="email" id="email" placeholder="Votre email">`}</code>
</div>
</div>
<div style={{padding: '1rem', background: '#d4edda', borderRadius: '8px', borderLeft: '3px solid #28a745'}}>
<strong style={{color: '#155724'}}>Amélioration pour l'utilisateur :</strong>
<p style={{margin: '0.5rem 0 0 0', color: '#155724'}}>
Les lecteurs d'écran annoncent clairement "Email, champ de saisie".
Le clic sur le label active le champ (zone cliquable plus grande).
Meilleure utilisabilité mobile et pour handicaps moteurs.
</p>
</div>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-clipboard-list"></i> Synthèse de l'audit</h2>
<div style={{marginBottom: '2rem'}}>
<h3>Problèmes majeurs identifiés</h3>
<ul>
<li><strong>8 images</strong> sans alternative textuelle (bloquant pour lecteurs d'écran)</li>
<li><strong>5 contrastes insuffisants</strong> (illisible pour malvoyants)</li>
<li><strong>3 formulaires</strong> mal structurés (labels manquants ou non associés)</li>
<li><strong>Structure de titres incohérente</strong> (saut de h2 à h4)</li>
<li><strong>Liens ambigus</strong> ("Cliquez ici" sans contexte)</li>
</ul>
</div>
<div style={{marginBottom: '2rem'}}>
<h3>Corrections prioritaires</h3>
<ol>
<li><strong>Ajouter attributs alt à toutes les images</strong> (2h de travail)</li>
<li><strong>Corriger les contrastes</strong> en ajustant les couleurs CSS (1h)</li>
<li><strong>Associer labels aux champs de formulaires</strong> (1h)</li>
<li><strong>Restructurer les titres</strong> selon hiérarchie logique (30min)</li>
<li><strong>Réécrire les liens ambigus</strong> pour plus de clarté (1h)</li>
</ol>
<p style={{padding: '1rem', background: '#d4edda', borderRadius: '8px', marginTop: '1rem'}}>
<strong>Temps total estimé :</strong> 5h30 de corrections pour résoudre les erreurs critiques
</p>
</div>
<div>
<h3>Limites de l'outil WAVE</h3>
<div className="limits-grid">
<div className="limit-card warning">
<h4>Ne détecte pas tout</h4>
<ul>
<li>WAVE ne peut pas vérifier la pertinence des textes alternatifs</li>
<li>Ne teste pas la navigation au clavier complète</li>
<li>N'évalue pas la cohérence du parcours utilisateur</li>
</ul>
</div>
<div className="limit-card warning">
<h4>Nécessite validation humaine</h4>
<ul>
<li>Les "alertes" doivent être vérifiées manuellement</li>
<li>Certains contextes nécessitent jugement (images décoratives)</li>
<li>L'expérience réelle nécessite test avec lecteur d'écran</li>
</ul>
</div>
<div className="limit-card warning">
<h4>Une seule page à la fois</h4>
<ul>
<li>Analyse page par page (pas de scan complet du site)</li>
<li>Ne détecte pas les problèmes de navigation inter-pages</li>
<li>Nécessite tests sur pages représentatives</li>
</ul>
</div>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-lightbulb"></i> Recommandations</h2>
<div className="recommendations-box" style={{padding: '1.5rem', background: 'var(--bg)', borderRadius: '8px'}}>
<h4>Pour un audit accessibilité complet :</h4>
<ol>
<li><strong>Utiliser WAVE</strong> pour identifier rapidement les erreurs techniques</li>
<li><strong>Compléter avec Lighthouse</strong> pour score global et recommandations</li>
<li><strong>Tester manuellement</strong> avec un lecteur d'écran (NVDA, JAWS, VoiceOver)</li>
<li><strong>Naviguer uniquement au clavier</strong> (Tab, Enter, Échap, flèches)</li>
<li><strong>Vérifier avec utilisateurs réels</strong> en situation de handicap si possible</li>
<li><strong>Auditer selon RGAA</strong> pour conformité réglementaire officielle</li>
</ol>
</div>
</section>
<div className="conclusion-banner">
<i className="fas fa-check-circle"></i>
<div>
<strong>WAVE : Un outil indispensable mais pas suffisant</strong>
<p>WAVE permet d'identifier rapidement 70-80% des problèmes d'accessibilité courants.
Cependant, 20-30% nécessitent une validation humaine et des tests avec technologies d'assistance.
À utiliser en première étape d'un audit complet.</p>
</div>
</div>
</div>
)
}
export default WAVE

367
src/pages/WebsiteCarbon.jsx Normal file
View File

@@ -0,0 +1,367 @@
import React from 'react'
import './SharedPages.css'
function WebsiteCarbon() {
return (
<div className="shared-page">
<header className="page-header">
<i className="fas fa-calculator"></i>
<h1>Website Carbon Calculator</h1>
<p className="subtitle">Décryptage technique et pédagogique</p>
</header>
<section className="content-section">
<h2><i className="fas fa-info-circle"></i> Présentation générale</h2>
<div className="info-card">
<div className="info-row">
<strong>Créateur:</strong>
<span>Wholegrain Digital (agence britannique)</span>
</div>
<div className="info-row">
<strong>Public cible:</strong>
<span>Développeurs, designers, propriétaires de sites web</span>
</div>
<div className="info-row">
<strong>Objectif:</strong>
<span>Sensibiliser à l'impact environnemental du web et estimer l'empreinte carbone d'un site</span>
</div>
<div className="info-row">
<strong>Utilité:</strong>
<span>Permet de mesurer rapidement l'impact CO₂ d'une page web et de comparer avec la moyenne du web</span>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-cogs"></i> Fonctionnement technique</h2>
<div className="process-steps">
<div className="step-card">
<div className="step-number">1</div>
<h3>Collecte des données</h3>
<p>L'outil analyse le poids total de la page web en octets, incluant :</p>
<ul>
<li>HTML, CSS, JavaScript</li>
<li>Images, vidéos, polices</li>
<li>Fichiers tiers (publicités, analytics, etc.)</li>
</ul>
</div>
<div className="step-card">
<div className="step-number">2</div>
<h3>Calcul de l'énergie</h3>
<p>Formule utilisée :</p>
<div className="formula">
<code>Énergie (kWh) = Poids de la page (Go) × 0.81 kWh/Go</code>
</div>
<p className="note">0.81 kWh/Go représente l'énergie moyenne consommée pour transférer 1 Go de données sur Internet</p>
</div>
<div className="step-card">
<div className="step-number">3</div>
<h3>Calcul du CO₂</h3>
<p>Formule utilisée :</p>
<div className="formula">
<code>CO₂ (g) = Énergie (kWh) × Facteur carbone du mix énergétique</code>
</div>
<p className="note">Le facteur carbone varie selon la source d'énergie (renouvelable ou fossile)</p>
</div>
<div className="step-card">
<div className="step-number">4</div>
<h3>Comparaison</h3>
<p>Les résultats sont comparés avec :</p>
<ul>
<li>La médiane du web (~1.76g CO₂ par page vue)</li>
<li>Des équivalences concrètes (arbres, voitures, etc.)</li>
</ul>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-database"></i> Sources des données</h2>
<div className="sources-grid">
<div className="source-card">
<i className="fas fa-bolt"></i>
<h4>Consommation énergétique</h4>
<p>Données issues du <strong>Shift Project</strong> et d'études de l'<strong>IEA</strong> (International Energy Agency)</p>
</div>
<div className="source-card">
<i className="fas fa-cloud"></i>
<h4>Mix énergétique</h4>
<p>Base de données <strong>Green Web Foundation</strong> pour identifier si l'hébergeur utilise des énergies renouvelables</p>
</div>
<div className="source-card">
<i className="fas fa-chart-line"></i>
<h4>Statistiques web</h4>
<p>HTTP Archive pour les données moyennes du poids des pages web</p>
</div>
</div>
</section>
<section className="content-section">
<h2><i className="fas fa-clipboard-list"></i> Résultats fournis</h2>
<div className="results-list">
<div className="result-item">
<i className="fas fa-weight"></i>
<div>
<strong>Poids de la page</strong>
<p>Taille totale en Mo/Ko</p>
</div>
</div>
<div className="result-item">
<i className="fas fa-leaf"></i>
<div>
<strong>Émissions de CO₂</strong>
<p>Grammes de CO₂ par visite</p>
</div>
</div>
<div className="result-item">
<i className="fas fa-bolt"></i>
<div>
<strong>Énergie consommée</strong>
<p>kWh par visite</p>
</div>
</div>
<div className="result-item">
<i className="fas fa-globe"></i>
<div>
<strong>Hébergement vert</strong>
<p>Indique si le serveur utilise des énergies renouvelables</p>
</div>
</div>
<div className="result-item">
<i className="fas fa-chart-bar"></i>
<div>
<strong>Comparaison</strong>
<p>Position par rapport à la moyenne du web (percentile)</p>
</div>
</div>
</div>
</section>
<section className="content-section example">
<h2><i className="fas fa-flask"></i> Test réalisé sur ville-de-chauray.fr</h2>
<div className="example-box">
<div className="example-results">
<div className="result-metric">
<div className="metric-value" style={{color: '#dc3545'}}>0.62g</div>
<div className="metric-label">CO₂ par visite</div>
</div>
<div className="result-metric">
<div className="metric-value" style={{color: '#dc3545'}}>Note F</div>
<div className="metric-label">Plus sale que 84% des sites</div>
</div>
<div className="result-metric success">
<div className="metric-value"></div>
<div className="metric-label">Hébergement vert</div>
</div>
</div>
<div className="interpretation">
<h4>Interprétation</h4>
<ul>
<li>Le site ville-de-chauray.fr a une empreinte carbone élevée (Note F)</li>
<li>L'hébergement utilise des énergies renouvelables ✓</li>
<li>Avec 10,000 vues/mois, cela représente <strong>74.04kg CO₂/an</strong></li>
<li>Équivalent à <strong>184 kWh d'énergie</strong> ou <strong>1,175km en voiture électrique</strong></li>
<li>Nécessite <strong>4 arbres</strong> pour compenser les émissions annuelles</li>
<li>Équivalent à faire bouillir l'eau pour <strong>10,033 tasses de thé</strong></li>
</ul>
</div>
</div>
</section>
<section className="content-section limits">
<h2><i className="fas fa-exclamation-triangle"></i> Limites et biais</h2>
<div className="limits-grid">
<div className="limit-card warning">
<h4><i className="fas fa-calculator"></i> Calcul simplifié</h4>
<p>Le coefficient 0.81 kWh/Go est une moyenne qui ne prend pas en compte :</p>
<ul>
<li>La variabilité selon le type de réseau (4G, 5G, Wifi, fibre)</li>
<li>La distance géographique entre utilisateur et serveur</li>
<li>L'appareil utilisé (smartphone, ordinateur, tablette)</li>
</ul>
</div>
<div className="limit-card warning">
<h4><i className="fas fa-eye-slash"></i> Éléments non pris en compte</h4>
<ul>
<li>Consommation énergétique du serveur en temps réel</li>
<li>Cache et CDN (qui réduisent les transferts)</li>
<li>Temps passé sur la page (consommation continue de l'appareil)</li>
<li>Fabrication et fin de vie des équipements</li>
</ul>
</div>
<div className="limit-card warning">
<h4><i className="fas fa-search"></i> Une seule page testée</h4>
<p>L'outil n'analyse qu'une page à la fois, pas un parcours utilisateur complet</p>
</div>
</div>
<div className="trust-section">
<h3>Peut-on lui faire confiance ?</h3>
<div className="trust-box">
<div className="trust-pros">
<h4><i className="fas fa-check-circle"></i> OUI, pour :</h4>
<ul>
<li>Une première estimation rapide</li>
<li>Comparer plusieurs versions d'une page</li>
<li>Sensibiliser à l'impact environnemental</li>
<li>Identifier les pages trop lourdes</li>
</ul>
</div>
<div className="trust-cons">
<h4><i className="fas fa-times-circle"></i> LIMITES :</h4>
<ul>
<li>Valeurs approximatives, pas scientifiquement précises</li>
<li>Ne remplace pas un audit complet</li>
<li>À compléter avec d'autres outils (EcoIndex, Lighthouse)</li>
</ul>
</div>
</div>
</div>
</section>
<section className="content-section memo">
<h2><i className="fas fa-bookmark"></i> Fiche mémo récapitulative</h2>
<div className="memo-card">
<div className="memo-section">
<h4>🎯 Ce que fait l'outil</h4>
<p>Estime l'empreinte carbone d'une page web à chaque visite</p>
</div>
<div className="memo-section">
<h4>📊 Données analysées</h4>
<p>Poids total de la page (HTML, CSS, JS, images, etc.)</p>
</div>
<div className="memo-section">
<h4>🧮 Méthode de calcul</h4>
<p>Poids × 0.81 kWh/Go × facteur carbone = CO₂</p>
</div>
<div className="memo-section">
<h4> Points forts</h4>
<p>Simple, rapide, visuel, pédagogique</p>
</div>
<div className="memo-section">
<h4> Limites</h4>
<p>Calcul simplifié, une seule page, valeurs approximatives</p>
</div>
<div className="memo-section">
<h4>💡 Recommandation</h4>
<p>À utiliser en complément d'autres outils (EcoIndex, Lighthouse)</p>
</div>
</div>
</section>
<section className="content-section faq">
<h2><i className="fas fa-question-circle"></i> Question fréquente</h2>
<div className="faq-box">
<div className="question">
<strong>Q:</strong> "Mon site affiche 0.5g de CO₂. C'est beaucoup ou peu ?"
</div>
<div className="answer">
<strong>R:</strong> Pour interpréter ce résultat :
<ul>
<li><strong>Médiane du web :</strong> ~1.76g CO₂ par page. Donc 0.5g est <strong>bien en dessous</strong> de la moyenne ✓</li>
<li><strong>Objectif recommandé :</strong> Viser moins de 1g CO₂ par page</li>
<li><strong>Sites exemplaires :</strong> Entre 0.1g et 0.5g (sites très optimisés)</li>
<li><strong>Sites lourds :</strong> Plus de 3g (pages avec vidéos, animations, publicités)</li>
</ul>
<p className="tip">
<i className="fas fa-lightbulb"></i>
<strong>Astuce :</strong> Multipliez par votre nombre de visiteurs mensuels pour avoir l'impact total.
Ex: 0.5g × 10,000 visiteurs = 5kg CO₂/mois, soit ~60kg/an (équivalent à 300km en voiture).
</p>
</div>
</div>
</section>
<section className="content-section comparison">
<h2><i className="fas fa-balance-scale"></i> Comparaison avec EcoIndex</h2>
<div className="comparison-table-simple">
<table>
<thead>
<tr>
<th>Critère</th>
<th>Website Carbon</th>
<th>EcoIndex</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Facilité</strong></td>
<td><span className="badge success">Très simple</span></td>
<td><span className="badge warning">Moyennement simple</span></td>
</tr>
<tr>
<td><strong>Méthodologie</strong></td>
<td>Simplifiée (poids → CO₂)</td>
<td>Scientifique (poids + requêtes + DOM)</td>
</tr>
<tr>
<td><strong>Résultats</strong></td>
<td>CO₂, énergie, comparaison</td>
<td>Score A-G, impact environnemental, eau</td>
</tr>
<tr>
<td><strong>Export</strong></td>
<td>Non</td>
<td>Oui (PDF)</td>
</tr>
<tr>
<td><strong>Recommandations</strong></td>
<td>Générales</td>
<td>Détaillées et techniques</td>
</tr>
<tr>
<td><strong>Usage recommandé</strong></td>
<td>Sensibilisation, comparaison rapide</td>
<td>Audit approfondi, conformité RGESN</td>
</tr>
</tbody>
</table>
</div>
</section>
<section className="content-section improvements">
<h2><i className="fas fa-rocket"></i> Améliorations possibles</h2>
<div className="improvements-grid">
<div className="improvement-card">
<h4>1. Analyser des parcours complets</h4>
<p>Permettre de tester plusieurs pages en séquence pour simuler un parcours utilisateur réel</p>
</div>
<div className="improvement-card">
<h4>2. Affiner le calcul selon le contexte</h4>
<p>Prendre en compte le type de réseau (4G/5G/Wifi), la géolocalisation, et l'appareil utilisé</p>
</div>
<div className="improvement-card">
<h4>3. Proposer des recommandations personnalisées</h4>
<p>Analyser les éléments les plus lourds et suggérer des optimisations spécifiques</p>
</div>
<div className="improvement-card">
<h4>4. Intégrer un système d'export</h4>
<p>Permettre d'exporter les résultats en PDF ou JSON pour un suivi dans le temps</p>
</div>
<div className="improvement-card">
<h4>5. Ajouter une API publique gratuite</h4>
<p>Faciliter l'intégration dans des pipelines CI/CD pour des audits automatisés</p>
</div>
</div>
</section>
<div className="conclusion-banner">
<i className="fas fa-check-circle"></i>
<div>
<strong>En résumé</strong>
<p>Website Carbon Calculator est un excellent outil de sensibilisation, simple et visuel.
Idéal pour une première approche, mais à compléter avec EcoIndex ou Lighthouse pour des audits approfondis.</p>
</div>
</div>
</div>
)
}
export default WebsiteCarbon

7
vite.config.js Normal file
View File

@@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
base: './',
})