Server Error The booking service is currently unavailable. Please try again later or contact support [closed]

The main purpose of the code below is for a booking session. Each time I click on the book a session button on the pop-up modal window I get Server Error The booking service is currently unavailable. Please try again later or contact support.

–booking.php–

<?php
// booking.php
require_once 'config.php';

use PHPMailerPHPMailerPHPMailer;
use PHPMailerPHPMailerException;

require __DIR__ . '/../assets/vendor/autoload.php';

header('Content-Type: application/json; charset=UTF-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, X-Requested-With');
header('Access-Control-Allow-Credentials: true');

// Handle preflight OPTIONS
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {

    http_response_code(200);
    exit;
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(["status" => "error", "message" => "Invalid request method"]);
    exit;
}

// Parse JSON
$raw = file_get_contents("php://input");
$input = json_decode($raw, true);

if (!$input) {
    echo json_encode([
        "status" => "error",
        "message" => "Invalid or empty JSON",
        "debug" => (APP_ENV === 'development' ? $raw : null)
    ]);

    exit;
}

// Required fields
$required = ['full_name', 'email', 'phone', 'subject', 'session_type', 'date', 'time', 'details'];

foreach ($required as $field) {

    if (empty($input[$field])) {
        echo json_encode([
            "status" => "error",
            "message" => "Missing required field: $field",
            "debug" => (APP_ENV === 'development' ? $input : null)
        ]);

        exit;
    }
}

// Core fields
$full_name = trim($input['full_name']);
$email = filter_var($input['email'], FILTER_VALIDATE_EMAIL);
$phone = trim($input['phone']);
$subject = trim($input['subject']);
$session_type = trim($input['session_type']);

$date = $input['date'];
$time = $input['time'];
$details = trim($input['details']);
$role = $input['role'] ?? null;

if (!$email) {
    echo json_encode(["status" => "error", "message" => "Invalid email address"]);
    exit;
}

// Optional fields (set null if missing)
$optionalFields = [
'current_challenges','personal_goals','group_size','group_type','group_objectives',
'institution_type','institution_name','educational_goals','org_size','org_sector',
'dev_focus','leadership_level','leadership_challenges','dev_areas','transformation_scope',
'current_state','desired_outcome','timeline'
];


foreach ($optionalFields as $field) {
    $$field = $input[$field] ?? null;
}

