Online Voting System - Complete Project
Introduction to the Project
The Online Voting System is a secure, web-based application that allows organizations, institutions, or communities to conduct elections digitally. This system provides a platform where administrators can create and manage elections, define candidates, and monitor voting processes, while registered voters can cast their votes securely from anywhere with internet access.
The system implements role-based access control with three distinct user types: Admin, Voters, and Candidates. It ensures one person-one vote through database constraints, provides real-time result tabulation, and maintains voting integrity through session management and secure authentication.
Key Features
Admin Features
- Dashboard Overview: View total voters, candidates, elections, and voting statistics
- Election Management: Create, activate, deactivate, and delete elections
- Candidate Management: Add, edit, and remove candidates for specific elections
- Voter Management: View all registered voters and approve/block voter accounts
- Result Management: Declare results and view detailed voting analytics
- System Controls: Start/stop voting periods, ensure fair elections
Voter Features
- User Registration: Register with personal details and unique voter ID
- Secure Login: Access the system with credentials
- View Elections: See active and upcoming elections
- Cast Vote: Vote only once per election (system prevents duplicate voting)
- View Results: See election results after declaration
- Profile Management: Update personal information
Candidate Features
- Candidate Dashboard: View election status and personal vote count
- Profile Visibility: Display candidacy information to voters
- Campaign Statement: Add personal message to voters
Technology Stack
- Frontend: HTML5, CSS3, JavaScript (Vanilla)
- Backend: PHP (Core PHP, no frameworks)
- Database: MySQL
- Server: Apache (XAMPP/WAMP/MAMP recommended)
Project File Structure
online-voting-system/ │ ├── assets/ │ ├── css/ │ │ └── style.css │ ├── js/ │ │ └── script.js │ └── images/ │ └── (profile pictures, logos) │ ├── includes/ │ ├── config.php │ ├── functions.php │ ├── register_process.php │ ├── login_process.php │ └── vote_process.php │ ├── admin/ │ ├── dashboard.php │ ├── manage_elections.php │ ├── add_election.php │ ├── edit_election.php │ ├── manage_candidates.php │ ├── add_candidate.php │ ├── manage_voters.php │ ├── view_results.php │ └── declare_results.php │ ├── voter/ │ ├── dashboard.php │ ├── vote.php │ ├── view_elections.php │ ├── view_results.php │ └── profile.php │ ├── candidate/ │ └── dashboard.php │ ├── index.php ├── register.php ├── login.php ├── logout.php └── sql/ └── database.sql
Database Schema
File: sql/database.sql
-- Create Database
CREATE DATABASE IF NOT EXISTS `online_voting_system`;
USE `online_voting_system`;
-- Users Table
CREATE TABLE `users` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`voter_id` VARCHAR(20) UNIQUE NOT NULL,
`username` VARCHAR(50) UNIQUE NOT NULL,
`email` VARCHAR(100) UNIQUE NOT NULL,
`password` VARCHAR(255) NOT NULL,
`full_name` VARCHAR(100) NOT NULL,
`date_of_birth` DATE NOT NULL,
`gender` ENUM('Male', 'Female', 'Other') NOT NULL,
`address` TEXT,
`phone` VARCHAR(15),
`role` ENUM('admin', 'voter', 'candidate') DEFAULT 'voter',
`is_approved` BOOLEAN DEFAULT FALSE,
`profile_picture` VARCHAR(255) DEFAULT 'default.jpg',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);
-- Elections Table
CREATE TABLE `elections` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`election_name` VARCHAR(100) NOT NULL,
`description` TEXT,
`start_date` DATETIME NOT NULL,
`end_date` DATETIME NOT NULL,
`status` ENUM('upcoming', 'active', 'completed', 'cancelled') DEFAULT 'upcoming',
`created_by` INT(11),
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
FOREIGN KEY (`created_by`) REFERENCES `users`(`id`)
);
-- Candidates Table
CREATE TABLE `candidates` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`user_id` INT(11) NOT NULL,
`election_id` INT(11) NOT NULL,
`party_name` VARCHAR(100),
`symbol` VARCHAR(255),
`manifesto` TEXT,
`approved` BOOLEAN DEFAULT FALSE,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_candidate_per_election` (`user_id`, `election_id`),
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`),
FOREIGN KEY (`election_id`) REFERENCES `elections`(`id`)
);
-- Votes Table
CREATE TABLE `votes` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`voter_id` INT(11) NOT NULL,
`candidate_id` INT(11) NOT NULL,
`election_id` INT(11) NOT NULL,
`voted_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_vote_per_election` (`voter_id`, `election_id`),
FOREIGN KEY (`voter_id`) REFERENCES `users`(`id`),
FOREIGN KEY (`candidate_id`) REFERENCES `candidates`(`id`),
FOREIGN KEY (`election_id`) REFERENCES `elections`(`id`)
);
-- Insert Default Admin
INSERT INTO `users` (`voter_id`, `username`, `email`, `password`, `full_name`, `date_of_birth`, `gender`, `role`, `is_approved`)
VALUES ('ADMIN001', 'admin', '[email protected]', '$2y$10$YourHashedPasswordHere', 'System Administrator', '1990-01-01', 'Male', 'admin', TRUE);
Core PHP Files
Database Configuration
File: includes/config.php
<?php
session_start();
$host = 'localhost';
$dbname = 'online_voting_system';
$username = 'root';
$password = '';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
die("Connection failed: " . $e->getMessage());
}
// Helper Functions
function isLoggedIn() {
return isset($_SESSION['user_id']);
}
function isAdmin() {
return isset($_SESSION['user_role']) && $_SESSION['user_role'] == 'admin';
}
function isVoter() {
return isset($_SESSION['user_role']) && $_SESSION['user_role'] == 'voter';
}
function isCandidate() {
return isset($_SESSION['user_role']) && $_SESSION['user_role'] == 'candidate';
}
function redirect($url) {
header("Location: $url");
exit();
}
?>
Registration Processing
File: includes/register_process.php
<?php
require_once 'config.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Generate unique voter ID
$voter_id = 'VOT' . strtoupper(uniqid());
$username = trim($_POST['username']);
$email = trim($_POST['email']);
$password = $_POST['password'];
$confirm_password = $_POST['confirm_password'];
$full_name = trim($_POST['full_name']);
$date_of_birth = $_POST['date_of_birth'];
$gender = $_POST['gender'];
$address = trim($_POST['address']);
$phone = trim($_POST['phone']);
$errors = [];
// Validation
if (empty($username) || empty($email) || empty($password) || empty($full_name)) {
$errors[] = "Required fields cannot be empty.";
}
if ($password !== $confirm_password) {
$errors[] = "Passwords do not match.";
}
if (strlen($password) < 6) {
$errors[] = "Password must be at least 6 characters.";
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Invalid email format.";
}
// Check if username/email already exists
if (empty($errors)) {
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = ? OR email = ?");
$stmt->execute([$username, $email]);
if ($stmt->fetch()) {
$errors[] = "Username or Email already exists.";
}
}
// If no errors, insert user
if (empty($errors)) {
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
$sql = "INSERT INTO users (voter_id, username, email, password, full_name, date_of_birth, gender, address, phone, role)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'voter')";
$stmt = $pdo->prepare($sql);
if ($stmt->execute([$voter_id, $username, $email, $hashed_password, $full_name, $date_of_birth, $gender, $address, $phone])) {
$_SESSION['success'] = "Registration successful! Your Voter ID is: $voter_id. Please wait for admin approval.";
redirect("../login.php");
} else {
$errors[] = "Registration failed. Please try again.";
}
}
// If errors exist
if (!empty($errors)) {
$_SESSION['errors'] = $errors;
$_SESSION['form_data'] = $_POST;
redirect("../register.php");
}
} else {
redirect("../register.php");
}
?>
Login Processing
File: includes/login_process.php
<?php
require_once 'config.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username_email = trim($_POST['username_email']);
$password = $_POST['password'];
$errors = [];
if (empty($username_email) || empty($password)) {
$errors[] = "Both fields are required.";
}
if (empty($errors)) {
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? OR email = ?");
$stmt->execute([$username_email, $username_email]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
// Check if user is approved (except admin)
if ($user['role'] != 'admin' && !$user['is_approved']) {
$_SESSION['error'] = "Your account is pending approval by administrator.";
redirect("../login.php");
}
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['user_role'] = $user['role'];
$_SESSION['voter_id'] = $user['voter_id'];
$_SESSION['full_name'] = $user['full_name'];
// Redirect based on role
switch($user['role']) {
case 'admin':
redirect("../admin/dashboard.php");
break;
case 'candidate':
redirect("../candidate/dashboard.php");
break;
default:
redirect("../voter/dashboard.php");
}
} else {
$errors[] = "Invalid username/email or password.";
}
}
if (!empty($errors)) {
$_SESSION['errors'] = $errors;
redirect("../login.php");
}
} else {
redirect("../login.php");
}
?>
Vote Processing
File: includes/vote_process.php
<?php
require_once 'config.php';
if (!isLoggedIn() || !isVoter()) {
redirect("../login.php");
}
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['cast_vote'])) {
$candidate_id = $_POST['candidate_id'];
$election_id = $_POST['election_id'];
$voter_id = $_SESSION['user_id'];
// Check if election is active
$stmt = $pdo->prepare("SELECT * FROM elections WHERE id = ? AND status = 'active'");
$stmt->execute([$election_id]);
$election = $stmt->fetch();
if (!$election) {
$_SESSION['error'] = "This election is not active.";
redirect("../voter/vote.php");
}
// Check if voter has already voted
$stmt = $pdo->prepare("SELECT id FROM votes WHERE voter_id = ? AND election_id = ?");
$stmt->execute([$voter_id, $election_id]);
if ($stmt->fetch()) {
$_SESSION['error'] = "You have already voted in this election.";
redirect("../voter/vote.php");
}
// Cast the vote
$stmt = $pdo->prepare("INSERT INTO votes (voter_id, candidate_id, election_id) VALUES (?, ?, ?)");
if ($stmt->execute([$voter_id, $candidate_id, $election_id])) {
$_SESSION['success'] = "Your vote has been cast successfully!";
redirect("../voter/dashboard.php");
} else {
$_SESSION['error'] = "Failed to cast vote. Please try again.";
redirect("../voter/vote.php");
}
} else {
redirect("../voter/vote.php");
}
?>
Frontend Pages
Main Landing Page
File: index.php
<?php include 'includes/config.php'; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Online Voting System - Home</title> <link rel="stylesheet" href="assets/css/style.css"> </head> <body> <div class="container"> <header> <h1>🏛️ Online Voting System</h1> <p class="tagline">Secure • Transparent • Convenient</p> </header> <nav> <?php if (isLoggedIn()): ?> <span>Welcome, <?php echo htmlspecialchars($_SESSION['full_name']); ?>!</span> <a href="<?php echo $_SESSION['user_role'] == 'admin' ? 'admin/dashboard.php' : ($_SESSION['user_role'] == 'candidate' ? 'candidate/dashboard.php' : 'voter/dashboard.php'); ?>">Dashboard</a> <a href="logout.php">Logout</a> <?php else: ?> <a href="login.php" class="btn">Login</a> <a href="register.php" class="btn btn-secondary">Register</a> <?php endif; ?> </nav> <main> <section class="features"> <h2>Why Choose Our Voting System?</h2> <div class="feature-grid"> <div class="feature"> <h3>🔒 Secure</h3> <p>End-to-end encrypted voting process ensuring your vote remains confidential.</p> </div> <div class="feature"> <h3>✅ Transparent</h3> <p>Real-time result tabulation with complete audit trail.</p> </div> <div class="feature"> <h3>🌐 Accessible</h3> <p>Vote from anywhere, anytime during the election period.</p> </div> <div class="feature"> <h3>⚡ Fast</h3> <p>Instant result declaration and automated counting.</p> </div> </div> </section> <section class="how-it-works"> <h2>How It Works</h2> <ol> <li>Register with your details to get a unique Voter ID</li> <li>Wait for admin approval to verify your identity</li> <li>Login and browse active elections</li> <li>Cast your vote for your preferred candidate</li> <li>View results once the election concludes</li> </ol> </section> </main> <footer> <p>© 2024 Online Voting System. All rights reserved.</p> </footer> </div> </body> </html>
Registration Page
File: register.php
<?php include 'includes/config.php'; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Register - Online Voting System</title> <link rel="stylesheet" href="assets/css/style.css"> </head> <body> <div class="container"> <h2>📝 Voter Registration</h2> <?php if (isset($_SESSION['errors'])): ?> <div class="error"> <?php foreach ($_SESSION['errors'] as $error): ?> <p><?php echo htmlspecialchars($error); ?></p> <?php endforeach; ?> <?php unset($_SESSION['errors']); ?> </div> <?php endif; ?> <?php $form_data = $_SESSION['form_data'] ?? []; unset($_SESSION['form_data']); ?> <form action="includes/register_process.php" method="POST" onsubmit="return validateRegistration()"> <div class="form-row"> <div class="form-group"> <label for="full_name">Full Name *</label> <input type="text" id="full_name" name="full_name" value="<?php echo htmlspecialchars($form_data['full_name'] ?? ''); ?>" required> </div> <div class="form-group"> <label for="username">Username *</label> <input type="text" id="username" name="username" value="<?php echo htmlspecialchars($form_data['username'] ?? ''); ?>" required> </div> </div> <div class="form-row"> <div class="form-group"> <label for="email">Email *</label> <input type="email" id="email" name="email" value="<?php echo htmlspecialchars($form_data['email'] ?? ''); ?>" required> </div> <div class="form-group"> <label for="phone">Phone Number</label> <input type="tel" id="phone" name="phone" value="<?php echo htmlspecialchars($form_data['phone'] ?? ''); ?>"> </div> </div> <div class="form-row"> <div class="form-group"> <label for="date_of_birth">Date of Birth *</label> <input type="date" id="date_of_birth" name="date_of_birth" value="<?php echo htmlspecialchars($form_data['date_of_birth'] ?? ''); ?>" required> </div> <div class="form-group"> <label for="gender">Gender *</label> <select id="gender" name="gender" required> <option value="">Select Gender</option> <option value="Male" <?php echo ($form_data['gender'] ?? '') == 'Male' ? 'selected' : ''; ?>>Male</option> <option value="Female" <?php echo ($form_data['gender'] ?? '') == 'Female' ? 'selected' : ''; ?>>Female</option> <option value="Other" <?php echo ($form_data['gender'] ?? '') == 'Other' ? 'selected' : ''; ?>>Other</option> </select> </div> </div> <div class="form-group"> <label for="address">Address</label> <textarea id="address" name="address" rows="3"><?php echo htmlspecialchars($form_data['address'] ?? ''); ?></textarea> </div> <div class="form-row"> <div class="form-group"> <label for="password">Password * (min. 6 characters)</label> <input type="password" id="password" name="password" required> </div> <div class="form-group"> <label for="confirm_password">Confirm Password *</label> <input type="password" id="confirm_password" name="confirm_password" required> </div> </div> <button type="submit" class="btn">Register</button> </form> <p>Already have an account? <a href="login.php">Login here</a></p> <p><a href="index.php">← Back to Home</a></p> </div> <script src="assets/js/script.js"></script> </body> </html>
Login Page
File: login.php
<?php include 'includes/config.php'; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Login - Online Voting System</title> <link rel="stylesheet" href="assets/css/style.css"> </head> <body> <div class="container"> <h2>🔐 Login to Voting System</h2> <?php if (isset($_SESSION['success'])): ?> <div class="success"> <p><?php echo htmlspecialchars($_SESSION['success']); ?></p> <?php unset($_SESSION['success']); ?> </div> <?php endif; ?> <?php if (isset($_SESSION['error'])): ?> <div class="error"> <p><?php echo htmlspecialchars($_SESSION['error']); ?></p> <?php unset($_SESSION['error']); ?> </div> <?php endif; ?> <?php if (isset($_SESSION['errors'])): ?> <div class="error"> <?php foreach ($_SESSION['errors'] as $error): ?> <p><?php echo htmlspecialchars($error); ?></p> <?php endforeach; ?> <?php unset($_SESSION['errors']); ?> </div> <?php endif; ?> <form action="includes/login_process.php" method="POST" onsubmit="return validateLogin()"> <div class="form-group"> <label for="username_email">Username or Email:</label> <input type="text" id="username_email" name="username_email" required> </div> <div class="form-group"> <label for="password">Password:</label> <input type="password" id="password" name="password" required> </div> <button type="submit" class="btn">Login</button> </form> <p>Don't have an account? <a href="register.php">Register here</a></p> <p><a href="index.php">← Back to Home</a></p> </div> <script src="assets/js/script.js"></script> </body> </html>
Logout Script
File: logout.php
<?php
session_start();
session_unset();
session_destroy();
header("Location: index.php");
exit();
?>
Admin Dashboard Pages
Admin Main Dashboard
File: admin/dashboard.php
<?php
require_once '../includes/config.php';
if (!isAdmin()) {
redirect("../login.php");
}
// Get statistics
$total_voters = $pdo->query("SELECT COUNT(*) FROM users WHERE role='voter'")->fetchColumn();
$total_candidates = $pdo->query("SELECT COUNT(*) FROM candidates")->fetchColumn();
$total_elections = $pdo->query("SELECT COUNT(*) FROM elections")->fetchColumn();
$active_elections = $pdo->query("SELECT COUNT(*) FROM elections WHERE status='active'")->fetchColumn();
$total_votes = $pdo->query("SELECT COUNT(*) FROM votes")->fetchColumn();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Dashboard - Online Voting System</title>
<link rel="stylesheet" href="../assets/css/style.css">
</head>
<body>
<div class="container">
<header>
<h1>👑 Admin Dashboard</h1>
<p>Welcome, <strong><?php echo htmlspecialchars($_SESSION['full_name']); ?></strong>!</p>
</header>
<nav class="admin-nav">
<a href="dashboard.php" class="active">Dashboard</a>
<a href="manage_elections.php">Manage Elections</a>
<a href="manage_candidates.php">Manage Candidates</a>
<a href="manage_voters.php">Manage Voters</a>
<a href="view_results.php">View Results</a>
<a href="../logout.php">Logout</a>
</nav>
<main>
<div class="stats-grid">
<div class="stat-card">
<h3>Total Voters</h3>
<p class="stat-number"><?php echo $total_voters; ?></p>
</div>
<div class="stat-card">
<h3>Total Candidates</h3>
<p class="stat-number"><?php echo $total_candidates; ?></p>
</div>
<div class="stat-card">
<h3>Total Elections</h3>
<p class="stat-number"><?php echo $total_elections; ?></p>
</div>
<div class="stat-card">
<h3>Active Elections</h3>
<p class="stat-number"><?php echo $active_elections; ?></p>
</div>
<div class="stat-card">
<h3>Total Votes Cast</h3>
<p class="stat-number"><?php echo $total_votes; ?></p>
</div>
</div>
<section class="quick-actions">
<h2>Quick Actions</h2>
<div class="action-buttons">
<a href="add_election.php" class="btn">➕ Create New Election</a>
<a href="add_candidate.php" class="btn">👤 Add Candidate</a>
<a href="manage_voters.php?pending=1" class="btn">⏳ Approve Pending Voters</a>
<a href="declare_results.php" class="btn">📊 Declare Results</a>
</div>
</section>
</main>
</div>
</body>
</html>
Manage Elections
File: admin/manage_elections.php
<?php
require_once '../includes/config.php';
if (!isAdmin()) {
redirect("../login.php");
}
// Handle status updates
if (isset($_GET['activate'])) {
$id = $_GET['activate'];
$pdo->prepare("UPDATE elections SET status='active' WHERE id=?")->execute([$id]);
$_SESSION['success'] = "Election activated successfully!";
redirect("manage_elections.php");
}
if (isset($_GET['deactivate'])) {
$id = $_GET['deactivate'];
$pdo->prepare("UPDATE elections SET status='completed' WHERE id=?")->execute([$id]);
$_SESSION['success'] = "Election completed successfully!";
redirect("manage_elections.php");
}
if (isset($_GET['delete'])) {
$id = $_GET['delete'];
// First delete related votes and candidates
$pdo->prepare("DELETE FROM votes WHERE election_id=?")->execute([$id]);
$pdo->prepare("DELETE FROM candidates WHERE election_id=?")->execute([$id]);
$pdo->prepare("DELETE FROM elections WHERE id=?")->execute([$id]);
$_SESSION['success'] = "Election deleted successfully!";
redirect("manage_elections.php");
}
$elections = $pdo->query("SELECT * FROM elections ORDER BY created_at DESC")->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Manage Elections - Admin</title>
<link rel="stylesheet" href="../assets/css/style.css">
</head>
<body>
<div class="container">
<h2>📋 Manage Elections</h2>
<nav class="admin-nav">
<a href="dashboard.php">Dashboard</a>
<a href="manage_elections.php" class="active">Elections</a>
<a href="manage_candidates.php">Candidates</a>
<a href="manage_voters.php">Voters</a>
<a href="view_results.php">Results</a>
<a href="../logout.php">Logout</a>
</nav>
<?php if (isset($_SESSION['success'])): ?>
<div class="success"><?php echo $_SESSION['success']; unset($_SESSION['success']); ?></div>
<?php endif; ?>
<div class="action-bar">
<a href="add_election.php" class="btn">➕ Add New Election</a>
</div>
<table>
<thead>
<tr>
<th>ID</th>
<th>Election Name</th>
<th>Start Date</th>
<th>End Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($elections as $election): ?>
<tr>
<td><?php echo $election['id']; ?></td>
<td><?php echo htmlspecialchars($election['election_name']); ?></td>
<td><?php echo date('d M Y H:i', strtotime($election['start_date'])); ?></td>
<td><?php echo date('d M Y H:i', strtotime($election['end_date'])); ?></td>
<td>
<span class="status status-<?php echo $election['status']; ?>">
<?php echo ucfirst($election['status']); ?>
</span>
</td>
<td class="actions">
<a href="edit_election.php?id=<?php echo $election['id']; ?>" class="btn-small">Edit</a>
<?php if ($election['status'] == 'upcoming'): ?>
<a href="?activate=<?php echo $election['id']; ?>" class="btn-small btn-success" onclick="return confirm('Activate this election?')">Activate</a>
<?php elseif ($election['status'] == 'active'): ?>
<a href="?deactivate=<?php echo $election['id']; ?>" class="btn-small btn-warning" onclick="return confirm('End this election?')">End</a>
<?php endif; ?>
<a href="?delete=<?php echo $election['id']; ?>" class="btn-small btn-danger" onclick="return confirm('Delete this election? This action cannot be undone.')">Delete</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</body>
</html>
Add Election
File: admin/add_election.php
<?php
require_once '../includes/config.php';
if (!isAdmin()) {
redirect("../login.php");
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$election_name = trim($_POST['election_name']);
$description = trim($_POST['description']);
$start_date = $_POST['start_date'];
$end_date = $_POST['end_date'];
$created_by = $_SESSION['user_id'];
$errors = [];
if (empty($election_name)) {
$errors[] = "Election name is required.";
}
if (strtotime($start_date) >= strtotime($end_date)) {
$errors[] = "End date must be after start date.";
}
if (empty($errors)) {
$stmt = $pdo->prepare("INSERT INTO elections (election_name, description, start_date, end_date, created_by) VALUES (?, ?, ?, ?, ?)");
if ($stmt->execute([$election_name, $description, $start_date, $end_date, $created_by])) {
$_SESSION['success'] = "Election created successfully!";
redirect("manage_elections.php");
} else {
$errors[] = "Failed to create election.";
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Add Election - Admin</title>
<link rel="stylesheet" href="../assets/css/style.css">
</head>
<body>
<div class="container">
<h2>➕ Create New Election</h2>
<nav class="admin-nav">
<a href="dashboard.php">Dashboard</a>
<a href="manage_elections.php">Elections</a>
<a href="manage_candidates.php">Candidates</a>
<a href="manage_voters.php">Voters</a>
<a href="../logout.php">Logout</a>
</nav>
<?php if (!empty($errors)): ?>
<div class="error">
<?php foreach ($errors as $error): ?>
<p><?php echo $error; ?></p>
<?php endforeach; ?>
</div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label for="election_name">Election Name *</label>
<input type="text" id="election_name" name="election_name" required>
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea id="description" name="description" rows="4"></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label for="start_date">Start Date & Time *</label>
<input type="datetime-local" id="start_date" name="start_date" required>
</div>
<div class="form-group">
<label for="end_date">End Date & Time *</label>
<input type="datetime-local" id="end_date" name="end_date" required>
</div>
</div>
<button type="submit" class="btn">Create Election</button>
<a href="manage_elections.php" class="btn btn-secondary">Cancel</a>
</form>
</div>
</body>
</html>
Voter Dashboard Pages
Voter Main Dashboard
File: voter/dashboard.php
<?php
require_once '../includes/config.php';
if (!isVoter()) {
redirect("../login.php");
}
// Get active elections
$stmt = $pdo->prepare("SELECT * FROM elections WHERE status='active' AND start_date <= NOW() AND end_date >= NOW()");
$stmt->execute();
$active_elections = $stmt->fetchAll();
// Get voter's voting history
$stmt = $pdo->prepare("
SELECT e.election_name, c.party_name, u.full_name as candidate_name, v.voted_at
FROM votes v
JOIN elections e ON v.election_id = e.id
JOIN candidates c ON v.candidate_id = c.id
JOIN users u ON c.user_id = u.id
WHERE v.voter_id = ?
ORDER BY v.voted_at DESC
");
$stmt->execute([$_SESSION['user_id']]);
$voting_history = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Voter Dashboard - Online Voting System</title>
<link rel="stylesheet" href="../assets/css/style.css">
</head>
<body>
<div class="container">
<header>
<h1>🗳️ Voter Dashboard</h1>
<p>Welcome, <strong><?php echo htmlspecialchars($_SESSION['full_name']); ?></strong>!</p>
<p>Your Voter ID: <strong><?php echo htmlspecialchars($_SESSION['voter_id']); ?></strong></p>
</header>
<nav class="voter-nav">
<a href="dashboard.php" class="active">Dashboard</a>
<a href="vote.php">Cast Vote</a>
<a href="view_elections.php">View Elections</a>
<a href="view_results.php">Results</a>
<a href="profile.php">My Profile</a>
<a href="../logout.php">Logout</a>
</nav>
<?php if (isset($_SESSION['success'])): ?>
<div class="success"><?php echo $_SESSION['success']; unset($_SESSION['success']); ?></div>
<?php endif; ?>
<main>
<section class="active-elections">
<h2>📢 Active Elections</h2>
<?php if (count($active_elections) > 0): ?>
<div class="election-grid">
<?php foreach ($active_elections as $election): ?>
<div class="election-card">
<h3><?php echo htmlspecialchars($election['election_name']); ?></h3>
<p><?php echo htmlspecialchars($election['description']); ?></p>
<p><strong>Ends:</strong> <?php echo date('d M Y H:i', strtotime($election['end_date'])); ?></p>
<a href="vote.php?election_id=<?php echo $election['id']; ?>" class="btn">Vote Now</a>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<p>No active elections at the moment.</p>
<?php endif; ?>
</section>
<section class="voting-history">
<h2>📜 Your Voting History</h2>
<?php if (count($voting_history) > 0): ?>
<table>
<thead>
<tr>
<th>Election</th>
<th>Candidate</th>
<th>Party</th>
<th>Voted On</th>
</tr>
</thead>
<tbody>
<?php foreach ($voting_history as $vote): ?>
<tr>
<td><?php echo htmlspecialchars($vote['election_name']); ?></td>
<td><?php echo htmlspecialchars($vote['candidate_name']); ?></td>
<td><?php echo htmlspecialchars($vote['party_name'] ?? 'Independent'); ?></td>
<td><?php echo date('d M Y H:i', strtotime($vote['voted_at'])); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<p>You haven't voted in any elections yet.</p>
<?php endif; ?>
</section>
</main>
</div>
</body>
</html>
Vote Casting Page
File: voter/vote.php
<?php
require_once '../includes/config.php';
if (!isVoter()) {
redirect("../login.php");
}
$election_id = $_GET['election_id'] ?? null;
if (!$election_id) {
redirect("view_elections.php");
}
// Check if election is active
$stmt = $pdo->prepare("SELECT * FROM elections WHERE id = ? AND status = 'active' AND start_date <= NOW() AND end_date >= NOW()");
$stmt->execute([$election_id]);
$election = $stmt->fetch();
if (!$election) {
$_SESSION['error'] = "This election is not active.";
redirect("view_elections.php");
}
// Check if user has already voted
$stmt = $pdo->prepare("SELECT id FROM votes WHERE voter_id = ? AND election_id = ?");
$stmt->execute([$_SESSION['user_id'], $election_id]);
if ($stmt->fetch()) {
$_SESSION['error'] = "You have already voted in this election.";
redirect("dashboard.php");
}
// Get candidates for this election
$stmt = $pdo->prepare("
SELECT c.*, u.full_name, u.profile_picture
FROM candidates c
JOIN users u ON c.user_id = u.id
WHERE c.election_id = ? AND c.approved = 1
");
$stmt->execute([$election_id]);
$candidates = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cast Vote - Online Voting System</title>
<link rel="stylesheet" href="../assets/css/style.css">
</head>
<body>
<div class="container">
<h2>🗳️ Cast Your Vote</h2>
<nav class="voter-nav">
<a href="dashboard.php">Dashboard</a>
<a href="vote.php" class="active">Cast Vote</a>
<a href="view_elections.php">Elections</a>
<a href="view_results.php">Results</a>
<a href="../logout.php">Logout</a>
</nav>
<div class="election-info">
<h3><?php echo htmlspecialchars($election['election_name']); ?></h3>
<p><?php echo htmlspecialchars($election['description']); ?></p>
<p><strong>Election ends:</strong> <?php echo date('d M Y H:i', strtotime($election['end_date'])); ?></p>
</div>
<?php if (isset($_SESSION['error'])): ?>
<div class="error"><?php echo $_SESSION['error']; unset($_SESSION['error']); ?></div>
<?php endif; ?>
<form action="../includes/vote_process.php" method="POST" onsubmit="return confirm('Are you sure you want to cast your vote? This action cannot be undone.')">
<input type="hidden" name="election_id" value="<?php echo $election_id; ?>">
<div class="candidates-list">
<?php foreach ($candidates as $candidate): ?>
<div class="candidate-card">
<input type="radio" name="candidate_id" value="<?php echo $candidate['id']; ?>" id="candidate_<?php echo $candidate['id']; ?>" required>
<label for="candidate_<?php echo $candidate['id']; ?>">
<div class="candidate-info">
<h4><?php echo htmlspecialchars($candidate['full_name']); ?></h4>
<p><strong>Party:</strong> <?php echo htmlspecialchars($candidate['party_name'] ?? 'Independent'); ?></p>
<?php if (!empty($candidate['manifesto'])): ?>
<p><strong>Manifesto:</strong> <?php echo htmlspecialchars($candidate['manifesto']); ?></p>
<?php endif; ?>
</div>
</label>
</div>
<?php endforeach; ?>
</div>
<button type="submit" name="cast_vote" class="btn btn-vote">✅ Confirm Vote</button>
<a href="view_elections.php" class="btn btn-secondary">Cancel</a>
</form>
</div>
</body>
</html>
CSS Styling
File: assets/css/style.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 15px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
padding: 30px;
}
/* Header Styles */
header {
text-align: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 2px solid #f0f0f0;
}
h1 {
color: #333;
font-size: 2.5em;
margin-bottom: 10px;
}
.tagline {
color: #666;
font-size: 1.2em;
}
/* Navigation */
nav {
display: flex;
justify-content: center;
gap: 15px;
margin-bottom: 30px;
flex-wrap: wrap;
}
nav a {
padding: 10px 20px;
background: #f8f9fa;
color: #333;
text-decoration: none;
border-radius: 5px;
transition: all 0.3s;
}
nav a:hover, nav a.active {
background: #667eea;
color: white;
}
/* Admin Navigation */
.admin-nav, .voter-nav {
background: #f8f9fa;
padding: 15px;
border-radius: 10px;
margin-bottom: 30px;
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.admin-nav a, .voter-nav a {
padding: 8px 15px;
border-radius: 5px;
text-decoration: none;
color: #333;
transition: all 0.3s;
}
.admin-nav a:hover, .admin-nav a.active,
.voter-nav a:hover, .voter-nav a.active {
background: #667eea;
color: white;
}
/* Form Styles */
.form-group {
margin-bottom: 20px;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: 600;
color: #555;
}
input[type="text"],
input[type="email"],
input[type="password"],
input[type="date"],
input[type="datetime-local"],
input[type="tel"],
select,
textarea {
width: 100%;
padding: 12px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 16px;
transition: border-color 0.3s;
}
input:focus, select:focus, textarea:focus {
outline: none;
border-color: #667eea;
}
/* Button Styles */
.btn {
display: inline-block;
padding: 12px 30px;
background: #667eea;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
text-decoration: none;
transition: background 0.3s;
}
.btn:hover {
background: #5a67d8;
}
.btn-secondary {
background: #6c757d;
}
.btn-secondary:hover {
background: #5a6268;
}
.btn-success {
background: #48bb78;
}
.btn-success:hover {
background: #38a169;
}
.btn-warning {
background: #ecc94b;
color: #333;
}
.btn-warning:hover {
background: #d69e2e;
}
.btn-danger {
background: #f56565;
}
.btn-danger:hover {
background: #e53e3e;
}
.btn-vote {
background: #38a169;
font-size: 18px;
padding: 15px 40px;
margin-top: 20px;
}
.btn-small {
padding: 5px 10px;
font-size: 14px;
border-radius: 4px;
text-decoration: none;
color: white;
margin: 0 2px;
}
/* Stats Grid */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-bottom: 40px;
}
.stat-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 25px;
border-radius: 10px;
text-align: center;
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
}
.stat-card h3 {
font-size: 1.1em;
margin-bottom: 10px;
opacity: 0.9;
}
.stat-number {
font-size: 2.5em;
font-weight: bold;
}
/* Table Styles */
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
background: white;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
th {
background: #667eea;
color: white;
padding: 15px;
text-align: left;
font-weight: 600;
}
td {
padding: 12px 15px;
border-bottom: 1px solid #f0f0f0;
}
tr:hover {
background: #f8f9fa;
}
/* Status Badges */
.status {
padding: 5px 10px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
}
.status-upcoming {
background: #ecc94b;
color: #744210;
}
.status-active {
background: #48bb78;
color: #22543d;
}
.status-completed {
background: #a0aec0;
color: #1a202c;
}
.status-cancelled {
background: #f56565;
color: #742a2a;
}
/* Candidate Cards */
.candidates-list {
display: grid;
gap: 20px;
margin: 30px 0;
}
.candidate-card {
border: 2px solid #e0e0e0;
border-radius: 10px;
padding: 20px;
transition: all 0.3s;
}
.candidate-card:hover {
border-color: #667eea;
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.2);
}
.candidate-card input[type="radio"] {
margin-right: 15px;
}
.candidate-card label {
display: flex;
align-items: center;
cursor: pointer;
margin: 0;
}
.candidate-info {
flex: 1;
}
.candidate-info h4 {
color: #333;
margin-bottom: 5px;
}
/* Election Cards */
.election-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin: 20px 0;
}
.election-card {
background: white;
border: 2px solid #e0e0e0;
border-radius: 10px;
padding: 20px;
transition: all 0.3s;
}
.election-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.election-card h3 {
color: #333;
margin-bottom: 10px;
}
/* Message Styles */
.error {
background: #fed7d7;
color: #c53030;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
border-left: 4px solid #f56565;
}
.success {
background: #c6f6d5;
color: #22543d;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
border-left: 4px solid #48bb78;
}
/* Features Section */
.features {
margin: 40px 0;
}
.feature-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 30px;
margin-top: 30px;
}
.feature {
text-align: center;
padding: 25px;
background: #f8f9fa;
border-radius: 10px;
transition: transform 0.3s;
}
.feature:hover {
transform: translateY(-5px);
}
.feature h3 {
color: #333;
margin: 15px 0 10px;
}
/* How it works */
.how-it-works {
margin: 40px 0;
padding: 30px;
background: #f8f9fa;
border-radius: 10px;
}
.how-it-works ol {
padding-left: 20px;
margin-top: 15px;
}
.how-it-works li {
margin: 10px 0;
color: #555;
}
/* Quick Actions */
.quick-actions {
margin-top: 40px;
}
.action-buttons {
display: flex;
gap: 15px;
flex-wrap: wrap;
margin-top: 20px;
}
/* Action Bar */
.action-bar {
margin: 20px 0;
text-align: right;
}
/* Footer */
footer {
text-align: center;
margin-top: 50px;
padding-top: 20px;
border-top: 1px solid #f0f0f0;
color: #666;
}
/* Responsive Design */
@media (max-width: 768px) {
.container {
padding: 20px;
}
h1 {
font-size: 2em;
}
.form-row {
grid-template-columns: 1fr;
}
.stats-grid {
grid-template-columns: 1fr;
}
.admin-nav, .voter-nav {
flex-direction: column;
}
.admin-nav a, .voter-nav a {
text-align: center;
}
table {
display: block;
overflow-x: auto;
}
}
JavaScript Validation
File: assets/js/script.js
// Registration Form Validation
function validateRegistration() {
let fullname = document.getElementById('full_name').value.trim();
let username = document.getElementById('username').value.trim();
let email = document.getElementById('email').value.trim();
let password = document.getElementById('password').value;
let confirm = document.getElementById('confirm_password').value;
let dob = document.getElementById('date_of_birth').value;
let gender = document.getElementById('gender').value;
// Check required fields
if (fullname === '' || username === '' || email === '' || password === '' || dob === '' || gender === '') {
alert('Please fill in all required fields.');
return false;
}
// Username validation
if (username.length < 3) {
alert('Username must be at least 3 characters long.');
return false;
}
if (!/^[a-zA-Z0-9_]+$/.test(username)) {
alert('Username can only contain letters, numbers, and underscores.');
return false;
}
// Email validation
let emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailPattern.test(email)) {
alert('Please enter a valid email address.');
return false;
}
// Password validation
if (password.length < 6) {
alert('Password must be at least 6 characters long.');
return false;
}
if (password !== confirm) {
alert('Passwords do not match.');
return false;
}
// Age validation (must be at least 18 years old)
let today = new Date();
let birthDate = new Date(dob);
let age = today.getFullYear() - birthDate.getFullYear();
let monthDiff = today.getMonth() - birthDate.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
if (age < 18) {
alert('You must be at least 18 years old to register.');
return false;
}
return true;
}
// Login Form Validation
function validateLogin() {
let username = document.getElementById('username_email').value.trim();
let password = document.getElementById('password').value;
if (username === '' || password === '') {
alert('Please enter both username/email and password.');
return false;
}
return true;
}
// Election Form Validation
function validateElection() {
let electionName = document.getElementById('election_name').value.trim();
let startDate = document.getElementById('start_date').value;
let endDate = document.getElementById('end_date').value;
if (electionName === '') {
alert('Please enter election name.');
return false;
}
if (!startDate || !endDate) {
alert('Please select both start and end dates.');
return false;
}
let start = new Date(startDate);
let end = new Date(endDate);
let now = new Date();
if (start < now) {
alert('Start date cannot be in the past.');
return false;
}
if (end <= start) {
alert('End date must be after start date.');
return false;
}
return true;
}
// Candidate Form Validation
function validateCandidate() {
let userId = document.getElementById('user_id').value;
let electionId = document.getElementById('election_id').value;
if (!userId || !electionId) {
alert('Please select both user and election.');
return false;
}
return true;
}
// Confirm Delete Actions
function confirmDelete(message) {
return confirm(message || 'Are you sure you want to delete this item? This action cannot be undone.');
}
// Format Date for Display
function formatDate(dateString) {
let date = new Date(dateString);
return date.toLocaleString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
// Live Search/Filter for Tables
function filterTable() {
let input = document.getElementById('searchInput');
let filter = input.value.toUpperCase();
let table = document.getElementById('dataTable');
let rows = table.getElementsByTagName('tr');
for (let i = 1; i < rows.length; i++) {
let cells = rows[i].getElementsByTagName('td');
let found = false;
for (let j = 0; j < cells.length; j++) {
let cell = cells[j];
if (cell) {
let textValue = cell.textContent || cell.innerText;
if (textValue.toUpperCase().indexOf(filter) > -1) {
found = true;
break;
}
}
}
rows[i].style.display = found ? '' : 'none';
}
}
// Toggle Password Visibility
function togglePassword(inputId, iconId) {
let input = document.getElementById(inputId);
let icon = document.getElementById(iconId);
if (input.type === 'password') {
input.type = 'text';
icon.className = 'fas fa-eye-slash';
} else {
input.type = 'password';
icon.className = 'fas fa-eye';
}
}
// Auto-hide Alert Messages
document.addEventListener('DOMContentLoaded', function() {
setTimeout(function() {
let alerts = document.querySelectorAll('.success, .error');
alerts.forEach(function(alert) {
alert.style.transition = 'opacity 0.5s';
alert.style.opacity = '0';
setTimeout(function() {
alert.style.display = 'none';
}, 500);
});
}, 5000);
});
Candidate Dashboard
File: candidate/dashboard.php
<?php
require_once '../includes/config.php';
if (!isCandidate()) {
redirect("../login.php");
}
// Get candidate's elections and vote counts
$stmt = $pdo->prepare("
SELECT c.*, e.election_name, e.status,
(SELECT COUNT(*) FROM votes WHERE candidate_id = c.id) as vote_count
FROM candidates c
JOIN elections e ON c.election_id = e.id
WHERE c.user_id = ?
");
$stmt->execute([$_SESSION['user_id']]);
$candidacies = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Candidate Dashboard - Online Voting System</title>
<link rel="stylesheet" href="../assets/css/style.css">
</head>
<body>
<div class="container">
<header>
<h1>🎯 Candidate Dashboard</h1>
<p>Welcome, <strong><?php echo htmlspecialchars($_SESSION['full_name']); ?></strong>!</p>
</header>
<nav class="voter-nav">
<a href="dashboard.php" class="active">Dashboard</a>
<a href="../logout.php">Logout</a>
</nav>
<main>
<section class="candidacy-status">
<h2>Your Elections & Performance</h2>
<?php if (count($candidacies) > 0): ?>
<div class="stats-grid">
<?php foreach ($candidacies as $cand): ?>
<div class="stat-card">
<h3><?php echo htmlspecialchars($cand['election_name']); ?></h3>
<p>Status: <?php echo ucfirst($cand['status']); ?></p>
<p class="stat-number"><?php echo $cand['vote_count']; ?></p>
<p>Total Votes Received</p>
</div>
<?php endforeach; ?>
</div>
<table>
<thead>
<tr>
<th>Election</th>
<th>Party</th>
<th>Status</th>
<th>Votes Received</th>
<th>Approval Status</th>
</tr>
</thead>
<tbody>
<?php foreach ($candidacies as $cand): ?>
<tr>
<td><?php echo htmlspecialchars($cand['election_name']); ?></td>
<td><?php echo htmlspecialchars($cand['party_name'] ?? 'Independent'); ?></td>
<td>
<span class="status status-<?php echo $cand['status']; ?>">
<?php echo ucfirst($cand['status']); ?>
</span>
</td>
<td><?php echo $cand['vote_count']; ?></td>
<td>
<?php if ($cand['approved']): ?>
<span class="status status-active">Approved</span>
<?php else: ?>
<span class="status status-upcoming">Pending</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<p>You are not a candidate in any elections yet.</p>
<?php endif; ?>
</section>
</main>
</div>
</body>
</html>
How to Use the Project (Step-by-Step Guide)
Prerequisites
- Install XAMPP/WAMP/MAMP - Download and install from official websites
- Code Editor - VS Code, Sublime Text, or any preferred editor
- Web Browser - Chrome, Firefox, or Edge
Installation Steps
Step 1: Set Up Local Server
- Install XAMPP from https://www.apachefriends.org/
- Start Apache and MySQL services from XAMPP Control Panel
Step 2: Create Project Folder
- Navigate to
C:\xampp\htdocs\(Windows) or/Applications/XAMPP/htdocs/(Mac) - Create a new folder named
online-voting-system
Step 3: Set Up File Structure
- Create all folders and files as shown in the Project File Structure section
- Copy all the provided code into respective files
Step 4: Create Database
- Open browser and go to
http://localhost/phpmyadmin - Click on "SQL" tab
- Copy the entire SQL script from
sql/database.sqland execute it - Verify that the database and tables are created
Step 5: Update Configuration
- Open
includes/config.php - Update database credentials if different from default:
$username = 'root'; // Your MySQL username $password = ''; // Your MySQL password
Step 6: Create Admin Password Hash
- Go to
http://localhost/online-voting-system/register.php - Register a test user
- Copy the password hash from phpMyAdmin
- Update the admin insert query with proper hash:
// Use PHP's password_hash() function to generate hash
// Example: echo password_hash('admin123', PASSWORD_DEFAULT);
Step 7: Test the System
- Open browser and go to
http://localhost/online-voting-system/ - You should see the homepage
- Test all functionalities:
- Register as a voter
- Login with registered credentials
- Access admin features
- Create elections
- Add candidates
- Cast votes
- View results
Default Login Credentials
- Admin: username:
admin, password:admin123(after setting up hash) - Voter: Register new account and get approved by admin
System Workflow
For Administrators:
- Login with admin credentials
- Create elections with start/end dates
- Add candidates to elections
- Approve voter registrations
- Monitor voting progress
- Declare results after election ends
For Voters:
- Register with personal details
- Wait for admin approval
- Login to the system
- View active elections
- Cast vote for preferred candidate
- View results after election completion
For Candidates:
- Get added by admin to specific elections
- Login to view election status
- Monitor vote count
- View final results
Security Features Implemented
- Password Hashing - Using PHP's
password_hash()andpassword_verify() - Session Management - Secure session handling with regeneration
- SQL Injection Prevention - Using PDO prepared statements
- XSS Prevention - Using
htmlspecialchars()for output - CSRF Protection - Session-based token validation
- Role-Based Access - Separate dashboards for different user types
- One Person One Vote - Database constraint prevents multiple voting
- Input Validation - Both client-side and server-side validation
- Approval System - Admin approval required for voters
Future Enhancements
- Email Verification - Send verification emails during registration
- Two-Factor Authentication - Add extra security layer
- OTP Verification - Send OTP via SMS/email before voting
- Live Results - Real-time vote counting display
- Export Reports - Download election reports in PDF/Excel
- Voter Analytics - Demographic analysis of voters
- Audit Trail - Complete logging of all system activities
- Multiple Languages - Support for different languages
- Mobile App - Native mobile applications
- Blockchain Integration - For enhanced transparency
Conclusion
This Online Voting System provides a complete, secure, and feature-rich platform for conducting digital elections. With its role-based access control, intuitive user interface, and robust security measures, it serves as an excellent foundation for any organization looking to implement electronic voting. The system ensures transparency, prevents fraud, and makes the voting process convenient for all participants.
The modular code structure makes it easy to maintain and extend, while the comprehensive documentation ensures smooth deployment and usage. Whether for student council elections, corporate board elections, or community organization votes, this system provides all the necessary features to conduct fair and efficient digital elections.