<?php
/**
* Registration Process
*
* This file implements a 2-step registration process:
* Step 1: User enters account information (username, email, password)
* Step 2: User enters personal information (first name, last name, phone)
* Step 3: User uploads a profile photo or skips to use default avatar
*
* If the user skips the photo upload, a default avatar from site_settings will be used.
*/
// Enable error reporting for debugging
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Start session
session_start();
// Check if already logged in
if (isset($_SESSION['user_id'])) {
header("Location: index.php");
exit;
}
// Include database configuration and PHPMailer
require_once 'admin/database/db_config.php';
require_once 'includes/oauth_config.php';
require_once 'libs/PHPMailer/src/Exception.php';
require_once 'libs/PHPMailer/src/PHPMailer.php';
require_once 'libs/PHPMailer/src/SMTP.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
// Get site settings
$site_logo = 'assets/img/logo.png'; // Default logo
$site_name = 'Popular Computer';
$primary_color = '#4e73df';
$secondary_color = '#224abe';
// Try to fetch settings from database
try {
$settings_query = "SELECT * FROM site_settings";
$settings_result = $conn->query($settings_query);
if ($settings_result && $settings_result->num_rows > 0) {
while ($row = $settings_result->fetch_assoc()) {
if ($row['setting_key'] == 'site_logo') {
$site_logo = $row['setting_value'];
} else if ($row['setting_key'] == 'site_name') {
$site_name = $row['setting_value'];
} else if ($row['setting_key'] == 'primary_color') {
$primary_color = $row['setting_value'];
} else if ($row['setting_key'] == 'secondary_color') {
$secondary_color = $row['setting_value'];
}
}
}
} catch (Exception $e) {
error_log("Error fetching site settings: " . $e->getMessage());
}
// Function to generate random token
function generate_token($length = 32) {
return bin2hex(random_bytes($length/2));
}
// Function to send verification email
function send_verification_email($user_id, $email, $first_name, $token) {
global $conn;
// Get site settings
$site_settings_query = "SELECT * FROM site_settings LIMIT 1";
$site_settings_result = mysqli_query($conn, $site_settings_query);
$site_settings = mysqli_fetch_assoc($site_settings_result);
$site_name = $site_settings['site_name'] ?? 'Popular Computer';
$site_email = $site_settings['email'] ?? '[email protected]';
$smtp_host = $site_settings['smtp_host'] ?? '';
$smtp_port = $site_settings['smtp_port'] ?? 587;
$smtp_user = $site_settings['smtp_username'] ?? '';
$smtp_pass = $site_settings['smtp_password'] ?? '';
// Create verification link
$verification_link = "http://" . $_SERVER['HTTP_HOST'] . "/verify_email.php?token=" . $token . "&id=" . $user_id;
// Create new PHPMailer instance
$mail = new PHPMailer(true);
try {
// Configure SMTP if settings are available
if (!empty($smtp_host) && !empty($smtp_user) && !empty($smtp_pass)) {
$mail->isSMTP();
$mail->Host = $smtp_host;
$mail->SMTPAuth = true;
$mail->Username = $smtp_user;
$mail->Password = $smtp_pass;
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = $smtp_port;
}
// Set email content
$mail->setFrom($site_email, $site_name);
$mail->addAddress($email, $first_name);
$mail->isHTML(true);
$mail->Subject = 'Verify Your Email Address';
// Create email body
$mail->Body = "
<html>
<head>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
.header { background-color: #4e73df; color: white; padding: 20px; text-align: center; }
.content { padding: 20px; background-color: #f9f9f9; }
.button { display: inline-block; padding: 10px 20px; background-color: #4e73df; color: white; text-decoration: none; border-radius: 5px; }
.footer { margin-top: 20px; font-size: 12px; color: #777; }
</style>
</head>
<body>
<div class='container'>
<div class='header'>
<img src='" . $site_logo . "' alt='Logo'>
<h1>" . htmlspecialchars($site_name) . "</h1>
</div>
<div class='content'>
<p>Dear " . htmlspecialchars($first_name) . ",</p>
<p>Thank you for registering with " . htmlspecialchars($site_name) . ". To complete your registration, please verify your email address by clicking the button below:</p>
<p style='text-align: center;'>
<a href='" . $verification_link . "' class='button'>Verify Email Address</a>
</p>
<p>If the button doesn't work, you can also copy and paste the following link into your browser:</p>
<p>" . $verification_link . "</p>
<p>This link will expire in 48 hours.</p>
<p>If you did not create an account, please ignore this email.</p>
</div>
<div class='footer'>
<p>© " . date('Y') . " " . htmlspecialchars($site_name) . ". All rights reserved.</p>
</div>
</div>
</body>
</html>
";
$mail->AltBody = "Dear " . $first_name . ",\n\nThank you for registering with " . $site_name . ". To complete your registration, please verify your email address by clicking the link below:\n\n" . $verification_link . "\n\nThis link will expire in 48 hours.\n\nIf you did not create an account, please ignore this email.\n\n" . $site_name;
// Send email
return $mail->send();
} catch (Exception $e) {
error_log("Email sending failed: " . $mail->ErrorInfo);
return false;
}
}
// Initialize variables
$step = isset($_GET['step']) ? (int)$_GET['step'] : 1;
$errors = [];
$success = false;
// Handle form submission based on step
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
switch ($step) {
case 1: // Basic Information
$username = trim($_POST['username']);
$email = trim($_POST['email']);
$password = $_POST['password'];
$confirm_password = $_POST['confirm_password'];
// Validate basic information
if (empty($username)) {
$errors[] = "Username is required";
} elseif (strlen($username) < 3) {
$errors[] = "Username must be at least 3 characters long";
}
if (empty($email)) {
$errors[] = "Email is required";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Invalid email format";
}
if (empty($password)) {
$errors[] = "Password is required";
} elseif (strlen($password) < 6) {
$errors[] = "Password must be at least 6 characters long";
}
if ($password !== $confirm_password) {
$errors[] = "Passwords do not match";
}
// Check if username or email already exists
if (empty($errors)) {
$check_query = "SELECT id FROM users WHERE username = ? OR email = ?";
$check_stmt = $conn->prepare($check_query);
$check_stmt->bind_param("ss", $username, $email);
$check_stmt->execute();
$result = $check_stmt->get_result();
if ($result->num_rows > 0) {
$errors[] = "Username or email already exists";
}
}
if (empty($errors)) {
$_SESSION['register_data'] = [
'username' => $username,
'email' => $email,
'password' => $password
];
header("Location: register.php?step=2");
exit;
}
break;
case 2: // Personal Information
if (!isset($_SESSION['register_data'])) {
header("Location: register.php?step=1");
exit;
}
$first_name = trim($_POST['first_name']);
$last_name = trim($_POST['last_name']);
$phone = trim($_POST['phone']);
if (empty($first_name)) {
$errors[] = "First name is required";
}
if (empty($last_name)) {
$errors[] = "Last name is required";
}
if (empty($phone)) {
$errors[] = "Phone number is required";
}
if (empty($errors)) {
$_SESSION['register_data'] = array_merge($_SESSION['register_data'], [
'first_name' => $first_name,
'last_name' => $last_name,
'phone' => $phone
]);
header("Location: register.php?step=3");
exit;
}
break;
case 3: // Profile Image
if (!isset($_SESSION['register_data'])) {
header("Location: register.php?step=1");
exit;
}
// Initialize profile_image as null
$profile_image = null;
// Check if this is a skip request
$skip_upload = isset($_POST['skip_upload']);
// Handle profile image upload (only if not skipping)
if (!$skip_upload && isset($_FILES['profile_image']) && $_FILES['profile_image']['error'] === UPLOAD_ERR_OK) {
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
$max_size = 5 * 1024 * 1024; // 5MB
if (!in_array($_FILES['profile_image']['type'], $allowed_types)) {
$errors[] = "Invalid file type. Only JPG, PNG and GIF are allowed.";
} elseif ($_FILES['profile_image']['size'] > $max_size) {
$errors[] = "File size too large. Maximum size is 5MB.";
} else {
$upload_dir = 'uploads/profiles/';
if (!file_exists($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
$file_extension = pathinfo($_FILES['profile_image']['name'], PATHINFO_EXTENSION);
$file_name = uniqid() . '.' . $file_extension;
$target_path = $upload_dir . $file_name;
if (!move_uploaded_file($_FILES['profile_image']['tmp_name'], $target_path)) {
$errors[] = "Failed to upload profile image";
} else {
$profile_image = $file_name;
}
}
}
if (empty($errors)) {
// Complete registration
$data = $_SESSION['register_data'];
$hashed_password = password_hash($data['password'], PASSWORD_DEFAULT);
// If skipping upload or if there was an error, use default avatar from site settings
if ($skip_upload || $profile_image === null) {
// Get default avatar from site settings
$default_avatar_query = "SELECT setting_value FROM site_settings WHERE setting_key = 'default_avatar'";
$default_avatar_result = $conn->query($default_avatar_query);
if ($default_avatar_result && $default_avatar_result->num_rows > 0) {
$default_avatar = $default_avatar_result->fetch_assoc()['setting_value'];
$profile_image = $default_avatar;
} else {
// Fallback to a modern default avatar if site setting is not available
$profile_image = 'assets/img/default-avatar.png';
}
} else {
// If user uploaded an image, use the full path for storing in DB
$profile_image = $upload_dir . $profile_image;
}
$insert_query = "INSERT INTO users (username, email, password, first_name, last_name, phone, profile_image, role, status, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, 'student', 'pending', NOW())";
$stmt = $conn->prepare($insert_query);
$stmt->bind_param("sssssss", $data['username'], $data['email'], $hashed_password,
$data['first_name'], $data['last_name'], $data['phone'], $profile_image);
if ($stmt->execute()) {
$user_id = $conn->insert_id;
// Generate verification token
$token = generate_token();
// Store token in user_verifications table with expiration
$verify_query = "INSERT INTO user_verifications (user_id, token, created_at, expires_at)
VALUES (?, ?, NOW(), DATE_ADD(NOW(), INTERVAL 48 HOUR))";
$verify_stmt = $conn->prepare($verify_query);
$verify_stmt->bind_param("is", $user_id, $token);
$verify_stmt->execute();
// Send verification email
$email_sent = send_verification_email($user_id, $data['email'], $data['first_name'], $token);
$success = true;
unset($_SESSION['register_data']);
$_SESSION['register_success'] = "Registration successful! Please check your email to verify your account.";
header("Location: login.php");
exit;
} else {
$errors[] = "Registration failed. Please try again.";
}
}
break;
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Student Registration - Popular Computer Institute</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
:root {
--primary-color: #4e73df;
--secondary-color: #224abe;
--success-color: #1cc88a;
--info-color: #36b9cc;
--warning-color: #f6c23e;
--danger-color: #e74a3b;
--light-color: #f8f9fc;
--dark-color: #5a5c69;
}
body {
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
background-size: 400% 400%;
animation: gradient 15s ease infinite;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
padding: 20px 10px;
overflow-x: hidden;
overflow-y: auto;
position: relative;
}
#particles-js {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 1;
}
@keyframes gradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.registration-container {
position: relative;
z-index: 2;
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2);
padding: 30px;
width: 100%;
max-width: 500px;
backdrop-filter: blur(10px);
transform: translateY(0);
transition: transform 0.3s ease;
margin: 20px 0;
}
.registration-container:hover {
transform: translateY(-5px);
}
.register-header {
text-align: center;
margin-bottom: 30px;
}
.register-header img {
width: 80px;
margin-bottom: 15px;
animation: float 3s ease-in-out infinite;
}
@keyframes float {
0% { transform: translateY(0px); }
50% { transform: translateY(-10px); }
100% { transform: translateY(0px); }
}
.register-header h2 {
color: #333;
font-weight: 600;
margin-bottom: 10px;
}
.form-floating {
margin-bottom: 20px;
}
.form-control {
border-radius: 10px;
padding: 12px 15px;
border: 2px solid #e1e5eb;
transition: all 0.3s ease;
}
.form-control:focus {
border-color: var(--primary-color);
box-shadow: 0 0 0 0.2rem rgba(78, 115, 223, 0.25);
}
.btn-register {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
border: none;
border-radius: 10px;
padding: 12px;
font-weight: 600;
width: 100%;
margin-top: 10px;
transition: all 0.3s ease;
animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(78, 115, 223, 0.7);
}
70% {
box-shadow: 0 0 0 10px rgba(78, 115, 223, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(78, 115, 223, 0);
}
}
.btn-register:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(78, 115, 223, 0.4);
}
.btn-sec{
border-radius: 10px;
padding: 12px;
font-weight: 600;
width: 100%;
margin-top: 10px;
transition: all 0.3s ease;
animation: pulse 2s infinite;
}
.links {
text-align: center;
margin-top: 20px;
}
.links a {
color: var(--primary-color);
text-decoration: none;
font-size: 14px;
transition: color 0.3s ease;
}
.links a:hover {
color: var(--secondary-color);
}
.alert {
border-radius: 10px;
margin-bottom: 20px;
}
.password-requirements {
font-size: 12px;
color: #666;
margin-top: -15px;
margin-bottom: 15px;
padding-left: 5px;
}
.password-requirements ul {
margin-bottom: 0;
padding-left: 20px;
}
.password-requirements li {
margin-bottom: 3px;
}
.password-requirements li i {
font-size: 10px;
margin-right: 5px;
}
.social-login {
margin-top: 10px;
text-align: center;
}
.social-login p {
color: #666;
position: relative;
}
.social-login p::before,
.social-login p::after {
content: "";
position: absolute;
top: 50%;
width: 45%;
height: 1px;
background: #ddd;
}
.social-login p::before { left: 0; }
.social-login p::after { right: 0; }
.social-buttons {
display: flex;
justify-content: center;
/* gap: 15px; */
}
.social-btn {
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
transition: all 0.3s ease;
}
.social-btn:hover {
transform: translateY(-3px);
}
.google { background: #DB4437; }
.facebook { background: #4267B2; }
.twitter { background: #1DA1F2; }
/* Loading spinner */
.spinner {
display: none;
width: 20px;
height: 20px;
border: 2px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top-color: #fff;
animation: spin 0.8s linear infinite;
margin-right: 8px;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.btn-register.loading .spinner {
display: inline-block;
}
.btn-register.loading span {
display: none;
}
/* Step Progress Bar */
.step-progress {
margin-bottom: 30px;
}
.step-progress-bar {
height: 6px;
background-color: #e9ecef;
border-radius: 3px;
position: relative;
margin-bottom: 15px;
}
.step-progress-fill {
height: 100%;
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
border-radius: 3px;
transition: width 0.3s ease;
}
.step-labels {
display: flex;
justify-content: space-between;
}
.step-label {
text-align: center;
width: 33.33%;
position: relative;
opacity: 0.6;
transition: opacity 0.3s ease;
}
.step-label.active {
opacity: 1;
}
.step-number {
display: inline-flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
background-color: #e9ecef;
color: #6c757d;
border-radius: 50%;
font-size: 14px;
font-weight: 600;
margin-bottom: 5px;
transition: all 0.3s ease;
}
.step-label.active .step-number {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
color: white;
box-shadow: 0 3px 10px rgba(78, 115, 223, 0.3);
}
.step-text {
display: block;
font-size: 12px;
color: #6c757d;
}
.step-label.active .step-text {
color: var(--primary-color);
font-weight: 600;
}
/* Profile Photo Upload */
.profile-photo-upload {
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
margin-bottom: 25px;
}
.profile-photo-preview {
width: 130px;
height: 130px;
border-radius: 50%;
overflow: hidden;
border: 3px solid #ffffff;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
justify-content: center;
background-color: #f8f9fc;
transition: all 0.3s ease;
}
.profile-photo-preview img {
width: 100%;
height: 100%;
object-fit: cover;
}
.upload-options {
text-align: center;
}
.form-buttons {
display: flex;
gap: 10px;
justify-content: space-between;
margin-top: 20px;
flex-wrap: wrap;
}
.form-buttons .btn {
flex: 1;
min-width: 100px;
}
.btn-outline-secondary {
border-color: #d9dce2;
color: #6c757d;
}
.btn-outline-secondary:hover {
background-color: #f8f9fc;
color: var(--primary-color);
}
/* Responsive adjustments */
@media (max-width: 576px) {
.registration-container {
padding: 20px 15px;
}
.form-buttons {
flex-direction: column;
}
.form-buttons .btn {
margin-bottom: 10px;
}
.step-label .step-text {
font-size: 10px;
}
}
@media (max-width: 400px) {
.profile-photo-preview {
width: 110px;
height: 110px;
}
}
@media (max-width: 576px) {
body {
padding: 10px;
align-items: flex-start;
}
.registration-container {
padding: 20px 15px;
margin: 10px 0;
max-width: 100%;
border-radius: 15px;
}
.form-buttons {
flex-direction: column;
}
.form-buttons .btn {
margin-bottom: 10px;
}
.step-label .step-text {
font-size: 10px;
}
.register-header {
margin-bottom: 20px;
}
.register-header img {
width: 60px;
}
.form-floating {
margin-bottom: 15px;
}
}
</style>
</head>
<body>
<div id="particles-js"></div>
<div class="registration-container">
<div class="register-header">
<img src="<?php echo $site_logo; ?>" alt="<?php echo htmlspecialchars($site_name); ?> Logo">
<h2>Create Account</h2>
<p class="text-muted">Join our learning community</p>
</div>
<?php if (!empty($errors)): ?>
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle me-2"></i>
<ul class="mb-0">
<?php foreach ($errors as $error): ?>
<li><?php echo htmlspecialchars($error); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success">
<i class="fas fa-check-circle me-2"></i>Registration successful! You can now login.
</div>
<div class="text-center mt-4">
<a href="login.php" class="btn btn-primary">
<i class="fas fa-sign-in-alt me-2"></i> Go to Login
</a>
</div>
<?php else: ?>
<!-- Registration Progress -->
<div class="step-progress mb-4">
<div class="step-progress-bar">
<div class="step-progress-fill" style="width: <?php echo ($step / 3) * 100; ?>%"></div>
</div>
<div class="step-labels">
<div class="step-label <?php echo $step >= 1 ? 'active' : ''; ?>">
<span class="step-number">1</span>
<span class="step-text">Account</span>
</div>
<div class="step-label <?php echo $step >= 2 ? 'active' : ''; ?>">
<span class="step-number">2</span>
<span class="step-text">Personal</span>
</div>
<div class="step-label <?php echo $step >= 3 ? 'active' : ''; ?>">
<span class="step-number">3</span>
<span class="step-text">Photo</span>
</div>
</div>
</div>
<?php if ($step == 1): ?>
<!-- Step 1: Account Information -->
<form method="post" action="" id="registerForm">
<div class="form-floating">
<input type="text" class="form-control" id="username" name="username" placeholder="Username" required value="<?php echo isset($_SESSION['register_data']['username']) ? htmlspecialchars($_SESSION['register_data']['username']) : ''; ?>">
<label for="username">Username</label>
</div>
<div class="form-floating">
<input type="email" class="form-control" id="email" name="email" placeholder="[email protected]" required value="<?php echo isset($_SESSION['register_data']['email']) ? htmlspecialchars($_SESSION['register_data']['email']) : ''; ?>">
<label for="email">Email address</label>
</div>
<div class="password-requirements">
<ul>
<li><i class="fas fa-circle"></i> At least 6 characters long</li>
<li><i class="fas fa-circle"></i> Include numbers and letters</li>
<li><i class="fas fa-circle"></i> Use special characters for strength</li>
</ul>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="password" name="password" placeholder="Password" required>
<label for="password">Password</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="confirm_password" name="confirm_password" placeholder="Confirm Password" required>
<label for="confirm_password">Confirm Password</label>
</div>
<button type="submit" class="btn btn-primary btn-register">
<span class="spinner"></span>
<span>Continue</span>
</button>
</form>
<?php elseif ($step == 2): ?>
<!-- Step 2: Personal Information -->
<form method="post" action="" id="registerForm">
<div class="form-floating">
<input type="text" class="form-control" id="first_name" name="first_name" placeholder="First Name" required value="<?php echo isset($_SESSION['register_data']['first_name']) ? htmlspecialchars($_SESSION['register_data']['first_name']) : ''; ?>">
<label for="first_name">First Name</label>
</div>
<div class="form-floating">
<input type="text" class="form-control" id="last_name" name="last_name" placeholder="Last Name" required value="<?php echo isset($_SESSION['register_data']['last_name']) ? htmlspecialchars($_SESSION['register_data']['last_name']) : ''; ?>">
<label for="last_name">Last Name</label>
</div>
<div class="form-floating">
<input type="tel" class="form-control" id="phone" name="phone" placeholder="Phone Number" required value="<?php echo isset($_SESSION['register_data']['phone']) ? htmlspecialchars($_SESSION['register_data']['phone']) : ''; ?>">
<label for="phone">Phone Number</label>
</div>
<div class="form-buttons">
<a href="register.php?step=1" class="btn btn-sec btn-outline-secondary">Back</a>
<button type="submit" class="btn btn-primary btn-register">
<span class="spinner"></span>
<span>Continue</span>
</button>
</div>
</form>
<?php elseif ($step == 3): ?>
<!-- Step 3: Profile Photo -->
<form method="post" action="" id="registerForm" enctype="multipart/form-data">
<div class="profile-photo-upload">
<div class="profile-photo-preview">
<img src="<?php
// Get default avatar from site settings
$default_avatar_query = "SELECT setting_value FROM site_settings WHERE setting_key = 'default_avatar'";
$default_avatar_result = $conn->query($default_avatar_query);
if ($default_avatar_result && $default_avatar_result->num_rows > 0) {
echo $default_avatar_result->fetch_assoc()['setting_value'];
} else {
echo 'assets/img/default-avatar.png';
}
?>" alt="Profile Preview" id="profilePreview">
</div>
<div class="upload-options">
<label for="profile_image" class="btn btn-sec btn-outline-primary">
<i class="fas fa-upload"></i> Choose Photo
</label>
<input type="file" class="form-control d-none" id="profile_image" name="profile_image" accept="image/*" onchange="previewImage(this)">
<p class="text-muted small">Upload a profile photo (Max size: 5MB)</p>
<p class="text-muted small">Supported formats: JPG, PNG, GIF</p>
</div>
</div>
<div class="form-buttons">
<a href="register.php?step=2" class="btn btn-sec btn-outline-secondary">Back</a>
<button type="submit" name="skip_upload" class="btn btn-sec btn-outline-primary">
Skip for now
</button>
<button type="submit" class="btn btn-primary btn-register">
<span class="spinner"></span>
<span>Sign Up</span>
</button>
</div>
</form>
<?php endif; ?>
<div class="links">
<p>Already have an account? <a href="login.php">Login</a></p>
</div>
<div class="social-login">
<p>Or register with</p>
<a href="<?php echo getOAuthLoginUrl('google'); ?>" class="btn btn-light w-100 border d-flex align-items-center justify-content-center gap-2 py-2">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 48 48">
<path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/>
<path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/>
<path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"/>
<path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/>
</svg>
Continue with Google
</a>
</div>
</div>
<?php endif; ?>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/particles.min.js"></script>
<script>
// Check if device is mobile
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
// Initialize particles.js with optimized settings for mobile
particlesJS('particles-js', {
particles: {
number: {
value: isMobile ? 30 : 80,
density: { enable: true, value_area: 800 }
},
color: { value: '#4e73df' },
shape: { type: 'circle' },
opacity: { value: 0.5, random: false },
size: { value: isMobile ? 2 : 3, random: true },
line_linked: {
enable: true,
distance: 150,
color: '#4e73df',
opacity: 0.4,
width: 1
},
move: {
enable: true,
speed: isMobile ? 1 : 2,
direction: 'none',
random: false,
straight: false,
out_mode: 'out',
bounce: false
}
},
interactivity: {
detect_on: 'canvas',
events: {
onhover: { enable: !isMobile, mode: 'repulse' },
onclick: { enable: !isMobile, mode: 'push' },
resize: true
}
},
retina_detect: !isMobile
});
// Preview image before upload
function previewImage(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
document.getElementById('profilePreview').src = e.target.result;
}
reader.readAsDataURL(input.files[0]);
}
}
// Form buttons loading state
const registerForm = document.getElementById('registerForm');
if (registerForm) {
registerForm.addEventListener('submit', function() {
const submitBtn = this.querySelector('.btn-register:not([name="skip_upload"])');
if (submitBtn) {
submitBtn.classList.add('loading');
}
});
}
</script>
</body>
</html>