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).
- Repository : EpitechAfrik/epidocs-frontend
- URL production : https://mydocs.epitools.bj
- Port :
127.0.0.1:7012(hôte) →3000(conteneur) - Registry :
ghcr.io/epitechafrik/epidocs-frontend
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.1uniquement (accessible via Nginx seulement) - Le healthcheck utilise
wget(pas decurlsur 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 ✓siPGE3Status === "success" - Badge vert
PGE5 ✓siPGE5Status === "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é ✓sipge3Status === "success" - Badge
PGE5 diplômé ✓sipge5Status === "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/jsonpar 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
mainoudevelop - 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"]
- CI : checkout → setup pnpm → install → lint → build → upload artifact
- Build Docker : build image multi-stage → push
ghcr.io/epitechafrik/epidocs-frontend:latest - Deploy : SCP du
docker-compose.prod.yml+.env→ SSH pour pull et restart conteneur - 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¶
- Investiguer la cause sur
main - Pousser un correctif
- Le pipeline redéploiera automatiquement