diff --git a/Design/Style.css b/Design/Style.css index 7a3dc1c..17dc582 100644 --- a/Design/Style.css +++ b/Design/Style.css @@ -1,5 +1,6 @@ :root { --Primary_Color: #2563EB; + --Primary_Light: #DBEAFE; --Secondary_Color: #64748B; --Background_Color: #F8FAFC; --Surface_Color: #FFFFFF; @@ -9,6 +10,7 @@ --Success_Color: #10B981; --Error_Color: #EF4444; --Overlay_Color: rgba(0, 0, 0, 0.65); + --Sidebar_Width: 260px; } * { @@ -23,7 +25,8 @@ body, html { font-family: 'Inter', system-ui, -apple-system, sans-serif; color: var(--Text_Primary); line-height: 1.5; - overflow-x: hidden; + overflow: hidden; /* Main page scroll is handled by content body */ + background-color: var(--Background_Color); } /* Landing Page Styles */ @@ -39,7 +42,7 @@ body, html { align-items: center; color: white; text-align: center; - overflow: hidden; /* Prevent overflow */ + overflow: hidden; } .Landing_Wrapper::before { @@ -134,10 +137,6 @@ body, html { color: rgba(255, 255, 255, 0.9); } -.Landing_Description strong { - font-weight: 700; -} - .Btn_Landing_Login { display: inline-flex; align-items: center; @@ -301,88 +300,433 @@ body, html { box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3); } -.Password_Toggle_Wrapper { - position: relative; +/* Dashboard Layout */ +.Dashboard_Container { + display: flex; + width: 100%; + height: 100vh; } -.Toggle_Button { - position: absolute; - right: 16px; - top: 50%; - transform: translateY(-50%); - background: none; - border: none; - cursor: pointer; - font-size: 0.75rem; - font-weight: 700; +.Sidebar { + width: var(--Sidebar_Width); + background: white; + border-right: 1px solid var(--Border_Color); + display: flex; + flex-direction: column; + flex-shrink: 0; +} + +.Sidebar_Header { + padding: 24px; + border-bottom: 1px solid var(--Border_Color); +} + +.Sidebar_Nav { + padding: 20px 0; + flex: 1; + overflow-y: auto; +} + +.Nav_Item { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 24px; + color: var(--Text_Secondary); + text-decoration: none; + font-weight: 600; + font-size: 0.95rem; + transition: all 0.2s; +} + +.Nav_Item:hover { + background: #F1F5F9; color: var(--Primary_Color); } -/* Responsive Design */ +.Nav_Item.Active { + background: var(--Primary_Light); + color: var(--Primary_Color); + border-right: 4px solid var(--Primary_Color); +} + +.Main_Content { + flex: 1; + display: flex; + flex-direction: column; + min-width: 0; +} + +.Top_Bar { + height: 70px; + background: white; + border-bottom: 1px solid var(--Border_Color); + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 32px; + flex-shrink: 0; +} + +.Search_Box { + display: flex; + align-items: center; + background: #F1F5F9; + border-radius: 8px; + padding: 8px 16px; + width: 100%; + max-width: 400px; +} + +.Search_Box input { + background: transparent; + border: none; + outline: none; + padding: 4px 8px; + width: 100%; + font-family: inherit; +} + +.Top_Bar_Actions { + display: flex; + align-items: center; + gap: 24px; +} + +.Content_Body { + flex: 1; + padding: 32px; + overflow-y: auto; +} + +.Page_Title_Section { + margin-bottom: 32px; + display: flex; + justify-content: space-between; + align-items: flex-start; +} + +.Page_Title { + font-size: 1.75rem; + font-weight: 800; + color: var(--Text_Primary); +} + +.Page_Subtitle { + color: var(--Text_Secondary); + font-size: 0.95rem; +} + +/* Stat Cards */ +.Stat_Cards_Grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 24px; + margin-bottom: 32px; +} + +.Stat_Card { + background: white; + padding: 24px; + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); + display: flex; + flex-direction: column; + gap: 8px; +} + +.Stat_Label { + font-size: 0.875rem; + font-weight: 600; + color: var(--Text_Secondary); + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.Stat_Value { + font-size: 2rem; + font-weight: 800; + color: var(--Text_Primary); +} + +.Stat_Trend { + font-size: 0.85rem; + font-weight: 600; +} + +.Trend_Up { color: var(--Success_Color); } +.Trend_Down { color: var(--Error_Color); } + +/* Dashboard Grid */ +.Dashboard_Grid { + display: grid; + grid-template-columns: 1fr; + gap: 24px; +} + +.Card { + background: white; + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); + padding: 24px; + margin-bottom: 24px; +} + +.Card_Header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; +} + +.Card_Title { + font-size: 1.15rem; + font-weight: 700; +} + +/* Table Styles */ +.Table_Wrapper { + overflow-x: auto; +} + +table { + width: 100%; + border-collapse: collapse; +} + +th { + text-align: left; + padding: 12px; + border-bottom: 1px solid var(--Border_Color); + color: var(--Text_Secondary); + font-size: 0.85rem; + font-weight: 700; + text-transform: uppercase; +} + +td { + padding: 16px 12px; + border-bottom: 1px solid var(--Border_Color); + font-size: 0.95rem; +} + +.Badge { + padding: 4px 12px; + border-radius: 20px; + font-size: 0.75rem; + font-weight: 700; + text-transform: uppercase; +} + +.Badge_Success { background: #DCFCE7; color: #166534; } +.Badge_Warning { background: #FEF9C3; color: #854D0E; } +.Badge_Danger { background: #FEE2E2; color: #991B1B; } + +/* Accordion / Collapsible */ +.Accordion_Item { + margin-bottom: 16px; + border: 1px solid var(--Border_Color); + border-radius: 12px; + overflow: hidden; + background: white; +} + +.Accordion_Header { + padding: 20px 24px; + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + background: white; + transition: background 0.2s; +} + +.Accordion_Header:hover { + background: #F8FAFC; +} + +.Accordion_Header h3 { + font-size: 1.15rem; + color: var(--Primary_Color); + font-weight: 700; +} + +.Accordion_Icon { + transition: transform 0.3s; + color: var(--Primary_Color); +} + +.Accordion_Content { + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease-out, padding 0.3s; + padding: 0 24px; +} + +.Accordion_Item.Active .Accordion_Content { + max-height: 2000px; /* Large enough to fit content */ + padding: 24px; + border-top: 1px solid var(--Border_Color); +} + +.Accordion_Item.Active .Accordion_Icon { + transform: rotate(180deg); +} + +/* List Items */ +.Data_List { + display: flex; + flex-direction: column; +} + +.Data_Row { + display: flex; + justify-content: space-between; + padding: 12px 0; + border-bottom: 1px solid var(--Border_Color); +} + +.Data_Row:last-child { + border-bottom: none; +} + +.Data_Label { + font-weight: 500; + color: var(--Text_Secondary); +} + +.Data_Value { + font-weight: 600; + color: var(--Text_Primary); +} + +@media (max-width: 1024px) { + .Dashboard_Grid { + grid-template-columns: 1fr; + } +} + @media (max-width: 768px) { - .Landing_Header { - top: 20px; - left: 20px; - } - - .Logo_Pill { - padding: 6px 16px 6px 8px; - } - - .Logo_Circle { - width: 32px; - height: 32px; - } - - .Logo_Title { - font-size: 0.7rem; - } - - .Logo_Subtitle { + .Sidebar { display: none; } - - .Landing_Content { - padding: 30px; + + .Top_Bar { + padding: 0 20px; } - - .Login_Card { - padding: 30px 20px; - max-width: 100%; + + .Search_Box { + display: none; } } -@media (max-width: 480px) { - .Landing_Title { - margin-bottom: 16px; - } +/* Custom Utilities */ +.Text_Muted { color: var(--Text_Secondary); } - .Landing_Description { - margin-bottom: 30px; - } - - .Btn_Landing_Login { - width: 100%; - justify-content: center; - padding: 14px 20px; - } - - .Login_Card .Title_Large { - font-size: 1.5rem; - } -} - -/* Common Utilities */ -.Alert { - padding: 16px; +.Select { + padding: 8px 16px; + border: 1px solid var(--Border_Color); border-radius: 8px; + background: white; + font-family: inherit; font-size: 0.9rem; - margin-bottom: 24px; - font-weight: 500; + color: var(--Text_Primary); + outline: none; } -.Alert_Error { - background-color: #FEF2F2; - color: var(--Error_Color); - border: 1px solid #FEE2E2; -} \ No newline at end of file +/* Breakdown & Summary Cards */ +.Summary_Breakdowns { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 20px; + margin-bottom: 30px; +} + +.Breakdown_Card { + background: white; + border-radius: 12px; + padding: 20px; + border: 1px solid var(--Border_Color); + box-shadow: 0 1px 2px rgba(0,0,0,0.05); +} + +.Breakdown_Title { + font-size: 0.9rem; + font-weight: 700; + color: var(--Primary_Color); + margin-bottom: 15px; + border-bottom: 2px solid var(--Primary_Light); + padding-bottom: 8px; +} + +.Breakdown_Item { + display: flex; + justify-content: space-between; + font-size: 0.85rem; + padding: 8px 0; + border-bottom: 1px solid #f8f9fa; +} + +.Breakdown_Item:last-child { + border-bottom: none; +} + +/* Filter Bar */ +.Filter_Bar { + background: white; + border-radius: 12px; + padding: 24px; + border: 1px solid var(--Border_Color); + display: grid; + grid-template-columns: 2fr repeat(auto-fit, minmax(150px, 1fr)); + gap: 20px; + margin-bottom: 24px; + align-items: flex-end; +} + +.Filter_Group label { + display: block; + font-size: 0.75rem; + font-weight: 700; + text-transform: uppercase; + color: var(--Text_Secondary); + margin-bottom: 8px; +} + +.Search_Input_Wrapper { + position: relative; +} + +.Search_Input_Wrapper i { + position: absolute; + left: 12px; + top: 50%; + transform: translateY(-50%); + color: var(--Text_Secondary); +} + +.Search_Input_Wrapper .Input { + padding-left: 38px; +} + +.Button_Secondary { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 10px 20px; + background: #4F46E5; + color: white; + border: none; + border-radius: 8px; + font-weight: 600; + font-size: 0.9rem; + cursor: pointer; + transition: all 0.2s; +} + +.Button_Secondary:hover { + background: #4338CA; + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(79, 70, 229, 0.2); +} diff --git a/Screens/Election_Dashboard.php b/Screens/Election_Dashboard.php index d48ac82..d34e0f1 100644 --- a/Screens/Election_Dashboard.php +++ b/Screens/Election_Dashboard.php @@ -1,5 +1,7 @@ Check_Auth(); @@ -7,46 +9,159 @@ if ($_SESSION['Access_Level'] < 1) { header('Location: Voting_Screen.php'); exit; } + +// Fetch Stats +$db = db(); +$totalVoters = $db->query("SELECT COUNT(*) FROM Voters")->fetchColumn(); +$totalCandidates = $db->query("SELECT COUNT(*) FROM Candidates")->fetchColumn(); +$totalVotes = $db->query("SELECT COUNT(*) FROM Voters WHERE Has_Voted = 1")->fetchColumn(); + +// Fetch Active Elections +$activeElections = $db->query("SELECT * FROM Election_History WHERE Status = 'Active' ORDER BY Start_Date DESC")->fetchAll(); + ?> - Election Dashboard - Online School Election System - + Election Dashboard | Online School Election System + + - +
+ + -
- Election History - Election Dashboard - Officers - Voters - Audit Trail + +
+ +
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + +
+
+

Election Dashboard

+

Welcome back! Here's what's happening with the current elections.

+
+ + +
+
+
Total Voters
+
+
Registered Students
+
+
+
Total Candidates
+
+
Running for Office
+
+
+
Total Votes Cast
+
+
Verified Ballots
+
+
+ + +
+ +
+
+

Active Elections

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Election TitleStart DateEnd DateStatusActions
+ No active elections found. Create one now. +
School Year ElectionActive + + +
+
+
+
+
+
- -
-

Election Dashboard

-
-
-

Active Election

-

No active election currently running.

- -
-
-

Voter Participation

-
0%
-

0 of 0 voters have cast their ballots.

-
-
-
- + \ No newline at end of file diff --git a/Screens/Election_History.html b/Screens/Election_History.html deleted file mode 100644 index e69de29..0000000 diff --git a/Screens/Election_History.php b/Screens/Election_History.php new file mode 100644 index 0000000..ebb9d39 --- /dev/null +++ b/Screens/Election_History.php @@ -0,0 +1,236 @@ +Check_Auth(); + +if ($_SESSION['Access_Level'] < 1) { + header('Location: Voting_Screen.php'); + exit; +} + +$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. + +?> + + + + + + Election History | Online School Election System + + + + + +
+ + + + +
+ +
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + +
+
+
+

Election History

+

Voter turnout and candidate results per election year

+
+
+ +
+
+ + +
+ +

No Election History Found

+

Completed elections will appear here once they are finalized.

+
+ + $item): ?> +
+
+

