Appendix _.
Sample Source Code
Admin Dashboard: responsible to displaying Data Analytic Dashboard For monitoring of Scholars and
Grantees Data.
<?php
//admin_dashboard.php
ob_start();
session_start();
// Check login
if (!isset($_SESSION['admin_id'])) {
header('Location: [Link]');
exit;
}
// Database connection
include '[Link]';
// Enrollment status counts
$sql = "
SELECT
COUNT(*) AS total,
SUM(status='enrolled') AS enrolled,
SUM(status='not enrolled') AS notenrolled,
SUM(status='graduated') AS graduated,
SUM(status='dropped') AS dropped
FROM (
SELECT LOWER(TRIM(status)) AS status FROM student
)s
";
$data = $conn->query($sql)->fetch_assoc();
$total = (int)$data['total'];
$enrolled = (int)$data['enrolled'];
$notenrolled = (int)$data['notenrolled'];
$graduated = (int)$data['graduated'];
$dropped = (int)$data['dropped'];
function pct($v, $t)
{
return $t ? round(($v / $t) * 100, 1) : 0;
}
$p_enrolled = pct($enrolled, $total);
$p_notenrolled = pct($notenrolled, $total);
$p_graduated = pct($graduated, $total);
$p_dropped = pct($dropped, $total);
// Scalar analytics
$total_scholars = (int)$conn->query("SELECT COUNT(*) AS c FROM student")->fetch_assoc()['c'];
$total_solo = (int)$conn->query("SELECT COUNT(*) AS c FROM student WHERE soloparent='Yes'")-
>fetch_assoc()['c'];
// Disability types
$disability_types = [
"Learning Disability",
"Speech Impairment",
"Hearing Disability",
"Orthopedic Disability",
"Vision Impairment",
"Visual Disability",
"Chronic Illness",
"Rare Disease",
"Psychosocial Disability",
"Intellectual Disability",
"Physical Disability"
];
$disability_counts = [];
foreach ($disability_types as $t) {
$disability_counts[$t] = (int)$conn->query(
"SELECT COUNT(*) AS c FROM student WHERE physicaldisability='" . $conn-
>real_escape_string($t) . "'"
)->fetch_assoc()['c'];
}
$total_disabled = array_sum($disability_counts);
// IP types
$ip_types = [
"Aeta / Agta",
"Ati",
"Bagobo / Klata",
"Bagobo / Tagabawa",
"Batak (Palawan)",
"Bicolano / Albay",
"Bicolano / Central Bikol",
"Bicolano / Rinconada",
"Bisaya (Cebuano)",
"Blaan (B'laan)",
"Bontoc / Central",
"Bontoc / Guinaang",
"Bugkalot (Ilongot)",
"Bukidnon / Talaandig",
"Cebuano / Boholano",
"Cebuano / Standard",
"Chinese Filipino / Cantonese",
"Chinese Filipino / Hokkien",
"Dibabawon",
"Gaddang",
"Higaonon",
"Hiligaynon (Ilonggo)",
"Ibaloi",
"Ibanag",
"Ifugao / Ayangan",
"Ifugao / Batad",
"Ifugao / Kalanguya",
"Ifugao / Tuwali",
"Igorot",
"Ilocano",
"Isneg (Apayao)",
"Itneg (Tingguian) / Binongan",
"Itneg (Tingguian) / Maeng",
"Ivatan",
"Iwak",
"Kalanguya",
"Kalinga / Balbalan",
"Kalinga / Lubuagan",
"Kalinga / Tabuk",
"Kankanaey / Northern",
"Kankanaey / Southern",
"Kapampangan",
"Maguindanaoan",
"Malay",
"Mandaya",
"Manobo / Agusan",
"Manobo / Ata",
"Manobo / Cotabato",
"Mansaka",
"Maranao (Meranaw)",
"Molbog",
"Palawano",
"Pangasinense (Pangalatok)",
"Sama-Bajau",
"Subanen",
"Tagalog / Batangas",
"Tagalog / Bulacan",
"Tagbanwa",
"Tausug",
"T'boli",
"Waray",
"Yakan",
"Yogad"
];
$ip_counts = [];
foreach ($ip_types as $t) {
$ip_counts[$t] = (int)$conn->query(
"SELECT COUNT(*) AS c FROM student WHERE ip='" . $conn->real_escape_string($t) . "'"
)->fetch_assoc()['c'];
}
$total_ip = array_sum(array_filter(
$ip_counts,
fn($key) => $key !== 'Ilocano',
ARRAY_FILTER_USE_KEY
));
// Chart data
$course_data = $conn->query("SELECT programcourse, COUNT(*) AS count FROM student GROUP BY
programcourse");
$course_labels = [];
$course_counts = [];
while ($r = $course_data->fetch_assoc()) {
$course_labels[] = $r['programcourse'];
$course_counts[] = $r['count'];
}
$town_data = $conn->query("SELECT town, COUNT(*) AS count FROM student GROUP BY town");
$town_labels = [];
$town_counts = [];
while ($r = $town_data->fetch_assoc()) {
$town_labels[] = $r['town'];
$town_counts[] = $r['count'];
}
$scholar_data = $conn->query("SELECT typesofscholar, COUNT(*) AS count FROM student GROUP BY
typesofscholar");
$scholar_labels = [];
$scholar_counts = [];
while ($r = $scholar_data->fetch_assoc()) {
$scholar_labels[] = $r['typesofscholar'];
$scholar_counts[] = $r['count'];
}
?>
<link rel="stylesheet" href="[Link]
[Link]">
<div class="an-wrap">
<!-- Top bar -->
<div class="an-topbar">
<h2>
<span class="an-page-icon">📊</span>
Analytics Dashboard
</h2>
<div style="display:flex; align-items:center; gap:10px; flex-wrap:wrap;">
<a href="admin_tableview.php" class="btn-tableview">
<i class="fa fa-table"></i> Table View
</a>
<div class="export-dropdown">
<button class="btn-export" id="exportToggle">
<i class="fa fa-download"></i> Export Charts
</button>
<div class="export-menu" id="exportMenu">
<div class="export-menu-header">Download as Image</div>
<a onclick="exportChart('courseChart', 'scholars-per-program')">
<i class="fa fa-graduation-cap"></i> Scholars per Program
</a>
<a onclick="exportChart('townChart', 'scholars-per-town')">
<i class="fa fa-map-marker-alt"></i> Scholars per Town
</a>
<a onclick="exportChart('scholarshipnameChart', 'scholars-per-scholarship')">
<i class="fa fa-award"></i> Scholars per Scholarship Type
</a>
<a onclick="exportChart('disabilityChart', 'scholars-by-disability')">
<i class="fa fa-wheelchair"></i> Scholars by Disability
</a>
<div class="export-menu-header" style="margin-top:4px;">Download All</div>
<a onclick="exportAllCharts()">
<i class="fa fa-images"></i> All Charts (ZIP)
</a>
</div>
</div>
</div>
</div>
<!-- 1. Stat cards -->
<div class="stat-grid">
<div class="an-stat sc-blue">
<div class="an-stat-icon"><i class="fa-solid fa-user-graduate"></i></div>
<div>
<p class="an-stat-num count" data-target="<?= $total_scholars ?>">0</p>
<p class="an-stat-lbl">Total Scholars</p>
</div>
</div>
<div class="an-stat sc-purple">
<div class="an-stat-icon"><i class="fa-solid fa-person-breastfeeding"></i></div>
<div>
<p class="an-stat-num count" data-target="<?= $total_solo ?>">0</p>
<p class="an-stat-lbl">Solo Parents</p>
</div>
</div>
<div class="an-stat sc-teal">
<div class="an-stat-icon"><i class="fa-solid fa-leaf"></i></div>
<div>
<p class="an-stat-num count" data-target="<?= $total_ip ?>">0</p>
<p class="an-stat-lbl">Indigenous (IP)</p>
</div>
</div>
<div class="an-stat sc-orange">
<div class="an-stat-icon"><i class="fa-solid fa-wheelchair"></i></div>
<div>
<p class="an-stat-num count" data-target="<?= $total_disabled ?>">0</p>
<p class="an-stat-lbl">With Disability</p>
</div>
</div>
</div>
<!-- 2. Program/Course -->
<div class="an-card">
<div class="an-card-header">
<div class="an-card-title">
<i class="fa fa-graduation-cap"></i>
Scholars per program / course
</div>
<span class="an-card-badge"><?= count($course_labels) ?> programs</span>
</div>
<div class="an-card-body">
<div class="chart-canvas-wrap">
<canvas id="courseChart"></canvas>
</div>
</div>
</div>
<!-- 3. Enrollment bars + Town doughnut -->
<div class="chart-pair">
<div class="an-card">
<div class="an-card-header">
<div class="an-card-title">
<i class="fa fa-chart-bar"></i>
Scholar enrollment monitoring analytics
</div>
<span class="total-badge"><strong><?= number_format($total) ?></strong> total</span>
</div>
<div class="enroll-bars">
<?php
$bars = [
['Enrolled', $enrolled, $p_enrolled, 'enrolled', 'ef-enrolled'],
['Not Enrolled', $notenrolled, $p_notenrolled, 'notenrolled', 'ef-notenrolled'],
['Graduated', $graduated, $p_graduated, 'graduated', 'ef-graduated'],
['Dropped', $dropped, $p_dropped, 'dropped', 'ef-dropped'],
];
foreach ($bars as [$lbl, $cnt, $pct_val, $chip, $fill]):
?>
<div class="enroll-row">
<div class="enroll-meta">
<span>
<span class="enroll-chip chip-<?= $chip ?>"><?= $lbl ?></span>
<?= number_format($cnt) ?> scholars
</span>
<span class="pct"><?= $pct_val ?>%</span>
</div>
<div class="enroll-track">
<div class="enroll-fill <?= $fill ?>" data-width="<?= $pct_val ?>"></div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="an-card">
<div class="an-card-header">
<div class="an-card-title">
<i class="fa fa-map-marker-alt"></i>
Scholars per town
</div>
<span class="an-card-badge"><?= count($town_labels) ?> towns</span>
</div>
<div class="an-card-body">
<div class="chart-canvas-wrap">
<canvas id="townChart"></canvas>
</div>
</div>
</div>
</div>
<!-- 4. Scholarship type -->
<div class="an-card">
<div class="an-card-header">
<div class="an-card-title">
<i class="fa fa-award"></i>
Scholars per scholarship type
</div>
<span class="an-card-badge"><?= count($scholar_labels) ?> types</span>
</div>
<div class="an-card-body">
<div class="chart-canvas-wrap" style="min-height:320px;">
<canvas id="scholarshipnameChart"></canvas>
</div>
</div>
</div>
<!-- 5. Disability type -->
<div class="an-card">
<div class="an-card-header">
<div class="an-card-title">
<i class="fa fa-wheelchair"></i>
Scholars by disability type
</div>
<span class="total-badge"><strong><?= number_format($total_disabled) ?></strong> with
disability</span>
</div>
<div class="an-card-body">
<div class="chart-canvas-wrap" style="min-height:320px;">
<canvas id="disabilityChart"></canvas>
</div>
</div>
</div>
</div><!-- /an-wrap -->
<script src="[Link]
<script src="[Link]
<script>
[Link]("DOMContentLoaded", () => {
/* Counter animation */
[Link]('.count').forEach(el => {
const target = +[Link];
let n = 0;
const step = [Link](target / 40) || 1;
const tick = () => {
n = [Link](n + step, target);
[Link] = [Link]();
if (n < target) setTimeout(tick, 30);
};
tick();
});
/* Progress bar animation */
setTimeout(() => {
[Link]('.enroll-fill').forEach(el => {
[Link] = [Link] + '%';
});
}, 250);
/* Gradient helper */
function grad(ctx, c1, c2, horiz) {
const w = [Link] || 400;
const h = [Link] || 400;
const g = horiz ?
[Link](0, 0, w, 0) :
[Link](0, 0, 0, h);
[Link](0, c1);
[Link](1, c2);
return g;
}
/* Shared Y-axis title config */
const yAxisTitle = {
display: true,
text: 'No. of Scholars',
font: {
size: 12,
weight: '600'
},
color: '#64748b',
padding: {
bottom: 8
}
};
[Link] = "'Segoe UI', system-ui, sans-serif";
[Link] = '#64748b';
/* Register datalabels globally (needed for doughnut) */
[Link](ChartDataLabels);
/* ── 1. Program/Course — area line ── */
const courseCtx = [Link]('courseChart').getContext('2d');
new Chart(courseCtx, {
type: 'line',
data: {
labels: <?= json_encode($course_labels) ?>,
datasets: [{
label: 'Scholars',
data: <?= json_encode($course_counts) ?>,
backgroundColor: grad(courseCtx, 'rgba(58,123,213,.35)', 'rgba(0,210,255,.05)'),
borderColor: '#3a7bd5',
borderWidth: 2.5,
pointBackgroundColor: '#3a7bd5',
pointRadius: 4,
fill: true,
tension: 0.45
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
// Inside courseChart [Link]:
datalabels: {
color: '#3a7bd5',
anchor: 'end',
align: 'top',
offset: 4,
font: {
weight: '600',
size: 11
},
formatter: v => v,
display: function(ctx) {
return [Link][[Link]] > 0;
},
backgroundColor: 'rgba(255,255,255,0.75)',
borderRadius: 4,
padding: {
top: 2,
bottom: 2,
left: 5,
right: 5
}
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: '#f1f5f9'
},
title: yAxisTitle
},
x: {
grid: {
display: false
}
}
}
}
});
/* ── 2. Town — doughnut ── */
const townCtx = [Link]('townChart').getContext('2d');
const palette = [
'#3b82f6', '#8b5cf6', '#22c55e', '#f97316', '#06b6d4',
'#e11d48', '#eab308', '#f472b6', '#10b981', '#f59e0b',
'#6366f1', '#a78bfa', '#f87171', '#22d3ee', '#34d399'
];
const townTotal = <?= array_sum($town_counts) ?>;
new Chart(townCtx, {
type: 'doughnut',
data: {
labels: <?= json_encode($town_labels) ?>,
datasets: [{
data: <?= json_encode($town_counts) ?>,
backgroundColor: palette,
borderWidth: 2,
borderColor: '#fff',
hoverOffset: 12
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
cutout: '50%',
layout: {
padding: 10
},
plugins: {
legend: {
position: 'right',
labels: {
usePointStyle: true,
pointStyle: 'circle',
font: {
size: 11
},
generateLabels: function(chart) {
const data = [Link];
const meta = [Link](0);
return [Link]((label, i) => {
const value = [Link][0].data[i];
const hidden = [Link][i] ? [Link][i].hidden : false;
const pct = townTotal ? ((value / townTotal) * 100).toFixed(1) : 0;
return {
text: `${label} — ${value} (${pct}%)`,
fillStyle: [Link][0].backgroundColor[i],
strokeStyle: [Link][0].backgroundColor[i],
hidden: hidden,
index: i,
pointStyle: 'circle',
fontColor: hidden ? '#aaa' : '#64748b'
};
});
}
},
onClick: function(e, item, legend) {
const meta = [Link](0);
[Link][[Link]].hidden = ![Link][[Link]].hidden;
[Link]();
}
},
datalabels: {
display: function(ctx) {
const value = [Link][[Link]];
const pct = townTotal ? (value / townTotal) * 100 : 0;
return pct >= 5;
},
color: '#ffffff',
textStrokeColor: 'rgba(0,0,0,0.6)',
textStrokeWidth: 4,
font: {
weight: '700',
size: 12
},
anchor: 'center',
align: 'center',
offset: 0,
formatter: function(value) {
const pct = townTotal ? (value / townTotal) * 100 : 0;
return [Link](1) + '%';
}
},
tooltip: {
backgroundColor: '#1e293b',
padding: 10,
cornerRadius: 10,
callbacks: {
label: function(t) {
const pct = townTotal ? (([Link] / townTotal) * 100).toFixed(1) : 0;
return ` ${[Link]}: ${[Link]} scholars (${pct}%)`;
}
}
}
}
}
});
/* ── 3. Scholarship type — vertical bar ── */
const scholarCtx = [Link]('scholarshipnameChart').getContext('2d');
new Chart(scholarCtx, {
type: 'bar',
data: {
labels: <?= json_encode($scholar_labels) ?>,
datasets: [{
label: 'Scholars',
data: <?= json_encode($scholar_counts) ?>,
backgroundColor: grad(scholarCtx, '#3a7bd5', '#00d2ff'),
borderRadius: 7,
barPercentage: 0.6
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
// AFTER — in both bar charts
datalabels: {
color: '#3a7bd5',
anchor: 'end',
align: 'top',
offset: 4,
font: {
weight: '600',
size: 11
},
formatter: v => v,
display: function(ctx) {
return [Link][[Link]] > 0;
}
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: '#f1f5f9'
},
title: yAxisTitle
},
x: {
grid: {
display: false
}
}
}
}
});
/* ── 4. Disability — vertical bar ── */
const disCtx = [Link]('disabilityChart').getContext('2d');
new Chart(disCtx, {
type: 'bar',
data: {
labels: <?= json_encode(array_keys($disability_counts)) ?>,
datasets: [{
label: 'Scholars',
data: <?= json_encode(array_values($disability_counts)) ?>,
backgroundColor: grad(disCtx, '#d5613a', '#ff8000'),
borderRadius: 7,
barPercentage: 0.6
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
datalabels: {
color: '#fff',
anchor: 'end',
align: 'start',
font: {
weight: '600',
size: 11
},
formatter: v => v
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: '#f1f5f9'
},
title: yAxisTitle
},
x: {
grid: {
display: false
}
}
}
}
});
});
/* ── Export charts ── */
[Link]('exportToggle').addEventListener('click', function(e) {
[Link]();
[Link]('exportMenu').[Link]('open');
});
[Link]('click', function() {
[Link]('exportMenu').[Link]('open');
});
function exportChart(canvasId, filename) {
const canvas = [Link](canvasId);
const exportCanvas = [Link]('canvas');
[Link] = [Link];
[Link] = [Link];
const ctx = [Link]('2d');
[Link] = '#ffffff';
[Link](0, 0, [Link], [Link]);
[Link](canvas, 0, 0);
const link = [Link]('a');
[Link] = filename + '.png';
[Link] = [Link]('image/png');
[Link]();
[Link]('exportMenu').[Link]('open');
}
function exportAllCharts() {
const charts = [{
id: 'courseChart',
name: 'scholars-per-program'
},
{
id: 'townChart',
name: 'scholars-per-town'
},
{
id: 'scholarshipnameChart',
name: 'scholars-per-scholarship'
},
{
id: 'disabilityChart',
name: 'scholars-by-disability'
},
];
[Link]((c, i) => {
setTimeout(() => exportChart([Link], [Link]), i * 300);
});
[Link]('exportMenu').[Link]('open');
}
</script>
<?php
$conn->close();
$content = ob_get_clean();
include 'admin_layout.php';
?>