Change Informasi in Beranda

This commit is contained in:
Randa Firman Putra
2025-07-15 15:18:38 +07:00
parent 4585f6a346
commit f9637c77af
4 changed files with 35 additions and 43 deletions

View File

@@ -10,16 +10,10 @@ interface MahasiswaTotal {
total_berprestasi: number; total_berprestasi: number;
prestasi_akademik: number; prestasi_akademik: number;
prestasi_non_akademik: number; prestasi_non_akademik: number;
ipk_rata_rata_aktif: number;
ipk_rata_rata_lulus: number;
total_mahasiswa_aktif_lulus: number; total_mahasiswa_aktif_lulus: number;
} total_mahasiswa_beasiswa: number;
total_mahasiswa_beasiswa_pemerintah: number;
interface IPKData { total_mahasiswa_beasiswa_non_pemerintah: number;
nim: string;
mahasiswa: {
ipk: number;
};
} }
// Fungsi untuk menangani preflight request (OPTIONS) // Fungsi untuk menangani preflight request (OPTIONS)
@@ -91,27 +85,22 @@ export async function GET() {
.select('*', { count: 'exact', head: true }) .select('*', { count: 'exact', head: true })
.in('status_kuliah', ['Aktif', 'Lulus']); .in('status_kuliah', ['Aktif', 'Lulus']);
// Get IPK rata-rata aktif // Total mahasiswa beasiswa
const { data: ipkAktifData } = await supabase const { count: totalMahasiswaBeasiswa } = await supabase
.from('mahasiswa') .from('beasiswa_mahasiswa')
.select('ipk') .select('*', { count: 'exact', head: true });
.eq('status_kuliah', 'Aktif')
.not('ipk', 'is', null);
const ipkRataRataAktif = ipkAktifData && ipkAktifData.length > 0 // Total mahasiswa beasiswa Pemerintah
? Math.round((ipkAktifData.reduce((sum, item: any) => sum + (item.ipk || 0), 0) / ipkAktifData.length) * 100) / 100 const { count: totalMahasiswaBeasiswaPemerintah } = await supabase
: 0; .from('beasiswa_mahasiswa')
.select('*', { count: 'exact', head: true })
.eq('jenis_beasiswa', 'Pemerintah');
// Get IPK rata-rata lulus // Total mahasiswa beasiswa Non-Pemerintah
const { data: ipkLulusData } = await supabase const { count: totalMahasiswaBeasiswaNonPemerintah } = await supabase
.from('mahasiswa') .from('beasiswa_mahasiswa')
.select('ipk') .select('*', { count: 'exact', head: true })
.eq('status_kuliah', 'Lulus') .eq('jenis_beasiswa', 'Non-Pemerintah');
.not('ipk', 'is', null);
const ipkRataRataLulus = ipkLulusData && ipkLulusData.length > 0
? Math.round((ipkLulusData.reduce((sum, item: any) => sum + (item.ipk || 0), 0) / ipkLulusData.length) * 100) / 100
: 0;
const results: MahasiswaTotal = { const results: MahasiswaTotal = {
total_mahasiswa: totalMahasiswa || 0, total_mahasiswa: totalMahasiswa || 0,
@@ -122,9 +111,10 @@ export async function GET() {
total_berprestasi: totalBerprestasi || 0, total_berprestasi: totalBerprestasi || 0,
prestasi_akademik: prestasiAkademik || 0, prestasi_akademik: prestasiAkademik || 0,
prestasi_non_akademik: prestasiNonAkademik || 0, prestasi_non_akademik: prestasiNonAkademik || 0,
ipk_rata_rata_aktif: ipkRataRataAktif,
ipk_rata_rata_lulus: ipkRataRataLulus,
total_mahasiswa_aktif_lulus: totalMahasiswaAktifLulus || 0, total_mahasiswa_aktif_lulus: totalMahasiswaAktifLulus || 0,
total_mahasiswa_beasiswa: totalMahasiswaBeasiswa || 0,
total_mahasiswa_beasiswa_pemerintah: totalMahasiswaBeasiswaPemerintah || 0,
total_mahasiswa_beasiswa_non_pemerintah: totalMahasiswaBeasiswaNonPemerintah || 0,
}; };
// Menambahkan header cache dan CORS // Menambahkan header cache dan CORS

View File

@@ -17,9 +17,10 @@ interface MahasiswaTotal {
total_berprestasi: number; total_berprestasi: number;
prestasi_akademik: number; prestasi_akademik: number;
prestasi_non_akademik: number; prestasi_non_akademik: number;
ipk_rata_rata_aktif: number;
ipk_rata_rata_lulus: number;
total_mahasiswa_aktif_lulus: number; total_mahasiswa_aktif_lulus: number;
total_mahasiswa_beasiswa: number;
total_mahasiswa_beasiswa_pemerintah: number;
total_mahasiswa_beasiswa_non_pemerintah: number;
} }
// Skeleton loading component // Skeleton loading component
@@ -50,11 +51,12 @@ export default function DashboardPage() {
total_berprestasi: 0, total_berprestasi: 0,
prestasi_akademik: 0, prestasi_akademik: 0,
prestasi_non_akademik: 0, prestasi_non_akademik: 0,
ipk_rata_rata_aktif: 0, total_mahasiswa_aktif_lulus: 0,
ipk_rata_rata_lulus: 0, total_mahasiswa_beasiswa: 0,
total_mahasiswa_aktif_lulus: 0 total_mahasiswa_beasiswa_pemerintah: 0,
total_mahasiswa_beasiswa_non_pemerintah: 0
}); });
const [selectedYear, setSelectedYear] = useState<string>("all");
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
@@ -177,18 +179,19 @@ export default function DashboardPage() {
</CardContent> </CardContent>
</Card> </Card>
{/* Kartu Rata-rata IPK */} {/* Kartu Mahasiswa Beasiswa */}
<Card className="bg-white dark:bg-slate-900 shadow-lg"> <Card className="bg-white dark:bg-slate-900 shadow-lg">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium dark:text-white"> <CardTitle className="text-sm font-medium dark:text-white">
Rata-rata IPK Mahasiswa Beasiswa
</CardTitle> </CardTitle>
<BookOpen className="h-4 w-4 text-muted-foreground" /> <BookOpen className="h-4 w-4 text-muted-foreground" />
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="text-2xl font-bold dark:text-white">{mahasiswaData.mahasiswa_aktif}</div> <div className="text-2xl font-bold dark:text-white">{mahasiswaData.total_mahasiswa_beasiswa}</div>
<div className="flex justify-between mt-2 text-xs text-muted-foreground"> <div className="flex justify-between mt-2 text-xs text-muted-foreground">
<span className="dark:text-white">Aktif: <span className="text-green-500">{mahasiswaData.ipk_rata_rata_aktif}</span></span> <span className="dark:text-white">Pemerintah: <span className="text-green-500">{mahasiswaData.total_mahasiswa_beasiswa_pemerintah}</span></span>
<span className="dark:text-white">Non-Pemerintah: <span className="text-amber-400">{mahasiswaData.total_mahasiswa_beasiswa_non_pemerintah}</span></span>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>

View File

@@ -3,7 +3,7 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { ThemeToggle } from '@/components/theme-toggle'; import { ThemeToggle } from '@/components/theme-toggle';
import { Menu, ChevronDown, BarChart, Database, School, GraduationCap, Clock, BookOpen, Award, Home, LogOut, User } from 'lucide-react'; import { Menu, ChevronDown, BarChart, Database, CircleCheck, School, GraduationCap, Clock, BookOpen, Award, Home, LogOut, User } from 'lucide-react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet'; import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
import { import {
@@ -127,7 +127,7 @@ const Navbar = () => {
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem asChild> <DropdownMenuItem asChild>
<Link href="/visualisasi/status" className="flex items-center gap-2 w-full"> <Link href="/visualisasi/status" className="flex items-center gap-2 w-full">
<GraduationCap className="h-4 w-4" /> <CircleCheck className="h-4 w-4" />
Status Kuliah Status Kuliah
</Link> </Link>
</DropdownMenuItem> </DropdownMenuItem>

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB