Files
yogibook_aury_new/public/cancellazioni.php
T
2026-10-14 15:56:09 +02:00

306 lines
13 KiB
PHP

<?php
require_once('include/headscript.php');
/**
* Storico delle lezioni cancellate dagli allievi (tabella bookingclass_cancellations).
* Sola consultazione: questa pagina non modifica nessun dato.
*/
$pdo = DBHandlerSelect::getInstance()->getConnection();
function e($value): string
{
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}
// Preavviso leggibile: minuti, ore o giorni
function formatPreavviso(?int $minutes): string
{
if ($minutes === null) return '-';
if ($minutes < 60) return $minutes . ' min';
if ($minutes < 48 * 60) return floor($minutes / 60) . ' ore';
return floor($minutes / 1440) . ' giorni';
}
$sql = "
SELECT
c.idcancellation,
c.iduser,
c.idorder,
c.is_gift,
c.reprogrammed_incremented,
c.cancelled_at,
COALESCE(ss.dateschedule, c.bookingstart) AS lesson_date,
TIMESTAMPDIFF(MINUTE, c.cancelled_at, COALESCE(ss.dateschedule, c.bookingstart)) AS preavviso_min,
u.first_name,
u.last_name,
u.email,
s.servicename,
o.reprogrammed,
o.maxreschedule
FROM bookingclass_cancellations c
LEFT JOIN auth_users u ON u.id = c.iduser
LEFT JOIN service s ON s.idservice = c.idservice
LEFT JOIN serviceschedule ss ON ss.idserviceschedule = c.idserviceschedule
LEFT JOIN orderbook o ON o.idorderbook = c.idorder
ORDER BY c.cancelled_at DESC";
$rows = $pdo->query($sql)->fetchAll();
// Contatori ultimi 7 / 30 giorni
$limit7 = strtotime('-7 days');
$limit30 = strtotime('-30 days');
$count7 = 0;
$count30 = 0;
foreach ($rows as $r) {
$t = strtotime($r['cancelled_at']);
if ($t >= $limit7) $count7++;
if ($t >= $limit30) $count30++;
}
?>
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8" />
<title>YogiBook - Cancellazioni</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="YogiBook" name="description" />
<meta content="Advanced Creative Solutions" name="author" />
<link rel="shortcut icon" href="assets/images/favicon.ico">
<link href="assets/css/bootstrap.min.css" id="bootstrap-style" rel="stylesheet" type="text/css" />
<link href="assets/css/icons.min.css" rel="stylesheet" type="text/css" />
<link href="assets/css/app.min.css" id="app-style" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<style>
.admin-card {
border: none;
border-radius: 14px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
}
.admin-card .card-body {
padding: 26px 30px;
}
.section-title {
font-size: 15px;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
color: #6b7280;
margin-bottom: 4px;
}
.section-lead {
color: #9ca3af;
font-size: 14px;
margin-bottom: 22px;
}
.counter {
border-radius: 8px;
padding: 8px 14px;
font-size: 14px;
font-weight: 600;
background: #fbe4c4;
color: #8a5a1a;
}
.counter.counter-30 {
background: #c4e1fb;
color: #1a4f7a;
}
#cancTable thead th {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.03em;
color: #6b7280;
}
#cancTable td {
vertical-align: middle;
}
.user-email {
display: block;
font-size: 12px;
color: #9ca3af;
}
.badge-soft {
display: inline-block;
border-radius: 6px;
padding: 2px 8px;
font-size: 12px;
font-weight: 600;
white-space: nowrap;
}
.badge-late {
background: #fbc7c4;
color: #a12820;
}
.badge-ok {
background: #cdfbc4;
color: #1a7f2e;
}
.badge-gift {
background: #e2d3f5;
color: #4c2c92;
}
.badge-neutral {
background: #eef0f3;
color: #4b5563;
}
</style>
</head>
<body>
<div id="layout-wrapper">
<header id="page-topbar" class="isvertical-topbar">
<div class="navbar-header">
<div class="d-flex">
<?php include('include/logoarea.php'); ?>
<button type="button" class="btn btn-sm px-3 font-size-24 header-item waves-effect vertical-menu-btn">
<i class="bx bx-menu align-middle"></i>
</button>
<div class="page-title-box align-self-center d-none d-md-block">
<h4 class="page-title mb-0">Cancellazioni</h4>
</div>
</div>
<div class="d-flex">
<?php include('include/languageselection.php'); ?>
<?php include('include/profiletopbar.php'); ?>
</div>
</div>
</header>
<?php include('include/sidebar.php'); ?>
<header class="ishorizontal-topbar">
<div class="navbar-header">
<div class="d-flex"></div>
</div>
<div class="topnav">
<div class="container-fluid">
<nav class="navbar navbar-light navbar-expand-lg topnav-menu"></nav>
</div>
</div>
</header>
<div class="main-content">
<div class="page-content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card admin-card">
<div class="card-body">
<div class="section-title">Lezioni cancellate dagli allievi</div>
<p class="section-lead">Storico delle cancellazioni, dalla più recente. Usa la ricerca per filtrare per nome, lezione o data.</p>
<div class="d-flex align-items-center gap-3 flex-wrap mb-3">
<span class="counter"><i class="fas fa-calendar-week me-1"></i> Ultimi 7 giorni: <strong><?php echo $count7; ?></strong></span>
<span class="counter counter-30"><i class="fas fa-calendar-alt me-1"></i> Ultimi 30 giorni: <strong><?php echo $count30; ?></strong></span>
<span class="counter badge-neutral"><i class="fas fa-list me-1"></i> Totale: <strong><?php echo count($rows); ?></strong></span>
</div>
<div class="table-responsive">
<table id="cancTable" class="table table-striped">
<thead>
<tr>
<th>Allievo</th>
<th>Lezione</th>
<th>Data lezione</th>
<th>Cancellata il</th>
<th>Preavviso</th>
<th>Ordine</th>
<th>Conta come riprog.</th>
</tr>
</thead>
<tbody>
<?php foreach ($rows as $r) :
$nome = trim(($r['first_name'] ?? '') . ' ' . ($r['last_name'] ?? ''));
if ($nome === '') $nome = 'Utente #' . (int) $r['iduser'];
$lessonTs = $r['lesson_date'] ? strtotime($r['lesson_date']) : null;
$cancTs = strtotime($r['cancelled_at']);
$preMin = $r['preavviso_min'] !== null ? (int) $r['preavviso_min'] : null;
?>
<tr>
<td>
<?php echo e($nome); ?>
<?php if (!empty($r['email'])) : ?>
<span class="user-email"><?php echo e($r['email']); ?></span>
<?php endif; ?>
</td>
<td><?php echo e($r['servicename'] ?? '-'); ?></td>
<td data-order="<?php echo $lessonTs ? date('Y-m-d H:i', $lessonTs) : ''; ?>">
<?php echo $lessonTs ? e(date('d/m/Y H:i', $lessonTs)) : '-'; ?>
</td>
<td data-order="<?php echo e(date('Y-m-d H:i:s', $cancTs)); ?>">
<?php echo e(date('d/m/Y H:i', $cancTs)); ?>
</td>
<td data-order="<?php echo $preMin ?? 0; ?>">
<?php if ($preMin !== null && $preMin < 24 * 60) : ?>
<span class="badge-soft badge-late"><?php echo e(formatPreavviso($preMin)); ?></span>
<?php else : ?>
<span class="badge-soft badge-ok"><?php echo e(formatPreavviso($preMin)); ?></span>
<?php endif; ?>
</td>
<td><?php echo $r['idorder'] !== null ? '#' . (int) $r['idorder'] : '-'; ?></td>
<td>
<?php if ($r['is_gift'] === 'Y' || $r['idorder'] === null) : ?>
<span class="badge-soft badge-gift">Omaggio</span>
<?php elseif ($r['reprogrammed_incremented'] === 'L') : ?>
<span class="badge-soft badge-late">Limite superato: lezione persa</span>
<?php elseif ($r['reprogrammed_incremented'] === 'Y') : ?>
<span class="badge-soft badge-neutral">
Sì<?php if ($r['reprogrammed'] !== null) : ?> (<?php echo (int) $r['reprogrammed']; ?>/<?php echo (int) $r['maxreschedule']; ?>)<?php endif; ?>
</span>
<?php else : ?>
<span class="badge-soft badge-neutral">No</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<?php include('include/footer.php'); ?>
</div>
</div>
</div>
<script src="assets/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="assets/libs/metismenujs/metismenujs.min.js"></script>
<script src="assets/libs/simplebar/simplebar.min.js"></script>
<script src="assets/libs/eva-icons/eva.min.js"></script>
<script src="assets/js/app.js"></script>
<script>
$('#cancTable').DataTable({
paging: true,
pageLength: 50,
searching: true,
ordering: true,
order: [
[3, 'desc']
],
language: {
url: "//cdn.datatables.net/plug-ins/1.13.6/i18n/it-IT.json"
}
});
</script>
</body>
</html>