prepare(" SELECT can_edit_slots FROM secretaire_praticien WHERE secretaire_user_id = :u AND praticien_id = :p AND is_active = 1 LIMIT 1 "); $st->execute([ 'u' => $compteId, 'p' => $praticien_id, ]); $pivot = $st->fetch(PDO::FETCH_ASSOC); if (! $pivot || (int) $pivot['can_edit_slots'] !== 1) { http_response_code(403); exit('Forbidden'); } // Récup nom praticien pour le titre $st = $pdo->prepare("SELECT prenom, nom, duree_rdv FROM praticien WHERE id = ? LIMIT 1"); $st->execute([$praticien_id]); $praticien = $st->fetch(PDO::FETCH_ASSOC); if (! $praticien) { http_response_code(404); exit('Praticien introuvable'); } $currentPraticienName = trim(((string) ($praticien['prenom'] ?? '')) . ' ' . ((string) ($praticien['nom'] ?? ''))); $duree_minutes = (int) ($praticien['duree_rdv'] ?? 0); if ($duree_minutes <= 0) { $duree_minutes = 30; } $erreur = null; $toMin = function (string $hhmm): ?int { if (! preg_match('/^\d{2}:\d{2}$/', $hhmm)) { return null; } [$h, $m] = array_map('intval', explode(':', $hhmm)); if ($h < 0 || $h > 23 || $m < 0 || $m > 59) { return null; } return $h * 60 + $m; }; // ---- Ajouter un créneau (POST + CSRF) if ( $_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'add' && isset($_POST['jour'], $_POST['heure_debut'], $_POST['heure_fin']) ) { require_post_csrf(); $jour = trim((string) $_POST['jour']); $debut = trim((string) $_POST['heure_debut']); $fin = trim((string) $_POST['heure_fin']); $joursValides = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche']; $md = $toMin($debut); $mf = $toMin($fin); if (! in_array($jour, $joursValides, true)) { $erreur = $translations['erreur_jour_invalide'] ?? 'Jour invalide.'; } elseif ($md === null || $mf === null) { $erreur = $translations['erreur_format_heure'] ?? "Format d'heure invalide."; } elseif ($md >= $mf) { $erreur = $translations['erreur_debut_avant_fin'] ?? "Heure de début après l’heure de fin."; } else { $window = $mf - $md; if ($window < $duree_minutes) { $erreur = sprintf( $translations['erreur_plage_trop_courte'] ?? "Créneau trop court (%d min). Minimum : %d min.", $window, $duree_minutes ); } elseif (($window % $duree_minutes) !== 0) { $erreur = sprintf( $translations['erreur_plage_incompatible_duree'] ?? "Créneau incompatible. La durée doit être un multiple de %d min.", $duree_minutes ); } else { $stmt = $pdo->prepare(" INSERT INTO disponibilite (praticien_id, jour_semaine, heure_debut, heure_fin) VALUES (:p, :j, :hd, :hf) "); $stmt->execute([ 'p' => $praticien_id, 'j' => $jour, 'hd' => $debut, 'hf' => $fin, ]); header('Location: /public/cabinet/disponibilites.php?praticien_id=' . $praticien_id . '&ok=added', true, 303); exit; } } } // ---- Récupérer les créneaux $stmt = $pdo->prepare(" SELECT * FROM disponibilite WHERE praticien_id = ? ORDER BY FIELD(jour_semaine,'lundi','mardi','mercredi','jeudi','vendredi','samedi','dimanche'), heure_debut "); $stmt->execute([$praticien_id]); $dispos = $stmt->fetchAll(PDO::FETCH_ASSOC); $jourKeyMap = [ 'lundi' => 'jour_lundi', 'mardi' => 'jour_mardi', 'mercredi' => 'jour_mercredi', 'jeudi' => 'jour_jeudi', 'vendredi' => 'jour_vendredi', 'samedi' => 'jour_samedi', 'dimanche' => 'jour_dimanche', ]; $PAGE_TITLE = $translations['titre_disponibilites'] ?? 'Disponibilités'; $HEAD_EXTRA = << HTML; require_once __DIR__ . '/../includes/header_cabinet.php'; ?>