diff --git a/bun.lockb b/bun.lockb
index 775d4131..347d9ab5 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index c9a52ec1..a23894c8 100644
--- a/package.json
+++ b/package.json
@@ -22,8 +22,9 @@
"@mantine/carousel": "^7.16.2",
"@mantine/charts": "^7.17.1",
"@mantine/core": "^7.17.4",
- "@mantine/dates": "^7.17.4",
- "@mantine/dropzone": "^7.17.0",
+ "@mantine/dates": "^8.1.0",
+ "@mantine/dropzone": "^8.1.1",
+ "@mantine/form": "^8.1.0",
"@mantine/hooks": "^7.17.4",
"@mantine/tiptap": "^7.17.4",
"@paljs/types": "^8.1.0",
diff --git a/prisma/data/desa/layanan/pelayanaPendudukNonPermanen.json b/prisma/data/desa/layanan/pelayanaPendudukNonPermanen.json
new file mode 100644
index 00000000..2259bea4
--- /dev/null
+++ b/prisma/data/desa/layanan/pelayanaPendudukNonPermanen.json
@@ -0,0 +1,7 @@
+[
+ {
+ "id": "1",
+ "name": "Pelayanan Penduduk Non-Permanent",
+ "deskripsi": "
Surat Keterangan Penduduk Non-Permanent adalah dokumen yang dikeluarkan oleh pihak berwenang untuk memberikan keterangan bahwa seseorang atau kelompok orang memiliki status penduduk non-permanent di suatu wilayah. Dokumen ini biasanya digunakan untuk keperluan administratif atau legal, seperti mendapatkan akses ke layanan kesehatan, pendidikan, atau pelayanan publik lainnya.
"
+ }
+]
\ No newline at end of file
diff --git a/prisma/data/desa/layanan/pelayananPerizinanBerusaha.json b/prisma/data/desa/layanan/pelayananPerizinanBerusaha.json
new file mode 100644
index 00000000..8df36cf0
--- /dev/null
+++ b/prisma/data/desa/layanan/pelayananPerizinanBerusaha.json
@@ -0,0 +1,8 @@
+[
+ {
+ "id": "1",
+ "name": "Pelayanan Perizinan Berusaha Berbasis Risiko Melalui Sistem ONLINE SINGLE SUBMISSION (OSS)",
+ "deskripsi": "Penyelenggaraan Perizinan Berusaha Berbasis Risiko melalui Sistem Online Single Submission (OSS) merupakan pelaksanaan Undang-Undang Nomor 11 Tahun 2020 Tentang Cipta Kerja. OSS Berbasis Risiko wajib digunakan oleh Pelaku Usaha, Kementerian/Lembaga, Pemerintah Daerah, Administrator Kawasan Ekonomi Khusus (KEK), dan Badan Pengusahaan Kawasan Perdagangan Bebas Pelabuhan Bebas (KPBPB).Berdasarkan Peraturan Pemerintah Nomor 5 Tahun 2021 terdapat 1.702 kegiatan usaha yang terdiri atas 1.349 Klasifikasi Baku Lapangan Usaha Indonesia (KBLI) yang sudah diimplementasikan dalam Sistem OSS Berbasis Risiko.
",
+ "link" : "https://oss.go.id/"
+ }
+]
\ No newline at end of file
diff --git a/prisma/data/desa/profile/lambang_desa.json b/prisma/data/desa/profile/lambang_desa.json
new file mode 100644
index 00000000..7827289a
--- /dev/null
+++ b/prisma/data/desa/profile/lambang_desa.json
@@ -0,0 +1,7 @@
+[
+ {
+ "id": "edit",
+ "judul": "Lambang Desa",
+ "deskripsi" : "Memperkokoh kerukunan hidup masyarakat dalam jalinan adat, budaya, olahraga, dan agama. Meningkatkan kualitas pelayanan publik dengan menerapkan teknologi informasi dan komunikasi terintegrasi. Meningkatkan tata kelola pemerintah desa dengan menerapkan prinsip good governance dan good clean government. Meningkatkan kualitas pendidikan, kesehatan, Keluarga Berencana serta pengelolaan kependudukan. Memperkuat usaha mikro kecil dan menengah (UMKM) dan BUMDesa sebagai pilar ekonomi masyarakat. Mewujudkan tatanan kehidupan bermasyarakat yang menjunjung tinggi penegakan hukum dan HAM. Meningkatkan perlindungan dan pengelolaan terhadap sumber daya alam dan lingkungan hidup. Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa. Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata. Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa. Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata. "
+ }
+]
\ No newline at end of file
diff --git a/prisma/data/desa/profile/maskot_desa.json b/prisma/data/desa/profile/maskot_desa.json
new file mode 100644
index 00000000..b405ff8f
--- /dev/null
+++ b/prisma/data/desa/profile/maskot_desa.json
@@ -0,0 +1,7 @@
+[
+ {
+ "id": "edit",
+ "judul": "Maskot Desa",
+ "deskripsi" : "Pudak adalah bunga dari tanaman sejenis pandan (Pandanaceae). Bentuk bunga ini tersusun dalam beberapa lapisan, terbungkus oleh kelopak warna putih (semacam daun lonjong) yang ujungnya meruncing.
Bunga Pudak berwarna kuning dan akan terlihat jika kelopak atau pelepahnya telah mekar. Kekhasan dari bunga pudak, yaitu mempunyai aroma wangi yang semerbak nan lembut (tidak menyengat), dan dapat menebar keharuman sepanjang pagi atau pun sore hari. Tanaman ini dapat tumbuh di sepanjang pantai, aliran sungai, di atas batu-batu karang, dan juga di tanah ladang.
Dalam Kamus Jawa Kuna- Indonesia kata “Pudak” berarti bunga pandan atau Pandanus Moschatus (Mardiwarsito: 1981: 442). Selain itu bunga pudak juga dapat disebut ketaka atau ketaki (Mardiwarsito, 1981: 276). Sedangkan kata “Sategal” berasal dari kata dasar “Tegal” yang berarti ladang (Mardiwarsito, 1981: 593). Jadi Pudak Sategal dapat diartikan sebagai satu ladang luas yang dipenuhi bunga pudak dan menabar keharuman.
Pada sebuah kesempatan, Ida Pedanda Putu Pemaron menjelaskan mengenai makna dari istilah Pudak Sategal dengan sebuah analogi bahwa, sekuntum bunga pudak memiliki aroma wangi atau keharuman yang sangat kuat, apalagi jika satu ladang penuh bunga pudak, maka dapat dipastikan aroma keharumannya akan membumbung menyebar ke segala penjuru (Wawancara, 18 Mei 2019 di Geria Putra Mandara Kenderan, Tegallalang). “Pudak” ialah sebuah bunga yang memiliki aroma wangi atau keharuman yang semerbak, lembut, dan khas.
Garapan Tari Maskot Desa Darmasaba Sekar Pudak diwujudkan ke dalam bentuk tari kreasi yang ditarikan secara berkelompok dengan jumlah lima orang penari perempuan (putri).
Pemilihan penari perempuan dimaksudkan untuk mempresentasikan keindahan, keluwesan, dan keharuman dari bunga pudak. Sedangkan penetapan jumlah penari lima orang didasarkan atas pertimbangan kebutuhan koreografi agar dapat membentuk desain-desain komposisi lantai yang menarik dan dinamis, baik ketika ditarikan di area panggung yang luas atau pun area panggung yang kecil. Penyajian tari maskot ini dirancang dengan durasi waktu 9 menit.
"
+ }
+]
\ No newline at end of file
diff --git a/prisma/data/desa/profile/profil_perbekel.json b/prisma/data/desa/profile/profil_perbekel.json
index 3f846693..efaf0021 100644
--- a/prisma/data/desa/profile/profil_perbekel.json
+++ b/prisma/data/desa/profile/profil_perbekel.json
@@ -1,6 +1,6 @@
[
{
- "id": "1",
+ "id": "edit",
"biodata": "I.B Surya Prabhawa Manuaba, S.H., M.H., adalah Perbekel Darmasaba periode 2021-2027, seorang advokat, pendiri Mantra Legal Consultants & Advocates, serta aktif di bidang musik dan akademis. Dia menempuh pendidikan hukum di Universitas Udayana dan Universitas Mahasaraswati Denpasar serta memiliki pengalaman luas di berbagai organisasi dan kepemimpinan.
",
"pengalaman": "2021 - 2027: Perbekel Desa Darmasaba 2015 - Sekarang: Founder & Managing Director Mantra Legal Consultants & Advocates 2020 - Sekarang: Founder Ugawa Record Music Studio 2010 - 2016: Dosen Fakultas Hukum Universitas Mahasaraswati Denpasar ",
"pengalamanOrganisasi": " 1996 – 1997: Ketua OSIS SMP Negeri 1 Abiansemal 1999 – 2000: Ketua OSIS SMA Negeri 1 Mengwi 2008 – 2009: Ketua BEM Universitas Mahasaraswati Denpasar 2008 – 2010: Ketua Sekaa Taruna Sila Dharma, Banjar Tengah, Desa Adat Tegal, Darmasaba 2020 – Sekarang: Pengurus Young Lawyer Committee Peradi Denpasar 2021 – Sekarang: Dewan Kehormatan Himpunan Pengusaha Muda Indonesia (HIPMI) Badung 2023 – 2028: Komite Tetap Advokasi – Bidang Hukum dan Regulasi Kamar Dagang dan Industri Badung ",
diff --git a/prisma/data/desa/profile/profile_desa.json b/prisma/data/desa/profile/profile_desa.json
deleted file mode 100644
index 29ed4d8a..00000000
--- a/prisma/data/desa/profile/profile_desa.json
+++ /dev/null
@@ -1,11 +0,0 @@
-[
- {
- "id": "1",
- "sejarah" : "Asal – usul nama Darmasaba tertuang dalam lontar Usada Bali. Seperti di tulis dalam monografi Desa Darmasaba tahun 1980 silam, nama Darmasaba berkaitan dengan keturunan Danghyang Nirarta diceritakan, Sang kawi-wiku asal Daha (Jawa Timur) itu memiliki cucu bernama Ida Pedanda Sakti Manuaba yang tigggal di Desa Kendran Tegalalang Gianyar. Merasa tidak disenangi sang ayah, Ida Pedanda Sakti Manuaba pergi mengembara bersama dua orang pengiringnya. Pengembaraan sang pendeta sampai di pura Sarin Buana di Jimbaran. Saat mengadakan semedi di tempat ini sang pendeta melihat sinar api. Yang sangat jauh di utara. Timbul keinginan Ida Pedanda Manuaba untuk mengunjungi tempat itu. Sampailah sang Pedanda di pura Batan Bila Peguyangan. Disini Ida Pedanda Manuaba singgah menghadap Ida Pedanda Budha yang tinggal disana. Selanjutnya, kedua pendeta bersama-sama menuju arah utara dan singgah di Taman Cang Ana, sebuah taman milik Arya Lanang Blusung. Di tempat ini kedua pendeta bersama-sama melaksanakan semedi dan menetap untuk sementara waktu.
",
- "visi" : "Mewujudkan Desa Darmasaba yang sejahtera, unggul, religius, berbudaya, dan aman dengan berlandaskan Tri Hita Karana
",
- "misi" : "Memperkokoh kerukunan hidup masyarakat dalam jalinan adat, budaya, olahraga, dan agama. Meningkatkan kualitas pelayanan publik dengan menerapkan teknologi informasi dan komunikasi terintegrasi. Meningkatkan tata kelola pemerintah desa dengan menerapkan prinsip good governance dan good clean government. Meningkatkan kualitas pendidikan, kesehatan, Keluarga Berencana serta pengelolaan kependudukan. Memperkuat usaha mikro kecil dan menengah (UMKM) dan BUMDesa sebagai pilar ekonomi masyarakat. Mewujudkan tatanan kehidupan bermasyarakat yang menjunjung tinggi penegakan hukum dan HAM. Meningkatkan perlindungan dan pengelolaan terhadap sumber daya alam dan lingkungan hidup. Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa. Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata. ",
- "lambang" : "Memperkokoh kerukunan hidup masyarakat dalam jalinan adat, budaya, olahraga, dan agama. Meningkatkan kualitas pelayanan publik dengan menerapkan teknologi informasi dan komunikasi terintegrasi. Meningkatkan tata kelola pemerintah desa dengan menerapkan prinsip good governance dan good clean government. Meningkatkan kualitas pendidikan, kesehatan, Keluarga Berencana serta pengelolaan kependudukan. Memperkuat usaha mikro kecil dan menengah (UMKM) dan BUMDesa sebagai pilar ekonomi masyarakat. Mewujudkan tatanan kehidupan bermasyarakat yang menjunjung tinggi penegakan hukum dan HAM. Meningkatkan perlindungan dan pengelolaan terhadap sumber daya alam dan lingkungan hidup. Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa. Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata. Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa. Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata. ",
- "maskot" : "Pudak adalah bunga dari tanaman sejenis pandan (Pandanaceae). Bentuk bunga ini tersusun dalam beberapa lapisan, terbungkus oleh kelopak warna putih (semacam daun lonjong) yang ujungnya meruncing.
Bunga Pudak berwarna kuning dan akan terlihat jika kelopak atau pelepahnya telah mekar. Kekhasan dari bunga pudak, yaitu mempunyai aroma wangi yang semerbak nan lembut (tidak menyengat), dan dapat menebar keharuman sepanjang pagi atau pun sore hari. Tanaman ini dapat tumbuh di sepanjang pantai, aliran sungai, di atas batu-batu karang, dan juga di tanah ladang.
Dalam Kamus Jawa Kuna- Indonesia kata “Pudak” berarti bunga pandan atau Pandanus Moschatus (Mardiwarsito: 1981: 442). Selain itu bunga pudak juga dapat disebut ketaka atau ketaki (Mardiwarsito, 1981: 276). Sedangkan kata “Sategal” berasal dari kata dasar “Tegal” yang berarti ladang (Mardiwarsito, 1981: 593). Jadi Pudak Sategal dapat diartikan sebagai satu ladang luas yang dipenuhi bunga pudak dan menabar keharuman.
Pada sebuah kesempatan, Ida Pedanda Putu Pemaron menjelaskan mengenai makna dari istilah Pudak Sategal dengan sebuah analogi bahwa, sekuntum bunga pudak memiliki aroma wangi atau keharuman yang sangat kuat, apalagi jika satu ladang penuh bunga pudak, maka dapat dipastikan aroma keharumannya akan membumbung menyebar ke segala penjuru (Wawancara, 18 Mei 2019 di Geria Putra Mandara Kenderan, Tegallalang). “Pudak” ialah sebuah bunga yang memiliki aroma wangi atau keharuman yang semerbak, lembut, dan khas.
Garapan Tari Maskot Desa Darmasaba Sekar Pudak diwujudkan ke dalam bentuk tari kreasi yang ditarikan secara berkelompok dengan jumlah lima orang penari perempuan (putri).
Pemilihan penari perempuan dimaksudkan untuk mempresentasikan keindahan, keluwesan, dan keharuman dari bunga pudak. Sedangkan penetapan jumlah penari lima orang didasarkan atas pertimbangan kebutuhan koreografi agar dapat membentuk desain-desain komposisi lantai yang menarik dan dinamis, baik ketika ditarikan di area panggung yang luas atau pun area panggung yang kecil. Penyajian tari maskot ini dirancang dengan durasi waktu 9 menit.
",
- "profilPerbekelId" : "1"
- }
-]
\ No newline at end of file
diff --git a/prisma/data/desa/profile/sejarah_desa.json b/prisma/data/desa/profile/sejarah_desa.json
new file mode 100644
index 00000000..347194e5
--- /dev/null
+++ b/prisma/data/desa/profile/sejarah_desa.json
@@ -0,0 +1,7 @@
+[
+ {
+ "id": "edit",
+ "judul": "Sejarah Desa",
+ "deskripsi": "Asal – usul nama Darmasaba tertuang dalam lontar Usada Bali. Seperti di tulis dalam monografi Desa Darmasaba tahun 1980 silam, nama Darmasaba berkaitan dengan keturunan Danghyang Nirarta diceritakan, Sang kawi-wiku asal Daha (Jawa Timur) itu memiliki cucu bernama Ida Pedanda Sakti Manuaba yang tigggal di Desa Kendran Tegalalang Gianyar. Merasa tidak disenangi sang ayah, Ida Pedanda Sakti Manuaba pergi mengembara bersama dua orang pengiringnya. Pengembaraan sang pendeta sampai di pura Sarin Buana di Jimbaran. Saat mengadakan semedi di tempat ini sang pendeta melihat sinar api. Yang sangat jauh di utara. Timbul keinginan Ida Pedanda Manuaba untuk mengunjungi tempat itu. Sampailah sang Pedanda di pura Batan Bila Peguyangan. Disini Ida Pedanda Manuaba singgah menghadap Ida Pedanda Budha yang tinggal disana. Selanjutnya, kedua pendeta bersama-sama menuju arah utara dan singgah di Taman Cang Ana, sebuah taman milik Arya Lanang Blusung. Di tempat ini kedua pendeta bersama-sama melaksanakan semedi dan menetap untuk sementara waktu.
"
+ }
+]
\ No newline at end of file
diff --git a/prisma/data/desa/profile/visi_misi_desa.json b/prisma/data/desa/profile/visi_misi_desa.json
new file mode 100644
index 00000000..5fd0b7bc
--- /dev/null
+++ b/prisma/data/desa/profile/visi_misi_desa.json
@@ -0,0 +1,7 @@
+[
+ {
+ "id" : "edit",
+ "visi" : "Mewujudkan Desa Darmasaba yang sejahtera, unggul, religius, berbudaya, dan aman dengan berlandaskan Tri Hita Karana
",
+ "misi" : "Memperkokoh kerukunan hidup masyarakat dalam jalinan adat, budaya, olahraga, dan agama. Meningkatkan kualitas pelayanan publik dengan menerapkan teknologi informasi dan komunikasi terintegrasi. Meningkatkan tata kelola pemerintah desa dengan menerapkan prinsip good governance dan good clean government. Meningkatkan kualitas pendidikan, kesehatan, Keluarga Berencana serta pengelolaan kependudukan. Memperkuat usaha mikro kecil dan menengah (UMKM) dan BUMDesa sebagai pilar ekonomi masyarakat. Mewujudkan tatanan kehidupan bermasyarakat yang menjunjung tinggi penegakan hukum dan HAM. Meningkatkan perlindungan dan pengelolaan terhadap sumber daya alam dan lingkungan hidup. Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa. Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata. "
+ }
+]
\ No newline at end of file
diff --git a/prisma/data/ppid/profile-ppid/profilePPid.json b/prisma/data/ppid/profile-ppid/profilePPid.json
index 3727382c..0c6828f7 100644
--- a/prisma/data/ppid/profile-ppid/profilePPid.json
+++ b/prisma/data/ppid/profile-ppid/profilePPid.json
@@ -1,11 +1,10 @@
[
{
- "id": "1",
+ "id": "edit",
"name": "I.B Surya Prabhawa Manuaba, S.H., M.H.",
"biodata": "I.B Surya Prabhawa Manuaba, S.H., M.H., adalah Perbekel Darmasaba periode 2021-2027, seorang advokat, pendiri Mantra Legal Consultants & Advocates, serta aktif di bidang musik dan akademis. Dia menempuh pendidikan hukum di Universitas Udayana dan Universitas Mahasaraswati Denpasar, serta memiliki pengalaman luas di berbagai organisasi dan kepemimpinan.
",
"riwayat": " 2021 - 2027: Perbekel Desa Darmasaba 2015 - Sekarang: Founder & Managing Director Mantra Legal Consultants & Advocates 2020 - Sekarang: Founder Ugawa Record Music Studio 2010 - 2016: Dosen Fakultas Hukum Universitas Mahasaraswati Denpasar ",
"pengalaman": " 1996 – 1997: Ketua OSIS SMP Negeri 1 Abiansemal 1999 – 2000: Ketua OSIS SMA Negeri 1 Mengwi 2008 – 2009: Ketua BEM Universitas Mahasaraswati Denpasar 2008 – 2010: Ketua Sekaa Taruna Sila Dharma, Banjar Tengah, Desa Adat Tegal, Darmasaba 2020 – Sekarang: Pengurus Young Lawyer Committee Peradi Denpasar 2021 – Sekarang: Dewan Kehormatan Himpunan Pengusaha Muda Indonesia (HIPMI) Badung 2023 – 2028: Komite Tetap Advokasi – Bidang Hukum dan Regulasi Kamar Dagang dan Industri Badung ",
- "unggulan": "Pemberdayaan Ekonomi dan UMKM Pelatihan dan pendampingan UMKM lokal Program bantuan modal usaha bagi pelaku usaha kecil Digitalisasi UMKM untuk meningkatkan pemasaran produk lokal ",
- "imageUrl": "/uploads/seeded-images/profile-ppid/perbekel.png"
+ "unggulan": "Pemberdayaan Ekonomi dan UMKM Pelatihan dan pendampingan UMKM lokal Program bantuan modal usaha bagi pelaku usaha kecil Digitalisasi UMKM untuk meningkatkan pemasaran produk lokal "
}
]
diff --git a/prisma/data/ppid/struktur-ppid/strukturPPID.json b/prisma/data/ppid/struktur-ppid/strukturPPID.json
new file mode 100644
index 00000000..cdc2ff14
--- /dev/null
+++ b/prisma/data/ppid/struktur-ppid/strukturPPID.json
@@ -0,0 +1,6 @@
+[
+ {
+ "id" : "1",
+ "name" : "Struktur PPID"
+ }
+]
\ No newline at end of file
diff --git a/prisma/migrations/20250616155255_16_jun/migration.sql b/prisma/migrations/20250616155255_16_jun/migration.sql
new file mode 100644
index 00000000..fff7b159
--- /dev/null
+++ b/prisma/migrations/20250616155255_16_jun/migration.sql
@@ -0,0 +1,193 @@
+/*
+ Warnings:
+
+ - You are about to drop the column `nomor` on the `DaftarInformasiPublik` table. All the data in the column will be lost.
+ - You are about to drop the column `image` on the `GalleryFoto` table. All the data in the column will be lost.
+ - You are about to drop the column `video` on the `GalleryVideo` table. All the data in the column will be lost.
+ - You are about to drop the column `videosId` on the `GalleryVideo` table. All the data in the column will be lost.
+ - The primary key for the `IndeksKepuasanMasyarakat` table will be changed. If it partially fails, the table could be left without primary key constraint.
+ - You are about to drop the column `profilPerbekelId` on the `ProfileDesa` table. All the data in the column will be lost.
+ - You are about to drop the column `imageUrl` on the `ProfilePPID` table. All the data in the column will be lost.
+ - You are about to drop the `Images` table. If the table is not empty, all the data it contains will be lost.
+ - You are about to drop the `Videos` table. If the table is not empty, all the data it contains will be lost.
+ - Added the required column `deskripsi` to the `GalleryFoto` table without a default value. This is not possible if the table is not empty.
+ - Added the required column `deskripsi` to the `GalleryVideo` table without a default value. This is not possible if the table is not empty.
+ - Added the required column `linkVideo` to the `GalleryVideo` table without a default value. This is not possible if the table is not empty.
+
+*/
+-- DropForeignKey
+ALTER TABLE "GalleryFoto" DROP CONSTRAINT "GalleryFoto_imagesId_fkey";
+
+-- DropForeignKey
+ALTER TABLE "GalleryVideo" DROP CONSTRAINT "GalleryVideo_videosId_fkey";
+
+-- DropForeignKey
+ALTER TABLE "ProfileDesa" DROP CONSTRAINT "ProfileDesa_profilPerbekelId_fkey";
+
+-- DropIndex
+DROP INDEX "GalleryVideo_videosId_key";
+
+-- AlterTable
+ALTER TABLE "DaftarInformasiPublik" DROP COLUMN "nomor";
+
+-- AlterTable
+ALTER TABLE "GalleryFoto" DROP COLUMN "image",
+ADD COLUMN "deskripsi" TEXT NOT NULL;
+
+-- AlterTable
+ALTER TABLE "GalleryVideo" DROP COLUMN "video",
+DROP COLUMN "videosId",
+ADD COLUMN "deskripsi" TEXT NOT NULL,
+ADD COLUMN "linkVideo" TEXT NOT NULL;
+
+-- AlterTable
+ALTER TABLE "IndeksKepuasanMasyarakat" DROP CONSTRAINT "IndeksKepuasanMasyarakat_pkey",
+ALTER COLUMN "id" DROP DEFAULT,
+ALTER COLUMN "id" SET DATA TYPE TEXT,
+ADD CONSTRAINT "IndeksKepuasanMasyarakat_pkey" PRIMARY KEY ("id");
+DROP SEQUENCE "IndeksKepuasanMasyarakat_id_seq";
+
+-- AlterTable
+ALTER TABLE "ProfileDesa" DROP COLUMN "profilPerbekelId";
+
+-- AlterTable
+ALTER TABLE "ProfilePPID" DROP COLUMN "imageUrl",
+ADD COLUMN "imageId" TEXT;
+
+-- DropTable
+DROP TABLE "Images";
+
+-- DropTable
+DROP TABLE "Videos";
+
+-- CreateTable
+CREATE TABLE "StrukturPPID" (
+ "id" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "imageId" TEXT,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
+
+ CONSTRAINT "StrukturPPID_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "ProfileDesaImage" (
+ "id" TEXT NOT NULL,
+ "label" TEXT NOT NULL,
+ "profileDesaId" TEXT NOT NULL,
+ "imageId" TEXT NOT NULL,
+
+ CONSTRAINT "ProfileDesaImage_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "PelayananSuratKeterangan" (
+ "id" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "deskripsi" TEXT NOT NULL,
+ "imageId" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
+
+ CONSTRAINT "PelayananSuratKeterangan_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "PelayananTelunjukSaktiDesa" (
+ "id" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "deskripsi" TEXT NOT NULL,
+ "link" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
+
+ CONSTRAINT "PelayananTelunjukSaktiDesa_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "PelayananPerizinanBerusaha" (
+ "id" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "deskripsi" TEXT NOT NULL,
+ "link" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
+
+ CONSTRAINT "PelayananPerizinanBerusaha_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "PelayananPendudukNonPermanen" (
+ "id" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "deskripsi" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
+
+ CONSTRAINT "PelayananPendudukNonPermanen_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "Penghargaan" (
+ "id" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "juara" TEXT NOT NULL,
+ "deskripsi" TEXT NOT NULL,
+ "imageId" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
+
+ CONSTRAINT "Penghargaan_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "Posyandu" (
+ "id" TEXT NOT NULL,
+ "name" TEXT NOT NULL,
+ "nomor" TEXT NOT NULL,
+ "deskripsi" TEXT NOT NULL,
+ "imageId" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
+
+ CONSTRAINT "Posyandu_pkey" PRIMARY KEY ("id")
+);
+
+-- AddForeignKey
+ALTER TABLE "StrukturPPID" ADD CONSTRAINT "StrukturPPID_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "ProfilePPID" ADD CONSTRAINT "ProfilePPID_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "ProfileDesaImage" ADD CONSTRAINT "ProfileDesaImage_profileDesaId_fkey" FOREIGN KEY ("profileDesaId") REFERENCES "ProfileDesa"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "ProfileDesaImage" ADD CONSTRAINT "ProfileDesaImage_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "GalleryFoto" ADD CONSTRAINT "GalleryFoto_imagesId_fkey" FOREIGN KEY ("imagesId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "PelayananSuratKeterangan" ADD CONSTRAINT "PelayananSuratKeterangan_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "Penghargaan" ADD CONSTRAINT "Penghargaan_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "Posyandu" ADD CONSTRAINT "Posyandu_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
diff --git a/prisma/migrations/20250617083234_17jun/migration.sql b/prisma/migrations/20250617083234_17jun/migration.sql
new file mode 100644
index 00000000..2ff042ca
--- /dev/null
+++ b/prisma/migrations/20250617083234_17jun/migration.sql
@@ -0,0 +1,78 @@
+/*
+ Warnings:
+
+ - You are about to drop the column `profileDesaId` on the `ProfileDesaImage` table. All the data in the column will be lost.
+ - You are about to drop the `ProfileDesa` table. If the table is not empty, all the data it contains will be lost.
+ - Added the required column `maskotDesaId` to the `ProfileDesaImage` table without a default value. This is not possible if the table is not empty.
+
+*/
+-- DropForeignKey
+ALTER TABLE "ProfileDesaImage" DROP CONSTRAINT "ProfileDesaImage_profileDesaId_fkey";
+
+-- AlterTable
+ALTER TABLE "ProfilPerbekel" ADD COLUMN "imageId" TEXT;
+
+-- AlterTable
+ALTER TABLE "ProfileDesaImage" DROP COLUMN "profileDesaId",
+ADD COLUMN "maskotDesaId" TEXT NOT NULL;
+
+-- DropTable
+DROP TABLE "ProfileDesa";
+
+-- CreateTable
+CREATE TABLE "SejarahDesa" (
+ "id" TEXT NOT NULL,
+ "judul" TEXT NOT NULL,
+ "deskripsi" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
+
+ CONSTRAINT "SejarahDesa_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "VisiMisiDesa" (
+ "id" TEXT NOT NULL,
+ "visi" TEXT NOT NULL,
+ "misi" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
+
+ CONSTRAINT "VisiMisiDesa_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "LambangDesa" (
+ "id" TEXT NOT NULL,
+ "judul" TEXT NOT NULL,
+ "deskripsi" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
+
+ CONSTRAINT "LambangDesa_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "MaskotDesa" (
+ "id" TEXT NOT NULL,
+ "judul" TEXT NOT NULL,
+ "deskripsi" TEXT NOT NULL,
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+ "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
+
+ CONSTRAINT "MaskotDesa_pkey" PRIMARY KEY ("id")
+);
+
+-- AddForeignKey
+ALTER TABLE "ProfileDesaImage" ADD CONSTRAINT "ProfileDesaImage_maskotDesaId_fkey" FOREIGN KEY ("maskotDesaId") REFERENCES "MaskotDesa"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "ProfilPerbekel" ADD CONSTRAINT "ProfilPerbekel_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 31430ab9..187b4e07 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -50,21 +50,42 @@ model AppMenuChild {
// ========================================= FILE STORAGE ========================================= //
model FileStorage {
- id String @id @default(cuid())
- name String @unique
- realName String
- path String
- mimeType String
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- deletedAt DateTime?
- isActive Boolean @default(true)
- link String
- Berita Berita[]
- PotensiDesa PotensiDesa[]
+ id String @id @default(cuid())
+ name String @unique
+ realName String
+ path String
+ mimeType String
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime?
+ isActive Boolean @default(true)
+ link String
+ Berita Berita[]
+ PotensiDesa PotensiDesa[]
+ Posyandu Posyandu[]
+ StrukturPPID StrukturPPID[]
+ GalleryFoto GalleryFoto[]
+ PelayananSuratKeterangan PelayananSuratKeterangan[]
+ Penghargaan Penghargaan[]
+ ProfileDesaImage ProfileDesaImage[]
+ ProfilePPID ProfilePPID[]
+ ProfilPerbekel ProfilPerbekel[]
}
//========================================= MENU PPID ========================================= //
+
+//========================================= STRUKTUR PPID ========================================= //
+model StrukturPPID {
+ id String @id @default(cuid())
+ name String @db.Text
+ image FileStorage? @relation(fields: [imageId], references: [id])
+ imageId String?
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
+}
+
// ========================================= VISI MISI PPID ========================================= //
model VisiMisiPPID {
id String @id @default(cuid())
@@ -89,23 +110,23 @@ model DasarHukumPPID {
// ========================================= PROFILE PPID ========================================= //
model ProfilePPID {
- id String @id @default(cuid())
- name String @db.Text
- biodata String @db.Text
- riwayat String @db.Text
- pengalaman String @db.Text
- unggulan String @db.Text
- imageUrl String?
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- deletedAt DateTime @default(now())
- isActive Boolean @default(true)
+ id String @id @default(cuid())
+ name String @db.Text
+ biodata String @db.Text
+ riwayat String @db.Text
+ pengalaman String @db.Text
+ unggulan String @db.Text
+ image FileStorage? @relation(fields: [imageId], references: [id])
+ imageId String?
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
}
// ========================================= DAFTAR INFORMASI PUBLIK ========================================= //
model DaftarInformasiPublik {
id String @id @default(cuid())
- nomor Int @default(autoincrement())
jenisInformasi String
deskripsi String
tanggal String
@@ -181,7 +202,7 @@ model FormulirPermohonanKeberatan {
// ========================================= IKM ========================================= //
model IndeksKepuasanMasyarakat {
- id Int @id @default(autoincrement())
+ id String @id @default(cuid())
label String
kepuasan String
createdAt DateTime @default(now())
@@ -226,32 +247,68 @@ model GrafikBerdasarkanUmur {
// ========================================= MENU DESA ========================================= //
// ========================================= PROFILE DESA ========================================= //
-model ProfileDesa {
- id String @id @default(cuid())
- sejarah String @db.Text
- visi String @db.Text
- misi String @db.Text
- lambang String @db.Text
- maskot String @db.Text
- ProfilPerbekel ProfilPerbekel? @relation(fields: [profilPerbekelId], references: [id])
- profilPerbekelId String?
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- deletedAt DateTime @default(now())
- isActive Boolean @default(true)
+model SejarahDesa {
+ id String @id @default(cuid())
+ judul String @db.Text
+ deskripsi String @db.Text
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
+}
+
+model VisiMisiDesa {
+ id String @id @default(cuid())
+ visi String @db.Text
+ misi String @db.Text
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
+}
+
+model LambangDesa {
+ 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 MaskotDesa {
+ id String @id @default(cuid())
+ judul String
+ deskripsi String @db.Text
+ images ProfileDesaImage[]
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
+}
+
+model ProfileDesaImage {
+ id String @id @default(cuid())
+ label String
+ image FileStorage @relation(fields: [imageId], references: [id])
+ imageId String
+ MaskotDesa MaskotDesa @relation(fields: [maskotDesaId], references: [id])
+ maskotDesaId String
}
model ProfilPerbekel {
- id String @id @default(cuid())
- biodata String @db.Text
- pengalaman String @db.Text
- pengalamanOrganisasi String @db.Text
- programUnggulan String @db.Text
- ProfileDesa ProfileDesa[]
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- deletedAt DateTime @default(now())
- isActive Boolean @default(true)
+ id String @id @default(cuid())
+ biodata String @db.Text
+ pengalaman String @db.Text
+ pengalamanOrganisasi String @db.Text
+ programUnggulan String @db.Text
+ image FileStorage? @relation(fields: [imageId], references: [id])
+ imageId String?
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
}
// ========================================= BERITA ========================================= //
@@ -319,51 +376,87 @@ model CategoryPengumuman {
isActive Boolean @default(true)
}
-// ========================================= IMAGES ========================================= //
-model Images {
- id String @id @default(cuid())
- url String
- label String @default("null")
- active Boolean @default(true)
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- GalleryFoto GalleryFoto[]
-}
-
-// ========================================= VIDEOS ========================================= //
-model Videos {
- id String @id @default(cuid())
- url String
- label String @default("null")
- active Boolean @default(true)
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- GalleryVideo GalleryVideo[]
-}
-
// ========================================= GALLERY ========================================= //
model GalleryFoto {
- id String @id @default(cuid())
+ id String @id @default(cuid())
name String
- image String
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- deletedAt DateTime @default(now())
- isActive Boolean @default(true)
- imagesId String? @unique
- imageGalleryFoto Images? @relation(fields: [imagesId], references: [id])
+ deskripsi String @db.Text
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
+ imagesId String? @unique
+ imageGalleryFoto FileStorage? @relation(fields: [imagesId], references: [id])
}
model GalleryVideo {
- id String @id @default(cuid())
- name String
- video String
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- deletedAt DateTime @default(now())
- isActive Boolean @default(true)
- videosId String? @unique
- videosGalleryVideo Videos? @relation(fields: [videosId], references: [id])
+ id String @id @default(cuid())
+ name String
+ deskripsi String @db.Text
+ linkVideo String
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
+}
+
+// ========================================= LAYANAN DESA ========================================= //
+model PelayananSuratKeterangan {
+ id String @id @default(cuid())
+ name String
+ deskripsi String @db.Text
+ 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 PelayananTelunjukSaktiDesa {
+ id String @id @default(cuid())
+ name String
+ deskripsi String @db.Text
+ link String
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
+}
+
+model PelayananPerizinanBerusaha {
+ id String @id @default(cuid())
+ name String
+ deskripsi String @db.Text
+ link String
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
+}
+
+model PelayananPendudukNonPermanen {
+ id String @id @default(cuid())
+ name String
+ deskripsi String @db.Text
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
+}
+
+// ========================================= PENGHARGAAN ========================================= //
+model Penghargaan {
+ id String @id @default(cuid())
+ name String
+ juara String
+ deskripsi String @db.Text
+ image FileStorage @relation(fields: [imageId], references: [id])
+ imageId String
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ deletedAt DateTime @default(now())
+ isActive Boolean @default(true)
}
// ========================================= MENU KESEHATAN ========================================= //
@@ -615,3 +708,17 @@ model DoctorSign {
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
+
+// ========================================= POSYANDU ========================================= //
+model Posyandu {
+ id String @id @default(cuid())
+ name String
+ nomor String
+ deskripsi 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)
+}
diff --git a/prisma/seed.ts b/prisma/seed.ts
index e3fe12c8..b6b9067b 100644
--- a/prisma/seed.ts
+++ b/prisma/seed.ts
@@ -6,13 +6,17 @@ import caraMemperolehSalinanInformasi from "./data/list-caraMemperolehSalinanInf
import jenisInformasiDiminta from "./data/list-jenisInfromasi.json";
import layanan from "./data/list-layanan.json";
import potensi from "./data/list-potensi.json";
-import visiMisiPPID from "./data/ppid/visi-misi-ppid/visimisiPPID.json";
import dasarHukumPPID from "./data/ppid/dasar-hukum-ppid/dasarhukumPPID.json";
import profilePPID from "./data/ppid/profile-ppid/profilePPid.json";
-import path from "path";
-import fs from "fs";
-import { mkdir, writeFile } from "fs/promises";
-import { v4 as uuid } from "uuid";
+import visiMisiPPID from "./data/ppid/visi-misi-ppid/visimisiPPID.json";
+import strukturPPID from "./data/ppid/struktur-ppid/strukturPPID.json";
+import pelayananPerizinanBerusaha from "./data/desa/layanan/pelayananPerizinanBerusaha.json";
+import pelayananPendudukNonPermanen from "./data/desa/layanan/pelayanaPendudukNonPermanen.json";
+import sejarahDesa from "./data/desa/profile/sejarah_desa.json";
+import visiMisiDesa from "./data/desa/profile/visi_misi_desa.json";
+import lambangDesa from "./data/desa/profile/lambang_desa.json";
+import maskotDesa from "./data/desa/profile/maskot_desa.json";
+import profilPerbekel from "./data/desa/profile/profil_perbekel.json";
(async () => {
for (const l of layanan) {
@@ -31,6 +35,159 @@ import { v4 as uuid } from "uuid";
console.log("layanan success ...");
+ for (const l of sejarahDesa) {
+ await prisma.sejarahDesa.upsert({
+ where: {
+ id: l.id,
+ },
+ update: {
+ judul: l.judul,
+ deskripsi: l.deskripsi,
+ },
+ create: {
+ id: l.id,
+ judul: l.judul,
+ deskripsi: l.deskripsi,
+ },
+ });
+ }
+
+ console.log("sejarah desa success ...");
+
+ for (const l of maskotDesa) {
+ await prisma.maskotDesa.upsert({
+ where: {
+ id: l.id,
+ },
+ update: {
+ judul: l.judul,
+ deskripsi: l.deskripsi,
+ },
+ create: {
+ id: l.id,
+ judul: l.judul,
+ deskripsi: l.deskripsi,
+ },
+ });
+ }
+
+ console.log("maskot desa success ...");
+
+ for (const l of lambangDesa) {
+ await prisma.lambangDesa.upsert({
+ where: {
+ id: l.id,
+ },
+ update: {
+ judul: l.judul,
+ deskripsi: l.deskripsi,
+ },
+ create: {
+ id: l.id,
+ judul: l.judul,
+ deskripsi: l.deskripsi,
+ },
+ });
+ }
+
+ console.log("lambang desa success ...");
+
+ for (const c of profilPerbekel) {
+ await prisma.profilPerbekel.upsert({
+ where: { id: c.id },
+ update: {
+ biodata: c.biodata,
+ pengalaman: c.pengalaman,
+ pengalamanOrganisasi: c.pengalamanOrganisasi,
+ programUnggulan: c.programUnggulan,
+ // imageId tidak di-update
+ },
+ create: {
+ id: c.id,
+ biodata: c.biodata,
+ pengalaman: c.pengalaman,
+ pengalamanOrganisasi: c.pengalamanOrganisasi,
+ programUnggulan: c.programUnggulan,
+ // imageId tidak di-create
+ },
+ });
+ }
+ console.log("✅ profilePerbekel seeded without imageId (editable later via UI)");
+
+ for (const l of visiMisiDesa) {
+ await prisma.visiMisiDesa.upsert({
+ where: {
+ id: l.id,
+ },
+ update: {
+ visi: l.visi,
+ misi: l.misi,
+ },
+ create: {
+ id: l.id,
+ visi: l.visi,
+ misi: l.misi,
+ },
+ });
+ }
+
+ console.log("visi misi desa success ...");
+
+ for (const l of pelayananPerizinanBerusaha) {
+ await prisma.pelayananPerizinanBerusaha.upsert({
+ where: {
+ id: l.id,
+ },
+ update: {
+ name: l.name,
+ deskripsi: l.deskripsi,
+ link: l.link,
+ },
+ create: {
+ id: l.id,
+ name: l.name,
+ deskripsi: l.deskripsi,
+ link: l.link,
+ },
+ });
+ }
+
+ console.log("pelayanan perizinan berusaha success ...");
+
+ for (const l of pelayananPendudukNonPermanen) {
+ await prisma.pelayananPendudukNonPermanen.upsert({
+ where: {
+ id: l.id,
+ },
+ update: {
+ name: l.name,
+ deskripsi: l.deskripsi,
+ },
+ create: {
+ id: l.id,
+ name: l.name,
+ deskripsi: l.deskripsi,
+ },
+ });
+ }
+ console.log("pelayanan penduduk non permanen success ...");
+
+ for (const s of strukturPPID) {
+ await prisma.strukturPPID.upsert({
+ where: {
+ id: s.id,
+ },
+ update: {
+ name: s.name,
+ },
+ create: {
+ id: s.id,
+ name: s.name,
+ },
+ });
+ }
+ console.log("struktur ppid success ...");
+
for (const p of potensi) {
await prisma.potensi.upsert({
where: {
@@ -124,56 +281,29 @@ import { v4 as uuid } from "uuid";
}
console.log("cara memperoleh salinan informasi success ...");
- const seedProfilePPID = async () => {
- const targetDir = path.resolve("public", "uploads", "seeded-images", "profile-ppid")
-
- // Buat folder hanya jika belum ada
- if (!fs.existsSync(targetDir)) {
- await mkdir(targetDir, { recursive: true })
- }
-
- for (const c of profilePPID) {
- let finalImageUrl = c.imageUrl
-
- if (c.imageUrl.startsWith("/uploads/seeded-images/")) {
- const filename = path.basename(c.imageUrl)
- const seedImagePath = path.resolve("prisma", "seed-images", filename)
-
- const targetFilename = `${uuid()}_${filename}`
- const targetPath = path.join(targetDir, targetFilename)
-
- const buffer = fs.readFileSync(seedImagePath)
- await writeFile(targetPath, buffer)
-
- finalImageUrl = `/uploads/seeded-images/profile-ppid/${targetFilename}`
- }
-
- await prisma.profilePPID.upsert({
- where: { id: c.id },
- update: {
- name: c.name,
- biodata: c.biodata,
- riwayat: c.riwayat,
- pengalaman: c.pengalaman,
- unggulan: c.unggulan,
- imageUrl: finalImageUrl,
- },
- create: {
- id: c.id,
- name: c.name,
- biodata: c.biodata,
- riwayat: c.riwayat,
- pengalaman: c.pengalaman,
- unggulan: c.unggulan,
- imageUrl: finalImageUrl,
- },
- })
- }
-
- console.log("✅ profilePPID seeded from JSON with image copying")
+ for (const c of profilePPID) {
+ await prisma.profilePPID.upsert({
+ where: { id: c.id },
+ update: {
+ name: c.name,
+ biodata: c.biodata,
+ riwayat: c.riwayat,
+ pengalaman: c.pengalaman,
+ unggulan: c.unggulan,
+ // imageId tidak di-update
+ },
+ create: {
+ id: c.id,
+ name: c.name,
+ biodata: c.biodata,
+ riwayat: c.riwayat,
+ pengalaman: c.pengalaman,
+ unggulan: c.unggulan,
+ // imageId tidak di-create
+ },
+ });
}
-
- await seedProfilePPID()
+ console.log("✅ profilePPID seeded without imageId (editable later via UI)");
for (const v of visiMisiPPID) {
await prisma.visiMisiPPID.upsert({
@@ -210,8 +340,6 @@ import { v4 as uuid } from "uuid";
});
}
console.log("dasar hukum PPID success ...");
-
-
})()
.then(() => prisma.$disconnect())
.catch((e) => {
diff --git a/public/Share.png b/public/Share.png
new file mode 100644
index 00000000..82ffa19d
Binary files /dev/null and b/public/Share.png differ
diff --git a/public/bagikanPostingan.png b/public/bagikanPostingan.png
new file mode 100644
index 00000000..72826cbf
Binary files /dev/null and b/public/bagikanPostingan.png differ
diff --git a/public/bungapudak.png b/public/bungapudak.png
new file mode 100644
index 00000000..e35e2875
Binary files /dev/null and b/public/bungapudak.png differ
diff --git a/uploads/image/darmasaba-icon.png b/public/darmasaba-icon.png
similarity index 100%
rename from uploads/image/darmasaba-icon.png
rename to public/darmasaba-icon.png
diff --git a/public/klimakstari.png b/public/klimakstari.png
new file mode 100644
index 00000000..e668ffdf
Binary files /dev/null and b/public/klimakstari.png differ
diff --git a/public/pohonpudak.png b/public/pohonpudak.png
new file mode 100644
index 00000000..0782bbc7
Binary files /dev/null and b/public/pohonpudak.png differ
diff --git a/uploads/image/pudak-icon.png b/public/pudak-icon.png
similarity index 100%
rename from uploads/image/pudak-icon.png
rename to public/pudak-icon.png
diff --git a/public/sematkan.png b/public/sematkan.png
new file mode 100644
index 00000000..9ce93c24
Binary files /dev/null and b/public/sematkan.png differ
diff --git a/public/struktur_ppid.png b/public/struktur_ppid.png
new file mode 100644
index 00000000..5124ac1e
Binary files /dev/null and b/public/struktur_ppid.png differ
diff --git a/public/tarisekar.png b/public/tarisekar.png
new file mode 100644
index 00000000..77dcc5d3
Binary files /dev/null and b/public/tarisekar.png differ
diff --git a/public/uploads/seeded-images/profile-ppid/2513dd3c-256d-4f15-9e35-75e9819acdf4_perbekel.png b/public/uploads/seeded-images/profile-ppid/2513dd3c-256d-4f15-9e35-75e9819acdf4_perbekel.png
new file mode 100644
index 00000000..ed1cbd10
Binary files /dev/null and b/public/uploads/seeded-images/profile-ppid/2513dd3c-256d-4f15-9e35-75e9819acdf4_perbekel.png differ
diff --git a/public/uploads/seeded-images/profile-ppid/2ee01665-bf74-44b8-b851-c71b00007436_perbekel.png b/public/uploads/seeded-images/profile-ppid/2ee01665-bf74-44b8-b851-c71b00007436_perbekel.png
new file mode 100644
index 00000000..ed1cbd10
Binary files /dev/null and b/public/uploads/seeded-images/profile-ppid/2ee01665-bf74-44b8-b851-c71b00007436_perbekel.png differ
diff --git a/public/uploads/seeded-images/profile-ppid/82fd837b-fd2d-440e-8207-35c65f1022c7_perbekel.png b/public/uploads/seeded-images/profile-ppid/82fd837b-fd2d-440e-8207-35c65f1022c7_perbekel.png
new file mode 100644
index 00000000..ed1cbd10
Binary files /dev/null and b/public/uploads/seeded-images/profile-ppid/82fd837b-fd2d-440e-8207-35c65f1022c7_perbekel.png differ
diff --git a/public/uploads/seeded-images/profile-ppid/9e891f51-e57c-4d5d-8b38-87022e88b0dd_perbekel.png b/public/uploads/seeded-images/profile-ppid/9e891f51-e57c-4d5d-8b38-87022e88b0dd_perbekel.png
new file mode 100644
index 00000000..ed1cbd10
Binary files /dev/null and b/public/uploads/seeded-images/profile-ppid/9e891f51-e57c-4d5d-8b38-87022e88b0dd_perbekel.png differ
diff --git a/public/video.png b/public/video.png
new file mode 100644
index 00000000..3c144bc0
Binary files /dev/null and b/public/video.png differ
diff --git a/src/app/admin/(dashboard)/_com/modalKonfirmasiHapus.tsx b/src/app/admin/(dashboard)/_com/modalKonfirmasiHapus.tsx
index ccedf0f0..db1e64af 100644
--- a/src/app/admin/(dashboard)/_com/modalKonfirmasiHapus.tsx
+++ b/src/app/admin/(dashboard)/_com/modalKonfirmasiHapus.tsx
@@ -21,7 +21,7 @@ export function ModalKonfirmasiHapus({
Konfirmasi Hapus}
centered
>
{text}
diff --git a/src/app/admin/(dashboard)/_state/desa/gallery.ts b/src/app/admin/(dashboard)/_state/desa/gallery.ts
new file mode 100644
index 00000000..3405a6ba
--- /dev/null
+++ b/src/app/admin/(dashboard)/_state/desa/gallery.ts
@@ -0,0 +1,415 @@
+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 fotoForm = z.object({
+ name: z.string().min(1, { message: "Name is required" }),
+ deskripsi: z.string().min(1, { message: "Deskripsi is required" }),
+ imagesId: z.string().nonempty(),
+});
+
+const videoForm = z.object({
+ name: z.string().min(1, { message: "Name is required" }),
+ deskripsi: z.string().min(1, { message: "Deskripsi is required" }),
+ linkVideo: z.string().min(1, { message: "Link video is required" }),
+});
+
+const defaultFormFoto = {
+ name: "",
+ deskripsi: "",
+ imagesId: "",
+};
+
+const defaultFormVideo = {
+ name: "",
+ deskripsi: "",
+ linkVideo: "",
+};
+
+const foto = proxy({
+ create: {
+ form: { ...defaultFormFoto },
+ loading: false,
+ async create() {
+ const cek = fotoForm.safeParse(foto.create.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ return toast.error(err);
+ }
+ try {
+ foto.create.loading = true;
+ const res = await ApiFetch.api.desa.gallery.foto["create"].post(
+ foto.create.form
+ );
+ if (res.status === 200) {
+ foto.findMany.load();
+ return toast.success("Foto berhasil disimpan!");
+ }
+ return toast.error("Gagal menyimpan foto");
+ } catch (error) {
+ console.log((error as Error).message);
+ } finally {
+ foto.create.loading = false;
+ }
+ },
+ resetForm() {
+ foto.create.form = { ...defaultFormFoto };
+ },
+ },
+ findMany: {
+ data: null as
+ | Prisma.GalleryFotoGetPayload<{
+ include: {
+ imageGalleryFoto: true;
+ };
+ }>[]
+ | null,
+ async load() {
+ const res = await ApiFetch.api.desa.gallery.foto["find-many"].get();
+ if (res.status === 200) {
+ foto.findMany.data = res.data?.data ?? [];
+ }
+ },
+ },
+ findUnique: {
+ data: null as Prisma.GalleryFotoGetPayload<{
+ include: {
+ imageGalleryFoto: true;
+ };
+ }> | null,
+ async load(id: string) {
+ try {
+ const res = await fetch(`/api/desa/gallery/foto/${id}`);
+ if (res.ok) {
+ const data = await res.json();
+ foto.findUnique.data = data.data ?? null;
+ } else {
+ console.error("Failed to fetch foto:", res.statusText);
+ foto.findUnique.data = null;
+ }
+ } catch (error) {
+ console.error("Error fetching foto:", error);
+ foto.findUnique.data = null;
+ }
+ },
+ },
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
+ try {
+ foto.delete.loading = true;
+ const response = await fetch(`/api/desa/gallery/foto/del/${id}`, {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const result = await response.json();
+ if (response.ok) {
+ toast.success(result.message || "Foto berhasil dihapus");
+ await foto.findMany.load(); // refresh list
+ } else {
+ toast.error(result.message || "Gagal menghapus foto");
+ }
+ } catch (error) {
+ console.error("Gagal delete:", error);
+ toast.error("Terjadi kesalahan saat menghapus foto");
+ } finally {
+ foto.delete.loading = false;
+ }
+ },
+ },
+ update: {
+ id: "",
+ form: { ...defaultFormFoto },
+ loading: false,
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+ try {
+ const response = await fetch(`/api/desa/gallery/foto/${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,
+ deskripsi: data.deskripsi,
+ imagesId: data.imagesId || "",
+ };
+ return data;
+ } else {
+ throw new Error(result.message || "Gagal memuat data");
+ }
+ } catch (error) {
+ console.error("Error loading foto:", error);
+ toast.error(
+ error instanceof Error ? error.message : "Gagal memuat data"
+ );
+ return null;
+ }
+ },
+ async update() {
+ const cek = fotoForm.safeParse(foto.update.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ toast.error(err);
+ return false;
+ }
+ try {
+ foto.update.loading = true;
+ const response = await fetch(`/api/desa/gallery/foto/${this.id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ name: this.form.name,
+ deskripsi: this.form.deskripsi,
+ imagesId: this.form.imagesId,
+ }),
+ });
+ 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(result.message || "Foto berhasil diupdate");
+ await foto.findMany.load(); // refresh list
+ return true;
+ } else {
+ throw new Error(result.message || "Gagal mengupdate foto");
+ }
+ } catch (error) {
+ console.error("Error updating foto:", error);
+ toast.error(
+ error instanceof Error ? error.message : "Gagal mengupdate foto"
+ );
+ return false;
+ } finally {
+ foto.update.loading = false;
+ }
+ },
+ reset() {
+ foto.update.id = "";
+ foto.update.form = { ...defaultFormFoto };
+ },
+ },
+});
+
+const video = proxy({
+ create: {
+ form: { ...defaultFormVideo },
+ loading: false,
+ async create() {
+ const cek = videoForm.safeParse(video.create.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ return toast.error(err);
+ }
+ try {
+ video.create.loading = true;
+ const res = await ApiFetch.api.desa.gallery.video["create"].post(
+ video.create.form
+ );
+ if (res.status === 200) {
+ video.findMany.load();
+ return toast.success("Video berhasil disimpan!");
+ }
+ return toast.error("Gagal menyimpan video");
+ } catch (error) {
+ console.log((error as Error).message);
+ } finally {
+ video.create.loading = false;
+ }
+ },
+ resetForm() {
+ video.create.form = { ...defaultFormVideo };
+ },
+ },
+ findMany: {
+ data: null as
+ | Prisma.GalleryVideoGetPayload<{
+ omit: {
+ isActive: true;
+ };
+ }>[]
+ | null,
+ async load() {
+ const res = await ApiFetch.api.desa.gallery.video["find-many"].get();
+ if (res.status === 200) {
+ video.findMany.data = res.data?.data ?? [];
+ }
+ },
+ },
+ findUnique: {
+ data: null as Prisma.GalleryVideoGetPayload<{
+ omit: {
+ isActive: true;
+ };
+ }> | null,
+ async load(id: string) {
+ try {
+ const res = await fetch(`/api/desa/gallery/video/${id}`);
+ if (res.ok) {
+ const data = await res.json();
+ video.findUnique.data = data.data ?? null;
+ } else {
+ console.error("Failed to fetch video:", res.statusText);
+ video.findUnique.data = null;
+ }
+ } catch (error) {
+ console.error("Error fetching video:", error);
+ video.findUnique.data = null;
+ }
+ },
+ },
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
+ try {
+ video.delete.loading = true;
+ const response = await fetch(`/api/desa/gallery/video/del/${id}`, {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const result = await response.json();
+ if (response.ok) {
+ toast.success(result.message || "Video berhasil dihapus");
+ await video.findMany.load(); // refresh list
+ } else {
+ toast.error(result?.message || "Gagal menghapus video");
+ }
+ } catch (error) {
+ console.error("Gagal delete:", error);
+ toast.error("Terjadi kesalahan saat menghapus video");
+ } finally {
+ video.delete.loading = false;
+ }
+ },
+ },
+ update: {
+ id: "",
+ form: { ...defaultFormVideo },
+ loading: false,
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+ try {
+ const response = await fetch(`/api/desa/gallery/video/${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,
+ deskripsi: data.deskripsi,
+ linkVideo: data.linkVideo,
+ };
+ return data;
+ } else {
+ throw new Error(result.message || "Gagal memuat data");
+ }
+ } catch (error) {
+ console.error("Error loading video:", error);
+ toast.error(
+ error instanceof Error ? error.message : "Gagal memuat data"
+ );
+ return null;
+ }
+ },
+ async update() {
+ const cek = videoForm.safeParse(video.update.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ toast.error(err);
+ return false;
+ }
+ try {
+ video.update.loading = true;
+ const response = await fetch(`/api/desa/gallery/video/${this.id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ name: this.form.name,
+ deskripsi: this.form.deskripsi,
+ linkVideo: this.form.linkVideo,
+ }),
+ });
+ 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(result.message || "Video berhasil diupdate");
+ await video.findMany.load(); // refresh list
+ return true;
+ } else {
+ throw new Error(result.message || "Gagal mengupdate video");
+ }
+ } catch (error) {
+ console.error("Error updating video:", error);
+ toast.error(
+ error instanceof Error ? error.message : "Gagal mengupdate video"
+ );
+ return false;
+ } finally {
+ video.update.loading = false;
+ }
+ },
+ reset() {
+ video.update.id = "";
+ video.update.form = { ...defaultFormVideo };
+ },
+ },
+});
+
+const stateGallery = proxy({
+ foto,
+ video,
+});
+
+export default stateGallery;
diff --git a/src/app/admin/(dashboard)/_state/desa/layananDesa.ts b/src/app/admin/(dashboard)/_state/desa/layananDesa.ts
new file mode 100644
index 00000000..558d4672
--- /dev/null
+++ b/src/app/admin/(dashboard)/_state/desa/layananDesa.ts
@@ -0,0 +1,718 @@
+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 templateSuratKeteranganForm = z.object({
+ name: z.string().min(3, "Nama minimal 3 karakter"),
+ deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
+ imageId: z.string().nonempty(),
+});
+
+const suratKeteranganForm = {
+ name: "",
+ deskripsi: "",
+ imageId: "",
+};
+
+const telunjukSaktiDesaForm = {
+ name: "",
+ deskripsi: "",
+ link: "",
+};
+
+const templateTelunjukSaktiDesaForm = z.object({
+ name: z.string().min(3, "Nama minimal 3 karakter"),
+ deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
+});
+
+
+const templatePelayananPerizinanBerusaha = z.object({
+ name: z.string().min(3, "Nama minimal 3 karakter"),
+ deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
+ link: z.string().min(3, "Link minimal 3 karakter"),
+});
+
+type pelayananPerizinanBerusahaForm =
+ Prisma.PelayananPerizinanBerusahaGetPayload<{
+ select: {
+ id: true;
+ name: true;
+ deskripsi: true;
+ link: true;
+ };
+ }>;
+
+const pelayananPerizinanBerusahaForm = {
+ name: "",
+ deskripsi: "",
+ link: "",
+};
+
+const templatePelayananPendudukNonPermanen = z.object({
+ name: z.string().min(3, "Nama minimal 3 karakter"),
+ deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
+});
+
+type pelayananPendudukNonPermanenForm =
+ Prisma.PelayananPendudukNonPermanenGetPayload<{
+ select: {
+ id: true;
+ name: true;
+ deskripsi: true;
+ };
+ }>;
+
+const pelayananPendudukNonPermanenForm = {
+ name: "",
+ deskripsi: "",
+};
+
+
+const suratKeterangan = proxy({
+ create: {
+ form: { ...suratKeteranganForm },
+ loading: false,
+ async create() {
+ const cek = templateSuratKeteranganForm.safeParse(
+ suratKeterangan.create.form
+ );
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ return toast.error(err);
+ }
+ try {
+ suratKeterangan.create.loading = true;
+ const res = await ApiFetch.api.desa.layanan.pelayanansuratketerangan[
+ "create"
+ ].post(suratKeterangan.create.form);
+ if (res.status === 200) {
+ suratKeterangan.findMany.load();
+ return toast.success("Surat Keterangan berhasil disimpan!");
+ }
+ return toast.error("Gagal menyimpan surat keterangan");
+ } catch (error) {
+ console.log((error as Error).message);
+ } finally {
+ suratKeterangan.create.loading = false;
+ }
+ },
+ resetForm() {
+ suratKeterangan.create.form = { ...suratKeteranganForm };
+ },
+ },
+ findMany: {
+ data: [] as Prisma.PelayananSuratKeteranganGetPayload<{
+ include: { image: true };
+ }>[],
+ async load() {
+ const res = await ApiFetch.api.desa.layanan.pelayanansuratketerangan[
+ "find-many"
+ ].get();
+ if (res.status === 200) {
+ suratKeterangan.findMany.data = res.data?.data ?? [];
+ }
+ },
+ },
+ findUnique: {
+ data: null as Prisma.PelayananSuratKeteranganGetPayload<{
+ include: {
+ image: true;
+ };
+ }> | null,
+ async load(id: string) {
+ try {
+ const res = await fetch(
+ `/api/desa/layanan/pelayanansuratketerangan/${id}`
+ );
+ if (res.ok) {
+ const data = await res.json();
+ suratKeterangan.findUnique.data = data.data ?? null;
+ } else {
+ console.error("Failed to fetch surat keterangan:", res.statusText);
+ suratKeterangan.findUnique.data = null;
+ }
+ } catch (error) {
+ console.error("Error fetching surat keterangan:", error);
+ suratKeterangan.findUnique.data = null;
+ }
+ },
+ },
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
+ try {
+ suratKeterangan.delete.loading = true;
+ const response = await fetch(
+ `/api/desa/layanan/pelayanansuratketerangan/del/${id}`,
+ {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ const result = await response.json();
+ if (response.ok) {
+ toast.success(result.message || "Surat Keterangan berhasil dihapus");
+ await suratKeterangan.findMany.load(); // refresh list
+ } else {
+ toast.error(result.message || "Gagal menghapus surat keterangan");
+ }
+ } catch (error) {
+ console.error("Gagal delete:", error);
+ toast.error("Terjadi kesalahan saat menghapus surat keterangan");
+ } finally {
+ suratKeterangan.delete.loading = false;
+ }
+ },
+ },
+ edit: {
+ id: "",
+ form: { ...suratKeteranganForm },
+ loading: false,
+
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+ try {
+ const response = await fetch(
+ `/api/desa/layanan/pelayanansuratketerangan/${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,
+ deskripsi: data.deskripsi,
+ imageId: data.imageId || "",
+ };
+ return data;
+ } else {
+ throw new Error(result.message || "Gagal memuat data");
+ }
+ } catch (error) {
+ console.error("Error fetching surat keterangan:", error);
+ toast.error(
+ error instanceof Error ? error.message : "Gagal memuat data"
+ );
+ return null;
+ }
+ },
+ async update() {
+ const cek = templateSuratKeteranganForm.safeParse(
+ suratKeterangan.edit.form
+ );
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ return toast.error(err);
+ }
+ try {
+ suratKeterangan.edit.loading = true;
+ const response = await fetch(
+ `/api/desa/layanan/pelayanansuratketerangan/${this.id}`,
+ {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ name: this.form.name,
+ deskripsi: this.form.deskripsi,
+ imageId: this.form.imageId,
+ }),
+ }
+ );
+ 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(result.message || "Surat Keterangan berhasil diupdate");
+ await suratKeterangan.findMany.load(); // refresh list
+ return true;
+ } else {
+ throw new Error(
+ result.message || "Gagal mengupdate surat keterangan"
+ );
+ }
+ } catch (error) {
+ console.error("Error updating surat keterangan:", error);
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : "Terjadi kesalahan saat update surat keterangan"
+ );
+ return false;
+ } finally {
+ suratKeterangan.edit.loading = false;
+ }
+ },
+ },
+});
+
+const pelayananTelunjukSaktiDesa = proxy({
+ create: {
+ form: { ...telunjukSaktiDesaForm },
+ loading: false,
+ async create() {
+ const cek = templateTelunjukSaktiDesaForm.safeParse(
+ pelayananTelunjukSaktiDesa.create.form
+ );
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ return toast.error(err);
+ }
+ try {
+ pelayananTelunjukSaktiDesa.create.loading = true;
+ const res = await ApiFetch.api.desa.layanan.pelayanantelunjuksaktidesa[
+ "create"
+ ].post(pelayananTelunjukSaktiDesa.create.form);
+ if (res.status === 200) {
+ pelayananTelunjukSaktiDesa.findMany.load();
+ return toast.success("Telunjuk Sakti Desa berhasil disimpan!");
+ }
+ return toast.error("Gagal menyimpan telunjuk sakti desa");
+ } catch (error) {
+ console.log((error as Error).message);
+ } finally {
+ pelayananTelunjukSaktiDesa.create.loading = false;
+ }
+ },
+ resetForm() {
+ pelayananTelunjukSaktiDesa.create.form = { ...telunjukSaktiDesaForm };
+ },
+ },
+ findMany: {
+ data: [] as Prisma.PelayananTelunjukSaktiDesaGetPayload<{
+ omit: { isActive: true };
+ }>[],
+ async load() {
+ const res = await ApiFetch.api.desa.layanan.pelayanantelunjuksaktidesa[
+ "find-many"
+ ].get();
+ if (res.status === 200) {
+ pelayananTelunjukSaktiDesa.findMany.data = res.data?.data ?? [];
+ }
+ },
+ },
+ findUnique: {
+ data: null as Prisma.PelayananTelunjukSaktiDesaGetPayload<{
+ omit: { isActive: true };
+ }> | null,
+ async load(id: string) {
+ try {
+ const res = await fetch(
+ `/api/desa/layanan/pelayanantelunjuksaktidesa/${id}`
+ );
+ if (res.ok) {
+ const data = await res.json();
+ pelayananTelunjukSaktiDesa.findUnique.data = data.data ?? null;
+ } else {
+ console.error("Failed to fetch telunjuk sakti desa:", res.statusText);
+ pelayananTelunjukSaktiDesa.findUnique.data = null;
+ }
+ } catch (error) {
+ console.error("Error fetching telunjuk sakti desa:", error);
+ pelayananTelunjukSaktiDesa.findUnique.data = null;
+ }
+ },
+ },
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
+ try {
+ pelayananTelunjukSaktiDesa.delete.loading = true;
+ const response = await fetch(
+ `/api/desa/layanan/pelayanantelunjuksaktidesa/del/${id}`,
+ {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ const result = await response.json();
+ if (response.ok) {
+ toast.success(result.message || "Telunjuk Sakti Desa berhasil dihapus");
+ await pelayananTelunjukSaktiDesa.findMany.load(); // refresh list
+ } else {
+ toast.error(result.message || "Gagal menghapus telunjuk sakti desa");
+ }
+ } catch (error) {
+ console.error("Gagal delete:", error);
+ toast.error("Terjadi kesalahan saat menghapus telunjuk sakti desa");
+ } finally {
+ pelayananTelunjukSaktiDesa.delete.loading = false;
+ }
+ },
+ },
+ edit: {
+ id: "",
+ form: { ...telunjukSaktiDesaForm },
+ loading: false,
+
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+ try {
+ const response = await fetch(
+ `/api/desa/layanan/pelayanantelunjuksaktidesa/${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,
+ deskripsi: data.deskripsi,
+ link: data.link,
+ };
+ return data;
+ } else {
+ throw new Error(result.message || "Gagal memuat data");
+ }
+ } catch (error) {
+ console.error("Error fetching telunjuk sakti desa:", error);
+ toast.error(
+ error instanceof Error ? error.message : "Gagal memuat data"
+ );
+ return null;
+ }
+ },
+ async update() {
+ const cek = templateTelunjukSaktiDesaForm.safeParse(
+ pelayananTelunjukSaktiDesa.edit.form
+ );
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ return toast.error(err);
+ }
+ try {
+ pelayananTelunjukSaktiDesa.edit.loading = true;
+ const response = await fetch(
+ `/api/desa/layanan/pelayanantelunjuksaktidesa/${this.id}`,
+ {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ name: this.form.name,
+ deskripsi: this.form.deskripsi,
+ link: this.form.link,
+ }),
+ }
+ );
+ 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(result.message || "Telunjuk Sakti Desa berhasil diupdate");
+ await pelayananTelunjukSaktiDesa.findMany.load(); // refresh list
+ return true;
+ } else {
+ throw new Error(
+ result.message || "Gagal mengupdate telunjuk sakti desa"
+ );
+ }
+ } catch (error) {
+ console.error("Error updating telunjuk sakti desa:", error);
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : "Terjadi kesalahan saat update telunjuk sakti desa"
+ );
+ return false;
+ } finally {
+ pelayananTelunjukSaktiDesa.edit.loading = false;
+ }
+ },
+ },
+})
+
+const pelayananPerizinanBerusaha = proxy({
+ findById: {
+ data: null as pelayananPerizinanBerusahaForm | null,
+ loading: false,
+ initialize() {
+ pelayananPerizinanBerusaha.findById.data = {
+ id: "",
+ name: "",
+ deskripsi: "",
+ link: "",
+ } as pelayananPerizinanBerusahaForm;
+ },
+ async load(id: string) {
+ try {
+ pelayananPerizinanBerusaha.findById.loading = true;
+ const res = await fetch(
+ `/api/desa/layanan/pelayananperizinanberusaha/${id}`
+ );
+ if (res.ok) {
+ const data = await res.json();
+ pelayananPerizinanBerusaha.findById.data = data.data ?? null;
+ } else {
+ console.error(
+ "Failed to fetch pelayanan perizinan berusaha:",
+ res.statusText
+ );
+ pelayananPerizinanBerusaha.findById.data = null;
+ }
+ } catch (error) {
+ console.error("Error fetching pelayanan perizinan berusaha:", error);
+ pelayananPerizinanBerusaha.findById.data = null;
+ }
+ },
+ },
+ update: {
+ id: "",
+ form: { ...pelayananPerizinanBerusahaForm },
+ loading: false,
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak boleh kosong");
+ return null;
+ }
+ try {
+ const response = await fetch(
+ `/api/desa/layanan/pelayananperizinanberusaha/${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;
+ pelayananPerizinanBerusaha.update.id = data.id;
+ pelayananPerizinanBerusaha.update.form = {
+ name: data.name,
+ deskripsi: data.deskripsi,
+ link: data.link,
+ };
+ return data;
+ } else {
+ throw new Error(result.message || "Gagal memuat data");
+ }
+ } catch (error) {
+ console.error("Error fetching pelayanan perizinan berusaha:", error);
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : "Gagal memuat data"
+ );
+ return null;
+ }
+ },
+ async update(data: pelayananPerizinanBerusahaForm) {
+ const cek = templatePelayananPerizinanBerusaha.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 {
+ pelayananPerizinanBerusaha.update.loading = true;
+ const res = await fetch(
+ `/api/desa/layanan/pelayananperizinanberusaha/${data.id}`,
+ {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(data),
+ }
+ );
+ if (res.ok) {
+ toast.success("Pelayanan perizinan berusaha berhasil diupdate");
+ await pelayananPerizinanBerusaha.findById.load(data.id);
+ } else {
+ toast.error("Gagal mengupdate pelayanan perizinan berusaha");
+ }
+ } catch (error) {
+ console.error("Error updating pelayanan perizinan berusaha:", error);
+ toast.error(
+ "Terjadi kesalahan saat mengupdate pelayanan perizinan berusaha"
+ );
+ } finally {
+ pelayananPerizinanBerusaha.update.loading = false;
+ }
+ },
+ },
+});
+
+const pelayananPendudukNonPermanen = proxy({
+ findById: {
+ data: null as pelayananPendudukNonPermanenForm | null,
+ loading: false,
+ initialize() {
+ pelayananPendudukNonPermanen.findById.data = {
+ id: "",
+ name: "",
+ deskripsi: "",
+ } as pelayananPendudukNonPermanenForm;
+ },
+ async load(id: string) {
+ try {
+ pelayananPendudukNonPermanen.findById.loading = true;
+ const res = await fetch(
+ `/api/desa/layanan/pelayananpenduduknonpermanen/${id}`
+ );
+ if (res.ok) {
+ const data = await res.json();
+ pelayananPendudukNonPermanen.findById.data = data.data ?? null;
+ } else {
+ console.error(
+ "Failed to fetch pelayanan penduduk non permanen:",
+ res.statusText
+ );
+ pelayananPendudukNonPermanen.findById.data = null;
+ }
+ } catch (error) {
+ console.error("Error fetching pelayanan penduduk non permanen:", error);
+ pelayananPendudukNonPermanen.findById.data = null;
+ }
+ },
+ },
+ update: {
+ id: "",
+ form: { ...pelayananPendudukNonPermanenForm },
+ loading: false,
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak boleh kosong");
+ return null;
+ }
+ try {
+ const response = await fetch(
+ `/api/desa/layanan/pelayananpenduduknonpermanen/${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;
+ pelayananPendudukNonPermanen.update.id = data.id;
+ pelayananPendudukNonPermanen.update.form = {
+ name: data.name,
+ deskripsi: data.deskripsi,
+ };
+ return data;
+ } else {
+ throw new Error(result.message || "Gagal memuat data");
+ }
+ } catch (error) {
+ console.error("Error fetching pelayanan penduduk non permanen:", error);
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : "Gagal memuat data"
+ );
+ return null;
+ }
+ },
+ async update(data: pelayananPendudukNonPermanenForm) {
+ const cek = templatePelayananPendudukNonPermanen.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 {
+ pelayananPendudukNonPermanen.update.loading = true;
+ const res = await fetch(
+ `/api/desa/layanan/pelayananpenduduknonpermanen/${data.id}`,
+ {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(data),
+ }
+ );
+ if (res.ok) {
+ toast.success("Pelayanan penduduk non permanen berhasil diupdate");
+ await pelayananPendudukNonPermanen.findById.load(data.id);
+ } else {
+ toast.error("Gagal mengupdate pelayanan penduduk non permanen");
+ }
+ } catch (error) {
+ console.error("Error updating pelayanan penduduk non permanen:", error);
+ toast.error(
+ "Terjadi kesalahan saat mengupdate pelayanan penduduk non permanen"
+ );
+ } finally {
+ pelayananPendudukNonPermanen.update.loading = false;
+ }
+ },
+ },
+});
+
+const stateLayananDesa = proxy({
+ suratKeterangan,
+ pelayananPerizinanBerusaha,
+ pelayananTelunjukSaktiDesa,
+ pelayananPendudukNonPermanen,
+});
+
+export default stateLayananDesa;
diff --git a/src/app/admin/(dashboard)/_state/desa/penghargaan.ts b/src/app/admin/(dashboard)/_state/desa/penghargaan.ts
new file mode 100644
index 00000000..2545ae1a
--- /dev/null
+++ b/src/app/admin/(dashboard)/_state/desa/penghargaan.ts
@@ -0,0 +1,221 @@
+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 templateForm = z.object({
+ name: z.string().min(1).max(50),
+ juara: z.string().min(1).max(50),
+ deskripsi: z.string().min(1).max(5000),
+ imageId: z.string().min(1).max(50),
+});
+
+const defaultForm = {
+ name: "",
+ juara: "",
+ deskripsi: "",
+ imageId: "",
+};
+
+const penghargaanState = proxy({
+ create: {
+ form: { ...defaultForm },
+ loading: false,
+ async create() {
+ const cek = templateForm.safeParse(penghargaanState.create.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ return toast.error(err);
+ }
+
+ try {
+ penghargaanState.create.loading = true;
+ const res = await ApiFetch.api.desa.penghargaan["create"].post(
+ penghargaanState.create.form
+ );
+ if (res.status === 200) {
+ penghargaanState.findMany.load();
+ return toast.success("success create");
+ }
+ console.log(res);
+ return toast.error("failed create");
+ } catch (error) {
+ console.log((error as Error).message);
+ } finally {
+ penghargaanState.create.loading = false;
+ }
+ },
+ },
+ findMany: {
+ data: null as
+ | Prisma.PenghargaanGetPayload<{
+ include: {
+ image: true;
+ };
+ }>[]
+ | null,
+ async load() {
+ const res = await ApiFetch.api.desa.penghargaan["find-many"].get();
+ if (res.status === 200) {
+ penghargaanState.findMany.data = res.data?.data ?? [];
+ }
+ },
+ },
+ findUnique: {
+ data: null as Prisma.PenghargaanGetPayload<{
+ include: {
+ image: true;
+ };
+ }> | null,
+ async load(id: string) {
+ try {
+ const res = await fetch(`/api/desa/penghargaan/${id}`);
+ if (res.ok) {
+ const data = await res.json();
+ penghargaanState.findUnique.data = data.data ?? null;
+ } else {
+ console.error("Failed to fetch data", res.status, res.statusText);
+ penghargaanState.findUnique.data = null;
+ }
+ } catch (error) {
+ console.error("Error loading penghargaan:", error);
+ penghargaanState.findUnique.data = null;
+ }
+ },
+ },
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
+
+ try {
+ penghargaanState.delete.loading = true;
+ const response = await fetch(`/api/desa/penghargaan/del/${id}`, {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const result = await response.json();
+
+ if (response.ok) {
+ toast.success(result.message || "Penghargaan berhasil dihapus");
+ await penghargaanState.findMany.load();
+ } else {
+ toast.error(result?.message || "Gagal menghapus penghargaan");
+ }
+ } catch (error) {
+ console.log((error as Error).message);
+ toast.error("Terjadi kesalahan saat menghapus penghargaan");
+ } finally {
+ penghargaanState.delete.loading = false;
+ }
+ },
+ },
+ edit: {
+ id: "",
+ form: { ...defaultForm },
+ loading: false,
+
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+
+ try {
+ const response = await fetch(`/api/desa/penghargaan/${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,
+ juara: data.juara,
+ deskripsi: data.deskripsi,
+ imageId: data.imageId,
+ };
+ return data;
+ } else {
+ throw new Error(result?.message || "Gagal memuat data");
+ }
+ } catch (error) {
+ console.error("Error loading penghargaan:", error);
+ toast.error(
+ error instanceof Error ? error.message : "Gagal memuat data"
+ );
+ return null;
+ }
+ },
+ async update() {
+ const cek = templateForm.safeParse(penghargaanState.edit.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ toast.error(err);
+ return false;
+ }
+
+ try {
+ penghargaanState.edit.loading = true;
+ const response = await fetch(
+ `/api/desa/penghargaan/${penghargaanState.edit.id}`,
+ {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ name: this.form.name,
+ juara: this.form.juara,
+ deskripsi: this.form.deskripsi,
+ imageId: this.form.imageId,
+ }),
+ }
+ );
+
+ 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 penghargaan");
+ await penghargaanState.findMany.load();
+ return true;
+ } else {
+ throw new Error(result?.message || "Gagal update penghargaan");
+ }
+ } catch (error) {
+ console.error("Error updating penghargaan:", error);
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : "Terjadi kesalahan saat update penghargaan"
+ );
+ return false;
+ } finally {
+ penghargaanState.edit.loading = false;
+ }
+ },
+ reset() {
+ penghargaanState.edit.id = "";
+ penghargaanState.edit.form = { ...defaultForm };
+ },
+ },
+});
+export default penghargaanState;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/_state/desa/pengumuman.ts b/src/app/admin/(dashboard)/_state/desa/pengumuman.ts
index 31987b33..91b4e311 100644
--- a/src/app/admin/(dashboard)/_state/desa/pengumuman.ts
+++ b/src/app/admin/(dashboard)/_state/desa/pengumuman.ts
@@ -1,83 +1,246 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
-import ApiFetch from "@/lib/api-fetch"
-import { Prisma } from "@prisma/client"
-import { toast } from "react-toastify"
-import { proxy } from "valtio"
-import { z } from "zod"
+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 templateFormPengumuman = z.object({
- judul: z.string().min(3, "Judul minimal 3 karakter"),
- deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
- content: z.string().min(3, "Content minimal 3 karakter"),
- categoryPengumumanId: z.string().nonempty(),
-})
+ judul: z.string().min(3, "Judul minimal 3 karakter"),
+ deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
+ content: z.string().min(3, "Content minimal 3 karakter"),
+ categoryPengumumanId: z.string().nonempty(),
+});
-const category = proxy ({
- findMany: {
- data: null as
- | null
- | Prisma.CategoryPengumumanGetPayload<{ omit: { isActive: true } }>[],
- async load() {
- const res = await ApiFetch.api.desa.pengumuman.category["find-many"].get();
- if (res.status === 200) {
- category.findMany.data = res.data?.data as any ?? [];
- }
- }
- }
-})
+const category = proxy({
+ findMany: {
+ data: null as
+ | null
+ | Prisma.CategoryPengumumanGetPayload<{ omit: { isActive: true } }>[],
+ async load() {
+ const res = await ApiFetch.api.desa.pengumuman.category[
+ "find-many"
+ ].get();
+ if (res.status === 200) {
+ category.findMany.data = (res.data?.data as any) ?? [];
+ }
+ },
+ },
+});
type PengumumanForm = Prisma.PengumumanGetPayload<{
- select: {
- judul: true;
- deskripsi: true;
- content: true;
- categoryPengumumanId: true;
- }
-}>
+ select: {
+ judul: true;
+ deskripsi: true;
+ content: true;
+ categoryPengumumanId: true;
+ };
+}>;
const pengumuman = proxy({
-create: {
+ create: {
form: {} as PengumumanForm,
loading: false,
async create() {
- const cek = templateFormPengumuman.safeParse(pengumuman.create.form);
- if (!cek.success) {
+ const cek = templateFormPengumuman.safeParse(pengumuman.create.form);
+ if (!cek.success) {
const err = `[${cek.error.issues
- .map((v) => `${v.path.join(".")}`)
- .join("\n")}] required`;
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
return toast.error(err);
- }
- try {
+ }
+ try {
pengumuman.create.loading = true;
- const res = await ApiFetch.api.desa.pengumuman["create"].post(pengumuman.create.form)
+ const res = await ApiFetch.api.desa.pengumuman["create"].post(
+ pengumuman.create.form
+ );
if (res.status === 200) {
- pengumuman.findMany.load();
- return toast.success("success create");
+ pengumuman.findMany.load();
+ return toast.success("success create");
}
- console.log(res)
+ console.log(res);
return toast.error("failed create");
- } catch (error) {
+ } catch (error) {
console.log((error as Error).message);
- } finally{
+ } finally {
pengumuman.create.loading = false;
- }
- }
-},
-findMany: {
+ }
+ },
+ },
+ findMany: {
data: null as
- | Prisma.PengumumanGetPayload<{omit: {isActive: true}}>[]
- | null,
- async load () {
- const res = await ApiFetch.api.desa.pengumuman["find-many"].get();
- console.log(res)
- if (res.status === 200) {
- pengumuman.findMany.data = res.data?.data ?? [];
+ | Prisma.PengumumanGetPayload<{
+ include: {
+ CategoryPengumuman: true;
}
- }
-}
-})
+ }>[]
+ | null,
+ async load() {
+ const res = await ApiFetch.api.desa.pengumuman["find-many"].get();
+ console.log(res);
+ if (res.status === 200) {
+ pengumuman.findMany.data = res.data?.data ?? [];
+ }
+ },
+ },
+ // findUnique: {
+ // data: null as
+ // | Prisma.PengumumanGetPayload<{
+ // include: {
+ // CategoryPengumuman: true;
+ // }
+ // }>
+ // | null,
+ // async load(id: string) {
+ // try {
+ // const res = await fetch(`/api/desa/pengumuman/${id}`);
+ // if (res.ok) {
+ // const data = await res.json();
+ // pengumuman.findUnique.data = data.data ?? null;
+ // } else {
+ // console.error('Failed to fetch pengumuman:', res.statusText);
+ // pengumuman.findUnique.data = null;
+ // }
+ // } catch (error) {
+ // console.error('Error fetching pengumuman:', error);
+ // pengumuman.findUnique.data = null;
+ // }
+ // },
+ // },
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
+
+ try {
+ pengumuman.delete.loading = true;
+
+ const response = await fetch(`/api/desa/pengumuman/delete/${id}`, {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ const result = await response.json();
+
+ if (response.ok && result?.success) {
+ toast.success(result.message || "Pengumuman berhasil dihapus");
+ await pengumuman.findMany.load(); // refresh list
+ } else {
+ toast.error(result?.message || "Gagal menghapus pengumuman");
+ }
+ } catch (error) {
+ console.error("Gagal delete:", error);
+ toast.error("Terjadi kesalahan saat menghapus pengumuman");
+ } finally {
+ pengumuman.delete.loading = false;
+ }
+ },
+ },
+ update: {
+ id: "",
+ form: {} as PengumumanForm,
+ loading: false,
+
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+
+ try {
+ const response = await fetch(`/api/desa/pengumuman/${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,
+ content: data.content,
+ categoryPengumumanId: data.categoryPengumumanId || "",
+ };
+ return data;
+ } else {
+ throw new Error(result?.message || "Gagal mengambil data pengumuman");
+ }
+ } catch (error) {
+ console.error((error as Error).message);
+ toast.error("Terjadi kesalahan saat mengambil data pengumuman");
+ } finally {
+ pengumuman.update.loading = false;
+ }
+ },
+
+ async update() {
+ const cek = templateFormPengumuman.safeParse(pengumuman.update.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ toast.error(err);
+ return false;
+ }
+
+ try {
+ pengumuman.update.loading = true;
+
+ const response = await fetch(`/api/desa/pengumuman/${this.id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ judul: this.form.judul,
+ deskripsi: this.form.deskripsi,
+ content: this.form.content,
+ categoryPengumumanId: this.form.categoryPengumumanId,
+ }),
+ });
+
+ 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 pengumuman");
+ await pengumuman.findMany.load(); // refresh list
+ return true;
+ } else {
+ throw new Error(result.message || "Gagal update pengumuman");
+ }
+ } catch (error) {
+ console.error("Error updating pengumuman:", error);
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : "Terjadi kesalahan saat update pengumuman"
+ );
+ return false;
+ } finally {
+ pengumuman.update.loading = false;
+ }
+ },
+ },
+});
const stateDesaPengumuman = proxy({
- category,
- pengumuman
-})
-export default stateDesaPengumuman
\ No newline at end of file
+ category,
+ pengumuman,
+});
+export default stateDesaPengumuman;
diff --git a/src/app/admin/(dashboard)/_state/desa/potensi.ts b/src/app/admin/(dashboard)/_state/desa/potensi.ts
index c61ec4f1..91e898a0 100644
--- a/src/app/admin/(dashboard)/_state/desa/potensi.ts
+++ b/src/app/admin/(dashboard)/_state/desa/potensi.ts
@@ -6,7 +6,7 @@ import { z } from "zod";
const templateForm = z.object({
name: z.string().min(1).max(50),
- deskripsi: z.string().min(1).max(50),
+ deskripsi: z.string().min(1).max(5000),
kategori: z.string().min(1).max(50),
imageId: z.string().min(1).max(50),
content: z.string().min(1).max(5000),
diff --git a/src/app/admin/(dashboard)/_state/desa/profile.ts b/src/app/admin/(dashboard)/_state/desa/profile.ts
index 744b426d..07142d72 100644
--- a/src/app/admin/(dashboard)/_state/desa/profile.ts
+++ b/src/app/admin/(dashboard)/_state/desa/profile.ts
@@ -1,239 +1,829 @@
-import ApiFetch from "@/lib/api-fetch";
-import { Prisma } from "@prisma/client";
import { toast } from "react-toastify";
import { proxy } from "valtio";
import { z } from "zod";
+import { Prisma } from "@prisma/client";
-/* Sejarah */
-const templateFormSejarahForm = z.object({
- sejarah: z.string().min(3, "Sejarah minimal 3 karakter"),
-})
-
-type SejarahForm = Prisma.ProfileDesaGetPayload<{
- select: {
- id: true;
- sejarah: true;
- }
-}>
-
-const Sejarah = proxy({
- findById: {
- data: null as SejarahForm | null,
- loading: false,
- initialize() {
- Sejarah.findById.data = {
- id: "",
- sejarah: "",
- } as SejarahForm;
- },
- async load(id: string) {
- try {
- Sejarah.findById.loading = true;
- const res = await ApiFetch.api.desa.profile["find-by-id"].get({
- query: { id },
- });
- if (res.status === 200) {
- Sejarah.findById.data = {
- id: id,
- sejarah: res.data?.data?.sejarah ?? ""
- };
- } else {
- toast.error("Gagal mengambil data sejarah");
- }
- } catch (error) {
- console.error((error as Error).message);
- toast.error("Terjadi kesalahan saat mengambil data sejarah");
- } finally {
- Sejarah.findById.loading = false;
- }
- }
- },
- update: {
- loading: false,
- async save(data: SejarahForm) {
- const cek = templateFormSejarahForm.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 {
- Sejarah.update.loading = true;
- const res = await ApiFetch.api.desa.profile.sejarah["update"].post(data);
- if (res.status === 200) {
- toast.success("Berhasil update sejarah");
- await Sejarah.findById.load(data.id);
- } else {
- toast.error("Gagal update sejarah");
- }
- } catch (error) {
- console.error((error as Error).message);
- toast.error("Terjadi kesalahan saat update sejarah");
- } finally {
- Sejarah.update.loading = false;
- }
- }
- }
-})
-
-/* Visi Misi Desa */
-const templateFormVisiForm = z.object({
- visi: z.string().min(3, "Visi minimal 3 karakter"),
- misi: z.string().min(3, "Misi minimal 3 karakter")
-})
-
-type VisiMisiDesaForm = Prisma.ProfileDesaGetPayload<{
- select: {
- id: true;
- visi: true;
- misi: true;
- }
-}>
-
-const VisiMisiDesa = proxy({
- findById: {
- data: null as VisiMisiDesaForm | null,
- loading: false,
- initialize() {
- VisiMisiDesa.findById.data = {
- id: "",
- visi: "",
- misi: ""
- } as VisiMisiDesaForm;
- },
- async load(id: string) {
- try {
- VisiMisiDesa.findById.loading = true;
- const res = await ApiFetch.api.desa.profile["find-by-id"].get({
- query: { id },
- });
- if (res.status === 200) {
- VisiMisiDesa.findById.data = {
- id: id,
- visi: res.data?.data?.visi ?? "",
- misi: res.data?.data?.misi ?? ""
- };
- } else {
- toast.error("Gagal mengambil data visi misi");
- }
- } catch (error) {
- console.error((error as Error).message);
- toast.error("Terjadi kesalahan saat mengambil data visi misi");
- } finally {
- VisiMisiDesa.findById.loading = false;
- }
- }
- },
- update: {
- loading: false,
- async save(data: VisiMisiDesaForm) {
- const cek = templateFormVisiForm.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 {
- VisiMisiDesa.update.loading = true;
- const res = await ApiFetch.api.desa.profile.visimisiDesa["update"].post(data);
- if (res.status === 200) {
- toast.success("Berhasil update visi misi");
- await VisiMisiDesa.findById.load(data.id);
- } else {
- toast.error("Gagal update visi");
- }
- } catch (error) {
- console.error((error as Error).message);
- toast.error("Terjadi kesalahan saat update visi misi");
- } finally {
- VisiMisiDesa.update.loading = false;
- }
- }
- }
-})
-/* Lambang Desa */
-const templateFormLambangDesaForm = z.object({
- lambang: z.string().min(3, "Lambang minimal 3 karakter"),
-})
-
-type LambangDesaForm = Prisma.ProfileDesaGetPayload<{
- select: {
- id: true;
- lambang: true;
- }
-}>
-
-const LambangDesa = proxy({
- findById: {
- data: null as LambangDesaForm | null,
- loading: false,
- initialize() {
- LambangDesa.findById.data = {
- id: "",
- lambang: "",
- } as LambangDesaForm;
- },
- async load(id: string) {
- try {
- LambangDesa.findById.loading = true;
- const res = await ApiFetch.api.desa.profile["find-by-id"].get({
- query: { id },
- });
- if (res.status === 200) {
- LambangDesa.findById.data = {
- id: id,
- lambang: res.data?.data?.lambang ?? ""
- };
- } else {
- toast.error("Gagal mengambil data lambang desa");
- }
- } catch (error) {
- console.error((error as Error).message);
- toast.error("Terjadi kesalahan saat mengambil data lambang desa");
- } finally {
- LambangDesa.findById.loading = false;
- }
- }
- },
- update: {
- loading: false,
- async save(data: LambangDesaForm) {
- const cek = templateFormLambangDesaForm.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 {
- LambangDesa.update.loading = true;
- const res = await ApiFetch.api.desa.profile.lambangDesa["update"].post(data);
- if (res.status === 200) {
- toast.success("Berhasil update lambang desa");
- await LambangDesa.findById.load(data.id);
- } else {
- toast.error("Gagal update lambang desa");
- }
- } catch (error) {
- console.error((error as Error).message);
- toast.error("Terjadi kesalahan saat update lambang desa");
- } finally {
- LambangDesa.update.loading = false;
- }
- }
- }
+// ========================================= SEJARAH DESA ========================================= //
+const sejarahDesaForm = z.object({
+ judul: z.string().min(3, "Judul minimal 3 karakter"),
+ deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
});
-const stateProfileDesa = {
- Sejarah,
- VisiMisiDesa,
- LambangDesa,
+const sejarahDesaDefaultForm = {
+ judul: "",
+ deskripsi: "",
};
+type SejarahDesaForm = Prisma.SejarahDesaGetPayload<{
+ select: {
+ id: true;
+ judul: true;
+ deskripsi: true;
+ };
+}>;
+
+const sejarahDesa = proxy({
+ findUnique: {
+ data: null as SejarahDesaForm | null,
+ loading: false,
+ error: null as string | null,
+
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(`/api/desa/profile/sejarah/${id}`);
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ const result = await response.json();
+
+ if (result.success) {
+ this.data = result.data;
+ return result.data;
+ } else {
+ throw new Error(
+ result.message || "Gagal mengambil data sejarah desa"
+ );
+ }
+ } catch (error) {
+ const msg = (error as Error).message;
+ this.error = msg;
+ console.error("Load sejarah desa error:", msg);
+ toast.error("Terjadi kesalahan saat mengambil data sejarah desa");
+ return null;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ reset() {
+ this.data = null;
+ this.error = null;
+ this.loading = false;
+ },
+ },
+ update: {
+ id: "",
+ form: { ...sejarahDesaDefaultForm },
+ loading: false,
+ error: null as string | null,
+ isReadOnly: false,
+
+ initialize(sejarahData: SejarahDesaForm) {
+ this.id = sejarahData.id;
+ this.isReadOnly = false;
+ this.form = {
+ judul: sejarahData.judul || "",
+ deskripsi: sejarahData.deskripsi || "",
+ };
+ },
+
+ updateField(field: keyof typeof sejarahDesaDefaultForm, value: string) {
+ this.form[field] = value;
+ },
+
+ async submit() {
+ // Validate form
+ const validation = sejarahDesaForm.safeParse(this.form);
+
+ if (!validation.success) {
+ const errors = validation.error.issues
+ .map((issue) => `${issue.path.join(".")}: ${issue.message}`)
+ .join(", ");
+ toast.error(`Form tidak valid: ${errors}`);
+ return false;
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(
+ `/api/desa/profile/sejarah/${this.id}`,
+ {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(this.form),
+ }
+ );
+
+ 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 profile");
+ // Refresh profile data
+ await sejarahDesa.findUnique.load(this.id);
+ return true;
+ } else {
+ throw new Error(result.message || "Gagal update profile");
+ }
+ } catch (error) {
+ const errorMessage = (error as Error).message;
+ this.error = errorMessage;
+ console.error("Update profile error:", errorMessage);
+ toast.error("Terjadi kesalahan saat update profile");
+ return false;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // Reset form
+ reset() {
+ this.id = "";
+ this.form = { ...sejarahDesaDefaultForm };
+ this.error = null;
+ this.loading = false;
+ this.isReadOnly = false;
+ },
+ },
+});
+
+// ========================================= VISI MISI DESA ========================================= //
+const visiMisiDesaForm = z.object({
+ visi: z.string().min(3, "Visi minimal 3 karakter"),
+ misi: z.string().min(3, "Misi minimal 3 karakter"),
+});
+
+const visiMisiDesaDefaultForm = {
+ visi: "",
+ misi: "",
+};
+
+type VisiMisiDesaForm = Prisma.VisiMisiDesaGetPayload<{
+ select: {
+ id: true;
+ visi: true;
+ misi: true;
+ };
+}>;
+
+const visiMisiDesa = proxy({
+ findUnique: {
+ data: null as VisiMisiDesaForm | null,
+ loading: false,
+ error: null as string | null,
+
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(`/api/desa/profile/visi-misi/${id}`);
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ const result = await response.json();
+
+ if (result.success) {
+ this.data = result.data;
+ return result.data;
+ } else {
+ throw new Error(
+ result.message || "Gagal mengambil data visi misi desa"
+ );
+ }
+ } catch (error) {
+ const msg = (error as Error).message;
+ this.error = msg;
+ console.error("Load visi misi desa error:", msg);
+ toast.error("Terjadi kesalahan saat mengambil data visi misi desa");
+ return null;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ reset() {
+ this.data = null;
+ this.error = null;
+ this.loading = false;
+ },
+ },
+ update: {
+ id: "",
+ form: { ...visiMisiDesaDefaultForm },
+ loading: false,
+ error: null as string | null,
+ isReadOnly: false,
+
+ initialize(visiMisiData: VisiMisiDesaForm) {
+ this.id = visiMisiData.id;
+ this.isReadOnly = false;
+ this.form = {
+ visi: visiMisiData.visi || "",
+ misi: visiMisiData.misi || "",
+ };
+ },
+
+ updateField(field: keyof typeof visiMisiDesaDefaultForm, value: string) {
+ this.form[field] = value;
+ },
+
+ async submit() {
+ // Validate form
+ const validation = visiMisiDesaForm.safeParse(this.form);
+
+ if (!validation.success) {
+ const errors = validation.error.issues
+ .map((issue) => `${issue.path.join(".")}: ${issue.message}`)
+ .join(", ");
+ toast.error(`Form tidak valid: ${errors}`);
+ return false;
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(`/api/desa/profile/visi-misi/${this.id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(this.form),
+ });
+
+ 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 visi misi desa");
+ // Refresh profile data
+ await visiMisiDesa.findUnique.load(this.id);
+ return true;
+ } else {
+ throw new Error(result.message || "Gagal update visi misi desa");
+ }
+ } catch (error) {
+ const errorMessage = (error as Error).message;
+ this.error = errorMessage;
+ console.error("Update visi misi desa error:", errorMessage);
+ toast.error("Terjadi kesalahan saat update visi misi desa");
+ return false;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // Reset form
+ reset() {
+ this.id = "";
+ this.form = { ...visiMisiDesaDefaultForm };
+ this.error = null;
+ this.loading = false;
+ this.isReadOnly = false;
+ },
+ },
+});
+
+// ========================================= LAMBANG DESA ========================================= //
+const lambangDesaForm = z.object({
+ judul: z.string().min(3, "Judul minimal 3 karakter"),
+ deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
+});
+
+const lambangDesaDefaultForm = {
+ judul: "",
+ deskripsi: "",
+};
+
+type LambangDesaForm = Prisma.LambangDesaGetPayload<{
+ select: {
+ id: true;
+ judul: true;
+ deskripsi: true;
+ };
+}>;
+
+const lambangDesa = proxy({
+ findUnique: {
+ data: null as LambangDesaForm | null,
+ loading: false,
+ error: null as string | null,
+
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(`/api/desa/profile/lambang/${id}`);
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ const result = await response.json();
+
+ if (result.success) {
+ this.data = result.data;
+ return result.data;
+ } else {
+ throw new Error(
+ result.message || "Gagal mengambil data lambang desa"
+ );
+ }
+ } catch (error) {
+ const msg = (error as Error).message;
+ this.error = msg;
+ console.error("Load lambang desa error:", msg);
+ toast.error("Terjadi kesalahan saat mengambil data lambang desa");
+ return null;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ reset() {
+ this.data = null;
+ this.error = null;
+ this.loading = false;
+ },
+ },
+ update: {
+ id: "",
+ form: { ...lambangDesaDefaultForm },
+ loading: false,
+ error: null as string | null,
+ isReadOnly: false,
+
+ initialize(lambangDesaData: LambangDesaForm) {
+ this.id = lambangDesaData.id;
+ this.isReadOnly = false;
+ this.form = {
+ judul: lambangDesaData.judul || "",
+ deskripsi: lambangDesaData.deskripsi || "",
+ };
+ },
+
+ updateField(field: keyof typeof lambangDesaDefaultForm, value: string) {
+ this.form[field] = value;
+ },
+
+ async submit() {
+ // Validate form
+ const validation = lambangDesaForm.safeParse(this.form);
+
+ if (!validation.success) {
+ const errors = validation.error.issues
+ .map((issue) => `${issue.path.join(".")}: ${issue.message}`)
+ .join(", ");
+ toast.error(`Form tidak valid: ${errors}`);
+ return false;
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(
+ `/api/desa/profile/lambang/${this.id}`,
+ {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(this.form),
+ }
+ );
+
+ 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 lambang desa");
+ // Refresh profile data
+ await lambangDesa.findUnique.load(this.id);
+ return true;
+ } else {
+ throw new Error(result.message || "Gagal update lambang desa");
+ }
+ } catch (error) {
+ const errorMessage = (error as Error).message;
+ this.error = errorMessage;
+ console.error("Update lambang desa error:", errorMessage);
+ toast.error("Terjadi kesalahan saat update lambang desa");
+ return false;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // Reset form
+ reset() {
+ this.id = "";
+ this.form = { ...lambangDesaDefaultForm };
+ this.error = null;
+ this.loading = false;
+ this.isReadOnly = false;
+ },
+ },
+});
+
+// ========================================= MASKOT DESA ========================================= //
+const maskotForm = z.object({
+ judul: z.string().min(3, "Judul minimal 3 karakter"),
+ deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
+ images: z
+ .array(
+ z.object({
+ label: z.string().min(1, "Label wajib"),
+ imageId: z.string().min(1, "Image ID wajib"),
+ })
+ )
+ .min(1, "Minimal 1 gambar harus diisi"),
+});
+
+const maskotDefaultForm = {
+ judul: "",
+ deskripsi: "",
+ images: [] as { label: string; imageId: string }[],
+};
+
+type FormData = typeof maskotDefaultForm;
+
+type MaskotDesaForm = Prisma.MaskotDesaGetPayload<{
+ include: {
+ images: {
+ include: {
+ image: {
+ select: {
+ id: true;
+ name: true;
+ path: true;
+ link: true;
+ };
+ };
+ };
+ };
+ };
+}>;
+
+const maskotDesa = proxy({
+ findUnique: {
+ data: null as MaskotDesaForm | null,
+ loading: false,
+ error: null as string | null,
+
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(`/api/desa/profile/maskot/${id}`);
+ const result = await response.json();
+
+ if (response.ok && result.success) {
+ this.data = result.data;
+ return result.data;
+ } else {
+ throw new Error(result.message || "Gagal mengambil data profile");
+ }
+ } catch (error) {
+ const msg = (error as Error).message;
+ this.error = msg;
+ console.error("Load profile error:", msg);
+ toast.error("Terjadi kesalahan saat mengambil data profile");
+ return null;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ reset() {
+ this.data = null;
+ this.error = null;
+ this.loading = false;
+ },
+ },
+
+ update: {
+ id: "",
+ form: { ...maskotDefaultForm },
+ loading: false,
+ error: null as string | null,
+ isReadOnly: false,
+
+ initialize(profileData: MaskotDesaForm) {
+ this.id = profileData.id;
+ this.isReadOnly = false;
+ this.form = {
+ judul: profileData.judul || "",
+ deskripsi: profileData.deskripsi || "",
+ images: (profileData.images || []).map((img) => ({
+ label: img.label,
+ imageId: img.image.id,
+ })),
+ };
+ },
+
+ updateField(field: K, value: FormData[K]) {
+ this.form[field] = value;
+ },
+
+ addImage() {
+ this.form.images.push({ label: "", imageId: "" });
+ },
+
+ removeImage(index: number) {
+ this.form.images.splice(index, 1);
+ },
+
+ async submit() {
+ const validation = maskotForm.safeParse(this.form);
+
+ if (!validation.success) {
+ const errors = validation.error.issues
+ .map((issue) => `${issue.path.join(".")}: ${issue.message}`)
+ .join(", ");
+ toast.error(`Form tidak valid: ${errors}`);
+ return false;
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(
+ `/api/desa/profile/maskot/${this.id}`,
+ {
+ method: "PUT",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(this.form),
+ }
+ );
+
+ const result = await response.json();
+
+ if (response.ok && result.success) {
+ toast.success("Berhasil update profile");
+ await maskotDesa.findUnique.load(this.id);
+ return true;
+ } else {
+ throw new Error(result.message || "Gagal update profile");
+ }
+ } catch (error) {
+ const msg = (error as Error).message;
+ this.error = msg;
+ toast.error("Terjadi kesalahan saat update profile");
+ return false;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ reset() {
+ this.id = "";
+ this.form = { ...maskotDefaultForm };
+ this.error = null;
+ this.loading = false;
+ this.isReadOnly = false;
+ },
+ },
+
+ async loadForEdit(id: string) {
+ const data = await this.findUnique.load(id);
+ if (data) {
+ this.update.initialize(data);
+ }
+ return data;
+ },
+
+ reset() {
+ this.findUnique.reset();
+ this.update.reset();
+ },
+});
+
+// ========================================= PROFIL PERBEKEL ========================================= //
+const profilPerbekelForm = z.object({
+ biodata: z.string().min(3, "Biodata minimal 3 karakter"),
+ pengalaman: z.string().min(3, "Pengalaman minimal 3 karakter"),
+ pengalamanOrganisasi: z
+ .string()
+ .min(3, "Pengalaman Organisasi minimal 3 karakter"),
+ programUnggulan: z.string().min(3, "Program Unggulan minimal 3 karakter"),
+ imageId: z.string().min(1, "Gambar wajib dipilih"),
+});
+
+const profilPerbekelDefaultForm = {
+ biodata: "",
+ pengalaman: "",
+ pengalamanOrganisasi: "",
+ programUnggulan: "",
+ imageId: "",
+};
+
+type ProfilPerbekelForm = Prisma.ProfilPerbekelGetPayload<{
+ select: {
+ id: true;
+ biodata: true;
+ pengalaman: true;
+ pengalamanOrganisasi: true;
+ programUnggulan: true;
+ imageId: true;
+ image?: {
+ select: {
+ link: true;
+ };
+ };
+ };
+}>;
+
+const profilPerbekel = proxy({
+ findUnique: {
+ data: null as ProfilPerbekelForm | null,
+ loading: false,
+ error: null as string | null,
+
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(`/api/desa/profile/profileperbekel/${id}`);
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+
+ const result = await response.json();
+
+ if (result.success) {
+ this.data = result.data;
+ return result.data;
+ } else {
+ throw new Error(
+ result.message || "Gagal mengambil data profil perbekel"
+ );
+ }
+ } catch (error) {
+ const msg = (error as Error).message;
+ this.error = msg;
+ toast.error("Terjadi kesalahan saat mengambil data profil perbekel");
+ return null;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ reset() {
+ this.data = null;
+ this.error = null;
+ this.loading = false;
+ },
+ },
+
+ edit: {
+ id: "",
+ form: { ...profilPerbekelDefaultForm },
+ loading: false,
+ error: null as string | null,
+ isReadOnly: false,
+
+ initialize(profilData: ProfilPerbekelForm) {
+ this.id = profilData.id;
+ this.isReadOnly = false;
+ this.form = {
+ biodata: profilData.biodata || "",
+ pengalaman: profilData.pengalaman || "",
+ pengalamanOrganisasi: profilData.pengalamanOrganisasi || "",
+ programUnggulan: profilData.programUnggulan || "",
+ imageId: profilData.imageId || "",
+ };
+ },
+
+ updateField(field: keyof typeof profilPerbekelDefaultForm, value: string) {
+ this.form[field] = value;
+ },
+
+ async submit() {
+ const validation = profilPerbekelForm.safeParse(this.form);
+
+ if (!validation.success) {
+ const errors = validation.error.issues
+ .map((issue) => `${issue.path.join(".")}: ${issue.message}`)
+ .join(", ");
+ toast.error(`Form tidak valid: ${errors}`);
+ return false;
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(
+ `/api/desa/profile/profileperbekel/${this.id}`,
+ {
+ method: "PUT",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(this.form),
+ }
+ );
+
+ 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 profil perbekel");
+ await profilPerbekel.findUnique.load(this.id);
+ return true;
+ } else {
+ throw new Error(result.message || "Gagal update profil perbekel");
+ }
+ } catch (error) {
+ const msg = (error as Error).message;
+ this.error = msg;
+ toast.error("Terjadi kesalahan saat update profil perbekel");
+ return false;
+ } finally {
+ this.loading = false;
+ }
+ },
+ reset() {
+ this.id = "";
+ this.form = { ...profilPerbekelDefaultForm };
+ this.error = null;
+ this.loading = false;
+ this.isReadOnly = false;
+ },
+ },
+
+ async loadForEdit(id: string) {
+ const profileData = await this.findUnique.load(id);
+ if (profileData) {
+ this.edit.initialize(profileData);
+ }
+ return profileData;
+ },
+
+ reset() {
+ this.findUnique.reset();
+ this.edit.reset();
+ },
+});
+
+const stateProfileDesa = proxy({
+ lambangDesa,
+ maskotDesa,
+ profilPerbekel,
+ visiMisiDesa,
+ sejarahDesa,
+});
export default stateProfileDesa;
diff --git a/src/app/admin/(dashboard)/_state/ppid/daftar_informasi_publik/daftarInformasiPublik.ts b/src/app/admin/(dashboard)/_state/ppid/daftar_informasi_publik/daftarInformasiPublik.ts
index ff0b2792..eee0179a 100644
--- a/src/app/admin/(dashboard)/_state/ppid/daftar_informasi_publik/daftarInformasiPublik.ts
+++ b/src/app/admin/(dashboard)/_state/ppid/daftar_informasi_publik/daftarInformasiPublik.ts
@@ -5,61 +5,239 @@ import { proxy } from "valtio";
import { z } from "zod";
const templateDaftarInformasi = z.object({
- jenisInformasi: z.string().min(3, "Jenis Informasi minimal 3 karakter"),
- deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
- tanggal: z.string().min(3, "Tanggal minimal 3 karakter"),
-})
+ jenisInformasi: z.string().min(3, "Jenis Informasi minimal 3 karakter"),
+ deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
+ tanggal: z.string().min(3, "Tanggal minimal 3 karakter"),
+});
+
+const defaultForm = {
+ jenisInformasi: "",
+ deskripsi: "",
+ tanggal: "",
+};
type DaftarInformasi = Prisma.DaftarInformasiPublikGetPayload<{
- select: {
- jenisInformasi: true;
- deskripsi: true;
- tanggal: true;
- };
+ select: {
+ jenisInformasi: true;
+ deskripsi: true;
+ tanggal: true;
+ };
}>;
-const daftarInformasi = proxy({
- create: {
- form: {} as DaftarInformasi,
- loading: false,
- async create() {
- const cek = templateDaftarInformasi.safeParse(daftarInformasi.create.form);
- if (!cek.success) {
- const err = `[${cek.error.issues
- .map((v) => `${v.path.join(".")}`)
- .join("\n")}] required`;
- return toast.error(err);
- }
- try {
- daftarInformasi.create.loading = true;
- const res = await ApiFetch.api.ppid.daftarinformasipublik["create"].post(daftarInformasi.create.form);
- if (res.status === 200) {
- daftarInformasi.findMany.load();
- return toast.success("success create");
- }
- return toast.error("failed create");
- } catch (error) {
- console.log((error as Error).message);
- } finally {
- daftarInformasi.create.loading = false;
- }
- },
- },
- findMany: {
- data: null as
- | Prisma.DaftarInformasiPublikGetPayload<{ omit: { isActive: true } }>[]
- | null,
- async load() {
- const res = await ApiFetch.api.ppid.daftarinformasipublik["find-many"].get();
- if (res.status === 200) {
- daftarInformasi.findMany.data = res.data?.data ?? [];
- }
+const daftarInformasiPublik = proxy({
+ create: {
+ form: {} as DaftarInformasi,
+ loading: false,
+ async create() {
+ const cek = templateDaftarInformasi.safeParse(
+ daftarInformasiPublik.create.form
+ );
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ return toast.error(err);
+ }
+ try {
+ daftarInformasiPublik.create.loading = true;
+ const res = await ApiFetch.api.ppid.daftarinformasipublik[
+ "create"
+ ].post(daftarInformasiPublik.create.form);
+ if (res.status === 200) {
+ daftarInformasiPublik.findMany.load();
+ return toast.success("success create");
}
- }
- });
+ return toast.error("failed create");
+ } catch (error) {
+ console.log((error as Error).message);
+ } finally {
+ daftarInformasiPublik.create.loading = false;
+ }
+ },
+ },
+ findMany: {
+ data: null as
+ | Prisma.DaftarInformasiPublikGetPayload<{ omit: { isActive: true } }>[]
+ | null,
+ async load() {
+ const res = await ApiFetch.api.ppid.daftarinformasipublik[
+ "find-many"
+ ].get();
+ if (res.status === 200) {
+ daftarInformasiPublik.findMany.data = res.data?.data ?? [];
+ }
+ },
+ },
+ findUnique: {
+ data: null as Prisma.DaftarInformasiPublikGetPayload<{
+ omit: { isActive: true };
+ }> | null,
+ async load(id: string) {
+ try {
+ const res = await fetch(`/api/ppid/daftarinformasipublik/${id}`);
+ if (res.ok) {
+ const data = await res.json();
+ daftarInformasiPublik.findUnique.data = data.data ?? null;
+ } else {
+ console.error(
+ "Failed to fetch daftar informasi publik:",
+ res.statusText
+ );
+ daftarInformasiPublik.findUnique.data = null;
+ }
+ } catch (error) {
+ console.error("Error fetching daftar informasi publik:", error);
+ daftarInformasiPublik.findUnique.data = null;
+ }
+ },
+ },
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
- const stateDaftarInformasiPublik = proxy({
- daftarInformasi
- })
+ try {
+ daftarInformasiPublik.delete.loading = true;
- export default stateDaftarInformasiPublik;
\ No newline at end of file
+ const response = await fetch(
+ `/api/ppid/daftarinformasipublik/del/${id}`,
+ {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ const result = await response.json();
+
+ if (response.ok && result?.success) {
+ toast.success(
+ result.message || "Daftar Informasi Publik berhasil dihapus"
+ );
+ await daftarInformasiPublik.findMany.load(); // refresh list
+ } else {
+ toast.error(
+ result?.message || "Gagal menghapus daftar informasi publik"
+ );
+ }
+ } catch (error) {
+ console.error("Gagal delete:", error);
+ toast.error("Terjadi kesalahan saat menghapus daftar informasi publik");
+ } finally {
+ daftarInformasiPublik.delete.loading = false;
+ }
+ },
+ },
+ edit: {
+ id: "",
+ form: { ...defaultForm },
+ loading: false,
+
+ async load(id: string) {
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+
+ try {
+ const response = await fetch(`/api/ppid/daftarinformasipublik/${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 = {
+ jenisInformasi: data.jenisInformasi,
+ deskripsi: data.deskripsi,
+ tanggal: data.tanggal,
+ };
+ return data;
+ } else {
+ throw new Error(result?.message || "Gagal mengambil data");
+ }
+ } catch (error) {
+ console.error("Error loading daftar informasi publik:", error);
+ toast.error(
+ error instanceof Error ? error.message : "Gagal memuat data"
+ );
+ return null;
+ }
+ },
+
+ async update() {
+ const cek = templateDaftarInformasi.safeParse(
+ daftarInformasiPublik.edit.form
+ );
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ return toast.error(err);
+ }
+ try {
+ daftarInformasiPublik.edit.loading = true;
+
+ const response = await fetch(
+ `/api/ppid/daftarinformasipublik/${this.id}`,
+ {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ jenisInformasi: this.form.jenisInformasi,
+ deskripsi: this.form.deskripsi,
+ tanggal: this.form.tanggal,
+ }),
+ }
+ );
+
+ 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 daftar informasi publik");
+ await daftarInformasiPublik.findMany.load(); // refresh list
+ return true;
+ } else {
+ throw new Error(
+ result.message || "Gagal update daftar informasi publik"
+ );
+ }
+ } catch (error) {
+ console.error("Error updating daftar informasi publik:", error);
+ toast.error(
+ error instanceof Error
+ ? error.message
+ : "Terjadi kesalahan saat update daftar informasi publik"
+ );
+ return false;
+ } finally {
+ daftarInformasiPublik.edit.loading = false;
+ }
+ },
+
+ reset() {
+ daftarInformasiPublik.edit.id = "";
+ daftarInformasiPublik.edit.form = { ...defaultForm };
+ },
+ },
+});
+
+export default daftarInformasiPublik;
diff --git a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin.ts b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin.ts
index 5e2c0192..164c6e81 100644
--- a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin.ts
+++ b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin.ts
@@ -11,12 +11,13 @@ const templateGrafikJenisKelamin = z.object({
type GrafikJenisKelamin = Prisma.GrafikBerdasarkanJenisKelaminGetPayload<{
select: {
+ id: true;
laki: true;
perempuan: true;
};
}>;
-const defaultForm: GrafikJenisKelamin = {
+const defaultForm: Omit & { id?: string } = {
laki: "",
perempuan: "",
};
@@ -41,9 +42,16 @@ const grafikBerdasarkanJenisKelamin = proxy({
"create"
].post(grafikBerdasarkanJenisKelamin.create.form);
if (res.status === 200) {
- grafikBerdasarkanJenisKelamin.create.form = defaultForm;
- grafikBerdasarkanJenisKelamin.findMany.load();
- return toast.success("success create");
+ const id = res.data?.data?.id;
+ if (id) {
+ toast.success("Success create");
+ grafikBerdasarkanJenisKelamin.create.form = {
+ laki: "",
+ perempuan: "",
+ };
+ grafikBerdasarkanJenisKelamin.findMany.load();
+ return id;
+ }
}
return toast.error("failed create");
} catch (error) {
@@ -69,9 +77,103 @@ const grafikBerdasarkanJenisKelamin = proxy({
}
},
},
+ findUnique: {
+ data: null as Prisma.GrafikBerdasarkanJenisKelaminGetPayload<{
+ omit: { isActive: true };
+ }> | null,
+ async load(id: string) {
+ try {
+ const res = await fetch(
+ `/api/ppid/grafikberdasarkanjeniskelamin/${id}`
+ );
+ if (res.ok) {
+ const data = await res.json();
+ grafikBerdasarkanJenisKelamin.findUnique.data = data.data ?? null;
+ } else {
+ console.error("Failed to fetch data", res.status, res.statusText);
+ grafikBerdasarkanJenisKelamin.findUnique.data = null;
+ }
+ } catch (error) {
+ console.error("Error loading grafik berdasarkan jenis kelamin:", error);
+ grafikBerdasarkanJenisKelamin.findUnique.data = null;
+ }
+ },
+ },
+ update: {
+ id: "",
+ form: {...defaultForm},
+ loading: false,
+ async byId() {
+ // Method implementation if needed
+ },
+ async submit() {
+ const id = this.id;
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+ const cek = templateGrafikJenisKelamin.safeParse(this.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues.map((v) => `${v.path.join(".")}`).join("\n")}] required`;
+ toast.error(err);
+ return null;
+ }
+ this.loading = true;
+ try {
+ const response = await fetch(
+ `/api/ppid/grafikberdasarkanjeniskelamin/${id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(this.form),
+ });
+ const result = await response.json();
+ if (!response.ok || !result?.success) {
+ throw new Error(result?.message || "Gagal update data");
+ }
+ toast.success("Berhasil update data!");
+ await grafikBerdasarkanJenisKelamin.findMany.load();
+ return result.data;
+ } catch (error) {
+ console.error("Error update data:", error);
+ toast.error("Gagal update data grafik berdasarkan jenis kelamin");
+ } finally {
+ this.loading = false;
+ }
+ },
+ },
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
+
+ try {
+ grafikBerdasarkanJenisKelamin.delete.loading = true;
+
+ const response = await fetch(`/api/ppid/grafikberdasarkanjeniskelamin/del/${id}`, {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ const result = await response.json();
+
+ if (response.ok && result?.success) {
+ toast.success(result.message || "Grafik berdasarkan jenis kelamin berhasil dihapus");
+ await grafikBerdasarkanJenisKelamin.findMany.load(); // refresh list
+ } else {
+ toast.error(result?.message || "Gagal menghapus grafik berdasarkan jenis kelamin");
+ }
+ } catch (error) {
+ console.error("Gagal delete:", error);
+ toast.error("Terjadi kesalahan saat menghapus grafik berdasarkan jenis kelamin");
+ } finally {
+ grafikBerdasarkanJenisKelamin.delete.loading = false;
+ }
+ },
+ }
});
-const stateGrafikBerdasarkanJenisKelamin = proxy({
- grafikBerdasarkanJenisKelamin,
-});
-export default stateGrafikBerdasarkanJenisKelamin;
+export default grafikBerdasarkanJenisKelamin;
diff --git a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden.ts b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden.ts
index 4fd2e69b..027669ad 100644
--- a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden.ts
+++ b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden.ts
@@ -13,6 +13,7 @@ const templateGrafikResponden = z.object({
type GrafikResponden = Prisma.GrafikBerdasarkanRespondenGetPayload<{
select: {
+ id: true;
sangatbaik: true;
baik: true;
kurangbaik: true;
@@ -20,7 +21,7 @@ type GrafikResponden = Prisma.GrafikBerdasarkanRespondenGetPayload<{
};
}>;
-const defaultForm: GrafikResponden = {
+const defaultForm: Omit & { id?: string } = {
sangatbaik: "",
baik: "",
kurangbaik: "",
@@ -47,9 +48,18 @@ const grafikBerdasarkanResponden = proxy({
"create"
].post(grafikBerdasarkanResponden.create.form);
if (res.status === 200) {
- grafikBerdasarkanResponden.create.form = defaultForm;
- grafikBerdasarkanResponden.findMany.load();
- return toast.success("success create");
+ const id = res.data?.data?.id;
+ if (id) {
+ toast.success("Success create");
+ grafikBerdasarkanResponden.create.form = {
+ sangatbaik: "",
+ baik: "",
+ kurangbaik: "",
+ tidakbaik: "",
+ };
+ grafikBerdasarkanResponden.findMany.load();
+ return id;
+ }
}
return toast.error("failed create");
} catch (error) {
@@ -75,10 +85,112 @@ const grafikBerdasarkanResponden = proxy({
}
},
},
+ findUnique: {
+ data: null as Prisma.GrafikBerdasarkanRespondenGetPayload<{
+ omit: { isActive: true };
+ }> | null,
+ async load(id: string) {
+ try {
+ const res = await fetch(
+ `/api/ppid/grafikberdasarkanresponden/${id}`
+ );
+ if (res.ok) {
+ const data = await res.json();
+ grafikBerdasarkanResponden.findUnique.data = data.data ?? null;
+ } else {
+ console.error("Failed to fetch data", res.status, res.statusText);
+ grafikBerdasarkanResponden.findUnique.data = null;
+ }
+ } catch (error) {
+ console.error("Error loading grafik berdasarkan responden:", error);
+ grafikBerdasarkanResponden.findUnique.data = null;
+ }
+ },
+ },
+ update: {
+ id: "",
+ form: {...defaultForm},
+ loading: false,
+ async byId() {
+ // Method implementation if needed
+ },
+ async submit() {
+ const id = this.id;
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+
+ const cek = templateGrafikResponden.safeParse(this.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ toast.error(err);
+ return null;
+ }
+
+ this.loading = true;
+
+ try {
+ const response = await fetch(`/api/ppid/grafikberdasarkanresponden/${id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(this.form),
+ });
+
+ const result = await response.json();
+
+ if (!response.ok || !result?.success) {
+ throw new Error(result?.message || "Gagal update data");
+ }
+
+ toast.success("Berhasil update data!");
+
+ await grafikBerdasarkanResponden.findMany.load();
+
+ return result.data;
+ } catch (error) {
+ console.error("Error update data:", error);
+ toast.error("Gagal update data grafik berdasarkan responden");
+ } finally {
+ this.loading = false;
+ }
+ }
+ },
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
+
+ try {
+ grafikBerdasarkanResponden.delete.loading = true;
+
+ const response = await fetch(`/api/ppid/grafikberdasarkanresponden/del/${id}`, {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ const result = await response.json();
+
+ if (response.ok && result?.success) {
+ toast.success(result.message || "Grafik berdasarkan responden berhasil dihapus");
+ await grafikBerdasarkanResponden.findMany.load(); // refresh list
+ } else {
+ toast.error(result?.message || "Gagal menghapus grafik berdasarkan responden");
+ }
+ } catch (error) {
+ console.error("Gagal delete:", error);
+ toast.error("Terjadi kesalahan saat menghapus grafik berdasarkan responden");
+ } finally {
+ grafikBerdasarkanResponden.delete.loading = false;
+ }
+ }
+ }
});
-const stateGrafikResponden = proxy({
- grafikBerdasarkanResponden,
-});
-
-export default stateGrafikResponden;
\ No newline at end of file
+export default grafikBerdasarkanResponden;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur.ts b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur.ts
index 3d05f6cf..7b3f4693 100644
--- a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur.ts
+++ b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur.ts
@@ -5,80 +5,182 @@ import { proxy } from "valtio";
import { z } from "zod";
const templateGrafikUmur = z.object({
- remaja: z.string().min(2, "Data remaja harus diisi"),
- dewasa: z.string().min(2, "Data dewasa harus diisi"),
- orangtua: z.string().min(2, "Data orangtua harus diisi"),
- lansia: z.string().min(2, "Data lansia harus diisi"),
+ remaja: z.string().min(2, "Data remaja harus diisi"),
+ dewasa: z.string().min(2, "Data dewasa harus diisi"),
+ orangtua: z.string().min(2, "Data orangtua harus diisi"),
+ lansia: z.string().min(2, "Data lansia harus diisi"),
});
type GrafikUmur = Prisma.GrafikBerdasarkanUmurGetPayload<{
- select: {
- remaja: true;
- dewasa: true;
- orangtua: true;
- lansia: true;
- };
+ select: {
+ id: true;
+ remaja: true;
+ dewasa: true;
+ orangtua: true;
+ lansia: true;
+ };
}>;
-const defaultForm: GrafikUmur = {
- remaja: "",
- dewasa: "",
- orangtua: "",
- lansia: "",
+const defaultForm: Omit & { id?: string } = {
+ remaja: "",
+ dewasa: "",
+ orangtua: "",
+ lansia: "",
};
const grafikBerdasarkanUmur = proxy({
- create: {
- form: defaultForm,
- loading: false,
- async create() {
- const cek = templateGrafikUmur.safeParse(
- grafikBerdasarkanUmur.create.form
- );
- if (!cek.success) {
- const err = `[${cek.error.issues
- .map((v) => `${v.path.join(".")}`)
- .join("\n")}] required`;
- return toast.error(err);
- }
- try {
- grafikBerdasarkanUmur.create.loading = true;
- const res = await ApiFetch.api.ppid.grafikberdasarkanumur[
- "create"
- ].post(grafikBerdasarkanUmur.create.form);
- if (res.status === 200) {
- grafikBerdasarkanUmur.create.form = defaultForm;
- grafikBerdasarkanUmur.findMany.load();
- return toast.success("success create");
- }
- return toast.error("failed create");
- } catch (error) {
- console.log((error as Error).message);
- } finally {
- grafikBerdasarkanUmur.create.loading = false;
- }
- },
+ create: {
+ form: defaultForm,
+ loading: false,
+ async create() {
+ const cek = templateGrafikUmur.safeParse(
+ grafikBerdasarkanUmur.create.form
+ );
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ return toast.error(err);
+ }
+ try {
+ grafikBerdasarkanUmur.create.loading = true;
+ const res = await ApiFetch.api.ppid.grafikberdasarkanumur[
+ "create"
+ ].post(grafikBerdasarkanUmur.create.form);
+ if (res.status === 200) {
+ const id = res.data?.data?.id;
+ if (id) {
+ toast.success("Success create");
+ grafikBerdasarkanUmur.create.form = {
+ remaja: "",
+ dewasa: "",
+ orangtua: "",
+ lansia: "",
+ };
+ grafikBerdasarkanUmur.findMany.load();
+ return id;
+ }
+ }
+ return toast.error("failed create");
+ } catch (error) {
+ console.log((error as Error).message);
+ } finally {
+ grafikBerdasarkanUmur.create.loading = false;
+ }
},
- findMany: {
- data: null as
- | Prisma.GrafikBerdasarkanUmurGetPayload<{
- omit: { isActive: true };
+ },
+ findMany: {
+ data: null as
+ | Prisma.GrafikBerdasarkanUmurGetPayload<{
+ omit: { isActive: true };
}>[]
- | null,
- loading: false,
- async load() {
- const res = await ApiFetch.api.ppid.grafikberdasarkanumur[
- "find-many"
- ].get();
- if (res.status === 200) {
- grafikBerdasarkanUmur.findMany.data = res.data?.data ?? [];
- }
- },
+ | null,
+ loading: false,
+ async load() {
+ const res = await ApiFetch.api.ppid.grafikberdasarkanumur[
+ "find-many"
+ ].get();
+ if (res.status === 200) {
+ grafikBerdasarkanUmur.findMany.data = res.data?.data ?? [];
+ }
},
-})
+ },
+ findUnique: {
+ data: null as Prisma.GrafikBerdasarkanUmurGetPayload<{
+ omit: { isActive: true };
+ }> | null,
+ async load(id: string) {
+ try {
+ const res = await fetch(`/api/ppid/grafikberdasarkanumur/${id}`);
+ if (res.ok) {
+ const data = await res.json();
+ grafikBerdasarkanUmur.findUnique.data = data.data ?? null;
+ } else {
+ console.error("Failed to fetch data", res.status, res.statusText);
+ grafikBerdasarkanUmur.findUnique.data = null;
+ }
+ } catch (error) {
+ console.error("Error loading grafik berdasarkan umur:", error);
+ grafikBerdasarkanUmur.findUnique.data = null;
+ }
+ },
+ },
+ update: {
+ id: "",
+ form: { ...defaultForm },
+ loading: false,
+ async byId() {
+ // Method implementation if needed
+ },
+ async submit() {
+ const id = this.id;
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+ const cek = templateGrafikUmur.safeParse(this.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues
+ .map((v) => `${v.path.join(".")}`)
+ .join("\n")}] required`;
+ toast.error(err);
+ return null;
+ }
+ this.loading = true;
+ try {
+ const response = await fetch(`/api/ppid/grafikberdasarkanumur/${id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(this.form),
+ });
+ const result = await response.json();
+ if (!response.ok || !result?.success) {
+ throw new Error(result?.message || "Gagal update data");
+ }
+ toast.success("Berhasil update data!");
+ await grafikBerdasarkanUmur.findMany.load();
+ return result.data;
+ } catch (error) {
+ console.error("Error update data:", error);
+ toast.error("Gagal update data grafik berdasarkan umur");
+ } finally {
+ this.loading = false;
+ }
+ }
+ },
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
-const stateGrafikBerdasarkanUmur = proxy({
- grafikBerdasarkanUmur,
-})
+ try {
+ grafikBerdasarkanUmur.delete.loading = true;
-export default stateGrafikBerdasarkanUmur;
\ No newline at end of file
+ const response = await fetch(`/api/ppid/grafikberdasarkanumur/del/${id}`, {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ const result = await response.json();
+
+ if (response.ok && result?.success) {
+ toast.success(result.message || "Grafik berdasarkan umur berhasil dihapus");
+ await grafikBerdasarkanUmur.findMany.load(); // refresh list
+ } else {
+ toast.error(result?.message || "Gagal menghapus grafik berdasarkan umur");
+ }
+ } catch (error) {
+ console.error("Gagal delete:", error);
+ toast.error("Terjadi kesalahan saat menghapus grafik berdasarkan umur");
+ } finally {
+ grafikBerdasarkanUmur.delete.loading = false;
+ }
+ }
+ }
+});
+
+export default grafikBerdasarkanUmur;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan.ts b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan.ts
index b8badf0c..65287269 100644
--- a/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan.ts
+++ b/src/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan.ts
@@ -11,12 +11,13 @@ const templateGrafikHasilKepuasanMasyarakat = z.object({
type GrafikHasilKepuasanMasyarakat = Prisma.IndeksKepuasanMasyarakatGetPayload<{
select: {
+ id: true;
label: true;
kepuasan: true;
};
}>;
-const defaultForm: GrafikHasilKepuasanMasyarakat = {
+const defaultForm: Omit & { id?: string } = {
label: "",
kepuasan: "",
};
@@ -41,13 +42,18 @@ const grafikHasilKepuasanMasyarakat = proxy({
grafikHasilKepuasanMasyarakat.create.form
);
if (res.status === 200) {
- grafikHasilKepuasanMasyarakat.create.form = {
- label: "",
- kepuasan: ""
- };
- grafikHasilKepuasanMasyarakat.findMany.load();
- return toast.success("success create");
+ const id = res.data?.data?.id;
+ if (id) {
+ toast.success("Success create");
+ grafikHasilKepuasanMasyarakat.create.form = {
+ label: "",
+ kepuasan: "",
+ };
+ grafikHasilKepuasanMasyarakat.findMany.load();
+ return id;
+ }
}
+
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
@@ -58,19 +64,127 @@ const grafikHasilKepuasanMasyarakat = proxy({
},
findMany: {
data: null as
- | Prisma.IndeksKepuasanMasyarakatGetPayload<{ omit: { isActive: true } }>[]
- | null,
+ | Prisma.IndeksKepuasanMasyarakatGetPayload<{
+ omit: { isActive: true };
+ }>[]
+ | null,
async load() {
- const res = await ApiFetch.api.ppid.grafikhasilkepuasamanmasyarakat["find-many"].get();
- if (res.status === 200) {
- grafikHasilKepuasanMasyarakat.findMany.data = res.data?.data ?? [];
+ const res = await ApiFetch.api.ppid.grafikhasilkepuasamanmasyarakat[
+ "find-many"
+ ].get();
+ if (res.status === 200) {
+ grafikHasilKepuasanMasyarakat.findMany.data = res.data?.data ?? [];
+ }
+ },
+ },
+ findUnique: {
+ data: null as Prisma.IndeksKepuasanMasyarakatGetPayload<{
+ omit: { isActive: true };
+ }> | null,
+
+ async load(id: string) {
+ try {
+ const res = await fetch(
+ `/api/ppid/grafikhasilkepuasamanmasyarakat/${id}`
+ );
+ if (res.ok) {
+ const data = await res.json();
+ grafikHasilKepuasanMasyarakat.findUnique.data = data.data ?? null;
+ } else {
+ console.error("Failed to fetch data", res.status, res.statusText);
+ grafikHasilKepuasanMasyarakat.findUnique.data = null;
}
+ } catch (error) {
+ console.error("Error loading grafik hasil kepuasan masyarakat:", error);
+ grafikHasilKepuasanMasyarakat.findUnique.data = null;
+ }
+ },
+ },
+ update: {
+ id: "",
+ form: { ...defaultForm },
+ loading: false,
+ async byId() {
+ // Method implementation if needed
+ },
+ async submit() {
+ const id = this.id;
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
+
+ // ✅ Validasi pakai Zod
+ const cek = templateGrafikHasilKepuasanMasyarakat.safeParse(this.form);
+ if (!cek.success) {
+ const err = `[${cek.error.issues.map((v) => `${v.path.join(".")}`).join("\n")}] required`;
+ toast.error(err);
+ return null;
+ }
+
+ this.loading = true;
+
+ try {
+ const response = await fetch(`/api/ppid/grafikhasilkepuasamanmasyarakat/${id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(this.form),
+ });
+
+ const result = await response.json();
+
+ if (!response.ok || !result?.success) {
+ throw new Error(result?.message || "Gagal update data");
+ }
+
+ toast.success("Berhasil update data!");
+
+ // ✅ Optional: refresh list kalau kamu langsung ke halaman list
+ await grafikHasilKepuasanMasyarakat.findMany.load();
+
+ return result.data;
+ } catch (error) {
+ console.error("Error update data:", error);
+ toast.error("Gagal update data grafik hasil kepuasan masyarakat");
+ } finally {
+ this.loading = false;
+ }
}
+
+ },
+ delete: {
+ loading: false,
+ async byId(id: string) {
+ if (!id) return toast.warn("ID tidak valid");
+
+ try {
+ grafikHasilKepuasanMasyarakat.delete.loading = true;
+
+ const response = await fetch(`/api/ppid/grafikhasilkepuasamanmasyarakat/del/${id}`, {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ const result = await response.json();
+
+ if (response.ok && result?.success) {
+ toast.success(result.message || "Grafik hasil kepuasan masyarakat berhasil dihapus");
+ await grafikHasilKepuasanMasyarakat.findMany.load(); // refresh list
+ } else {
+ toast.error(result?.message || "Gagal menghapus grafik hasil kepuasan masyarakat");
+ }
+ } catch (error) {
+ console.error("Gagal delete:", error);
+ toast.error("Terjadi kesalahan saat menghapus grafik hasil kepuasan masyarakat");
+ } finally {
+ grafikHasilKepuasanMasyarakat.delete.loading = false;
+ }
+ },
}
});
-const stateGrafikHasilKepuasanMasyarakat = proxy({
- grafikHasilKepuasanMasyarakat,
-});
-
-export default stateGrafikHasilKepuasanMasyarakat;
+export default grafikHasilKepuasanMasyarakat;
diff --git a/src/app/admin/(dashboard)/_state/ppid/profile_ppid/profile_PPID.ts b/src/app/admin/(dashboard)/_state/ppid/profile_ppid/profile_PPID.ts
index 167d8edd..0a6304b8 100644
--- a/src/app/admin/(dashboard)/_state/ppid/profile_ppid/profile_PPID.ts
+++ b/src/app/admin/(dashboard)/_state/ppid/profile_ppid/profile_PPID.ts
@@ -1,4 +1,3 @@
-import ApiFetch from "@/lib/api-fetch";
import { Prisma } from "@prisma/client";
import { toast } from "react-toastify";
import { proxy } from "valtio";
@@ -13,11 +12,18 @@ const templateForm = z.object({
riwayat: z.string().min(3, "Riwayat minimal 3 karakter"),
pengalaman: z.string().min(3, "Pengalaman minimal 3 karakter"),
unggulan: z.string().min(3, "Unggulan minimal 3 karakter"),
+ imageId: z.string().min(1, "Gambar wajib dipilih"),
});
-/**
- * Tipe data ProfilePPID yang digunakan dalam form dan API, berdasarkan Prisma schema.
- */
+const defaultForm = {
+ name: "",
+ biodata: "",
+ riwayat: "",
+ pengalaman: "",
+ unggulan: "",
+ imageId: "",
+};
+
type ProfilePPIDForm = Prisma.ProfilePPIDGetPayload<{
select: {
id: true;
@@ -26,147 +32,170 @@ type ProfilePPIDForm = Prisma.ProfilePPIDGetPayload<{
riwayat: true;
pengalaman: true;
unggulan: true;
- imageUrl: true;
+ imageId: true;
+ image?: {
+ select: {
+ link: true;
+ };
+ };
};
}>;
/**
- * State utama ProfilePPID yang mencakup fitur:
- * - Ambil data berdasarkan ID
- * - Update data
- * - Upload gambar
+ * Improved State Management - Consolidated and more robust
*/
const stateProfilePPID = proxy({
- /**
- * Bagian untuk ambil data berdasarkan ID
- */
- findById: {
+ // Consolidated data management
+ profile: {
data: null as ProfilePPIDForm | null,
loading: false,
+ error: null as string | null,
- /**
- * Inisialisasi data kosong ke dalam state.
- */
- initialize() {
- stateProfilePPID.findById.data = {
- id: '',
- name: '',
- biodata: '',
- riwayat: '',
- pengalaman: '',
- unggulan: '',
- imageUrl: ''
- } as ProfilePPIDForm;
- },
-
- /**
- * Mengambil data profil berdasarkan ID.
- * @param {string} id - ID dari profile yang ingin diambil.
- */
+ // Single method to load profile data
async load(id: string) {
- try {
- stateProfilePPID.findById.loading = true;
- const res = await ApiFetch.api.ppid.profileppid["find-by-id"].get({
- query: { id },
- });
+ if (!id) {
+ toast.warn("ID tidak valid");
+ return null;
+ }
- if (res.status === 200) {
- stateProfilePPID.findById.data = res.data?.data ?? null;
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(`/api/ppid/profileppid/${id}`);
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+
+ const result = await response.json();
+
+ if (result.success) {
+ this.data = result.data;
+ return result.data;
} else {
- toast.error("Gagal mengambil data profile");
+ throw new Error(result.message || "Gagal mengambil data profile");
}
} catch (error) {
- console.error((error as Error).message);
+ const errorMessage = (error as Error).message;
+ this.error = errorMessage;
+ console.error("Load profile error:", errorMessage);
toast.error("Terjadi kesalahan saat mengambil data profile");
+ return null;
} finally {
- stateProfilePPID.findById.loading = false;
+ this.loading = false;
}
},
+
+ // Reset profile data
+ reset() {
+ this.data = null;
+ this.error = null;
+ this.loading = false;
+ }
},
- /**
- * Bagian untuk update data profile
- */
- update: {
+ // Edit form management
+ editForm: {
+ id: "",
+ form: { ...defaultForm },
loading: false,
+ error: null as string | null,
+ isReadOnly: false, // Flag untuk data yang tidak bisa diedit
- /**
- * Melakukan validasi dan menyimpan perubahan data profile ke server.
- * @param {ProfilePPIDForm} data - Data profil yang akan disimpan.
- */
- async save(data: ProfilePPIDForm) {
- const cek = templateForm.safeParse(data);
+ // Initialize form with profile data
+ initialize(profileData: ProfilePPIDForm) {
+ this.id = profileData.id;
+ this.isReadOnly = false; // Semua data bisa diedit
+ this.form = {
+ name: profileData.name || "",
+ biodata: profileData.biodata || "",
+ riwayat: profileData.riwayat || "",
+ pengalaman: profileData.pengalaman || "",
+ unggulan: profileData.unggulan || "",
+ imageId: profileData.imageId || "",
+ };
+ },
- if (!cek.success) {
- const errors = cek.error.issues
+ // Update form field
+ updateField(field: keyof typeof defaultForm, value: string) {
+ this.form[field] = value;
+ },
+
+ // Submit form
+ async submit() {
+ // Validate form
+ const validation = templateForm.safeParse(this.form);
+
+ if (!validation.success) {
+ const errors = validation.error.issues
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
.join(", ");
toast.error(`Form tidak valid: ${errors}`);
- return;
+ return false;
}
- try {
- stateProfilePPID.update.loading = true;
- const res = await ApiFetch.api.ppid.profileppid["update"].post(data);
+ this.loading = true;
+ this.error = null;
- if (res.status === 200) {
+ try {
+ const response = await fetch(`/api/ppid/profileppid/${this.id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(this.form),
+ });
+
+ 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 profile");
- await stateProfilePPID.findById.load(data.id);
+ // Refresh profile data
+ await stateProfilePPID.profile.load(this.id);
+ return true;
} else {
- toast.error("Gagal update profile");
+ throw new Error(result.message || "Gagal update profile");
}
} catch (error) {
- console.error((error as Error).message);
+ const errorMessage = (error as Error).message;
+ this.error = errorMessage;
+ console.error("Update profile error:", errorMessage);
toast.error("Terjadi kesalahan saat update profile");
+ return false;
} finally {
- stateProfilePPID.update.loading = false;
+ this.loading = false;
}
},
+
+ // Reset form
+ reset() {
+ this.id = "";
+ this.form = { ...defaultForm };
+ this.error = null;
+ this.loading = false;
+ this.isReadOnly = false;
+ }
},
- /**
- * Bagian untuk upload gambar profil
- */
- uploadImage: {
- loading: false,
-
- /**
- * Mengunggah gambar profil berdasarkan ID.
- * @param {File} file - File gambar yang akan diunggah.
- * @param {string} id - ID dari profil yang akan diperbarui gambarnya.
- */
- async save(file: File, id: string) {
- if (!file || !id) {
- toast.error("File atau ID harus disertakan");
- return;
- }
-
- try {
- stateProfilePPID.uploadImage.loading = true;
-
- const form = new FormData();
- form.append("file", file);
- form.append("id", id);
-
- const res = await ApiFetch.api.ppid.profileppid["edit-img"].post(form);
-
- if (res.status === 200) {
- toast.success("Berhasil mengunggah gambar");
- await stateProfilePPID.findById.load(id);
- } else {
- toast.error("Gagal mengunggah gambar");
- }
- } catch (error) {
- console.error((error as Error).message);
- toast.error("Terjadi kesalahan saat mengunggah gambar");
- } finally {
- stateProfilePPID.uploadImage.loading = false;
- }
- },
+ // Helper methods
+ async loadForEdit(id: string) {
+ const profileData = await this.profile.load(id);
+ if (profileData) {
+ this.editForm.initialize(profileData);
+ }
+ return profileData;
},
+
+ reset() {
+ this.profile.reset();
+ this.editForm.reset();
+ }
});
-/**
- * Ekspor state utama ProfilePPID untuk digunakan di komponen lain.
- */
-export default stateProfilePPID;
+export default stateProfilePPID;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/_state/ppid/struktur_ppid/struktur_PPID.ts b/src/app/admin/(dashboard)/_state/ppid/struktur_ppid/struktur_PPID.ts
new file mode 100644
index 00000000..4df4347c
--- /dev/null
+++ b/src/app/admin/(dashboard)/_state/ppid/struktur_ppid/struktur_PPID.ts
@@ -0,0 +1,169 @@
+import { Prisma } from "@prisma/client";
+import { toast } from "react-toastify";
+import { proxy } from "valtio";
+import { z } from "zod";
+
+const templateForm = z.object({
+ name: z.string().min(3, "Nama minimal 3 karakter"),
+ imageId: z.string().min(1, "Gambar wajib dipilih"),
+})
+
+const defaultForm = {
+ name: "",
+ imageId: "",
+};
+
+type StrukturPPIDForm = Prisma.StrukturPPIDGetPayload<{
+ select: {
+ id: true;
+ name: true;
+ imageId: true;
+ image?: {
+ select: {
+ link: true;
+ };
+ };
+ };
+}>;
+
+const stateStrukturPPID = proxy({
+ struktur: {
+ data: null as StrukturPPIDForm | null,
+ loading: false,
+ error: null as string | null,
+
+ async load(id: string) {
+ if(!id) {
+ toast.warn("ID tidak valid")
+ return null
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(`/api/ppid/strukturppid/${id}`);
+
+ if(!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`)
+ }
+
+ const result = await response.json();
+
+ if(result.success) {
+ this.data = result.data;
+ return result.data
+ } else {
+ throw new Error(result.message || "Gagal mengambil data struktur")
+ }
+ } catch (error) {
+ const errorMessage = (error as Error).message;
+ this.error = errorMessage;
+ console.error("Load struktur error:", errorMessage);
+ toast.error("Terjadi kesalahan saat mengambil data struktur");
+ return null;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ reset() {
+ this.data = null;
+ this.error = null;
+ this.loading = false;
+ }
+ },
+
+ editStruktur: {
+ id: "",
+ form: { ...defaultForm },
+ loading: false,
+ error: null as string | null,
+ isReadOnly: false,
+
+ initialize(strukturData: StrukturPPIDForm) {
+ this.id = strukturData.id;
+ this.isReadOnly = false;
+ this.form = {
+ name: strukturData.name || "",
+ imageId: strukturData.imageId || "",
+ };
+ },
+
+ updateField(field: keyof typeof defaultForm, value: string) {
+ this.form[field] = value;
+ },
+
+ async submit() {
+ const validation = templateForm.safeParse(this.form);
+
+ if (!validation.success) {
+ const errors = validation.error.issues
+ .map((issue) => `${issue.path.join(".")}: ${issue.message}`)
+ .join(", ");
+ toast.error(`Form tidak valid: ${errors}`);
+ return false;
+ }
+
+ this.loading = true;
+ this.error = null;
+
+ try {
+ const response = await fetch(`/api/ppid/strukturppid/${this.id}`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(this.form),
+ })
+
+ 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 struktur");
+ await stateStrukturPPID.struktur.load(this.id);
+ return true;
+ } else {
+ throw new Error(result.message || "Gagal update struktur");
+ }
+ } catch (error) {
+ const errorMessage = (error as Error).message;
+ this.error = errorMessage;
+ console.error("Update struktur error:", errorMessage);
+ toast.error("Terjadi kesalahan saat update struktur");
+ return false;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ reset() {
+ this.id = "";
+ this.form = { ...defaultForm };
+ this.error = null;
+ this.loading = false;
+ this.isReadOnly = false;
+ }
+ },
+
+ async loadForEdit(id: string) {
+ const strukturData = await this.struktur.load(id);
+ if (strukturData) {
+ this.editStruktur.initialize(strukturData);
+ }
+ return strukturData;
+ },
+
+ reset() {
+ this.struktur.reset();
+ this.editStruktur.reset();
+ }
+})
+
+export default stateStrukturPPID;
+
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/desa/_com/layoutTabLayanan.tsx b/src/app/admin/(dashboard)/desa/_com/layoutTabLayanan.tsx
new file mode 100644
index 00000000..47eea7f9
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/_com/layoutTabLayanan.tsx
@@ -0,0 +1,72 @@
+/* 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 LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
+ const router = useRouter()
+ const pathname = usePathname()
+ const tabs = [
+ {
+ label: "Pelayanan Surat Keterangan",
+ value: "pelayanansuratketerangan",
+ href: "/admin/desa/layanan/pelayanan_surat_keterangan"
+ },
+ {
+ label: "Pelayanan Perizinan Berusaha",
+ value: "pelayananperizinanusaha",
+ href: "/admin/desa/layanan/pelayanan_perizinan_berusaha"
+ },
+ {
+ label: "Pelayanan Telunjuk Sakti Desa",
+ value: "pelayanantelunjuksaktidesa",
+ href: "/admin/desa/layanan/pelayanan_telunjuk_sakti_desa"
+ },
+ {
+ label: "Pelayanan Penduduk Non-Permanent",
+ value: "pelayanantelunjuknonpermanent",
+ href: "/admin/desa/layanan/pelayanan_penduduk_non_permanent"
+ }
+ ];
+ 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 (
+
+ Layanan
+
+
+ {tabs.map((e, i) => (
+ {e.label}
+ ))}
+
+ {tabs.map((e, i) => (
+
+ {/* Konten dummy, bisa diganti tergantung routing */}
+ <>>
+
+ ))}
+
+ {children}
+
+ );
+}
+
+export default LayoutTabsLayanan;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/desa/berita/[id]/edit/page.tsx b/src/app/admin/(dashboard)/desa/berita/[id]/edit/page.tsx
index a753aede..b5ea38d1 100644
--- a/src/app/admin/(dashboard)/desa/berita/[id]/edit/page.tsx
+++ b/src/app/admin/(dashboard)/desa/berita/[id]/edit/page.tsx
@@ -125,16 +125,6 @@ function EditBerita() {
placeholder="masukkan judul"
/>
- {
- setFormData({
- ...formData,
- kategoriBeritaId: val?.id || ''
- });
- }}
- />
-
setFormData({ ...formData, deskripsi: e.target.value })}
@@ -174,6 +164,16 @@ function EditBerita() {
/>
+ {
+ setFormData({
+ ...formData,
+ kategoriBeritaId: val?.id || ''
+ });
+ }}
+ />
+
Edit Berita
diff --git a/src/app/admin/(dashboard)/desa/berita/create/page.tsx b/src/app/admin/(dashboard)/desa/berita/create/page.tsx
index f27cc51f..4f5e7dff 100644
--- a/src/app/admin/(dashboard)/desa/berita/create/page.tsx
+++ b/src/app/admin/(dashboard)/desa/berita/create/page.tsx
@@ -63,9 +63,9 @@ export default function CreateBerita() {
return (
- router.back()}>
-
-
+ router.back()}>
+
+
@@ -79,8 +79,9 @@ export default function CreateBerita() {
placeholder="masukkan judul"
/>
{
- beritaState.berita.create.form.kategoriBeritaId = val.id;
+ beritaState.berita.create.form.kategoriBeritaId = val?.id || "";
}}
/>
Konten
{
- beritaState.berita.create.form.content = htmlContent;
- }}
+ value={beritaState.berita.create.form.content}
+ onChange={(htmlContent) => {
+ beritaState.berita.create.form.content = htmlContent;
+ }}
/>
Simpan Berita
@@ -126,26 +127,37 @@ export default function CreateBerita() {
);
- function SelectCategory({
- onChange,
- }: {
+ interface SelectCategoryProps {
onChange: (value: Prisma.KategoriBeritaGetPayload<{
select: {
name: true;
id: true;
};
- }>) => void;
- }) {
+ }> | null) => void;
+ value?: string | null;
+ defaultValue?: string | null;
+ }
+
+ function SelectCategory({
+ onChange,
+ value,
+ defaultValue,
+ }: SelectCategoryProps) {
const categoryState = useProxy(stateDashboardBerita.category);
-
+
useShallowEffect(() => {
- categoryState.findMany.load();
+ categoryState.findMany.load().then(() => {
+ console.log("Kategori berhasil dimuat:", categoryState.findMany.data);
+ });
}, []);
-
+
if (!categoryState.findMany.data) {
return ;
}
-
+
+
+ const selectedValue = value || defaultValue;
+
return (
Kategori}
@@ -154,13 +166,19 @@ export default function CreateBerita() {
label: item.name,
value: item.id,
}))}
- onChange={(val) => {
- const selected = categoryState.findMany.data?.find((item) => item.id === val);
- if (selected) {
- onChange(selected);
+ value={selectedValue || null}
+ onChange={(val: string | null) => {
+ if (val) {
+ const selected = categoryState.findMany.data?.find((item) => item.id === val);
+ if (selected) {
+ onChange(selected);
+ }
+ } else {
+ onChange(null);
}
}}
searchable
+ clearable
nothingFoundMessage="Tidak ditemukan"
/>
);
diff --git a/src/app/admin/(dashboard)/desa/berita/page.tsx b/src/app/admin/(dashboard)/desa/berita/page.tsx
index 01a96511..201338fe 100644
--- a/src/app/admin/(dashboard)/desa/berita/page.tsx
+++ b/src/app/admin/(dashboard)/desa/berita/page.tsx
@@ -4,9 +4,7 @@ import { Box, Button, Grid, GridCol, Image, Paper, Skeleton, Stack, Table, Table
import { useShallowEffect } from '@mantine/hooks';
import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
-import { useState } from 'react';
import { useProxy } from 'valtio/utils';
-import { ModalKonfirmasiHapus } from '../../_com/modalKonfirmasiHapus';
import stateDashboardBerita from '../../_state/desa/berita';
@@ -32,76 +30,8 @@ function Page() {
);
}
-
-
-
-
-
-// function BeritaList() {
-// const beritaState = useProxy(stateDashboardBerita)
-// useShallowEffect(() => {
-// beritaState.berita.findMany.load()
-// }, [])
-
-
-
-// const router = useRouter()
-
-// if (!beritaState.berita.findMany.data) return
-// {Array.from({ length: 10 }).map((v, k) => )}
-//
-// return (
-//
-//
-//
-// List Berita
-//
-// {beritaState.berita.findMany.data?.map((item) => (
-//
-//
-//
-// beritaState.berita.delete.byId(item.id)}
-// disabled={beritaState.berita.delete.loading}
-// color={colors['blue-button']} variant='transparent'>
-//
-//
-// {
-// router.push("/desa/berita/edit");
-// }} color={colors['blue-button']} variant='transparent'>
-//
-//
-//
-//
-// Kategori
-//
-// {item.kategoriBerita?.name}
-//
-// Judul
-//
-// {item.judul}
-//
-// Deskripsi
-//
-// {item.deskripsi}
-//
-// Gambar
-//
-//
-//
-//
-// ))}
-//
-//
-//
-//
-// )
-// }
-
function BeritaList() {
const beritaState = useProxy(stateDashboardBerita)
- const [modalHapus, setModalHapus] = useState(false)
- const [selectedId, setSelectedId] = useState(null)
useShallowEffect(() => {
beritaState.berita.findMany.load()
@@ -109,14 +39,6 @@ function BeritaList() {
const router = useRouter()
- const handleHapus = () => {
- if (selectedId) {
- beritaState.berita.delete.byId(selectedId)
- setModalHapus(false)
- setSelectedId(null)
- }
- }
-
if (!beritaState.berita.findMany.data) {
return (
@@ -175,13 +97,6 @@ function BeritaList() {
- {/* Modal Konfirmasi Hapus */}
- setModalHapus(false)}
- onConfirm={handleHapus}
- text='Apakah anda yakin ingin menghapus berita ini?'
- />
)
}
diff --git a/src/app/admin/(dashboard)/desa/gallery/foto/[id]/edit/page.tsx b/src/app/admin/(dashboard)/desa/gallery/foto/[id]/edit/page.tsx
new file mode 100644
index 00000000..9fb7f3ff
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/gallery/foto/[id]/edit/page.tsx
@@ -0,0 +1,119 @@
+'use client'
+/* eslint-disable react-hooks/exhaustive-deps */
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery';
+import colors from '@/con/colors';
+import ApiFetch from '@/lib/api-fetch';
+import { Box, Button, Center, FileInput, Group, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } 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 EditFoto() {
+ const fotoState = useProxy(stateGallery.foto)
+ const router = useRouter();
+ const params = useParams();
+ const [previewImage, setPreviewImage] = useState(null);
+ const [file, setFile] = useState(null);
+
+ useEffect(() => {
+ const loadFoto = async () => {
+ const id = params?.id as string;
+ if (!id) return;
+ try {
+ const data = await fotoState.update.load(id);
+ if (data) {
+ if (data?.imageGalleryFoto?.link) {
+ setPreviewImage(data.imageGalleryFoto.link);
+ }
+ }
+ } catch (error) {
+ console.error('Error loading foto:', error);
+ toast.error('Gagal memuat data foto');
+ }
+ };
+ loadFoto();
+ }, [params?.id]);
+
+ const handleSubmit = async () => {
+ try {
+ 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");
+ }
+ fotoState.update.form.imagesId = uploaded.id;
+ }
+ await fotoState.update.update();
+ toast.success('Foto berhasil diperbarui!');
+ router.push('/admin/desa/gallery/foto');
+ } catch (error) {
+ console.error('Error updating foto:', error);
+ toast.error('Terjadi kesalahan saat memperbarui foto');
+ }
+ };
+
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Foto
+ Judul Foto}
+ placeholder='Masukkan judul foto'
+ value={fotoState.update.form.name}
+ onChange={(e) =>
+ (fotoState.update.form.name = e.target.value)
+ }
+ />
+ Upload Gambar}
+ value={file}
+ onChange={async (e) => {
+ if (!e) return;
+ setFile(e);
+ const base64 = await e.arrayBuffer().then((buf) =>
+ "data:image/png;base64," + Buffer.from(buf).toString("base64")
+ );
+ setPreviewImage(base64);
+ }}
+ />
+ {previewImage ? (
+
+ ) : (
+
+
+
+ )}
+
+ Deskripsi Foto
+ {
+ fotoState.update.form.deskripsi = val;
+ }}
+ />
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditFoto;
diff --git a/src/app/admin/(dashboard)/desa/gallery/foto/[id]/page.tsx b/src/app/admin/(dashboard)/desa/gallery/foto/[id]/page.tsx
new file mode 100644
index 00000000..682c33c0
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/gallery/foto/[id]/page.tsx
@@ -0,0 +1,112 @@
+'use client'
+import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery';
+import React from 'react';
+import { useProxy } from 'valtio/utils';
+import { useState } from 'react';
+import { useParams, useRouter } from 'next/navigation';
+import { useShallowEffect } from '@mantine/hooks';
+import { Box, Button, Flex, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import colors from '@/con/colors';
+import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
+
+function DetailFoto() {
+ const fotoState = useProxy(stateGallery.foto)
+ const [modalHapus, setModalHapus] = useState(false);
+ const [selectedId, setSelectedId] = useState(null)
+ const params = useParams()
+ const router = useRouter()
+
+ useShallowEffect(() => {
+ fotoState.findUnique.load(params?.id as string)
+ }, [])
+
+ const handleHapus = () => {
+ if (selectedId) {
+ fotoState.delete.byId(selectedId)
+ setModalHapus(false)
+ setSelectedId(null)
+ router.push("/admin/desa/gallery/foto")
+ }
+ }
+
+ if (!fotoState.findUnique.data) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Foto
+ {fotoState.findUnique.data ? (
+
+
+
+ Judul
+ {fotoState.findUnique.data?.name}
+
+
+ Tanggal Foto
+ {new Date(fotoState.findUnique.data?.createdAt).toDateString()}
+
+
+ Deskripsi
+
+
+
+ Gambar
+
+
+
+ {
+ if (fotoState.findUnique.data) {
+ setSelectedId(fotoState.findUnique.data.id);
+ setModalHapus(true);
+ }
+ }}
+ disabled={fotoState.delete.loading || !fotoState.findUnique.data}
+ color={"red"}
+ >
+
+
+ {
+ if (fotoState.findUnique.data) {
+ router.push(`/admin/desa/gallery/foto/${fotoState.findUnique.data.id}/edit`);
+ }
+ }}
+ disabled={!fotoState.findUnique.data}
+ color={"green"}
+ >
+
+
+
+
+
+ ) : null}
+
+
+
+ {/* Modal Konfirmasi Hapus */}
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text='Apakah anda yakin ingin menghapus berita ini?'
+ />
+
+ );
+}
+
+export default DetailFoto;
diff --git a/src/app/admin/(dashboard)/desa/gallery/foto/create/page.tsx b/src/app/admin/(dashboard)/desa/gallery/foto/create/page.tsx
new file mode 100644
index 00000000..8f681295
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/gallery/foto/create/page.tsx
@@ -0,0 +1,109 @@
+'use client'
+import CreateEditor from '@/app/admin/(dashboard)/_com/createEditor';
+import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery';
+import colors from '@/con/colors';
+import ApiFetch from '@/lib/api-fetch';
+import { Box, Button, Center, FileInput, Group, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useState } from 'react';
+import { toast } from 'react-toastify';
+import { useProxy } from 'valtio/utils';
+
+
+
+function CreateFoto() {
+ const fotoState = useProxy(stateGallery.foto)
+ const router = useRouter();
+ const [previewImage, setPreviewImage] = useState(null);
+ const [file, setFile] = useState(null);
+
+ const resetForm = () => {
+ fotoState.create.form = {
+ name: "",
+ deskripsi: "",
+ imagesId: "",
+ };
+
+ setPreviewImage(null)
+ setFile(null)
+ };
+
+ const handleSubmit = async () => {
+ if (!file) {
+ return toast.warn("Pilih file gambar terlebih dahulu");
+ }
+
+ 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");
+ }
+
+ fotoState.create.form.imagesId = uploaded.id;
+ await fotoState.create.create();
+ resetForm();
+ router.push("/admin/desa/gallery/foto")
+ };
+
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Foto
+ Judul Foto}
+ placeholder='Masukkan judul foto'
+ value={fotoState.create.form.name}
+ onChange={(val) => {
+ fotoState.create.form.name = val.target.value;
+ }}
+ />
+ Upload Gambar}
+ value={file}
+ onChange={async (e) => {
+ if (!e) return;
+ setFile(e);
+ const base64 = await e.arrayBuffer().then((buf) =>
+ "data:image/png;base64," + Buffer.from(buf).toString("base64")
+ );
+ setPreviewImage(base64);
+ }}
+ />
+ {previewImage ? (
+
+ ) : (
+
+
+
+ )}
+
+ Deskripsi Foto
+ {
+ fotoState.create.form.deskripsi = val;
+ }}
+ />
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateFoto;
diff --git a/src/app/admin/(dashboard)/desa/gallery/foto/page.tsx b/src/app/admin/(dashboard)/desa/gallery/foto/page.tsx
new file mode 100644
index 00000000..08035001
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/gallery/foto/page.tsx
@@ -0,0 +1,67 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Skeleton, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import JudulListTab from '../../../_com/jusulListTab';
+import { useProxy } from 'valtio/utils';
+import stateGallery from '../../../_state/desa/gallery';
+import { useShallowEffect } from '@mantine/hooks';
+
+function Foto() {
+ const fotoState = useProxy(stateGallery.foto)
+ const router = useRouter();
+
+ useShallowEffect(() => {
+ fotoState.findMany.load()
+ }, [])
+
+ if (!fotoState.findMany.data) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+ }
+ />
+
+
+
+ Judul Foto
+ Tanggal Foto
+ Deskripsi Foto
+ Detail
+
+
+
+ {fotoState.findMany.data?.map((item) => (
+
+ {item.name}
+ {new Date(item.createdAt).toDateString()}
+
+
+
+
+ router.push(`/admin/desa/gallery/foto/${item.id}`)}>
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
+
+export default Foto;
diff --git a/src/app/admin/(dashboard)/desa/gallery/layout.tsx b/src/app/admin/(dashboard)/desa/gallery/layout.tsx
new file mode 100644
index 00000000..78a5c467
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/gallery/layout.tsx
@@ -0,0 +1,10 @@
+'use client'
+import LayoutTabsGallery from "../../ppid/_com/layoutTabsGallery"
+
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/desa/gallery/lib/youtube-utils.ts b/src/app/admin/(dashboard)/desa/gallery/lib/youtube-utils.ts
new file mode 100644
index 00000000..26fa1175
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/gallery/lib/youtube-utils.ts
@@ -0,0 +1,31 @@
+export function convertYoutubeUrlToEmbed(url: string) {
+ const videoIdMatch = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/);
+ return videoIdMatch ? `https://www.youtube.com/embed/${videoIdMatch[1]}` : null;
+}
+
+
+
+
+
+
+
+
+
+// (url: string): string | null {
+// const watchRegex = /(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?v=([^&]+)/;
+// const shortRegex = /(?:https?:\/\/)?youtu\.be\/([^?]+)/;
+
+// const matchWatch = url.match(watchRegex);
+// const matchShort = url.match(shortRegex);
+
+// if (matchWatch) {
+// return `https://www.youtube.com/embed/${matchWatch[1]}`;
+// }
+
+// if (matchShort) {
+// return `https://www.youtube.com/embed/${matchShort[1]}`;
+// }
+
+// return null;
+// }
+
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/desa/gallery/lib/youtubeEmbed.tsx b/src/app/admin/(dashboard)/desa/gallery/lib/youtubeEmbed.tsx
new file mode 100644
index 00000000..fcf4d266
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/gallery/lib/youtubeEmbed.tsx
@@ -0,0 +1,33 @@
+// components/YoutubeEmbed.tsx
+"use client";
+
+import { Box, Text } from "@mantine/core";
+
+type YoutubeEmbedProps = {
+ url?: string;
+ showRawUrl?: boolean; // opsional, buat nampilin URL mentahnya
+};
+
+export default function YoutubeEmbed({ url, showRawUrl = false }: YoutubeEmbedProps) {
+ if (!url || !url.includes("embed")) {
+ return Link embed Youtube tidak valid ;
+ }
+
+ return (
+
+
+ {showRawUrl && (
+
+ {url}
+
+ )}
+
+ );
+}
diff --git a/src/app/admin/(dashboard)/desa/gallery/page.tsx b/src/app/admin/(dashboard)/desa/gallery/page.tsx
deleted file mode 100644
index bb753607..00000000
--- a/src/app/admin/(dashboard)/desa/gallery/page.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
-import { IconPhoto, IconVideo } from '@tabler/icons-react';
-import Foto from './ui/foto/page';
-import Video from './ui/video/page';
-
-function Gallery() {
- return (
-
-
- Gallery
-
-
- }>
- Foto
-
- }>
- Video
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default Gallery;
diff --git a/src/app/admin/(dashboard)/desa/gallery/ui/foto/listPage.tsx b/src/app/admin/(dashboard)/desa/gallery/ui/foto/listPage.tsx
deleted file mode 100644
index 4cecb3a0..00000000
--- a/src/app/admin/(dashboard)/desa/gallery/ui/foto/listPage.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Title } from '@mantine/core';
-import React from 'react';
-
-function ListFoto() {
- return (
-
-
-
- List Foto
-
-
-
- );
-}
-
-export default ListFoto;
diff --git a/src/app/admin/(dashboard)/desa/gallery/ui/foto/page.tsx b/src/app/admin/(dashboard)/desa/gallery/ui/foto/page.tsx
deleted file mode 100644
index a696750c..00000000
--- a/src/app/admin/(dashboard)/desa/gallery/ui/foto/page.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Center, Group, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
-import { IconUpload } from '@tabler/icons-react';
-import { DesaEditor } from '../../../_com/desaEditor';
-import ListFoto from './listPage';
-
-function Foto() {
- return (
-
-
-
-
-
- Foto
- Tanggal Foto}
- placeholder="2022-01-01"
- />
- Judul Foto}
- placeholder="Judul Foto"
- />
- Upload Foto
-
-
-
-
-
-
- Deskripsi Foto
-
-
-
-
- Submit
-
-
-
-
-
-
-
-
- );
-}
-
-export default Foto;
diff --git a/src/app/admin/(dashboard)/desa/gallery/ui/video/listPage.tsx b/src/app/admin/(dashboard)/desa/gallery/ui/video/listPage.tsx
deleted file mode 100644
index 83880a4d..00000000
--- a/src/app/admin/(dashboard)/desa/gallery/ui/video/listPage.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Title } from '@mantine/core';
-import React from 'react';
-
-function ListVideo() {
- return (
-
-
-
- List Video
-
-
-
- );
-}
-
-export default ListVideo;
diff --git a/src/app/admin/(dashboard)/desa/gallery/ui/video/page.tsx b/src/app/admin/(dashboard)/desa/gallery/ui/video/page.tsx
deleted file mode 100644
index f25c6873..00000000
--- a/src/app/admin/(dashboard)/desa/gallery/ui/video/page.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Center, Group, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
-import { IconUpload } from '@tabler/icons-react';
-import { DesaEditor } from '../../../_com/desaEditor';
-import ListVideo from './listPage';
-
-function Video() {
- return (
-
-
-
-
-
- Video
- Tanggal Video}
- placeholder="2022-01-01"
- />
- Judul Video}
- placeholder="Judul Video"
- />
- Upload Video
-
-
-
-
-
-
- Deskripsi Video
-
-
-
-
- Submit
-
-
-
-
-
-
-
-
- );
-}
-
-export default Video;
diff --git a/src/app/admin/(dashboard)/desa/gallery/video/[id]/edit/page.tsx b/src/app/admin/(dashboard)/desa/gallery/video/[id]/edit/page.tsx
new file mode 100644
index 00000000..25550868
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/gallery/video/[id]/edit/page.tsx
@@ -0,0 +1,134 @@
+/* eslint-disable react-hooks/exhaustive-deps */
+'use client'
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery';
+import colors from '@/con/colors';
+import { Box, Button, Group, 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';
+import { convertYoutubeUrlToEmbed } from '../../../lib/youtube-utils';
+
+function EditVideo() {
+ const router = useRouter();
+ const videoState = useProxy(stateGallery.video)
+ const params = useParams()
+
+ const [formData, setFormData] = useState({
+ name: '',
+ deskripsi: '',
+ linkVideo: '',
+ });
+
+ useEffect(() => {
+ const loadVideo = async () => {
+ const id = params?.id as string;
+ if (!id) return;
+ try {
+ const data = await videoState.update.load(id);
+ if (data) {
+ setFormData({
+ name: data.name || '',
+ deskripsi: data.deskripsi || '',
+ linkVideo: data.linkVideo || '',
+ });
+ }
+ } catch (error) {
+ console.error('Error loading video:', error);
+ toast.error('Gagal memuat data video');
+ }
+ };
+ loadVideo();
+ }, [params?.id]);
+
+ const embedLink = convertYoutubeUrlToEmbed(formData.linkVideo);
+
+ const handleSubmit = async () => {
+ const converted = convertYoutubeUrlToEmbed(formData.linkVideo);
+ if (!converted) {
+ toast.error("Link YouTube tidak valid. Pastikan formatnya benar.");
+ return;
+ }
+
+ try {
+ videoState.update.form = {
+ ...videoState.update.form,
+ name: formData.name,
+ deskripsi: formData.deskripsi,
+ linkVideo: formData.linkVideo,
+ };
+ await videoState.update.update();
+ toast.success('Video berhasil diperbarui!');
+ router.push('/admin/desa/gallery/video');
+ } catch (error) {
+ console.error('Error updating video:', error);
+ toast.error('Terjadi kesalahan saat memperbarui video');
+ }
+ }
+
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Video
+
+ Judul Video}
+ placeholder='Masukkan judul video'
+ value={formData.name}
+ onChange={(val) => {
+ setFormData({ ...formData, name: val.target.value });
+ }}
+ />
+
+
+ {
+ setFormData({ ...formData, linkVideo: e.currentTarget.value });
+ }}
+ required
+ />
+
+ {embedLink && (
+
+ )}
+
+
+
+ Deskripsi Video
+ {
+ setFormData({ ...formData, deskripsi: val });
+ }}
+ />
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditVideo;
diff --git a/src/app/admin/(dashboard)/desa/gallery/video/[id]/page.tsx b/src/app/admin/(dashboard)/desa/gallery/video/[id]/page.tsx
new file mode 100644
index 00000000..b8783c63
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/gallery/video/[id]/page.tsx
@@ -0,0 +1,133 @@
+'use client'
+import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
+import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery';
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Skeleton, Stack, Text } from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useParams, useRouter } from 'next/navigation';
+import { useState } from 'react';
+import { useProxy } from 'valtio/utils';
+
+
+function DetailVideo() {
+ const videoState = useProxy(stateGallery.video)
+ const [modalHapus, setModalHapus] = useState(false);
+ const [selectedId, setSelectedId] = useState(null)
+ const params = useParams()
+ const router = useRouter()
+
+ useShallowEffect(() => {
+ videoState.findUnique.load(params?.id as string)
+ }, [])
+
+ const handleHapus = () => {
+ if (selectedId) {
+ videoState.delete.byId(selectedId)
+ setModalHapus(false)
+ setSelectedId(null)
+ router.push("/admin/desa/gallery/video")
+ }
+ }
+
+ if (!videoState.findUnique.data) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Video
+ {videoState.findUnique.data ? (
+
+
+
+ Judul
+ {videoState.findUnique.data?.name}
+
+
+ Video
+
+
+
+
+
+ Tanggal Video
+ {new Date(videoState.findUnique.data?.createdAt).toDateString()}
+
+
+ Deskripsi
+
+
+
+ {
+ if (videoState.findUnique.data) {
+ setSelectedId(videoState.findUnique.data.id);
+ setModalHapus(true);
+ }
+ }}
+ disabled={videoState.delete.loading || !videoState.findUnique.data}
+ color={"red"}
+ >
+
+
+ {
+ if (videoState.findUnique.data) {
+ router.push(`/admin/desa/gallery/video/${videoState.findUnique.data.id}/edit`);
+ }
+ }}
+ disabled={!videoState.findUnique.data}
+ color={"green"}
+ >
+
+
+
+
+
+ ) : null}
+
+
+
+ {/* Modal Konfirmasi Hapus */}
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text='Apakah anda yakin ingin menghapus berita ini?'
+ />
+
+
+ );
+ function convertToEmbedUrl(youtubeUrl: string): string {
+ try {
+ const url = new URL(youtubeUrl);
+ const videoId = url.searchParams.get("v");
+ if (!videoId) return youtubeUrl;
+
+ return `https://www.youtube.com/embed/${videoId}`;
+ } catch (err) {
+ console.error("Error converting YouTube URL to embed:", err);
+ return youtubeUrl;
+ }
+ }
+}
+
+export default DetailVideo;
diff --git a/src/app/admin/(dashboard)/desa/gallery/video/create/page.tsx b/src/app/admin/(dashboard)/desa/gallery/video/create/page.tsx
new file mode 100644
index 00000000..bf48f34d
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/gallery/video/create/page.tsx
@@ -0,0 +1,100 @@
+'use client'
+import CreateEditor from '@/app/admin/(dashboard)/_com/createEditor';
+import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery';
+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 { useState } from 'react';
+import { toast } from 'react-toastify';
+import { useProxy } from 'valtio/utils';
+import { convertYoutubeUrlToEmbed } from '../../lib/youtube-utils';
+
+
+
+function CreateVideo() {
+ const videoState = useProxy(stateGallery.video)
+ const router = useRouter();
+ const [link, setLink] = useState("");
+ const embedLink = convertYoutubeUrlToEmbed(link);
+
+ const resetForm = () => {
+ videoState.create.form = {
+ name: "",
+ deskripsi: "",
+ linkVideo: "",
+ };
+ };
+ const handleSubmit = async () => {
+ if (!embedLink) {
+ toast.error("Link YouTube tidak valid. Pastikan formatnya benar.");
+ return;
+ }
+
+ videoState.create.form.linkVideo = embedLink; // pastikan diset di sini juga (jaga-jaga)
+ await videoState.create.create();
+ resetForm();
+ router.push("/admin/desa/gallery/video");
+ };
+
+
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Video
+ Judul Video}
+ placeholder='Masukkan judul video'
+ value={videoState.create.form.name}
+ onChange={(val) => {
+ videoState.create.form.name = val.target.value;
+ }}
+ />
+
+
+ {
+ setLink(e.currentTarget.value);
+ }}
+ required
+ />
+
+ {embedLink && (
+
+ )}
+
+
+
+ Deskripsi Video
+ {
+ videoState.create.form.deskripsi = val;
+ }}
+ />
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateVideo;
diff --git a/src/app/admin/(dashboard)/desa/gallery/video/page.tsx b/src/app/admin/(dashboard)/desa/gallery/video/page.tsx
new file mode 100644
index 00000000..f0cea1d9
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/gallery/video/page.tsx
@@ -0,0 +1,67 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Skeleton, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import JudulListTab from '../../../_com/jusulListTab';
+import { useProxy } from 'valtio/utils';
+import stateGallery from '../../../_state/desa/gallery';
+import { useShallowEffect } from '@mantine/hooks';
+
+function Video() {
+ const videoState = useProxy(stateGallery.video)
+ const router = useRouter();
+
+ useShallowEffect(() => {
+ videoState.findMany.load()
+ }, [])
+
+ if (!videoState.findMany.data) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+ }
+ />
+
+
+
+ Judul Video
+ Tanggal Video
+ Deskripsi Video
+ Detail
+
+
+
+ {videoState.findMany.data?.map((item) => (
+
+ {item.name}
+ {new Date(item.createdAt).toDateString()}
+
+
+
+
+ router.push(`/admin/desa/gallery/video/${item.id}`)}>
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
+
+export default Video;
diff --git a/src/app/admin/(dashboard)/desa/layanan/layout.tsx b/src/app/admin/(dashboard)/desa/layanan/layout.tsx
new file mode 100644
index 00000000..7113ca7e
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/layout.tsx
@@ -0,0 +1,10 @@
+'use client'
+import LayoutTabsLayanan from "../_com/layoutTabLayanan";
+
+export default function Layout({children} : {children: React.ReactNode}) {
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/desa/layanan/page.tsx b/src/app/admin/(dashboard)/desa/layanan/page.tsx
deleted file mode 100644
index 83f6a69b..00000000
--- a/src/app/admin/(dashboard)/desa/layanan/page.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
-import SuratKeterangan from './ui/surat_keterangan/page';
-import PerizinanUsaha from './ui/perizinan_usaha/page';
-import TelunjukSaktiDesa from './ui/telunjuk_sakti_desa/page';
-import PendudukNonPermanent from './ui/penduduk_non_permanent/page';
-
-function Page() {
- return (
-
-
- Layanan
-
-
-
- Pelayanan Surat Keterangan
-
-
- Pelayanan Perizinan Berusaha
-
-
- Pelayanan Telunjuk Sakti Desa
-
-
- Pelayanan Penduduk Non-Permanent
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default Page;
-
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/edit/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/edit/page.tsx
new file mode 100644
index 00000000..80841411
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/edit/page.tsx
@@ -0,0 +1,103 @@
+'use client'
+/* eslint-disable react-hooks/exhaustive-deps */
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
+import colors from '@/con/colors';
+import { Box, Button, Group, 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 EditPelayananPendudukNonPermanent() {
+ const router = useRouter();
+ const params = useParams()
+ const statePendudukNonPermanent = useProxy(stateLayananDesa.pelayananPendudukNonPermanen)
+ const [formData, setFormData] = useState({
+ name: statePendudukNonPermanent.findById.data?.name || '',
+ deskripsi: statePendudukNonPermanent.findById.data?.deskripsi || '',
+ })
+
+ useEffect(() => {
+ const loadPelayananPerizinan = async () => {
+ const id = params?.id as string;
+ if (!id) return;
+ try {
+ const data = await statePendudukNonPermanent.update.load(id);
+ if (data) {
+ setFormData({
+ name: data.name || '',
+ deskripsi: data.deskripsi || '',
+ });
+ }
+ } catch (error) {
+ console.error("Error loading pelayanan perizinan berusaha:", error);
+ toast.error("Gagal memuat data pelayanan perizinan berusaha");
+ }
+ };
+ loadPelayananPerizinan();
+ }, [params?.id]);
+
+ const handleSubmit = async () => {
+ if (statePendudukNonPermanent.findById.data) {
+ statePendudukNonPermanent.findById.data.name = formData.name;
+ statePendudukNonPermanent.findById.data.deskripsi = formData.deskripsi;
+ statePendudukNonPermanent.update.update(statePendudukNonPermanent.findById.data)
+ }
+ router.push('/admin/desa/layanan/pelayanan_penduduk_non_permanent')
+ }
+ return (
+
+
+
+ router.back()}
+ >
+
+
+
+
+
+
+ Edit Pelayanan Penduduk Non Permanent
+ Judul
+ {
+ setFormData({
+ ...formData,
+ name: val.target.value,
+ })
+ }}
+ />
+ Deskripsi
+ {
+ setFormData({
+ ...formData,
+ deskripsi: val,
+ })
+ }}
+ />
+
+
+
+ Submit
+
+
+
+
+
+
+
+ );
+}
+
+export default EditPelayananPendudukNonPermanent;
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/page.tsx
new file mode 100644
index 00000000..3d9065f3
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/page.tsx
@@ -0,0 +1,51 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Grid, GridCol, Paper, Skeleton, Stack, Text } 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 stateLayananDesa from '../../../_state/desa/layananDesa';
+
+function SuratKeterangan() {
+ const router = useRouter()
+ const pelayananPendudukNonPermanen = useProxy(stateLayananDesa.pelayananPendudukNonPermanen)
+
+ useShallowEffect(() => {
+ pelayananPendudukNonPermanen.findById.load('1')
+ }, [])
+
+ if (!pelayananPendudukNonPermanen.findById.data) {
+ return (
+
+
+
+ )
+ }
+ return (
+
+
+
+
+
+
+
+ Preview Pelayanan Perizinan Berusaha
+
+
+ router.push('/admin/desa/layanan/pelayanan_penduduk_non_permanent/edit')}>
+
+
+
+
+
+
+ {pelayananPendudukNonPermanen.findById.data.name}
+
+
+
+
+ );
+}
+
+export default SuratKeterangan;
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/edit/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/edit/page.tsx
new file mode 100644
index 00000000..777b65ef
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/edit/page.tsx
@@ -0,0 +1,116 @@
+'use client'
+/* eslint-disable react-hooks/exhaustive-deps */
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
+import colors from '@/con/colors';
+import { Box, Button, Group, 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 EditPelayananPerizinanBerusaha() {
+ const router = useRouter();
+ const params = useParams()
+ const statePerizinanBerusaha = useProxy(stateLayananDesa.pelayananPerizinanBerusaha)
+ const [formData, setFormData] = useState({
+ name: statePerizinanBerusaha.findById.data?.name || '',
+ deskripsi: statePerizinanBerusaha.findById.data?.deskripsi || '',
+ link: statePerizinanBerusaha.findById.data?.link || '',
+ })
+
+ useEffect(() => {
+ const loadPelayananPerizinan = async () => {
+ const id = params?.id as string;
+ if (!id) return;
+ try {
+ const data = await statePerizinanBerusaha.update.load(id);
+ if (data) {
+ setFormData({
+ name: data.name || '',
+ deskripsi: data.deskripsi || '',
+ link: data.link || '',
+ });
+ }
+ } catch (error) {
+ console.error("Error loading pelayanan perizinan berusaha:", error);
+ toast.error("Gagal memuat data pelayanan perizinan berusaha");
+ }
+ };
+ loadPelayananPerizinan();
+ }, [params?.id]);
+
+ const handleSubmit = async () => {
+ if (statePerizinanBerusaha.findById.data) {
+ statePerizinanBerusaha.findById.data.name = formData.name;
+ statePerizinanBerusaha.findById.data.deskripsi = formData.deskripsi;
+ statePerizinanBerusaha.findById.data.link = formData.link;
+ statePerizinanBerusaha.update.update(statePerizinanBerusaha.findById.data)
+ }
+ router.push('/admin/desa/layanan/pelayanan_perizinan_berusaha')
+ }
+ return (
+
+
+
+ router.back()}
+ >
+
+
+
+
+
+
+ Edit Pelayanan Perizinan Berusaha
+ Judul
+ {
+ setFormData({
+ ...formData,
+ name: val.target.value,
+ })
+ }}
+ />
+ Link
+ {
+ setFormData({
+ ...formData,
+ link: val.target.value,
+ })
+ }}
+ />
+ Deskripsi
+ {
+ setFormData({
+ ...formData,
+ deskripsi: val,
+ })
+ }}
+ />
+
+
+
+ Submit
+
+
+
+
+
+
+
+ );
+}
+
+export default EditPelayananPerizinanBerusaha;
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/page.tsx
new file mode 100644
index 00000000..21ad4f68
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/page.tsx
@@ -0,0 +1,97 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Grid, GridCol, Group, Paper, Skeleton, Stack, Stepper, StepperCompleted, StepperStep, Text } from '@mantine/core';
+import { IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useState } from 'react';
+import stateLayananDesa from '../../../_state/desa/layananDesa';
+import { useProxy } from 'valtio/utils';
+import { useShallowEffect } from '@mantine/hooks';
+
+function PerizinanBerusaha() {
+ const router = useRouter()
+ const pelayananPerizinanBerusaha = useProxy(stateLayananDesa.pelayananPerizinanBerusaha)
+ const [active, setActive] = useState(1);
+ const nextStep = () => setActive((current) => (current < 6 ? current + 1 : current));
+ const prevStep = () => setActive((current) => (current > 0 ? current - 1 : current));
+ useShallowEffect(() => {
+ pelayananPerizinanBerusaha.findById.load('1')
+ }, [])
+
+ if(!pelayananPerizinanBerusaha.findById.data) {
+ return (
+
+
+
+ )
+ }
+ return (
+
+
+
+
+
+
+
+ Preview Pelayanan Perizinan Berusaha
+
+
+ router.push('/admin/desa/layanan/pelayanan_perizinan_berusaha/edit')}>
+
+
+
+
+
+
+ {pelayananPerizinanBerusaha.findById.data.name}
+
+ Proses pendaftaran NIB melalui OSS mencakup beberapa langkah umum, seperti:
+
+
+
+ Pendaftaran akun pada portal OSS
+
+
+ Mengisi informasi perusahaan, termasuk data pemegang saham, alamat perusahaan, dan lainnya
+
+
+ Memilih KBLI dengan jenis usaha yang akan didaftarkan
+
+
+ Mengunggah dokumen-dokumen yang diperlukan, seperti akta pendirian perusahaan, surat izin usaha, dan dokumen lainnya sesuai dengan ketentuan yang berlaku
+
+
+ Proses verifikasi dan persetujuan oleh instansi terkait
+
+
+ Jika proses sebelumnya berhasil, perusahaan akan menerima NIB sebagai identitas resmi usaha anda
+
+
+ Selesai, anda telah mengikuti proses pendaftaran NIB melalui OSS
+
+
+
+
+ Back
+ Next step
+
+ Penting untuk diingat bahwa prosedur dan persyaratan dapat berubah
+ seiring waktu. Untuk informasi yang lebih akurat dan terkini, saya sarankan untuk mengunjungi situs
+ resmi OSS {pelayananPerizinanBerusaha.findById.data.link} atau menghubungi instansi terkait di pemerintah Indonesia yang bertanggung jawab atas urusan perizinan usaha.
+
+
+
+
+ );
+}
+
+export default PerizinanBerusaha;
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/[id]/edit/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/[id]/edit/page.tsx
new file mode 100644
index 00000000..fb2c0ad3
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/[id]/edit/page.tsx
@@ -0,0 +1,132 @@
+'use client'
+/* eslint-disable react-hooks/exhaustive-deps */
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
+import colors from '@/con/colors';
+import ApiFetch from '@/lib/api-fetch';
+import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } 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 EditSuratKeterangan() {
+ const router = useRouter()
+ const params = useParams()
+ const stateSurat = useProxy(stateLayananDesa.suratKeterangan)
+ const [previewImage, setPreviewImage] = useState(null);
+ const [file, setFile] = useState(null);
+ const [formData, setFormData] = useState({
+ name: stateSurat.edit.form.name,
+ deskripsi: stateSurat.edit.form.deskripsi,
+ imageId: stateSurat.edit.form.imageId,
+ })
+
+ useEffect(() => {
+ const loadSurat = async () => {
+ const id = params?.id as string;
+ if (!id) return;
+ try {
+ const data = await stateSurat.edit.load(id);
+ if (data) {
+ setFormData({
+ name: data.name,
+ deskripsi: data.deskripsi,
+ imageId: data.imageId,
+ });
+ if (data?.image?.link) {
+ setPreviewImage(data.image.link);
+ }
+ }
+ } catch (error) {
+ console.error("Error loading surat:", error);
+ toast.error("Gagal memuat data surat");
+ }
+ };
+ loadSurat();
+ }, [params?.id]);
+
+ const handleSubmit = async () => {
+ try {
+ stateSurat.edit.form = {
+ ...stateSurat.edit.form,
+ name: formData.name,
+ deskripsi: formData.deskripsi,
+ 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");
+ }
+
+ stateSurat.edit.form.imageId = uploaded.id;
+ }
+
+ await stateSurat.edit.update()
+ toast.success("Surat berhasil diperbarui!")
+ router.push("/admin/desa/layanan/pelayanan_surat_keterangan")
+ } catch (error) {
+ console.error("Error updating surat:", error);
+ toast.error("Terjadi kesalahan saat memperbarui surat");
+ }
+ }
+
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Edit Surat Keterangan
+ {
+ setFormData({ ...formData, name: val.target.value });
+ }}
+ label={Nama Surat Keterangan }
+ placeholder="masukkan nama surat keterangan"
+ />
+
+ Konten
+ {
+ setFormData({ ...formData, deskripsi: htmlContent });
+ }}
+ />
+
+ Upload Gambar Konten}
+ value={file}
+ onChange={async (e) => {
+ if (!e) return;
+ setFile(e);
+ const base64 = await e.arrayBuffer().then((buf) =>
+ "data:image/png;base64," + Buffer.from(buf).toString("base64")
+ );
+ setPreviewImage(base64);
+ }}
+ />
+ {previewImage ? (
+
+ ) : (
+
+
+
+ )}
+ Simpan
+
+
+
+ );
+}
+
+export default EditSuratKeterangan;
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/[id]/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/[id]/page.tsx
new file mode 100644
index 00000000..70404c80
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/[id]/page.tsx
@@ -0,0 +1,109 @@
+'use client'
+import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
+import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
+import colors from '@/con/colors';
+import { Box, Button, Flex, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useParams, useRouter } from 'next/navigation';
+import { useState } from 'react';
+import { useProxy } from 'valtio/utils';
+
+function DetailSuratKeterangan() {
+ const suratKeteranganState = useProxy(stateLayananDesa.suratKeterangan)
+ const [modalHapus, setModalHapus] = useState(false)
+ const [selectedId, setSelectedId] = useState(null)
+ const params = useParams()
+ const router = useRouter()
+
+ useShallowEffect(() => {
+ suratKeteranganState.findUnique.load(params?.id as string)
+ }, [])
+
+ const handleHapus = () => {
+ if (selectedId) {
+ suratKeteranganState.delete.byId(selectedId)
+ setModalHapus(false)
+ setSelectedId(null)
+ router.push("/admin/desa/layanan/pelayanan_surat_keterangan")
+ }
+ }
+
+ if (!suratKeteranganState.findUnique.data) {
+ return (
+
+ {Array.from({ length: 10 }).map((_, k) => (
+
+ ))}
+
+ )
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Surat Keterangan
+ {suratKeteranganState.findUnique.data ? (
+
+
+
+ Nama
+ {suratKeteranganState.findUnique.data?.name}
+
+
+ Deskripsi
+
+
+
+ Gambar
+
+
+
+ {
+ if (suratKeteranganState.findUnique.data) {
+ setSelectedId(suratKeteranganState.findUnique.data.id);
+ setModalHapus(true);
+ }
+ }}
+ disabled={suratKeteranganState.delete.loading || !suratKeteranganState.findUnique.data}
+ color={"red"}
+ >
+
+
+ {
+ if (suratKeteranganState.findUnique.data) {
+ router.push(`/admin/desa/layanan/pelayanan_surat_keterangan/${suratKeteranganState.findUnique.data.id}/edit`);
+ }
+ }}
+ disabled={!suratKeteranganState.findUnique.data}
+ color={"green"}
+ >
+
+
+
+
+
+ ) : null}
+
+
+
+ {/* Modal Konfirmasi Hapus */}
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text='Apakah anda yakin ingin menghapus berita ini?'
+ />
+
+ );
+}
+
+export default DetailSuratKeterangan;
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/create/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/create/page.tsx
new file mode 100644
index 00000000..fa1a9c3a
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/create/page.tsx
@@ -0,0 +1,104 @@
+'use client'
+import CreateEditor from '@/app/admin/(dashboard)/_com/createEditor';
+import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
+import colors from '@/con/colors';
+import ApiFetch from '@/lib/api-fetch';
+import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useState } from 'react';
+import { toast } from 'react-toastify';
+import { useProxy } from 'valtio/utils';
+
+function CreateSuratKeterangan() {
+ const stateSurat = useProxy(stateLayananDesa.suratKeterangan)
+ const [previewImage, setPreviewImage] = useState(null);
+ const [file, setFile] = useState(null);
+ const router = useRouter()
+
+ const resetForm = () => {
+ stateSurat.create.form = {
+ name: "",
+ deskripsi: "",
+ imageId: "",
+ }
+ setPreviewImage(null)
+ setFile(null)
+ }
+
+ const handleSubmit = async () => {
+ if (!file) {
+ return toast.error("Silahkan pilih file gambar terlebih dahulu")
+ }
+
+ const res = await ApiFetch.api.fileStorage.create.post({
+ file: file,
+ name: file.name
+ })
+
+ const uploaded = res.data?.data
+ if (!uploaded?.id) {
+ return toast.error("Gagal upload gambar")
+ }
+
+ stateSurat.create.form.imageId = uploaded.id
+
+ await stateSurat.create.create()
+ resetForm()
+ router.push("/admin/desa/layanan/pelayanan_surat_keterangan")
+
+ }
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Create Surat Keterangan
+ {
+ stateSurat.create.form.name = val.target.value;
+ }}
+ label={Nama Surat Keterangan }
+ placeholder="masukkan nama surat keterangan"
+ />
+
+ Konten
+ {
+ stateSurat.create.form.deskripsi = htmlContent;
+ }}
+ />
+
+ Upload Gambar Konten}
+ value={file}
+ onChange={async (e) => {
+ if (!e) return;
+ setFile(e);
+ const base64 = await e.arrayBuffer().then((buf) =>
+ "data:image/png;base64," + Buffer.from(buf).toString("base64")
+ );
+ setPreviewImage(base64);
+ }}
+ />
+ {previewImage ? (
+
+ ) : (
+
+
+
+ )}
+ Simpan
+
+
+
+ );
+}
+
+export default CreateSuratKeterangan;
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/page.tsx
new file mode 100644
index 00000000..9257c5d1
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/page.tsx
@@ -0,0 +1,71 @@
+'use client'
+import JudulListTab from '@/app/admin/(dashboard)/_com/jusulListTab';
+import colors from '@/con/colors';
+import { Box, Button, Image, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import { useProxy } from 'valtio/utils';
+import stateLayananDesa from '../../../_state/desa/layananDesa';
+import { useShallowEffect } from '@mantine/hooks';
+import { useRouter } from 'next/navigation';
+
+function SuratKeterangan() {
+ const suratKeteranganState = useProxy(stateLayananDesa.suratKeterangan)
+ const router = useRouter()
+
+ useShallowEffect(() => {
+ suratKeteranganState.findMany.load()
+ }, [])
+
+ if (!suratKeteranganState.findMany.data) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+ }
+ />
+
+
+
+ Nama
+ Deskripsi
+ Image
+ Detail
+
+
+
+ {suratKeteranganState.findMany.data?.map((item) => (
+
+ {item.name}
+
+
+
+
+
+
+
+
+ router.push(`/admin/desa/layanan/pelayanan_surat_keterangan/${item.id}`)}>
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
+
+export default SuratKeterangan;
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/[id]/edit/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/[id]/edit/page.tsx
new file mode 100644
index 00000000..a8502e56
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/[id]/edit/page.tsx
@@ -0,0 +1,103 @@
+'use client'
+/* eslint-disable react-hooks/exhaustive-deps */
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
+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 EditPelayananTelunjukSakti() {
+ const stateTelunjukDesa = useProxy(stateLayananDesa.pelayananTelunjukSaktiDesa)
+ const router = useRouter()
+ const params = useParams()
+ const [formData, setFormData] = useState({
+ name: stateTelunjukDesa.edit.form.name,
+ deskripsi: stateTelunjukDesa.edit.form.deskripsi,
+ link: stateTelunjukDesa.edit.form.link,
+ })
+
+ useEffect(() => {
+ const loadPelayananTelunjukSakti = async () => {
+ const id = params?.id as string;
+ if (!id) return;
+ try {
+ const data = await stateTelunjukDesa.edit.load(id);
+ if (data) {
+ setFormData({
+ name: data.name,
+ deskripsi: data.deskripsi,
+ link: data.link,
+ });
+ }
+ } catch (error) {
+ console.error("Error loading pelayanan telunjuk sakti:", error);
+ toast.error("Gagal memuat data pelayanan telunjuk sakti");
+ }
+ };
+ loadPelayananTelunjukSakti();
+ }, [params?.id]);
+
+ const handleSubmit = async () => {
+ try {
+ stateTelunjukDesa.edit.form = {
+ ...stateTelunjukDesa.edit.form,
+ name: formData.name,
+ deskripsi: formData.deskripsi,
+ link: formData.link,
+ }
+ await stateTelunjukDesa.edit.update()
+ toast.success("Pelayanan telunjuk sakti berhasil diperbarui!")
+ router.push("/admin/desa/layanan/pelayanan_telunjuk_sakti_desa")
+ } catch (error) {
+ console.error("Error updating pelayanan telunjuk sakti:", error);
+ toast.error("Terjadi kesalahan saat memperbarui pelayanan telunjuk sakti");
+ }
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Edit Surat Keterangan
+ {
+ setFormData({ ...formData, name: val.target.value });
+ }}
+ label={Nama Surat Keterangan }
+ placeholder="masukkan nama surat keterangan"
+ />
+ {
+ setFormData({ ...formData, link: val.target.value });
+ }}
+ label={Link }
+ placeholder="masukkan link"
+ />
+
+ Konten
+ {
+ setFormData({ ...formData, deskripsi: htmlContent });
+ }}
+ />
+
+ Simpan
+
+
+
+ );
+}
+
+export default EditPelayananTelunjukSakti;
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/[id]/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/[id]/page.tsx
new file mode 100644
index 00000000..c13d2fc5
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/[id]/page.tsx
@@ -0,0 +1,109 @@
+'use client'
+import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
+import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Skeleton, Stack, Text } from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useParams, useRouter } from 'next/navigation';
+import { useState } from 'react';
+import { useProxy } from 'valtio/utils';
+
+function DetailPelayananTelunjukSakti() {
+ const telunjukSaktiState = useProxy(stateLayananDesa.pelayananTelunjukSaktiDesa)
+ const [modalHapus, setModalHapus] = useState(false)
+ const [selectedId, setSelectedId] = useState(null)
+ const params = useParams()
+ const router = useRouter()
+
+ useShallowEffect(() => {
+ telunjukSaktiState.findUnique.load(params?.id as string)
+ }, [])
+
+ const handleHapus = () => {
+ if (selectedId) {
+ telunjukSaktiState.delete.byId(selectedId)
+ setModalHapus(false)
+ setSelectedId(null)
+ router.push("/admin/desa/layanan/pelayanan_telunjuk_sakti_desa")
+ }
+ }
+
+ if (!telunjukSaktiState.findUnique.data) {
+ return (
+
+ {Array.from({ length: 10 }).map((_, k) => (
+
+ ))}
+
+ )
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Pelayanan Telunjuk Sakti Desa
+ {telunjukSaktiState.findUnique.data ? (
+
+
+
+ Nama
+ {telunjukSaktiState.findUnique.data?.name}
+
+
+ Link
+ {telunjukSaktiState.findUnique.data?.link}
+
+
+ Deskripsi
+
+
+
+ {
+ if (telunjukSaktiState.findUnique.data) {
+ setSelectedId(telunjukSaktiState.findUnique.data.id);
+ setModalHapus(true);
+ }
+ }}
+ disabled={telunjukSaktiState.delete.loading || !telunjukSaktiState.findUnique.data}
+ color={"red"}
+ >
+
+
+ {
+ if (telunjukSaktiState.findUnique.data) {
+ router.push(`/admin/desa/layanan/pelayanan_telunjuk_sakti_desa/${telunjukSaktiState.findUnique.data.id}/edit`);
+ }
+ }}
+ disabled={!telunjukSaktiState.findUnique.data}
+ color={"green"}
+ >
+
+
+
+
+
+ ) : null}
+
+
+
+ {/* Modal Konfirmasi Hapus */}
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text='Apakah anda yakin ingin menghapus berita ini?'
+ />
+
+ );
+}
+
+export default DetailPelayananTelunjukSakti;
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/create/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/create/page.tsx
new file mode 100644
index 00000000..746d1e5f
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/create/page.tsx
@@ -0,0 +1,70 @@
+'use client'
+import CreateEditor from '@/app/admin/(dashboard)/_com/createEditor';
+import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
+import colors from '@/con/colors';
+import { Box, Button, 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 CreatePelayananTelunjukDesa() {
+ const stateTelunjukDesa = useProxy(stateLayananDesa.pelayananTelunjukSaktiDesa)
+ const router = useRouter()
+
+ const resetForm = () => {
+ stateTelunjukDesa.create.form = {
+ name: "",
+ deskripsi: "",
+ link: "",
+ }
+ }
+
+ const handleSubmit = async () => {
+ await stateTelunjukDesa.create.create()
+ resetForm()
+ router.push("/admin/desa/layanan/pelayanan_telunjuk_sakti_desa")
+
+ }
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Create Pelayanan Telunjuk Sakti Desa
+ {
+ stateTelunjukDesa.create.form.name = val.target.value;
+ }}
+ label={Nama Pelayanan Telunjuk Sakti Desa }
+ placeholder="masukkan nama pelayanan telunjuk sakti desa"
+ />
+ {
+ stateTelunjukDesa.create.form.link = val.target.value;
+ }}
+ label={Link }
+ placeholder="masukkan link"
+ />
+
+ Konten
+ {
+ stateTelunjukDesa.create.form.deskripsi = htmlContent;
+ }}
+ />
+
+ Simpan
+
+
+
+ );
+}
+
+export default CreatePelayananTelunjukDesa;
diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/page.tsx
new file mode 100644
index 00000000..40e7e102
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/page.tsx
@@ -0,0 +1,65 @@
+'use client'
+import JudulListTab from '@/app/admin/(dashboard)/_com/jusulListTab';
+import colors from '@/con/colors';
+import { Box, Button, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import { useProxy } from 'valtio/utils';
+import stateLayananDesa from '../../../_state/desa/layananDesa';
+import { useShallowEffect } from '@mantine/hooks';
+import { useRouter } from 'next/navigation';
+
+function PelayananTelunjukSakti() {
+ const telunjukSaktiState = useProxy(stateLayananDesa.pelayananTelunjukSaktiDesa)
+ const router = useRouter()
+
+ useShallowEffect(() => {
+ telunjukSaktiState.findMany.load()
+ }, [])
+
+ if (!telunjukSaktiState.findMany.data) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+ }
+ />
+
+
+
+ Nama
+ Deskripsi
+ Detail
+
+
+
+ {telunjukSaktiState.findMany.data?.map((item) => (
+
+ {item.name}
+
+
+
+ router.push(`/admin/desa/layanan/pelayanan_telunjuk_sakti_desa/${item.id}`)}>
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
+
+export default PelayananTelunjukSakti;
diff --git a/src/app/admin/(dashboard)/desa/layanan/ui/penduduk_non_permanent/listPage.tsx b/src/app/admin/(dashboard)/desa/layanan/ui/penduduk_non_permanent/listPage.tsx
deleted file mode 100644
index 93d7c0dc..00000000
--- a/src/app/admin/(dashboard)/desa/layanan/ui/penduduk_non_permanent/listPage.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Title } from '@mantine/core';
-import React from 'react';
-
-function ListPendudukNonPermanent() {
- return (
-
-
-
- List Penduduk Non-Permanent
-
-
-
- );
-}
-
-export default ListPendudukNonPermanent;
diff --git a/src/app/admin/(dashboard)/desa/layanan/ui/penduduk_non_permanent/page.tsx b/src/app/admin/(dashboard)/desa/layanan/ui/penduduk_non_permanent/page.tsx
deleted file mode 100644
index a3585e50..00000000
--- a/src/app/admin/(dashboard)/desa/layanan/ui/penduduk_non_permanent/page.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import colors from '@/con/colors';
-import { Box, SimpleGrid, Paper, Stack, Title, Group, Button, Text } from '@mantine/core';
-import React from 'react';
-import { DesaEditor } from '../../../_com/desaEditor';
-import ListPendudukNonPermanent from './listPage';
-
-function PendudukNonPermanent() {
- return (
-
-
-
-
-
- Penduduk Non-Permanent
- Deskripsi Penduduk Non-Permanent
-
-
-
- Submit
-
-
-
-
-
-
-
-
- );
-}
-
-export default PendudukNonPermanent;
-
diff --git a/src/app/admin/(dashboard)/desa/layanan/ui/perizinan_usaha/listPage.tsx b/src/app/admin/(dashboard)/desa/layanan/ui/perizinan_usaha/listPage.tsx
deleted file mode 100644
index 440f1a43..00000000
--- a/src/app/admin/(dashboard)/desa/layanan/ui/perizinan_usaha/listPage.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Title } from '@mantine/core';
-import React from 'react';
-
-function ListPerizinanUsaha() {
- return (
-
-
-
- List Perizinan Usaha
-
-
-
- );
-}
-
-export default ListPerizinanUsaha;
diff --git a/src/app/admin/(dashboard)/desa/layanan/ui/perizinan_usaha/page.tsx b/src/app/admin/(dashboard)/desa/layanan/ui/perizinan_usaha/page.tsx
deleted file mode 100644
index aa85a19f..00000000
--- a/src/app/admin/(dashboard)/desa/layanan/ui/perizinan_usaha/page.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
-import React from 'react';
-import ListPerizinanUsaha from './listPage';
-import { DesaEditor } from '../../../_com/desaEditor';
-
-function PerizinanUsaha() {
- return (
-
-
-
-
-
-
- Pelayanan Perizinan Usaha
-
- Deskripsi Perizinan Usaha
-
-
-
-
- Submit
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default PerizinanUsaha;
diff --git a/src/app/admin/(dashboard)/desa/layanan/ui/surat_keterangan/listPage.tsx b/src/app/admin/(dashboard)/desa/layanan/ui/surat_keterangan/listPage.tsx
deleted file mode 100644
index bd4dd422..00000000
--- a/src/app/admin/(dashboard)/desa/layanan/ui/surat_keterangan/listPage.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Title } from '@mantine/core';
-import React from 'react';
-
-function ListSuratKeterangan() {
- return (
-
-
-
- List Surat Keterangan
-
-
-
- );
-}
-
-export default ListSuratKeterangan;
diff --git a/src/app/admin/(dashboard)/desa/layanan/ui/surat_keterangan/page.tsx b/src/app/admin/(dashboard)/desa/layanan/ui/surat_keterangan/page.tsx
deleted file mode 100644
index 5ac1070e..00000000
--- a/src/app/admin/(dashboard)/desa/layanan/ui/surat_keterangan/page.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import colors from '@/con/colors';
-import { Box, SimpleGrid, Paper, Stack, Title, Button, Group, TextInput, Text, Center, Flex } from '@mantine/core';
-import { IconUpload } from '@tabler/icons-react';
-import React from 'react';
-import ListSuratKeterangan from './listPage';
-
-function SuratKeterangan() {
- return (
-
-
-
-
-
-
- Pelayanan Surat Keterangan
- Nama Surat Keterangan}
- placeholder='masukkan nama surat keterangan'
- />
- Upload Gambar Surat Keterangan
-
-
-
-
-
-
- *
- Upload foto untuk konten surat keterangan
-
-
-
- Submit
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default SuratKeterangan;
diff --git a/src/app/admin/(dashboard)/desa/layanan/ui/telunjuk_sakti_desa/listPage.tsx b/src/app/admin/(dashboard)/desa/layanan/ui/telunjuk_sakti_desa/listPage.tsx
deleted file mode 100644
index 42f8d68a..00000000
--- a/src/app/admin/(dashboard)/desa/layanan/ui/telunjuk_sakti_desa/listPage.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Title } from '@mantine/core';
-import React from 'react';
-
-function ListTelunjukSaktiDesa() {
- return (
-
-
-
- List Telunjuk Sakti Desa
-
-
-
- );
-}
-
-export default ListTelunjukSaktiDesa;
diff --git a/src/app/admin/(dashboard)/desa/layanan/ui/telunjuk_sakti_desa/page.tsx b/src/app/admin/(dashboard)/desa/layanan/ui/telunjuk_sakti_desa/page.tsx
deleted file mode 100644
index 60a28a7c..00000000
--- a/src/app/admin/(dashboard)/desa/layanan/ui/telunjuk_sakti_desa/page.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import colors from '@/con/colors';
-import { Box, SimpleGrid, Paper, Stack, Title, Group, Button, Text } from '@mantine/core';
-import React from 'react';
-import { DesaEditor } from '../../../_com/desaEditor';
-import ListTelunjukSaktiDesa from './listPage';
-
-function TelunjukSaktiDesa() {
- return (
-
-
-
-
-
- Telunjuk Sakti Desa
-
- Deskripsi Telunjuk Sakti Desa
-
-
-
-
- Submit
-
-
-
-
-
-
-
-
- );
-}
-
-export default TelunjukSaktiDesa;
diff --git a/src/app/admin/(dashboard)/desa/penghargaan/[id]/edit/page.tsx b/src/app/admin/(dashboard)/desa/penghargaan/[id]/edit/page.tsx
new file mode 100644
index 00000000..761d2ee9
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/penghargaan/[id]/edit/page.tsx
@@ -0,0 +1,147 @@
+'use client'
+/* eslint-disable react-hooks/exhaustive-deps */
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import penghargaanState from '@/app/admin/(dashboard)/_state/desa/penghargaan';
+import colors from '@/con/colors';
+import ApiFetch from '@/lib/api-fetch';
+import { Box, Button, Paper, Stack, Title, TextInput, FileInput, Center, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useParams, useRouter } from 'next/navigation';
+import React, { useEffect, useState } from 'react';
+import { toast } from 'react-toastify';
+import { useProxy } from 'valtio/utils';
+
+function EditPenghargaan() {
+ const statePenghargaan = useProxy(penghargaanState)
+ const router = useRouter()
+ const params = useParams()
+ const [previewImage, setPreviewImage] = useState(null)
+ const [file, setFile] = useState(null)
+ const [formData, setFormData] = useState({
+ name: statePenghargaan.findUnique.data?.name || '',
+ juara: statePenghargaan.findUnique.data?.juara || '',
+ deskripsi: statePenghargaan.findUnique.data?.deskripsi || '',
+ imageId: statePenghargaan.findUnique.data?.imageId || '',
+ })
+
+ useEffect(() => {
+ const loadPenghargaan = async () => {
+ const id = params?.id as string;
+ if (!id) return;
+
+ try {
+ const data = await statePenghargaan.edit.load(id);
+ if (data) {
+ setFormData({
+ name: data.name || '',
+ juara: data.juara || '',
+ deskripsi: data.deskripsi || '',
+ imageId: data.imageId || '',
+ });
+
+ if (data?.image?.link) {
+ setPreviewImage(data.image.link);
+ }
+ }
+ } catch (error) {
+ console.error("Error loading penghargaan:", error);
+ toast.error("Gagal memuat data penghargaan");
+ }
+ };
+
+ loadPenghargaan();
+ }, [params?.id]);
+
+ const handleSubmit = async () => {
+ try {
+ statePenghargaan.edit.form = {
+ ...statePenghargaan.edit.form,
+ name: formData.name,
+ juara: formData.juara,
+ deskripsi: formData.deskripsi,
+ 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");
+ }
+
+ statePenghargaan.edit.form.imageId = uploaded.id;
+ }
+
+ await statePenghargaan.edit.update();
+ toast.success("Penghargaan berhasil diperbarui!");
+ router.push("/admin/desa/penghargaan");
+ } catch (error) {
+ console.error("Error updating penghargaan:", error);
+ toast.error("Terjadi kesalahan saat memperbarui penghargaan");
+ }
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Edit Penghargaan
+ setFormData({ ...formData, name: e.target.value })}
+ label={Judul }
+ placeholder="masukkan judul"
+ />
+
+ setFormData({ ...formData, juara: e.target.value })}
+ label={Juara }
+ placeholder="masukkan juara"
+ />
+ Upload Gambar Baru (Opsional)}
+ value={file}
+ onChange={async (e) => {
+ if (!e) return;
+ setFile(e);
+ const base64 = await e.arrayBuffer().then((buf) =>
+ "data:image/png;base64," + Buffer.from(buf).toString("base64")
+ );
+ setPreviewImage(base64);
+ }}
+ />
+
+ {previewImage ? (
+
+ ) : (
+
+
+
+ )}
+
+
+ Deskripsi
+ {
+ setFormData((prev) => ({ ...prev, deskripsi: htmlContent }));
+ statePenghargaan.edit.form.deskripsi = htmlContent;
+ }}
+ />
+
+
+ Edit Penghargaan
+
+
+
+ );
+}
+
+export default EditPenghargaan;
diff --git a/src/app/admin/(dashboard)/desa/penghargaan/[id]/page.tsx b/src/app/admin/(dashboard)/desa/penghargaan/[id]/page.tsx
new file mode 100644
index 00000000..4b094730
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/penghargaan/[id]/page.tsx
@@ -0,0 +1,111 @@
+'use client'
+import React, { useState } from 'react';
+import penghargaanState from '../../../_state/desa/penghargaan';
+import { useProxy } from 'valtio/utils';
+import { useParams, useRouter } from 'next/navigation';
+import { useShallowEffect } from '@mantine/hooks';
+import { Box, Button, Flex, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
+import colors from '@/con/colors';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailPenghargaan() {
+ const statePenghargaan = useProxy(penghargaanState)
+ const [modalHapus, setModalHapus] = useState(false);
+ const [selectedId, setSelectedId] = useState(null);
+ const router = useRouter()
+ const params = useParams()
+
+ useShallowEffect(() => {
+ statePenghargaan.findUnique.load(params?.id as string)
+ }, [])
+
+ const handleHapus = () => {
+ if (selectedId) {
+ statePenghargaan.delete.byId(selectedId)
+ setModalHapus(false)
+ setSelectedId(null)
+ router.push("/admin/desa/penghargaan")
+ }
+ }
+
+ if (!statePenghargaan.findUnique.data) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Penghargaan
+ {statePenghargaan.findUnique.data ? (
+
+
+
+ Judul
+ {statePenghargaan.findUnique.data?.name}
+
+
+ Juara
+ {statePenghargaan.findUnique.data?.juara}
+
+
+ Deskripsi
+
+
+
+ Gambar
+
+
+
+ {
+ if (statePenghargaan.findUnique.data) {
+ setSelectedId(statePenghargaan.findUnique.data.id);
+ setModalHapus(true);
+ }
+ }}
+ disabled={statePenghargaan.delete.loading || !statePenghargaan.findUnique.data}
+ color={"red"}
+ >
+
+
+ {
+ if (statePenghargaan.findUnique.data) {
+ router.push(`/admin/desa/penghargaan/${statePenghargaan.findUnique.data.id}/edit`);
+ }
+ }}
+ disabled={!statePenghargaan.findUnique.data}
+ color={"green"}
+ >
+
+
+
+
+
+ ) : null}
+
+
+
+ {/* Modal Konfirmasi Hapus */}
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text='Apakah anda yakin ingin menghapus penghargaan ini?'
+ />
+
+ );
+}
+
+export default DetailPenghargaan;
diff --git a/src/app/admin/(dashboard)/desa/penghargaan/create/page.tsx b/src/app/admin/(dashboard)/desa/penghargaan/create/page.tsx
new file mode 100644
index 00000000..838aa368
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/penghargaan/create/page.tsx
@@ -0,0 +1,114 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Center, FileInput, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useState } from 'react';
+import { toast } from 'react-toastify';
+import { useProxy } from 'valtio/utils';
+import penghargaanState from '../../../_state/desa/penghargaan';
+import ApiFetch from '@/lib/api-fetch';
+import CreateEditor from '../../../_com/createEditor';
+
+
+function CreatePenghargaan() {
+ const statePenghargaan = useProxy(penghargaanState)
+ const [previewImage, setPreviewImage] = useState(null);
+ const [file, setFile] = useState(null);
+ const router = useRouter()
+
+ const resetForm = () => {
+ statePenghargaan.create.form = {
+ name: "",
+ juara: "",
+ deskripsi: "",
+ imageId: "",
+ }
+ setPreviewImage(null)
+ setFile(null)
+ }
+
+ const handleSubmit = async () => {
+ if (!file) {
+ return toast.error("Silahkan pilih file gambar terlebih dahulu")
+ }
+
+ const res = await ApiFetch.api.fileStorage.create.post({
+ file: file,
+ name: file.name
+ })
+
+ const uploaded = res.data?.data
+ if (!uploaded?.id) {
+ return toast.error("Gagal upload gambar")
+ }
+
+ statePenghargaan.create.form.imageId = uploaded.id
+
+ await statePenghargaan.create.create()
+ resetForm()
+ router.push("/admin/desa/penghargaan")
+
+ }
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Create Penghargaan
+ {
+ statePenghargaan.create.form.name = val.target.value;
+ }}
+ label={Nama Penghargaan }
+ placeholder="masukkan nama penghargaan"
+ />
+ {
+ statePenghargaan.create.form.juara = val.target.value;
+ }}
+ label={Juara }
+ placeholder="masukkan juara"
+ />
+
+ Deskripsi
+ {
+ statePenghargaan.create.form.deskripsi = htmlContent;
+ }}
+ />
+
+ Upload Gambar Konten}
+ value={file}
+ onChange={async (e) => {
+ if (!e) return;
+ setFile(e);
+ const base64 = await e.arrayBuffer().then((buf) =>
+ "data:image/png;base64," + Buffer.from(buf).toString("base64")
+ );
+ setPreviewImage(base64);
+ }}
+ />
+ {previewImage ? (
+
+ ) : (
+
+
+
+ )}
+ Simpan
+
+
+
+ );
+}
+
+export default CreatePenghargaan;
diff --git a/src/app/admin/(dashboard)/desa/penghargaan/page.tsx b/src/app/admin/(dashboard)/desa/penghargaan/page.tsx
index 40e01edb..6d839be6 100644
--- a/src/app/admin/(dashboard)/desa/penghargaan/page.tsx
+++ b/src/app/admin/(dashboard)/desa/penghargaan/page.tsx
@@ -1,34 +1,69 @@
+'use client'
+import penghargaanState from '@/app/admin/(dashboard)/_state/desa/penghargaan';
import colors from '@/con/colors';
-import { Box, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
-import React from 'react';
-import Penghargaan from './ui/penghargaan/page';
-import GambarPerhargaan from './ui/gambar_perhargaan/page';
+import { Box, Button, Image, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useProxy } from 'valtio/utils';
+import JudulListTab from '../../_com/jusulListTab';
-function Page() {
+function Penghargaan() {
+ const state = useProxy(penghargaanState)
+ const router = useRouter()
+ useShallowEffect(() => {
+ state.findMany.load()
+ }, [])
+
+ if (!state.findMany.data) {
+ return(
+
+
+
+ )
+ }
return (
-
- Penghargaan
-
-
-
- Penghargaan
-
-
- Gambar Penghargaan
-
-
-
-
-
-
-
-
-
-
-
+
+ }
+ />
+
+
+
+ Nama
+ Deskripsi
+ Image
+ Detail
+
+
+
+ {state.findMany.data?.map((item) => (
+
+ {item.name}
+
+
+
+
+
+
+
+
+ router.push(`/admin/desa/penghargaan/${item.id}`)}>
+
+
+
+
+
+ ))}
+
+
+
);
}
-export default Page;
+export default Penghargaan;
diff --git a/src/app/admin/(dashboard)/desa/penghargaan/ui/gambar_perhargaan/listPage.tsx b/src/app/admin/(dashboard)/desa/penghargaan/ui/gambar_perhargaan/listPage.tsx
deleted file mode 100644
index cfdaf4c7..00000000
--- a/src/app/admin/(dashboard)/desa/penghargaan/ui/gambar_perhargaan/listPage.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Title } from '@mantine/core';
-import React from 'react';
-
-function ListGambarPenghargaan() {
- return (
-
-
-
- List Gambar Penghargaan
-
-
-
- );
-}
-
-export default ListGambarPenghargaan;
diff --git a/src/app/admin/(dashboard)/desa/penghargaan/ui/gambar_perhargaan/page.tsx b/src/app/admin/(dashboard)/desa/penghargaan/ui/gambar_perhargaan/page.tsx
deleted file mode 100644
index 93bfcbe7..00000000
--- a/src/app/admin/(dashboard)/desa/penghargaan/ui/gambar_perhargaan/page.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, SimpleGrid, Stack, Title, Text, Group, Button, TextInput, Center } from '@mantine/core';
-import React from 'react';
-import { DesaEditor } from '../../../_com/desaEditor';
-import ListGambarPenghargaan from './listPage';
-import { IconUpload } from '@tabler/icons-react';
-
-
-function GambarPerhargaan() {
- return (
-
-
-
-
-
-
- Tambah Gambar Penghargaan
-
- Deskripsi Gambar Penghargaan
-
-
- Upload Gambar Penghargaan
-
-
-
-
-
-
-
-
- Submit
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default GambarPerhargaan;
diff --git a/src/app/admin/(dashboard)/desa/penghargaan/ui/penghargaan/listPage.tsx b/src/app/admin/(dashboard)/desa/penghargaan/ui/penghargaan/listPage.tsx
deleted file mode 100644
index d217eb80..00000000
--- a/src/app/admin/(dashboard)/desa/penghargaan/ui/penghargaan/listPage.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Title } from '@mantine/core';
-import React from 'react';
-
-function ListPenghargaan() {
- return (
-
-
-
- List Penghargaan
-
-
-
- );
-}
-
-export default ListPenghargaan;
diff --git a/src/app/admin/(dashboard)/desa/penghargaan/ui/penghargaan/page.tsx b/src/app/admin/(dashboard)/desa/penghargaan/ui/penghargaan/page.tsx
deleted file mode 100644
index ba63a677..00000000
--- a/src/app/admin/(dashboard)/desa/penghargaan/ui/penghargaan/page.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
-import React from 'react';
-import { DesaEditor } from '../../../_com/desaEditor';
-import ListPenghargaan from './listPage';
-
-function Penghargaan() {
- return (
-
-
-
-
-
-
- Penghargaan
-
- Deskripsi Penghargaan
-
-
-
-
- Submit
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default Penghargaan;
diff --git a/src/app/admin/(dashboard)/desa/pengumuman/[id]/edit/page.tsx b/src/app/admin/(dashboard)/desa/pengumuman/[id]/edit/page.tsx
new file mode 100644
index 00000000..ccbb4eb3
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/pengumuman/[id]/edit/page.tsx
@@ -0,0 +1,53 @@
+'use client'
+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 { KeamananEditor } from '@/app/admin/(dashboard)/keamanan/_com/keamananEditor';
+
+function EditPengumuman() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Pengumuman
+ Judul}
+ placeholder='Masukkan judul'
+ />
+ Deskripsi Singkat}
+ placeholder='Masukkan deskripsi singkat'
+ />
+ Tanggal}
+ placeholder='Masukkan tanggal'
+ />
+ Waktu}
+ placeholder='Masukkan waktu'
+ />
+
+ Deskripsi
+
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditPengumuman;
diff --git a/src/app/admin/(dashboard)/desa/pengumuman/[id]/page.tsx b/src/app/admin/(dashboard)/desa/pengumuman/[id]/page.tsx
new file mode 100644
index 00000000..5090a523
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/pengumuman/[id]/page.tsx
@@ -0,0 +1,110 @@
+'use client'
+
+import { Box, Button, Paper } from '@mantine/core';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+import colors from '@/con/colors';
+
+
+function DetailPengumuman() {
+ // const pengumumanState = useProxy(stateDesaPengumuman)
+ // const [modalHapus, setModalHapus] = useState(false)
+ // const [selectedId, setSelectedId] = useState(null)
+ // const params = useParams()
+ const router = useRouter()
+
+ // useShallowEffect(() => {
+ // pengumumanState.pengumuman.findUnique.load(params?.id as string)
+ // }, [])
+
+
+ // const handleHapus = () => {
+ // if (selectedId) {
+ // pengumumanState.pengumuman.delete.byId(selectedId)
+ // setModalHapus(false)
+ // setSelectedId(null)
+ // router.push("/admin/desa/pengumuman")
+ // }
+ // }
+
+ // if (!pengumumanState.pengumuman.findUnique.data) {
+ // return (
+ //
+ //
+ //
+ // )
+ // }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+ {/*
+ Detail Pengumuman
+ {pengumumanState.pengumuman.findUnique.data ? (
+
+
+
+ Kategori
+ {pengumumanState.pengumuman.findUnique.data?.CategoryPengumuman?.name}
+
+
+ Judul
+ {pengumumanState.pengumuman.findUnique.data?.judul}
+
+
+ Deskripsi
+ {pengumumanState.pengumuman.findUnique.data?.deskripsi}
+
+
+ Konten
+
+
+
+ {
+ if (pengumumanState.pengumuman.findUnique.data) {
+ setSelectedId(pengumumanState.pengumuman.findUnique.data.id);
+ setModalHapus(true);
+ }
+ }}
+ disabled={pengumumanState.pengumuman.delete.loading || !pengumumanState.pengumuman.findUnique.data}
+ color={"red"}
+ >
+
+
+ {
+ if (pengumumanState.pengumuman.findUnique.data) {
+ router.push(`/admin/desa/pengumuman/${pengumumanState.pengumuman.findUnique.data.id}/edit`);
+ }
+ }}
+ disabled={!pengumumanState.pengumuman.findUnique.data}
+ color={"green"}
+ >
+
+
+
+
+
+ ) : null}
+ */}
+
+
+ {/* Modal Konfirmasi Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text='Apakah anda yakin ingin menghapus berita ini?'
+ /> */}
+
+ );
+}
+
+export default DetailPengumuman;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/desa/pengumuman/create/page.tsx b/src/app/admin/(dashboard)/desa/pengumuman/create/page.tsx
new file mode 100644
index 00000000..3355f8de
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/pengumuman/create/page.tsx
@@ -0,0 +1,110 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Select, Stack, Text, TextInput, Title } from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import { Prisma } from '@prisma/client';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useProxy } from 'valtio/utils';
+import CreateEditor from '../../../_com/createEditor';
+import stateDesaPengumuman from '../../../_state/desa/pengumuman';
+
+function CreatePengumuman() {
+ const pengumumanState = useProxy(stateDesaPengumuman)
+ const router = useRouter();
+
+ const handleSubmit = async () => {
+ await pengumumanState.pengumuman.create.create()
+ resetForm()
+ router.push("/admin/desa/pengumuman")
+ }
+
+ const resetForm = () => {
+ pengumumanState.pengumuman.create.form = {
+ judul: "",
+ deskripsi: "",
+ content: "",
+ categoryPengumumanId: "",
+ };
+ };
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Pengumuman
+ Judul}
+ placeholder='Masukkan judul'
+ onChange={(val) => {
+ pengumumanState.pengumuman.create.form.judul = val.target.value
+ }}
+ />
+ {
+ pengumumanState.pengumuman.create.form.categoryPengumumanId = val.id;
+ }}
+ />
+ Deskripsi Singkat}
+ placeholder='Masukkan deskripsi singkat'
+ onChange={(val) => {
+ pengumumanState.pengumuman.create.form.deskripsi = val.target.value
+ }}
+ />
+
+ Deskripsi
+ {
+ pengumumanState.pengumuman.create.form.content = htmlContent;
+ }}
+ />
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+function SelectCategory({
+ onChange,
+}: {
+ onChange: (value: Prisma.CategoryPengumumanGetPayload<{ select: { name: true; id: true; } }>) => void;
+}) {
+ const categoryState = useProxy(stateDesaPengumuman.category);
+
+ useShallowEffect(() => {
+ categoryState.findMany.load();
+ }, []);
+
+ return (
+ Kategori}
+ placeholder='Pilih kategori'
+ data={categoryState.findMany.data?.map((item) => ({
+ label: item.name,
+ value: item.id,
+ }))}
+ onChange={(val) => {
+ const selected = categoryState.findMany.data?.find((item) => item.id === val);
+ if (selected) {
+ onChange(selected);
+ }
+ }}
+ searchable
+ nothingFoundMessage="Tidak ditemukan"
+ />
+ );
+}
+
+export default CreatePengumuman;
diff --git a/src/app/admin/(dashboard)/desa/pengumuman/page.tsx b/src/app/admin/(dashboard)/desa/pengumuman/page.tsx
index 22ebd3d9..ad3df221 100644
--- a/src/app/admin/(dashboard)/desa/pengumuman/page.tsx
+++ b/src/app/admin/(dashboard)/desa/pengumuman/page.tsx
@@ -1,102 +1,111 @@
'use client'
-import { Box, Group, Paper, Select, SimpleGrid, Skeleton, Stack, Text, TextInput, Title } from '@mantine/core';
-import React from 'react';
-import { useProxy } from 'valtio/utils';
-import stateDesaPengumuman from '../../_state/desa/pengumuman';
-import { useShallowEffect } from '@mantine/hooks';
-import { Prisma } from '@prisma/client';
-import { BeritaEditor } from '../berita/_com/BeritaEditor';
import colors from '@/con/colors';
+import { Box, Button, Grid, GridCol, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useProxy } from 'valtio/utils';
+import HeaderSearch from '../../_com/header';
+import stateDesaPengumuman from '../../_state/desa/pengumuman';
+import { ModalKonfirmasiHapus } from '../../_com/modalKonfirmasiHapus';
+import { useState } from 'react';
+
function Page() {
return (
- Pengumuman
-
-
-
-
+ }
+ />
+
);
}
-function PengumumanCreate() {
- const pengumumanState = useProxy(stateDesaPengumuman)
-
-
- return (
-
-
-
- {
- pengumumanState.pengumuman.create.form.categoryPengumumanId = val.id
- }} />
- {
- pengumumanState.pengumuman.create.form.judul = val.target.value
- }} label={Judul } placeholder='masukkan judul' />
- {
- pengumumanState.pengumuman.create.form.deskripsi = val.target.value
- }} label={Deskripsi } placeholder='masukkan deskripsi' />
- {
- pengumumanState.pengumuman.create.form.content = val
- pengumumanState.pengumuman.create.create()
- }} />
-
-
-
- )
-}
-
function PengumumanList() {
const pengumumanState = useProxy(stateDesaPengumuman)
+ const [modalHapus, setModalHapus] = useState(false)
+ const [selectedId, setSelectedId] = useState(null)
+
useShallowEffect(() => {
pengumumanState.pengumuman.findMany.load()
}, [])
- if (!pengumumanState.pengumuman.findMany.data) return
- {Array.from({ length: 10 }).map((v, k) => )}
-
+ const router = useRouter()
+
+ const handleHapus = () => {
+ if (selectedId) {
+ pengumumanState.pengumuman.delete.byId(selectedId)
+ setModalHapus(false)
+ setSelectedId(null)
+ }
+ }
+
+ if (!pengumumanState.pengumuman.findMany.data) {
+ return (
+
+
+
+ )
+ }
+
return (
-
- List Pengumuman
- {pengumumanState.pengumuman.findMany.data?.map((item) => (
- {item.judul}
- ))}
+
+
+
+ List Pengumuman
+
+
+ router.push("/admin/desa/pengumuman/create")} bg={colors['blue-button']}>
+
+
+
+
+
+
+
+
+ Judul
+ Kategori
+ Detail
+
+
+
+
+ {pengumumanState.pengumuman.findMany.data?.map((item) => (
+
+
+
+ {item.judul}
+
+
+ {item.CategoryPengumuman?.name}
+
+ router.push(`/admin/desa/pengumuman/detail`)}>
+
+
+
+
+ ))}
+
+
+
+
+ {/* Modal Konfirmasi Hapus */}
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text='Apakah anda yakin ingin menghapus berita ini?'
+ />
)
}
-function SelectCategory({ onChange }: {
- onChange: (value: Prisma.CategoryPengumumanGetPayload<{
- select: {
- name: true,
- id: true
- }
- }>) => void
-}) {
- const pengumumanState = useProxy(stateDesaPengumuman)
- useShallowEffect(() => {
- pengumumanState.category.findMany.load()
- }, [])
-
- if (!pengumumanState.category.findMany.data) return
- return
- {/* {JSON.stringify(pengumumanState.category.findMany.data)} */}
- Pilih Kategori} data={pengumumanState.category.findMany.data.map((item) => ({
- value: item.id,
- label: item.name
- }))} onChange={(v) => {
- const data = pengumumanState.category.findMany.data?.find((item) => item.id === v)
- if (!data) return
- onChange(data)
- }}
- />
-
-}
export default Page;
diff --git a/src/app/admin/(dashboard)/desa/profile/_lib/layoutTabsDetail.tsx b/src/app/admin/(dashboard)/desa/profile/_lib/layoutTabsDetail.tsx
new file mode 100644
index 00000000..1cd94190
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/profile/_lib/layoutTabsDetail.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 LayoutTabsDetail({ children }: { children: React.ReactNode }) {
+ const router = useRouter()
+ const pathname = usePathname()
+ const tabs = [
+ {
+ label: "Profile Desa",
+ value: "profiledesa",
+ href: "/admin/desa/profile/profile-desa"
+ },
+ {
+ label: "Profile Perbekel",
+ value: "profileperbekel",
+ href: "/admin/desa/profile/profile-perbekel"
+ }
+ ];
+ 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 (
+
+ Profile Desa
+
+
+ {tabs.map((e, i) => (
+ {e.label}
+ ))}
+
+ {tabs.map((e, i) => (
+
+ {/* Konten dummy, bisa diganti tergantung routing */}
+ <>>
+
+ ))}
+
+ {children}
+
+ );
+}
+
+export default LayoutTabsDetail;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/desa/profile/_lib/layoutTabsEdit.tsx b/src/app/admin/(dashboard)/desa/profile/_lib/layoutTabsEdit.tsx
new file mode 100644
index 00000000..75201d3d
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/profile/_lib/layoutTabsEdit.tsx
@@ -0,0 +1,71 @@
+/* eslint-disable react-hooks/exhaustive-deps */
+'use client'
+import colors from '@/con/colors';
+import { Stack, Tabs, TabsList, TabsPanel, TabsTab } from '@mantine/core';
+import { usePathname, useRouter } from 'next/navigation';
+import React, { useEffect, useState } from 'react';
+
+function LayoutTabsEdit({ children }: { children: React.ReactNode }) {
+ const router = useRouter()
+ const pathname = usePathname()
+ const tabs = [
+ {
+ label: "Sejarah Desa",
+ value: "sejarahdesa",
+ href: "/admin/desa/profile/edit/sejarah_desa"
+ },
+ {
+ label: "Visi Misi Desa",
+ value: "visimisidesa",
+ href: "/admin/desa/profile/edit/visi_misi_desa"
+ },
+ {
+ label: "Lambang Desa",
+ value: "lambangdesa",
+ href: "/admin/desa/profile/edit/lambang_desa"
+ },
+ {
+ label: "Maskot Desa",
+ value: "maskotdesa",
+ href: "/admin/desa/profile/edit/maskot_desa"
+ },
+ ];
+ 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 (
+
+
+
+ {tabs.map((e, i) => (
+ {e.label}
+ ))}
+
+ {tabs.map((e, i) => (
+
+ {/* Konten dummy, bisa diganti tergantung routing */}
+ <>>
+
+ ))}
+
+ {children}
+
+ );
+}
+
+export default LayoutTabsEdit;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/desa/profile/layout.tsx b/src/app/admin/(dashboard)/desa/profile/layout.tsx
new file mode 100644
index 00000000..f82687f5
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/profile/layout.tsx
@@ -0,0 +1,11 @@
+'use client'
+
+import LayoutTabsDetail from "./_lib/layoutTabsDetail"
+
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/desa/profile/page.tsx b/src/app/admin/(dashboard)/desa/profile/page.tsx
deleted file mode 100644
index 8f85b2fa..00000000
--- a/src/app/admin/(dashboard)/desa/profile/page.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import colors from '@/con/colors';
-import { Stack, Title, Tabs, TabsList, TabsTab, TabsPanel } from '@mantine/core';
-import React from 'react';
-import SejarahDesa from './ui/sejarah_desa/page';
-import VisiMisiDesa from './ui/visi_misi_desa/page';
-import LambangDesa from './ui/lambang_desa/page';
-import MaskotDesa from './ui/maskot_desa/page';
-import ProfilePerbekel from './ui/profile_perbekel/page';
-
-function Page() {
- return (
-
- Profile Desa
-
-
-
- Sejarah Desa
-
-
- Visi Misi Desa
-
-
- Lambang Desa
-
-
- Maskot Desa
-
-
- Profile Perbekel
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default Page;
diff --git a/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/lambang_desa/page.tsx b/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/lambang_desa/page.tsx
new file mode 100644
index 00000000..c0d2fb78
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/lambang_desa/page.tsx
@@ -0,0 +1,126 @@
+/* eslint-disable react-hooks/exhaustive-deps */
+'use client'
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
+import colors from '@/con/colors';
+import { Box, Button, Center, Group, 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 Page() {
+ const lambangState = useProxy(stateProfileDesa.lambangDesa)
+ const router = useRouter()
+ const params = useParams()
+ const [isSubmitting, setIsSubmitting] = useState(false);
+
+ useEffect(() => {
+ const loadData = async () => {
+ const id = params?.id as string;
+ if (!id) {
+ toast.error("ID tidak valid");
+ router.push("/admin/desa/profile/profile-desa");
+ return;
+ }
+
+ const data = await lambangState.findUnique.load(id);
+ if (data) {
+ lambangState.update.initialize(data);
+ }
+ };
+
+ loadData();
+
+ return () => {
+ lambangState.update.reset();
+ lambangState.findUnique.reset(); // opsional: reset juga data lama
+ };
+ }, [params?.id, router]);
+
+
+ const handleSubmit = async () => {
+ if (isSubmitting || !lambangState.update.form.judul.trim()) {
+ toast.error("Judul wajib diisi");
+ return;
+ }
+ setIsSubmitting(true)
+ try {
+ const success = await lambangState.update.submit()
+ if (success) {
+ toast.success("Data berhasil disimpan");
+ router.push("/admin/desa/profile/profile-desa");
+ }
+ } catch (error) {
+ console.error("Error update lambang desa:", error);
+ toast.error("Terjadi kesalahan saat update lambang desa");
+ } finally {
+ setIsSubmitting(false);
+ }
+ }
+
+ const handleBack = () => {
+ router.back()
+ }
+
+ if (
+ lambangState.findUnique.loading ||
+ !lambangState.findUnique.data ||
+ lambangState.update.loading
+ ) {
+ return (
+
+
+ Memuat data...
+
+
+ );
+ }
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ Edit Lambang Desa
+ Judul}
+ placeholder="Judul"
+ value={lambangState.update.form.judul}
+ onChange={(e) => lambangState.update.form.judul = e.currentTarget.value}
+ error={!lambangState.update.form.judul && "Judul wajib diisi"}
+ />
+
+ Deskripsi
+ lambangState.update.form.deskripsi = val}
+ />
+
+
+
+ Submit
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default Page;
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
new file mode 100644
index 00000000..5a2c5505
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/maskot_desa/page.tsx
@@ -0,0 +1,244 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable react-hooks/exhaustive-deps */
+'use client'
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
+import colors from '@/con/colors';
+import ApiFetch from '@/lib/api-fetch';
+import { Box, Button, Group, Image, Paper, SimpleGrid, 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 Page() {
+ const maskotState = useProxy(stateProfileDesa.maskotDesa)
+ const router = useRouter()
+ const params = useParams()
+
+ const [images, setImages] = useState<
+ Array<{ file: File; preview: string; label: string }>
+ >([]);
+
+ const [formData, setFormData] = useState({
+ judul: maskotState.update.form.judul || '',
+ deskripsi: maskotState.update.form.deskripsi || '',
+ images: [] as Array<{ label: string; imageId: string }>
+ })
+
+ useEffect(() => {
+ const loadData = async () => {
+ const id = params?.id as string;
+ if (!id) return;
+
+ try {
+ const data = await maskotState.findUnique.load(id);
+ if (data) {
+ // 🔥 INI YANG KURANG!
+ maskotState.update.initialize(data);
+
+ setFormData({
+ judul: data.judul || '',
+ deskripsi: data.deskripsi || '',
+ images: (data.images || []).map((img: any) => ({
+ label: img.label,
+ imageId: img.image?.id ?? '',
+ })),
+ });
+
+ if (data?.images?.length > 0 && data.images[0].image?.link) {
+ setImages(data.images.map((img: any) => ({
+ file: null,
+ preview: img.image.link,
+ label: img.label,
+ })));
+ }
+ }
+ } catch (error) {
+ console.error("Error loading berita:", error);
+ toast.error("Gagal memuat data berita");
+ }
+ };
+
+ loadData();
+ }, [params?.id]);
+
+
+ const handleBack = () => {
+ router.back()
+ }
+
+ const handleSubmit = async () => {
+ try {
+ const uploadedImages = [];
+
+ // Upload semua gambar baru
+ for (const img of images) {
+ if (!img.file || !(img.file instanceof File)) {
+ toast.error("File tidak valid untuk di-upload");
+ continue; // atau return kalau kamu mau hentikan semua
+ }
+
+ const res = await ApiFetch.api.fileStorage.create.post({
+ file: img.file,
+ name: img.file.name,
+ });
+
+ const uploaded = res.data?.data;
+ if (!uploaded?.id) {
+ toast.error("Gagal upload salah satu gambar");
+ return;
+ }
+
+ uploadedImages.push({
+ imageId: uploaded.id,
+ label: img.label || 'main',
+ });
+ }
+
+ // Update ke global state
+ maskotState.update.updateField("judul", formData.judul);
+ maskotState.update.updateField("deskripsi", formData.deskripsi);
+ maskotState.update.updateField("images", uploadedImages);
+
+ const success = await maskotState.update.submit();
+
+ if (success) {
+ toast.success("Maskot berhasil diperbarui!");
+ router.push("/admin/desa/profile/profile-desa");
+ }
+
+ } catch (error) {
+ console.error("Error update maskot:", error);
+ toast.error("Gagal update maskot");
+ }
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ Edit Maskot Desa
+ Judul}
+ placeholder="Masukkan judul"
+ value={formData.judul}
+ onChange={(val) => setFormData({ ...formData, judul: val.currentTarget.value })}
+ />
+
+ Deskripsi
+ setFormData({ ...formData, deskripsi: val })}
+ />
+
+
+ Gambar
+
+ {
+ const newImages = files.map((file) => ({
+ file,
+ preview: URL.createObjectURL(file),
+ label: '',
+ }));
+ setImages((prev) => [...prev, ...newImages]);
+ }}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Drag images here or click to select files
+
+
+ Attach as many files as you like, each file should not exceed 5mb
+
+
+
+
+
+
+
+ {images.map((img, index) => (
+
+
+
+
+ {
+ const updated = [...images];
+ updated.splice(index, 1);
+ setImages(updated);
+ }}
+ >
+ Hapus
+
+
+
+ {
+ const updated = [...images];
+ updated[index].label = e.currentTarget.value;
+ setImages(updated);
+ }}
+ />
+
+
+
+ ))}
+
+
+
+ Submit
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default Page;
diff --git a/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/sejarah_desa/page.tsx b/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/sejarah_desa/page.tsx
new file mode 100644
index 00000000..d1592de1
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/sejarah_desa/page.tsx
@@ -0,0 +1,126 @@
+/* eslint-disable react-hooks/exhaustive-deps */
+'use client'
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
+import colors from '@/con/colors';
+import { Box, Button, Center, Group, 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 Page() {
+ const sejarahState = useProxy(stateProfileDesa.sejarahDesa)
+ const router = useRouter()
+ const params = useParams()
+ const [isSubmitting, setIsSubmitting] = useState(false);
+
+ useEffect(() => {
+ const loadData = async () => {
+ const id = params?.id as string;
+ if (!id) {
+ toast.error("ID tidak valid");
+ router.push("/admin/desa/profile/profile-desa");
+ return;
+ }
+
+ const data = await sejarahState.findUnique.load(id);
+ if (data) {
+ sejarahState.update.initialize(data);
+ }
+ };
+
+ loadData();
+
+ return () => {
+ sejarahState.update.reset();
+ sejarahState.findUnique.reset(); // opsional: reset juga data lama
+ };
+ }, [params?.id, router]);
+
+
+ const handleSubmit = async () => {
+ if (isSubmitting || !sejarahState.update.form.judul.trim()) {
+ toast.error("Judul wajib diisi");
+ return;
+ }
+ setIsSubmitting(true)
+ try {
+ const success = await sejarahState.update.submit()
+ if (success) {
+ toast.success("Data berhasil disimpan");
+ router.push("/admin/desa/profile/profile-desa");
+ }
+ } catch (error) {
+ console.error("Error update sejarah desa:", error);
+ toast.error("Terjadi kesalahan saat update sejarah desa");
+ } finally {
+ setIsSubmitting(false);
+ }
+ }
+
+ const handleBack = () => {
+ router.back()
+ }
+
+ if (
+ sejarahState.findUnique.loading ||
+ !sejarahState.findUnique.data ||
+ sejarahState.update.loading
+ ) {
+ return (
+
+
+ Memuat data...
+
+
+ );
+ }
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ Edit Sejarah Desa
+ Judul}
+ placeholder="Judul"
+ value={sejarahState.update.form.judul}
+ onChange={(e) => sejarahState.update.form.judul = e.currentTarget.value}
+ error={!sejarahState.update.form.judul && "Judul wajib diisi"}
+ />
+
+ Deskripsi
+ sejarahState.update.form.deskripsi = val}
+ />
+
+
+
+ Submit
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default Page;
diff --git a/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/visi_misi_desa/page.tsx b/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/visi_misi_desa/page.tsx
new file mode 100644
index 00000000..dbbacc8d
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/profile/profile-desa/[id]/visi_misi_desa/page.tsx
@@ -0,0 +1,124 @@
+/* eslint-disable react-hooks/exhaustive-deps */
+'use client'
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
+import colors from '@/con/colors';
+import { Box, Button, Center, Group, Paper, Stack, Text, 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 Page() {
+ const visiMisiState = useProxy(stateProfileDesa.visiMisiDesa)
+ const router = useRouter()
+ const params = useParams()
+ const [isSubmitting, setIsSubmitting] = useState(false);
+
+ useEffect(() => {
+ const loadData = async () => {
+ const id = params?.id as string;
+ if (!id) {
+ toast.error("ID tidak valid");
+ router.push("/admin/desa/profile/profile-desa");
+ return;
+ }
+
+ const data = await visiMisiState.findUnique.load(id);
+ if (data) {
+ visiMisiState.update.initialize(data);
+ }
+ };
+
+ loadData();
+
+ return () => {
+ visiMisiState.update.reset();
+ visiMisiState.findUnique.reset(); // opsional: reset juga data lama
+ };
+ }, [params?.id, router]);
+
+
+ const handleSubmit = async () => {
+ if (isSubmitting || !visiMisiState.update.form.visi.trim()) {
+ toast.error("Visi wajib diisi");
+ return;
+ }
+ setIsSubmitting(true)
+ try {
+ const success = await visiMisiState.update.submit()
+ if (success) {
+ toast.success("Data berhasil disimpan");
+ router.push("/admin/desa/profile/profile-desa");
+ }
+ } catch (error) {
+ console.error("Error update sejarah desa:", error);
+ toast.error("Terjadi kesalahan saat update sejarah desa");
+ } finally {
+ setIsSubmitting(false);
+ }
+ }
+
+ const handleBack = () => {
+ router.back()
+ }
+
+ if (
+ visiMisiState.findUnique.loading ||
+ !visiMisiState.findUnique.data ||
+ visiMisiState.update.loading
+ ) {
+ return (
+
+
+ Memuat data...
+
+
+ );
+ }
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ Edit Visi Misi Desa
+ Visi
+ visiMisiState.update.form.visi = val}
+ />
+
+ Misi
+ visiMisiState.update.form.misi = val}
+ />
+
+
+
+ Submit
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default Page;
diff --git a/src/app/admin/(dashboard)/desa/profile/profile-desa/page.tsx b/src/app/admin/(dashboard)/desa/profile/profile-desa/page.tsx
new file mode 100644
index 00000000..2e105a0f
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/profile/profile-desa/page.tsx
@@ -0,0 +1,171 @@
+'use client'
+
+import colors from '@/con/colors';
+import { Box, Button, Card, Center, Grid, GridCol, Group, Image, Paper, Stack, Text, Title } from '@mantine/core';
+import { useSnapshot } from 'valtio';
+import stateProfileDesa from '../../../_state/desa/profile';
+import { useEffect } from 'react';
+import { IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+function Page() {
+ const router = useRouter();
+ const snap = useSnapshot(stateProfileDesa);
+
+ // Panggil load data sekali saat komponen mount
+ useEffect(() => {
+ stateProfileDesa.sejarahDesa.findUnique.load("edit");
+ stateProfileDesa.visiMisiDesa.findUnique.load("edit");
+ stateProfileDesa.lambangDesa.findUnique.load("edit");
+ stateProfileDesa.maskotDesa.findUnique.load("edit");
+ }, []);
+
+ const sejarah = snap.sejarahDesa.findUnique.data;
+ const visiMisi = snap.visiMisiDesa.findUnique.data;
+ const lambang = snap.lambangDesa.findUnique.data;
+ const maskot = snap.maskotDesa.findUnique.data;
+
+ return (
+
+
+ Preview Profile Desa
+ {/* Sejarah Desa */}
+ {sejarah && (
+
+
+
+
+
+ Preview Sejarah Desa
+
+
+ router.push(`/admin/desa/profile/profile-desa/${sejarah.id}/sejarah_desa`)}>
+
+
+
+
+
+
+
+
+ {sejarah.judul}
+
+
+
+
+
+
+
+ )}
+
+ {/* Visi Misi Desa */}
+ {visiMisi && (
+
+
+
+
+
+ Preview Visi Misi Desa
+
+
+ router.push(`/admin/desa/profile/profile-desa/${visiMisi.id}/visi_misi_desa`)} bg={colors['blue-button']}>
+
+
+
+
+
+
+
+
+ Visi Misi Desa
+
+
+ Visi Desa
+
+ Misi Desa
+
+
+
+
+
+ )}
+
+ {/* Lambang Desa */}
+ {lambang && (
+
+
+
+
+
+ Preview Lambang Desa
+
+
+ router.push(`/admin/desa/profile/profile-desa/${lambang.id}/lambang_desa`)} bg={colors['blue-button']}>
+
+
+
+
+
+
+
+
+ Lambang Desa
+
+
+
+
+
+
+
+ )}
+
+ {/* Maskot Desa */}
+ {maskot && (
+
+
+
+
+
+ Preview Maskot Desa
+
+
+ router.push(`/admin/desa/profile/profile-desa/${maskot.id}/maskot_desa`)} bg={colors['blue-button']}>
+
+
+
+
+
+
+
+
+ Maskot Desa
+
+
+
+
+ {maskot.images.map((img, index) => (
+
+
+ {img.label}
+
+ ))}
+
+
+
+
+
+ )}
+
+
+ );
+}
+
+export default Page;
diff --git a/src/app/admin/(dashboard)/desa/profile/profile-perbekel/[id]/page.tsx b/src/app/admin/(dashboard)/desa/profile/profile-perbekel/[id]/page.tsx
new file mode 100644
index 00000000..2768b0ae
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/profile/profile-perbekel/[id]/page.tsx
@@ -0,0 +1,193 @@
+'use client'
+/* eslint-disable react-hooks/exhaustive-deps */
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
+import colors from '@/con/colors';
+import ApiFetch from '@/lib/api-fetch';
+import { Box, Button, Center, FileInput, Group, Image, Paper, Stack, Text, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } 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 ProfilePerbekel() {
+ const perbekelState = useProxy(stateProfileDesa.profilPerbekel)
+ const router = useRouter()
+ const params = useParams()
+ const [isSubmitting, setIsSubmitting] = useState(false);
+ const [previewImage, setPreviewImage] = useState(null);
+ const [file, setFile] = useState(null);
+
+ useEffect(() => {
+ const loadData = async () => {
+ const id = params?.id as string;
+ if (!id) {
+ toast.error("ID tidak valid");
+ router.push("/admin/desa/profile/profile-perbekel");
+ return;
+ }
+
+ const data = await perbekelState.findUnique.load(id);
+ if (data) {
+ perbekelState.edit.initialize(data);
+ }
+ if (data?.image?.link) {
+ setPreviewImage(data.image.link);
+ }
+ };
+
+ loadData();
+
+ return () => {
+ perbekelState.edit.reset();
+ perbekelState.findUnique.reset(); // opsional: reset juga data lama
+ };
+ }, [params?.id, router]);
+
+ const handleFileChange = (newFile: File | null) => {
+ if (!newFile) {
+ setFile(null);
+ return;
+ }
+
+ setFile(newFile);
+
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ setPreviewImage(event.target?.result as string);
+ };
+ reader.readAsDataURL(newFile);
+ };
+
+ const handleSubmit = async () => {
+ if (isSubmitting || !perbekelState.edit.form.biodata.trim()) {
+ toast.error("Biodata wajib diisi");
+ return;
+ }
+ setIsSubmitting(true)
+ try {
+ if (file) {
+ const uploadResponse = await ApiFetch.api.fileStorage.create.post({ file, name: file.name });
+ const uploaded = uploadResponse.data?.data;
+
+ if (!uploaded?.id) {
+ toast.error("Gagal upload gambar");
+ return;
+ }
+
+ perbekelState.edit.form.imageId = uploaded.id;
+ }
+ const success = await perbekelState.edit.submit()
+ if (success) {
+ toast.success("Data berhasil disimpan");
+ router.push("/admin/desa/profile/profile-perbekel");
+ }
+ } catch (error) {
+ console.error("Error update sejarah desa:", error);
+ toast.error("Terjadi kesalahan saat update sejarah desa");
+ } finally {
+ setIsSubmitting(false);
+ }
+ }
+
+ const handleBack = () => {
+ router.back()
+ }
+
+ if (
+ perbekelState.findUnique.loading ||
+ !perbekelState.findUnique.data ||
+ perbekelState.edit.loading
+ ) {
+ return (
+
+
+ Memuat data...
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ Edit Profil Perbekel
+ Biodata
+ perbekelState.edit.form.biodata = val}
+ />
+ {/* File Upload */}
+ Upload Gambar Baru (Opsional)}
+ value={file}
+ onChange={handleFileChange}
+ accept="image/*"
+ />
+
+ {/* Preview Gambar */}
+
+ Preview Gambar
+ {previewImage ? (
+
+ ) : (
+
+
+
+ Tidak ada gambar
+
+
+ )}
+
+
+
+ Pengalaman
+ perbekelState.edit.form.pengalaman = val}
+ />
+
+
+ Pengalaman Organisasi
+ perbekelState.edit.form.pengalamanOrganisasi = val}
+ />
+
+
+ Program Unggulan
+ perbekelState.edit.form.programUnggulan = val}
+ />
+
+
+
+ Submit
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default ProfilePerbekel;
diff --git a/src/app/admin/(dashboard)/desa/profile/profile-perbekel/page.tsx b/src/app/admin/(dashboard)/desa/profile/profile-perbekel/page.tsx
new file mode 100644
index 00000000..97b4f13a
--- /dev/null
+++ b/src/app/admin/(dashboard)/desa/profile/profile-perbekel/page.tsx
@@ -0,0 +1,112 @@
+'use client'
+
+import colors from '@/con/colors';
+import { Box, Button, Center, Divider, Grid, GridCol, Image, Paper, Stack, Text, Title } from '@mantine/core';
+import { IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useEffect } from 'react';
+import { useSnapshot } from 'valtio';
+import stateProfileDesa from '../../../_state/desa/profile';
+
+function Page() {
+ const router = useRouter();
+ const snap = useSnapshot(stateProfileDesa);
+
+ // Panggil load data sekali saat komponen mount
+ useEffect(() => {
+ stateProfileDesa.profilPerbekel.findUnique.load("edit");
+ }, []);
+
+ const perbekel = snap.profilPerbekel.findUnique.data;
+
+ return (
+
+
+
+
+ Preview Profile PPID
+
+
+ router.push(`/admin/desa/profile/profile-perbekel/${snap.profilPerbekel.findUnique.data?.id}`)}>
+
+
+
+
+ {perbekel && (
+
+
+
+
+
+
+
+
+
+
+ PROFIL PIMPINAN BADAN PUBLIK DESA DARMASABA
+
+
+
+
+ {/* biodata perbekel */}
+
+
+
+
+
+ {
+ e.currentTarget.src = "/perbekel.png";
+ }}
+ />
+
+
+
+ I.B. Surya Prabhawa Manuaba, S.H.,M.H.,NL.P.
+
+
+
+
+
+
+
+ Biodata
+
+
+
+ Pengalaman
+
+
+
+
+ Pengalaman Organisasi
+
+
+
+
+
+ Program Kerja Unggulan
+
+
+
+
+
+
+
+ )}
+
+
+ );
+}
+
+export default Page;
diff --git a/src/app/admin/(dashboard)/desa/profile/ui/lambang_desa/page.tsx b/src/app/admin/(dashboard)/desa/profile/ui/lambang_desa/page.tsx
deleted file mode 100644
index ca48c832..00000000
--- a/src/app/admin/(dashboard)/desa/profile/ui/lambang_desa/page.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import colors from '@/con/colors';
-import { Box, SimpleGrid, Paper, Stack, Title, Group, Button, Text } from '@mantine/core';
-import React from 'react';
-import { DesaEditor } from '../../../_com/desaEditor';
-
-function LambangDesa() {
- return (
-
-
-
-
-
- Lambang Desa
- Deskripsi Lambang Desa
-
-
-
- Submit
-
-
-
-
-
-
-
-
- List Lambang Desa
-
-
-
-
-
- );
-}
-
-export default LambangDesa;
diff --git a/src/app/admin/(dashboard)/desa/profile/ui/maskot_desa/page.tsx b/src/app/admin/(dashboard)/desa/profile/ui/maskot_desa/page.tsx
deleted file mode 100644
index 9fc4973b..00000000
--- a/src/app/admin/(dashboard)/desa/profile/ui/maskot_desa/page.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import colors from '@/con/colors';
-import { Box, SimpleGrid, Paper, Stack, Title, Group, Button, Text } from '@mantine/core';
-import React from 'react';
-import { DesaEditor } from '../../../_com/desaEditor';
-
-function MaskotDesa() {
- return (
-
-
-
-
-
- Maskot Desa
- Deskripsi Maskot Desa
-
-
-
- Submit
-
-
-
-
-
-
-
-
- List Maskot Desa
-
-
-
-
-
- );
-}
-
-export default MaskotDesa;
diff --git a/src/app/admin/(dashboard)/desa/profile/ui/profile_perbekel/page.tsx b/src/app/admin/(dashboard)/desa/profile/ui/profile_perbekel/page.tsx
deleted file mode 100644
index 702189dd..00000000
--- a/src/app/admin/(dashboard)/desa/profile/ui/profile_perbekel/page.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import colors from '@/con/colors';
-import { Box, SimpleGrid, Paper, Stack, Title, Group, Button, TextInput, Text } from '@mantine/core';
-import React from 'react';
-import { DesaEditor } from '../../../_com/desaEditor';
-
-function ProfilePerbekel() {
- return (
-
-
-
-
-
- Profil Perbekel
-
- Biodata
-
- Pengalaman
-
- Pengalaman Organisasi
-
- Program Unggulan
-
-
-
- Submit
-
-
-
-
-
-
-
-
- List Profil Perbekel
-
-
-
-
-
- );
-}
-
-export default ProfilePerbekel;
diff --git a/src/app/admin/(dashboard)/desa/profile/ui/sejarah_desa/listPage.tsx b/src/app/admin/(dashboard)/desa/profile/ui/sejarah_desa/listPage.tsx
deleted file mode 100644
index 35a8dbda..00000000
--- a/src/app/admin/(dashboard)/desa/profile/ui/sejarah_desa/listPage.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Title } from '@mantine/core';
-import React from 'react';
-
-function ListPage() {
- return (
-
-
-
- List Sejarah Desa
-
-
-
- );
-}
-
-export default ListPage;
diff --git a/src/app/admin/(dashboard)/desa/profile/ui/sejarah_desa/page.tsx b/src/app/admin/(dashboard)/desa/profile/ui/sejarah_desa/page.tsx
deleted file mode 100644
index ea95455e..00000000
--- a/src/app/admin/(dashboard)/desa/profile/ui/sejarah_desa/page.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-'use client'
-import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
-import { useProxy } from 'valtio/utils';
-import DesaEditorText from '../../../_com/desaEditorText';
-import ListPage from './listPage';
-import { useShallowEffect } from '@mantine/hooks';
-
-
-function SejarahDesa() {
- const stateSejarah = useProxy(stateProfileDesa.Sejarah)
-
- useShallowEffect(() => {
- if (!stateSejarah.findById.data) {
- stateSejarah.findById.initialize()
- }
- }, [])
-
- const submit = () => {
- if (stateSejarah.findById.data?.id && stateSejarah.findById.data.sejarah) {
- stateSejarah.update.save({
- id: stateSejarah.findById.data.id,
- sejarah: stateSejarah.findById.data.sejarah
- })
- }
- }
-
- return (
-
-
-
-
-
- Sejarah Desa
- Deskripsi Sejarah Desa
- {
- if (stateSejarah.findById.data) {
- stateSejarah.findById.data.sejarah = val
- }
- }}
- initialContent={stateSejarah.findById.data?.sejarah ?? ""}
- />
-
-
- Submit
-
-
-
-
-
-
-
-
- );
-}
-
-export default SejarahDesa;
diff --git a/src/app/admin/(dashboard)/desa/profile/ui/visi_misi_desa/page.tsx b/src/app/admin/(dashboard)/desa/profile/ui/visi_misi_desa/page.tsx
deleted file mode 100644
index f0ccf437..00000000
--- a/src/app/admin/(dashboard)/desa/profile/ui/visi_misi_desa/page.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
-import { DesaEditor } from '../../../_com/desaEditor';
-
-function VisiMisiDesa() {
- return (
-
-
-
-
-
- Visi Desa
- Deskripsi Visi Desa
-
-
-
- Submit
-
-
-
-
-
-
-
-
- List Visi Desa
-
-
-
-
-
-
-
-
- Misi Desa
- Deskripsi Misi Desa
-
-
-
- Submit
-
-
-
-
-
-
-
-
- List Misi Desa
-
-
-
-
-
- );
-}
-
-export default VisiMisiDesa;
diff --git a/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/create/page.tsx b/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/create/page.tsx
new file mode 100644
index 00000000..5048c1ba
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/create/page.tsx
@@ -0,0 +1,42 @@
+'use client'
+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';
+
+
+function CreateDemografiPekerjaan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Demografi Pekerjaan
+ Pekerjaan}
+ placeholder='Masukkan pekerjaan'
+ />
+ Jumlah Pekerja Laki - Laki}
+ placeholder='Masukkan jumlah pekerja laki - laki'
+ />
+ Jumlah Pekerja Perempuan}
+ placeholder='Masukkan jumlah pekerja perempuan'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateDemografiPekerjaan;
diff --git a/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/detail/page.tsx b/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/detail/page.tsx
new file mode 100644
index 00000000..fd52618b
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/detail/page.tsx
@@ -0,0 +1,62 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailDemografiPekerjaan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Demografi Pekerjaan
+
+
+
+
+ Pekerjaan
+ Karyawan
+
+
+ Jumlah Pekerja Laki - Laki
+ 200
+
+
+ Jumlah Pekerja Perempuan
+ 100
+
+
+
+
+
+
+ router.push('/admin/ekonomi/demografi-pekerjaan/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailDemografiPekerjaan;
+
diff --git a/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/edit/page.tsx b/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/edit/page.tsx
new file mode 100644
index 00000000..e992abeb
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/edit/page.tsx
@@ -0,0 +1,42 @@
+'use client'
+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';
+
+
+function EditDemografiPekerjaan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Demografi Pekerjaan
+ Pekerjaan}
+ placeholder='Masukkan pekerjaan'
+ />
+ Jumlah Pekerja Laki - Laki}
+ placeholder='Masukkan jumlah pekerja laki - laki'
+ />
+ Jumlah Pekerja Perempuan}
+ placeholder='Masukkan jumlah pekerja perempuan'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditDemografiPekerjaan;
diff --git a/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/page.tsx b/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/page.tsx
index c2a37b38..f0ff9c12 100644
--- a/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/page.tsx
+++ b/src/app/admin/(dashboard)/ekonomi/demografi-pekerjaan/page.tsx
@@ -1,47 +1,58 @@
+'use client'
import colors from '@/con/colors';
-import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import React from 'react';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function DemografiPekerjaan() {
return (
-
-
-
-
- Demografi Pekerjaan
- Jumlah Pekerja Laki - Laki}
- placeholder="Masukkan jumlah pekerja laki - laki"
- />
- Jumlah Pekerja Perempuan}
- placeholder="Masukkan jumlah pekerja perempuan"
- />
- Nama Pekerjaan}
- placeholder="Masukkan nama pekerjaan"
- />
-
-
- Submit
-
-
-
-
-
-
-
-
- Grafik Demografi Pekerjaan
-
-
-
-
+ }
+ />
+
);
}
-export default Page;
+function ListDemografiPekerjaan() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Pekerjaan
+ Jumlah Pekerja Laki - Laki
+ Jumlah Pekerja Perempuan
+ Detail
+
+
+
+
+ Karyawan
+ 200
+ 100
+
+ router.push('/admin/ekonomi/demografi-pekerjaan/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default DemografiPekerjaan;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/create/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/create/page.tsx
new file mode 100644
index 00000000..a6a29f6c
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/create/page.tsx
@@ -0,0 +1,38 @@
+'use client'
+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';
+
+
+function CreateJumlahPendudukMiskin() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Jumlah Penduduk Miskin
+ Tahun}
+ placeholder='Masukkan tahun'
+ />
+ Jumlah Penduduk Miskin}
+ placeholder='Masukkan jumlah penduduk miskin'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateJumlahPendudukMiskin;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/detail/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/detail/page.tsx
new file mode 100644
index 00000000..9226b603
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/detail/page.tsx
@@ -0,0 +1,58 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailJumlahPendudukMiskin() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Jumlah Penduduk Miskin
+
+
+
+
+ Tahun
+ 2024
+
+
+ Jumlah Penduduk Miskin
+ 100
+
+
+
+
+
+
+ router.push('/admin/ekonomi/jumlah-penduduk-miskin-2024-2025/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailJumlahPendudukMiskin;
+
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/edit/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/edit/page.tsx
new file mode 100644
index 00000000..b9e94ac7
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/edit/page.tsx
@@ -0,0 +1,38 @@
+'use client'
+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';
+
+
+function EditJumlahPendudukMiskin() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Jumlah Penduduk Miskin
+ Tahun}
+ placeholder='Masukkan tahun'
+ />
+ Jumlah Penduduk Miskin}
+ placeholder='Masukkan jumlah penduduk miskin'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditJumlahPendudukMiskin;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/page.tsx
index 2b121b34..96db28f8 100644
--- a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/page.tsx
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-miskin-2024-2025/page.tsx
@@ -1,43 +1,56 @@
-import { Box, Button, Group, Paper, Stack, TextInput, Title } from '@mantine/core';
+'use client'
import colors from '@/con/colors';
-import React from 'react';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function JumlahPendudukMiskin() {
return (
-
-
-
-
- Jumlah Penduduk Miskin 2024-2025
-
-
-
-
- Submit
-
-
-
-
-
-
-
-
- Grafik Jumlah Penduduk Miskin 2024-2025
-
-
-
-
+ }
+ />
+
);
}
-export default Page;
+function ListJumlahPendudukMiskin() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Tahun
+ Jumlah Penduduk Miskin
+ Detail
+
+
+
+
+ 2024
+ 100
+
+ router.push('/admin/ekonomi/jumlah-penduduk-miskin-2024-2025/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default JumlahPendudukMiskin;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/page.tsx
index 6f9e8e20..dcf2acfa 100644
--- a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/page.tsx
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/page.tsx
@@ -1,27 +1,27 @@
import colors from "@/con/colors";
import { Box, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from "@mantine/core";
-import PengangguranBerdasarkanUsia from "./ui/pengangguranBerdasarkanUsia/page";
-import PengangguranBerdasarkanPendidikan from "./ui/pengangguranBerdasarkanPendidikan/page";
+import PengangguranBerdasarkanUsia from "./pengangguran_berdasarkan_usia/page";
+import PengangguranBerdasarkanPendidikan from "./pengangguran_berdasarkan_pendidikan/page";
export default function Page() {
return (
Jumlah Penduduk Usia Kerja yang Menganggur
-
+
-
- Pengangguran Bredasarkan Usia
+
+ Pengangguran Berdasarkan Usia
-
- Pengangguran Bredasarkan Pendidikan
+
+ Pengangguran Berdasarkan Pendidikan
-
+
-
+
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/create/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/create/page.tsx
new file mode 100644
index 00000000..144a6e4c
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/create/page.tsx
@@ -0,0 +1,54 @@
+'use client'
+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';
+
+
+function CreatePengangguranBerdasarkanPendidikan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Pengangguran Berdasarkan Pendidikan
+ Pendidikan SD}
+ placeholder='Masukkan pendidikan sd'
+ />
+ Pendidikan SMP}
+ placeholder='Masukkan pendidikan smp'
+ />
+ Pendidikan SMA}
+ placeholder='Masukkan pendidikan sma'
+ />
+ Pendidikan S1}
+ placeholder='Masukkan pendidikan s1'
+ />
+ Pendidikan S2}
+ placeholder='Masukkan pendidikan s2'
+ />
+ Pendidikan S3}
+ placeholder='Masukkan pendidikan s3'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreatePengangguranBerdasarkanPendidikan;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/detail/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/detail/page.tsx
new file mode 100644
index 00000000..1fac895a
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/detail/page.tsx
@@ -0,0 +1,74 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailPengangguranBerdasarkanPendidikan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Pengangguran Berdasarkan Pendidikan
+
+
+
+
+ Pendidikan SD
+ 50
+
+
+ Pendidikan SMP
+ 60
+
+
+ Pendidikan SMA
+ 80
+
+
+ Pendidikan S1
+ 40
+
+
+ Pendidikan S2
+ 20
+
+
+ Pendidikan S3
+ 10
+
+
+
+
+
+
+ router.push('/admin/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailPengangguranBerdasarkanPendidikan;
+
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/edit/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/edit/page.tsx
new file mode 100644
index 00000000..14614608
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/edit/page.tsx
@@ -0,0 +1,54 @@
+'use client'
+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';
+
+
+function EditPengangguranBerdasarkanPendidikan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Pengangguran Berdasarkan Pendidikan
+ Pendidikan SD}
+ placeholder='Masukkan pendidikan sd'
+ />
+ Pendidikan SMP}
+ placeholder='Masukkan pendidikan smp'
+ />
+ Pendidikan SMA}
+ placeholder='Masukkan pendidikan sma'
+ />
+ Pendidikan S1}
+ placeholder='Masukkan pendidikan s1'
+ />
+ Pendidikan S2}
+ placeholder='Masukkan pendidikan s2'
+ />
+ Pendidikan S3}
+ placeholder='Masukkan pendidikan s3'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditPengangguranBerdasarkanPendidikan;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/page.tsx
new file mode 100644
index 00000000..932035aa
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/page.tsx
@@ -0,0 +1,49 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Title } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import JudulListTab from '../../../_com/jusulListTab';
+
+function PengangguranBerdasarkanPendidikan() {
+ const router = useRouter();
+ return (
+
+
+
+ }
+ />
+ List Pengangguran Berdasarkan Pendidikan
+
+
+
+ Pendidikan SD
+ Pendidikan SMP
+ Pendidikan SMA
+ Detail
+
+
+
+
+ 80
+ 40
+ 20
+
+ router.push('/admin/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_pendidikan/detail')}>
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default PengangguranBerdasarkanPendidikan;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/create/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/create/page.tsx
new file mode 100644
index 00000000..c35c6118
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/create/page.tsx
@@ -0,0 +1,45 @@
+'use client'
+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';
+
+function CreatePengangguranBerdasarkanUsia() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Pengangguran Berdasarkan Usia
+ Usia 18 - 25}
+ placeholder='Masukkan usia'
+ />
+ Usia 26 - 35}
+ placeholder='Masukkan usia'
+ />
+ Usia 36 - 45}
+ placeholder='Masukkan usia'
+ />
+ Usia 46 +}
+ placeholder='Masukkan usia'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreatePengangguranBerdasarkanUsia;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/detail/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/detail/page.tsx
new file mode 100644
index 00000000..d10bbf64
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/detail/page.tsx
@@ -0,0 +1,70 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailPengangguranBerdasarkanUsia() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Pengangguran Berdasarkan Usia
+
+
+
+
+ Usia 18 - 25
+ 80
+
+
+ Usia 26 - 35
+ 40
+
+
+ Usia 36 - 45
+ 20
+
+
+ Usia 46 +
+ 10
+
+
+ Total
+ 150
+
+
+
+
+
+
+ router.push('/admin/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailPengangguranBerdasarkanUsia;
+
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/edit/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/edit/page.tsx
new file mode 100644
index 00000000..c7ea2b81
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/edit/page.tsx
@@ -0,0 +1,47 @@
+'use client'
+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';
+
+
+
+function EditPengangguranBerdasarkanUsia() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Pengangguran Berdasarkan Usia
+ Usia 18 - 25}
+ placeholder='Masukkan usia'
+ />
+ Usia 26 - 35}
+ placeholder='Masukkan usia'
+ />
+ Usia 36 - 45}
+ placeholder='Masukkan usia'
+ />
+ Usia 46 +}
+ placeholder='Masukkan usia'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditPengangguranBerdasarkanUsia;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/page.tsx
new file mode 100644
index 00000000..1540744a
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/page.tsx
@@ -0,0 +1,49 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Title } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import JudulListTab from '../../../_com/jusulListTab';
+
+function PengangguranBerdasarkanUsia() {
+ const router = useRouter();
+ return (
+
+
+
+ }
+ />
+ List Pengangguran Berdasarkan Usia
+
+
+
+ Usia 18 - 25
+ Usia 26 - 35
+ Usia 36 - 45
+ Detail
+
+
+
+
+ 80
+ 40
+ 20
+
+ router.push('/admin/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran_berdasarkan_usia/detail')}>
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default PengangguranBerdasarkanUsia;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/ui/pengangguranBerdasarkanPendidikan/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/ui/pengangguranBerdasarkanPendidikan/page.tsx
deleted file mode 100644
index 89bfd0f2..00000000
--- a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/ui/pengangguranBerdasarkanPendidikan/page.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import React from 'react';
-
-function PengangguranBerdasarkanPendidikan() {
- return (
-
-
-
-
- Pengangguran Berdasarkan Pendidikan
- Pendidikan SD}
- placeholder="masukkan jumlah penduduk Pendidikan SD yang menganggur"
- />
- Pendidikan SMP}
- placeholder="masukkan jumlah penduduk Pendidikan SMP yang menganggur"
- />
- Pendidikan SMA / SMK}
- placeholder="masukkan jumlah penduduk Pendidikan SMA / SMK yang menganggur"
- />
- Pendidikan D1-D3 / S1}
- placeholder="masukkan jumlah penduduk Pendidikan D1-D3 yang menganggur"
- />
-
-
- Submit
-
-
-
-
-
-
-
-
- Grafik Pengangguran Berdasarkan Pendidikan
-
-
-
-
- );
-}
-
-export default PengangguranBerdasarkanPendidikan;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/ui/pengangguranBerdasarkanUsia/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/ui/pengangguranBerdasarkanUsia/page.tsx
deleted file mode 100644
index 32bc78aa..00000000
--- a/src/app/admin/(dashboard)/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/ui/pengangguranBerdasarkanUsia/page.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import React from 'react';
-
-function PengangguranBerdasarkanUsia() {
- return (
-
-
-
-
- Pengangguran Berdasarkan Usia
- Usia 18 - 25 tahun}
- placeholder="masukkan jumlah penduduk usia 18 - 25 tahun yang menganggur"
- />
- Usia 26 - 35 tahun}
- placeholder="masukkan jumlah penduduk usia 26 - 35 tahun yang menganggur"
- />
- Usia 36 - 45 tahun}
- placeholder="masukkan jumlah penduduk usia 36 - 45 tahun yang menganggur"
- />
- Usia 46+}
- placeholder="masukkan jumlah penduduk usia 46+ yang menganggur"
- />
-
-
- Submit
-
-
-
-
-
-
-
-
- Grafik Pengangguran Berdasarkan Usia
-
-
-
-
- );
-}
-
-export default PengangguranBerdasarkanUsia;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/create/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/create/page.tsx
new file mode 100644
index 00000000..6dff3a24
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/create/page.tsx
@@ -0,0 +1,45 @@
+'use client'
+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';
+
+function CreateJumlahPengangguran() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Jumlah Pengangguran
+ Pengangguran Terdidik}
+ placeholder='Masukkan pengangguran terdidik'
+ />
+ Usia Produktif}
+ placeholder='Masukkan usia produktif'
+ />
+ Sedang Mencari Kerja}
+ placeholder='Masukkan sedang mencari kerja'
+ />
+ Pengangguran Tidak Terdidik}
+ placeholder='Masukkan pengangguran tidak terdidik'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateJumlahPengangguran;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/detail/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/detail/page.tsx
new file mode 100644
index 00000000..d829de7a
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/detail/page.tsx
@@ -0,0 +1,66 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailJumlahPengangguran() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Jumlah Pengangguran
+
+
+
+
+ Pengangguran Terdidik
+ 100
+
+
+ Usia Produktif
+ 200
+
+
+ Sedang Mencari Kerja
+ 300
+
+
+ Pengangguran Tidak Terdidik
+ 30
+
+
+
+
+
+
+ router.push('/admin/ekonomi/jumlah-pengangguran-2024-2025/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailJumlahPengangguran;
+
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/edit/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/edit/page.tsx
new file mode 100644
index 00000000..16917566
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/edit/page.tsx
@@ -0,0 +1,45 @@
+'use client'
+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';
+
+function EditJumlahPengangguran() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Jumlah Pengangguran
+ Pengangguran Terdidik}
+ placeholder='Masukkan pengangguran terdidik'
+ />
+ Usia Produktif}
+ placeholder='Masukkan usia produktif'
+ />
+ Sedang Mencari Kerja}
+ placeholder='Masukkan sedang mencari kerja'
+ />
+ Pengangguran Tidak Terdidik}
+ placeholder='Masukkan pengangguran tidak terdidik'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditJumlahPengangguran;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/page.tsx
index 3f21fdb6..d02d535a 100644
--- a/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/page.tsx
+++ b/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/page.tsx
@@ -1,37 +1,58 @@
+'use client'
import colors from '@/con/colors';
-import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
-import DataPengangguran from './ui/dataPengangguran/page';
-import GrafikDataPengangguran from './ui/grafikDataPengangguran/page';
-import DetailDataPengangguran from './ui/detailDataPengangguran/page';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function JumlahPengangguran() {
return (
-
- Jumlah Pengangguran 2024-2025
-
-
-
- Data Pengangguran Desa
-
-
- Grafik Data Pengangguran Desa
-
-
- Detail Data Pengangguran Desa
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
+
+ }
+ />
+
+
+ );
}
-export default Page;
+function ListJumlahPengangguran() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Pengangguran Terdidik
+ Usia Produktif
+ Sedang Mencari Kerja
+ Detail
+
+
+
+
+ 100
+ 200
+ 300
+
+ router.push('/admin/ekonomi/jumlah-pengangguran-2024-2025/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default JumlahPengangguran;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/ui/dataPengangguran/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/ui/dataPengangguran/page.tsx
deleted file mode 100644
index 45d9ff2f..00000000
--- a/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/ui/dataPengangguran/page.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
-
-function DataPengangguran() {
- return (
-
-
-
-
-
-
- Data Pengangguran
- Total Pengangguran}
- placeholder="masukkan total pengangguran"
- />
- Pengangguran Terdidik}
- placeholder="masukkan pengangguran terdidik"
- />
- Usia Produktif}
- placeholder="masukkan usia produktif"
- />
- Sedang Mencari Kerja}
- placeholder="masukkan jumlah sedang mencari kerja"
- />
-
-
- Submit
-
-
-
-
-
-
-
-
- List Data Pengangguran
-
-
-
-
-
-
-
- );
-}
-
-export default DataPengangguran;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/ui/detailDataPengangguran/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/ui/detailDataPengangguran/page.tsx
deleted file mode 100644
index 5da9dec4..00000000
--- a/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/ui/detailDataPengangguran/page.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Title } from '@mantine/core';
-
-function DetailDataPengangguran() {
- return (
-
-
-
-
- Detail Data Pengangguran
-
-
-
-
- );
-}
-
-export default DetailDataPengangguran;
diff --git a/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/ui/grafikDataPengangguran/page.tsx b/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/ui/grafikDataPengangguran/page.tsx
deleted file mode 100644
index d0cf2a55..00000000
--- a/src/app/admin/(dashboard)/ekonomi/jumlah-pengangguran-2024-2025/ui/grafikDataPengangguran/page.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-
-function GrafikDataPengangguran() {
- return (
-
-
-
-
-
- Data Pengangguran
- Total Pengangguran}
- placeholder="masukkan total pengangguran"
- />
- Pengangguran Terdidik}
- placeholder="masukkan pengangguran terdidik"
- />
- Usia Produktif}
- placeholder="masukkan usia produktif"
- />
- Sedang Mencari Kerja}
- placeholder="masukkan jumlah sedang mencari kerja"
- />
-
-
- Submit
-
-
-
-
-
-
-
-
- List Data Pengangguran
-
-
-
-
-
-
- );
-}
-
-export default GrafikDataPengangguran;
diff --git a/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/create/createLowongan.tsx b/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/create/createLowongan.tsx
deleted file mode 100644
index 715e9f28..00000000
--- a/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/create/createLowongan.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { Box, Stack, Text, TextInput, Title } from '@mantine/core';
-
-function CreateLowongan() {
- return (
-
-
- Lowongan Kerja Lokal
- Bekerja Sebagai}
- placeholder="masukkan bekerja sebagai"
- />
- Alamat Usaha}
- placeholder="masukkan alamat usaha"
- />
- Waktu Kerja}
- placeholder="masukkan waktu kerja"
- />
- Gaji selama 1 bulan}
- placeholder="masukkan gaji selama 1 bulan"
- />
-
-
- );
-}
-
-export default CreateLowongan;
diff --git a/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/create/page.tsx b/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/create/page.tsx
new file mode 100644
index 00000000..ce9c4cbb
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/create/page.tsx
@@ -0,0 +1,57 @@
+'use client'
+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 { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+
+function CreateLowonganKerja() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Lowongan Kerja Lokal
+ Pekerjaan}
+ placeholder='Masukkan pekerjaan'
+ />
+ Nama Usaha}
+ placeholder='Masukkan nama usaha'
+ />
+ Alamat Usaha}
+ placeholder='Masukkan alamat usaha'
+ />
+ Nomor Telepon}
+ placeholder='Masukkan nomor telepon'
+ />
+ Gaji selama 1 bulan}
+ placeholder='Masukkan gaji'
+ />
+
+ Deskripsi Lowongan Kerja
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateLowonganKerja;
diff --git a/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/detail/page.tsx b/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/detail/page.tsx
new file mode 100644
index 00000000..9ba61771
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/detail/page.tsx
@@ -0,0 +1,78 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailLowonganKerjaLokal() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Lowongan Kerja Lokal
+
+
+
+
+ Bekerja Sebagai
+ Karyawan
+
+
+ Nama Usaha
+ BIBD
+
+
+ Alamat Usaha
+ Jalan In Aja
+
+
+ Nomor Telepon
+ 0896232831883
+
+
+ Waktu Kerja
+ Full Time
+
+
+ Gaji selama 1 bulan
+ Rp. 3.000.000
+
+
+ Deskripsi Lowongan Kerja
+ Pekerjaan dengan gaji Rp. 3.000.000
+
+
+
+
+
+
+ router.push('/admin/ekonomi/lowongan-kerja-lokal/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailLowonganKerjaLokal;
+
diff --git a/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/edit/page.tsx b/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/edit/page.tsx
new file mode 100644
index 00000000..fc5037af
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/edit/page.tsx
@@ -0,0 +1,57 @@
+'use client'
+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 { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+
+function EditLowonganKerja() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Lowongan Kerja Lokal
+ Pekerjaan}
+ placeholder='Masukkan pekerjaan'
+ />
+ Nama Usaha}
+ placeholder='Masukkan nama usaha'
+ />
+ Alamat Usaha}
+ placeholder='Masukkan alamat usaha'
+ />
+ Nomor Telepon}
+ placeholder='Masukkan nomor telepon'
+ />
+ Gaji selama 1 bulan}
+ placeholder='Masukkan gaji'
+ />
+
+ Deskripsi Lowongan Kerja
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditLowonganKerja;
diff --git a/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/listData/page.tsx b/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/listData/page.tsx
deleted file mode 100644
index 199264e2..00000000
--- a/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/listData/page.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Title, Text } from '@mantine/core';
-import React from 'react';
-
-function ListDataLowongan() {
- return (
-
-
- List Data Lowongan Kerja Lokal
-
- Bekerja Sebagai
-
- Alamat Usaha
-
- Waktu Kerja
-
- Gaji selama 1 bulan
-
-
-
-
- );
-}
-
-export default ListDataLowongan;
diff --git a/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/page.tsx b/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/page.tsx
index b222a023..52d9737a 100644
--- a/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/page.tsx
+++ b/src/app/admin/(dashboard)/ekonomi/lowongan-kerja-lokal/page.tsx
@@ -1,32 +1,58 @@
+'use client'
import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Title } from '@mantine/core';
-import React from 'react';
-import CreateLowongan from './create/createLowongan';
-import ListDataLowongan from './listData/page';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function LowonganKerjaLokal() {
return (
-
-
-
-
- Lowongan Kerja Lokal
-
-
-
- Submit
-
-
-
-
-
-
-
-
-
-
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListLowonganKerjaLokal() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Bekerja Sebagai
+ Nama Usaha
+ Alamat Usaha
+ Detail
+
+
+
+
+ Karyawan
+ BIBD
+ Jalan In Aja
+
+ router.push('/admin/ekonomi/lowongan-kerja-lokal/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default LowonganKerjaLokal;
diff --git a/src/app/admin/(dashboard)/ekonomi/pasar-desa/create/createPasarDesa.tsx b/src/app/admin/(dashboard)/ekonomi/pasar-desa/create/createPasarDesa.tsx
deleted file mode 100644
index ca116352..00000000
--- a/src/app/admin/(dashboard)/ekonomi/pasar-desa/create/createPasarDesa.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Stack, Text, TextInput, Title } from '@mantine/core';
-import { IconImageInPicture } from '@tabler/icons-react';
-import React from 'react';
-
-function CreatePasarDesa() {
- return (
-
-
- Produk Pasar Desa
-
- Masukkan Foto Produk
-
-
- Nama Produk}
- placeholder="masukkan nama produk"
- />
- Harga Produk}
- placeholder="masukkan harga produk"
- />
- Rating Produk}
- placeholder="masukkan rating produk"
- />
- Alamat Usaha}
- placeholder="masukkan alamat usaha"
- />
-
-
- );
-}
-
-export default CreatePasarDesa;
diff --git a/src/app/admin/(dashboard)/ekonomi/pasar-desa/create/page.tsx b/src/app/admin/(dashboard)/ekonomi/pasar-desa/create/page.tsx
new file mode 100644
index 00000000..6c7a8f14
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/pasar-desa/create/page.tsx
@@ -0,0 +1,56 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+function CreatePasarDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Pasar Desa
+
+ Masukkan Image
+
+
+ Nama Produk}
+ placeholder='Masukkan nama produk'
+ />
+ Harga Produk}
+ placeholder='Masukkan harga produk'
+ />
+ Rating Produk}
+ placeholder='Masukkan rating produk'
+ />
+ Alamat Usaha}
+ placeholder='Masukkan alamat usaha'
+ />
+
+ Deskripsi Produk
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreatePasarDesa;
diff --git a/src/app/admin/(dashboard)/ekonomi/pasar-desa/detail/page.tsx b/src/app/admin/(dashboard)/ekonomi/pasar-desa/detail/page.tsx
new file mode 100644
index 00000000..fac32b9f
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/pasar-desa/detail/page.tsx
@@ -0,0 +1,74 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailPasarDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Pasar Desa
+
+
+
+
+ Nama Produk
+ Test Judul
+
+
+ Harga Produk
+ Rp. 20.000
+
+
+ Rating Produk
+ 5
+
+
+ Alamat Usaha
+ Jalan In Aja
+
+
+ Gambar
+
+
+
+ Deskripsi
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/ekonomi/pasar-desa/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailPasarDesa;
diff --git a/src/app/admin/(dashboard)/ekonomi/pasar-desa/edit/page.tsx b/src/app/admin/(dashboard)/ekonomi/pasar-desa/edit/page.tsx
new file mode 100644
index 00000000..92335984
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/pasar-desa/edit/page.tsx
@@ -0,0 +1,56 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+function EditPasarDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Pasar Desa
+
+ Masukkan Image
+
+
+ Nama Produk}
+ placeholder='Masukkan nama produk'
+ />
+ Harga Produk}
+ placeholder='Masukkan harga produk'
+ />
+ Rating Produk}
+ placeholder='Masukkan rating produk'
+ />
+ Alamat Usaha}
+ placeholder='Masukkan alamat usaha'
+ />
+
+ Deskripsi Produk
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditPasarDesa;
diff --git a/src/app/admin/(dashboard)/ekonomi/pasar-desa/listData/page.tsx b/src/app/admin/(dashboard)/ekonomi/pasar-desa/listData/page.tsx
deleted file mode 100644
index 3809f2ad..00000000
--- a/src/app/admin/(dashboard)/ekonomi/pasar-desa/listData/page.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Text, Title } from '@mantine/core';
-import { IconImageInPicture } from '@tabler/icons-react';
-import React from 'react';
-
-function ListDataUsaha() {
- return (
-
-
-
-
- List Produk Pasar Desa
-
- Foto Produk
-
-
- Nama Produk
-
- Harga Produk
-
- Rating Produk
-
- Alamat Usaha
-
-
-
-
-
- );
-}
-
-export default ListDataUsaha;
diff --git a/src/app/admin/(dashboard)/ekonomi/pasar-desa/page.tsx b/src/app/admin/(dashboard)/ekonomi/pasar-desa/page.tsx
index 95de3555..185e8f98 100644
--- a/src/app/admin/(dashboard)/ekonomi/pasar-desa/page.tsx
+++ b/src/app/admin/(dashboard)/ekonomi/pasar-desa/page.tsx
@@ -1,31 +1,60 @@
+'use client'
import colors from '@/con/colors';
-import { Box, Button, Group, Paper, Stack, Title } from '@mantine/core';
-import React from 'react';
-import CreatePasarDesa from './create/createPasarDesa';
-import ListDataUsaha from './listData/page';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function PasarDesa() {
return (
-
-
-
-
- Pasar Desa
-
-
-
- Submit
-
-
-
-
-
-
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListPasarDesa() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Produk
+ Harga Produk
+ Rating Produk
+ Alamat Usaha
+ Detail
+
+
+
+
+ Produk 1
+ Harga Rp. 20.000
+ Rating 5
+ Jalan In Aja
+
+ router.push('/admin/ekonomi/pasar-desa/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default PasarDesa;
diff --git a/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/create/page.tsx b/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/create/page.tsx
new file mode 100644
index 00000000..d75821c2
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/create/page.tsx
@@ -0,0 +1,46 @@
+'use client'
+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';
+
+
+function CreateProgramKemiskinan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Program Kemiskinan
+ Judul Program}
+ placeholder='Masukkan judul program'
+ />
+ Deskripsi Singkat}
+ placeholder='Masukkan deskripsi'
+ />
+ Jumlah Masyarakat Miskin}
+ placeholder='Masukkan jumlah masyarakat miskin'
+ />
+ Deskripsi}
+ placeholder='Masukkan deskripsi'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateProgramKemiskinan;
diff --git a/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/detail/page.tsx b/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/detail/page.tsx
new file mode 100644
index 00000000..81f605e7
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/detail/page.tsx
@@ -0,0 +1,66 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailProgramKemiskinan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Program Kemiskinan
+
+
+
+
+ Judul Program
+ Program A
+
+
+ Deskripsi Singkat
+ Deskripsi Program A
+
+
+ Jumlah Masyarakat Miskin
+ 100
+
+
+ Deskripsi
+ Deskripsi Program A
+
+
+
+
+
+
+ router.push('/admin/ekonomi/program-kemiskinan/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailProgramKemiskinan;
+
diff --git a/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/edit/page.tsx b/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/edit/page.tsx
new file mode 100644
index 00000000..bda57c97
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/edit/page.tsx
@@ -0,0 +1,46 @@
+'use client'
+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';
+
+
+function EditProgramKemiskinan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Program Kemiskinan
+ Judul Program}
+ placeholder='Masukkan judul program'
+ />
+ Deskripsi Singkat}
+ placeholder='Masukkan deskripsi'
+ />
+ Jumlah Masyarakat Miskin}
+ placeholder='Masukkan jumlah masyarakat miskin'
+ />
+ Deskripsi}
+ placeholder='Masukkan deskripsi'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditProgramKemiskinan;
diff --git a/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/page.tsx b/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/page.tsx
index 690a8999..256305d8 100644
--- a/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/page.tsx
+++ b/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/page.tsx
@@ -1,31 +1,58 @@
+'use client'
import colors from '@/con/colors';
-import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
-import ProgramKemiskinan from './ui/program/page';
-import StatistikKemiskinan from './ui/statistik/page';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function ProgramKemiskinan() {
return (
-
- Program Kemiskinan
-
-
-
- Program Kemiskinan
-
-
- Statistik Kemiskinan
-
-
-
-
-
-
-
-
-
-
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListProgramKemiskinan() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Judul Program
+ Deskripsi Singkat
+ Jumlah Masyarakat Miskin
+ Detail
+
+
+
+
+ Program A
+ Deskripsi Program A
+ 100
+
+ router.push('/admin/ekonomi/program-kemiskinan/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default ProgramKemiskinan;
diff --git a/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/ui/program/page.tsx b/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/ui/program/page.tsx
deleted file mode 100644
index 78a78521..00000000
--- a/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/ui/program/page.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
-import React from 'react';
-
-function ProgramKemiskinan() {
- return (
-
-
-
-
-
- Program Kemiskinan
- Nama Program}
- placeholder="Masukkan nama program"
- />
- Deskripsi Program}
- placeholder="Masukkan deskripsi program"
- />
-
-
- Submit
-
-
-
-
-
-
-
-
- List Data Program Kemiskinan
-
-
-
-
-
- );
-}
-
-export default ProgramKemiskinan;
diff --git a/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/ui/statistik/page.tsx b/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/ui/statistik/page.tsx
deleted file mode 100644
index 0786257c..00000000
--- a/src/app/admin/(dashboard)/ekonomi/program-kemiskinan/ui/statistik/page.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import React from 'react';
-
-function StatistikKemiskinan() {
- return (
-
-
-
-
-
- Statistik Kemiskinan
- Tahun}
- placeholder="Masukkan tahun"
- />
- Jumlah Penduduk Miskin}
- placeholder="Masukkan jumlah penduduk miskin"
- />
-
-
- Submit
-
-
-
-
-
-
-
-
- Statistik Kemiskinan
-
-
-
-
-
- );
-}
-
-export default StatistikKemiskinan;
diff --git a/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/create/page.tsx b/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/create/page.tsx
new file mode 100644
index 00000000..bccbf601
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/create/page.tsx
@@ -0,0 +1,45 @@
+'use client'
+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 { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+
+function CreateSektorUnggulanDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Sektor Unggulan Desa
+ Nama Sektor Unggulan}
+ placeholder='Masukkan nama sektor unggulan'
+ />
+
+ Deskripsi Sektor Unggulan
+
+
+ Jumlah Sektor Unggulan}
+ placeholder='Masukkan jumlah sektor unggulan'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateSektorUnggulanDesa;
diff --git a/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/detail/page.tsx b/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/detail/page.tsx
new file mode 100644
index 00000000..815112d1
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/detail/page.tsx
@@ -0,0 +1,62 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailSektorUnggulanDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Sektor Unggulan Desa
+
+
+
+
+ Nama Sektor Unggulan
+ Petani
+
+
+ Deskripsi Sektor Unggulan
+ BIBD
+
+
+ Jumlah Sektor Unggulan
+ 200
+
+
+
+
+
+
+ router.push('/admin/ekonomi/sektor-unggulan-desa/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailSektorUnggulanDesa;
+
diff --git a/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/edit/page.tsx b/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/edit/page.tsx
new file mode 100644
index 00000000..541b7b21
--- /dev/null
+++ b/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/edit/page.tsx
@@ -0,0 +1,45 @@
+'use client'
+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 { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+
+function EditSektorUnggulanDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Sektor Unggulan Desa
+ Nama Sektor Unggulan}
+ placeholder='Masukkan nama sektor unggulan'
+ />
+
+ Deskripsi Sektor Unggulan
+
+
+ Jumlah Sektor Unggulan}
+ placeholder='Masukkan jumlah sektor unggulan'
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditSektorUnggulanDesa;
diff --git a/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/page.tsx b/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/page.tsx
index f308290e..2d0a122b 100644
--- a/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/page.tsx
+++ b/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/page.tsx
@@ -1,32 +1,56 @@
+'use client'
import colors from '@/con/colors';
-import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
-import React from 'react';
-import DataSektorUnggulan from './ui/data_sektor_unggulan/page';
-import GrafikDataSektor from './ui/grafik_data_sektor/page';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function SektorUnggulanDesa() {
return (
-
- Sektor Unggulan Desa
-
-
-
- Data Sektor Unggulan Desa
-
-
- Grafik Data Sektor Unggulan Desa
-
-
-
-
-
-
-
-
-
-
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListSektorUnggulanDesa() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Sektor Unggulan
+ Deskripsi Sektor Unggulan
+ Detail
+
+
+
+
+ Sektor 1
+ Deskripsi Sektor 1
+
+ router.push('/admin/ekonomi/sektor-unggulan-desa/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default SektorUnggulanDesa;
diff --git a/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/ui/data_sektor_unggulan/page.tsx b/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/ui/data_sektor_unggulan/page.tsx
deleted file mode 100644
index 7281ed4f..00000000
--- a/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/ui/data_sektor_unggulan/page.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
-import React from 'react';
-
-function DataSektorUnggulan() {
- return (
-
-
-
-
-
-
- Data Sektor Unggulan
- Nama Sektor Unggulan}
- placeholder="Masukkan nama sektor unggulan"
- />
- Deskripsi Sektor Unggulan}
- placeholder="Masukkan deskripsi sektor unggulan"
- />
-
-
- Submit
-
-
-
-
-
-
-
-
- Data Sektor Unggulan
-
-
-
-
-
-
- );
-}
-
-export default DataSektorUnggulan;
diff --git a/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/ui/grafik_data_sektor/page.tsx b/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/ui/grafik_data_sektor/page.tsx
deleted file mode 100644
index 5c9985e2..00000000
--- a/src/app/admin/(dashboard)/ekonomi/sektor-unggulan-desa/ui/grafik_data_sektor/page.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import React from 'react';
-
-function GrafikDataSektor() {
- return (
-
-
-
-
-
- Grafik Data Sektor Unggulan
- Nama Sektor Unggulan}
- placeholder="Masukkan nama sektor unggulan"
- />
- Jumlah Sektor Unggulan}
- placeholder="Masukkan jumlah sektor unggulan"
- />
-
-
- Submit
-
-
-
-
-
-
-
-
- Grafik Sektor Unggulan
-
-
-
-
-
-
- );
-}
-
-export default GrafikDataSektor;
diff --git a/src/app/admin/(dashboard)/inovasi/ajukan-ide-inovatif/page.tsx b/src/app/admin/(dashboard)/inovasi/ajukan-ide-inovatif/page.tsx
index 6ff04673..15c2392a 100644
--- a/src/app/admin/(dashboard)/inovasi/ajukan-ide-inovatif/page.tsx
+++ b/src/app/admin/(dashboard)/inovasi/ajukan-ide-inovatif/page.tsx
@@ -1,28 +1,43 @@
import colors from '@/con/colors';
import { Box, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Title } from '@mantine/core';
+import { IconSearch } from '@tabler/icons-react';
import React from 'react';
+import HeaderSearch from '../../_com/header';
-function Page() {
+function AjukanIdeInofativ() {
return (
-
-
-
- Ajukan Ide Inovatif
-
-
-
-
- No
- Nama
- Alamat
- Nama Ide Inovatif
- Deskripsi
- Masalah yang ingin diatasi
- Benefit
-
-
-
-
+
+ }
+ />
+
+
+ );
+}
+
+function ListAjukanIdeInovatif() {
+ return (
+
+
+
+ List Ajukan Ide Inovatif
+
+
+
+
+ No
+ Nama
+ Alamat
+ Nama Ide Inovatif
+ Deskripsi
+ Masalah yang ingin diatasi
+ Benefit
+
+
+
+
1
nama
@@ -32,13 +47,13 @@ function Page() {
masalah
benefit
-
-
-
-
-
-
- );
+
+
+
+
+
+
+ )
}
-export default Page;
+export default AjukanIdeInofativ;
diff --git a/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/create/page.tsx b/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/create/page.tsx
new file mode 100644
index 00000000..dce0a6f8
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/create/page.tsx
@@ -0,0 +1,49 @@
+'use client'
+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 { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+
+function CreateDesaDigital() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Desa Digital Smart Village
+ Nama Inovasi}
+ placeholder='Masukkan nama inovasi'
+ />
+ Deskripsi Singkat Inovasi}
+ placeholder='Masukkan deskripsi singkat inovasi'
+ />
+ Image}
+ placeholder='Masukkan image'
+ />
+
+ Deskripsi Inovasi
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateDesaDigital;
diff --git a/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/detail/page.tsx b/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/detail/page.tsx
new file mode 100644
index 00000000..0ba76e42
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/detail/page.tsx
@@ -0,0 +1,66 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconImageInPicture, IconX } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailDesaDigital() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Desa Digital Smart Village
+
+
+
+
+ Nama Inovasi
+ Pelayanan Admin Digital
+
+
+ Deskripsi Singkat Inovasi
+ Deskripsi Singkat Inovasi
+
+
+ Image
+
+
+
+ Deskripsi Inovasi
+ Deskripsi Inovasi
+
+
+
+
+
+
+ router.push('/admin/inovasi/desa-digital-smart-village/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailDesaDigital;
+
diff --git a/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/edit/page.tsx b/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/edit/page.tsx
new file mode 100644
index 00000000..a0526aac
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/edit/page.tsx
@@ -0,0 +1,49 @@
+'use client'
+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 { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+
+function EditDesaDigital() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Desa Digital Smart Village
+ Nama Inovasi}
+ placeholder='Masukkan nama inovasi'
+ />
+ Deskripsi Singkat Inovasi}
+ placeholder='Masukkan deskripsi singkat inovasi'
+ />
+ Image}
+ placeholder='Masukkan image'
+ />
+
+ Deskripsi Inovasi
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditDesaDigital;
diff --git a/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/page.tsx b/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/page.tsx
index 348012b2..cf6ed32c 100644
--- a/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/page.tsx
+++ b/src/app/admin/(dashboard)/inovasi/desa-digital-smart-village/page.tsx
@@ -1,50 +1,60 @@
+'use client'
import colors from '@/con/colors';
-import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import { IconImageInPicture } from '@tabler/icons-react';
-import React from 'react';
+import { Box, Button, Image, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function DesaDigitalSmartVillage() {
return (
-
-
-
-
- Create Data Desa Digital Smart Village
- Nama Desa Digital Smart Village}
- placeholder="Masukkan nama desa digital smart village"
- />
- Deskripsi Desa Digital Smart Village}
- placeholder="Masukkan deskripsi desa digital smart village"
- />
-
-
- Upload Gambar Desa Digital Smart Village
-
-
-
-
-
- Submit
-
-
-
-
-
-
-
-
- Create Data Desa Digital Smart Village
-
-
-
-
+ }
+ />
+
);
}
-export default Page;
+function ListDesaDigitalSmartVillage() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Inovasi
+ Deskripsi Singkat Inovasi
+ Image
+ Detail
+
+
+
+
+ Layanan Admin Digital
+ Deskripsi Singkat Inovasi
+
+
+
+
+ router.push('/admin/inovasi/desa-digital-smart-village/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default DesaDigitalSmartVillage;
diff --git a/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/create/page.tsx b/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/create/page.tsx
index 101f56e2..8da1f73f 100644
--- a/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/create/page.tsx
+++ b/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/create/page.tsx
@@ -1,34 +1,44 @@
+'use client'
import colors from '@/con/colors';
import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import { IconImageInPicture } from '@tabler/icons-react';
-import React from 'react';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
function CreateInfoTeknologiTepatGuna() {
+ const router = useRouter();
return (
-
-
-
- Create Info Teknologi Tepat Guna
-
- Masukkan Image
-
-
- Nama Info Teknologi Tepat Guna}
- placeholder="Masukkan nama info teknologi tepat guna"
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Info Teknologi Tepat Guna
+
+ Masukkan Image
+
+
+ Nama Info Teknologi Tepat Guna}
+ placeholder='Masukkan nama info teknologi tepat guna'
+ />
+
+ Deskripsi Info Teknologi Tepat Guna
+
- Deskripsi Info Teknologi Tepat Guna}
- placeholder="Masukkan deskripsi info teknologi tepat guna"
- />
-
- Submit
-
-
-
-
-
+
+
+ Submit
+
+
+
+
);
}
diff --git a/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/detail/page.tsx b/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/detail/page.tsx
new file mode 100644
index 00000000..13733e19
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/detail/page.tsx
@@ -0,0 +1,62 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailInfoTeknologiTepatGuna() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Info Teknologi Tepat Guna
+
+
+
+
+ Nama Info Teknologi Tepat Guna
+ Test Judul
+
+
+ Gambar
+
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+
+
+
+
+ router.push('/admin/inovasi/info-teknologi-tepat-guna/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailInfoTeknologiTepatGuna;
diff --git a/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/edit/page.tsx b/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/edit/page.tsx
new file mode 100644
index 00000000..c69b8370
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/edit/page.tsx
@@ -0,0 +1,45 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+
+function EditInfoTeknologiTepatGuna() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Info Teknologi Tepat Guna
+
+ Masukkan Image
+
+
+ Nama Info Teknologi Tepat Guna}
+ placeholder='Masukkan nama info teknologi tepat guna'
+ />
+
+ Deskripsi Info Teknologi Tepat Guna
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditInfoTeknologiTepatGuna;
diff --git a/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/listData/page.tsx b/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/listData/page.tsx
deleted file mode 100644
index 45f080e9..00000000
--- a/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/listData/page.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, SimpleGrid, Stack, Title } from '@mantine/core';
-import React from 'react';
-
-function ListDataInfoTeknologiTepatGuna() {
- return (
-
-
-
- List Data Info Teknologi Tepat Guna
-
-
- Data 1
-
-
- Data 2
-
-
- Data 3
-
-
- Data 4
-
-
-
-
-
- );
-}
-
-export default ListDataInfoTeknologiTepatGuna;
diff --git a/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/page.tsx b/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/page.tsx
index 68273de5..0d842475 100644
--- a/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/page.tsx
+++ b/src/app/admin/(dashboard)/inovasi/info-teknologi-tepat-guna/page.tsx
@@ -1,18 +1,58 @@
-import { Box, Stack, Title } from '@mantine/core';
-import React from 'react';
-import CreateInfoTeknologiTepatGuna from './create/page';
-import ListDataInfoTeknologiTepatGuna from './listData/page';
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function InfoTeknologiTepatGuna() {
return (
-
- Info Teknologi Tepat Guna
-
-
-
+ }
+ />
+
);
}
-export default Page;
+function ListInfoTeknologiTepatGuna() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Info Teknologi Tepat Guna
+ Image
+ Deskripsi
+ Detail
+
+
+
+
+ Info Teknologi Tepat Guna 1
+ Image
+ Deskripsi
+
+ router.push('/admin/inovasi/info-teknologi-tepat-guna/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default InfoTeknologiTepatGuna;
diff --git a/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/create/page.tsx b/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/create/page.tsx
new file mode 100644
index 00000000..4bfdf210
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/create/page.tsx
@@ -0,0 +1,50 @@
+'use client'
+import { KeamananEditor } from '@/app/admin/(dashboard)/keamanan/_com/keamananEditor';
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+
+
+function CreateKolaborasiInovasi() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Kolaborasi Inovasi
+
+ Masukkan Image
+
+
+ Nama Kolaborasi Inovasi}
+ placeholder='Masukkan nama kolaborasi inovasi'
+ />
+ Deskripsi Singkat Kolaborasi Inovasi}
+ placeholder='Masukkan deskripsi singkat kolaborasi inovasi'
+ />
+
+ Deskripsi Kolaborasi Inovasi
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateKolaborasiInovasi;
diff --git a/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/detail/page.tsx b/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/detail/page.tsx
new file mode 100644
index 00000000..b52fe1e8
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/detail/page.tsx
@@ -0,0 +1,66 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailKolaborasiInovasi() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Kolaborasi Inovasi
+
+
+
+
+ Nama Kolaborasi Inovasi
+ Test Judul
+
+
+ Gambar
+
+
+
+ Deskripsi Singkat
+ Test Deskripsi Singkat
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+
+
+
+
+ router.push('/admin/inovasi/kolaborasi-inovasi/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailKolaborasiInovasi;
diff --git a/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/edit/page.tsx b/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/edit/page.tsx
new file mode 100644
index 00000000..b3553f4e
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/edit/page.tsx
@@ -0,0 +1,49 @@
+'use client'
+import { KeamananEditor } from '@/app/admin/(dashboard)/keamanan/_com/keamananEditor';
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+
+function EditKolaborasiInovasi() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Kolaborasi Inovasi
+
+ Masukkan Image
+
+
+ Nama Kolaborasi Inovasi}
+ placeholder='Masukkan nama kolaborasi inovasi'
+ />
+ Deskripsi Singkat Kolaborasi Inovasi}
+ placeholder='Masukkan deskripsi singkat kolaborasi inovasi'
+ />
+
+ Deskripsi Kolaborasi Inovasi
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditKolaborasiInovasi;
diff --git a/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/page.tsx b/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/page.tsx
index 9ffe9a5d..7344cdb1 100644
--- a/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/page.tsx
+++ b/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/page.tsx
@@ -1,35 +1,58 @@
+'use client'
import colors from '@/con/colors';
-import { Box, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
-import React from 'react';
-import KolaborasiInovasi from './ui/kolaborasiInovasi/page';
-import MitraKolaborasi from './ui/mitraKolaborasi/page';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function KolaborasiInovasi() {
return (
-
- Kolaborasi Inovasi
-
-
-
- Kolaborasi Inovasi
-
-
- Mitra Kolaborasi
-
-
-
-
-
-
-
-
-
-
-
-
+ }
+ />
+
);
}
-export default Page;
+function ListKolaborasiInovasi() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Kolaborasi Inovasi
+ Image
+ Deskripsi Singkat
+ Detail
+
+
+
+
+ Kolaborasi Inovasi 1
+ Image
+ Deskripsi Singkat
+
+ router.push('/admin/inovasi/kolaborasi-inovasi/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default KolaborasiInovasi;
diff --git a/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/ui/kolaborasiInovasi/page.tsx b/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/ui/kolaborasiInovasi/page.tsx
deleted file mode 100644
index 06233369..00000000
--- a/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/ui/kolaborasiInovasi/page.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
-import React from 'react';
-
-function KolaborasiInovasi() {
- return (
-
-
-
-
-
- Create Kolaborasi Inovasi
- Tahun}
- placeholder="Masukkan tahun"
- />
- Nama Kolaborasi Inovasi}
- placeholder="Masukkan nama kolaborasi inovasi"
- />
- Deskripsi Kolaborasi Inovasi}
- placeholder="Masukkan deskripsi kolaborasi inovasi"
- />
-
-
-
-
-
-
- List Data Kolaborasi Inovasi
-
-
- Data 1
-
-
- Data 2
-
-
- Data 3
-
-
- Data 4
-
-
-
-
-
-
- );
-}
-
-export default KolaborasiInovasi;
diff --git a/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/ui/mitraKolaborasi/page.tsx b/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/ui/mitraKolaborasi/page.tsx
deleted file mode 100644
index bb82016e..00000000
--- a/src/app/admin/(dashboard)/inovasi/kolaborasi-inovasi/ui/mitraKolaborasi/page.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import React from 'react';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
-import colors from '@/con/colors';
-import { IconImageInPicture } from '@tabler/icons-react';
-
-function MitraKolaborasi() {
- return (
-
-
-
-
-
- Create Mitra Kolaborasi
- Nama Mitra Kolaborasi}
- placeholder="Masukkan nama mitra kolaborasi"
- />
-
- Masukkan Image
-
-
-
- Submit
-
-
-
-
-
-
- List Data Kolaborasi Inovasi
-
-
- Foto 1
-
-
- Foto 2
-
-
- Foto 3
-
-
- Foto 4
-
-
-
-
-
-
- );
-}
-
-export default MitraKolaborasi;
diff --git a/src/app/admin/(dashboard)/inovasi/layanan-online-desa/create/page.tsx b/src/app/admin/(dashboard)/inovasi/layanan-online-desa/create/page.tsx
new file mode 100644
index 00000000..a5a78206
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/layanan-online-desa/create/page.tsx
@@ -0,0 +1,44 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+function CreateLayananOnlineDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Layanan Online Desa
+
+ Masukkan Image
+
+
+ Nama Layanan Online Desa}
+ placeholder='Masukkan nama LayananOnlineDesa'
+ />
+
+ Deskripsi Layanan Online Desa
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateLayananOnlineDesa;
diff --git a/src/app/admin/(dashboard)/inovasi/layanan-online-desa/detail/page.tsx b/src/app/admin/(dashboard)/inovasi/layanan-online-desa/detail/page.tsx
new file mode 100644
index 00000000..ffa68d5e
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/layanan-online-desa/detail/page.tsx
@@ -0,0 +1,66 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailLayananOnlineDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Layanan Online Desa
+
+
+
+
+ Gambar
+
+
+
+ Nama Layanan Online Desa
+ Test Judul
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/inovasi/layanan-online-desa/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailLayananOnlineDesa;
diff --git a/src/app/admin/(dashboard)/inovasi/layanan-online-desa/edit/page.tsx b/src/app/admin/(dashboard)/inovasi/layanan-online-desa/edit/page.tsx
new file mode 100644
index 00000000..3f844e7f
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/layanan-online-desa/edit/page.tsx
@@ -0,0 +1,42 @@
+'use client'
+import colors from "@/con/colors";
+import { Box, Button, Paper, Stack, Title, TextInput, Group, Text } from "@mantine/core";
+import { IconArrowBack, IconImageInPicture } from "@tabler/icons-react";
+import { useRouter } from "next/navigation";
+import { KeamananEditor } from "../../../keamanan/_com/keamananEditor";
+
+export default function EditLayananOnlineDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Layanan Online Desa
+
+ Masukkan Image
+
+
+ Nama Layanan Online Desa}
+ placeholder='Masukkan nama LayananOnlineDesa'
+ />
+
+ Deskripsi Layanan Online Desa
+
+
+
+ Submit
+
+
+
+
+ );
+ }
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/inovasi/layanan-online-desa/page.tsx b/src/app/admin/(dashboard)/inovasi/layanan-online-desa/page.tsx
index 6274543f..2db5b2f7 100644
--- a/src/app/admin/(dashboard)/inovasi/layanan-online-desa/page.tsx
+++ b/src/app/admin/(dashboard)/inovasi/layanan-online-desa/page.tsx
@@ -1,41 +1,56 @@
+'use client'
import colors from '@/con/colors';
-import { Box, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import { IconImageInPicture } from '@tabler/icons-react';
-import React from 'react';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function LayananOnlineDesa() {
return (
-
-
-
-
- Layanan Online Desa
- Nama Layanan}
- placeholder="Masukkan nama layanan"
- />
- Deskripsi Layanan}
- placeholder="Masukkan deskripsi layanan"
- />
-
- Upload Gambar Layanan
-
-
-
-
-
-
-
-
- List Data Layanan Online Desa
-
-
-
-
+ }
+ />
+
);
}
-export default Page;
+function ListLayananOnlineDesa() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Layanan
+ Deskripsi
+ Detail
+
+
+
+
+ Layanan Online Desa 1
+ Deskripsi Layanan Online Desa 1
+
+ router.push('/admin/inovasi/layanan-online-desa/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default LayananOnlineDesa;
diff --git a/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/create/page.tsx b/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/create/page.tsx
index 73761550..9894191c 100644
--- a/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/create/page.tsx
+++ b/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/create/page.tsx
@@ -1,37 +1,49 @@
+'use client'
import colors from '@/con/colors';
import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import { IconImageInPicture } from '@tabler/icons-react';
-import React from 'react';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
-function ProgramKreatifCreate() {
+
+function CreateProgramKreatifDesa() {
+ const router = useRouter();
return (
-
-
-
- Create Program Kreatif Desa
-
- Gambar
-
-
- Nama Program}
- placeholder="Masukkan nama program"
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Program Kreatif Desa
+
+ Masukkan Image
+
+
+ Nama Program Kreatif Desa}
+ placeholder='Masukkan nama program kreatif desa'
+ />
+ Deskripsi Singkat Program Kreatif Desa}
+ placeholder='Masukkan deskripsi singkat program kreatif desa'
+ />
+
+ Deskripsi Program Kreatif Desa
+
- Deskripsi}
- placeholder="Masukkan deskripsi"
- />
-
- Simpan
-
-
-
-
-
+
+
+ Submit
+
+
+
+
);
}
-export default ProgramKreatifCreate;
+export default CreateProgramKreatifDesa;
diff --git a/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/detail/page.tsx b/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/detail/page.tsx
new file mode 100644
index 00000000..aa154fd2
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/detail/page.tsx
@@ -0,0 +1,66 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailProgramKreatifDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Program Kreatif Desa
+
+
+
+
+ Nama Program Kreatif Desa
+ Test Judul
+
+
+ Gambar
+
+
+
+ Deskripsi Singkat
+ Test Deskripsi Singkat
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+
+
+
+
+ router.push('/admin/inovasi/program-kreatif-desa/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailProgramKreatifDesa;
diff --git a/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/edit/page.tsx b/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/edit/page.tsx
new file mode 100644
index 00000000..7368cb26
--- /dev/null
+++ b/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/edit/page.tsx
@@ -0,0 +1,49 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+
+function EditProgramKreatifDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Program Kreatif Desa
+
+ Masukkan Image
+
+
+ Nama Program Kreatif Desa}
+ placeholder='Masukkan nama Program Kreatif Desa'
+ />
+ Deskripsi Singkat Program Kreatif Desa}
+ placeholder='Masukkan deskripsi singkat program kreatif desa'
+ />
+
+ Deskripsi Program Kreatif Desa
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditProgramKreatifDesa;
diff --git a/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/listData/page.tsx b/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/listData/page.tsx
deleted file mode 100644
index 4089bed5..00000000
--- a/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/listData/page.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, SimpleGrid, Stack, Title } from '@mantine/core';
-import React from 'react';
-
-function ListDataProgramKreatifDesa() {
- return (
-
-
- List Data Program Kreatif Desa
-
-
- Data 1
-
-
- Data 2
-
-
- Data 3
-
-
- Data 4
-
-
-
-
- );
-}
-
-export default ListDataProgramKreatifDesa;
diff --git a/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/page.tsx b/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/page.tsx
index c529c95d..50ed41fc 100644
--- a/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/page.tsx
+++ b/src/app/admin/(dashboard)/inovasi/program-kreatif-desa/page.tsx
@@ -1,18 +1,58 @@
-import { Box, Stack, Title } from '@mantine/core';
-import React from 'react';
-import ProgramKreatifCreate from './create/page';
-import ListDataProgramKreatifDesa from './listData/page';
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function ProgramKreatifDesa() {
return (
-
- Program Kreatif Desa
-
-
-
+ }
+ />
+
);
}
-export default Page;
+function ListProgramKreatifDesa() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Program Kreatif Desa
+ Image
+ Deskripsi Singkat
+ Detail
+
+
+
+
+ Program Kreatif Desa 1
+ Image
+ Deskripsi Singkat
+
+ router.push('/admin/inovasi/program-kreatif-desa/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default ProgramKreatifDesa;
diff --git a/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/create/page.tsx b/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/create/page.tsx
new file mode 100644
index 00000000..224b81fe
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/create/page.tsx
@@ -0,0 +1,44 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function CreateKeamananLingkungan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Keamanan Lingkungan
+
+ Masukkan Image
+
+
+ Nama Keamanan Lingkungan}
+ placeholder='Masukkan nama KeamananLingkungan'
+ />
+
+ Deskripsi KeamananLingkungan
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateKeamananLingkungan;
diff --git a/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/detail/page.tsx b/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/detail/page.tsx
new file mode 100644
index 00000000..e7d52a38
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/detail/page.tsx
@@ -0,0 +1,70 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailKeamananLingkungan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Keamanan Lingkungan
+
+
+
+
+ Nama Keamanan Lingkungan
+ Test Judul
+
+
+ Nomor Keamanan Lingkungan
+ Test Kategori
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/keamanan/keamanan-lingkungan-pecalang-patwal/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailKeamananLingkungan;
diff --git a/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/edit/page.tsx b/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/edit/page.tsx
new file mode 100644
index 00000000..35be3435
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/edit/page.tsx
@@ -0,0 +1,44 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function EditKeamananLingkungan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Keamanan Lingkungan
+
+ Masukkan Image
+
+
+ Nama Keamanan Lingkungan}
+ placeholder='Masukkan nama Keamanan Lingkungan'
+ />
+
+ Deskripsi Keamanan Lingkungan
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditKeamananLingkungan;
diff --git a/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/page.tsx b/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/page.tsx
index 7b7edc9f..7a6cefe7 100644
--- a/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/page.tsx
+++ b/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/page.tsx
@@ -1,36 +1,58 @@
+'use client'
import colors from '@/con/colors';
-import { Box, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
-import React from 'react';
-import CreateKeamananLingkungan from './ui/tambah_keamanan_lingkungan/page';
-import ListKeamananLingkungan from './ui/list_keamanan_lingkungan/page';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-
-function Page() {
+function KeamananLingkungan() {
return (
-
- Keamanan Lingkungan
-
-
-
- Tambah Keamanan Lingkungan
-
-
- List Keamanan Lingkungan
-
-
-
-
-
-
-
-
-
-
-
-
+ }
+ />
+
);
}
-export default Page;
+function ListKeamananLingkungan() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Keamanan Lingkungan
+ Nomor Keamanan Lingkungan
+ Deskripsi
+ Detail
+
+
+
+
+ Keamanan Lingkungan 1
+ 0896232831883
+ Keamanan Lingkungan 1
+
+ router.push('/admin/keamanan/keamanan-lingkungan-pecalang-patwal/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default KeamananLingkungan;
diff --git a/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/ui/list_keamanan_lingkungan/page.tsx b/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/ui/list_keamanan_lingkungan/page.tsx
deleted file mode 100644
index df888243..00000000
--- a/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/ui/list_keamanan_lingkungan/page.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { Box, Paper, Stack, Table, TableTbody, TableTh, TableThead, TableTr, Title } from '@mantine/core';
-import colors from '@/con/colors';
-import React from 'react';
-
-function ListKeamananLingkungan() {
- return (
-
-
-
- List Keamanan Lingkungan
-
-
-
-
- Image
- Nama Keamanan Lingkungan
- Deskripsi Keamanan Lingkungan
- Aksi
- Detail
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default ListKeamananLingkungan;
diff --git a/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/ui/tambah_keamanan_lingkungan/page.tsx b/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/ui/tambah_keamanan_lingkungan/page.tsx
deleted file mode 100644
index 1d556e92..00000000
--- a/src/app/admin/(dashboard)/keamanan/keamanan-lingkungan-pecalang-patwal/ui/tambah_keamanan_lingkungan/page.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
-import { IconImageInPicture } from '@tabler/icons-react';
-import React from 'react';
-import { KeamananEditor } from '../../../_com/keamananEditor';
-
-
-function KeamananLingkungan() {
- return (
-
-
-
-
-
-
- Tambah Keamanan Lingkungan
-
- Masukkan Image
-
-
- Nama Keamanan Lingkungan}
- placeholder='Masukkan nama keamanan lingkungan'
- />
-
- Deskripsi Keamanan Lingkungan
-
-
-
- Submit
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default KeamananLingkungan;
diff --git a/src/app/admin/(dashboard)/keamanan/kontak-darurat/create/createKontak.tsx b/src/app/admin/(dashboard)/keamanan/kontak-darurat/create/createKontak.tsx
deleted file mode 100644
index 98ebd6ab..00000000
--- a/src/app/admin/(dashboard)/keamanan/kontak-darurat/create/createKontak.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Stack, Text, TextInput } from '@mantine/core';
-import { IconImageInPicture } from '@tabler/icons-react';
-
-function CreateKontakDarurat() {
- return (
-
-
- Judul Kontak Darurat}
- placeholder="masukkan judul kontak darurat"
- />
-
- Nama Kontak Darurat}
- placeholder="masukkan nama kontak darurat"
- />
-
- Nomor Kontak Darurat}
- placeholder="masukkan nomor kontak darurat"
- />
-
-
- );
-}
-
-export default CreateKontakDarurat;
diff --git a/src/app/admin/(dashboard)/keamanan/kontak-darurat/create/page.tsx b/src/app/admin/(dashboard)/keamanan/kontak-darurat/create/page.tsx
new file mode 100644
index 00000000..b9b314ee
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/kontak-darurat/create/page.tsx
@@ -0,0 +1,44 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function CreateKontakDarurat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Kontak Darurat
+
+ Masukkan Image
+
+
+ Nama Kontak Darurat}
+ placeholder='Masukkan nama Kontak Darurat'
+ />
+
+ Deskripsi Kontak Darurat
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateKontakDarurat;
diff --git a/src/app/admin/(dashboard)/keamanan/kontak-darurat/detail/page.tsx b/src/app/admin/(dashboard)/keamanan/kontak-darurat/detail/page.tsx
new file mode 100644
index 00000000..e6473fe5
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/kontak-darurat/detail/page.tsx
@@ -0,0 +1,70 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailKontakDarurat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Kontak Darurat
+
+
+
+
+ Nama Kontak Darurat
+ Test Judul
+
+
+ Nomor Kontak Darurat
+ Test Kategori
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/keamanan/kontak-darurat/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailKontakDarurat;
diff --git a/src/app/admin/(dashboard)/keamanan/kontak-darurat/edit/page.tsx b/src/app/admin/(dashboard)/keamanan/kontak-darurat/edit/page.tsx
new file mode 100644
index 00000000..06b4bf60
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/kontak-darurat/edit/page.tsx
@@ -0,0 +1,44 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function EditKontakDarurat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Kontak Darurat
+
+ Masukkan Image
+
+
+ Nama Kontak Darurat}
+ placeholder='Masukkan nama Kontak Darurat'
+ />
+
+ Deskripsi Kontak Darurat
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditKontakDarurat;
diff --git a/src/app/admin/(dashboard)/keamanan/kontak-darurat/listData/page.tsx b/src/app/admin/(dashboard)/keamanan/kontak-darurat/listData/page.tsx
deleted file mode 100644
index 6de1176b..00000000
--- a/src/app/admin/(dashboard)/keamanan/kontak-darurat/listData/page.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Text, Title } from '@mantine/core';
-import React from 'react';
-
-function ListDataKontakDarurat() {
- return (
-
-
- List Data Kontak Darurat
-
- Judul Kontak Darurat
-
- Nama Kontak Darurat
-
- Nomor Kontak Darurat
-
-
-
-
- );
-}
-
-export default ListDataKontakDarurat;
diff --git a/src/app/admin/(dashboard)/keamanan/kontak-darurat/page.tsx b/src/app/admin/(dashboard)/keamanan/kontak-darurat/page.tsx
index 10f224ff..4d424d7a 100644
--- a/src/app/admin/(dashboard)/keamanan/kontak-darurat/page.tsx
+++ b/src/app/admin/(dashboard)/keamanan/kontak-darurat/page.tsx
@@ -1,31 +1,58 @@
+'use client'
import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Title } from '@mantine/core';
-import React from 'react';
-import CreateKontakDarurat from './create/createKontak';
-import ListDataKontakDarurat from './listData/page';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function KontakDaurat() {
return (
-
-
-
-
- Kontak Darurat
-
-
-
- Submit
-
-
-
-
-
-
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListKontakDaurat() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Kontak Darurat
+ Nomor Kontak Darurat
+ Deskripsi
+ Detail
+
+
+
+
+ Kontak Darurat 1
+ 0896232831883
+ Kontak Darurat 1
+
+ router.push('/admin/keamanan/kontak-darurat/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default KontakDaurat;
diff --git a/src/app/admin/(dashboard)/keamanan/laporan-publik/create/createLaporan.tsx b/src/app/admin/(dashboard)/keamanan/laporan-publik/create/createLaporan.tsx
deleted file mode 100644
index 72943bb3..00000000
--- a/src/app/admin/(dashboard)/keamanan/laporan-publik/create/createLaporan.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import { Box, Stack, Text, TextInput } from '@mantine/core';
-import React from 'react';
-import { KeamananEditor } from '../../_com/keamananEditor';
-
-
-function CreateLaporanPublik() {
- return (
-
-
- Judul Laporan Publik}
- placeholder="masukkan judul laporan publik"
- />
- Tanggal Laporan Publik}
- placeholder="masukkan tanggal laporan publik"
- />
-
- Deskripsi Laporan Publik
-
-
-
-
- );
-}
-
-export default CreateLaporanPublik;
diff --git a/src/app/admin/(dashboard)/keamanan/laporan-publik/create/page.tsx b/src/app/admin/(dashboard)/keamanan/laporan-publik/create/page.tsx
new file mode 100644
index 00000000..0b0cdbe2
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/laporan-publik/create/page.tsx
@@ -0,0 +1,48 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function CreateLaporanPublik() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Laporan Publik
+
+ Masukkan Image
+
+
+ Judul Laporan Publik}
+ placeholder='Masukkan judul LaporanPublik'
+ />
+ Tanggal Laporan Publik}
+ placeholder='Masukkan tanggal LaporanPublik'
+ />
+
+ Deskripsi Laporan Publik
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateLaporanPublik;
diff --git a/src/app/admin/(dashboard)/keamanan/laporan-publik/detail/page.tsx b/src/app/admin/(dashboard)/keamanan/laporan-publik/detail/page.tsx
new file mode 100644
index 00000000..2283733d
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/laporan-publik/detail/page.tsx
@@ -0,0 +1,70 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailLaporanPublik() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Laporan Publik
+
+
+
+
+ Judul Laporan Publik
+ Test Judul
+
+
+ Tanggal Laporan Publik
+ Test Tanggal
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/keamanan/laporan-publik/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailLaporanPublik;
diff --git a/src/app/admin/(dashboard)/keamanan/laporan-publik/edit/page.tsx b/src/app/admin/(dashboard)/keamanan/laporan-publik/edit/page.tsx
new file mode 100644
index 00000000..59408928
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/laporan-publik/edit/page.tsx
@@ -0,0 +1,48 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function EditLaporanPublik() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Laporan Publik
+
+ Masukkan Image
+
+
+ Judul Laporan Publik}
+ placeholder='Masukkan judul Laporan Publik'
+ />
+ Tanggal Laporan Publik}
+ placeholder='Masukkan tanggal Laporan Publik'
+ />
+
+ Deskripsi Laporan Publik
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditLaporanPublik;
diff --git a/src/app/admin/(dashboard)/keamanan/laporan-publik/listData/page.tsx b/src/app/admin/(dashboard)/keamanan/laporan-publik/listData/page.tsx
deleted file mode 100644
index 7acdb40b..00000000
--- a/src/app/admin/(dashboard)/keamanan/laporan-publik/listData/page.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import React from 'react';
-import { Box, Paper, Stack, Text, Title } from '@mantine/core';
-import colors from '@/con/colors';
-
-function ListDataLaporanPublik() {
- return (
-
-
- List Data Laporan Publik
-
- Judul Laporan Publik
-
- Tanggal Laporan Publik
-
- Deskripsi Laporan Publik
-
-
-
-
- );
-}
-
-export default ListDataLaporanPublik;
diff --git a/src/app/admin/(dashboard)/keamanan/laporan-publik/page.tsx b/src/app/admin/(dashboard)/keamanan/laporan-publik/page.tsx
index 0dcd6de5..afd521cb 100644
--- a/src/app/admin/(dashboard)/keamanan/laporan-publik/page.tsx
+++ b/src/app/admin/(dashboard)/keamanan/laporan-publik/page.tsx
@@ -1,28 +1,58 @@
-import colors from "@/con/colors";
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Title } from "@mantine/core";
-import CreateLaporanPublik from "./create/createLaporan";
-import ListDataLaporanPublik from "./listData/page";
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-export default function Page() {
+function LaporanPublik() {
return (
-
-
-
-
- Laporan Publik
-
-
-
- Submit
-
-
-
-
-
-
-
- )
-}
\ No newline at end of file
+
+ }
+ />
+
+
+ );
+}
+
+function ListLaporanPublik() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Judul Laporan Publik
+ Tanggal Laporan Publik
+ Deskripsi
+ Detail
+
+
+
+
+ Laporan Publik 1
+ 0896232831883
+ Laporan Publik 1
+
+ router.push('/admin/keamanan/laporan-publik/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default LaporanPublik;
diff --git a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/create/createPencegahan.tsx b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/create/createPencegahan.tsx
deleted file mode 100644
index 3a7cf61b..00000000
--- a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/create/createPencegahan.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Stack, Text, TextInput } from '@mantine/core';
-import { IconImageInPicture } from '@tabler/icons-react';
-import React from 'react';
-
-function CreatePencegahan() {
- return (
-
-
- Judul Pencegahan Kriminalitas}
- placeholder="masukkan judul pencegahan kriminalitas"
- />
- Deskripsi Pencegahan Kriminalitas}
- placeholder="masukkan deskripsi pencegahan kriminalitas"
- />
- Gambar Pencegahan Kriminalitas
-
-
-
- );
-}
-
-export default CreatePencegahan;
diff --git a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/create/page.tsx b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/create/page.tsx
new file mode 100644
index 00000000..3d4445bc
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/create/page.tsx
@@ -0,0 +1,44 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function CreatePencegahanKriminalitas() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Pencegahan Kriminalitas
+
+ Masukkan Image
+
+
+ Nama Pencegahan Kriminalitas}
+ placeholder='Masukkan nama Pencegahan Kriminalitas'
+ />
+
+ Deskripsi Pencegahan Kriminalitas
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreatePencegahanKriminalitas;
diff --git a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/detail/page.tsx b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/detail/page.tsx
new file mode 100644
index 00000000..4a052948
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/detail/page.tsx
@@ -0,0 +1,70 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailPencegahanKriminalitas() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Pencegahan Kriminalitas
+
+
+
+
+ Nama Pencegahan Kriminalitas
+ Test Judul
+
+
+ Nomor Pencegahan Kriminalitas
+ Test Kategori
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/keamanan/pencegahan-kriminalitas/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailPencegahanKriminalitas;
diff --git a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/edit/page.tsx b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/edit/page.tsx
new file mode 100644
index 00000000..dd1afee7
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/edit/page.tsx
@@ -0,0 +1,44 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function EditPencegahanKriminalitas() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Pencegahan Kriminalitas
+
+ Masukkan Image
+
+
+ Nama Pencegahan Kriminalitas}
+ placeholder='Masukkan nama Pencegahan Kriminalitas'
+ />
+
+ Deskripsi Pencegahan Kriminalitas
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditPencegahanKriminalitas;
diff --git a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/listData/page.tsx b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/listData/page.tsx
deleted file mode 100644
index 4153abe6..00000000
--- a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/listData/page.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Text, Title } from '@mantine/core';
-import React from 'react';
-
-function ListDataPencegahan() {
- return (
-
-
- List Data Pencegahan Kriminalitas
-
- Judul Pencegahan Kriminalitas
-
- Deskripsi Pencegahan Kriminalitas
-
- Gambar Pencegahan Kriminalitas
-
-
-
-
- );
-}
-
-export default ListDataPencegahan;
diff --git a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/page.tsx b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/page.tsx
index be34aed5..99816ed1 100644
--- a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/page.tsx
+++ b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/page.tsx
@@ -1,32 +1,58 @@
+'use client'
import colors from '@/con/colors';
-import { Stack, SimpleGrid, Box, Paper, Title, Group, Button } from '@mantine/core';
-import React from 'react';
-import CreatePencegahan from './create/createPencegahan';
-import ListDataPencegahan from './listData/page';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-
-function Page() {
+function PencegahanKriminalitas() {
return (
-
-
-
-
- Kontak Darurat
-
-
-
- Submit
-
-
-
-
-
-
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListPencegahanKriminalitas() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Pencegahan Kriminalitas
+ Nomor Pencegahan Kriminalitas
+ Deskripsi
+ Detail
+
+
+
+
+ Pencegahan Kriminalitas 1
+ 0896232831883
+ Pencegahan Kriminalitas 1
+
+ router.push('/admin/keamanan/pencegahan-kriminalitas/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default PencegahanKriminalitas;
diff --git a/src/app/admin/(dashboard)/keamanan/polsek-terdekat/create/page.tsx b/src/app/admin/(dashboard)/keamanan/polsek-terdekat/create/page.tsx
new file mode 100644
index 00000000..86e957a5
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/polsek-terdekat/create/page.tsx
@@ -0,0 +1,44 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function CreatePolsekTerdekat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Polsek Terdekat
+
+ Masukkan Image
+
+
+ Nama Polsek Terdekat}
+ placeholder='Masukkan nama Polsek Terdekat'
+ />
+
+ Deskripsi Polsek Terdekat
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreatePolsekTerdekat;
diff --git a/src/app/admin/(dashboard)/keamanan/polsek-terdekat/detail/page.tsx b/src/app/admin/(dashboard)/keamanan/polsek-terdekat/detail/page.tsx
new file mode 100644
index 00000000..b981cb6f
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/polsek-terdekat/detail/page.tsx
@@ -0,0 +1,70 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailPolsekTerdekat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Polsek Terdekat
+
+
+
+
+ Nama Polsek Terdekat
+ Test Judul
+
+
+ Nomor Polsek Terdekat
+ Test Kategori
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/keamanan/polsek-terdekat/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailPolsekTerdekat;
diff --git a/src/app/admin/(dashboard)/keamanan/polsek-terdekat/edit/page.tsx b/src/app/admin/(dashboard)/keamanan/polsek-terdekat/edit/page.tsx
new file mode 100644
index 00000000..ef12dd43
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/polsek-terdekat/edit/page.tsx
@@ -0,0 +1,44 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function EditPolsekTerdekat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Polsek Terdekat
+
+ Masukkan Image
+
+
+ Nama Polsek Terdekat}
+ placeholder='Masukkan nama Polsek Terdekat'
+ />
+
+ Deskripsi Polsek Terdekat
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditPolsekTerdekat;
diff --git a/src/app/admin/(dashboard)/keamanan/polsek-terdekat/page.tsx b/src/app/admin/(dashboard)/keamanan/polsek-terdekat/page.tsx
index 92031007..7d8d8e51 100644
--- a/src/app/admin/(dashboard)/keamanan/polsek-terdekat/page.tsx
+++ b/src/app/admin/(dashboard)/keamanan/polsek-terdekat/page.tsx
@@ -1,36 +1,58 @@
+'use client'
import colors from '@/con/colors';
-import { Box, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
-import React from 'react';
-import CreatePolsekTerdekat from './ui/tambah_polsek_terdekat/page';
-import ListPolsekTerdekat from './ui/list_polsek_terdekat/page';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-
-function Page() {
+function PolsekTerdekat() {
return (
-
- Polsek Terdekat
-
-
-
- Tambah Polsek Terdekat
-
-
- List Polsek Terdekat
-
-
-
-
-
-
-
-
-
-
-
-
+ }
+ />
+
);
}
-export default Page;
+function ListPolsekTerdekat() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Polsek Terdekat
+ Nomor Polsek Terdekat
+ Deskripsi
+ Detail
+
+
+
+
+ Polsek Terdekat 1
+ 0896232831883
+ Polsek Terdekat 1
+
+ router.push('/admin/keamanan/polsek-terdekat/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default PolsekTerdekat;
diff --git a/src/app/admin/(dashboard)/keamanan/polsek-terdekat/ui/list_polsek_terdekat/page.tsx b/src/app/admin/(dashboard)/keamanan/polsek-terdekat/ui/list_polsek_terdekat/page.tsx
deleted file mode 100644
index 7c119c36..00000000
--- a/src/app/admin/(dashboard)/keamanan/polsek-terdekat/ui/list_polsek_terdekat/page.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import { Box, Paper, Stack, Table, TableTbody, TableTh, TableThead, TableTr, Title } from '@mantine/core';
-import colors from '@/con/colors';
-import React from 'react';
-
-function ListPolsekTerdekat() {
- return (
-
-
-
- List Polsek Terdekat
-
-
-
-
- Nama Polsek Terdekat
- Jarak Polsek Terdekat
- Alamat Polsek Terdekat
- Nomor Telepon Polsek Terdekat
- Jam Aktif
- Deskripsi Polsek Terdekat
- Aksi
- Detail
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default ListPolsekTerdekat;
diff --git a/src/app/admin/(dashboard)/keamanan/polsek-terdekat/ui/tambah_polsek_terdekat/page.tsx b/src/app/admin/(dashboard)/keamanan/polsek-terdekat/ui/tambah_polsek_terdekat/page.tsx
deleted file mode 100644
index ba2a4c32..00000000
--- a/src/app/admin/(dashboard)/keamanan/polsek-terdekat/ui/tambah_polsek_terdekat/page.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
-import { KeamananEditor } from '../../../_com/keamananEditor';
-
-
-function CreatePolsekTerdekat() {
- return (
-
-
-
-
-
-
- Tambah Polsek Terdekat
- Nama Polsek Terdekat}
- placeholder='Masukkan nama polsek terdekat'
- />
- Jarak Polsek Terdekat}
- placeholder='Masukkan jarak polsek terdekat'
- />
- Alamat Polsek Terdekat}
- placeholder='Masukkan alamat polsek terdekat'
- />
- Nomor Telepon Polsek Terdekat}
- placeholder='Masukkan nomor telepon polsek terdekat'
- />
- Jam Aktif}
- placeholder='Masukkan jam aktif polsek terdekat'
- />
-
- Deskripsi Polsek Terdekat
-
-
-
- Submit
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default CreatePolsekTerdekat;
diff --git a/src/app/admin/(dashboard)/keamanan/tips-keamanan/create/createTips.tsx b/src/app/admin/(dashboard)/keamanan/tips-keamanan/create/createTips.tsx
deleted file mode 100644
index 4fb1ada6..00000000
--- a/src/app/admin/(dashboard)/keamanan/tips-keamanan/create/createTips.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Stack, Text, TextInput } from '@mantine/core';
-import { IconImageInPicture } from '@tabler/icons-react';
-import React from 'react';
-import { KeamananEditor } from '../../_com/keamananEditor';
-
-function CreateTipsKeamanan() {
- return (
-
-
- Judul Tips Keamanan}
- placeholder="masukkan judul tips keamanan"
- />
-
- Upload Gambar
-
-
-
-
-
- );
-}
-
-export default CreateTipsKeamanan;
diff --git a/src/app/admin/(dashboard)/keamanan/tips-keamanan/create/page.tsx b/src/app/admin/(dashboard)/keamanan/tips-keamanan/create/page.tsx
new file mode 100644
index 00000000..7012f30a
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/tips-keamanan/create/page.tsx
@@ -0,0 +1,44 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function CreateTipsKeamanan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Tips Keamanan
+
+ Masukkan Image
+
+
+ Nama Tips Keamanan}
+ placeholder='Masukkan nama tips keamanan'
+ />
+
+ Deskripsi Tips Keamanan
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateTipsKeamanan;
diff --git a/src/app/admin/(dashboard)/keamanan/tips-keamanan/detail/page.tsx b/src/app/admin/(dashboard)/keamanan/tips-keamanan/detail/page.tsx
new file mode 100644
index 00000000..194c46aa
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/tips-keamanan/detail/page.tsx
@@ -0,0 +1,70 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailTipsKeamanan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Tips Keamanan
+
+
+
+
+ Nama Tips Keamanan
+ Test Judul
+
+
+ Nomor Tips Keamanan
+ Test Kategori
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/keamanan/tips-keamanan/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailTipsKeamanan;
diff --git a/src/app/admin/(dashboard)/keamanan/tips-keamanan/edit/page.tsx b/src/app/admin/(dashboard)/keamanan/tips-keamanan/edit/page.tsx
new file mode 100644
index 00000000..fe6d6a9f
--- /dev/null
+++ b/src/app/admin/(dashboard)/keamanan/tips-keamanan/edit/page.tsx
@@ -0,0 +1,44 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../_com/keamananEditor';
+
+function EditTipsKeamanan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Tips Keamanan
+
+ Masukkan Image
+
+
+ Nama Tips Keamanan}
+ placeholder='Masukkan nama Tips Keamanan'
+ />
+
+ Deskripsi Tips Keamanan
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditTipsKeamanan;
diff --git a/src/app/admin/(dashboard)/keamanan/tips-keamanan/listData/page.tsx b/src/app/admin/(dashboard)/keamanan/tips-keamanan/listData/page.tsx
deleted file mode 100644
index 4bead65a..00000000
--- a/src/app/admin/(dashboard)/keamanan/tips-keamanan/listData/page.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import colors from '@/con/colors';
-import { Box, Paper, Stack, Text, Title } from '@mantine/core';
-import { IconImageInPicture } from '@tabler/icons-react';
-import React from 'react';
-
-function ListDataTipsKeamanan() {
- return (
-
-
- List Data Tips Keamanan
-
- Judul Tips Keamanan
-
- Gambar Tips Keamanan
-
- Deskripsi Tips Keamanan
-
-
-
-
- );
-}
-
-export default ListDataTipsKeamanan;
diff --git a/src/app/admin/(dashboard)/keamanan/tips-keamanan/page.tsx b/src/app/admin/(dashboard)/keamanan/tips-keamanan/page.tsx
index e1b672b8..995fba9d 100644
--- a/src/app/admin/(dashboard)/keamanan/tips-keamanan/page.tsx
+++ b/src/app/admin/(dashboard)/keamanan/tips-keamanan/page.tsx
@@ -1,31 +1,58 @@
+'use client'
import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Title } from '@mantine/core';
-import React from 'react';
-import CreateTipsKeamanan from './create/createTips';
-import ListDataTipsKeamanan from './listData/page';
+import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
+import HeaderSearch from '../../_com/header';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function TipsKeamanan() {
return (
-
-
-
-
- Tips Keamanan
-
-
-
- Submit
-
-
-
-
-
-
-
- )
+
+ }
+ />
+
+
+ );
}
-export default Page;
+function ListTipsKeamanan() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+ Nama Tips Keamanan
+ Nomor Tips Keamanan
+ Deskripsi
+ Detail
+
+
+
+
+ Tips Keamanan 1
+ 0896232831883
+ Tips Keamanan 1
+
+ router.push('/admin/keamanan/tips-keamanan/detail')}>
+
+
+
+
+
+
+
+
+ );
+}
+
+export default TipsKeamanan;
diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/detail/page.tsx
index 329fea96..2b9163d5 100644
--- a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/detail/page.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/detail/page.tsx
@@ -1,33 +1,70 @@
-import { Box, Paper, Stack, Table, TableTbody, TableTh, TableThead, TableTr, Title } from '@mantine/core';
+'use client'
import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
-function ListInfoWabahPenyakit() {
+function DetailInfoWabahPenyakit() {
+ const router = useRouter();
return (
-
-
- List Info Wabah/Penyakit
-
-
-
-
- Image
- Nama Info Wabah/Penyakit
- Deskripsi Info Wabah/Penyakit
- Aksi
- Detail
-
-
-
-
-
-
-
+
+ router.back()}>
+
+
+
+
+
+ Detail Info Wabah/Penyakit
+
+
+
+
+ Nama Info Wabah/Penyakit
+ Test Judul
+
+
+ Deskripsi Info Wabah/Penyakit
+ Test Kategori
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/kesehatan/info-wabah-penyakit/edit')} color="green">
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus penanganan darurat ini?"
+ /> */}
);
}
-export default ListInfoWabahPenyakit;
+export default DetailInfoWabahPenyakit;
diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/edit/page.tsx
new file mode 100644
index 00000000..885ce912
--- /dev/null
+++ b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/edit/page.tsx
@@ -0,0 +1,62 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Stack, SimpleGrid, Paper, Title, TextInput, Text, Button, Image } from '@mantine/core';
+import { KesehatanEditor } from '../../_com/kesehatanEditor';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+
+function EditInfoWabahPenyakit() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+
+
+
+ Edit Info Wabah/Penyakit
+ Nama Info Wabah/Penyakit}
+ placeholder='Masukkan nama Info Wabah/Penyakit'
+ />
+ Deskripsi Info Wabah/Penyakit}
+ placeholder='Masukkan deskripsi Info Wabah/Penyakit'
+ />
+
+ Deskripsi
+
+
+
+ Gambar
+
+
+
+
+
+
+
+
+ Preview Data Info Wabah/Penyakit
+ Nama Info Wabah/Penyakit
+ Deskripsi Info Wabah/Penyakit
+ Deskripsi
+ Gambar
+
+
+
+
+
+
+ );
+}
+
+export default EditInfoWabahPenyakit;
diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/page.tsx
index ce902a41..9ce24e0f 100644
--- a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/page.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/page.tsx
@@ -1,8 +1,10 @@
+'use client'
import colors from '@/con/colors';
import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import JudulList from '../../_com/judulList';
import HeaderSearch from '../../_com/header';
+import { useRouter } from 'next/navigation';
function InfoWabahPenyakit() {
return (
@@ -18,6 +20,7 @@ function InfoWabahPenyakit() {
}
function ListInfoWabahPenyakit() {
+ const router = useRouter()
return (
@@ -47,7 +50,7 @@ function ListInfoWabahPenyakit() {
-
+ router.push('/admin/kesehatan/info-wabah-penyakit/detail')}>
diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/detail/page.tsx
new file mode 100644
index 00000000..7ed97108
--- /dev/null
+++ b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/detail/page.tsx
@@ -0,0 +1,70 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailKontakDarurat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Kontak Darurat
+
+
+
+
+ Nama Kontak Darurat
+ Test Judul
+
+
+ Deskripsi Kontak Darurat
+ Test Kategori
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/kesehatan/kontak-darurat/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus penanganan darurat ini?"
+ /> */}
+
+ );
+}
+
+export default DetailKontakDarurat;
diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/edit/page.tsx
new file mode 100644
index 00000000..e7338470
--- /dev/null
+++ b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/edit/page.tsx
@@ -0,0 +1,62 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Stack, SimpleGrid, Paper, Title, TextInput, Text, Button, Image } from '@mantine/core';
+import { KesehatanEditor } from '../../_com/kesehatanEditor';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+
+function EditKontakDarurat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+
+
+
+ Edit Kontak Darurat
+ Nama Kontak Darurat}
+ placeholder='Masukkan nama Kontak Darurat'
+ />
+ Deskripsi Kontak Darurat}
+ placeholder='Masukkan deskripsi Kontak Darurat'
+ />
+
+ Deskripsi
+
+
+
+ Gambar
+
+
+
+
+
+
+
+
+ Preview Data Kontak Darurat
+ Nama Kontak Darurat
+ Deskripsi Kontak Darurat
+ Deskripsi
+ Gambar
+
+
+
+
+
+
+ );
+}
+
+export default EditKontakDarurat;
diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/page.tsx
index 8fa70bf8..52168304 100644
--- a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/page.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/page.tsx
@@ -1,8 +1,10 @@
+'use client'
import colors from '@/con/colors';
import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import JudulList from '../../_com/judulList';
import HeaderSearch from '../../_com/header';
+import { useRouter } from 'next/navigation';
function KontakDarurat() {
return (
@@ -18,6 +20,7 @@ function KontakDarurat() {
}
function ListKontakDarurat() {
+ const router = useRouter();
return (
@@ -47,7 +50,7 @@ function ListKontakDarurat() {
-
+ router.push('/admin/kesehatan/kontak-darurat/detail')}>
diff --git a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/detail/page.tsx
index c6f233eb..847728db 100644
--- a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/detail/page.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/detail/page.tsx
@@ -1,33 +1,70 @@
-import { Box, Paper, Stack, Table, TableTbody, TableTh, TableThead, TableTr, Title } from '@mantine/core';
+'use client'
import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
-function ListPenangananDarurat() {
+function DetailPenangananDarurat() {
+ const router = useRouter();
return (
-
-
- List Penanganan Darurat
-
-
-
-
- Image
- Nama Penanganan Darurat
- Deskripsi Penanganan Darurat
- Aksi
- Detail
-
-
-
-
-
-
-
+
+ router.back()}>
+
+
+
+
+
+ Detail Penanganan Darurat
+
+
+
+
+ Nama Penanganan Darurat
+ Test Judul
+
+
+ Deskripsi Penanganan Darurat
+ Test Kategori
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/kesehatan/penanganan-darurat/edit')} color="green">
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus penanganan darurat ini?"
+ /> */}
);
}
-export default ListPenangananDarurat;
+export default DetailPenangananDarurat;
diff --git a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/edit/page.tsx
new file mode 100644
index 00000000..68539b65
--- /dev/null
+++ b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/edit/page.tsx
@@ -0,0 +1,62 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Stack, SimpleGrid, Paper, Title, TextInput, Text, Button, Image } from '@mantine/core';
+import { KesehatanEditor } from '../../_com/kesehatanEditor';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+
+function EditPenangananDarurat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+
+
+
+ Edit Penanganan Darurat
+ Nama Penanganan Darurat}
+ placeholder='Masukkan nama Penanganan Darurat'
+ />
+ Deskripsi Penanganan Darurat}
+ placeholder='Masukkan deskripsi Penanganan Darurat'
+ />
+
+ Deskripsi
+
+
+
+ Gambar
+
+
+
+
+
+
+
+
+ Preview Data Penanganan Darurat
+ Nama Penanganan Darurat
+ No Telp Penanganan Darurat
+ Deskripsi
+ Pelayanan Posyandu
+
+
+
+
+
+
+ );
+}
+
+export default EditPenangananDarurat;
diff --git a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/page.tsx b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/page.tsx
index 26e341d8..714ac745 100644
--- a/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/page.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/penanganan-darurat/page.tsx
@@ -1,8 +1,10 @@
+'use client'
import colors from '@/con/colors';
import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import JudulList from '../../_com/judulList';
import HeaderSearch from '../../_com/header';
+import { useRouter } from 'next/navigation';
function PenangananDarurat() {
return (
@@ -18,6 +20,7 @@ function PenangananDarurat() {
}
function ListPenangananDarurat() {
+ const router = useRouter();
return (
@@ -47,7 +50,7 @@ function ListPenangananDarurat() {
-
+ router.push('/admin/kesehatan/penanganan-darurat/detail')}>
diff --git a/src/app/admin/(dashboard)/kesehatan/posyandu/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/posyandu/create/page.tsx
index 02150313..6060f701 100644
--- a/src/app/admin/(dashboard)/kesehatan/posyandu/create/page.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/posyandu/create/page.tsx
@@ -12,11 +12,11 @@ function CreatePosyandu() {
router.back()} variant='subtle' color={'blue'}>
-
+
-
+
Create Posyandu
@@ -24,8 +24,12 @@ function CreatePosyandu() {
Nama Posyandu}
- placeholder='Masukkan nama posyandu'
+ label={Nama Posyandu }
+ placeholder='Masukkan nama posyandu'
+ />
+ Nomor Posyandu}
+ placeholder='Masukkan nomor posyandu'
/>
Deskripsi Posyandu
@@ -36,9 +40,9 @@ function CreatePosyandu() {
Submit
-
+
-
+
);
}
diff --git a/src/app/admin/(dashboard)/kesehatan/posyandu/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/posyandu/detail/page.tsx
index 42c5732d..ec649457 100644
--- a/src/app/admin/(dashboard)/kesehatan/posyandu/detail/page.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/posyandu/detail/page.tsx
@@ -17,36 +17,32 @@ function DetailPosyandu() {
- Detail Potensi
+ Detail Posyandu
- Judul
+ Nama Posyandu
Test Judul
- Kategori
- Test Kategori
+ Nomor Posyandu
+ 089647038426
- Deskripsi
- Test Deskripsi
+ Deskripsi Posyandu
+ Test Kategori
Gambar
-
- Konten
- Test Konten
-
-
+ router.push('/admin/kesehatan/posyandu/edit')} color="green">
@@ -61,7 +57,7 @@ function DetailPosyandu() {
opened={modalHapus}
onClose={() => setModalHapus(false)}
onConfirm={handleHapus}
- text="Apakah anda yakin ingin menghapus potensi ini?"
+ text="Apakah anda yakin ingin menghapus penanganan darurat ini?"
/> */}
);
diff --git a/src/app/admin/(dashboard)/kesehatan/posyandu/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/posyandu/edit/page.tsx
index c13a6c7c..5ecb68d2 100644
--- a/src/app/admin/(dashboard)/kesehatan/posyandu/edit/page.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/posyandu/edit/page.tsx
@@ -26,6 +26,10 @@ function EditPosyandu() {
Nama Posyandu}
placeholder='Masukkan nama posyandu'
+ />
+ Nomor Posyandu}
+ placeholder='Masukkan nomor posyandu'
/>
Deskripsi Posyandu
diff --git a/src/app/admin/(dashboard)/kesehatan/posyandu/page.tsx b/src/app/admin/(dashboard)/kesehatan/posyandu/page.tsx
index 2c470611..b6c17360 100644
--- a/src/app/admin/(dashboard)/kesehatan/posyandu/page.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/posyandu/page.tsx
@@ -1,8 +1,10 @@
+'use client'
import colors from '@/con/colors';
import { Box, Button, Paper, Table, TableTbody, TableTd, TableTh, TableThead, TableTr } from '@mantine/core';
import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
import HeaderSearch from '../../_com/header';
import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
function Posyandu() {
return (
@@ -18,6 +20,7 @@ function Posyandu() {
}
function ListPosyandu() {
+ const router = useRouter();
return (
@@ -40,7 +43,7 @@ function ListPosyandu() {
0896232831883
Posyandu 1
-
+ router.push('/admin/kesehatan/posyandu/detail')}>
diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/detail/page.tsx
new file mode 100644
index 00000000..193f9366
--- /dev/null
+++ b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/detail/page.tsx
@@ -0,0 +1,70 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailProgramKesehatan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Potensi
+
+
+
+
+ Judul
+ Test Judul
+
+
+ Kategori
+ Test Kategori
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/kesehatan/program-kesehatan/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailProgramKesehatan;
diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/edit/page.tsx
new file mode 100644
index 00000000..d6e72783
--- /dev/null
+++ b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/edit/page.tsx
@@ -0,0 +1,64 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Stack, SimpleGrid, Paper, Title, TextInput, Text, Button } from '@mantine/core';
+import { KesehatanEditor } from '../../_com/kesehatanEditor';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+
+function EditProgramKesehatan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+
+
+
+ Edit Program Kesehatan
+ Nama Program Kesehatan}
+ placeholder='Masukkan nama Program Kesehatan'
+ />
+ No Telp Program Kesehatan}
+ placeholder='Masukkan no telp Program Kesehatan'
+ />
+
+ Deskripsi
+
+
+
+ Pelayanan Posyandu
+
+
+
+
+
+
+
+
+ Preview Data Program Kesehatan
+ Nama Program Kesehatan
+ No Telp Program Kesehatan
+ Deskripsi
+ Pelayanan Posyandu
+
+
+
+
+
+
+ );
+}
+
+export default EditProgramKesehatan;
diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/page.tsx
index 1987939d..8461d09c 100644
--- a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/page.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/page.tsx
@@ -1,8 +1,10 @@
+'use client'
import colors from '@/con/colors';
import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import JudulList from '../../_com/judulList';
import HeaderSearch from '../../_com/header';
+import { useRouter } from 'next/navigation';
function ProgramKesehatan() {
return (
@@ -18,6 +20,7 @@ function ProgramKesehatan() {
}
function ListProgramKesehatan() {
+ const router = useRouter()
return (
@@ -47,7 +50,7 @@ function ListProgramKesehatan() {
-
+ router.push('/admin/kesehatan/program-kesehatan/detail')}>
diff --git a/src/app/admin/(dashboard)/kesehatan/puskesmas/detail/page.tsx b/src/app/admin/(dashboard)/kesehatan/puskesmas/detail/page.tsx
new file mode 100644
index 00000000..e43adab4
--- /dev/null
+++ b/src/app/admin/(dashboard)/kesehatan/puskesmas/detail/page.tsx
@@ -0,0 +1,70 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailPuskesmas() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Potensi
+
+
+
+
+ Judul
+ Test Judul
+
+
+ Kategori
+ Test Kategori
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+ Konten
+ Test Konten
+
+
+
+
+
+
+ router.push('/admin/kesehatan/puskesmas/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailPuskesmas;
diff --git a/src/app/admin/(dashboard)/kesehatan/puskesmas/edit/updatePuskesmas.tsx b/src/app/admin/(dashboard)/kesehatan/puskesmas/edit/page.tsx
similarity index 76%
rename from src/app/admin/(dashboard)/kesehatan/puskesmas/edit/updatePuskesmas.tsx
rename to src/app/admin/(dashboard)/kesehatan/puskesmas/edit/page.tsx
index 8435b6f4..fa27e730 100644
--- a/src/app/admin/(dashboard)/kesehatan/puskesmas/edit/updatePuskesmas.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/puskesmas/edit/page.tsx
@@ -1,11 +1,20 @@
+'use client'
import colors from '@/con/colors';
-import { Box, Stack, SimpleGrid, Paper, Title, TextInput, Text } from '@mantine/core';
+import { Box, Stack, SimpleGrid, Paper, Title, TextInput, Text, Button } from '@mantine/core';
import { KesehatanEditor } from '../../_com/kesehatanEditor';
+import { useRouter } from 'next/navigation';
+import { IconArrowBack } from '@tabler/icons-react';
-function UpdatePuskesmas() {
- return (
-
+function EditPuskesmas() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
@@ -52,4 +61,4 @@ function UpdatePuskesmas() {
);
}
-export default UpdatePuskesmas;
+export default EditPuskesmas;
diff --git a/src/app/admin/(dashboard)/kesehatan/puskesmas/page.tsx b/src/app/admin/(dashboard)/kesehatan/puskesmas/page.tsx
index 554e7897..a11048ae 100644
--- a/src/app/admin/(dashboard)/kesehatan/puskesmas/page.tsx
+++ b/src/app/admin/(dashboard)/kesehatan/puskesmas/page.tsx
@@ -1,8 +1,10 @@
+'use client'
import colors from '@/con/colors';
import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import JudulList from '../../_com/judulList';
import HeaderSearch from '../../_com/header';
+import { useRouter } from 'next/navigation';
function Puskesmas() {
return (
@@ -18,6 +20,7 @@ function Puskesmas() {
}
function ListPuskesmas() {
+ const router = useRouter();
return (
@@ -47,7 +50,7 @@ function ListPuskesmas() {
-
+ router.push('/admin/kesehatan/puskesmas/detail')}>
diff --git a/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/create/page.tsx b/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/create/page.tsx
index 88e6e01a..069e862f 100644
--- a/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/create/page.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/create/page.tsx
@@ -4,6 +4,7 @@ import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core
import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import React from 'react';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
function CreateDataLingkunganDesa() {
const router = useRouter()
@@ -19,10 +20,13 @@ function CreateDataLingkunganDesa() {
Create Data Lingkungan Desa
Judul}
- placeholder="masukkan judul"
+ label={Nama Data Lingkungan Desa }
+ placeholder="masukkan nama data lingkungan desa"
+ />
+ Jumlah}
+ placeholder="masukkan jumlah"
/>
-
Deskripsi}
placeholder="masukkan deskripsi"
@@ -51,15 +55,11 @@ function CreateDataLingkunganDesa() {
)} */}
-
- Konten
- {/* {
- potensiState.create.form.content = htmlContent;
- }}
- /> */}
+ Deskripsi Data Lingkungan Desa
+
Simpan Data
diff --git a/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/detail/page.tsx b/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/detail/page.tsx
new file mode 100644
index 00000000..7b7ded58
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/detail/page.tsx
@@ -0,0 +1,66 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailDataLingkunganDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Data Lingkungan Desa
+
+
+
+
+ Nama Data Lingkungan Desa
+ Test Judul
+
+
+ Gambar
+
+
+
+ Jumlah
+ Test Jumlah
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+
+
+
+
+ router.push('/admin/lingkungan/data-lingkungan-desa/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailDataLingkunganDesa;
diff --git a/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/edit/page.tsx b/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/edit/page.tsx
new file mode 100644
index 00000000..310c62d7
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/edit/page.tsx
@@ -0,0 +1,73 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+function EditDataLingkunganDesa() {
+ const router = useRouter()
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+
+ Edit Data Lingkungan Desa
+ Nama Data Lingkungan Desa}
+ placeholder="masukkan nama data lingkungan desa"
+ />
+ Jumlah}
+ placeholder="masukkan jumlah"
+ />
+ Deskripsi}
+ placeholder="masukkan deskripsi"
+ />
+
+ Gambar
+
+
+ {/* Upload Gambar}
+ value={file}
+ onChange={async (e) => {
+ if (!e) return;
+ setFile(e);
+ const base64 = await e.arrayBuffer().then((buf) =>
+ 'data:image/png;base64,' + Buffer.from(buf).toString('base64')
+ );
+ setPreviewImage(base64);
+ }}
+ /> */}
+
+ {/* {previewImage ? (
+
+ ) : (
+
+
+
+ )} */}
+
+ Deskripsi Data Lingkungan Desa
+
+
+
+ Simpan Data
+
+
+
+
+ );
+}
+
+export default EditDataLingkunganDesa;
diff --git a/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/page.tsx b/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/page.tsx
index d9ba4dfc..bb62b62a 100644
--- a/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/page.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/data-lingkungan-desa/page.tsx
@@ -1,9 +1,11 @@
+'use client'
import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import React from 'react';
import HeaderSearch from '../../_com/header';
import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import colors from '@/con/colors';
import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
function DataLingkunganDesa() {
return (
@@ -19,6 +21,7 @@ function DataLingkunganDesa() {
}
function ListDataLingkunganDesa() {
+ const router = useRouter();
return (
@@ -31,7 +34,7 @@ function ListDataLingkunganDesa() {
- Judul
+ Nama Data Lingkungan
Gambar
Deskripsi
Detail
@@ -41,15 +44,15 @@ function ListDataLingkunganDesa() {
- Judul
+ Lingkungan Desa
-
+
Deskripsi
-
+ router.push('/admin/lingkungan/data-lingkungan-desa/detail')}>
diff --git a/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/create/page.tsx b/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/create/page.tsx
index df1978c0..e4f01858 100644
--- a/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/create/page.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/create/page.tsx
@@ -5,7 +5,7 @@ import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core
import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
-function Page() {
+function CreateEdukasiLingkungan() {
const router = useRouter()
return (
@@ -19,12 +19,12 @@ function Page() {
Create Edukasi Lingkungan
Judul}
- placeholder="masukkan judul"
+ label={Judul Edukasi Lingkungan }
+ placeholder="masukkan judul edukasi lingkungan"
/>
Deskripsi}
- placeholder="masukkan deskripsi"
+ label={Deskripsi Edukasi Lingkungan }
+ placeholder="masukkan deskripsi edukasi lingkungan"
/>
{/* Upload Gambar}
@@ -58,4 +58,4 @@ function Page() {
);
}
-export default Page;
+export default CreateEdukasiLingkungan;
diff --git a/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/detail/page.tsx b/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/detail/page.tsx
new file mode 100644
index 00000000..4eb6f96d
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/detail/page.tsx
@@ -0,0 +1,62 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailEdukasiLingkungan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Edukasi Lingkungan
+
+
+
+
+ Judul Edukasi Lingkungan
+ Test Judul
+
+
+ Gambar
+
+
+
+ Deskripsi Edukasi Lingkungan
+ Test Deskripsi
+
+
+
+
+
+
+ router.push('/admin/lingkungan/edukasi-lingkungan/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailEdukasiLingkungan;
diff --git a/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/edit/page.tsx b/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/edit/page.tsx
new file mode 100644
index 00000000..ca48b81a
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/edit/page.tsx
@@ -0,0 +1,61 @@
+'use client'
+import React from 'react';
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+function EditEdukasiLingkungan() {
+ const router = useRouter()
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+
+ Edit Edukasi Lingkungan
+ Judul Edukasi Lingkungan}
+ placeholder="masukkan judul edukasi lingkungan"
+ />
+ Deskripsi Edukasi Lingkungan}
+ placeholder="masukkan deskripsi edukasi lingkungan"
+ />
+ {/* Upload Gambar}
+ value={file}
+ onChange={async (e) => {
+ if (!e) return;
+ setFile(e);
+ const base64 = await e.arrayBuffer().then((buf) =>
+ 'data:image/png;base64,' + Buffer.from(buf).toString('base64')
+ );
+ setPreviewImage(base64);
+ }}
+ /> */}
+ {/* {previewImage ? (
+
+ ) : (
+
+
+
+ )} */}
+
+ Gambar
+
+
+
+ Simpan
+
+
+
+
+ );
+}
+
+export default EditEdukasiLingkungan;
diff --git a/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/page.tsx b/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/page.tsx
index eaf32a93..fae291e3 100644
--- a/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/page.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/edukasi-lingkungan/page.tsx
@@ -1,9 +1,11 @@
+'use client'
import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import React from 'react';
import HeaderSearch from '../../_com/header';
import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import colors from '@/con/colors';
import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
function Page() {
return (
@@ -19,6 +21,7 @@ function Page() {
}
function ListEdukasiLingkungan() {
+ const router = useRouter();
return (
@@ -31,9 +34,9 @@ function ListEdukasiLingkungan() {
- Judul
+ Judul Edukasi Lingkungan
Gambar
- Deskripsi
+ Deskripsi Edukasi Lingkungan
Detail
@@ -47,9 +50,9 @@ function ListEdukasiLingkungan() {
- Deskripsi
+ Deskripsi Edukasi Lingkungan
-
+ router.push('/admin/lingkungan/edukasi-lingkungan/detail')}>
diff --git a/src/app/admin/(dashboard)/lingkungan/gotong-royong/create/page.tsx b/src/app/admin/(dashboard)/lingkungan/gotong-royong/create/page.tsx
index 07cfb090..e7b57fe6 100644
--- a/src/app/admin/(dashboard)/lingkungan/gotong-royong/create/page.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/gotong-royong/create/page.tsx
@@ -4,8 +4,9 @@ import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core
import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import React from 'react';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
-function Page() {
+function CreateGotongRoyong() {
const router = useRouter()
return (
@@ -19,17 +20,19 @@ function Page() {
Create Gotong Royong
Judul}
- placeholder="masukkan judul"
+ label={Judul Gotong Royong }
+ placeholder="masukkan judul gotong royong"
/>
Kategori}
- placeholder="masukkan kategori"
- />
- Deskripsi}
- placeholder="masukkan deskripsi"
+ label={Kategori Gotong Royong }
+ placeholder="masukkan kategori gotong royong"
/>
+
+ Deskripsi Gotong Royong
+
+
{/* Upload Gambar}
value={file}
@@ -62,4 +65,4 @@ function Page() {
);
}
-export default Page;
+export default CreateGotongRoyong;
diff --git a/src/app/admin/(dashboard)/lingkungan/gotong-royong/detail/page.tsx b/src/app/admin/(dashboard)/lingkungan/gotong-royong/detail/page.tsx
new file mode 100644
index 00000000..06e3a53d
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/gotong-royong/detail/page.tsx
@@ -0,0 +1,66 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailGotongRoyong() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Gotong Royong
+
+
+
+
+ Judul Gotong Royong
+ Test Judul
+
+
+ Kategori Gotong Royong
+ Test Kategori
+
+
+ Deskripsi Gotong Royong
+ Test Deskripsi
+
+
+ Gambar
+
+
+
+
+
+
+
+ router.push('/admin/lingkungan/gotong-royong/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailGotongRoyong;
diff --git a/src/app/admin/(dashboard)/lingkungan/gotong-royong/edit/page.tsx b/src/app/admin/(dashboard)/lingkungan/gotong-royong/edit/page.tsx
new file mode 100644
index 00000000..acff7b2f
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/gotong-royong/edit/page.tsx
@@ -0,0 +1,68 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+function EditGotongRoyong() {
+ const router = useRouter()
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+
+ Edit Gotong Royong
+ Judul Gotong Royong}
+ placeholder="masukkan judul gotong royong"
+ />
+ Kategori Gotong Royong}
+ placeholder="masukkan kategori gotong royong"
+ />
+
+ Deskripsi Gotong Royong
+
+
+ {/* Upload Gambar}
+ value={file}
+ onChange={async (e) => {
+ if (!e) return;
+ setFile(e);
+ const base64 = await e.arrayBuffer().then((buf) =>
+ 'data:image/png;base64,' + Buffer.from(buf).toString('base64')
+ );
+ setPreviewImage(base64);
+ }}
+ /> */}
+ {/* {previewImage ? (
+
+ ) : (
+
+
+
+ )} */}
+
+ Gambar
+
+
+
+ Simpan
+
+
+
+
+ );
+}
+
+export default EditGotongRoyong;
diff --git a/src/app/admin/(dashboard)/lingkungan/gotong-royong/page.tsx b/src/app/admin/(dashboard)/lingkungan/gotong-royong/page.tsx
index 0f0e90aa..28a109bf 100644
--- a/src/app/admin/(dashboard)/lingkungan/gotong-royong/page.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/gotong-royong/page.tsx
@@ -1,8 +1,10 @@
+'use client'
import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import HeaderSearch from '../../_com/header';
import colors from '@/con/colors';
import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
function GotongRoyong() {
return (
@@ -18,6 +20,7 @@ function GotongRoyong() {
}
function ListGotongRoyong() {
+ const router = useRouter();
return (
@@ -30,10 +33,10 @@ function ListGotongRoyong() {
- Judul
- Kategori
+ Judul Gotong Royong
+ Kategori Gotong Royong
Image
- Deskripsi
+ Deskripsi Gotong Royong
Detail
@@ -50,7 +53,7 @@ function ListGotongRoyong() {
Deskripsi
-
+ router.push('/admin/lingkungan/gotong-royong/detail')}>
diff --git a/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/create/page.tsx b/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/create/page.tsx
index 68bd0e1e..9fef945c 100644
--- a/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/create/page.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/create/page.tsx
@@ -1,11 +1,10 @@
'use client'
-import React from 'react';
import colors from '@/con/colors';
-import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
-function Page() {
+function CreateKonservasiAdatBali() {
const router = useRouter()
return (
@@ -19,12 +18,12 @@ function Page() {
Create Konservasi Adat Bali
Judul}
- placeholder="masukkan judul"
+ label={Judul Konservasi Adat Bali }
+ placeholder="masukkan judul konservasi adat bali"
/>
Deskripsi}
- placeholder="masukkan deskripsi"
+ label={Deskripsi Konservasi Adat Bali }
+ placeholder="masukkan deskripsi konservasi adat bali"
/>
{/* Upload Gambar}
@@ -46,17 +45,15 @@ function Page() {
)} */}
-
- Gambar
-
-
-
+
+
Simpan
+
);
}
-export default Page;
+export default CreateKonservasiAdatBali;
diff --git a/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/detail/page.tsx b/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/detail/page.tsx
new file mode 100644
index 00000000..3fe2fd7b
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/detail/page.tsx
@@ -0,0 +1,57 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailKonservasiAdatBali() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Konservasi Adat Bali
+
+
+
+
+ Judul Konservasi Adat Bali
+ Test Judul
+
+
+ Deskripsi Konservasi Adat Bali
+ Test Deskripsi
+
+
+
+
+
+
+ router.push('/admin/lingkungan/konservasi-adat-bali/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailKonservasiAdatBali;
diff --git a/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/edit/page.tsx b/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/edit/page.tsx
new file mode 100644
index 00000000..049cd020
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/edit/page.tsx
@@ -0,0 +1,59 @@
+'use client'
+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';
+
+function EditKonservasiAdatBali() {
+ const router = useRouter()
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+
+ Edit Konservasi Adat Bali
+ Judul Konservasi Adat Bali}
+ placeholder="masukkan judul konservasi adat bali"
+ />
+ Deskripsi Konservasi Adat Bali}
+ placeholder="masukkan deskripsi konservasi adat bali"
+ />
+ {/* Upload Gambar}
+ value={file}
+ onChange={async (e) => {
+ if (!e) return;
+ setFile(e);
+ const base64 = await e.arrayBuffer().then((buf) =>
+ 'data:image/png;base64,' + Buffer.from(buf).toString('base64')
+ );
+ setPreviewImage(base64);
+ }}
+ />
+ */}
+ {/* {previewImage ? (
+
+ ) : (
+
+
+
+ )} */}
+
+
+ Simpan
+
+
+
+
+
+ );
+}
+
+export default EditKonservasiAdatBali;
diff --git a/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/page.tsx b/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/page.tsx
index 6361c664..d9e13f25 100644
--- a/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/page.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/konservasi-adat-bali/page.tsx
@@ -1,9 +1,10 @@
-import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
-import React from 'react';
-import HeaderSearch from '../../_com/header';
-import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
+'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 HeaderSearch from '../../_com/header';
import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
function KonservasiAdatBali() {
return (
@@ -19,6 +20,7 @@ function KonservasiAdatBali() {
}
function ListKonservasiAdatBali() {
+ const router = useRouter();
return (
@@ -31,9 +33,8 @@ function ListKonservasiAdatBali() {
- Judul
- Gambar
- Deskripsi
+ Judul Konservasi Adat Bali
+ Deskripsi Konservasi Adat Bali
Detail
@@ -41,15 +42,12 @@ function ListKonservasiAdatBali() {
- Judul
+ Judul Konservasi Adat Bali
+ Deskripsi Konservasi Adat Bali
-
-
- Deskripsi
-
-
+ router.push("/admin/lingkungan/konservasi-adat-bali/detail")}>
diff --git a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/create/page.tsx b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/create/page.tsx
deleted file mode 100644
index c8697ae0..00000000
--- a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/create/page.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-'use client'
-import colors from "@/con/colors";
-import { Box, Button, Paper, Stack, Title, TextInput, Text } from "@mantine/core";
-import { IconArrowBack } from "@tabler/icons-react";
-import { useRouter } from "next/navigation";
-
-
-export default function CreatePengelolaanSampahBankSampah() {
- const router = useRouter()
- return (
-
-
- router.back()}>
-
-
-
-
-
-
- Create Mekanisme Bank Sampah
-
- Judul}
- placeholder="masukkan judul"
- />
-
- Deskripsi}
- placeholder="masukkan deskripsi"
- />
-
- {/* Upload Gambar}
- value={file}
- onChange={async (e) => {
- if (!e) return;
- setFile(e);
- const base64 = await e.arrayBuffer().then((buf) =>
- 'data:image/png;base64,' + Buffer.from(buf).toString('base64')
- );
- setPreviewImage(base64);
- }}
- /> */}
-
- {/* {previewImage ? (
-
- ) : (
-
-
-
- )} */}
-
-
- Konten
- {/* {
- potensiState.create.form.content = htmlContent;
- }}
- /> */}
-
-
-
- Simpan
-
-
-
-
- )
-}
-
diff --git a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/create/page.tsx b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/create/page.tsx
new file mode 100644
index 00000000..84db20f6
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/create/page.tsx
@@ -0,0 +1,46 @@
+'use client'
+import { KeamananEditor } from '@/app/admin/(dashboard)/keamanan/_com/keamananEditor';
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+
+
+function CreateKeteranganBankSampahTerdekat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Keterangan Bank Sampah Terdekat
+
+ Masukkan Image
+
+
+ Nama Bank Sampah Terdekat}
+ placeholder='Masukkan nama bank sampah terdekat'
+ />
+
+ Deskripsi Bank Sampah Terdekat
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateKeteranganBankSampahTerdekat;
diff --git a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/detail/page.tsx b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/detail/page.tsx
new file mode 100644
index 00000000..9d90797e
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/detail/page.tsx
@@ -0,0 +1,62 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailKeteranganBankSampahTerdekat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Keterangan Bank Sampah Terdekat
+
+
+
+
+ Nama Bank Sampah Terdekat
+ Test Judul
+
+
+ Gambar
+
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+
+
+
+
+ router.push('/admin/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailKeteranganBankSampahTerdekat;
diff --git a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/edit/page.tsx b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/edit/page.tsx
new file mode 100644
index 00000000..3ef09d42
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/edit/page.tsx
@@ -0,0 +1,46 @@
+'use client'
+import { KeamananEditor } from '@/app/admin/(dashboard)/keamanan/_com/keamananEditor';
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+
+
+function EditKeteranganBankSampahTerdekat() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Keterangan Bank Sampah Terdekat
+
+ Masukkan Image
+
+
+ Nama Bank Sampah Terdekat}
+ placeholder='Masukkan nama bank sampah terdekat'
+ />
+
+ Deskripsi Bank Sampah Terdekat
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditKeteranganBankSampahTerdekat;
diff --git a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/page.tsx b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/page.tsx
new file mode 100644
index 00000000..af496ce6
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/page.tsx
@@ -0,0 +1,55 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
+import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import JudulListTab from '../../../_com/jusulListTab';
+
+function KeteranganBankSampahTerdekat() {
+ const router = useRouter();
+ return (
+
+
+
+ }
+ />
+ List Keterangan Bank Sampah Terdekat
+
+
+
+
+ Nama Bank Sampah Terdekat
+ Gambar
+ Detail
+
+
+
+
+
+
+ Bank Sampah Sarana Gathi
+
+
+
+
+
+
+ router.push('/admin/lingkungan/pengelolaan-sampah-bank-sampah/keterangan_bank_sampah_terdekat/detail')}>
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default KeteranganBankSampahTerdekat;
diff --git a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/create/page.tsx b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/create/page.tsx
new file mode 100644
index 00000000..58b82dcc
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/create/page.tsx
@@ -0,0 +1,46 @@
+'use client'
+import { KeamananEditor } from '@/app/admin/(dashboard)/keamanan/_com/keamananEditor';
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+
+
+function CreateMekanismeBankSampah() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Create Mekanisme Bank Sampah
+
+ Masukkan Image
+
+
+ Judul}
+ placeholder='Masukkan judul'
+ />
+
+ Deskripsi
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default CreateMekanismeBankSampah;
diff --git a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/detail/page.tsx b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/detail/page.tsx
new file mode 100644
index 00000000..2621b440
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/detail/page.tsx
@@ -0,0 +1,61 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconImageInPicture, IconX } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailPengelolaanSampahBankSampah() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Mekanisme Bank Sampah
+
+
+
+
+ Judul
+ Test Judul
+
+
+ Gambar
+
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+
+
+
+
+ router.push('/admin/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailPengelolaanSampahBankSampah;
diff --git a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/edit/page.tsx b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/edit/page.tsx
new file mode 100644
index 00000000..70086bdb
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/edit/page.tsx
@@ -0,0 +1,46 @@
+'use client'
+import { KeamananEditor } from '@/app/admin/(dashboard)/keamanan/_com/keamananEditor';
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+
+
+
+function EditMekanismeBankSampah() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Mekanisme Bank Sampah
+
+ Masukkan Image
+
+
+ Judul}
+ placeholder='Masukkan judul'
+ />
+
+ Deskripsi
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditMekanismeBankSampah;
diff --git a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/ui/list_page/listPage.tsx b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/page.tsx
similarity index 60%
rename from src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/ui/list_page/listPage.tsx
rename to src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/page.tsx
index c6bef31a..923625eb 100644
--- a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/ui/list_page/listPage.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/page.tsx
@@ -1,39 +1,29 @@
-import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
-import React from 'react';
-import HeaderSearch from '@/app/admin/(dashboard)/_com/header';
-import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
+'use client'
import colors from '@/con/colors';
-import JudulList from '@/app/admin/(dashboard)/_com/judulList';
-
-function ListPage() {
- return (
-
- }
- />
-
-
- );
-}
+import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
+import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import JudulListTab from '../../../_com/jusulListTab';
function ListPengelolaanSampahBankSampah() {
+ const router = useRouter();
return (
-
-
+ }
/>
+ List Mekanisme Bank Sampah
Judul
Gambar
- Deskripsi
Detail
@@ -45,11 +35,10 @@ function ListPengelolaanSampahBankSampah() {
-
+
- Deskripsi
-
+ router.push('/admin/lingkungan/pengelolaan-sampah-bank-sampah/list_pengelolaan_sampah_bank_sampah/detail')}>
@@ -63,4 +52,4 @@ function ListPengelolaanSampahBankSampah() {
)
}
-export default ListPage;
+export default ListPengelolaanSampahBankSampah;
diff --git a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/page.tsx b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/page.tsx
index 85239543..d7ad5a36 100644
--- a/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/page.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/pengelolaan-sampah-bank-sampah/page.tsx
@@ -1,6 +1,9 @@
import { Box, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
-import ListPage from './ui/list_page/listPage';
+
import colors from '@/con/colors';
+import ListPengelolaanSampahBankSampah from './list_pengelolaan_sampah_bank_sampah/page';
+import KeteranganBankSampahTerdekat from './keterangan_bank_sampah_terdekat/page';
+
function PengelolaanSampahBankSampah() {
return (
@@ -13,16 +16,16 @@ function PengelolaanSampahBankSampah() {
List Pengelolaan Sampah Bank Sampah
- Maps
+ Keterangan Bank Sampah Terdekat
-
+
-
+
- Maps
+
diff --git a/src/app/admin/(dashboard)/lingkungan/program-penghijauan/create/page.tsx b/src/app/admin/(dashboard)/lingkungan/program-penghijauan/create/page.tsx
index 4c1e91c2..210924d8 100644
--- a/src/app/admin/(dashboard)/lingkungan/program-penghijauan/create/page.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/program-penghijauan/create/page.tsx
@@ -1,73 +1,53 @@
'use client'
import colors from '@/con/colors';
-import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
-function Page() {
- const router = useRouter()
+
+function CreateProgramKreatifDesa() {
+ const router = useRouter();
return (
-
- router.back()}>
-
+
+ router.back()} variant='subtle' color={'blue'}>
+
-
+
- Create Program Penghijauan
-
- Judul}
- placeholder="masukkan judul"
- />
-
- Deskripsi}
- placeholder="masukkan deskripsi"
- />
-
- Gambar
-
- {/* Upload Gambar}
- value={file}
- onChange={async (e) => {
- if (!e) return;
- setFile(e);
- const base64 = await e.arrayBuffer().then((buf) =>
- 'data:image/png;base64,' + Buffer.from(buf).toString('base64')
- );
- setPreviewImage(base64);
- }}
- /> */}
-
- {/* {previewImage ? (
-
- ) : (
-
-
-
- )} */}
-
+ Create Program Penghijauan
- Konten
- {/* {
- potensiState.create.form.content = htmlContent;
- }}
- /> */}
+ Masukkan Image
+
-
-
- Simpan Potensi
-
-
+ Nama Program Penghijauan}
+ placeholder='Masukkan nama program penghijauan'
+ />
+ Deskripsi Singkat Program Penghijauan}
+ placeholder='Masukkan deskripsi singkat program penghijauan'
+ />
+ Jumlah}
+ placeholder='Masukkan jumlah'
+ />
+
+ Deskripsi Program Kreatif Desa
+
+
+
+ Submit
+
+
-
+
);
}
-export default Page;
+export default CreateProgramKreatifDesa;
diff --git a/src/app/admin/(dashboard)/lingkungan/program-penghijauan/detail/page.tsx b/src/app/admin/(dashboard)/lingkungan/program-penghijauan/detail/page.tsx
new file mode 100644
index 00000000..0bfd8eb8
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/program-penghijauan/detail/page.tsx
@@ -0,0 +1,62 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Flex, Text, Image } from '@mantine/core';
+import { IconArrowBack, IconX, IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React from 'react';
+// import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function DetailProgramPenghijauan() {
+ const router = useRouter();
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Program Penghijauan
+
+
+
+
+ Nama Program Penghijauan
+ Test Judul
+
+
+ Gambar
+
+
+
+ Deskripsi
+ Test Deskripsi
+
+
+
+
+
+
+ router.push('/admin/lingkungan/program-penghijauan/edit')} color="green">
+
+
+
+
+
+
+
+
+
+ {/* Modal Hapus
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text="Apakah anda yakin ingin menghapus potensi ini?"
+ /> */}
+
+ );
+}
+
+export default DetailProgramPenghijauan;
diff --git a/src/app/admin/(dashboard)/lingkungan/program-penghijauan/edit/page.tsx b/src/app/admin/(dashboard)/lingkungan/program-penghijauan/edit/page.tsx
new file mode 100644
index 00000000..bf340820
--- /dev/null
+++ b/src/app/admin/(dashboard)/lingkungan/program-penghijauan/edit/page.tsx
@@ -0,0 +1,53 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { KeamananEditor } from '../../../keamanan/_com/keamananEditor';
+
+
+function EditProgramKreatifDesa() {
+ const router = useRouter();
+ return (
+
+
+ router.back()} variant='subtle' color={'blue'}>
+
+
+
+
+
+
+ Edit Program Penghijauan
+
+ Masukkan Image
+
+
+ Nama Program Penghijauan}
+ placeholder='Masukkan nama program penghijauan'
+ />
+ Deskripsi Singkat Program Penghijauan}
+ placeholder='Masukkan deskripsi singkat program penghijauan'
+ />
+ Jumlah}
+ placeholder='Masukkan jumlah'
+ />
+
+ Deskripsi Program Kreatif Desa
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditProgramKreatifDesa;
diff --git a/src/app/admin/(dashboard)/lingkungan/program-penghijauan/page.tsx b/src/app/admin/(dashboard)/lingkungan/program-penghijauan/page.tsx
index e818879d..a5c4278e 100644
--- a/src/app/admin/(dashboard)/lingkungan/program-penghijauan/page.tsx
+++ b/src/app/admin/(dashboard)/lingkungan/program-penghijauan/page.tsx
@@ -1,8 +1,10 @@
+'use client'
import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import HeaderSearch from '../../_com/header';
import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
import colors from '@/con/colors';
import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
function ProgramPenghijauan() {
return (
@@ -18,20 +20,21 @@ function ProgramPenghijauan() {
}
function ListManfaatPenghijauan() {
+ const router = useRouter();
return (
- Judul
+ Nama Program Penghijauan
Gambar
- Jumlah
Deskripsi
Detail
@@ -42,16 +45,13 @@ function ListManfaatPenghijauan() {
Judul
-
-
- Jumlah
-
+
Deskripsi
-
+ router.push('/admin/lingkungan/program-penghijauan/detail')}>
diff --git a/src/app/admin/(dashboard)/pendidikan/beasiswa-desa/page.tsx b/src/app/admin/(dashboard)/pendidikan/beasiswa-desa/page.tsx
index acec3acc..c55b299b 100644
--- a/src/app/admin/(dashboard)/pendidikan/beasiswa-desa/page.tsx
+++ b/src/app/admin/(dashboard)/pendidikan/beasiswa-desa/page.tsx
@@ -1,11 +1,70 @@
-import React from 'react';
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
+import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import HeaderSearch from '../../_com/header';
-function Page() {
+function BeasiswaDesa() {
return (
-
- beasiswa-desa
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListBeasiswaDesa() {
+ const router = useRouter();
+ return (
+
+
+
+ List Beasiswa Desa
+
+
+
+
+ Nomor
+ Nama Lengkap
+ Nomor Telepon
+ Email
+ Detail
+
+
+
+
+
+
+ 1
+
+
+
+ Nama Lengkap
+
+
+ Nomor Telepon
+
+
+ Email
+
+
+ router.push('/admin/pendidikan/beasiswa-desa/detail')}>
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default BeasiswaDesa;
diff --git a/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/page.tsx b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/page.tsx
index a18fa7b1..ed7a421e 100644
--- a/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/page.tsx
+++ b/src/app/admin/(dashboard)/pendidikan/bimbingan-belajar-desa/page.tsx
@@ -1,11 +1,74 @@
-import React from 'react';
+'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 Page() {
+function BimbinganBelajarDesa() {
return (
-
- bimbingan-belajar-desa
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListBimbinganBelajarDesa() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+
+
+ Nomor
+ Nama Lengkap
+ Nomor Telepon
+ Email
+ Detail
+
+
+
+
+
+
+ 1
+
+
+
+ Nama Lengkap
+
+
+ Nomor Telepon
+
+
+ Email
+
+
+ router.push('/admin/pendidikan/bimbingan-belajar-desa/detail')}>
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default BimbinganBelajarDesa;
diff --git a/src/app/admin/(dashboard)/pendidikan/data-pendidikan/page.tsx b/src/app/admin/(dashboard)/pendidikan/data-pendidikan/page.tsx
index 42093829..ce2f64e4 100644
--- a/src/app/admin/(dashboard)/pendidikan/data-pendidikan/page.tsx
+++ b/src/app/admin/(dashboard)/pendidikan/data-pendidikan/page.tsx
@@ -1,11 +1,74 @@
-import React from 'react';
+'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 Page() {
+function DataPendidikan() {
return (
-
- data-pendidikan
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListDataPendidikan() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+
+
+ Nomor
+ Nama Lengkap
+ Nomor Telepon
+ Email
+ Detail
+
+
+
+
+
+
+ 1
+
+
+
+ Nama Lengkap
+
+
+ Nomor Telepon
+
+
+ Email
+
+
+ router.push('/admin/pendidikan/data-pendidikan/detail')}>
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default DataPendidikan;
diff --git a/src/app/admin/(dashboard)/pendidikan/info-sekolah-paud/page.tsx b/src/app/admin/(dashboard)/pendidikan/info-sekolah-paud/page.tsx
index c32a09bf..d20a948c 100644
--- a/src/app/admin/(dashboard)/pendidikan/info-sekolah-paud/page.tsx
+++ b/src/app/admin/(dashboard)/pendidikan/info-sekolah-paud/page.tsx
@@ -1,11 +1,69 @@
+'use client'
+import { Box, Button, Image, Paper, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import React from 'react';
+import HeaderSearch from '../../_com/header';
+import { IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
+import colors from '@/con/colors';
+import JudulList from '../../_com/judulList';
+import { useRouter } from 'next/navigation';
-function Page() {
+function InfoSekolahPaud() {
return (
-
- info-sekolah-paud
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListInfoSekolahPaud() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+
+
+ Nama Sekolah PAUD
+ Gambar
+ Deskripsi
+ Detail
+
+
+
+
+
+
+ Sekolah PAUD
+
+
+
+
+
+ Deskripsi
+
+ router.push('/admin/pendidikan/info-sekolah-paud/detail')}>
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default InfoSekolahPaud;
diff --git a/src/app/admin/(dashboard)/pendidikan/pendidikan-non-formal/page.tsx b/src/app/admin/(dashboard)/pendidikan/pendidikan-non-formal/page.tsx
index ed113e5f..a7451ab4 100644
--- a/src/app/admin/(dashboard)/pendidikan/pendidikan-non-formal/page.tsx
+++ b/src/app/admin/(dashboard)/pendidikan/pendidikan-non-formal/page.tsx
@@ -1,11 +1,74 @@
-import React from 'react';
+'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 Page() {
+function PendidikanNonFormal() {
return (
-
- pendidikan-non-formal
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListPendidikanNonFormal() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+
+
+ Nomor
+ Nama Lengkap
+ Nomor Telepon
+ Email
+ Detail
+
+
+
+
+
+
+ 1
+
+
+
+ Nama Lengkap
+
+
+ Nomor Telepon
+
+
+ Email
+
+
+ router.push('/admin/pendidikan/pendidikan-non-formal/detail')}>
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default PendidikanNonFormal;
diff --git a/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/page.tsx b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/page.tsx
index d441bb49..cb057167 100644
--- a/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/page.tsx
+++ b/src/app/admin/(dashboard)/pendidikan/perpustakaan-digital/page.tsx
@@ -1,11 +1,74 @@
-import React from 'react';
+'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 Page() {
+function PerpustakaanDigital() {
return (
-
- perpustakaan-digital
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListPerpustakaanDigital() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+
+
+ Nomor
+ Nama Lengkap
+ Nomor Telepon
+ Email
+ Detail
+
+
+
+
+
+
+ 1
+
+
+
+ Nama Lengkap
+
+
+ Nomor Telepon
+
+
+ Email
+
+
+ router.push('/admin/pendidikan/perpustakaan-digital/detail')}>
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default PerpustakaanDigital;
diff --git a/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/page.tsx b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/page.tsx
index 19f97fd2..221e27cb 100644
--- a/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/page.tsx
+++ b/src/app/admin/(dashboard)/pendidikan/program-pendidikan-anak/page.tsx
@@ -1,11 +1,74 @@
-import React from 'react';
+'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 Page() {
+function ProgramPendidikanAnak() {
return (
-
- program-pendidikan-anak
-
+
+ }
+ />
+
+
);
}
-export default Page;
+function ListProgramPendidikanAnak() {
+ const router = useRouter();
+ return (
+
+
+
+
+
+
+
+
+ Nomor
+ Nama Lengkap
+ Nomor Telepon
+ Email
+ Detail
+
+
+
+
+
+
+ 1
+
+
+
+ Nama Lengkap
+
+
+ Nomor Telepon
+
+
+ Email
+
+
+ router.push('/admin/pendidikan/program-pendidikan-anak/detail')}>
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default ProgramPendidikanAnak;
diff --git a/src/app/admin/(dashboard)/ppid/_com/PPIDTextEditor.tsx b/src/app/admin/(dashboard)/ppid/_com/PPIDTextEditor.tsx
index 2e6629aa..21ca7786 100644
--- a/src/app/admin/(dashboard)/ppid/_com/PPIDTextEditor.tsx
+++ b/src/app/admin/(dashboard)/ppid/_com/PPIDTextEditor.tsx
@@ -40,7 +40,7 @@ export function PPIDTextEditor({ onSubmit, onChange, showSubmit = true, initialC
}, [initialContent, editor]);
return (
-
+
diff --git a/src/app/admin/(dashboard)/ppid/_com/layoutTabs.tsx b/src/app/admin/(dashboard)/ppid/_com/layoutTabs.tsx
new file mode 100644
index 00000000..6003362d
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/_com/layoutTabs.tsx
@@ -0,0 +1,72 @@
+/* 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: "Grafik Hasil Kepuasan Masyarakat",
+ value: "grafikhasilkepuasamanmasyarakat",
+ href: "/admin/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat"
+ },
+ {
+ label: "Grafik Berdasarkan Jenis Kelamin Responden",
+ value: "grafikberdasarkanjeniskelaminresponden",
+ href: "/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden"
+ },
+ {
+ label: "Grafik Berdasarkan Pilihan Responden",
+ value: "grafikberdasarkanpilihanresponden",
+ href: "/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden"
+ },
+ {
+ label: "Grafik Berdasarkan Umur Responden",
+ value: "grafikberdasarkanumurresponden",
+ href: "/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur"
+ }
+ ];
+ 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 (
+
+ Indeks Kepuasan Masyarakat (IKM) Desa Darmasaba
+
+
+ {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)/ppid/_com/layoutTabsGallery.tsx b/src/app/admin/(dashboard)/ppid/_com/layoutTabsGallery.tsx
new file mode 100644
index 00000000..fd3cbfcf
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/_com/layoutTabsGallery.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 LayoutTabsGallery({ children }: { children: React.ReactNode }) {
+ const router = useRouter()
+ const pathname = usePathname()
+ const tabs = [
+ {
+ label: "Foto",
+ value: "foto",
+ href: "/admin/desa/gallery/foto"
+ },
+ {
+ label: "Video",
+ value: "video",
+ href: "/admin/desa/gallery/video"
+ },
+
+ ];
+ 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 (
+
+ Gallery
+
+
+ {tabs.map((e, i) => (
+ {e.label}
+ ))}
+
+ {tabs.map((e, i) => (
+
+ {/* Konten dummy, bisa diganti tergantung routing */}
+ <>>
+
+ ))}
+
+ {children}
+
+ );
+}
+
+export default LayoutTabsGallery;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/[id]/edit/page.tsx b/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/[id]/edit/page.tsx
new file mode 100644
index 00000000..b5ffe26f
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/[id]/edit/page.tsx
@@ -0,0 +1,113 @@
+'use client'
+/* eslint-disable react-hooks/exhaustive-deps */
+import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
+import daftarInformasiPublik from '@/app/admin/(dashboard)/_state/ppid/daftar_informasi_publik/daftarInformasiPublik';
+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 EditDaftarInformasiPublik() {
+ const daftarInformasi = useProxy(daftarInformasiPublik)
+ const router = useRouter()
+ const params = useParams()
+
+ const [formData, setFormData] = useState({
+ jenisInformasi: daftarInformasi.edit.form.jenisInformasi || '',
+ deskripsi: daftarInformasi.edit.form.deskripsi || '',
+ tanggal: daftarInformasi.edit.form.tanggal || '',
+ })
+
+ useEffect(() => {
+ const loadDaftarInformasi = async () => {
+ const id = params?.id as string;
+ if (!id) return;
+
+ try {
+ const data = await daftarInformasi.edit.load(id);
+ if (data) {
+ setFormData({
+ jenisInformasi: data.jenisInformasi || '',
+ deskripsi: data.deskripsi || '',
+ tanggal: data.tanggal || '',
+ });
+ }
+ } catch (error) {
+ console.error("Error loading daftar informasi:", error);
+ toast.error("Gagal memuat data daftar informasi");
+ }
+ }
+
+ loadDaftarInformasi();
+ }, [params?.id]);
+
+ const handleSubmit = async () => {
+ try {
+ daftarInformasi.edit.form = {
+ ...daftarInformasi.edit.form,
+ jenisInformasi: formData.jenisInformasi,
+ deskripsi: formData.deskripsi,
+ tanggal: formData.tanggal,
+ }
+ await daftarInformasi.edit.update()
+ toast.success("Berita berhasil diperbarui!");
+ router.push("/admin/ppid/daftar-informasi-publik-desa-darmasaba");
+ } catch (error) {
+ console.error("Error updating berita:", error);
+ toast.error("Terjadi kesalahan saat memperbarui berita");
+ }
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Edit Daftar Informasi Publik Desa Darmasaba
+ {
+ setFormData({
+ ...formData,
+ jenisInformasi: val.target.value
+ })
+ }}
+ />
+
+ Deskripsi
+ {
+ setFormData((prev) => ({ ...prev, deskripsi: htmlContent }));
+ daftarInformasi.edit.form.deskripsi = htmlContent;
+ }}
+ />
+
+ {
+ setFormData({
+ ...formData,
+ tanggal: val.target.value
+ })
+ }}
+ />
+ Edit Berita
+
+
+
+ );
+}
+
+export default EditDaftarInformasiPublik;
diff --git a/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/[id]/page.tsx b/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/[id]/page.tsx
new file mode 100644
index 00000000..8e70db82
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/[id]/page.tsx
@@ -0,0 +1,107 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Skeleton, Stack, Text } from '@mantine/core';
+import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
+import { useParams, useRouter } from 'next/navigation';
+import { useState } from 'react';
+import { useProxy } from 'valtio/utils';
+import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+import daftarInformasiPublik from '../../../_state/ppid/daftar_informasi_publik/daftarInformasiPublik';
+import { useShallowEffect } from '@mantine/hooks';
+
+function DetailDaftarInformasiPublik() {
+ const [modalHapus, setModalHapus] = useState(false)
+ const stateDaftarInformasi = useProxy(daftarInformasiPublik)
+ const router = useRouter()
+ const params = useParams()
+ const [selectedId, setSelectedId] = useState(null)
+
+ useShallowEffect(() => {
+ stateDaftarInformasi.findUnique.load(params?.id as string)
+ }, [params?.id])
+
+ const handleHapus = () => {
+ if (selectedId) {
+ stateDaftarInformasi.delete.byId(selectedId)
+ setModalHapus(false)
+ setSelectedId(null)
+ router.push("/admin/ppid/daftar-informasi-publik-desa-darmasaba")
+ }
+ }
+
+ if (!stateDaftarInformasi.findUnique.data) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Detail Berita
+ {stateDaftarInformasi.findUnique.data ? (
+
+
+
+ Jenis Informasi
+ {stateDaftarInformasi.findUnique.data?.jenisInformasi}
+
+
+ Tanggal
+ {stateDaftarInformasi.findUnique.data?.tanggal}
+
+
+ Deskripsi
+
+
+
+ {
+ if (stateDaftarInformasi.findUnique.data) {
+ setSelectedId(stateDaftarInformasi.findUnique.data.id);
+ setModalHapus(true);
+ }
+ }}
+ disabled={stateDaftarInformasi.delete.loading || !stateDaftarInformasi.findUnique.data}
+ color={"red"}
+ >
+
+
+ {
+ if (stateDaftarInformasi.findUnique.data) {
+ router.push(`/admin/ppid/daftar-informasi-publik-desa-darmasaba/${stateDaftarInformasi.findUnique.data.id}/edit`);
+ }
+ }}
+ disabled={!stateDaftarInformasi.findUnique.data}
+ color={"green"}
+ >
+
+
+
+
+
+ ) : null}
+
+
+
+ {/* Modal Konfirmasi Hapus */}
+ setModalHapus(false)}
+ onConfirm={handleHapus}
+ text='Apakah anda yakin ingin menghapus berita ini?'
+ />
+
+ );
+}
+
+export default DetailDaftarInformasiPublik;
diff --git a/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/create/page.tsx b/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/create/page.tsx
new file mode 100644
index 00000000..8a77e209
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/create/page.tsx
@@ -0,0 +1,72 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useProxy } from 'valtio/utils';
+import CreateEditor from '../../../_com/createEditor';
+import daftarInformasiPublik from '../../../_state/ppid/daftar_informasi_publik/daftarInformasiPublik';
+
+export default function CreateBerita() {
+ const daftarInformasi = useProxy(daftarInformasiPublik)
+ const router = useRouter()
+
+ const resetForm = () => {
+ // Reset state di valtio
+ daftarInformasi.create.form = {
+ jenisInformasi: "",
+ deskripsi: "",
+ tanggal: "",
+ };
+
+ // Reset state lokal
+ };
+
+ const handleSubmit = async () => {
+ // Submit data berita
+ await daftarInformasi.create.create();
+
+ // Reset form setelah submit
+ resetForm();
+ router.push("/admin/ppid/daftar-informasi-publik-desa-darmasaba")
+ };
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Create Daftar Informasi Publik Desa Darmasaba
+ {
+ daftarInformasi.create.form.jenisInformasi = val.target.value
+ }}
+ />
+
+ Deskripsi
+ {
+ daftarInformasi.create.form.deskripsi = htmlContent;
+ }}
+ />
+
+ {
+ daftarInformasi.create.form.tanggal = val.target.value
+ }}
+ />
+ Simpan Berita
+
+
+
+ );
+}
diff --git a/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/page.tsx b/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/page.tsx
index 756426ac..05862507 100644
--- a/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/page.tsx
+++ b/src/app/admin/(dashboard)/ppid/daftar-informasi-publik-desa-darmasaba/page.tsx
@@ -1,112 +1,97 @@
'use client'
import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, TextInput, Title } from '@mantine/core';
+import { Box, Button, Grid, GridCol, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, TextInput, Title } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
+import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
import { useProxy } from 'valtio/utils';
-import stateDaftarInformasiPublik from '../../_state/ppid/daftar_informasi_publik/daftarInformasiPublik';
-import { PPIDTextEditor } from '../_com/PPIDTextEditor';
+import daftarInformasiPublik from '../../_state/ppid/daftar_informasi_publik/daftarInformasiPublik';
function Page() {
- const daftarInformasi = useProxy(stateDaftarInformasiPublik.daftarInformasi)
- const submit = () => {
- if (daftarInformasi.create.form.jenisInformasi &&
- daftarInformasi.create.form.deskripsi &&
- daftarInformasi.create.form.tanggal) {
- daftarInformasi.create.create()
- }
- }
return (
-
-
-
-
- Daftar Informasi Publik Desa Darmasaba
- {
- daftarInformasi.create.form.jenisInformasi = val.target.value
- }}
- />
- {
- daftarInformasi.create.form.deskripsi = val
- }}
- />
- {
- daftarInformasi.create.form.tanggal = val.target.value
- }}
- />
-
- Submit
-
-
+
+
+ Daftar Informasi Publik Desa Darmasaba
+
+
+
+ }
+ />
-
-
-
-
-
+
+
+
);
}
function ListDaftarInformasi() {
- const listData = useProxy(stateDaftarInformasiPublik.daftarInformasi)
+ const listData = useProxy(daftarInformasiPublik)
+
useShallowEffect(() => {
listData.findMany.load()
}, [])
- if (!listData.findMany.data) return
- {Array.from({ length: 10 }).map((v, k) => )}
-
+
+ const router = useRouter()
+
+ if (!listData.findMany.data) {
+ return (
+
+
+
+ )
+ }
+
return (
-
+
-
- List Daftar Informasi Publik Desa Darmasaba
-
-
-
-
- No
-
-
- Jenis Informasi
-
-
- Deskripsi
-
-
- Tanggal Publikasi
-
-
-
-
- {listData.findMany.data?.map((item) => (
-
- {item.nomor}
- {item.jenisInformasi}
-
- {item.tanggal}
+
+
+
+ List Daftar Informasi Publik Desa Darmasaba
+
+
+ router.push("/admin/ppid/daftar-informasi-publik-desa-darmasaba/create")} bg={colors['blue-button']}>
+
+
+
+
+
+
+
+
+ No
+ Jenis Informasi
+ Deskripsi
+ Detail
- ))}
-
-
+
+
+ {listData.findMany.data?.map((item, index) => (
+
+ {index + 1}
+ {item.jenisInformasi}
+
+
+ router.push(`/admin/ppid/daftar-informasi-publik-desa-darmasaba/${item.id}`)}>
+
+
+
+
+ ))}
+
+
+
diff --git a/src/app/admin/(dashboard)/ppid/dasar-hukum/create/create.tsx b/src/app/admin/(dashboard)/ppid/dasar-hukum/create/create.tsx
deleted file mode 100644
index 4783166a..00000000
--- a/src/app/admin/(dashboard)/ppid/dasar-hukum/create/create.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-'use client'
-import { Box, Stack, Text } from '@mantine/core';
-import dynamic from 'next/dynamic';
-
-const PPIDTextEditor = dynamic(() => import('../../_com/PPIDTextEditor').then(mod => mod.PPIDTextEditor), {
- ssr: false,
-});
-
-function CreateDasarHukum({
- valueJudul,
- valueContent,
- onJudulChange,
- onContentChange,
- error
-} : {
- valueJudul: string;
- valueContent: string;
- onJudulChange: (val: string) => void;
- onContentChange: (val: string) => void;
- error?: string;
-}) {
-
- return (
-
-
- Judul
-
- Content
-
- {error && {error} }
-
-
- );
-}
-
-export default CreateDasarHukum;
diff --git a/src/app/admin/(dashboard)/ppid/dasar-hukum/edit/page.tsx b/src/app/admin/(dashboard)/ppid/dasar-hukum/edit/page.tsx
new file mode 100644
index 00000000..3db09f04
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/dasar-hukum/edit/page.tsx
@@ -0,0 +1,87 @@
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Group, Paper, Stack, Text, Title } from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import dynamic from 'next/dynamic';
+import { useEffect, useState } from 'react';
+import { useProxy } from 'valtio/utils';
+import stateDasarHukumPPID from '../../../_state/ppid/dasar_hukum/dasarHukum';
+import { useRouter } from 'next/navigation';
+import { IconArrowBack } from '@tabler/icons-react';
+
+const PPIDTextEditor = dynamic(() => import('../../_com/PPIDTextEditor').then(mod => mod.PPIDTextEditor), {
+ ssr: false,
+});
+
+function EditDasarHukum() {
+ const router = useRouter()
+ const dasarHukumState = useProxy(stateDasarHukumPPID)
+ const [judul, setJudul] = useState('');
+ const [content, setContent] = useState('');
+
+ useShallowEffect(() => {
+ if (!dasarHukumState.findById.data) {
+ dasarHukumState.findById.initialize(); // biar masuk ke `findFirst` route kamu
+ }
+ }, []);
+
+ useEffect(() => {
+ if (dasarHukumState.findById.data) {
+ setJudul(dasarHukumState.findById.data.judul ?? '')
+ setContent(dasarHukumState.findById.data.content ?? '')
+ }
+ }, [dasarHukumState.findById.data])
+
+ const submit = () => {
+ if (dasarHukumState.findById.data) {
+ dasarHukumState.findById.data.judul = judul;
+ dasarHukumState.findById.data.content = content;
+ dasarHukumState.update.save(dasarHukumState.findById.data)
+ }
+ router.push('/admin/ppid/dasar-hukum')
+ }
+ return (
+
+
+
+ router.back()}
+ >
+
+
+
+
+
+
+ Edit Dasar Hukum PPID
+ Judul
+
+ Content
+
+
+
+ Submit
+
+
+
+
+
+
+
+ );
+}
+
+export default EditDasarHukum;
diff --git a/src/app/admin/(dashboard)/ppid/dasar-hukum/listData/page.tsx b/src/app/admin/(dashboard)/ppid/dasar-hukum/listData/page.tsx
deleted file mode 100644
index e1d7af57..00000000
--- a/src/app/admin/(dashboard)/ppid/dasar-hukum/listData/page.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-'use client'
-import React from 'react';
-import { useProxy } from 'valtio/utils';
-import stateDasarHukumPPID from '../../../_state/ppid/dasar_hukum/dasarHukum';
-import { useShallowEffect } from '@mantine/hooks';
-import { Box, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
-import colors from '@/con/colors';
-
-function ListDataDasarHukum() {
- const dataList = useProxy(stateDasarHukumPPID)
- useShallowEffect(() => {
- dataList.findById.load("")
- }, [])
-
- if(!dataList.findById.data) return
- {Array.from({length: 10}).map((v, k) => )}
-
-
-const dataArray = Array.isArray(dataList.findById.data)
- ? dataList.findById.data
- : [dataList.findById.data];
-
- return (
-
-
- List Dasar Hukum PPID
- {dataArray.map((item) => (
-
- Judul
-
- Content
-
-
- ))}
-
-
- );
-}
-
-export default ListDataDasarHukum;
diff --git a/src/app/admin/(dashboard)/ppid/dasar-hukum/page.tsx b/src/app/admin/(dashboard)/ppid/dasar-hukum/page.tsx
index dcb5c899..35be5294 100644
--- a/src/app/admin/(dashboard)/ppid/dasar-hukum/page.tsx
+++ b/src/app/admin/(dashboard)/ppid/dasar-hukum/page.tsx
@@ -1,61 +1,53 @@
'use client'
import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Title } from '@mantine/core';
-import CreateDasarHukum from './create/create';
-import ListDataDasarHukum from './listData/page';
+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 stateDasarHukumPPID from '../../_state/ppid/dasar_hukum/dasarHukum';
-import { useEffect, useState } from 'react';
function Page() {
- const dasarHukumState = useProxy(stateDasarHukumPPID)
- const [judul, setJudul] = useState('');
- const [content, setContent] = useState('');
-
+ const router = useRouter()
+ const listDasarHukum = useProxy(stateDasarHukumPPID)
useShallowEffect(() => {
- if (!dasarHukumState.findById.data) {
- dasarHukumState.findById.initialize(); // biar masuk ke `findFirst` route kamu
- }
- }, []);
+ listDasarHukum.findById.load('1')
+ }, [])
- useEffect(() => {
- if (dasarHukumState.findById.data) {
- setJudul(dasarHukumState.findById.data.judul ?? '')
- setContent(dasarHukumState.findById.data.content ?? '')
- }
- }, [dasarHukumState.findById.data])
-
- const submit = () => {
- if (dasarHukumState.findById.data) {
- dasarHukumState.findById.data.judul = judul;
- dasarHukumState.findById.data.content = content;
- dasarHukumState.update.save(dasarHukumState.findById.data)
- }
+ if (!listDasarHukum.findById.data) {
+ return (
+
+
+
+ )
}
-
return (
-
-
+
+
+
+
+ Preview Dasar Hukum PPID
+
+
+ router.push('/admin/ppid/dasar-hukum/edit')}>
+
+
+
+
-
- Dasar Hukum PPID
-
-
-
- Submit
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
)
}
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_berdasarkan_jenis_kelamin_responden/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_berdasarkan_jenis_kelamin_responden/page.tsx
deleted file mode 100644
index 18a8bf35..00000000
--- a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_berdasarkan_jenis_kelamin_responden/page.tsx
+++ /dev/null
@@ -1,142 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-'use client'
-import stateGrafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
-import colors from '@/con/colors';
-import { Box, Button, Center, Flex, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import { useShallowEffect } from '@mantine/hooks';
-import { useEffect, useState } from 'react';
-import { Cell, Pie, PieChart } from 'recharts';
-import { useProxy } from 'valtio/utils';
-
-function GrafikBerdasarkanJenisKelamin() {
- const grafikBerdasarkanJenisKelamin = useProxy(stateGrafikBerdasarkanJenisKelamin.grafikBerdasarkanJenisKelamin)
- const [donutData, setDonutData] = useState([]);
- const [mounted, setMounted] = useState(false);
-
- useEffect(() => {
- setMounted(true);
- }, [])
-
- const updateChartData = (data: any) => {
- if (data && data.length > 0) {
- const totalLaki = data.reduce((acc: number, cur: any) => acc + Number(cur.laki || 0), 0);
- const totalPerempuan = data.reduce((acc: number, cur: any) => acc + Number(cur.perempuan || 0), 0);
-
- setDonutData([
- { name: 'Laki-laki', value: totalLaki, color: colors['blue-button'], key: 'laki-laki' },
- { name: 'Perempuan', value: totalPerempuan, color: '#FF6384', key: 'perempuan' }
- ]);
- }
- };
-
- useShallowEffect(() => {
- fetchData();
- }, []);
-
- const fetchData = async () => {
- await grafikBerdasarkanJenisKelamin.findMany.load();
- if (grafikBerdasarkanJenisKelamin.findMany.data) {
- updateChartData(grafikBerdasarkanJenisKelamin.findMany.data);
- }
- };
-
- const handleSubmit = async () => {
- try {
- // Simpan data baru
- await grafikBerdasarkanJenisKelamin.create.create();
-
- // Muat ulang data
- await grafikBerdasarkanJenisKelamin.findMany.load();
-
- // Update chart dengan data baru
- if (grafikBerdasarkanJenisKelamin.findMany.data) {
- updateChartData(grafikBerdasarkanJenisKelamin.findMany.data);
- }
-
- // Reset form setelah submit
- grafikBerdasarkanJenisKelamin.create.form.laki = '';
- grafikBerdasarkanJenisKelamin.create.form.perempuan = '';
- } catch (error) {
- console.error("Error submitting data:", error);
- }
- };
-
- return (
-
-
-
- Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
- {
- grafikBerdasarkanJenisKelamin.create.form.laki = val.currentTarget.value;
- }}
- />
- {
- grafikBerdasarkanJenisKelamin.create.form.perempuan = val.currentTarget.value;
- }}
- />
-
- Submit
-
-
-
-
- {/* Chart */}
-
-
-
- Grafik Berdasarkan Jenis Kelamin Responden
- {mounted && donutData.length > 0 && (
-
-
-
-
-
- {donutData.map((entry, index) => (
- |
- ))}
-
-
-
-
-
- Perempuan: {donutData.find((entry) => entry.name === 'Perempuan')?.value}
-
-
-
- Laki-laki: {donutData.find((entry) => entry.name === 'Laki-laki')?.value}
-
-
- )}
-
-
-
-
- );
-}
-
-export default GrafikBerdasarkanJenisKelamin;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_berdasarkan_responden/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_berdasarkan_responden/page.tsx
deleted file mode 100644
index 1a578cba..00000000
--- a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_berdasarkan_responden/page.tsx
+++ /dev/null
@@ -1,173 +0,0 @@
-'use client'
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import stateGrafikResponden from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
-import colors from '@/con/colors';
-import { Box, Button, Center, Flex, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import { useShallowEffect } from '@mantine/hooks';
-import React, { useEffect, useState } from 'react';
-import { PieChart, Pie, Cell } from 'recharts';
-import { useProxy } from 'valtio/utils';
-
-function GrafikBerdasarkanResponden() {
- const grafikBerdasarkanResponden = useProxy(stateGrafikResponden.grafikBerdasarkanResponden)
- const [donutData, setDonutData] = useState([]);
- const [mounted, setMounted] = useState(false);
-
- useEffect(() => {
- setMounted(true);
- }, [])
-
- const updateChartData = (data: any) => {
- if (data && data.length > 0) {
- const totalSangatBaik = data.reduce((acc: number, cur: any) => acc + Number(cur.sangatbaik || 0), 0);
- const totalBaik = data.reduce((acc: number, cur: any) => acc + Number(cur.baik || 0), 0);
- const totalKurangBaik = data.reduce((acc: number, cur: any) => acc + Number(cur.kurangbaik || 0), 0);
- const totalTidakBaik = data.reduce((acc: number, cur: any) => acc + Number(cur.tidakbaik || 0), 0);
- setDonutData([
- { name: 'sangatbaik', value: totalSangatBaik, color: colors['blue-button'], key: 'sangatbaik' },
- { name: 'baik', value: totalBaik, color: '#10A85AFF', key: 'baik' },
- { name: 'kurangbaik', value: totalKurangBaik, color: '#B3AA12FF', key: 'kurangbaik' },
- { name: 'tidakbaik', value: totalTidakBaik, color: '#B21313FF', key: 'tidakbaik' }
- ]);
- }
- };
-
- useShallowEffect(() => {
- fetchData();
- }, []);
-
- const fetchData = async () => {
- await grafikBerdasarkanResponden.findMany.load();
- if (grafikBerdasarkanResponden.findMany.data) {
- updateChartData(grafikBerdasarkanResponden.findMany.data);
- }
- };
-
- const handleSubmit = async () => {
- try {
- // Simpan data baru
- await grafikBerdasarkanResponden.create.create();
-
- // Muat ulang data
- await grafikBerdasarkanResponden.findMany.load();
-
- // Update chart dengan data baru
- if (grafikBerdasarkanResponden.findMany.data) {
- updateChartData(grafikBerdasarkanResponden.findMany.data);
- }
-
- // Reset form setelah submit
- grafikBerdasarkanResponden.create.form.sangatbaik = '';
- grafikBerdasarkanResponden.create.form.baik = '';
- grafikBerdasarkanResponden.create.form.kurangbaik = '';
- grafikBerdasarkanResponden.create.form.tidakbaik = '';
- } catch (error) {
- console.error("Error submitting data:", error);
- }
- };
- return (
-
-
-
-
- Grafik Berdasarkan Responden
- {
- grafikBerdasarkanResponden.create.form.sangatbaik = val.currentTarget.value;
- }}
- />
- {
- grafikBerdasarkanResponden.create.form.baik = val.currentTarget.value;
- }}
- />
- {
- grafikBerdasarkanResponden.create.form.kurangbaik = val.currentTarget.value;
- }}
- />
- {
- grafikBerdasarkanResponden.create.form.tidakbaik = val.currentTarget.value;
- }}
- />
-
-
- Submit
-
-
-
-
-
-
- {/* Chart */}
-
-
-
- Grafik Berdasarkan Responden
- {mounted && donutData.length > 0 && (
-
-
-
-
- {donutData.map((entry, index) => (
- |
- ))}
-
-
-
-
-
- Sangat Baik: {donutData.find((entry) => entry.name === 'sangatbaik')?.value}
-
-
-
- Baik: {donutData.find((entry) => entry.name === 'baik')?.value}
-
-
-
- Kurang Baik: {donutData.find((entry) => entry.name === 'kurangbaik')?.value}
-
-
-
- Tidak Baik: {donutData.find((entry) => entry.name === 'tidakbaik')?.value}
-
-
- )}
-
-
-
-
- );
-}
-
-export default GrafikBerdasarkanResponden;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_berdasarkan_umur/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_berdasarkan_umur/page.tsx
deleted file mode 100644
index 5e3d0e1f..00000000
--- a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_berdasarkan_umur/page.tsx
+++ /dev/null
@@ -1,164 +0,0 @@
-'use client'
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import colors from '@/con/colors';
-import { Box, Button, Center, Flex, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
-import React, { useEffect, useState } from 'react';
-import { useProxy } from 'valtio/utils';
-import stateGrafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
-import { useShallowEffect } from '@mantine/hooks';
-import { PieChart, Pie, Cell } from 'recharts';
-
-function GrafikBerdasarakanUmur() {
- const grafikBerdasarkanUmur = useProxy(stateGrafikBerdasarkanUmur.grafikBerdasarkanUmur)
- const [donutData, setDonutData] = useState([]);
- const [mounted, setMounted] = useState(false);
-
- useEffect(() => {
- setMounted(true);
- }, []);
-
- const updateChartData = (data: any) => {
- if (data && data.length > 0) {
- const totalRemaja = data.reduce((acc: number, cur: any) => acc + Number(cur.remaja || 0), 0);
- const totalDewasa = data.reduce((acc: number, cur: any) => acc + Number(cur.dewasa || 0), 0);
- const totalOrangtua = data.reduce((acc: number, cur: any) => acc + Number(cur.orangtua || 0), 0);
- const totalLansia = data.reduce((acc: number, cur: any) => acc + Number(cur.lansia || 0), 0);
-
- setDonutData([
- { name: 'Remaja', value: totalRemaja, color: colors['blue-button'], key: 'remaja' },
- { name: 'Dewasa', value: totalDewasa, color: '#D32711FF', key: 'dewasa' },
- { name: 'Orangtua', value: totalOrangtua, color: '#B46B04FF', key: 'orangtua' },
- { name: 'Lansia', value: totalLansia, color: '#038617FF', key: 'lansia' }
- ]);
- }
- };
-
- useShallowEffect(() => {
- fetchData();
- }, []);
-
- const fetchData = async () => {
- await grafikBerdasarkanUmur.findMany.load();
- if (grafikBerdasarkanUmur.findMany.data) {
- updateChartData(grafikBerdasarkanUmur.findMany.data);
- }
- }
-
- const handleSubmit = async () => {
- try {
- await grafikBerdasarkanUmur.create.create();
- await grafikBerdasarkanUmur.findMany.load();
- if (grafikBerdasarkanUmur.findMany.data) {
- updateChartData(grafikBerdasarkanUmur.findMany.data);
- }
- } catch (error) {
- console.error("Error submitting data:", error);
- }
- }
- return (
-
-
-
-
- Grafik Berdasarkan Umur Responden
- {
- grafikBerdasarkanUmur.create.form.remaja = val.currentTarget.value;
- }}
- />
- {
- grafikBerdasarkanUmur.create.form.dewasa = val.currentTarget.value;
- }}
- />
- {
- grafikBerdasarkanUmur.create.form.orangtua = val.currentTarget.value;
- }}
- />
- {
- grafikBerdasarkanUmur.create.form.lansia = val.currentTarget.value;
- }}
- />
-
-
- Submit
-
-
-
-
-
-
- {/* Chart */}
-
-
-
- Grafik Berdasarkan Umur Responden
- {mounted && donutData.length > 0 && (
-
-
-
-
- {donutData.map((entry, index) => (
- |
- ))}
-
-
-
-
-
- 17 - 25 tahun: {donutData.find((entry) => entry.name === 'remaja')?.value}
-
-
-
- 26 - 45 tahun: {donutData.find((entry) => entry.name === 'dewasa')?.value}
-
-
-
- 46 - 60 tahun: {donutData.find((entry) => entry.name === 'orangtua')?.value}
-
-
-
- di atas 60 tahun: {donutData.find((entry) => entry.name === 'lansia')?.value}
-
-
- )}
-
-
-
-
- );
-}
-
-export default GrafikBerdasarakanUmur;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_hasil_kepuasan_masyarakat/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_hasil_kepuasan_masyarakat/page.tsx
deleted file mode 100644
index b114d94e..00000000
--- a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/_ui/grafik_hasil_kepuasan_masyarakat/page.tsx
+++ /dev/null
@@ -1,94 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-'use client'
-import stateGrafikHasilKepuasanMasyarakat from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
-import colors from '@/con/colors';
-import { Box, Button, Paper, Stack, TextInput, Title } from '@mantine/core';
-import { useMediaQuery, useShallowEffect } from '@mantine/hooks';
-import React, { useEffect, useState } from 'react';
-import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts';
-import { useProxy } from 'valtio/utils';
-
-function GrafikHasilKepuasan() {
- const grafikHasilKepuasan = useProxy(stateGrafikHasilKepuasanMasyarakat.grafikHasilKepuasanMasyarakat)
- const [chartData, setChartData] = useState([]);
- const [mounted, setMounted] = useState(false);
- const isTablet = useMediaQuery('(max-width: 1024px)')
- const isMobile = useMediaQuery('(max-width: 768px)')
-
- useEffect(() => {
- setMounted(true);
- }, [])
-
- useShallowEffect(() => {
- const fetchData = async () => {
- await grafikHasilKepuasan.findMany.load();
- if (grafikHasilKepuasan.findMany.data && grafikHasilKepuasan.findMany.data.length > 0) {
- setChartData(grafikHasilKepuasan.findMany.data);
- }
- };
- fetchData();
- }, []);
-
- return (
-
-
-
-
- Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
- {
- grafikHasilKepuasan.create.form.label = val.currentTarget.value;
- }}
- />
- {
- grafikHasilKepuasan.create.form.kepuasan = val.currentTarget.value;
- }}
- />
- {
- await grafikHasilKepuasan.create.create();
- await grafikHasilKepuasan.findMany.load();
- if (grafikHasilKepuasan.findMany.data) {
- setChartData(grafikHasilKepuasan.findMany.data);
- }
- }}
- >
- Submit
-
-
-
-
-
- {/* Chart */}
-
-
-
- Data Kepuasan Masyarakat
- {mounted && chartData.length > 0 && (
-
-
-
-
-
-
-
- )}
-
-
-
-
-
- );
-}
-
-export default GrafikHasilKepuasan;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/[id]/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/[id]/page.tsx
new file mode 100644
index 00000000..e3c00ade
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/[id]/page.tsx
@@ -0,0 +1,78 @@
+'use client'
+/* eslint-disable react-hooks/exhaustive-deps */
+import React, { useEffect } from 'react';
+import { useRouter, useParams } from 'next/navigation';
+import { useProxy } from 'valtio/utils';
+import grafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Title, TextInput } from '@mantine/core';
+import { IconArrowBack } from '@tabler/icons-react';
+
+function EditGrafikBerdasarkanJenisKelaminResponden() {
+ const router = useRouter()
+ const params = useParams() as { id: string }
+ const stategrafikBerdasarkanJenisKelamin = useProxy(grafikBerdasarkanJenisKelamin)
+ const id = params.id
+
+ useEffect(() => {
+ if(id){
+ stategrafikBerdasarkanJenisKelamin.findUnique.load(id).then(() => {
+ const data = stategrafikBerdasarkanJenisKelamin.findUnique.data
+ if(data){
+ stategrafikBerdasarkanJenisKelamin.update.form = {
+ laki: data.laki || '',
+ perempuan: data.perempuan || '',
+ }
+ }
+ })
+ }
+ }, [id])
+
+ const handleSubmit = async () => {
+ stategrafikBerdasarkanJenisKelamin.update.id = id;
+ await stategrafikBerdasarkanJenisKelamin.update.submit();
+ router.push('/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden')
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
+ {
+ stategrafikBerdasarkanJenisKelamin.update.form.laki = val.currentTarget.value;
+ }}
+ />
+ {
+ stategrafikBerdasarkanJenisKelamin.update.form.perempuan = val.currentTarget.value;
+ }}
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditGrafikBerdasarkanJenisKelaminResponden;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/create/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/create/page.tsx
new file mode 100644
index 00000000..cc07a64d
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/create/page.tsx
@@ -0,0 +1,79 @@
+'use client'
+/* eslint-disable @typescript-eslint/no-unused-vars */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import React from 'react';
+import { useRouter } from 'next/navigation';
+import grafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
+import { useProxy } from 'valtio/utils';
+import { useState } from 'react';
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Title, TextInput } from '@mantine/core';
+import { IconArrowBack } from '@tabler/icons-react';
+
+function GrafikBerdasarkanJenisKelaminRespondenCreate() {
+ const router = useRouter();
+ const stategrafikBerdasarkanJenisKelamin = useProxy(grafikBerdasarkanJenisKelamin)
+ const [donutData, setDonutData] = useState([]);
+
+ const resetForm = () => {
+ stategrafikBerdasarkanJenisKelamin.create.form = {
+ ...stategrafikBerdasarkanJenisKelamin.create.form,
+ laki: "",
+ perempuan: "",
+ }
+ }
+
+ const handleSubmit = async () => {
+ const id = await stategrafikBerdasarkanJenisKelamin.create.create();
+ if (id) {
+ const idStr = String(id);
+ await stategrafikBerdasarkanJenisKelamin.findUnique.load(idStr);
+ if (stategrafikBerdasarkanJenisKelamin.findUnique.data) {
+ setDonutData([stategrafikBerdasarkanJenisKelamin.findUnique.data]);
+ }
+ }
+ resetForm();
+ router.push("/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden")
+ }
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
+ {
+ stategrafikBerdasarkanJenisKelamin.create.form.laki = val.currentTarget.value;
+ }}
+ />
+ {
+ stategrafikBerdasarkanJenisKelamin.create.form.perempuan = val.currentTarget.value;
+ }}
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default GrafikBerdasarkanJenisKelaminRespondenCreate;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/page.tsx
new file mode 100644
index 00000000..3544a288
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/page.tsx
@@ -0,0 +1,165 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+'use client'
+import grafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useEffect, useState } from 'react';
+import { Cell, Pie, PieChart } from 'recharts';
+import { useProxy } from 'valtio/utils';
+import JudulListTab from '../../../_com/jusulListTab';
+import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function GrafikBerdasarkanJenisKelamin() {
+ const stategrafikBerdasarkanJenisKelamin = useProxy(grafikBerdasarkanJenisKelamin)
+ const [donutData, setDonutData] = useState([]);
+ const [mounted, setMounted] = useState(false);
+ const [modalHapus, setModalHapus] = useState(false)
+ const [selectedId, setSelectedId] = useState(null)
+ const router = useRouter();
+
+ const handleDelete = async () => {
+ if (selectedId) {
+ await grafikBerdasarkanJenisKelamin.delete.byId(selectedId)
+ setModalHapus(false)
+ setSelectedId(null)
+
+ stategrafikBerdasarkanJenisKelamin.findMany.load()
+ }
+ }
+
+ useShallowEffect(() => {
+ setMounted(true);
+ stategrafikBerdasarkanJenisKelamin.findMany.load()
+ }, []);
+
+ useEffect(() => {
+ if (stategrafikBerdasarkanJenisKelamin.findMany.data) {
+ const totalLaki = stategrafikBerdasarkanJenisKelamin.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.laki || 0), 0);
+ const totalPerempuan = stategrafikBerdasarkanJenisKelamin.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.perempuan || 0), 0);
+ setDonutData([
+ { name: 'laki', value: totalLaki, color: colors['blue-button'], key: 'laki' },
+ { name: 'perempuan', value: totalPerempuan, color: '#10A85AFF', key: 'perempuan' }
+ ]);
+ }
+ }, [stategrafikBerdasarkanJenisKelamin.findMany.data])
+
+ if (!stategrafikBerdasarkanJenisKelamin.findMany.data) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+
+ }
+ />
+
+
+
+ Laki-laki
+ Perempuan
+ Edit
+ Delete
+
+
+
+ {stategrafikBerdasarkanJenisKelamin.findMany.data.length === 0 ? (
+
+
+ Belum ada data grafik responden
+
+
+ ) : (
+ stategrafikBerdasarkanJenisKelamin.findMany.data.map((item) => (
+
+ {item.laki}
+ {item.perempuan}
+
+ router.push(`/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin_responden/${item.id}`)}>
+
+
+
+
+ {
+ setSelectedId(item.id)
+ setModalHapus(true)
+ }}>
+
+
+
+
+ ))
+ )}
+
+
+
+
+
+ {/* Chart */}
+
+
+
+ Grafik Berdasarkan Responden
+ {mounted && donutData.length > 0 ? (
+
+
+ {donutData.map((entry, index) => (
+ |
+ ))}
+
+
+
+
+ Laki-laki: {donutData.find((entry) => entry.name === 'laki')?.value}
+
+
+
+ Perempuan: {donutData.find((entry) => entry.name === 'perempuan')?.value}
+
+
+ ) : (
+ Belum ada data untuk ditampilkan dalam grafik
+ )}
+
+
+
+
+
+ {/* Modal Konfirmasi Hapus */}
+ setModalHapus(false)}
+ onConfirm={handleDelete}
+ text='Apakah anda yakin ingin menghapus grafik berdasarkan hasil responden ini?'
+ />
+
+ );
+}
+
+export default GrafikBerdasarkanJenisKelamin;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/[id]/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/[id]/page.tsx
new file mode 100644
index 00000000..beed61a7
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/[id]/page.tsx
@@ -0,0 +1,98 @@
+/* eslint-disable react-hooks/exhaustive-deps */
+'use client'
+import React, { useEffect } from 'react';
+import { useRouter, useParams } from 'next/navigation';
+import { useProxy } from 'valtio/utils';
+import grafikBerdasarkanResponden from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Title, TextInput } from '@mantine/core';
+import { IconArrowBack } from '@tabler/icons-react';
+
+function EditGrafikBerdasarkanResponden() {
+ const router = useRouter()
+ const params = useParams() as { id: string }
+ const stateGrafikResponden = useProxy(grafikBerdasarkanResponden)
+ const id = params.id
+
+ useEffect(() => {
+ if(id){
+ stateGrafikResponden.findUnique.load(id).then(() => {
+ const data = stateGrafikResponden.findUnique.data
+ if(data){
+ stateGrafikResponden.update.form = {
+ sangatbaik: data.sangatbaik || '',
+ baik: data.baik || '',
+ kurangbaik: data.kurangbaik || '',
+ tidakbaik: data.tidakbaik || '',
+ }
+ }
+ })
+ }
+ }, [id])
+
+ const handleSubmit = async () => {
+ stateGrafikResponden.update.id = id;
+ await stateGrafikResponden.update.submit();
+ router.push('/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden')
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
+ {
+ stateGrafikResponden.update.form.sangatbaik = val.currentTarget.value;
+ }}
+ />
+ {
+ stateGrafikResponden.update.form.baik = val.currentTarget.value;
+ }}
+ />
+ {
+ stateGrafikResponden.update.form.kurangbaik = val.currentTarget.value;
+ }}
+ />
+ {
+ stateGrafikResponden.update.form.tidakbaik = val.currentTarget.value;
+ }}
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditGrafikBerdasarkanResponden;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/create/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/create/page.tsx
new file mode 100644
index 00000000..af8b6180
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/create/page.tsx
@@ -0,0 +1,98 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+'use client'
+import grafikBerdasarkanResponden from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, TextInput, Title } from '@mantine/core';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useState } from 'react';
+import { useProxy } from 'valtio/utils';
+
+function GrafikBerdasarkanRespondenCreate() {
+ const router = useRouter()
+ const stategrafikBerdasarkanResponden = useProxy(grafikBerdasarkanResponden)
+ const [donutData, setDonutData] = useState([]);
+
+ const resetForm = () => {
+ stategrafikBerdasarkanResponden.create.form = {
+ ...stategrafikBerdasarkanResponden.create.form,
+ sangatbaik: "",
+ baik: "",
+ kurangbaik: "",
+ tidakbaik: "",
+ }
+ }
+
+ const handleSubmit = async () => {
+ const id = await stategrafikBerdasarkanResponden.create.create();
+ if (id) {
+ const idStr = String(id);
+ await stategrafikBerdasarkanResponden.findUnique.load(idStr);
+ if (stategrafikBerdasarkanResponden.findUnique.data) {
+ setDonutData([stategrafikBerdasarkanResponden.findUnique.data]);
+ }
+ }
+ resetForm();
+ router.push("/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden")
+ }
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
+ {
+ stategrafikBerdasarkanResponden.create.form.sangatbaik = val.currentTarget.value;
+ }}
+ />
+ {
+ stategrafikBerdasarkanResponden.create.form.baik = val.currentTarget.value;
+ }}
+ />
+ {
+ stategrafikBerdasarkanResponden.create.form.kurangbaik = val.currentTarget.value;
+ }}
+ />
+ {
+ stategrafikBerdasarkanResponden.create.form.tidakbaik = val.currentTarget.value;
+ }}
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default GrafikBerdasarkanRespondenCreate;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/page.tsx
new file mode 100644
index 00000000..73161b0b
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/page.tsx
@@ -0,0 +1,184 @@
+'use client'
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useEffect, useState } from 'react';
+import { Cell, Pie, PieChart } from 'recharts';
+import { useSnapshot } from 'valtio';
+import JudulListTab from '../../../_com/jusulListTab';
+import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+import grafikBerdasarkanResponden from '../../../_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
+
+function GrafikBerdasarkanResponden() {
+
+ const stategrafikBerdasarkanResponden = useSnapshot(grafikBerdasarkanResponden)
+ const [donutData, setDonutData] = useState([]);
+ const [mounted, setMounted] = useState(false);
+ const [modalHapus, setModalHapus] = useState(false)
+ const [selectedId, setSelectedId] = useState(null)
+ const router = useRouter();
+
+ const handleDelete = async () => {
+ if (selectedId) {
+ await stategrafikBerdasarkanResponden.delete.byId(selectedId);
+ setModalHapus(false);
+ setSelectedId(null);
+
+ // Refresh data agar chart & tabel ikut update
+ stategrafikBerdasarkanResponden.findMany.load();
+ }
+ }
+
+
+ useShallowEffect(() => {
+ setMounted(true)
+ stategrafikBerdasarkanResponden.findMany.load()
+ }, [])
+
+ useEffect(() => {
+ if (stategrafikBerdasarkanResponden.findMany.data) {
+ const totalSangatBaik = stategrafikBerdasarkanResponden.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.sangatbaik || 0), 0);
+ const totalBaik = stategrafikBerdasarkanResponden.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.baik || 0), 0);
+ const totalKurangBaik = stategrafikBerdasarkanResponden.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.kurangbaik || 0), 0);
+ const totalTidakBaik = stategrafikBerdasarkanResponden.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.tidakbaik || 0), 0);
+ setDonutData([
+ { name: 'sangatbaik', value: totalSangatBaik, color: colors['blue-button'], key: 'sangatbaik' },
+ { name: 'baik', value: totalBaik, color: '#10A85AFF', key: 'baik' },
+ { name: 'kurangbaik', value: totalKurangBaik, color: '#B3AA12FF', key: 'kurangbaik' },
+ { name: 'tidakbaik', value: totalTidakBaik, color: '#B21313FF', key: 'tidakbaik' }
+ ]);
+ }
+
+ }, [stategrafikBerdasarkanResponden.findMany.data])
+
+ if (!stategrafikBerdasarkanResponden.findMany.data) {
+ return (
+
+
+
+ )
+ }
+ return (
+
+
+
+ }
+ />
+
+
+
+ Sangat Baik
+ Baik
+ Kurang Baik
+ Tidak Baik
+ Edit
+ Delete
+
+
+
+ {stategrafikBerdasarkanResponden.findMany.data.length === 0 ? (
+
+
+ Belum ada data grafik responden
+
+
+ ) : (
+ stategrafikBerdasarkanResponden.findMany.data.map((item) => (
+
+ {item.sangatbaik}
+ {item.baik}
+ {item.kurangbaik}
+ {item.tidakbaik}
+
+ router.push(`/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_responden/${item.id}`)}>
+
+
+
+
+ {
+ setSelectedId(item.id)
+ setModalHapus(true)
+ }}>
+
+
+
+
+ ))
+ )}
+
+
+
+
+
+ {/* Chart */}
+
+
+
+ Grafik Berdasarkan Responden
+ {mounted && donutData.length > 0 ? (
+
+
+ {donutData.map((entry, index) => (
+ |
+ ))}
+
+
+
+
+ Sangat Baik: {donutData.find((entry) => entry.name === 'sangatbaik')?.value}
+
+
+
+ Baik: {donutData.find((entry) => entry.name === 'baik')?.value}
+
+
+
+ Kurang Baik: {donutData.find((entry) => entry.name === 'kurangbaik')?.value}
+
+
+
+ Tidak Baik: {donutData.find((entry) => entry.name === 'tidakbaik')?.value}
+
+
+ ) : (
+ Belum ada data untuk ditampilkan dalam grafik
+ )}
+
+
+
+
+
+ {/* Modal Konfirmasi Hapus */}
+ setModalHapus(false)}
+ onConfirm={handleDelete}
+ text='Apakah anda yakin ingin menghapus grafik berdasarkan hasil responden ini?'
+ />
+
+ );
+}
+
+export default GrafikBerdasarkanResponden;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/[id]/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/[id]/page.tsx
new file mode 100644
index 00000000..373150fa
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/[id]/page.tsx
@@ -0,0 +1,97 @@
+'use client'
+/* eslint-disable react-hooks/exhaustive-deps */
+import grafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Title, TextInput } from '@mantine/core';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useParams, useRouter } from 'next/navigation';
+import React, { useEffect } from 'react';
+import { useProxy } from 'valtio/utils';
+
+function EditGrafikBerdasarakanUmur() {
+ const router = useRouter()
+ const params = useParams() as { id: string }
+ const stategrafikBerdasarkanUmur = useProxy(grafikBerdasarkanUmur)
+ const id = params.id
+
+ useEffect(() => {
+ if(id){
+ stategrafikBerdasarkanUmur.findUnique.load(id).then(() => {
+ const data = stategrafikBerdasarkanUmur.findUnique.data
+ if(data){
+ stategrafikBerdasarkanUmur.update.form = {
+ remaja: data.remaja || '',
+ dewasa: data.dewasa || '',
+ orangtua: data.orangtua || '',
+ lansia: data.lansia || '',
+ }
+ }
+ })
+ }
+ }, [id])
+
+ const handleSubmit = async () => {
+ stategrafikBerdasarkanUmur.update.id = id;
+ await stategrafikBerdasarkanUmur.update.submit();
+ router.push('/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur')
+ }
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
+ {
+ stategrafikBerdasarkanUmur.update.form.remaja = val.currentTarget.value;
+ }}
+ />
+ {
+ stategrafikBerdasarkanUmur.update.form.dewasa = val.currentTarget.value;
+ }}
+ />
+ {
+ stategrafikBerdasarkanUmur.update.form.orangtua = val.currentTarget.value;
+ }}
+ />
+ {
+ stategrafikBerdasarkanUmur.update.form.lansia = val.currentTarget.value;
+ }}
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default EditGrafikBerdasarakanUmur;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/create/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/create/page.tsx
new file mode 100644
index 00000000..e84e7c3e
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/create/page.tsx
@@ -0,0 +1,98 @@
+'use client'
+/* eslint-disable @typescript-eslint/no-unused-vars */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import grafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, Title, TextInput } from '@mantine/core';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import React, { useState } from 'react';
+import { useProxy } from 'valtio/utils';
+
+function GrafikBerdasarakanUmurCreate() {
+ const stategrafikBerdasarkanUmur = useProxy(grafikBerdasarkanUmur)
+ const [donutData, setDonutData] = useState([]);
+ const router = useRouter()
+
+ const resetForm = () => {
+ stategrafikBerdasarkanUmur.create.form = {
+ ...stategrafikBerdasarkanUmur.create.form,
+ remaja: "",
+ dewasa: "",
+ orangtua: "",
+ lansia: "",
+ }
+ }
+
+ const handleSubmit = async () => {
+ const id = await stategrafikBerdasarkanUmur.create.create();
+ if (id) {
+ const idStr = String(id);
+ await stategrafikBerdasarkanUmur.findUnique.load(idStr);
+ if (stategrafikBerdasarkanUmur.findUnique.data) {
+ setDonutData([stategrafikBerdasarkanUmur.findUnique.data]);
+ }
+ }
+ resetForm();
+ router.push("/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur")
+ }
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
+ {
+ stategrafikBerdasarkanUmur.create.form.remaja = val.currentTarget.value;
+ }}
+ />
+ {
+ stategrafikBerdasarkanUmur.create.form.dewasa = val.currentTarget.value;
+ }}
+ />
+ {
+ stategrafikBerdasarkanUmur.create.form.orangtua = val.currentTarget.value;
+ }}
+ />
+ {
+ stategrafikBerdasarkanUmur.create.form.lansia = val.currentTarget.value;
+ }}
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+export default GrafikBerdasarakanUmurCreate;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/page.tsx
new file mode 100644
index 00000000..6cfaae71
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/page.tsx
@@ -0,0 +1,181 @@
+'use client'
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import grafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
+import colors from '@/con/colors';
+import { Box, Button, Flex, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useEffect, useState } from 'react';
+import { Cell, Pie, PieChart } from 'recharts';
+import { useProxy } from 'valtio/utils';
+import JudulListTab from '../../../_com/jusulListTab';
+import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+
+function GrafikBerdasarakanUmur() {
+ const stategrafikBerdasarkanUmur = useProxy(grafikBerdasarkanUmur)
+ const [donutData, setDonutData] = useState([]);
+ const [mounted, setMounted] = useState(false);
+ const [modalHapus, setModalHapus] = useState(false)
+ const [selectedId, setSelectedId] = useState(null)
+ const router = useRouter()
+
+ const handleDelete = async () => {
+ if (selectedId) {
+ await grafikBerdasarkanUmur.delete.byId(selectedId)
+ setModalHapus(false)
+ setSelectedId(null)
+
+ stategrafikBerdasarkanUmur.findMany.load()
+ }
+ }
+
+ useShallowEffect(() => {
+ setMounted(true);
+ stategrafikBerdasarkanUmur.findMany.load()
+ }, []);
+
+ useEffect(() => {
+ if (stategrafikBerdasarkanUmur.findMany.data) {
+ const totalRemaja = stategrafikBerdasarkanUmur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.remaja || 0), 0);
+ const totalDewasa = stategrafikBerdasarkanUmur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.dewasa || 0), 0);
+ const totalOrangtua = stategrafikBerdasarkanUmur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.orangtua || 0), 0);
+ const totalLansia = stategrafikBerdasarkanUmur.findMany.data.reduce((acc: number, cur: any) => acc + Number(cur.lansia || 0), 0);
+ setDonutData([
+ { name: 'remaja', value: totalRemaja, color: colors['blue-button'], key: 'remaja' },
+ { name: 'dewasa', value: totalDewasa, color: '#D32711FF', key: 'dewasa' },
+ { name: 'orangtua', value: totalOrangtua, color: '#B46B04FF', key: 'orangtua' },
+ { name: 'lansia', value: totalLansia, color: '#038617FF', key: 'lansia' }
+ ]);
+ }
+ }, [stategrafikBerdasarkanUmur.findMany.data])
+
+ if (!stategrafikBerdasarkanUmur.findMany.data) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+
+ }
+ />
+
+
+
+ Remaja
+ Dewasa
+ Orangtua
+ Lansia
+ Edit
+ Delete
+
+
+
+ {stategrafikBerdasarkanUmur.findMany.data.length === 0 ? (
+
+
+ Belum ada data grafik responden
+
+
+ ) : (
+ stategrafikBerdasarkanUmur.findMany.data.map((item) => (
+
+ {item.remaja}
+ {item.dewasa}
+ {item.orangtua}
+ {item.lansia}
+
+ router.push(`/admin/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur/${item.id}`)}>
+
+
+
+
+ {
+ setSelectedId(item.id)
+ setModalHapus(true)
+ }}>
+
+
+
+
+ ))
+ )}
+
+
+
+
+
+ {/* Chart */}
+
+
+
+ Grafik Berdasarkan Responden
+ {mounted && donutData.length > 0 ? (
+
+
+ {donutData.map((entry, index) => (
+ |
+ ))}
+
+
+
+
+ Remaja: {donutData.find((entry) => entry.name === 'remaja')?.value}
+
+
+
+ Dewasa: {donutData.find((entry) => entry.name === 'dewasa')?.value}
+
+
+
+ Orangtua: {donutData.find((entry) => entry.name === 'orangtua')?.value}
+
+
+
+ Lansia: {donutData.find((entry) => entry.name === 'lansia')?.value}
+
+
+ ) : (
+ Belum ada data untuk ditampilkan dalam grafik
+ )}
+
+
+
+
+
+ {/* Modal Konfirmasi Hapus */}
+ setModalHapus(false)}
+ onConfirm={handleDelete}
+ text='Apakah anda yakin ingin menghapus grafik berdasarkan hasil responden ini?'
+ />
+
+ );
+}
+
+export default GrafikBerdasarakanUmur;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/[id]/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/[id]/page.tsx
new file mode 100644
index 00000000..09676dcb
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/[id]/page.tsx
@@ -0,0 +1,81 @@
+/* eslint-disable react-hooks/exhaustive-deps */
+'use client'
+
+import grafikHasilKepuasanMasyarakat from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, TextInput, Title } from '@mantine/core';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter, useParams } from 'next/navigation';
+import { useEffect } from 'react';
+import { useProxy } from 'valtio/utils';
+
+function EditGrafikHasilKepuasan() {
+ const router = useRouter()
+ const params = useParams() as { id: string }
+ const grafikHasilKepuasan = useProxy(grafikHasilKepuasanMasyarakat)
+
+ const id = params.id
+
+ // Load data saat komponen mount
+ useEffect(() => {
+ if (id) {
+ grafikHasilKepuasan.findUnique.load(id).then(() => {
+ const data = grafikHasilKepuasan.findUnique.data
+ if (data) {
+ grafikHasilKepuasan.update.form = {
+ label: data.label || '',
+ kepuasan: data.kepuasan || '',
+ }
+ }
+ })
+ }
+ }, [id])
+
+ const handleSubmit = async () => {
+ // Set the ID before submitting
+ grafikHasilKepuasan.update.id = id;
+ await grafikHasilKepuasan.update.submit();
+ router.push('/admin/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat')
+ }
+
+ return (
+
+
+ router.back()}>
+
+
+
+
+
+ Edit Grafik Hasil Kepuasan Masyarakat
+ {
+ grafikHasilKepuasan.update.form.label = val.currentTarget.value;
+ }}
+ />
+ {
+ grafikHasilKepuasan.update.form.kepuasan = val.currentTarget.value;
+ }}
+ />
+
+ Simpan Perubahan
+
+
+
+
+ )
+}
+
+export default EditGrafikHasilKepuasan;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/create/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/create/page.tsx
new file mode 100644
index 00000000..6947d435
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/create/page.tsx
@@ -0,0 +1,83 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+'use client'
+
+import grafikHasilKepuasanMasyarakat from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
+import colors from '@/con/colors';
+import { Box, Button, Paper, Stack, TextInput, Title } from '@mantine/core';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useState } from 'react';
+import { useProxy } from 'valtio/utils';
+
+
+function GrafikHasilKepuasan() {
+ const router = useRouter()
+ const grafikHasilKepuasan = useProxy(grafikHasilKepuasanMasyarakat)
+ const [chartData, setChartData] = useState([]);
+
+
+const resetForm = () => {
+ grafikHasilKepuasan.create.form = {
+ ...grafikHasilKepuasan.create.form,
+ label: "",
+ kepuasan: "",
+ }
+}
+
+const handleSubmit = async () => {
+ const id = await grafikHasilKepuasan.create.create();
+ if (id) {
+ // Ensure id is a string
+ const idStr = String(id);
+ await grafikHasilKepuasan.findUnique.load(idStr);
+ if (grafikHasilKepuasan.findUnique.data) {
+ setChartData([grafikHasilKepuasan.findUnique.data]);
+ }
+ }
+ resetForm();
+ router.push("/admin/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat")
+}
+ return (
+
+
+
+ router.back()}>
+
+
+
+
+
+ Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
+ {
+ grafikHasilKepuasan.create.form.label = val.currentTarget.value;
+ }}
+ />
+ {
+ grafikHasilKepuasan.create.form.kepuasan = val.currentTarget.value;
+ }}
+ />
+
+ Submit
+
+
+
+
+ );
+}
+
+
+export default GrafikHasilKepuasan;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/page.tsx
new file mode 100644
index 00000000..532ff1c6
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/page.tsx
@@ -0,0 +1,149 @@
+'use client'
+import JudulListTab from '@/app/admin/(dashboard)/_com/jusulListTab';
+import colors from '@/con/colors';
+import { Box, Button, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
+import { useMediaQuery, useShallowEffect } from '@mantine/hooks';
+import { IconEdit, IconSearch, IconTrash } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useEffect, useState } from 'react';
+import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts';
+import { useSnapshot } from 'valtio';
+import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
+import grafikHasilKepuasanMasyarakat from '../../../_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
+
+
+function GrafikHasilKepuasanMasyarakat() {
+ type IKMGrafik = {
+ id: string;
+ label: string;
+ kepuasan: number;
+ }
+
+
+ const stateGrafikHasilKepuasan = useSnapshot(grafikHasilKepuasanMasyarakat)
+ const [mounted, setMounted] = useState(false);
+ const [chartData, setChartData] = useState([]);
+ const isTablet = useMediaQuery('(max-width: 1024px)')
+ const isMobile = useMediaQuery('(max-width: 768px)')
+ const [modalHapus, setModalHapus] = useState(false)
+ const [selectedId, setSelectedId] = useState(null)
+ const router = useRouter();
+
+
+
+ const handleDelete = () => {
+ if (selectedId) {
+ stateGrafikHasilKepuasan.delete.byId(selectedId)
+ setModalHapus(false)
+ setSelectedId(null)
+
+ stateGrafikHasilKepuasan.findMany.load()
+ }
+ }
+
+ useShallowEffect(() => {
+ setMounted(true)
+ stateGrafikHasilKepuasan.findMany.load()
+ }, [])
+
+ useEffect(() => {
+ if (stateGrafikHasilKepuasan.findMany.data) {
+ setChartData(
+ stateGrafikHasilKepuasan.findMany.data.map((item) => ({
+ id: item.id,
+ label: item.label,
+ kepuasan: Number(item.kepuasan),
+ }))
+ );
+ }
+ }, [stateGrafikHasilKepuasan.findMany.data]);
+
+
+
+ if (!stateGrafikHasilKepuasan.findMany.data) {
+ return (
+
+
+
+ )
+ }
+ return (
+
+
+
+ }
+ />
+
+
+
+ Label
+ Jumlah Kepuasan
+ Edit
+ Delete
+
+
+
+ {stateGrafikHasilKepuasan.findMany.data?.map((item) => (
+
+ {item.label}
+ {item.kepuasan}
+
+ router.push(`/admin/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/${item.id}`)}>
+
+
+
+
+ {
+ setSelectedId(item.id)
+ setModalHapus(true)
+ }}>
+
+
+
+
+ ))}
+
+
+
+
+ {/* Chart */}
+
+
+
+ Data Kepuasan Masyarakat
+ {mounted && chartData.length > 0 ? (
+
+
+
+
+
+
+
+ ) : (
+ Belum ada data untuk ditampilkan dalam grafik
+ )}
+
+
+
+
+
+ {/* Modal Konfirmasi Hapus */}
+ setModalHapus(false)}
+ onConfirm={handleDelete}
+ text='Apakah anda yakin ingin menghapus grafik hasil kepuasan masyarakat ini?'
+ />
+
+
+ );
+}
+
+export default GrafikHasilKepuasanMasyarakat;
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/layout.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/layout.tsx
new file mode 100644
index 00000000..0b71bb62
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/layout.tsx
@@ -0,0 +1,10 @@
+'use client'
+import LayoutTabs from "../_com/layoutTabs";
+
+export default function Layout({children} : {children: React.ReactNode}) {
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/page.tsx b/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/page.tsx
deleted file mode 100644
index dbc9bdb3..00000000
--- a/src/app/admin/(dashboard)/ppid/ikm-desa-darmasaba/page.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
-import React from 'react';
-import colors from '@/con/colors';
-import GrafikHasilKepuasan from './_ui/grafik_hasil_kepuasan_masyarakat/page';
-import GrafikBerdasarkanJenisKelamin from './_ui/grafik_berdasarkan_jenis_kelamin_responden/page';
-import GrafikBerdasarkanResponden from './_ui/grafik_berdasarkan_responden/page';
-import GrafikBerdasarakanUmur from './_ui/grafik_berdasarkan_umur/page';
-
-function Page() {
- return (
-
- Indeks Kepuasan Masyarakat (IKM) Desa Darmasaba
-
-
-
- Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik
-
-
- Grafik Berdasarkan Jenis Kelamin Responden
-
-
- Grafik Berdasarkan Pilihan Responden
-
-
- Grafik Berdasarkan Umur Responden
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default Page;
diff --git a/src/app/admin/(dashboard)/ppid/permohonan-informasi-publik/page.tsx b/src/app/admin/(dashboard)/ppid/permohonan-informasi-publik/page.tsx
index 020e782f..0f5559d7 100644
--- a/src/app/admin/(dashboard)/ppid/permohonan-informasi-publik/page.tsx
+++ b/src/app/admin/(dashboard)/ppid/permohonan-informasi-publik/page.tsx
@@ -10,9 +10,10 @@ function Page() {
useShallowEffect(() => {
permohonanInformasiPublikState.statepermohonanInformasiPublik.findMany.load()
}, [])
- if (!permohonanInformasiPublikState.statepermohonanInformasiPublik.findMany.data) return
- {Array.from({ length: 10 }).map((v, k) => )}
-
+ if (!permohonanInformasiPublikState.statepermohonanInformasiPublik.findMany.data)
+ return
+
+
return (
diff --git a/src/app/admin/(dashboard)/ppid/permohonan-keberatan-informasi-publik/page.tsx b/src/app/admin/(dashboard)/ppid/permohonan-keberatan-informasi-publik/page.tsx
index a367b20d..a53f6f4d 100644
--- a/src/app/admin/(dashboard)/ppid/permohonan-keberatan-informasi-publik/page.tsx
+++ b/src/app/admin/(dashboard)/ppid/permohonan-keberatan-informasi-publik/page.tsx
@@ -11,9 +11,11 @@ function Page() {
listState.findMany.load()
}, [])
- if (!listState.findMany.data) return
- {Array.from({ length: 10 }).map((v, k) => )}
-
+ if (!listState.findMany.data)
+ return
+
+
+
return (
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/biodata/biodataForm.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/biodata/biodataForm.tsx
new file mode 100644
index 00000000..a47d7cc3
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/biodata/biodataForm.tsx
@@ -0,0 +1,28 @@
+'use client'
+import { Box, Text } from '@mantine/core';
+import EditPPIDEditor from '../../_com/editPPIDEditor';
+
+
+
+function Biodata({
+ value,
+ onChange,
+ error,
+}: {
+ value: string;
+ onChange: (val: string) => void;
+ error?: string;
+}) {
+
+ return (
+ Biodata
+
+ {error && {error} }
+
+ );
+}
+
+export default Biodata;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/page.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/page.tsx
new file mode 100644
index 00000000..72956a86
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/page.tsx
@@ -0,0 +1,256 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+'use client'
+import colors from '@/con/colors';
+import { Alert, Box, Button, Center, FileInput, Group, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
+import { useEffect, useState } from 'react';
+import { useProxy } from 'valtio/utils';
+import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
+
+import ApiFetch from '@/lib/api-fetch';
+import { IconAlertCircle, IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useParams, useRouter } from 'next/navigation';
+import { toast } from 'react-toastify';
+import Biodata from './biodata/biodataForm';
+import PengalamanOrganisasi from './pengalaman_organisasi/pengalamanForm';
+import ProgramKerjaUnggulan from './program_kerja_unggulan/programKerjaForm';
+import RiwayatKarir from './riwayat_karir/riwayatKarirForm';
+
+function EditProfilePPID() {
+ const allState = useProxy(stateProfilePPID);
+ const params = useParams();
+ const router = useRouter();
+
+ // UI States
+ const [previewImage, setPreviewImage] = useState(null);
+ const [file, setFile] = useState(null);
+ const [isSubmitting, setIsSubmitting] = useState(false);
+
+ // Load data on mount
+ useEffect(() => {
+ const loadData = async () => {
+ const id = params?.id as string;
+ if (!id) {
+ toast.error("ID tidak valid");
+ router.push("/admin/ppid/profile-ppid");
+ return;
+ }
+
+ try {
+ const profileData = await stateProfilePPID.loadForEdit(id);
+
+ if (profileData && profileData.image?.link) {
+ setPreviewImage(profileData.image.link);
+ }
+ } catch (error) {
+ console.error("Error loading profile:", error);
+ toast.error("Gagal memuat data profile");
+ }
+ };
+
+ loadData();
+
+ return () => {
+ stateProfilePPID.editForm.reset(); // cleanup form
+ };
+ }, [params?.id, router]);
+
+ const handleFieldChange = (field: string, value: string) => {
+ stateProfilePPID.editForm.updateField(field as any, value);
+ };
+
+ const handleFileChange = (newFile: File | null) => {
+ if (!newFile) {
+ setFile(null);
+ return;
+ }
+
+ setFile(newFile);
+
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ setPreviewImage(event.target?.result as string);
+ };
+ reader.readAsDataURL(newFile);
+ };
+
+ const handleSubmit = async () => {
+ if (isSubmitting || !stateProfilePPID.editForm.form.name.trim()) {
+ toast.error("Nama wajib diisi");
+ return;
+ }
+
+ setIsSubmitting(true);
+
+ try {
+ // Upload file jika ada
+ if (file) {
+ const uploadResponse = await ApiFetch.api.fileStorage.create.post({ file, name: file.name });
+ const uploaded = uploadResponse.data?.data;
+
+ if (!uploaded?.id) {
+ toast.error("Gagal upload gambar");
+ return;
+ }
+
+ stateProfilePPID.editForm.form.imageId = uploaded.id;
+ }
+
+ // Submit form
+ const success = await stateProfilePPID.editForm.submit();
+
+ if (success) {
+ toast.success("Berhasil menyimpan perubahan");
+ router.push("/admin/ppid/profile-ppid");
+ }
+ } catch (error) {
+ console.error("Error submitting form:", error);
+ toast.error("Gagal menyimpan profile");
+ } finally {
+ setIsSubmitting(false);
+ }
+ };
+
+ const handleBack = () => {
+ router.back();
+ };
+
+ // Loading state
+ if (allState.profile.loading) {
+ return (
+
+
+ Memuat data profile...
+
+
+ );
+ }
+
+ // Error state
+ if (allState.profile.error) {
+ return (
+
+
+
+
+
+ } color="red">
+ Error
+ {allState.profile.error}
+
+
+
+ );
+ }
+
+ // No data state
+ if (!allState.profile.data) {
+ return (
+
+
+
+
+
+ } color="yellow">
+ Data tidak ditemukan
+ Profile PPID tidak dapat ditemukan
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ Edit Profile PPID
+
+ {/* Nama Field */}
+ Nama Perbekel}
+ placeholder="Masukkan nama perbekel"
+ value={allState.editForm.form.name}
+ onChange={(e) => handleFieldChange('name', e.currentTarget.value)}
+ error={!allState.editForm.form.name && "Nama wajib diisi"}
+ />
+
+ {/* File Upload */}
+ Upload Gambar Baru (Opsional)}
+ value={file}
+ onChange={handleFileChange}
+ accept="image/*"
+ />
+
+ {/* Preview Gambar */}
+
+ Preview Gambar
+ {previewImage ? (
+
+ ) : (
+
+
+
+ Tidak ada gambar
+
+
+ )}
+
+
+ {/* Rich Components */}
+ handleFieldChange('biodata', val)}
+ />
+
+ handleFieldChange('riwayat', val)}
+ />
+
+ handleFieldChange('pengalaman', val)}
+ />
+
+ handleFieldChange('unggulan', val)}
+ />
+
+ {/* Submit Button */}
+
+
+ {isSubmitting ? 'Menyimpan...' : 'Simpan Perubahan'}
+
+
+
+ Batal
+
+
+
+
+
+
+
+ );
+}
+
+export default EditProfilePPID;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/pengalaman_organisasi/pengalamanForm.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/pengalaman_organisasi/pengalamanForm.tsx
new file mode 100644
index 00000000..9ff967de
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/pengalaman_organisasi/pengalamanForm.tsx
@@ -0,0 +1,26 @@
+'use client'
+import { Box, Text } from '@mantine/core';
+import EditPPIDEditor from '../../_com/editPPIDEditor';
+
+
+function PengalamanOrganisasi({
+ value,
+ onChange,
+ error,
+}: {
+ value: string;
+ onChange: (val: string) => void;
+ error?: string;
+}) {
+ return (
+ Pengalaman Organisasi
+
+ {error && {error} }
+
+ );
+}
+
+export default PengalamanOrganisasi;
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/program_kerja_unggulan/programKerjaForm.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/program_kerja_unggulan/programKerjaForm.tsx
new file mode 100644
index 00000000..5512fe9f
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/program_kerja_unggulan/programKerjaForm.tsx
@@ -0,0 +1,26 @@
+'use client'
+import { Box, Text } from '@mantine/core';
+import EditPPIDEditor from '../../_com/editPPIDEditor';
+
+function ProgramKerjaUnggulan({
+ value,
+ onChange,
+ error,
+}: {
+ value: string;
+ onChange: (val: string) => void;
+ error?: string;
+}) {
+
+ return (
+ Program Kerja Unggulan
+
+ {error && {error} }
+
+ );
+}
+
+export default ProgramKerjaUnggulan;
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/riwayat_karir/riwayatKarirForm.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/riwayat_karir/riwayatKarirForm.tsx
new file mode 100644
index 00000000..31077f3f
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/profile-ppid/[id]/riwayat_karir/riwayatKarirForm.tsx
@@ -0,0 +1,29 @@
+'use client';
+
+import { Box, Text } from '@mantine/core';
+import EditPPIDEditor from '../../_com/editPPIDEditor';
+
+
+
+function RiwayatKarir({
+ value,
+ onChange,
+ error,
+}: {
+ value: string;
+ onChange: (val: string) => void;
+ error?: string;
+}) {
+ return (
+
+ Riwayat Karir
+
+ {error && {error} }
+
+ );
+}
+
+export default RiwayatKarir;
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/_com/biodata.ts b/src/app/admin/(dashboard)/ppid/profile-ppid/_com/biodata.ts
deleted file mode 100644
index 418aeb48..00000000
--- a/src/app/admin/(dashboard)/ppid/profile-ppid/_com/biodata.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-const biodata = {
- id: "1",
- name: "I.B Surya Prabhawa Manuaba, S.H., M.H.
",
- biodata: "Biodata ....
",
- riwayat: "Riwayat Karir ",
- pengalaman: "Pengalaman Organisasi ",
- unggulan: "Program Kerja Unggulan ... ",
-}
-
-export default biodata
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/_com/editPPIDEditor.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/_com/editPPIDEditor.tsx
new file mode 100644
index 00000000..987100c5
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/profile-ppid/_com/editPPIDEditor.tsx
@@ -0,0 +1,101 @@
+'use client'
+import { RichTextEditor, Link } from '@mantine/tiptap';
+import { useEditor } from '@tiptap/react';
+import Highlight from '@tiptap/extension-highlight';
+import StarterKit from '@tiptap/starter-kit';
+import Underline from '@tiptap/extension-underline';
+import TextAlign from '@tiptap/extension-text-align';
+import Superscript from '@tiptap/extension-superscript';
+import SubScript from '@tiptap/extension-subscript';
+import { useEffect } from 'react';
+
+type EditEditorProps = {
+ value: string;
+ onChange: (content: string) => void;
+};
+
+export default function EditPPIDEditor({ value, onChange }: EditEditorProps) {
+ const editor = useEditor({
+ extensions: [
+ StarterKit,
+ Underline,
+ Link,
+ Superscript,
+ SubScript,
+ Highlight,
+ TextAlign.configure({ types: ['heading', 'paragraph'] }),
+ ],
+ onUpdate({ editor }) {
+ onChange(editor.getHTML());
+ },
+ });
+
+ useEffect(() => {
+ if (editor && value && value !== editor.getHTML()) {
+ editor.commands.setContent(value);
+ }
+ }, [editor, value]);
+
+ useEffect(() => {
+ if (!editor) return;
+
+ const updateHandler = () => onChange(editor.getHTML());
+ editor.on('update', updateHandler);
+
+ return () => {
+ editor.off('update', updateHandler);
+ };
+ }, [editor, onChange]);
+
+ return (
+
+
+ {/* Toolbar seperti sebelumnya */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/biodata/page.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/biodata/page.tsx
deleted file mode 100644
index bde2d57d..00000000
--- a/src/app/admin/(dashboard)/ppid/profile-ppid/biodata/page.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-'use client'
-import { Box, Group, Text } from '@mantine/core';
-import { useState } from 'react';
-
-import ApiFetch from '@/lib/api-fetch';
-import { Dropzone, MIME_TYPES } from '@mantine/dropzone';
-import { IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
-import { useProxy } from 'valtio/utils';
-import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
-import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
-
-function Biodata() {
- const biodataState = useProxy(stateProfilePPID)
- const [loading, setLoading] = useState(false);
-
- return (
- Biodata
- {
- setLoading(true);
- for (const file of droppedFiles) {
- await ApiFetch.api.ppid.profileppid["edit-img"].post({
- file: file,
- id: biodataState.findById.data?.id,
- });
- }
-
- setLoading(false);
- if (biodataState.findById.data?.id) {
- biodataState.findById.load(biodataState.findById.data.id);
- }
- }}
- accept={[MIME_TYPES.jpeg, MIME_TYPES.png, MIME_TYPES.webp]}
- loading={loading}
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
- Drag & drop gambar di sini atau klik untuk pilih file
-
-
- Maksimal ukuran file 5MB. Format: JPG, PNG, WebP
-
-
-
-
-
-
-
- {
- if (biodataState.findById.data) {
- biodataState.findById.data.biodata = val;
- }
- }}
- initialContent={biodataState.findById.data?.biodata ?? ''}
- />
-
-
- );
-}
-
-export default Biodata;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/listPage.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/listPage.tsx
deleted file mode 100644
index 76120428..00000000
--- a/src/app/admin/(dashboard)/ppid/profile-ppid/listPage.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import colors from '@/con/colors';
-import { Stack, Skeleton, Paper, Title, Box, Text, Image } from '@mantine/core';
-import { useShallowEffect } from '@mantine/hooks';
-import React from 'react';
-import { useProxy } from 'valtio/utils';
-import stateProfilePPID from '../../_state/ppid/profile_ppid/profile_PPID';
-
-function ProfileList() {
- const allList = useProxy(stateProfilePPID)
- useShallowEffect(() => {
- allList.findById.load("1") // Assuming "1" is your default ID, adjust as needed
- }, [])
-
- if (!allList.findById.data) return
- {Array.from({ length: 10 }).map((v, k) => )}
-
-
- const dataArray = Array.isArray(allList.findById.data)
- ? allList.findById.data
- : [allList.findById.data];
-
- return (
-
-
- List Profile PPID
- {dataArray.map((item) => (
-
- {item.imageUrl && (
-
- Preview Gambar:
-
-
- )}
-
- Nama
-
-
-
- Biodata
-
-
-
- Riwayat
-
-
-
- Pengalaman
-
-
-
- Program Kerja Unggulan
-
-
-
- ))}
-
-
- )
-}
-
-export default ProfileList;
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/page.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/page.tsx
index de1a55a3..17cfc301 100644
--- a/src/app/admin/(dashboard)/ppid/profile-ppid/page.tsx
+++ b/src/app/admin/(dashboard)/ppid/profile-ppid/page.tsx
@@ -1,89 +1,120 @@
'use client'
import colors from '@/con/colors';
-import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
-import Biodata from './biodata/page';
-import PengalamanOrganisasi from './pengalaman_organisasi/page';
-import RiwayatKarir from './riwayat_karir/page';
-import ProgramKerjaUnggulan from './program_kerja_unggulan/page';
+import { Box, Button, Center, Divider, Grid, GridCol, Image, 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 stateProfilePPID from '../../_state/ppid/profile_ppid/profile_PPID';
-import { useShallowEffect } from '@mantine/hooks';
-import ProfileList from './listPage';
-import { useState } from 'react';
-import { toast } from 'react-toastify';
function Page() {
- return (
-
-
-
-
-
-
- );
-}
-
-function ProfileCreate() {
- const [isLoading, setIsLoading] = useState(false)
- const allState = useProxy(stateProfilePPID)
-
- // Initialize data if it doesn't exist
+ const router = useRouter()
+ const allList = useProxy(stateProfilePPID)
useShallowEffect(() => {
- if (!allState.findById.data && isLoading) {
- allState.findById.initialize()
- setIsLoading(false)
- }
- }, [isLoading])
+ allList.profile.load("edit") // Assuming "1" is your default ID, adjust as needed
+ }, [])
- const submit = () => {
- if (
- allState.findById.data?.name &&
- allState.findById.data?.biodata &&
- allState.findById.data?.riwayat &&
- allState.findById.data?.pengalaman &&
- allState.findById.data?.unggulan
- ) {
- allState.update.save(allState.findById.data)
- setIsLoading(true)
- toast.success("success")
- console.log("[SUBMIT SUCCESS]", JSON.stringify(allState.findById.data, null, 2))
- allState.findById.initialize()
- } else {
- toast.error("error")
- }
+ if (!allList.profile.data) {
+ return
+
+
}
+ const dataArray = Array.isArray(allList.profile.data)
+ ? allList.profile.data
+ : [allList.profile.data];
+
return (
-
+
- Profile PPID
- Nama Perbekel}
- placeholder="masukkan nama perbekel"
- value={allState.findById.data?.name || ''}
- onChange={(val) => {
- if (allState.findById.data) {
- allState.findById.data.name = val.currentTarget.value
- }
- }}
- />
-
-
-
-
-
-
- Submit
-
-
+
+
+ Preview Profile PPID
+
+
+ router.push(`/admin/ppid/profile-ppid/${allList.profile.data?.id}`)}>
+
+
+
+
+ {dataArray.map((item) => (
+
+
+
+
+
+
+
+
+
+
+ PROFIL PIMPINAN BADAN PUBLIK DESA DARMASABA
+
+
+
+
+ {/* biodata perbekel */}
+
+
+
+
+
+ {
+ e.currentTarget.src = "/perbekel.png";
+ }}
+ />
+
+
+
+ {item.name}
+
+
+
+
+
+
+
+ Biodata
+
+
+
+ Riwayat Karir
+
+
+
+
+ Pengalaman Organisasi
+
+
+
+
+
+ Program Kerja Unggulan
+
+
+
+
+
+
+
+ ))}
)
}
+
+
export default Page;
\ No newline at end of file
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/pengalaman_organisasi/page.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/pengalaman_organisasi/page.tsx
deleted file mode 100644
index 20be1859..00000000
--- a/src/app/admin/(dashboard)/ppid/profile-ppid/pengalaman_organisasi/page.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-'use client'
-import { Box, Text } from '@mantine/core';
-import React from 'react';
-import { useProxy } from 'valtio/utils';
-import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
-import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
-
-function PengalamanOrganisasi() {
- const pengalamanOrganisasiState = useProxy(stateProfilePPID)
- return (
- Pengalaman Organisasi
- {
- if (pengalamanOrganisasiState.findById.data) {
- pengalamanOrganisasiState.findById.data.pengalaman = val;
- }
- }}
- initialContent={pengalamanOrganisasiState.findById.data?.pengalaman ?? ''}
- />
-
- );
-}
-
-export default PengalamanOrganisasi;
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/program_kerja_unggulan/page.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/program_kerja_unggulan/page.tsx
deleted file mode 100644
index c643f51e..00000000
--- a/src/app/admin/(dashboard)/ppid/profile-ppid/program_kerja_unggulan/page.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-'use client'
-import { Box, Text } from '@mantine/core';
-import React from 'react';
-import { useProxy } from 'valtio/utils';
-import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
-import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
-
-function ProgramKerjaUnggulan() {
- const programKerjaUnggulanState = useProxy(stateProfilePPID)
- return (
- Program Kerja Unggulan
- {
- if (programKerjaUnggulanState.findById.data) {
- programKerjaUnggulanState.findById.data.unggulan = val;
- }
- }}
- initialContent={programKerjaUnggulanState.findById.data?.unggulan ?? ''}
- />
-
- );
-}
-
-export default ProgramKerjaUnggulan;
diff --git a/src/app/admin/(dashboard)/ppid/profile-ppid/riwayat_karir/page.tsx b/src/app/admin/(dashboard)/ppid/profile-ppid/riwayat_karir/page.tsx
deleted file mode 100644
index f1ecd870..00000000
--- a/src/app/admin/(dashboard)/ppid/profile-ppid/riwayat_karir/page.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-'use client';
-
-import { Box, Text } from '@mantine/core';
-import React from 'react';
-import { useProxy } from 'valtio/utils';
-import dynamic from 'next/dynamic';
-import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
-
-// ini penting
-const PPIDTextEditor = dynamic(() => import('../../_com/PPIDTextEditor').then(mod => mod.PPIDTextEditor), {
- ssr: false, // disable server side rendering
-});
-function RiwayatKarir() {
- const riwayatKarirState = useProxy(stateProfilePPID);
-
- return (
-
- Riwayat Karir
- {
- if (riwayatKarirState.findById.data) {
- riwayatKarirState.findById.data.riwayat = val;
- }
- }}
- initialContent={riwayatKarirState.findById.data?.riwayat ?? ''}
- />
-
- );
-}
-
-export default RiwayatKarir;
diff --git a/src/app/admin/(dashboard)/ppid/struktur-ppid/[id]/page.tsx b/src/app/admin/(dashboard)/ppid/struktur-ppid/[id]/page.tsx
new file mode 100644
index 00000000..e07ca511
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/struktur-ppid/[id]/page.tsx
@@ -0,0 +1,225 @@
+/* eslint-disable react-hooks/exhaustive-deps */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+'use client'
+import colors from '@/con/colors';
+import {
+ Alert,
+ Box,
+ Button, Center, FileInput, Group, Image, Paper,
+ Stack,
+ Text,
+ TextInput,
+ Title
+} from '@mantine/core';
+import { IconAlertCircle, IconArrowBack, IconImageInPicture } from '@tabler/icons-react';
+import { useParams, useRouter } from 'next/navigation';
+import { useEffect, useState } from 'react';
+import { useProxy } from 'valtio/utils';
+import stateStrukturPPID from '../../../_state/ppid/struktur_ppid/struktur_PPID';
+import { toast } from 'react-toastify';
+import ApiFetch from '@/lib/api-fetch';
+
+
+function EditStrukturPPID() {
+ const strukturPPID = useProxy(stateStrukturPPID);
+ const params = useParams();
+ const router = useRouter()
+
+ const [previewImage, setPreviewImage] = useState(null);
+ const [file, setFile] = useState(null);
+ const [isSubmitting, setIsSubmitting] = useState(false);
+
+ useEffect(() => {
+ const loadData = async () => {
+ const id = params?.id as string;
+ if (!id) {
+ toast.error("ID tidak valid");
+ router.push("/admin/ppid/struktur-ppid");
+ return;
+ }
+
+ try {
+ const profileData = await strukturPPID.loadForEdit(id);
+
+ if (profileData && profileData.image?.link) {
+ setPreviewImage(profileData.image.link);
+ }
+ } catch (error) {
+ console.error("Error loading profile:", error);
+ toast.error("Gagal memuat data profile");
+ }
+ };
+
+ loadData();
+
+ return () => {
+ strukturPPID.editStruktur.reset(); // cleanup form
+ };
+ }, [params?.id, router]);
+
+ const handleFieldChange = (field: string, value: string) => {
+ strukturPPID.editStruktur.updateField(field as any, value);
+ };
+
+ const handleFileChange = (newFile: File | null) => {
+ if (!newFile) {
+ setFile(null);
+ return;
+ }
+
+ setFile(newFile);
+
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ setPreviewImage(event.target?.result as string);
+ };
+ reader.readAsDataURL(newFile);
+ };
+
+ const handleSubmit = async () => {
+ if (isSubmitting || !strukturPPID.editStruktur.form.name.trim()) {
+ toast.error("Nama wajib diisi");
+ return;
+ }
+
+ setIsSubmitting(true);
+
+ try {
+ // Upload file jika ada
+ if (file) {
+ const uploadResponse = await ApiFetch.api.fileStorage.create.post({ file, name: file.name });
+ const uploaded = uploadResponse.data?.data;
+
+ if (!uploaded?.id) {
+ toast.error("Gagal upload gambar");
+ return;
+ }
+
+ strukturPPID.editStruktur.form.imageId = uploaded.id;
+ }
+
+ // Submit form
+ const success = await strukturPPID.editStruktur.submit();
+
+ if (success) {
+ toast.success("Berhasil menyimpan perubahan");
+ router.push("/admin/ppid/struktur-ppid");
+ }
+ } catch (error) {
+ console.error("Error submitting form:", error);
+ toast.error("Gagal menyimpan profile");
+ } finally {
+ setIsSubmitting(false);
+ }
+ };
+
+ const handleBack = () => {
+ router.back();
+ };
+
+ if (strukturPPID.struktur.loading) {
+ return (
+
+
+ Memuat data struktur...
+
+
+ );
+ }
+
+ // Error state
+ if (strukturPPID.struktur.error) {
+ return (
+
+
+
+
+
+ } color="red">
+ Error
+ {strukturPPID.struktur.error}
+
+
+
+ );
+ }
+
+ // No data state
+ if (!strukturPPID.struktur.data) {
+ return (
+
+
+
+
+
+ } color="yellow">
+ Data tidak ditemukan
+ Profile PPID tidak dapat ditemukan
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ Edit Struktur PPID
+ handleFieldChange('name', e.currentTarget.value)}
+ label={Judul }
+ placeholder="Masukkan judul"
+ />
+ {/* File Upload */}
+ Upload Gambar Baru (Opsional)}
+ value={file}
+ onChange={handleFileChange}
+ accept="image/*"
+ />
+
+ {/* Preview Gambar */}
+
+ Preview Gambar
+ {previewImage ? (
+
+ ) : (
+
+
+
+ Tidak ada gambar
+
+
+ )}
+
+
+
+
+ Submit
+
+
+
+
+
+
+
+ );
+}
+
+export default EditStrukturPPID;
diff --git a/src/app/admin/(dashboard)/ppid/struktur-ppid/page.tsx b/src/app/admin/(dashboard)/ppid/struktur-ppid/page.tsx
index 705991db..fcdb063a 100644
--- a/src/app/admin/(dashboard)/ppid/struktur-ppid/page.tsx
+++ b/src/app/admin/(dashboard)/ppid/struktur-ppid/page.tsx
@@ -1,10 +1,59 @@
-import React from 'react';
+'use client'
+import colors from '@/con/colors';
+import { Box, Button, Grid, GridCol, Image, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
+import { IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useProxy } from 'valtio/utils';
+import stateStrukturPPID from '../../_state/ppid/struktur_ppid/struktur_PPID';
+import { useShallowEffect } from '@mantine/hooks';
function Page() {
+ const router = useRouter()
+ const strukturPPID = useProxy(stateStrukturPPID)
+ useShallowEffect(() => {
+ strukturPPID.struktur.load("1")
+ }, [])
+
+ if (!strukturPPID.struktur.data) {
+ return
+
+
+ }
+
+ const dataArray = Array.isArray(strukturPPID.struktur.data)
+ ? strukturPPID.struktur.data
+ : [strukturPPID.struktur.data];
+
return (
-
- struktur-ppid
-
+
+
+
+
+ Preview Struktur PPID
+
+
+ router.push(`/admin/ppid/struktur-ppid/${strukturPPID.struktur.data?.id}`)} bg={colors['blue-button']}>
+
+
+
+
+ {dataArray.map((item) => (
+
+
+ {item.name}
+ {
+ e.currentTarget.src = "/struktur_ppid.png";
+ }}
+ />
+
+
+ ))}
+
+
);
}
diff --git a/src/app/admin/(dashboard)/ppid/visi-misi-ppid/edit/backup.txt b/src/app/admin/(dashboard)/ppid/visi-misi-ppid/edit/backup.txt
new file mode 100644
index 00000000..c73e804b
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/visi-misi-ppid/edit/backup.txt
@@ -0,0 +1,115 @@
+'use client'
+import colors from '@/con/colors';
+import {
+ Box, Button, Group, Paper, SimpleGrid, Skeleton, Stack, Text, Title
+} from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import { useProxy } from 'valtio/utils';
+import { useEffect, useState } from 'react';
+import stateVisiMisiPPID from '../../../_state/ppid/visi_misi_ppid/visimisiPPID';
+import MisiPPID from '../misiPPID/misi-PPID';
+import VisiPPID from '../visiPPID/visi-PPID';
+
+
+
+
+function Page() {
+ return (
+
+
+
+
+
+
+ );
+}
+
+function VisiMisiPPIDCreate() {
+ const visiMisi = useProxy(stateVisiMisiPPID);
+ const [draftVisi, setDraftVisi] = useState('');
+ const [draftMisi, setDraftMisi] = useState('');
+
+ useShallowEffect(() => {
+ if (!visiMisi.findById.data) {
+ visiMisi.findById.initialize();
+ }
+ }, []);
+
+ useEffect(() => {
+ if (visiMisi.findById.data) {
+ setDraftVisi(visiMisi.findById.data.visi ?? '');
+ setDraftMisi(visiMisi.findById.data.misi ?? '');
+ }
+ }, [visiMisi.findById.data]);
+
+ const submit = () => {
+ if (visiMisi.findById.data) {
+ // update nilai di state global hanya saat submit
+ visiMisi.findById.data.visi = draftVisi;
+ visiMisi.findById.data.misi = draftMisi;
+ visiMisi.update.save(visiMisi.findById.data);
+ }
+ };
+
+ return (
+
+
+ Visi Misi PPID
+
+
+
+
+ Submit
+
+
+
+
+ );
+}
+
+function VisiMisiPPIDList() {
+ const listVisiMisi = useProxy(stateVisiMisiPPID);
+ useShallowEffect(() => {
+ listVisiMisi.findById.load('1');
+ }, []);
+
+ if (!listVisiMisi.findById.data) {
+ return (
+
+ {Array.from({ length: 10 }).map((_, k) => (
+
+ ))}
+
+ );
+ }
+
+ return (
+
+
+ List Visi Misi PPID
+
+ Visi PPID
+
+
+
+ Misi PPID
+
+
+
+
+ );
+}
+
+export default Page;
diff --git a/src/app/admin/(dashboard)/ppid/visi-misi-ppid/edit/page.tsx b/src/app/admin/(dashboard)/ppid/visi-misi-ppid/edit/page.tsx
new file mode 100644
index 00000000..f88bb835
--- /dev/null
+++ b/src/app/admin/(dashboard)/ppid/visi-misi-ppid/edit/page.tsx
@@ -0,0 +1,81 @@
+'use client'
+import colors from '@/con/colors';
+import {
+ Box,
+ Button, Group, Paper,
+ Stack,
+ Title
+} from '@mantine/core';
+import { useShallowEffect } from '@mantine/hooks';
+import { IconArrowBack } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
+import { useEffect, useState } from 'react';
+import { useProxy } from 'valtio/utils';
+import stateVisiMisiPPID from '../../../_state/ppid/visi_misi_ppid/visimisiPPID';
+import MisiPPID from '../misiPPID/misi-PPID';
+import VisiPPID from '../visiPPID/visi-PPID';
+
+
+function VisiMisiPPIDEdit() {
+ const router = useRouter()
+ const visiMisi = useProxy(stateVisiMisiPPID);
+ const [draftVisi, setDraftVisi] = useState('');
+ const [draftMisi, setDraftMisi] = useState('');
+
+ useShallowEffect(() => {
+ if (!visiMisi.findById.data) {
+ visiMisi.findById.initialize();
+ }
+ }, []);
+
+ useEffect(() => {
+ if (visiMisi.findById.data) {
+ setDraftVisi(visiMisi.findById.data.visi ?? '');
+ setDraftMisi(visiMisi.findById.data.misi ?? '');
+ }
+ }, [visiMisi.findById.data]);
+
+ const submit = () => {
+ if (visiMisi.findById.data) {
+ // update nilai di state global hanya saat submit
+ visiMisi.findById.data.visi = draftVisi;
+ visiMisi.findById.data.misi = draftMisi;
+ visiMisi.update.save(visiMisi.findById.data);
+ }
+ };
+
+ return (
+
+
+
+ router.back()}
+ >
+
+
+
+
+
+
+ Edit Visi Misi PPID
+
+
+
+
+ Submit
+
+
+
+
+
+
+
+ );
+}
+
+export default VisiMisiPPIDEdit;
diff --git a/src/app/admin/(dashboard)/ppid/visi-misi-ppid/page.tsx b/src/app/admin/(dashboard)/ppid/visi-misi-ppid/page.tsx
index 5cbdbbb5..362d72db 100644
--- a/src/app/admin/(dashboard)/ppid/visi-misi-ppid/page.tsx
+++ b/src/app/admin/(dashboard)/ppid/visi-misi-ppid/page.tsx
@@ -1,76 +1,25 @@
'use client'
import colors from '@/con/colors';
import {
- Box, Button, Group, Paper, SimpleGrid, Skeleton, Stack, Text, Title
+ Box,
+ Button,
+ Center,
+ Grid,
+ GridCol,
+ Image,
+ Paper,
+ Skeleton, Stack, Text,
+ Title
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { useProxy } from 'valtio/utils';
-import { useEffect, useState } from 'react';
import stateVisiMisiPPID from '../../_state/ppid/visi_misi_ppid/visimisiPPID';
-import VisiPPID from './visiPPID/visi-PPID';
-import MisiPPID from './misiPPID/misi-PPID';
+import { IconEdit } from '@tabler/icons-react';
+import { useRouter } from 'next/navigation';
-
-function Page() {
- return (
-
-
-
-
-
-
- );
-}
-
-function VisiMisiPPIDCreate() {
- const visiMisi = useProxy(stateVisiMisiPPID);
- const [draftVisi, setDraftVisi] = useState('');
- const [draftMisi, setDraftMisi] = useState('');
-
- useShallowEffect(() => {
- if (!visiMisi.findById.data) {
- visiMisi.findById.initialize();
- }
- }, []);
-
- useEffect(() => {
- if (visiMisi.findById.data) {
- setDraftVisi(visiMisi.findById.data.visi ?? '');
- setDraftMisi(visiMisi.findById.data.misi ?? '');
- }
- }, [visiMisi.findById.data]);
-
- const submit = () => {
- if (visiMisi.findById.data) {
- // update nilai di state global hanya saat submit
- visiMisi.findById.data.visi = draftVisi;
- visiMisi.findById.data.misi = draftMisi;
- visiMisi.update.save(visiMisi.findById.data);
- }
- };
-
- return (
-
-
- Visi Misi PPID
-
-
-
-
- Submit
-
-
-
-
- );
-}
-
function VisiMisiPPIDList() {
+ const router = useRouter()
const listVisiMisi = useProxy(stateVisiMisiPPID);
useShallowEffect(() => {
listVisiMisi.findById.load('1');
@@ -79,36 +28,56 @@ function VisiMisiPPIDList() {
if (!listVisiMisi.findById.data) {
return (
- {Array.from({ length: 10 }).map((_, k) => (
-
- ))}
+
);
}
return (
-
- List Visi Misi PPID
+
+
+
+ Preview Visi Misi PPID
+
+
+ router.push('/admin/ppid/visi-misi-ppid/edit')}>
+
+
+
+
- Visi PPID
-
-
-
- Misi PPID
-
+
+
+
+
+
+
+
+ MOTO PPID DESA DARMASABA
+
+
+ MEMBERIKAN INFORMASI YANG CEPAT, MUDAH, TEPAT DAN TRANSPARAN
+
+
+
+
+ VISI PPID
+
+
+
+
+
+ MISI PPID
+
+
+
+
+
);
}
-export default Page;
+export default VisiMisiPPIDList;
diff --git a/src/app/admin/_com/list_PageAdmin.tsx b/src/app/admin/_com/list_PageAdmin.tsx
index dcc54654..d5d9606c 100644
--- a/src/app/admin/_com/list_PageAdmin.tsx
+++ b/src/app/admin/_com/list_PageAdmin.tsx
@@ -94,7 +94,7 @@ export const navBar = [
{
id: "PPID_8",
name: "IKM Desa Darmasaba",
- path: "/admin/ppid/ikm-desa-darmasaba"
+ path: "/admin/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat"
},
]
@@ -108,7 +108,7 @@ export const navBar = [
{
id: "Desa_1",
name: "Profile",
- path: "/admin/desa/profile"
+ path: "/admin/desa/profile/profile-desa"
},
{
id: "Desa_2",
@@ -128,12 +128,12 @@ export const navBar = [
{
id: "Desa_5",
name: "Gallery",
- path: "/admin/desa/gallery"
+ path: "/admin/desa/gallery/foto"
},
{
id: "Desa_6",
name: "Layanan",
- path: "/admin/desa/layanan"
+ path: "/admin/desa/layanan/pelayanan_surat_keterangan"
},
{
id: "Desa_7",
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/create.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/create.ts
new file mode 100644
index 00000000..e53f35af
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/create.ts
@@ -0,0 +1,32 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+
+type FormCreate = Prisma.GalleryFotoGetPayload<{
+ select: {
+ name: true;
+ imagesId: true;
+ deskripsi: true;
+
+ };
+}>;
+async function galleryFotoCreate(context: Context) {
+ const body = context.body as FormCreate;
+
+ await prisma.galleryFoto.create({
+ data: {
+ name: body.name,
+ deskripsi: body.deskripsi,
+ imagesId: body.imagesId,
+ },
+ });
+ return {
+ success: true,
+ message: "Success create gallery foto",
+ data: {
+ ...body,
+ },
+ };
+}
+
+export default galleryFotoCreate
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/del.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/del.ts
new file mode 100644
index 00000000..859c1a4b
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/del.ts
@@ -0,0 +1,53 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+import fs from "fs/promises";
+import path from "path";
+
+const galleryFotoDelete = async (context: Context) => {
+ const id = context.params?.id as string;
+
+ if (!id) {
+ return {
+ status: 400,
+ body: "ID tidak diberikan",
+ };
+ }
+
+ const foto = await prisma.galleryFoto.findUnique({
+ where: { id },
+ include: {
+ imageGalleryFoto: true,
+ },
+ });
+
+ if (!foto) {
+ return {
+ status: 404,
+ body: "Foto tidak ditemukan",
+ };
+ }
+
+ // Hapus file gambar dari filesystem jika ada
+ if (foto.imageGalleryFoto) {
+ try {
+ const filePath = path.join(foto.imageGalleryFoto.path, foto.imageGalleryFoto.name);
+ await fs.unlink(filePath);
+ await prisma.fileStorage.delete({
+ where: { id: foto.imageGalleryFoto.id },
+ });
+ } catch (err) {
+ console.error("Gagal hapus gambar lama:", err);
+ }
+ }
+
+ await prisma.galleryFoto.delete({
+ where: { id },
+ });
+
+ return {
+ status: 200,
+ body: "Foto berhasil dihapus",
+ };
+}
+
+export default galleryFotoDelete
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/find-many.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/find-many.ts
new file mode 100644
index 00000000..bd880117
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/find-many.ts
@@ -0,0 +1,25 @@
+import prisma from "@/lib/prisma";
+
+async function galleryFotoFindMany() {
+ try {
+ const data = await prisma.galleryFoto.findMany({
+ where: { isActive: true },
+ include: {
+ imageGalleryFoto: true,
+ },
+ });
+
+ return {
+ success: true,
+ message: "Success fetch gallery foto",
+ data,
+ };
+ } catch (e) {
+ console.error("Find many error:", e);
+ return {
+ success: false,
+ message: "Failed fetch gallery foto",
+ };
+ }
+}
+export default galleryFotoFindMany
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/findUnique.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/findUnique.ts
new file mode 100644
index 00000000..31f1f14b
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/findUnique.ts
@@ -0,0 +1,49 @@
+import prisma from "@/lib/prisma";
+
+export default async function galleryFotoFindUnique(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 });
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 });
+ }
+
+ const data = await prisma.galleryFoto.findUnique({
+ where: { id },
+ include: {
+ imageGalleryFoto: true,
+ },
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Gallery foto tidak ditemukan",
+ }, { status: 404 });
+ }
+
+ return Response.json({
+ success: true,
+ message: "Success fetch gallery foto by ID",
+ data,
+ }, { status: 200 });
+ } catch (e) {
+ console.error("Find by ID error:", e);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil gallery foto: " + (e instanceof Error ? e.message : 'Unknown error'),
+ }, { status: 500 });
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/index.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/index.ts
new file mode 100644
index 00000000..bb19aa97
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/index.ts
@@ -0,0 +1,34 @@
+import Elysia, { t } from "elysia";
+import galleryFotoCreate from "./create";
+import galleryFotoDelete from "./del";
+import galleryFotoFindMany from "./find-many";
+import galleryFotoUpdate from "./updt";
+import galleryFotoFindUnique from "./findUnique";
+
+const GalleryFoto = new Elysia({ prefix: "/gallery/foto", tags: ["Desa/Gallery/Foto"] })
+ .get("/find-many", galleryFotoFindMany)
+ .get("/:id", async (context) => {
+ const response = await galleryFotoFindUnique(new Request(context.request));
+ return response;
+ })
+ .post("/create", galleryFotoCreate, {
+ body: t.Object({
+ name: t.String(),
+ deskripsi: t.String(),
+ imagesId: t.String(),
+ }),
+ })
+ .delete("/del/:id", galleryFotoDelete)
+ .put("/:id", async (context) => {
+ const response = await galleryFotoUpdate(context);
+ return response;
+ },
+ {
+ body: t.Object({
+ name: t.String(),
+ deskripsi: t.String(),
+ imagesId: t.String(),
+ }),
+ })
+
+export default GalleryFoto
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/updt.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/updt.ts
new file mode 100644
index 00000000..bd012f74
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/foto/updt.ts
@@ -0,0 +1,90 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+import fs from "fs/promises";
+import path from "path";
+
+type FormUpdate = Prisma.GalleryFotoGetPayload<{
+ select: {
+ id: true;
+ name: true;
+ deskripsi: true;
+ imagesId: true;
+ };
+}>;
+
+async function galleryFotoUpdate(context: Context) {
+ try {
+ const id = context.params?.id;
+ const body = (await context.body) as Omit;
+
+ const { name, deskripsi, imagesId } = body;
+
+ if (!id) {
+ return new Response(
+ JSON.stringify({ success: false, message: "ID tidak diberikan" }),
+ { status: 400, headers: { "Content-Type": "application/json" } }
+ );
+ }
+
+ const existing = await prisma.galleryFoto.findUnique({
+ where: { id },
+ include: {
+ imageGalleryFoto: true,
+ },
+ });
+
+ if (!existing) {
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "Gallery foto tidak ditemukan",
+ }),
+ { status: 404, headers: { "Content-Type": "application/json" } }
+ );
+ }
+
+ if (existing.imagesId && existing.imagesId !== imagesId) {
+ const oldImage = existing.imageGalleryFoto;
+ if (oldImage) {
+ try {
+ const filePath = path.join(oldImage.path, oldImage.name);
+ await fs.unlink(filePath);
+ await prisma.fileStorage.delete({
+ where: { id: oldImage.id },
+ });
+ } catch (err) {
+ console.error("Gagal hapus gambar lama:", err);
+ }
+ }
+ }
+
+ const updated = await prisma.galleryFoto.update({
+ where: { id },
+ data: {
+ name,
+ deskripsi,
+ imagesId,
+ },
+ });
+
+ return new Response(
+ JSON.stringify({
+ success: true,
+ message: "Success update gallery foto",
+ data: updated,
+ }),
+ { status: 200, headers: { "Content-Type": "application/json" } }
+ );
+ } catch (error) {
+ console.error("Error updating gallery foto:", error);
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "Terjadi kesalahan saat mengupdate gallery foto",
+ }),
+ { status: 500, headers: { "Content-Type": "application/json" } }
+ );
+ }
+}
+export default galleryFotoUpdate;
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/video/create.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/create.ts
new file mode 100644
index 00000000..b3b5a558
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/create.ts
@@ -0,0 +1,30 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+
+type FormCreate = Prisma.GalleryVideoGetPayload<{
+ select: {
+ name: true;
+ deskripsi: true;
+ linkVideo: true;
+ }
+}>
+async function galleryVideoCreate(context: Context) {
+ const body = context.body as FormCreate;
+
+ await prisma.galleryVideo.create({
+ data: {
+ name: body.name,
+ deskripsi: body.deskripsi,
+ linkVideo: body.linkVideo,
+ },
+ });
+ return {
+ success: true,
+ message: "Success create gallery video",
+ data: {
+ ...body,
+ },
+ };
+}
+export default galleryVideoCreate;
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/video/del.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/del.ts
new file mode 100644
index 00000000..ae294f81
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/del.ts
@@ -0,0 +1,34 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+const galleryVideoDelete = async (context: Context) => {
+ const id = context.params?.id as string;
+
+ if (!id) {
+ return {
+ status: 400,
+ body: "ID tidak diberikan",
+ };
+ }
+
+ const galleryVideo = await prisma.galleryVideo.findUnique({
+ where: { id },
+ });
+
+ if (!galleryVideo) {
+ return {
+ status: 404,
+ body: "Gallery video tidak ditemukan",
+ };
+ }
+ // Hapus gallery video dari database
+ await prisma.galleryVideo.delete({
+ where: { id },
+ });
+
+ return {
+ status: 200,
+ body: "Gallery video berhasil dihapus",
+ };
+}
+export default galleryVideoDelete;
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/video/find-many.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/find-many.ts
new file mode 100644
index 00000000..e171715e
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/find-many.ts
@@ -0,0 +1,22 @@
+import prisma from "@/lib/prisma";
+
+async function galleryVideoFindMany() {
+ try {
+ const data = await prisma.galleryVideo.findMany({
+ where: { isActive: true },
+ });
+
+ return {
+ success: true,
+ message: "Success fetch gallery video",
+ data,
+ };
+ } catch (e) {
+ console.error("Find many error:", e);
+ return {
+ success: false,
+ message: "Failed fetch gallery video",
+ };
+ }
+}
+export default galleryVideoFindMany;
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/video/findUnique.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/findUnique.ts
new file mode 100644
index 00000000..a7927b3a
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/findUnique.ts
@@ -0,0 +1,46 @@
+import prisma from "@/lib/prisma";
+
+export default async function galleryVideoFindUnique(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if(!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 });
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 });
+ }
+
+ const data = await prisma.galleryVideo.findUnique({
+ where: { id },
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Gallery video tidak ditemukan",
+ }, { status: 404 });
+ }
+
+ return Response.json({
+ success: true,
+ message: "Success fetch gallery video by ID",
+ data,
+ }, { status: 200 });
+ } catch (error) {
+ console.error("Find by ID error:", error);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil gallery video: " + (error instanceof Error ? error.message : 'Unknown error'),
+ }, { status: 500 });
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/video/index.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/index.ts
new file mode 100644
index 00000000..47c3fa27
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/index.ts
@@ -0,0 +1,39 @@
+import Elysia, { t } from "elysia";
+import galleryVideoFindMany from "./find-many";
+import galleryVideoFindUnique from "./findUnique";
+import galleryVideoCreate from "./create";
+import galleryVideoDelete from "./del";
+import galleryVideoUpdate from "./updt";
+
+const GalleryVideo = new Elysia({
+ prefix: "/gallery/video",
+ tags: ["Desa/Gallery/Video"],
+})
+ .get("/find-many", galleryVideoFindMany)
+ .get("/:id", async (context) => {
+ const response = await galleryVideoFindUnique(new Request(context.request));
+ return response;
+ })
+ .post("/create", galleryVideoCreate, {
+ body: t.Object({
+ name: t.String(),
+ deskripsi: t.String(),
+ linkVideo: t.String(),
+ }),
+ })
+ .delete("/del/:id", galleryVideoDelete)
+ .put(
+ "/:id",
+ async (context) => {
+ const response = await galleryVideoUpdate(context);
+ return response;
+ },
+ {
+ body: t.Object({
+ name: t.String(),
+ deskripsi: t.String(),
+ linkVideo: t.String(),
+ }),
+ }
+ );
+export default GalleryVideo;
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/gallery/video/updt.ts b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/updt.ts
new file mode 100644
index 00000000..553f8f6d
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/gallery/video/updt.ts
@@ -0,0 +1,85 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+
+type FormUpdate = Prisma.GalleryVideoGetPayload<{
+ select: {
+ id: true;
+ name: true;
+ deskripsi: true;
+ linkVideo: true;
+ }
+}>;
+
+async function galleryVideoUpdate(context: Context) {
+ try {
+ const id = context.params?.id as string;
+ const body = (await context.body) as Omit;
+
+ const {
+ name,
+ deskripsi,
+ linkVideo,
+ } = body;
+
+ if (!id) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }), {
+ status: 400,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
+ const existing = await prisma.galleryVideo.findUnique({
+ where: {id}
+ })
+
+ if (!existing) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Gallery video tidak ditemukan",
+ }), {
+ status: 404,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
+ const updated = await prisma.galleryVideo.update({
+ where: {id},
+ data: {
+ name,
+ deskripsi,
+ linkVideo,
+ }
+ })
+
+ return new Response(JSON.stringify({
+ success: true,
+ message: "Gallery video berhasil diupdate",
+ data: updated,
+ }), {
+ status: 200,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ } catch (error) {
+ console.error("Update error:", error);
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Gagal mengupdate gallery video: " + (error instanceof Error ? error.message : 'Unknown error'),
+ }), {
+ status: 500,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+}
+export default galleryVideoUpdate;
diff --git a/src/app/api/[[...slugs]]/_lib/desa/index.ts b/src/app/api/[[...slugs]]/_lib/desa/index.ts
index fc8b25db..1955ed81 100644
--- a/src/app/api/[[...slugs]]/_lib/desa/index.ts
+++ b/src/app/api/[[...slugs]]/_lib/desa/index.ts
@@ -3,11 +3,20 @@ import Berita from "./berita";
import Pengumuman from "./pengumuman";
import ProfileDesa from "./profile/profile_desa";
import PotensiDesa from "./potensi";
+import GalleryFoto from "./gallery/foto";
+import GalleryVideo from "./gallery/video";
+import LayananDesa from "./layanan";
+import Penghargaan from "./penghargaan";
+
const Desa = new Elysia({ prefix: "/api/desa", tags: ["Desa"] })
.use(Berita)
.use(Pengumuman)
.use(ProfileDesa)
.use(PotensiDesa)
+ .use(GalleryFoto)
+ .use(GalleryVideo)
+ .use(LayananDesa)
+ .use(Penghargaan)
export default Desa;
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/index.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/index.ts
new file mode 100644
index 00000000..d1bc1017
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/index.ts
@@ -0,0 +1,13 @@
+import Elysia from "elysia";
+import PelayananSuratKeterangan from "./pelayanan_surat_keterangan";
+import PelayananTelunjukSaktiDesa from "./pelayanan_telunjuk_sakti_desa";
+import PelayananPerizinanBerusaha from "./pelayanan_perizinan_berusaha";
+import PelayananPendudukNonPermanen from "./pelayanan_penduduk_non_permanen";
+
+const LayananDesa = new Elysia({ prefix: "/layanan", tags: ["Desa/Layanan"] })
+.use(PelayananSuratKeterangan)
+.use(PelayananTelunjukSaktiDesa)
+.use(PelayananPerizinanBerusaha)
+.use(PelayananPendudukNonPermanen)
+
+export default LayananDesa
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_penduduk_non_permanen/findUnique.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_penduduk_non_permanen/findUnique.ts
new file mode 100644
index 00000000..0a02c36d
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_penduduk_non_permanen/findUnique.ts
@@ -0,0 +1,60 @@
+import prisma from "@/lib/prisma";
+
+export default async function pelayananPendudukNonPermanenFindUnique(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split("/");
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json(
+ {
+ success: false,
+ message: "ID tidak boleh kosong",
+ },
+ { status: 400 }
+ );
+ }
+
+ try {
+ if (typeof id !== "string") {
+ return Response.json(
+ {
+ success: false,
+ message: "ID tidak valid",
+ },
+ { status: 400 }
+ );
+ }
+ const data = await prisma.pelayananPendudukNonPermanen.findUnique({
+ where: { id },
+ });
+
+ if (!data) {
+ return Response.json(
+ {
+ success: false,
+ message: "Pelayanan penduduk non permanen tidak ditemukan",
+ },
+ { status: 404 }
+ );
+ }
+
+ return Response.json(
+ {
+ success: true,
+ message: "Success fetch pelayanan penduduk non permanen by ID",
+ data,
+ },
+ { status: 200 }
+ );
+ } catch (e) {
+ console.error("Find by ID error:", e);
+ return Response.json(
+ {
+ success: false,
+ message: "Gagal mengambil pelayanan penduduk non permanen: " + (e instanceof Error ? e.message : 'Unknown error'),
+ },
+ { status: 500 }
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_penduduk_non_permanen/index.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_penduduk_non_permanen/index.ts
new file mode 100644
index 00000000..2f54e753
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_penduduk_non_permanen/index.ts
@@ -0,0 +1,20 @@
+import Elysia, { t } from "elysia";
+import pelayananPendudukNonPermanenFindUnique from "./findUnique";
+import pelayananPendudukNonPermanenUpdate from "./updt";
+
+const PelayananPendudukNonPermanen = new Elysia({ prefix: "/pelayananpenduduknonpermanen", tags: ["Desa/Layanan/Pelayanan Penduduk Non Permanen"] })
+.get("/:id", async (context) => {
+ const response = await pelayananPendudukNonPermanenFindUnique(new Request(context.request));
+ return response;
+})
+.put("/:id", async (context) => {
+ const response = await pelayananPendudukNonPermanenUpdate(context);
+ return response;
+},
+{
+ body: t.Object({
+ name: t.String(),
+ deskripsi: t.String(),
+ }),
+})
+export default PelayananPendudukNonPermanen;
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_penduduk_non_permanen/updt.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_penduduk_non_permanen/updt.ts
new file mode 100644
index 00000000..0aea8a08
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_penduduk_non_permanen/updt.ts
@@ -0,0 +1,72 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+
+type FormUpdate = Prisma.PelayananPendudukNonPermanenGetPayload<{
+ select: {
+ name: true;
+ deskripsi: true;
+ };
+}>;
+export default async function pelayananPendudukNonPermanenUpdate(context: Context) {
+ try {
+ const id = context.params?.id;
+ const body = (await context.body) as Omit;
+
+ const { name, deskripsi } = body;
+
+ if (!id) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "ID tidak diberikan",
+ }), {
+ status: 400,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+ const existing = await prisma.pelayananPendudukNonPermanen.findUnique({
+ where: { id },
+ });
+
+ if (!existing) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Pelayanan penduduk non permanen tidak ditemukan",
+ }), {
+ status: 404,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
+ const updated = await prisma.pelayananPendudukNonPermanen.update({
+ where: { id },
+ data: { name, deskripsi },
+ });
+
+ return new Response(JSON.stringify({
+ success: true,
+ message: "Success update pelayanan penduduk non permanen",
+ data: updated,
+ }), {
+ status: 200,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ } catch (e) {
+ console.error("Update error:", e);
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Gagal mengupdate pelayanan penduduk non permanen: " + (e instanceof Error ? e.message : 'Unknown error'),
+ }), {
+ status: 500,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_perizinan_berusaha/findUnique.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_perizinan_berusaha/findUnique.ts
new file mode 100644
index 00000000..02c992f4
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_perizinan_berusaha/findUnique.ts
@@ -0,0 +1,64 @@
+import prisma from "@/lib/prisma";
+
+export default async function pelayananPerizinanBerusahaFindUnique(
+ request: Request
+) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split("/");
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json(
+ {
+ success: false,
+ message: "ID tidak boleh kosong",
+ },
+ { status: 400 }
+ );
+ }
+
+ try {
+ if (typeof id !== "string") {
+ return Response.json(
+ {
+ success: false,
+ message: "ID tidak valid",
+ },
+ { status: 400 }
+ );
+ }
+ const data = await prisma.pelayananPerizinanBerusaha.findUnique({
+ where: { id },
+ });
+
+ if (!data) {
+ return Response.json(
+ {
+ success: false,
+ message: "Pelayanan perizinan berusaha tidak ditemukan",
+ },
+ { status: 404 }
+ );
+ }
+
+ return Response.json(
+ {
+ success: true,
+ message: "Success fetch pelayanan perizinan berusaha by ID",
+ data,
+ },
+ { status: 200 }
+ );
+ } catch (error) {
+ console.error("Find by ID error:", error);
+ return Response.json(
+ {
+ success: false,
+ message:
+ "Gagal mengambil pelayanan perizinan berusaha: " +
+ (error instanceof Error ? error.message : "Unknown error"),
+ },
+ { status: 500 }
+ );
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_perizinan_berusaha/index.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_perizinan_berusaha/index.ts
new file mode 100644
index 00000000..583b3040
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_perizinan_berusaha/index.ts
@@ -0,0 +1,21 @@
+import Elysia, { t } from "elysia";
+import pelayananPerizinanBerusahaFindUnique from "./findUnique";
+import pelayananPerizinanBerusahaUpdate from "./updt";
+
+const PelayananPerizinanBerusaha = new Elysia({ prefix: "/pelayananperizinanberusaha", tags: ["Desa/Layanan/Pelayanan Perizinan Berusaha"] })
+.get("/:id", async (context) => {
+ const response = await pelayananPerizinanBerusahaFindUnique(new Request(context.request));
+ return response;
+})
+.put("/:id", async (context) => {
+ const response = await pelayananPerizinanBerusahaUpdate(context);
+ return response;
+},
+{
+ body: t.Object({
+ name: t.String(),
+ deskripsi: t.String(),
+ link: t.String(),
+ }),
+})
+export default PelayananPerizinanBerusaha;
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_perizinan_berusaha/updt.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_perizinan_berusaha/updt.ts
new file mode 100644
index 00000000..7729ee4b
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_perizinan_berusaha/updt.ts
@@ -0,0 +1,77 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+
+type FormUpdate = Prisma.PelayananPerizinanBerusahaGetPayload<{
+ select: {
+ name: true;
+ deskripsi: true;
+ link: true;
+ };
+}>;
+export default async function pelayananPerizinanBerusahaUpdate(context: Context) {
+ try {
+ const id = context.params?.id;
+ const body = (await context.body) as Omit;
+
+ const { name, deskripsi, link } = body;
+
+ if (!id) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "ID tidak diberikan",
+ }), {
+ status: 400,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+ const existing = await prisma.pelayananPerizinanBerusaha.findUnique({
+ where: { id },
+ });
+
+ if (!existing) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Pelayanan perizinan berusaha tidak ditemukan",
+ }), {
+ status: 404,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
+ const updated = await prisma.pelayananPerizinanBerusaha.update({
+ where: { id },
+ data: {
+ name,
+ deskripsi,
+ link,
+ },
+ });
+
+ return new Response(JSON.stringify({
+ success: true,
+ message: "Success update pelayanan perizinan berusaha",
+ data: updated,
+ }), {
+ status: 200,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ } catch (error) {
+ console.error("Error updating pelayanan perizinan berusaha:", error);
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Terjadi kesalahan saat mengupdate pelayanan perizinan berusaha",
+ }), {
+ status: 500,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/create.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/create.ts
new file mode 100644
index 00000000..1963e7b6
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/create.ts
@@ -0,0 +1,30 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+
+type FormCreate = Prisma.PelayananSuratKeteranganGetPayload<{
+ select: {
+ name: true;
+ deskripsi: true;
+ imageId: true;
+ };
+}>;
+async function createPelayananSuratKeterangan(context: Context) {
+ const body = context.body as FormCreate;
+
+ await prisma.pelayananSuratKeterangan.create({
+ data: {
+ name: body.name,
+ deskripsi: body.deskripsi,
+ imageId: body.imageId,
+ },
+ });
+ return {
+ success: true,
+ message: "Success create pelayanan surat keterangan",
+ data: {
+ ...body,
+ },
+ };
+}
+export default createPelayananSuratKeterangan
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/del.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/del.ts
new file mode 100644
index 00000000..fcebb32e
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/del.ts
@@ -0,0 +1,52 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+import path from "path";
+import fs from "fs/promises";
+
+const pelayananSuratKeteranganDelete = async (context: Context) => {
+ const id = context.params?.id as string;
+
+ if (!id) {
+ return {
+ status: 400,
+ body: "ID tidak diberikan",
+ };
+ }
+
+ const pelayananSuratKeterangan = await prisma.pelayananSuratKeterangan.findUnique({
+ where: { id },
+ include: {
+ image: true,
+ },
+ });
+
+ if (!pelayananSuratKeterangan) {
+ return {
+ status: 404,
+ body: "Pelayanan surat keterangan tidak ditemukan",
+ };
+ }
+
+ // Hapus file gambar dari filesystem jika ada
+ if (pelayananSuratKeterangan.image) {
+ try {
+ const filePath = path.join(pelayananSuratKeterangan.image.path, pelayananSuratKeterangan.image.name);
+ await fs.unlink(filePath);
+ await prisma.fileStorage.delete({
+ where: { id: pelayananSuratKeterangan.image.id },
+ });
+ } catch (err) {
+ console.error("Gagal hapus gambar lama:", err);
+ }
+ }
+
+ const deleted = await prisma.pelayananSuratKeterangan.delete({
+ where: { id },
+ });
+
+ return {
+ status: 200,
+ body: deleted,
+ };
+};
+export default pelayananSuratKeteranganDelete;
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/find-many.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/find-many.ts
new file mode 100644
index 00000000..9581f2f1
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/find-many.ts
@@ -0,0 +1,24 @@
+import prisma from "@/lib/prisma";
+
+export default async function pelayananSuratKeteranganFindMany() {
+ try {
+ const data = await prisma.pelayananSuratKeterangan.findMany({
+ where: { isActive: true },
+ include: {
+ image: true,
+ },
+ });
+
+ return {
+ success: true,
+ message: "Success fetch pelayanan surat keterangan",
+ data,
+ };
+ } catch (e) {
+ console.error("Find many error:", e);
+ return {
+ success: false,
+ message: "Failed fetch pelayanan surat keterangan",
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/findUnique.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/findUnique.ts
new file mode 100644
index 00000000..364d5c7b
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/findUnique.ts
@@ -0,0 +1,49 @@
+import prisma from "@/lib/prisma";
+
+export default async function pelayananSuratKeteranganFindUnique(request: Request){
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if(!id){
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 });
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 });
+ }
+
+ const data = await prisma.pelayananSuratKeterangan.findUnique({
+ where: { id },
+ include: {
+ image: true,
+ },
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Pelayanan surat keterangan tidak ditemukan",
+ }, { status: 404 });
+ }
+
+ return Response.json({
+ success: true,
+ message: "Success fetch pelayanan surat keterangan by ID",
+ data,
+ }, { status: 200 });
+ } catch (error) {
+ console.error("Find by ID error:", error);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil pelayanan surat keterangan: " + (error instanceof Error ? error.message : 'Unknown error'),
+ }, { status: 500 });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/index.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/index.ts
new file mode 100644
index 00000000..9c289902
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/index.ts
@@ -0,0 +1,35 @@
+import Elysia from "elysia";
+import pelayananSuratKeteranganFindMany from "./find-many";
+import pelayananSuratKeteranganFindUnique from "./findUnique";
+import pelayananSuratKeteranganCreate from "./create";
+import pelayananSuratKeteranganUpdate from "./updt";
+import pelayananSuratKeteranganDelete from "./del";
+
+import { t } from "elysia";
+
+const PelayananSuratKeterangan = new Elysia({ prefix: "/pelayanansuratketerangan", tags: ["Desa/Layanan/Pelayanan Surat Keterangan"] })
+.get("/find-many", pelayananSuratKeteranganFindMany)
+.get("/:id", async (context) => {
+ const response = await pelayananSuratKeteranganFindUnique(new Request(context.request));
+ return response;
+})
+.post("/create", pelayananSuratKeteranganCreate, {
+ body: t.Object({
+ name: t.String(),
+ deskripsi: t.String(),
+ imageId: t.String(),
+ }),
+})
+.delete("/del/:id", pelayananSuratKeteranganDelete)
+.put("/:id", async (context) => {
+ const response = await pelayananSuratKeteranganUpdate(context);
+ return response;
+},
+{
+ body: t.Object({
+ name: t.String(),
+ deskripsi: t.String(),
+ imageId: t.String(),
+ }),
+})
+export default PelayananSuratKeterangan;
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/updt.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/updt.ts
new file mode 100644
index 00000000..06b301f0
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_surat_keterangan/updt.ts
@@ -0,0 +1,97 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import path from "path";
+import fs from "fs/promises";
+import { Context } from "elysia";
+
+type FormUpdate = Prisma.PelayananSuratKeteranganGetPayload<{
+ select: {
+ name: true;
+ deskripsi: true;
+ imageId: true;
+ };
+}>;
+export default async function updatePelayananSuratKeterangan(context: Context) {
+ try {
+ const id = context.params?.id;
+ const body = (await context.body) as Omit;
+
+ const { name, deskripsi, imageId } = body;
+
+ if (!id) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "ID tidak diberikan",
+ }), {
+ status: 400,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+ const existing = await prisma.pelayananSuratKeterangan.findUnique({
+ where: { id },
+ include: {
+ image: true,
+ }
+ });
+
+ if (!existing) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Pelayanan surat keterangan tidak ditemukan",
+ }), {
+ status: 404,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
+ if (existing.imageId && existing.imageId !== imageId) {
+ const oldImage = existing.image;
+ if (oldImage) {
+ try {
+ const filePath = path.join(oldImage.path, oldImage.name);
+ await fs.unlink(filePath);
+ await prisma.fileStorage.delete({
+ where: { id: oldImage.id },
+ });
+ } catch (err) {
+ console.error("Gagal hapus gambar lama:", err);
+ }
+ }
+ }
+
+ const updated = await prisma.pelayananSuratKeterangan.update({
+ where: { id },
+ data: {
+ name,
+ deskripsi,
+ imageId,
+ },
+ })
+
+ return new Response(JSON.stringify({
+ success: true,
+ message: "Success update pelayanan surat keterangan",
+ data: updated,
+ }), {
+ status: 200,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ } catch (error) {
+ console.error("Error updating pelayanan surat keterangan:", error);
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Terjadi kesalahan saat mengupdate pelayanan surat keterangan",
+ }), {
+ status: 500,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/create.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/create.ts
new file mode 100644
index 00000000..3de921e0
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/create.ts
@@ -0,0 +1,29 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+
+type FormCreate = Prisma.PelayananTelunjukSaktiDesaGetPayload<{
+ select: {
+ name: true;
+ deskripsi: true;
+ link: true;
+ };
+}>;
+export default async function pelayananTelunjukSaktiDesaCreate(context: Context) {
+ const body = context.body as FormCreate;
+
+ await prisma.pelayananTelunjukSaktiDesa.create({
+ data: {
+ name: body.name,
+ deskripsi: body.deskripsi,
+ link: body.link,
+ },
+ });
+ return {
+ success: true,
+ message: "Success create pelayanan telunjuk sakti desa",
+ data: {
+ ...body,
+ },
+ };
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/del.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/del.ts
new file mode 100644
index 00000000..eff4b050
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/del.ts
@@ -0,0 +1,33 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+export default async function pelayananTelunjukSaktiDesaDelete(context: Context) {
+ const id = context.params?.id as string;
+
+ if (!id) {
+ return {
+ status: 400,
+ body: "ID tidak diberikan",
+ };
+ }
+
+ const pelayananTelunjukSaktiDesa = await prisma.pelayananTelunjukSaktiDesa.findUnique({
+ where: { id },
+ });
+
+ if (!pelayananTelunjukSaktiDesa) {
+ return {
+ status: 404,
+ body: "Pelayanan telunjuk sakti desa tidak ditemukan",
+ };
+ }
+
+ await prisma.pelayananTelunjukSaktiDesa.delete({
+ where: { id },
+ });
+
+ return {
+ status: 200,
+ body: "Pelayanan telunjuk sakti desa berhasil dihapus",
+ };
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/find-many.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/find-many.ts
new file mode 100644
index 00000000..7881f161
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/find-many.ts
@@ -0,0 +1,21 @@
+import prisma from "@/lib/prisma";
+
+export default async function pelayananTelunjukSaktiDesaFindMany() {
+ try {
+ const data = await prisma.pelayananTelunjukSaktiDesa.findMany({
+ where: { isActive: true },
+ });
+
+ return {
+ success: true,
+ message: "Success fetch pelayanan telunjuk sakti desa",
+ data,
+ };
+ } catch (e) {
+ console.error("Find many error:", e);
+ return {
+ success: false,
+ message: "Failed fetch pelayanan telunjuk sakti desa",
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/findUnique.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/findUnique.ts
new file mode 100644
index 00000000..908e39ae
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/findUnique.ts
@@ -0,0 +1,46 @@
+import prisma from "@/lib/prisma";
+
+export default async function pelayananTelunjukSaktiDesaFindUnique(request: Request){
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if(!id){
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 });
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 });
+ }
+
+ const data = await prisma.pelayananTelunjukSaktiDesa.findUnique({
+ where: { id },
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Pelayanan telunjuk sakti desa tidak ditemukan",
+ }, { status: 404 });
+ }
+
+ return Response.json({
+ success: true,
+ message: "Success fetch pelayanan telunjuk sakti desa by ID",
+ data,
+ }, { status: 200 });
+ } catch (error) {
+ console.error("Find by ID error:", error);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil pelayanan telunjuk sakti desa: " + (error instanceof Error ? error.message : 'Unknown error'),
+ }, { status: 500 });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/index.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/index.ts
new file mode 100644
index 00000000..9a2e41b5
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/index.ts
@@ -0,0 +1,33 @@
+import Elysia, { t } from "elysia";
+import pelayananTelunjukSaktiDesaFindUnique from "./findUnique";
+import pelayananTelunjukSaktiDesaUpdate from "./updt";
+import pelayananTelunjukSaktiDesaCreate from "./create";
+import pelayananTelunjukSaktiDesaDelete from "./del";
+import pelayananTelunjukSaktiDesaFindMany from "./find-many";
+
+const pelayananTelunjukSaktiDesa = new Elysia({ prefix: "/pelayanantelunjuksaktidesa", tags: ["Desa/Layanan/Pelayanan Telunjuk Sakti Desa"] })
+.get("/find-many", pelayananTelunjukSaktiDesaFindMany)
+.get("/:id", async (context) => {
+ const response = await pelayananTelunjukSaktiDesaFindUnique(new Request(context.request));
+ return response;
+})
+.put("/:id", async (context) => {
+ const response = await pelayananTelunjukSaktiDesaUpdate(context);
+ return response;
+},
+{
+ body: t.Object({
+ name: t.String(),
+ deskripsi: t.String(),
+ link: t.String(),
+ }),
+})
+.post("/create", pelayananTelunjukSaktiDesaCreate, {
+ body: t.Object({
+ name: t.String(),
+ deskripsi: t.String(),
+ link: t.String(),
+ }),
+})
+.delete("/:id", pelayananTelunjukSaktiDesaDelete)
+export default pelayananTelunjukSaktiDesa;
diff --git a/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/updt.ts b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/updt.ts
new file mode 100644
index 00000000..9694b078
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/layanan/pelayanan_telunjuk_sakti_desa/updt.ts
@@ -0,0 +1,83 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+
+type FormUpdate = Prisma.PelayananTelunjukSaktiDesaGetPayload<{
+ select: {
+ name: true;
+ deskripsi: true;
+ link: true;
+ };
+}>;
+export default async function pelayananTelunjukSaktiDesaUpdate(context: Context) {
+ try {
+ const id = context.params?.id;
+ const body = (await context.body) as Omit;
+
+ const { name, deskripsi, link } = body;
+
+ if (!id) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "ID tidak diberikan",
+ }), {
+ status: 400,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
+ const data = await prisma.pelayananTelunjukSaktiDesa.update({
+ where: { id },
+ data: {
+ name,
+ deskripsi,
+ link,
+ },
+ });
+
+ if (!data) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Gagal update pelayanan telunjuk sakti desa",
+ }), {
+ status: 404,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
+ const updated = await prisma.pelayananTelunjukSaktiDesa.update({
+ where: { id },
+ data: {
+ name,
+ deskripsi,
+ link,
+ },
+ });
+
+ return new Response(JSON.stringify({
+ success: true,
+ message: "Success update pelayanan telunjuk sakti desa",
+ data: updated,
+ }), {
+ status: 200,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ } catch (error) {
+ console.error(error);
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Gagal update pelayanan telunjuk sakti desa",
+ }), {
+ status: 500,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/penghargaan/create.ts b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/create.ts
new file mode 100644
index 00000000..199a8f75
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/create.ts
@@ -0,0 +1,32 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+
+type FormCreate = Prisma.PenghargaanGetPayload<{
+ select: {
+ juara: true;
+ name: true;
+ deskripsi: true;
+ imageId: true;
+ }
+}>
+export default async function penghargaanCreate(context: Context){
+ const body = context.body as FormCreate;
+
+ await prisma.penghargaan.create({
+ data: {
+ juara: body.juara,
+ name: body.name,
+ deskripsi: body.deskripsi,
+ imageId: body.imageId,
+ }
+ })
+
+ return {
+ success: true,
+ message: "Success create penghargaan",
+ data: {
+ ...body,
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/penghargaan/del.ts b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/del.ts
new file mode 100644
index 00000000..72f8222a
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/del.ts
@@ -0,0 +1,53 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+import fs from "fs/promises";
+import path from "path";
+
+const penghargaanDelete = async (context: Context) => {
+ const id = context.params?.id as string;
+
+ if (!id) {
+ return {
+ status: 400,
+ body: "ID tidak diberikan",
+ };
+ }
+
+ const penghargaan = await prisma.penghargaan.findUnique({
+ where: { id },
+ include: {
+ image: true,
+ }
+ });
+
+ if (!penghargaan) {
+ return {
+ status: 404,
+ body: "Penghargaan tidak ditemukan",
+ };
+ }
+
+ if (penghargaan.image) {
+ try {
+ const filePath = path.join(penghargaan.image.path, penghargaan.image.name);
+ await fs.unlink(filePath);
+ await prisma.fileStorage.delete({
+ where: { id: penghargaan.image.id },
+ });
+ } catch (error) {
+ console.error("Gagal hapus file image:", error);
+ }
+ }
+
+ await prisma.penghargaan.delete({
+ where: { id },
+ });
+
+ return {
+ success: true,
+ message: "Penghargaan berhasil dihapus",
+ status: 200,
+ };
+}
+
+export default penghargaanDelete
diff --git a/src/app/api/[[...slugs]]/_lib/desa/penghargaan/find-many.ts b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/find-many.ts
new file mode 100644
index 00000000..9c2f44ec
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/find-many.ts
@@ -0,0 +1,23 @@
+import prisma from "@/lib/prisma";
+
+export default async function penghargaanFindMany() {
+ try {
+ const data = await prisma.penghargaan.findMany({
+ include: {
+ image: true,
+ },
+ });
+
+ return {
+ success: true,
+ message: "Success fetch penghargaan",
+ data,
+ };
+ } catch (error) {
+ console.error("Find many error:", error);
+ return {
+ success: false,
+ message: "Failed fetch penghargaan",
+ };
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/desa/penghargaan/findUnique.ts b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/findUnique.ts
new file mode 100644
index 00000000..5bf8e5c3
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/findUnique.ts
@@ -0,0 +1,49 @@
+import prisma from "@/lib/prisma";
+
+export default async function penghargaanFindUnique(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split("/");
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak ditemukan",
+ }, {status: 400});
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, {status: 400});
+ }
+
+ const data = await prisma.penghargaan.findUnique({
+ where: { id },
+ include: {
+ image: true,
+ },
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Penghargaan tidak ditemukan",
+ }, {status: 404});
+ }
+
+ return Response.json({
+ success: true,
+ message: "Success fetch penghargaan by ID",
+ data,
+ }, {status: 200});
+ } catch (error) {
+ console.error("Find by ID error:", error);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil penghargaan: " + (error instanceof Error ? error.message : 'Unknown error'),
+ }, {status: 500});
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/desa/penghargaan/index.ts b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/index.ts
new file mode 100644
index 00000000..223fa815
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/index.ts
@@ -0,0 +1,35 @@
+import Elysia, { t } from "elysia";
+import penghargaanFindMany from "./find-many";
+import penghargaanFindUnique from "./findUnique";
+import penghargaanCreate from "./create";
+import penghargaanDelete from "./del";
+import penghargaanUpdate from "./updt";
+
+
+const Penghargaan = new Elysia({prefix: "/penghargaan", tags: ["Desa/Penghargaan"]})
+ .get("/find-many", penghargaanFindMany)
+ .get("/:id", async (context) => {
+ const response = await penghargaanFindUnique(context.request);
+ return response;
+ })
+ .post("/create", penghargaanCreate, {
+ body: t.Object({
+ juara: t.String(),
+ name: t.String(),
+ deskripsi: t.String(),
+ imageId: t.String(),
+ }),
+ })
+ .delete("/del/:id", penghargaanDelete)
+ .put("/:id", async (context) => {
+ const response = await penghargaanUpdate(context);
+ return response;
+ }, {
+ body: t.Object({
+ juara: t.String(),
+ name: t.String(),
+ deskripsi: t.String(),
+ imageId: t.String(),
+ }),
+ });
+export default Penghargaan;
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/penghargaan/updt.ts b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/updt.ts
new file mode 100644
index 00000000..82a4e1a3
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/penghargaan/updt.ts
@@ -0,0 +1,106 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import path from "path";
+import fs from "fs/promises";
+import { Context } from "elysia";
+
+type FormUpdate = Prisma.PenghargaanGetPayload<{
+ select: {
+ id: true;
+ juara: true;
+ name: true;
+ deskripsi: true;
+ imageId: true;
+ }
+}>
+export default async function penghargaanUpdate(context: Context) {
+try {
+ const id = context.params?.id as string;
+ const body = (await context.body) as Omit;
+
+ const {
+ juara,
+ name,
+ deskripsi,
+ imageId
+ } = body;
+
+ if (!id) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "ID tidak ditemukan",
+ }), {
+ status: 400,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+ }
+
+ const existing = await prisma.penghargaan.findUnique({
+ where: {id},
+ include: {
+ image: true,
+ }
+ })
+
+ if (!existing) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Penghargaan tidak ditemukan",
+ }), {
+ status: 404,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+ }
+
+ if (existing.imageId && existing.imageId !== imageId) {
+ const oldImage = existing.image;
+ if (oldImage) {
+ try {
+ const filePath = path.join(oldImage.path, oldImage.name);
+ await fs.unlink(filePath);
+ await prisma.fileStorage.delete({
+ where: { id: oldImage.id },
+ });
+ } catch (error) {
+ console.error("Gagal hapus gambar lama:", error);
+ }
+ }
+ }
+
+ const updated = await prisma.penghargaan.update({
+ where: { id },
+ data: {
+ juara,
+ name,
+ deskripsi,
+ imageId,
+ }
+ })
+
+ return new Response(JSON.stringify({
+ success: true,
+ message: "Penghargaan berhasil diupdate",
+ data: updated,
+ }), {
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+} catch (error) {
+ console.error("Error updating penghargaan:", error);
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Terjadi kesalahan saat mengupdate penghargaan",
+ }), {
+ status: 500,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+}
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/pengumuman/del.ts b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/del.ts
new file mode 100644
index 00000000..4a5c86cd
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/del.ts
@@ -0,0 +1,39 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+const pengumumanDelete = async (context: Context) => {
+ const id = context.params?.id as string;
+
+ if (!id) {
+ return {
+ status: 400,
+ body: "ID tidak ditemukan",
+ }
+ }
+
+ const pengumuman = await prisma.pengumuman.findUnique({
+ where: {id},
+ include: {
+ CategoryPengumuman: true,
+ }
+ })
+
+ if (!pengumuman) {
+ return {
+ status: 404,
+ body: "Pengumuman tidak ditemukan",
+ }
+ }
+
+ await prisma.pengumuman.delete({
+ where: {id},
+ })
+
+ return {
+ status: 200,
+ success: true,
+ message: "Pengumuman berhasil dihapus",
+ }
+}
+
+export default pengumumanDelete
diff --git a/src/app/api/[[...slugs]]/_lib/desa/pengumuman/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/find-by-id.ts
new file mode 100644
index 00000000..3cc93307
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/find-by-id.ts
@@ -0,0 +1,37 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+const pengumumanFindById = async (context: Context) => {
+ const id = context.params?.id as string;
+
+ if (!id) {
+ return {
+ status: 400,
+ body: "ID tidak diberikan",
+ };
+ }
+
+ const pengumuman = await prisma.pengumuman.findUnique({
+ where: { id },
+ include: {
+ CategoryPengumuman: true,
+ },
+ });
+
+ if (!pengumuman) {
+ return {
+ status: 404,
+ body: "Pengumuman tidak ditemukan",
+ };
+ }
+
+ return {
+ status: 200,
+ success: true,
+ message: "Success fetch pengumuman by ID",
+ data: pengumuman,
+ };
+};
+
+export default pengumumanFindById;
+
diff --git a/src/app/api/[[...slugs]]/_lib/desa/pengumuman/find-many.ts b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/find-many.ts
index 394e0ac6..b7574008 100644
--- a/src/app/api/[[...slugs]]/_lib/desa/pengumuman/find-many.ts
+++ b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/find-many.ts
@@ -1,8 +1,23 @@
import prisma from "@/lib/prisma";
export default async function pengumumanFindMany() {
- const res = await prisma.pengumuman.findMany();
+ try {
+ const data = await prisma.pengumuman.findMany({
+ where: { isActive: true },
+ include: {
+ CategoryPengumuman: true,
+ },
+ });
return {
- data: res,
+ success: true,
+ message: "Success fetch pengumuman",
+ data,
};
-}
\ No newline at end of file
+ } catch (e) {
+ console.error("Find many error:", e);
+ return {
+ success: false,
+ message: "Failed fetch pengumuman",
+ };
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/desa/pengumuman/index.ts b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/index.ts
index 145aa01c..0b059ea5 100644
--- a/src/app/api/[[...slugs]]/_lib/desa/pengumuman/index.ts
+++ b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/index.ts
@@ -3,10 +3,15 @@ import { pengumumanCreate } from "./create";
import pengumumanFindMany from "./find-many";
import { t } from "elysia";
import pengumumanCategoryFindMany from "./category";
+import pengumumanDelete from "./del";
+import pengumumanFindById from "./find-by-id";
+import pengumumanUpdate from "./updt";
const Pengumuman = new Elysia({ prefix: "/pengumuman", tags: ["Desa/Pengumuman"] })
.get("/category/find-many", pengumumanCategoryFindMany)
.get("/find-many", pengumumanFindMany)
+ .get("/:id", pengumumanFindById)
+ .delete("/delete/:id", pengumumanDelete)
.post("/create", pengumumanCreate, {
body: t.Object({
judul: t.String(),
@@ -14,6 +19,15 @@ const Pengumuman = new Elysia({ prefix: "/pengumuman", tags: ["Desa/Pengumuman"]
content: t.String(),
categoryPengumumanId: t.Union([t.String(), t.Null()]),
}),
+ })
+ .put("/:id", pengumumanUpdate, {
+ body: t.Object({
+ id: t.String(),
+ judul: t.String(),
+ deskripsi: t.String(),
+ content: t.String(),
+ categoryPengumumanId: t.Union([t.String(), t.Null()]),
+ }),
});
export default Pengumuman;
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/pengumuman/updt.ts b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/updt.ts
new file mode 100644
index 00000000..9a5f2d15
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/updt.ts
@@ -0,0 +1,39 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+
+type FormUpdate = Prisma.PengumumanGetPayload<{
+ select: {
+ id: true;
+ judul: true;
+ deskripsi: true;
+ content: true;
+ categoryPengumumanId: true;
+ imageId: true;
+ };
+}>;
+
+async function pengumumanUpdate(context: Context) {
+ const body = context.body as FormUpdate;
+
+ await prisma.pengumuman.update({
+ where: { id: body.id },
+ data: {
+ judul: body.judul,
+ deskripsi: body.deskripsi,
+ content: body.content,
+ categoryPengumumanId: body.categoryPengumumanId,
+ },
+ });
+
+ return {
+ success: true,
+ message: "Success update pengumuman",
+ data: {
+ ...body,
+ },
+ };
+}
+
+export default pengumumanUpdate;
+
diff --git a/src/app/api/[[...slugs]]/_lib/desa/potensi/del.ts b/src/app/api/[[...slugs]]/_lib/desa/potensi/del.ts
index 8f8eb916..fd6e9956 100644
--- a/src/app/api/[[...slugs]]/_lib/desa/potensi/del.ts
+++ b/src/app/api/[[...slugs]]/_lib/desa/potensi/del.ts
@@ -1,6 +1,6 @@
import prisma from "@/lib/prisma";
import path from "path";
-import { Context } from "vm";
+import { Context } from "elysia";
import fs from "fs/promises";
const potensiDesaDelete = async (context: Context) => {
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profilePerbekel/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profilePerbekel/find-by-id.ts
new file mode 100644
index 00000000..ad95798b
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profilePerbekel/find-by-id.ts
@@ -0,0 +1,49 @@
+import prisma from "@/lib/prisma";
+
+export default async function profilePerbekelFindById(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 });
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 });
+ }
+
+ const data = await prisma.profilPerbekel.findUnique({
+ where: { id },
+ include: {
+ image: true,
+ }
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ }, { status: 404 });
+ }
+
+ return Response.json({
+ success: true,
+ message: "Data berhasil ditemukan",
+ data,
+ }, { status: 200 });
+ } catch (error) {
+ console.error("Error fetching profile Perbekel:", error);
+ return Response.json({
+ success: false,
+ message: "Terjadi kesalahan saat mengambil data profile Perbekel",
+ }, { status: 500 });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profilePerbekel/index.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profilePerbekel/index.ts
new file mode 100644
index 00000000..89f93490
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profilePerbekel/index.ts
@@ -0,0 +1,32 @@
+import Elysia, { t } from "elysia";
+import profilePerbekelFindById from "./find-by-id";
+import profilePerbekelUpdate from "./update";
+
+const ProfilPerbekel = new Elysia({
+ prefix: "/profileperbekel",
+ tags: ["Desa/Profile"],
+})
+ .get("/:id", async (context) => {
+ const response = await profilePerbekelFindById(
+ new Request(context.request)
+ );
+ return response;
+ })
+ .put(
+ "/:id",
+ async (context) => {
+ const response = await profilePerbekelUpdate(context);
+ return response;
+ },
+ {
+ body: t.Object({
+ biodata: t.String(),
+ pengalaman: t.String(),
+ pengalamanOrganisasi: t.String(),
+ programUnggulan: t.String(),
+ imageId: t.String(),
+ }),
+ }
+ );
+
+export default ProfilPerbekel;
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profilePerbekel/update.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profilePerbekel/update.ts
index 7b81bfda..00bec4ed 100644
--- a/src/app/api/[[...slugs]]/_lib/desa/profile/profilePerbekel/update.ts
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profilePerbekel/update.ts
@@ -1,33 +1,118 @@
import prisma from "@/lib/prisma";
import { Prisma } from "@prisma/client";
import { Context } from "elysia";
+import path from "path";
+import fs from "fs/promises";
-type FormCreate = Prisma.ProfilPerbekelGetPayload<{
- select: {
- id: true;
- biodata: true;
- pengalaman: true;
- pengalamanOrganisasi: true;
- programUnggulan: true;
- }
-}>
+type FormUpdate = Prisma.ProfilPerbekelGetPayload<{
+ select: {
+ id: true;
+ biodata: true;
+ pengalaman: true;
+ pengalamanOrganisasi: true;
+ programUnggulan: true;
+ imageId: true;
+ };
+}>;
export default async function profilePerbekelUpdate(context: Context) {
- const body = context.body as FormCreate;
+ try {
+ const id = context.params?.id as string;
+ const body = (await context.body) as Omit;
- await prisma.profilPerbekel.update({
- where: {
- id: body.id
- },
+ const { biodata, pengalaman, pengalamanOrganisasi, programUnggulan, imageId } = body;
+
+ if (!id) {
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }),
+ {
+ status: 400,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ }
+
+ const exisitng = await prisma.profilPerbekel.findUnique({
+ where: {
+ id,
+ },
+ include: {
+ image: true,
+ },
+ });
+
+ if (!exisitng) {
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "Data tidak ditemukan",
+ }),
+ {
+ status: 404,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ }
+
+ if (exisitng.imageId !== imageId) {
+ const oldImage = exisitng.image;
+ if (oldImage) {
+ try {
+ const filePath = path.join(oldImage.path, oldImage.name);
+ await fs.unlink(filePath);
+ await prisma.fileStorage.delete({
+ where: { id: oldImage.id },
+ });
+ } catch (error) {
+ console.error("Gagal hapus gambar lama:", error);
+ }
+ }
+ }
+
+ const updated = await prisma.profilPerbekel.update({
+ where: {id},
data: {
- biodata: body.biodata,
- pengalaman: body.pengalaman,
- pengalamanOrganisasi: body.pengalamanOrganisasi,
- programUnggulan: body.programUnggulan,
+ biodata,
+ pengalaman,
+ pengalamanOrganisasi,
+ programUnggulan,
+ imageId,
}
})
- return {
- success: true,
- message: "Profile Perbekel Berhasil Diupdate",
- }
-}
\ No newline at end of file
+ return new Response(
+ JSON.stringify({
+ success: true,
+ message: "Data berhasil diperbarui",
+ data: updated,
+ }),
+ {
+ status: 200,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ } catch (error) {
+ console.error("Error updating profile Perbekel:", error);
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "Terjadi kesalahan saat mengupdate profile Perbekel",
+ }),
+ {
+ status: 500,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/find-by-id.ts
deleted file mode 100644
index 6443567e..00000000
--- a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/find-by-id.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import prisma from "@/lib/prisma";
-import { Context } from "elysia";
-
-export default async function profileDesaFindById(context: Context) {
- try {
- const id = context?.params?.slugs?.[0];
-
- // If no ID provided, get the first profile
- if (!id) {
- const data = await prisma.profileDesa.findFirst();
- return {
- success: true,
- data,
- };
- }
-
- const data = await prisma.profileDesa.findUniqueOrThrow({
- where: { id },
- });
-
- return {
- success: true,
- data,
- };
- } catch (error) {
- console.error("Error fetching profileDesa:", error);
-
- return {
- success: false,
- message: error instanceof Error ? error.message : "Unknown error",
- };
- }
-}
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/index.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/index.ts
index 26e2e225..51da94ae 100644
--- a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/index.ts
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/index.ts
@@ -1,51 +1,18 @@
-import Elysia, { t } from "elysia";
-import lambangDesaUpdate from "./lambangDesa/update";
-import maskotDesaUpdate from "./maskotDesa/update";
-import profilePerbekelUpdate from "../profilePerbekel/update";
-import sejarahDesaUpdate from "./sejarah/update";
-import visimisiDesaUpdate from "./visimisiDesa/update";
-import profileDesaFindById from "./find-by-id";
+import SejarahDesa from "./sejarah";
+import VisiMisiDesa from "./visi-misi";
+import LambangDesa from "./lambang-desa";
+import MaskotDesa from "./maskot-desa";
+import Elysia from "elysia";
+import ProfilPerbekel from "../profilePerbekel";
const ProfileDesa = new Elysia({
- prefix: "/profile",
- tags: ["Desa/Profile"]
-})
-.get("/find-by-id", profileDesaFindById)
-.post("/profilePerbekel/update", profilePerbekelUpdate, {
- body: t.Object({
- id: t.String(),
- biodata: t.String(),
- pengalaman: t.String(),
- pengalamanOrganisasi: t.String(),
- programUnggulan: t.String(),
- })
-})
-.post("/visimisiDesa/update", visimisiDesaUpdate, {
- body: t.Object({
- id: t.String(),
- visi: t.String(),
- misi: t.String(),
- })
-})
-.post("/sejarah/update", sejarahDesaUpdate, {
- body: t.Object({
- id: t.String(),
- sejarah: t.String(),
- })
-})
-.post("/lambangDesa/update", lambangDesaUpdate, {
- body: t.Object({
- id: t.String(),
- lambang: t.String(),
- })
-})
-.post("/maskotDesa/update", maskotDesaUpdate, {
- body: t.Object({
- id: t.String(),
- maskot: t.String(),
- })
+ prefix: "/profile",
+ tags: ["Desa/Profile"],
})
+ .use(SejarahDesa)
+ .use(VisiMisiDesa)
+ .use(LambangDesa)
+ .use(MaskotDesa)
+ .use(ProfilPerbekel);
-
-
-export default ProfileDesa
+export default ProfileDesa;
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambang-desa/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambang-desa/find-by-id.ts
new file mode 100644
index 00000000..3e5d68f9
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambang-desa/find-by-id.ts
@@ -0,0 +1,60 @@
+import prisma from "@/lib/prisma";
+
+export default async function lambangDesaFindById(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split("/");
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json(
+ {
+ success: false,
+ message: "ID tidak boleh kosong",
+ },
+ { status: 400 }
+ );
+ }
+
+ try {
+ if (typeof id !== "string") {
+ return Response.json(
+ {
+ success: false,
+ message: "ID tidak valid",
+ },
+ { status: 400 }
+ );
+ }
+
+ const data = await prisma.lambangDesa.findUnique({
+ where: { id },
+ });
+
+ if (!data) {
+ return Response.json(
+ {
+ success: false,
+ message: "Data tidak ditemukan",
+ },
+ { status: 404 }
+ );
+ }
+
+ return Response.json(
+ {
+ success: true,
+ data,
+ },
+ { status: 200 }
+ );
+ } catch (error) {
+ console.error("Gagal mengambil data lambang desa:", error);
+ return Response.json(
+ {
+ success: false,
+ message: "Terjadi kesalahan saat mengambil data",
+ },
+ { status: 500 }
+ );
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambang-desa/index.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambang-desa/index.ts
new file mode 100644
index 00000000..dd959c73
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambang-desa/index.ts
@@ -0,0 +1,28 @@
+import Elysia, { t } from "elysia";
+
+import lambangDesaFindById from "./find-by-id";
+import lambangDesaUpdate from "./update";
+
+const LambangDesa = new Elysia({
+ prefix: "/lambang",
+ tags: ["Desa/Profile"],
+})
+ .get("/:id", async (context) => {
+ const response = await lambangDesaFindById(new Request(context.request));
+ return response;
+ })
+ .put(
+ "/:id",
+ async (context) => {
+ const response = await lambangDesaUpdate(context);
+ return response;
+ },
+ {
+ body: t.Object({
+ judul: t.String(),
+ deskripsi: t.String(),
+ }),
+ }
+ );
+
+export default LambangDesa;
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambang-desa/update.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambang-desa/update.ts
new file mode 100644
index 00000000..6c2b353f
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambang-desa/update.ts
@@ -0,0 +1,50 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+export default async function lambangDesaUpdate(context: Context) {
+ try {
+ const id = context.params?.id as string;
+ const body = await context.body as {
+ judul: string;
+ deskripsi: string;
+ };
+
+ if (!id) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }), { status: 400 });
+ }
+
+ const existing = await prisma.lambangDesa.findUnique({
+ where: { id },
+ });
+
+ if (!existing) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Data tidak ditemukan",
+ }), { status: 404 });
+ }
+
+ const updated = await prisma.lambangDesa.update({
+ where: { id },
+ data: {
+ judul: body.judul,
+ deskripsi: body.deskripsi,
+ },
+ });
+
+ return new Response(JSON.stringify({
+ success: true,
+ message: "Berhasil memperbarui data",
+ data: updated,
+ }), { status: 200 });
+ } catch (error) {
+ console.error("Update error:", error);
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Gagal memperbarui data: " + (error instanceof Error ? error.message : 'Unknown error'),
+ }), { status: 500 });
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambangDesa/update.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambangDesa/update.ts
deleted file mode 100644
index 34f1c992..00000000
--- a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/lambangDesa/update.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import prisma from "@/lib/prisma";
-import { Prisma } from "@prisma/client";
-import { Context } from "elysia";
-
-type FormCreate = Prisma.ProfileDesaGetPayload<{
- select: {
- id: true;
- lambang: true;
- }
-}>
-
-export default async function lambangDesaUpdate(context: Context) {
- const body = context.body as FormCreate;
-
- await prisma.profileDesa.update({
- where: {
- id: body.id
- },
- data: {
- lambang: body.lambang,
- }
- })
-
- return {
- success: true,
- message: "Profile Desa Berhasil Diupdate",
- }
-}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskot-desa/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskot-desa/find-by-id.ts
new file mode 100644
index 00000000..e16ddd7d
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskot-desa/find-by-id.ts
@@ -0,0 +1,53 @@
+import prisma from "@/lib/prisma";
+
+export default async function maskotDesaFindById(request: Request){
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, {status: 400})
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, {status: 400})
+ }
+
+ const data = await prisma.maskotDesa.findUnique({
+ where: { id },
+ include: {
+ images: {
+ include: {
+ image: true,
+ }
+ }
+ }
+ })
+
+ if(!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ }, {status: 404})
+ }
+
+ return Response.json({
+ success: true,
+ message: "Berhasil mengambil data berdasarkan ID",
+ data,
+ }, {status: 200})
+ } catch (error) {
+ console.error("Find by ID error:", error);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil data: " + (error instanceof Error ? error.message : 'Unknown error'),
+ }, {status: 500})
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskot-desa/index.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskot-desa/index.ts
new file mode 100644
index 00000000..f8f708f0
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskot-desa/index.ts
@@ -0,0 +1,32 @@
+import maskotDesaUpdate from "./update";
+import maskotDesaFindById from "./find-by-id";
+import Elysia, { t } from "elysia";
+
+const MaskotDesa = new Elysia({
+ prefix: "/maskot",
+ tags: ["Desa/Profile"],
+})
+ .get("/:id", async (context) => {
+ const response = await maskotDesaFindById(new Request(context.request));
+ return response;
+ })
+ .put(
+ "/:id",
+ async (context) => {
+ const response = await maskotDesaUpdate(context);
+ return response;
+ },
+ {
+ body: t.Object({
+ judul: t.String(),
+ deskripsi: t.String(),
+ images: t.Array(
+ t.Object({
+ imageId: t.String(),
+ label: t.String(),
+ })
+ ),
+ }),
+ }
+ );
+export default MaskotDesa;
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskot-desa/update.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskot-desa/update.ts
new file mode 100644
index 00000000..161a3a93
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskot-desa/update.ts
@@ -0,0 +1,78 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+export default async function maskotDesaUpdate(context: Context) {
+ try {
+ const id = context.params?.id as string;
+ const body = await context.body as {
+ judul: string;
+ deskripsi: string;
+ images: { label: string; imageId: string }[];
+ };
+
+ if (!id) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }), { status: 400 });
+ }
+
+ const existing = await prisma.maskotDesa.findUnique({
+ where: { id },
+ include: { images: { include: { image: true } } }
+ });
+
+ if (!existing) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Data tidak ditemukan",
+ }), { status: 404 });
+ }
+
+ // Hapus semua gambar lama (dan file-nya jika perlu)
+ for (const old of existing.images) {
+ try {
+ await prisma.fileStorage.delete({ where: { id: old.imageId } });
+ // opsional: hapus file dari disk juga kalau kamu simpan file fisik
+ // await fs.unlink(path.join(old.image.path, old.image.name));
+ } catch (error) {
+ console.warn("Gagal hapus gambar lama:", error);
+ }
+ }
+
+ // Update profile & re-create images
+ const updated = await prisma.maskotDesa.update({
+ where: { id },
+ data: {
+ judul: body.judul,
+ deskripsi: body.deskripsi,
+ images: {
+ deleteMany: {},
+ create: body.images.map((img) => ({
+ label: img.label,
+ imageId: img.imageId
+ }))
+ }
+ },
+ include: {
+ images: {
+ include: {
+ image: true
+ }
+ }
+ }
+ });
+
+ return new Response(JSON.stringify({
+ success: true,
+ message: "Data berhasil diperbarui",
+ data: updated,
+ }), { status: 200 });
+ } catch (error) {
+ console.error("Gagal update MaskotDesa:", error);
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Terjadi kesalahan saat update",
+ }), { status: 500 });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskotDesa/update.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskotDesa/update.ts
deleted file mode 100644
index a94ff33c..00000000
--- a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/maskotDesa/update.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import prisma from "@/lib/prisma";
-import { Prisma } from "@prisma/client";
-import { Context } from "elysia";
-
-type FormCreate = Prisma.ProfileDesaGetPayload<{
- select: {
- id: true;
- maskot: true;
- }
-}>
-
-export default async function maskotDesaUpdate(context: Context) {
- const body = context.body as FormCreate;
-
- await prisma.profileDesa.update({
- where: {
- id: body.id
- },
- data: {
- maskot: body.maskot,
- }
- })
-
- return {
- success: true,
- message: "Profile Desa Berhasil Diupdate",
- }
-}
-
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/find-by-id.ts
new file mode 100644
index 00000000..cc8b5890
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/find-by-id.ts
@@ -0,0 +1,45 @@
+import prisma from "@/lib/prisma";
+
+export default async function sejarahDesaFindById(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, {status: 400})
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, {status: 400})
+ }
+
+ const data = await prisma.sejarahDesa.findUnique({
+ where: { id },
+ })
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ }, {status: 404})
+ }
+
+ return Response.json({
+ success: true,
+ data,
+ }, {status: 200})
+ } catch (error) {
+ console.error("Gagal mengambil data sejarah desa:", error)
+ return Response.json({
+ success: false,
+ message: "Terjadi kesalahan saat mengambil data",
+ }, {status: 500})
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/index.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/index.ts
new file mode 100644
index 00000000..bb972b6d
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/index.ts
@@ -0,0 +1,27 @@
+import Elysia, { t } from "elysia";
+import sejarahDesaFindById from "./find-by-id";
+import sejarahDesaUpdate from "./update";
+
+const SejarahDesa = new Elysia({
+ prefix: "/sejarah",
+ tags: ["Desa/Profile"],
+})
+ .get("/:id", async (context) => {
+ const response = await sejarahDesaFindById(new Request(context.request));
+ return response;
+ })
+ .put(
+ "/:id",
+ async (context) => {
+ const response = await sejarahDesaUpdate(context);
+ return response;
+ },
+ {
+ body: t.Object({
+ judul: t.String(),
+ deskripsi: t.String(),
+ }),
+ }
+ );
+
+export default SejarahDesa;
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/update.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/update.ts
index 316ebc6f..32958feb 100644
--- a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/update.ts
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/update.ts
@@ -1,29 +1,50 @@
import prisma from "@/lib/prisma";
-import { Prisma } from "@prisma/client";
import { Context } from "elysia";
-type FormCreate = Prisma.ProfileDesaGetPayload<{
- select: {
- id: true;
- sejarah: true;
- }
-}>
-
export default async function sejarahDesaUpdate(context: Context) {
- const body = context.body as FormCreate;
+ try {
+ const id = context.params?.id as string;
+ const body = await context.body as {
+ judul: string;
+ deskripsi: string;
+ };
- await prisma.profileDesa.update({
- where: {
- id: body.id
- },
- data: {
- sejarah: body.sejarah,
+ if (!id) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }), { status: 400 });
}
- })
- return {
- success: true,
- message: "Profile Desa Berhasil Diupdate",
+ const existing = await prisma.sejarahDesa.findUnique({
+ where: { id },
+ });
+
+ if (!existing) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Data tidak ditemukan",
+ }), { status: 404 });
+ }
+
+ const updated = await prisma.sejarahDesa.update({
+ where: { id },
+ data: {
+ judul: body.judul,
+ deskripsi: body.deskripsi,
+ },
+ });
+
+ return new Response(JSON.stringify({
+ success: true,
+ message: "Berhasil memperbarui data",
+ data: updated,
+ }), { status: 200 });
+ } catch (error) {
+ console.error("Update error:", error);
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Gagal memperbarui data: " + (error instanceof Error ? error.message : 'Unknown error'),
+ }), { status: 500 });
}
-}
-
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visi-misi/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visi-misi/find-by-id.ts
new file mode 100644
index 00000000..ff0f4c00
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visi-misi/find-by-id.ts
@@ -0,0 +1,46 @@
+import prisma from "@/lib/prisma";
+
+export default async function visiMisiDesaFindById(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, {status: 400})
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, {status: 400})
+ }
+
+ const data = await prisma.visiMisiDesa.findUnique({
+ where: { id },
+ })
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ }, {status: 404})
+ }
+
+ return Response.json({
+ success: true,
+ message: "Data ditemukan",
+ data: data,
+ }, {status: 200})
+ } catch (error) {
+ console.error("Find by ID error:", error);
+ return Response.json({
+ success: false,
+ message: "Gagal menemukan data: " + (error instanceof Error ? error.message : 'Unknown error'),
+ }, {status: 500})
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visi-misi/index.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visi-misi/index.ts
new file mode 100644
index 00000000..0f6b0c8e
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visi-misi/index.ts
@@ -0,0 +1,27 @@
+import Elysia, { t } from "elysia";
+import visiMisiDesaUpdate from "./update";
+import visiMisiDesaFindById from "./find-by-id";
+
+const VisiMisiDesa = new Elysia({
+ prefix: "/visi-misi",
+ tags: ["Desa/Profile"],
+})
+ .get("/:id", async (context) => {
+ const response = await visiMisiDesaFindById(new Request(context.request));
+ return response;
+ })
+ .put(
+ "/:id",
+ async (context) => {
+ const response = await visiMisiDesaUpdate(context);
+ return response;
+ },
+ {
+ body: t.Object({
+ visi: t.String(),
+ misi: t.String(),
+ }),
+ }
+ );
+
+export default VisiMisiDesa;
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visi-misi/update.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visi-misi/update.ts
new file mode 100644
index 00000000..442aff8e
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visi-misi/update.ts
@@ -0,0 +1,50 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+export default async function visiMisiDesaUpdate(context: Context) {
+ try {
+ const id = context.params?.id as string;
+ const body = await context.body as {
+ visi: string;
+ misi: string;
+ };
+
+ if (!id) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }), { status: 400 });
+ }
+
+ const existing = await prisma.visiMisiDesa.findUnique({
+ where: { id },
+ });
+
+ if (!existing) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Data tidak ditemukan",
+ }), { status: 404 });
+ }
+
+ const updated = await prisma.visiMisiDesa.update({
+ where: { id },
+ data: {
+ visi: body.visi,
+ misi: body.misi,
+ },
+ });
+
+ return new Response(JSON.stringify({
+ success: true,
+ message: "Berhasil memperbarui data",
+ data: updated,
+ }), { status: 200 });
+ } catch (error) {
+ console.error("Update error:", error);
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Gagal memperbarui data: " + (error instanceof Error ? error.message : 'Unknown error'),
+ }), { status: 500 });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visimisiDesa/update.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visimisiDesa/update.ts
deleted file mode 100644
index a7dedf4d..00000000
--- a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/visimisiDesa/update.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import prisma from "@/lib/prisma";
-import { Prisma } from "@prisma/client";
-import { Context } from "elysia";
-
-type FormCreate = Prisma.ProfileDesaGetPayload<{
- select: {
- id: true;
- visi: true;
- misi: true;
- }
-}>
-export default async function visimisiDesaUpdate(context: Context) {
- const body = context.body as FormCreate;
-
- await prisma.profileDesa.update({
- where: {
- id: body.id
- },
- data: {
- visi: body.visi,
- misi: body.misi,
- }
- })
-
- return {
- success: true,
- message: "Profile Desa Berhasil Diupdate",
- }
-}
diff --git a/src/app/api/[[...slugs]]/_lib/fileStorage/_lib/create.ts b/src/app/api/[[...slugs]]/_lib/fileStorage/_lib/create.ts
index b9397d00..cc9f0ad8 100644
--- a/src/app/api/[[...slugs]]/_lib/fileStorage/_lib/create.ts
+++ b/src/app/api/[[...slugs]]/_lib/fileStorage/_lib/create.ts
@@ -34,7 +34,7 @@ const fileStorageCreate = async (context: Context) => {
body: "UPLOAD_DIR is not defined",
};
}
- const pathName = "desa/ppid/profile-ppid";
+ const pathName = "allFile";
const rootPath = path.join(UPLOAD_DIR, pathName);
await fs.mkdir(rootPath, { recursive: true });
diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts
index f8cae369..bc5a99df 100644
--- a/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts
+++ b/src/app/api/[[...slugs]]/_lib/kesehatan/index.ts
@@ -19,6 +19,7 @@ import Prevention from "./data_kesehatan_warga/artikel_kesehatan/prevention";
import FirstAid from "./data_kesehatan_warga/artikel_kesehatan/first_aid";
import MythVsFact from "./data_kesehatan_warga/artikel_kesehatan/myth_vs_fact";
import DoctorSign from "./data_kesehatan_warga/artikel_kesehatan/doctor_sign";
+import Posyandu from "./posyandu";
const Kesehatan = new Elysia({
@@ -45,4 +46,5 @@ const Kesehatan = new Elysia({
.use(FirstAid)
.use(MythVsFact)
.use(DoctorSign)
+.use(Posyandu)
export default Kesehatan;
diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/create.ts
new file mode 100644
index 00000000..3b13083a
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/create.ts
@@ -0,0 +1,31 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+
+type FormCreate = Prisma.PosyanduGetPayload<{
+ select: {
+ name: true;
+ nomor: true;
+ deskripsi: true;
+ imageId: true;
+ };
+}>;
+export default async function posyanduCreate(context: Context) {
+ const body = context.body as FormCreate;
+
+ await prisma.posyandu.create({
+ data: {
+ name: body.name,
+ nomor: body.nomor,
+ deskripsi: body.deskripsi,
+ imageId: body.imageId,
+ }
+ })
+ return {
+ success: true,
+ message: "Success create posyandu",
+ data: {
+ ...body,
+ },
+ };
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/del.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/del.ts
new file mode 100644
index 00000000..d5aa434c
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/del.ts
@@ -0,0 +1,52 @@
+import prisma from "@/lib/prisma";
+import fs from "fs/promises";
+import { Context } from "elysia";
+import path from "path";
+
+const posyanduDelete = async (context: Context) => {
+ const id = context.params?.id as string;
+
+ if (!id) {
+ return {
+ status: 400,
+ body: "ID tidak diberikan",
+ };
+ }
+
+ const posyandu = await prisma.posyandu.findUnique({
+ where: { id },
+ include: { image: true },
+ });
+
+ if (!posyandu) {
+ return {
+ status: 404,
+ body: "Posyandu tidak ditemukan",
+ };
+ }
+
+ // Hapus file gambar dari filesystem jika ada
+ if (posyandu.image) {
+ try {
+ const filePath = path.join(posyandu.image.path, posyandu.image.name);
+ await fs.unlink(filePath);
+ await prisma.fileStorage.delete({
+ where: { id: posyandu.image.id },
+ });
+ } catch (error) {
+ console.error("Gagal hapus file image:", error);
+ }
+ }
+
+ // Hapus berita dari DB
+ await prisma.posyandu.delete({
+ where: { id },
+ });
+
+ return {
+ success: true,
+ message: "Posyandu dan file terkait berhasil dihapus",
+ };
+};
+
+export default posyanduDelete;
diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/find-by-id.ts
new file mode 100644
index 00000000..d992044f
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/find-by-id.ts
@@ -0,0 +1,49 @@
+import prisma from "@/lib/prisma";
+
+export default async function findPosyanduById(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 })
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 })
+ }
+
+ const data = await prisma.posyandu.findUnique({
+ where: {id},
+ include: {
+ image: true
+ }
+ })
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ }, { status: 404 })
+ }
+
+ return Response.json({
+ success: true,
+ message: "Success fetch posyandu by ID",
+ data,
+ }, { status: 200 })
+ } catch (error) {
+ console.error("Find by ID error:", error);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil posyandu: " + (error instanceof Error ? error.message : 'Unknown error'),
+ }, { status: 500 })
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/find-many.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/find-many.ts
new file mode 100644
index 00000000..d52ea93b
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/find-many.ts
@@ -0,0 +1,26 @@
+import prisma from "@/lib/prisma";
+
+export default async function posyanduFindMany() {
+try {
+ const data = await prisma.posyandu.findMany({
+ where: {
+ isActive: true,
+ },
+ include: {
+ image: true,
+ }
+ })
+ return {
+ success: true,
+ message: "Success fetch posyandu",
+ data,
+ }
+} catch (error) {
+ console.error("Find many error:", error);
+ return {
+ success: false,
+ message: "Failed fetch posyandu",
+ }
+}
+
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/index.ts
new file mode 100644
index 00000000..ec3547ec
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/index.ts
@@ -0,0 +1,42 @@
+import Elysia, { t } from "elysia";
+import posyanduCreate from "./create";
+import posyanduDelete from "./del";
+import findPosyanduById from "./find-by-id";
+import posyanduUpdate from "./updt";
+import posyanduFindMany from "./find-many";
+
+const Posyandu = new Elysia({
+ prefix: "/posyandu",
+ tags: ["Kesehatan/Posyandu"]
+})
+.post("/create", posyanduCreate, {
+ body: t.Object({
+ name: t.String(),
+ nomor: t.String(),
+ deskripsi: t.String(),
+ imageId: t.String(),
+ })
+})
+.get("/find-many", posyanduFindMany)
+.delete("/del/:id", posyanduDelete)
+.get("/:id", async (context) => {
+ const response = await findPosyanduById(new Request(context.request));
+ return response;
+})
+.put(
+ "/:id",
+ async (context) => {
+ const response = await posyanduUpdate(context);
+ return response;
+ },
+ {
+ body: t.Object({
+ name: t.String(),
+ nomor: t.String(),
+ deskripsi: t.String(),
+ imageId: t.String(),
+ })
+ }
+)
+
+export default Posyandu;
diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/updt.ts
new file mode 100644
index 00000000..707b296b
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/kesehatan/posyandu/updt.ts
@@ -0,0 +1,105 @@
+import prisma from "@/lib/prisma";
+import { Prisma } from "@prisma/client";
+import { Context } from "elysia";
+import path from "path";
+import fs from "fs/promises";
+
+type FormUpdate = Prisma.PosyanduGetPayload<{
+ select: {
+ id: true;
+ name: true;
+ nomor: true;
+ deskripsi: true;
+ imageId: true;
+ }
+}>
+
+export default async function posyanduUpdate(context: Context) {
+ try {
+ const id = context.params?.id as string;
+ const body = (await context.body) as Omit;
+
+ const {
+ name,
+ nomor,
+ deskripsi,
+ imageId,
+ } = body;
+
+ if(!id) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }), {
+ status: 400,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+ }
+
+ const existing = await prisma.posyandu.findUnique({
+ where: { id },
+ include: {
+ image: true,
+ }
+ })
+
+ if (!existing) {
+ return new Response(JSON.stringify({
+ success: false,
+ message: "Posyandu tidak ditemukan",
+ }), {
+ status: 404,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+ }
+
+ if (existing.imageId && existing.imageId !== imageId) {
+ const oldImage = existing.image;
+ if (oldImage) {
+ try {
+ const filePath = path.join(oldImage.path, oldImage.name);
+ await fs.unlink(filePath);
+ await prisma.fileStorage.delete({
+ where: { id: oldImage.id },
+ });
+ } catch (err) {
+ console.error("Gagal hapus gambar lama:", err);
+ }
+ }
+ }
+
+ const updated = await prisma.posyandu.update({
+ where: { id },
+ data: {
+ name,
+ nomor,
+ deskripsi,
+ imageId,
+ }
+ })
+
+ return new Response(JSON.stringify({
+ success: true,
+ message: "Posyandu berhasil diupdate",
+ data: updated,
+ }), {
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+ } catch (error) {
+ console.error("Error updating posyandu:", error);
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "Terjadi kesalahan saat mengupdate posyandu",
+ }),
+ { status: 500, headers: { 'Content-Type': 'application/json' } }
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/create.ts b/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/create.ts
index 252c10f0..6a22c5bc 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/create.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/create.ts
@@ -11,12 +11,8 @@ type FormCreate = Prisma.DaftarInformasiPublikGetPayload<{
}>
export default async function daftarInformasiPublikCreate(context: Context) {
const body = context.body as FormCreate;
- const jumlahData = await prisma.daftarInformasiPublik.count({
- where: { isActive: true }, // hitung data aktif aja
- })
await prisma.daftarInformasiPublik.create({
- data: {
- nomor: jumlahData + 1,
+ data: {
jenisInformasi: body.jenisInformasi,
deskripsi: body.deskripsi,
tanggal: body.tanggal,
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/del.ts b/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/del.ts
new file mode 100644
index 00000000..ddaac4b1
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/del.ts
@@ -0,0 +1,36 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+const daftarInformasiPublikDelete = async (context: Context) => {
+ const id = context.params?.id as string;
+
+ if (!id) {
+ return {
+ status: 400,
+ body: "ID tidak diberikan",
+ };
+ }
+
+ const daftarInformasi = await prisma.daftarInformasiPublik.findUnique({
+ where: { id },
+ });
+
+ if (!daftarInformasi) {
+ return {
+ status: 400,
+ body: "Daftar Informasi Publik tidak ditemukan",
+ };
+ }
+
+ await prisma.daftarInformasiPublik.delete({
+ where: { id },
+ });
+
+ return {
+ success: true,
+ status: 200,
+ body: "Daftar Informasi Publik berhasil dihapus",
+ };
+};
+
+export default daftarInformasiPublikDelete;
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/edit.ts b/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/edit.ts
new file mode 100644
index 00000000..65e7b39b
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/edit.ts
@@ -0,0 +1,47 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+export default async function daftarInformasiPublikEdit(context: Context) {
+ const id = context.params?.id;
+
+ if (!id) {
+ return {
+ success: false,
+ message: "ID tidak ditemukan",
+ };
+ }
+
+ const { jenisInformasi, deskripsi, tanggal } = context.body as {
+ jenisInformasi: string;
+ deskripsi: string;
+ tanggal: string;
+ };
+
+ const existing = await prisma.daftarInformasiPublik.findUnique({
+ where: {
+ id: id,
+ },
+ });
+
+ if (!existing) {
+ return {
+ success: false,
+ message: "Data tidak ditemukan",
+ };
+ }
+
+ const updated = await prisma.daftarInformasiPublik.update({
+ where: { id },
+ data: {
+ jenisInformasi,
+ deskripsi,
+ tanggal,
+ },
+ });
+
+ return {
+ success: true,
+ message: "Data berhasil diupdate",
+ data: updated,
+ };
+}
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/find-by-id.ts
new file mode 100644
index 00000000..e79af663
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/find-by-id.ts
@@ -0,0 +1,46 @@
+import prisma from "@/lib/prisma";
+
+export default async function handler(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 });
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 });
+ }
+
+ const data = await prisma.daftarInformasiPublik.findUnique({
+ where: { id },
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ }, { status: 404 });
+ }
+
+ return Response.json({
+ success: true,
+ message: "Berhasil mengambil data berdasarkan ID",
+ data,
+ }, { status: 200 });
+ } catch (e) {
+ console.error("Find by ID error:", e);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil data: " + (e instanceof Error ? e.message : 'Unknown error'),
+ }, { status: 500 });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/index.ts b/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/index.ts
index 36b0fcf4..06825093 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/index.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/daftar_informasi_publik/index.ts
@@ -1,18 +1,36 @@
import Elysia, { t } from "elysia";
import daftarInformasiPublikCreate from "./create";
import daftarInformasiPublikFindMany from "./find-many";
+import daftarInformasiPublikFindById from "./find-by-id";
+import daftarInformasiPublikEdit from "./edit";
+import daftarInformasiPublikDelete from "./del";
const DaftarInformasiPublik = new Elysia({
- prefix: "/daftarinformasipublik",
- tags: ["PPID/Daftar Informasi Publik"]
+ prefix: "/daftarinformasipublik",
+ tags: ["PPID/Daftar Informasi Publik"],
})
- .get("/find-many", daftarInformasiPublikFindMany)
- .post("/create", daftarInformasiPublikCreate, {
- body: t.Object({
- jenisInformasi: t.String(),
- deskripsi: t.String(),
- tanggal: t.String(),
- }),
- })
+ .put("/:id", daftarInformasiPublikEdit, {
+ params: t.Object({
+ id: t.String(),
+ }),
+ body: t.Object({
+ jenisInformasi: t.String(),
+ deskripsi: t.String(),
+ tanggal: t.String(),
+ }),
+ })
+ .delete("/del/:id", daftarInformasiPublikDelete)
+ .get("/:id", async (context) => {
+ const response = await daftarInformasiPublikFindById(new Request(context.request))
+ return response
+ })
+ .get("/find-many", daftarInformasiPublikFindMany)
+ .post("/create", daftarInformasiPublikCreate, {
+ body: t.Object({
+ jenisInformasi: t.String(),
+ deskripsi: t.String(),
+ tanggal: t.String(),
+ }),
+ });
-export default DaftarInformasiPublik
\ No newline at end of file
+export default DaftarInformasiPublik;
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/create.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/create.ts
index 3c58f22d..a92ac5d4 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/create.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/create.ts
@@ -11,17 +11,20 @@ type FormCreate = Prisma.GrafikBerdasarkanJenisKelaminGetPayload<{
export default async function grafikBerdasarkanJenisKelaminCreate(context: Context) {
const body = context.body as FormCreate;
- await prisma.grafikBerdasarkanJenisKelamin.create({
+ const created = await prisma.grafikBerdasarkanJenisKelamin.create({
data: {
perempuan: body.perempuan,
laki: body.laki,
},
+ select: {
+ id: true,
+ perempuan: true,
+ laki: true,
+ }
});
return {
success: true,
message: "Success create grafik berdasarkan jenis kelamin",
- data: {
- ...body,
- },
+ data: created,
};
}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/del.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/del.ts
new file mode 100644
index 00000000..0b3b5996
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/del.ts
@@ -0,0 +1,43 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+export default async function grafikBerdasarkanJenisKelaminDelete(context: Context) {
+ const {id} = context.params as {id: string}
+
+ try {
+ const existingData = await prisma.grafikBerdasarkanJenisKelamin.findUnique({
+ where: {
+ id: id,
+ }
+ })
+
+ if (!existingData) {
+ return {
+ success: false,
+ message: "Data tidak ditemukan",
+ data: null,
+ }
+ }
+
+ await prisma.grafikBerdasarkanJenisKelamin.delete({
+ where: {
+ id: id
+ }
+ })
+
+ return {
+ success: true,
+ message: "Data berhasil dihapus",
+ data: {
+ id: id,
+ deleted: true,
+ },
+ }
+ } catch (error) {
+ return {
+ success: false,
+ message: error instanceof Error ? error.message : "Unknown error",
+ data: null,
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/find-by-id.ts
new file mode 100644
index 00000000..c3eea972
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/find-by-id.ts
@@ -0,0 +1,52 @@
+import prisma from "@/lib/prisma";
+
+export default async function grafikBerdasarakanJenisKelaminFindById(
+ request: Request,
+) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 });
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 });
+ }
+
+ const data = await prisma.grafikBerdasarkanJenisKelamin.findUnique({
+ where: { id },
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ }, { status: 404 });
+ }
+
+ return Response.json({
+ success: true,
+ message: "Berhasil mengambil data berdasarkan ID",
+ data,
+ }, { status: 200 });
+ } catch (e) {
+ console.error("Find by ID error:", e);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil data: " + (e instanceof Error ? e.message : 'Unknown error'),
+ }, {
+ status: 500,
+ });
+ }
+
+
+}
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/index.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/index.ts
index 88c7ddd7..6b556afe 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/index.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/index.ts
@@ -1,6 +1,9 @@
import Elysia, { t } from "elysia";
import grafikBerdasarkanJenisKelaminCreate from "./create";
import grafikBerdasarkanJenisKelaminFindMany from "./find-many";
+import grafikBerdasarakanJenisKelaminFindById from "./find-by-id";
+import grafikBerdasarakanJenisKelaminUpdate from "./update";
+import grafikBerdasarkanJenisKelaminDelete from "./del";
const GrafikBerdasarkanJenisKelamin = new Elysia({
@@ -8,10 +11,28 @@ const GrafikBerdasarkanJenisKelamin = new Elysia({
tags: ["PPID/IKM/grafikberdasarkanjeniskelamin"],
})
.get("/find-many", grafikBerdasarkanJenisKelaminFindMany)
+ .get("/:id", async (context) => {
+ const response = await grafikBerdasarakanJenisKelaminFindById(new Request(context.request))
+ return response
+ })
+ .put("/:id", grafikBerdasarakanJenisKelaminUpdate, {
+ params: t.Object({
+ id: t.String(),
+ }),
+ body: t.Object({
+ perempuan: t.String(),
+ laki: t.String(),
+ }),
+ })
.post("/create", grafikBerdasarkanJenisKelaminCreate, {
body: t.Object({
perempuan: t.String(),
laki: t.String(),
}),
+ })
+ .delete("/del/:id", grafikBerdasarkanJenisKelaminDelete, {
+ params: t.Object({
+ id: t.String(),
+ }),
});
export default GrafikBerdasarkanJenisKelamin;
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/update.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/update.ts
new file mode 100644
index 00000000..73745391
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_jenis_kelamin/update.ts
@@ -0,0 +1,49 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+export default async function grafikBerdasarakanJenisKelaminUpdate(
+ context: Context
+) {
+ const id = context.params?.id;
+
+ if (!id) {
+ return {
+ success: false,
+ message: "Id tidak ditemukan",
+ }
+ }
+
+ const {perempuan, laki} = context.body as {
+ perempuan: string;
+ laki: string;
+ }
+
+ const existing = await prisma.grafikBerdasarkanJenisKelamin.findUnique({
+ where: {
+ id: id,
+ },
+ })
+
+ if (!existing) {
+ return {
+ success: false,
+ message: "Data tidak ditemukan",
+ }
+ }
+
+ const updated = await prisma.grafikBerdasarkanJenisKelamin.update({
+ where: {
+ id
+ },
+ data: {
+ perempuan: perempuan,
+ laki: laki,
+ },
+ })
+
+ return {
+ success: true,
+ message: "Data berhasil diupdate",
+ data: updated,
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/create.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/create.ts
index 8444d0df..e1063e5c 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/create.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/create.ts
@@ -13,19 +13,24 @@ type FormCreate = Prisma.GrafikBerdasarkanUmurGetPayload<{
export async function grafikBerdasarkanUmurCreate(context: Context) {
const body = context.body as FormCreate;
- await prisma.grafikBerdasarkanUmur.create({
+ const created = await prisma.grafikBerdasarkanUmur.create({
data: {
remaja: body.remaja,
dewasa: body.dewasa,
orangtua: body.orangtua,
lansia: body.lansia,
},
+ select: {
+ id: true,
+ remaja: true,
+ dewasa: true,
+ orangtua: true,
+ lansia: true,
+ }
});
return {
success: true,
message: "Success create grafik berdasarkan umur",
- data: {
- ...body,
- },
+ data: created,
};
}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/del.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/del.ts
new file mode 100644
index 00000000..b37776c0
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/del.ts
@@ -0,0 +1,43 @@
+import prisma from "@/lib/prisma"
+import { Context } from "elysia"
+
+export default async function grafikBerdasarkanUmurDelete(context: Context) {
+ const {id} = context.params as {id: string}
+
+ try {
+ const existingData = await prisma.grafikBerdasarkanUmur.findUnique({
+ where: {
+ id: id,
+ }
+ })
+
+ if (!existingData) {
+ return {
+ success: false,
+ message: "Data tidak ditemukan",
+ data: null,
+ }
+ }
+
+ await prisma.grafikBerdasarkanUmur.delete({
+ where: {
+ id: id
+ }
+ })
+
+ return {
+ success: true,
+ message: "Data berhasil dihapus",
+ data: {
+ id: id,
+ deleted: true,
+ },
+ }
+ } catch (error) {
+ return {
+ success: false,
+ message: error instanceof Error ? error.message : "Unknown error",
+ data: null,
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/find-by-id.ts
new file mode 100644
index 00000000..37b7135a
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/find-by-id.ts
@@ -0,0 +1,53 @@
+import prisma from "@/lib/prisma";
+
+export default async function grafikBerdasarakanUmurFindById(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split("/");
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json(
+ {
+ success: false,
+ message: "ID tidak boleh kosong",
+ },
+ { status: 400 }
+ );
+ }
+
+ try {
+ if (typeof id !== "string") {
+ return Response.json(
+ {
+ success: false,
+ message: "ID tidak valid",
+ },
+ { status: 400 }
+ );
+ }
+
+ const data = await prisma.grafikBerdasarkanUmur.findUnique({
+ where: { id },
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ data: null,
+ }, { status: 404 });
+ }
+
+ return Response.json({
+ success: true,
+ message: "Berhasil mengambil data berdasarkan ID",
+ data: data,
+ }, { status: 200 });
+ } catch (error) {
+ console.error("Error fetching grafik berdasarkan umur:", error);
+ return Response.json({
+ success: false,
+ message: error instanceof Error ? error.message : "Unknown error",
+ }, { status: 500 });
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/index.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/index.ts
index 94051b31..8b237b8e 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/index.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/index.ts
@@ -1,19 +1,42 @@
import Elysia, { t } from "elysia";
import { grafikBerdasarkanUmurFindMany } from "./find-many";
import { grafikBerdasarkanUmurCreate } from "./create";
+import grafikBerdasarakanUmurUpdate from "./update";
+import grafikBerdasarakanUmurFindById from "./find-by-id";
+import grafikBerdasarkanUmurDelete from "./del";
const GrafikBerdasarkanUmur = new Elysia({
- prefix: "/grafikberdasarkanumur",
- tags: ["PPID/IKM/grafikberdasarkanumur"]
+ prefix: "/grafikberdasarkanumur",
+ tags: ["PPID/IKM/grafikberdasarkanumur"],
})
- .get("/find-many", grafikBerdasarkanUmurFindMany)
- .post("/create", grafikBerdasarkanUmurCreate, {
- body: t.Object({
- remaja: t.String(),
- dewasa: t.String(),
- orangtua: t.String(),
- lansia: t.String(),
- }),
- });
+ .get("/find-many", grafikBerdasarkanUmurFindMany)
+ .post("/create", grafikBerdasarkanUmurCreate, {
+ body: t.Object({
+ remaja: t.String(),
+ dewasa: t.String(),
+ orangtua: t.String(),
+ lansia: t.String(),
+ }),
+ })
+ .get("/:id", async (context) => {
+ const response = await grafikBerdasarakanUmurFindById(new Request(context.request))
+ return response
+ })
+ .put("/:id", grafikBerdasarakanUmurUpdate, {
+ params: t.Object({
+ id: t.String(),
+ }),
+ body: t.Object({
+ remaja: t.String(),
+ dewasa: t.String(),
+ orangtua: t.String(),
+ lansia: t.String(),
+ }),
+ })
+ .delete("/del/:id", grafikBerdasarkanUmurDelete, {
+ params: t.Object({
+ id: t.String(),
+ }),
+ });
-export default GrafikBerdasarkanUmur;
\ No newline at end of file
+export default GrafikBerdasarkanUmur;
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/update.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/update.ts
new file mode 100644
index 00000000..24632602
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_berdasarkan_umur/update.ts
@@ -0,0 +1,51 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+export default async function grafikBerdasarakanUmurUpdate(context: Context) {
+ const id = context.params?.id;
+
+ if (!id) {
+ return {
+ success: false,
+ message: "Id tidak ditemukan",
+ }
+ }
+
+ const {remaja, dewasa, orangtua, lansia} = context.body as {
+ remaja: string;
+ dewasa: string;
+ orangtua: string;
+ lansia: string;
+ }
+
+ const existing = await prisma.grafikBerdasarkanUmur.findUnique({
+ where: {
+ id: id
+ }
+ })
+
+ if (!existing) {
+ return {
+ success: false,
+ message: "Grafik tidak ditemukan"
+ }
+ }
+
+ const updated = await prisma.grafikBerdasarkanUmur.update({
+ where: {
+ id: id
+ },
+ data: {
+ remaja: remaja,
+ dewasa: dewasa,
+ orangtua: orangtua,
+ lansia: lansia,
+ },
+ })
+
+ return {
+ success: true,
+ message: "Data berhasil diupdate",
+ data: updated,
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/create.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/create.ts
index 8d57d7e4..a9d5646a 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/create.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/create.ts
@@ -11,17 +11,20 @@ type FormCreate = Prisma.IndeksKepuasanMasyarakatGetPayload<{
export default async function grafikHasilKepuasanMasyarakatCreate(context: Context) {
const body = context.body as FormCreate;
- await prisma.indeksKepuasanMasyarakat.create({
+ const created = await prisma.indeksKepuasanMasyarakat.create({
data: {
label: body.label,
kepuasan: body.kepuasan,
},
+ select: {
+ id: true,
+ label: true,
+ kepuasan: true,
+ }
});
return {
success: true,
message: "Success create grafik hasil kepuasan masyarakat",
- data: {
- ...body,
- },
+ data: created,
};
}
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/del.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/del.ts
new file mode 100644
index 00000000..b7de741c
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/del.ts
@@ -0,0 +1,43 @@
+import prisma from "@/lib/prisma"
+import { Context } from "elysia"
+
+export default async function grafikHasilKepuasanMasyarakatDelete(context: Context) {
+ const {id} = context.params as {id: string}
+
+ try {
+ const existingData = await prisma.indeksKepuasanMasyarakat.findUnique({
+ where: {
+ id: id,
+ }
+ })
+
+ if (!existingData) {
+ return {
+ success: false,
+ message: "Data tidak ditemukan",
+ data: null,
+ }
+ }
+
+ await prisma.indeksKepuasanMasyarakat.delete({
+ where: {
+ id: id
+ }
+ })
+
+ return {
+ success: true,
+ message: "Data berhasil dihapus",
+ data: {
+ id: id,
+ deleted: true,
+ },
+ }
+ } catch (error) {
+ return {
+ success: false,
+ message: error instanceof Error ? error.message : "Unknown error",
+ data: null,
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/find-by-id.ts
new file mode 100644
index 00000000..04677d9a
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/find-by-id.ts
@@ -0,0 +1,46 @@
+import prisma from "@/lib/prisma";
+
+export default async function handler(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 });
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 });
+ }
+
+ const data = await prisma.indeksKepuasanMasyarakat.findUnique({
+ where: { id },
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ }, { status: 404 });
+ }
+
+ return Response.json({
+ success: true,
+ message: "Berhasil mengambil data berdasarkan ID",
+ data,
+ }, { status: 200 });
+ } catch (e) {
+ console.error("Find by ID error:", e);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil data: " + (e instanceof Error ? e.message : 'Unknown error'),
+ }, { status: 500 });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/index.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/index.ts
index 29358dd5..9c86e4cc 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/index.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/index.ts
@@ -1,17 +1,38 @@
import Elysia, { t } from "elysia";
import grafikHasilKepuasanMasyarakatCreate from "./create";
import grafikHasilKepuasanMasyarakatFindMany from "./find-many";
+import grafikHasilKepuasanMasyarakatFindById from "./find-by-id";
+import grafikHasilKepuasanMasyarakatUpdate from "./update";
+import grafikHasilKepuasanMasyarakatDelete from "./del";
const GrafikHasilKepuasanMasyarakat = new Elysia({
prefix: "/grafikhasilkepuasamanmasyarakat",
tags: ["PPID/IKM/grafikhasilkepuasanmasyarakat"],
})
.get("/find-many", grafikHasilKepuasanMasyarakatFindMany)
+ .get("/:id", async (context) => {
+ const response = await grafikHasilKepuasanMasyarakatFindById(new Request(context.request))
+ return response
+ })
+ .put("/:id", grafikHasilKepuasanMasyarakatUpdate, {
+ params: t.Object({
+ id: t.String(),
+ }),
+ body: t.Object({
+ label: t.String(),
+ kepuasan: t.String(),
+ }),
+ })
.post("/create", grafikHasilKepuasanMasyarakatCreate, {
body: t.Object({
label: t.String(),
kepuasan: t.String(),
}),
+ })
+ .delete("/del/:id", grafikHasilKepuasanMasyarakatDelete, {
+ params: t.Object({
+ id: t.String(),
+ }),
});
export default GrafikHasilKepuasanMasyarakat;
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/update.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/update.ts
new file mode 100644
index 00000000..aaccb5e6
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_hasil_kepuasan_masyarakat/update.ts
@@ -0,0 +1,45 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+export default async function grafikHasilKepuasanMasyarakatUpdate(context: Context) {
+ const id = context.params?.id;
+
+ if (!id) {
+ return {
+ success: false,
+ message: "Id tidak ditemukan",
+ }
+ }
+
+ const {label, kepuasan} = context.body as {
+ label: string;
+ kepuasan: string;
+ }
+
+ const existing = await prisma.indeksKepuasanMasyarakat.findUnique({
+ where: {
+ id: id,
+ },
+ })
+
+ if (!existing) {
+ return {
+ success: false,
+ message: "Data tidak ditemukan",
+ }
+ }
+
+ const updated = await prisma.indeksKepuasanMasyarakat.update({
+ where: { id },
+ data: {
+ label,
+ kepuasan,
+ },
+ })
+
+ return {
+ success: true,
+ message: "Data berhasil diupdate",
+ data: updated,
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/create.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/create.ts
index 89c71102..3b23b738 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/create.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/create.ts
@@ -2,30 +2,16 @@ import prisma from "@/lib/prisma";
import { Prisma } from "@prisma/client";
import { Context } from "elysia";
-type FormCreate = Prisma.GrafikBerdasarkanRespondenGetPayload<{
- select: {
- sangatbaik: true;
- baik: true;
- kurangbaik: true;
- tidakbaik: true
- };
-}>;
export default async function grafikRespondenCreate(context: Context) {
- const body = context.body as FormCreate;
+ const body = context.body as Prisma.GrafikBerdasarkanRespondenCreateInput;
- await prisma.grafikBerdasarkanResponden.create({
- data: {
- sangatbaik: body.sangatbaik,
- baik: body.baik,
- kurangbaik: body.kurangbaik,
- tidakbaik: body.tidakbaik,
- },
+ const created = await prisma.grafikBerdasarkanResponden.create({
+ data: body,
});
+
return {
success: true,
message: "Success create grafik berdasarkan responden",
- data: {
- ...body,
- },
+ data: created, // ini termasuk id
};
-}
\ No newline at end of file
+}
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/del.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/del.ts
new file mode 100644
index 00000000..4d2249e9
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/del.ts
@@ -0,0 +1,40 @@
+import prisma from "@/lib/prisma"
+import { Context } from "elysia"
+
+export default async function grafikRespondenDelete(context: Context) {
+ const { id } = context.params as { id: string }
+
+ try {
+ const existingData = await prisma.grafikBerdasarkanResponden.findUnique({
+ where: {
+ id: id,
+ }
+ })
+
+ if (!existingData) {
+ return {
+ success: false,
+ message: "Data tidak ditemukan",
+ data: null,
+ }
+ }
+
+ await prisma.grafikBerdasarkanResponden.delete({
+ where: {
+ id: id
+ }
+ })
+
+ return {
+ success: true,
+ message: "Data berhasil dihapus",
+ data: null,
+ }
+ } catch (error) {
+ return {
+ success: false,
+ message: error instanceof Error ? error.message : "Unknown error",
+ data: null,
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/find-by-id.ts
new file mode 100644
index 00000000..60984d2d
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/find-by-id.ts
@@ -0,0 +1,48 @@
+import prisma from "@/lib/prisma";
+
+export default async function grafikRespondenFindById(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id ) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 });
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 });
+ }
+
+ const data = await prisma.grafikBerdasarkanResponden.findUnique({
+ where: { id },
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ }, { status: 404 });
+ }
+
+ return Response.json({
+ success: true,
+ message: "Berhasil mengambil data berdasarkan ID",
+ data,
+ }, { status: 200 });
+ } catch (e) {
+ console.error("Find by ID error:", e);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil data: " + (e instanceof Error ? e.message : 'Unknown error'),
+ }, {
+ status: 500,
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/index.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/index.ts
index 4bae7832..afa87d59 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/index.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/index.ts
@@ -1,11 +1,29 @@
import Elysia, { t } from "elysia";
import grafikRespondenCreate from "./create";
import grafikRespondenFindMany from "./find-many";
+import grafikRespondenFindById from "./find-by-id";
+import grafikRespondenUpdate from "./update";
+import grafikRespondenDelete from "./del";
const GrafikBerdasarkanResponden = new Elysia({
prefix: "/grafikberdasarkanresponden",
tags: ["PPID/IKM/grafikberdasarkanresponden"]
})
+.get("/:id", async (context) => {
+ const response = await grafikRespondenFindById(new Request(context.request))
+ return response
+})
+.put("/:id", grafikRespondenUpdate, {
+ params: t.Object({
+ id: t.String(),
+ }),
+ body: t.Object({
+ sangatbaik: t.String(),
+ baik: t.String(),
+ kurangbaik: t.String(),
+ tidakbaik: t.String(),
+ }),
+})
.get("/find-many", grafikRespondenFindMany)
.post("/create", grafikRespondenCreate, {
body: t.Object({
@@ -15,6 +33,11 @@ const GrafikBerdasarkanResponden = new Elysia({
tidakbaik: t.String(),
}),
})
+.delete("/del/:id", grafikRespondenDelete, {
+ params: t.Object({
+ id: t.String(),
+ }),
+})
export default GrafikBerdasarkanResponden
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/update.ts b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/update.ts
new file mode 100644
index 00000000..4d82012c
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/ikm/grafik_responden/update.ts
@@ -0,0 +1,49 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+
+export default async function grafikRespondenUpdate(context: Context) {
+ const id = context.params?.id;
+
+ if(!id) {
+ return {
+ success: false,
+ message: "ID tidak ditemukan"
+ }
+ }
+
+ const {sangatbaik, baik, kurangbaik, tidakbaik} = context.body as {
+ sangatbaik: string;
+ baik: string;
+ kurangbaik: string;
+ tidakbaik: string;
+ }
+
+ const existing = await prisma.grafikBerdasarkanResponden.findUnique({
+ where: {
+ id: id,
+ },
+ })
+
+ if (!existing) {
+ return {
+ success: false,
+ message: "Data tidak ditemukan",
+ }
+ }
+
+ const updated = await prisma.grafikBerdasarkanResponden.update({
+ where: { id },
+ data: {
+ sangatbaik,
+ baik,
+ kurangbaik,
+ tidakbaik,
+ },
+ })
+
+ return {
+ success: true,
+ message: "Data berhasil diupdate",
+ data: updated,
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/index.ts b/src/app/api/[[...slugs]]/_lib/ppid/index.ts
index d830064c..b590bd86 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/index.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/index.ts
@@ -9,6 +9,7 @@ import PermohonanKeberatanInformasiPublik from "./permohonan_keberatan_informasi
import ProfilePPID from "./profile_ppid";
import VisiMisiPPID from "./visi_misi_ppid/visi_misi_ppid";
import DasarHukumPPID from "./dasar_hukum";
+import StrukturPPID from "./struktur_ppid";
@@ -24,6 +25,7 @@ const PPID = new Elysia({ prefix: "/api/ppid", tags: ["PPID"] })
.use(PermohonanKeberatanInformasiPublik)
.use(VisiMisiPPID)
.use(DasarHukumPPID)
+.use(StrukturPPID)
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/edit-img.ts b/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/edit-img.ts
deleted file mode 100644
index b989b2ce..00000000
--- a/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/edit-img.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import prisma from "@/lib/prisma";
-import { Context } from "elysia";
-import { writeFile, unlink } from "fs/promises";
-import path from "path";
-import fs from "fs";
-import { mkdir } from "fs/promises";
-
-interface ProfilePPIDBody {
- id: string;
- file: Blob & { name: string; type: string };
-}
-
-export default async function editImageProfilePPID(context: Context<{ body: ProfilePPIDBody }>) {
- const { id, file } = context.body;
-
- if (!file || !id) {
- return {
- success: false,
- message: "File atau ID harus disertakan",
- };
- }
-
- // Validasi ekstensi file
- const allowedTypes = ["image/jpeg", "image/png", "image/webp"];
- if (!allowedTypes.includes(file.type)) {
- return {
- success: false,
- message: "Tipe file tidak diizinkan. Hanya JPG, PNG, atau WEBP",
- };
- }
-
- const bytes = await file.arrayBuffer();
- const buffer = Buffer.from(bytes);
- const filename = `${id}_${Date.now()}_${file.name}`;
- const folderPath = path.resolve("public", "assets", "images", "ppid", "profile-ppid");
-
- try {
- await mkdir(folderPath, { recursive: true });
-
- console.log('Folder path:', folderPath);
- const filePath = path.join(folderPath, filename);
- console.log('File path:', filePath);
-
- await writeFile(filePath, buffer);
-
- if (!fs.existsSync(filePath)) {
- return {
- success: false,
- message: "Failed to write file to disk",
- };
- }
-
- const imageUrl = `/assets/images/ppid/profile-ppid/${filename}`;
-
- // Hapus file lama (opsional, kalau mau bersih)
- const oldData = await prisma.profilePPID.findUnique({ where: { id } });
- if (oldData?.imageUrl) {
- const oldPath = path.resolve("public", oldData.imageUrl.replace(/^\//, ""));
- if (fs.existsSync(oldPath)) {
- await unlink(oldPath).catch(() => {});
- }
- }
-
- // Update DB
- await prisma.profilePPID.update({
- where: { id },
- data: { imageUrl },
- });
-
- return {
- success: true,
- message: "Gambar berhasil diunggah",
- url: imageUrl,
- };
- } catch (error) {
- console.error('Error uploading file:', error);
- return {
- success: false,
- message: "Gagal mengunggah gambar",
- };
- }
-}
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/find-by-id.ts
index 95ea591e..468178cb 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/find-by-id.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/find-by-id.ts
@@ -1,33 +1,51 @@
import prisma from "@/lib/prisma";
-import { Context } from "elysia";
-export default async function profilePPIDFindById(context: Context) {
+export default async function handler(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 });
+ }
+
try {
- const id = context?.params?.slugs?.[0];
-
- // If no ID provided, get the first profile
- if (!id) {
- const data = await prisma.profilePPID.findFirst();
- return {
- success: true,
- data,
- };
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 });
}
- const data = await prisma.profilePPID.findUniqueOrThrow({
+ const data = await prisma.profilePPID.findUnique({
where: { id },
+ include: {
+ image: true,
+ }
});
- return {
- success: true,
- data,
- };
- } catch (error) {
- console.error("Error fetching profilePPID:", error);
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ }, { status: 404 });
+ }
- return {
+ return Response.json({
+ success: true,
+ message: "Berhasil mengambil data berdasarkan ID",
+ data,
+ }, { status: 200 });
+ } catch (e) {
+ console.error("Find by ID error:", e);
+ return Response.json({
success: false,
- message: error instanceof Error ? error.message : "Unknown error",
- };
+ message: "Gagal mengambil data: " + (e instanceof Error ? e.message : 'Unknown error'),
+ }, {
+ status: 500,
+ });
}
}
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/index.ts b/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/index.ts
index fb274096..da842cd9 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/index.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/index.ts
@@ -1,24 +1,30 @@
import Elysia, { t } from "elysia";
import profilePPIDFindById from "./find-by-id";
import profilePPIDUpdate from "./update";
-import editImageProfilePPID from "./edit-img";
const ProfilePPID = new Elysia({
prefix: "/profileppid",
tags: ["PPID/Profile PPID"]
})
- .get("/find-by-id", profilePPIDFindById)
- .post("/update", profilePPIDUpdate, {
+ .get("/:id", async (context) => {
+ const response = await profilePPIDFindById(new Request(context.request))
+ return response
+ })
+ .put("/:id", async (context) => {
+ const response = await profilePPIDUpdate(context)
+ return response
+ },
+ {
body: t.Object({
- id: t.String(),
name: t.String(),
biodata: t.String(),
riwayat: t.String(),
pengalaman: t.String(),
unggulan: t.String(),
+ imageId: t.String(),
})
- })
- .post("/edit-img", editImageProfilePPID)
+ }
+)
export default ProfilePPID;
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/update.ts b/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/update.ts
index 621e98f4..ab55ca00 100644
--- a/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/update.ts
+++ b/src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/update.ts
@@ -1,38 +1,121 @@
import prisma from "@/lib/prisma";
import { Prisma } from "@prisma/client";
import { Context } from "elysia";
+import fs from "fs/promises";
+import path from "path";
-type FormCreate = Prisma.ProfilePPIDGetPayload<{
- select: {
- id: true;
- name: true;
- biodata: true;
- riwayat: true;
- pengalaman: true;
- unggulan: true;
- }
-}>
+type FormUpdate = Prisma.ProfilePPIDGetPayload<{
+ select: {
+ id: true;
+ name: true;
+ biodata: true;
+ riwayat: true;
+ pengalaman: true;
+ unggulan: true;
+ imageId: true;
+ };
+}>;
export default async function profilePPIDUpdate(context: Context) {
- const body = context.body as FormCreate;
+ try {
+ const id = context.params?.id as string;
+ const body = (await context.body) as Omit;
- await prisma.profilePPID.update({
- where: {
- id: body.id
- },
- data: {
- name: body.name,
- biodata: body.biodata,
- riwayat: body.riwayat,
- pengalaman: body.pengalaman,
- unggulan: body.unggulan,
+ const { name, biodata, riwayat, pengalaman, unggulan, imageId } = body;
+
+ if (!id) {
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }),
+ {
+ status: 400,
+ headers: {
+ "Content-Type": "application/json",
+ },
}
- })
+ );
+ }
- return {
+ const existing = await prisma.profilePPID.findUnique({
+ where: {
+ id,
+ },
+ include: {
+ image: true,
+ },
+ });
+
+ if (!existing) {
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "Data tidak ditemukan",
+ }),
+ {
+ status: 404,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ }
+
+ if (existing.imageId !== imageId) {
+ const oldImage = existing.image;
+ if (oldImage) {
+ try {
+ const filePath = path.join(oldImage.path, oldImage.name);
+ await fs.unlink(filePath);
+ await prisma.fileStorage.delete({
+ where: { id: oldImage.id },
+ });
+ } catch (error) {
+ console.error("Gagal hapus gambar lama:", error);
+ }
+ }
+ }
+
+ const updated = await prisma.profilePPID.update({
+ where: {
+ id,
+ },
+ data: {
+ name,
+ biodata,
+ riwayat,
+ pengalaman,
+ imageId,
+ unggulan,
+ },
+ });
+
+ return new Response(
+ JSON.stringify({
success: true,
message: "Profile PPID Berhasil Dibuat",
- data: {
- ...body,
- }
- }
-}
\ No newline at end of file
+ data: updated,
+ }),
+ {
+ status: 200,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ } catch (error) {
+ console.error("Error updating profile PPID:", error);
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "Terjadi kesalahan saat mengupdate profile PPID",
+ }),
+ {
+ status: 500,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ }
+}
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/struktur_ppid/find-by-id.ts b/src/app/api/[[...slugs]]/_lib/ppid/struktur_ppid/find-by-id.ts
new file mode 100644
index 00000000..8ea16406
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/struktur_ppid/find-by-id.ts
@@ -0,0 +1,51 @@
+import prisma from "@/lib/prisma";
+
+export default async function strukturPPIDFindById(request: Request) {
+ const url = new URL(request.url);
+ const pathSegments = url.pathname.split('/');
+ const id = pathSegments[pathSegments.length - 1];
+
+ if (!id) {
+ return Response.json({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }, { status: 400 });
+ }
+
+ try {
+ if (typeof id !== 'string') {
+ return Response.json({
+ success: false,
+ message: "ID tidak valid",
+ }, { status: 400 });
+ }
+
+ const data = await prisma.strukturPPID.findUnique({
+ where: { id },
+ include: {
+ image: true,
+ }
+ });
+
+ if (!data) {
+ return Response.json({
+ success: false,
+ message: "Data tidak ditemukan",
+ }, { status: 404 });
+ }
+
+ return Response.json({
+ success: true,
+ message: "Berhasil mengambil data berdasarkan ID",
+ data,
+ }, { status: 200 });
+ } catch (e) {
+ console.error("Find by ID error:", e);
+ return Response.json({
+ success: false,
+ message: "Gagal mengambil data: " + (e instanceof Error ? e.message : 'Unknown error'),
+ }, {
+ status: 500,
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/struktur_ppid/index.ts b/src/app/api/[[...slugs]]/_lib/ppid/struktur_ppid/index.ts
new file mode 100644
index 00000000..5b12d4b8
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/struktur_ppid/index.ts
@@ -0,0 +1,23 @@
+import Elysia, { t } from "elysia";
+import strukturPPIDFindById from "./find-by-id";
+import strukturPPIDUpdate from "./update";
+
+const StrukturPPID = new Elysia({
+ prefix: "/strukturppid",
+ tags: ["PPID/Struktur PPID"]
+})
+.get("/:id", async (context) => {
+ const response = await strukturPPIDFindById(new Request(context.request))
+ return response
+})
+.put("/:id", async (context) => {
+ const response = await strukturPPIDUpdate(context)
+ return response
+}, {
+ body: t.Object({
+ name: t.String(),
+ imageId: t.String(),
+ })
+})
+
+export default StrukturPPID
diff --git a/src/app/api/[[...slugs]]/_lib/ppid/struktur_ppid/update.ts b/src/app/api/[[...slugs]]/_lib/ppid/struktur_ppid/update.ts
new file mode 100644
index 00000000..6af97693
--- /dev/null
+++ b/src/app/api/[[...slugs]]/_lib/ppid/struktur_ppid/update.ts
@@ -0,0 +1,116 @@
+import prisma from "@/lib/prisma";
+import { Context } from "elysia";
+import path from "path";
+import fs from "fs/promises";
+import { Prisma } from "@prisma/client";
+
+type FormUpdate = Prisma.StrukturPPIDGetPayload<{
+ select: {
+ id: true;
+ name: true;
+ imageId: true;
+ };
+}>;
+
+export default async function strukturPPIDUpdate(context: Context) {
+try {
+ const id = context.params?.id as string;
+ const body = (await context.body) as Omit;
+
+ const { name, imageId } = body;
+
+ if (!id) {
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "ID tidak boleh kosong",
+ }),
+ {
+ status: 400,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ )
+ }
+
+ const existing = await prisma.strukturPPID.findUnique({
+ where: {
+ id
+ },
+ include: {
+ image: true,
+ }
+ })
+
+ if (!existing) {
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "Data tidak ditemukan",
+ }),
+ {
+ status: 404,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ )
+ }
+
+ if (existing.imageId !== imageId) {
+ const oldImage = existing.image;
+ if (oldImage) {
+ try {
+ const filePath = path.join(oldImage.path, oldImage.name);
+ await fs.unlink(filePath);
+ await prisma.fileStorage.delete({
+ where: { id: oldImage.id },
+ })
+ } catch (error) {
+ console.error("Gagal hapus gambar lama:", error);
+ }
+ }
+ }
+
+ const updated = await prisma.strukturPPID.update({
+ where: {
+ id
+ },
+ data: {
+ name,
+ imageId,
+ }
+ })
+
+ return new Response(
+ JSON.stringify({
+ success: true,
+ message: "Struktur PPID Berhasil Dibuat",
+ data: updated,
+ }),
+ {
+ status: 200,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ )
+
+} catch (error) {
+ console.error("Error updating struktur PPID:", error);
+ return new Response(
+ JSON.stringify({
+ success: false,
+ message: "Terjadi kesalahan saat mengupdate struktur PPID",
+ }),
+ {
+ status: 500,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ )
+}
+}
+
\ No newline at end of file
diff --git a/src/app/darmasaba/(pages)/ppid/daftar-informasi-publik-desa-darmasaba/page.tsx b/src/app/darmasaba/(pages)/ppid/daftar-informasi-publik-desa-darmasaba/page.tsx
index ba894c94..432d07ed 100644
--- a/src/app/darmasaba/(pages)/ppid/daftar-informasi-publik-desa-darmasaba/page.tsx
+++ b/src/app/darmasaba/(pages)/ppid/daftar-informasi-publik-desa-darmasaba/page.tsx
@@ -1,5 +1,5 @@
'use client'
-import stateDaftarInformasiPublik from '@/app/admin/(dashboard)/_state/ppid/daftar_informasi_publik/daftarInformasiPublik';
+import daftarInformasiPublik from '@/app/admin/(dashboard)/_state/ppid/daftar_informasi_publik/daftarInformasiPublik';
import colors from '@/con/colors';
import { Box, Center, Image, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, TextInput } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
@@ -8,7 +8,7 @@ import { useProxy } from 'valtio/utils';
import BackButton from '../../desa/layanan/_com/BackButto';
function Page() {
- const listData = useProxy(stateDaftarInformasiPublik.daftarInformasi)
+ const listData = useProxy(daftarInformasiPublik)
useShallowEffect(() => {
listData.findMany.load()
}, [])
@@ -51,9 +51,9 @@ function Page() {
- {listData.findMany.data?.map((item) => (
+ {listData.findMany.data?.map((item, index) => (
- {item.nomor}
+ {index + 1}
{item.jenisInformasi}
{item.tanggal}
diff --git a/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin/page.tsx b/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin/page.tsx
index 977ec842..6667281b 100644
--- a/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin/page.tsx
+++ b/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_jenis_kelamin/page.tsx
@@ -1,15 +1,15 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
'use client'
-import React, { useEffect, useState } from 'react';
-import { Box, Center, Flex, Skeleton, Stack, Text, Title } from '@mantine/core';
-import { Cell, Pie, PieChart } from 'recharts';
+import grafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
import colors from '@/con/colors';
+import { Box, Center, Flex, Skeleton, Stack, Text, Title } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
+import { useEffect, useState } from 'react';
+import { Cell, Pie, PieChart } from 'recharts';
import { useProxy } from 'valtio/utils';
-import stateGrafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
function GrafikBerdasarkanJenisKelamin() {
- const grafikBerdasarkanJenisKelamin = useProxy(stateGrafikBerdasarkanJenisKelamin.grafikBerdasarkanJenisKelamin)
+ const stategrafikBerdasarkanJenisKelamin = useProxy(grafikBerdasarkanJenisKelamin)
const [mounted, setMounted] = useState(false);
const [donutData, setDonutData] = useState([]);
@@ -34,13 +34,13 @@ function GrafikBerdasarkanJenisKelamin() {
}, []);
const fetchData = async () => {
- await grafikBerdasarkanJenisKelamin.findMany.load();
- if (grafikBerdasarkanJenisKelamin.findMany.data) {
- updateChartData(grafikBerdasarkanJenisKelamin.findMany.data);
+ await stategrafikBerdasarkanJenisKelamin.findMany.load();
+ if (stategrafikBerdasarkanJenisKelamin.findMany.data) {
+ updateChartData(stategrafikBerdasarkanJenisKelamin.findMany.data);
}
};
- if(!grafikBerdasarkanJenisKelamin.findMany.data) return
+ if(!stategrafikBerdasarkanJenisKelamin.findMany.data) return
Grafik Berdasarkan Jenis Kelamin Responden
diff --git a/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_pilihan_responden/page.tsx b/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_pilihan_responden/page.tsx
index 57a14c08..ae20835b 100644
--- a/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_pilihan_responden/page.tsx
+++ b/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_pilihan_responden/page.tsx
@@ -1,15 +1,15 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
'use client'
-import stateGrafikResponden from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
+import grafikBerdasarkanResponden from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
import colors from '@/con/colors';
-import { Stack, Title, Box, Center, Flex, Text, Skeleton } from '@mantine/core';
+import { Box, Center, Flex, Skeleton, Stack, Text, Title } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
-import React, { useEffect, useState } from 'react';
-import { PieChart, Pie, Cell } from 'recharts';
+import { useEffect, useState } from 'react';
+import { Cell, Pie, PieChart } from 'recharts';
import { useProxy } from 'valtio/utils';
function GrafikBerdasarkanResponden() {
- const grafikBerdasarkanResponden = useProxy(stateGrafikResponden.grafikBerdasarkanResponden)
+ const stategrafikBerdasarkanResponden = useProxy(grafikBerdasarkanResponden)
const [donutData, setDonutData] = useState([]);
const [mounted, setMounted] = useState(false);
@@ -37,13 +37,13 @@ function GrafikBerdasarkanResponden() {
}, []);
const fetchData = async () => {
- await grafikBerdasarkanResponden.findMany.load();
- if (grafikBerdasarkanResponden.findMany.data) {
- updateChartData(grafikBerdasarkanResponden.findMany.data);
+ await stategrafikBerdasarkanResponden.findMany.load();
+ if (stategrafikBerdasarkanResponden.findMany.data) {
+ updateChartData(stategrafikBerdasarkanResponden.findMany.data);
}
};
- if (!grafikBerdasarkanResponden.findMany.data) return
+ if (!stategrafikBerdasarkanResponden.findMany.data) return
Grafik Berdasarkan Responden
diff --git a/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur_responden/page.tsx b/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur_responden/page.tsx
index e1786eaa..a64f9822 100644
--- a/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur_responden/page.tsx
+++ b/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_berdasarkan_umur_responden/page.tsx
@@ -1,15 +1,15 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
'use client'
-import stateGrafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
+import grafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
import colors from '@/con/colors';
-import { Stack, Title, Box, Center, Flex, Text, Skeleton } from '@mantine/core';
+import { Box, Center, Flex, Skeleton, Stack, Text, Title } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
-import React, { useEffect, useState } from 'react';
-import { PieChart, Pie, Cell } from 'recharts';
+import { useEffect, useState } from 'react';
+import { Cell, Pie, PieChart } from 'recharts';
import { useProxy } from 'valtio/utils';
function GrafikBerdasarakanUmur() {
- const grafikBerdasarkanUmur = useProxy(stateGrafikBerdasarkanUmur.grafikBerdasarkanUmur)
+ const stategrafikBerdasarkanUmur = useProxy(grafikBerdasarkanUmur)
const [donutData, setDonutData] = useState([]);
const [mounted, setMounted] = useState(false);
@@ -38,13 +38,13 @@ function GrafikBerdasarakanUmur() {
}, []);
const fetchData = async () => {
- await grafikBerdasarkanUmur.findMany.load();
- if (grafikBerdasarkanUmur.findMany.data) {
- updateChartData(grafikBerdasarkanUmur.findMany.data);
+ await stategrafikBerdasarkanUmur.findMany.load();
+ if (stategrafikBerdasarkanUmur.findMany.data) {
+ updateChartData(stategrafikBerdasarkanUmur.findMany.data);
}
}
- if(!grafikBerdasarkanUmur.findMany.data) return
+ if(!stategrafikBerdasarkanUmur.findMany.data) return
Grafik Berdasarkan Umur Responden
diff --git a/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/page.tsx b/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/page.tsx
index d504cbb1..8dd2c57d 100644
--- a/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/page.tsx
+++ b/src/app/darmasaba/(pages)/ppid/ikm-desa-darmasaba/grafik_hasil_kepuasan_masyarakat/page.tsx
@@ -1,15 +1,15 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
'use client'
-import stateGrafikHasilKepuasanMasyarakat from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
+import grafikHasilKepuasanMasyarakat from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
import colors from '@/con/colors';
import { Box, Skeleton, Stack, Text, Title } from '@mantine/core';
import { useMediaQuery, useShallowEffect } from '@mantine/hooks';
-import React, { useEffect, useState } from 'react';
-import { BarChart, Tooltip, XAxis, YAxis, Legend, Bar } from 'recharts';
+import { useEffect, useState } from 'react';
+import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts';
import { useProxy } from 'valtio/utils';
function GrafikHasilKepuasan() {
- const grafikHasilKepuasan = useProxy(stateGrafikHasilKepuasanMasyarakat.grafikHasilKepuasanMasyarakat)
+ const grafikHasilKepuasan = useProxy(grafikHasilKepuasanMasyarakat)
const [chartData, setChartData] = useState([]);
const [mounted, setMounted] = useState(false);
const isTablet = useMediaQuery('(max-width: 1024px)')
diff --git a/src/app/darmasaba/(pages)/ppid/profile-ppid/page.tsx b/src/app/darmasaba/(pages)/ppid/profile-ppid/page.tsx
index 136c7ce7..4e361459 100644
--- a/src/app/darmasaba/(pages)/ppid/profile-ppid/page.tsx
+++ b/src/app/darmasaba/(pages)/ppid/profile-ppid/page.tsx
@@ -9,10 +9,10 @@ import BackButton from '../../desa/layanan/_com/BackButto';
function Page() {
const allList = useProxy(stateProfilePPID)
useShallowEffect(() => {
- allList.findById.load("1") // Assuming "1" is your default ID, adjust as needed
+ allList.profile.load("1") // Assuming "1" is your default ID, adjust as needed
}, [])
- if (!allList.findById.data) return
+ if (!allList.profile.data) return
@@ -28,9 +28,9 @@ function Page() {
- const dataArray = Array.isArray(allList.findById.data)
- ? allList.findById.data
- : [allList.findById.data];
+ const dataArray = Array.isArray(allList.profile.data)
+ ? allList.profile.data
+ : [allList.profile.data];
return (
diff --git a/src/app/darmasaba/_com/main-page/landing-page/index.tsx b/src/app/darmasaba/_com/main-page/landing-page/index.tsx
index 2a862ad4..a477896a 100644
--- a/src/app/darmasaba/_com/main-page/landing-page/index.tsx
+++ b/src/app/darmasaba/_com/main-page/landing-page/index.tsx
@@ -13,8 +13,63 @@ import {
} from "@mantine/core";
import ModuleView from "./ModuleView";
import SosmedView from "./SosmedView";
+import { useEffect, useState } from "react";
+
+const getDayOfWeek = () => {
+ const days = ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'];
+ const today = new Date();
+ return days[today.getDay()];
+}
+
+const getCurrentTime = () => {
+ const now = new Date();
+ const hours = String(now.getHours()).padStart(2, '0');
+ const minutes = String(now.getMinutes()).padStart(2, '0');
+ return `${hours}:${minutes}`;
+}
+
+const isWorkingHours = (currentTime: string): boolean => {
+ const [openTime, closeTime] = ['08:00', '16:00'];
+
+ const compareTimes = (time1: string, time2: string) => {
+ const [hour1, minute1] = time1.split(':').map(Number);
+ const [hour2, minute2] = time2.split(':').map(Number);
+
+ if (hour1 < hour2) return true;
+ if (hour1 > hour2) return false;
+ return minute1 <= minute2;
+ };
+ return compareTimes(currentTime, closeTime) && !compareTimes(currentTime, openTime);
+}
+const getWorkStatus = (day: string, currentTime: string): { status: string; message: string } => {
+ const workingDays = ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat'];
+
+ if (!workingDays.includes(day)) {
+ return {
+ status: 'Tutup',
+ message: 'Sabtu - Minggu'
+ }
+ }
+ const isOpen = isWorkingHours(currentTime)
+ return isOpen ? { status: 'Buka', message: '08:00 - 16:00' } : { status: 'Tutup', message: '08:00 - 16:00' };
+}
+
function LandingPage() {
+ const [workStatus, setWorkStatus] = useState<{ status: string; message: string }>
+ ({ status: '', message: '' });
+
+ useEffect(() => {
+ const updateWorkStatus = () => {
+ const day = getDayOfWeek();
+ const time = getCurrentTime();
+ const status = getWorkStatus(day, time);
+ setWorkStatus(status);
+ }
+ updateWorkStatus();
+ const intervalId = setInterval(updateWorkStatus, 60 * 1000);
+ return () => clearInterval(intervalId);
+ }, []);
return (
-
- Jadwal Kerja
-
-
-
-
-
- Buka
-
-
- 08:00
-
-
- -
-
-
- Tutup
-
-
- 16:00
-
-
-
-
-
+
+ Jadwal Kerja
+
+
+
+
+
+
+
+ {workStatus.status}
+
+
+ {workStatus.message}
+
+
+
+
+
+
-
-
-
-
- Rabu, 10 Maret 2025
-
-
-
-
- Buka
+ {/* Edit yang ini */}
+
+
+
+ {new Intl.DateTimeFormat('id-ID', {
+ weekday: 'long',
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric'
+ }).format(new Date())}
+
+
+
+ Status
-
- Sabtu - Minggu
+
+ {workStatus.status === 'Buka' ? 'Operasional' : 'Tutup'}
-
-
-
+
+
+
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index e37ccf44..f747e5df 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -11,6 +11,7 @@ import '@mantine/charts/styles.css';
import '@mantine/dates/styles.css';
import '@mantine/tiptap/styles.css';
+
import LoadDataFirstClient from "@/app/darmasaba/_com/LoadDataFirstClient";
import {
ColorSchemeScript,