From 1c8104ee69c9733792f824e17936be134d51dd81 Mon Sep 17 00:00:00 2001 From: nico Date: Fri, 11 Jul 2025 18:50:20 +0800 Subject: [PATCH] API & UI Admin Menu Ekonomi, Submenu PADesa --- .../(dashboard)/_state/ekonomi/PADesa.ts | 18 +- .../apbdesa/[id]/edit/page.tsx | 235 +++++++++++++++++- .../pendapatan-asli-desa/apbDesa/index.ts | 46 ++-- .../pendapatan-asli-desa/apbDesa/updt.ts | 23 +- 4 files changed, 280 insertions(+), 42 deletions(-) diff --git a/src/app/admin/(dashboard)/_state/ekonomi/PADesa.ts b/src/app/admin/(dashboard)/_state/ekonomi/PADesa.ts index 1ece171f..edda9a97 100644 --- a/src/app/admin/(dashboard)/_state/ekonomi/PADesa.ts +++ b/src/app/admin/(dashboard)/_state/ekonomi/PADesa.ts @@ -105,8 +105,22 @@ const ApbDesa = proxy({ if (!response.ok) { throw new Error("Gagal mengambil APB Desa"); } - const data = await response.json(); + const result = await response.json(); + + if (!result.success) { + throw new Error(result.message || "Gagal memuat APB Desa"); + } + + const data = result.data; + this.id = id; + this.form = { + tahun: data.tahun || 0, + pendapatanIds: data.pendapatan?.map((p: any) => p.id) || [], + belanjaIds: data.belanja?.map((b: any) => b.id) || [], + pembiayaanIds: data.pembiayaan?.map((p: any) => p.id) || [], + }; + return data; } catch (error) { console.error("Error loading APB Desa:", error); @@ -152,7 +166,7 @@ const ApbDesa = proxy({ try { this.loading = true; const response = await fetch( - `/api/ekonomi/pendapatanaslidesa/apbdesa/${id}`, + `/api/ekonomi/pendapatanaslidesa/apbdesa/del/${id}`, { method: "DELETE", } diff --git a/src/app/admin/(dashboard)/ekonomi/PADesa-pendapatan-asli-desa/apbdesa/[id]/edit/page.tsx b/src/app/admin/(dashboard)/ekonomi/PADesa-pendapatan-asli-desa/apbdesa/[id]/edit/page.tsx index 69da2f21..dbe04cf3 100644 --- a/src/app/admin/(dashboard)/ekonomi/PADesa-pendapatan-asli-desa/apbdesa/[id]/edit/page.tsx +++ b/src/app/admin/(dashboard)/ekonomi/PADesa-pendapatan-asli-desa/apbdesa/[id]/edit/page.tsx @@ -1,11 +1,234 @@ -import React from 'react'; +/* eslint-disable @typescript-eslint/no-explicit-any */ +'use client' +/* eslint-disable react-hooks/exhaustive-deps */ +import PendapatanAsliDesa from '@/app/admin/(dashboard)/_state/ekonomi/PADesa'; +import colors from '@/con/colors'; +import { Box, Button, MultiSelect, Paper, Skeleton, Stack, Text, TextInput, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { toast } from 'react-toastify'; +import { useProxy } from 'valtio/utils'; + +function EditAPBDesa() { + const apbState = useProxy(PendapatanAsliDesa.ApbDesa); + const router = useRouter(); + const params = useParams(); + + const [formData, setFormData] = useState({ + tahun: apbState.update.form.tahun || '', + pendapatanIds: apbState.update.form.pendapatanIds || [], + belanjaIds: apbState.update.form.belanjaIds || [], + pembiayaanIds: apbState.update.form.pembiayaanIds || [], + }); + + // Load APB desa by id saat pertama kali + useEffect(() => { + const loadAPBdesa = async () => { + const id = params?.id as string; + if (!id) return; + + try { + const data = await apbState.update.load(id); + if (data) { + setFormData({ + tahun: data.tahun || 0, + pendapatanIds: data.pendapatan?.map((p: any) => p.id) || [], + belanjaIds: data.belanja?.map((b: any) => b.id) || [], + pembiayaanIds: data.pembiayaan?.map((p: any) => p.id) || [], + }); + } + } catch (error) { + console.error("Error loading APBdesa:", error); + toast.error("Gagal memuat data APBdesa"); + } + }; + + loadAPBdesa(); + }, [params?.id]); // ✅ hapus beritaState dari dependency + + const handleSubmit = async () => { + + try { + // Update global state with form data + apbState.update.form = { + ...apbState.update.form, + tahun: Number(formData.tahun), + pendapatanIds: formData.pendapatanIds, + belanjaIds: formData.belanjaIds, + pembiayaanIds: formData.pembiayaanIds, + }; + + await apbState.update.update(); + toast.success("APB Desa berhasil diperbarui!"); + router.push("/admin/ekonomi/PADesa-pendapatan-asli-desa/apbdesa"); + } catch (error) { + console.error("Error updating APBdesa:", error); + toast.error("Terjadi kesalahan saat memperbarui APBdesa"); + } + }; -function Page() { return ( -
- Page -
+ + + + + + + Edit APB Desa + { + setFormData({ ...formData, tahun: val.target.value }); + }} + label={Tahun} + placeholder="masukkan tahun" + /> + { + setFormData({ ...formData, pendapatanIds: ids }); + }} + /> + { + setFormData({ ...formData, belanjaIds: ids }); + }} + /> + { + setFormData({ ...formData, pembiayaanIds: ids }); + }} + /> + + + + ); + + + /* Select Pendapatan */ + interface SelectPendapatanProps { + selectedIds: string[]; + onSelectionChange: (ids: string[]) => void; + } + + function SelectPendapatan({ + selectedIds = [], + onSelectionChange, + }: SelectPendapatanProps) { + const pendapatanState = useProxy(PendapatanAsliDesa.pendapatan); + + useShallowEffect(() => { + pendapatanState.findMany.load().then(() => { + console.log("Pendapatan berhasil dimuat:", pendapatanState.findMany.data); + }); + }, []); + + if (!pendapatanState.findMany.data) { + return ; + } + + return ( + Pendapatan} + data={pendapatanState.findMany.data.map(p => ({ + value: p.id, + label: p.name + }))} + value={selectedIds} + onChange={onSelectionChange} + searchable + clearable + placeholder="Pilih pendapatan..." + nothingFoundMessage="Tidak ditemukan" + /> + ); + } + + /* Select Belanja */ + interface SelectBelanjaProps { + selectedIds: string[]; + onSelectionChange: (ids: string[]) => void; + } + + function SelectBelanja({ + selectedIds = [], + onSelectionChange, + }: SelectBelanjaProps) { + const belanjaState = useProxy(PendapatanAsliDesa.belanja); + + useShallowEffect(() => { + belanjaState.findMany.load().then(() => { + console.log("Belanja berhasil dimuat:", belanjaState.findMany.data); + }); + }, []); + + if (!belanjaState.findMany.data) { + return ; + } + + return ( + Belanja} + data={belanjaState.findMany.data.map(b => ({ + value: b.id, + label: b.name + }))} + value={selectedIds} + onChange={onSelectionChange} + searchable + clearable + placeholder="Pilih belanja..." + nothingFoundMessage="Tidak ditemukan" + /> + ); + } + + /* Select Pembiayaan */ + interface SelectPembiayaanProps { + selectedIds: string[]; + onSelectionChange: (ids: string[]) => void; + } + + function SelectPembiayaan({ + selectedIds = [], + onSelectionChange, + }: SelectPembiayaanProps) { + const pembiayaanState = useProxy(PendapatanAsliDesa.pembiayaan); + + useShallowEffect(() => { + pembiayaanState.findMany.load().then(() => { + console.log("Pembiayaan berhasil dimuat:", pembiayaanState.findMany.data); + }); + }, []); + + if (!pembiayaanState.findMany.data) { + return ; + } + + return ( + Pembiayaan} + data={pembiayaanState.findMany.data.map(b => ({ + value: b.id, + label: b.name + }))} + value={selectedIds} + onChange={onSelectionChange} + searchable + clearable + placeholder="Pilih pembiayaan..." + nothingFoundMessage="Tidak ditemukan" + /> + ); + } } -export default Page; +export default EditAPBDesa; diff --git a/src/app/api/[[...slugs]]/_lib/ekonomi/pendapatan-asli-desa/apbDesa/index.ts b/src/app/api/[[...slugs]]/_lib/ekonomi/pendapatan-asli-desa/apbDesa/index.ts index bb5ef117..4910e25d 100644 --- a/src/app/api/[[...slugs]]/_lib/ekonomi/pendapatan-asli-desa/apbDesa/index.ts +++ b/src/app/api/[[...slugs]]/_lib/ekonomi/pendapatan-asli-desa/apbDesa/index.ts @@ -6,36 +6,36 @@ import apbDesaDelete from "./del"; import apbDesaUpdate from "./updt"; const APBDesa = new Elysia({ - prefix: "/apbdesa", - tags: ["Ekonomi/Pendapatan Asli Desa/APB Desa"], + prefix: "/apbdesa", + tags: ["Ekonomi/Pendapatan Asli Desa/APB Desa"], }) -.get("/find-many", apbDesaFindMany) -.get("/:id", async (context) => { + .get("/find-many", apbDesaFindMany) + .get("/:id", async (context) => { const response = await apbDesaFindUnique(new Request(context.request)); return response; -}) -.post("/create", apbDesaCreate, { + }) + .post("/create", apbDesaCreate, { body: t.Object({ + tahun: t.Number(), + pendapatanIds: t.Array(t.String()), + belanjaIds: t.Array(t.String()), + pembiayaanIds: t.Array(t.String()), + }), + }) + .delete("/del/:id", apbDesaDelete) + .put( + "/:id", + async (context) => { + const response = await apbDesaUpdate(context); + return response; + }, + { + body: t.Object({ tahun: t.Number(), pendapatanIds: t.Array(t.String()), belanjaIds: t.Array(t.String()), pembiayaanIds: t.Array(t.String()), - }), -}) -.delete("/delete/:id", apbDesaDelete) -.put( - "/:id", - async (context) => { - const response = await apbDesaUpdate(context); - return response; - }, - { - body: t.Object({ - tahun: t.Number(), - pendapatanIds: t.Array(t.String()), - belanjaIds: t.Array(t.String()), - pembiayaanIds: t.Array(t.String()), - }), + }), } -); + ); export default APBDesa; diff --git a/src/app/api/[[...slugs]]/_lib/ekonomi/pendapatan-asli-desa/apbDesa/updt.ts b/src/app/api/[[...slugs]]/_lib/ekonomi/pendapatan-asli-desa/apbDesa/updt.ts index 643d7fd3..1d8456de 100644 --- a/src/app/api/[[...slugs]]/_lib/ekonomi/pendapatan-asli-desa/apbDesa/updt.ts +++ b/src/app/api/[[...slugs]]/_lib/ekonomi/pendapatan-asli-desa/apbDesa/updt.ts @@ -41,18 +41,19 @@ export default async function apbDesaUpdate(context: Context) { const updated = await prisma.apbDesa.update({ where: { id }, data: { - tahun, - pendapatan: { - connect: pendapatanIds.map((id) => ({ id })), - }, - belanja: { - connect: belanjaIds.map((id) => ({ id })), - }, - pembiayaan: { - connect: pembiayaanIds.map((id) => ({ id })), - }, + tahun, + pendapatan: { + set: pendapatanIds.map((id) => ({ id })), + }, + belanja: { + set: belanjaIds.map((id) => ({ id })), + }, + pembiayaan: { + set: pembiayaanIds.map((id) => ({ id })), + }, } - }); + }); + return { success: true, message: "Success update APB Desa",