0% ont trouvé ce document utile (0 vote)
116 vues17 pages

Gestion des Stagiaires: Code Source Web

exemple de développement

Transféré par

Ronis Nanda
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats TXT, PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
116 vues17 pages

Gestion des Stagiaires: Code Source Web

exemple de développement

Transféré par

Ronis Nanda
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats TXT, PDF, TXT ou lisez en ligne sur Scribd

## Application Web de Gestion des Stagiaires pour LYS EVENT

Voici un code source détaillé et complet d'une application web fonctionnelle de


gestion des stagiaires pour LYS EVENT, incluant l'inscription, la connexion, la
gestion des stagiaires, des tuteurs, et des tâches, ainsi que des styles CSS et du
code JavaScript pour une expérience utilisateur optimale.

**Structure du Projet:**

```
├── public
│ ├── css
│ │ ├── [Link]
│ │ └── [Link]
│ ├── images
│ │ ├── [Link]
│ │ └── [Link]
│ ├── js
│ │ ├── [Link]
│ │ └── [Link]
│ ├── [Link]
│ └── [Link]
├── [Link]
└── models
└── [Link]
```

**1. Backend ([Link]):**

```javascript
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');

// Importation des modèles de données


const Stagiaire = require('./models/stagiaire');
const Tuteur = require('./models/tuteur');
const Tache = require('./models/tache');

const app = express();

// Configuration de l'API
[Link]([Link]());
[Link]([Link]({ extended: true }));

// Configuration de la base de données MongoDB


[Link]('mongodb://localhost:27017/lys-event-stagiaires', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
[Link]('Connecté à la base de données MongoDB');
})
.catch((err) => {
[Link]('Erreur de connexion à la base de données MongoDB:', err);
});
// Route pour l'inscription
[Link]('/api/signup', async (req, res) => {
const { nom, prenom, email, password } = [Link];

// Vérification si l'email existe déjà


const existingUser = await [Link]({ email });
if (existingUser) {
return [Link](400).json({ message: 'L\'email est déjà utilisé.' });
}

// Hash du mot de passe


const hashedPassword = await [Link](password, 10);

// Création du nouveau stagiaire


const newStagiaire = new Stagiaire({
nom,
prenom,
email,
password: hashedPassword,
});

try {
await [Link]();
[Link](201).json({ message: 'Inscription réussie.' });
} catch (err) {
[Link]('Erreur lors de l\'inscription:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Route pour la connexion


[Link]('/api/login', async (req, res) => {
const { email, password } = [Link];

// Vérification si l'email existe


const user = await [Link]({ email });
if (!user) {
return [Link](401).json({ message: 'Email ou mot de passe incorrect.' });
}

// Vérification du mot de passe


const passwordMatch = await [Link](password, [Link]);
if (!passwordMatch) {
return [Link](401).json({ message: 'Email ou mot de passe incorrect.' });
}

// Génération du token JWT


const token = [Link]({ userId: user._id }, 'your_secret_key', { expiresIn: '1h'
});

[Link](200).json({ message: 'Connexion réussie.', token });


});

// Middleware pour l'authentification


function authenticateToken(req, res, next) {
const authHeader = [Link]['authorization'];
const token = authHeader && [Link](' ')[1];

if (token == null) {
return [Link](401).json({ message: 'Authentification requise.' });
}

[Link](token, 'your_secret_key', (err, user) => {


if (err) {
return [Link](403).json({ message: 'Token invalide.' });
}
[Link] = user;
next();
});
}

// Route pour la gestion des stagiaires (nécessite l'authentification)


[Link]('/api/stagiaires', authenticateToken, async (req, res) => {
try {
const stagiaires = await [Link]();
[Link](200).json(stagiaires);
} catch (err) {
[Link]('Erreur lors de la récupération des stagiaires:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Route pour la création d'un stagiaire (nécessite l'authentification)


[Link]('/api/stagiaires', authenticateToken, async (req, res) => {
const { nom, prenom, email, password, tuteur } = [Link];

// Vérification si l'email existe déjà


const existingStagiaire = await [Link]({ email });
if (existingStagiaire) {
return [Link](400).json({ message: 'L\'email est déjà utilisé.' });
}

// Hash du mot de passe


const hashedPassword = await [Link](password, 10);

// Création du nouveau stagiaire


const newStagiaire = new Stagiaire({
nom,
prenom,
email,
password: hashedPassword,
tuteur,
});

try {
await [Link]();
[Link](201).json({ message: 'Stagiaire créé avec succès.' });
} catch (err) {
[Link]('Erreur lors de la création du stagiaire:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Route pour la mise à jour d'un stagiaire (nécessite l'authentification)


[Link]('/api/stagiaires/:id', authenticateToken, async (req, res) => {
const { id } = [Link];
const { nom, prenom, email, tuteur } = [Link];
try {
const updatedStagiaire = await [Link](id, { nom, prenom,
email, tuteur });
[Link](200).json({ message: 'Stagiaire mis à jour avec succès.' });
} catch (err) {
[Link]('Erreur lors de la mise à jour du stagiaire:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Route pour la suppression d'un stagiaire (nécessite l'authentification)


[Link]('/api/stagiaires/:id', authenticateToken, async (req, res) => {
const { id } = [Link];

try {
await [Link](id);
[Link](200).json({ message: 'Stagiaire supprimé avec succès.' });
} catch (err) {
[Link]('Erreur lors de la suppression du stagiaire:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Route pour la gestion des tuteurs (nécessite l'authentification)


[Link]('/api/tuteurs', authenticateToken, async (req, res) => {
try {
const tuteurs = await [Link]();
[Link](200).json(tuteurs);
} catch (err) {
[Link]('Erreur lors de la récupération des tuteurs:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Route pour la création d'un tuteur (nécessite l'authentification)


[Link]('/api/tuteurs', authenticateToken, async (req, res) => {
const { nom, prenom, email } = [Link];

// Vérification si l'email existe déjà


const existingTuteur = await [Link]({ email });
if (existingTuteur) {
return [Link](400).json({ message: 'L\'email est déjà utilisé.' });
}

// Création du nouveau tuteur


const newTuteur = new Tuteur({
nom,
prenom,
email,
});

try {
await [Link]();
[Link](201).json({ message: 'Tuteur créé avec succès.' });
} catch (err) {
[Link]('Erreur lors de la création du tuteur:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});
// Route pour la mise à jour d'un tuteur (nécessite l'authentification)
[Link]('/api/tuteurs/:id', authenticateToken, async (req, res) => {
const { id } = [Link];
const { nom, prenom, email } = [Link];

try {
const updatedTuteur = await [Link](id, { nom, prenom,
email });
[Link](200).json({ message: 'Tuteur mis à jour avec succès.' });
} catch (err) {
[Link]('Erreur lors de la mise à jour du tuteur:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Route pour la suppression d'un tuteur (nécessite l'authentification)


[Link]('/api/tuteurs/:id', authenticateToken, async (req, res) => {
const { id } = [Link];

try {
await [Link](id);
[Link](200).json({ message: 'Tuteur supprimé avec succès.' });
} catch (err) {
[Link]('Erreur lors de la suppression du tuteur:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Route pour la gestion des tâches (nécessite l'authentification)


[Link]('/api/taches', authenticateToken, async (req, res) => {
try {
const taches = await [Link]();
[Link](200).json(taches);
} catch (err) {
[Link]('Erreur lors de la récupération des tâches:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Route pour la création d'une tâche (nécessite l'authentification)


[Link]('/api/taches', authenticateToken, async (req, res) => {
const { titre, description, deadline, stagiaire } = [Link];

// Création de la nouvelle tâche


const newTache = new Tache({
titre,
description,
deadline,
stagiaire,
});

try {
await [Link]();
[Link](201).json({ message: 'Tâche créée avec succès.' });
} catch (err) {
[Link]('Erreur lors de la création de la tâche:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Route pour la mise à jour d'une tâche (nécessite l'authentification)


[Link]('/api/taches/:id', authenticateToken, async (req, res) => {
const { id } = [Link];
const { titre, description, deadline, stagiaire } = [Link];

try {
const updatedTache = await [Link](id, { titre, description,
deadline, stagiaire });
[Link](200).json({ message: 'Tâche mise à jour avec succès.' });
} catch (err) {
[Link]('Erreur lors de la mise à jour de la tâche:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Route pour la suppression d'une tâche (nécessite l'authentification)


[Link]('/api/taches/:id', authenticateToken, async (req, res) => {
const { id } = [Link];

try {
await [Link](id);
[Link](200).json({ message: 'Tâche supprimée avec succès.' });
} catch (err) {
[Link]('Erreur lors de la suppression de la tâche:', err);
[Link](500).json({ message: 'Erreur serveur.' });
}
});

// Lancement du serveur
[Link](3000, () => {
[Link]('Serveur démarré sur le port 3000');
});

```

