Refactor controllers and views for improved functionality and styling

This commit is contained in:
Noah 2026-06-08 16:51:09 +02:00
parent dc7d96d826
commit 3aad6d41af
7 changed files with 238 additions and 125 deletions

View file

@ -1,64 +1,92 @@
<?php <?php
function planning_afficher_ctrl() { function planning_afficher_ctrl() {
require('models/connection.php');
require('models/lecture_page_model.php');
require_once 'models/connection.php'; $c = connection();
require_once 'models/lecture_page_model.php';
$co = connection();
// Date : aujourd'hui par défaut, modifiable via ?date=YYYY-MM-DD
$date = $_GET['date'] ?? date('Y-m-d'); $date = $_GET['date'] ?? date('Y-m-d');
$date_precedente = date('Y-m-d', strtotime($date . ' -1 day'));
$date_suivante = date('Y-m-d', strtotime($date . ' +1 day'));
$sauveteurs = get_all_sauveteurs($co); // Tous les sauveteurs et leurs missions du jour
$missions = get_missions_by_date($co, $date); $sauveteurs = get_all_sauveteurs($c);
$missions = get_missions_by_date($c, $date);
// Couleurs // Couleurs par spécialité (numéro → couleur)
$couleurs = [ $couleurs = [
'Sauveteur disponible' => '#2ecc71', 1 => '#e74c3c', // Évacuation
'Sauveteur en approche de la cavité' => '#9b59b6', 2 => '#3498db', // ASV
'Sauveteur sous terre' => '#8B4513', 3 => '#f39c12', // Transmission
'Sauveteur équipe de gestion' => '#f1c40f', 4 => '#9b59b6', // Conseiller technique
"Sauveteur en mission à l'extérieur" => '#e67e22', 5 => '#2ecc71', // Gestion
'Sauveteur en repos' => '#3498db', 6 => '#8B4513', // Désobstruction
'Sauveteur en brancardage civière' => '#e74c3c', 7 => '#e91e63', // Médical
8 => '#00bcd4', // Ventilation
9 => '#95a5a6', // Pas de spécialité
]; ];
// Créneaux 8h - 20h (30 min) // Créneaux 8h-20h (toutes les 30 min)
$creneaux = []; $creneaux = [];
for ($min = 8 * 60; $min < 20 * 60; $min += 30) { for ($min = 8 * 60; $min < 20 * 60; $min += 30) {
$creneaux[] = sprintf('%02d:%02d', intdiv($min, 60), $min % 60); $creneaux[] = sprintf('%02d:%02d', intdiv($min, 60), $min % 60);
} }
// Index sauveteurs + grille vide // Index des sauveteurs + couleur par spécialité
$sauveteursById = []; $sauveteurs_index = [];
$grille = [];
foreach ($sauveteurs as $s) { foreach ($sauveteurs as $s) {
$sauveteursById[$s['ID']] = $s; $spe_num = (int) ($s['specialite'] ?? 0);
$grille[$s['ID']] = array_fill_keys($creneaux, ''); $s['couleur'] = $couleurs[$spe_num] ?? '#cccccc';
$sauveteurs_index[$s['ID']] = $s;
} }
// Remplissage des missions // Grille : sauveteur_id → créneau → [couleur, en_prepa]
$grille = [];
foreach ($sauveteurs as $s) {
$grille[$s['ID']] = [];
foreach ($creneaux as $c) {
$grille[$s['ID']][$c] = null;
}
}
// Remplissage de la grille avec les missions
foreach ($missions as $m) { foreach ($missions as $m) {
$id_sauv = $m['ID_Sauveteur'];
$id = $m['ID']; if (!isset($grille[$id_sauv])) continue;
if (!isset($grille[$id])) continue;
$specialite = $sauveteursById[$id]['Specialite'] ?? '';
$couleur = $couleurs[$specialite] ?? '#cccccc';
$debut = new DateTime($m['DateHeureDebut']); $debut = new DateTime($m['DateHeureDebut']);
$fin = new DateTime($m['DateHeureFin']); $fin = new DateTime($m['DateHeureFin']);
$en_prepa = (bool) $m['EnPrepa'];
foreach ($creneaux as $c) { foreach ($creneaux as $c) {
$debut_creneau = new DateTime($date . ' ' . $c . ':00');
$fin_creneau = (clone $debut_creneau)->modify('+30 minutes');
$start = new DateTime($date . ' ' . $c . ':00'); if ($debut < $fin_creneau && $fin > $debut_creneau) {
$end = (clone $start)->modify('+30 minutes'); $grille[$id_sauv][$c] = [
'couleur' => $sauveteurs_index[$id_sauv]['couleur'],
if ($debut < $end && $fin > $start) { 'en_prepa' => $en_prepa,
$grille[$id][$c] = $couleur; 'mission_id' => $m['ID'],
];
} }
} }
} }
// Légende des spécialités
$legendes = [
1 => 'Évacuation',
2 => 'ASV',
3 => 'Transmission',
4 => 'Conseiller technique',
5 => 'Gestion',
6 => 'Désobstruction',
7 => 'Médical',
8 => 'Ventilation',
9 => 'Pas de spécialité',
];
require('views/lecture_page.php');
planning_view($sauveteurs, $sauveteurs_index, $creneaux, $grille, $date, $date_precedente, $date_suivante, $couleurs, $legendes);
} }

