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();
?>
Indirizzo:
Email:
Telefono:
Sito Web:
Non specificato
Descrizione:
Categoria
Nome
Descrizione
Foto
Stato
Azioni
Nessuna foto
$class['category_id'],
"name" => htmlspecialchars($class['name'], ENT_QUOTES),
"description" => htmlspecialchars($class['description'] ?? '', ENT_QUOTES),
"requirements" => htmlspecialchars($class['requirements'] ?? '', ENT_QUOTES),
"status" => $class['status']
]); ?>)'
data-bs-toggle="tooltip" data-bs-placement="top" title="Modifica">
)'
data-bs-toggle="tooltip" data-bs-placement="top" title="Aggiungi Variazione">
Variazione
Nessuna variazione disponibile per questa classe.
Livello
Durata (min)
Posti Massimi
Giorno
Orario
Sala
Insegnante
Stato
Prenotati
Azioni
$variation['teacher_id']
]); ?>)'>
null
]); ?>)'>
Non assegnato
$variation['class_id'],
"level" => $variation['level'],
"typical_duration" => $variation['typical_duration'] ?? '',
"max_capacity" => $variation['max_capacity'],
"day_of_week" => $variation['day_of_week'],
"start_time" => $variation['start_time'],
"room_name" => htmlspecialchars($variation['room_name'] ?? '', ENT_QUOTES),
"notes" => htmlspecialchars($variation['notes'] ?? '', ENT_QUOTES),
"status" => $variation['status']
]); ?>)'
data-bs-toggle="tooltip" data-bs-placement="top" title="Modifica">
)'
data-bs-toggle="tooltip" data-bs-placement="top" title="Propaga">
Propaga
)'
data-bs-toggle="tooltip" data-bs-placement="top" title="Rimuovi Propagazione">
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): ?>
prenotati
$session['class_type_id'],
"session_date" => $session['session_date'],
"start_time" => $session['start_time'],
"end_time" => $session['end_time'],
"teacher_id" => $session['teacher_id'],
"status" => $session['status']
]); ?>)'>
Descrizione
Foto
Requisiti
Seleziona Insegnante
Nessun insegnante (Non assegnato)
Data
Insegnante
Nessun insegnante (Non assegnato)
Stato
Programmata
Completata
Annullata
0): ?>
Nome
Email
Telefono
Stato
Prenotato