Aller au contenu

EPIDOCS — Frontend

Description

EPIDOCS est un système de gestion documentaire pour les étudiants d'EPITECH Bénin. Le frontend fournit deux interfaces distinctes : un portail étudiant (demande de documents, suivi, réclamations) et un dashboard administrateur (gestion des modèles, génération de documents, maintenance système).

Fonctionnalités principales

Portail étudiant

  • Demande de documents : certificats de scolarité, lettres de recommandation, etc.
  • Suivi de demande : timeline visuelle avec tracking par code unique
  • Réclamations : soumission et suivi des réclamations
  • Gestion de compte : sessions actives, demandes de modification d'informations
  • Notes d'information : téléchargement de PDFs publiés par l'administration
  • Annonces : bandeaux d'annonces ciblés par classe

Dashboard administrateur

  • Modèles de documents : upload, extraction d'attributs, activation/désactivation
  • Gestion des étudiants : recherche, suspension, migration entre classes, validation du statut diplômé (PGE3/PGE5)
  • Génération de documents : génération individuelle (wizard 3 étapes) et en lot par classe
  • Notes d'information : upload de PDFs ciblés par classe, activation/désactivation, suivi des téléchargements
  • Statistiques : tableau de bord avec métriques d'utilisation
  • Historique : consultation de l'historique documentaire par étudiant

Fonctionnalités superadmin

  • Mode maintenance : activation/désactivation avec redirection automatique des étudiants
  • Maintenance planifiée : programmation avec date de début/fin
  • Annonces : création et gestion de bandeaux d'information
  • Analytics : métriques détaillées par période
  • Logs d'audit : traçabilité des actions administratives
  • Sauvegarde : export/import de la base de données

Architecture

Stack technique

Composant Technologie Version
Framework Next.js (App Router) 16.1.0
Runtime Node.js 20 (Alpine)
UI React 19.0.0
Composants Chakra UI 2.8.2
Styling Tailwind CSS 3.4.1
HTTP Axios 1.7.3
Formulaires React Hook Form 7.62.0
Data fetching TanStack React Query 5.90.21
Animations Framer Motion 11.3.12
Gestionnaire de paquets pnpm 10.18.3
Conteneur Docker (node:20-alpine)

Structure des dossiers

src/
├── app/
│   ├── admin/                  # Dashboard administrateur
│   │   ├── components/         # Navbar, Sidebar
│   │   ├── admins/             # Gestion des admins
│   │   ├── analytics/          # Analytics (superadmin)
│   │   ├── announcements/      # Annonces (superadmin)
│   │   ├── audit-logs/         # Logs d'audit (superadmin)
│   │   ├── backup/             # Sauvegarde BDD (superadmin)
│   │   ├── batch-generate/     # Génération en lot
│   │   ├── dashboard/          # Statistiques
│   │   ├── documents/          # Historique documents
│   │   ├── generate-document/  # Génération unitaire
│   │   ├── info-notes/          # Notes d'information (PDFs)
│   │   ├── info-requests/      # Demandes de modification
│   │   ├── migration/          # Migration étudiants
│   │   ├── models/             # Modèles de documents
│   │   ├── pending/            # Étudiants en attente
│   │   ├── students/           # Gestion étudiants
│   │   ├── system-status/      # Maintenance (superadmin)
│   │   └── layout.js
│   │
│   ├── student/                # Portail étudiant
│   │   ├── components/         # Navbar, Profile, Banners
│   │   ├── historiques/        # Historique documents
│   │   ├── mes-demandes/       # Demandes de modification
│   │   ├── reclamations/       # Réclamations
│   │   ├── sessions/           # Gestion sessions
│   │   └── layout.js
│   │
│   ├── auth/                   # Authentification OAuth
│   ├── maintenance/            # Page maintenance
│   └── documents/tracking/     # Suivi public par code
├── services/                   # Couche API (Axios)
│   ├── axios.js                # Instance + intercepteurs
│   ├── auth/authServices.js    # Auth (login, logout, sessions)
│   ├── admin/adminServices.js  # Opérations admin
│   ├── admin/announcementService.js
│   ├── admin/infoNotesService.js
│   ├── admin/systemStatusService.js
│   └── students/index.js       # Opérations étudiant
├── context/                    # React Context
│   ├── userContext.js           # Auth + user state
│   └── sidebarContext.js        # Sidebar state
├── middlewares/                 # Helpers côté client
│   ├── protectedRoute.js       # Route protégée par droits
│   └── isAuthorizedShow.js     # Affichage conditionnel
├── components/                 # Composants partagés
├── utils/                      # Utilitaires (storage, dates)
├── constant/                   # Constantes (couleurs)
└── proxy.js                    # Middleware Next.js (auth guard)

