diff --git a/prisma/schema.prisma b/prisma/schema.prisma index c577c7cd..ca91104e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1842,7 +1842,7 @@ model Pengajar { // ========================================= PROGRAM PENDIDIKAN ANAK ========================================= // model TujuanProgram { id String @id @default(cuid()) - judul String + judul String deskripsi String @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -1852,7 +1852,7 @@ model TujuanProgram { model ProgramUnggulan { id String @id @default(cuid()) - judul String + judul String deskripsi String @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -1863,7 +1863,7 @@ model ProgramUnggulan { // ========================================= BIMBINGAN BELAJAR DESA ========================================= // model TujuanBimbinganBelajarDesa { id String @id @default(cuid()) - judul String + judul String deskripsi String @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -1873,7 +1873,7 @@ model TujuanBimbinganBelajarDesa { model LokasiJadwalBimbinganBelajarDesa { id String @id @default(cuid()) - judul String + judul String deskripsi String @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -1883,7 +1883,7 @@ model LokasiJadwalBimbinganBelajarDesa { model FasilitasBimbinganBelajarDesa { id String @id @default(cuid()) - judul String + judul String deskripsi String @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -1894,7 +1894,7 @@ model FasilitasBimbinganBelajarDesa { // ========================================= PENDIDIKAN NON FORMAL ========================================= // model TujuanPendidikanNonFormal { id String @id @default(cuid()) - judul String + judul String deskripsi String @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -1904,7 +1904,7 @@ model TujuanPendidikanNonFormal { model TempatKegiatan { id String @id @default(cuid()) - judul String + judul String deskripsi String @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -1914,10 +1914,21 @@ model TempatKegiatan { model JenisProgramYangDiselenggarakan { id String @id @default(cuid()) - judul String + judul String deskripsi String @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime @default(now()) isActive Boolean @default(true) } + +// ========================================= DATA PENDIDIKAN ========================================= // +model DataPendidikan { + id String @id @default(cuid()) + name String + jumlah String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} diff --git a/src/app/admin/(dashboard)/_state/ekonomi/jumlah-penduduk-miskin.ts b/src/app/admin/(dashboard)/_state/ekonomi/jumlah-penduduk-miskin.ts index 31c0cb8a..bbb1dfa8 100644 --- a/src/app/admin/(dashboard)/_state/ekonomi/jumlah-penduduk-miskin.ts +++ b/src/app/admin/(dashboard)/_state/ekonomi/jumlah-penduduk-miskin.ts @@ -5,176 +5,190 @@ import { proxy } from "valtio"; import { z } from "zod"; const templateJumlahPendudukMiskin = z.object({ - year: z.number().min(1, "Data tahun harus diisi"), - totalPoorPopulation: z.number().min(1, "Data total penduduk miskin harus diisi"), + year: z.number().min(1, "Data tahun harus diisi"), + totalPoorPopulation: z + .number() + .min(1, "Data total penduduk miskin harus diisi"), }); type JumlahPendudukMiskin = Prisma.GrafikJumlahPendudukMiskinGetPayload<{ - select: { - id: true; - year: true; - totalPoorPopulation: true; - }; + select: { + id: true; + year: true; + totalPoorPopulation: true; + }; }>; -const defaultForm: Omit & { id?: string } = { - year: 0, - totalPoorPopulation: 0, +const defaultForm: Omit & { id?: string } = { + year: 0, + totalPoorPopulation: 0, }; const jumlahPendudukMiskin = proxy({ - create: { - form: defaultForm, - loading: false, - async create() { - const cek = templateJumlahPendudukMiskin.safeParse( - jumlahPendudukMiskin.create.form - ); - if (!cek.success) { - const err = `[${cek.error.issues - .map((v) => `${v.path.join(".")}`) - .join("\n")}] required`; - return toast.error(err); - } - try { - jumlahPendudukMiskin.create.loading = true; - const res = await ApiFetch.api.ekonomi.jumlahpendudukmiskin[ - "create" - ].post(jumlahPendudukMiskin.create.form); - if (res.status === 200) { - const id = res.data?.data?.id; - if (id) { - toast.success("Success create"); - jumlahPendudukMiskin.create.form = { - year: 0, - totalPoorPopulation: 0, - }; - jumlahPendudukMiskin.findMany.load(); - return id; - } - } - return toast.error("failed create"); - } catch (error) { - console.log((error as Error).message); - } finally { - jumlahPendudukMiskin.create.loading = false; - } - }, - }, - findMany: { - data: null as - | Prisma.GrafikJumlahPendudukMiskinGetPayload<{ - select: { id: true; year: true; totalPoorPopulation: true; }; - }>[] - | null, - loading: false, - async load() { - const res = await ApiFetch.api.ekonomi.jumlahpendudukmiskin[ - "find-many" - ].get(); - if (res.status === 200) { - jumlahPendudukMiskin.findMany.data = res.data?.data ?? []; - } - }, - }, - findUnique: { - data: null as Prisma.GrafikJumlahPendudukMiskinGetPayload<{ - select: { id: true; year: true; totalPoorPopulation: true; }; - }> | null, - async load(id: string) { - try { - const res = await fetch( - `/api/ekonomi/jumlahpendudukmiskin/${id}` - ); - if (res.ok) { - const data = await res.json(); - jumlahPendudukMiskin.findUnique.data = data.data ?? null; - } else { - console.error("Failed to fetch data", res.status, res.statusText); - jumlahPendudukMiskin.findUnique.data = null; - } - } catch (error) { - console.error("Error loading grafik jumlah penduduk miskin:", error); - jumlahPendudukMiskin.findUnique.data = null; - } - }, - }, - update: { - id: "", - form: {...defaultForm}, - loading: false, - async byId() { - // Method implementation if needed - }, - async submit() { - const id = this.id; - if (!id) { - toast.warn("ID tidak valid"); - return null; - } - const cek = templateJumlahPendudukMiskin.safeParse(this.form); - if (!cek.success) { - const err = `[${cek.error.issues.map((v) => (v.path as string[]).join(".")).join("\n")}] required`; - toast.error(err); - return null; - } - this.loading = true; - try { - const response = await fetch( - `/api/ekonomi/jumlahpendudukmiskin/${id}`, { - method: "PUT", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(this.form), - }); - const result = await response.json(); - if (!response.ok || !result?.success) { - throw new Error(result?.message || "Gagal update data"); - } - toast.success("Berhasil update data!"); - await jumlahPendudukMiskin.findMany.load(); - return result.data; - } catch (error) { - console.error("Error update data grafik jumlah penduduk miskin:", error); - toast.error("Gagal update data grafik jumlah penduduk miskin"); - } finally { - this.loading = false; - } - }, - }, - delete: { - loading: false, - async byId(id: string) { - if (!id) return toast.warn("ID tidak valid"); - - try { - jumlahPendudukMiskin.delete.loading = true; - - const response = await fetch(`/api/ekonomi/jumlahpendudukmiskin/del/${id}`, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - }); - - const result = await response.json(); - - if (response.ok && result?.success) { - toast.success(result.message || "Grafik jumlah penduduk miskin berhasil dihapus"); - await jumlahPendudukMiskin.findMany.load(); // refresh list - } else { - toast.error(result?.message || "Gagal menghapus grafik jumlah penduduk miskin"); - } - } catch (error) { - console.error("Gagal delete grafik jumlah penduduk miskin:", error); - toast.error("Terjadi kesalahan saat menghapus grafik jumlah penduduk miskin"); - } finally { - jumlahPendudukMiskin.delete.loading = false; - } - }, + create: { + form: defaultForm, + loading: false, + async create() { + const cek = templateJumlahPendudukMiskin.safeParse( + jumlahPendudukMiskin.create.form + ); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); } -}) -export default jumlahPendudukMiskin - - \ No newline at end of file + try { + jumlahPendudukMiskin.create.loading = true; + const res = await ApiFetch.api.ekonomi.jumlahpendudukmiskin[ + "create" + ].post(jumlahPendudukMiskin.create.form); + if (res.status === 200) { + const id = res.data?.data?.id; + if (id) { + toast.success("Success create"); + jumlahPendudukMiskin.create.form = { + year: 0, + totalPoorPopulation: 0, + }; + jumlahPendudukMiskin.findMany.load(); + return id; + } + } + return toast.error("failed create"); + } catch (error) { + console.log((error as Error).message); + } finally { + jumlahPendudukMiskin.create.loading = false; + } + }, + }, + findMany: { + data: null as + | Prisma.GrafikJumlahPendudukMiskinGetPayload<{ + select: { id: true; year: true; totalPoorPopulation: true }; + }>[] + | null, + loading: false, + async load() { + const res = await ApiFetch.api.ekonomi.jumlahpendudukmiskin[ + "find-many" + ].get(); + if (res.status === 200) { + jumlahPendudukMiskin.findMany.data = res.data?.data ?? []; + } + }, + }, + findUnique: { + data: null as Prisma.GrafikJumlahPendudukMiskinGetPayload<{ + select: { id: true; year: true; totalPoorPopulation: true }; + }> | null, + async load(id: string) { + try { + const res = await fetch(`/api/ekonomi/jumlahpendudukmiskin/${id}`); + if (res.ok) { + const data = await res.json(); + jumlahPendudukMiskin.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch data", res.status, res.statusText); + jumlahPendudukMiskin.findUnique.data = null; + } + } catch (error) { + console.error("Error loading grafik jumlah penduduk miskin:", error); + jumlahPendudukMiskin.findUnique.data = null; + } + }, + }, + update: { + id: "", + form: { ...defaultForm }, + loading: false, + async byId() { + // Method implementation if needed + }, + async submit() { + const id = this.id; + if (!id) { + toast.warn("ID tidak valid"); + return null; + } + const cek = templateJumlahPendudukMiskin.safeParse(this.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => (v.path as string[]).join(".")) + .join("\n")}] required`; + toast.error(err); + return null; + } + this.loading = true; + try { + const response = await fetch( + `/api/ekonomi/jumlahpendudukmiskin/${id}`, + { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(this.form), + } + ); + const result = await response.json(); + if (!response.ok || !result?.success) { + throw new Error(result?.message || "Gagal update data"); + } + toast.success("Berhasil update data!"); + await jumlahPendudukMiskin.findMany.load(); + return result.data; + } catch (error) { + console.error( + "Error update data grafik jumlah penduduk miskin:", + error + ); + toast.error("Gagal update data grafik jumlah penduduk miskin"); + } finally { + this.loading = false; + } + }, + }, + delete: { + loading: false, + async byId(id: string) { + if (!id) return toast.warn("ID tidak valid"); + + try { + jumlahPendudukMiskin.delete.loading = true; + + const response = await fetch( + `/api/ekonomi/jumlahpendudukmiskin/del/${id}`, + { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + } + ); + + const result = await response.json(); + + if (response.ok && result?.success) { + toast.success( + result.message || "Grafik jumlah penduduk miskin berhasil dihapus" + ); + await jumlahPendudukMiskin.findMany.load(); // refresh list + } else { + toast.error( + result?.message || "Gagal menghapus grafik jumlah penduduk miskin" + ); + } + } catch (error) { + console.error("Gagal delete grafik jumlah penduduk miskin:", error); + toast.error( + "Terjadi kesalahan saat menghapus grafik jumlah penduduk miskin" + ); + } finally { + jumlahPendudukMiskin.delete.loading = false; + } + }, + }, +}); +export default jumlahPendudukMiskin; diff --git a/src/app/admin/(dashboard)/_state/pendidikan/data-pendidikan.ts b/src/app/admin/(dashboard)/_state/pendidikan/data-pendidikan.ts new file mode 100644 index 00000000..08189a83 --- /dev/null +++ b/src/app/admin/(dashboard)/_state/pendidikan/data-pendidikan.ts @@ -0,0 +1,178 @@ +import ApiFetch from "@/lib/api-fetch"; +import { Prisma } from "@prisma/client"; +import { toast } from "react-toastify"; +import { proxy } from "valtio"; +import { z } from "zod"; + +const templateDataPendidikan = z.object({ + name: z.string().min(1, "Data nama harus diisi"), + jumlah: z.string().min(1, "Data jumlah harus diisi"), +}); + +type DataPendidikan = Prisma.DataPendidikanGetPayload<{ + select: { + id: true; + name: true; + jumlah: true; + }; +}>; + +const defaultForm: Omit & { id?: string } = { + name: "", + jumlah: "", +}; + +const dataPendidikan = proxy({ + create: { + form: defaultForm, + loading: false, + async create() { + const cek = templateDataPendidikan.safeParse(dataPendidikan.create.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + try { + dataPendidikan.create.loading = true; + const res = await ApiFetch.api.pendidikan.datapendidikan["create"].post( + dataPendidikan.create.form + ); + if (res.status === 200) { + const id = res.data?.data?.id; + if (id) { + toast.success("Success create"); + dataPendidikan.create.form = { + name: "", + jumlah: "", + }; + dataPendidikan.findMany.load(); + return id; + } + } + return toast.error("failed create"); + } catch (error) { + console.log((error as Error).message); + } finally { + dataPendidikan.create.loading = false; + } + }, + }, + findMany: { + data: null as + | Prisma.DataPendidikanGetPayload<{ + select: { id: true; name: true; jumlah: true }; + }>[] + | null, + loading: false, + async load() { + const res = await ApiFetch.api.pendidikan.datapendidikan[ + "findMany" + ].get(); + if (res.status === 200) { + dataPendidikan.findMany.data = res.data?.data ?? []; + } + }, + }, + findUnique: { + data: null as Prisma.DataPendidikanGetPayload<{ + select: { id: true; name: true; jumlah: true }; + }> | null, + async load(id: string) { + try { + const res = await fetch(`/api/pendidikan/datapendidikan/${id}`); + if (res.ok) { + const data = await res.json(); + dataPendidikan.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch data", res.status, res.statusText); + dataPendidikan.findUnique.data = null; + } + } catch (error) { + console.error("Error loading data pendidikan:", error); + dataPendidikan.findUnique.data = null; + } + }, + }, + update: { + id: "", + form: { ...defaultForm }, + loading: false, + async byId() { + // Method implementation if needed + }, + async submit() { + const id = this.id; + if (!id) { + toast.warn("ID tidak valid"); + return null; + } + const cek = templateDataPendidikan.safeParse(this.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => (v.path as string[]).join(".")) + .join("\n")}] required`; + toast.error(err); + return null; + } + this.loading = true; + try { + const response = await fetch(`/api/pendidikan/datapendidikan/${id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(this.form), + }); + const result = await response.json(); + if (!response.ok || !result?.success) { + throw new Error(result?.message || "Gagal update data"); + } + toast.success("Berhasil update data!"); + await dataPendidikan.findMany.load(); + return result.data; + } catch (error) { + console.error("Error update data data pendidikan:", error); + toast.error("Gagal update data data pendidikan"); + } finally { + this.loading = false; + } + }, + }, + delete: { + loading: false, + async byId(id: string) { + if (!id) return toast.warn("ID tidak valid"); + + try { + dataPendidikan.delete.loading = true; + + const response = await fetch( + `/api/pendidikan/datapendidikan/del/${id}`, + { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + } + ); + + const result = await response.json(); + + if (response.ok && result?.success) { + toast.success(result.message || "Data berhasil dihapus"); + await dataPendidikan.findMany.load(); // refresh list + } else { + toast.error(result?.message || "Gagal menghapus data"); + } + } catch (error) { + console.error("Gagal delete data pendidikan:", error); + toast.error("Terjadi kesalahan saat menghapus data pendidikan"); + } finally { + dataPendidikan.delete.loading = false; + } + }, + }, +}); +export default dataPendidikan; diff --git a/src/app/admin/(dashboard)/pendidikan/data-pendidikan/[id]/page.tsx b/src/app/admin/(dashboard)/pendidikan/data-pendidikan/[id]/page.tsx new file mode 100644 index 00000000..c1479a82 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/data-pendidikan/[id]/page.tsx @@ -0,0 +1,80 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' + +import colors from '@/con/colors'; +import { Box, Button, Paper, Stack, TextInput, Title } from '@mantine/core'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useEffect } from 'react'; +import { useProxy } from 'valtio/utils'; +import dataPendidikan from '../../../_state/pendidikan/data-pendidikan'; + +function EditDataPendidikan() { + const router = useRouter() + const params = useParams() as { id: string } + const stateDPM = useProxy(dataPendidikan) + + const id = params.id + + // Load data saat komponen mount + useEffect(() => { + if (id) { + stateDPM.findUnique.load(id).then(() => { + const data = stateDPM.findUnique.data + if (data) { + stateDPM.update.form = { + name: data.name || "", + jumlah: data.jumlah || "", + } + } + }) + } + }, [id]) + + const handleSubmit = async () => { + // Set the ID before submitting + stateDPM.update.id = id; + await stateDPM.update.submit(); + router.push('/admin/pendidikan/data-pendidikan') + } +return ( + + + + + + + Edit Data Pendidikan + { + stateDPM.update.form.name = val.currentTarget.value; + }} + /> + { + stateDPM.update.form.jumlah = val.currentTarget.value; + }} + /> + + + + + ) +} + +export default EditDataPendidikan; diff --git a/src/app/admin/(dashboard)/pendidikan/data-pendidikan/create/page.tsx b/src/app/admin/(dashboard)/pendidikan/data-pendidikan/create/page.tsx new file mode 100644 index 00000000..c97094e2 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/data-pendidikan/create/page.tsx @@ -0,0 +1,81 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Group, Paper, Stack, TextInput, Title } from '@mantine/core'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useState } from 'react'; +import { useProxy } from 'valtio/utils'; +import dataPendidikan from '../../../_state/pendidikan/data-pendidikan'; + +function CreateDataPendidikan() { + const stateDPM = useProxy(dataPendidikan); + const [chartData, setChartData] = useState([]); + const router = useRouter() + + const resetForm = () => { + stateDPM.create.form = { + name: "", + jumlah: "", + } + } + + const handleSubmit = async () => { + const id = await stateDPM.create.create(); + if (id) { + const idStr = String(id); + await stateDPM.findUnique.load(idStr); + if (stateDPM.findUnique.data) { + setChartData([stateDPM.findUnique.data]); + } + } + resetForm(); + router.push("/admin/pendidikan/data-pendidikan"); + } + return ( + + + + + + + Tambah Data Pendidikan + + { + stateDPM.create.form.name = val.currentTarget.value; + }} + /> + { + stateDPM.create.form.jumlah = val.currentTarget.value; + }} + /> + + + + + + + + ); +} + +export default CreateDataPendidikan; diff --git a/src/app/admin/(dashboard)/pendidikan/data-pendidikan/page.tsx b/src/app/admin/(dashboard)/pendidikan/data-pendidikan/page.tsx index ce2f64e4..5ac0e91e 100644 --- a/src/app/admin/(dashboard)/pendidikan/data-pendidikan/page.tsx +++ b/src/app/admin/(dashboard)/pendidikan/data-pendidikan/page.tsx @@ -1,74 +1,169 @@ 'use client' import colors from '@/con/colors'; -import { Box, Button, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; -import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react'; +import { Box, Button, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core'; +import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; +import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react'; import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts'; +import { useProxy } from 'valtio/utils'; import HeaderSearch from '../../_com/header'; import JudulList from '../../_com/judulList'; +import { ModalKonfirmasiHapus } from '../../_com/modalKonfirmasiHapus'; +import dataPendidikan from '../../_state/pendidikan/data-pendidikan'; function DataPendidikan() { + const [search, setSearch] = useState(""); return ( } + title='Data Pendidikan' + placeholder='pencarian' + searchIcon={} + value={search} + onChange={(e) => setSearch(e.currentTarget.value)} /> - + ); } -function ListDataPendidikan() { +function ListDataPendidikan({ search }: { search: string }) { + type DPMrafik = { + id: string; + name: string; + jumlah: number; + } + const stateDPM = useProxy(dataPendidikan); + const [chartData, setChartData] = useState([]); + const [mounted, setMounted] = useState(false); // untuk memastikan DOM sudah ready + const isTablet = useMediaQuery('(max-width: 1024px)') + const isMobile = useMediaQuery('(max-width: 768px)') + const [modalHapus, setModalHapus] = useState(false) + const [selectedId, setSelectedId] = useState(null) const router = useRouter(); + + const handleDelete = () => { + if (selectedId) { + stateDPM.delete.byId(selectedId) + setModalHapus(false) + setSelectedId(null) + + stateDPM.findMany.load() + } + } + + useShallowEffect(() => { + setMounted(true) + stateDPM.findMany.load() + }, []) + + useEffect(() => { + setMounted(true); + if (stateDPM.findMany.data) { + setChartData(stateDPM.findMany.data.map((item) => ({ + id: item.id, + name: item.name, + jumlah: Number(item.jumlah) + }))); + } + }, [stateDPM.findMany.data]); + + const filteredData = (stateDPM.findMany.data || []).filter(item => { + const keyword = search.toLowerCase(); + return ( + item.name.toLowerCase().includes(keyword) || + item.jumlah.toLowerCase().includes(keyword) + ); + }); + + if (!stateDPM.findMany.data) { + return ( + + + + ) + } + return ( - - - + + - - - - - Nomor - Nama Lengkap - Nomor Telepon - Email - Detail - - - - +
+ + + Nama + Jumlah + Edit + Delete + + + + {filteredData.map((item) => ( + + {item.name} + {item.jumlah} - - 1 - + - Nama Lengkap - - - Nomor Telepon - - - Email - - - - -
+ ))} + + +
+ + {/* Chart */} + {!mounted && !chartData ? ( + + + Grafik Data Pendidikan + Belum ada data untuk ditampilkan dalam grafik + -
-
+ ) : ( + + + Grafik Data Pendidikan + {mounted && chartData.length > 0 && ( + + + + + + + + )} + + + )} + + + {/* Modal Konfirmasi Hapus */} + setModalHapus(false)} + onConfirm={handleDelete} + text='Apakah anda yakin ingin menghapus grafik data pendidikan ini?' + />
- ) + ); } export default DataPendidikan; diff --git a/src/app/api/[[...slugs]]/_lib/ekonomi/jumlah-penduduk-miskin/index.ts b/src/app/api/[[...slugs]]/_lib/ekonomi/jumlah-penduduk-miskin/index.ts index 9205f477..d658d00b 100644 --- a/src/app/api/[[...slugs]]/_lib/ekonomi/jumlah-penduduk-miskin/index.ts +++ b/src/app/api/[[...slugs]]/_lib/ekonomi/jumlah-penduduk-miskin/index.ts @@ -6,33 +6,35 @@ import grafikJumlahPendudukMiskinCreate from "./create"; import grafikJumlahPendudukMiskinDelete from "./del"; const JumlahPendudukMiskin = new Elysia({ - prefix: "/jumlahpendudukmiskin", - tags: ["Ekonomi/Jumlah Penduduk Miskin"], + prefix: "/jumlahpendudukmiskin", + tags: ["Ekonomi/Jumlah Penduduk Miskin"], }) - .get("/find-many", grafikJumlahPendudukMiskinFindMany) - .get("/:id", async (context) => { - const response = await grafikJumlahPendudukMiskinFindById(new Request(context.request)) - return response - }) - .put("/:id", grafikJumlahPendudukMiskinUpdate, { - params: t.Object({ - id: t.String(), - }), - body: t.Object({ - year: t.Number(), - totalPoorPopulation: t.Number(), - }), - }) - .post("/create", grafikJumlahPendudukMiskinCreate, { - body: t.Object({ - year: t.Number(), - totalPoorPopulation: t.Number(), - }), - }) - .delete("/del/:id", grafikJumlahPendudukMiskinDelete, { - params: t.Object({ - id: t.String(), - }), - }); + .get("/find-many", grafikJumlahPendudukMiskinFindMany) + .get("/:id", async (context) => { + const response = await grafikJumlahPendudukMiskinFindById( + new Request(context.request) + ); + return response; + }) + .put("/:id", grafikJumlahPendudukMiskinUpdate, { + params: t.Object({ + id: t.String(), + }), + body: t.Object({ + year: t.Number(), + totalPoorPopulation: t.Number(), + }), + }) + .post("/create", grafikJumlahPendudukMiskinCreate, { + body: t.Object({ + year: t.Number(), + totalPoorPopulation: t.Number(), + }), + }) + .delete("/del/:id", grafikJumlahPendudukMiskinDelete, { + params: t.Object({ + id: t.String(), + }), + }); -export default JumlahPendudukMiskin; \ No newline at end of file +export default JumlahPendudukMiskin; diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/create.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/create.ts new file mode 100644 index 00000000..d5398cc3 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/create.ts @@ -0,0 +1,31 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; + +type FormCreate = Prisma.DataPendidikanGetPayload<{ + select: { + name: true; + jumlah: true; + }; +}>; +export default async function dataPendidikanCreate(context: Context) { + const body = context.body as FormCreate; + + const created = await prisma.dataPendidikan.create({ + data: { + name: body.name, + jumlah: body.jumlah, + }, + select: { + id: true, + name: true, + jumlah: true, + }, + }); + + return { + success: true, + message: "Data pendidikan berhasil dibuat", + data: created, + }; +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/del.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/del.ts new file mode 100644 index 00000000..f0c400b4 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/del.ts @@ -0,0 +1,43 @@ +import prisma from "@/lib/prisma" +import { Context } from "elysia" + +export default async function dataPendidikanDelete(context: Context) { + const {id} = context.params as {id: string} + + try { + const existingData = await prisma.dataPendidikan.findUnique({ + where: { + id: id, + } + }) + + if (!existingData) { + return { + success: false, + message: "Data tidak ditemukan", + data: null, + } + } + + await prisma.dataPendidikan.delete({ + where: { + id: id + } + }) + + return { + success: true, + message: "Data berhasil dihapus", + data: { + id: id, + deleted: true, + }, + } + } catch (error) { + return { + success: false, + message: error instanceof Error ? error.message : "Unknown error", + data: null, + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/findMany.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/findMany.ts new file mode 100644 index 00000000..395beef9 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/findMany.ts @@ -0,0 +1,8 @@ +import prisma from "@/lib/prisma"; + +export default async function dataPendidikanFindMany() { + const res = await prisma.dataPendidikan.findMany(); + return { + data: res, + }; +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/findUnique.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/findUnique.ts new file mode 100644 index 00000000..5f000834 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/findUnique.ts @@ -0,0 +1,65 @@ +import prisma from "@/lib/prisma"; + +export default async function dataPendidikanFindUnique( + request: Request +) { + const url = new URL(request.url); + const pathSegments = url.pathname.split("/"); + const id = pathSegments[pathSegments.length - 1]; + + if (!id) { + return Response.json( + { + success: false, + message: "ID tidak boleh kosong", + }, + { status: 400 } + ); + } + + try { + if (typeof id !== "string") { + return Response.json( + { + success: false, + message: "ID tidak valid", + }, + { status: 400 } + ); + } + + const data = await prisma.dataPendidikan.findUnique({ + where: { id }, + }); + + if (!data) { + return Response.json( + { + success: false, + message: "Data tidak ditemukan", + }, + { status: 404 } + ); + } + + return Response.json( + { + success: true, + message: "Berhasil mengambil data pendidikan berdasarkan ID", + data, + }, + { status: 200 } + ); + } catch (e) { + console.error("Find by ID error:", e); + return Response.json( + { + success: false, + message: + "Gagal mengambil data pendidikan: " + + (e instanceof Error ? e.message : "Unknown error"), + }, + { status: 500 } + ); + } +} diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/index.ts new file mode 100644 index 00000000..3ab85454 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/index.ts @@ -0,0 +1,39 @@ +import Elysia, { t } from "elysia"; +import dataPendidikanFindMany from "./findMany"; +import dataPendidikanFindUnique from "./findUnique"; +import dataPendidikanUpdate from "./updt"; +import dataPendidikanCreate from "./create"; +import dataPendidikanDelete from "./del"; + +const DataPendidikan = new Elysia({ + prefix: "/datapendidikan", + tags: ["Pendidikan/Data Pendidikan"], +}) + .get("/findMany", dataPendidikanFindMany) + .get("/:id", async (context) => { + const response = await dataPendidikanFindUnique( + new Request(context.request) + ); + return response; + }) + .put("/:id", dataPendidikanUpdate, { + params: t.Object({ + id: t.String(), + }), + body: t.Object({ + name: t.String(), + jumlah: t.String(), + }), + }) + .post("/create", dataPendidikanCreate, { + body: t.Object({ + name: t.String(), + jumlah: t.String(), + }), + }) + .delete("/del/:id", dataPendidikanDelete, { + params: t.Object({ + id: t.String(), + }), + }); +export default DataPendidikan; diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/updt.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/updt.ts new file mode 100644 index 00000000..ab2d3d51 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/data-pendidikan/updt.ts @@ -0,0 +1,48 @@ +import { Context } from "elysia"; +import prisma from "@/lib/prisma"; + +export default async function dataPendidikanUpdate(context: Context) { + const id = context.params?.id; + + if (!id) { + return { + success: false, + message: "Id tidak ditemukan", + } + } + + const existingData = await prisma.dataPendidikan.findUnique({ + where: { + id: id, + } + }) + + const {name, jumlah} = context.body as { + name: string; + jumlah: string; + } + + if (!existingData) { + return { + success: false, + message: "Data tidak ditemukan", + data: null, + } + } + + const updated = await prisma.dataPendidikan.update({ + where: { + id: id, + }, + data: { + name: name, + jumlah: jumlah, + }, + }) + + return { + success: true, + message: "Data pendidikan berhasil diupdate", + data: updated, + } +} diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts index 141e6757..eb39241d 100644 --- a/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts @@ -3,6 +3,7 @@ import InfoSekolahPAUD from "./info-sekolah-paud"; import ProgramPendidikanAnak from "./program-pendidikan-anak"; import BimbinganBelajarDesa from "./bimbingan-belajar-desa"; import PendidikanNonFormal from "./pendidikan-non-formal"; +import DataPendidikan from "./data-pendidikan"; const Pendidikan = new Elysia({ prefix: "/api/pendidikan", @@ -13,5 +14,6 @@ const Pendidikan = new Elysia({ .use(ProgramPendidikanAnak) .use(BimbinganBelajarDesa) .use(PendidikanNonFormal) +.use(DataPendidikan) export default Pendidikan; \ No newline at end of file