getConnection(); // Verifica che iduserlogin sia definito if (!isset($iduserlogin)) { die("Errore: ID utente non definito."); } // Recupera i dati della scuola in base all'utente loggato $stmt = $pdo->prepare(" SELECT id, name, website, email, phone, description, address_street, address_city, address_postal_code, address_province, address_country, logo, status FROM schools WHERE owner_id = ? "); $stmt->execute([$iduserlogin]); $school = $stmt->fetch(); if (!$school) { die("Errore: Nessuna scuola trovata per l'utente loggato."); } $school_id = $school['id']; $school_name = $school['name']; // Recupera tutte le categorie disponibili $stmt = $pdo->prepare("SELECT id, name FROM class_categories WHERE status = 'active' ORDER BY name"); $stmt->execute(); $categories = $stmt->fetchAll(); // Recupera tutti gli insegnanti della scuola $stmt = $pdo->prepare("SELECT id, first_name, last_name FROM teachers WHERE user_id = ? AND status = 'active' ORDER BY first_name, last_name"); $stmt->execute([$iduserlogin]); $teachers = $stmt->fetchAll(); // Funzione per ridimensionare l'immagine function resizeImage($source_path, $dest_path, $max_width = 800) { list($width, $height, $type) = getimagesize($source_path); if ($width <= $max_width) { copy($source_path, $dest_path); return; } $new_width = $max_width; $new_height = (int)(($height * $new_width) / $width); switch ($type) { case IMAGETYPE_JPEG: $source = imagecreatefromjpeg($source_path); break; case IMAGETYPE_PNG: $source = imagecreatefrompng($source_path); break; case IMAGETYPE_GIF: $source = imagecreatefromgif($source_path); break; default: throw new Exception("Formato immagine non supportato."); } $dest = imagecreatetruecolor($new_width, $new_height); if ($type == IMAGETYPE_PNG) { imagealphablending($dest, false); imagesavealpha($dest, true); } imagecopyresampled($dest, $source, 0, 0, 0, 0, $new_width, $new_height, $width, $height); switch ($type) { case IMAGETYPE_JPEG: imagejpeg($dest, $dest_path, 90); break; case IMAGETYPE_PNG: imagepng($dest, $dest_path); break; case IMAGETYPE_GIF: imagegif($dest, $dest_path); break; } imagedestroy($source); imagedestroy($dest); } // Gestione delle azioni (aggiunta, modifica, cancellazione) if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (isset($_POST['action'])) { $action = $_POST['action']; // Aggiunta di una nuova classe if ($action === 'add') { $category_id = $_POST['category_id'] ?? 0; $name = $_POST['name'] ?? ''; $description = $_POST['description'] ?? null; $requirements = $_POST['requirements'] ?? null; $status = $_POST['status'] === 'active' ? 'active' : 'inactive'; if (empty($name) || $category_id <= 0) { $error = "I campi obbligatori non sono stati compilati."; } else { $photo = null; if (isset($_FILES['photo']) && $_FILES['photo']['error'] === UPLOAD_ERR_OK) { $file = $_FILES['photo']; $timestamp = time(); $original_name = basename($file['name']); $extension = strtolower(pathinfo($original_name, PATHINFO_EXTENSION)); $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif']; if (in_array($extension, $allowed_extensions)) { $new_filename = "photoclass/{$school_id}-{$timestamp}-{$original_name}"; $temp_path = $file['tmp_name']; try { resizeImage($temp_path, $new_filename); $photo = $new_filename; } catch (Exception $e) { $error = "Errore durante il ridimensionamento della foto: " . $e->getMessage(); } } else { $error = "Estensione del file non consentita. Usa JPG, JPEG, PNG o GIF."; } } if (!isset($error)) { $stmt = $pdo->prepare(" INSERT INTO classes (school_id, category_id, name, description, photo, requirements, status) VALUES (?, ?, ?, ?, ?, ?, ?) "); $success = $stmt->execute([ $school_id, $category_id, $name, $description, $photo, $requirements, $status ]); if ($success) { $success_message = "Classe aggiunta con successo!"; } else { $error = "Errore durante l'aggiunta della classe."; } } } } // Modifica di una classe esistente if ($action === 'edit') { $id = $_POST['id'] ?? 0; $category_id = $_POST['category_id'] ?? 0; $name = $_POST['name'] ?? ''; $description = $_POST['description'] ?? null; $requirements = $_POST['requirements'] ?? null; $status = $_POST['status'] === 'active' ? 'active' : 'inactive'; if (empty($name) || $category_id <= 0) { $error = "I campi obbligatori non sono stati compilati."; } else { // Recupera la classe esistente per ottenere il percorso della foto attuale $stmt = $pdo->prepare("SELECT photo FROM classes WHERE id = ? AND school_id = ?"); $stmt->execute([$id, $school_id]); $class = $stmt->fetch(); if (!$class) { $error = "Classe non trovata."; } else { $photo = $class['photo']; if (isset($_FILES['photo']) && $_FILES['photo']['error'] === UPLOAD_ERR_OK) { $file = $_FILES['photo']; $timestamp = time(); $original_name = basename($file['name']); $extension = strtolower(pathinfo($original_name, PATHINFO_EXTENSION)); $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif']; if (in_array($extension, $allowed_extensions)) { $new_filename = "photoclass/{$school_id}-{$timestamp}-{$original_name}"; $temp_path = $file['tmp_name']; try { resizeImage($temp_path, $new_filename); $photo = $new_filename; if ($class['photo'] && file_exists($class['photo'])) { unlink($class['photo']); } } catch (Exception $e) { $error = "Errore durante il ridimensionamento della foto: " . $e->getMessage(); } } else { $error = "Estensione del file non consentita. Usa JPG, JPEG, PNG o GIF."; } } if (!isset($error)) { $stmt = $pdo->prepare(" UPDATE classes SET category_id = ?, name = ?, description = ?, photo = ?, requirements = ?, status = ? WHERE id = ? AND school_id = ? "); $success = $stmt->execute([ $category_id, $name, $description, $photo, $requirements, $status, $id, $school_id ]); if ($success) { $success_message = "Classe aggiornata con successo!"; } else { $error = "Errore durante l'aggiornamento della classe."; } } } } } // Cancellazione di una classe if ($action === 'delete') { $id = $_POST['id'] ?? 0; $stmt = $pdo->prepare("SELECT photo FROM classes WHERE id = ? AND school_id = ?"); $stmt->execute([$id, $school_id]); $class = $stmt->fetch(); if ($class) { if ($class['photo'] && file_exists($class['photo'])) { unlink($class['photo']); } $stmt = $pdo->prepare("DELETE FROM classes WHERE id = ? AND school_id = ?"); $success = $stmt->execute([$id, $school_id]); if ($success) { $success_message = "Classe eliminata con successo!"; } else { $error = "Errore durante l'eliminazione della classe."; } } else { $error = "Classe non trovata."; } } // Aggiunta di una variazione if ($action === 'add_variation') { $class_id = $_POST['class_id'] ?? 0; $level = in_array($_POST['level'], ['beginner', 'intermediate', 'advanced']) ? $_POST['level'] : 'beginner'; $typical_duration = $_POST['typical_duration'] ? (int)$_POST['typical_duration'] : null; $max_capacity = $_POST['max_capacity'] ? (int)$_POST['max_capacity'] : 0; $day_of_week = in_array($_POST['day_of_week'], ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']) ? $_POST['day_of_week'] : null; $start_time = $_POST['start_time'] ?? ''; $room_name = $_POST['room_name'] ?? null; $notes = $_POST['notes'] ?? null; $status = $_POST['status'] === 'active' ? 'active' : 'inactive'; if ($class_id <= 0 || empty($day_of_week) || empty($start_time)) { $error = "I campi obbligatori non sono stati compilati."; } else { $photo = null; if (isset($_FILES['photo']) && $_FILES['photo']['error'] === UPLOAD_ERR_OK) { $file = $_FILES['photo']; $timestamp = time(); $original_name = basename($file['name']); $extension = strtolower(pathinfo($original_name, PATHINFO_EXTENSION)); $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif']; if (in_array($extension, $allowed_extensions)) { $new_filename = "photoclass/{$school_id}-{$timestamp}-{$original_name}"; $temp_path = $file['tmp_name']; try { resizeImage($temp_path, $new_filename); $photo = $new_filename; } catch (Exception $e) { $error = "Errore durante il ridimensionamento della foto: " . $e->getMessage(); } } else { $error = "Estensione del file non consentita. Usa JPG, JPEG, PNG o GIF."; } } if (!isset($error)) { $stmt = $pdo->prepare(" INSERT INTO class_types (class_id, school_id, level, typical_duration, max_capacity, day_of_week, start_time, room_name, notes, photo, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); $success = $stmt->execute([ $class_id, $school_id, $level, $typical_duration, $max_capacity, $day_of_week, $start_time, $room_name, $notes, $photo, $status ]); if ($success) { $success_message = "Variazione aggiunta con successo!"; } else { $error = "Errore durante l'aggiunta della variazione."; } } } } // Modifica di una variazione if ($action === 'edit_variation') { $id = $_POST['id'] ?? 0; $class_id = $_POST['class_id'] ?? 0; $level = in_array($_POST['level'], ['beginner', 'intermediate', 'advanced']) ? $_POST['level'] : 'beginner'; $typical_duration = $_POST['typical_duration'] ? (int)$_POST['typical_duration'] : null; $max_capacity = $_POST['max_capacity'] ? (int)$_POST['max_capacity'] : 0; $day_of_week = in_array($_POST['day_of_week'], ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']) ? $_POST['day_of_week'] : null; $start_time = $_POST['start_time'] ?? ''; $room_name = $_POST['room_name'] ?? null; $notes = $_POST['notes'] ?? null; $status = $_POST['status'] === 'active' ? 'active' : 'inactive'; if ($id <= 0 || $class_id <= 0 || empty($day_of_week) || empty($start_time)) { $error = "I campi obbligatori non sono stati compilati."; } else { // Recupera la variazione esistente per ottenere il percorso della foto attuale $stmt = $pdo->prepare("SELECT photo FROM class_types WHERE id = ? AND school_id = ? AND class_id = ?"); $stmt->execute([$id, $school_id, $class_id]); $variation = $stmt->fetch(); if (!$variation) { $error = "Variazione non trovata."; } else { $photo = $variation['photo']; if (isset($_FILES['photo']) && $_FILES['photo']['error'] === UPLOAD_ERR_OK) { $file = $_FILES['photo']; $timestamp = time(); $original_name = basename($file['name']); $extension = strtolower(pathinfo($original_name, PATHINFO_EXTENSION)); $allowed_extensions = ['jpg', 'jpeg', 'png', 'gif']; if (in_array($extension, $allowed_extensions)) { $new_filename = "photoclass/{$school_id}-{$timestamp}-{$original_name}"; $temp_path = $file['tmp_name']; try { resizeImage($temp_path, $new_filename); $photo = $new_filename; if ($variation['photo'] && file_exists($variation['photo'])) { unlink($variation['photo']); } } catch (Exception $e) { $error = "Errore durante il ridimensionamento della foto: " . $e->getMessage(); } } else { $error = "Estensione del file non consentita. Usa JPG, JPEG, PNG o GIF."; } } if (!isset($error)) { $stmt = $pdo->prepare(" UPDATE class_types SET level = ?, typical_duration = ?, max_capacity = ?, day_of_week = ?, start_time = ?, room_name = ?, notes = ?, photo = ?, status = ? WHERE id = ? AND school_id = ? AND class_id = ? "); $success = $stmt->execute([ $level, $typical_duration, $max_capacity, $day_of_week, $start_time, $room_name, $notes, $photo, $status, $id, $school_id, $class_id ]); if ($success) { $success_message = "Variazione aggiornata con successo!"; } else { $error = "Errore durante l'aggiornamento della variazione."; } } } } } // Cancellazione di una variazione if ($action === 'delete_variation') { $id = $_POST['id'] ?? 0; $class_id = $_POST['class_id'] ?? 0; $stmt = $pdo->prepare("SELECT photo FROM class_types WHERE id = ? AND school_id = ? AND class_id = ?"); $stmt->execute([$id, $school_id, $class_id]); $variation = $stmt->fetch(); if ($variation) { if ($variation['photo'] && file_exists($variation['photo'])) { unlink($variation['photo']); } $stmt = $pdo->prepare("DELETE FROM class_types WHERE id = ? AND school_id = ? AND class_id = ?"); $success = $stmt->execute([$id, $school_id, $class_id]); if ($success) { $success_message = "Variazione eliminata con successo!"; } else { $error = "Errore durante l'eliminazione della variazione."; } } else { $error = "Variazione non trovata."; } } // Assegnazione di un insegnante if ($action === 'assign_teacher') { $class_type_id = $_POST['class_type_id'] ?? 0; $teacher_id = !empty($_POST['teacher_id']) ? (int)$_POST['teacher_id'] : null; // Verifica che la variazione appartenga alla scuola $stmt = $pdo->prepare("SELECT id FROM class_types WHERE id = ? AND school_id = ?"); $stmt->execute([$class_type_id, $school_id]); if (!$stmt->fetch()) { $error = "Variazione non trovata."; } else { // Se teacher_id è null, rimuoviamo l'assegnazione; altrimenti, assegniamo l'insegnante $stmt = $pdo->prepare("UPDATE class_types SET teacher_id = ? WHERE id = ?"); $success = $stmt->execute([$teacher_id, $class_type_id]); if ($success) { $success_message = "Insegnante assegnato con successo!"; } else { $error = "Errore durante l'assegnazione dell'insegnante."; } } } // Propagazione delle sessioni if ($action === 'propagate_sessions') { $class_type_id = $_POST['class_type_id'] ?? 0; $start_date = $_POST['start_date'] ?? ''; $end_date = $_POST['end_date'] ?? ''; // Validazione delle date if (empty($start_date) || empty($end_date)) { $error = "Le date di inizio e fine sono obbligatorie."; } elseif (strtotime($end_date) < strtotime($start_date)) { $error = "La data di fine non può essere precedente alla data di inizio."; } else { // Verifica che la variazione appartenga alla scuola $stmt = $pdo->prepare(" SELECT ct.day_of_week, ct.start_time, ct.typical_duration, ct.teacher_id, ct.class_id, ct.school_id, ct.max_capacity, ct.notes FROM class_types ct WHERE ct.id = ? AND ct.school_id = ? "); $stmt->execute([$class_type_id, $school_id]); $variation = $stmt->fetch(); if (!$variation) { $error = "Variazione non trovata."; } else { // Recupera i giorni di chiusura della scuola $stmt = $pdo->prepare(" SELECT start_date, end_date FROM day_off WHERE school_id = ? AND ( (start_date BETWEEN ? AND ?) OR (end_date BETWEEN ? AND ?) OR (start_date <= ? AND end_date >= ?) ) "); $stmt->execute([ $school_id, $start_date, $end_date, $start_date, $end_date, $start_date, $end_date ]); $days_off = $stmt->fetchAll(); // Crea un array di giorni di chiusura $off_dates = []; foreach ($days_off as $day_off) { $current = new DateTime($day_off['start_date']); $end = new DateTime($day_off['end_date']); while ($current <= $end) { $off_dates[] = $current->format('Y-m-d'); $current->modify('+1 day'); } } // Mappa i giorni della settimana per il confronto $days_map = [ 'monday' => 'Monday', 'tuesday' => 'Tuesday', 'wednesday' => 'Wednesday', 'thursday' => 'Thursday', 'friday' => 'Friday', 'saturday' => 'Saturday', 'sunday' => 'Sunday' ]; $day_of_week_english = $days_map[$variation['day_of_week']]; // Calcola l'orario di fine $start_time = new DateTime($variation['start_time']); $end_time = clone $start_time; if ($variation['typical_duration']) { $end_time->modify("+{$variation['typical_duration']} minutes"); } else { $end_time->modify("+60 minutes"); // Default: 1 ora se la durata non è specificata } // Genera un propagation_id univoco $propagation_id = uniqid('prop_', true); // Genera le sessioni $current_date = new DateTime($start_date); $end_date_dt = new DateTime($end_date); $end_date_dt->setTime(23, 59, 59); // Include l'ultimo giorno // Prepara la query per verificare se una sessione esiste già $checkStmt = $pdo->prepare(" SELECT id FROM class_sessions WHERE class_type_id = ? AND session_date = ? "); // Prepara la query di inserimento $stmt = $pdo->prepare(" INSERT INTO class_sessions (class_id, school_id, class_type_id, session_date, start_time, end_time, teacher_id, max_capacity, notes, status, propagation_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'scheduled', ?) "); $sessions_created = 0; $sessions_skipped = 0; while ($current_date <= $end_date_dt) { $day_of_week = $current_date->format('l'); $current_date_str = $current_date->format('Y-m-d'); if (!in_array($current_date_str, $off_dates) && $day_of_week === $day_of_week_english) { $session_date = $current_date->format('Y-m-d'); $start_time_str = $start_time->format('H:i:s'); $end_time_str = $end_time->format('H:i:s'); // Verifica se una sessione esiste già per questa variazione e data $checkStmt->execute([$class_type_id, $session_date]); if ($checkStmt->fetch()) { $sessions_skipped++; continue; // Salta se esiste già } try { $stmt->execute([ $variation['class_id'], $variation['school_id'], $class_type_id, $session_date, $start_time_str, $end_time_str, $variation['teacher_id'], $variation['max_capacity'], $variation['notes'], $propagation_id ]); $sessions_created++; } catch (PDOException $e) { $error = "Errore durante la propagazione delle sessioni: " . $e->getMessage(); break; } } $current_date->modify('+1 day'); } if (!isset($error)) { $success_message = "Propagate $sessions_created sessioni con successo! (Saltate $sessions_skipped sessioni già esistenti) (ID Propagazione: $propagation_id)"; echo ""; } if (!isset($error)) { $success_message = "Propagate $sessions_created sessioni con successo! (ID Propagazione: $propagation_id)"; echo ""; } } } } // Rimozione di una propagazione if ($action === 'remove_propagation') { $propagation_id = $_POST['propagation_id'] ?? ''; $class_type_id = $_POST['class_type_id'] ?? 0; if (empty($propagation_id) || $class_type_id <= 0) { $error = "ID di propagazione o variazione non validi."; } else { // Verifica che la variazione appartenga alla scuola $stmt = $pdo->prepare("SELECT id FROM class_types WHERE id = ? AND school_id = ?"); $stmt->execute([$class_type_id, $school_id]); if (!$stmt->fetch()) { $error = "Variazione non trovata."; } else { // Elimina tutte le sessioni associate a questa propagazione $stmt = $pdo->prepare(" DELETE FROM class_sessions WHERE propagation_id = ? AND class_type_id = ? "); $stmt->execute([$propagation_id, $class_type_id]); $deleted_rows = $stmt->rowCount(); $success_message = "Propagazione rimossa con successo! ($deleted_rows sessioni eliminate)"; } } } // Cancellazione di una sessione if ($action === 'delete_session') { $id = $_POST['id'] ?? 0; // Verifica che la sessione appartenga alla scuola $stmt = $pdo->prepare(" SELECT cs.id 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([$id, $school_id]); if ($stmt->fetch()) { $stmt = $pdo->prepare("DELETE FROM class_sessions WHERE id = ?"); $success = $stmt->execute([$id]); if ($success) { $success_message = "Sessione eliminata con successo!"; } else { $error = "Errore durante l'eliminazione della sessione."; } } else { $error = "Sessione non trovata."; } } // Modifica di una sessione if ($action === 'edit_session') { $id = $_POST['id'] ?? 0; $class_type_id = $_POST['class_type_id'] ?? 0; $session_date = $_POST['session_date'] ?? ''; $start_time = $_POST['start_time'] ?? ''; $end_time = $_POST['end_time'] ?? ''; $teacher_id = !empty($_POST['teacher_id']) ? (int)$_POST['teacher_id'] : null; $status = in_array($_POST['status'], ['scheduled', 'completed', 'cancelled']) ? $_POST['status'] : 'scheduled'; if (empty($session_date) || empty($start_time) || empty($end_time)) { $error = "I campi obbligatori non sono stati compilati."; } elseif (strtotime($end_time) <= strtotime($start_time)) { $error = "L'orario di fine non può essere precedente o uguale all'orario di inizio."; } else { // Verifica che la sessione appartenga alla scuola $stmt = $pdo->prepare(" SELECT cs.id 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([$id, $school_id]); if (!$stmt->fetch()) { $error = "Sessione non trovata."; } else { $stmt = $pdo->prepare(" UPDATE class_sessions SET session_date = ?, start_time = ?, end_time = ?, teacher_id = ?, status = ? WHERE id = ? "); $success = $stmt->execute([ $session_date, $start_time, $end_time, $teacher_id, $status, $id ]); if ($success) { $success_message = "Sessione aggiornata con successo!"; } else { $error = "Errore durante l'aggiornamento della sessione."; } } } } // Non Reindirizza per evitare il doppio invio del form } } // Recupera tutte le classi della scuola con le loro variazioni $stmt = $pdo->prepare(" SELECT c.*, cc.name AS category_name FROM classes c LEFT JOIN class_categories cc ON c.category_id = cc.id WHERE c.school_id = ? ORDER BY c.created_at DESC "); $stmt->execute([$school_id]); $classes = $stmt->fetchAll(); // Recupera le variazioni per ogni classe $class_variations = []; foreach ($classes as $class) { $stmt = $pdo->prepare(" SELECT ct.*, t.first_name AS teacher_first_name, t.last_name AS teacher_last_name FROM class_types ct LEFT JOIN teachers t ON ct.teacher_id = t.id WHERE ct.class_id = ? AND ct.school_id = ? ORDER BY ct.day_of_week, ct.start_time "); $stmt->execute([$class['id'], $school_id]); $class_variations[$class['id']] = $stmt->fetchAll(); } // Recupera la data selezionata per le sessioni della giornata (default: oggi) $selected_date = $_GET['session_date'] ?? date('Y-m-d'); $selected_date_dt = new DateTime($selected_date); $day_of_week_english = $selected_date_dt->format('l'); // Giorno della settimana in inglese (es. Monday) // Mappa i giorni della settimana per il confronto $days_map_reverse = [ 'Monday' => 'monday', 'Tuesday' => 'tuesday', 'Wednesday' => 'wednesday', 'Thursday' => 'thursday', 'Friday' => 'friday', 'Saturday' => 'saturday', 'Sunday' => 'sunday' ]; $day_of_week = $days_map_reverse[$day_of_week_english]; // Recupera le sessioni per la data selezionata $stmt = $pdo->prepare(" SELECT cs.*, ct.level, ct.day_of_week, ct.start_time, ct.room_name, ct.teacher_id, c.name AS class_name, c.photo AS class_photo, ct.photo AS variation_photo, t.first_name AS teacher_first_name, t.last_name AS teacher_last_name 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 cs.session_date = ? AND ct.day_of_week = ? AND c.school_id = ? ORDER BY cs.start_time "); $stmt->execute([$selected_date, $day_of_week, $school_id]); $daily_sessions = $stmt->fetchAll(); ?>
Logo Scuola

