Skip to content

#02 — rgz-web

PLANIFIÉ

Priorité: 🔴 CRITIQUE · Type: TYPE A · Conteneur: rgz-web · Code: web/src/

Dépendances: #01 rgz-api


Description

rgz-web est le dashboard d'administration de la plateforme RGZ. Il couvre deux profils d'utilisateurs : les opérateurs NOC (surveillance temps réel, incidents, infrastructure) et les revendeurs WiFi Zone (revenus, abonnés, statistiques de leur réseau). L'interface est une SPA (Single Page Application) React 18, compilée avec Vite et servie par nginx.

La stack React + Tailwind CSS assure une interface réactive et moderne. Les composants réutilisables (tableaux, cartes métriques, graphiques) sont centralisés dans web/src/components/. Les pages correspondent directement aux outils de la catégorie H : NocDashboard.tsx (#52), ResellerDashboard.tsx (#51), BannersAdmin.tsx (#53), RmaDashboard.tsx (#54), StatusPage.tsx (#55). Chaque page communique exclusivement avec rgz-api via le client Axios défini dans web/src/services/.

Le build est multi-stage : une image node:20-alpine compile le bundle React (Vite), puis l'artefact statique est copié dans une image nginx:alpine légère. La configuration nginx proxy les appels /api/ vers rgz-api:8000 — avec la règle LL#28 (resolver 127.0.0.11 + variable $backend, jamais de bloc upstream statique). Le domaine public est admin-rgz.duckdns.org, protégé par Traefik avec un certificat Let's Encrypt valide jusqu'au 2026-05-20.

La charte graphique ACCESS est implémentée via des variables CSS globales : --access-blue: #3f68ae pour les headers et sidebars, --access-yellow: #f5c445 pour les accents et boutons principaux, --access-red: #da3747 pour les alertes et CTAs urgents. La police Poppins (Google Fonts) est utilisée pour toute l'interface.

Architecture Interne

Build (CI/CD ou docker build)

  node:20-alpine
      ├── npm install
      ├── vite build → dist/


  nginx:alpine (runtime)

      ├── /          → dist/ (SPA React)
      ├── /api/      → proxy rgz-api:8000/api/ (LL#28: resolver 127.0.0.11)


  React SPA (navigateur)

      ├── React Router — routes protégées (AuthGuard)
      ├── Axios client → /api/v1/ (token JWT Authorization header)
      └── Pages:
          ├── /login              → Login.tsx
          ├── /noc                → NocDashboard.tsx (#52)
          ├── /reseller/:id       → ResellerDashboard.tsx (#51)
          ├── /banners            → BannersAdmin.tsx (#53)
          ├── /rma                → RmaDashboard.tsx (#54)
          └── /status             → StatusPage.tsx (#55, public)

Configuration

Variables d'environnement (build-time Vite)

VariableExempleDescription
VITE_API_URLhttps://api-rgz.duckdns.orgURL base de l'API REST
VITE_APP_NAMERGZ NOC DashboardNom affiché dans l'interface
VITE_GRAFANA_URLhttps://grafana-rgz.duckdns.orgURL Grafana pour les iframes
VITE_APP_ENVproductionContrôle les comportements dev/prod

Fichiers de configuration

web/
├── package.json              # Dépendances: react, react-router, axios, tailwind, chart.js, leaflet
├── vite.config.ts            # Build config, proxy dev, alias
├── tailwind.config.js        # Extension thème ACCESS colors
├── index.html                # Point d'entrée HTML
└── src/
    ├── main.tsx              # ReactDOM.render + providers
    ├── App.tsx               # BrowserRouter + AuthGuard + routes
    ├── types/index.ts        # TypeScript types (mirror schemas Python)
    ├── services/
    │   ├── api.ts            # Axios instance + intercepteurs JWT
    │   └── auth.ts           # Login, refresh token, logout
    ├── hooks/
    │   ├── useAuth.ts        # Context auth
    │   ├── useWebSocket.ts   # WS temps réel NOC
    │   └── usePagination.ts  # Pagination {items, total, page, pages}
    └── components/
        ├── MetricCard.tsx    # Carte KPI réutilisable
        ├── DataTable.tsx     # Tableau paginé avec tri
        ├── AlertBanner.tsx   # Bandeau alerte P0/P1/P2
        └── Sidebar.tsx       # Navigation latérale ACCESS blue

Tailwind ACCESS Theme

javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        'access-yellow': '#f5c445',
        'access-blue':   '#3f68ae',
        'access-red':    '#da3747',
        'access-dark':   '#34383c',
      },
      fontFamily: {
        sans: ['Poppins', 'sans-serif'],
      },
    },
  },
}

Endpoints API Consommés

EndpointPageDescription
POST /api/v1/auth/loginLoginAuthentification JWT
GET /api/v1/resellers/{id}/statsResellerDashboardStats revenus/abonnés
GET /api/v1/monitoring/slaNocDashboardMétriques SLA temps réel
GET /api/v1/monitoring/alertsNocDashboardAlertes actives Prometheus
GET /api/v1/rma/ticketsRmaDashboardFile RMA en cours
GET /api/v1/bannersBannersAdminListe bannières publicitaires
POST /api/v1/bannersBannersAdminUpload nouvelle bannière
GET /api/v1/status/incidentsStatusPageIncidents actifs (public)

Healthcheck

bash
# LL#43 : utiliser 127.0.0.1 (jamais localhost — IPv6 ::1 dans Docker)
# Healthcheck Docker dans docker-compose.core.yml
wget -qO- http://127.0.0.1:80/ | grep -q "RGZ" && echo "OK"

# Depuis l'hôte
curl -s -o /dev/null -w "%{http_code}" https://admin-rgz.duckdns.org/
# Attendu: 200

# Vérifier le proxy /api/
curl -s https://admin-rgz.duckdns.org/api/v1/health | jq .

Sécurité

RègleImplémentation
SEC-10 JWTToken stocké en mémoire (pas localStorage), refresh via cookie HttpOnly
SEC-11 CORSnginx proxy uniquement /api/, pas de direct cross-origin
SEC-13 XSStextContent uniquement pour les données utilisateur, jamais innerHTML
LL#28 nginxset $backend rgz-api:8000; resolver 127.0.0.11; — jamais de bloc upstream
LL#2 CORSLes requêtes API passent via le proxy nginx, pas de CORS navigateur côté admin
nginx
# docker/web/nginx.conf — proxy correct (LL#28)
location /api/ {
    resolver 127.0.0.11 valid=30s;
    set $backend "http://rgz-api:8000";
    proxy_pass $backend;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

Commandes Utiles

bash
# Build et démarrage
docker compose -f /home/claude-dev/RGZ/docker-compose.core.yml up -d --build rgz-web

# Logs nginx
docker logs rgz-web -f --tail=100

# Status
docker inspect rgz-web --format='{}'

# Accéder au shell
docker exec -it rgz-web sh

# Rebuild sans cache (après modif tailwind.config.js)
docker compose -f /home/claude-dev/RGZ/docker-compose.core.yml build --no-cache rgz-web

# Développement local (hot-reload)
cd /home/claude-dev/RGZ/web && npm run dev

# Build de production local
cd /home/claude-dev/RGZ/web && npm run build && ls -lh dist/

# Vérifier taille du bundle (objectif < 500KB gzipped)
cd /home/claude-dev/RGZ/web && npm run build 2>&1 | grep -E "dist|gzip"

Implémentation TODO

  • [x] Dockerfile créé (docker/web/Dockerfile)
  • [x] nginx.conf créé (docker/web/nginx.conf)
  • [x] Service défini dans docker-compose.core.yml
  • [x] Variables d'env dans .env.example
  • [ ] web/package.json — dépendances React 18 + Tailwind + Vite
  • [ ] web/vite.config.ts — config build + proxy dev
  • [ ] web/tailwind.config.js — thème ACCESS colors
  • [ ] web/src/main.tsx — point d'entrée
  • [ ] web/src/App.tsx — router + auth guard
  • [ ] web/src/services/api.ts — client Axios + intercepteurs
  • [ ] web/src/types/index.ts — types TypeScript (mirror Python schemas)
  • [ ] web/src/pages/Login.tsx
  • [ ] web/src/pages/NocDashboard.tsx (#52)
  • [ ] web/src/pages/ResellerDashboard.tsx (#51)
  • [ ] web/src/pages/BannersAdmin.tsx (#53)
  • [ ] web/src/pages/RmaDashboard.tsx (#54)
  • [ ] web/src/pages/StatusPage.tsx (#55, accès public sans auth)
  • [ ] Tests composants (Vitest + React Testing Library)

Dernière mise à jour: 2026-02-21

PROJET MOSAÏQUE — 81 outils, 22 conteneurs, 500+ revendeurs WiFi Zone