View file

@ -1,45 +1,37 @@
<?php <?php
error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
ini_set('display_errors', 1);
require_once('models/connection.php');
require_once('models/operation_crud.php');
function operations_form_ctrl() { function operations_form_ctrl() {
// Appelle TA vue exacte
require('views/operations_view.php'); require('views/operations_view.php');
} }
function add_operation_write_ctrl() { function add_operation_write_ctrl() {
if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
// 1. On récupère les 3 champs de ton formulaire
$date_debut = $_POST['date_debut'];
$date_fin = $_POST['date_fin'];
$lieu = $_POST['lieu'];
// 2. On force les champs obligatoires de la BDD en arrière-plan
$en_prepa = 0;
$id_sauveteur = 1; // Par défaut
$id_statut = 1; // Par défaut
$id_utilisateur = 1; // Par défaut
$connex = connection();
// On envoie tout au modèle
$resultat = create_operation_crud($connex, $date_debut, $date_fin, $lieu, $en_prepa, $id_sauveteur, $id_statut, $id_utilisateur);
require('models/close_connection.php');
if ($resultat) {
$_SESSION['notification'] = "Opération enregistrée avec succès.";
} else {
$_SESSION['notification'] = "<span style='color:red;'>Erreur lors de l'enregistrement.</span>";
}
header('Location: index.php?route=operations'); header('Location: index.php?route=operations');
exit(); exit;
} }
$date_debut = $_POST['date_debut'];
$date_fin = $_POST['date_fin'];
$lieu = $_POST['lieu'];
// Valeurs par défaut pour les clés étrangères (à adapter quand l'auth sera active)
$en_prepa = 0;
$id_sauveteur = 1;
$id_statut = 1;
$id_utilisateur = 1;
require('models/connection.php');
$c = connection();
require('models/operation_crud.php');
$resultat = create_operation_crud($c, $date_debut, $date_fin, $lieu, $en_prepa, $id_sauveteur, $id_statut, $id_utilisateur);
if ($resultat) {
$_SESSION['notification'] = 'Opération enregistrée avec succès.';
} else {
$_SESSION['notification'] = 'Erreur lors de l\'enregistrement.';
}
header('Location: index.php?route=operations');
exit;
} }
?>

View file

