Autosave: 20260216-025634
This commit is contained in:
parent
3aa07f42ec
commit
edfdd98535
@ -24,7 +24,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
|
||||
audit_log('Created election', 'elections', $id);
|
||||
|
||||
header("Location: ../view_election.php?id=$id&success=1");
|
||||
$redirect = $_POST['redirect'] ?? "../view_election.php?id=$id&success=1";
|
||||
header("Location: $redirect");
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
die("Error: " . $e->getMessage());
|
||||
|
||||
46
api/manage_election_action.php
Normal file
46
api/manage_election_action.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../auth_helper.php';
|
||||
require_login();
|
||||
require_role(['Admin', 'Adviser']);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$id = $_POST['id'] ?? '';
|
||||
$status = $_POST['status'] ?? '';
|
||||
$end_time = $_POST['end_time'] ?? '';
|
||||
|
||||
if (!$id) {
|
||||
die("Missing election ID");
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$params = [];
|
||||
$sql = "UPDATE elections SET ";
|
||||
|
||||
if ($status) {
|
||||
$sql .= "status = ?, ";
|
||||
$params[] = $status;
|
||||
}
|
||||
|
||||
if ($end_time) {
|
||||
$sql .= "end_date_and_time = ?, ";
|
||||
$params[] = str_replace('T', ' ', $end_time);
|
||||
}
|
||||
|
||||
// Remove trailing comma and space
|
||||
$sql = rtrim($sql, ', ');
|
||||
$sql .= " WHERE id = ?";
|
||||
$params[] = $id;
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
|
||||
audit_log("Election Managed: Status=$status, EndTime=$end_time", 'elections', $id);
|
||||
|
||||
header("Location: ../dashboard.php?success=Election updated successfully");
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
die($e->getMessage());
|
||||
}
|
||||
}
|
||||
@ -18,9 +18,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$stmt->execute([$status, $id]);
|
||||
|
||||
audit_log("Updated election status to $status", 'elections', $id);
|
||||
|
||||
header("Location: ../view_election.php?id=$id&success=1");
|
||||
|
||||
$redirect = $_POST['redirect'] ?? "../view_election.php?id=$id&success=1";
|
||||
header("Location: $redirect");
|
||||
exit;
|
||||
|
||||
} catch (Exception $e) {
|
||||
die($e->getMessage());
|
||||
}
|
||||
|
||||
271
dashboard.php
271
dashboard.php
@ -3,11 +3,18 @@ require_once 'auth_helper.php';
|
||||
require_login();
|
||||
$user = get_user();
|
||||
|
||||
$pdo = db();
|
||||
$electionId = get_active_election_id();
|
||||
$election = get_active_election();
|
||||
$pdo = db();
|
||||
$electionId = get_active_election_id();
|
||||
$election = get_active_election();
|
||||
|
||||
// For Election Management Section
|
||||
$allElections = [];
|
||||
if (in_array($user['role'], ['Admin', 'Adviser', 'Officer'])) {
|
||||
$allElections = $pdo->query("SELECT * FROM elections WHERE archived = FALSE ORDER BY created_at DESC")->fetchAll();
|
||||
}
|
||||
|
||||
// Statistics (Filtered by Election)
|
||||
|
||||
// Statistics (Filtered by Election)
|
||||
$totalVoters = $pdo->prepare("SELECT COUNT(*) FROM election_assignments WHERE election_id = ? AND role_in_election = 'Voter'");
|
||||
$totalVoters->execute([$electionId]);
|
||||
$totalVoters = $totalVoters->fetchColumn();
|
||||
@ -64,6 +71,81 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Online Election System
|
||||
<link rel="stylesheet" href="assets/css/dashboard.css?v=<?= time() ?>">
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<style>
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 1000;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.modal-content {
|
||||
background: white;
|
||||
padding: 24px;
|
||||
border-radius: 12px;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
box-shadow: 0 10px 25px rgba(0,0,0,0.1);
|
||||
}
|
||||
.modal-header {
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
.modal-title {
|
||||
font-weight: 700;
|
||||
font-size: 1.1rem;
|
||||
color: #1e293b;
|
||||
}
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.form-group label {
|
||||
display: block;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: #64748b;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.form-control {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
font-size: 0.875rem;
|
||||
outline: none;
|
||||
}
|
||||
.modal-footer {
|
||||
margin-top: 24px;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
.btn-submit {
|
||||
flex: 1;
|
||||
background: #4f46e5;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn-cancel {
|
||||
flex: 1;
|
||||
background: white;
|
||||
border: 1px solid #e2e8f0;
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="dashboard-body">
|
||||
|
||||
@ -74,6 +156,16 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Online Election System
|
||||
<?php require_once 'includes/header.php'; ?>
|
||||
|
||||
<main class="dashboard-content animate-fade-in">
|
||||
<?php if (isset($_GET['success'])): ?>
|
||||
<div style="background: #ecfdf5; color: #10b981; padding: 12px 16px; border-radius: 8px; margin-bottom: 24px; font-size: 0.875rem; border: 1px solid #10b981;">
|
||||
<?= htmlspecialchars($_GET['success']) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($_GET['error'])): ?>
|
||||
<div style="background: #fef2f2; color: #ef4444; padding: 12px 16px; border-radius: 8px; margin-bottom: 24px; font-size: 0.875rem; border: 1px solid #ef4444;">
|
||||
<?= htmlspecialchars($_GET['error']) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="dashboard-header">
|
||||
<div>
|
||||
<h1 style="margin: 0 0 4px 0; font-size: 1.5rem; color: #1e293b;">Election Dashboard</h1>
|
||||
@ -83,6 +175,73 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Online Election System
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($allElections)): ?>
|
||||
<!-- Election Control Center -->
|
||||
<div class="content-section animate-stagger" style="margin-bottom: 32px;">
|
||||
<div class="section-header">
|
||||
<div class="section-title">Election Control Center</div>
|
||||
<button class="btn-new-election" id="btnNewElection" style="border: none; cursor: pointer; display: flex; align-items: center; gap: 8px;">
|
||||
<i data-lucide="plus"></i> New Election
|
||||
</button>
|
||||
</div>
|
||||
<table class="election-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Election Title</th>
|
||||
<th>Status</th>
|
||||
<th>Current End Time</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($allElections as $e): ?>
|
||||
<tr>
|
||||
<td style="font-weight: 500;"><a href="view_election.php?id=<?= $e['id'] ?>" style="color: #6366f1; text-decoration: none;"><?= htmlspecialchars($e['title']) ?></a></td>
|
||||
<td>
|
||||
<span class="status-badge status-<?= strtolower($e['status']) ?>">
|
||||
<?= htmlspecialchars($e['status']) ?>
|
||||
</span>
|
||||
</td>
|
||||
<td style="color: #64748b; font-size: 0.8rem;">
|
||||
<?= date('M d, H:i', strtotime($e['end_date_and_time'])) ?>
|
||||
</td>
|
||||
<td>
|
||||
<div class="quick-actions">
|
||||
<?php if ($e['status'] === 'Preparing'): ?>
|
||||
<form action="api/update_election_status.php" method="POST" style="display:inline;">
|
||||
<input type="hidden" name="id" value="<?= $e['id'] ?>">
|
||||
<input type="hidden" name="status" value="Ongoing">
|
||||
<input type="hidden" name="redirect" value="../dashboard.php?success=Election started">
|
||||
<button type="submit" class="btn-update" style="background: #10b981;">Start</button>
|
||||
</form>
|
||||
<?php elseif ($e['status'] === 'Ongoing'): ?>
|
||||
<form action="api/update_election_status.php" method="POST" style="display:inline;">
|
||||
<input type="hidden" name="id" value="<?= $e['id'] ?>">
|
||||
<input type="hidden" name="status" value="Finished">
|
||||
<input type="hidden" name="redirect" value="../dashboard.php?success=Election ended">
|
||||
<button type="submit" class="btn-update" style="background: #ef4444;">End</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (in_array($user['role'], ['Admin', 'Adviser'])): ?>
|
||||
<button
|
||||
class="btn-update btn-manage-election"
|
||||
style="background: #6366f1;"
|
||||
data-id="<?= $e['id'] ?>"
|
||||
data-title="<?= htmlspecialchars($e['title']) ?>"
|
||||
data-status="<?= $e['status'] ?>"
|
||||
data-end="<?= $e['end_date_and_time'] ?>"
|
||||
>Manage</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Stats Grid -->
|
||||
<div class="stats-grid animate-stagger">
|
||||
<div class="stat-card">
|
||||
@ -243,5 +402,109 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Online Election System
|
||||
updateSectionChart(trackFilter.value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Override/Manage Modal -->
|
||||
<div id="manageElectionModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title" id="modalElectionTitle">Manage Election</div>
|
||||
</div>
|
||||
<form action="api/manage_election_action.php" method="POST">
|
||||
<input type="hidden" name="id" id="modalElectionId">
|
||||
<div class="form-group">
|
||||
<label>Override Status</label>
|
||||
<select name="status" id="modalElectionStatus" class="form-control">
|
||||
<option value="Preparing">Preparing</option>
|
||||
<option value="Ongoing">Ongoing</option>
|
||||
<option value="Finished">Finished</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Change End Time</label>
|
||||
<input type="datetime-local" name="end_time" id="modalElectionEndTime" class="form-control">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn-cancel" onclick="closeModal('manageElectionModal')">Cancel</button>
|
||||
<button type="submit" class="btn-submit">Save Changes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New Election Modal -->
|
||||
<div id="createElectionModal" class="modal">
|
||||
<div class="modal-content" style="max-width: 500px;">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title">Create New Election</div>
|
||||
</div>
|
||||
<form action="api/create_election.php" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Election Title</label>
|
||||
<input type="text" name="title" class="form-control" placeholder="e.g. SSG General Election 2026" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<textarea name="description" class="form-control" rows="3" placeholder="Briefly describe the purpose..."></textarea>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
|
||||
<div class="form-group">
|
||||
<label>Start Date & Time</label>
|
||||
<input type="datetime-local" name="start_date" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>End Date & Time</label>
|
||||
<input type="datetime-local" name="end_date" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn-cancel" onclick="closeModal('createElectionModal')">Cancel</button>
|
||||
<button type="submit" class="btn-submit">Create Election</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('btnNewElection').addEventListener('click', function() {
|
||||
document.getElementById('createElectionModal').style.display = 'flex';
|
||||
});
|
||||
|
||||
document.querySelectorAll('.btn-manage-election').forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const id = this.getAttribute('data-id');
|
||||
const title = this.getAttribute('data-title');
|
||||
const status = this.getAttribute('data-status');
|
||||
const end = this.getAttribute('data-end');
|
||||
|
||||
document.getElementById('modalElectionId').value = id;
|
||||
document.getElementById('modalElectionTitle').innerText = 'Manage: ' + title;
|
||||
document.getElementById('modalElectionStatus').value = status;
|
||||
|
||||
if (end) {
|
||||
const date = new Date(end);
|
||||
const offset = date.getTimezoneOffset() * 60000;
|
||||
const localISODate = new Date(date.getTime() - offset).toISOString().slice(0, 16);
|
||||
document.getElementById('modalElectionEndTime').value = localISODate;
|
||||
}
|
||||
|
||||
document.getElementById('manageElectionModal').style.display = 'flex';
|
||||
});
|
||||
});
|
||||
|
||||
function closeModal(modalId) {
|
||||
if (modalId) {
|
||||
document.getElementById(modalId).style.display = 'none';
|
||||
} else {
|
||||
document.getElementById('manageElectionModal').style.display = 'none';
|
||||
document.getElementById('createElectionModal').style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
window.onclick = function(event) {
|
||||
if (event.target.classList.contains('modal')) {
|
||||
event.target.style.display = 'none';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -26,94 +26,137 @@ $users = $pdo->query("SELECT id, name, student_id FROM users WHERE role = 'Voter
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Manage Candidates | <?= htmlspecialchars($position['name']) ?></title>
|
||||
<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;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/style.css?v=<?= time() ?>">
|
||||
<link rel="stylesheet" href="assets/css/dashboard.css?v=<?= time() ?>">
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<a href="index.php" class="brand">E-Vote Pro</a>
|
||||
<div>
|
||||
<a href="view_election.php?id=<?= $position['election_id'] ?>" class="btn btn-outline">Back to Election</a>
|
||||
</div>
|
||||
</nav>
|
||||
<body class="dashboard-body">
|
||||
<?php require_once 'includes/sidebar.php'; ?>
|
||||
|
||||
<div class="container">
|
||||
<div class="header-actions">
|
||||
<div class="main-wrapper">
|
||||
<?php require_once 'includes/header.php'; ?>
|
||||
|
||||
<main class="dashboard-content animate-fade-in">
|
||||
<div class="dashboard-header">
|
||||
<div>
|
||||
<h1>Candidates for <?= htmlspecialchars($position['name']) ?></h1>
|
||||
<p><?= htmlspecialchars($position['election_title']) ?></p>
|
||||
<h1 style="margin: 0; font-size: 1.75rem; color: #1e293b;">Candidates for <?= htmlspecialchars($position['name']) ?></h1>
|
||||
<p class="welcome-msg" style="margin-top: 4px;"><?= htmlspecialchars($position['election_title']) ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a href="view_election.php?id=<?= $position['election_id'] ?>" style="display: flex; align-items: center; gap: 8px; color: #4f46e5; font-weight: 600; text-decoration: none; background: #ffffff; padding: 10px 20px; border-radius: 8px; border: 1px solid #e2e8f0;">
|
||||
<i data-lucide="arrow-left" style="width: 16px;"></i>
|
||||
Back to Election
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1fr 2fr; gap: 1.5rem;">
|
||||
<div class="card">
|
||||
<h3>Add Candidate</h3>
|
||||
<form action="api/add_candidate.php" method="POST">
|
||||
<input type="hidden" name="position_id" value="<?= $position_id ?>">
|
||||
<input type="hidden" name="election_id" value="<?= $position['election_id'] ?>">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Select User (Student)</label>
|
||||
<select name="user_id" class="form-control" required>
|
||||
<option value="">-- Choose Student --</option>
|
||||
<?php foreach ($users as $u): ?>
|
||||
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['name']) ?> (<?= $u['student_id'] ?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Party Name</label>
|
||||
<input type="text" name="party_name" class="form-control" placeholder="e.g. Independent">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Manifesto</label>
|
||||
<textarea name="manifesto" class="form-control" rows="3"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" style="width: 100%;">Add Candidate</button>
|
||||
</form>
|
||||
<div style="display: grid; grid-template-columns: 1fr 2fr; gap: 24px;">
|
||||
<div style="background: #ffffff; border: 1px solid #f3f4f6; border-radius: 16px; padding: 24px; height: fit-content;">
|
||||
<h3 style="margin-top: 0; font-size: 1.1rem; font-weight: 700; color: #1e293b; margin-bottom: 20px;">Add New Candidate</h3>
|
||||
<form action="api/add_candidate.php" method="POST">
|
||||
<input type="hidden" name="position_id" value="<?= $position_id ?>">
|
||||
<input type="hidden" name="election_id" value="<?= $position['election_id'] ?>">
|
||||
|
||||
<div style="margin-bottom: 16px;">
|
||||
<label style="display: block; font-size: 0.75rem; font-weight: 600; color: #64748b; margin-bottom: 6px;">Select Student</label>
|
||||
<select name="user_id" style="width: 100%; padding: 10px; border: 1px solid #e2e8f0; border-radius: 8px; outline: none; background: #ffffff; font-size: 0.875rem;" required>
|
||||
<option value="">-- Choose Student --</option>
|
||||
<?php foreach ($users as $u): ?>
|
||||
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['name']) ?> (<?= $u['student_id'] ?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 16px;">
|
||||
<label style="display: block; font-size: 0.75rem; font-weight: 600; color: #64748b; margin-bottom: 6px;">Party Name</label>
|
||||
<input type="text" name="party_name" style="width: 100%; padding: 10px; border: 1px solid #e2e8f0; border-radius: 8px; outline: none; font-size: 0.875rem;" placeholder="e.g. Independent">
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 24px;">
|
||||
<label style="display: block; font-size: 0.75rem; font-weight: 600; color: #64748b; margin-bottom: 6px;">Manifesto</label>
|
||||
<textarea name="manifesto" rows="4" style="width: 100%; padding: 10px; border: 1px solid #e2e8f0; border-radius: 8px; outline: none; font-size: 0.875rem; font-family: inherit;" placeholder="Briefly describe the candidate's goals..."></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" style="width: 100%; background: #4f46e5; color: white; border: none; padding: 12px; border-radius: 8px; font-weight: 700; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px;">
|
||||
<i data-lucide="user-plus" style="width: 18px;"></i>
|
||||
Register Candidate
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>Current Candidates</h3>
|
||||
<?php if (empty($candidates)): ?>
|
||||
<p class="text-muted">No candidates added yet.</p>
|
||||
<?php else: ?>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Student</th>
|
||||
<th>Party</th>
|
||||
<th>Approved</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($candidates as $c): ?>
|
||||
<tr>
|
||||
<td>
|
||||
<strong><?= htmlspecialchars($c['name']) ?></strong><br>
|
||||
<small><?= $c['student_id'] ?></small>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($c['party_name'] ?: 'None') ?></td>
|
||||
<td>
|
||||
<span class="badge" style="background: <?= $c['approved'] ? '#22c55e' : '#94a3b8' ?>">
|
||||
<?= $c['approved'] ? 'Yes' : 'Pending' ?>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<form action="api/toggle_candidate_approval.php" method="POST" style="display:inline;">
|
||||
<input type="hidden" name="id" value="<?= $c['id'] ?>">
|
||||
<button type="submit" class="btn btn-outline" style="padding: 0.25rem 0.5rem; font-size: 0.75rem;">
|
||||
<?= $c['approved'] ? 'Revoke' : 'Approve' ?>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
<div style="background: #ffffff; border: 1px solid #f3f4f6; border-radius: 16px; overflow: hidden;">
|
||||
<div style="padding: 24px; border-bottom: 1px solid #f3f4f6;">
|
||||
<h3 style="margin: 0; font-size: 1.1rem; font-weight: 700; color: #1e293b;">Registered Candidates</h3>
|
||||
</div>
|
||||
|
||||
<div style="overflow-x: auto;">
|
||||
<table style="width: 100%; border-collapse: collapse;">
|
||||
<thead>
|
||||
<tr style="background: #f9fafb; border-bottom: 1px solid #f3f4f6;">
|
||||
<th style="padding: 12px 24px; text-align: left; font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase;">Student Info</th>
|
||||
<th style="padding: 12px 24px; text-align: left; font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase;">Party Affiliation</th>
|
||||
<th style="padding: 12px 24px; text-align: left; font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase;">Status</th>
|
||||
<th style="padding: 12px 24px; text-align: right; font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase;">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($candidates)): ?>
|
||||
<tr>
|
||||
<td colspan="4" style="padding: 48px; text-align: center; color: #94a3b8;">
|
||||
<div style="display: flex; flex-direction: column; align-items: center; gap: 12px;">
|
||||
<i data-lucide="users" style="width: 48px; height: 48px; color: #e2e8f0;"></i>
|
||||
<span>No candidates have been registered for this position yet.</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($candidates as $c): ?>
|
||||
<tr style="border-bottom: 1px solid #f3f4f6; transition: background 0.2s;" onmouseover="this.style.background='#f8fafc'" onmouseout="this.style.background='transparent'">
|
||||
<td style="padding: 16px 24px;">
|
||||
<div style="display: flex; align-items: center; gap: 12px;">
|
||||
<div style="width: 36px; height: 36px; background: #e0e7ff; color: #4f46e5; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.875rem;">
|
||||
<?= strtoupper(substr($c['name'], 0, 1)) ?>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 600; color: #1e293b;"><?= htmlspecialchars($c['name']) ?></div>
|
||||
<div style="font-size: 0.75rem; color: #64748b;"><?= $c['student_id'] ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td style="padding: 16px 24px;">
|
||||
<span style="background: #f1f5f9; padding: 4px 10px; border-radius: 6px; font-size: 0.75rem; font-weight: 600; color: #475569;">
|
||||
<?= htmlspecialchars($c['party_name'] ?: 'Independent') ?>
|
||||
</span>
|
||||
</td>
|
||||
<td style="padding: 16px 24px;">
|
||||
<span style="padding: 4px 12px; border-radius: 9999px; font-size: 0.75rem; font-weight: 600; background: <?= $c['approved'] ? '#dcfce7' : '#f1f5f9' ?>; color: <?= $c['approved'] ? '#166534' : '#475569' ?>;">
|
||||
<?= $c['approved'] ? 'Approved' : 'Pending' ?>
|
||||
</span>
|
||||
</td>
|
||||
<td style="padding: 16px 24px; text-align: right;">
|
||||
<form action="api/toggle_candidate_approval.php" method="POST" style="display:inline;">
|
||||
<input type="hidden" name="id" value="<?= $c['id'] ?>">
|
||||
<button type="submit" style="background: <?= $c['approved'] ? '#fef2f2' : '#f0f9ff' ?>; color: <?= $c['approved'] ? '#ef4444' : '#0ea5e9' ?>; border: 1px solid <?= $c['approved'] ? '#fee2e2' : '#e0f2fe' ?>; padding: 6px 12px; border-radius: 6px; font-size: 0.75rem; font-weight: 700; cursor: pointer; transition: all 0.2s;">
|
||||
<?= $c['approved'] ? 'Revoke Approval' : 'Approve' ?>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
lucide.createIcons();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@ -34,176 +34,254 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Online Election System
|
||||
<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;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/style.css?v=<?= time() ?>">
|
||||
<link rel="stylesheet" href="assets/css/dashboard.css?v=<?= time() ?>">
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<a href="index.php" class="brand">E-Vote Pro</a>
|
||||
<div>
|
||||
<span style="margin-right: 1rem; color: var(--text-muted);"><?= htmlspecialchars($user['name']) ?></span>
|
||||
<a href="index.php" class="btn btn-outline">Back to Dashboard</a>
|
||||
</div>
|
||||
</nav>
|
||||
<body class="dashboard-body">
|
||||
<?php require_once 'includes/sidebar.php'; ?>
|
||||
|
||||
<div class="container">
|
||||
<div class="card">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start;">
|
||||
<div class="main-wrapper">
|
||||
<?php require_once 'includes/header.php'; ?>
|
||||
|
||||
<main class="dashboard-content animate-fade-in">
|
||||
<div class="dashboard-header" style="align-items: center;">
|
||||
<div>
|
||||
<h1 style="margin: 0; font-size: 1.5rem;"><?= htmlspecialchars($election['title']) ?></h1>
|
||||
<p style="margin: 0.5rem 0; color: var(--text-muted);"><?= htmlspecialchars($election['description']) ?></p>
|
||||
<div style="margin-top: 1rem; font-size: 0.875rem;">
|
||||
<strong>Status:</strong> <span class="badge badge-<?= strtolower($election['status']) ?>"><?= $election['status'] ?></span> |
|
||||
<strong>Period:</strong> <?= date('M d, H:i', strtotime($election['start_date_and_time'])) ?> to <?= date('M d, H:i', strtotime($election['end_date_and_time'])) ?>
|
||||
</div>
|
||||
<h1 style="margin: 0; font-size: 1.75rem; color: #1e293b;"><?= htmlspecialchars($election['title']) ?></h1>
|
||||
<p class="welcome-msg" style="margin-top: 4px;"><?= htmlspecialchars($election['description']) ?></p>
|
||||
</div>
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
<div style="display: flex; gap: 12px;">
|
||||
<?php if (in_array($user['role'], ['Admin', 'Adviser', 'Officer'])): ?>
|
||||
<button class="btn btn-outline" onclick="document.getElementById('editElectionModal').style.display='flex'">Edit Info</button>
|
||||
<button class="btn-action" style="background: #ffffff; border: 1px solid #e2e8f0; color: #4b5563; padding: 10px 20px; border-radius: 8px; font-weight: 600; cursor: pointer; display: flex; align-items: center; gap: 8px;" onclick="document.getElementById('editElectionModal').style.display='flex'">
|
||||
<i data-lucide="edit-3" style="width: 16px;"></i>
|
||||
Edit Info
|
||||
</button>
|
||||
<?php if ($election['status'] === 'Preparing'): ?>
|
||||
<form action="api/update_election_status.php" method="POST">
|
||||
<input type="hidden" name="id" value="<?= $election['id'] ?>">
|
||||
<input type="hidden" name="status" value="Ongoing">
|
||||
<button type="submit" class="btn btn-primary" style="background: #166534;">Launch Election</button>
|
||||
<button type="submit" class="btn-action" style="background: #166534; color: white; padding: 10px 20px; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; display: flex; align-items: center; gap: 8px;">
|
||||
<i data-lucide="play" style="width: 16px;"></i>
|
||||
Launch Election
|
||||
</button>
|
||||
</form>
|
||||
<?php elseif ($election['status'] === 'Ongoing'): ?>
|
||||
<form action="api/update_election_status.php" method="POST">
|
||||
<input type="hidden" name="id" value="<?= $election['id'] ?>">
|
||||
<input type="hidden" name="status" value="Finished">
|
||||
<button type="submit" class="btn btn-primary" style="background: #ef4444;">End Election</button>
|
||||
<button type="submit" class="btn-action" style="background: #ef4444; color: white; padding: 10px 20px; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; display: flex; align-items: center; gap: 8px;">
|
||||
<i data-lucide="square" style="width: 16px;"></i>
|
||||
End Election
|
||||
</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 1.5rem;">
|
||||
<div>
|
||||
<div class="card">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
||||
<h2 style="margin: 0; font-size: 1.1rem;">Positions</h2>
|
||||
<?php if ($election['status'] === 'Preparing'): ?>
|
||||
<button onclick="document.getElementById('addPositionForm').style.display='block'" class="btn btn-outline" style="padding: 0.25rem 0.5rem; font-size: 0.75rem;">+ Add Position</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div id="addPositionForm" style="display:none; margin-bottom: 1.5rem; padding: 1rem; background: #f8fafc; border-radius: 8px;">
|
||||
<form action="api/add_position.php" method="POST">
|
||||
<input type="hidden" name="election_id" value="<?= $election['id'] ?>">
|
||||
<div style="display: flex; gap: 0.5rem; align-items: flex-end;">
|
||||
<div style="flex: 2;">
|
||||
<label style="display:block; font-size: 0.75rem;">Position Name</label>
|
||||
<input type="text" name="name" class="form-control" placeholder="e.g. President" required>
|
||||
</div>
|
||||
<div style="flex: 1;">
|
||||
<label style="display:block; font-size: 0.75rem;">Max Votes</label>
|
||||
<input type="number" name="max_votes" class="form-control" value="1" min="1">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
<button type="button" onclick="document.getElementById('addPositionForm').style.display='none'" class="btn btn-outline">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php if (empty($positions)): ?>
|
||||
<div style="text-align: center; padding: 1.5rem; border: 1px dashed var(--border-color); border-radius: var(--radius);">
|
||||
<p style="color: var(--text-muted); margin: 0;">No positions defined yet.</p>
|
||||
<div class="stats-grid" style="grid-template-columns: repeat(3, 1fr); margin-bottom: 24px;">
|
||||
<div class="stat-card">
|
||||
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">
|
||||
<div style="background: #eef2ff; padding: 10px; border-radius: 10px; color: #4f46e5;">
|
||||
<i data-lucide="check-square"></i>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Position Name</th>
|
||||
<th>Max Votes</th>
|
||||
<th>Candidates</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($positions as $pos):
|
||||
$cStmt = $pdo->prepare("SELECT COUNT(*) FROM candidates WHERE position_id = ?");
|
||||
$cStmt->execute([$pos['id']]);
|
||||
$cCount = $cStmt->fetchColumn();
|
||||
?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($pos['name']) ?></td>
|
||||
<td><?= $pos['max_votes'] ?></td>
|
||||
<td><?= $cCount ?></td>
|
||||
<td>
|
||||
<a href="manage_candidates.php?position_id=<?= $pos['id'] ?>" class="btn btn-outline" style="padding: 0.25rem 0.5rem; font-size: 0.75rem;">Candidates</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
<span style="font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: 0.05em;">Status</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<span class="status-indicator <?= strtolower($election['status']) ?>" style="padding: 4px 12px; border-radius: 9999px; font-size: 0.875rem; font-weight: 600; background: <?= $election['status'] === 'Ongoing' ? '#dcfce7' : ($election['status'] === 'Preparing' ? '#fef9c3' : '#f1f5f9') ?>; color: <?= $election['status'] === 'Ongoing' ? '#166534' : ($election['status'] === 'Preparing' ? '#854d0e' : '#475569') ?>;">
|
||||
<?= $election['status'] ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="card">
|
||||
<h2 style="margin-top: 0; font-size: 1.1rem;">Quick Stats</h2>
|
||||
<div class="stat-card">
|
||||
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">
|
||||
<div style="background: #fff7ed; padding: 10px; border-radius: 10px; color: #f97316;">
|
||||
<i data-lucide="calendar"></i>
|
||||
</div>
|
||||
<span style="font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: 0.05em;">Election Period</span>
|
||||
</div>
|
||||
<div style="font-size: 0.875rem; font-weight: 600; color: #1e293b;">
|
||||
<?= date('M d, H:i', strtotime($election['start_date_and_time'])) ?> — <?= date('M d, H:i', strtotime($election['end_date_and_time'])) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">
|
||||
<div style="background: #ecfdf5; padding: 10px; border-radius: 10px; color: #10b981;">
|
||||
<i data-lucide="users"></i>
|
||||
</div>
|
||||
<span style="font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: 0.05em;">Total Participation</span>
|
||||
</div>
|
||||
<?php
|
||||
$vStmt = $pdo->prepare("SELECT COUNT(DISTINCT voter_id) FROM votes WHERE election_id = ?");
|
||||
$vStmt->execute([$id]);
|
||||
$votesCount = $vStmt->fetchColumn();
|
||||
?>
|
||||
<div style="margin-bottom: 1rem;">
|
||||
<div style="font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; font-weight: 600;">Total Votes Cast</div>
|
||||
<div style="font-size: 1.5rem; font-weight: 700;"><?= $votesCount ?></div>
|
||||
<div style="font-size: 1.5rem; font-weight: 800; color: #1e293b;"><?= $votesCount ?> <small style="font-size: 0.875rem; color: #64748b; font-weight: 500;">Votes Cast</small></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 24px;">
|
||||
<div style="background: #ffffff; border: 1px solid #f3f4f6; border-radius: 16px; overflow: hidden;">
|
||||
<div style="padding: 24px; border-bottom: 1px solid #f3f4f6; display: flex; justify-content: space-between; align-items: center;">
|
||||
<h2 style="margin: 0; font-size: 1.1rem; color: #1e293b; font-weight: 700;">Positions & Structure</h2>
|
||||
<?php if ($election['status'] === 'Preparing'): ?>
|
||||
<button onclick="document.getElementById('addPositionForm').style.display='block'" style="background: #4f46e5; color: white; border: none; padding: 8px 16px; border-radius: 8px; font-size: 0.875rem; font-weight: 600; cursor: pointer; display: flex; align-items: center; gap: 6px;">
|
||||
<i data-lucide="plus" style="width: 14px;"></i>
|
||||
Add Position
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div style="margin-bottom: 1rem;">
|
||||
<?php
|
||||
$canStmt = $pdo->prepare("SELECT COUNT(*) FROM candidates WHERE election_id = ?");
|
||||
$canStmt->execute([$id]);
|
||||
$candidatesTotal = $canStmt->fetchColumn();
|
||||
?>
|
||||
<div style="font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; font-weight: 600;">Total Candidates</div>
|
||||
<div style="font-size: 1.5rem; font-weight: 700;"><?= $candidatesTotal ?></div>
|
||||
|
||||
<div id="addPositionForm" style="display:none; margin: 24px; padding: 20px; background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px;">
|
||||
<form action="api/add_position.php" method="POST">
|
||||
<input type="hidden" name="election_id" value="<?= $election['id'] ?>">
|
||||
<div style="display: grid; grid-template-columns: 2fr 1fr auto; gap: 16px; align-items: flex-end;">
|
||||
<div>
|
||||
<label style="display:block; font-size: 0.75rem; font-weight: 600; color: #64748b; margin-bottom: 6px;">Position Name</label>
|
||||
<input type="text" name="name" style="width: 100%; padding: 10px; border: 1px solid #e2e8f0; border-radius: 8px; outline: none;" placeholder="e.g. President" required>
|
||||
</div>
|
||||
<div>
|
||||
<label style="display:block; font-size: 0.75rem; font-weight: 600; color: #64748b; margin-bottom: 6px;">Max Votes</label>
|
||||
<input type="number" name="max_votes" style="width: 100%; padding: 10px; border: 1px solid #e2e8f0; border-radius: 8px; outline: none;" value="1" min="1">
|
||||
</div>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<button type="submit" style="background: #2563eb; color: white; border: none; padding: 10px 20px; border-radius: 8px; font-weight: 600; cursor: pointer;">Save</button>
|
||||
<button type="button" onclick="document.getElementById('addPositionForm').style.display='none'" style="background: #f1f5f9; color: #475569; border: none; padding: 10px 20px; border-radius: 8px; font-weight: 600; cursor: pointer;">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div style="overflow-x: auto;">
|
||||
<table style="width: 100%; border-collapse: collapse;">
|
||||
<thead>
|
||||
<tr style="background: #f9fafb; border-bottom: 1px solid #f3f4f6;">
|
||||
<th style="padding: 12px 24px; text-align: left; font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase;">Position Name</th>
|
||||
<th style="padding: 12px 24px; text-align: left; font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase;">Max Votes</th>
|
||||
<th style="padding: 12px 24px; text-align: left; font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase;">Candidates</th>
|
||||
<th style="padding: 12px 24px; text-align: right; font-size: 0.75rem; font-weight: 700; color: #64748b; text-transform: uppercase;">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($positions)): ?>
|
||||
<tr>
|
||||
<td colspan="4" style="padding: 48px; text-align: center; color: #94a3b8;">
|
||||
<div style="display: flex; flex-direction: column; align-items: center; gap: 12px;">
|
||||
<i data-lucide="layers" style="width: 48px; height: 48px; color: #e2e8f0;"></i>
|
||||
<span>No positions defined yet. Start by adding one.</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($positions as $pos):
|
||||
$cStmt = $pdo->prepare("SELECT COUNT(*) FROM candidates WHERE position_id = ?");
|
||||
$cStmt->execute([$pos['id']]);
|
||||
$cCount = $cStmt->fetchColumn();
|
||||
?>
|
||||
<tr style="border-bottom: 1px solid #f3f4f6; transition: background 0.2s;" onmouseover="this.style.background='#f8fafc'" onmouseout="this.style.background='transparent'">
|
||||
<td style="padding: 16px 24px; font-weight: 600; color: #1e293b;"><?= htmlspecialchars($pos['name']) ?></td>
|
||||
<td style="padding: 16px 24px; color: #4b5563;">
|
||||
<span style="background: #f1f5f9; padding: 4px 10px; border-radius: 6px; font-size: 0.75rem; font-weight: 600;"><?= $pos['max_votes'] ?> Vote<?= $pos['max_votes'] > 1 ? 's' : '' ?></span>
|
||||
</td>
|
||||
<td style="padding: 16px 24px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<div style="width: 8px; height: 8px; border-radius: 50%; background: #10b981;"></div>
|
||||
<span style="font-weight: 600; color: #1e293b;"><?= $cCount ?></span>
|
||||
</div>
|
||||
</td>
|
||||
<td style="padding: 16px 24px; text-align: right;">
|
||||
<a href="manage_candidates.php?position_id=<?= $pos['id'] ?>" style="color: #4f46e5; text-decoration: none; font-size: 0.875rem; font-weight: 600; display: inline-flex; align-items: center; gap: 6px;">
|
||||
Manage Candidates
|
||||
<i data-lucide="arrow-right" style="width: 14px;"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 24px;">
|
||||
<div style="background: #ffffff; border: 1px solid #f3f4f6; border-radius: 16px; padding: 24px;">
|
||||
<h2 style="margin-top: 0; font-size: 1.1rem; color: #1e293b; font-weight: 700; margin-bottom: 20px;">Quick Stats</h2>
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 20px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div>
|
||||
<div style="font-size: 0.7rem; color: #64748b; text-transform: uppercase; font-weight: 700; letter-spacing: 0.05em;">Total Candidates</div>
|
||||
<?php
|
||||
$canStmt = $pdo->prepare("SELECT COUNT(*) FROM candidates WHERE election_id = ?");
|
||||
$canStmt->execute([$id]);
|
||||
$candidatesTotal = $canStmt->fetchColumn();
|
||||
?>
|
||||
<div style="font-size: 1.5rem; font-weight: 800; color: #1e293b;"><?= $candidatesTotal ?></div>
|
||||
</div>
|
||||
<div style="background: #fef2f2; padding: 12px; border-radius: 12px; color: #ef4444;">
|
||||
<i data-lucide="user-check"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div>
|
||||
<div style="font-size: 0.7rem; color: #64748b; text-transform: uppercase; font-weight: 700; letter-spacing: 0.05em;">Voter Turnout</div>
|
||||
<div style="font-size: 1.5rem; font-weight: 800; color: #1e293b;"><?= $votesCount ?></div>
|
||||
</div>
|
||||
<div style="background: #f0fdf4; padding: 12px; border-radius: 12px; color: #22c55e;">
|
||||
<i data-lucide="bar-chart-3"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="background: linear-gradient(135deg, #4f46e5 0%, #3730a3 100%); border-radius: 16px; padding: 24px; color: white;">
|
||||
<h3 style="margin: 0; font-size: 1rem; font-weight: 700; margin-bottom: 12px;">Need Help?</h3>
|
||||
<p style="font-size: 0.875rem; opacity: 0.9; margin-bottom: 20px;">Manage your election structure by adding positions and assigning candidates to them. Once ready, you can launch the election.</p>
|
||||
<a href="reports_audit.php" style="display: block; width: 100%; text-align: center; background: white; color: #4f46e5; padding: 12px; border-radius: 8px; font-weight: 700; text-decoration: none; font-size: 0.875rem;">View Reports</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
<div id="editElectionModal" class="modal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:1000; align-items:center; justify-content:center;">
|
||||
<div class="card" style="width: 100%; max-width: 500px; padding: 2rem;">
|
||||
<h2 style="margin-top: 0; font-size: 1.25rem;">Edit Election</h2>
|
||||
|
||||
<div id="editElectionModal" class="modal">
|
||||
<div class="modal-content animate-scale-in" style="max-width: 550px;">
|
||||
<div class="modal-header">
|
||||
<h2 style="font-weight: 800;">Edit Election Details</h2>
|
||||
<button type="button" onclick="document.getElementById('editElectionModal').style.display='none'" class="close-btn">×</button>
|
||||
</div>
|
||||
<form action="api/update_election.php" method="POST">
|
||||
<input type="hidden" name="id" value="<?= $election['id'] ?>">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Election Title</label>
|
||||
<input type="text" name="title" class="form-control" value="<?= htmlspecialchars($election['title']) ?>" required>
|
||||
<div class="form-group" style="margin-bottom: 20px;">
|
||||
<label>Election Title</label>
|
||||
<input type="text" name="title" value="<?= htmlspecialchars($election['title']) ?>" style="width: 100%; padding: 12px; border: 1px solid #e2e8f0; border-radius: 10px; outline: none;" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Description</label>
|
||||
<textarea name="description" class="form-control" rows="3"><?= htmlspecialchars($election['description']) ?></textarea>
|
||||
<div class="form-group" style="margin-bottom: 20px;">
|
||||
<label>Description</label>
|
||||
<textarea name="description" rows="3" style="width: 100%; padding: 12px; border: 1px solid #e2e8f0; border-radius: 10px; outline: none; font-family: inherit;"><?= htmlspecialchars($election['description']) ?></textarea>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1.5rem;">
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 32px;">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Start Date</label>
|
||||
<input type="datetime-local" name="start_date" class="form-control" value="<?= date('Y-m-d\TH:i', strtotime($election['start_date_and_time'])) ?>" required>
|
||||
<label>Start Date & Time</label>
|
||||
<input type="datetime-local" name="start_date" value="<?= date('Y-m-d\TH:i', strtotime($election['start_date_and_time'])) ?>" style="width: 100%; padding: 12px; border: 1px solid #e2e8f0; border-radius: 10px; outline: none;" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">End Date</label>
|
||||
<input type="datetime-local" name="end_date" class="form-control" value="<?= date('Y-m-d\TH:i', strtotime($election['end_date_and_time'])) ?>" required>
|
||||
<label>End Date & Time</label>
|
||||
<input type="datetime-local" name="end_date" value="<?= date('Y-m-d\TH:i', strtotime($election['end_date_and_time'])) ?>" style="width: 100%; padding: 12px; border: 1px solid #e2e8f0; border-radius: 10px; outline: none;" required>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 1rem;">
|
||||
<button type="submit" class="btn btn-primary" style="flex: 1;">Update</button>
|
||||
<button type="button" onclick="document.getElementById('editElectionModal').style.display='none'" class="btn btn-outline" style="flex: 1;">Cancel</button>
|
||||
<div class="modal-footer">
|
||||
<button type="button" onclick="document.getElementById('editElectionModal').style.display='none'" class="btn-cancel">Cancel</button>
|
||||
<button type="submit" class="btn-submit" style="background: #4f46e5;">Save Changes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.modal { display: flex; }
|
||||
.form-control { width: 100%; padding: 0.5rem; border: 1px solid var(--border-color); border-radius: var(--radius); margin-top: 0.25rem; }
|
||||
.form-group { margin-bottom: 1rem; }
|
||||
.form-label { font-size: 0.75rem; font-weight: 600; color: var(--text-muted); }
|
||||
</style>
|
||||
|
||||
<script>
|
||||
lucide.createIcons();
|
||||
window.onclick = function(event) {
|
||||
if (event.target.id === 'editElectionModal') {
|
||||
event.target.style.display = 'none';
|
||||
@ -212,3 +290,4 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Online Election System
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user