Files
maria_uslugi/public/praticien/disponibilites_date.php
T
2026-03-05 10:25:39 +01:00

250 lines
9.8 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
// /public/praticien/disponibilites_date.php
require_once __DIR__ . '/../includes/init_praticien.php';
$praticien_id = (int) ($_SESSION['reference_id'] ?? 0);
if ($praticien_id <= 0) {http_response_code(403);exit('Forbidden');}
// Durée RDV praticien (garde-fou strict)
$stmt = $pdo->prepare("SELECT duree_rdv FROM praticien WHERE id = ?");
$stmt->execute([$praticien_id]);
$duree_minutes = (int) ($stmt->fetchColumn() ?: 0);
if ($duree_minutes <= 0) {
$duree_minutes = 30;
}
// ---- Ajouter une dispo ponctuelle (POST) ----
$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;
};
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['date_dispo'], $_POST['heure_debut'], $_POST['heure_fin'])) {
$date_dispo = trim((string) $_POST['date_dispo']); // YYYY-MM-DD
$debut = trim((string) $_POST['heure_debut']); // HH:MM
$fin = trim((string) $_POST['heure_fin']); // HH:MM
// Validation date simple
$dt = DateTimeImmutable::createFromFormat('Y-m-d', $date_dispo);
if (! $dt || $dt->format('Y-m-d') !== $date_dispo) {
$erreur = $translations['erreur_format_date'] ?? "Format de date invalide.";
} else {
$md = $toMin($debut);
$mf = $toMin($fin);
if ($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_date (praticien_id, date_dispo, heure_debut, heure_fin)
VALUES (?, ?, ?, ?)"
);
$stmt->execute([$praticien_id, $date_dispo, $debut, $fin]);
header('Location: /public/praticien/disponibilites_date.php?ok=added', true, 303);
exit;
}
}
}
}
// ---- Supprimer une plage datée (GET) ----
if (isset($_GET['supprimer'])) {
$id = (int) $_GET['supprimer'];
$stmt = $pdo->prepare("DELETE FROM disponibilite_date WHERE id = ? AND praticien_id = ?");
$stmt->execute([$id, $praticien_id]);
header('Location: /public/praticien/disponibilites_date.php?ok=deleted', true, 303);
exit;
}
// ---- Récupérer les plages datées ----
$stmt = $pdo->prepare(
"SELECT id, date_dispo, heure_debut, heure_fin
FROM disponibilite_date
WHERE praticien_id = ?
ORDER BY date_dispo ASC, heure_debut ASC"
);
$stmt->execute([$praticien_id]);
$dates = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 1️⃣ Titre de la page
$PAGE_TITLE = $translations['titre_disponibilites_date'] ?? 'Disponibilités (dates)';
// 2️⃣ Ce qui doit aller dans <head> EN PLUS du header global
$HEAD_EXTRA = <<<HTML
<script src="/js/sweetalert2@11.js"></script>
HTML;
require_once __DIR__ . '/../includes/header.php';
?>
<div class="main1">
<div class="container py-5">
<div class="shadow p-4 rounded bg-light">
<h2 class="mb-4 text-center"><?php echo htmlspecialchars($translations['h2_disponibilites_date'] ?? 'Mes disponibilités ponctuelles') ?></h2>
<div class="d-flex justify-content-between align-items-center mb-3">
<a class="btn btn-outline-secondary"
href="/public/praticien/disponibilites.php">
<?php echo htmlspecialchars($translations['retour_au_planning'] ?? 'Retour') ?>
</a>
</div>
<div class="table-responsive mb-4">
<table class="table table-bordered table-striped align-middle text-center mobile-cards" id="table_rdv">
<thead class="table-light">
<tr>
<th><?php echo htmlspecialchars($translations['cl_date_rdv'] ?? 'Date') ?></th>
<th><?php echo htmlspecialchars($translations['table_debut'] ?? 'Début') ?></th>
<th><?php echo htmlspecialchars($translations['table_fin'] ?? 'Fin') ?></th>
<th><?php echo htmlspecialchars($translations['table_action'] ?? 'Action') ?></th>
</tr>
</thead>
<tbody>
<?php if ($dates): foreach ($dates as $d): ?>
<tr>
<td>
<?php echo htmlspecialchars(
date('d/m/Y', strtotime($d['date_dispo']))
) ?>
</td>
<td><?php echo htmlspecialchars(substr((string) $d['heure_debut'], 0, 5)) ?></td>
<td><?php echo htmlspecialchars(substr((string) $d['heure_fin'], 0, 5)) ?></td>
<td>
<button type="button"
class="btn btn-sm btn-danger js-del"
data-id="<?php echo (int) $d['id'] ?>">
<?php echo htmlspecialchars($translations['btn_supprimer'] ?? 'Supprimer') ?>
</button>
</td>
</tr>
<?php endforeach;else: ?>
<tr><td colspan="4"><?php echo htmlspecialchars($translations['aucun_creneau'] ?? 'Aucun créneau.') ?></td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
<div class="card shadow-sm p-4">
<h4 class="mb-3 text-center"><?php echo htmlspecialchars($translations['card_ajouter_creneau_date'] ?? 'Ajouter une disponibilité ponctuelle') ?></h4>
<form method="POST">
<div class="mb-3">
<label class="form-label" for="date_dispo"><?php echo htmlspecialchars($translations['cl_date_rdv'] ?? 'Date') ?></label>
<input type="date" name="date_dispo" id="date_dispo" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label" for="heure_debut"><?php echo htmlspecialchars($translations['label_heure_debut'] ?? 'Heure de début') ?></label>
<input type="time" name="heure_debut" id="heure_debut" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label" for="heure_fin"><?php echo htmlspecialchars($translations['label_heure_fin'] ?? 'Heure de fin') ?></label>
<input type="time" name="heure_fin" id="heure_fin" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary w-100">
<?php echo htmlspecialchars($translations['btn_ajouter'] ?? 'Ajouter') ?>
</button>
</form>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function(){
const okParam = '<?php echo isset($_GET['ok']) ? addslashes((string) $_GET['ok']) : '' ?>';
const erreurMsg = '<?php echo $erreur ? addslashes((string) $erreur) : '' ?>';
if (okParam === 'added') {
Swal.fire({ icon:'success', title:'<?php echo addslashes($translations["msg_creneau_ajoute"] ?? "Créneau ajouté.") ?>', timer:1800, showConfirmButton:false });
} else if (okParam === 'deleted') {
Swal.fire({ icon:'success', title:'<?php echo addslashes($translations["msg_creneau_supprime"] ?? "Créneau supprimé.") ?>', timer:1800, showConfirmButton:false });
}
if (erreurMsg) {
Swal.fire({
icon: 'error',
title: '<?php echo addslashes($translations["erreur_titre"] ?? "Erreur") ?>',
html: erreurMsg,
showCancelButton: true,
confirmButtonText: '<?php echo addslashes($translations["btn_modifier_profil"] ?? "Modifier mon profil") ?>',
cancelButtonText: 'OK'
}).then((result) => {
if (result.isConfirmed) {
window.location.href = '/public/praticien/modifier.php';
}
});
}
});
document.addEventListener('click', async function(e){
const btn = e.target.closest('.js-del');
if (!btn) return;
const id = btn.dataset.id;
const result = await Swal.fire({
icon: 'warning',
title: '<?php echo addslashes($translations["confirm_title"] ?? "Confirmation") ?>',
text: '<?php echo addslashes($translations["confirm_supprimer_creneau"] ?? "Supprimer ce créneau ?") ?>',
showCancelButton: true,
confirmButtonText: '<?php echo addslashes($translations["btn_da_udalit"] ?? "Oui") ?>',
cancelButtonText: '<?php echo addslashes($translations["btn_annuler"] ?? "Annuler") ?>',
reverseButtons: true
});
if (result.isConfirmed) {
window.location.href = '?supprimer=' + encodeURIComponent(id);
}
});
</script>
<!--*********Adaptation des tables pour un affichage mobile***************-->
<script defer>
(function(){
function initMobileCards(tbl){
if (!tbl) return;
const heads = Array.from(tbl.querySelectorAll('thead th')).map(th => th.textContent.trim());
tbl.querySelectorAll('tbody tr').forEach(tr => {
Array.from(tr.children).forEach((td, i) => {
if (!td.hasAttribute('data-label')) td.setAttribute('data-label', heads[i] || '');
});
});
document.documentElement.classList.add('mc-ready');
}
function ready(fn){ if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', fn); else fn(); }
ready(function(){ initMobileCards(document.getElementById('table_rdv')); });
})();
</script>
<footer class="site-footer">
<div class="container">
<p><?php echo $translations['copyr'] ?? '&copy; ' . date('Y') ?></p>
</div>
</footer>
</body>
</html>