Files
webval/gerer_evaluation.php

814 lines
29 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* GESTION DES ÉVALUATIONS - VERSION ADAPTÉE
* Compatible avec le schéma existant de Nicolas
* Interface enseignant pour gérer les paramètres et accès d'une évaluation
*/
require_once 'config/database.php';
require_once 'config/session.php';
// Session déjà démarrée dans session.php
// Vérification connexion enseignant
if (!isset($_SESSION['user_id']) || $_SESSION['id_type'] != 1) {
header('Location: login.php');
exit();
}
$db = Database::getInstance()->getConnection();
$id_evaluation = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($id_evaluation <= 0) {
header('Location: enseignant/dashboard.php');
exit();
}
// === TRAITEMENT DES ACTIONS ===
$message = '';
$message_type = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
try {
switch ($action) {
case 'toggle_active':
$nouveau_statut = (int)$_POST['actif'];
$stmt = $db->prepare("UPDATE evaluations SET actif = ? WHERE id_evaluation = ?");
$stmt->execute([$nouveau_statut, $id_evaluation]);
$message = "Statut modifié avec succès";
$message_type = "success";
break;
case 'update_params':
$duree = (int)$_POST['duree_minutes'];
$tentatives = (int)$_POST['tentatives_max'];
$correction = (int)$_POST['afficher_correction'];
$melanger = (int)$_POST['melanger_questions'];
$stmt = $db->prepare("
UPDATE evaluations
SET duree_minutes = ?, tentatives_max = ?,
afficher_correction = ?, melanger_questions = ?
WHERE id_evaluation = ?
");
$stmt->execute([$duree, $tentatives, $correction, $melanger, $id_evaluation]);
$message = "Paramètres mis à jour";
$message_type = "success";
break;
case 'update_acces':
$id_classe = (int)$_POST['id_classe'];
$date_debut = $_POST['date_debut'];
$date_fin = $_POST['date_fin'];
$actif_acces = (int)$_POST['actif'];
$stmt = $db->prepare("
UPDATE acces_evaluations
SET date_debut = ?, date_fin = ?, actif = ?
WHERE id_evaluation = ? AND id_classe = ?
");
$stmt->execute([$date_debut, $date_fin, $actif_acces, $id_evaluation, $id_classe]);
$message = "Accès classe mis à jour";
$message_type = "success";
break;
case 'add_acces':
$id_classe = (int)$_POST['id_classe_new'];
$date_debut = $_POST['date_debut_new'];
$date_fin = $_POST['date_fin_new'];
// Vérifier si l'accès n'existe pas déjà
$check = $db->prepare("
SELECT COUNT(*) FROM acces_evaluations
WHERE id_evaluation = ? AND id_classe = ?
");
$check->execute([$id_evaluation, $id_classe]);
if ($check->fetchColumn() == 0) {
$stmt = $db->prepare("
INSERT INTO acces_evaluations
(id_evaluation, id_classe, date_debut, date_fin, actif)
VALUES (?, ?, ?, ?, 1)
");
$stmt->execute([$id_evaluation, $id_classe, $date_debut, $date_fin]);
$message = "Accès classe ajouté";
$message_type = "success";
} else {
$message = "Cette classe a déjà accès à l'évaluation";
$message_type = "warning";
}
break;
case 'delete_acces':
$id_classe = (int)$_POST['id_classe'];
$stmt = $db->prepare("
DELETE FROM acces_evaluations
WHERE id_evaluation = ? AND id_classe = ?
");
$stmt->execute([$id_evaluation, $id_classe]);
$message = "Accès classe supprimé";
$message_type = "success";
break;
case 'reset_tentatives':
$stmt = $db->prepare("
DELETE FROM tentatives_eleves
WHERE id_evaluation = ?
");
$stmt->execute([$id_evaluation]);
$message = "Toutes les tentatives ont été réinitialisées";
$message_type = "success";
break;
case 'delete_evaluation':
// Supprimer en cascade
$stmt = $db->prepare("DELETE FROM evaluations WHERE id_evaluation = ?");
$stmt->execute([$id_evaluation]);
header('Location: enseignant/dashboard.php?msg=eval_deleted');
exit();
break;
}
} catch (PDOException $e) {
$message = "Erreur : " . $e->getMessage();
$message_type = "error";
}
}
// === RÉCUPÉRATION DES DONNÉES ===
// Informations évaluation
$stmt = $db->prepare("
SELECT e.*,
COUNT(DISTINCT q.id_question) as nb_questions
FROM evaluations e
LEFT JOIN questions q ON e.id_evaluation = q.id_evaluation
WHERE e.id_evaluation = ?
GROUP BY e.id_evaluation
");
$stmt->execute([$id_evaluation]);
$evaluation = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$evaluation) {
header('Location: enseignant/dashboard.php');
exit();
}
// Statistiques
$stmt = $db->prepare("
SELECT
COUNT(DISTINCT t.id_eleve) as nb_eleves_participes,
COUNT(t.id_tentative) as nb_tentatives_total,
SUM(CASE WHEN t.statut = 'terminee' THEN 1 ELSE 0 END) as nb_terminees,
AVG(CASE WHEN t.statut = 'terminee' THEN t.note ELSE NULL END) as moyenne
FROM tentatives_eleves t
WHERE t.id_evaluation = ?
");
$stmt->execute([$id_evaluation]);
$stats = $stmt->fetch(PDO::FETCH_ASSOC);
// Accès par classe
$stmt = $db->prepare("
SELECT a.*, c.nom_classe
FROM acces_evaluations a
JOIN classes c ON a.id_classe = c.id_classe
WHERE a.id_evaluation = ?
ORDER BY c.nom_classe
");
$stmt->execute([$id_evaluation]);
$acces_classes = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Classes disponibles pour ajout
$stmt = $db->prepare("
SELECT c.id_classe, c.nom_classe
FROM classes c
WHERE c.id_classe NOT IN (
SELECT id_classe FROM acces_evaluations
WHERE id_evaluation = ?
)
ORDER BY c.nom_classe
");
$stmt->execute([$id_evaluation]);
$classes_disponibles = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gérer : <?php echo htmlspecialchars($evaluation['titre']); ?></title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.header {
background: white;
padding: 25px;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
margin-bottom: 20px;
}
.header h1 {
color: #667eea;
font-size: 24px;
margin-bottom: 15px;
}
.eval-info {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
margin-top: 15px;
}
.info-box {
background: #f8f9fa;
padding: 12px;
border-radius: 8px;
border-left: 4px solid #667eea;
}
.info-label {
font-size: 12px;
color: #666;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.info-value {
font-size: 18px;
font-weight: bold;
color: #333;
margin-top: 5px;
}
.card {
background: white;
padding: 25px;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
margin-bottom: 20px;
}
.card h2 {
color: #667eea;
font-size: 20px;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid #f0f0f0;
}
.toggle-container {
display: flex;
align-items: center;
justify-content: space-between;
padding: 15px;
background: #f8f9fa;
border-radius: 10px;
margin-bottom: 20px;
}
.toggle-label {
font-size: 16px;
font-weight: 600;
color: #333;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .4s;
border-radius: 34px;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
transition: .4s;
border-radius: 50%;
}
input:checked + .slider {
background-color: #4CAF50;
}
input:checked + .slider:before {
transform: translateX(26px);
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 20px;
}
.stat-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
border-radius: 10px;
text-align: center;
}
.stat-number {
font-size: 32px;
font-weight: bold;
margin-bottom: 5px;
}
.stat-label {
font-size: 14px;
opacity: 0.9;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
font-weight: 600;
color: #333;
margin-bottom: 8px;
font-size: 14px;
}
.form-group input,
.form-group select {
width: 100%;
padding: 12px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 14px;
transition: border-color 0.3s;
}
.form-group input:focus,
.form-group select:focus {
outline: none;
border-color: #667eea;
}
.form-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
.btn {
padding: 12px 24px;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
text-decoration: none;
display: inline-block;
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.btn-success {
background: #4CAF50;
color: white;
}
.btn-danger {
background: #f44336;
color: white;
}
.btn-warning {
background: #ff9800;
color: white;
}
.btn-secondary {
background: #6c757d;
color: white;
}
.btn-group {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 20px;
}
.acces-table {
width: 100%;
border-collapse: collapse;
margin-top: 15px;
}
.acces-table th,
.acces-table td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #e0e0e0;
}
.acces-table th {
background: #f8f9fa;
font-weight: 600;
color: #667eea;
}
.acces-table tr:hover {
background: #f8f9fa;
}
.status-badge {
display: inline-block;
padding: 4px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
}
.status-active {
background: #d4edda;
color: #155724;
}
.status-inactive {
background: #f8d7da;
color: #721c24;
}
.message {
padding: 15px 20px;
border-radius: 8px;
margin-bottom: 20px;
font-weight: 500;
}
.message-success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.message-error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.message-warning {
background: #fff3cd;
color: #856404;
border: 1px solid #ffeeba;
}
.back-link {
display: inline-block;
margin-bottom: 20px;
color: white;
text-decoration: none;
font-weight: 600;
padding: 10px 20px;
background: rgba(255,255,255,0.2);
border-radius: 8px;
transition: background 0.3s;
}
.back-link:hover {
background: rgba(255,255,255,0.3);
}
@media (max-width: 768px) {
body {
padding: 10px;
}
.eval-info {
grid-template-columns: 1fr;
}
.stats-grid {
grid-template-columns: 1fr;
}
.form-row {
grid-template-columns: 1fr;
}
.acces-table {
font-size: 12px;
}
.acces-table th,
.acces-table td {
padding: 8px;
}
.btn-group {
flex-direction: column;
}
.btn {
width: 100%;
}
}
</style>
</head>
<body>
<div class="container">
<a href="enseignant/dashboard.php" class="back-link">← Retour au tableau de bord</a>
<?php if ($message): ?>
<div class="message message-<?php echo $message_type; ?>">
<?php echo htmlspecialchars($message); ?>
</div>
<?php endif; ?>
<!-- En-tête avec informations évaluation -->
<div class="header">
<h1><?php echo htmlspecialchars($evaluation['titre']); ?></h1>
<div class="eval-info">
<div class="info-box">
<div class="info-label">Type</div>
<div class="info-value"><?php echo ucfirst($evaluation['type']); ?></div>
</div>
<div class="info-box">
<div class="info-label">Durée</div>
<div class="info-value"><?php echo $evaluation['duree_minutes']; ?> min</div>
</div>
<div class="info-box">
<div class="info-label">Barème</div>
<div class="info-value"><?php echo $evaluation['note_totale']; ?> pts</div>
</div>
<div class="info-box">
<div class="info-label">Questions</div>
<div class="info-value"><?php echo $evaluation['nb_questions']; ?></div>
</div>
</div>
</div>
<!-- Activation globale -->
<div class="card">
<div class="toggle-container">
<span class="toggle-label">
Évaluation <?php echo $evaluation['actif'] ? 'ACTIVE' : 'INACTIVE'; ?>
</span>
<form method="POST" style="margin: 0;">
<input type="hidden" name="action" value="toggle_active">
<input type="hidden" name="actif" value="<?php echo $evaluation['actif'] ? 0 : 1; ?>">
<label class="switch">
<input type="checkbox" <?php echo $evaluation['actif'] ? 'checked' : ''; ?>
onchange="this.form.submit()">
<span class="slider"></span>
</label>
</form>
</div>
</div>
<!-- Statistiques -->
<div class="card">
<h2>📊 Statistiques</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-number"><?php echo $stats['nb_eleves_participes'] ?? 0; ?></div>
<div class="stat-label">Élèves participants</div>
</div>
<div class="stat-card">
<div class="stat-number"><?php echo $stats['nb_tentatives_total'] ?? 0; ?></div>
<div class="stat-label">Tentatives totales</div>
</div>
<div class="stat-card">
<div class="stat-number"><?php echo $stats['nb_terminees'] ?? 0; ?></div>
<div class="stat-label">Évaluations terminées</div>
</div>
<div class="stat-card">
<div class="stat-number">
<?php
$moyenne = $stats['moyenne'] ?? 0;
echo $moyenne > 0 ? number_format($moyenne, 1) . '/20' : 'N/A';
?>
</div>
<div class="stat-label">Moyenne générale</div>
</div>
</div>
</div>
<!-- Paramètres -->
<div class="card">
<h2>⚙️ Paramètres de l'évaluation</h2>
<form method="POST">
<input type="hidden" name="action" value="update_params">
<div class="form-row">
<div class="form-group">
<label>Durée (minutes)</label>
<input type="number" name="duree_minutes" min="1" max="240"
value="<?php echo $evaluation['duree_minutes']; ?>" required>
</div>
<div class="form-group">
<label>Tentatives maximum</label>
<input type="number" name="tentatives_max" min="1" max="10"
value="<?php echo $evaluation['tentatives_max']; ?>" required>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label>Afficher la correction</label>
<select name="afficher_correction">
<option value="1" <?php echo $evaluation['afficher_correction'] ? 'selected' : ''; ?>>Oui</option>
<option value="0" <?php echo !$evaluation['afficher_correction'] ? 'selected' : ''; ?>>Non</option>
</select>
</div>
<div class="form-group">
<label>Mélanger les questions</label>
<select name="melanger_questions">
<option value="1" <?php echo $evaluation['melanger_questions'] ? 'selected' : ''; ?>>Oui</option>
<option value="0" <?php echo !$evaluation['melanger_questions'] ? 'selected' : ''; ?>>Non</option>
</select>
</div>
</div>
<button type="submit" class="btn btn-primary">💾 Enregistrer les modifications</button>
</form>
</div>
<!-- Gestion des accès par classe -->
<div class="card">
<h2>🎓 Accès par classe</h2>
<?php if (count($acces_classes) > 0): ?>
<table class="acces-table">
<thead>
<tr>
<th>Classe</th>
<th>Date début</th>
<th>Date fin</th>
<th>Statut</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($acces_classes as $acces): ?>
<tr>
<td><strong><?php echo htmlspecialchars($acces['nom_classe']); ?></strong></td>
<td>
<form method="POST" style="display: inline;">
<input type="hidden" name="action" value="update_acces">
<input type="hidden" name="id_classe" value="<?php echo $acces['id_classe']; ?>">
<input type="datetime-local" name="date_debut"
value="<?php echo date('Y-m-d\TH:i', strtotime($acces['date_debut'])); ?>"
onchange="this.form.submit()" style="width: auto; padding: 5px;">
<input type="hidden" name="date_fin" value="<?php echo $acces['date_fin']; ?>">
<input type="hidden" name="actif" value="<?php echo $acces['actif']; ?>">
</form>
</td>
<td>
<form method="POST" style="display: inline;">
<input type="hidden" name="action" value="update_acces">
<input type="hidden" name="id_classe" value="<?php echo $acces['id_classe']; ?>">
<input type="hidden" name="date_debut" value="<?php echo $acces['date_debut']; ?>">
<input type="datetime-local" name="date_fin"
value="<?php echo date('Y-m-d\TH:i', strtotime($acces['date_fin'])); ?>"
onchange="this.form.submit()" style="width: auto; padding: 5px;">
<input type="hidden" name="actif" value="<?php echo $acces['actif']; ?>">
</form>
</td>
<td>
<span class="status-badge status-<?php echo $acces['actif'] ? 'active' : 'inactive'; ?>">
<?php echo $acces['actif'] ? 'Actif' : 'Inactif'; ?>
</span>
</td>
<td>
<form method="POST" style="display: inline;">
<input type="hidden" name="action" value="update_acces">
<input type="hidden" name="id_classe" value="<?php echo $acces['id_classe']; ?>">
<input type="hidden" name="date_debut" value="<?php echo $acces['date_debut']; ?>">
<input type="hidden" name="date_fin" value="<?php echo $acces['date_fin']; ?>">
<input type="hidden" name="actif" value="<?php echo $acces['actif'] ? 0 : 1; ?>">
<button type="submit" class="btn btn-<?php echo $acces['actif'] ? 'warning' : 'success'; ?>"
style="padding: 6px 12px; font-size: 12px;">
<?php echo $acces['actif'] ? 'Désactiver' : 'Activer'; ?>
</button>
</form>
<form method="POST" style="display: inline;"
onsubmit="return confirm('Supprimer l\'accès pour cette classe ?');">
<input type="hidden" name="action" value="delete_acces">
<input type="hidden" name="id_classe" value="<?php echo $acces['id_classe']; ?>">
<button type="submit" class="btn btn-danger" style="padding: 6px 12px; font-size: 12px;">
❌ Supprimer
</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<p style="color: #666; font-style: italic;">Aucune classe n'a accès à cette évaluation.</p>
<?php endif; ?>
<!-- Ajouter une classe -->
<?php if (count($classes_disponibles) > 0): ?>
<div style="margin-top: 30px; padding-top: 20px; border-top: 2px solid #f0f0f0;">
<h3 style="color: #667eea; font-size: 16px; margin-bottom: 15px;"> Ajouter une classe</h3>
<form method="POST">
<input type="hidden" name="action" value="add_acces">
<div class="form-row">
<div class="form-group">
<label>Classe</label>
<select name="id_classe_new" required>
<option value="">-- Sélectionner --</option>
<?php foreach ($classes_disponibles as $classe): ?>
<option value="<?php echo $classe['id_classe']; ?>">
<?php echo htmlspecialchars($classe['nom_classe']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label>Date début</label>
<input type="datetime-local" name="date_debut_new" required>
</div>
<div class="form-group">
<label>Date fin</label>
<input type="datetime-local" name="date_fin_new" required>
</div>
</div>
<button type="submit" class="btn btn-success">✅ Ajouter l'accès</button>
</form>
</div>
<?php endif; ?>
</div>
<!-- Actions -->
<div class="card">
<h2>🔧 Actions</h2>
<div class="btn-group">
<form method="POST" style="margin: 0;"
onsubmit="return confirm('Réinitialiser TOUTES les tentatives ? Cette action est irréversible.');">
<input type="hidden" name="action" value="reset_tentatives">
<button type="submit" class="btn btn-warning">
🔄 Réinitialiser les tentatives
</button>
</form>
<form method="POST" style="margin: 0;"
onsubmit="return confirm('Supprimer cette évaluation ? Cette action est irréversible.');">
<input type="hidden" name="action" value="delete_evaluation">
<button type="submit" class="btn btn-danger">
🗑️ Supprimer l'évaluation
</button>
</form>
</div>
</div>
</div>
</body>
</html>