Rôles et permissions

Droit Superadmin Admin Étudiant
Gestion modèles oui oui non
Génération unitaire oui oui non
Génération en lot oui non non
Notes d'information oui oui téléchargement
Migration étudiants oui non non
Mode maintenance oui non non
Annonces oui non non
Analytics / Audit oui non non
Sauvegarde BDD oui non non
Demande de documents non non oui
Réclamations non non oui

Diagrammes

Architecture globale

graph TB
    User[Utilisateur / Navigateur]
    Nginx["Nginx<br/>Reverse proxy + TLS"]
    Frontend["Frontend Next.js<br/>:3000"]
    Backend["Backend Django<br/>API REST"]
    DB["Base de données"]
    Azure["Microsoft Azure AD<br/>(OAuth SSO)"]

    User --> Nginx
    Nginx --> Frontend
    Frontend --> Backend
    Backend --> DB
    Frontend --> Azure
    Backend --> Azure

Flux d'authentification

sequenceDiagram
    participant User as Utilisateur
    participant FE as Frontend Next.js
    participant Azure as Microsoft OAuth
    participant BE as Backend Django
    participant Cookie as Cookie auth_token

    User->>FE: Clic "Connexion Microsoft"
    FE->>Azure: Redirect OAuth
    Azure->>FE: Callback /auth/callback?code=XXX
    FE->>BE: POST /auth/sign_in {code, session_state}
    BE->>Azure: Validation du token
    BE->>Cookie: Set auth_token (HttpOnly)
    BE-->>FE: {user, role, rights}
    FE->>FE: Stockage user dans localStorage
    FE->>FE: Redirection selon rôle (admin/student)

Flux de génération de document

sequenceDiagram
    participant Admin as Admin (Frontend)
    participant API as Backend API
    participant PDF as Moteur PDF

    Admin->>API: GET /documents/available-document-types?studentEmail=xxx
    API-->>Admin: {documents: {allowed_documents: [...]}}

    Admin->>API: POST /documents/admin/generate-for-student<br/>{studentEmail, docId}
    API->>PDF: Génération du PDF
    PDF-->>API: Blob PDF
    API-->>Admin: Content-Type: application/pdf
    Admin->>Admin: Téléchargement automatique

Flux de génération en lot

sequenceDiagram
    participant Admin as Superadmin
    participant API as Backend API
    participant PDF as Moteur PDF

    Admin->>API: POST /documents/admin/batch-generate<br/>{classe: "PGE1", doc_id: "certificat_scolarite"}
    API->>PDF: Génération N PDFs
    PDF-->>API: ZIP contenant tous les PDFs
    API-->>Admin: Content-Type: application/zip<br/>X-Batch-Total: 45<br/>X-Batch-Generated: 43<br/>X-Batch-Errors: 2
    Admin->>Admin: Téléchargement ZIP + résumé

Flux des notes d'information

sequenceDiagram
    participant Admin as Admin (Frontend)
    participant API as Backend API
    participant Student as Étudiant (Frontend)

    Admin->>API: POST /documents/admin/info-notes<br/>(multipart: title, pdf_file, target_classes)
    API-->>Admin: {id, title, targetClasses, isActive}

    Student->>API: GET /documents/available-document-types
    API-->>Student: {documents: {...}, infoNotes: [{id, title, ...}]}

    Student->>API: GET /documents/info-notes/:id/download
    API-->>Student: Content-Type: application/pdf (blob)
    Student->>Student: Téléchargement automatique

Docker

Dockerfile

Image multi-stage basée sur node:20-alpine avec pnpm. Les variables NEXT_PUBLIC_* sont injectées au build via ARG.

  • Stage builder : installation des dépendances + build Next.js
  • Stage runner : copie du build optimisé, exécution en production

docker-compose.prod.yml

