getConnection();
if (!isset($iduserlogin)) {
die("Errore: ID utente non definito.");
}
// (Optional) Set Italian locale for month names if needed
// setlocale(LC_TIME, 'it_IT.UTF-8', 'it_IT', 'Italian_Italy');
$stmt = $pdo->prepare("SELECT id, name, logo FROM schools WHERE owner_id = ?");
$stmt->execute([$iduserlogin]);
$school = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$school) {
die("Errore: Nessuna scuola trovata.");
}
$school_id = (int)$school['id'];
$school_name = $school['name'];
// === School users for "Add participant" dropdown ===
$stmtUsers = $pdo->prepare("
SELECT au.id, au.first_name, au.last_name, au.email
FROM user_schools us
JOIN auth_users au ON au.id = us.user_id
WHERE us.school_id = ?
AND us.status = 'active'
ORDER BY au.first_name, au.last_name
");
$stmtUsers->execute([$school_id]);
$schoolUsers = $stmtUsers->fetchAll(PDO::FETCH_ASSOC);
// === Month filter (ym=YYYY-MM) ===
$ym = $_GET['ym'] ?? date('Y-m');
if (!preg_match('/^\d{4}\-\d{2}$/', $ym)) {
$ym = date('Y-m');
}
$startDate = $ym . '-01';
$dtStart = new DateTime($startDate);
$dtEnd = (clone $dtStart)->modify('first day of next month');
$endDate = $dtEnd->format('Y-m-d');
// Month navigation
$prevYm = (clone $dtStart)->modify('-1 month')->format('Y-m');
$nextYm = (clone $dtStart)->modify('+1 month')->format('Y-m');
// Build months dropdown (last 24 months + next 2 months)
$monthsList = [];
$base = new DateTime(date('Y-m-01'));
for ($i = 24; $i >= 1; $i--) {
$m = (clone $base)->modify("-{$i} month")->format('Y-m');
$monthsList[] = $m;
}
$monthsList[] = $base->format('Y-m');
$monthsList[] = (clone $base)->modify('+1 month')->format('Y-m');
$monthsList[] = (clone $base)->modify('+2 month')->format('Y-m');
// === Actions (same as future_sessions) ===
$feedback = '';
$showEmailModal = false;
$emailData = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
// Delete session (optionally with email)
if ($action === 'delete_session') {
$session_id = (int)($_POST['session_id'] ?? 0);
$send_email = isset($_POST['send_email']) && $_POST['send_email'] === '1';
$stmt = $pdo->prepare("
SELECT cs.id, cs.session_date, cs.start_time, cs.end_time,
c.name AS class_name, ct.level
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.id = ? AND c.school_id = ?
");
$stmt->execute([$session_id, $school_id]);
$session = $stmt->fetch(PDO::FETCH_ASSOC);
if ($session) {
$recipients = [];
if ($send_email) {
$stmt2 = $pdo->prepare("
SELECT au.email, au.first_name
FROM session_bookings sb
JOIN auth_users au ON sb.user_id = au.id
WHERE sb.session_id = ?
");
$stmt2->execute([$session_id]);
$recipients = $stmt2->fetchAll(PDO::FETCH_ASSOC);
}
// If email requested and recipients exist -> open email modal, do not delete yet
if ($send_email && !empty($recipients)) {
$showEmailModal = true;
$emailData = [
'session_id' => $session_id,
'class_name' => $session['class_name'],
'level' => $session['level'] ?? '',
'date' => date('d/m/Y', strtotime($session['session_date'])),
'time' => substr($session['start_time'], 0, 5) . ' - ' . substr($session['end_time'], 0, 5),
'recipients' => $recipients
];
} else {
// Delete immediately
$stmtDel = $pdo->prepare("
DELETE cs 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.id = ? AND c.school_id = ?
");
$stmtDel->execute([$session_id, $school_id]);
$feedback = '
Lezione cancellata con successo!
';
}
}
}
// Send cancellation email then delete
elseif ($action === 'send_cancellation_email') {
$session_id = (int)($_POST['session_id'] ?? 0);
$body_text = $_POST['email_body'] ?? '';
$stmt = $pdo->prepare("
SELECT c.name AS class_name, ct.level, cs.session_date, cs.start_time, cs.end_time
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.id = ? AND c.school_id = ?
");
$stmt->execute([$session_id, $school_id]);
$session = $stmt->fetch(PDO::FETCH_ASSOC);
$class_info = $session ? ($session['class_name'] . ($session['level'] ? ' (' . ucfirst($session['level']) . ')' : '')) : '';
$date = $session ? date('d/m/Y', strtotime($session['session_date'])) : '';
$time = $session ? substr($session['start_time'], 0, 5) . '-' . substr($session['end_time'], 0, 5) : '';
$stmt = $pdo->prepare("
SELECT au.email, au.first_name
FROM session_bookings sb
JOIN auth_users au ON sb.user_id = au.id
WHERE sb.session_id = ?
");
$stmt->execute([$session_id]);
$recipients = $stmt->fetchAll(PDO::FETCH_ASSOC);
$subject = "Lezione cancellata - {$school_name}";
$sent = 0;
foreach ($recipients as $r) {
$personal_body = str_replace(
['{nome}', '{classe}', '{data}', '{ora}'],
[$r['first_name'] ?: 'Gentile utente', $class_info, $date, $time],
$body_text
);
$result = sendEmail($r['email'], $subject, $personal_body);
if (!empty($result['success'])) $sent++;
}
$stmtDel = $pdo->prepare("
DELETE cs 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.id = ? AND c.school_id = ?
");
$stmtDel->execute([$session_id, $school_id]);
$feedback = "
Email inviate a {$sent} partecipanti.
";
}
// Skip email then delete
elseif ($action === 'skip_cancellation_email') {
$session_id = (int)($_POST['session_id'] ?? 0);
$stmtDel = $pdo->prepare("
DELETE cs 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.id = ? AND c.school_id = ?
");
$stmtDel->execute([$session_id, $school_id]);
$feedback = "
Lezione cancellata (email non inviata).
";
}
// Add booking
elseif ($action === 'add_booking') {
$session_id = (int)($_POST['session_id'] ?? 0);
$user_id = (int)($_POST['user_id'] ?? 0);
if ($session_id <= 0 || $user_id <= 0) {
$feedback = 'Dati non validi.
';
} else {
$stmt = $pdo->prepare("
SELECT cs.id, ct.max_capacity,
(SELECT COUNT(*) FROM session_bookings sb
WHERE sb.session_id = cs.id AND sb.status IN ('booked','attended','rescheduled')
) AS booked_count
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.id = ? AND c.school_id = ?
LIMIT 1
");
$stmt->execute([$session_id, $school_id]);
$info = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$info) {
$feedback = 'Lezione non trovata o non autorizzata.
';
} else {
$stmt = $pdo->prepare("
SELECT 1
FROM user_schools
WHERE user_id = ? AND school_id = ? AND status = 'active'
LIMIT 1
");
$stmt->execute([$user_id, $school_id]);
$isMember = (bool)$stmt->fetchColumn();
if (!$isMember) {
$feedback = 'Utente non associato a questa scuola.
';
} else {
$stmt = $pdo->prepare("SELECT 1 FROM session_bookings WHERE session_id = ? AND user_id = ? LIMIT 1");
$stmt->execute([$session_id, $user_id]);
$already = (bool)$stmt->fetchColumn();
if ($already) {
$feedback = 'Questo utente è già presente nella lezione.
';
} else {
$max = (int)($info['max_capacity'] ?? 0);
$cnt = (int)($info['booked_count'] ?? 0);
if ($max > 0 && $cnt >= $max) {
$feedback = 'Lezione piena: capienza massima raggiunta.
';
} else {
$stmtIns = $pdo->prepare("
INSERT INTO session_bookings (session_id, user_id, status, created_at, updated_at)
VALUES (?, ?, 'booked', NOW(), NOW())
");
$stmtIns->execute([$session_id, $user_id]);
$feedback = 'Partecipante aggiunto alla lezione!
';
}
}
}
}
}
}
// Mark lost
elseif ($action === 'mark_lost') {
$booking_id = (int)($_POST['booking_id'] ?? 0);
$stmt = $pdo->prepare("
UPDATE 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
SET sb.status = 'missed'
WHERE sb.id = ? AND c.school_id = ?
");
$stmt->execute([$booking_id, $school_id]);
$feedback = 'Presenza segnata come persa.
';
}
// Cancel booking
elseif ($action === 'cancel_booking') {
$booking_id = (int)($_POST['booking_id'] ?? 0);
$stmt = $pdo->prepare("
DELETE sb 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 c.school_id = ?
");
$stmt->execute([$booking_id, $school_id]);
$feedback = 'Prenotazione rimossa.
';
}
// Keep current month in redirect-less flow: we simply render again with the same ym from GET.
}
// === Sessions of selected month ===
$stmt = $pdo->prepare("
SELECT
cs.id AS session_id,
cs.session_date,
cs.start_time,
cs.end_time,
c.name AS class_name,
ct.level,
ct.room_name,
ct.max_capacity,
t.first_name,
t.last_name,
(SELECT COUNT(*)
FROM session_bookings sb
WHERE sb.session_id = cs.id
AND sb.status IN ('booked','attended','rescheduled')
) AS booked_count,
(SELECT GROUP_CONCAT(
CONCAT(sb.id,'|||',au.id,'|||',au.first_name,' ',au.last_name,'|||',au.email,'|||',COALESCE(au.phone,''),'|||',sb.status)
SEPARATOR ';;;'
)
FROM session_bookings sb
JOIN auth_users au ON sb.user_id = au.id
WHERE sb.session_id = cs.id
AND sb.status IN ('booked','attended','rescheduled','missed')
) AS booked_students_details
FROM class_sessions cs
JOIN class_types ct ON cs.class_type_id = ct.id
JOIN classes c ON ct.class_id = c.id
LEFT JOIN teachers t ON cs.teacher_id = t.id
WHERE c.school_id = ?
AND cs.session_date >= ?
AND cs.session_date < ?
ORDER BY cs.session_date, cs.start_time
");
$stmt->execute([$school_id, $startDate, $endDate]);
$sessions = $stmt->fetchAll(PDO::FETCH_ASSOC);
function humanMonthLabel($ym)
{
$dt = DateTime::createFromFormat('Y-m', $ym);
if (!$dt) return $ym;
return ucfirst($dt->format('F Y')); // if locale not set, this will be English
}
?>
Archivio Lezioni -
Archivio Lezioni -
Vedi le lezioni mese per mese con le stesse funzioni (prenotati, P/C, cancellazione con email).
Nessuna lezione trovata per il mese selezionato ().
Data
Orario
Classe
Livello
Sala
Insegnante
Prenotati
Azioni
Non assegnato'; ?>
0) ? "{$bc}/{$max}" : "{$bc}/∞";
?>
Cancella
(int)($parts[0] ?? 0),
'user_id' => (int)($parts[1] ?? 0),
'name' => $parts[2] ?? '',
'email' => $parts[3] ?? '',
'phone' => $parts[4] ?? '—',
'status' => $parts[5] ?? 'booked'
];
}
}
?>
0 && $bookedCnt >= $maxCap);
?>
Aggiungi partecipante
Capienza: 0 ? ($bookedCnt . '/' . $maxCap) : ($bookedCnt . '/∞'); ?>
Lezione piena: non puoi aggiungere altri partecipanti.
Nessun utente disponibile (tutti già presenti o nessun utente associato alla scuola).
Nessuno prenotato.
Nome
Email
Telefono
Stato
Azioni
P
C
Confermi di segnare come persa la lezione per ?
Confermi di rimuovere dalla lezione?