109 lines
4.4 KiB
PHP
109 lines
4.4 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
require_once __DIR__ . '/auth_helper.php';
|
|
require_login();
|
|
$user = get_user();
|
|
|
|
$id = $_GET['id'] ?? '';
|
|
if (!$id) {
|
|
header("Location: index.php");
|
|
exit;
|
|
}
|
|
|
|
$pdo = db();
|
|
$stmt = $pdo->prepare("SELECT * FROM elections WHERE id = ?");
|
|
$stmt->execute([$id]);
|
|
$election = $stmt->fetch();
|
|
|
|
if (!$election) die("Election not found");
|
|
|
|
// Summary stats
|
|
$vStmt = $pdo->prepare("SELECT COUNT(DISTINCT voter_id) FROM votes WHERE election_id = ?");
|
|
$vStmt->execute([$id]);
|
|
$totalVoters = $vStmt->fetchColumn();
|
|
|
|
// Positions and results
|
|
$positions = $pdo->prepare("SELECT * FROM positions WHERE election_id = ? ORDER BY sort_order ASC");
|
|
$positions->execute([$id]);
|
|
$positions = $positions->fetchAll();
|
|
|
|
?>
|
|
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>Results: <?= htmlspecialchars($election['title']) ?></title>
|
|
<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() ?>">
|
|
<style>
|
|
.result-bar-container { background: #e2e8f0; height: 12px; border-radius: 6px; overflow: hidden; margin-top: 0.5rem; }
|
|
.result-bar { background: #2563eb; height: 100%; transition: width 0.5s; }
|
|
.candidate-result { margin-bottom: 1.5rem; padding: 1rem; border: 1px solid #e2e8f0; border-radius: 8px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<nav class="navbar">
|
|
<a href="index.php" class="brand">E-Vote Pro</a>
|
|
<div>
|
|
<a href="index.php" class="btn btn-outline">Dashboard</a>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="container">
|
|
<div class="card text-center mb-4">
|
|
<h1><?= htmlspecialchars($election['title']) ?> - Results</h1>
|
|
<p class="text-muted"><?= $election['status'] ?> Election</p>
|
|
<div style="font-size: 2rem; font-weight: 800;"><?= $totalVoters ?></div>
|
|
<div style="font-size: 0.75rem; color: #64748b; text-transform: uppercase;">Total Ballots Cast</div>
|
|
</div>
|
|
|
|
<?php if ($election['status'] === 'Preparing'): ?>
|
|
<div class="card text-center">
|
|
<p>Results will be available once the election starts.</p>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="row">
|
|
<?php foreach ($positions as $pos): ?>
|
|
<div class="col-12 mb-4">
|
|
<div class="card">
|
|
<h2 style="font-size: 1.25rem; border-bottom: 1px solid #e2e8f0; padding-bottom: 0.5rem; margin-bottom: 1rem;">
|
|
<?= htmlspecialchars($pos['name']) ?>
|
|
</h2>
|
|
|
|
<?php
|
|
$rStmt = $pdo->prepare("
|
|
SELECT c.*, u.name,
|
|
(SELECT COUNT(*) FROM votes v WHERE v.candidate_id = c.id) as vote_count
|
|
FROM candidates c
|
|
JOIN users u ON c.user_id = u.id
|
|
WHERE c.position_id = ?
|
|
ORDER BY vote_count DESC
|
|
");
|
|
$rStmt->execute([$pos['id']]);
|
|
$results = $rStmt->fetchAll();
|
|
|
|
$posTotal = array_sum(array_column($results, 'vote_count'));
|
|
?>
|
|
|
|
<?php foreach ($results as $res):
|
|
$percent = $posTotal > 0 ? round(($res['vote_count'] / $posTotal) * 100, 1) : 0;
|
|
?>
|
|
<div class="candidate-result">
|
|
<div style="display: flex; justify-content: space-between; font-weight: 600;">
|
|
<span><?= htmlspecialchars($res['name']) ?> (<?= htmlspecialchars($res['party_name'] ?: 'Ind.') ?>)</span>
|
|
<span><?= $res['vote_count'] ?> votes (<?= $percent ?>%)</span>
|
|
</div>
|
|
<div class="result-bar-container">
|
|
<div class="result-bar" style="width: <?= $percent ?>%"></div>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</body>
|
|
</html>
|