**2. Modèles de Données (models/[Link]):**

```javascript
const mongoose = require('mongoose');

const stagiaireSchema = new [Link]({


nom: { type: String, required: true },
prenom: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
tuteur: { type: [Link], ref: 'Tuteur' },
taches: [{ type: [Link], ref: 'Tache' }],
});

const tuteurSchema = new [Link]({


nom: { type: String, required: true },
prenom: { type: String, required: true },
email: { type: String, required: true, unique: true },
stagiaires: [{ type: [Link], ref: 'Stagiaire' }],
});

const tacheSchema = new [Link]({


titre: { type: String, required: true },
description: { type: String, required: true },
deadline: { type: Date, required: true },
stagiaire: { type: [Link], ref: 'Stagiaire' },
});

const Stagiaire = [Link]('Stagiaire', stagiaireSchema);


const Tuteur = [Link]('Tuteur', tuteurSchema);
const Tache = [Link]('Tache', tacheSchema);

[Link] = { Stagiaire, Tuteur, Tache };


```

**3. Frontend (public/[Link]):**

```html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gestion des Stagiaires - LYS EVENT</title>
<link rel="stylesheet" href="css/[Link]">
</head>
<body>
<header>
<div class="container">
<img src="images/[Link]" alt="Logo LYS EVENT">
<h1>Gestion des Stagiaires</h1>
</div>
</header>

<main>
<div class="container">
<!-- Contenu dynamique -->
<div id="app">
<!-- Contenu chargé par JavaScript -->
</div>
</div>
</main>

<footer>
<div class="container">
<p>© 2023 LYS EVENT</p>
</div>
</footer>

<script src="js/[Link]"></script>
</body>
</html>
```

