Init Git Prod Mars 2026
This commit is contained in:
commit
d81efe93b1
362 files changed
+86627
No files matched your search
@@ -0,0 +1,244 @@
|
||||
<?php
|
||||
// /public/cabinet/rendez_vous_du_jour.php
|
||||
require_once __DIR__ . '/../includes/init_secretaire.php';
|
||||
|
||||
|
||||
|
||||
if (!function_exists('h')) { function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } }
|
||||
|
||||
// --- contexte secrétaire + praticien requis ---
|
||||
$compteId = (int)($_SESSION['compte_id'] ?? 0);
|
||||
$userRole = strtolower((string)($_SESSION['role'] ?? ''));
|
||||
$praticien_id = isset($_GET['praticien_id']) ? (int)$_GET['praticien_id'] : 0;
|
||||
|
||||
if ($userRole !== 'secretaire' || $compteId <= 0 || $praticien_id <= 0) {
|
||||
http_response_code(403); exit('Forbidden');
|
||||
}
|
||||
|
||||
// --- vérification pivot + droit can_manage_rdv ---
|
||||
$st = $pdo->prepare("
|
||||
SELECT can_manage_rdv
|
||||
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_manage_rdv'] !== 1) {
|
||||
http_response_code(403); exit('Forbidden');
|
||||
}
|
||||
|
||||
// --- Aujourd’hui en Europe/Paris ---
|
||||
date_default_timezone_set('Europe/Paris');
|
||||
$tz = new DateTimeZone('Europe/Paris');
|
||||
$todayStart = (new DateTime('today', $tz))->setTime(0, 0, 0);
|
||||
$todayEnd = (clone $todayStart)->setTime(23, 59, 59);
|
||||
$today_start = $todayStart->format('Y-m-d H:i:s');
|
||||
$today_end = $todayEnd->format('Y-m-d H:i:s');
|
||||
|
||||
// --- RDV du jour pour ce praticien ---
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT rv.*, c.nom AS nom_client, c.prenom AS prenom_client, c.email
|
||||
FROM rendez_vous rv
|
||||
JOIN client c ON rv.client_id = c.id
|
||||
WHERE rv.praticien_id = :p
|
||||
AND rv.date_rdv BETWEEN :d1 AND :d2
|
||||
ORDER BY rv.date_rdv ASC
|
||||
");
|
||||
$stmt->execute(['p'=>$praticien_id, 'd1'=>$today_start, 'd2'=>$today_end]);
|
||||
$rdvs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Map statuts (valeurs BDD -> libellés traduits)
|
||||
$statutMap = [
|
||||
'prévu' => $translations['statut_prevu'] ?? 'Prévu',
|
||||
'confirmé' => $translations['statut_confirme'] ?? 'Confirmé',
|
||||
'annulé' => $translations['statut_annule'] ?? 'Annulé',
|
||||
'terminé' => $translations['statut_termine'] ?? 'Terminé',
|
||||
];
|
||||
|
||||
$PAGE_TITRE = $translations['titre_rdv_du_jour'] ?? 'Rendez-vous du jour';
|
||||
$HEAD_EXTRA = <<<HTML
|
||||
<script src="/js/sweetalert2@11.js"></script>
|
||||
HTML;
|
||||
require_once __DIR__ . '/../includes/header_cabinet.php';
|
||||
?>
|
||||
<div class="main1">
|
||||
<div class="container py-5">
|
||||
<div class="shadow p-4 rounded bg-light">
|
||||
<h2 class="mb-4 text-center"><?= htmlspecialchars($currentPraticienName, ENT_QUOTES, 'UTF-8') ?> - <?= h($translations['titre_rdv_du_jour'] ?? 'Rendez-vous du jour') ?></h2>
|
||||
|
||||
<a href="/public/cabinet/rendez_vous.php?praticien_id=<?= (int)$praticien_id ?>" class="btn btn-outline-secondary mb-4">
|
||||
<?= h($translations['retour_liste_complete'] ?? 'Retour à la liste complète') ?>
|
||||
</a>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-hover align-middle text-center mobile-cards" id="table_rdv">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th><?= h($translations['col_heure'] ?? 'Heure') ?></th>
|
||||
<th><?= h($translations['col_client'] ?? 'Client') ?></th>
|
||||
<th><?= h($translations['col_duree'] ?? 'Durée') ?></th>
|
||||
<th><?= h($translations['col_statut'] ?? 'Statut') ?></th>
|
||||
<!--<th><?= h($translations['btn_chat'] ?? 'Chat') ?></th>
|
||||
<th><?= h($translations['status_online'] ?? 'Visio') ?></th>-->
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($rdvs as $r):
|
||||
$dt = new DateTime($r['date_rdv'], $tz);
|
||||
$id = (int)$r['id'];
|
||||
?>
|
||||
<tr data-statut="<?= h($r['statut']) ?>">
|
||||
<td><?= h($dt->format('H:i')) ?></td>
|
||||
<td><?= h(($r['prenom_client'] ?? '').' '.($r['nom_client'] ?? '')) ?></td>
|
||||
<td><?= (int)$r['duree_minutes'] . ' ' . h($translations['min_abbr'] ?? 'min') ?></td>
|
||||
<td>
|
||||
<select class="form-select form-select-sm" onchange="changerStatut(<?= $id ?>, this.value, this, <?= (int)$praticien_id ?>)">
|
||||
<?php foreach (['prévu','confirmé','annulé','terminé'] as $s): ?>
|
||||
<option value="<?= $s ?>" <?= ($r['statut'] === $s ? 'selected' : '') ?>>
|
||||
<?= h($statutMap[$s] ?? ucfirst($s)) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<!-- Chat -->
|
||||
<!--<td>
|
||||
<a class="btn btn-outline-secondary btn-sm btn-table" href="/messages/start.php?client_id=<?= (int)$r['client_id'] ?>">
|
||||
<?= h($translations['chat_praticien'] ?? 'Ouvrir le chat') ?>
|
||||
</a>
|
||||
</td>-->
|
||||
|
||||
<!-- Visio / Cabinet -->
|
||||
<!--<td>
|
||||
<?php
|
||||
$lieu = strtolower(trim((string)($r['lieu'] ?? '')));
|
||||
if ($lieu === 'online') {
|
||||
$statut = $r['statut']; // 'confirmé' | 'prévu' | 'annulé' | 'terminé'
|
||||
$now = new DateTime('now', $tz);
|
||||
$start = new DateTime($r['date_rdv'], $tz);
|
||||
$open = (clone $start)->modify('-15 minutes');
|
||||
$close = (clone $start)->modify('+'.(int)($r['duree_minutes'] ?? 120).' minutes');
|
||||
|
||||
if ($statut === 'confirmé') {
|
||||
if ($now >= $open && $now <= $close) {
|
||||
?>
|
||||
<a href="/visio/join.php?rdv=<?= (int)$r['id'] ?>&start=1" class="btn btn-outline-secondary btn-sm btn-table">
|
||||
<?= h($translations['visio_nachalo'] ?? 'Démarrer la visio') ?>
|
||||
</a>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<small class="text-muted d-block mt-1">
|
||||
<?php
|
||||
if ($now < $open) echo h(($translations['ouvert_a'] ?? 'Ouvert à').' '.$open->format('H:i'));
|
||||
elseif ($now > $close) echo h(($translations['ferme_a'] ?? 'Fermé à').' '.$close->format('H:i'));
|
||||
else echo h(($translations['prev_a'] ?? 'Prévu le').' '.$start->format('d/m/Y \à H:i').'.');
|
||||
?>
|
||||
</small>
|
||||
<?php
|
||||
}
|
||||
} elseif ($statut === 'prévu') {
|
||||
?>
|
||||
<small class="text-danger d-block mt-1"><?= h($translations['votre_rdv_jdet'] ?? 'En attente de confirmation') ?></small>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<small class="text-muted d-block mt-1"><?= h(($translations['zaverchen_a'] ?? 'Terminé').' '.$close->format('H:i')) ?></small>
|
||||
<?php
|
||||
}
|
||||
} else {
|
||||
echo '<span class="text-nowrap">'.h($translations['option_cabinet'] ?? 'Очно').'</span>';
|
||||
}
|
||||
?>
|
||||
</td>-->
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($rdvs)): ?>
|
||||
<tr>
|
||||
<td colspan="6" class="text-muted">
|
||||
<?= h($translations['aucun_rdv_aujourdhui'] ?? "Aucun rendez-vous aujourd'hui") ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// MAJ statut via endpoint cabinet + praticien_id
|
||||
function changerStatut(id, statut, selEl, praticienId) {
|
||||
fetch('/public/cabinet/changer_statut.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
|
||||
body: new URLSearchParams({ id: String(id), statut: String(statut), praticien_id: String(praticienId) })
|
||||
})
|
||||
.then(async (r) => {
|
||||
const raw = (await r.text()).trim();
|
||||
let ok = false, message = '';
|
||||
try {
|
||||
const data = JSON.parse(raw);
|
||||
ok = !!data.ok;
|
||||
message = data.message || '';
|
||||
} catch (_) {
|
||||
if (raw.toUpperCase().includes('OK')) { ok = true; message = raw; }
|
||||
else { throw new Error(raw.slice(0, 180)); }
|
||||
}
|
||||
|
||||
if (!ok) throw new Error(message || 'Erreur');
|
||||
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: message || '<?= addslashes($translations['maj_ok'] ?? "Mise à jour réussie") ?>',
|
||||
timer: 1800,
|
||||
showConfirmButton: false
|
||||
});
|
||||
|
||||
try {
|
||||
const tr = selEl && selEl.closest('tr');
|
||||
if (tr) tr.dataset.statut = statut;
|
||||
} catch(e){}
|
||||
})
|
||||
.catch((e) => {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: '<?= addslashes($translations['erreur_mise_a_jour'] ?? "Erreur de mise à jour") ?>',
|
||||
text: e.message || '<?= addslashes($translations['erreur_mise_a_jour'] ?? "Erreur de mise à jour.") ?>',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<!--********* Adaptation 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><?= $translations['copyr'] ?? '© '.date('Y') ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user