services:
  frontend:
    image: ghcr.io/epitechafrik/epidocs-frontend:latest
    container_name: epidocs_frontend_container
    restart: unless-stopped
    ports:
      - "127.0.0.1:7012:3000"
    env_file:
      - .env
    environment:
      - NODE_ENV=production
      - NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
      - NEXT_PUBLIC_WEB_URL=${NEXT_PUBLIC_WEB_URL}
    networks:
      - epidocs-network
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

networks:
  epidocs-network:
    driver: bridge

Points importants :

  • Le port est bindé sur 127.0.0.1 uniquement (accessible via Nginx seulement)
  • Le healthcheck utilise wget (pas de curl sur Alpine par défaut)
  • Logging limité à 30 Mo (3 fichiers de 10 Mo)
  • Réseau bridge dédié epidocs-network

Routes de l'application

Routes publiques (sans authentification)

Route Description
/auth Page de connexion Microsoft OAuth
/auth/callback Callback OAuth
/noaccount Page "aucun compte"
/register Inscription étudiant en attente
/desactivated Compte désactivé
/documents/tracking/:id Suivi public d'un document
/maintenance Page de maintenance
/unauthorized Accès non autorisé

Routes admin (role: admin ou superadmin)

Route Description
/admin Dashboard principal
/admin/models Gestion des modèles de documents
/admin/students Gestion des étudiants
/admin/pending Validation des inscriptions
/admin/migration Migration de classe
/admin/info-requests Demandes de modification
/admin/dashboard Statistiques
/admin/documents Historique documentaire
/admin/admins Gestion des admins
/admin/generate-document Génération unitaire
/admin/batch-generate Génération en lot (superadmin)
/admin/info-notes Notes d'information (PDFs)
/admin/system-status Mode maintenance (superadmin)
/admin/announcements Annonces (superadmin)
/admin/analytics Analytics (superadmin)
/admin/audit-logs Logs d'audit (superadmin)
/admin/backup Sauvegarde BDD (superadmin)

Routes étudiant (role: student)

Route Description
/student Page principale + profil
/student/historiques Historique des demandes
/student/mes-demandes Demandes de modification
/student/reclamations Réclamations
/student/sessions Sessions actives

Fonctionnalités détaillées

Migration et validation du statut diplômé (/admin/migration)

La page migration permet deux opérations distinctes sur une sélection d'étudiants :

1. Migration de classe

Déplace les étudiants sélectionnés vers une autre section (ex. PGE1 → PGE2) avec choix de l'année scolaire.

2. Validation du statut diplômé

Marque les étudiants PGE3 ou PGE5 comme diplômés. Une fois diplômé, l'étudiant voit une Attestation de scolarité à la place du Certificat de scolarité.

Raccourcis de sélection rapide

Des boutons "TEK3 (PGE3)" et "MSc Pro 2 (PGE5)" permettent de sélectionner tous les étudiants d'une section en une action (requête avec pageSize=9999).

Détection automatique des groupes

Lors de l'ouverture du modal, le frontend analyse la sélection et constitue deux groupes à partir du champ section de chaque étudiant. Si la sélection est mixte, le modal affiche le résumé par groupe :

12 étudiant(s) seront marqués diplômés en PGE3 (TEK 3)
 8 étudiant(s) seront marqués diplômés en PGE5 (MSc Pro 2)

Requêtes parallèles

Deux appels sont effectués en parallèle (Promise.all) — un par groupe — vers POST /student/admin/set-graduation-status/ avec le champ section approprié. Les résultats sont fusionnés et affichés dans une vue unifiée.

Colonne "Statut diplôme" dans le tableau

  • Badge vert PGE3 ✓ si PGE3Status === "success"
  • Badge vert PGE5 ✓ si PGE5Status === "success"
  • Tiret si les deux statuts sont absents, vides ou null

Nommage des champs camelCase — deux endpoints différents

Les deux endpoints ne retournent pas les mêmes noms de champs :

  • GET /student/ (fiche étudiant) → pge3Status, pge5Status (tout en minuscules)
  • GET /student/admin/list/ (migration) → PGE3Status, PGE5Status (majuscules préservées)

Adapter le nom du champ selon l'endpoint utilisé dans le composant.

Reset

Un bouton reset (icône ✕, rouge) apparaît dès qu'un filtre ou une sélection est actif.

