713.23K

Rapport_Gestion_Rendez_Vous

1.

Gestion des Rendez-vous
Application Web Full-Stack — Spring Boot 4 + React 19 + MySQ

2.

Sommaire
Plan 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 projet

4.

Présentation du projet
Application 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érale

6.

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 communication
1. 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 — Frontend

9.

Technologies Frontend
Technologie
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 — Backend

11.

Technologies Backend
Technologie
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 Frontend

13.

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 Backend

15.

Package com.gestion.rendezvous_backend
controller/
service/
RendezVousController (REST) — 5 endpoints
Interface + Impl (logique métier

16.

7. Composants Frontend

17.

Composants réutilisables
Rô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 CRUD

19.

Pages et fonctionnalités
Page
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

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 i18n
import 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 — Endpoints

25.

Endpoints
Mé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ées

28.

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 + DTO
StatutRendezVous
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 erreurs

32.

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é Frontend
Les 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 — Intercepteur
const 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. Validation

36.

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. Tests

38.

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ésultats
Scénario
Dashboard
Liste
Création
Détails
Modification
PhoneInput
Langue
Filtre
Suppression

40.

15. Configuration

41.

Profiles Spring Boot
application.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. Conclusion

44.

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 attention
Gestion des Rendez-vous — Projet Universitaire
React 19 + Spring Boot 4 + MySQL + Bootstrap 5 + i18n
English     Русский Rules