try {
    // Save booking
    $stmt = $pdo->prepare("INSERT INTO bookings 
   (full_name,email,phone,subject,session_type,date,time,details,role,
current_challenges,personal_goals,group_size,group_type,group_objectives,
         institution_type,institution_name,educational_goals,
         org_size,org_sector,dev_focus,
         leadership_level,leadership_challenges,dev_areas,
         transformation_scope,current_state,desired_outcome,timeline)
        VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");

    $stmt->execute([
        $full_name, $email, $phone, $subject, $session_type, $date, $time, $details, $role,
$current_challenges,$personal_goals,$group_size,$group_type,$group_objectives,
        $institution_type,$institution_name,$educational_goals,
        $org_size,$org_sector,$dev_focus,
        $leadership_level,$leadership_challenges,$dev_areas,
        $transformation_scope,$current_state,$desired_outcome,$timeline
    ]);

    $booking_id = $pdo->lastInsertId();

    // Send Admin Email
    try {
        $mail = new PHPMailer(true);
        $mail->isSMTP();
        $mail->Host = 'smtp.gmail.com';
        $mail->SMTPAuth = true;
        $mail->Username = MAIL_FROM;
        $mail->Password = MAIL_PASS;
        $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
        $mail->Port = 587;
        $mail->setFrom(MAIL_FROM, 'Booking System');
        $mail->addAddress(MAIL_TO);
        $mail->isHTML(true);
        $mail->Subject = "New Booking (#$booking_id): $session_type by $full_name";

        $mail->Body = "
            <h2>New Booking Received</h2>
            <p><strong>Name:</strong> $full_name</p>
            <p><strong>Email:</strong> $email</p>
            <p><strong>Phone:</strong> $phone</p>
            <p><strong>Subject:</strong> $subject</p>
            <p><strong>Session:</strong> $session_type</p>
            <p><strong>Date:</strong> $date</p>
            <p><strong>Time:</strong> $time</p>
            <p><strong>Details:</strong><br>" . nl2br($details) . "</p>";
        $mail->send();

    } catch (Exception $e) {
        error_log("Email Error (Admin): " . $e->getMessage());
        echo json_encode(["status"=>"error","message"=>"Email error (admin)","debug"=>(APP_ENV==='development'?$e->getMessage():null)]);
        exit;
    }

    // Send Customer Confirmation
    try {
        $mail = new PHPMailer(true);
        $mail->isSMTP();
        $mail->Host = 'smtp.gmail.com';
        $mail->SMTPAuth = true;
        $mail->Username = MAIL_FROM;
        $mail->Password = MAIL_PASS;
        $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
        $mail->Port = 587;

        $mail->setFrom(MAIL_FROM, '360 Sages');
        $mail->addAddress($email);
        $mail->isHTML(true);
        $mail->Subject = "Booking Confirmation - $session_type";
        $mail->Body = "
            <h2>Hello $full_name,</h2>
            <p>Thank you for booking a <strong>$session_type</strong> session with us.</p>
            <p><strong>Date:</strong> $date</p>
            <p><strong>Time:</strong> $time</p>
            <p>We’ll contact you soon with further details.</p>
            <br>
            <p>Best regards,<br>360 Sages Team</p>";

        $mail->send();
    } catch (Exception $e) {
        error_log("Email Error (Customer): " . $e->getMessage());
        echo json_encode(["status"=>"error","message"=>"Email error (customer)","debug"=>(APP_ENV==='development'?$e->getMessage():null)]);
        exit;
    }

    echo json_encode(["status"=>"success","message"=>"Booking submitted successfully!"]);

} catch (PDOException $e) {
    error_log("Database Error: " . $e->getMessage());
    echo json_encode([
        "status" => "error",
        "message" => "Database error while saving booking",
        "debug" => (APP_ENV === 'development' ? $e->getMessage() : null)
    ]);

    exit;
}

--script.js--
document.addEventListener("DOMContentLoaded", function () {
  const bookingForm = document.getElementById("bookingForm");
  const sessionTypeSelect = document.getElementById("session_type");

  // Inject CSS for shake + label highlight + SweetAlert error color + success glow

  if (!document.getElementById("error-style")) {
    const style = document.createElement("style");
    style.id = "error-style";
    style.textContent = `

      .field-error {
        border: 2px solid red !important;
        animation: shake 0.3s ease-in-out;
      }

      .label-error {
        color: red !important;
        font-weight: bold;
      }

      .form-success {
        animation: glowSuccess 1s ease-in-out;
      }

      .swal2-popup.swal2-toast .swal2-title,
      .swal2-popup .swal2-title,
      .swal2-popup .swal2-html-container {
        color: red !important;
      }

      @keyframes shake {
        0% { transform: translateX(0); }
        25% { transform: translateX(-5px); }
        50% { transform: translateX(5px); }
        75% { transform: translateX(-5px); }
        100% { transform: translateX(0); }
      }

      @keyframes glowSuccess {
        0% { box-shadow: 0 0 0px rgba(0,255,0,0); }
        50% { box-shadow: 0 0 15px rgba(0,255,0,0.7); }
        100% { box-shadow: 0 0 0px rgba(0,255,0,0); }
      }
    `;

    document.head.appendChild(style);
  }

  if (bookingForm) {
    bookingForm.addEventListener("submit", async (e) => {
      e.preventDefault();
      const formDataObj = {};
      const invalidFields = [];

      function getFieldLabel(el) {
        const label = bookingForm.querySelector(`label[for="${el.id}"]`);
        return label ? label.textContent.trim() : el.name.replace("_", " ");
      }

      bookingForm.querySelectorAll("input, textarea, select").forEach((el) => {

        if (el.name) {
          const value = el.value.trim();
          formDataObj[el.name] = value;
          const label = bookingForm.querySelector(`label[for="${el.id}"]`);

          if (label) label.classList.remove("label-error");

          el.classList.remove("field-error");

          if (el.hasAttribute("required") && !value) {

            invalidFields.push({ field: el, message: `${getFieldLabel(el)} is required.` });
          }

          if (el.type === "email" && value) {
            const emailRegex = /^[^s@]+@[^s@]+.[^s@]+$/;

            if (!emailRegex.test(value)) {
              invalidFields.push({ field: el, message: `Please enter a valid ${getFieldLabel(el)}.` });
            }
          }

          if (el.type === "tel" && value) {
            const phoneDigits = value.replace(/D/g, "");

            if (phoneDigits.length < 7) {
              invalidFields.push({ field: el, message: `${getFieldLabel(el)} must have at least 7 digits.` });
            }
          }
        }
      });

      formDataObj.session_type = sessionTypeSelect.value;

      for (const invalid of invalidFields) {
        const field = invalid.field;
        const label = bookingForm.querySelector(`label[for="${field.id}"]`);

        field.classList.add("field-error");

        if (label) label.classList.add("label-error");

        field.scrollIntoView({ behavior: "smooth", block: "center" });

        await Swal.fire({
          icon: "error",
          title: "Invalid Field",
          html: `<span style="color:red; font-weight:bold;">⚠️ ${invalid.message}</span>`,
          confirmButtonColor: "#152942",
          didClose: () => {
            field.focus();
            field.classList.remove("field-error");

            if (label) label.classList.remove("label-error");
          },
        });
      }

      if (invalidFields.length > 0) return;

      Swal.fire({
        title: "Submitting...",
        text: "Please wait while we process your booking.",
        allowOutsideClick: false,
        didOpen: () => Swal.showLoading(),
      });

      try {
        const apiUrl = new URL(
          "includes/booking.php",
          window.location.origin + window.location.pathname
        ).href;

        const response = await fetch(apiUrl, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(formDataObj),
        });

        const result = await response.json();

        if (result.status === "success") {
          window.scrollTo({ top: 0, behavior: "smooth" });

          // Add subtle green glow animation
          bookingForm.classList.add("form-success");
          setTimeout(() => bookingForm.classList.remove("form-success"), 1000);


          Swal.fire({
            icon: "success",
            title: "Booking Confirmed",
            text: result.message,
            confirmButtonColor: "#152942",
          });

          bookingForm.reset();

          if (typeof closeModal === "function") closeModal();

        } else {
          let errorMsg = "Booking failed. Please try again.";

          if (result.message.includes("Database")) errorMsg = "Database Error: Unable to save your booking.";

          else if (result.message.includes("Email error (admin)")) errorMsg = "Email Error: Failed to notify admin.";

          else if (result.message.includes("Email error (customer)")) errorMsg = "Email Error: Failed to send confirmation to your email.";

          Swal.fire({
            icon: "error",
            title: "Error",
            html: `<span style="color:red; font-weight:bold;">${errorMsg}</span>`,
            confirmButtonColor: "#152942",
          });

          if (result.debug) console.error("Debug Info:", result.debug);
        }
      } catch (error) {
        console.error("Error:", error);

        Swal.fire({
          icon: "error",
          title: "Server Error",
          html: `<span style="color:red; font-weight:bold;">⚠️ The booking service is unavailable.</span>`,
          confirmButtonColor: "#152942",
        });
      }
    });
  }
}
);