merge: feat(beasiswa) dynamic stats penerima & dana tersalurkan + formatDana
This commit is contained in:
@@ -7,7 +7,12 @@ async function beasiswaConfigFindUnique() {
|
||||
orderBy: { createdAt: 'desc' },
|
||||
});
|
||||
|
||||
return { success: true, data };
|
||||
return {
|
||||
success: true,
|
||||
data: data
|
||||
? { ...data, danaTersalurkan: data.danaTersalurkan.toString() }
|
||||
: null,
|
||||
};
|
||||
} catch (e) {
|
||||
console.error("Error di beasiswaConfigFindUnique:", e);
|
||||
return { success: false, message: "Gagal mengambil konfigurasi beasiswa" };
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use client'
|
||||
import beasiswaDesaState from '@/app/admin/(dashboard)/_state/pendidikan/beasiswa-desa';
|
||||
import ringkasanBeasiswaState from '@/app/admin/(dashboard)/_state/pendidikan/ringkasan-beasiswa';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Divider, Group, Image, Modal, Pagination, Paper, Select, SimpleGrid, Skeleton, Stack, Stepper, Text, TextInput, Title } from '@mantine/core';
|
||||
import { useDisclosure, useShallowEffect } from '@mantine/hooks';
|
||||
@@ -9,15 +10,20 @@ import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||
|
||||
const dataBeasiswa = [
|
||||
{ id: 1, nama: 'Penerima Beasiswa', jumlah: '250+', icon: IconUsers },
|
||||
{ id: 2, nama: 'Peluang Kelulusan', jumlah: '90%', icon: IconSchool },
|
||||
{ id: 3, nama: 'Dana Tersalurkan', jumlah: '1.5M', icon: IconCoin },
|
||||
];
|
||||
function formatDana(value: string | number): string {
|
||||
const num = typeof value === 'string' ? parseFloat(value.replace(/[^0-9.-]/g, '')) : value;
|
||||
if (isNaN(num)) return String(value);
|
||||
if (num >= 1_000_000_000_000) return `${(num / 1_000_000_000_000).toFixed(num % 1_000_000_000_000 === 0 ? 0 : 1)}T`;
|
||||
if (num >= 1_000_000_000) return `${(num / 1_000_000_000).toFixed(num % 1_000_000_000 === 0 ? 0 : 1)}M`;
|
||||
if (num >= 1_000_000) return `${(num / 1_000_000).toFixed(num % 1_000_000 === 0 ? 0 : 1)}Jt`;
|
||||
if (num >= 1_000) return `${(num / 1_000).toFixed(num % 1_000 === 0 ? 0 : 1)}Rb`;
|
||||
return String(num);
|
||||
}
|
||||
|
||||
function Page() {
|
||||
const beasiswaDesa = useProxy(beasiswaDesaState.beasiswaPendaftar)
|
||||
const ungggulanDesa = useProxy(beasiswaDesaState.keunggulanProgram)
|
||||
const statsBeasiswa = useProxy(ringkasanBeasiswaState.findStats)
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
const router = useTransitionRouter()
|
||||
const resetForm = () => {
|
||||
@@ -61,6 +67,16 @@ function Page() {
|
||||
load(page, 3, "");
|
||||
}, [page])
|
||||
|
||||
useShallowEffect(() => {
|
||||
statsBeasiswa.load();
|
||||
}, [])
|
||||
|
||||
const dataBeasiswa = [
|
||||
{ id: 1, nama: 'Penerima Beasiswa', jumlah: statsBeasiswa.data?.jumlahPenerima?.toString() ?? '-', icon: IconUsers },
|
||||
{ id: 2, nama: 'Peluang Kelulusan', jumlah: '90%', icon: IconSchool },
|
||||
{ id: 3, nama: 'Dana Tersalurkan', jumlah: statsBeasiswa.data?.danaTersalurkan ? formatDana(statsBeasiswa.data.danaTersalurkan) : '-', icon: IconCoin },
|
||||
];
|
||||
|
||||
const handleSubmit = async () => {
|
||||
await beasiswaDesa.create.create();
|
||||
resetForm();
|
||||
|
||||
6
tasks-sample.csv
Normal file
6
tasks-sample.csv
Normal file
@@ -0,0 +1,6 @@
|
||||
"title","description","kind","priority","startsAt","dueAt","estimateHours","assigneeEmail","tagNames"
|
||||
"[Beasiswa] Import ringkasanBeasiswaState ke halaman publik beasiswa-desa","Import ringkasanBeasiswaState dari src/app/admin/(dashboard)/_state/pendidikan/ringkasan-beasiswa.ts ke src/app/darmasaba/(pages)/pendidikan/beasiswa-desa/page.tsx untuk mengakses data stats beasiswa secara dinamis.","TASK","MEDIUM","","","0.5","nicoarya20@gmail.com",""
|
||||
"[Beasiswa] Tambah useProxy + useShallowEffect fetch stats beasiswa","Tambah useProxy(ringkasanBeasiswaState.findStats) dan useShallowEffect untuk memanggil statsBeasiswa.load() saat komponen mount di halaman publik beasiswa-desa/page.tsx.","TASK","MEDIUM","","","0.5","nicoarya20@gmail.com",""
|
||||
"[Beasiswa] Ubah dataBeasiswa dari static ke dynamic (penerima & dana tersalurkan)","Pindahkan dataBeasiswa dari static array di luar komponen menjadi computed array di dalam Page(). Field 'Penerima Beasiswa' diambil dari statsBeasiswa.data.jumlahPenerima dan 'Dana Tersalurkan' dari statsBeasiswa.data.danaTersalurkan. Fallback '-' bila data belum tersedia.","TASK","MEDIUM","","","0.5","nicoarya20@gmail.com",""
|
||||
"[Beasiswa] Buat fungsi formatDana untuk konversi angka ke format pendek Indonesia","Buat helper function formatDana(value: string | number) di halaman beasiswa-desa/page.tsx. Konversi: >= 1T → XT, >= 1M (miliar) → XM, >= 1Jt → XJt, >= 1Rb → XRb. Desimal 1 angka hanya muncul jika ada sisa (misal 1.5Jt), bilangan bulat tanpa desimal (misal 2Jt).","TASK","MEDIUM","","","0.5","nicoarya20@gmail.com",""
|
||||
"[Beasiswa] Terapkan formatDana ke field Dana Tersalurkan di dataBeasiswa","Terapkan formatDana(statsBeasiswa.data.danaTersalurkan) pada entry Dana Tersalurkan di array dataBeasiswa agar nilai dari API otomatis diformat ke representasi singkat (Rb/Jt/M/T).","TASK","MEDIUM","","","0.5","nicoarya20@gmail.com",""
|
||||
|
Reference in New Issue
Block a user