diff --git a/src/app/admin/(dashboard)/pendidikan/beasiswa-desa/_lib/layoutTabs.tsx b/src/app/admin/(dashboard)/pendidikan/beasiswa-desa/_lib/layoutTabs.tsx index 7bae982f..9c00a64f 100644 --- a/src/app/admin/(dashboard)/pendidikan/beasiswa-desa/_lib/layoutTabs.tsx +++ b/src/app/admin/(dashboard)/pendidikan/beasiswa-desa/_lib/layoutTabs.tsx @@ -2,7 +2,7 @@ 'use client' import colors from '@/con/colors'; import { Box, ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core'; -import { IconSchool, IconStar } from '@tabler/icons-react'; +import { IconSchool, IconSettings2, IconStar } from '@tabler/icons-react'; import { usePathname, useRouter } from 'next/navigation'; import React, { useEffect, useState } from 'react'; @@ -23,6 +23,12 @@ function LayoutTabs({ children }: { children: React.ReactNode }) { href: "/admin/pendidikan/beasiswa-desa/keunggulan-program", icon: }, + { + label: "Konfigurasi Beasiswa", + value: "beasiswa-config", + href: "/admin/pendidikan/beasiswa-desa/beasiswa-config", + icon: + }, ]; const currentTab = tabs.find(tab => tab.href === pathname); diff --git a/src/app/admin/(dashboard)/pendidikan/beasiswa-desa/beasiswa-config/page.tsx b/src/app/admin/(dashboard)/pendidikan/beasiswa-desa/beasiswa-config/page.tsx new file mode 100644 index 00000000..2b67d9a3 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/beasiswa-desa/beasiswa-config/page.tsx @@ -0,0 +1,192 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import colors from '@/con/colors'; +import { + Badge, + Box, + Button, + Card, + Divider, + Group, + NumberInput, + Paper, + SimpleGrid, + Skeleton, + Stack, + Text, + TextInput, + Title, +} from '@mantine/core'; +import { IconCash, IconCalendar, IconUsers, IconDeviceFloppy, IconRefresh } from '@tabler/icons-react'; +import { useEffect, useState } from 'react'; +import { useProxy } from 'valtio/utils'; +import ringkasanBeasiswaState from '../../../_state/pendidikan/ringkasan-beasiswa'; + +function formatRupiah(value: string | number) { + const num = typeof value === 'string' ? parseInt(value, 10) : value; + if (isNaN(num)) return 'Rp 0'; + return new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', maximumFractionDigits: 0 }).format(num); +} + +export default function BeasiswaConfigPage() { + const state = useProxy(ringkasanBeasiswaState); + + const [tahunAjaran, setTahunAjaran] = useState(''); + const [danaTersalurkan, setDanaTersalurkan] = useState(''); + + useEffect(() => { + state.beasiswaConfig.find(); + state.findStats.load(); + }, []); + + useEffect(() => { + const cfg = state.beasiswaConfig.data; + if (cfg) { + setTahunAjaran(cfg.tahunAjaran); + setDanaTersalurkan(parseInt(cfg.danaTersalurkan, 10) || 0); + } + }, [state.beasiswaConfig.data]); + + const handleSave = async () => { + await state.beasiswaConfig.update.submit( + tahunAjaran, + String(danaTersalurkan), + ); + }; + + const isLoading = state.beasiswaConfig.loading; + const isSaving = state.beasiswaConfig.update.loading; + const stats = state.findStats.data; + + return ( + + {/* ─── Header ─── */} + + + Konfigurasi Beasiswa + Atur tahun ajaran aktif dan total dana yang tersalurkan + + + Tahun Aktif: {stats?.tahunAjaran ?? '-'} + + + + {/* ─── Stats Cards ─── */} + {state.findStats.loading ? ( + + + + + + ) : ( + + + + + + + + Jumlah Penerima + {stats?.jumlahPenerima ?? 0} + + + + + + + + + + + Dana Tersalurkan + + {stats ? formatRupiah(stats.danaTersalurkan) : 'Rp 0'} + + + + + + + + + + + + Tahun Ajaran + {stats?.tahunAjaran ?? '-'} + + + + + )} + + + + {/* ─── Form Edit ─── */} + + Edit Konfigurasi + + {isLoading ? ( + + + + + ) : ( + + setTahunAjaran(e.currentTarget.value)} + leftSection={} + radius="md" + description="Format: YYYY/YYYY" + /> + + setDanaTersalurkan(val)} + leftSection={} + radius="md" + min={0} + step={1000000} + thousandSeparator="." + decimalSeparator="," + allowNegative={false} + description="Total dana yang tersalurkan untuk tahun ajaran ini" + /> + + + + + + + )} + + + ); +}