**4. Frontend (public/[Link]):**

```html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Connexion - LYS EVENT</title>
<link rel="stylesheet" href="css/[Link]">
</head>
<body>
<div class="container">
<div class="login-form">
<img src="images/[Link]" alt="Logo LYS EVENT">
<h1>Connexion</h1>
<form id="login-form">
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="password">Mot de passe:</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">Se connecter</button>
</form>
<p>Pas encore de compte ? <a href="[Link]">S'inscrire</a></p>
</div>
</div>

<script src="js/[Link]"></script>
</body>
</html>
```

**5. Styles CSS (public/css/[Link]):**

```css
/* Styles généraux */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
}

header {
background-color: #333;
color: #fff;
padding: 20px 0;
}

.container {
max-width: 960px;
margin: 0 auto;
padding: 0 20px;
}

h1, h2 {
margin-top: 0;
}

/* Styles du contenu */
main {
padding: 20px 0;
}

.app-content {
background-color: #fff;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}

.table-container {
margin-top: 20px;
}

table {
width: 100%;
border-collapse: collapse;
}

th, td {
padding: 10px;
text-align: left;
border-bottom: 1px solid #ddd;
}

th {
background-color: #f0f0f0;
}

/* Styles du pied de page */


footer {
background-color: #333;
color: #fff;
padding: 10px 0;
text-align: center;
margin-top: 20px;
}

/* Styles de la page de connexion */


.login-form {
background-color: #fff;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
text-align: center;
}

.form-group {
margin-bottom: 15px;
}

input[type="email"], input[type="password"] {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
box-sizing: border-box;
}

button[type="submit"] {
background-color: #007bff;
color: #fff;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
}

button[type="submit"]:hover {
background-color: #0056b3;
}

/* Responsive Design */
@media (max-width: 768px) {
.container {
padding: 0 10px;
}
}
```

**6. Frontend (public/css/[Link]):**

```css
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}

.container {
background-color: #fff;
border-radius: 10px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
padding: 40px;
width: 400px;
}

.login-form img {
width: 100px;
margin-bottom: 20px;
}

h1 {
color: #333;
text-align: center;
margin-bottom: 30px;
}

.form-group {
margin-bottom: 15px;
}

label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}

input[type="email"], input[type="password"] {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
box-sizing: border-box;
}

button[type="submit"] {
background-color: #007bff;
color: #fff;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
width: 100%;
}

button[type="submit"]:hover {
background-color: #0056b3;
}

a {
color: #007bff;
text-decoration: none;
}

a:hover {
text-decoration: underline;
}
```

