Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fb157b86c |
127
admin_competitions.php
Normal file
127
admin_competitions.php
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
// Handle form submission
|
||||||
|
$message = '';
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$title = $_POST['title'] ?? '';
|
||||||
|
$description = $_POST['description'] ?? '';
|
||||||
|
$start_date = $_POST['start_date'] ?? '';
|
||||||
|
$end_date = $_POST['end_date'] ?? '';
|
||||||
|
|
||||||
|
if (!empty($title) && !empty($start_date) && !empty($end_date)) {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$sql = "INSERT INTO competitions (title, description, start_date, end_date) VALUES (?, ?, ?, ?)";
|
||||||
|
$stmt = $pdo->prepare($sql);
|
||||||
|
$stmt->execute([$title, $description, $start_date, $end_date]);
|
||||||
|
$message = '<div class="alert alert-success">Competition created successfully!</div>';
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = '<div class="alert alert-danger">Error: ' . $e->getMessage() . '</div>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$message = '<div class="alert alert-danger">Please fill in all required fields.</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch all competitions
|
||||||
|
$competitions = [];
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->query("SELECT id, title, description, start_date, end_date FROM competitions ORDER BY created_at DESC");
|
||||||
|
$competitions = $stmt->fetchAll();
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
// Handle error if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Admin: Manage Competitions</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<?php include 'includes/header.php'; ?>
|
||||||
|
|
||||||
|
<main class="container mt-5">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<h2>Manage Competitions</h2>
|
||||||
|
<hr>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<!-- Create Competition Form -->
|
||||||
|
<div class="col-md-4">
|
||||||
|
<h3>Create New Competition</h3>
|
||||||
|
<?php echo $message; ?>
|
||||||
|
<form action="admin_competitions.php" method="POST">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="title" class="form-label">Title</label>
|
||||||
|
<input type="text" class="form-control" id="title" name="title" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="description" class="form-label">Description</label>
|
||||||
|
<textarea class="form-control" id="description" name="description" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="start_date" class="form-label">Start Date</label>
|
||||||
|
<input type="datetime-local" class="form-control" id="start_date" name="start_date" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="end_date" class="form-label">End Date</label>
|
||||||
|
<input type="datetime-local" class="form-control" id="end_date" name="end_date" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Create Competition</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Competitions List -->
|
||||||
|
<div class="col-md-8">
|
||||||
|
<h3>Existing Competitions</h3>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Start Date</th>
|
||||||
|
<th>End Date</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if (empty($competitions)): ?>
|
||||||
|
<tr>
|
||||||
|
<td colspan="5" class="text-center">No competitions found.</td>
|
||||||
|
</tr>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($competitions as $comp): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars($comp['id']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($comp['title']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($comp['start_date']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($comp['end_date']); ?></td>
|
||||||
|
<td>
|
||||||
|
<a href="#" class="btn btn-sm btn-warning">Edit</a>
|
||||||
|
<a href="#" class="btn btn-sm btn-danger">Delete</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include 'includes/footer.php'; ?>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
145
admin_submissions.php
Normal file
145
admin_submissions.php
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'includes/header.php';
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
// Check if user is logged in and is an admin (for simplicity, we'll just check if they are logged in)
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header("Location: login.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Handle status update
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submission_id']) && isset($_POST['status'])) {
|
||||||
|
$submission_id = $_POST['submission_id'];
|
||||||
|
$status = $_POST['status'];
|
||||||
|
|
||||||
|
// Begin transaction
|
||||||
|
$pdo->beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Update submission status
|
||||||
|
$stmt = $pdo->prepare("UPDATE submissions SET status = ? WHERE id = ?");
|
||||||
|
$stmt->execute([$status, $submission_id]);
|
||||||
|
|
||||||
|
if ($status == 'approved') {
|
||||||
|
// Check if a certificate already exists
|
||||||
|
$stmt_check = $pdo->prepare("SELECT id FROM certificates WHERE submission_id = ?");
|
||||||
|
$stmt_check->execute([$submission_id]);
|
||||||
|
if ($stmt_check->rowCount() == 0) {
|
||||||
|
// Generate a unique certificate code
|
||||||
|
$certificate_code = uniqid('CERT-');
|
||||||
|
$stmt_insert = $pdo->prepare("INSERT INTO certificates (submission_id, certificate_code) VALUES (?, ?)");
|
||||||
|
$stmt_insert->execute([$submission_id, $certificate_code]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If status is not 'approved', delete any existing certificate
|
||||||
|
$stmt_delete = $pdo->prepare("DELETE FROM certificates WHERE submission_id = ?");
|
||||||
|
$stmt_delete->execute([$submission_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit transaction
|
||||||
|
$pdo->commit();
|
||||||
|
echo "<div class='alert alert-success'>Submission status updated successfully.</div>";
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Rollback transaction on error
|
||||||
|
$pdo->rollBack();
|
||||||
|
echo "<div class='alert alert-danger'>Failed to update submission status: " . $e->getMessage() . "</div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch all competitions
|
||||||
|
$stmt_competitions = $pdo->query("SELECT id, title FROM competitions ORDER BY start_date DESC");
|
||||||
|
$competitions = $stmt_competitions->fetchAll();
|
||||||
|
|
||||||
|
// Fetch all submissions with user and competition info
|
||||||
|
$stmt_submissions = $pdo->query("
|
||||||
|
SELECT
|
||||||
|
s.id,
|
||||||
|
s.file_path,
|
||||||
|
s.uploaded_at,
|
||||||
|
s.status,
|
||||||
|
u.name as user_name,
|
||||||
|
c.title as competition_title,
|
||||||
|
c.id as competition_id
|
||||||
|
FROM
|
||||||
|
submissions s
|
||||||
|
JOIN
|
||||||
|
users u ON s.user_id = u.id
|
||||||
|
JOIN
|
||||||
|
competitions c ON s.competition_id = c.id
|
||||||
|
ORDER BY
|
||||||
|
c.id, s.uploaded_at DESC
|
||||||
|
");
|
||||||
|
$submissions_by_competition = [];
|
||||||
|
while ($row = $stmt_submissions->fetch()) {
|
||||||
|
$submissions_by_competition[$row['competition_id']][] = $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container mt-5">
|
||||||
|
<h1 class="mb-4">Competition Submissions</h1>
|
||||||
|
|
||||||
|
<?php if (empty($competitions)): ?>
|
||||||
|
<div class="alert alert-info">No competitions found.</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="accordion" id="competitionsAccordion">
|
||||||
|
<?php foreach ($competitions as $competition): ?>
|
||||||
|
<div class="accordion-item">
|
||||||
|
<h2 class="accordion-header" id="heading-<?php echo $competition['id']; ?>">
|
||||||
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-<?php echo $competition['id']; ?>" aria-expanded="false" aria-controls="collapse-<?php echo $competition['id']; ?>">
|
||||||
|
<?php echo htmlspecialchars($competition['title']); ?>
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div id="collapse-<?php echo $competition['id']; ?>" class="accordion-collapse collapse" aria-labelledby="heading-<?php echo $competition['id']; ?>" data-bs-parent="#competitionsAccordion">
|
||||||
|
<div class="accordion-body">
|
||||||
|
<?php if (isset($submissions_by_competition[$competition['id']]) && !empty($submissions_by_competition[$competition['id']])) : ?>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>User</th>
|
||||||
|
<th>File</th>
|
||||||
|
<th>Uploaded At</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($submissions_by_competition[$competition['id']] as $submission): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars($submission['user_name']); ?></td>
|
||||||
|
<td><a href="<?php echo htmlspecialchars($submission['file_path']); ?>" target="_blank">View Submission</a></td>
|
||||||
|
<td><?php echo date("F j, Y, g:i a", strtotime($submission['uploaded_at'])); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($submission['status']); ?></td>
|
||||||
|
<td>
|
||||||
|
<form action="admin_submissions.php" method="post">
|
||||||
|
<input type="hidden" name="submission_id" value="<?php echo $submission['id']; ?>">
|
||||||
|
<select name="status" class="form-select form-select-sm">
|
||||||
|
<option value="pending" <?php echo ($submission['status'] == 'pending') ? 'selected' : ''; ?>>Pending</option>
|
||||||
|
<option value="approved" <?php echo ($submission['status'] == 'approved') ? 'selected' : ''; ?>>Approved</option>
|
||||||
|
<option value="rejected" <?php echo ($submission['status'] == 'rejected') ? 'selected' : ''; ?>>Rejected</option>
|
||||||
|
</select>
|
||||||
|
<button type="submit" class="btn btn-primary btn-sm mt-1">Update</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<?php else: ?>
|
||||||
|
<p>No submissions for this competition yet.</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php require_once 'includes/footer.php'; ?>
|
||||||
57
admin_users.php
Normal file
57
admin_users.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
require_once 'includes/header.php';
|
||||||
|
|
||||||
|
// Protect the page: redirect if user is not logged in
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch all users from the database
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->query("SELECT id, name, email, created_at FROM users ORDER BY created_at DESC");
|
||||||
|
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main class="container mt-5 pt-5">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h1 class="h2">Registered Users</h1>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p>This table displays all users who have registered on the platform.</p>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead class="thead-dark">
|
||||||
|
<tr>
|
||||||
|
<th scope="col">ID</th>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Email</th>
|
||||||
|
<th scope="col">Registration Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if (empty($users)): ?>
|
||||||
|
<tr>
|
||||||
|
<td colspan="4" class="text-center">No users found.</td>
|
||||||
|
</tr>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($users as $user): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars($user['id']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($user['name']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($user['email']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars(date('F j, Y, g:i a', strtotime($user['created_at']))); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php require_once 'includes/footer.php'; ?>
|
||||||
52
assets/css/custom.css
Normal file
52
assets/css/custom.css
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
body {
|
||||||
|
padding-top: 56px; /* Adjust for fixed navbar */
|
||||||
|
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#hero {
|
||||||
|
height: 80vh;
|
||||||
|
background: linear-gradient(45deg, rgba(13, 110, 253, 0.1), rgba(13, 202, 240, 0.1));
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#hero h1 {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-image: linear-gradient(45deg, #0D6EFD, #0DCAF0);
|
||||||
|
border: none;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
scroll-margin-top: 56px; /* Offset for navbar */
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#contactForm .form-control {
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contactForm .form-control:focus {
|
||||||
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||||
|
border-color: #0D6EFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
#form-feedback .alert {
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
46
assets/js/main.js
Normal file
46
assets/js/main.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
// Smooth scrolling for anchor links
|
||||||
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||||
|
anchor.addEventListener('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
document.querySelector(this.getAttribute('href')).scrollIntoView({
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Contact form submission
|
||||||
|
const contactForm = document.getElementById('contactForm');
|
||||||
|
if (contactForm) {
|
||||||
|
contactForm.addEventListener('submit', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const name = document.getElementById('name').value;
|
||||||
|
const email = document.getElementById('email').value;
|
||||||
|
const message = document.getElementById('message').value;
|
||||||
|
const feedbackContainer = document.getElementById('form-feedback');
|
||||||
|
const formContainer = document.getElementById('contact-form-container');
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('name', name);
|
||||||
|
formData.append('email', email);
|
||||||
|
formData.append('message', message);
|
||||||
|
|
||||||
|
fetch('contact.php', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
let alertClass = data.success ? 'alert-success' : 'alert-danger';
|
||||||
|
feedbackContainer.innerHTML = `<div class="alert ${alertClass}">${data.message}</div>`;
|
||||||
|
if (data.success) {
|
||||||
|
formContainer.style.display = 'none';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
feedbackContainer.innerHTML = `<div class="alert alert-danger">An unexpected error occurred. Please try again.</div>`;
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
87
competition_details.php
Normal file
87
competition_details.php
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'includes/header.php';
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
$competition_id = $_GET['id'] ?? null;
|
||||||
|
if (!$competition_id) {
|
||||||
|
echo "<div class='alert alert-danger'>Competition ID is missing.</div>";
|
||||||
|
require_once 'includes/footer.php';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM competitions WHERE id = ?");
|
||||||
|
$stmt->execute([$competition_id]);
|
||||||
|
$competition = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$competition) {
|
||||||
|
echo "<div class='alert alert-danger'>Competition not found.</div>";
|
||||||
|
require_once 'includes/footer.php';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['submission_file'])) {
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
echo "<div class='alert alert-danger'>You must be logged in to make a submission.</div>";
|
||||||
|
} else {
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
$file = $_FILES['submission_file'];
|
||||||
|
|
||||||
|
// File validation
|
||||||
|
if ($file['error'] === UPLOAD_ERR_OK) {
|
||||||
|
$upload_dir = 'uploads/';
|
||||||
|
$file_name = uniqid() . '-' . basename($file['name']);
|
||||||
|
$target_path = $upload_dir . $file_name;
|
||||||
|
|
||||||
|
if (move_uploaded_file($file['tmp_name'], $target_path)) {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO submissions (competition_id, user_id, file_path) VALUES (?, ?, ?)");
|
||||||
|
if ($stmt->execute([$competition_id, $user_id, $target_path])) {
|
||||||
|
echo "<div class='alert alert-success'>Submission uploaded successfully.</div>";
|
||||||
|
} else {
|
||||||
|
echo "<div class='alert alert-danger'>Failed to save submission to the database.</div>";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "<div class='alert alert-danger'>Failed to move uploaded file.</div>";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "<div class='alert alert-danger'>Error uploading file.</div>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="mt-5"><?php echo htmlspecialchars($competition['title']); ?></h1>
|
||||||
|
<p class="lead">
|
||||||
|
<strong>Start Date:</strong> <?php echo date("F j, Y, g:i a", strtotime($competition['start_date'])); ?><br>
|
||||||
|
<strong>End Date:</strong> <?php echo date("F j, Y, g:i a", strtotime($competition['end_date'])); ?>
|
||||||
|
</p>
|
||||||
|
<p><?php echo nl2br(htmlspecialchars($competition['description'])); ?></p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<?php if (isset($_SESSION['user_id'])): ?>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3>Submit Your Entry</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="competition_details.php?id=<?php echo $competition_id; ?>" method="post" enctype="multipart/form-data">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="submission_file">Select file to upload:</label>
|
||||||
|
<input type="file" class="form-control-file" id="submission_file" name="submission_file" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary mt-3">Upload Submission</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="alert alert-info">
|
||||||
|
Please <a href="login.php?return_url=<?php echo urlencode($_SERVER['REQUEST_URI']); ?>">login</a> to submit your entry for this competition.
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php require_once 'includes/footer.php'; ?>
|
||||||
67
competitions.php
Normal file
67
competitions.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
// Fetch all competitions
|
||||||
|
$competitions = [];
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->query("SELECT id, title, description, start_date, end_date FROM competitions WHERE end_date > NOW() ORDER BY start_date ASC");
|
||||||
|
$competitions = $stmt->fetchAll();
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
// In a real app, you'd log this error.
|
||||||
|
$error_message = "Sorry, we couldn't load competitions at this time.";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Competitions - READY BUDDY</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<?php include 'includes/header.php'; ?>
|
||||||
|
|
||||||
|
<main class="container mt-5">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<h2 class="fw-bold">Available Competitions</h2>
|
||||||
|
<p>Join a competition and show your skills!</p>
|
||||||
|
<hr>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<?php if (isset($error_message)): ?>
|
||||||
|
<div class="alert alert-danger"><?php echo $error_message; ?></div>
|
||||||
|
<?php elseif (empty($competitions)): ?>
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="alert alert-info">No upcoming competitions right now. Please check back later!</div>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($competitions as $comp): ?>
|
||||||
|
<div class="col-md-4 mb-4">
|
||||||
|
<div class="card h-100">
|
||||||
|
<div class="card-body d-flex flex-column">
|
||||||
|
<h5 class="card-title fw-bold"><?php echo htmlspecialchars($comp['title']); ?></h5>
|
||||||
|
<p class="card-text flex-grow-1"><?php echo nl2br(htmlspecialchars($comp['description'])); ?></p>
|
||||||
|
<p class="card-text"><small class="text-muted">Starts: <?php echo date('F j, Y, g:i a', strtotime($comp['start_date'])); ?></small></p>
|
||||||
|
<p class="card-text"><small class="text-muted">Ends: <?php echo date('F j, Y, g:i a', strtotime($comp['end_date'])); ?></small></p>
|
||||||
|
<a href="competition_details.php?id=<?php echo $comp['id']; ?>" class="btn btn-primary mt-auto">View Details</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include 'includes/footer.php'; ?>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
38
contact.php
Normal file
38
contact.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
require_once __DIR__ . '/mail/MailService.php';
|
||||||
|
|
||||||
|
$response = [
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'An error occurred.'
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$name = trim($_POST['name'] ?? '');
|
||||||
|
$email = trim($_POST['email'] ?? '');
|
||||||
|
$message = trim($_POST['message'] ?? '');
|
||||||
|
|
||||||
|
if (empty($name) || empty($email) || empty($message)) {
|
||||||
|
$response['message'] = 'Please fill out all fields.';
|
||||||
|
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$response['message'] = 'Please provide a valid email address.';
|
||||||
|
} else {
|
||||||
|
$to = getenv('MAIL_TO') ?: null; // Use environment variable or default in MailService
|
||||||
|
$subject = 'New Contact Form Submission from READY BUDDY';
|
||||||
|
|
||||||
|
$mailResult = MailService::sendContactMessage($name, $email, $message, $to, $subject);
|
||||||
|
|
||||||
|
if (!empty($mailResult['success'])) {
|
||||||
|
$response['success'] = true;
|
||||||
|
$response['message'] = 'Thank you for your message! We will get back to you shortly.';
|
||||||
|
} else {
|
||||||
|
// In a real app, you would log the detailed error: error_log($mailResult['error']);
|
||||||
|
$response['message'] = 'Sorry, there was an issue sending your message. Please try again later.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$response['message'] = 'Invalid request method.';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode($response);
|
||||||
19
db/migrations/001_create_competitions_table.php
Normal file
19
db/migrations/001_create_competitions_table.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../config.php';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$sql = "
|
||||||
|
CREATE TABLE IF NOT EXISTS competitions (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
start_date DATETIME,
|
||||||
|
end_date DATETIME,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);";
|
||||||
|
$pdo->exec($sql);
|
||||||
|
echo "Table 'competitions' created successfully (if it didn't exist)." . PHP_EOL;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
die("DB ERROR: " . $e->getMessage());
|
||||||
|
}
|
||||||
23
db/migrations/002_create_users_table.php
Normal file
23
db/migrations/002_create_users_table.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../../db/config.php';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
// Check if the table already exists
|
||||||
|
$stmt = $pdo->query("SHOW TABLES LIKE 'users'");
|
||||||
|
if ($stmt->rowCount() == 0) {
|
||||||
|
$sql = "CREATE TABLE users (
|
||||||
|
id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
email VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
password VARCHAR(255) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)";
|
||||||
|
$pdo->exec($sql);
|
||||||
|
echo "Table 'users' created successfully." . PHP_EOL;
|
||||||
|
} else {
|
||||||
|
echo "Table 'users' already exists." . PHP_EOL;
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
die("Could not connect to the database or create table: " . $e->getMessage());
|
||||||
|
}
|
||||||
21
db/migrations/003_create_submissions_table.php
Normal file
21
db/migrations/003_create_submissions_table.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../../db/config.php';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$sql = "
|
||||||
|
CREATE TABLE IF NOT EXISTS submissions (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
competition_id INT NOT NULL,
|
||||||
|
user_id INT(11) UNSIGNED NOT NULL,
|
||||||
|
file_path VARCHAR(255) NOT NULL,
|
||||||
|
uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (competition_id) REFERENCES competitions(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
";
|
||||||
|
$pdo->exec($sql);
|
||||||
|
echo "Migration 003_create_submissions_table executed successfully." . PHP_EOL;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
die("Could not connect to the database: " . $e->getMessage());
|
||||||
|
}
|
||||||
11
db/migrations/004_add_status_to_submissions.php
Normal file
11
db/migrations/004_add_status_to_submissions.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../../db/config.php';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$sql = "ALTER TABLE submissions ADD COLUMN status VARCHAR(50) DEFAULT 'pending' NOT NULL";
|
||||||
|
$pdo->exec($sql);
|
||||||
|
echo "Migration 004_add_status_to_submissions executed successfully." . PHP_EOL;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
die("Could not connect to the database: " . $e->getMessage());
|
||||||
|
}
|
||||||
19
db/migrations/005_create_certificates_table.php
Normal file
19
db/migrations/005_create_certificates_table.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../../db/config.php';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$sql = "
|
||||||
|
CREATE TABLE IF NOT EXISTS certificates (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
submission_id INT NOT NULL,
|
||||||
|
certificate_code VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (submission_id) REFERENCES submissions(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
";
|
||||||
|
$pdo->exec($sql);
|
||||||
|
echo "Migration 005_create_certificates_table executed successfully." . PHP_EOL;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
die("Could not connect to the database: " . $e->getMessage());
|
||||||
|
}
|
||||||
91
generate_certificate.php
Normal file
91
generate_certificate.php
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_GET['code'])) {
|
||||||
|
die("Certificate code is missing.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$certificate_code = $_GET['code'];
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT
|
||||||
|
c.certificate_code,
|
||||||
|
u.name as user_name,
|
||||||
|
comp.title as competition_title,
|
||||||
|
s.uploaded_at
|
||||||
|
FROM certificates c
|
||||||
|
JOIN submissions s ON c.submission_id = s.id
|
||||||
|
JOIN users u ON s.user_id = u.id
|
||||||
|
JOIN competitions comp ON s.competition_id = comp.id
|
||||||
|
WHERE c.certificate_code = ?
|
||||||
|
");
|
||||||
|
$stmt->execute([$certificate_code]);
|
||||||
|
$certificate = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$certificate) {
|
||||||
|
die("Invalid certificate code.");
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Certificate of Achievement</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #f0f2f5;
|
||||||
|
}
|
||||||
|
.certificate-container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 50px auto;
|
||||||
|
border: 10px solid #ddd;
|
||||||
|
padding: 50px;
|
||||||
|
background: #fff;
|
||||||
|
text-align: center;
|
||||||
|
font-family: 'Times New Roman', Times, serif;
|
||||||
|
}
|
||||||
|
.certificate-title {
|
||||||
|
font-size: 50px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.certificate-subtitle {
|
||||||
|
font-size: 25px;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
.user-name {
|
||||||
|
font-size: 40px;
|
||||||
|
font-style: italic;
|
||||||
|
color: #007bff;
|
||||||
|
margin: 40px 0;
|
||||||
|
}
|
||||||
|
.competition-title {
|
||||||
|
font-size: 30px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.date {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #777;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="certificate-container">
|
||||||
|
<div class="certificate-title">Certificate of Achievement</div>
|
||||||
|
<div class="certificate-subtitle">This is to certify that</div>
|
||||||
|
<div class="user-name"><?php echo htmlspecialchars($certificate['user_name']); ?></div>
|
||||||
|
<div class="certificate-subtitle">has successfully participated in the</div>
|
||||||
|
<div class="competition-title"><?php echo htmlspecialchars($certificate['competition_title']); ?></div>
|
||||||
|
<div class="date">Date: <?php echo date("F j, Y", strtotime($certificate['uploaded_at'])); ?></div>
|
||||||
|
<div class="mt-5">
|
||||||
|
<small>Certificate Code: <?php echo htmlspecialchars($certificate['certificate_code']); ?></small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
6
includes/footer.php
Normal file
6
includes/footer.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<footer class="footer bg-dark text-white text-center py-3 mt-auto">
|
||||||
|
<div class="container">
|
||||||
|
<p>© <?php echo date("Y"); ?> READY BUDDY. All Rights Reserved.</p>
|
||||||
|
<p><a href="admin_competitions.php" class="text-white-50">Admin Panel</a></p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
53
includes/header.php
Normal file
53
includes/header.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
if (session_status() == PHP_SESSION_NONE) {
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<header class="header fixed-top">
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand" href="index.php">READY BUDDY</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav ms-auto">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="index.php#home">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="index.php#about">About</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="competitions.php">Competitions</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="index.php#contact">Contact</a>
|
||||||
|
</li>
|
||||||
|
<?php if (isset($_SESSION['user_id'])): ?>
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
Profile
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
|
<li><a class="dropdown-item" href="admin_competitions.php">Competitions</a></li>
|
||||||
|
<li><a class="dropdown-item" href="admin_users.php">Users</a></li>
|
||||||
|
<li><a class="dropdown-item" href="admin_submissions.php">Submissions</a></li>
|
||||||
|
<li><a class="dropdown-item" href="my_certificates.php">My Certificates</a></li>
|
||||||
|
<li><hr class="dropdown-divider"></li>
|
||||||
|
<li><a class="dropdown-item" href="logout.php">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<?php else: ?>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="login.php">Login</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="btn btn-primary" href="register.php">Register</a>
|
||||||
|
</li>
|
||||||
|
<?php endif; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
236
index.php
236
index.php
@ -1,150 +1,106 @@
|
|||||||
<?php
|
<!DOCTYPE html>
|
||||||
declare(strict_types=1);
|
|
||||||
@ini_set('display_errors', '1');
|
|
||||||
@error_reporting(E_ALL);
|
|
||||||
@date_default_timezone_set('UTC');
|
|
||||||
|
|
||||||
$phpVersion = PHP_VERSION;
|
|
||||||
$now = date('Y-m-d H:i:s');
|
|
||||||
?>
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>New Style</title>
|
<title>READY BUDDY</title>
|
||||||
<?php
|
<meta name="description" content="Join competitions, showcase your skills, and win prizes with READY BUDDY.">
|
||||||
// Read project preview data from environment
|
<meta name="keywords" content="competitions, contests, prizes, challenges, skills, community, Built with Flatlogic Generator">
|
||||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
<meta property="og:title" content="READY BUDDY">
|
||||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
<meta property="og:description" content="The ultimate platform for online competitions and challenges.">
|
||||||
?>
|
<meta property="og:image" content="">
|
||||||
<?php if ($projectDescription): ?>
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
<!-- Meta description -->
|
<meta name="twitter:image" content="">
|
||||||
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
|
||||||
<!-- Open Graph meta tags -->
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||||
<!-- Twitter meta tags -->
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if ($projectImageUrl): ?>
|
|
||||||
<!-- Open Graph image -->
|
|
||||||
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
|
||||||
<!-- Twitter image -->
|
|
||||||
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
|
||||||
<?php endif; ?>
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--bg-color-start: #6a11cb;
|
|
||||||
--bg-color-end: #2575fc;
|
|
||||||
--text-color: #ffffff;
|
|
||||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
|
||||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
font-family: 'Inter', sans-serif;
|
|
||||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
|
||||||
color: var(--text-color);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 100vh;
|
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
body::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
|
||||||
animation: bg-pan 20s linear infinite;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
@keyframes bg-pan {
|
|
||||||
0% { background-position: 0% 0%; }
|
|
||||||
100% { background-position: 100% 100%; }
|
|
||||||
}
|
|
||||||
main {
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
.card {
|
|
||||||
background: var(--card-bg-color);
|
|
||||||
border: 1px solid var(--card-border-color);
|
|
||||||
border-radius: 16px;
|
|
||||||
padding: 2rem;
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
-webkit-backdrop-filter: blur(20px);
|
|
||||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
.loader {
|
|
||||||
margin: 1.25rem auto 1.25rem;
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
|
||||||
border-top-color: #fff;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
@keyframes spin {
|
|
||||||
from { transform: rotate(0deg); }
|
|
||||||
to { transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
.hint {
|
|
||||||
opacity: 0.9;
|
|
||||||
}
|
|
||||||
.sr-only {
|
|
||||||
position: absolute;
|
|
||||||
width: 1px; height: 1px;
|
|
||||||
padding: 0; margin: -1px;
|
|
||||||
overflow: hidden;
|
|
||||||
clip: rect(0, 0, 0, 0);
|
|
||||||
white-space: nowrap; border: 0;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: 3rem;
|
|
||||||
font-weight: 700;
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
letter-spacing: -1px;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
code {
|
|
||||||
background: rgba(0,0,0,0.2);
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
||||||
}
|
|
||||||
footer {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 1rem;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
<?php include 'includes/header.php'; ?>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="card">
|
<section id="hero" class="d-flex align-items-center text-center">
|
||||||
<h1>Analyzing your requirements and generating your website…</h1>
|
<div class="container">
|
||||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
<h1 class="display-3 fw-bold">Welcome to READY BUDDY</h1>
|
||||||
<span class="sr-only">Loading…</span>
|
<p class="lead col-lg-6 mx-auto">The ultimate platform to challenge yourself, compete with others, and win amazing prizes. Your journey to greatness starts here.</p>
|
||||||
|
<a href="#contact" class="btn btn-primary btn-lg rounded-pill">Get Started</a>
|
||||||
</div>
|
</div>
|
||||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
</section>
|
||||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
|
||||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
<section id="about" class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row align-items-center">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<h2 class="fw-bold">About Us</h2>
|
||||||
|
<p>READY BUDDY is a vibrant community and competition platform designed to bring out the best in you. We believe in the power of healthy competition to foster growth, learning, and connection. Whether you're a student, a professional, or a hobbyist, our platform provides the stage for you to shine.</p>
|
||||||
|
<p>We host a variety of competitions, from coding challenges and design contests to quizzes and creative showcases. Join us to test your skills, win prizes, and become part of a supportive community.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-lg-6 text-center">
|
||||||
|
<i class="bi bi-trophy-fill display-1 text-primary"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="portfolio" class="py-5 bg-light">
|
||||||
|
<div class="container text-center">
|
||||||
|
<h2 class="fw-bold">Portfolio</h2>
|
||||||
|
<p class="text-muted mb-5">Check out some of our past competitions and winner showcases.</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4 mb-4"><div class="card h-100"><div class="card-body"><h5 class="card-title">CodeFest 2025</h5><p class="card-text">An intense coding marathon.</p></div></div></div>
|
||||||
|
<div class="col-md-4 mb-4"><div class="card h-100"><div class="card-body"><h5 class="card-title">Design Masters</h5><p class="card-text">A creative design challenge.</p></div></div></div>
|
||||||
|
<div class="col-md-4 mb-4"><div class="card h-100"><div class="card-body"><h5 class="card-title">Quiz Bowl</h5><p class="card-text">A battle of wits and knowledge.</p></div></div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="testimonials" class="py-5">
|
||||||
|
<div class="container text-center">
|
||||||
|
<h2 class="fw-bold">What Our Users Say</h2>
|
||||||
|
<div id="testimonialCarousel" class="carousel slide" data-bs-ride="carousel">
|
||||||
|
<div class="carousel-inner">
|
||||||
|
<div class="carousel-item active"><p class="lead fst-italic col-lg-8 mx-auto">"A fantastic platform! I won the CodeFest and it was a great experience."</p><p class="fw-bold">- Alex Doe</p></div>
|
||||||
|
<div class="carousel-item"><p class="lead fst-italic col-lg-8 mx-auto">"The community is so supportive. I learned a lot."</p><p class="fw-bold">- Jane Smith</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="contact" class="py-5 bg-light">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-8 mx-auto text-center">
|
||||||
|
<h2 class="fw-bold">Contact Us</h2>
|
||||||
|
<p class="text-muted mb-4">Have questions? We'd love to hear from you.</p>
|
||||||
|
<div id="contact-form-container">
|
||||||
|
<form id="contactForm">
|
||||||
|
<div class="form-floating mb-3">
|
||||||
|
<input type="text" class="form-control" id="name" placeholder="Your Name" required>
|
||||||
|
<label for="name">Your Name</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-floating mb-3">
|
||||||
|
<input type="email" class="form-control" id="email" placeholder="name@example.com" required>
|
||||||
|
<label for="email">Email address</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-floating mb-3">
|
||||||
|
<textarea class="form-control" id="message" placeholder="Your Message" style="height: 150px" required></textarea>
|
||||||
|
<label for="message">Your Message</label>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary btn-lg rounded-pill">Send Message</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="form-feedback"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
|
||||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
<?php include 'includes/footer.php'; ?>
|
||||||
</footer>
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
91
login.php
Normal file
91
login.php
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
$return_url = $_REQUEST['return_url'] ?? 'index.php';
|
||||||
|
|
||||||
|
if (isset($_SESSION['user_id'])) {
|
||||||
|
header("Location: " . $return_url);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||||
|
$email = trim($_POST['email']);
|
||||||
|
$password = trim($_POST['password']);
|
||||||
|
|
||||||
|
if (empty($email) || empty($password)) {
|
||||||
|
$error = 'Email and password are required.';
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("SELECT id, password, name FROM users WHERE email = ?");
|
||||||
|
$stmt->execute([$email]);
|
||||||
|
$user = $stmt->fetch();
|
||||||
|
|
||||||
|
if ($user && password_verify($password, $user['password'])) {
|
||||||
|
$_SESSION['user_id'] = $user['id'];
|
||||||
|
$_SESSION['user_name'] = $user['name'];
|
||||||
|
|
||||||
|
header("Location: " . $return_url);
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$error = 'Invalid email or password.';
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$error = "Database error: " . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Login - READY BUDDY</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<?php include 'includes/header.php'; ?>
|
||||||
|
|
||||||
|
<main class="container mt-5 pt-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title text-center">Login</h2>
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="alert alert-danger"><?php echo $error; ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<form action="login.php" method="post">
|
||||||
|
<input type="hidden" name="return_url" value="<?php echo htmlspecialchars($return_url); ?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="email" class="form-label">Email address</label>
|
||||||
|
<input type="email" class="form-control" id="email" name="email" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="password" class="form-label">Password</label>
|
||||||
|
<input type="password" class="form-control" id="password" name="password" required>
|
||||||
|
</div>
|
||||||
|
<div class="d-grid">
|
||||||
|
<button type="submit" class="btn btn-primary">Login</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="text-center mt-3">
|
||||||
|
<p>Don't have an account? <a href="register.php">Register here</a>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include 'includes/footer.php'; ?>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="assets/js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
6
logout.php
Normal file
6
logout.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
session_unset();
|
||||||
|
session_destroy();
|
||||||
|
header("Location: index.php");
|
||||||
|
exit;
|
||||||
45
my_certificates.php
Normal file
45
my_certificates.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'includes/header.php';
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header("Location: login.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT
|
||||||
|
c.certificate_code,
|
||||||
|
comp.title as competition_title
|
||||||
|
FROM certificates c
|
||||||
|
JOIN submissions s ON c.submission_id = s.id
|
||||||
|
JOIN competitions comp ON s.competition_id = comp.id
|
||||||
|
WHERE s.user_id = ?
|
||||||
|
");
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$certificates = $stmt->fetchAll();
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container mt-5">
|
||||||
|
<h1 class="mb-4">My Certificates</h1>
|
||||||
|
|
||||||
|
<?php if (empty($certificates)): ?>
|
||||||
|
<div class="alert alert-info">You have not earned any certificates yet.</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<ul class="list-group">
|
||||||
|
<?php foreach ($certificates as $certificate): ?>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
<?php echo htmlspecialchars($certificate['competition_title']); ?>
|
||||||
|
<a href="generate_certificate.php?code=<?php echo htmlspecialchars($certificate['certificate_code']); ?>" class="btn btn-primary" target="_blank">View Certificate</a>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php require_once 'includes/footer.php'; ?>
|
||||||
96
register.php
Normal file
96
register.php
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
$success = '';
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||||
|
$name = trim($_POST['name']);
|
||||||
|
$email = trim($_POST['email']);
|
||||||
|
$password = trim($_POST['password']);
|
||||||
|
|
||||||
|
if (empty($name) || empty($email) || empty($password)) {
|
||||||
|
$error = 'All fields are required.';
|
||||||
|
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$error = 'Invalid email format.';
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
|
||||||
|
$stmt->execute([$email]);
|
||||||
|
if ($stmt->fetch()) {
|
||||||
|
$error = 'Email already exists.';
|
||||||
|
} else {
|
||||||
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO users (name, email, password) VALUES (?, ?, ?)");
|
||||||
|
if ($stmt->execute([$name, $email, $hashed_password])) {
|
||||||
|
$success = 'Registration successful! You can now <a href="login.php">login</a>.';
|
||||||
|
} else {
|
||||||
|
$error = 'Something went wrong. Please try again.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$error = "Database error: " . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Register - READY BUDDY</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<?php include 'includes/header.php'; ?>
|
||||||
|
|
||||||
|
<main class="container mt-5 pt-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title text-center">Create Account</h2>
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="alert alert-danger"><?php echo $error; ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($success): ?>
|
||||||
|
<div class="alert alert-success"><?php echo $success; ?></div>
|
||||||
|
<?php else: ?>
|
||||||
|
<form action="register.php" method="post">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="name" class="form-label">Full Name</label>
|
||||||
|
<input type="text" class="form-control" id="name" name="name" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="email" class="form-label">Email address</label>
|
||||||
|
<input type="email" class="form-control" id="email" name="email" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="password" class="form-label">Password</label>
|
||||||
|
<input type="password" class="form-control" id="password" name="password" required>
|
||||||
|
</div>
|
||||||
|
<div class="d-grid">
|
||||||
|
<button type="submit" class="btn btn-primary">Register</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
<div class="text-center mt-3">
|
||||||
|
<p>Already have an account? <a href="login.php">Login here</a>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php include 'includes/footer.php'; ?>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="assets/js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user