From ac0eb926ebd6c1e9d446297a2e9ba5ce125bfd2b Mon Sep 17 00:00:00 2001 From: nico Date: Mon, 28 Jul 2025 16:45:36 +0800 Subject: [PATCH] UI & API Menu Pendidikan & Submenu Bimbingan Belajar Desa --- .../fasilitas-yang-disediakan.json | 7 + .../lokasi-dan-jadwal.json | 7 + .../tujuan-bimbingan-belajar-desa.json | 7 + .../program-unggulan.json | 7 + .../tujuan-program.json | 7 + prisma/schema.prisma | 118 +++++--- prisma/seed.ts | 85 ++++++ .../pendidikan/bimbingan-belajar-desa.ts | 260 ++++++++++++++++++ .../pendidikan/program-pendidikan-anak.ts | 181 ++++++++++++ .../_lib/bimbinganBelajarDesaTextEditor.tsx | 99 +++++++ .../_lib/layoutTabs.tsx | 68 +++++ .../fasilitas-yang-disediakan/edit/page.tsx | 86 ++++++ .../fasilitas-yang-disediakan/page.tsx | 54 ++++ .../bimbingan-belajar-desa/layout.tsx | 12 + .../lokasi-dan-jadwal/edit/page.tsx | 86 ++++++ .../lokasi-dan-jadwal/page.tsx | 54 ++++ .../bimbingan-belajar-desa/page.tsx | 74 ----- .../tujuan-program/edit/page.tsx | 86 ++++++ .../tujuan-program/page.tsx | 54 ++++ .../_lib/layoutTabs.tsx | 62 +++++ .../_lib/programPendidikanAnakTextEditor.tsx | 100 +++++++ .../program-pendidikan-anak/layout.tsx | 11 + .../program-pendidikan-anak/page.tsx | 74 ----- .../program-unggulan/edit/page.tsx | 86 ++++++ .../program-unggulan/page.tsx | 54 ++++ .../tujuan-program/edit/page.tsx | 86 ++++++ .../tujuan-program/page.tsx | 54 ++++ src/app/admin/_com/list_PageAdmin.tsx | 4 +- .../findUnique.ts | 60 ++-- .../fasilitas-yang-disediakan/findUnique.ts | 37 +++ .../fasilitas-yang-disediakan/index.ts | 18 ++ .../fasilitas-yang-disediakan/updt.ts | 29 ++ .../bimbingan-belajar-desa/index.ts | 14 + .../lokasi-dan-jadwal/findUnique.ts | 37 +++ .../lokasi-dan-jadwal/index.ts | 18 ++ .../lokasi-dan-jadwal/updt.ts | 29 ++ .../tujuan-program/findUnique.ts | 37 +++ .../tujuan-program/index.ts | 18 ++ .../tujuan-program/updt.ts | 29 ++ .../api/[[...slugs]]/_lib/pendidikan/index.ts | 4 + .../program-pendidikan-anak/index.ts | 12 + .../program-unggulan/findUnique.ts | 33 +++ .../program-unggulan/index.ts | 18 ++ .../program-unggulan/updt.ts | 29 ++ .../tujuan-program/findUnique.ts | 37 +++ .../tujuan-program/index.ts | 18 ++ .../tujuan-program/updt.ts | 29 ++ 47 files changed, 2178 insertions(+), 211 deletions(-) create mode 100644 prisma/data/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan.json create mode 100644 prisma/data/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal.json create mode 100644 prisma/data/pendidikan/bimbingan-belajar-desa/tujuan-bimbingan-belajar-desa.json create mode 100644 prisma/data/pendidikan/program-pendidikan-anak/program-unggulan.json create mode 100644 prisma/data/pendidikan/program-pendidikan-anak/tujuan-program.json create mode 100644 src/app/admin/(dashboard)/_state/pendidikan/bimbingan-belajar-desa.ts create mode 100644 src/app/admin/(dashboard)/_state/pendidikan/program-pendidikan-anak.ts create mode 100644 src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/_lib/bimbinganBelajarDesaTextEditor.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/_lib/layoutTabs.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/edit/page.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/page.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/layout.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/edit/page.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/page.tsx delete mode 100644 src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/page.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/tujuan-program/edit/page.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/tujuan-program/page.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/_lib/layoutTabs.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/_lib/programPendidikanAnakTextEditor.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/layout.tsx delete mode 100644 src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/page.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/program-unggulan/edit/page.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/program-unggulan/page.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/tujuan-program/edit/page.tsx create mode 100644 src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/tujuan-program/page.tsx create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/findUnique.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/index.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/updt.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/index.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/findUnique.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/index.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/updt.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/findUnique.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/index.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/updt.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/index.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/findUnique.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/index.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/updt.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/findUnique.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/index.ts create mode 100644 src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/updt.ts diff --git a/prisma/data/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan.json b/prisma/data/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan.json new file mode 100644 index 00000000..8b34a3e6 --- /dev/null +++ b/prisma/data/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan.json @@ -0,0 +1,7 @@ +[ + { + "id": "edit", + "judul": "Fasilitas yang Disediakan", + "deskripsi": "" + } +] \ No newline at end of file diff --git a/prisma/data/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal.json b/prisma/data/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal.json new file mode 100644 index 00000000..4a12868f --- /dev/null +++ b/prisma/data/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal.json @@ -0,0 +1,7 @@ +[ + { + "id": "edit", + "judul": "Lokasi dan Jadwal", + "deskripsi": "" + } +] \ No newline at end of file diff --git a/prisma/data/pendidikan/bimbingan-belajar-desa/tujuan-bimbingan-belajar-desa.json b/prisma/data/pendidikan/bimbingan-belajar-desa/tujuan-bimbingan-belajar-desa.json new file mode 100644 index 00000000..26d87bc2 --- /dev/null +++ b/prisma/data/pendidikan/bimbingan-belajar-desa/tujuan-bimbingan-belajar-desa.json @@ -0,0 +1,7 @@ +[ + { + "id": "edit", + "judul": "Tujuan Program", + "deskripsi": "" + } +] \ No newline at end of file diff --git a/prisma/data/pendidikan/program-pendidikan-anak/program-unggulan.json b/prisma/data/pendidikan/program-pendidikan-anak/program-unggulan.json new file mode 100644 index 00000000..b7d4291f --- /dev/null +++ b/prisma/data/pendidikan/program-pendidikan-anak/program-unggulan.json @@ -0,0 +1,7 @@ +[ + { + "id": "edit", + "judul": "Program Unggulan", + "deskripsi": "" + } +] diff --git a/prisma/data/pendidikan/program-pendidikan-anak/tujuan-program.json b/prisma/data/pendidikan/program-pendidikan-anak/tujuan-program.json new file mode 100644 index 00000000..8da34bb2 --- /dev/null +++ b/prisma/data/pendidikan/program-pendidikan-anak/tujuan-program.json @@ -0,0 +1,7 @@ +[ + { + "id": "edit", + "judul": "Tujuan Program", + "deskripsi": "" + } +] diff --git a/prisma/schema.prisma b/prisma/schema.prisma index db494111..a9aad026 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1795,46 +1795,98 @@ model NilaiKonservasiAdat { // ========================================= MENU PENDIDIKAN ========================================= // // ========================================= INFO SEKOLAH & PAUD ========================================= // model JenjangPendidikan { - id String @id @default(cuid()) - nama String // TK/PAUD, SD, SMP, SMA/SMK - lembagas Lembaga[] // Relasi ke lembaga - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + id String @id @default(cuid()) + nama String // TK/PAUD, SD, SMP, SMA/SMK + lembagas Lembaga[] // Relasi ke lembaga + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) } model Lembaga { - id String @id @default(cuid()) - nama String - jenjangPendidikan JenjangPendidikan @relation(fields: [jenjangId], references: [id]) - jenjangId String - siswa Siswa[] - pengajar Pengajar[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + id String @id @default(cuid()) + nama String + jenjangPendidikan JenjangPendidikan @relation(fields: [jenjangId], references: [id]) + jenjangId String + siswa Siswa[] + pengajar Pengajar[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) } model Siswa { - id String @id @default(cuid()) - nama String - lembaga Lembaga @relation(fields: [lembagaId], references: [id]) - lembagaId String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + id String @id @default(cuid()) + nama String + lembaga Lembaga @relation(fields: [lembagaId], references: [id]) + lembagaId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) } model Pengajar { - id String @id @default(cuid()) - nama String - lembaga Lembaga @relation(fields: [lembagaId], references: [id]) - lembagaId String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + id String @id @default(cuid()) + nama String + lembaga Lembaga @relation(fields: [lembagaId], references: [id]) + lembagaId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} + +// ========================================= PROGRAM PENDIDIKAN ANAK ========================================= // +model TujuanProgram { + id String @id @default(cuid()) + judul String + deskripsi String @db.Text + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} + +model ProgramUnggulan { + id String @id @default(cuid()) + judul String + deskripsi String @db.Text + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} + +// ========================================= BIMBINGAN BELAJAR DESA ========================================= // +model TujuanBimbinganBelajarDesa { + id String @id @default(cuid()) + judul String + deskripsi String @db.Text + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} + +model LokasiJadwalBimbinganBelajarDesa { + id String @id @default(cuid()) + judul String + deskripsi String @db.Text + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) +} + +model FasilitasBimbinganBelajarDesa { + id String @id @default(cuid()) + judul String + deskripsi String @db.Text + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) } diff --git a/prisma/seed.ts b/prisma/seed.ts index 40676081..91bbdac3 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -29,6 +29,11 @@ import nilaiKonservasiAdat from './data/lingkungan/konservasi-adat-bali/nilai-ko import bentukKonservasiBerdasarkanAdat from './data/lingkungan/konservasi-adat-bali/bentuk-konservasi.json'; import filosofiTriHita from './data/lingkungan/konservasi-adat-bali/filosofi-tri-hita.json'; import profilePejabatDesa from './data/landing-page/profile.json'; +import tujuanProgram from './data/pendidikan/program-pendidikan-anak/tujuan-program.json'; +import programUnggulan from './data/pendidikan/program-pendidikan-anak/program-unggulan.json'; +import tujuanBimbinganBelajarDesa from './data/pendidikan/bimbingan-belajar-desa/tujuan-bimbingan-belajar-desa.json'; +import lokasiJadwalBimbinganBelajarDesa from './data/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal.json'; +import fasilitasBimbinganBelajarDesa from './data/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan.json'; (async () => { for (const l of layanan) { @@ -594,6 +599,86 @@ import profilePejabatDesa from './data/landing-page/profile.json'; } console.log("✅ profilePejabatDesa seeded without imageId (editable later via UI)"); + for (const t of tujuanProgram) { + await prisma.tujuanProgram.upsert({ + where: { id: t.id }, + update: { + judul: t.judul, + deskripsi: t.deskripsi, + }, + create: { + id: t.id, + judul: t.judul, + deskripsi: t.deskripsi, + }, + }); + } + console.log("✅ tujuan program seeded (editable later via UI)"); + + for (const t of programUnggulan) { + await prisma.programUnggulan.upsert({ + where: { id: t.id }, + update: { + judul: t.judul, + deskripsi: t.deskripsi, + }, + create: { + id: t.id, + judul: t.judul, + deskripsi: t.deskripsi, + }, + }); + } + console.log("✅ program unggulan seeded (editable later via UI)"); + + for (const t of tujuanBimbinganBelajarDesa) { + await prisma.tujuanBimbinganBelajarDesa.upsert({ + where: { id: t.id }, + update: { + judul: t.judul, + deskripsi: t.deskripsi, + }, + create: { + id: t.id, + judul: t.judul, + deskripsi: t.deskripsi, + }, + }); + } + console.log("✅ tujuan bimbingan belajar desa seeded (editable later via UI)"); + + for (const t of lokasiJadwalBimbinganBelajarDesa) { + await prisma.lokasiJadwalBimbinganBelajarDesa.upsert({ + where: { id: t.id }, + update: { + judul: t.judul, + deskripsi: t.deskripsi, + }, + create: { + id: t.id, + judul: t.judul, + deskripsi: t.deskripsi, + }, + }); + } + console.log("✅ lokasi jadwal bimbingan belajar desa seeded (editable later via UI)"); + + for (const t of fasilitasBimbinganBelajarDesa) { + await prisma.fasilitasBimbinganBelajarDesa.upsert({ + where: { id: t.id }, + update: { + judul: t.judul, + deskripsi: t.deskripsi, + }, + create: { + id: t.id, + judul: t.judul, + deskripsi: t.deskripsi, + }, + }); + } + console.log("✅ fasilitas bimbingan belajar desa seeded (editable later via UI)"); + })() .then(() => prisma.$disconnect()) .catch((e) => { diff --git a/src/app/admin/(dashboard)/_state/pendidikan/bimbingan-belajar-desa.ts b/src/app/admin/(dashboard)/_state/pendidikan/bimbingan-belajar-desa.ts new file mode 100644 index 00000000..2c29ee46 --- /dev/null +++ b/src/app/admin/(dashboard)/_state/pendidikan/bimbingan-belajar-desa.ts @@ -0,0 +1,260 @@ +import ApiFetch from "@/lib/api-fetch"; +import { Prisma } from "@prisma/client"; +import { toast } from "react-toastify"; +import { proxy } from "valtio"; +import { z } from "zod"; + +// ========================================= TUJUAN PROGRAM ========================================= // + +const templateTujuanProgramForm = z.object({ + judul: z.string().min(3, "Judul minimal 3 karakter"), + deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"), +}); + +type TujuanProgramForm = Prisma.TujuanBimbinganBelajarDesaGetPayload<{ + select: { + id: true; + judul: true; + deskripsi: true; + }; +}>; + +const stateTujuanProgram = proxy({ + findById: { + data: null as TujuanProgramForm | null, + loading: false, + initialize() { + stateTujuanProgram.findById.data = { + id: "", + judul: "", + deskripsi: "", + } as TujuanProgramForm; + }, + async load(id: string) { + try { + stateTujuanProgram.findById.loading = true; + const res = + await ApiFetch.api.pendidikan.bimbinganbelajardesa.tujuanprogram[ + "find-by-id" + ].get({ + query: { id }, + }); + if (res.status === 200) { + stateTujuanProgram.findById.data = res.data?.data ?? null; + } else { + toast.error("Gagal mengambil data tujuan program"); + } + } catch (error) { + console.error((error as Error).message); + toast.error("Terjadi kesalahan saat mengambil data tujuan program"); + } finally { + stateTujuanProgram.findById.loading = false; + } + }, + }, + + update: { + loading: false, + async save(data: TujuanProgramForm) { + const cek = templateTujuanProgramForm.safeParse(data); + if (!cek.success) { + const errors = cek.error.issues + .map((issue) => `${issue.path.join(".")}: ${issue.message}`) + .join(", "); + toast.error(`Form tidak valid: ${errors}`); + return; + } + + try { + stateTujuanProgram.update.loading = true; + const res = + await ApiFetch.api.pendidikan.bimbinganbelajardesa.tujuanprogram[ + "update" + ].post(data); + if (res.status === 200) { + toast.success("Data tujuan program berhasil diubah"); + await stateTujuanProgram.findById.load(data.id); + } else { + toast.error("Gagal mengubah data tujuan program"); + } + } catch (error) { + console.error((error as Error).message); + toast.error("Terjadi kesalahan saat mengubah data tujuan program"); + } finally { + stateTujuanProgram.update.loading = false; + } + }, + }, +}); + +// ========================================= LOKASI DAN JADWAL ========================================= // + +const templateLokasiDanJadwalForm = z.object({ + judul: z.string().min(3, "Judul minimal 3 karakter"), + deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"), +}); + +type LokasiDanJadwalForm = Prisma.LokasiJadwalBimbinganBelajarDesaGetPayload<{ + select: { + id: true; + judul: true; + deskripsi: true; + }; +}>; + +const lokasiDanJadwalState = proxy({ + findById: { + data: null as LokasiDanJadwalForm | null, + loading: false, + initialize() { + lokasiDanJadwalState.findById.data = { + id: "", + judul: "", + deskripsi: "", + } as LokasiDanJadwalForm; + }, + async load(id: string) { + try { + lokasiDanJadwalState.findById.loading = true; + const res = + await ApiFetch.api.pendidikan.bimbinganbelajardesa.lokasidanjadwal[ + "find-by-id" + ].get({ + query: { id }, + }); + if (res.status === 200) { + lokasiDanJadwalState.findById.data = res.data?.data ?? null; + } else { + toast.error("Gagal mengambil data lokasi dan jadwal"); + } + } catch (error) { + console.error((error as Error).message); + toast.error("Terjadi kesalahan saat mengambil data lokasi dan jadwal"); + } finally { + lokasiDanJadwalState.findById.loading = false; + } + }, + }, + update: { + loading: false, + async save(data: LokasiDanJadwalForm) { + const cek = templateLokasiDanJadwalForm.safeParse(data); + if (!cek.success) { + const errors = cek.error.issues + .map((issue) => `${issue.path.join(".")}: ${issue.message}`) + .join(", "); + toast.error(`Form tidak valid: ${errors}`); + return; + } + + try { + lokasiDanJadwalState.update.loading = true; + const res = + await ApiFetch.api.pendidikan.bimbinganbelajardesa.lokasidanjadwal[ + "update" + ].post(data); + if (res.status === 200) { + toast.success("Data lokasi dan jadwal berhasil diubah"); + await lokasiDanJadwalState.findById.load(data.id); + } else { + toast.error("Gagal mengubah data lokasi dan jadwal"); + } + } catch (error) { + console.error((error as Error).message); + toast.error("Terjadi kesalahan saat mengubah data lokasi dan jadwal"); + } finally { + lokasiDanJadwalState.update.loading = false; + } + }, + }, +}); + +// ========================================= FASILITAS YANG DISEDIAKAN ========================================= // + +const templateFasilitasYangDisediakanForm = z.object({ + judul: z.string().min(3, "Judul minimal 3 karakter"), + deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"), +}); + +type FasilitasYangDisediakanForm = Prisma.FasilitasBimbinganBelajarDesaGetPayload<{ + select: { + id: true; + judul: true; + deskripsi: true; + }; +}>; + +const fasilitasYangDisediakanState = proxy({ + findById: { + data: null as FasilitasYangDisediakanForm | null, + loading: false, + initialize() { + fasilitasYangDisediakanState.findById.data = { + id: "", + judul: "", + deskripsi: "", + } as FasilitasYangDisediakanForm; + }, + async load(id: string) { + try { + fasilitasYangDisediakanState.findById.loading = true; + const res = + await ApiFetch.api.pendidikan.bimbinganbelajardesa.fasilitasyangdisediakan[ + "find-by-id" + ].get({ + query: { id }, + }); + if (res.status === 200) { + fasilitasYangDisediakanState.findById.data = res.data?.data ?? null; + } else { + toast.error("Gagal mengambil data fasilitas yang disediakan"); + } + } catch (error) { + console.error((error as Error).message); + toast.error("Terjadi kesalahan saat mengambil data fasilitas yang disediakan"); + } finally { + fasilitasYangDisediakanState.findById.loading = false; + } + }, + }, + update: { + loading: false, + async save(data: FasilitasYangDisediakanForm) { + const cek = templateFasilitasYangDisediakanForm.safeParse(data); + if (!cek.success) { + const errors = cek.error.issues + .map((issue) => `${issue.path.join(".")}: ${issue.message}`) + .join(", "); + toast.error(`Form tidak valid: ${errors}`); + return; + } + + try { + fasilitasYangDisediakanState.update.loading = true; + const res = + await ApiFetch.api.pendidikan.bimbinganbelajardesa.fasilitasyangdisediakan[ + "update" + ].post(data); + if (res.status === 200) { + toast.success("Data fasilitas yang disediakan berhasil diubah"); + await fasilitasYangDisediakanState.findById.load(data.id); + } else { + toast.error("Gagal mengubah data fasilitas yang disediakan"); + } + } catch (error) { + console.error((error as Error).message); + toast.error("Terjadi kesalahan saat mengubah data fasilitas yang disediakan"); + } finally { + fasilitasYangDisediakanState.update.loading = false; + } + }, + }, +}); + +const stateBimbinganBelajarDesa = proxy({ + stateTujuanProgram, + lokasiDanJadwalState, + fasilitasYangDisediakanState, +}); + +export default stateBimbinganBelajarDesa; diff --git a/src/app/admin/(dashboard)/_state/pendidikan/program-pendidikan-anak.ts b/src/app/admin/(dashboard)/_state/pendidikan/program-pendidikan-anak.ts new file mode 100644 index 00000000..7cc43719 --- /dev/null +++ b/src/app/admin/(dashboard)/_state/pendidikan/program-pendidikan-anak.ts @@ -0,0 +1,181 @@ +import ApiFetch from "@/lib/api-fetch"; +import { Prisma } from "@prisma/client"; +import { toast } from "react-toastify"; +import { proxy } from "valtio"; +import { z } from "zod"; + +// ========================================= TUJUAN PROGRAM ========================================= // + +const templateTujuanProgramForm = z.object({ + judul: z.string().min(3, "Judul minimal 3 karakter"), + deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"), +}); + +type TujuanProgramForm = Prisma.TujuanProgramGetPayload<{ + select: { + id: true; + judul: true; + deskripsi: true; + }; +}>; + +const stateTujuanProgram = proxy({ + findById: { + data: null as TujuanProgramForm | null, + loading: false, + initialize() { + stateTujuanProgram.findById.data = { + id: "", + judul: "", + deskripsi: "", + } as TujuanProgramForm; + }, + async load(id: string) { + try { + stateTujuanProgram.findById.loading = true; + const res = + await ApiFetch.api.pendidikan.programpendidikananak.tujuanprogram[ + "find-by-id" + ].get({ + query: { id }, + }); + if (res.status === 200) { + stateTujuanProgram.findById.data = res.data?.data ?? null; + } else { + toast.error("Gagal mengambil data tujuan program"); + } + } catch (error) { + console.error((error as Error).message); + toast.error("Terjadi kesalahan saat mengambil data tujuan program"); + } finally { + stateTujuanProgram.findById.loading = false; + } + }, + }, + + update: { + loading: false, + async save(data: TujuanProgramForm) { + const cek = templateTujuanProgramForm.safeParse(data); + if (!cek.success) { + const errors = cek.error.issues + .map((issue) => `${issue.path.join(".")}: ${issue.message}`) + .join(", "); + toast.error(`Form tidak valid: ${errors}`); + return; + } + + try { + stateTujuanProgram.update.loading = true; + const res = + await ApiFetch.api.pendidikan.programpendidikananak.tujuanprogram[ + "update" + ].post(data); + if (res.status === 200) { + toast.success("Data tujuan program berhasil diubah"); + await stateTujuanProgram.findById.load(data.id); + } else { + toast.error("Gagal mengubah data tujuan program"); + } + } catch (error) { + console.error((error as Error).message); + toast.error("Terjadi kesalahan saat mengubah data tujuan program"); + } finally { + stateTujuanProgram.update.loading = false; + } + }, + }, +}); + +// ========================================= PROGRAM UNGGULAN ========================================= // + +const templateProgramUnggulanForm = z.object({ + judul: z.string().min(3, "Judul minimal 3 karakter"), + deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"), +}); + +type ProgramUnggulanForm = Prisma.ProgramUnggulanGetPayload<{ + select: { + id: true; + judul: true; + deskripsi: true; + }; +}>; + +const programUnggulanState = proxy({ + findById: { + data: null as ProgramUnggulanForm | null, + loading: false, + initialize() { + programUnggulanState.findById.data = { + id: "", + judul: "", + deskripsi: "", + } as ProgramUnggulanForm; + }, + async load(id: string) { + try { + programUnggulanState.findById.loading = true; + const res = + await ApiFetch.api.pendidikan.programpendidikananak.programunggulan[ + "find-by-id" + ].get({ + query: { id }, + }); + if (res.status === 200) { + programUnggulanState.findById.data = res.data?.data ?? null; + } else { + toast.error("Gagal mengambil data program pendidikan anak"); + } + } catch (error) { + console.error((error as Error).message); + toast.error( + "Terjadi kesalahan saat mengambil data program pendidikan anak" + ); + } finally { + programUnggulanState.findById.loading = false; + } + }, + }, + update: { + loading: false, + async save(data: ProgramUnggulanForm) { + const cek = templateProgramUnggulanForm.safeParse(data); + if (!cek.success) { + const errors = cek.error.issues + .map((issue) => `${issue.path.join(".")}: ${issue.message}`) + .join(", "); + toast.error(`Form tidak valid: ${errors}`); + return; + } + + try { + programUnggulanState.update.loading = true; + const res = + await ApiFetch.api.pendidikan.programpendidikananak.programunggulan[ + "update" + ].post(data); + if (res.status === 200) { + toast.success("Data program pendidikan anak berhasil diubah"); + await programUnggulanState.findById.load(data.id); + } else { + toast.error("Gagal mengubah data program pendidikan anak"); + } + } catch (error) { + console.error((error as Error).message); + toast.error( + "Terjadi kesalahan saat mengubah data program pendidikan anak" + ); + } finally { + programUnggulanState.update.loading = false; + } + }, + }, +}); + +const stateProgramPendidikanAnak = proxy({ + stateTujuanProgram, + programUnggulanState, +}); + +export default stateProgramPendidikanAnak; diff --git a/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/_lib/bimbinganBelajarDesaTextEditor.tsx b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/_lib/bimbinganBelajarDesaTextEditor.tsx new file mode 100644 index 00000000..f4cc56f4 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/_lib/bimbinganBelajarDesaTextEditor.tsx @@ -0,0 +1,99 @@ +'use client' +import { Button, Stack } from '@mantine/core'; +import { Link, RichTextEditor } from '@mantine/tiptap'; +import Highlight from '@tiptap/extension-highlight'; +import SubScript from '@tiptap/extension-subscript'; +import Superscript from '@tiptap/extension-superscript'; +import TextAlign from '@tiptap/extension-text-align'; +import Underline from '@tiptap/extension-underline'; +import { useEditor } from '@tiptap/react'; +import StarterKit from '@tiptap/starter-kit'; +import { useEffect } from 'react'; + +export function BimbinganBelajarDesaTextEditor({ onSubmit, onChange, showSubmit = true, initialContent = '', }: { + onSubmit?: (val: string) => void, + onChange: (val: string) => void, + showSubmit?: boolean, + initialContent?: string }) { + const editor = useEditor({ + extensions: [ + StarterKit, + Underline, + Link, + Superscript, + SubScript, + Highlight, + TextAlign.configure({ types: ['heading', 'paragraph'] }), + ], + immediatelyRender: false, + content: initialContent, + onUpdate : ({editor}) => { + onChange(editor.getHTML()) + } + }); + + useEffect(() => { + if (editor && initialContent !== editor.getHTML()) { + editor.commands.setContent(initialContent || '

'); + } + }, [initialContent, editor]); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {showSubmit && ( + + )} + + ); +} \ No newline at end of file diff --git a/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/_lib/layoutTabs.tsx b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/_lib/layoutTabs.tsx new file mode 100644 index 00000000..d5c09000 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/_lib/layoutTabs.tsx @@ -0,0 +1,68 @@ +/* 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: "Tujuan Program", + value: "tujuan-program", + href: "/admin/pendidikan/bimbingan-belajar-desa/tujuan-program" + }, + { + label: "Lokasi dan Jadwal", + value: "lokasi-dan-jadwal", + href: "/admin/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal" + }, + { + label: "Fasilitas yang disediakan", + value: "fasilitas-yang-disediakan", + href: "/admin/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan" + }, + + ]; + 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 ( + + Bimbingan Belajar Desa + + + {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/bimbingan-belajar-desa/fasilitas-yang-disediakan/edit/page.tsx b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/edit/page.tsx new file mode 100644 index 00000000..6a8e2f23 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/edit/page.tsx @@ -0,0 +1,86 @@ +'use client' +import stateBimbinganBelajarDesa from '@/app/admin/(dashboard)/_state/pendidikan/bimbingan-belajar-desa'; +import colors from '@/con/colors'; +import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack } from '@tabler/icons-react'; +import dynamic from 'next/dynamic'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { useProxy } from 'valtio/utils'; + +const BimbinganBelajarDesaTextEditor = dynamic(() => import('../../_lib/bimbinganBelajarDesaTextEditor').then(mod => mod.BimbinganBelajarDesaTextEditor), { + ssr: false, +}); + +function EditTujuanProgram() { + const router = useRouter() + const editState = useProxy(stateBimbinganBelajarDesa.fasilitasYangDisediakanState) + const [judul, setJudul] = useState(''); + const [content, setContent] = useState(''); + + useShallowEffect(() => { + if (!editState.findById.data) { + editState.findById.initialize(); // biar masuk ke `findFirst` route kamu + } + }, []); + + useEffect(() => { + if (editState.findById.data) { + setJudul(editState.findById.data.judul ?? '') + setContent(editState.findById.data.deskripsi ?? '') + } + }, [editState.findById.data]) + + const submit = () => { + if (editState.findById.data) { + editState.findById.data.judul = judul; + editState.findById.data.deskripsi = content; + editState.update.save(editState.findById.data) + } + router.push('/admin/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan') + } + return ( + + + + + + + + + Edit Fasilitas Yang Disediakan + Judul} + value={judul} + onChange={(e) => setJudul(e.target.value)} + /> + Deskripsi + + + + + + + + + + ); +} + +export default EditTujuanProgram; diff --git a/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/page.tsx b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/page.tsx new file mode 100644 index 00000000..9d41cd0b --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/page.tsx @@ -0,0 +1,54 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Grid, GridCol, Paper, Skeleton, Stack, Text, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconEdit } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import stateBimbinganBelajarDesa from '../../../_state/pendidikan/bimbingan-belajar-desa'; + +function Page() { + const router = useRouter() + const listPreview = useProxy(stateBimbinganBelajarDesa.fasilitasYangDisediakanState) + useShallowEffect(() => { + listPreview.findById.load('edit') + }, []) + + if (!listPreview.findById.data) { + return ( + + + + ) + } + return ( + + + + + Preview Fasilitas Yang Disediakan + + + + + + + + + + + + + + + + + + + + ) +} + +export default Page; diff --git a/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/layout.tsx b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/layout.tsx new file mode 100644 index 00000000..3a414c77 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/layout.tsx @@ -0,0 +1,12 @@ +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/bimbingan-belajar-desa/lokasi-dan-jadwal/edit/page.tsx b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/edit/page.tsx new file mode 100644 index 00000000..e4f28a3e --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/edit/page.tsx @@ -0,0 +1,86 @@ +'use client' +import stateBimbinganBelajarDesa from '@/app/admin/(dashboard)/_state/pendidikan/bimbingan-belajar-desa'; +import colors from '@/con/colors'; +import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack } from '@tabler/icons-react'; +import dynamic from 'next/dynamic'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { useProxy } from 'valtio/utils'; + +const BimbinganBelajarDesaTextEditor = dynamic(() => import('../../_lib/bimbinganBelajarDesaTextEditor').then(mod => mod.BimbinganBelajarDesaTextEditor), { + ssr: false, +}); + +function EditTujuanProgram() { + const router = useRouter() + const editState = useProxy(stateBimbinganBelajarDesa.lokasiDanJadwalState) + const [judul, setJudul] = useState(''); + const [content, setContent] = useState(''); + + useShallowEffect(() => { + if (!editState.findById.data) { + editState.findById.initialize(); // biar masuk ke `findFirst` route kamu + } + }, []); + + useEffect(() => { + if (editState.findById.data) { + setJudul(editState.findById.data.judul ?? '') + setContent(editState.findById.data.deskripsi ?? '') + } + }, [editState.findById.data]) + + const submit = () => { + if (editState.findById.data) { + editState.findById.data.judul = judul; + editState.findById.data.deskripsi = content; + editState.update.save(editState.findById.data) + } + router.push('/admin/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal') + } + return ( + + + + + + + + + Edit Lokasi Dan Jadwal + Judul} + value={judul} + onChange={(e) => setJudul(e.target.value)} + /> + Deskripsi + + + + + + + + + + ); +} + +export default EditTujuanProgram; diff --git a/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/page.tsx b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/page.tsx new file mode 100644 index 00000000..6145a65a --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/page.tsx @@ -0,0 +1,54 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Grid, GridCol, Paper, Skeleton, Stack, Text, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconEdit } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import stateBimbinganBelajarDesa from '../../../_state/pendidikan/bimbingan-belajar-desa'; + +function Page() { + const router = useRouter() + const listPreview = useProxy(stateBimbinganBelajarDesa.lokasiDanJadwalState) + useShallowEffect(() => { + listPreview.findById.load('edit') + }, []) + + if (!listPreview.findById.data) { + return ( + + + + ) + } + return ( + + + + + Preview Lokasi Dan Jadwal + + + + + + + + + + + + + + + + + + + + ) +} + +export default Page; diff --git a/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/page.tsx b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/page.tsx deleted file mode 100644 index ed7a421e..00000000 --- a/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/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 BimbinganBelajarDesa() { - return ( - - } - /> - - - ); -} - -function ListBimbinganBelajarDesa() { - const router = useRouter(); - return ( - - - - - - - - - Nomor - Nama Lengkap - Nomor Telepon - Email - Detail - - - - - - - 1 - - - - Nama Lengkap - - - Nomor Telepon - - - Email - - - - - - -
-
-
-
-
- ) -} - -export default BimbinganBelajarDesa; diff --git a/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/tujuan-program/edit/page.tsx b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/tujuan-program/edit/page.tsx new file mode 100644 index 00000000..a54f42c3 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/tujuan-program/edit/page.tsx @@ -0,0 +1,86 @@ +'use client' +import stateBimbinganBelajarDesa from '@/app/admin/(dashboard)/_state/pendidikan/bimbingan-belajar-desa'; +import colors from '@/con/colors'; +import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack } from '@tabler/icons-react'; +import dynamic from 'next/dynamic'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { useProxy } from 'valtio/utils'; + +const BimbinganBelajarDesaTextEditor = dynamic(() => import('../../_lib/bimbinganBelajarDesaTextEditor').then(mod => mod.BimbinganBelajarDesaTextEditor), { + ssr: false, +}); + +function EditTujuanProgram() { + const router = useRouter() + const editState = useProxy(stateBimbinganBelajarDesa.stateTujuanProgram) + const [judul, setJudul] = useState(''); + const [content, setContent] = useState(''); + + useShallowEffect(() => { + if (!editState.findById.data) { + editState.findById.initialize(); // biar masuk ke `findFirst` route kamu + } + }, []); + + useEffect(() => { + if (editState.findById.data) { + setJudul(editState.findById.data.judul ?? '') + setContent(editState.findById.data.deskripsi ?? '') + } + }, [editState.findById.data]) + + const submit = () => { + if (editState.findById.data) { + editState.findById.data.judul = judul; + editState.findById.data.deskripsi = content; + editState.update.save(editState.findById.data) + } + router.push('/admin/pendidikan/bimbingan-belajar-desa/tujuan-program') + } + return ( + + + + + + + + + Edit Tujuan Program + Judul} + value={judul} + onChange={(e) => setJudul(e.target.value)} + /> + Deskripsi + + + + + + + + + + ); +} + +export default EditTujuanProgram; diff --git a/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/tujuan-program/page.tsx b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/tujuan-program/page.tsx new file mode 100644 index 00000000..f8b1519d --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/tujuan-program/page.tsx @@ -0,0 +1,54 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Grid, GridCol, Paper, Skeleton, Stack, Text, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconEdit } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import stateBimbinganBelajarDesa from '../../../_state/pendidikan/bimbingan-belajar-desa'; + +function Page() { + const router = useRouter() + const listPreview = useProxy(stateBimbinganBelajarDesa.stateTujuanProgram) + useShallowEffect(() => { + listPreview.findById.load('edit') + }, []) + + if (!listPreview.findById.data) { + return ( + + + + ) + } + return ( + + + + + Preview Tujuan Program + + + + + + + + + + + + + + + + + + + + ) +} + +export default Page; diff --git a/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/_lib/layoutTabs.tsx b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/_lib/layoutTabs.tsx new file mode 100644 index 00000000..464fd7fd --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/_lib/layoutTabs.tsx @@ -0,0 +1,62 @@ +/* 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: "Program Unggulan", + value: "program-unggulan", + href: "/admin/pendidikan/program-pendidikan-anak/program-unggulan" + }, + { + label: "Tujuan Program", + value: "tujuan-program", + href: "/admin/pendidikan/program-pendidikan-anak/tujuan-program" + }, + ]; + 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 ( + + Program Pendidikan Anak + + + {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/program-pendidikan-anak/_lib/programPendidikanAnakTextEditor.tsx b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/_lib/programPendidikanAnakTextEditor.tsx new file mode 100644 index 00000000..b9599de1 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/_lib/programPendidikanAnakTextEditor.tsx @@ -0,0 +1,100 @@ +'use client' +import { Button, Stack } from '@mantine/core'; +import { Link, RichTextEditor } from '@mantine/tiptap'; +import Highlight from '@tiptap/extension-highlight'; +import SubScript from '@tiptap/extension-subscript'; +import Superscript from '@tiptap/extension-superscript'; +import TextAlign from '@tiptap/extension-text-align'; +import Underline from '@tiptap/extension-underline'; +import { useEditor } from '@tiptap/react'; +import StarterKit from '@tiptap/starter-kit'; +import { useEffect } from 'react'; + + +export function ProgramPendidikanAnakTextEditor({ onSubmit, onChange, showSubmit = true, initialContent = '', }: { + onSubmit?: (val: string) => void, + onChange: (val: string) => void, + showSubmit?: boolean, + initialContent?: string }) { + const editor = useEditor({ + extensions: [ + StarterKit, + Underline, + Link, + Superscript, + SubScript, + Highlight, + TextAlign.configure({ types: ['heading', 'paragraph'] }), + ], + immediatelyRender: false, + content: initialContent, + onUpdate : ({editor}) => { + onChange(editor.getHTML()) + } + }); + + useEffect(() => { + if (editor && initialContent !== editor.getHTML()) { + editor.commands.setContent(initialContent || '

'); + } + }, [initialContent, editor]); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {showSubmit && ( + + )} + + ); +} \ No newline at end of file diff --git a/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/layout.tsx b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/layout.tsx new file mode 100644 index 00000000..1fa8572a --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/layout.tsx @@ -0,0 +1,11 @@ +'use client' +import LayoutTabs from "./_lib/layoutTabs" + + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ) +} \ No newline at end of file diff --git a/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/page.tsx b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/page.tsx deleted file mode 100644 index 221e27cb..00000000 --- a/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/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 ProgramPendidikanAnak() { - return ( - - } - /> - - - ); -} - -function ListProgramPendidikanAnak() { - const router = useRouter(); - return ( - - - - - - - - - Nomor - Nama Lengkap - Nomor Telepon - Email - Detail - - - - - - - 1 - - - - Nama Lengkap - - - Nomor Telepon - - - Email - - - - - - -
-
-
-
-
- ) -} - -export default ProgramPendidikanAnak; diff --git a/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/program-unggulan/edit/page.tsx b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/program-unggulan/edit/page.tsx new file mode 100644 index 00000000..7f8daa7f --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/program-unggulan/edit/page.tsx @@ -0,0 +1,86 @@ +'use client' +import stateProgramPendidikanAnak from '@/app/admin/(dashboard)/_state/pendidikan/program-pendidikan-anak'; +import colors from '@/con/colors'; +import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack } from '@tabler/icons-react'; +import dynamic from 'next/dynamic'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { useProxy } from 'valtio/utils'; + +const ProgramPendidikanAnakTextEditor = dynamic(() => import('../../_lib/programPendidikanAnakTextEditor').then(mod => mod.ProgramPendidikanAnakTextEditor), { + ssr: false, +}); + +function EditTujuanProgram() { + const router = useRouter() + const editState = useProxy(stateProgramPendidikanAnak.programUnggulanState) + const [judul, setJudul] = useState(''); + const [content, setContent] = useState(''); + + useShallowEffect(() => { + if (!editState.findById.data) { + editState.findById.initialize(); // biar masuk ke `findFirst` route kamu + } + }, []); + + useEffect(() => { + if (editState.findById.data) { + setJudul(editState.findById.data.judul ?? '') + setContent(editState.findById.data.deskripsi ?? '') + } + }, [editState.findById.data]) + + const submit = () => { + if (editState.findById.data) { + editState.findById.data.judul = judul; + editState.findById.data.deskripsi = content; + editState.update.save(editState.findById.data) + } + router.push('/admin/pendidikan/program-pendidikan-anak/program-unggulan') + } + return ( + + + + + + + + + Edit Program Unggulan + Judul} + value={judul} + onChange={(e) => setJudul(e.target.value)} + /> + Deskripsi + + + + + + + + + + ); +} + +export default EditTujuanProgram; diff --git a/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/program-unggulan/page.tsx b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/program-unggulan/page.tsx new file mode 100644 index 00000000..5a0c2afe --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/program-unggulan/page.tsx @@ -0,0 +1,54 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Grid, GridCol, Paper, Skeleton, Stack, Text, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconEdit } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import stateProgramPendidikanAnak from '../../../_state/pendidikan/program-pendidikan-anak'; + +function Page() { + const router = useRouter() + const listPreview = useProxy(stateProgramPendidikanAnak.programUnggulanState) + useShallowEffect(() => { + listPreview.findById.load('edit') + }, []) + + if (!listPreview.findById.data) { + return ( + + + + ) + } + return ( + + + + + Preview Program Unggulan + + + + + + + + + + + + + + + + + + + + ) +} + +export default Page; diff --git a/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/tujuan-program/edit/page.tsx b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/tujuan-program/edit/page.tsx new file mode 100644 index 00000000..36ca3593 --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/tujuan-program/edit/page.tsx @@ -0,0 +1,86 @@ +'use client' +import stateProgramPendidikanAnak from '@/app/admin/(dashboard)/_state/pendidikan/program-pendidikan-anak'; +import colors from '@/con/colors'; +import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack } from '@tabler/icons-react'; +import dynamic from 'next/dynamic'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { useProxy } from 'valtio/utils'; + +const ProgramPendidikanAnakTextEditor = dynamic(() => import('../../_lib/programPendidikanAnakTextEditor').then(mod => mod.ProgramPendidikanAnakTextEditor), { + ssr: false, +}); + +function EditTujuanProgram() { + const router = useRouter() + const editState = useProxy(stateProgramPendidikanAnak.stateTujuanProgram) + const [judul, setJudul] = useState(''); + const [content, setContent] = useState(''); + + useShallowEffect(() => { + if (!editState.findById.data) { + editState.findById.initialize(); // biar masuk ke `findFirst` route kamu + } + }, []); + + useEffect(() => { + if (editState.findById.data) { + setJudul(editState.findById.data.judul ?? '') + setContent(editState.findById.data.deskripsi ?? '') + } + }, [editState.findById.data]) + + const submit = () => { + if (editState.findById.data) { + editState.findById.data.judul = judul; + editState.findById.data.deskripsi = content; + editState.update.save(editState.findById.data) + } + router.push('/admin/pendidikan/program-pendidikan-anak/tujuan-program') + } + return ( + + + + + + + + + Edit Tujuan Program + Judul} + value={judul} + onChange={(e) => setJudul(e.target.value)} + /> + Deskripsi + + + + + + + + + + ); +} + +export default EditTujuanProgram; diff --git a/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/tujuan-program/page.tsx b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/tujuan-program/page.tsx new file mode 100644 index 00000000..04c284eb --- /dev/null +++ b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/tujuan-program/page.tsx @@ -0,0 +1,54 @@ +'use client' +import colors from '@/con/colors'; +import { Box, Button, Grid, GridCol, Paper, Skeleton, Stack, Text, Title } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconEdit } from '@tabler/icons-react'; +import { useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import stateProgramPendidikanAnak from '../../../_state/pendidikan/program-pendidikan-anak'; + +function Page() { + const router = useRouter() + const listPreview = useProxy(stateProgramPendidikanAnak.stateTujuanProgram) + useShallowEffect(() => { + listPreview.findById.load('edit') + }, []) + + if (!listPreview.findById.data) { + return ( + + + + ) + } + return ( + + + + + Preview Tujuan Program + + + + + + + + + + + + + + + + + + + + ) +} + +export default Page; diff --git a/src/app/admin/_com/list_PageAdmin.tsx b/src/app/admin/_com/list_PageAdmin.tsx index 98e2444b..2aa7563a 100644 --- a/src/app/admin/_com/list_PageAdmin.tsx +++ b/src/app/admin/_com/list_PageAdmin.tsx @@ -354,12 +354,12 @@ export const navBar = [ { id: "Pendidikan_3", name: "Program Pendidikan Anak", - path: "/admin/pendidikan/program-pendidikan-anak" + path: "/admin/pendidikan/program-pendidikan-anak/program-unggulan" }, { id: "Pendidikan_4", name: "Bimbingan Belajar Desa", - path: "/admin/pendidikan/bimbingan-belajar-desa" + path: "/admin/pendidikan/bimbingan-belajar-desa/tujuan-program" }, { id: "Pendidikan_5", diff --git a/src/app/api/[[...slugs]]/_lib/lingkungan/konservasi-adat-bali/bentuk-konservasi-berdasarkan-adat/findUnique.ts b/src/app/api/[[...slugs]]/_lib/lingkungan/konservasi-adat-bali/bentuk-konservasi-berdasarkan-adat/findUnique.ts index e37dbcbf..566724c3 100644 --- a/src/app/api/[[...slugs]]/_lib/lingkungan/konservasi-adat-bali/bentuk-konservasi-berdasarkan-adat/findUnique.ts +++ b/src/app/api/[[...slugs]]/_lib/lingkungan/konservasi-adat-bali/bentuk-konservasi-berdasarkan-adat/findUnique.ts @@ -1,33 +1,37 @@ import prisma from "@/lib/prisma"; import { Context } from "elysia"; -export default async function bentukKonservasiBerdasarkanAdatFindUnique(context: Context) { - try { - const id = context?.params?.slugs?.[0]; +export default async function bentukKonservasiBerdasarkanAdatFindUnique( + context: Context +) { + try { + const id = context?.params?.slugs?.[0]; - // If no ID provided, get the first profile - if (!id) { - const data = await prisma.bentukKonservasiBerdasarkanAdat.findFirst(); - return { - success: true, - data, - }; - } - - const data = await prisma.bentukKonservasiBerdasarkanAdat.findUniqueOrThrow({ - where: { id }, - }); - - return { - success: true, - data, - }; - } catch (error) { - console.error("Error fetching bentuk konservasi berdasarkan adat:", error); - - return { - success: false, - message: error instanceof Error ? error.message : "Unknown error", - }; + // If no ID provided, get the first profile + if (!id) { + const data = await prisma.bentukKonservasiBerdasarkanAdat.findFirst(); + return { + success: true, + data, + }; } -} \ No newline at end of file + + const data = await prisma.bentukKonservasiBerdasarkanAdat.findUniqueOrThrow( + { + where: { id }, + } + ); + + return { + success: true, + data, + }; + } catch (error) { + console.error("Error fetching bentuk konservasi berdasarkan adat:", error); + + return { + success: false, + message: error instanceof Error ? error.message : "Unknown error", + }; + } +} diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/findUnique.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/findUnique.ts new file mode 100644 index 00000000..481b7ce5 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/findUnique.ts @@ -0,0 +1,37 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function fasilitasYangDisediakanFindUnique( + context: Context +) { + try { + const id = context?.params?.slugs?.[0]; + + // If no ID provided, get the first profile + if (!id) { + const data = await prisma.fasilitasBimbinganBelajarDesa.findFirst(); + return { + success: true, + data, + }; + } + + const data = await prisma.fasilitasBimbinganBelajarDesa.findUniqueOrThrow( + { + where: { id }, + } + ); + + return { + success: true, + data, + }; + } catch (error) { + console.error("Error fetching fasilitas yang disediakan:", error); + + return { + success: false, + message: error instanceof Error ? error.message : "Unknown error", + }; + } +} diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/index.ts new file mode 100644 index 00000000..d8a9bf77 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/index.ts @@ -0,0 +1,18 @@ +import Elysia, { t } from "elysia"; +import fasilitasYangDisediakanFindUnique from "./findUnique"; +import fasilitasYangDisediakanUpdate from "./updt"; + +const FasilitasYangDisediakan = new Elysia({ + prefix: "/fasilitasyangdisediakan", + tags: ["Pendidikan/Bimbingan Belajar Desa/Fasilitas Yang Disediakan"] +}) + .get("/find-by-id", fasilitasYangDisediakanFindUnique) + .post("/update", fasilitasYangDisediakanUpdate, { + body: t.Object({ + id: t.String(), + judul: t.String(), + deskripsi: t.String(), + }) + }) + +export default FasilitasYangDisediakan \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/updt.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/updt.ts new file mode 100644 index 00000000..651710b0 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan/updt.ts @@ -0,0 +1,29 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; + +type FormCreate = Prisma.FasilitasBimbinganBelajarDesaGetPayload<{ + select: { + id: true; + judul: true; + deskripsi: true; + } +}> +export default async function fasilitasYangDisediakanUpdate(context: Context) { + const body = context.body as FormCreate; + + await prisma.fasilitasBimbinganBelajarDesa.update({ + where: { + id: body.id + }, + data: { + judul: body.judul, + deskripsi: body.deskripsi, + } + }) + + return { + success: true, + message: "Fasilitas yang disediakan berhasil diupdate", + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/index.ts new file mode 100644 index 00000000..07b93b29 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/index.ts @@ -0,0 +1,14 @@ +import Elysia from "elysia"; +import TujuanProgram from "./tujuan-program"; +import LokasiDanJadwal from "./lokasi-dan-jadwal"; +import FasilitasYangDisediakan from "./fasilitas-yang-disediakan"; + +const BimbinganBelajarDesa = new Elysia({ + prefix: "/bimbinganbelajardesa", + tags: ["Pendidikan/Bimbingan Belajar Desa"] +}) +.use(TujuanProgram) +.use(LokasiDanJadwal) +.use(FasilitasYangDisediakan) + +export default BimbinganBelajarDesa \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/findUnique.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/findUnique.ts new file mode 100644 index 00000000..ef3e08ee --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/findUnique.ts @@ -0,0 +1,37 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function lokasiDanJadwalFindUnique( + context: Context +) { + try { + const id = context?.params?.slugs?.[0]; + + // If no ID provided, get the first profile + if (!id) { + const data = await prisma.lokasiJadwalBimbinganBelajarDesa.findFirst(); + return { + success: true, + data, + }; + } + + const data = await prisma.lokasiJadwalBimbinganBelajarDesa.findUniqueOrThrow( + { + where: { id }, + } + ); + + return { + success: true, + data, + }; + } catch (error) { + console.error("Error fetching lokasi dan jadwal:", error); + + return { + success: false, + message: error instanceof Error ? error.message : "Unknown error", + }; + } +} diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/index.ts new file mode 100644 index 00000000..2abf3204 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/index.ts @@ -0,0 +1,18 @@ +import Elysia, { t } from "elysia"; +import lokasiDanJadwalFindUnique from "./findUnique"; +import lokasiDanJadwalUpdate from "./updt"; + +const LokasiDanJadwal = new Elysia({ + prefix: "/lokasidanjadwal", + tags: ["Pendidikan/Bimbingan Belajar Desa/Lokasi dan Jadwal"] +}) + .get("/find-by-id", lokasiDanJadwalFindUnique) + .post("/update", lokasiDanJadwalUpdate, { + body: t.Object({ + id: t.String(), + judul: t.String(), + deskripsi: t.String(), + }) + }) + +export default LokasiDanJadwal \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/updt.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/updt.ts new file mode 100644 index 00000000..145d73e7 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal/updt.ts @@ -0,0 +1,29 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; + +type FormCreate = Prisma.LokasiJadwalBimbinganBelajarDesaGetPayload<{ + select: { + id: true; + judul: true; + deskripsi: true; + } +}> +export default async function lokasiDanJadwalUpdate(context: Context) { + const body = context.body as FormCreate; + + await prisma.lokasiJadwalBimbinganBelajarDesa.update({ + where: { + id: body.id + }, + data: { + judul: body.judul, + deskripsi: body.deskripsi, + } + }) + + return { + success: true, + message: "Lokasi dan jadwal berhasil diupdate", + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/findUnique.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/findUnique.ts new file mode 100644 index 00000000..dcdc97d1 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/findUnique.ts @@ -0,0 +1,37 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function tujuanProgramFindUnique( + context: Context +) { + try { + const id = context?.params?.slugs?.[0]; + + // If no ID provided, get the first profile + if (!id) { + const data = await prisma.tujuanBimbinganBelajarDesa.findFirst(); + return { + success: true, + data, + }; + } + + const data = await prisma.tujuanBimbinganBelajarDesa.findUniqueOrThrow( + { + where: { id }, + } + ); + + return { + success: true, + data, + }; + } catch (error) { + console.error("Error fetching tujuan program:", error); + + return { + success: false, + message: error instanceof Error ? error.message : "Unknown error", + }; + } +} diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/index.ts new file mode 100644 index 00000000..34f73183 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/index.ts @@ -0,0 +1,18 @@ +import Elysia, { t } from "elysia"; +import tujuanProgramFindUnique from "./findUnique"; +import tujuanProgramUpdate from "./updt"; + +const TujuanProgram = new Elysia({ + prefix: "/tujuanprogram", + tags: ["Pendidikan/Bimbingan Belajar Desa/Tujuan Program"] +}) + .get("/find-by-id", tujuanProgramFindUnique) + .post("/update", tujuanProgramUpdate, { + body: t.Object({ + id: t.String(), + judul: t.String(), + deskripsi: t.String(), + }) + }) + +export default TujuanProgram \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/updt.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/updt.ts new file mode 100644 index 00000000..f493da3e --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/bimbingan-belajar-desa/tujuan-program/updt.ts @@ -0,0 +1,29 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; + +type FormCreate = Prisma.TujuanBimbinganBelajarDesaGetPayload<{ + select: { + id: true; + judul: true; + deskripsi: true; + } +}> +export default async function tujuanProgramUpdate(context: Context) { + const body = context.body as FormCreate; + + await prisma.tujuanBimbinganBelajarDesa.update({ + where: { + id: body.id + }, + data: { + judul: body.judul, + deskripsi: body.deskripsi, + } + }) + + return { + success: true, + message: "Tujuan program berhasil diupdate", + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts index 5b5ee45f..307b4908 100644 --- a/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/index.ts @@ -1,5 +1,7 @@ import Elysia from "elysia"; import InfoSekolahPAUD from "./info-sekolah-paud"; +import ProgramPendidikanAnak from "./program-pendidikan-anak"; +import BimbinganBelajarDesa from "./bimbingan-belajar-desa"; const Pendidikan = new Elysia({ prefix: "/api/pendidikan", @@ -7,5 +9,7 @@ const Pendidikan = new Elysia({ }) .use(InfoSekolahPAUD) +.use(ProgramPendidikanAnak) +.use(BimbinganBelajarDesa) export default Pendidikan; \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/index.ts new file mode 100644 index 00000000..5a25f295 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/index.ts @@ -0,0 +1,12 @@ +import Elysia from "elysia"; +import ProgramUnggulan from "./program-unggulan"; +import TujuanProgram from "./tujuan-program"; + +const ProgramPendidikanAnak = new Elysia({ + prefix: "/programpendidikananak", + tags: ["Pendidikan/Program Pendidikan Anak"] +}) +.use(ProgramUnggulan) +.use(TujuanProgram) + +export default ProgramPendidikanAnak diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/findUnique.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/findUnique.ts new file mode 100644 index 00000000..06b8ee3a --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/findUnique.ts @@ -0,0 +1,33 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function programUnggulanFindUnique(context: Context) { + try { + const id = context?.params?.slugs?.[0]; + + // If no ID provided, get the first profile + if (!id) { + const data = await prisma.programUnggulan.findFirst(); + return { + success: true, + data, + }; + } + + const data = await prisma.programUnggulan.findUniqueOrThrow({ + where: { id }, + }); + + return { + success: true, + data, + }; + } catch (error) { + console.error("Error fetching program unggulan:", error); + + return { + success: false, + message: error instanceof Error ? error.message : "Unknown error", + }; + } +} diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/index.ts new file mode 100644 index 00000000..92e30853 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/index.ts @@ -0,0 +1,18 @@ +import Elysia, { t } from "elysia"; +import programUnggulanFindUnique from "./findUnique"; +import programUnggulanUpdate from "./updt"; + +const ProgramUnggulan = new Elysia({ + prefix: "/programunggulan", + tags: ["Pendidikan/Program Pendidikan Anak/Program Unggulan"] +}) + .get("/find-by-id", programUnggulanFindUnique) + .post("/update", programUnggulanUpdate, { + body: t.Object({ + id: t.String(), + judul: t.String(), + deskripsi: t.String(), + }) + }) + +export default ProgramUnggulan \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/updt.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/updt.ts new file mode 100644 index 00000000..64d4807e --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/program-unggulan/updt.ts @@ -0,0 +1,29 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; + +type FormCreate = Prisma.ProgramUnggulanGetPayload<{ + select: { + id: true; + judul: true; + deskripsi: true; + } +}> +export default async function programUnggulanUpdate(context: Context) { + const body = context.body as FormCreate; + + await prisma.programUnggulan.update({ + where: { + id: body.id + }, + data: { + judul: body.judul, + deskripsi: body.deskripsi, + } + }) + + return { + success: true, + message: "Program unggulan berhasil diupdate", + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/findUnique.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/findUnique.ts new file mode 100644 index 00000000..109479ef --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/findUnique.ts @@ -0,0 +1,37 @@ +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +export default async function tujuanProgramFindUnique( + context: Context +) { + try { + const id = context?.params?.slugs?.[0]; + + // If no ID provided, get the first profile + if (!id) { + const data = await prisma.tujuanProgram.findFirst(); + return { + success: true, + data, + }; + } + + const data = await prisma.tujuanProgram.findUniqueOrThrow( + { + where: { id }, + } + ); + + return { + success: true, + data, + }; + } catch (error) { + console.error("Error fetching tujuan program:", error); + + return { + success: false, + message: error instanceof Error ? error.message : "Unknown error", + }; + } +} diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/index.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/index.ts new file mode 100644 index 00000000..53a2e25a --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/index.ts @@ -0,0 +1,18 @@ +import Elysia, { t } from "elysia"; +import tujuanProgramFindUnique from "./findUnique"; +import tujuanProgramUpdate from "./updt"; + +const TujuanProgram = new Elysia({ + prefix: "/tujuanprogram", + tags: ["Pendidikan/Program Pendidikan Anak/Tujuan Program"] +}) + .get("/find-by-id", tujuanProgramFindUnique) + .post("/update", tujuanProgramUpdate, { + body: t.Object({ + id: t.String(), + judul: t.String(), + deskripsi: t.String(), + }) + }) + +export default TujuanProgram \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/updt.ts b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/updt.ts new file mode 100644 index 00000000..87f15615 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/pendidikan/program-pendidikan-anak/tujuan-program/updt.ts @@ -0,0 +1,29 @@ +import prisma from "@/lib/prisma"; +import { Prisma } from "@prisma/client"; +import { Context } from "elysia"; + +type FormCreate = Prisma.TujuanProgramGetPayload<{ + select: { + id: true; + judul: true; + deskripsi: true; + } +}> +export default async function tujuanProgramUpdate(context: Context) { + const body = context.body as FormCreate; + + await prisma.tujuanProgram.update({ + where: { + id: body.id + }, + data: { + judul: body.judul, + deskripsi: body.deskripsi, + } + }) + + return { + success: true, + message: "Tujuan program berhasil diupdate", + } +} \ No newline at end of file