Indirizzo:

Email:

Telefono:

Sito Web: Non specificato

Descrizione:

Classi della scuola
Categoria Nome Descrizione Foto Stato Azioni
Foto Classe Nessuna foto

Nessuna variazione disponibile per questa classe.

Livello Durata (min) Posti Massimi Giorno Orario Sala Insegnante Stato Prenotati Azioni
Sessioni Programmata
Oggi
La data di fine non può essere precedente alla data di inizio.
'; $end_date = $start_date; } // Recupera tutte le sessioni nell'intervallo // === NUOVA QUERY CON CONTEGGIO E LISTA PRENOTATI === $stmt = $pdo->prepare(" SELECT cs.*, ct.level, ct.day_of_week, ct.start_time AS ct_start_time, ct.room_name, ct.teacher_id, c.name AS class_name, c.photo AS class_photo, ct.photo AS variation_photo, t.first_name AS teacher_first_name, t.last_name AS teacher_last_name, -- Contiamo gli studenti prenotati (solo booked, attended, rescheduled) (SELECT COUNT(*) FROM session_bookings sb WHERE sb.session_id = cs.id AND sb.status IN ('booked', 'attended', 'rescheduled') ) AS booked_count, -- Capacità massima (da class_sessions o da class_types se null) COALESCE(cs.max_capacity, ct.max_capacity, 0) AS effective_capacity, -- Lista studenti prenotati (per il modale) (SELECT GROUP_CONCAT( CONCAT(au.first_name, ' ', au.last_name, '|', au.email, '|', COALESCE(au.phone, '')) 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') ) AS booked_students 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 cs.session_date BETWEEN ? AND ? AND c.school_id = ? ORDER BY cs.session_date, cs.start_time "); $stmt->execute([$start_date, $end_date, $school_id]); $range_sessions = $stmt->fetchAll(); ?>
Sessioni del Sessioni dal al ( totali)
Data Classe Livello Orario Sala Insegnante Stato Prenotati Azioni
Nessuna sessione programmata in questo intervallo.
- Non assegnato'; ?> 0 ? $session['effective_capacity'] : '∞'; $color = ($capacity !== '∞' && $booked >= $capacity) ? 'danger' : 'success'; ?>
0): ?>