34950-vm/register.php
Flatlogic Bot a2b2e8ae3b rrrrr
2025-10-17 10:52:07 +00:00

290 lines
16 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';
// Helper function to fetch webinar details
function get_webinar_details($id) {
if (empty($id)) {
return null;
}
try {
$stmt = db()->prepare("SELECT id, title, description, scheduled_at, presenter FROM webinars WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
error_log("Database error fetching webinar ID $id: " . $e->getMessage());
return null;
}
}
// --- AJAX FORM SUBMISSION (POST REQUEST) ---
if ($_SERVER["REQUEST_METHOD"] == "POST") {
header('Content-Type: application/json');
$response = [];
// --- DATA CAPTURE ---
$webinar_id = filter_input(INPUT_POST, 'webinar_id', FILTER_VALIDATE_INT) ?: filter_input(INPUT_GET, 'webinar_id', FILTER_VALIDATE_INT) ?: 1;
$webinar = get_webinar_details($webinar_id);
$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 (!$webinar) {
$response = ['success' => false, 'error' => 'Webinar not found. Tried to find webinar with ID: ' . $webinar_id];
} elseif (!$first_name || !$last_name || !$email) {
$response = ['success' => false, 'error' => 'Please fill out all required fields.'];
} elseif ($password !== $confirm_password) {
$response = ['success' => false, 'error' => 'Passwords do not match.'];
} else {
try {
$stmt = db()->prepare("SELECT id FROM attendees WHERE webinar_id = ? AND email = ?");
$stmt->execute([$webinar_id, $email]);
if ($stmt->fetch()) {
$response = ['success' => false, 'error' => 'You are already registered for this webinar.'];
} else {
$password_hash = password_hash($password, PASSWORD_DEFAULT);
$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]);
$webinar_date_obj = new DateTime($webinar['scheduled_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_obj->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);
// --- PREPARE SUCCESS RESPONSE ---
$webinar_date = new DateTime($webinar['scheduled_at'], new DateTimeZone('UTC'));
$start_time_utc = $webinar_date->format('Ymd H is Z');
$webinar_date->add(new DateInterval('PT1H')); // Assume 1 hour duration
$end_time_utc = $webinar_date->format('Ymd H is Z');
$google_link = 'https://www.google.com/calendar/render?action=TEMPLATE&text=' . urlencode($webinar['title']) . '&dates=' . $start_time_utc . '/' . $end_time_utc . '&details=' . urlencode($webinar['description']) . '&ctz=UTC';
$ics_content = implode("\r\n", [
'BEGIN:VCALENDAR', 'VERSION:2.0', 'BEGIN:VEVENT',
'URL:' . 'http://' . $_SERVER['HTTP_HOST'],
'DTSTART:' . $start_time_utc, 'DTEND:' . $end_time_utc,
'SUMMARY:' . $webinar['title'], 'DESCRIPTION:' . $webinar['description'],
'END:VEVENT', 'END:VCALENDAR'
]);
$outlook_link = 'data:text/calendar;charset=utf-8,' . rawurlencode($ics_content);
$response = [
'success' => true,
'webinar_title' => $webinar['title'],
'google_link' => $google_link,
'outlook_link' => $outlook_link
];
}
} catch (Exception $e) {
error_log("Registration error: " . $e->getMessage());
$response = ['success' => false, 'error' => 'An unexpected error occurred. Please try again.'];
}
}
echo json_encode($response);
exit;
}
// --- RENDER PAGE (Initial GET Request) ---
$webinar_id = filter_input(INPUT_GET, 'webinar_id', FILTER_VALIDATE_INT) ?: 1;
$webinar = get_webinar_details($webinar_id);
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; }
.right-pane .card { background-color: #2d3748; border-radius: 0.5rem; padding: 2rem; border: 1px solid #4a5568; }
.right-pane 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: #a0aec0; cursor: not-allowed; }
.error-message { background-color: #c53030; color: #fff; padding: 1rem; border-radius: 0.375rem; text-align: center; margin-bottom: 1.5rem; }
.success-message { text-align: center; }
.success-message h1 { color: #f6e05e; font-size: 2rem; margin-top: 0; }
.success-message p { color: #cbd5e0; font-size: 1.1rem; line-height: 1.6; }
.calendar-buttons a { display: inline-block; background-color: #4a5568; color: #e2e8f0; padding: 0.75rem 1.5rem; border-radius: 0.375rem; text-decoration: none; margin: 1rem 0.5rem 0; font-weight: bold; transition: background-color 0.2s; }
.calendar-buttons a:hover { background-color: #5a6578; }
@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-container" class="card">
<div id="error-container"></div>
<form id="registration-form" method="POST" action="register.php?webinar_id=<?= $webinar['id'] ?>">
<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">Register Now</button>
</form>
</div>
</div>
</div>
<script>
// --- TIMEZONE & DATE LOCALIZATION ---
document.getElementById('timezone').value = Intl.DateTimeFormat().resolvedOptions().timeZone;
const webinarDateUTC = '<?= $webinar["scheduled_at"] ?>';
const localDate = new Date(webinarDateUTC + 'Z');
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 container = document.getElementById('registration-container');
const errorContainer = document.getElementById('error-container');
form.addEventListener('submit', function(event) {
event.preventDefault();
const submitButton = form.querySelector('.submit-btn');
submitButton.disabled = true;
submitButton.textContent = 'Processing...';
errorContainer.innerHTML = '';
const formData = new FormData(form);
fetch(form.action, {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
container.innerHTML = `
<div class="success-message">
<h1>Youre in!</h1>
<p>Thanks for registering for <strong>${escapeHTML(data.webinar_title)}</strong>.</p>
<p>Check your email for your confirmation. You can now log in to see the details.</p>
<div class="calendar-buttons">
<a href="${escapeHTML(data.google_link)}" target="_blank">Add to Google Calendar</a>
<a href="${escapeHTML(data.outlook_link)}" download="webinar.ics">Add to Outlook (ICS)</a>
</div>
</div>
`;
} else {
errorContainer.innerHTML = `<div class="error-message">${escapeHTML(data.error)}</div>`;
submitButton.disabled = false;
submitButton.textContent = 'Register Now';
}
})
.catch(error => {
console.error('Error:', error);
errorContainer.innerHTML = '<div class="error-message">A network error occurred. Please try again.</div>';
submitButton.disabled = false;
submitButton.textContent = 'Register Now';
});
});
function escapeHTML(str) {
var p = document.createElement("p");
p.appendChild(document.createTextNode(str));
return p.innerHTML;
}
</script>
</body>
</html>