34950-vm/register.php
Flatlogic Bot f8e0cdfba4 my latest
2025-10-17 10:14:29 +00:00

339 lines
17 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
require_once 'db/config.php';
require_once 'mail/MailService.php';
// --- CONFIGURATION ---
$webinar_id = filter_input(INPUT_GET, 'webinar_id', FILTER_VALIDATE_INT);
$response = [];
// --- WEBINAR DETAILS ---
$webinar = null;
if ($webinar_id) {
try {
$stmt = $pdo->prepare("SELECT title, description, starts_at, ends_at FROM webinars WHERE id = ?");
$stmt->execute([$webinar_id]);
$webinar = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
// Log error, but don't show to user
}
}
// --- FORM SUBMISSION (POST REQUEST) ---
if ($_SERVER["REQUEST_METHOD"] == "POST") {
header('Content-Type: application/json');
// --- DATA CAPTURE ---
$webinar_id = filter_input(INPUT_POST, 'webinar_id', FILTER_VALIDATE_INT);
$webinar = null;
if ($webinar_id) {
try {
$stmt = $pdo->prepare("SELECT title, description, starts_at, ends_at FROM webinars WHERE id = ?");
$stmt->execute([$webinar_id]);
$webinar = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
// Log error, but don't show to user
}
}
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$first_name = filter_input(INPUT_POST, 'first_name', FILTER_SANITIZE_STRING);
$last_name = filter_input(INPUT_POST, 'last_name', FILTER_SANITIZE_STRING);
$company = filter_input(INPUT_POST, 'company', FILTER_SANITIZE_STRING);
$how_did_you_hear = filter_input(INPUT_POST, 'how_did_you_hear', FILTER_SANITIZE_STRING);
$password = filter_input(INPUT_POST, 'password', FILTER_UNSAFE_RAW);
$confirm_password = filter_input(INPUT_POST, 'confirm_password', FILTER_UNSAFE_RAW);
$timezone = filter_input(INPUT_POST, 'timezone', FILTER_SANITIZE_STRING);
// Tracking data
$utm_source = filter_input(INPUT_POST, 'utm_source', FILTER_SANITIZE_STRING);
$utm_medium = filter_input(INPUT_POST, 'utm_medium', FILTER_SANITIZE_STRING);
$utm_campaign = filter_input(INPUT_POST, 'utm_campaign', FILTER_SANITIZE_STRING);
$utm_term = filter_input(INPUT_POST, 'utm_term', FILTER_SANITIZE_STRING);
$utm_content = filter_input(INPUT_POST, 'utm_content', FILTER_SANITIZE_STRING);
$referrer = filter_input(INPUT_POST, 'referrer', FILTER_SANITIZE_STRING);
$gclid = filter_input(INPUT_POST, 'gclid', FILTER_SANITIZE_STRING);
$fbclid = filter_input(INPUT_POST, 'fbclid', FILTER_SANITIZE_STRING);
if (!$first_name || !$last_name || !$email) {
$response['error'] = 'Please fill out all required fields.';
echo json_encode($response);
exit;
}
if (!$webinar) {
$response['error'] = 'Webinar not found.';
echo json_encode($response);
exit;
}
if ($password !== $confirm_password) {
$response['error'] = 'Passwords do not match.';
echo json_encode($response);
exit;
}
$password_hash = password_hash($password, PASSWORD_DEFAULT);
try {
// Check for duplicates
$stmt = db()->prepare("SELECT id FROM attendees WHERE webinar_id = ? AND email = ?");
$stmt->execute([$webinar_id, $email]);
if ($stmt->fetch()) {
$response['error'] = 'You are already registered for this webinar.';
echo json_encode($response);
exit;
}
// Insert attendee
$sql = "INSERT INTO attendees (webinar_id, first_name, last_name, email, company, how_did_you_hear, password, timezone, utm_source, utm_medium, utm_campaign, utm_term, utm_content, referrer, gclid, fbclid)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = db()->prepare($sql);
$stmt->execute([$webinar_id, $first_name, $last_name, $email, $company, $how_did_you_hear, $password_hash, $timezone, $utm_source, $utm_medium, $utm_campaign, $utm_term, $utm_content, $referrer, $gclid, $fbclid]);
$attendee_id = db()->lastInsertId();
// --- SEND CONFIRMATION EMAIL ---
$webinar_date = new DateTime($webinar['starts_at']);
$subject = "Confirmation: You're Registered for " . $webinar['title'];
$body_html = "<h1>You're in!</h1>"
. "<p>Thanks for registering for our webinar: <strong>{$webinar['title']}</strong>.</p>"
. "<p>It will take place on <strong>" . $webinar_date->format('l, F j, Y \a\t g:i A T') . "</strong>.</p>"
. "<p>You can now log in to your dashboard to see the details.</p>";
MailService::sendMail($email, $subject, $body_html);
$response['success'] = true;
$response['webinar_title'] = $webinar['title'];
$response['webinar_date_utc'] = $webinar['starts_at'];
} catch (PDOException $e) {
// Log error
$response['error'] = 'A database error occurred. Please try again later.';
} catch (Exception $e) {
// Log error
$response['error'] = 'An error occurred: ' . $e->getMessage();
}
echo json_encode($response);
exit;
}
// --- RENDER PAGE (GET REQUEST) ---
if (!$webinar) {
http_response_code(404);
echo "Webinar not found.";
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register for <?= htmlspecialchars($webinar['title']) ?></title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background-color: #1a202c; color: #e2e8f0; margin: 0; padding: 2rem; }
.container { max-width: 900px; margin: auto; display: grid; grid-template-columns: 1fr 1fr; gap: 4rem; align-items: start; }
.left-pane h1 { font-size: 2.5rem; color: #f6e05e; margin-bottom: 1rem; }
.left-pane .date-time { font-size: 1.25rem; font-weight: bold; margin-bottom: 1.5rem; }
.left-pane .value-prop { font-size: 1.1rem; color: #a0aec0; line-height: 1.6; }
.speakers { margin-top: 2rem; }
.speakers h3 { font-size: 1.2rem; color: #cbd5e0; margin-bottom: 1rem; }
.speaker { display: flex; align-items: center; margin-bottom: 1rem; }
.speaker img { width: 50px; height: 50px; border-radius: 50%; margin-right: 1rem; background-color: #4a5568; }
.form-card { background-color: #2d3748; border-radius: 0.5rem; padding: 2rem; border: 1px solid #4a5568; }
.form-card h2 { margin-top: 0; font-size: 1.5rem; color: #f6e05e; text-align: center; }
.form-group { margin-bottom: 1.5rem; }
label { display: block; margin-bottom: 0.5rem; font-weight: bold; }
input[type="email"], input[type="text"], input[type="password"] { width: 100%; padding: 0.75rem; background-color: #1a202c; border: 1px solid #4a5568; border-radius: 0.375rem; color: #e2e8f0; font-size: 1rem; box-sizing: border-box; }
.submit-btn { display: block; width: 100%; background-color: #f6e05e; color: #1a202c; padding: 0.85rem; border: none; border-radius: 0.375rem; font-weight: bold; font-size: 1.125rem; cursor: pointer; transition: background-color 0.2s; }
.submit-btn:hover { background-color: #f6d32d; }
.submit-btn:disabled { background-color: #4a5568; cursor: not-allowed; }
#form-result { margin-top: 1.5rem; text-align: center; }
.success-message { background-color: #2d3748; border: 1px solid #4a5568; padding: 2rem; border-radius: 0.5rem; text-align: center; }
.error-message { background-color: #c53030; padding: 1rem; border-radius: 0.375rem; }
.calendar-buttons a { display: inline-block; background-color: #4a5568; color: #e2e8f0; padding: 0.75rem 1.5rem; border-radius: 0.375rem; text-decoration: none; margin: 0.5rem; font-weight: bold; }
@media (max-width: 768px) { .container { grid-template-columns: 1fr; } }
</style>
</head>
<body>
<header style="padding: 1rem;">
<a href="index.php" style="color: #1a202c; text-decoration: none; background-color: #f6e05e; padding: 0.75rem 1.5rem; border-radius: 0.375rem; font-weight: bold; font-size: 1.125rem;">Back to Home</a>
</header>
<div class="container">
<div class="left-pane">
<h1><?= htmlspecialchars($webinar['title']) ?></h1>
<div class="date-time" id="local-date-time">Loading date...</div>
<p class="value-prop"><?= htmlspecialchars($webinar['description']) ?></p>
<div class="speakers">
<h3>Speakers</h3>
<div class="speaker"><img src="assets/images/pexels/22601971.jpg" alt="Philip Daineka"> <span>Philip Daineka</span></div>
<div class="speaker"><img src="assets/images/pexels/34285016.jpg" alt="Alex Rubanau"> <span>Alex Rubanau</span></div>
<div class="speaker"><img src="assets/images/pexels/34238049.jpg" alt="Alexey Vertel"> <span>Alexey Vertel</span></div>
</div>
</div>
<div class="right-pane">
<div id="registration-form-container">
<form id="registration-form" class="form-card" method="POST">
<h2>Register & Get Calendar Invite</h2>
<div class="form-group">
<label for="email">Email (required)</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="first_name">First name</label>
<input type="text" id="first_name" name="first_name" required>
</div>
<div class="form-group">
<label for="last_name">Last name</label>
<input type="text" id="last_name" name="last_name" required>
</div>
<div class="form-group">
<label for="company">Company</label>
<input type="text" id="company" name="company">
</div>
<div class="form-group">
<label for="how_did_you_hear">How did you hear about this webinar?</label>
<input type="text" id="how_did_you_hear" name="how_did_you_hear">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<div class="form-group">
<label for="confirm_password">Confirm Password</label>
<input type="password" id="confirm_password" name="confirm_password" required>
</div>
<input type="hidden" name="webinar_id" value="<?= $webinar_id ?>">
<input type="hidden" name="timezone" id="timezone">
<input type="hidden" name="utm_source" id="utm_source">
<input type="hidden" name="utm_medium" id="utm_medium">
<input type="hidden" name="utm_campaign" id="utm_campaign">
<input type="hidden" name="utm_term" id="utm_term">
<input type="hidden" name="utm_content" id="utm_content">
<input type="hidden" name="referrer" id="referrer">
<input type="hidden" name="gclid" id="gclid">
<input type="hidden" name="fbclid" id="fbclid">
<button type="submit" class="submit-btn" id="submit-button">Register Now</button>
</form>
</div>
<div id="form-result"></div>
</div>
</div>
<script>
// --- TIMEZONE & DATE LOCALIZATION ---
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
document.getElementById('timezone').value = timezone;
const webinarDateUTC = '<?= $webinar["starts_at"] ?>';
const localDate = new Date(webinarDateUTC + 'Z'); // 'Z' for UTC
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' };
document.getElementById('local-date-time').textContent = localDate.toLocaleDateString(undefined, options);
// --- TRACKING PARAMS ---
const urlParams = new URLSearchParams(window.location.search);
['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'gclid', 'fbclid'].forEach(param => {
if (urlParams.has(param)) {
document.getElementById(param).value = urlParams.get(param);
}
});
document.getElementById('referrer').value = document.referrer;
// --- AJAX FORM SUBMISSION ---
const form = document.getElementById('registration-form');
const formContainer = document.getElementById('registration-form-container');
const formResult = document.getElementById('form-result');
const submitButton = document.getElementById('submit-button');
form.addEventListener('submit', function(e) {
e.preventDefault();
submitButton.disabled = true;
submitButton.textContent = 'Processing...';
const formData = new FormData(form);
const xhr = new XMLHttpRequest();
xhr.open('POST', window.location.href, true);
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 400) {
console.log("Response from server:", xhr.responseText);
let data;
try {
data = JSON.parse(xhr.responseText);
} catch (e) {
formResult.innerHTML = '<div class="error-message">An unexpected error occurred parsing the server response.</div>';
console.error("JSON Parsing Error:", e);
return;
}
if (data.success) {
formContainer.style.display = 'none';
const webinarTitle = encodeURIComponent(data.webinar_title);
const webinarDate = new Date(data.webinar_date_utc + 'Z');
const formatUTCDate = (date) => {
return date.toISOString().replace(/\.\d{3}Z$/, 'Z').replace(/[-:]/g, '');
};
const startTime = formatUTCDate(webinarDate);
const endTime = formatUTCDate(new Date(webinarDate.getTime() + (60 * 60 * 1000)));
const googleLink = `https://www.google.com/calendar/render?action=TEMPLATE&text=${webinarTitle}&dates=${startTime}/${endTime}&details=Join+the+webinar!&ctz=UTC`;
const icsContent = [
'BEGIN:VCALENDAR',
'VERSION:2.0',
'BEGIN:VEVENT',
`URL:${window.location.href}`,
`DTSTART:${startTime}`,
`DTEND:${endTime}`,
`SUMMARY:${data.webinar_title}`,
'DESCRIPTION:Join the webinar!',
'END:VEVENT',
'END:VCALENDAR'
].join('\n');
const outlookLink = `data:text/calendar;charset=utf-8,${encodeURIComponent(icsContent)}`;
formResult.innerHTML = `
<div class="success-message">
<h3 style="color: #f6e05e; font-size: 1.75rem;">Youre in for ${data.webinar_title}!</h3>
<p style="color: #cbd5e0; font-size: 1.1rem;">Check your email for your confirmation. You can now log in to see the details.</p>
<div class="calendar-buttons">
<a href="${googleLink}" target="_blank">Add to Google Calendar</a>
<a href="${outlookLink}" download="webinar.ics">Add to Outlook (ICS)</a>
</div>
</div>
`;
} else {
formResult.innerHTML = `<div class="error-message">${data.error || 'An unknown error occurred.'}</div>`;
submitButton.disabled = false;
submitButton.textContent = 'Register Now';
}
} else {
formResult.innerHTML = '<div class="error-message">A server error occurred. Please try again later.</div>';
submitButton.disabled = false;
submitButton.textContent = 'Register Now';
}
};
xhr.onerror = function() {
formResult.innerHTML = '<div class="error-message">A network error occurred. Please check your connection.</div>';
submitButton.disabled = false;
submitButton.textContent = 'Register Now';
};
xhr.send(formData);
});
</script>
</body>
</html>