initial commit

This commit is contained in:
Randa Firman Putra
2025-09-08 22:47:42 +07:00
parent eaaf9f6436
commit a5f2a1f069
5 changed files with 231 additions and 21 deletions

View File

@@ -1,6 +1,6 @@
'use client';
import { useState } from "react";
import { useState, useEffect } from "react";
import StatistikMahasiswaChart from "@/components/charts/StatistikMahasiswaChart";
import StatistikPerAngkatanChart from "@/components/charts/StatistikPerAngkatanChart";
import JenisPendaftaranChart from "@/components/charts/JenisPendaftaranChart";
@@ -23,9 +23,76 @@ import ProvinsiMahasiswaChart from "@/components/chartsDashboard/ProvinsiMahasis
import TingkatPrestasiPieChartDash from "@/components/chartsDashboard/TingkatPrestasiPieChartDash";
import LulusTepatWaktuChart from "@/components/charts/LulusTepatWaktuChart";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { ChevronDown, Navigation, ArrowUp } from "lucide-react";
export default function TotalMahasiswaPage() {
const [selectedYear, setSelectedYear] = useState<string>("all");
const [dropdownOpen, setDropdownOpen] = useState(false);
const [showBackToTop, setShowBackToTop] = useState(false);
// Handle scroll event to show/hide back to top button
useEffect(() => {
const handleScroll = () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
setShowBackToTop(scrollTop > 300); // Show button after scrolling 300px
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// Function to scroll to top smoothly
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
};
// Function to scroll to section smoothly
const scrollToSection = (sectionId: string) => {
// Close dropdown first
setDropdownOpen(false);
// Use requestAnimationFrame to ensure smooth operation
requestAnimationFrame(() => {
setTimeout(() => {
const element = document.getElementById(sectionId);
if (element) {
element.scrollIntoView({
behavior: 'smooth',
block: 'start',
inline: 'nearest'
});
}
}, 100);
});
};
// Navigation menu items for all data
const allDataNavItems = [
{ id: 'overview', label: 'Jumlah & Status Mahasiswa' },
{ id: 'academic', label: 'IPK & Jenis Pendaftaran' },
{ id: 'study-duration', label: 'Kelulusan Tepat Waktu & Masa Studi' },
{ id: 'expertise', label: 'Kelompok Keahlian' },
{ id: 'scholarship', label: 'Beasiswa & Prestasi' },
{ id: 'demographics', label: 'Asal Kabupaten & Provinsi' }
];
// Navigation menu items for per year data
const perYearNavItems = [
{ id: 'overview-year', label: 'Jumlah & Status per Angkatan' },
{ id: 'status-year', label: 'Jenis Pendaftaran & Kelompok Keahlian' },
{ id: 'achievement-year', label: 'Beasiswa & Prestasi per Angkatan' },
{ id: 'demographics-year', label: 'Asal Kabupaten per Angkatan' }
];
return (
<div className="container mx-auto p-4 space-y-6">
@@ -43,43 +110,67 @@ export default function TotalMahasiswaPage() {
selectedYear={selectedYear}
onYearChange={setSelectedYear}
/>
{/* Quick Navigation Dropdown */}
<DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="flex items-center gap-2">
Judul Visualisasi
<ChevronDown className="size-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-80">
{(selectedYear === "all" ? allDataNavItems : perYearNavItems).map((item) => (
<DropdownMenuItem
key={item.id}
onClick={(e) => {
e.preventDefault();
scrollToSection(item.id);
}}
className="cursor-pointer"
>
{item.label}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
{selectedYear === "all" ? (
<div className="space-y-6">
{/* Overview Section */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div id="overview" className="grid grid-cols-1 md:grid-cols-2 gap-4 scroll-mt-24">
<StatistikMahasiswaChart />
<StatusMahasiswaChart />
</div>
{/* Academic Performance Section */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div id="academic" className="grid grid-cols-1 md:grid-cols-2 gap-4 scroll-mt-24">
<IPKChart />
<JenisPendaftaranChart />
</div>
{/* Study Duration Section */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div id="study-duration" className="grid grid-cols-1 md:grid-cols-2 gap-4 scroll-mt-24">
<LulusTepatWaktuChart selectedYear={selectedYear} />
<MasaStudiLulusChart selectedYear={selectedYear} />
</div>
{/* Expertise & Achievement Section */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div id="expertise" className="grid grid-cols-1 md:grid-cols-2 gap-4 scroll-mt-24">
<KelompokKeahlianStatusChart selectedYear={selectedYear} />
<KelompokKeahlianLulusTepatPieChart />
</div>
{/* Scholarship & Achievement Section */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div id="scholarship" className="grid grid-cols-1 md:grid-cols-2 gap-4 scroll-mt-24">
<NamaBeasiswaChart selectedYear={selectedYear} />
<TingkatPrestasiChart selectedYear={selectedYear} />
</div>
{/* Demographics Section */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div id="demographics" className="grid grid-cols-1 md:grid-cols-2 gap-4 scroll-mt-24">
<div className="col-span-1">
<AsalDaerahChart />
</div>
@@ -91,28 +182,48 @@ export default function TotalMahasiswaPage() {
) : (
<div className="space-y-6">
{/* Overview Section */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div id="overview-year" className="grid grid-cols-1 md:grid-cols-2 gap-4 scroll-mt-24">
<StatistikPerAngkatanChart tahunAngkatan={selectedYear} />
<StatusMahasiswaPieChartPerangkatan selectedYear={selectedYear} />
</div>
{/* Status Section */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div id="status-year" className="grid grid-cols-1 md:grid-cols-2 gap-4 scroll-mt-24">
<JenisPendaftaranPerAngkatanChart tahunAngkatan={selectedYear} />
<KelompokKeahlianPieChartPerAngkatan selectedYear={selectedYear} />
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div id="achievement-year" className="grid grid-cols-1 md:grid-cols-2 gap-4 scroll-mt-24">
<NamaBeasiswaDashPieChartPerangkatan selectedYear={selectedYear} />
<TingkatPrestasiPieChartDash selectedYear={selectedYear} />
</div>
{/* Demographics Section */}
<div className="grid grid-cols-1 md:grid-cols-1 gap-4">
<div id="demographics-year" className="grid grid-cols-1 md:grid-cols-1 gap-4 scroll-mt-24">
<AsalDaerahPerAngkatanChart tahunAngkatan={selectedYear} />
</div>
</div>
)}
{/* Back to Top Button */}
{showBackToTop && (
<button
onClick={scrollToTop}
className={`
fixed bottom-6 right-6 z-50
w-12 h-12 rounded-full
bg-primary text-primary-foreground
shadow-lg hover:shadow-xl
transition-all duration-300 ease-in-out
hover:scale-110 hover:bg-primary/90
flex items-center justify-center
group
`}
aria-label="Kembali ke atas"
>
<ArrowUp className="size-5 transition-transform duration-200 group-hover:-translate-y-0.5" />
</button>
)}
</div>
);
}