**7. Frontend (public/js/[Link]):**

```javascript
// Configuration de l'API
const apiUrl = '[Link] // Remplacez par l'URL de votre serveur

// Fonction pour afficher la liste des stagiaires


function displayStagiaires() {
fetch(`${apiUrl}/stagiaires`, {
headers: {
Authorization: `Bearer ${[Link]('token')}`,
},
})
.then(response => {
if (![Link]) {
throw new Error('Erreur lors de la récupération des stagiaires');
}
return [Link]();
})
.then(stagiaires => {
const stagiairesContainer = [Link]('stagiaires-list');
[Link] = '';
const table = [Link]('table');
const headerRow = [Link]();
[Link]().textContent = 'Nom';
[Link]().textContent = 'Prénom';
[Link]().textContent = 'Email';
[Link]().textContent = 'Tuteur';
[Link]().textContent = 'Actions';

[Link](stagiaire => {
const row = [Link]();
[Link]().textContent = [Link];
[Link]().textContent = [Link];
[Link]().textContent = [Link];
[Link]().textContent = [Link] ? [Link] + '
' + [Link] : 'Non attribué';
const actionsCell = [Link]();

// Bouton de modification
const editButton = [Link]('button');
[Link] = 'Modifier';
[Link]('click', () => {
// Fonction de modification du stagiaire
editStagiaire(stagiaire._id);
});
[Link](editButton);

// Bouton de suppression
const deleteButton = [Link]('button');
[Link] = 'Supprimer';
[Link]('click', () => {
// Fonction de suppression du stagiaire
deleteStagiaire(stagiaire._id);
});
[Link](deleteButton);
});

[Link](table);
})
.catch(error => {
[Link]('Erreur lors de l\'affichage des stagiaires:', error);
// Afficher un message d'erreur à l'utilisateur
});
}

// Fonction pour afficher le formulaire de création de stagiaire


function showCreateStagiaireForm() {
const stagiairesContainer = [Link]('stagiaires-list');
[Link] = '';

// Créer le formulaire
const form = [Link]('form');
[Link] = 'create-stagiaire-form';

// Champs du formulaire
const nomInput = [Link]('input');
[Link] = 'text';
[Link] = 'nom';
[Link] = 'nom';
[Link] = 'Nom';
const prenomInput = [Link]('input');
[Link] = 'text';
[Link] = 'prenom';
[Link] = 'prenom';
[Link] = 'Prénom';
const emailInput = [Link]('input');
[Link] = 'email';
[Link] = 'email';
[Link] = 'email';
[Link] = 'Email';
const passwordInput = [Link]('input');
[Link] = 'password';
[Link] = 'password';
[Link] = 'password';
[Link] = 'Mot de passe';
const tuteurSelect = [Link]('select');
[Link] = 'tuteur';
[Link] = 'tuteur';

// Charger la liste des tuteurs


fetch(`${apiUrl}/tuteurs`, {
headers: {
Authorization: `Bearer ${[Link]('token')}`,
},
})
.then(response => {
if (![Link]) {
throw new Error('Erreur lors de la récupération des tuteurs');
}
return [Link]();
})
.then(tuteurs => {
// Ajouter les tuteurs à la liste déroulante
[Link](tuteur => {
const option = [Link]('option');
[Link] = tuteur._id;
[Link] = [Link] + ' ' + [Link];
[Link](option);
});

// Ajouter les champs au formulaire


[Link](nomInput);
[Link](prenomInput);
[Link](emailInput);
[Link](passwordInput);
[Link](tuteurSelect);

// Bouton de soumission du formulaire


const submitButton = [Link]('button');
[Link] = 'submit';
[Link] = 'Créer';
[Link]('click', (event) => {
[Link]();
// Fonction de création du stagiaire
createStagiaire();
});
[Link](submitButton);
// Ajouter le formulaire au conteneur
[Link](form);
})
.catch(error => {
[Link]('Erreur lors du chargement des tuteurs:', error);
// Afficher un message d'erreur à l'utilisateur
});
}

// Fonction pour afficher le formulaire de modification de stagiaire


function editStagiaire(id) {
fetch(`${apiUrl}/stagiaires/${id}`, {
headers: {
Authorization: `Bearer ${[Link]('token')}`,
},
})
.then(response => {
if (![Link]) {
throw new Error('Erreur lors de la récupération du stagiaire');
}
return [Link]();
})
.then(stagiaire => {
const stagiairesContainer = [Link]('stagiaires-list');
[Link] = '';

// Créer le formulaire
const form = [Link]('form');
[Link] = 'edit-stagiaire-form';

// Champs du formulaire
const nomInput = [Link]('input');
[Link] = 'text';
[Link] = 'nom';
[Link] = 'nom';
[Link] = 'Nom';
[Link] = [Link];
const prenomInput = [Link]('input');
[Link] = 'text';
[Link] = 'prenom';
[Link] = 'prenom';
[Link] = 'Prénom';
[Link] = [Link];
const emailInput = [Link]('input');
[Link] = 'email';
[Link] = 'email';
[Link] = 'email';
[Link] = 'Email';
[Link] = [Link];
const tuteurSelect = [Link]('select');
[Link] = 'tuteur';
[Link] = 'tuteur';

// Charger la liste des tuteurs


fetch(`${apiUrl}/tuteurs`, {
headers: {
Authorization: `Bearer ${[Link]('token')}`,
},
})
.then(response => {
if (![Link]) {
throw new Error('Erreur lors de la récupération des tuteurs');
}
return [Link]();
})
.then(tuteurs => {
// Ajouter les tuteurs à la liste déroulante
[Link](tuteur => {
const option = [Link]('option');
[Link] = tuteur._id;
[Link] = [Link] + ' ' + [Link];
if (tuteur._id === [Link]) {
[Link] = true;
}
[Link](option);
});

// Ajouter les champs au formulaire


[Link](nomInput);
[Link](prenomInput);
[Link](emailInput);
[Link](tuteurSelect);

// Bouton de soumission du formulaire


const submitButton = [Link]('button');
[Link] = 'submit';
[Link] = 'Modifier';
[Link]('click', (event) => {
[Link]();
// Fonction de modification du stagiaire
updateStagiaire(id);
});
[Link](submitButton);

// Ajouter le formulaire au conteneur


[Link](form);
})
.catch(error => {
[Link]('Erreur lors du chargement des tuteurs:', error);
// Afficher un message d'erreur à l'utilisateur
});
})
.catch(error => {
[Link]('Erreur lors de la récupération du stagiaire:', error);
// Afficher un message d'erreur à l'utilisateur
});
}

// Fonction pour supprimer un stagiaire


function deleteStagiaire(id) {
fetch(`${apiUrl}/stagiaires/${id}`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${[Link]('token')}`,
},
})
.then(response => {
if (![Link]) {
throw new Error('Erreur lors de la suppression du stagiaire');
}
return [Link]();
})
.then(() => {
// Recharger la liste des stagiaires après la suppression
displayStagiaires();
})
.catch(error => {
[Link]('Erreur lors de la suppression du stagiaire:', error);
// Afficher un message d'erreur à l'utilisateur
});
}

