diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx index 08d6c58..d4a48e3 100644 --- a/app/dashboard/page.tsx +++ b/app/dashboard/page.tsx @@ -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("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 (
@@ -43,43 +110,67 @@ export default function TotalMahasiswaPage() { selectedYear={selectedYear} onYearChange={setSelectedYear} /> + + {/* Quick Navigation Dropdown */} + + + + + + {(selectedYear === "all" ? allDataNavItems : perYearNavItems).map((item) => ( + { + e.preventDefault(); + scrollToSection(item.id); + }} + className="cursor-pointer" + > + {item.label} + + ))} + +
{selectedYear === "all" ? (
{/* Overview Section */} -
+
{/* Academic Performance Section */} -
+
{/* Study Duration Section */} -
+
{/* Expertise & Achievement Section */} -
+
{/* Scholarship & Achievement Section */} -
+
{/* Demographics Section */} -
+
@@ -91,28 +182,48 @@ export default function TotalMahasiswaPage() { ) : (
{/* Overview Section */} -
+
{/* Status Section */} -
+
-
+
{/* Demographics Section */} -
+
)} + + {/* Back to Top Button */} + {showBackToTop && ( + + )}
); } diff --git a/app/detail/jumlah-mahasiswa/page.tsx b/app/detail/jumlah-mahasiswa/page.tsx new file mode 100644 index 0000000..7632a7e --- /dev/null +++ b/app/detail/jumlah-mahasiswa/page.tsx @@ -0,0 +1,78 @@ +'use client'; + +import { useState } from "react"; +import StatistikMahasiswaChart from "@/components/charts/StatistikMahasiswaChart"; +import StatistikPerAngkatanChart from "@/components/charts/StatistikPerAngkatanChart"; +import FilterTahunAngkatan from "@/components/FilterTahunAngkatan"; + +export default function JumlahMahasiswaDetailPage() { + const [selectedYear, setSelectedYear] = useState("all"); + + return ( +
+
+ {/* Header Section */} + + + {/* Filter Section */} + + + + {/* Chart Section - Enhanced Size */} +
+ {/* Chart untuk semua data atau hanya satu chart ketika tahun tertentu dipilih */} + {selectedYear === "all" ? ( +
+ +
+ ) : ( + <> + + + )} +
+ + {/* Information Section */} +
+

+ Informasi Visualisasi +

+
+
+

+ Grafik Utama (Semua Angkatan) +

+
    +
  • • Menampilkan jumlah mahasiswa per tahun angkatan
  • +
  • • Data dibagi berdasarkan jenis kelamin (Laki-laki & Perempuan)
  • +
  • • Grafik batang dengan tiga kategori: Laki-laki, Total, dan Perempuan
  • +
  • • Data dapat ditampilkan berdasarkan kategori dan di-download
  • +
+
+ {selectedYear !== "all" && ( +
+

+ Grafik Per Angkatan ({selectedYear}) +

+
    +
  • • Menampilkan distribusi jenis kelamin untuk angkatan {selectedYear}
  • +
  • • Grafik pie chart dengan persentase laki-laki dan perempuan
  • +
  • • Data spesifik untuk tahun angkatan yang dipilih
  • +
  • • Memberikan insight detail untuk angkatan tertentu
  • +
+
+ )} +
+
+
+
+ ); +} diff --git a/components/charts/AsalDaerahChart.tsx b/components/charts/AsalDaerahChart.tsx index 7d2fdfd..7b17119 100644 --- a/components/charts/AsalDaerahChart.tsx +++ b/components/charts/AsalDaerahChart.tsx @@ -266,7 +266,7 @@ export default function AsalDaerahChart() { - Asal Daerah Mahasiswa + Asal Kabupaten Mahasiswa diff --git a/components/charts/StatistikMahasiswaChart.tsx b/components/charts/StatistikMahasiswaChart.tsx index 44bd1b3..5decb1a 100644 --- a/components/charts/StatistikMahasiswaChart.tsx +++ b/components/charts/StatistikMahasiswaChart.tsx @@ -3,7 +3,10 @@ import { useEffect, useState } from 'react'; import dynamic from 'next/dynamic'; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; import { useTheme } from "next-themes"; +import { ExternalLink } from "lucide-react"; +import Link from "next/link"; // Import ApexCharts secara dinamis untuk menghindari error SSR const Chart = dynamic(() => import('react-apexcharts'), { ssr: false }); @@ -15,7 +18,15 @@ interface MahasiswaStatistik { wanita: number; } -export default function StatistikMahasiswaChart() { +interface StatistikMahasiswaChartProps { + height?: string; + showDetailButton?: boolean; +} + +export default function StatistikMahasiswaChart({ + height = "h-[300px] sm:h-[350px] md:h-[300px]", + showDetailButton = true +}: StatistikMahasiswaChartProps) { const { theme } = useTheme(); const [statistikData, setStatistikData] = useState([]); const [loading, setLoading] = useState(true); @@ -306,12 +317,22 @@ export default function StatistikMahasiswaChart() { return ( - - Jumlah Mahasiswa - +
+ + Jumlah Mahasiswa + + {showDetailButton && ( + + + + )} +
-
+
{children} - + ) @@ -166,7 +166,7 @@ function SelectScrollDownButton({ )} {...props} > - + ) }