reprogrammed functionality
This commit is contained in:
@@ -0,0 +1,500 @@
|
||||
<?php
|
||||
session_start();
|
||||
//setlocale(LC_TIME, 'it_IT.UTF-8', 'it_IT.utf8', 'Italian_Italy.1252', 'it_IT');
|
||||
include('include/headscript.php');
|
||||
|
||||
if (!isset($iduserlogin)) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$school_id = $_SESSION['school_id'];
|
||||
if (!$school_id) die("Nessuna scuola selezionata");
|
||||
|
||||
$booking_id = (int)($_GET['booking'] ?? 0);
|
||||
if ($booking_id <= 0) die("Prenotazione non valida");
|
||||
|
||||
$dbHandler = DBHandlerSelect::getInstance();
|
||||
$pdo = $dbHandler->getConnection();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT name, address_street, address_city, address_province FROM schools WHERE id = ?");
|
||||
$stmt->execute([$school_id]);
|
||||
$school = $stmt->fetch();
|
||||
// Recupera dettagli vecchia prenotazione
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT
|
||||
sb.id, sb.order_id,
|
||||
c.name AS class_name, ct.level, ct.class_id, cs.session_date, cs.start_time, cs.end_time
|
||||
FROM session_bookings sb
|
||||
JOIN class_sessions cs ON sb.session_id = cs.id
|
||||
JOIN class_types ct ON cs.class_type_id = ct.id
|
||||
JOIN classes c ON ct.class_id = c.id
|
||||
WHERE sb.id = ? AND sb.user_id = ? AND sb.status = 'booked'
|
||||
");
|
||||
$stmt->execute([$booking_id, $iduserlogin]);
|
||||
$old_booking = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$old_booking) die("Prenotazione non trovata o non modificabile");
|
||||
|
||||
// Recupera impostazioni scuola (per auto-approved)
|
||||
$stmt = $pdo->prepare("SELECT rebooking_auto_approved FROM school_settings WHERE school_id = ?");
|
||||
$stmt->execute([$school_id]);
|
||||
$settings = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$auto_approved = $settings['rebooking_auto_approved'] ?? 1;
|
||||
|
||||
// Lezioni future disponibili (tutte le scheduled future)
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT
|
||||
cs.id AS session_id,
|
||||
cs.session_date,
|
||||
cs.start_time,
|
||||
cs.end_time,
|
||||
cs.room_name,
|
||||
cs.max_capacity,
|
||||
c.name AS class_name,
|
||||
ct.level,
|
||||
(SELECT COUNT(*) FROM session_bookings WHERE session_id = cs.id AND status IN ('booked', 'pending')) AS booked_count,
|
||||
(SELECT COUNT(*) FROM session_bookings WHERE session_id = cs.id AND user_id = ? AND status IN ('booked', 'pending')) AS user_booked
|
||||
FROM class_sessions cs
|
||||
JOIN class_types ct ON cs.class_type_id = ct.id
|
||||
JOIN classes c ON ct.class_id = c.id
|
||||
WHERE cs.school_id = ?
|
||||
AND cs.status = 'scheduled'
|
||||
AND cs.session_date >= CURDATE()
|
||||
ORDER BY cs.session_date ASC, cs.start_time ASC
|
||||
");
|
||||
$stmt->execute([$iduserlogin, $school_id]);
|
||||
$available_lessons = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Gestione POST: riprogrammazione
|
||||
$success = $error = "";
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['new_session_id'])) {
|
||||
$new_session_id = (int)$_POST['new_session_id'];
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// Verifica disponibilità nuova sessione
|
||||
$stmt_check = $pdo->prepare("
|
||||
SELECT max_capacity,
|
||||
(SELECT COUNT(*) FROM session_bookings WHERE session_id = ? AND status IN ('booked', 'pending')) AS booked_count
|
||||
FROM class_sessions
|
||||
WHERE id = ? AND status = 'scheduled' AND session_date >= CURDATE()
|
||||
");
|
||||
$stmt_check->execute([$new_session_id, $new_session_id]);
|
||||
$new_session = $stmt_check->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$new_session || $new_session['booked_count'] >= $new_session['max_capacity']) {
|
||||
throw new Exception("Lezione non disponibile o piena");
|
||||
}
|
||||
|
||||
// Crea nuova prenotazione
|
||||
$status_new = $auto_approved ? 'booked' : 'pending';
|
||||
$stmt_new = $pdo->prepare("
|
||||
INSERT INTO session_bookings
|
||||
(session_id, user_id, order_id, status, booked_at, created_at)
|
||||
VALUES (?, ?, ?, ?, NOW(), NOW())
|
||||
");
|
||||
$stmt_new->execute([$new_session_id, $iduserlogin, $old_booking['order_id'], $status_new]);
|
||||
|
||||
// Marca vecchia come rescheduled
|
||||
$stmt_old = $pdo->prepare("
|
||||
UPDATE session_bookings
|
||||
SET status = 'rescheduled', updated_at = NOW()
|
||||
WHERE id = ?
|
||||
");
|
||||
$stmt_old->execute([$booking_id]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
// Redirect to my_lessons.php with a success flag/message
|
||||
$msg = $auto_approved ? "Riprogrammazione completata. Lezione confermata." : "Riprogrammazione inviata. In attesa di approvazione.";
|
||||
header("Location: my_lessons.php?rebook=1&msg=" . urlencode($msg));
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
$pdo->rollBack();
|
||||
$error = "Errore durante la riprogrammazione: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
function it_weekday($dateYmd)
|
||||
{
|
||||
$fmt = new IntlDateFormatter(
|
||||
'it_IT',
|
||||
IntlDateFormatter::FULL,
|
||||
IntlDateFormatter::NONE,
|
||||
'Europe/Rome',
|
||||
IntlDateFormatter::GREGORIAN,
|
||||
'EEEE'
|
||||
);
|
||||
return ucfirst($fmt->format(strtotime($dateYmd)));
|
||||
}
|
||||
|
||||
function it_day_month($dateYmd)
|
||||
{
|
||||
$fmt = new IntlDateFormatter(
|
||||
'it_IT',
|
||||
IntlDateFormatter::NONE,
|
||||
IntlDateFormatter::NONE,
|
||||
'Europe/Rome',
|
||||
IntlDateFormatter::GREGORIAN,
|
||||
'd MMMM'
|
||||
);
|
||||
return ucfirst($fmt->format(strtotime($dateYmd)));
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<!doctype html>
|
||||
<html lang="it">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Riprogramma Lezione - YoGiBook</title>
|
||||
<?php include('cssinclude.php'); ?>
|
||||
<?php include('siteinfo.php'); ?>
|
||||
<style>
|
||||
/* Riutilizzo esatto gli stili da my_lessons.php */
|
||||
.page-content {
|
||||
background: #f9fff9;
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
|
||||
.month-header {
|
||||
background: white;
|
||||
padding: 0.9rem 1rem;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.07);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
margin-bottom: 1.2rem;
|
||||
}
|
||||
|
||||
.lesson-card {
|
||||
background: white;
|
||||
border-radius: 18px;
|
||||
margin: 1rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.09);
|
||||
}
|
||||
|
||||
.lesson-card.available {
|
||||
border-left: 6px solid #10b981;
|
||||
/* Verde */
|
||||
}
|
||||
|
||||
.lesson-card.user-booked {
|
||||
border-left: 6px solid #f59e0b;
|
||||
/* Arancione */
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.lesson-card.full {
|
||||
border-left: 6px solid #6b7280;
|
||||
/* Grigio */
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.date-header {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
padding: 1.4rem 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Mantieni il verde chiaro originale per date-header delle card disponibili */
|
||||
.lesson-card.available .date-header {
|
||||
background: #d1fae5;
|
||||
/* Verde chiaro originale */
|
||||
color: #065f46;
|
||||
}
|
||||
|
||||
/* Date-header più scuro per card già prenotate (arancione) */
|
||||
.lesson-card.user-booked .date-header {
|
||||
background: #ff8c4f;
|
||||
/* Arancione scuro */
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Date-header più scuro per card piena (grigio) */
|
||||
.lesson-card.full .date-header {
|
||||
background: linear-gradient(135deg, #4b5563, #6b7280);
|
||||
/* Grigio scuro */
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Opzionale: rendi testo data più leggibile su sfondi scuri */
|
||||
.lesson-card.user-booked .date-header .date-num,
|
||||
.lesson-card.full .date-header .date-num {
|
||||
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.lesson-card.user-booked .date-header .date-day,
|
||||
.lesson-card.full .date-header .date-day {
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
}
|
||||
|
||||
.date-num {
|
||||
font-size: 2.1rem;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.date-day {
|
||||
font-size: 1.18rem;
|
||||
font-weight: 600;
|
||||
margin: 5px 0 0;
|
||||
}
|
||||
|
||||
.lesson-body {
|
||||
padding: 1.4rem 1.3rem;
|
||||
}
|
||||
|
||||
.lesson-title {
|
||||
font-size: 1.38rem;
|
||||
font-weight: 700;
|
||||
color: #1a1a1a;
|
||||
margin: 0 0 0.8rem;
|
||||
}
|
||||
|
||||
.lesson-meta {
|
||||
font-size: 0.98rem;
|
||||
color: #444;
|
||||
margin: 0.5rem 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.lesson-meta i {
|
||||
width: 20px;
|
||||
color: #666;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.entries-badge {
|
||||
display: inline-block;
|
||||
background: #dbeafe;
|
||||
color: #1e40af;
|
||||
padding: 0.6rem 1rem;
|
||||
border-radius: 12px;
|
||||
font-weight: 600;
|
||||
font-size: 0.92rem;
|
||||
margin: 0.8rem 0;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
margin-top: 1.2rem;
|
||||
}
|
||||
|
||||
.btn-custom {
|
||||
padding: 0.85rem;
|
||||
border-radius: 14px;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn-primary-custom {
|
||||
background: #10b981;
|
||||
color: white;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.lesson-card {
|
||||
background: white;
|
||||
border-radius: 18px;
|
||||
margin: 1rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.09);
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.lesson-card.available {
|
||||
border-left: 6px solid #10b981;
|
||||
/* Verde solo bordo sinistro */
|
||||
}
|
||||
|
||||
.lesson-card.user-booked {
|
||||
background: #fff7ed !important;
|
||||
/* Arancione chiaro sfondo tutta card */
|
||||
border-left: 6px solid #f59e0b;
|
||||
opacity: 0.92;
|
||||
}
|
||||
|
||||
.lesson-card.full {
|
||||
background: #f3f4f6 !important;
|
||||
/* Grigio chiaro sfondo tutta card */
|
||||
border-left: 6px solid #6b7280;
|
||||
opacity: 0.75;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<?php include('include/navbar.php'); ?>
|
||||
<?php include('include/topbar.php'); ?>
|
||||
|
||||
<div class="page-wrapper">
|
||||
<div class="page-content">
|
||||
|
||||
<div class="month-header">
|
||||
<h2>Riprogramma lezione</h2>
|
||||
<p class="text-muted small mt-2 mb-1">
|
||||
<?= htmlspecialchars($old_booking['class_name']) ?>
|
||||
<?php if ($old_booking['level']): ?> - <?= ucfirst($old_booking['level']) ?><?php endif; ?>
|
||||
</p>
|
||||
<p class="fw-bold text-primary mb-0">
|
||||
<?= htmlspecialchars(it_day_month($old_booking['session_date'])) ?> <?= date('Y', strtotime($old_booking['session_date'])) ?>
|
||||
dalle <?= date('H:i', strtotime($old_booking['start_time'])) ?>
|
||||
alle <?= date('H:i', strtotime($old_booking['end_time'])) ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="text-end mb-3">
|
||||
<a href="my_lessons.php" class="btn btn-outline-secondary">
|
||||
<i class="bx bx-arrow-back me-1"></i> Annulla e torna indietro
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid px-0">
|
||||
<?php if ($success): ?>
|
||||
<div class="alert alert-success alert-dismissible fade show mb-4">
|
||||
<?= htmlspecialchars($success) ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger alert-dismissible fade show mb-4">
|
||||
<?= htmlspecialchars($error) ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="row">
|
||||
<?php if (empty($available_lessons)): ?>
|
||||
<div class="text-center py-5">
|
||||
<i class="bx bx-calendar-x bx-lg text-muted"></i>
|
||||
<h5 class="mt-3 text-secondary">Nessuna lezione disponibile per la riprogrammazione</h5>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($available_lessons as $lesson): ?>
|
||||
<?php
|
||||
$is_full = $lesson['booked_count'] >= $lesson['max_capacity'];
|
||||
$is_user_booked = $lesson['user_booked'] > 0;
|
||||
$card_class = $is_full ? 'full' : ($is_user_booked ? 'user-booked' : 'available');
|
||||
?>
|
||||
<div class="col-md-6 col-lg-4 mb-4">
|
||||
<div class="lesson-card <?= $card_class ?>">
|
||||
<div class="date-header">
|
||||
<div class="date-num"><?= htmlspecialchars(it_day_month($lesson['session_date'])) ?></div>
|
||||
<div class="date-day">
|
||||
<?= htmlspecialchars(it_weekday($lesson['session_date'])) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-body">
|
||||
<h3 class="lesson-title">
|
||||
<?= htmlspecialchars($lesson['class_name']) ?>
|
||||
<?php if ($lesson['level']): ?>
|
||||
<small style="color:#666;">- <?= ucfirst($lesson['level']) ?></small>
|
||||
<?php endif; ?>
|
||||
</h3>
|
||||
|
||||
<div class="lesson-meta">
|
||||
<i class="bx bx-time"></i>
|
||||
<?= date('H:i', strtotime($lesson['start_time'])) ?> - <?= date('H:i', strtotime($lesson['end_time'])) ?>
|
||||
</div>
|
||||
|
||||
<div class="lesson-meta">
|
||||
<i class="bx bx-home"></i>
|
||||
<?= htmlspecialchars($school['name']) ?>
|
||||
<?php if ($lesson['room_name']): ?> - <?= htmlspecialchars($lesson['room_name']) ?><?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="lesson-meta">
|
||||
<i class="bx bx-map"></i>
|
||||
<?= htmlspecialchars(trim($school['address_street'] . ', ' . $school['address_city'] . ' ' . $school['address_province'])) ?>
|
||||
</div>
|
||||
|
||||
<div class="entries-badge">
|
||||
Posti liberi: <strong><?= max(0, $lesson['max_capacity'] - $lesson['booked_count']) ?></strong>
|
||||
</div>
|
||||
|
||||
<?php if ($is_full): ?>
|
||||
<div class="text-danger fw-bold text-center mt-4 fs-5">
|
||||
Lezione piena
|
||||
</div>
|
||||
<?php elseif ($is_user_booked): ?>
|
||||
<div class="text-warning fw-bold text-center mt-4 fs-5">
|
||||
Già prenotata da te
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="action-buttons">
|
||||
<form method="POST" class="js-rebook-form"
|
||||
data-date="<?= htmlspecialchars(date('d/m/Y', strtotime($lesson['session_date']))) ?>"
|
||||
data-start="<?= htmlspecialchars(date('H:i', strtotime($lesson['start_time']))) ?>"
|
||||
data-end="<?= htmlspecialchars(date('H:i', strtotime($lesson['end_time']))) ?>"
|
||||
data-class="<?= htmlspecialchars($lesson['class_name']) ?>">
|
||||
<input type="hidden" name="new_session_id" value="<?= (int)$lesson['session_id'] ?>">
|
||||
<button type="submit" class="btn-custom btn-primary-custom">
|
||||
Riprogramma qui
|
||||
</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include('include/footer.php'); ?>
|
||||
</div>
|
||||
|
||||
<?php include('jsinclude.php'); ?>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.querySelectorAll('.js-rebook-form').forEach(function(form) {
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const d = form.dataset.date || '';
|
||||
const s = form.dataset.start || '';
|
||||
const en = form.dataset.end || '';
|
||||
const cls = form.dataset.class || '';
|
||||
|
||||
Swal.fire({
|
||||
title: 'Confermi la riprogrammazione?',
|
||||
html: `
|
||||
<div style="text-align:left">
|
||||
<div><strong>Lezione:</strong> ${cls}</div>
|
||||
<div><strong>Quando:</strong> ${d} ${s} - ${en}</div>
|
||||
</div>
|
||||
`,
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Sì, riprogramma',
|
||||
cancelButtonText: 'No, annulla',
|
||||
reverseButtons: true
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
form.submit();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user