School Year

+ +
+
+ +
+
+
Total Voters
+
+
100%
+
+
+
Have Voted
+ +
+
%
+
+
+
Did Not Vote
+ +
+
%
+
+
+ + +
+
+
+

Voters by Track / Strand

+
+
+
+
STEM
+
60
+
+
+
ABM
+
40
+
+
+
HUMSS
+
45
+
+
+
TVL
+
35
+
+
+
+ +
+
+

Voters by Grade Level

+
+
+
+
Grade 11
+
95
+
+
+
Grade 12
+
85
+
+
+
+ +
+
+

Candidate Results

+
+
+ Detailed candidate performance data for this year. +
+
+
+
+
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/Screens/Voters.html b/Screens/Voters.html deleted file mode 100644 index e69de29..0000000 diff --git a/Screens/Voters.php b/Screens/Voters.php new file mode 100644 index 0000000..2ccc66a --- /dev/null +++ b/Screens/Voters.php @@ -0,0 +1,291 @@ +Check_Auth(); + +if ($_SESSION['Access_Level'] < 1) { + header('Location: Voting_Screen.php'); + exit; +} + +$db = db(); + +// Filters +$search = $_GET['search'] ?? ''; +$filterTrack = $_GET['track'] ?? ''; +$filterGrade = $_GET['grade'] ?? ''; +$filterSection = $_GET['section'] ?? ''; + +// Fetch Stats +$totalVoters = $db->query("SELECT COUNT(*) FROM Voters")->fetchColumn(); +$votedCount = $db->query("SELECT COUNT(*) FROM Voters WHERE Has_Voted = 1")->fetchColumn(); +$notVotedCount = $totalVoters - $votedCount; + +// Fetch Breakdowns +$tracks = $db->query("SELECT Track_Cluster as label, COUNT(*) as value FROM Voters GROUP BY Track_Cluster")->fetchAll(); +$grades = $db->query("SELECT Grade_Level as label, COUNT(*) as value FROM Voters GROUP BY Grade_Level")->fetchAll(); +$sections = $db->query("SELECT Section as label, COUNT(*) as value FROM Voters GROUP BY Section")->fetchAll(); + +// Build Query for List +$queryStr = "SELECT * FROM Voters WHERE 1=1"; +$params = []; + +if ($search) { + $queryStr .= " AND Email LIKE ?"; + $params[] = "%$search%"; +} +if ($filterTrack) { + $queryStr .= " AND Track_Cluster = ?"; + $params[] = $filterTrack; +} +if ($filterGrade) { + $queryStr .= " AND Grade_Level = ?"; + $params[] = $filterGrade; +} +if ($filterSection) { + $queryStr .= " AND Section = ?"; + $params[] = $filterSection; +} + +$queryStr .= " ORDER BY Email ASC"; +$stmt = $db->prepare($queryStr); +$stmt->execute($params); +$votersList = $stmt->fetchAll(); + +?> + + + + + + Voter Management | Online School Election System + + + + +
+ + + + +
+ +
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+ +
+
+

