Rapport_Gestion_Rendez_Vous
1.
Gestion des Rendez-vousApplication Web Full-Stack — Spring Boot 4 + React 19 + MySQ
2.
SommairePlan de la présentation
1. Présentation du projet
2. Architecture générale
3. Stack technique (Frontend)
4. Stack technique (Backend)
5. Structure du Frontend
6. Structure du Backend
7. Composants Frontend
8. Pages et CRUD
9. API REST — Endpoints
10. Modèle de données
11. Internationalisation (i18n)
3.
1. Présentation du projet4.
Présentation du projetApplication web de gestion de rendez-vous permettant de :
Créer, consulter, modifier et supprimer des rendez-vous (CRUD)
Visualiser des statistiques sur le tableau de bord (5 cartes)
Rechercher et filtrer les rendez-vous par nom et statut
Pagination des résultats (10 par page)
Support multilingue : Français, Anglais, Arabe (RTL)
Saisie de numéros de téléphone internationaux (27 pays)
Validation complète côté client et serveur
Interface responsive avec Bootstrap 5
5.
2. Architecture générale6.
Frontend (React 19)Backend (Spring Boot 4)
React (JSX)
Java 17 + Maven
Vite 8 (bundler)
Spring WebMVC
Bootstrap 5 (UI)
Spring Data JPA
Axios (HTTP)
Jakarta Validation
React Router DOM v7
SpringDoc OpenAPI
i18next (traduction)
Lombok
Port 5173
Port 8080
7.
Flux de communication1. L'utilisateur interagit avec l'interface React (localhost:5173)
2. React envoie des requêtes HTTP via Axios vers l'API REST
3. Le Controller Spring reçoit la requête et la valide
4. Le Service traite la logique métier
5. Le Repository interagit avec MySQL via JPA/Hibernate
6. La réponse retourne sous format JSON
7. React met à jour l'interface utilisateur
8.
3. Stack technique — Frontend9.
Technologies FrontendTechnologie
Version
React
19.2.6
Bibliothèque UI (c
Vite
8.0.12
Bundler rapide ave
Bootstrap
5.3.8
Framework CSS r
Axios
1.18.0
Client HTTP pour
React Router
7.18.0
Routing SPA (Bro
i18next
26.3.1
Internationalisation
ESLint
10.3.0
Linting avec flat co
Playwright
1.61.0
Tests E2E (Micros
10.
4. Stack technique — Backend11.
Technologies BackendTechnologie
Version
Spring Boot
4.1.1-SNAPSHOT
Framework d'appl
Java
17
Langage de progr
Maven
—
Gestionnaire de d
Spring Data JPA
—
Accès aux donnée
Hibernate
7.4.1
ORM avec auto-dé
MySQL
—
Base de données
H2
—
Base de données
Jackson 3
—
Sérialisation JSON
Lombok
—
Réduction du code
12.
5. Structure du Frontend13.
Arborescence src/components/
pages/
11 composants réutilisables
6 pages fonctionnelles
Navbar, StatCard, Pagination, PhoneInput, etc.
Dashboard, List, Add, Edit, Deta
14.
6. Structure du Backend15.
Package com.gestion.rendezvous_backendcontroller/
service/
RendezVousController (REST) — 5 endpoints
Interface + Impl (logique métier
16.
7. Composants Frontend17.
Composants réutilisablesRôle
Composant
Navbar
Barre de navigation + LanguageSwitcher
— (useLocation)
StatCard
Carte de statistique avec icône
title, value, icon, c
SearchBar
Barre de recherche par nom
onSearch, placeho
StatusFilter
Filtre dropdown par statut
value, onChange
Pagination
Navigation paginée
page, totalPages,
DeleteModal
Modal de confirmation suppression
show, appointmen
PhoneInput
Saisie téléphone international (27 pays)
value, onChange,
LanguageSwitcher
Bouton changement de langue (FR/EN/AR)
— (useTranslation
LoadingSpinner
Indicateur de chargement
—
18.
8. Pages et CRUD19.
Pages et fonctionnalitésPage
Route
CRUD
Dashboard
/
READ
5c
AppointmentList
/rendez-vous
READ
Pag
AddAppointment
/rendez-vous/ajouter
CREATE
For
EditAppointment
/rendez-vous/modifier/:id
UPDATE
Pre
AppointmentDetails
/rendez-vous/:id
READ
Dé
NotFound
*
—
Pag
20.
PhoneInput — Code clé// Extraction du préfixe (+212, +33, etc.)
function extractPrefix(val) {
if (!val || !val.startsWith('+')) return '+212';
const m = val.match(/^\+(\d{1,3})/);
return m ? '+' + m[1] : '+212';
}
// Combinaison préfixe + numéro local
const handlePrefix = (e) => onChange(e.target.value + local);
const handleLocal = (e) => {
const digits = e.target.value.replace(/\D/g, '');
onChange(prefix + digits);
};
// 27 pays disponibles : Maroc, France, USA, UK, etc.
<select value={prefix} onChange={handlePrefix}>
{COUNTRIES.map(c => <option value={c.code}>{c.label}</option>)}
21.
9. Internationalisation (i18n)22.
Multilingue — Français / English / العربية3 fichiers JSON de traduction : fr.json (170+ clés), en.json, ar.json
Détection automatique de la langue via localStorage et navigateur
Support RTL (Right-to-Left) pour l'arabe avec document.documentElement.dir
CSS personnalisé pour les ajustements RTL (navbar, input-group, dropdown)
Utilisation de react-i18next avec useTranslation() et t("key")
Bouton de changement de langue dans la barre de navigation
Persistance du choix dans localStorage
23.
Configuration i18nimport i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import fr from './locales/fr.json';
import en from './locales/en.json';
import ar from './locales/ar.json';
i18n.use(LanguageDetector).use(initReactI18next).init({
resources: { fr: { translation: fr }, en, ar },
fallbackLng: 'fr',
detection: { order: ['localStorage', 'navigator'], caches: ['localStorage'] },
interpolation: { escapeValue: false },
});
24.
10. API REST — Endpoints25.
EndpointsMéthode
URL
Paramètres
Réponse
GET
/api/rendezvous
?nomClient=&statut=&page=0&
size=10
Page<RendezVousResponse
GET
/api/rendezvous/{id}
—
RendezVousResponse
POST
/api/rendezvous
Body: RendezvousRequest
(JSON)
RendezVousResponse
PUT
/api/rendezvous/{id}
Body: RendezvousRequest
(JSON)
RendezVousResponse
DELETE
/api/rendezvous/{id}
—
—
26.
RendezVousController — Code clé@RestController
@RequestMapping("/api/rendezvous")
@RequiredArgsConstructor
public class RendezVousController {
private final RendezVousService service;
@GetMapping
public ResponseEntity<Page<RendezVousResponse>> getAll(
@RequestParam(required=false) String nomClient,
@RequestParam(required=false) String statut,
@PageableDefault(size=10, sort="dateRendezVous", direction=DESC) Pageable p) {
return ResponseEntity.ok(service.getAllRendezVous(nomClient, statut, p));
}
@PostMapping
public ResponseEntity<RendezVousResponse> create(
@Valid @RequestBody RendezVousRequest request) {
27.
11. Modèle de données28.
Entity RendezVous@Entity @Table(name = "rendez_vous")
@Data @NoArgsConstructor @AllArgsConstructor @Builder
public class RendezVous {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank @Column(nullable = false)
private String nomClient;
@NotBlank @Column(nullable = false)
private String telephone;
@NotNull @FutureOrPresent @Column(nullable = false)
private LocalDate dateRendezVous;
@NotNull @Column(nullable = false)
private LocalTime heureRendezVous;
29.
Enum + DTOStatutRendezVous
EN_ATTENTE (En attente) — Valeur par défaut
CONFIRME (Confirmé)
ANNULE (Annulé)
TERMINE (Terminé)
30.
RendezVousRequest (Record)public record RendezVousRequest(
@NotBlank String nomClient,
@NotBlank @Pattern(regexp = "^\\+?\\d{7,15}$") String telephone,
@NotNull @FutureOrPresent LocalDate dateRendezVous,
@NotNull LocalTime heureRendezVous,
@NotNull StatutRendezVous statut
) {}
31.
12. Gestion des erreurs32.
GlobalExceptionHandler@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<?> handleNotFound(ResourceNotFoundException ex) {
return buildResponse(HttpStatus.NOT_FOUND, ex.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidation(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
for (FieldError fe : ex.getBindingResult().getFieldErrors())
errors.put(fe.getField(), fe.getDefaultMessage());
return ResponseEntity.badRequest().body(Map.of(
"error", "Validation échouée", "details", errors));
}
33.
Gestion des erreurs côté FrontendLes erreurs backend sont affichées via ErrorAlert :
Validation échouée → champs spécifiques affichés
Rendez-vous introuvable → message clair à l'utilisateur
Erreur réseau → message de fallback explicite
Le composant ErrorAlert est dismissible (bouton fermer)
34.
Service Axios — Intercepteurconst api = axios.create({
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:8080/api',
headers: { 'Content-Type': 'application/json' },
});
// Intercepteur : convertit HH:mm → HH:mm:ss pour LocalTime
api.interceptors.request.use((config) => {
if (config.data?.heureRendezVous?.length === 5)
config.data.heureRendezVous += ':00';
return config;
});
export const rendezvousService = {
getAll:
(params) => api.get('/rendezvous', { params }),
getById: (id) =>
api.get(\`/rendezvous/\$\{id}\`),
create:
(data) =>
api.post('/rendezvous', data),
update:
(id, data) => api.put(\`/rendezvous/\$\{id}\`, data),
35.
13. Validation36.
Côté Frontend (React)Côté Backend (Spring)
nomClient : requis (trim)
@NotBlank sur nomClient, telep
telephone : regex + 4 chiffres min
@Pattern regex téléphone intern
dateRendezVous : requis (type=date)
@NotNull + @FutureOrPresent
heureRendezVous : requis (type=time)
@NotNull time + statut
Messages d'erreur localisés (FR/EN/AR)
Validation échouée → 400 + dét
37.
14. Tests38.
Backend (Maven)Frontend E2E (Playwright)
mvnw test → 1 test (H2)
Microsoft Edge + chrominum
RendezvousBackendApplicationTests
Test complet du CRUD
Contexte Spring Boot chargé
Vérification Dashboard
Validation des dépendances
Test PhoneInput + i18n
39.
Tests E2E — RésultatsScénario
Dashboard
Liste
Création
Détails
Modification
PhoneInput
Langue
Filtre
Suppression
40.
15. Configuration41.
Profiles Spring Bootapplication.properties — Profile: prod
spring.application.name=rendezvous-backend
spring.profiles.active=prod
spring.jpa.open-in-view=false
42.
application-prod.properties# MySQL
spring.datasource.url=jdbc:mysql://localhost:3306/rendezvous-backend
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
server.port=8080
43.
16. Conclusion44.
Bilan du projet✓ Application Full-Stack fonctionnelle avec React 19 + Spring Boot 4
✓ CRUD complet avec validation, pagination, recherche et filtres
✓ Interface responsive avec Bootstrap 5 (mobile-first)
✓ Support multilingue Français / Anglais / Arabe (RTL)
✓ Saisie téléphone internationale avec sélecteur de pays
✓ Documentation API avec Swagger UI
✓ Tests E2E automatisés avec Playwright + Microsoft Edge
✓ Architecture propre (Clean Architecture) : Controller → Service → Repository
✓ Base de données MySQL en production, H2 pour les tests
45.
Merci pour votre attentionGestion des Rendez-vous — Projet Universitaire
React 19 + Spring Boot 4 + MySQL + Bootstrap 5 + i18n