// Fonction pour créer un nouveau stagiaire


function createStagiaire() {
const nom = [Link]('nom').value;
const prenom = [Link]('prenom').value;
const email = [Link]('email').value;
const password = [Link]('password').value;
const tuteur = [Link]('tuteur').value;

fetch(`${apiUrl}/stagiaires`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${[Link]('token')}`,
},
body: [Link]({ nom, prenom, email, password, tuteur }),
})
.then(response => {
if (![Link]) {
throw new Error('Erreur lors de la création du stagiaire');
}
return [Link]();
})
.then(() => {
// Recharger la liste des stagiaires après la création
displayStagiaires();
})
.catch(error => {
[Link]('Erreur lors de la création du stagiaire:', error);
// Afficher un message d'erreur à l'utilisateur
});
}

// Fonction pour mettre à jour un stagiaire


function updateStagiaire(id) {
const nom = [Link]('nom').value;
const prenom = [Link]('prenom').value;
const email = [Link]('email').value;
const tuteur = [Link]('tuteur').value;

fetch(`${apiUrl}/stagiaires/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${[Link]('token')}`,
},
body: [Link]({ nom, prenom, email, tuteur }),
})
.then(response => {
if (![Link]) {
throw new Error('Erreur lors de la mise à jour du stagiaire');
}
return [Link]();
})
.then(() => {
// Recharger la liste des stagiaires après la mise à jour
displayStagiaires();
})
.catch(error => {
[Link]('Erreur lors de la mise à jour du stagiaire:', error);
// Afficher un message d'erreur à l'

Vous aimerez peut-être aussi