34950-vm/register.php
Flatlogic Bot b7c23d9356 2
2025-10-17 09:19:56 +00:00

306 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';
// --- CONFIGURATION ---
$webinar_id = filter_input(INPUT_GET, 'webinar_id', FILTER_VALIDATE_INT);
$response = [];
// --- WEBINAR DETAILS ---
$webinar = null;
if ($webinar_id) {
try {
$stmt = db()->prepare("SELECT * FROM webinars WHERE id = ?");
$stmt->execute([$webinar_id]);
$webinar = $stmt->fetch();
} 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 ---
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$first_name = filter_input(INPUT_POST, 'first_name', FILTER_SANITIZE_STRING);
$password = filter_input(INPUT_POST, 'password', FILTER_UNSAFE_RAW);
$confirm_password = filter_input(INPUT_POST, 'confirm_password', FILTER_UNSAFE_RAW);
$consent = filter_input(INPUT_POST, 'consent', FILTER_VALIDATE_BOOLEAN);
$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 (!$email || !$consent || !$webinar) {
$response['error'] = 'Please provide a valid email and agree to the terms.';
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, name, email, 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, $email, $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['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->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['scheduled_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"] { 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; }
.consent-group { display: flex; align-items: start; gap: 0.75rem; }
.consent-group label { font-weight: normal; font-size: 0.9rem; color: #a0aec0; }
.microcopy { font-size: 0.8rem; color: #718096; margin-top: 0.5rem; }
.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; }
.error-message { background-color: #c53030; padding: 1rem; border-radius: 0.375rem; }
.calendar-buttons a, .copy-link-btn { 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>
<p class="microcopy">Well send the join link & calendar invite.</p>
</div>
<div class="form-group">
<label for="first_name">First name (optional)</label>
<input type="text" id="first_name" name="first_name">
</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>
<div class="form-group consent-group">
<input type="checkbox" id="consent" name="consent" required>
<label for="consent">I agree to receive info about this webinar.</label>
</div>
<p class="microcopy" style="margin-top:-1rem; margin-bottom: 1.5rem;">No spam. Unsubscribe anytime.</p>
<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["scheduled_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);
fetch(window.location.href, {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
formContainer.style.display = 'none';
const webinarTitle = encodeURIComponent(data.webinar_title);
const webinarDate = new Date(data.webinar_date_utc + 'Z');
const startTime = webinarDate.toISOString().replace(/-|:|..*Z/g, '') + 'Z';
const endTime = new Date(webinarDate.getTime() + (60 * 60 * 1000)).toISOString().replace(/-|:|..*Z/g, '') + 'Z';
const googleLink = `https://www.google.com/calendar/render?action=TEMPLATE&text=${webinarTitle}&dates=${startTime.replace(/Z$/, '')}/${endTime.replace(/Z$/, '')}&details=Join+the+webinar!`;
const icsContent = [
'BEGIN:VCALENDAR',
'VERSION:2.0',
'BEGIN:VEVENT',
`URL:${window.location.href}`,
`DTSTART:${startTime.replace(/Z$/, '')}`,
`DTEND:${endTime.replace(/Z$/, '')}`,
`SUMMARY:${data.webinar_title}`,
'DESCRIPTION:Join the webinar!',
'END:VEVENT',
'END:VCALENDAR'
].join('\n');
const outlookLink = `data:text/calendar;charset=utf8,${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}</div>`;
submitButton.disabled = false;
submitButton.textContent = 'Register Now';
}
})
.catch(error => {
formResult.innerHTML = `<div class="error-message">An unexpected error occurred.</div>`;
submitButton.disabled = false;
submitButton.textContent = 'Register Now';
});
});
// --- COPY LINK ---
formResult.addEventListener('click', function(e) {
if (e.target.classList.contains('copy-link-btn')) {
e.preventDefault();
const link = e.target.dataset.link;
navigator.clipboard.writeText(link).then(() => {
e.target.textContent = 'Copied!';
setTimeout(() => {
e.target.textContent = 'Copy Join Link';
}, 2000);
});
}
});
</script>
</body>
</html>