Voters List

+

View and manage registered voters

+
+
+
+ + +
+
+
Total Voters
+
+
+
+
Voters Who Voted
+
+
+
+
Voters Who Haven't Voted
+
+
+
+ + +
+
+

Total by Track

+ +
+ + +
+ +
+
+

Total by Grade

+ +
+ Grade + +
+ +
+
+

Total by Section

+ +
+ + +
+ + 5): ?> +
+ more sections
+ +
+
+ + +
+ + +
+ + +
+
+ +
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
EmailTrackGradeSectionStatus
+ No voters found matching your criteria. +
Grade + + Voted + + Pending + +
+
+
+ Showing of voters +
+
+
+
+
+ + \ No newline at end of file diff --git a/assets/pasted-20260204-200921-0cdb8fcc.png b/assets/pasted-20260204-200921-0cdb8fcc.png new file mode 100644 index 0000000..b11ef3e Binary files /dev/null and b/assets/pasted-20260204-200921-0cdb8fcc.png differ diff --git a/assets/pasted-20260204-201746-b63fc6e9.png b/assets/pasted-20260204-201746-b63fc6e9.png new file mode 100644 index 0000000..f0dfc6d Binary files /dev/null and b/assets/pasted-20260204-201746-b63fc6e9.png differ diff --git a/assets/pasted-20260204-202142-e8ddf1bb.png b/assets/pasted-20260204-202142-e8ddf1bb.png new file mode 100644 index 0000000..37a6a21 Binary files /dev/null and b/assets/pasted-20260204-202142-e8ddf1bb.png differ