@ -70,7 +70,7 @@ nav a.nav-right { margin-left: auto; }
/* CONTENU */ /* CONTENU */
article { article {
max-width: 1000px; max-width: 1100px;
margin: 20px auto; margin: 20px auto;
padding: 20px 30px; padding: 20px 30px;
background: #fff; background: #fff;
@ -101,6 +101,79 @@ table { width: 100%; border-collapse: collapse; margin: 10px 0; }
table th { background: #f8f6f0; color: #3b4a2e; padding: 10px; text-align: left; border-bottom: 2px solid #c49a3c; } table th { background: #f8f6f0; color: #3b4a2e; padding: 10px; text-align: left; border-bottom: 2px solid #c49a3c; }
table td { padding: 8px 10px; border-bottom: 1px solid #e8e2d2; } table td { padding: 8px 10px; border-bottom: 1px solid #e8e2d2; }
/* PLANNING */
.planning-nav {
margin-bottom: 15px;
display: flex;
justify-content: space-between;
align-items: center;
}
.planning-nav a {
color: #c49a3c;
text-decoration: none;
}
.planning-nav a:hover { text-decoration: underline; }
.planning-tableau {
overflow-x: auto;
margin-bottom: 20px;
}
.planning-tableau table { margin: 0; }
.planning-tableau th {
font-size: 0.7rem;
padding: 5px 3px;
text-align: center;
min-width: 35px;
writing-mode: horizontal-tb;
}
.planning-tableau td {
padding: 0;
height: 28px;
min-width: 35px;
border: 1px solid #e0dbce;
text-align: center;
font-size: 0.65rem;
vertical-align: middle;
}
.sauveteur-nom {
min-width: 150px;
padding: 4px 8px;
font-size: 0.85rem;
white-space: nowrap;
border-right: 2px solid #c49a3c;
}
.sauveteur-nom small { color: #8b7a5c; font-size: 0.7rem; }
.cell-actif { opacity: 0.85; }
.cell-prepa { opacity: 0.4; }
.planning-legende {
margin-top: 15px;
padding-top: 10px;
border-top: 1px solid #e8e2d2;
}
.planning-legende h3 { font-size: 0.9rem; margin-bottom: 8px; }
.legende-item { display: inline-block; margin-right: 15px; font-size: 0.8rem; }
.legende-couleur {
display: inline-block;
width: 14px;
height: 14px;
border-radius: 2px;
margin-right: 4px;
vertical-align: middle;
}
/* FORMULAIRES */ /* FORMULAIRES */
form label { display: inline-block; min-width: 140px; } form label { display: inline-block; min-width: 140px; }
form input[type="text"], form input[type="text"],

View file

@ -83,12 +83,8 @@
break; break;
case 'lecture': case 'lecture':
require('views/lecture_page.php');
planning_afficher_ctrl();
break;
case 'lecture_ctrl':
require('controllers/lecture_page_ctrl.php'); require('controllers/lecture_page_ctrl.php');
planning_afficher_ctrl();
break; break;
default: default:

View file

@ -1,26 +1,21 @@
<?php <?php
require('config/config.php');
// Récupère tous les sauveteurs // Récupère tous les sauveteurs
function get_all_sauveteurs(PDO $c): array { function get_all_sauveteurs(PDO $c): array {
$req = "SELECT ID, nom, prenom, specialite FROM Sauveteur ORDER BY Nom, Prenom"; $req = "SELECT ID, nom, prenom, specialite FROM Sauveteur ORDER BY nom, prenom";
return $c->query($req)->fetchAll(PDO::FETCH_ASSOC); return $c->query($req)->fetchAll(PDO::FETCH_ASSOC);
} }
// Récupère les missions d'une date // Récupère les missions d'une date donnée
function get_missions_by_date(PDO $c, string $date): array { function get_missions_by_date(PDO $c, string $date): array {
$req = " $req = "SELECT ID, DateHeureDebut, DateHeureFin, ID_Sauveteur, EnPrepa
SELECT ID, DateHeureDebut, DateHeureFin, ID_Sauveteur FROM Mission
FROM Mission WHERE DATE(DateHeureDebut) = :date
WHERE DATE(DateHeureDebut) = :date OR DATE(DateHeureFin) = :date
OR DATE(DateHeureFin) = :date ORDER BY DateHeureDebut";
";
$stmt = $c->prepare($req); $stmt = $c->prepare($req);
$stmt->bindValue(':date', $date); $stmt->bindValue(':date', $date);
$stmt->execute(); $stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC); return $stmt->fetchAll(PDO::FETCH_ASSOC);
} }

View file

@ -1,37 +1,68 @@
<?php <?php
error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED); function planning_view(array $sauveteurs, array $sauveteurs_index, array $creneaux, array $grille, string $date, string $date_prec, string $date_suiv, array $couleurs, array $legendes) {
ini_set('display_errors', 1); require('views/header.php');
function planning_view(array $sauveteurs, array $creneaux, array $grille, string $date) {
?> ?>
<!DOCTYPE html>
<html lang="fr">
<head><meta charset="UTF-8"><title>Planning</title></head>
<body>
<h2>Planning du <?= $date ?></h2> <h2>Planning du <?= date('d/m/Y', strtotime($date)) ?></h2>
<table border="1"> <!-- Navigation des dates -->
<tr> <nav class="planning-nav">
<th>Nom / Prénom</th> <a href="index.php?date=<?= $date_prec ?>">&larr; Jour précédent</a>
<?php foreach ($creneaux as $c): ?> <strong><?= date('d/m/Y', strtotime($date)) ?></strong>
<th><?= $c ?></th> <a href="index.php?date=<?= $date_suiv ?>">Jour suivant &rarr;</a>
</nav>
<!-- Tableau du planning -->
<div class="planning-tableau">
<table>
<thead>
<tr>
<th>Sauveteur</th>
<?php foreach ($creneaux as $c): ?>
<th><?= substr($c, 0, 5) ?></th>
<?php endforeach; ?>
</tr>
</thead>
<tbody>
<?php foreach ($sauveteurs as $s): ?>
<tr>
<td class="sauveteur-nom">
<?= htmlentities($s['nom'] . ' ' . $s['prenom']) ?>
<br><small><?= $legendes[(int) $s['specialite']] ?? 'Inconnu' ?></small>
</td>
<?php foreach ($creneaux as $c):
$cell = $grille[$s['ID']][$c] ?? null;
$bg = $cell ? $cell['couleur'] : '';
$class = '';
if ($cell) {
$class = $cell['en_prepa'] ? 'cell-prepa' : 'cell-actif';
}
?>
<td class="<?= $class ?>" style="<?= $bg ? 'background:' . $bg : '' ?>">
<?= $cell && $cell['en_prepa'] ? 'P' : '' ?>
</td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?> <?php endforeach; ?>
</tr> </tbody>
<?php foreach ($sauveteurs as $s): ?>
<tr>
<td><?= $s['Nom'] ?> <?= $s['Prenom'] ?></td>
<?php foreach ($creneaux as $c):
$couleur = $grille[$s['ID_Sauveteur']][$c];
?>
<td <?= $couleur ? 'bgcolor="' . $couleur . '"' : '' ?>></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</table> </table>
</div>
</body> <!-- Légende -->
</html> <div class="planning-legende">
<?php <h3>Légende : Spécialités</h3>
<?php foreach ($legendes as $num => $nom): ?>
<span class="legende-item">
<span class="legende-couleur" style="background:<?= $couleurs[$num] ?>"></span>
<?= $nom ?>
</span>
<?php endforeach; ?>
<span class="legende-item">
<span class="legende-couleur" style="background:#ccc; opacity:0.5;"></span>
En préparation (P)
</span>
</div>
<?php require('views/footer.php');
} }

View file

@ -1,17 +1,15 @@
<?php <?php
#ceci est la partie "view" de la page de login, le header et le footer ne sont pour l'instant pas actif
error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
ini_set('display_errors', 1);
function login_form_view(?string $route) { function login_form_view(?string $route) {
#require('header.php'); require('views/header.php');
echo '<h2>Page d\'authentification</h2>'; echo '<h2>Page d\'authentification</h2>';
echo '<p>Merci de vous authentifier pour accéder à cette fonctionnalité.</p>';
echo '<form action="index.php?route=auth&ask=' . $route . '" method="post">'; echo '<form action="index.php?route=auth&ask=' . $route . '" method="post">';
echo '<p>Login<input type="text" name="login" /></p>'; echo '<p><label>Login :</label> <input type="text" name="login"></p>';
echo '<p>Mot de passe<input type="passwd" name="password" /></p>'; echo '<p><label>Mot de passe :</label> <input type="password" name="password"></p>';
echo '<p><input type="submit" value="Valider" /></form>'; echo '<p><input type="submit" value="Valider"></p>';
echo '</form>';
#require('footer.php'); require('views/footer.php');
} }