diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 82e93d93..03e772a0 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -96,6 +96,8 @@ model FileStorage { APBDesImage APBDes[] @relation("APBDesImage") APBDesFile APBDes[] @relation("APBDesFile") PrestasiDesa PrestasiDesa[] + + DataPerpustakaan DataPerpustakaan[] } //========================================= MENU LANDING PAGE ========================================= // @@ -1851,23 +1853,23 @@ model KeunggulanProgram { } model BeasiswaPendaftar { - id String @id @default(cuid()) - namaLengkap String - nik String @unique - tempatLahir String - tanggalLahir DateTime - jenisKelamin JenisKelamin - kewarganegaraan String - agama Agama - alamatKTP String - alamatDomisili String? - noHp String - email String @unique - statusPernikahan StatusPernikahan - ukuranBaju UkuranBaju? - isActive Boolean @default(true) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + namaLengkap String + nik String @unique + tempatLahir String + tanggalLahir DateTime + jenisKelamin JenisKelamin + kewarganegaraan String + agama Agama + alamatKTP String + alamatDomisili String? + noHp String + email String @unique + statusPernikahan StatusPernikahan + ukuranBaju UkuranBaju? + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } enum JenisKelamin { @@ -1900,7 +1902,6 @@ enum UkuranBaju { LAINNYA } - // ========================================= PROGRAM PENDIDIKAN ANAK ========================================= // model TujuanProgram { id String @id @default(cuid()) @@ -1984,6 +1985,31 @@ model JenisProgramYangDiselenggarakan { isActive Boolean @default(true) } +// ========================================= PERPUSTAKAAN ========================================= // +model DataPerpustakaan { + id String @id @default(cuid()) + judul String + deskripsi String @db.Text + kategori KategoriBuku @relation(fields: [kategoriId], references: [id]) + kategoriId String + image FileStorage @relation(fields: [imageId], references: [id]) + imageId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} + +model KategoriBuku { + id String @id @default(cuid()) + name String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) + DataPerpustakaan DataPerpustakaan[] +} + // ========================================= DATA PENDIDIKAN ========================================= // model DataPendidikan { id String @id @default(cuid()) diff --git a/src/app/admin/(dashboard)/_state/pendidikan/perpustakaan-digital.ts b/src/app/admin/(dashboard)/_state/pendidikan/perpustakaan-digital.ts new file mode 100644 index 00000000..3fab5c03 --- /dev/null +++ b/src/app/admin/(dashboard)/_state/pendidikan/perpustakaan-digital.ts @@ -0,0 +1,478 @@ +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 templateDataPerpustakaan = z.object({ + judul: z.string().min(1, "Judul harus diisi"), + deskripsi: z.string().min(1, "Deskripsi harus diisi"), + imageId: z.string().min(1, "Image ID harus diisi"), + kategoriId: z.string().min(1, "Kategori ID harus diisi"), +}); + +const defaultDataPerpustakaan = { + judul: "", + deskripsi: "", + imageId: "", + kategoriId: "", +}; + +const dataPerpustakaan = proxy({ + create: { + form: { ...defaultDataPerpustakaan }, + loading: false, + async create() { + const cek = templateDataPerpustakaan.safeParse( + dataPerpustakaan.create.form + ); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + dataPerpustakaan.create.loading = true; + const res = + await ApiFetch.api.pendidikan.perpustakaandigital.dataperpustakaan[ + "create" + ].post(dataPerpustakaan.create.form); + if (res.status === 200) { + dataPerpustakaan.findMany.load(); + return toast.success("Data Data Perpustakaan Berhasil Dibuat"); + } + console.log(res); + return toast.error("failed create"); + } catch (error) { + console.log(error); + return toast.error("failed create"); + } finally { + dataPerpustakaan.create.loading = false; + } + }, + }, + findMany: { + data: [] as Prisma.DataPerpustakaanGetPayload<{ + include: { + kategori: true; + image: true; + }; + }>[], + loading: false, + async load() { + const res = + await ApiFetch.api.pendidikan.perpustakaandigital.dataperpustakaan[ + "findMany" + ].get(); + if (res.status === 200) { + dataPerpustakaan.findMany.data = res.data?.data ?? []; + } + }, + }, + findUnique: { + data: null as Prisma.DataPerpustakaanGetPayload<{ + include: { + kategori: true; + image: true; + }; + }> | null, + loading: false, + async load(id: string) { + try { + const res = await fetch( + `/api/pendidikan/perpustakaandigital/dataperpustakaan/${id}` + ); + if (res.ok) { + const data = await res.json(); + dataPerpustakaan.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch data", res.status, res.statusText); + dataPerpustakaan.findUnique.data = null; + } + } catch (error) { + console.error("Error fetching data:", error); + dataPerpustakaan.findUnique.data = null; + } + }, + }, + delete: { + loading: false, + async delete(id: string) { + if (!id) return toast.warn("ID tidak valid"); + + try { + dataPerpustakaan.delete.loading = true; + + const response = await fetch( + `/api/pendidikan/perpustakaandigital/dataperpustakaan/del/${id}`, + { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + } + ); + + const result = await response.json(); + + if (response.ok && result?.success) { + toast.success(result.message || "Data Perpustakaan berhasil dihapus"); + await dataPerpustakaan.findMany.load(); // refresh list + } else { + toast.error(result?.message || "Gagal menghapus Data Perpustakaan"); + } + } catch (error) { + console.error("Gagal delete:", error); + toast.error("Terjadi kesalahan saat menghapus Data Perpustakaan"); + } finally { + dataPerpustakaan.delete.loading = false; + } + }, + }, + update: { + id: "", + form: { ...defaultDataPerpustakaan }, + loading: false, + async load(id: string) { + if (!id) { + toast.warn("ID tidak valid"); + return null; + } + + try { + const response = await fetch( + `/api/pendidikan/perpustakaandigital/dataperpustakaan/${id}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + + if (result?.success) { + const data = result.data; + this.id = data.id; + this.form = { + judul: data.judul, + deskripsi: data.deskripsi, + imageId: data.imageId, + kategoriId: data.kategoriId, + }; + return data; // Return the loaded data + } else { + throw new Error(result?.message || "Gagal memuat data"); + } + } catch (error) { + console.error("Error loading perpustakaan digital:", error); + toast.error( + error instanceof Error ? error.message : "Gagal memuat data" + ); + return null; + } + }, + async update() { + const cek = templateDataPerpustakaan.safeParse( + dataPerpustakaan.update.form + ); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + toast.error(err); + return false; + } + + try { + dataPerpustakaan.update.loading = true; + + const response = await fetch( + `/api/pendidikan/perpustakaandigital/dataperpustakaan/${this.id}`, + { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + judul: this.form.judul, + deskripsi: this.form.deskripsi, + imageId: this.form.imageId, + kategoriId: this.form.kategoriId, + }), + } + ); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error( + errorData.message || `HTTP error! status: ${response.status}` + ); + } + + const result = await response.json(); + + if (result.success) { + toast.success("Berhasil update data perpustakaan digital"); + await dataPerpustakaan.findMany.load(); // refresh list + return true; + } else { + throw new Error( + result.message || "Gagal update data perpustakaan digital" + ); + } + } catch (error) { + console.error("Error updating data perpustakaan digital:", error); + toast.error( + error instanceof Error + ? error.message + : "Terjadi kesalahan saat update data perpustakaan digital" + ); + return false; + } finally { + dataPerpustakaan.update.loading = false; + } + }, + reset() { + dataPerpustakaan.update.id = ""; + dataPerpustakaan.update.form = { ...defaultDataPerpustakaan }; + }, + }, +}); + +const templateKategoriBuku = z.object({ + name: z.string().min(1, "Nama harus diisi"), +}); + +const defaultKategoriBuku = { + name: "", +}; + +const kategoriBuku = proxy({ + create: { + form: { ...defaultKategoriBuku }, + loading: false, + async create() { + const cek = templateKategoriBuku.safeParse(kategoriBuku.create.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + return toast.error(err); + } + + try { + kategoriBuku.create.loading = true; + const res = + await ApiFetch.api.pendidikan.perpustakaandigital.kategoribuku[ + "create" + ].post(kategoriBuku.create.form); + if (res.status === 200) { + kategoriBuku.findMany.load(); + return toast.success("Data Kategori Buku Berhasil Dibuat"); + } + console.log(res); + return toast.error("failed create"); + } catch (error) { + console.log(error); + return toast.error("failed create"); + } finally { + kategoriBuku.create.loading = false; + } + }, + }, + findMany: { + data: [] as Prisma.KategoriBukuGetPayload<{ + omit: { + isActive: true; + }; + }>[], + loading: false, + async load() { + const res = + await ApiFetch.api.pendidikan.perpustakaandigital.kategoribuku[ + "findMany" + ].get(); + if (res.status === 200) { + kategoriBuku.findMany.data = res.data?.data ?? []; + } + }, + }, + findUnique: { + data: null as Prisma.KategoriBukuGetPayload<{ + omit: { + isActive: true; + }; + }> | null, + loading: false, + async load(id: string) { + try { + const res = await fetch( + `/api/pendidikan/perpustakaandigital/kategoribuku/${id}` + ); + if (res.ok) { + const data = await res.json(); + kategoriBuku.findUnique.data = data.data ?? null; + } else { + console.error("Failed to fetch data", res.status, res.statusText); + kategoriBuku.findUnique.data = null; + } + } catch (error) { + console.error("Error fetching data:", error); + kategoriBuku.findUnique.data = null; + } + }, + }, + delete: { + loading: false, + async delete(id: string) { + if (!id) return toast.warn("ID tidak valid"); + + try { + kategoriBuku.delete.loading = true; + + const response = await fetch( + `/api/pendidikan/perpustakaandigital/kategoribuku/del/${id}`, + { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + } + ); + + const result = await response.json(); + + if (response.ok && result?.success) { + toast.success( + result.message || "Data Kategori Buku berhasil dihapus" + ); + await kategoriBuku.findMany.load(); // refresh list + } else { + toast.error(result?.message || "Gagal menghapus Data Kategori Buku"); + } + } catch (error) { + console.error("Gagal delete:", error); + toast.error("Terjadi kesalahan saat menghapus Data Kategori Buku"); + } finally { + kategoriBuku.delete.loading = false; + } + }, + }, + update: { + id: "", + form: { ...defaultKategoriBuku }, + loading: false, + async load(id: string) { + if (!id) { + toast.warn("ID tidak valid"); + return null; + } + + try { + const response = await fetch( + `/api/pendidikan/perpustakaandigital/kategoribuku/${id}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + + if (result?.success) { + const data = result.data; + this.id = data.id; + this.form = { + name: data.name, + }; + return data; // Return the loaded data + } else { + throw new Error(result?.message || "Gagal memuat data"); + } + } catch (error) { + console.error("Error loading kategori buku:", error); + toast.error( + error instanceof Error ? error.message : "Gagal memuat data" + ); + return null; + } + }, + async update() { + const cek = templateKategoriBuku.safeParse(kategoriBuku.update.form); + if (!cek.success) { + const err = `[${cek.error.issues + .map((v) => `${v.path.join(".")}`) + .join("\n")}] required`; + toast.error(err); + return false; + } + + try { + kategoriBuku.update.loading = true; + + const response = await fetch( + `/api/pendidikan/perpustakaandigital/kategoribuku/${this.id}`, + { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name: this.form.name, + }), + } + ); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error( + errorData.message || `HTTP error! status: ${response.status}` + ); + } + + const result = await response.json(); + + if (result.success) { + toast.success("Berhasil update data kategori buku"); + await kategoriBuku.findMany.load(); // refresh list + return true; + } else { + throw new Error(result.message || "Gagal update data kategori buku"); + } + } catch (error) { + console.error("Error updating data kategori buku:", error); + toast.error( + error instanceof Error + ? error.message + : "Terjadi kesalahan saat update data kategori buku" + ); + return false; + } finally { + kategoriBuku.update.loading = false; + } + }, + reset() { + kategoriBuku.update.id = ""; + kategoriBuku.update.form = { ...defaultKategoriBuku }; + }, + }, +}); + +const perpustakaanDigitalState = proxy({ + dataPerpustakaan, + kategoriBuku, +}); + +export default perpustakaanDigitalState; diff --git a/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/maskot_desa/page.tsx b/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/maskot_desa/page.tsx index 5a2c5505..b252024a 100644 --- a/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/maskot_desa/page.tsx +++ b/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/maskot_desa/page.tsx @@ -148,7 +148,6 @@ function Page() { Gambar { const newImages = files.map((file) => ({ file, diff --git a/src/app/admin/(dashboard)/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/_lib/layoutTabs.tsx b/src/app/admin/(dashboard)/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/_lib/layoutTabs.tsx index fb8a133b..e56ed08c 100644 --- a/src/app/admin/(dashboard)/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/_lib/layoutTabs.tsx +++ b/src/app/admin/(dashboard)/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/_lib/layoutTabs.tsx @@ -12,17 +12,17 @@ function LayoutTabs({ children }: { children: React.ReactNode }) { { label: "Posisi Organisasi", value: "posisiorganisasi", - href: "/admin/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/posisi-organisasi" + href: "/admin/ekonomi/Struktur-Organisasi-dan-SK-Pengurus-BUMDesa/posisi-organisasi" }, { label: "Pegawai", value: "pegawai", - href: "/admin/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/pegawai" + href: "/admin/ekonomi/Struktur-Organisasi-dan-SK-Pengurus-BUMDesa/pegawai" }, { label: "Hubungan Organisasi", value: "hubunganorganisasi", - href: "/admin/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/hubungan-organisasi" + href: "/admin/ekonomi/Struktur-Organisasi-dan-SK-Pengurus-BUMDesa/hubungan-organisasi" }, ]; const curentTab = tabs.find(tab => tab.href === pathname) diff --git a/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/_lib/layoutTabs.tsx b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/_lib/layoutTabs.tsx new file mode 100644 index 00000000..63543d4f --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/_lib/layoutTabs.tsx @@ -0,0 +1,63 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import colors from '@/con/colors'; +import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core'; +import { usePathname, useRouter } from 'next/navigation'; +import React, { useEffect, useState } from 'react'; + +function LayoutTabs({ children }: { children: React.ReactNode }) { + const router = useRouter() + const pathname = usePathname() + const tabs = [ + { + label: "Data Perpustakaan", + value: "data-perpustakaan", + href: "/admin/pendidikan/perpustakaan-digital/data-perpustakaan" + }, + { + label: "Kategori Buku", + value: "kategori-buku", + href: "/admin/pendidikan/perpustakaan-digital/kategori-buku" + }, + + ]; + const curentTab = tabs.find(tab => tab.href === pathname) + const [activeTab, setActiveTab] = useState(curentTab?.value || tabs[0].value); + + const handleTabChange = (value: string | null) => { + const tab = tabs.find(t => t.value === value) + if (tab) { + router.push(tab.href) + } + setActiveTab(value) + } + + useEffect(() => { + const match = tabs.find(tab => tab.href === pathname) + if (match) { + setActiveTab(match.value) + } + }, [pathname]) + + return ( + + Perpustakaan Digital + + + {tabs.map((e, i) => ( + {e.label} + ))} + + {tabs.map((e, i) => ( + + {/* Konten dummy, bisa diganti tergantung routing */} + <> + + ))} + + {children} + + ); +} + +export default LayoutTabs; \ No newline at end of file diff --git a/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/data-perpustakaan/[id]/edit/page.tsx b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/data-perpustakaan/[id]/edit/page.tsx new file mode 100644 index 00000000..9f607565 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/data-perpustakaan/[id]/edit/page.tsx @@ -0,0 +1,198 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import EditEditor from '@/app/admin/(dashboard)/_com/editEditor'; +import perpustakaanDigitalState from '@/app/admin/(dashboard)/_state/pendidikan/perpustakaan-digital'; +import colors from '@/con/colors'; +import ApiFetch from '@/lib/api-fetch'; +import { Box, Button, Group, Image, Paper, Select, Stack, Text, TextInput, Title } from '@mantine/core'; +import { Dropzone } from '@mantine/dropzone'; +import { IconArrowBack, IconPhoto, IconUpload, IconX } 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 EditPasarDesa() { + const editState = useProxy(perpustakaanDigitalState.dataPerpustakaan) + const router = useRouter(); + const params = useParams(); + + const [previewImage, setPreviewImage] = useState(null); + const [file, setFile] = useState(null); + const [formData, setFormData] = useState({ + judul: editState.update.form.judul || "", + deskripsi: editState.update.form.deskripsi || "", + imageId: editState.update.form.imageId || "", + kategoriId: editState.update.form.kategoriId || "", + }) + + useEffect(() => { + perpustakaanDigitalState.kategoriBuku.findMany.load(); + const loadDataPerpustakaan = async () => { + const id = params?.id as string; + if (!id) return; + + try { + const data = await editState.update.load(id); + if (data) { + setFormData({ + judul: data.judul || "", + deskripsi: data.deskripsi || "", + imageId: data.imageId || "", + kategoriId: data.kategoriId || "", + }); + // Tampilkan preview gambar + if (data.image?.link) { + setPreviewImage(data.image.link); + } + } + } catch (error) { + console.error("Error loading data perpustakaan:", error); + toast.error( + error instanceof Error ? error.message : "Gagal mengambil data perpustakaan" + ); + } + } + + loadDataPerpustakaan(); + }, [params?.id]); + + const handleSubmit = async () => { + try { + editState.update.form = { + ...editState.update.form, + judul: formData.judul, + deskripsi: formData.deskripsi, + kategoriId: formData.kategoriId, + imageId: formData.imageId, + } + if (file) { + const res = await ApiFetch.api.fileStorage.create.post({ file, name: file.name }); + const uploaded = res.data?.data; + + if (!uploaded?.id) { + return toast.error("Gagal upload gambar"); + } + + // Update imageId in global state + editState.update.form.imageId = uploaded.id; + } + + await editState.update.update(); + toast.success("Data perpustakaan berhasil diperbarui!"); + router.push("/admin/pendidikan/perpustakaan-digital/data-perpustakaan"); + } catch (error) { + console.error("Error updating data perpustakaan:", error); + toast.error("Terjadi kesalahan saat memperbarui data perpustakaan"); + } + }; + + return ( + + + + + + + + Edit Data Perpustakaan + + Gambar + + { + const selectedFile = files[0]; // Ambil file pertama + if (selectedFile) { + setFile(selectedFile); + setPreviewImage(URL.createObjectURL(selectedFile)); // Buat preview + } + }} + onReject={() => toast.error('File tidak valid.')} + maxSize={5 * 1024 ** 2} // Maks 5MB + accept={{ 'image/*': [] }} + > + + + + + + + + + + + +
+ + Drag gambar ke sini atau klik untuk pilih file + + + Maksimal 5MB dan harus format gambar + +
+
+
+ + {/* Tampilkan preview kalau ada */} + {previewImage && ( + + Preview + + )} + +
+
+ setFormData({ ...formData, judul: e.target.value })} + label={Judul} + placeholder='Masukkan judul' + /> + + Deskripsi + { + setFormData({ ...formData, deskripsi: val }); + }} + /> + + Kategori} + placeholder='Pilih kategori' + value={createState.create.form.kategoriId || ""} + onChange={(val) => { + createState.create.form.kategoriId = val ?? ""; + }} + data={perpustakaanDigitalState.kategoriBuku.findMany.data?.map((item) => ({ + value: item.id, + label: item.name, + }))} + /> + + Gambar + + { + const selectedFile = files[0]; // Ambil file pertama + if (selectedFile) { + setFile(selectedFile); + setPreviewImage(URL.createObjectURL(selectedFile)); // Buat preview + } + }} + onReject={() => toast.error('File tidak valid.')} + maxSize={5 * 1024 ** 2} // Maks 5MB + accept={{ 'image/*': [] }} + > + + + + + + + + + + + +
+ + Drag gambar ke sini atau klik untuk pilih file + + + Maksimal 5MB dan harus format gambar + +
+
+
+ + {/* Tampilkan preview kalau ada */} + {previewImage && ( + + Preview + + )} + +
+
+ + + +
+
+
+ ); +} + +export default CreateDataPerpustakaan; diff --git a/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/data-perpustakaan/page.tsx b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/data-perpustakaan/page.tsx new file mode 100644 index 00000000..9f6fb391 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/data-perpustakaan/page.tsx @@ -0,0 +1,104 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; +import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { useProxy } from 'valtio/utils'; +import HeaderSearch from '../../../_com/header'; +import JudulList from '../../../_com/judulList'; +import perpustakaanDigitalState from '../../../_state/pendidikan/perpustakaan-digital'; + + + +function DataPerpustakaan() { + const [search, setSearch] = useState(''); + return ( + + } + value={search} + onChange={(e) => setSearch(e.currentTarget.value)} + /> + + + ); +} + +function ListDataPerpustakaan({ search }: { search: string }) { + const listDataState = useProxy(perpustakaanDigitalState.dataPerpustakaan) + const router = useRouter(); + + useEffect(() => { + perpustakaanDigitalState.dataPerpustakaan.findMany.load() + listDataState.findMany.load() + }, []) + + const filteredData = (listDataState.findMany.data || []).filter(item => { + const keyword = search.toLowerCase(); + return ( + item.judul.toLowerCase().includes(keyword) || + item.deskripsi.toLowerCase().includes(keyword) || + item.kategori.name.toLowerCase().includes(keyword) + ); + }); + + if (!listDataState.findMany.data) { + return ( + + + + ) + } + return ( + + + + + + + + + No + Judul + Kategori + Detail + + + + {filteredData.map((item, index) => ( + + + + {index + 1} + + + + {item.judul} + + + {item.kategori.name} + + + + + + ))} + +
+
+
+
+
+ ) +} + +export default DataPerpustakaan; diff --git a/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/kategori-buku/[id]/page.tsx b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/kategori-buku/[id]/page.tsx new file mode 100644 index 00000000..0db1c670 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/kategori-buku/[id]/page.tsx @@ -0,0 +1,80 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import perpustakaanDigitalState from '@/app/admin/(dashboard)/_state/pendidikan/perpustakaan-digital'; +import colors from '@/con/colors'; +import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +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 EditKategoriBuku() { + const editState = useProxy(perpustakaanDigitalState.kategoriBuku) + const router = useRouter(); + const params = useParams(); + const [formData, setFormData] = useState({ + name: editState.update.form.name || '', + }); + + useEffect(() => { + const loadKategori = async () => { + const id = params?.id as string; + if (!id) return; + + try { + const data = await editState.update.load(id); // akses langsung, bukan dari proxy + if (data) { + setFormData({ + name: data.name || '', + }); + } + } catch (error) { + console.error("Error loading kategori buku:", error); + toast.error("Gagal memuat data kategori buku"); + } + }; + + loadKategori(); + }, [params?.id]); + + const handleSubmit = async () => { + try { + editState.update.form = { + ...editState.update.form, + name: formData.name, + }; + await editState.update.update(); + toast.success('Kategori Buku berhasil diperbarui!'); + router.push('/admin/pendidikan/perpustakaan-digital/kategori-buku'); + } catch (error) { + console.error('Error updating kategori buku:', error); + toast.error('Terjadi kesalahan saat memperbarui kategori buku'); + } + }; + + return ( + + + + + + + Edit Kategori Buku + setFormData({ ...formData, name: e.target.value })} + label={Nama Kategori Buku} + placeholder="masukkan nama kategori buku" + /> + + + + + + ); +} + +export default EditKategoriBuku; diff --git a/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/kategori-buku/create/page.tsx b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/kategori-buku/create/page.tsx new file mode 100644 index 00000000..7bc11e2e --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/kategori-buku/create/page.tsx @@ -0,0 +1,55 @@ +'use client' +import perpustakaanDigitalState from '@/app/admin/(dashboard)/_state/pendidikan/perpustakaan-digital'; +import colors from '@/con/colors'; +import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; + + + +function CreateKategoriBuku() { + const createState = useProxy(perpustakaanDigitalState.kategoriBuku) + const router = useRouter(); + + const resetForm = () => { + createState.create.form = { + name: "", + }; + }; + + const handleSubmit = async () => { + await createState.create.create(); + resetForm(); + router.push("/admin/pendidikan/perpustakaan-digital/kategori-buku") + }; + + return ( + + + + + + + + Create Kategori Buku + Nama Kategori Buku} + placeholder='Masukkan nama kategori buku' + value={createState.create.form.name} + onChange={(val) => { + createState.create.form.name = val.target.value; + }} + /> + + + + + + + ); +} + +export default CreateKategoriBuku; diff --git a/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/kategori-buku/page.tsx b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/kategori-buku/page.tsx new file mode 100644 index 00000000..e8245d18 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/kategori-buku/page.tsx @@ -0,0 +1,128 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core'; +import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { useProxy } from 'valtio/utils'; +import HeaderSearch from '../../../_com/header'; +import JudulList from '../../../_com/judulList'; +import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus'; +import perpustakaanDigitalState from '../../../_state/pendidikan/perpustakaan-digital'; + + + +function KategoriBuku() { + const [search, setSearch] = useState(''); + return ( + + } + value={search} + onChange={(e) => setSearch(e.currentTarget.value)} + /> + + + ); +} + +function ListKategoriBuku({ search }: { search: string }) { + const listDataState = useProxy(perpustakaanDigitalState.kategoriBuku) + const router = useRouter(); + const [modalHapus, setModalHapus] = useState(false) + const [selectedId, setSelectedId] = useState(null) + + useEffect(() => { + listDataState.findMany.load() + }, []) + + const handleDelete = () => { + if (selectedId) { + perpustakaanDigitalState.kategoriBuku.delete.delete(selectedId) + setModalHapus(false) + setSelectedId(null) + + perpustakaanDigitalState.kategoriBuku.findMany.load() + } + } + + const filteredData = (listDataState.findMany.data || []).filter(item => { + const keyword = search.toLowerCase(); + return ( + item.name.toLowerCase().includes(keyword) + ); + }); + + if (!listDataState.findMany.data) { + return ( + + + + ) + } + return ( + + + + + + + + + No + Nama + Edit + Hapus + + + + {filteredData.map((item, index) => ( + + + + {index + 1} + + + {item.name} + + + + + + + + ))} + +
+
+
+
+ + {/* Modal Konfirmasi Hapus */} + setModalHapus(false)} + onConfirm={handleDelete} + text='Apakah anda yakin ingin menghapus kategori buku ini?' + /> +
+ ) +} + +export default KategoriBuku; diff --git a/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/layout.tsx b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/layout.tsx new file mode 100644 index 00000000..4f25d331 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/layout.tsx @@ -0,0 +1,13 @@ +'use client' +import React from 'react'; +import LayoutTabs from './_lib/layoutTabs'; + +function Layout({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} + +export default Layout; diff --git a/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/page.tsx b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/page.tsx deleted file mode 100644 index cb057167..00000000 --- a/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/page.tsx +++ /dev/null @@ -1,74 +0,0 @@ -'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 { useRouter } from 'next/navigation'; -import HeaderSearch from '../../_com/header'; -import JudulList from '../../_com/judulList'; - -function PerpustakaanDigital() { - return ( - - } - /> - - - ); -} - -function ListPerpustakaanDigital() { - const router = useRouter(); - return ( - - - - - - - - - Nomor - Nama Lengkap - Nomor Telepon - Email - Detail - - - - - - - 1 - - - - Nama Lengkap - - - Nomor Telepon - - - Email - - - - - - -
-
-
-
-
- ) -} - -export default PerpustakaanDigital; diff --git a/src/app/admin/_com/list_PageAdmin.tsx b/src/app/admin/_com/list_PageAdmin.tsx index 370feda9..2efda014 100644 --- a/src/app/admin/_com/list_PageAdmin.tsx +++ b/src/app/admin/_com/list_PageAdmin.tsx @@ -225,7 +225,7 @@ export const navBar = [ { id: "Ekonomi_3", name: "Struktur Organisasi dan SK Pengurus BUMDesa", - path: "/admin/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/posisi-organisasi" + path: "/admin/ekonomi/Struktur-Organisasi-dan-SK-Pengurus-BUMDesa/posisi-organisasi" }, { id: "Ekonomi_4", @@ -369,7 +369,7 @@ export const navBar = [ { id: "Pendidikan_6", name: "Perpustakaan Digital", - path: "/admin/pendidikan/perpustakaan-digital" + path: "/admin/pendidikan/perpustakaan-digital/data-perpustakaan" }, { id: "Pendidikan_7", diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts index ed4b40a6..ebbc947f 100644 --- a/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts @@ -5,6 +5,7 @@ import BimbinganBelajarDesa from "./bimbingan-belajar-desa"; import PendidikanNonFormal from "./pendidikan-non-formal"; import DataPendidikan from "./data-pendidikan"; import Beasiswa from "./beasiswa-desa"; +import PerpustakaanDigital from "./perpustakaan-digital"; const Pendidikan = new Elysia({ prefix: "/api/pendidikan", @@ -17,5 +18,6 @@ const Pendidikan = new Elysia({ .use(PendidikanNonFormal) .use(DataPendidikan) .use(Beasiswa) +.use(PerpustakaanDigital) export default Pendidikan; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/create.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/create.ts new file mode 100644 index 00000000..69a45851 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/create.ts @@ -0,0 +1,32 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type FormCreate = { + judul: string; + deskripsi: string; + imageId: string; + kategoriId: string; +} + +export default async function dataPerpustakaanCreate(context: Context) { + const body = (await context.body) as FormCreate; + + try { + const result = await prisma.dataPerpustakaan.create({ + data: { + judul: body.judul, + deskripsi: body.deskripsi, + imageId: body.imageId, + kategoriId: body.kategoriId, + }, + }); + return { + success: true, + message: "Berhasil membuat data perpustakaan", + data: result, + }; + } catch (error) { + console.error("Error creating data perpustakaan:", error); + throw new Error("Gagal membuat data perpustakaan: " + (error as Error).message); + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/del.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/del.ts new file mode 100644 index 00000000..74b1004f --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/del.ts @@ -0,0 +1,16 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function dataPerpustakaanDelete(context: Context) { + const id = context.params.id as string; + + await prisma.dataPerpustakaan.delete({ + where: { id }, + }); + + return { + status: 200, + success: true, + message: "Success delete data perpustakaan", + }; +} diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/findMany.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/findMany.ts new file mode 100644 index 00000000..37ef5433 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/findMany.ts @@ -0,0 +1,16 @@ +import prisma from "@/lib/prisma"; + +export default async function dataPerpustakaanFindMany() { + const data = await prisma.dataPerpustakaan.findMany({ + include: { + kategori: true, + image: true, + }, + }); + + return { + success: true, + message: "Success get all data perpustakaan", + data, + }; +} diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/findUnique.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/findUnique.ts new file mode 100644 index 00000000..84a87961 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/findUnique.ts @@ -0,0 +1,50 @@ +import prisma from "@/lib/prisma"; + +export default async function dataPerpustakaanFindUnique(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const id = pathSegments[pathSegments.length - 1]; + + if (!id) { + return { + success: false, + message: "ID is required", + } + } + + try { + if (typeof id !== 'string') { + return { + success: false, + message: "ID is required", + } + } + + const data = await prisma.dataPerpustakaan.findUnique({ + where: { id }, + include: { + kategori: true, + image: true, + }, + }); + + if (!data) { + return { + success: false, + message: "Data not found", + } + } + + return { + success: true, + message: "Success get data perpustakaan", + data, + } + } catch (error) { + console.error("Find by ID error:", error); + return { + success: false, + message: "Gagal mengambil data: " + (error instanceof Error ? error.message : 'Unknown error'), + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/index.ts new file mode 100644 index 00000000..768f4bba --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/index.ts @@ -0,0 +1,39 @@ +import Elysia, { t } from "elysia"; +import dataPerpustakaanCreate from "./create"; +import dataPerpustakaanDelete from "./del"; +import dataPerpustakaanFindMany from "./findMany"; +import dataPerpustakaanFindUnique from "./findUnique"; +import dataPerpustakaanUpdate from "./updt"; + +const DataPerpustakaan = new Elysia({ + prefix: "/dataperpustakaan", + tags: ["Pendidikan / Perpustakaan Digital / Data Perpustakaan"], +}) + + .post("/create", dataPerpustakaanCreate, { + body: t.Object({ + judul: t.String(), + deskripsi: t.String(), + imageId: t.String(), + kategoriId: t.String(), + }), + }) + + .get("/findMany", dataPerpustakaanFindMany) + .get("/:id", async (context) => { + const response = await dataPerpustakaanFindUnique( + new Request(context.request) + ); + return response; + }) + .put("/:id", dataPerpustakaanUpdate, { + body: t.Object({ + judul: t.String(), + deskripsi: t.String(), + imageId: t.String(), + kategoriId: t.String(), + }), + }) + .delete("/del/:id", dataPerpustakaanDelete); + +export default DataPerpustakaan; diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/updt.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/updt.ts new file mode 100644 index 00000000..3b2226f7 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/data-perpustakaan/updt.ts @@ -0,0 +1,35 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type FormUpdate = { + judul: string; + deskripsi: string; + imageId: string; + kategoriId: string; +} + +export default async function dataPerpustakaanUpdate(context: Context) { + const body = (await context.body) as FormUpdate; + const id = context.params.id as string; + + try { + const result = await prisma.dataPerpustakaan.update({ + where: { id }, + data: { + judul: body.judul, + deskripsi: body.deskripsi, + imageId: body.imageId, + kategoriId: body.kategoriId, + }, + }); + return { + success: true, + message: "Berhasil mengupdate data perpustakaan", + data: result, + }; + } catch (error) { + console.error("Error updating data perpustakaan:", error); + throw new Error("Gagal mengupdate data perpustakaan: " + (error as Error).message); + } +} + \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/index.ts new file mode 100644 index 00000000..c2abe457 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/index.ts @@ -0,0 +1,12 @@ +import Elysia from "elysia"; +import DataPerpustakaan from "./data-perpustakaan"; +import KategoriBuku from "./kategori-buku"; + +const PerpustakaanDigital = new Elysia({ + prefix: "/perpustakaandigital", + tags: ["Pendidikan / Perpustakaan Digital"], +}) + .use(DataPerpustakaan) + .use(KategoriBuku); + +export default PerpustakaanDigital; diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/create.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/create.ts new file mode 100644 index 00000000..bc6fb491 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/create.ts @@ -0,0 +1,26 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type FormCreate = { + name: string; +} + +export default async function kategoriBukuCreate(context: Context) { + const body = (await context.body) as FormCreate; + + try { + const result = await prisma.kategoriBuku.create({ + data: { + name: body.name, + }, + }); + return { + success: true, + message: "Berhasil membuat kategori buku", + data: result, + }; + } catch (error) { + console.error("Error creating kategori buku:", error); + throw new Error("Gagal membuat kategori buku: " + (error as Error).message); + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/del.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/del.ts new file mode 100644 index 00000000..c6f300a7 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/del.ts @@ -0,0 +1,16 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function kategoriBukuDelete(context: Context) { + const id = context.params.id as string; + + await prisma.kategoriBuku.delete({ + where: { id }, + }); + + return { + status: 200, + success: true, + message: "Success delete kategori buku", + }; +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/findMany.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/findMany.ts new file mode 100644 index 00000000..a764fe41 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/findMany.ts @@ -0,0 +1,11 @@ +import prisma from "@/lib/prisma"; + +export default async function kategoriBukuFindMany() { + const data = await prisma.kategoriBuku.findMany(); + + return { + success: true, + message: "Success get all kategori buku", + data, + }; +} diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/findUnique.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/findUnique.ts new file mode 100644 index 00000000..631b927a --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/findUnique.ts @@ -0,0 +1,46 @@ +import prisma from "@/lib/prisma"; + +export default async function kategoriBukuFindUnique(request: Request) { + const url = new URL(request.url); + const pathSegments = url.pathname.split('/'); + const id = pathSegments[pathSegments.length - 1]; + + if (!id) { + return { + success: false, + message: "ID is required", + } + } + + try { + if (typeof id !== 'string') { + return { + success: false, + message: "ID is required", + } + } + + const data = await prisma.kategoriBuku.findUnique({ + where: { id }, + }); + + if (!data) { + return { + success: false, + message: "Data not found", + } + } + + return { + success: true, + message: "Success get kategori buku", + data, + } + } catch (error) { + console.error("Find by ID error:", error); + return { + success: false, + message: "Gagal mengambil data: " + (error instanceof Error ? error.message : 'Unknown error'), + } + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/index.ts new file mode 100644 index 00000000..6ef2bbfd --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/index.ts @@ -0,0 +1,33 @@ +import Elysia, { t } from "elysia"; +import kategoriBukuCreate from "./create"; +import kategoriBukuDelete from "./del"; +import kategoriBukuFindMany from "./findMany"; +import kategoriBukuFindUnique from "./findUnique"; +import kategoriBukuUpdate from "./updt"; + +const KategoriBuku = new Elysia({ + prefix: "/kategoribuku", + tags: ["Pendidikan / Perpustakaan Digital / Kategori Buku"], +}) + + .post("/create", kategoriBukuCreate, { + body: t.Object({ + name: t.String(), + }), + }) + + .get("/findMany", kategoriBukuFindMany) + .get("/:id", async (context) => { + const response = await kategoriBukuFindUnique( + new Request(context.request) + ); + return response; + }) + .put("/:id", kategoriBukuUpdate, { + body: t.Object({ + name: t.String(), + }), + }) + .delete("/del/:id", kategoriBukuDelete); + +export default KategoriBuku; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/updt.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/updt.ts new file mode 100644 index 00000000..a0516393 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/perpustakaan-digital/kategori-buku/updt.ts @@ -0,0 +1,28 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +type FormUpdate = { + name: string; +} + +export default async function kategoriBukuUpdate(context: Context) { + const body = (await context.body) as FormUpdate; + const id = context.params.id as string; + + try { + const result = await prisma.kategoriBuku.update({ + where: { id }, + data: { + name: body.name, + }, + }); + return { + success: true, + message: "Berhasil mengupdate kategori buku", + data: result, + }; + } catch (error) { + console.error("Error updating kategori buku:", error); + throw new Error("Gagal mengupdate kategori buku: " + (error as Error).message); + } +} \ No newline at end of file diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index a543cfbc..9a7611bc 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -12,7 +12,7 @@ function Page() {
- +
diff --git a/src/app/registrasi/page.tsx b/src/app/registrasi/page.tsx index 115d4fb0..92188f35 100644 --- a/src/app/registrasi/page.tsx +++ b/src/app/registrasi/page.tsx @@ -12,7 +12,7 @@ function Page() { </Box> <Box px={{ base: 'md', md: 100 }} > <Center> - <Image src={"/api/img/darmasaba-icon.png"} alt="" w={80} /> + <Image src={"/darmasaba-icon.png"} alt="" w={80} /> </Center> <Box> <Title ta={'center'} order={1} fw={'bold'} c={colors['blue-button']}>