sequenceDiagram
    participant Admin as Admin (Frontend)
    participant API as Backend API

    Admin->>Admin: Clique "TEK3 (PGE3)"
    Admin->>API: GET /student/admin/list/?section=PGE3&pageSize=9999
    API-->>Admin: {results: [...tous les PGE3]}
    Admin->>Admin: Sélectionne tous les logins

    Admin->>Admin: Clique "Valider diplômé"
    Admin->>Admin: Groupe les logins par section (PGE3 / PGE5)

    par Appels parallèles
        Admin->>API: POST /student/admin/set-graduation-status/ {emails: [...], section: "PGE3"}
        Admin->>API: POST /student/admin/set-graduation-status/ {emails: [...], section: "PGE5"}
    end
    API-->>Admin: {updated, not_found_emails, wrong_section_emails}
    Admin->>Admin: Fusionne résultats et affiche le rapport

Fiche étudiant (/admin/students)

Le panneau de détail affiche toujours le champ Statut diplôme (endpoint /student/pge3Status) :

  • Badge PGE3 diplômé ✓ si pge3Status === "success"
  • Badge PGE5 diplômé ✓ si pge5Status === "success"
  • Tiret si aucun diplôme validé

Page modèles (/admin/models)

Spinner de chargement initial pendant la récupération des modèles, évitant le flash "Aucun document trouvé".

Intercepteurs Axios

L'instance Axios (src/services/axios.js) gère automatiquement :

  • Requêtes : Content-Type: application/json par défaut, withCredentials: true
  • Erreur 401 : redirection vers /auth (sauf si déjà sur la page auth)
  • Erreur 503 : mode maintenance — redirige les étudiants vers /maintenance, les admins/superadmins ne sont pas redirigés

Variables d'environnement

Variable Description Exemple
NEXT_PUBLIC_WEB_URL URL publique du frontend https://mydocs.epitools.bj
NEXT_PUBLIC_API_URL URL publique du backend API https://api-mydocs.epitools.bj
NODE_ENV Mode d'exécution production

Variables NEXT_PUBLIC_*

Les variables préfixées par NEXT_PUBLIC_ sont exposées au navigateur. Ne jamais y mettre de secrets. Ces variables sont injectées au build time (pas au runtime), donc un changement nécessite un rebuild de l'image Docker.

Pipeline CI/CD

Déclencheurs

  • Push sur main ou develop
  • Pull request vers main
  • Dispatch manuel

Jobs

graph LR
    CI["CI<br/>Lint + Build"] --> Docker["Build Docker<br/>Push GHCR"]
    Docker --> Deploy["Déploiement<br/>SCP + SSH"]
    Deploy --> Health["Health Check"]
  1. CI : checkout → setup pnpm → install → lint → build → upload artifact
  2. Build Docker : build image multi-stage → push ghcr.io/epitechafrik/epidocs-frontend:latest
  3. Deploy : SCP du docker-compose.prod.yml + .env → SSH pour pull et restart conteneur
  4. Health check : vérification que le conteneur répond sur le port 3000

Secrets GitHub nécessaires

Secret Description
NEXT_PUBLIC_API_URL URL du backend
NEXT_PUBLIC_WEB_URL URL du frontend
SSH_PRIVATE_KEY Clé SSH pour accès au VPS
VPS_IP Adresse IP du VPS
VPS_USER Utilisateur SSH (root)
ENV_FILE Contenu complet du fichier .env
GITHUB_TOKEN Token GHCR (auto-fourni)

Rollback

Procédure

# 1. Lister les images disponibles
docker images ghcr.io/epitechafrik/epidocs-frontend --format "table {{.Tag}}\t{{.CreatedAt}}"

# 2. Modifier le tag dans docker-compose.prod.yml
#    image: ghcr.io/epitechafrik/epidocs-frontend:sha-XXXXXXX

# 3. Redéployer
cd /root/projects/epidocs/epidocs-frontend
docker compose -f docker-compose.prod.yml down
docker compose -f docker-compose.prod.yml up -d

# 4. Vérifier
docker ps | grep epidocs_frontend
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:7012

Après le rollback

  1. Investiguer la cause sur main
  2. Pousser un correctif
  3. Le pipeline redéploiera automatiquement