penjadwalan-ga/resources/views/admin/pages/dashboard.blade.php

454 lines
18 KiB
PHP

@extends('admin.layouts.app')
@section('title', 'Dashboard')
@push('style')
<style>
#edit .modal-dialog{
max-width: 800px!important;
}
.total .box{
padding-block: 10px;
padding-inline: 30px;
}
.total .box .media{
display: flex;
align-items: center;
}
.total .box .icon{
width: 50px;
height: 50px;
border-radius: 8px;
}
.card.border-radius-cus{
border-radius: 8px;
}
p.dash-title{
padding-bottom: 5px;
margin-bottom: 14px!important;
border-bottom: 1.5px dashed #c9c9c9;
color: #6c757d;
font-weight: 500!important;
}
.dash-counts .card{
border-radius: 8px;
padding: 10px;
border: 1.8px solid transparent ;
transition: .3s all ease-in-out;
}
.dash-counts .card:hover{
border: 1.8px solid #f74eb3 ;
}
.dash-counts .card:hover .detail-btn p,
.dash-counts .card:hover .detail-btn i {
color: #f74eb3;
}
.dash-counts .dash-count-item{
display: flex;
gap: 10px;
padding-bottom: 10px;
margin-bottom: 5px;
border-bottom: 1.5px dashed #c9c9c9;
}
.dash-counts .dash-count-item .icon{
width: 50px;
height: 50px;
display: flex;
border-radius: 6px;
justify-content: center;
align-items: center;
}
.icon.bg-blue{
background: linear-gradient(190deg, #3685C8, #78a5ce);
}
.icon.bg-purple{
background: linear-gradient(190deg, #6736c8, #9d84da);
}
.icon.bg-green{
background: linear-gradient(190deg, #6ad56a, #b2e0b2);
}
.icon.bg-orange{
background: linear-gradient(190deg, #EB9557, #eeb183);
}
.icon.bg-pink{
background: linear-gradient(190deg, #EF7272, #f5a4a4);
}
.icon.bg-yellow{
background: linear-gradient(190deg, #FDB827, #f6dc9d);
}
.icon.bg-brown{
background: linear-gradient(190deg, #23120B, #3A1E13);
}
.dash-counts .dash-count-item i{
font-size: 24px;
color: #fff;
}
.dash-counts .dash-count-item h5{
font-weight: 700!important;
color: #000;
}
.dash-counts .detail-btn{
color: #6c757d;
transition: .3s;
cursor: pointer;
}
.notif-box {
display: flex;
align-items: center;
gap: 10px;
border: 1.5px solid rgba(189, 189, 189, 0.36);
padding: 8px;
border-radius: 6px;
position: relative;
margin-bottom: 6px;
}
.notif-box:hover{
border-color: #EF7272;
}
.notif-box:hover .notif-close-btn{
right: -20px;
visibility: visible;
}
.notif-box p{
line-height: 15px;
}
.notif-box .notif-icon{
width: 35px;
height: 35px;
display: flex;
border-radius: 6px;
justify-content: center;
align-items: center;
color: #fff;
}
.notif-box .notif-close-btn{
cursor: pointer;
transition: .3s;
visibility: hidden;
position: absolute;
top: 50%;
right: 0;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 3px;
color: #fff;
font-size: 12px;
background: linear-gradient(190deg, #EF7272, #f5a4a4);
}
.notif-box .notif-link{
width: 100%;
height: 100%;
position: absolute;
left: 0;
}
#notif1::before,
#notif2::before,
#notif3::before{
content: 'Klik untuk melihat detail';
position: absolute;
top: 0;
right: 0;
background-color: #e5e5e5;
color: #535353;
font-size: .85em;
font-weight: 500;
padding: 0 5px;
border-radius: 4px;
opacity: 0;
transition: .3s;
}
#notif1:hover::before,
#notif2:hover::before,
#notif3:hover::before{
opacity: 1;
top: -50%;
}
</style>
@endpush
@section('main')
<div class="main-content">
<section class="section">
<div class="section-header" style="display: flex; justify-content: space-between; align-items: center">
<h1>Dashboard</h1>
<span class="time">Time</span>
</div>
<div class="section-body">
<div class="row dash-counts px-2">
<div class="col-lg-6 col-xl-4 col-xxl-4 px-2 py-2">
<div class="card m-0">
<div class="dash-count-item">
<div class="box">
<div class="icon bg-blue">
<i class="bx bx-group"></i>
</div>
</div>
<div class="box">
<h5 class="m-0 counter" data-target="{{ $totalSiswaAktif ?? 0 }}" id="count-siswa-aktif">-</h5>
<p class="m-0 text-muted" style="font-size: .9em">Siswa Aktif</p>
</div>
</div>
<div class="detail-btn d-flex align-items-center justify-content-between" id="detail-siswa-aktif">
<p class="m-0">Lihat detail</p>
<i class='bx bx-right-arrow-alt' ></i>
</div>
</div>
</div>
<div class="col-lg-6 col-xl-4 col-xxl-4 px-2 py-2">
<div class="card m-0">
<div class="dash-count-item">
<div class="box">
<div class="icon bg-green">
<i class='bx bx-book-open'></i>
</div>
</div>
<div class="box">
<h5 class="m-0 counter" data-target="{{ $totalKelas ?? 0 }}" id="count-kelas">-</h5>
<p class="m-0 text-muted" style="font-size: .9em">Jumlah Kelas Semester Ini</p>
</div>
</div>
<div class="detail-btn d-flex align-items-center justify-content-between" id="detail-kelas">
<p class="m-0">Lihat detail</p>
<i class='bx bx-right-arrow-alt' ></i>
</div>
</div>
</div>
<div class="col-lg-4 col-xl-4 col-xxl-4 px-2 py-2">
<div class="card m-0">
<div class="dash-count-item">
<div class="box">
<div class="icon bg-orange">
<i class='bx bx-user-voice'></i>
</div>
</div>
<div class="box">
<h5 class="m-0 counter" data-target="{{ $totalGuru ?? 0 }}" id="count-guru">-</h5>
<p class="m-0 text-muted" style="font-size: .9em">Jumlah Guru Aktif</p>
</div>
</div>
<div class="detail-btn d-flex align-items-center justify-content-between" id="detail-guru">
<p class="m-0">Lihat detail</p>
<i class='bx bx-right-arrow-alt' ></i>
</div>
</div>
</div>
<div class="col-lg-4 col-xl-4 col-xxl-4 px-2 py-2">
<div class="card m-0">
<div class="dash-count-item">
<div class="box">
<div class="icon bg-purple">
<i class='bx bx-building-house'></i>
</div>
</div>
<div class="box">
<h5 class="m-0 counter" data-target="{{ $totalRuangan ?? 0 }}" id="count-ruangan">-</h5>
<p class="m-0 text-muted" style="font-size: .9em">Jumlah Ruangan Tersedia</p>
</div>
</div>
<div class="detail-btn d-flex align-items-center justify-content-between" id="detail-ruangan">
<p class="m-0">Lihat detail</p>
<i class='bx bx-right-arrow-alt' ></i>
</div>
</div>
</div>
<div class="col-lg-4 col-xl-4 col-xxl-4 px-2 py-2">
<div class="card m-0">
<div class="dash-count-item">
<div class="box">
<div class="icon bg-yellow">
<i class='bx bx-time-five'></i>
</div>
</div>
<div class="box">
<h5 class="m-0 counter" data-target="{{ $totalSesi ?? 0 }}" id="count-sesi">-</h5>
<p class="m-0 text-muted" style="font-size: .9em">Jumlah Sesi</p>
</div>
</div>
<div class="detail-btn d-flex align-items-center justify-content-between" id="detail-sesi">
<p class="m-0">Lihat detail</p>
<i class='bx bx-right-arrow-alt' ></i>
</div>
</div>
</div>
<!-- Card Notification GA (Disamping Jumlah Sesi) -->
<div class="col-lg-4 col-xl-4 col-xxl-4 px-2 py-2" id="ga-notif-box">
@if(isset($gaResult) && $gaResult)
<div class="card m-0">
<div class="dash-count-item">
<div class="box">
<div class="icon bg-pink">
<i class='bx bx-git-repo-forked'></i>
</div>
</div>
<div class="box">
<h5 class="m-0" style="font-weight: 700!important; color: #000; font-size: 1.05rem;">Hasil Generate GA</h5>
<p class="m-0 text-muted" style="font-size: .85em">
Fitness: {{ isset($gaResult['bestChromosome']) ? number_format($gaResult['bestChromosome']->fitness, 4) : '1.0000' }} | {{ $gaResult['executionTime'] ?? '0.00' }}s
</p>
</div>
</div>
<div class="detail-btn d-flex align-items-center justify-content-between" id="detail-ga-result">
<p class="m-0">Lihat hasil GA Terbaru</p>
<i class='bx bx-right-arrow-alt'></i>
</div>
</div>
@endif
</div>
</div>
</div>
</section>
</div>
@endsection
@push('scripts')
<script>
// Fungsi animasi counter untuk statistik atas
function animateCounter(element, start, end, duration) {
let startTimestamp = null;
const step = (timestamp) => {
if (!startTimestamp) startTimestamp = timestamp;
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
const currentCount = Math.floor(progress * (end - start) + start);
element.textContent = currentCount;
if (progress < 1) {
window.requestAnimationFrame(step);
} else {
element.textContent = end;
}
};
window.requestAnimationFrame(step);
}
function runCounter(){
const counters = document.querySelectorAll('.counter');
counters.forEach(counter => {
const target = parseInt(counter.getAttribute('data-target')) || 0;
animateCounter(counter, 0, target, 1500);
});
}
function fetchDashboardCounts() {
$.ajax({
url: "{{ url('/admin/dashboard-data') }}",
type: 'GET',
dataType: 'json',
success: function(data) {
$('#count-siswa-aktif').attr('data-target', data.total_siswa_aktif);
$('#count-sesi').attr('data-target', data.total_sesi);
$('#count-kelas').attr('data-target', data.total_kelas);
$('#count-guru').attr('data-target', data.total_guru);
$('#count-ruangan').attr('data-target', data.total_ruangan);
runCounter();
if (data.ga_result) {
var html = `
<div class="card m-0">
<div class="dash-count-item">
<div class="box">
<div class="icon bg-pink">
<i class='bx bx-git-repo-forked'></i>
</div>
</div>
<div class="box">
<h5 class="m-0" style="font-weight: 700!important; color: #000; font-size: 1.05rem;">Hasil Generate GA</h5>
<p class="m-0 text-muted" style="font-size: .85em">
Fitness: ${data.ga_result.fitness} | ${data.ga_result.executionTime}s
</p>
</div>
</div>
<div class="detail-btn d-flex align-items-center justify-content-between" id="detail-ga-result">
<p class="m-0">Lihat hasil GA Terbaru</p>
<i class='bx bx-right-arrow-alt'></i>
</div>
</div>
`;
$('#ga-notif-box').html(html);
$('#detail-ga-result').click(function(){
window.location.href = '{{ url('/admin/hasil-ga') }}';
});
} else {
$('#ga-notif-box').empty();
}
},
error: function(xhr, status, error) {
console.error("Error fetching dashboard data:", error);
}
});
}
fetchDashboardCounts();
$('#detail-siswa-aktif').click(function(){
window.location.href = '{{ url('/admin/siswa') }}';
});
$('#detail-sesi').click(function(){
window.location.href = '{{ url('/admin/jadwal') }}';
});
$('#detail-kelas').click(function(){
window.location.href = '{{ url('/admin/kelas') }}';
});
$('#detail-guru').click(function(){
window.location.href = '{{ url('/admin/guru') }}';
});
$('#detail-ruangan').click(function(){
window.location.href = '{{ url('/admin/ruangan') }}';
});
$(document).on('click', '#detail-ga-result', function(){
window.location.href = '{{ url('/admin/hasil-ga') }}';
});
</script>
<script>
function getWaktuJakarta() {
const now = new Date();
const options = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
timeZone: 'Asia/Jakarta'
};
const tanggal = now.toLocaleDateString('id-ID', options);
const jam = now.toLocaleTimeString('id-ID', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
timeZone: 'Asia/Jakarta'
}).replace(/:/g, '.');
return `${tanggal} ${jam} WIB`;
}
document.querySelector('.time').innerHTML = getWaktuJakarta();
setInterval(() => {
document.querySelector('.time').innerHTML = getWaktuJakarta();
}, 1000);
</script>
<!-- Page Specific JS File -->
@endpush