Online_Election_System - B1

This commit is contained in:
Flatlogic Bot 2026-02-04 21:58:30 +00:00
parent b3fd5e275d
commit 79ea87f550
15 changed files with 926 additions and 167 deletions

View File

@ -11,6 +11,7 @@
--Error_Color: #EF4444;
--Overlay_Color: rgba(0, 0, 0, 0.65);
--Sidebar_Width: 260px;
--Topbar_Height: 70px;
}
* {
@ -317,8 +318,11 @@ body, html {
}
.Sidebar_Header {
padding: 24px;
height: var(--Topbar_Height);
padding: 0 24px;
border-bottom: 1px solid var(--Border_Color);
display: flex;
align-items: center;
}
.Sidebar_Nav {
@ -358,7 +362,7 @@ body, html {
}
.Top_Bar {
height: 70px;
height: var(--Topbar_Height);
background: white;
border-bottom: 1px solid var(--Border_Color);
display: flex;
@ -730,3 +734,14 @@ td {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(79, 70, 229, 0.2);
}
/* Navbar for Voting Screen */
.Dashboard_Navbar {
height: var(--Topbar_Height);
background: white;
border-bottom: 1px solid var(--Border_Color);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 32px;
}

View File

@ -12,16 +12,25 @@ class Authentication_Handler {
public function Login($User_Type, $Email, $Password, $User_ID) {
$Table = ($User_Type === 'Voter') ? 'Voters' : 'Officers';
$sql = "SELECT * FROM $Table WHERE Email = ? AND User_ID = ?";
// Try to find user by UID first as it's the primary key
$sql = "SELECT * FROM $Table WHERE User_ID = ?";
$stmt = $this->pdo->prepare($sql);
$stmt->execute([$Email, $User_ID]);
$stmt->execute([$User_ID]);
$User = $stmt->fetch();
// If not found and email is provided, try by Email
if (!$User && !empty($Email)) {
$sql = "SELECT * FROM $Table WHERE Email = ?";
$stmt = $this->pdo->prepare($sql);
$stmt->execute([$Email]);
$User = $stmt->fetch();
}
if ($User && password_verify($Password, $User['Password'])) {
$_SESSION['User_ID'] = $User['User_ID'];
$_SESSION['User_Role'] = ($User_Type === 'Voter') ? 'Voter' : $User['Role'];
$_SESSION['Access_Level'] = ($User_Type === 'Voter') ? 0 : $User['Access_Level'];
$_SESSION['User_Name'] = $User['Name'] ?? 'Voter';
$_SESSION['Access_Level'] = ($User_Type === 'Voter') ? 0 : ($User['Access_Level'] ?? 0);
$_SESSION['User_Name'] = $User['Name'] ?? ($User_Type === 'Voter' ? 'Voter' : 'User');
// Log to Audit_Trail if Access_Level >= 1
if ($_SESSION['Access_Level'] >= 1) {
@ -31,7 +40,7 @@ class Authentication_Handler {
return ['success' => true];
}
return ['success' => false, 'error' => 'Invalid credentials'];
return ['success' => false, 'error' => 'Invalid credentials. Please check your UID/Email and Password.'];
}
public function Log_Action($User_ID, $User_Role, $Action_Type, $Action_Details) {
@ -48,8 +57,34 @@ class Authentication_Handler {
}
public function Logout() {
if (isset($_SESSION['User_ID']) && isset($_SESSION['Access_Level']) && $_SESSION['Access_Level'] >= 1) {
$this->Log_Action($_SESSION['User_ID'], $_SESSION['User_Role'], 'Logout', 'User logged out of the system');
}
session_destroy();
header('Location: ../../Screens/Login.php');
exit;
}
}
// Handle POST request for Login
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['User_ID']) && isset($_POST['Password'])) {
$handler = new Authentication_Handler();
$userType = $_POST['User_Type'] ?? 'Voter';
$email = $_POST['Email'] ?? '';
$uid = $_POST['User_ID'];
$password = $_POST['Password'];
$result = $handler->Login($userType, $email, $password, $uid);
if ($result['success']) {
if ($_SESSION['Access_Level'] >= 1) {
header('Location: ../../Screens/Election_Dashboard.php');
} else {
header('Location: ../../Screens/Voting_Screen.php');
}
exit;
} else {
header('Location: ../../Screens/Login.php?error=' . urlencode($result['error']));
exit;
}
}

View File

@ -0,0 +1,68 @@
<?php
require_once __DIR__ . '/Authentication_Handler.php';
require_once __DIR__ . '/../../db/config.php';
$Auth = new Authentication_Handler();
$Auth->Check_Auth();
if ($_SESSION['Access_Level'] < 1) {
header('Location: ../../Screens/Login.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
$file = $_FILES['csv_file']['tmp_name'];
if (!is_uploaded_file($file)) {
header("Location: ../../Screens/Voters.php?error=No file uploaded");
exit;
}
$handle = fopen($file, "r");
if ($handle === false) {
header("Location: ../../Screens/Voters.php?error=Could not open file");
exit;
}
$db = db();
$db->beginTransaction();
try {
// Skip header
$header = fgetcsv($handle);
$importedCount = 0;
while (($data = fgetcsv($handle)) !== false) {
// Mapping: User_ID, Email, Track_Cluster, Grade_Level, Section, Password
$userId = $data[0] ?: 'V-' . bin2hex(random_bytes(4));
$email = $data[1];
$track = $data[2];
$grade = intval($data[3]);
$section = $data[4];
$password = !empty($data[5]) ? password_hash($data[5], PASSWORD_DEFAULT) : password_hash('Voter123', PASSWORD_DEFAULT);
if (empty($email)) continue;
$stmt = $db->prepare("INSERT INTO Voters (User_ID, Email, Password, Track_Cluster, Grade_Level, Section) VALUES (?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE Email = VALUES(Email), Track_Cluster = VALUES(Track_Cluster), Grade_Level = VALUES(Grade_Level), Section = VALUES(Section)");
$stmt->execute([$userId, $email, $password, $track, $grade, $section]);
$importedCount++;
}
$db->commit();
fclose($handle);
$Auth->Log_Action($_SESSION['User_ID'], $_SESSION['User_Role'], 'Import Voters', "Imported $importedCount voters via CSV");
header("Location: ../../Screens/Voters.php?success=Successfully imported $importedCount voters");
exit;
} catch (Exception $e) {
$db->rollBack();
fclose($handle);
header("Location: ../../Screens/Voters.php?error=Error importing CSV: " . $e->getMessage());
exit;
}
} else {
header("Location: ../../Screens/Voters.php");
exit;
}

135
Screens/Audit_Trail.php Normal file
View File

@ -0,0 +1,135 @@
<?php
require_once __DIR__ . '/../Logic/Backend/Authentication_Handler.php';
require_once __DIR__ . '/../db/config.php';
$Auth = new Authentication_Handler();
$Auth->Check_Auth();
if ($_SESSION['Access_Level'] < 1) {
header('Location: Voting_Screen.php');
exit;
}
$db = db();
// Fetch Logs
$query = "SELECT * FROM Audit_Trail ORDER BY Timestamp DESC LIMIT 100";
$logs = $db->query($query)->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Audit Trail | Online School Election System</title>
<link rel="stylesheet" href="../Design/Style.css?v=<?php echo time(); ?>">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body>
<div class="Dashboard_Container">
<!-- Sidebar -->
<aside class="Sidebar">
<div class="Sidebar_Header">
<div class="Logo_Text">
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">Click to Vote</div>
<div class="Logo_Subtitle">Administrator Portal</div>
</div>
</div>
<nav class="Sidebar_Nav">
<a href="Election_Dashboard.php" class="Nav_Item">
<i class="fas fa-th-large"></i> Election Dashboard
</a>
<a href="Election_History.php" class="Nav_Item">
<i class="fas fa-vote-yea"></i> Election History
</a>
<a href="Voters.php" class="Nav_Item">
<i class="fas fa-users"></i> Voter Management
</a>
<a href="Candidates.php" class="Nav_Item">
<i class="fas fa-user-tie"></i> Candidate Management
</a>
<a href="Officers.php" class="Nav_Item">
<i class="fas fa-user-shield"></i> Officers Management
</a>
<a href="Audit_Trail.php" class="Nav_Item Active">
<i class="fas fa-file-alt"></i> Reports & Audit
</a>
<a href="Credits.php" class="Nav_Item">
<i class="fas fa-info-circle"></i> Credits
</a>
</nav>
<div style="padding: 24px; border-top: 1px solid var(--Border_Color);">
<a href="Logout.php" class="Nav_Item" style="padding: 0; color: var(--Error_Color);">
<i class="fas fa-sign-out-alt"></i> Logout
</a>
</div>
</aside>
<!-- Main Content -->
<main class="Main_Content">
<!-- Top Bar -->
<header class="Top_Bar">
<div class="Search_Box">
<i class="fas fa-search" style="color: var(--Secondary_Color);"></i>
<input type="text" placeholder="Search logs...">
</div>
<div class="Top_Bar_Actions">
<div style="display: flex; align-items: center; gap: 12px;">
<div style="text-align: right;">
<div style="font-weight: 700; font-size: 0.9rem;"><?php echo htmlspecialchars($_SESSION['User_Name']); ?></div>
<div style="font-size: 0.75rem; color: var(--Text_Secondary);"><?php echo htmlspecialchars($_SESSION['User_Role']); ?></div>
</div>
<div style="width: 40px; height: 40px; background: var(--Primary_Light); color: var(--Primary_Color); border-radius: 50%; display: flex; justify-content: center; align-items: center; font-weight: 700;">
<?php echo strtoupper(substr($_SESSION['User_Name'] ?? 'A', 0, 1)); ?>
</div>
</div>
</div>
</header>
<!-- Content Body -->
<div class="Content_Body">
<div class="Page_Title_Section">
<h1 class="Page_Title">Audit Trail</h1>
<p class="Page_Subtitle">System activity and security logs</p>
</div>
<div class="Card" style="padding: 0; overflow: hidden;">
<div class="Table_Wrapper">
<table>
<thead>
<tr>
<th>Timestamp</th>
<th>User ID</th>
<th>Role</th>
<th>Action</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<?php if (empty($logs)): ?>
<tr>
<td colspan="5" style="text-align: center; padding: 40px; color: var(--Text_Secondary);">
No activity logs found.
</td>
</tr>
<?php else: ?>
<?php foreach ($logs as $log): ?>
<tr>
<td><?php echo date('Y-m-d H:i:s', strtotime($log['Timestamp'])); ?></td>
<td style="font-weight: 600;"><?php echo htmlspecialchars($log['User_ID']); ?></td>
<td><span class="Badge" style="background: var(--Primary_Light); color: var(--Primary_Color);"><?php echo htmlspecialchars($log['User_Role']); ?></span></td>
<td><strong><?php echo htmlspecialchars($log['Action_Type']); ?></strong></td>
<td><?php echo htmlspecialchars($log['Action_Details']); ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</main>
</div>
</body>
</html>

View File

@ -42,6 +42,9 @@ if ($migrationNeeded && $electionId) {
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $electionStatus === 'Preparing') {
if (isset($_POST['action'])) {
$changed = false;
$logAction = "";
$logDetails = "";
if ($_POST['action'] === 'add_position' && !empty($_POST['new_position'])) {
$newPosName = trim($_POST['new_position']);
$newPosType = $_POST['position_type'] ?? 'Uniform';
@ -54,26 +57,38 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && $electionStatus === 'Preparing') {
if (!$exists) {
$electionPositions[] = ['name' => $newPosName, 'type' => $newPosType];
$changed = true;
$logAction = "Add Position";
$logDetails = "Added new position: $newPosName ($newPosType)";
}
} elseif ($_POST['action'] === 'remove_position') {
$posNameToRemove = $_POST['position'];
$electionPositions = array_values(array_filter($electionPositions, fn($p) => $p['name'] !== $posNameToRemove));
$changed = true;
$logAction = "Remove Position";
$logDetails = "Removed position: $posNameToRemove";
} elseif ($_POST['action'] === 'add_party' && !empty($_POST['new_party'])) {
$newParty = trim($_POST['new_party']);
if (!in_array($newParty, $electionParties)) {
$electionParties[] = $newParty;
$changed = true;
$logAction = "Add Party";
$logDetails = "Added new political party: $newParty";
}
} elseif ($_POST['action'] === 'remove_party') {
$partyToRemove = $_POST['party'];
$electionParties = array_values(array_filter($electionParties, fn($p) => $p !== $partyToRemove));
$changed = true;
$logAction = "Remove Party";
$logDetails = "Removed political party: $partyToRemove";
}
if ($changed) {
$stmt = $db->prepare("UPDATE Election_History SET Parties = ?, Positions = ? WHERE Election_ID = ?");
$stmt->execute([json_encode($electionParties), json_encode($electionPositions), $electionId]);
// Log to Audit Trail
$Auth->Log_Action($_SESSION['User_ID'], $_SESSION['User_Role'], $logAction, $logDetails);
header("Location: Candidates.php");
exit;
}
@ -156,8 +171,7 @@ $candidatesList = $stmt->fetchAll();
color: var(--Primary_Color);
display: flex;
justify-content: center;
align-items: center;
font-weight: 700;
align-items: center; font-weight: 700;
overflow: hidden;
object-fit: cover;
}
@ -229,7 +243,7 @@ $candidatesList = $stmt->fetchAll();
<aside class="Sidebar">
<div class="Sidebar_Header">
<div class="Logo_Text">
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">ElectionSystem</div>
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">Click to Vote</div>
<div class="Logo_Subtitle">Administrator Portal</div>
</div>
</div>
@ -249,9 +263,12 @@ $candidatesList = $stmt->fetchAll();
<a href="Officers.php" class="Nav_Item">
<i class="fas fa-user-shield"></i> Officers Management
</a>
<a href="Audit_Trail.html" class="Nav_Item">
<a href="Audit_Trail.php" class="Nav_Item">
<i class="fas fa-file-alt"></i> Reports & Audit
</a>
<a href="Credits.php" class="Nav_Item">
<i class="fas fa-info-circle"></i> Credits
</a>
</nav>
<div style="padding: 24px; border-top: 1px solid var(--Border_Color);">
<a href="Logout.php" class="Nav_Item" style="padding: 0; color: var(--Error_Color);">
@ -373,8 +390,8 @@ $candidatesList = $stmt->fetchAll();
<input type="email" name="email" class="Input" placeholder="juan@school.edu" required>
</div>
<div class="Form_Group">
<label class="Label">User ID (Leave blank for random)</label>
<input type="text" name="user_id" class="Input" placeholder="00-0000">
<label class="Label">User ID</label>
<input type="text" name="user_id" class="Input" placeholder="Leave blank for random">
</div>
<div class="Form_Group">
<label class="Label">Position</label>
@ -412,8 +429,8 @@ $candidatesList = $stmt->fetchAll();
</select>
</div>
<div class="Form_Group">
<label class="Label">Password (Leave blank for default)</label>
<input type="password" name="password" class="Input" placeholder="Set password">
<label class="Label">Password</label>
<input type="password" name="password" class="Input" placeholder="Leave blank for default">
</div>
<div class="Form_Group">
<label class="Label">Candidate Photo</label>
@ -586,4 +603,4 @@ $candidatesList = $stmt->fetchAll();
</main>
</div>
</body>
</html>
</html>

105
Screens/Credits.php Normal file
View File

@ -0,0 +1,105 @@
<?php
require_once __DIR__ . '/../Logic/Backend/Authentication_Handler.php';
require_once __DIR__ . '/../db/config.php';
$Auth = new Authentication_Handler();
$Auth->Check_Auth();
if ($_SESSION['Access_Level'] < 1) {
header('Location: Voting_Screen.php');
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Credits | Online School Election System</title>
<link rel="stylesheet" href="../Design/Style.css?v=<?php echo time(); ?>">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body>
<div class="Dashboard_Container">
<!-- Sidebar -->
<aside class="Sidebar">
<div class="Sidebar_Header">
<div class="Logo_Text">
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">Click to Vote</div>
<div class="Logo_Subtitle">Administrator Portal</div>
</div>
</div>
<nav class="Sidebar_Nav">
<a href="Election_Dashboard.php" class="Nav_Item">
<i class="fas fa-th-large"></i> Election Dashboard
</a>
<a href="Election_History.php" class="Nav_Item">
<i class="fas fa-vote-yea"></i> Election History
</a>
<a href="Voters.php" class="Nav_Item">
<i class="fas fa-users"></i> Voter Management
</a>
<a href="Candidates.php" class="Nav_Item">
<i class="fas fa-user-tie"></i> Candidate Management
</a>
<a href="Officers.php" class="Nav_Item">
<i class="fas fa-user-shield"></i> Officers Management
</a>
<a href="Audit_Trail.php" class="Nav_Item">
<i class="fas fa-file-alt"></i> Reports & Audit
</a>
<a href="Credits.php" class="Nav_Item Active">
<i class="fas fa-info-circle"></i> Credits
</a>
</nav>
<div style="padding: 24px; border-top: 1px solid var(--Border_Color);">
<a href="Logout.php" class="Nav_Item" style="padding: 0; color: var(--Error_Color);">
<i class="fas fa-sign-out-alt"></i> Logout
</a>
</div>
</aside>
<!-- Main Content -->
<main class="Main_Content">
<!-- Top Bar -->
<header class="Top_Bar">
<div class="Top_Bar_Actions" style="margin-left: auto;">
<div style="display: flex; align-items: center; gap: 12px;">
<div style="text-align: right;">
<div style="font-weight: 700; font-size: 0.9rem;"><?php echo htmlspecialchars($_SESSION['User_Name']); ?></div>
<div style="font-size: 0.75rem; color: var(--Text_Secondary);"><?php echo htmlspecialchars($_SESSION['User_Role']); ?></div>
</div>
<div style="width: 40px; height: 40px; background: var(--Primary_Light); color: var(--Primary_Color); border-radius: 50%; display: flex; justify-content: center; align-items: center; font-weight: 700;">
<?php echo strtoupper(substr($_SESSION['User_Name'] ?? 'A', 0, 1)); ?>
</div>
</div>
</div>
</header>
<!-- Content Body -->
<div class="Content_Body">
<div class="Page_Title_Section">
<h1 class="Page_Title">Credits</h1>
<p class="Page_Subtitle">Information about the application development</p>
</div>
<div class="Card" style="text-align: center; padding: 60px;">
<div style="margin-bottom: 30px;">
<img src="https://flatlogic.com/assets/logo-flatlogic-d698f1f54497525330e6211116631f24.svg" alt="Flatlogic Logo" style="width: 200px; margin-bottom: 20px;">
<h2 style="font-size: 2rem; color: var(--Primary_Color); margin-bottom: 10px;">Built with Flatlogic</h2>
<p class="Text_Muted" style="max-width: 600px; margin: 0 auto; line-height: 1.8;">
This Online School Election System was built using the Flatlogic Platform.
Flatlogic is a platform for building full-stack web applications in minutes.
</p>
</div>
<div style="display: flex; justify-content: center; gap: 20px; margin-top: 40px;">
<a href="https://flatlogic.com" target="_blank" class="Button_Primary" style="width: auto; padding: 12px 30px; text-decoration: none;">Visit Flatlogic</a>
<a href="https://flatlogic.com/documentation" target="_blank" class="Button_Secondary" style="width: auto; padding: 12px 30px; text-decoration: none;">Documentation</a>
</div>
</div>
</div>
</main>
</div>
</body>
</html>

View File

@ -12,12 +12,66 @@ if ($_SESSION['Access_Level'] < 1) {
$db = db();
// Handle New Election Creation
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['create_election'])) {
$year = $_POST['election_year'] ?? date('Y');
// Default configuration for a new election
$defaultParties = json_encode(['Independent']);
$defaultPositions = json_encode([
['name' => 'President', 'type' => 'Uniform'],
['name' => 'Vice President', 'type' => 'Uniform'],
['name' => 'Secretary', 'type' => 'Uniform'],
['name' => 'Treasurer', 'type' => 'Uniform']
]);
$startDate = date('Y-m-d H:i:s');
$endDate = date('Y-m-d H:i:s', strtotime('+7 days'));
try {
$stmt = $db->prepare("INSERT INTO Election_History (Year, Parties, Positions, Status, Start_Date, End_Date, Total_Voters) VALUES (?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$year, $defaultParties, $defaultPositions, 'Preparing', $startDate, $endDate, 0]);
$Auth->Log_Action($_SESSION['User_ID'], $_SESSION['User_Role'], 'Create New Election', "Created a new election for School Year $year");
header("Location: Election_Dashboard.php?success=New election created successfully");
exit;
} catch (Exception $e) {
header("Location: Election_Dashboard.php?error=Error creating election: " . $e->getMessage());
exit;
}
}
// Handle Status Change
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_status'])) {
$newStatus = $_POST['new_status'];
$electionId = $_POST['election_id'];
$stmt = $db->prepare("UPDATE Election_History SET Status = ? WHERE Election_ID = ?");
$stmt->execute([$newStatus, $electionId]);
// Fetch current status
$currentElectionStmt = $db->prepare("SELECT * FROM Election_History WHERE Election_ID = ?");
$currentElectionStmt->execute([$electionId]);
$electionData = $currentElectionStmt->fetch();
if ($newStatus === 'Finished') {
// Save current details to history record
$totalVoters = $db->query("SELECT COUNT(*) FROM Voters")->fetchColumn();
$votedCount = $db->query("SELECT COUNT(*) FROM Voters WHERE Has_Voted = 1")->fetchColumn();
// Fetch Candidates and potentially calculate results if there was a voting table
$candidates = $db->query("SELECT Name, Position, Party FROM Candidates")->fetchAll(PDO::FETCH_ASSOC);
$stmt = $db->prepare("UPDATE Election_History SET Status = ?, Total_Voters = ?, Results = ? WHERE Election_ID = ?");
$stmt->execute([$newStatus, $totalVoters, json_encode($candidates), $electionId]);
} else {
$stmt = $db->prepare("UPDATE Election_History SET Status = ? WHERE Election_ID = ?");
$stmt->execute([$newStatus, $electionId]);
}
// Log to Audit Trail
$year = $electionData['Year'] ?? 'Unknown';
$oldStatus = $electionData['Status'] ?? 'Unknown';
$Auth->Log_Action($_SESSION['User_ID'], $_SESSION['User_Role'], 'Update Election Status', "Changed SY $year Election status from $oldStatus to $newStatus");
header("Location: Election_Dashboard.php");
exit;
}
@ -50,6 +104,45 @@ $activeElections = $db->query("SELECT * FROM Election_History WHERE Status IN ('
.Status_Active, .Status_Ongoing { background: #DCFCE7; color: #166534; }
.Status_Preparing { background: #FEF3C7; color: #92400E; }
.Status_Completed, .Status_Finished { background: #F1F5F9; color: #475569; }
/* Modal Styles */
.Modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
z-index: 1000;
justify-content: center;
align-items: center;
backdrop-filter: blur(4px);
}
.Modal_Content {
background: white;
padding: 32px;
border-radius: 20px;
width: 90%;
max-width: 400px;
position: relative;
box-shadow: 0 20px 25px -5px rgba(0,0,0,0.1);
}
.Modal_Header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.Modal_Title {
font-size: 1.25rem;
font-weight: 700;
}
.Modal_Close {
cursor: pointer;
font-size: 1.25rem;
color: var(--Text_Secondary);
}
</style>
</head>
<body>
@ -58,7 +151,7 @@ $activeElections = $db->query("SELECT * FROM Election_History WHERE Status IN ('
<aside class="Sidebar">
<div class="Sidebar_Header">
<div class="Logo_Text">
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">ElectionSystem</div>
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">Click to Vote</div>
<div class="Logo_Subtitle">Administrator Portal</div>
</div>
</div>
@ -78,9 +171,12 @@ $activeElections = $db->query("SELECT * FROM Election_History WHERE Status IN ('
<a href="Officers.php" class="Nav_Item">
<i class="fas fa-user-shield"></i> Officers Management
</a>
<a href="Audit_Trail.html" class="Nav_Item">
<a href="Audit_Trail.php" class="Nav_Item">
<i class="fas fa-file-alt"></i> Reports & Audit
</a>
<a href="Credits.php" class="Nav_Item">
<i class="fas fa-info-circle"></i> Credits
</a>
</nav>
<div style="padding: 24px; border-top: 1px solid var(--Border_Color);">
<a href="Logout.php" class="Nav_Item" style="padding: 0; color: var(--Error_Color);">
@ -112,6 +208,17 @@ $activeElections = $db->query("SELECT * FROM Election_History WHERE Status IN ('
<!-- Content Body -->
<div class="Content_Body">
<?php if (isset($_GET['success'])): ?>
<div class="Badge Badge_Success" style="width: 100%; padding: 15px; margin-bottom: 20px; text-align: center;">
<i class="fas fa-check-circle"></i> <?php echo htmlspecialchars($_GET['success']); ?>
</div>
<?php endif; ?>
<?php if (isset($_GET['error'])): ?>
<div class="Badge" style="width: 100%; padding: 15px; margin-bottom: 20px; text-align: center; background: #FEE2E2; color: #EF4444;">
<i class="fas fa-exclamation-circle"></i> <?php echo htmlspecialchars($_GET['error']); ?>
</div>
<?php endif; ?>
<div class="Page_Title_Section">
<h1 class="Page_Title">Election Dashboard</h1>
<p class="Page_Subtitle">Welcome back! Here's what's happening with the current elections.</p>
@ -142,7 +249,7 @@ $activeElections = $db->query("SELECT * FROM Election_History WHERE Status IN ('
<div class="Card">
<div class="Card_Header">
<h2 class="Card_Title">Active & Upcoming Elections</h2>
<button class="Button_Primary" style="width: auto; padding: 8px 16px; font-size: 0.85rem;">
<button onclick="openNewElectionModal()" class="Button_Primary" style="width: auto; padding: 8px 16px; font-size: 0.85rem;">
<i class="fas fa-plus"></i> New Election
</button>
</div>
@ -160,7 +267,7 @@ $activeElections = $db->query("SELECT * FROM Election_History WHERE Status IN ('
<?php if (empty($activeElections)): ?>
<tr>
<td colspan="4" style="text-align: center; padding: 40px; color: var(--Text_Secondary);">
No active elections found. <a href="#" style="color: var(--Primary_Color); font-weight: 600;">Create one now.</a>
No active elections found. <a href="javascript:void(0)" onclick="openNewElectionModal()" style="color: var(--Primary_Color); font-weight: 600;">Create one now.</a>
</td>
</tr>
<?php else: ?>
@ -195,5 +302,37 @@ $activeElections = $db->query("SELECT * FROM Election_History WHERE Status IN ('
</div>
</main>
</div>
<!-- New Election Modal -->
<div id="NewElectionModal" class="Modal">
<div class="Modal_Content">
<div class="Modal_Header">
<h2 class="Modal_Title">Create New Election</h2>
<span class="Modal_Close" onclick="closeNewElectionModal()">&times;</span>
</div>
<form method="POST">
<div class="Form_Group">
<label class="Label">School Year</label>
<input type="number" name="election_year" class="Input" value="<?php echo date('Y'); ?>" min="2000" max="2100" required>
<p class="Text_Muted" style="font-size: 0.75rem; margin-top: 5px;">Example: 2026 for SY 2026-2027</p>
</div>
<button type="submit" name="create_election" class="Button_Primary" style="width: 100%; margin-top: 24px;">Initialize Election</button>
</form>
</div>
</div>
<script>
function openNewElectionModal() {
document.getElementById('NewElectionModal').style.display = 'flex';
}
function closeNewElectionModal() {
document.getElementById('NewElectionModal').style.display = 'none';
}
window.onclick = function(event) {
if (event.target == document.getElementById('NewElectionModal')) {
closeNewElectionModal();
}
}
</script>
</body>
</html>

View File

@ -15,11 +15,6 @@ $db = db();
// Fetch all completed elections
$history = $db->query("SELECT * FROM Election_History ORDER BY Year DESC")->fetchAll();
// For each election, we might want to fetch more detailed stats if they were stored.
// Since it's a history page, we'll mock some of the breakdown data if it's not in the DB,
// or calculate it based on current voters if we assume the voter list represents the latest.
// In a real system, these would be snapshots.
?>
<!DOCTYPE html>
<html lang="en">
@ -43,7 +38,7 @@ $history = $db->query("SELECT * FROM Election_History ORDER BY Year DESC")->fetc
<aside class="Sidebar">
<div class="Sidebar_Header">
<div class="Logo_Text">
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">ElectionSystem</div>
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">Click to Vote</div>
<div class="Logo_Subtitle">Administrator Portal</div>
</div>
</div>
@ -63,9 +58,12 @@ $history = $db->query("SELECT * FROM Election_History ORDER BY Year DESC")->fetc
<a href="Officers.php" class="Nav_Item">
<i class="fas fa-user-shield"></i> Officers Management
</a>
<a href="Audit_Trail.html" class="Nav_Item">
<a href="Audit_Trail.php" class="Nav_Item">
<i class="fas fa-file-alt"></i> Reports & Audit
</a>
<a href="Credits.php" class="Nav_Item">
<i class="fas fa-info-circle"></i> Credits
</a>
</nav>
<div style="padding: 24px; border-top: 1px solid var(--Border_Color);">
<a href="Logout.php" class="Nav_Item" style="padding: 0; color: var(--Error_Color);">
@ -123,7 +121,10 @@ $history = $db->query("SELECT * FROM Election_History ORDER BY Year DESC")->fetc
<div class="Accordion_Item <?php echo $index === 0 ? 'Active' : ''; ?>" id="year-<?php echo $item['Year']; ?>">
<div class="Accordion_Header">
<h3>School Year <?php echo $item['Year']; ?><?php echo $item['Year']+1; ?></h3>
<i class="fas fa-chevron-down Accordion_Icon"></i>
<div style="display: flex; align-items: center; gap: 10px;">
<span class="Badge <?php echo $item['Status'] === 'Finished' ? 'Badge_Success' : 'Badge_Warning'; ?>"><?php echo $item['Status']; ?></span>
<i class="fas fa-chevron-down Accordion_Icon"></i>
</div>
</div>
<div class="Accordion_Content">
<!-- Stats Overview -->
@ -131,77 +132,47 @@ $history = $db->query("SELECT * FROM Election_History ORDER BY Year DESC")->fetc
<div class="Stat_Card">
<div class="Stat_Label">Total Voters</div>
<div class="Stat_Value"><?php echo $item['Total_Voters']; ?></div>
<div class="Stat_Trend">100%</div>
</div>
<div class="Stat_Card">
<div class="Stat_Label">Have Voted</div>
<?php
// Mocking these values for historical data as requested by UI
$voted = round($item['Total_Voters'] * 0.789);
$votedPercent = 78.9;
?>
<div class="Stat_Value"><?php echo $voted; ?></div>
<div class="Stat_Trend Trend_Up"><?php echo $votedPercent; ?>%</div>
</div>
<div class="Stat_Card">
<div class="Stat_Label">Did Not Vote</div>
<?php
$notVoted = $item['Total_Voters'] - $voted;
$notVotedPercent = 100 - $votedPercent;
?>
<div class="Stat_Value"><?php echo $notVoted; ?></div>
<div class="Stat_Trend Trend_Down"><?php echo $notVotedPercent; ?>%</div>
<div class="Stat_Label">Election Period</div>
<div style="font-size: 1rem; font-weight: 600;">
<?php echo date('M d, Y', strtotime($item['Start_Date'])); ?> to <?php echo date('M d, Y', strtotime($item['End_Date'])); ?>
</div>
</div>
</div>
<!-- Breakdown Tables -->
<div class="Dashboard_Grid" style="grid-template-columns: 1fr; gap: 24px;">
<div class="Card" style="padding: 0; box-shadow: none; border: 1px solid var(--Border_Color);">
<div class="Card_Header" style="padding: 20px 24px; margin-bottom: 0; border-bottom: 1px solid var(--Border_Color);">
<h4 class="Card_Title" style="font-size: 1rem;">Voters by Track / Strand</h4>
</div>
<div class="Data_List" style="padding: 0 24px;">
<div class="Data_Row">
<div class="Data_Label">STEM</div>
<div class="Data_Value">60</div>
</div>
<div class="Data_Row">
<div class="Data_Label">ABM</div>
<div class="Data_Value">40</div>
</div>
<div class="Data_Row">
<div class="Data_Label">HUMSS</div>
<div class="Data_Value">45</div>
</div>
<div class="Data_Row">
<div class="Data_Label">TVL</div>
<div class="Data_Value">35</div>
</div>
</div>
</div>
<div class="Card" style="padding: 0; box-shadow: none; border: 1px solid var(--Border_Color);">
<div class="Card_Header" style="padding: 20px 24px; margin-bottom: 0; border-bottom: 1px solid var(--Border_Color);">
<h4 class="Card_Title" style="font-size: 1rem;">Voters by Grade Level</h4>
</div>
<div class="Data_List" style="padding: 0 24px;">
<div class="Data_Row">
<div class="Data_Label">Grade 11</div>
<div class="Data_Value">95</div>
</div>
<div class="Data_Row">
<div class="Data_Label">Grade 12</div>
<div class="Data_Value">85</div>
</div>
</div>
</div>
<div class="Card" style="padding: 0; box-shadow: none; border: 1px solid var(--Border_Color);">
<div class="Card_Header" style="padding: 20px 24px; margin-bottom: 0; border-bottom: 1px solid var(--Border_Color);">
<h4 class="Card_Title" style="font-size: 1rem;">Candidate Results</h4>
</div>
<div style="padding: 24px; text-align: center; color: var(--Text_Secondary);">
Detailed candidate performance data for this year.
<div class="Table_Wrapper">
<table>
<thead>
<tr>
<th>Candidate Name</th>
<th>Position</th>
<th>Party</th>
</tr>
</thead>
<tbody>
<?php
$results = json_decode($item['Results'] ?? '[]', true) ?: [];
if (empty($results)):
?>
<tr><td colspan="3" style="text-align: center; padding: 20px;">No detailed results saved for this election.</td></tr>
<?php else: ?>
<?php foreach ($results as $candidate): ?>
<tr>
<td style="font-weight: 600;"><?php echo htmlspecialchars($candidate['Name']); ?></td>
<td><?php echo htmlspecialchars($candidate['Position']); ?></td>
<td><?php echo htmlspecialchars($candidate['Party']); ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>

View File

@ -14,29 +14,225 @@ if (isset($_SESSION['User_ID'])) {
<link rel="stylesheet" href="../Design/Style.css?v=<?php echo time(); ?>">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--Modal_Header_Bg: #4E66D1; /* Specific blue from screenshot */
}
.Landing_Wrapper {
background-image: url('../assets/pasted-20260204-200305-388a4105.jpg');
}
.Landing_Info_Card {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
padding: 48px;
border-radius: 32px;
border: 1px solid rgba(255, 255, 255, 0.1);
background: white;
padding: 0;
border-radius: 24px;
overflow: hidden;
box-shadow: 0 20px 40px rgba(0,0,0,0.3);
max-width: 850px;
width: 90%;
margin: 0 auto;
border: none;
}
.Landing_Card_Header {
background: var(--Modal_Header_Bg);
padding: 20px 30px;
color: white;
display: flex;
align-items: center;
gap: 15px;
}
.Landing_Card_Body {
padding: 40px 48px;
color: var(--Text_Primary);
text-align: left;
}
.Landing_Title {
font-size: clamp(2rem, 6vw, 3.5rem);
font-size: clamp(1.5rem, 5vw, 2.5rem);
margin-bottom: 16px;
font-weight: 800;
color: var(--Text_Primary);
text-transform: none;
letter-spacing: normal;
}
.Landing_Description {
margin-bottom: 32px;
font-size: 1.1rem;
color: var(--Text_Secondary);
}
/* Modal Redesign */
.Login_Card {
padding: 0;
border-radius: 20px;
overflow: hidden;
border: none;
max-width: 480px;
}
.Modal_Header {
background: var(--Modal_Header_Bg);
padding: 24px;
color: white;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.Modal_Header_Content {
display: flex;
align-items: center;
gap: 16px;
flex: 1;
justify-content: center;
}
.Modal_Header_Title {
font-size: 1.75rem;
font-weight: 700;
margin: 0;
letter-spacing: 0.5px;
}
.Modal_Header_Icon {
font-size: 1.8rem;
border: 2px solid rgba(255,255,255,0.3);
padding: 6px;
border-radius: 8px;
}
.Btn_Close_Modal_New {
background: rgba(15, 23, 42, 0.4);
border: none;
width: 30px;
height: 30px;
border-radius: 50%;
color: white;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
transition: background 0.2s;
font-size: 0.9rem;
}
.Btn_Close_Modal_New:hover {
background: rgba(15, 23, 42, 0.6);
}
.Modal_Body {
padding: 32px 40px;
}
.Form_Group_New {
margin-bottom: 24px;
}
.Label_New {
display: block;
font-size: 0.85rem;
font-weight: 700;
margin-bottom: 10px;
color: #475569;
text-transform: uppercase;
}
.Input_Wrapper {
position: relative;
}
.Input_Icon_Left {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
color: #64748B;
font-size: 1.1rem;
}
.Input_New {
width: 100%;
padding: 14px 16px 14px 48px;
border: 2px solid #E2E8F0;
border-radius: 12px;
font-size: 1rem;
color: #1E293B;
transition: all 0.2s;
background: white;
}
.Input_New::placeholder {
color: #94A3B8;
}
.Input_New:focus {
outline: none;
border-color: var(--Modal_Header_Bg);
box-shadow: 0 0 0 4px rgba(78, 102, 209, 0.1);
}
.Select_New {
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2364748B'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 16px center;
background-size: 18px;
}
.Btn_Password_Toggle {
position: absolute;
right: 16px;
top: 50%;
transform: translateY(-50%);
color: #64748B;
cursor: pointer;
background: none;
border: none;
padding: 0;
font-size: 1.1rem;
}
.Btn_Login_Submit {
width: 100%;
padding: 16px;
background: var(--Modal_Header_Bg);
color: white;
border: none;
border-radius: 12px;
font-weight: 700;
font-size: 1.1rem;
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
cursor: pointer;
transition: all 0.2s;
margin-top: 8px;
text-transform: uppercase;
}
.Btn_Login_Submit:hover {
background: #3D54B8;
transform: translateY(-1px);
box-shadow: 0 8px 15px rgba(78, 102, 209, 0.3);
}
.Forgot_Password {
display: block;
text-align: center;
margin-top: 20px;
color: #4E66D1;
text-decoration: none;
font-weight: 600;
font-size: 0.95rem;
}
.Forgot_Password:hover {
text-decoration: underline;
}
</style>
</head>
@ -58,15 +254,21 @@ if (isset($_SESSION['User_ID'])) {
<!-- Main Landing Content wrapped in a card for visual separation -->
<main class="Landing_Content">
<div class="Landing_Info_Card">
<h1 class="Landing_Title">CLICK TO VOTE</h1>
<p class="Landing_Description">
This portal is currently a <strong>PROTOTYPE MODEL</strong> under active development to demonstrate the digital election process.
Please be aware that all features are in a testing phase and interactions are for demonstration purposes only. We are
continuously refining the system to ensure a seamless experience for the final implementation.
</p>
<button id="Open_Login_Btn" class="Btn_Landing_Login">
<i class="fas fa-sign-in-alt"></i> LOGIN
</button>
<div class="Landing_Card_Header">
<i class="fas fa-info-circle" style="font-size: 1.5rem;"></i>
<span style="font-weight: 700; letter-spacing: 1px;">SYSTEM INFORMATION</span>
</div>
<div class="Landing_Card_Body">
<h1 class="Landing_Title">CLICK TO VOTE</h1>
<p class="Landing_Description">
This portal is currently a <strong>PROTOTYPE MODEL</strong> under active development to demonstrate the digital election process.
Please be aware that all features are in a testing phase and interactions are for demonstration purposes only. We are
continuously refining the system to ensure a seamless experience for the final implementation.
</p>
<button id="Open_Login_Btn" class="Btn_Landing_Login" style="background: var(--Modal_Header_Bg); color: white;">
<i class="fas fa-sign-in-alt"></i> LOGIN
</button>
</div>
</div>
</main>
@ -78,46 +280,71 @@ if (isset($_SESSION['User_ID'])) {
<!-- Login Modal -->
<div id="Login_Modal" class="Modal_Overlay">
<div class="Login_Card">
<button class="Btn_Close_Modal" id="Close_Login_Btn" title="Close">
<i class="fas fa-times"></i>
</button>
<div style="text-align: center; margin-bottom: 24px;">
<div style="width: 64px; height: 64px; background: var(--Primary_Light); color: var(--Primary_Color); border-radius: 16px; display: flex; justify-content: center; align-items: center; font-size: 2rem; margin: 0 auto 16px;">
<i class="fas fa-vote-yea"></i>
<div class="Modal_Header">
<div class="Modal_Header_Content">
<i class="fas fa-users-viewfinder Modal_Header_Icon"></i>
<h2 class="Modal_Header_Title">Login</h2>
</div>
<h1 class="Title_Large">Welcome Back</h1>
<p class="Text_Muted">Sign in to manage the school election</p>
</div>
<div id="Error_Alert" class="Alert Alert_Error" style="padding: 12px; border-radius: 10px; font-size: 0.85rem; margin-bottom: 20px; display: none; background: #FEE2E2; color: #EF4444; border: 1px solid #FCA5A5;">
<i class="fas fa-exclamation-circle"></i> <span id="Error_Message"></span>
</div>
<form action="../Logic/Backend/Authentication_Handler.php" method="POST">
<div class="Form_Group">
<label class="Label" for="User_ID">User ID</label>
<div style="position: relative;">
<i class="fas fa-id-card" style="position: absolute; left: 16px; top: 50%; transform: translateY(-50%); color: var(--Text_Secondary);"></i>
<input class="Input" type="text" name="User_ID" id="User_ID" placeholder="e.g. 00-0000" required style="padding-left: 48px;">
</div>
</div>
<div class="Form_Group">
<label class="Label" for="Password">Password</label>
<div style="position: relative;">
<i class="fas fa-lock" style="position: absolute; left: 16px; top: 50%; transform: translateY(-50%); color: var(--Text_Secondary);"></i>
<input class="Input" type="password" name="Password" id="Password" placeholder="••••••••" required style="padding-left: 48px;">
</div>
</div>
<div class="Form_Group" style="margin-top: 10px;">
<label class="Label" style="display: flex; align-items: center; gap: 8px; font-weight: 500; cursor: pointer; text-transform: none; letter-spacing: normal;">
<input type="checkbox" name="User_Type" value="Voter" style="width: 16px; height: 16px;">
Sign in as Voter
</label>
</div>
<button type="submit" class="Button_Primary">
Sign In
<button class="Btn_Close_Modal_New" id="Close_Login_Btn" title="Close">
<i class="fas fa-times"></i>
</button>
</form>
</div>
<div class="Modal_Body">
<div id="Error_Alert" class="Alert Alert_Error" style="padding: 12px; border-radius: 10px; font-size: 0.85rem; margin-bottom: 20px; display: none; background: #FEE2E2; color: #EF4444; border: 1px solid #FCA5A5;">
<i class="fas fa-exclamation-circle"></i> <span id="Error_Message"></span>
</div>
<form action="../Logic/Backend/Authentication_Handler.php" method="POST">
<div class="Form_Group_New">
<label class="Label_New" for="User_Type">User Type</label>
<div class="Input_Wrapper">
<i class="fas fa-user-check Input_Icon_Left"></i>
<select class="Input_New Select_New" name="User_Type_Select" id="User_Type_Select">
<option value="Voter">Voter</option>
<option value="Adviser">Adviser</option>
<option value="Officer">Officer</option>
<option value="Admin">Admin</option>
</select>
</div>
</div>
<div class="Form_Group_New">
<label class="Label_New" for="User_ID">UID</label>
<div class="Input_Wrapper">
<i class="fas fa-id-card Input_Icon_Left"></i>
<input class="Input_New" type="text" name="User_ID" id="User_ID" placeholder="00-0000" required>
</div>
</div>
<div class="Form_Group_New">
<label class="Label_New" for="Email">Email Account</label>
<div class="Input_Wrapper">
<i class="fas fa-envelope Input_Icon_Left"></i>
<input class="Input_New" type="email" name="Email" id="Email" placeholder="firstname.lastname@iloilonhs.edu.ph">
</div>
</div>
<div class="Form_Group_New">
<label class="Label_New" for="Password">Password</label>
<div class="Input_Wrapper">
<i class="fas fa-lock Input_Icon_Left"></i>
<input class="Input_New" type="password" name="Password" id="Password" placeholder="Enter your password" required>
<button type="button" id="Toggle_Password" class="Btn_Password_Toggle">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<input type="hidden" name="User_Type" id="User_Type_Hidden" value="Voter">
<button type="submit" class="Btn_Login_Submit">
<i class="fas fa-sign-in-alt"></i> LOGIN
</button>
<a href="#" class="Forgot_Password">Forgot Password?</a>
</form>
</div>
</div>
</div>
@ -125,6 +352,10 @@ if (isset($_SESSION['User_ID'])) {
const loginModal = document.getElementById('Login_Modal');
const openLoginBtn = document.getElementById('Open_Login_Btn');
const closeLoginBtn = document.getElementById('Close_Login_Btn');
const userTypeSelect = document.getElementById('User_Type_Select');
const userTypeHidden = document.getElementById('User_Type_Hidden');
const togglePassword = document.getElementById('Toggle_Password');
const passwordInput = document.getElementById('Password');
openLoginBtn.addEventListener('click', () => {
loginModal.classList.add('Active');
@ -141,6 +372,19 @@ if (isset($_SESSION['User_ID'])) {
}
});
// Sync Select to Hidden Input (if backend expects specific User_Type field)
userTypeSelect.addEventListener('change', (e) => {
userTypeHidden.value = e.target.value;
});
// Toggle Password Visibility
togglePassword.addEventListener('click', () => {
const type = passwordInput.getAttribute('type') === 'password' ? 'text' : 'password';
passwordInput.setAttribute('type', type);
togglePassword.querySelector('i').classList.toggle('fa-eye');
togglePassword.querySelector('i').classList.toggle('fa-eye-slash');
});
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('error')) {
loginModal.classList.add('Active');

View File

View File

@ -193,7 +193,7 @@ $totalOfficers = count($comeaOfficers);
<aside class="Sidebar">
<div class="Sidebar_Header">
<div class="Logo_Text">
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">ElectionSystem</div>
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">Click to Vote</div>
<div class="Logo_Subtitle">Administrator Portal</div>
</div>
</div>
@ -213,9 +213,12 @@ $totalOfficers = count($comeaOfficers);
<a href="Officers.php" class="Nav_Item Active">
<i class="fas fa-user-shield"></i> Officers Management
</a>
<a href="Audit_Trail.html" class="Nav_Item">
<a href="Audit_Trail.php" class="Nav_Item">
<i class="fas fa-file-alt"></i> Reports & Audit
</a>
<a href="Credits.php" class="Nav_Item">
<i class="fas fa-info-circle"></i> Credits
</a>
</nav>
<div style="padding: 24px; border-top: 1px solid var(--Border_Color);">
<a href="Logout.php" class="Nav_Item" style="padding: 0; color: var(--Error_Color);">
@ -284,8 +287,8 @@ $totalOfficers = count($comeaOfficers);
<input type="email" name="email" class="Input" placeholder="email@school.edu" required>
</div>
<div class="Form_Group">
<label class="Label">User ID (Leave blank for random)</label>
<input type="text" name="user_id" class="Input" placeholder="00-0000">
<label class="Label">User ID</label>
<input type="text" name="user_id" class="Input" placeholder="Leave blank for random">
</div>
<div class="Form_Group">
<label class="Label">Role</label>
@ -296,8 +299,8 @@ $totalOfficers = count($comeaOfficers);
</select>
</div>
<div class="Form_Group">
<label class="Label">Password (Leave blank for default)</label>
<input type="password" name="password" class="Input" placeholder="Set password">
<label class="Label">Password</label>
<input type="password" name="password" class="Input" placeholder="Leave blank for default">
</div>
<div class="Form_Group" style="display: flex; align-items: flex-end;">
<button type="submit" class="Button_Primary" style="margin-top: 0; width: 100%;">
@ -448,8 +451,8 @@ $totalOfficers = count($comeaOfficers);
</select>
</div>
<div class="Form_Group" style="margin-top: 15px;">
<label class="Label">New Password (Leave blank to keep current)</label>
<input type="password" name="password" class="Input" placeholder="Enter new password">
<label class="Label">New Password</label>
<input type="password" name="password" class="Input" placeholder="Leave blank to keep current">
</div>
<button type="submit" class="Button_Primary" style="width: 100%; margin-top: 24px;">Update Officer</button>
</form>

View File

@ -122,7 +122,7 @@ $votersList = $stmt->fetchAll();
<aside class="Sidebar">
<div class="Sidebar_Header">
<div class="Logo_Text">
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">ElectionSystem</div>
<div class="Logo_Title" style="font-size: 1.1rem; color: var(--Primary_Color);">Click to Vote</div>
<div class="Logo_Subtitle">Administrator Portal</div>
</div>
</div>
@ -142,9 +142,12 @@ $votersList = $stmt->fetchAll();
<a href="Officers.php" class="Nav_Item">
<i class="fas fa-user-shield"></i> Officers Management
</a>
<a href="Audit_Trail.html" class="Nav_Item">
<a href="Audit_Trail.php" class="Nav_Item">
<i class="fas fa-file-alt"></i> Reports & Audit
</a>
<a href="Credits.php" class="Nav_Item">
<i class="fas fa-info-circle"></i> Credits
</a>
</nav>
<div style="padding: 24px; border-top: 1px solid var(--Border_Color);">
<a href="Logout.php" class="Nav_Item" style="padding: 0; color: var(--Error_Color);">
@ -254,7 +257,7 @@ $votersList = $stmt->fetchAll();
<button class="Button_Primary Voter_Actions_Btn" onclick="openAddModal()">
<i class="fas fa-plus"></i> Add Voter
</button>
<button class="Button_Secondary Voter_Actions_Btn">
<button class="Button_Secondary Voter_Actions_Btn" onclick="openImportModal()">
<i class="fas fa-file-import"></i> Import CSV
</button>
</div>
@ -358,7 +361,7 @@ $votersList = $stmt->fetchAll();
<div class="Modal_Content">
<div class="Modal_Header">
<h2 class="Modal_Title">Add New Voter</h2>
<span class="Modal_Close" onclick="closeModal()">&times;</span>
<span class="Modal_Close" onclick="closeModal('AddModal')">&times;</span>
</div>
<form action="../Logic/Backend/Add_Voter_Handler.php" method="POST">
<div class="Form_Group">
@ -366,8 +369,8 @@ $votersList = $stmt->fetchAll();
<input type="email" name="email" class="Input" placeholder="voter@school.edu" required>
</div>
<div class="Form_Group" style="margin-top: 15px;">
<label class="Label">User ID (Leave blank for random)</label>
<input type="text" name="user_id" class="Input" placeholder="00-0000">
<label class="Label">User ID</label>
<input type="text" name="user_id" class="Input" placeholder="Leave blank for random">
</div>
<div class="Form_Group" style="margin-top: 15px;">
<label class="Label">Track / Strand</label>
@ -385,29 +388,52 @@ $votersList = $stmt->fetchAll();
<input type="text" name="section" class="Input" placeholder="e.g. A" required>
</div>
<div class="Form_Group" style="margin-top: 15px;">
<label class="Label">Password (Leave blank for default)</label>
<input type="password" name="password" class="Input" placeholder="Set password">
<label class="Label">Password</label>
<input type="password" name="password" class="Input" placeholder="Leave blank for default">
</div>
<button type="submit" class="Button_Primary" style="width: 100%; margin-top: 24px;">Save Voter</button>
</form>
</div>
</div>
<!-- Import CSV Modal -->
<div id="ImportModal" class="Modal">
<div class="Modal_Content">
<div class="Modal_Header">
<h2 class="Modal_Title">Import Voters via CSV</h2>
<span class="Modal_Close" onclick="closeModal('ImportModal')">&times;</span>
</div>
<p class="Text_Muted" style="margin-bottom: 20px; font-size: 0.85rem;">
Upload a CSV file with the following headers: <br>
<strong>User_ID, Email, Track_Cluster, Grade_Level, Section, Password</strong>
</p>
<form action="../Logic/Backend/Import_Voters_Handler.php" method="POST" enctype="multipart/form-data">
<div class="Form_Group">
<label class="Label">Select CSV File</label>
<input type="file" name="csv_file" class="Input" accept=".csv" required>
</div>
<button type="submit" class="Button_Primary" style="width: 100%; margin-top: 24px;">Upload & Import</button>
</form>
</div>
</div>
<script>
function openAddModal() {
document.getElementById('AddModal').style.display = 'flex';
}
function closeModal() {
document.getElementById('AddModal').style.display = 'none';
function openImportModal() {
document.getElementById('ImportModal').style.display = 'flex';
}
function closeModal(id) {
document.getElementById(id).style.display = 'none';
}
// Close modal when clicking outside
window.onclick = function(event) {
if (event.target == document.getElementById('AddModal')) {
closeModal();
if (event.target.classList.contains('Modal')) {
event.target.style.display = 'none';
}
}
</script>
</body>
</html>
</html>

View File

@ -13,7 +13,7 @@ $Auth->Check_Auth();
</head>
<body>
<nav class="Dashboard_Navbar">
<div class="Logo"><strong>ElectionSystem</strong></div>
<div class="Logo"><strong>Click to Vote</strong></div>
<div class="User_Info">
<span><?php echo $_SESSION['User_Name']; ?> (Voter)</span>
<a href="Logout.php" style="margin-left: 20px; font-size: 0.875rem;">Logout</a>

View File

@ -39,6 +39,7 @@ try {
Election_ID INT AUTO_INCREMENT PRIMARY KEY,
Year INT,
Parties TEXT,
Positions TEXT,
Candidates TEXT,
Results TEXT,
Total_Voters INT,
@ -68,4 +69,4 @@ try {
} catch (Exception $e) {
die("Error initializing database: " . $e->getMessage());
}
}