diff --git a/public/userarea/include/headscript.php b/public/userarea/include/headscript.php index 169d203..444fb62 100644 --- a/public/userarea/include/headscript.php +++ b/public/userarea/include/headscript.php @@ -63,3 +63,6 @@ $_SESSION["emailuser"] = $emailuser; $_SESSION["photouser"] = $avatar; $photouser = $_SESSION["photouser"]; + +// include school settings +include('school_settings_loader.php'); diff --git a/public/userarea/include/navbar.php b/public/userarea/include/navbar.php index 17d1734..13895f6 100644 --- a/public/userarea/include/navbar.php +++ b/public/userarea/include/navbar.php @@ -24,12 +24,14 @@ -
  • - -
    - -
    -
  • + +
  • + +
    + +
    +
  • +
  • diff --git a/public/userarea/include/school_settings_loader.php b/public/userarea/include/school_settings_loader.php new file mode 100644 index 0000000..a93617c --- /dev/null +++ b/public/userarea/include/school_settings_loader.php @@ -0,0 +1,70 @@ + 0, + 'allowed_product_types' => 'subscription,carnet,drop_in', + 'payment_methods' => 'manual', + 'currency_code' => 'EUR', + 'enable_notifications' => 1, + 'allow_freeze_global' => 1, + 'freeze_max_days_global' => 30, + 'auto_propagate_on_purchase' => 1, + 'allow_full_access_rebooking' => 1, + // ... aggiungi tutti gli altri campi con default sensati + ]; +} else { + $pdo = DBHandlerSelect::getInstance()->getConnection(); + + $stmt = $pdo->prepare(" + SELECT * + FROM school_settings + WHERE school_id = ? + LIMIT 1 + "); + $stmt->execute([$school_id]); + $settings = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($settings) { + $schoolSettings = $settings; + } else { + // Scuola senza impostazioni → crea record con default + $stmt_insert = $pdo->prepare(" + INSERT INTO school_settings (school_id) VALUES (?) + "); + $stmt_insert->execute([$school_id]); + + // Ricarica dopo insert + $stmt = $pdo->prepare("SELECT * FROM school_settings WHERE school_id = ? LIMIT 1"); + $stmt->execute([$school_id]); + $schoolSettings = $stmt->fetch(PDO::FETCH_ASSOC) ?: []; + } + + // Fallback per campi che potrebbero essere NULL + $schoolSettings = array_merge([ + 'portal_purchases_enabled' => 1, + 'allowed_product_types' => 'subscription,carnet,drop_in', + 'payment_methods' => 'manual', + 'currency_code' => 'EUR', + 'enable_notifications' => 1, + 'allow_freeze_global' => 1, + 'freeze_max_days_global' => 30, + 'auto_propagate_on_purchase' => 1, + 'allow_full_access_rebooking' => 1, + // ... tutti gli altri campi che vuoi default + ], $schoolSettings); +} + +// Trasforma stringhe separate da virgola in array (molto comodo) +$schoolSettings['payment_methods_array'] = array_filter(explode(',', $schoolSettings['payment_methods'] ?? '')); +$schoolSettings['allowed_product_types_array'] = array_filter(explode(',', $schoolSettings['allowed_product_types'] ?? '')); diff --git a/public/userarea/my_lessons.php b/public/userarea/my_lessons.php index 4f05d4d..9268dbf 100644 --- a/public/userarea/my_lessons.php +++ b/public/userarea/my_lessons.php @@ -219,6 +219,12 @@ $has_valid_cert = ($cert_result['valid_count'] > 0);
    + +
    + + +
    +
    @@ -357,6 +363,10 @@ $has_valid_cert = ($cert_result['valid_count'] > 0); } }); }; + + const reschedule = id => { + location = 'reschedule.php?booking=' + id; + }; diff --git a/public/userarea/reschedule.php b/public/userarea/reschedule.php new file mode 100644 index 0000000..d0bb07f --- /dev/null +++ b/public/userarea/reschedule.php @@ -0,0 +1,500 @@ +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))); +} + +?> + + + + + + + + Riprogramma Lezione - YoGiBook + + + + + + +
    + + + +
    +
    + +
    +

    Riprogramma lezione

    +

    + + - +

    +

    + + dalle + alle +

    +
    + + + +
    + +
    + + +
    + + + +
    + + +
    + + +
    + +
    + +
    Nessuna lezione disponibile per la riprogrammazione
    +
    + + + = $lesson['max_capacity']; + $is_user_booked = $lesson['user_booked'] > 0; + $card_class = $is_full ? 'full' : ($is_user_booked ? 'user-booked' : 'available'); + ?> +
    +
    +
    +
    +
    + +
    +
    + +
    +

    + + + - + +

    + +
    + + - +
    + +
    + + + - +
    + +
    + + +
    + +
    + Posti liberi: +
    + + +
    + Lezione piena +
    + +
    + Già prenotata da te +
    + +
    +
    + + +
    + +
    + +
    +
    +
    + + +
    +
    +
    +
    + + +
    + + + + + + + + \ No newline at end of file diff --git a/public/userarea/school_settings.php b/public/userarea/school_settings.php index 531d054..9dc4a76 100644 --- a/public/userarea/school_settings.php +++ b/public/userarea/school_settings.php @@ -23,6 +23,10 @@ if ($settings && !array_key_exists('portal_purchases_enabled', $settings)) { $settings['portal_purchases_enabled'] = 1; } +if ($settings && !array_key_exists('rebooking_auto_approved', $settings)) { + $settings['rebooking_auto_approved'] = 1; +} + $is_new = !$settings; $success_message = $error = ""; @@ -55,6 +59,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $portal_purchases_enabled = !empty($_POST['portal_purchases_enabled']) ? 1 : 0; + $rebooking_auto_approved = !empty($_POST['rebooking_auto_approved']) ? 1 : 0; // Se acquisti portale disabilitati → forza anche propagate a 0 $auto_propagate_on_purchase = $portal_purchases_enabled @@ -68,8 +73,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { school_id, header_color, sidebar_color, payment_methods, currency_code, enable_notifications, allow_freeze_global, freeze_max_days_global, auto_propagate_on_purchase, allow_full_access_rebooking, allowed_product_types, - portal_purchases_enabled - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + portal_purchases_enabled, rebooking_auto_approved + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); $stmt->execute([ $school_id, @@ -83,7 +88,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $auto_propagate_on_purchase, $allow_full_access_rebooking, $allowed_product_types, - $portal_purchases_enabled + $portal_purchases_enabled, + $rebooking_auto_approved ]); $success_message = "Impostazioni create con successo!"; } else { @@ -92,7 +98,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { header_color = ?, sidebar_color = ?, payment_methods = ?, currency_code = ?, enable_notifications = ?, allow_freeze_global = ?, freeze_max_days_global = ?, auto_propagate_on_purchase = ?, allow_full_access_rebooking = ?, allowed_product_types = ?, - portal_purchases_enabled = ? + portal_purchases_enabled = ?, rebooking_auto_approved = ? WHERE school_id = ? "); $stmt->execute([ @@ -107,8 +113,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $allow_full_access_rebooking, $allowed_product_types, $portal_purchases_enabled, + $rebooking_auto_approved, $school_id - ]); $success_message = "Impostazioni aggiornate con successo!"; } @@ -292,6 +298,24 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    +
    + + +
    Approvazioni e Lezioni
    + +
    +
    + > + +
    + + Se disattivato, ogni richiesta di riprogrammazione dovrà essere approvata manualmente dalla segreteria. + +
    +
    - -
    - -
    -
    -
    -

    -

    Lezioni acquistate totali

    + +
    + +
    +
    +
    +

    +

    Acquistate

    - -
    -
    -
    -

    -

    Lezioni da praticare

    + +
    +
    +
    +

    +

    Praticate

    - -
    -
    -
    -

    -

    Lezioni perse

    + +
    +
    +
    +

    +

    Da praticare

    - -
    -
    -
    -

    Prossimamente...

    + +
    +
    +
    +

    +

    Perse

    +
    +
    +
    + + +
    +
    +
    +

    +

    Da programmare