fix homepage and admin dashboard

This commit is contained in:
root
2026-02-27 17:15:40 -05:00
parent 253be573ac
commit 6d543c52cc
5 changed files with 198 additions and 31 deletions
@@ -416,8 +416,10 @@ class AdministratorController extends BaseController
$totalStudents = (int) ( $totalStudents = (int) (
$this->db->table('student_class') $this->db->table('student_class')
->select('COUNT(DISTINCT student_class.student_id) AS cnt') ->select('COUNT(DISTINCT student_class.student_id) AS cnt')
->join('students', 'students.id = student_class.student_id', 'inner')
->where('student_class.school_year', $this->schoolYear) ->where('student_class.school_year', $this->schoolYear)
->where('student_class.class_section_id IS NOT NULL', null, false) ->where('student_class.class_section_id IS NOT NULL', null, false)
->where('students.is_active', 1)
->get() ->get()
->getRow('cnt') ->getRow('cnt')
?? 0 ?? 0
@@ -517,37 +517,28 @@
<section class="mb-5"> <section class="mb-5">
<h2 class="mb-4 text-center">Statistics</h2> <h2 class="mb-4 text-center">Statistics</h2>
<div class="stats-row"> <div class="stats-row">
<!-- Students -->
<div class="stat-circle circle-primary"> <div class="stat-circle circle-primary">
<div class="stat-icon"><i class="bi bi-people-fill"></i></div> <div class="stat-icon"><i class="fas fa-user-graduate"></i></div>
<div class="stat-value" data-stat="students">—</div> <div class="stat-value" data-stat="students">—</div>
<div class="stat-title">Students</div> <div class="stat-title">Students</div>
</div> </div>
<!-- Teachers -->
<div class="stat-circle circle-info"> <div class="stat-circle circle-info">
<div class="stat-icon"><i class="bi bi-person-video2"></i></div> <div class="stat-icon"><i class="fas fa-chalkboard-teacher"></i></div>
<div class="stat-value" data-stat="teachers">—</div> <div class="stat-value" data-stat="teachers">—</div>
<div class="stat-title">Teachers</div> <div class="stat-title">Teachers</div>
</div> </div>
<!-- Teacher Assistants -->
<div class="stat-circle circle-success"> <div class="stat-circle circle-success">
<div class="stat-icon"><i class="bi bi-person-badge-fill"></i></div> <div class="stat-icon"><i class="fas fa-user-cog"></i></div>
<div class="stat-value" data-stat="teacherAssistants">—</div> <div class="stat-value" data-stat="teacherAssistants">—</div>
<div class="stat-title">Teachers' Assistants</div> <div class="stat-title">TAs</div>
</div> </div>
<!-- Admins -->
<div class="stat-circle circle-warning"> <div class="stat-circle circle-warning">
<div class="stat-icon"><i class="bi bi-shield-lock-fill"></i></div> <div class="stat-icon"><i class="fas fa-user-shield"></i></div>
<div class="stat-value" data-stat="admins">—</div> <div class="stat-value" data-stat="admins">—</div>
<div class="stat-title">Admins</div> <div class="stat-title">Admins</div>
</div> </div>
<!-- Parents -->
<div class="stat-circle circle-light"> <div class="stat-circle circle-light">
<div class="stat-icon"><i class="bi bi-people"></i></div> <div class="stat-icon"><i class="fas fa-users"></i></div>
<div class="stat-value" data-stat="parents">—</div> <div class="stat-value" data-stat="parents">—</div>
<div class="stat-title">Parents</div> <div class="stat-title">Parents</div>
</div> </div>
@@ -71,9 +71,20 @@
max-height: none; max-height: none;
overflow: visible; overflow: visible;
} }
.attn-pie-wrap {
width: 320px;
height: 320px;
margin: 0 auto;
}
@media (max-width: 1200px) { @media (max-width: 1200px) {
.attn-analysis-half { grid-column: span 12; } .attn-analysis-half { grid-column: span 12; }
} }
@media (max-width: 576px) {
.attn-pie-wrap {
width: 180px;
height: 180px;
}
}
</style> </style>
<?= $this->endSection() ?> <?= $this->endSection() ?>
@@ -291,7 +302,9 @@
<div class="attn-analysis-grid"> <div class="attn-analysis-grid">
<div class="attn-analysis-card attn-analysis-half"> <div class="attn-analysis-card attn-analysis-half">
<h6>Overall Distribution</h6> <h6>Overall Distribution</h6>
<canvas id="attnPieChart" height="50" aria-label="Overall attendance pie chart"></canvas> <div class="attn-pie-wrap">
<canvas id="attnPieChart" aria-label="Overall attendance pie chart"></canvas>
</div>
<table class="attn-analysis-table mt-3 no-mgmt-sticky" data-no-mgmt-sticky> <table class="attn-analysis-table mt-3 no-mgmt-sticky" data-no-mgmt-sticky>
<thead> <thead>
<tr> <tr>
@@ -415,6 +428,8 @@
}] }]
}, },
options: { options: {
responsive: true,
maintainAspectRatio: false,
plugins: { plugins: {
tooltip: { tooltip: {
callbacks: { callbacks: {
+161 -2
View File
@@ -322,6 +322,72 @@
min-height: 400px; min-height: 400px;
} }
.home-stats {
background: #ffffff;
border-radius: 16px;
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.08);
padding: 2.5rem 1.5rem;
}
.home-stats .stats-row {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
justify-content: center;
}
.home-stats .stat-circle {
width: 190px;
height: 190px;
border-radius: 50%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #ffffff;
font-weight: 700;
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.12);
}
.home-stats .stat-value {
font-size: 1.8rem;
line-height: 1;
}
.home-stats .stat-icon {
font-size: 2rem;
margin-bottom: .2rem;
opacity: .9;
}
.home-stats .stat-title {
font-size: 1.1rem;
margin-top: .25rem;
font-weight: 500;
text-align: center;
line-height: 1.2;
}
.home-stats .circle-primary {
background: radial-gradient(circle at 30% 30%, #0d6efd, #0044aa);
}
.home-stats .circle-success {
background: radial-gradient(circle at 30% 30%, #198754, #0c4f2c);
}
.home-stats .circle-warning {
background: radial-gradient(circle at 30% 30%, #daa544ff, #a66f00);
}
.home-stats .circle-info {
background: radial-gradient(circle at 30% 30%, #0dcaf0, #047e9c);
}
.home-stats .circle-light {
background: radial-gradient(circle at 30% 30%, #63af4cff, #00eb7dff);
}
@media (max-width: 992px) { @media (max-width: 992px) {
.image-column { .image-column {
min-height: 300px; min-height: 300px;
@@ -332,6 +398,13 @@
border-radius: 0 0 10px 10px !important; border-radius: 0 0 10px 10px !important;
} }
} }
@media (max-width: 768px) {
.home-stats .stat-circle {
width: 160px;
height: 160px;
}
}
</style> </style>
</head> </head>
@@ -448,8 +521,43 @@
<h4 class="fw-bold my-0"><u>Join Al Rahma family today! Click here for a quick guide on how to create an account.</u></h4> <h4 class="fw-bold my-0"><u>Join Al Rahma family today! Click here for a quick guide on how to create an account.</u></h4>
</a> </a>
</section> </section>
<!-- Statistics Start -->
<div class="container-xxl py-2 content-section">
<div class="container">
<div class="home-stats" data-dashboard-endpoint="<?= site_url('api/administrator/dashboard') ?>">
<h1 class="d-flex justify-content-center p-md-1">Active Participants</h1>
<br>
<div class="stats-row">
<div class="stat-circle circle-primary">
<div class="stat-icon"><i class="fa-solid fa-user-graduate"></i></div>
<div class="stat-value" data-stat="students">—</div>
<div class="stat-title">Students</div>
</div>
<div class="stat-circle circle-info">
<div class="stat-icon"><i class="fa-solid fa-chalkboard-user"></i></div>
<div class="stat-value" data-stat="teachers">—</div>
<div class="stat-title">Teachers</div>
</div>
<div class="stat-circle circle-success">
<div class="stat-icon"><i class="fa-solid fa-user-gear"></i></div>
<div class="stat-value" data-stat="teacherAssistants">—</div>
<div class="stat-title">TAs</div>
</div>
<div class="stat-circle circle-warning">
<div class="stat-icon"><i class="fa-solid fa-user-shield"></i></div>
<div class="stat-value" data-stat="admins">—</div>
<div class="stat-title">Admins</div>
</div>
<div class="stat-circle circle-light">
<div class="stat-icon"><i class="fa-solid fa-people-group"></i></div>
<div class="stat-value" data-stat="parents">—</div>
<div class="stat-title">Parents</div>
</div>
</div>
</div>
</div>
</div>
<!-- Statistics End -->
<div class="container-xxl py-2 content-section"> <div class="container-xxl py-2 content-section">
<div class="container"> <div class="container">
<div class="row bg-light squared align-items-center"> <div class="row bg-light squared align-items-center">
@@ -677,6 +785,57 @@
} }
}); });
</script> </script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const container = document.querySelector('.home-stats[data-dashboard-endpoint]');
if (!container) return;
const endpoint = container.dataset.dashboardEndpoint;
const statElements = container.querySelectorAll('[data-stat]');
const numberFormatter = new Intl.NumberFormat();
let isLoading = false;
const loadStats = function() {
if (isLoading) return;
isLoading = true;
fetch(endpoint, {
headers: {
'Accept': 'application/json'
},
credentials: 'same-origin',
})
.then(function(response) {
if (!response.ok) {
throw new Error('Request failed');
}
return response.json();
})
.then(function(payload) {
const counts = payload && typeof payload === 'object' && payload.counts ?
payload.counts :
{};
statElements.forEach(function(element) {
const key = element.dataset.stat;
const value = counts[key];
element.textContent = Number.isFinite(value) ?
numberFormatter.format(value) :
'—';
});
})
.catch(function() {})
.finally(function() {
isLoading = false;
});
};
loadStats();
setInterval(loadStats, 60000);
document.addEventListener('visibilitychange', function() {
if (document.visibilityState === 'visible') {
loadStats();
}
});
});
</script>
</body> </body>
</html> </html>
File diff suppressed because one or more lines are too long