Compare commits
3 Commits
nico/17-ja
...
nico/21-ja
| Author | SHA1 | Date | |
|---|---|---|---|
| 3fcfec22fb | |||
| 6ca1e032a6 | |||
| 78c55a8a71 |
@@ -45,6 +45,7 @@
|
||||
"@types/bun": "^1.2.2",
|
||||
"@types/leaflet": "^1.9.20",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/mime-types": "^3.0.1",
|
||||
"@types/nodemailer": "^7.0.2",
|
||||
"add": "^2.0.6",
|
||||
"adm-zip": "^0.5.16",
|
||||
@@ -72,6 +73,7 @@
|
||||
"leaflet": "^1.9.4",
|
||||
"list": "^2.0.19",
|
||||
"lodash": "^4.17.21",
|
||||
"mime-types": "^3.0.2",
|
||||
"motion": "^12.4.1",
|
||||
"nanoid": "^5.1.5",
|
||||
"next": "^15.5.2",
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{
|
||||
"id": "795b3e69-2bdb-4d2b-8331-9433fc604723",
|
||||
"year": 2021,
|
||||
"totalPoorPopulation": 480
|
||||
},
|
||||
{
|
||||
"id": "0e61ed28-1789-4329-86bc-67bdb715d4fa",
|
||||
"year": 2022,
|
||||
"totalPoorPopulation": 450
|
||||
},
|
||||
{
|
||||
"id": "0f80e31e-56d7-42aa-aede-e3104f1bca4f",
|
||||
"year": 2023,
|
||||
"totalPoorPopulation": 430
|
||||
},
|
||||
{
|
||||
"id": "3668ecd4-4c4c-4a87-a39a-72661fce5a2c",
|
||||
"year": 2024,
|
||||
"totalPoorPopulation": 410
|
||||
},
|
||||
{
|
||||
"id": "854a375e-4662-4e4c-abd8-59115b4910a9",
|
||||
"year": 2025,
|
||||
"totalPoorPopulation": 390
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkko983k000104l2ff4i8awk",
|
||||
"SD": "35",
|
||||
"SMP": "28",
|
||||
"SMA": "20",
|
||||
"D3": "8",
|
||||
"S1": "15"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkko8wam000004l2h99rekid",
|
||||
"usia18_25": "25",
|
||||
"usia26_35": "18",
|
||||
"usia36_45": "12",
|
||||
"usia46_keatas": "10"
|
||||
}
|
||||
]
|
||||
@@ -94,6 +94,24 @@
|
||||
"educatedUnemployment": 78,
|
||||
"uneducatedUnemployment": 54,
|
||||
"percentageChange": -2.22
|
||||
},
|
||||
{
|
||||
"id": "13f11e4f-c96e-4155-bf30-3f45076ee34c",
|
||||
"month": "Jan",
|
||||
"year": 2026,
|
||||
"totalUnemployment": 350,
|
||||
"educatedUnemployment": 200,
|
||||
"uneducatedUnemployment": 150,
|
||||
"percentageChange": 0.0
|
||||
},
|
||||
{
|
||||
"id": "477b3b0c-af18-4816-a00b-dcac530d57cd",
|
||||
"month": "Feb",
|
||||
"year": 2026,
|
||||
"totalUnemployment": 270,
|
||||
"educatedUnemployment": 150,
|
||||
"uneducatedUnemployment": 120,
|
||||
"percentageChange": -22.9
|
||||
}
|
||||
]
|
||||
|
||||
6
prisma/data/ekonomi/pendapatan-asli-desa/apbDesa.json
Normal file
6
prisma/data/ekonomi/pendapatan-asli-desa/apbDesa.json
Normal file
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{
|
||||
"id": "6b52d644-09b7-4af5-a78b-3dad854973e7",
|
||||
"tahun": 2025
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "82b8c96f-7817-482f-ba5e-85ad78c7bd57",
|
||||
"name": "Belanja Desa (Realisasi Semester I)",
|
||||
"nilai": 43871400
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "cb593f99-9f15-4294-9c17-a93c8c149a25",
|
||||
"name": "Pembiayaan Neto (SILPA 2024)",
|
||||
"nilai": 69289666
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "24576ca1-3dee-4608-9fb3-51f16efce901",
|
||||
"name": "Pendapatan Asli Desa (PADes)",
|
||||
"nilai": 10610011
|
||||
}
|
||||
]
|
||||
@@ -1169,5 +1169,212 @@
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/6DQbAvn0St-xHdPGW3vpY-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkew56ls0000vnysrnzr9ttx",
|
||||
"name": "YdCBnK-bWxlyHjwsk4Qie-desktop.webp",
|
||||
"realName": "WarungPasar.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/YdCBnK-bWxlyHjwsk4Qie-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkewaa2s0001vnysvvs9tu56",
|
||||
"name": "TWdNTZZbTOhFTNJGGPDyG-desktop.webp",
|
||||
"realName": "JajananPasar.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/TWdNTZZbTOhFTNJGGPDyG-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkewcvfq0002vnys6985nm90",
|
||||
"name": "mtQsaKtQnhxIYVIooCkiQ-desktop.webp",
|
||||
"realName": "SayurSegar.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/mtQsaKtQnhxIYVIooCkiQ-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkewf4u90003vnys87en35nj",
|
||||
"name": "Ez-SkRyf_F-1gksz_amNg-desktop.webp",
|
||||
"realName": "AyamDaging.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/Ez-SkRyf_F-1gksz_amNg-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkksb3jr0005vni4sp3ogr87",
|
||||
"name": "r_gBF0FuFpFPfSENHc4XI-desktop.webp",
|
||||
"realName": "desa-digital.jpeg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/r_gBF0FuFpFPfSENHc4XI-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkksoze80008vni4ki2ry81r",
|
||||
"name": "uE2QwpbcXyBWxVYqCWQQT-desktop.webp",
|
||||
"realName": "Digital2.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/uE2QwpbcXyBWxVYqCWQQT-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkkx9e38000bvni4azjd3u53",
|
||||
"name": "SQqSobKRg3ShvgPw_H41h-desktop.webp",
|
||||
"realName": "pengaduan1.webp",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/SQqSobKRg3ShvgPw_H41h-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkkxep9l000evni4xkegbk72",
|
||||
"name": "gyNi4s8TnK2UrViU-gN2C-desktop.webp",
|
||||
"realName": "pd2.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/gyNi4s8TnK2UrViU-gN2C-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkky60sq0000vnjjc55k84d2",
|
||||
"name": "y78xZ2axTOjz87gRKjVAf-desktop.webp",
|
||||
"realName": "penanganan-sampah-rumah-tangga-di-desa copy.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/y78xZ2axTOjz87gRKjVAf-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkm0w0my0001vnswthy6ihaw",
|
||||
"name": "SVeScDA6-OAVvGoAfNC0c-desktop.webp",
|
||||
"realName": "desadg1.jpeg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/SVeScDA6-OAVvGoAfNC0c-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkm0z9hx0004vnswtjd2bk3z",
|
||||
"name": "kN09yF3sahmy-d5EaeGqA-desktop.webp",
|
||||
"realName": "desadg1.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/kN09yF3sahmy-d5EaeGqA-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkm1a14d0005vnsww1tsd92o",
|
||||
"name": "c7xWNyoYp8Cak28NG5NoG-desktop.webp",
|
||||
"realName": "desadg2.jpeg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/c7xWNyoYp8Cak28NG5NoG-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkm1c8py0008vnsw0unbxkpq",
|
||||
"name": "h_Gd0SoeIJVTi_5TWUO-P-desktop.webp",
|
||||
"realName": "desadg3.jpeg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/h_Gd0SoeIJVTi_5TWUO-P-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkm1zis2000bvnsw85m6wdlf",
|
||||
"name": "qJFWokQLCaO60j0XJU_33-desktop.webp",
|
||||
"realName": "mitrakl1.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/qJFWokQLCaO60j0XJU_33-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkm2dgif000evnswskk0dfo9",
|
||||
"name": "nzLJoEAfl7HkpUcYa8Y1E-desktop.webp",
|
||||
"realName": "mitrak2.webp",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/nzLJoEAfl7HkpUcYa8Y1E-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkm2fzub000hvnswnvoytlzs",
|
||||
"name": "JFd5C2FoaZcgDQUmvp-AO-desktop.webp",
|
||||
"realName": "mitrakl3.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/JFd5C2FoaZcgDQUmvp-AO-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkm3b1a2000nvnswb9x48dzk",
|
||||
"name": "JjUDrfqxuEMYSAza-s7A8-desktop.webp",
|
||||
"realName": "desa-digital.jpeg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/JjUDrfqxuEMYSAza-s7A8-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkm3bnkt000qvnswzhqa4upf",
|
||||
"name": "xVrwJgdwtcoABPU6DB__Y-desktop.webp",
|
||||
"realName": "Digital2.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/xVrwJgdwtcoABPU6DB__Y-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkm3fwg4000rvnsw5d1vbiz0",
|
||||
"name": "42RCCpBZla4ZWxXcwx7kG-desktop.webp",
|
||||
"realName": "infotek3-1.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/42RCCpBZla4ZWxXcwx7kG-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmkm3hjhz000uvnswwqu6z9f6",
|
||||
"name": "TrbkwnYM5rKZeHlISHCX4-desktop.webp",
|
||||
"realName": "infotek4.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/TrbkwnYM5rKZeHlISHCX4-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmknb59md0000vnmam828iuzt",
|
||||
"name": "YgOX5qAP3O1PHG5XmQXkr-desktop.webp",
|
||||
"realName": "gr-1.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/YgOX5qAP3O1PHG5XmQXkr-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmknbp3vd0001vnmarjz542o7",
|
||||
"name": "qxqSDHe-akIRi1EkQFUbG-desktop.webp",
|
||||
"realName": "gr-2.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/qxqSDHe-akIRi1EkQFUbG-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmknbrj4r0002vnmantw9rn0l",
|
||||
"name": "iHTVkQZ1VdkMOXLt5qdAd-desktop.webp",
|
||||
"realName": "gr-3.jpg",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/iHTVkQZ1VdkMOXLt5qdAd-desktop.webp",
|
||||
"category": "image"
|
||||
}
|
||||
]
|
||||
|
||||
38
prisma/data/inovasi/ajukan-ide/ajukan-ide.json
Normal file
38
prisma/data/inovasi/ajukan-ide/ajukan-ide.json
Normal file
@@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkm710n3000xvnsw1ni0vlam",
|
||||
"name": "I Made Rudi",
|
||||
"alamat": "Darmasaba, Abiansemal, Badung, Bali",
|
||||
"namaIde": "Program Bersama Jaga Rabies (BAJRA)",
|
||||
"deskripsi": "Inovasi berbasis komunitas yang mengintegrasikan pelaporan cepat masyarakat, edukasi berkelanjutan, serta koordinasi lintas sektor untuk penanggulangan rabies secara efektif di Desa Darmasaba.",
|
||||
"masalah": "Tingginya kasus rabies dan rendahnya pelaporan serta koordinasi penanganan antar warga sehingga perlunya pendekatan komunitas yang terstruktur.",
|
||||
"benefit": "Meningkatkan kesadaran vaksinasi, respons cepat terhadap kasus gigitan, serta memperkuat sistem kesiapsiagaan kesehatan hewan dan manusia di komunitas."
|
||||
},
|
||||
{
|
||||
"id": "cmkm710n3000xvnsw1ni1wmbn",
|
||||
"name": "I Made Rudja",
|
||||
"alamat": "Darmasaba, Abiansemal, Badung, Bali",
|
||||
"namaIde": "Program LESTARI – Ekowisata dan Edukasi Lingkungan",
|
||||
"deskripsi": "Inovasi pengembangan ekowisata berbasis persawahan yang menggabungkan edukasi lingkungan dan potensi desa untuk menarik wisatawan serta meningkatkan kesejahteraan masyarakat.",
|
||||
"masalah": "Kurangnya sarana edukasi lingkungan dan kurang optimalnya pemanfaatan potensi lahan persawahan sebagai sumber pendapatan masyarakat.",
|
||||
"benefit": "Menambah peluang ekonomi desa, meningkatkan kesadaran lingkungan, dan memperkuat daya tarik wisata lokal Desa Darmasaba."
|
||||
},
|
||||
{
|
||||
"id": "cmkm710n3000xvnsw1ni2xnco",
|
||||
"name": "I Wayan Sumi",
|
||||
"alamat": "Darmasaba, Abiansemal, Badung, Bali",
|
||||
"namaIde": "Darmasaba Digital Project",
|
||||
"deskripsi": "Ide inovatif untuk mengembangkan satu platform digital terpadu bagi layanan pemerintahan desa serta administrasi kerja desa yang lebih cepat dan transparan.",
|
||||
"masalah": "Proses administrasi dan pelayanan publik desa yang masih belum terintegrasi secara digital sehingga kurang efisien.",
|
||||
"benefit": "Meningkatkan efisiensi kerja perangkat desa, transparansi data, dan kecepatan layanan kepada masyarakat."
|
||||
},
|
||||
{
|
||||
"id": "cmkm710n3000xvnsw1ni3yodp",
|
||||
"name": "I Ketut Surya",
|
||||
"alamat": "Darmasaba, Abiansemal, Badung, Bali",
|
||||
"namaIde": "Program CINTA – Cara Indah Tangani Sampah",
|
||||
"deskripsi": "Inovasi pengelolaan sampah melalui mekanisme pilah, kompos, dan bursa sampah (BARES) untuk mengurangi volume sampah di desa dan meningkatkan nilai ekonomi dari sampah yang ternyata bernilai jual.",
|
||||
"masalah": "Volume sampah meningkat yang berdampak pada lingkungan, kurangnya sistem pengelolaan sampah berbasis komunitas.",
|
||||
"benefit": "Lingkungan desa menjadi bersih, sampah bernilai ekonomi dan peningkatan keterlibatan masyarakat dalam pengelolaan sampah."
|
||||
}
|
||||
]
|
||||
32
prisma/data/inovasi/desa-digital/desa-digital.json
Normal file
32
prisma/data/inovasi/desa-digital/desa-digital.json
Normal file
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkkshcox000504l88lp54coc",
|
||||
"name": "Darmasaba Digital App",
|
||||
"deskripsi": "<p>Aplikasi digital desa yang dikembangkan oleh Pemerintah Desa Darmasaba pada tahun 2024 untuk mempermudah pelayanan publik dan informasi pemerintahan berbasis digital.</p>",
|
||||
"imageId": "cmkksb3jr0005vni4sp3ogr87"
|
||||
},
|
||||
{
|
||||
"id": "cmkkshln8000604l8c9b5b4il",
|
||||
"name": "D’DAMART (Darmasaba Digital Market)",
|
||||
"deskripsi": "<p>Sistem pasar UMKM digital berbasis website yang dikembangkan untuk meningkatkan akses pasar dan pemasaran produk UMKM Desa Darmasaba melalui platform digital.</p>",
|
||||
"imageId": "cmkksoze80008vni4ki2ry81r"
|
||||
},
|
||||
{
|
||||
"id": "cmkm1a1g80007vnsw8ejmj816",
|
||||
"name": "Media Aspirasi dan Pengaduan Warga",
|
||||
"deskripsi": "<p>Media aspirasi dan pengaduan warga disediakan sebagai wadah partisipasi masyarakat dalam menyampaikan saran, masukan, maupun keluhan secara transparan dan terstruktur. Fitur ini memperkuat komunikasi dua arah antara pemerintah desa dan masyarakat, sehingga setiap aspirasi dapat ditindaklanjuti secara lebih cepat dan akuntabel.</p>",
|
||||
"imageId": "cmkm1a14d0005vnsww1tsd92o"
|
||||
},
|
||||
{
|
||||
"id": "cmkm0w0s50003vnswmwpnqsi5",
|
||||
"name": "Website Desa Resmi",
|
||||
"deskripsi": "<p>Website Desa Darmasaba berfungsi sebagai sarana utama penyampaian informasi resmi kepada masyarakat. Melalui website ini, pemerintah desa menghadirkan keterbukaan informasi publik, mempermudah akses warga terhadap berita, pengumuman, serta agenda kegiatan desa, sekaligus menjadi pusat data dan referensi terkait profil dan struktur pemerintahan desa.</p>",
|
||||
"imageId": "cmkm0z9hx0004vnswtjd2bk3z"
|
||||
},
|
||||
{
|
||||
"id": "cmkm1c8wx000avnswksc56orq",
|
||||
"name": "Publikasi Kegiatan Desa Secara Digital",
|
||||
"deskripsi": "<p>Publikasi kegiatan desa secara digital bertujuan untuk mendokumentasikan dan menyebarluaskan berbagai aktivitas serta program kerja pemerintah desa. Melalui artikel dan dokumentasi foto, masyarakat dapat mengetahui perkembangan kegiatan desa secara terbuka, sekaligus meningkatkan kepercayaan publik terhadap pelaksanaan program desa.</p>",
|
||||
"imageId": "cmkm1c8py0008vnsw0unbxkpq"
|
||||
}
|
||||
]
|
||||
26
prisma/data/inovasi/info-teknologi/info-teknologi.json
Normal file
26
prisma/data/inovasi/info-teknologi/info-teknologi.json
Normal file
@@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkm2xlqr000mvnswdaymiho6",
|
||||
"name": "Darmasaba Digital App",
|
||||
"deskripsi": "<p>Aplikasi layanan desa berbasis teknologi untuk transparansi informasi dan layanan publik di Desa Darmasaba yang membantu warga mendapatkan informasi administratif, berita desa, dan pelayanan digital lainnya secara cepat dan mudah.</p>",
|
||||
"imageId": "cmkm3bnkt000qvnswzhqa4upf"
|
||||
},
|
||||
{
|
||||
"id": "cmkm3b1fw000pvnswpr7hgzhp",
|
||||
"name": "Program Digitalisasi Desa",
|
||||
"deskripsi": "<p>Program kerja sama Desa Darmasaba bersama PT. Bali Interaktif Perkasa untuk memperkuat kapasitas pemanfaatan teknologi informasi dan komunikasi dalam administrasi desa, pelayanan publik, serta pemberdayaan digital masyarakat.</p>",
|
||||
"imageId": "cmkm3b1a2000nvnswb9x48dzk"
|
||||
},
|
||||
{
|
||||
"id": "cmkm3fwmq000tvnswejmhm7yc",
|
||||
"name": "Pengembangan Sistem Informasi Desa",
|
||||
"deskripsi": "<p>Inisiatif pengembangan Sistem Informasi Desa yang mendukung pengelolaan data desa secara digital, termasuk data publik, laporan, dan statistik warga, sebagai bagian dari peningkatan kapabilitas teknologi informasi desa.</p>",
|
||||
"imageId": "cmkm3fwg4000rvnsw5d1vbiz0"
|
||||
},
|
||||
{
|
||||
"id": "cmkm3hjp6000wvnswkuylnf53",
|
||||
"name": "Pelayanan Kependudukan Berbasis Digital",
|
||||
"deskripsi": "<p>Program untuk menyediakan layanan kependudukan secara digital, termasuk integrasi sistem administrasi kependudukan desa dengan sistem nasional, guna mempercepat layanan e-KTP, kartu keluarga, dan berkas kependudukan lainnya.</p>",
|
||||
"imageId": "cmkm3hjhz000uvnswwqu6z9f6"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": "cmklzhfjb0000vnswml6z7xnj",
|
||||
"name": "Bersama Jaga Rabies (BAJRA)",
|
||||
"tahun": 2025,
|
||||
"slug": "Program kolaborasi penanggulangan rabies",
|
||||
"deskripsi": "<p>Inovasi BAJRA (Bersama Jaga Rabies) merupakan program kolaboratif Desa Darmasaba bersama berbagai pihak, termasuk Sahabat Anti Rabies Indonesia dan Dinas Pertanian dan Pangan Kabupaten Badung, yang fokus pada edukasi publik, pelaporan cepat, serta strategis vaksinasi anjing guna upaya eliminasi rabies. Inovasi ini diangkat hingga tingkat internasional di Konferensi Rabies in Borneo 2025.</p>",
|
||||
"kolaborator": "Sahabat Anti Rabies Indonesia, Bidang Kesehatan Hewan Dinas Pertanian dan Pangan Kabupaten Badung"
|
||||
},
|
||||
{
|
||||
"id": "cmklzhfjb0000vnswml6z8yok",
|
||||
"name": "Inovasi Eco-Enzyme dan Optimalisasi Tata Kelola BUMDes",
|
||||
"tahun": 2025,
|
||||
"slug": "Kolaborasi inovasi ekonomi & lingkungan",
|
||||
"deskripsi": "<p>Program kerja sama Desa Darmasaba dengan Universitas Warmadewa dan BUMDes setempat yang berfokus pada pelatihan produksi eco-enzyme ramah lingkungan dan pengembangan tata kelola BUMDes modern untuk meningkatkan kesejahteraan masyarakat berbasis usaha hijau dan ekonomi kreatif.</p>",
|
||||
"kolaborator": "Universitas Warmadewa, Pengurus BUMDes Darmasaba"
|
||||
},
|
||||
{
|
||||
"id": "cmklzhfjb0000vnswml6z9zpl",
|
||||
"name": "Ekowisata dan Kuliner Berkelanjutan",
|
||||
"tahun": 2025,
|
||||
"slug": "Kolaborasi pengembangan ekowisata dan kuliner berbasis budaya",
|
||||
"deskripsi": "<p>Kegiatan yang melibatkan desa adat, BUMDes, UMKM, akademisi, dan pemerintah desa untuk mengembangkan ekowisata dan kuliner lokal berbasis keberlanjutan lingkungan serta potensi budaya setempat, sebagai wujud sinergi inovatif di Darmasaba.</p>",
|
||||
"kolaborator": "Desa Adat Darmasaba, BUMDes, UMKM lokal, Akademisi"
|
||||
}
|
||||
]
|
||||
17
prisma/data/inovasi/kolaborasi-inovasi/mitra-kolaborasi.json
Normal file
17
prisma/data/inovasi/kolaborasi-inovasi/mitra-kolaborasi.json
Normal file
@@ -0,0 +1,17 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkm1ziyi000dvnsweg8lp3f7",
|
||||
"name": "TP Posyandu Bali",
|
||||
"imageId": "cmkm1zis2000bvnsw85m6wdlf"
|
||||
},
|
||||
{
|
||||
"id": "cmkm1ziyi000dvnsweg8lq4g8",
|
||||
"name": "BRI Peduli",
|
||||
"imageId": "cmkm2dgif000evnswskk0dfo9"
|
||||
},
|
||||
{
|
||||
"id": "cmkm1ziyi000dvnsweg8lr5h9",
|
||||
"name": "Universitas Warmadewa (KKN-PMM)",
|
||||
"imageId": "cmkm2fzub000hvnswnvoytlzs"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,44 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkkt91ma000004lb4dpq7ll1",
|
||||
"name": "Surat Keterangan Domisili Organisasi",
|
||||
"alamat": "Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung, Bali",
|
||||
"nomorTelepon": "0361-9876543",
|
||||
"jenisLayananId": "dnllt91ma000004lb4dpq7ll1"
|
||||
},
|
||||
{
|
||||
"id": "cmkkt91ma000004lb4dpq8mm2",
|
||||
"name": "Surat Keterangan Penghasilan",
|
||||
"alamat": "Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung, Bali",
|
||||
"nomorTelepon": "0361-9776543",
|
||||
"jenisLayananId": "dnllt91ma000004lb4dpq8mm2"
|
||||
},
|
||||
{
|
||||
"id": "cmkkt91ma000004lb4dpq9nn3",
|
||||
"name": "Surat Keterangan Tidak Mampu",
|
||||
"alamat": "Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung, Bali",
|
||||
"nomorTelepon": "0361-9676543",
|
||||
"jenisLayananId": "dnllt91ma000004lb4dpq9nn3"
|
||||
},
|
||||
{
|
||||
"id": "cmkkt91ma000004lb4dpq0oo4",
|
||||
"name": "Surat Keterangan Kelahiran",
|
||||
"alamat": "Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung, Bali",
|
||||
"nomorTelepon": "0361-9576543",
|
||||
"jenisLayananId": "dnllt91ma000004lb4dpq0oo4"
|
||||
},
|
||||
{
|
||||
"id": "cmkkt91ma000004lb4dpq1pp5",
|
||||
"name": "Surat Keterangan Usaha",
|
||||
"alamat": "Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung, Bali",
|
||||
"nomorTelepon": "0361-9476543",
|
||||
"jenisLayananId": "dnllt91ma000004lb4dpq1pp5"
|
||||
},
|
||||
{
|
||||
"id": "cmkkt91ma000004lb4dpq2qq6",
|
||||
"name": "Perizinan Berusaha OSS",
|
||||
"alamat": "Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung, Bali",
|
||||
"nomorTelepon": "0361-9376543",
|
||||
"jenisLayananId": "dnllt91ma000004lb4dpq2qq6"
|
||||
}
|
||||
]
|
||||
32
prisma/data/inovasi/layanan-online-desa/jenis-layanan.json
Normal file
32
prisma/data/inovasi/layanan-online-desa/jenis-layanan.json
Normal file
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"id": "dnllt91ma000004lb4dpq7ll1",
|
||||
"nama": "Surat Keterangan Domisili Organisasi",
|
||||
"deskripsi": "Administrasi Online Surat Keterangan Domisili Organisasi"
|
||||
},
|
||||
{
|
||||
"id": "dnllt91ma000004lb4dpq8mm2",
|
||||
"nama": "Surat Keterangan Penghasilan",
|
||||
"deskripsi": "Administrasi Online Surat Keterangan Penghasilan"
|
||||
},
|
||||
{
|
||||
"id": "dnllt91ma000004lb4dpq9nn3",
|
||||
"nama": "Surat Keterangan Tidak Mampu",
|
||||
"deskripsi": "Administrasi Online Surat Keterangan Tidak Mampu"
|
||||
},
|
||||
{
|
||||
"id": "dnllt91ma000004lb4dpq0oo4",
|
||||
"nama": "Surat Keterangan Kelahiran",
|
||||
"deskripsi": "Administrasi Online Surat Keterangan Kelahiran"
|
||||
},
|
||||
{
|
||||
"id": "dnllt91ma000004lb4dpq1pp5",
|
||||
"nama": "Surat Keterangan Usaha",
|
||||
"deskripsi": "Administrasi Online Surat Keterangan Usaha"
|
||||
},
|
||||
{
|
||||
"id": "dnllt91ma000004lb4dpq2qq6",
|
||||
"nama": "Perizinan Berusaha OSS",
|
||||
"deskripsi": "Administrasi Online Perizinan Usaha Online Single Submission (OSS)"
|
||||
}
|
||||
]
|
||||
26
prisma/data/inovasi/layanan-online-desa/jenis-pengaduan.json
Normal file
26
prisma/data/inovasi/layanan-online-desa/jenis-pengaduan.json
Normal file
@@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": "eommt91ma000004lb4dpq7ll1",
|
||||
"nama": "Lingkungan"
|
||||
},
|
||||
{
|
||||
"id": "eommt91ma000004lb4dpq8mm2",
|
||||
"nama": "Ketertiban Umum"
|
||||
},
|
||||
{
|
||||
"id": "eommt91ma000004lb4dpq9nn3",
|
||||
"nama": "Kesehatan Masyarakat"
|
||||
},
|
||||
{
|
||||
"id": "eommt91ma000004lb4dpq0oo4",
|
||||
"nama": "Pendidikan"
|
||||
},
|
||||
{
|
||||
"id": "eommt91ma000004lb4dpq1pp5",
|
||||
"nama": "Pembangunan Infrastuktur"
|
||||
},
|
||||
{
|
||||
"id": "eommt91ma000004lb4dpq2qq6",
|
||||
"nama": "Perizinan Berusaha"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkkrxmub0004vni41cwyhid4",
|
||||
"name": "Nyoman Putra",
|
||||
"email": "nyoman.putra@example.com",
|
||||
"nomorTelepon": "081234567890",
|
||||
"nik": "3175011234567890",
|
||||
"judulPengaduan": "Permintaan Pemasangan Spanduk Larangan Bagi Hewan",
|
||||
"deskripsiPengaduan": "<p>Permintaan Pemasangan Spanduk Larangan Bagi Hewan</p>",
|
||||
"lokasiKejadian": "Banjar Darmasaba Tengah",
|
||||
"jenisPengaduanId": "eommt91ma000004lb4dpq7ll1",
|
||||
"imageId": "cmkkxep9l000evni4xkegbk72"
|
||||
},
|
||||
{
|
||||
"id": "cmkkrxmub0004vni41cwyhid5",
|
||||
"name": "I Made Sari",
|
||||
"email": "imade.sari@example.com",
|
||||
"nomorTelepon": "087654321098",
|
||||
"nik": "3175010987654321",
|
||||
"judulPengaduan": "Laporan Anjing Liar Sering Menyerang Warga",
|
||||
"deskripsiPengaduan": "<p>Laporan Anjing Liar Sering Menyerang Warga</p>",
|
||||
"lokasiKejadian": "Jl. Raya Darmasaba",
|
||||
"jenisPengaduanId": "eommt91ma000004lb4dpq8mm2",
|
||||
"imageId": "cmkkx9e38000bvni4azjd3u53"
|
||||
},
|
||||
{
|
||||
"id": "cmkkrxmub0004vni41cwyhid6",
|
||||
"name": "Ketut Widi",
|
||||
"email": "ketut.widi@example.com",
|
||||
"nomorTelepon": "085612347890",
|
||||
"nik": "3175011122334455",
|
||||
"judulPengaduan": "Pengelolaan Sampah Rumah Tangga Belum Efektif",
|
||||
"deskripsiPengaduan": "<p>Pengelolaan Sampah Rumah Tangga Belum Efektif</p>",
|
||||
"lokasiKejadian": "Banjar Bucu",
|
||||
"jenisPengaduanId": "eommt91ma000004lb4dpq7ll1",
|
||||
"imageId": "cmkky60sq0000vnjjc55k84d2"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,44 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkkyux9x000104jo4gwi9frv",
|
||||
"name": "Pelatihan Pembuatan Eco-Enzyme",
|
||||
"slug": "Pelatihan pembuatan cairan eco-enzyme dari limbah organik rumah tangga",
|
||||
"deskripsi": "<p>Program ini mengajarkan masyarakat Desa Darmasaba cara membuat eco-enzyme dari limbah organik yang dapat digunakan sebagai pembersih alami, pupuk organik, dan produk ramah lingkungan untuk meningkatkan nilai tambah ekonomi lokal.</p>",
|
||||
"icon": "lingkunganSehat"
|
||||
},
|
||||
{
|
||||
"id": "cmkkyux9x000104jo4gwi0gsw",
|
||||
"name": "Green House dan Biopori Berkelanjutan",
|
||||
"slug": "Perancangan rumah kaca dan lubang biopori di TPS3R",
|
||||
"deskripsi": "<p>Program perancangan dan pembangunan green house di kawasan TPS3R Pudak Mesari serta pembuatan lubang biopori untuk pengelolaan sampah organik dan konservasi air yang ramah lingkungan sebagai bagian dari pengembangan ekonomi hijau desa.</p>",
|
||||
"icon": "lingkunganSehat"
|
||||
},
|
||||
{
|
||||
"id": "cmkkyux9x000104jo4gwi1htx",
|
||||
"name": "Ekowisata dan Eco-Kuliner Desa",
|
||||
"slug": "Pengembangan paket ekowisata dan kuliner berbasis potensi lokal",
|
||||
"deskripsi": "<p>Kolaborasi antara desa, BUMDes, dan akademisi untuk mengembangkan potensi ekowisata berkelanjutan serta produk kuliner khas desa dengan pendekatan pemasaran digital untuk memperkuat ekonomi kreatif dan pariwisata lokal.</p>",
|
||||
"icon": "ekowisata"
|
||||
},
|
||||
{
|
||||
"id": "cmkkyux9x000104jo4gwi2iuy",
|
||||
"name": "Sosialisasi Kewirausahaan",
|
||||
"slug": "Sosialisasi kewirausahaan bagi masyarakat desa",
|
||||
"deskripsi": "<p>Program ini memberikan pengetahuan dan motivasi kepada warga Darmasaba tentang kewirausahaan, pemasaran digital, pencatatan usaha, dan strategi pengembangan UMKM agar produk lokal lebih produktif dan bernilai ekonomi.</p>",
|
||||
"icon": "ekonomi"
|
||||
},
|
||||
{
|
||||
"id": "cmkkyux9x000104jo4gwi3jvz",
|
||||
"name": "E-Book Kuliner Lokal",
|
||||
"slug": "Publikasi e-book tentang kuliner khas Desa Darmasaba",
|
||||
"deskripsi": "<p>Produksi dan distribusi e-book yang mengangkat resep dan cerita kuliner khas Desa Darmasaba sebagai media edukatif dan promosi budaya pangan lokal yang kreatif serta bisa diperluas untuk pemasaran UMKM desa.</p>",
|
||||
"icon": "book"
|
||||
},
|
||||
{
|
||||
"id": "cmkkyux9x000104jo4gwi4kwa",
|
||||
"name": "Tes Kompetensi",
|
||||
"slug": "Program pemetaan minat dan keterampilan masyarakat untuk mendukung pengembangan potensi dan kesiapan kerja.",
|
||||
"deskripsi": "<p>Tes Kompetensi merupakan program untuk membantu masyarakat, khususnya generasi muda, dalam mengenali minat, bakat, dan keterampilan yang dimiliki. Hasil tes dapat menjadi dasar dalam perencanaan pelatihan, pengembangan potensi diri, serta kesiapan menghadapi dunia kerja dan wirausaha.</p>",
|
||||
"icon": "layananPublik"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,44 @@
|
||||
[
|
||||
{
|
||||
"id": "bnlneq3zg0000vn8issps1eg8",
|
||||
"name": "Pelaksanaan Kebersihan Lingkungan Desa",
|
||||
"jumlah": "1 paket kegiatan",
|
||||
"deskripsi": "Kegiatan pelaksanaan kebersihan lingkungan desa Darmasaba untuk meningkatkan kualitas lingkungan dan kesehatan masyarakat.",
|
||||
"icon": "lingkunganSehat"
|
||||
},
|
||||
{
|
||||
"id": "bnlneq3zg0000vn8issps2fh9",
|
||||
"name": "Penataan Taman Telajakan",
|
||||
"jumlah": "1 paket kegiatan",
|
||||
"deskripsi": "Program penataan taman telajakan sebagai upaya memperindah lingkungan desa serta ruang terbuka publik di desa Darmasaba.",
|
||||
"icon": "lingkunganSehat"
|
||||
},
|
||||
{
|
||||
"id": "bnlneq3zg0000vn8issps3gi0",
|
||||
"name": "Pelatihan/Sosialisasi Peduli Lingkungan",
|
||||
"jumlah": "1 paket kegiatan",
|
||||
"deskripsi": "Pelatihan dan sosialisasi penyuluhan tentang kepedulian lingkungan hidup dan kehutanan bagi masyarakat.",
|
||||
"icon": "pelatihan"
|
||||
},
|
||||
{
|
||||
"id": "bnlneq3zg0000vn8issps4hj2",
|
||||
"name": "Pemanfaatan Pekarangan Rumah",
|
||||
"jumlah": "1 paket kegiatan",
|
||||
"deskripsi": "Program pemanfaatan lingkungan pekarangan rumah menjadi produktif untuk mendukung ketahanan pangan keluarga.",
|
||||
"icon": "sumberOksigen"
|
||||
},
|
||||
{
|
||||
"id": "bnlneq3zg0000vn8issps5ik3",
|
||||
"name": "Pengelolaan Daerah Aliran Sungai",
|
||||
"jumlah": "1 paket kegiatan",
|
||||
"deskripsi": "Kegiatan pengelolaan dan pemeliharaan daerah aliran sungai untuk menjaga kualitas sumber air dan mencegah erosi.",
|
||||
"icon": "air"
|
||||
},
|
||||
{
|
||||
"id": "bnlneq3zg0000vn8issps6jl4",
|
||||
"name": "Pengelolaan Sampah Desa (Inovasi CINtA)",
|
||||
"jumlah": "1 paket kegiatan",
|
||||
"deskripsi": "Program inovatif cara indah tangani sampah (CINtA) di desa Darmasaba termasuk TPS3R dan pemilahan sampah berbasis rumah tangga.",
|
||||
"icon": "sampah"
|
||||
}
|
||||
]
|
||||
35
prisma/data/lingkungan/gotong-royong/gotong-royong.json
Normal file
35
prisma/data/lingkungan/gotong-royong/gotong-royong.json
Normal file
@@ -0,0 +1,35 @@
|
||||
[
|
||||
{
|
||||
"id": "ee38b9ee-88ca-4a11-8fa0-7d407ea7e774",
|
||||
"judul": "Gotong Royong PKK Mareresik Pura Desa dan Pura Dalem",
|
||||
"deskripsiSingkat": "TP PKK Desa Darmasaba melaksanakan gotong royong mareresik di Pura Desa dan Pura Dalem Desa Adat Tegal.",
|
||||
"deskripsiLengkap": "Pada tanggal 28 Januari 2024, TP PKK Desa Darmasaba bersama Ketua Kelompok PKK Banjar se-Desa Darmasaba melakukan kegiatan gotong royong membersihkan area Pura Desa dan Pura Dalem untuk mendukung kebersihan dan kesehatan lingkungan desa.",
|
||||
"tanggal": "2024-01-28T00:00:00.000Z",
|
||||
"lokasi": "Pura Desa dan Pura Dalem, Desa Adat Tegal, Desa Darmasaba, Badung",
|
||||
"partisipan": 30,
|
||||
"imageId": "cmknb59md0000vnmam828iuzt",
|
||||
"kategoriKegiatanId": "cmknan39v000004l8eiql149r"
|
||||
},
|
||||
{
|
||||
"id": "dead9da0-e2e2-494c-9f88-721f2c3aa62a",
|
||||
"judul": "Mareresik (Gotong Royong)",
|
||||
"deskripsiSingkat": "Kegiatan mareresik (gotong royong) yang dilaksanakan di lingkungan desa Darmasaba.",
|
||||
"deskripsiLengkap": "Mareresik (gotong royong) dilakukan pada tanggal 17 November 2023 oleh warga Desa Darmasaba sebagai bagian dari tradisi membersihkan dan menjaga lingkungan desa secara kolektif.",
|
||||
"tanggal": "2023-11-17T00:00:00.000Z",
|
||||
"lokasi": "Desa Darmasaba, Badung",
|
||||
"partisipan": 25,
|
||||
"imageId": "cmknbp3vd0001vnmarjz542o7",
|
||||
"kategoriKegiatanId": "cmknan39v000004l8eiql149r"
|
||||
},
|
||||
{
|
||||
"id": "5186e23b-28a6-4f64-89b8-43a35e5048a5",
|
||||
"judul": "Gotong Royong dan Rapat Rutin TP PKK Desa Darmasaba",
|
||||
"deskripsiSingkat": "Gotong royong bersama TP PKK Desa Darmasaba di Pura Dalem Kangin Desa Adat Tegal sekaligus rapat rutin.",
|
||||
"deskripsiLengkap": "Pada tanggal 26 Mei 2022, TP PKK Desa Darmasaba bersama anggota se-Desa Darmasaba melaksanakan gotong royong mereresik Pura Dalem Kangin Desa Adat Tegal dan dilanjutkan dengan rapat rutin TP PKK sebagai wujud semangat kerja bersama dan kebersamaan sosial.",
|
||||
"tanggal": "2022-05-26T00:00:00.000Z",
|
||||
"lokasi": "Pura Dalem Kangin, Desa Adat Tegal, Desa Darmasaba, Badung",
|
||||
"partisipan": 28,
|
||||
"imageId": "cmknbrj4r0002vnmantw9rn0l",
|
||||
"kategoriKegiatanId": "cmknan39v000004l8eiql149r"
|
||||
}
|
||||
]
|
||||
@@ -1,6 +1,6 @@
|
||||
[
|
||||
{ "nama": "Kebersihan" },
|
||||
{ "nama": "Infrastruktur" },
|
||||
{ "nama": "Sosial" },
|
||||
{ "nama": "Lingkungan" }
|
||||
]
|
||||
{ "id": "cmknan39v000004l8eiql816o", "nama": "Kebersihan" },
|
||||
{ "id": "cmknan39v000004l8eiql927p", "nama": "Infrastruktur" },
|
||||
{ "id": "cmknan39v000004l8eiql038q", "nama": "Sosial" },
|
||||
{ "id": "cmknan39v000004l8eiql149r", "nama": "Lingkungan" }
|
||||
]
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkm8z5v70000vnrmu60qyd7b",
|
||||
"name": "TPS 3R Pudak Mesari",
|
||||
"alamat": "Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung, Bali 80352",
|
||||
"namaTempatMaps": "TPS 3R Pudak Mesari",
|
||||
"linkPetunjukArah": "https://www.google.com/maps/dir/?api=1&destination=-8.5680,115.2040",
|
||||
"lat": -8.5680,
|
||||
"lng": 115.2040
|
||||
},
|
||||
{
|
||||
"id": "dummy0000000000000000000001",
|
||||
"name": "Bank Sampah Darmasaba Mandiri",
|
||||
"alamat": "Banjar Darmasaba Tengah, Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung, Bali",
|
||||
"namaTempatMaps": "Bank Sampah Darmasaba Mandiri",
|
||||
"linkPetunjukArah": "https://www.google.com/maps/dir/?api=1&destination=-8.5670,115.2000",
|
||||
"lat": -8.5670,
|
||||
"lng": 115.2000
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkkshcox000504l88lp54coc",
|
||||
"name": "Pilah sampah sesuai jenisnya",
|
||||
"icon": "trash"
|
||||
},
|
||||
{
|
||||
"id": "cmkkshcox000504l99mq65dpd",
|
||||
"name": "Bawa sampah ke Bank Sampah",
|
||||
"icon": "truck"
|
||||
},
|
||||
{
|
||||
"id": "cmkkshcox000504l00nr76eqe",
|
||||
"name": "Timbang sampah di Bank Sampah",
|
||||
"icon": "scale"
|
||||
},
|
||||
{
|
||||
"id": "cmkkshcox000504l11os87frf",
|
||||
"name": "Catat hasil timbangan di buku tabungan",
|
||||
"icon": "clipboard"
|
||||
},
|
||||
{
|
||||
"id": "cmkkshcox000504l22pt98gsg",
|
||||
"name": "Sampah didaur ulang oleh petugas Bank Sampah",
|
||||
"icon": "sampah"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
[
|
||||
{
|
||||
"id": "cmkmdp3zg0000vn8issps1eg8",
|
||||
"name": "Penghijauan Desa Darmasaba",
|
||||
"judul": "Program Penghijauan Lingkungan",
|
||||
"deskripsi": "<p>Program penghijauan desa Darmasaba bertujuan menanam pohon di area publik dan pinggiran jalan desa sebagai upaya meningkatkan kualitas lingkungan, menyerap karbon, dan memperindah desa.</p>",
|
||||
"icon": "pohon"
|
||||
},
|
||||
{
|
||||
"id": "cmkmdp3zg0000vn8isspt2fh9",
|
||||
"name": "Komunitas Tanam Pohon",
|
||||
"judul": "Gerakan Komunitas Tanam Pohon",
|
||||
"deskripsi": "<p>Pelibatan warga desa dalam kegiatan rutin penanaman pohon di area perbukitan dan ruang terbuka hijau untuk meningkatkan kesadaran lingkungan dan mengurangi erosi.</p>",
|
||||
"icon": "pohon"
|
||||
},
|
||||
{
|
||||
"id": "cmkmdp3zg0000vn8isspu3gi0",
|
||||
"name": "Taman Hijau Bersama",
|
||||
"judul": "Pembangunan Taman Hijau Desa",
|
||||
"deskripsi": "<p>Pembangunan taman hijau di beberapa titik strategis desa, melibatkan banjar adat dan kelompok pemuda untuk menciptakan ruang publik yang nyaman dan ramah lingkungan.</p>",
|
||||
"icon": "pohon"
|
||||
}
|
||||
]
|
||||
@@ -1655,17 +1655,17 @@ model Pembiayaan {
|
||||
|
||||
// ========================================= MENU INOVASI ========================================= //
|
||||
// ========================================= DESA DIGITAL / SMART VILLAGE ========================================= //
|
||||
model DesaDigital {
|
||||
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 DesaDigital {
|
||||
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)
|
||||
}
|
||||
|
||||
// ========================================= PROGRAM KREATIF ========================================= //
|
||||
model ProgramKreatif {
|
||||
@@ -1719,19 +1719,19 @@ model InfoTekno {
|
||||
}
|
||||
|
||||
// ========================================= AJUKAN IDE INOVATIF ========================================= //
|
||||
model AjukanIdeInovatif {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
alamat String
|
||||
namaIde String
|
||||
deskripsi String @db.Text
|
||||
masalah String @db.Text
|
||||
benefit String @db.Text
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
model AjukanIdeInovatif {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
alamat String
|
||||
namaIde String
|
||||
deskripsi String @db.Text
|
||||
masalah String @db.Text
|
||||
benefit String @db.Text
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
// ========================================= LAYANAN ONLINE DESA ========================================= //
|
||||
model AdministrasiOnline {
|
||||
|
||||
575
prisma/seed.ts
575
prisma/seed.ts
@@ -63,6 +63,25 @@ import demografiPekerjaan from "./data/ekonomi/demografi-pekerjaan/demografi-pek
|
||||
import sektorUnggulanDesa from "./data/ekonomi/sektor-unggulan/sektor-unggulan.json";
|
||||
import programKemiskinan from "./data/ekonomi/program-kemiskinan/program-kemiskinan.json";
|
||||
import statistikKemiskinan from "./data/ekonomi/program-kemiskinan/statistik-kemiskinan.json";
|
||||
import grafikMenganggurBerdasarkanUsia from "./data/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran-berdasarkan-usia.json";
|
||||
import grafikMenganggurBerdasarkanPendidikan from "./data/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur/pengangguran-berdasarkan-pendidikan.json";
|
||||
import jumlahPendudukMiskin from "./data/ekonomi/jumlah-penduduk-miskin/jumlah-penduduk-miskin.json";
|
||||
import desaDigital from "./data/inovasi/desa-digital/desa-digital.json";
|
||||
import jenisLayanan from "./data/inovasi/layanan-online-desa/jenis-layanan.json";
|
||||
import jenisPengaduan from "./data/inovasi/layanan-online-desa/jenis-pengaduan.json";
|
||||
import administrasiOnline from "./data/inovasi/layanan-online-desa/administrasi-online.json";
|
||||
import pengaduanMasyarakat from "./data/inovasi/layanan-online-desa/pengaduan-masyarakat.json";
|
||||
import programKreatif from "./data/inovasi/program-kreatif-desa/program-kreatif-desa.json";
|
||||
import kolaborasiInovasi from "./data/inovasi/kolaborasi-inovasi/kolaborasi-inovasi.json";
|
||||
import mitraKolaborasi from "./data/inovasi/kolaborasi-inovasi/mitra-kolaborasi.json";
|
||||
import infoTeknologi from "./data/inovasi/info-teknologi/info-teknologi.json";
|
||||
import ajukanIde from "./data/inovasi/ajukan-ide/ajukan-ide.json";
|
||||
import pengelolaanSampah from "./data/lingkungan/pengelolaan-sampah/pengelolaan-sampah.json";
|
||||
import keteranganBankSampah from "./data/lingkungan/pengelolaan-sampah/keterangan-bank-sampah.json"
|
||||
import programPenghijauan from "./data/lingkungan/program-penghijauan/program-penghijauan.json"
|
||||
import dataLingkunganDesa from "./data/lingkungan/data-lingkungan-desa/data-lingkungan-desa.json";
|
||||
import kategoriGotongRoyong from "./data/lingkungan/gotong-royong/kategori-gotong-royong.json";
|
||||
import gotongRoyong from "./data/lingkungan/gotong-royong/gotong-royong.json"
|
||||
import berita from "./data/desa/berita/berita.json";
|
||||
import kategoriBerita from "./data/desa/berita/kategori-berita.json";
|
||||
import contohEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/contoh-kegiatan-di-desa-darmasaba.json";
|
||||
@@ -128,7 +147,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
category: f.category,
|
||||
deletedAt: null,
|
||||
isActive: true,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -150,7 +169,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
description: roleData.description,
|
||||
permissions: roleData.permissions || {}, // ✅ Include permissions
|
||||
isActive: roleData.isActive,
|
||||
}
|
||||
},
|
||||
);
|
||||
console.log(`✅ Seeded role -> ${roleData.name}`);
|
||||
} catch (error: any) {
|
||||
@@ -175,7 +194,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
|
||||
if (!roleExists) {
|
||||
console.error(
|
||||
`❌ Role with id ${u.roleId} not found for user ${u.username}`
|
||||
`❌ Role with id ${u.roleId} not found for user ${u.username}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -190,13 +209,13 @@ import resolveImageById from "./resolveImageByName";
|
||||
roleId: u.roleId.toString(),
|
||||
isActive: u.isActive,
|
||||
sessionInvalid: false,
|
||||
}
|
||||
},
|
||||
);
|
||||
console.log(`✅ Seeded user -> ${u.username}`);
|
||||
} catch (error: any) {
|
||||
if (error.code === "P2003") {
|
||||
console.error(
|
||||
`❌ Foreign key constraint failed for user ${u.username}: Role ${u.roleId} does not exist`
|
||||
`❌ Foreign key constraint failed for user ${u.username}: Role ${u.roleId} does not exist`,
|
||||
);
|
||||
} else {
|
||||
console.error(`❌ Failed to seed user ${u.username}:`, error.message);
|
||||
@@ -219,7 +238,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
|
||||
if (!imageExists) {
|
||||
console.warn(
|
||||
`⚠️ Image not found for PejabatDesa ${p.name}, skipping...`
|
||||
`⚠️ Image not found for PejabatDesa ${p.name}, skipping...`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -233,7 +252,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
name: p.name,
|
||||
position: p.position,
|
||||
imageId: p.imageId,
|
||||
}
|
||||
},
|
||||
);
|
||||
console.log(`✅ Seeded Pejabat Desa -> ${p.name}`);
|
||||
} catch (error: any) {
|
||||
@@ -264,7 +283,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${p.imageId} not found for ${p.name}`);
|
||||
@@ -311,7 +330,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${m.imageId} not found for ${m.name}`);
|
||||
@@ -393,7 +412,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${l.imageId} not found for ${l.name}`);
|
||||
@@ -512,7 +531,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
const parentExists = flattenedPosisi.some((pos) => pos.id === p.parentId);
|
||||
if (!parentExists) {
|
||||
console.warn(
|
||||
`⚠️ Parent tidak ditemukan: ${p.parentId} untuk ${p.nama}`
|
||||
`⚠️ Parent tidak ditemukan: ${p.parentId} untuk ${p.nama}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -550,12 +569,12 @@ import resolveImageById from "./resolveImageByName";
|
||||
} catch (error: any) {
|
||||
if (error.code === "P2002") {
|
||||
console.warn(
|
||||
`⚠️ Pegawai PPID with duplicate email (skipping): ${p.email}`
|
||||
`⚠️ Pegawai PPID with duplicate email (skipping): ${p.email}`,
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
`❌ Failed to seed pegawai PPID ${p.namaLengkap}:`,
|
||||
error.message
|
||||
error.message,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -804,7 +823,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${c.imageId} not found for ${c.biodata}`);
|
||||
@@ -853,7 +872,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${c.imageId} not found for ${c.nama}`);
|
||||
@@ -938,7 +957,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${p.imageId} not found for ${p.name}`);
|
||||
@@ -974,13 +993,16 @@ import resolveImageById from "./resolveImageByName";
|
||||
for (const k of kategoriBerita) {
|
||||
await prisma.kategoriBerita.upsert({
|
||||
where: {
|
||||
id: k.id,
|
||||
name: k.name, // ✅ cocok dengan @unique
|
||||
},
|
||||
update: {
|
||||
name: k.name,
|
||||
isActive: true,
|
||||
},
|
||||
create: {
|
||||
id: k.id, // ✅ id tetap bisa disimpan
|
||||
name: k.name,
|
||||
isActive: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1007,7 +1029,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${b.imageId} not found for ${b.judul}`);
|
||||
@@ -1046,7 +1068,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
{
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1230,7 +1252,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${p.imageId} not found for ${p.name}`);
|
||||
@@ -1281,7 +1303,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${p.imageId} not found for ${p.name}`);
|
||||
@@ -1375,7 +1397,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${p.imageId} not found for ${p.name}`);
|
||||
@@ -1425,7 +1447,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${p.imageId} not found for ${p.name}`);
|
||||
@@ -1473,7 +1495,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${p.imageId} not found for ${p.name}`);
|
||||
@@ -1519,7 +1541,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${p.imageId} not found for ${p.name}`);
|
||||
@@ -1567,7 +1589,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${p.imageId} not found for ${p.name}`);
|
||||
@@ -1616,7 +1638,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
if (fileRecord) {
|
||||
imageId = fileRecord.id;
|
||||
console.log(
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`
|
||||
`✅ Found file by ID: ${fileRecord.name} (${fileRecord.id})`,
|
||||
);
|
||||
} else {
|
||||
console.warn(`⚠️ File with ID ${k.imageId} not found for ${k.name}`);
|
||||
@@ -1642,6 +1664,24 @@ import resolveImageById from "./resolveImageByName";
|
||||
console.log("info wabah penyakit success ...");
|
||||
|
||||
// ==================== SUBMENU POLSEK TERDEKAT ================
|
||||
console.log("🔄 Seeding Layanan Polsek...");
|
||||
for (const k of layananPolsek) {
|
||||
await prisma.layananPolsek.upsert({
|
||||
where: {
|
||||
id: k.id,
|
||||
},
|
||||
update: {
|
||||
nama: k.nama,
|
||||
},
|
||||
create: {
|
||||
id: k.id,
|
||||
nama: k.nama,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("layanan polsek success ...");
|
||||
|
||||
console.log("🔄 Seeding Polsek Terdekat...");
|
||||
for (const k of polsekTerdekat) {
|
||||
await prisma.polsekTerdekat.upsert({
|
||||
@@ -1678,24 +1718,6 @@ import resolveImageById from "./resolveImageByName";
|
||||
|
||||
console.log("polsek terdekat success ...");
|
||||
|
||||
console.log("🔄 Seeding Layanan Polsek...");
|
||||
for (const k of layananPolsek) {
|
||||
await prisma.layananPolsek.upsert({
|
||||
where: {
|
||||
id: k.id,
|
||||
},
|
||||
update: {
|
||||
nama: k.nama,
|
||||
},
|
||||
create: {
|
||||
id: k.id,
|
||||
nama: k.nama,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("layanan polsek success ...");
|
||||
|
||||
console.log("🔄 Seeding Layanan To Polsek...");
|
||||
for (const k of layananToPolsek) {
|
||||
await prisma.layananToPolsek.upsert({
|
||||
@@ -1774,7 +1796,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
|
||||
if (!kontakDaruratExists) {
|
||||
console.warn(
|
||||
`⚠️ KontakDarurat ${f.kontakDaruratId} not found, skipping...`
|
||||
`⚠️ KontakDarurat ${f.kontakDaruratId} not found, skipping...`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -1993,7 +2015,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
|
||||
// ==================== SUBMENU STRUKTUR ORGANISASI DAN SK PENGURUS BUMDES ==========
|
||||
const sortedPosisiBumdes = flattenedPosisiBumdes.sort(
|
||||
(a, b) => a.hierarki - b.hierarki
|
||||
(a, b) => a.hierarki - b.hierarki,
|
||||
);
|
||||
|
||||
for (const p of sortedPosisiBumdes) {
|
||||
@@ -2003,7 +2025,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
const parentExists = flattenedPosisi.some((pos) => pos.id === p.parentId);
|
||||
if (!parentExists) {
|
||||
console.warn(
|
||||
`⚠️ Parent tidak ditemukan: ${p.parentId} untuk ${p.nama}`
|
||||
`⚠️ Parent tidak ditemukan: ${p.parentId} untuk ${p.nama}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -2074,21 +2096,82 @@ import resolveImageById from "./resolveImageByName";
|
||||
console.log("📊 detailDataPengangguran success ...");
|
||||
|
||||
// ==================== SUBMENU PENDUDUK USIA KERJA ==========
|
||||
for (const p of grafikMenganggurBerdasarkanUsia) {
|
||||
await prisma.grafikMenganggurBerdasarkanUsia.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
usia18_25: p.usia18_25,
|
||||
usia26_35: p.usia26_35,
|
||||
usia36_45: p.usia36_45,
|
||||
usia46_keatas: p.usia46_keatas,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
usia18_25: p.usia18_25,
|
||||
usia26_35: p.usia26_35,
|
||||
usia36_45: p.usia36_45,
|
||||
usia46_keatas: p.usia46_keatas,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("📊 grafikMenganggurBerdasarkanUsia success ...");
|
||||
|
||||
for (const p of grafikMenganggurBerdasarkanPendidikan) {
|
||||
await prisma.grafikMenganggurBerdasarkanPendidikan.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
SD: p.SD,
|
||||
SMP: p.SMP,
|
||||
SMA: p.SMA,
|
||||
D3: p.D3,
|
||||
S1: p.S1,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
SD: p.SD,
|
||||
SMP: p.SMP,
|
||||
SMA: p.SMA,
|
||||
D3: p.D3,
|
||||
S1: p.S1,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("📊 grafikMenganggurBerdasarkanUsia success ...");
|
||||
|
||||
// ==================== SUBMENU PENDUDUK MISKIN =============
|
||||
console.log("🔄 Seeding Jumlah Penduduk Miskin...");
|
||||
for (const k of jumlahPendudukMiskin) {
|
||||
await prisma.grafikJumlahPendudukMiskin.upsert({
|
||||
where: {
|
||||
id: k.id,
|
||||
},
|
||||
update: {
|
||||
year: k.year,
|
||||
totalPoorPopulation: k.totalPoorPopulation,
|
||||
},
|
||||
create: {
|
||||
id: k.id,
|
||||
year: k.year,
|
||||
totalPoorPopulation: k.totalPoorPopulation,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Jumlah Penduduk Miskin seeded successfully");
|
||||
|
||||
// ==================== SUBMENU PROGRAM KEMISKINAN =============
|
||||
for (const k of statistikKemiskinan) {
|
||||
await prisma.statistikKemiskinan.upsert({
|
||||
where: {
|
||||
id: k.id,
|
||||
tahun: k.tahun,
|
||||
},
|
||||
update: {
|
||||
tahun: k.tahun,
|
||||
jumlah: k.jumlah,
|
||||
},
|
||||
create: {
|
||||
id: k.id,
|
||||
tahun: k.tahun,
|
||||
jumlah: k.jumlah,
|
||||
},
|
||||
@@ -2163,14 +2246,340 @@ import resolveImageById from "./resolveImageByName";
|
||||
}
|
||||
console.log("✅ Demografi Pekerjaan seeded successfully");
|
||||
|
||||
// =========== KATEGORI GOTONG ROYONG ===========
|
||||
// Add IDs to the kategoriKegiatan data
|
||||
const kategoriKegiatan = kategoriKegiatanData.map((k, index) => ({
|
||||
...k,
|
||||
id: `kategori-${index + 1}`,
|
||||
}));
|
||||
// ====================== MENU INOVASI ==========================
|
||||
// ====================== SUBMENU AJUKAN IDE INOVATIF ===========
|
||||
console.log("🔄 Seeding Ajukan Ide Inovatif...");
|
||||
for (const d of ajukanIde) {
|
||||
await prisma.ajukanIdeInovatif.upsert({
|
||||
where: {
|
||||
id: d.id,
|
||||
},
|
||||
update: {
|
||||
name: d.name,
|
||||
alamat: d.alamat,
|
||||
namaIde: d.namaIde,
|
||||
deskripsi: d.deskripsi,
|
||||
masalah: d.masalah,
|
||||
benefit: d.benefit,
|
||||
},
|
||||
create: {
|
||||
id: d.id,
|
||||
name: d.name,
|
||||
alamat: d.alamat,
|
||||
namaIde: d.namaIde,
|
||||
deskripsi: d.deskripsi,
|
||||
masalah: d.masalah,
|
||||
benefit: d.benefit,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Ajukan Ide Inovatif seeded successfully");
|
||||
// ==================== SUBMENU DESA DIGITAL ====================
|
||||
console.log("🔄 Seeding Desa Digital...");
|
||||
for (const d of desaDigital) {
|
||||
await prisma.desaDigital.upsert({
|
||||
where: {
|
||||
id: d.id,
|
||||
},
|
||||
update: {
|
||||
name: d.name,
|
||||
deskripsi: d.deskripsi,
|
||||
imageId: d.imageId,
|
||||
},
|
||||
create: {
|
||||
id: d.id,
|
||||
name: d.name,
|
||||
deskripsi: d.deskripsi,
|
||||
imageId: d.imageId,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Desa Digital seeded successfully");
|
||||
|
||||
for (const k of kategoriKegiatan) {
|
||||
// ==================== SUBMENU LAYANAN ONLINE DESA ==========
|
||||
console.log("🔄 Seeding Jenis Layanan...");
|
||||
for (const j of jenisLayanan) {
|
||||
await prisma.jenisLayanan.upsert({
|
||||
where: {
|
||||
id: j.id,
|
||||
},
|
||||
update: {
|
||||
nama: j.nama,
|
||||
deskripsi: j.deskripsi,
|
||||
},
|
||||
create: {
|
||||
id: j.id,
|
||||
nama: j.nama,
|
||||
deskripsi: j.deskripsi,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Jenis Layanan seeded successfully");
|
||||
|
||||
console.log("🔄 Seeding Administrasi Online...");
|
||||
for (const d of administrasiOnline) {
|
||||
await prisma.administrasiOnline.upsert({
|
||||
where: {
|
||||
id: d.id,
|
||||
},
|
||||
update: {
|
||||
name: d.name,
|
||||
alamat: d.alamat,
|
||||
nomorTelepon: d.nomorTelepon,
|
||||
jenisLayananId: d.jenisLayananId,
|
||||
},
|
||||
create: {
|
||||
id: d.id,
|
||||
name: d.name,
|
||||
alamat: d.alamat,
|
||||
nomorTelepon: d.nomorTelepon,
|
||||
jenisLayananId: d.jenisLayananId,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Administrasi Online seeded successfully");
|
||||
|
||||
console.log("🔄 Seeding Jenis Pengaduan Masyarakat...");
|
||||
for (const d of jenisPengaduan) {
|
||||
await prisma.jenisPengaduan.upsert({
|
||||
where: {
|
||||
id: d.id,
|
||||
},
|
||||
update: {
|
||||
nama: d.nama,
|
||||
},
|
||||
create: {
|
||||
id: d.id,
|
||||
nama: d.nama,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Jenis Pengaduan Masyarakat seeded successfully");
|
||||
|
||||
console.log("🔄 Seeding Pengaduan Masyarakat...");
|
||||
for (const d of pengaduanMasyarakat) {
|
||||
await prisma.pengaduanMasyarakat.upsert({
|
||||
where: {
|
||||
id: d.id,
|
||||
},
|
||||
update: {
|
||||
name: d.name,
|
||||
email: d.email,
|
||||
nik: d.nik,
|
||||
nomorTelepon: d.nomorTelepon,
|
||||
judulPengaduan: d.judulPengaduan,
|
||||
lokasiKejadian: d.lokasiKejadian,
|
||||
imageId: d.imageId,
|
||||
deskripsiPengaduan: d.deskripsiPengaduan,
|
||||
jenisPengaduanId: d.jenisPengaduanId,
|
||||
},
|
||||
create: {
|
||||
id: d.id,
|
||||
name: d.name,
|
||||
email: d.email,
|
||||
nik: d.nik,
|
||||
nomorTelepon: d.nomorTelepon,
|
||||
judulPengaduan: d.judulPengaduan,
|
||||
lokasiKejadian: d.lokasiKejadian,
|
||||
imageId: d.imageId,
|
||||
deskripsiPengaduan: d.deskripsiPengaduan,
|
||||
jenisPengaduanId: d.jenisPengaduanId,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Pengaduan Masyarakat seeded successfully");
|
||||
|
||||
// ==================== SUBMENU PROGRAM KREATIF ==========
|
||||
console.log("🔄 Seeding Program Kreatif...");
|
||||
for (const p of programKreatif) {
|
||||
await prisma.programKreatif.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
name: p.name,
|
||||
deskripsi: p.deskripsi,
|
||||
icon: p.icon,
|
||||
slug: p.slug,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
deskripsi: p.deskripsi,
|
||||
icon: p.icon,
|
||||
slug: p.slug,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Program Kreatif seeded successfully");
|
||||
|
||||
// ==================== SUBMENU KOLABORASI INOVASI ==========
|
||||
console.log("🔄 Seeding Kolaborasi Inovasi...");
|
||||
for (const p of kolaborasiInovasi) {
|
||||
await prisma.kolaborasiInovasi.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
name: p.name,
|
||||
tahun: p.tahun,
|
||||
slug: p.slug,
|
||||
deskripsi: p.deskripsi,
|
||||
kolaborator: p.kolaborator,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
tahun: p.tahun,
|
||||
slug: p.slug,
|
||||
deskripsi: p.deskripsi,
|
||||
kolaborator: p.kolaborator,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Kolaborasi Inovasi seeded successfully");
|
||||
|
||||
console.log("🔄 Seeding Mitra Kolaborasi...");
|
||||
for (const p of mitraKolaborasi) {
|
||||
await prisma.mitraKolaborasi.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
name: p.name,
|
||||
imageId: p.imageId,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
imageId: p.imageId,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Mitra Kolaborasi seeded successfully");
|
||||
|
||||
// ==================== SUBMENU INFO TEKNOLOGI TEPAT GUNA ==========
|
||||
console.log("🔄 Seeding Info Teknologi...");
|
||||
for (const p of infoTeknologi) {
|
||||
await prisma.infoTekno.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
name: p.name,
|
||||
deskripsi: p.deskripsi,
|
||||
imageId: p.imageId,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
deskripsi: p.deskripsi,
|
||||
imageId: p.imageId,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Info Teknologi seeded successfully");
|
||||
|
||||
// ====================== MENU LINGKUNGAN ==========================
|
||||
// ==================== SUBMENU PENGELOLAAN SAMPAH ==========
|
||||
console.log("🔄 Seeding Pengelolaan Sampah...");
|
||||
for (const p of pengelolaanSampah) {
|
||||
await prisma.pengelolaanSampah.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
name: p.name,
|
||||
icon: p.icon
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
icon: p.icon
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Pengelolaan Sampah seeded successfully");
|
||||
|
||||
console.log("🔄 Seeding Keterangan Bank Sampah...");
|
||||
for (const p of keteranganBankSampah) {
|
||||
await prisma.keteranganBankSampahTerdekat.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
name: p.name,
|
||||
alamat: p.alamat,
|
||||
namaTempatMaps: p.namaTempatMaps,
|
||||
linkPetunjukArah: p.linkPetunjukArah,
|
||||
lat: p.lat,
|
||||
lng: p.lng
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
alamat: p.alamat,
|
||||
namaTempatMaps: p.namaTempatMaps,
|
||||
linkPetunjukArah: p.linkPetunjukArah,
|
||||
lat: p.lat,
|
||||
lng: p.lng
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Keterangan Bank Sampah seeded successfully");
|
||||
|
||||
// ==================== SUBMENU PROGRAM PENGHIJAUAN ==========
|
||||
console.log("🔄 Seeding Program Penghijauan...");
|
||||
for (const p of programPenghijauan) {
|
||||
await prisma.programPenghijauan.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
name: p.name,
|
||||
judul: p.judul,
|
||||
deskripsi: p.deskripsi,
|
||||
icon: p.icon
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
judul: p.judul,
|
||||
deskripsi: p.deskripsi,
|
||||
icon: p.icon
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Program Penghijauan seeded successfully");
|
||||
|
||||
// ==================== SUBMENU DATA LINGKUNGAN DESA ==========
|
||||
console.log("🔄 Seeding Data Lingkungan Desa...");
|
||||
for (const p of dataLingkunganDesa) {
|
||||
await prisma.dataLingkunganDesa.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
name: p.name,
|
||||
jumlah: p.jumlah,
|
||||
deskripsi: p.deskripsi,
|
||||
icon: p.icon
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
jumlah: p.jumlah,
|
||||
deskripsi: p.deskripsi,
|
||||
icon: p.icon
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Data Lingkungan Desa seeded successfully");
|
||||
|
||||
// =========== SUBMENU GOTONG ROYONG ===========
|
||||
console.log("🔄 Seeding Kategori Gotong Royong...");
|
||||
|
||||
for (const k of kategoriGotongRoyong) {
|
||||
await prisma.kategoriKegiatan.upsert({
|
||||
where: {
|
||||
id: k.id,
|
||||
@@ -2185,8 +2594,44 @@ import resolveImageById from "./resolveImageByName";
|
||||
});
|
||||
}
|
||||
|
||||
console.log("kategori kegiatan success ...");
|
||||
console.log("✅ Kategori Gotong Royong seeded successfully");
|
||||
|
||||
console.log("🔄 Seeding Gotong Royong...");
|
||||
|
||||
for (const k of gotongRoyong) {
|
||||
await prisma.kegiatanDesa.upsert({
|
||||
where: {
|
||||
id: k.id,
|
||||
},
|
||||
update: {
|
||||
judul: k.judul,
|
||||
deskripsiSingkat: k.deskripsiSingkat,
|
||||
deskripsiLengkap: k.deskripsiLengkap,
|
||||
tanggal: k.tanggal,
|
||||
lokasi: k.lokasi,
|
||||
partisipan: k.partisipan,
|
||||
imageId: k.imageId,
|
||||
kategoriKegiatanId: k.kategoriKegiatanId,
|
||||
},
|
||||
create: {
|
||||
id: k.id,
|
||||
judul: k.judul,
|
||||
deskripsiSingkat: k.deskripsiSingkat,
|
||||
deskripsiLengkap: k.deskripsiLengkap,
|
||||
tanggal: k.tanggal,
|
||||
lokasi: k.lokasi,
|
||||
partisipan: k.partisipan,
|
||||
imageId: k.imageId,
|
||||
kategoriKegiatanId: k.kategoriKegiatanId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("✅ Kategori Gotong Royong seeded successfully");
|
||||
|
||||
|
||||
|
||||
|
||||
for (const e of tujuanEdukasiLingkungan) {
|
||||
await prisma.tujuanEdukasiLingkungan.upsert({
|
||||
where: {
|
||||
@@ -2348,7 +2793,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
});
|
||||
}
|
||||
console.log(
|
||||
"✅ tujuan bimbingan belajar desa seeded (editable later via UI)"
|
||||
"✅ tujuan bimbingan belajar desa seeded (editable later via UI)",
|
||||
);
|
||||
|
||||
for (const t of lokasiJadwalBimbinganBelajarDesa) {
|
||||
@@ -2366,7 +2811,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
});
|
||||
}
|
||||
console.log(
|
||||
"✅ lokasi jadwal bimbingan belajar desa seeded (editable later via UI)"
|
||||
"✅ lokasi jadwal bimbingan belajar desa seeded (editable later via UI)",
|
||||
);
|
||||
|
||||
for (const t of fasilitasBimbinganBelajarDesa) {
|
||||
@@ -2384,7 +2829,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
});
|
||||
}
|
||||
console.log(
|
||||
"✅ fasilitas bimbingan belajar desa seeded (editable later via UI)"
|
||||
"✅ fasilitas bimbingan belajar desa seeded (editable later via UI)",
|
||||
);
|
||||
|
||||
for (const t of tujuanProgram2) {
|
||||
@@ -2402,7 +2847,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
});
|
||||
}
|
||||
console.log(
|
||||
"✅ fasilitas bimbingan belajar desa seeded (editable later via UI)"
|
||||
"✅ fasilitas bimbingan belajar desa seeded (editable later via UI)",
|
||||
);
|
||||
|
||||
for (const t of tempatKegiatan) {
|
||||
@@ -2420,7 +2865,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
});
|
||||
}
|
||||
console.log(
|
||||
"✅ fasilitas bimbingan belajar desa seeded (editable later via UI)"
|
||||
"✅ fasilitas bimbingan belajar desa seeded (editable later via UI)",
|
||||
);
|
||||
|
||||
for (const t of jenisProgramYangDiselenggarakan) {
|
||||
@@ -2438,7 +2883,7 @@ import resolveImageById from "./resolveImageByName";
|
||||
});
|
||||
}
|
||||
console.log(
|
||||
"✅ fasilitas bimbingan belajar desa seeded (editable later via UI)"
|
||||
"✅ fasilitas bimbingan belajar desa seeded (editable later via UI)",
|
||||
);
|
||||
|
||||
for (const j of jenjangPendidikan) {
|
||||
|
||||
@@ -1,27 +1,222 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
// /* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
// // prisma/seedAssets.ts
|
||||
// import prisma from "@/lib/prisma";
|
||||
// import AdmZip from "adm-zip";
|
||||
// import fs from "fs/promises";
|
||||
// import path from "path";
|
||||
// import sharp from "sharp";
|
||||
// import fetchWithRetry from "./data/fetchWithRetry";
|
||||
|
||||
// const UPLOADS_DIR = path.resolve(
|
||||
// process.env.WIBU_UPLOAD_DIR || "uploads"
|
||||
// );
|
||||
|
||||
// // --- Helper: deteksi kategori file ---
|
||||
// function detectCategory(filename: string): "image" | "document" | "other" {
|
||||
// const ext = path.extname(filename).toLowerCase();
|
||||
// if ([".jpg", ".jpeg", ".png", ".webp"].includes(ext)) return "image";
|
||||
// if ([".pdf", ".doc", ".docx"].includes(ext)) return "document";
|
||||
// return "other";
|
||||
// }
|
||||
|
||||
// // --- Helper: recursive walk dir ---
|
||||
// async function walkDir(
|
||||
// dir: string,
|
||||
// fileList: string[] = []
|
||||
// ): Promise<string[]> {
|
||||
// const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||
|
||||
// for (const entry of entries) {
|
||||
// const fullPath = path.join(dir, entry.name);
|
||||
|
||||
// if (entry.isDirectory()) {
|
||||
// if (entry.name === "__MACOSX") continue; // skip folder sampah
|
||||
// await walkDir(fullPath, fileList);
|
||||
// } else {
|
||||
// if (entry.name.startsWith(".") || entry.name === ".DS_Store") continue; // skip file sampah
|
||||
// fileList.push(fullPath);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return fileList;
|
||||
// }
|
||||
|
||||
// export default async function seedAssets() {
|
||||
// console.log("🚀 Seeding assets...");
|
||||
// console.log("📁 Upload dir:", UPLOADS_DIR);
|
||||
|
||||
// await fs.mkdir(UPLOADS_DIR, { recursive: true });
|
||||
|
||||
// // 1. Download zip
|
||||
// const url =
|
||||
// "https://cld-dkr-makuro-seafile.wibudev.com/f/eadd52c5bd654ec789a3/?dl=1";
|
||||
// const res = await fetchWithRetry(url, 3, 20000);
|
||||
|
||||
// // Validasi content-type
|
||||
// const contentType = res.headers.get("content-type");
|
||||
// if (!contentType?.includes("zip")) {
|
||||
// throw new Error(`Invalid content-type (${contentType}). Expected ZIP file`);
|
||||
// }
|
||||
|
||||
// const buffer = Buffer.from(await res.arrayBuffer());
|
||||
|
||||
// // Validasi ukuran file
|
||||
// if (buffer.length < 100) {
|
||||
// throw new Error("Downloaded ZIP is empty or corrupted");
|
||||
// }
|
||||
|
||||
// // Validasi signature ZIP ("PK")
|
||||
// if (buffer.toString("utf8", 0, 2) !== "PK") {
|
||||
// throw new Error("Invalid ZIP signature (PK not found)");
|
||||
// }
|
||||
|
||||
// // 2. Extract zip ke folder tmp
|
||||
// const extractDir = path.join(process.cwd(), "tmp_assets");
|
||||
// await fs.rm(extractDir, { recursive: true, force: true });
|
||||
// await fs.mkdir(extractDir, { recursive: true });
|
||||
|
||||
// let zip: AdmZip;
|
||||
|
||||
// try {
|
||||
// zip = new AdmZip(buffer);
|
||||
// } catch (err) {
|
||||
// throw new Error("Failed to parse ZIP file (corrupted or invalid)");
|
||||
// }
|
||||
|
||||
// try {
|
||||
// zip.extractAllTo(extractDir, true);
|
||||
// } catch (err) {
|
||||
// throw new Error("Failed to extract ZIP contents");
|
||||
// }
|
||||
|
||||
// // 3. Cari semua file valid (recursive)
|
||||
// const files = await walkDir(extractDir);
|
||||
|
||||
// // 4. Loop tiap file & simpan
|
||||
// for (const filePath of files) {
|
||||
// const entryName = path.basename(filePath);
|
||||
// const category = detectCategory(entryName);
|
||||
|
||||
// let finalName = entryName;
|
||||
// let mimeType = "application/octet-stream";
|
||||
// let targetPath = "";
|
||||
|
||||
// if (category === "image") {
|
||||
// const fileBaseName = path.parse(entryName).name;
|
||||
// finalName = `${fileBaseName}.webp`;
|
||||
// targetPath = path.join(UPLOADS_DIR, "images", finalName);
|
||||
// await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
||||
// await sharp(filePath).webp({ quality: 80 }).toFile(targetPath);
|
||||
// mimeType = "image/webp";
|
||||
// } else if (category === "document") {
|
||||
// targetPath = path.join(UPLOADS_DIR, "documents", entryName);
|
||||
// await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
||||
// await fs.copyFile(filePath, targetPath);
|
||||
// mimeType = "application/pdf";
|
||||
// } else {
|
||||
// targetPath = path.join(UPLOADS_DIR, "other", entryName);
|
||||
// await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
||||
// await fs.copyFile(filePath, targetPath);
|
||||
// }
|
||||
|
||||
// const existing = await prisma.fileStorage.findUnique({
|
||||
// where: { name: finalName },
|
||||
// });
|
||||
|
||||
// if (existing) {
|
||||
// // Restore kalau soft deleted
|
||||
// await prisma.fileStorage.update({
|
||||
// where: { name: finalName },
|
||||
// data: {
|
||||
// path: targetPath,
|
||||
// realName: entryName,
|
||||
// mimeType,
|
||||
// link: `/uploads/${category}/${finalName}`,
|
||||
// category,
|
||||
// deletedAt: null,
|
||||
// isActive: true,
|
||||
// },
|
||||
// });
|
||||
|
||||
// console.log(`♻️ restored: ${category}/${finalName}`);
|
||||
// } else {
|
||||
// await prisma.fileStorage.create({
|
||||
// data: {
|
||||
// name: finalName,
|
||||
// realName: entryName,
|
||||
// path: targetPath,
|
||||
// mimeType,
|
||||
// link: `/uploads/${category}/${finalName}`,
|
||||
// category,
|
||||
// },
|
||||
// });
|
||||
|
||||
// console.log(`📂 created: ${category}/${finalName}`);
|
||||
// }
|
||||
|
||||
// console.log(`📂 saved: ${category}/${finalName}`);
|
||||
// }
|
||||
|
||||
// // 6. Cleanup
|
||||
// await fs.rm(extractDir, { recursive: true, force: true });
|
||||
|
||||
// console.log("✅ Selesai seed assets!");
|
||||
// console.log("DB URL (asset):", process.env.DATABASE_URL);
|
||||
|
||||
// }
|
||||
|
||||
// // --- Auto run kalau dipanggil langsung ---
|
||||
// if (import.meta.main) {
|
||||
// seedAssets()
|
||||
// .catch((err) => {
|
||||
// console.error("❌ Error seeding assets:", err);
|
||||
// process.exit(1);
|
||||
// })
|
||||
// .finally(async () => {
|
||||
// await prisma.$disconnect();
|
||||
// });
|
||||
// }
|
||||
|
||||
|
||||
// prisma/seedAssets.ts
|
||||
import prisma from "@/lib/prisma";
|
||||
import AdmZip from "adm-zip";
|
||||
import fs from "fs/promises";
|
||||
import path from "path";
|
||||
import sharp from "sharp";
|
||||
import mime from "mime-types";
|
||||
import fetchWithRetry from "./data/fetchWithRetry";
|
||||
|
||||
const UPLOADS_DIR =
|
||||
process.env.WIBU_UPLOAD_DIR || path.join(process.cwd(), "uploads");
|
||||
/* =========================
|
||||
* CONFIG
|
||||
* ========================= */
|
||||
const UPLOADS_DIR = path.resolve(
|
||||
process.env.WIBU_UPLOAD_DIR || "uploads"
|
||||
);
|
||||
|
||||
// --- Helper: deteksi kategori file ---
|
||||
function detectCategory(filename: string): "image" | "document" | "other" {
|
||||
const TMP_DIR = path.join(process.cwd(), "tmp_assets");
|
||||
|
||||
const CATEGORY_DIR: Record<FileCategory, string> = {
|
||||
image: "images",
|
||||
document: "documents",
|
||||
other: "other",
|
||||
};
|
||||
|
||||
type FileCategory = "image" | "document" | "other";
|
||||
|
||||
/* =========================
|
||||
* HELPERS
|
||||
* ========================= */
|
||||
function detectCategory(filename: string): FileCategory {
|
||||
const ext = path.extname(filename).toLowerCase();
|
||||
if ([".jpg", ".jpeg", ".png", ".webp"].includes(ext)) return "image";
|
||||
if ([".pdf", ".doc", ".docx"].includes(ext)) return "document";
|
||||
if ([".pdf", ".doc", ".docx", ".txt"].includes(ext)) return "document";
|
||||
return "other";
|
||||
}
|
||||
|
||||
// --- Helper: recursive walk dir ---
|
||||
async function walkDir(
|
||||
dir: string,
|
||||
fileList: string[] = []
|
||||
result: string[] = []
|
||||
): Promise<string[]> {
|
||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||
|
||||
@@ -29,139 +224,139 @@ async function walkDir(
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
if (entry.name === "__MACOSX") continue; // skip folder sampah
|
||||
await walkDir(fullPath, fileList);
|
||||
if (entry.name === "__MACOSX") continue;
|
||||
await walkDir(fullPath, result);
|
||||
} else {
|
||||
if (entry.name.startsWith(".") || entry.name === ".DS_Store") continue; // skip file sampah
|
||||
fileList.push(fullPath);
|
||||
if (entry.name.startsWith(".") || entry.name === ".DS_Store") continue;
|
||||
result.push(fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
return fileList;
|
||||
return result;
|
||||
}
|
||||
|
||||
async function ensureDir(dir: string) {
|
||||
await fs.mkdir(dir, { recursive: true });
|
||||
}
|
||||
|
||||
/* =========================
|
||||
* FILE PROCESSORS
|
||||
* ========================= */
|
||||
async function processImage(filePath: string, entryName: string) {
|
||||
const baseName = path.parse(entryName).name;
|
||||
const finalName = `${baseName}.webp`;
|
||||
const targetDir = path.join(UPLOADS_DIR, CATEGORY_DIR.image);
|
||||
const targetPath = path.join(targetDir, finalName);
|
||||
|
||||
await ensureDir(targetDir);
|
||||
await sharp(filePath).webp({ quality: 80 }).toFile(targetPath);
|
||||
|
||||
return {
|
||||
finalName,
|
||||
targetPath,
|
||||
mimeType: "image/webp",
|
||||
};
|
||||
}
|
||||
|
||||
async function processNonImage(
|
||||
filePath: string,
|
||||
entryName: string,
|
||||
category: FileCategory
|
||||
) {
|
||||
const targetDir = path.join(UPLOADS_DIR, CATEGORY_DIR[category]);
|
||||
const targetPath = path.join(targetDir, entryName);
|
||||
|
||||
await ensureDir(targetDir);
|
||||
await fs.copyFile(filePath, targetPath);
|
||||
|
||||
return {
|
||||
finalName: entryName,
|
||||
targetPath,
|
||||
mimeType: mime.lookup(entryName) || "application/octet-stream",
|
||||
};
|
||||
}
|
||||
|
||||
/* =========================
|
||||
* MAIN
|
||||
* ========================= */
|
||||
export default async function seedAssets() {
|
||||
console.log("🚀 Seeding assets...");
|
||||
console.log("📁 Upload dir:", UPLOADS_DIR);
|
||||
|
||||
// 1. Download zip
|
||||
await ensureDir(UPLOADS_DIR);
|
||||
|
||||
/* ===== Download ZIP ===== */
|
||||
const url =
|
||||
"https://cld-dkr-makuro-seafile.wibudev.com/f/88293b915cf34b939819/?dl=1";
|
||||
"https://cld-dkr-makuro-seafile.wibudev.com/f/eadd52c5bd654ec789a3/?dl=1";
|
||||
const res = await fetchWithRetry(url, 3, 20000);
|
||||
|
||||
// Validasi content-type
|
||||
const contentType = res.headers.get("content-type");
|
||||
if (!contentType?.includes("zip")) {
|
||||
throw new Error(`Invalid content-type (${contentType}). Expected ZIP file`);
|
||||
if (!res.headers.get("content-type")?.includes("zip")) {
|
||||
throw new Error("Invalid ZIP content-type");
|
||||
}
|
||||
|
||||
const buffer = Buffer.from(await res.arrayBuffer());
|
||||
|
||||
// Validasi ukuran file
|
||||
if (buffer.length < 100) {
|
||||
throw new Error("Downloaded ZIP is empty or corrupted");
|
||||
if (buffer.length < 100 || buffer.toString("utf8", 0, 2) !== "PK") {
|
||||
throw new Error("Corrupted ZIP file");
|
||||
}
|
||||
|
||||
// Validasi signature ZIP ("PK")
|
||||
if (buffer.toString("utf8", 0, 2) !== "PK") {
|
||||
throw new Error("Invalid ZIP signature (PK not found)");
|
||||
}
|
||||
/* ===== Extract ===== */
|
||||
await fs.rm(TMP_DIR, { recursive: true, force: true });
|
||||
await ensureDir(TMP_DIR);
|
||||
|
||||
// 2. Extract zip ke folder tmp
|
||||
const extractDir = path.join(process.cwd(), "tmp_assets");
|
||||
await fs.rm(extractDir, { recursive: true, force: true });
|
||||
await fs.mkdir(extractDir, { recursive: true });
|
||||
const zip = new AdmZip(buffer);
|
||||
zip.extractAllTo(TMP_DIR, true);
|
||||
|
||||
let zip: AdmZip;
|
||||
/* ===== Process Files ===== */
|
||||
const files = await walkDir(TMP_DIR);
|
||||
|
||||
try {
|
||||
zip = new AdmZip(buffer);
|
||||
} catch (err) {
|
||||
throw new Error("Failed to parse ZIP file (corrupted or invalid)");
|
||||
}
|
||||
|
||||
try {
|
||||
zip.extractAllTo(extractDir, true);
|
||||
} catch (err) {
|
||||
throw new Error("Failed to extract ZIP contents");
|
||||
}
|
||||
|
||||
// 3. Cari semua file valid (recursive)
|
||||
const files = await walkDir(extractDir);
|
||||
|
||||
// 4. Loop tiap file & simpan
|
||||
for (const filePath of files) {
|
||||
const entryName = path.basename(filePath);
|
||||
const category = detectCategory(entryName);
|
||||
|
||||
let finalName = entryName;
|
||||
let mimeType = "application/octet-stream";
|
||||
let targetPath = "";
|
||||
let result;
|
||||
|
||||
if (category === "image") {
|
||||
const fileBaseName = path.parse(entryName).name;
|
||||
finalName = `${fileBaseName}.webp`;
|
||||
targetPath = path.join(UPLOADS_DIR, "images", finalName);
|
||||
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
||||
await sharp(filePath).webp({ quality: 80 }).toFile(targetPath);
|
||||
mimeType = "image/webp";
|
||||
} else if (category === "document") {
|
||||
targetPath = path.join(UPLOADS_DIR, "documents", entryName);
|
||||
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
||||
await fs.copyFile(filePath, targetPath);
|
||||
mimeType = "application/pdf";
|
||||
result = await processImage(filePath, entryName);
|
||||
} else {
|
||||
targetPath = path.join(UPLOADS_DIR, "other", entryName);
|
||||
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
||||
await fs.copyFile(filePath, targetPath);
|
||||
result = await processNonImage(filePath, entryName, category);
|
||||
}
|
||||
|
||||
const { finalName, targetPath, mimeType } = result;
|
||||
|
||||
const existing = await prisma.fileStorage.findUnique({
|
||||
where: { name: finalName },
|
||||
});
|
||||
|
||||
const data = {
|
||||
name: finalName,
|
||||
realName: entryName,
|
||||
path: targetPath,
|
||||
mimeType,
|
||||
link: `/uploads/${CATEGORY_DIR[category]}/${finalName}`,
|
||||
category,
|
||||
deletedAt: null,
|
||||
isActive: true,
|
||||
};
|
||||
|
||||
if (existing) {
|
||||
// Restore kalau soft deleted
|
||||
await prisma.fileStorage.update({
|
||||
where: { name: finalName },
|
||||
data: {
|
||||
path: targetPath,
|
||||
realName: entryName,
|
||||
mimeType,
|
||||
link: `/uploads/${category}/${finalName}`,
|
||||
category,
|
||||
deletedAt: null,
|
||||
isActive: true,
|
||||
},
|
||||
data,
|
||||
});
|
||||
|
||||
console.log(`♻️ restored: ${category}/${finalName}`);
|
||||
} else {
|
||||
await prisma.fileStorage.create({
|
||||
data: {
|
||||
name: finalName,
|
||||
realName: entryName,
|
||||
path: targetPath,
|
||||
mimeType,
|
||||
link: `/uploads/${category}/${finalName}`,
|
||||
category,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.fileStorage.create({ data });
|
||||
console.log(`📂 created: ${category}/${finalName}`);
|
||||
}
|
||||
|
||||
console.log(`📂 saved: ${category}/${finalName}`);
|
||||
}
|
||||
|
||||
// 6. Cleanup
|
||||
await fs.rm(extractDir, { recursive: true, force: true });
|
||||
/* ===== Cleanup ===== */
|
||||
await fs.rm(TMP_DIR, { recursive: true, force: true });
|
||||
|
||||
console.log("✅ Selesai seed assets!");
|
||||
console.log("DB URL (asset):", process.env.DATABASE_URL);
|
||||
|
||||
}
|
||||
|
||||
// --- Auto run kalau dipanggil langsung ---
|
||||
/* ===== Auto Run ===== */
|
||||
if (import.meta.main) {
|
||||
seedAssets()
|
||||
.catch((err) => {
|
||||
|
||||
@@ -41,6 +41,7 @@ import {
|
||||
IconMessageReport,
|
||||
IconUsers,
|
||||
IconQuestionMark,
|
||||
IconBook,
|
||||
} from '@tabler/icons-react'
|
||||
|
||||
/* =======================
|
||||
@@ -90,6 +91,7 @@ export type IconKey =
|
||||
| 'informasi'
|
||||
| 'pengaduan'
|
||||
| 'layananPublik'
|
||||
| 'book'
|
||||
|
||||
/* =======================
|
||||
Icon Map
|
||||
@@ -138,6 +140,7 @@ const iconMap: Record<IconKey, React.FC<any>> = {
|
||||
informasi: IconInfoCircle,
|
||||
pengaduan: IconMessageReport,
|
||||
layananPublik: IconUsers,
|
||||
book: IconBook
|
||||
}
|
||||
|
||||
/* =======================
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Box, rem, Select } from '@mantine/core';
|
||||
import {
|
||||
IconAlertTriangle,
|
||||
IconAmbulance,
|
||||
IconBook,
|
||||
IconBuilding,
|
||||
IconBuildingCommunity,
|
||||
IconCash,
|
||||
@@ -85,6 +86,7 @@ const iconMap = {
|
||||
informasi: { label: 'Informasi', icon: IconInfoCircle },
|
||||
pengaduan: { label: 'Pengaduan', icon: IconMessageReport },
|
||||
layananPublik: { label: 'Layanan Publik', icon: IconUsers },
|
||||
book: { label: 'Buku', icon: IconBook }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
IconShield,
|
||||
IconStethoscope,
|
||||
IconUsers,
|
||||
IconBook,
|
||||
} from '@tabler/icons-react';
|
||||
|
||||
const iconMap = {
|
||||
@@ -83,6 +84,7 @@ const iconMap = {
|
||||
informasi: { label: 'Informasi', icon: IconInfoCircle },
|
||||
pengaduan: { label: 'Pengaduan', icon: IconMessageReport },
|
||||
layananPublik: { label: 'Layanan Publik', icon: IconUsers },
|
||||
book: { label: 'Buku', icon: IconBook }
|
||||
};
|
||||
|
||||
export type IconKey = keyof typeof iconMap;
|
||||
|
||||
@@ -222,7 +222,6 @@ function ListKategoriBerita({ search }: { search: string }) {
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center mt={{ base: 'lg', md: 'xl' }}>
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -235,7 +234,6 @@ function ListKategoriBerita({ search }: { search: string }) {
|
||||
radius="md"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
|
||||
{/* Modal Konfirmasi Hapus */}
|
||||
<ModalKonfirmasiHapus
|
||||
|
||||
@@ -186,7 +186,6 @@ function ListAjukanPermohonan({ search }: { search: string }) {
|
||||
</Box>
|
||||
</Paper>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center mt="md">
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -199,7 +198,6 @@ function ListAjukanPermohonan({ search }: { search: string }) {
|
||||
radius="md"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -267,8 +267,6 @@ function ListPendapatan({ search }: { search: string }) {
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
{/* Pagination */}
|
||||
{totalPages > 1 && (
|
||||
<Center mt={{ base: 'sm', md: 'md' }} mb={{ base: 'sm', md: 'md' }}>
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -282,7 +280,6 @@ function ListPendapatan({ search }: { search: string }) {
|
||||
size="sm"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
|
||||
{/* Modal Konfirmasi Hapus */}
|
||||
<ModalKonfirmasiHapus
|
||||
|
||||
@@ -284,7 +284,6 @@ function ListPosisiOrganisasiBumDes({ search }: { search: string }) {
|
||||
</Box>
|
||||
</Paper>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -299,7 +298,6 @@ function ListPosisiOrganisasiBumDes({ search }: { search: string }) {
|
||||
radius="md"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
|
||||
{/* Modal Hapus */}
|
||||
<ModalKonfirmasiHapus
|
||||
|
||||
@@ -224,7 +224,6 @@ function ListDetailDataPengangguran({ search }: { search: string }) {
|
||||
</Paper>
|
||||
|
||||
{/* Pagination */}
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -239,7 +238,6 @@ function ListDetailDataPengangguran({ search }: { search: string }) {
|
||||
radius="md"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
|
||||
{/* Chart Section */}
|
||||
<Paper withBorder bg={colors['white-1']} p={{ base: 'sm', md: 'lg' }} shadow="md" radius="md">
|
||||
|
||||
@@ -84,6 +84,13 @@ function CreateProgramKreatifDesa() {
|
||||
required
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
label={<Text fz="sm" fw="bold">Deskripsi Singkat</Text>}
|
||||
placeholder="Masukkan deskripsi singkat"
|
||||
value={stateCreate.create.form.slug || ''}
|
||||
onChange={(e) => stateCreate.create.form.slug = e.currentTarget.value}
|
||||
/>
|
||||
|
||||
<YearPickerInput
|
||||
clearable
|
||||
value={stateCreate.create.form.tahun ? new Date(stateCreate.create.form.tahun, 0, 1) : null}
|
||||
@@ -95,6 +102,13 @@ function CreateProgramKreatifDesa() {
|
||||
}}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
label={<Text fz="sm" fw="bold">Kolaborator</Text>}
|
||||
placeholder="Masukkan kolaborator"
|
||||
value={stateCreate.create.form.kolaborator || ''}
|
||||
onChange={(e) => stateCreate.create.form.kolaborator = e.currentTarget.value}
|
||||
/>
|
||||
|
||||
<Box>
|
||||
<Text fw="bold" fz="sm" mb={6}>
|
||||
Deskripsi
|
||||
@@ -103,14 +117,7 @@ function CreateProgramKreatifDesa() {
|
||||
value={stateCreate.create.form.deskripsi}
|
||||
onChange={(val) => stateCreate.create.form.deskripsi = val}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<TextInput
|
||||
label={<Text fz="sm" fw="bold">Kolaborator</Text>}
|
||||
placeholder="Masukkan kolaborator"
|
||||
value={stateCreate.create.form.kolaborator || ''}
|
||||
onChange={(e) => stateCreate.create.form.kolaborator = e.currentTarget.value}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Group justify="right" mt="md">
|
||||
<Button
|
||||
|
||||
@@ -245,7 +245,6 @@ function ListKolaborasiInovasi({ search }: { search: string }) {
|
||||
</Box>
|
||||
</Paper>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -260,7 +259,6 @@ function ListKolaborasiInovasi({ search }: { search: string }) {
|
||||
radius="md"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@ import {
|
||||
Text,
|
||||
Title,
|
||||
} from '@mantine/core';
|
||||
import { IconEdit, IconPlus, IconSearch, IconX } from '@tabler/icons-react';
|
||||
import { useDebouncedValue } from '@mantine/hooks';
|
||||
import { IconEdit, IconPlus, IconSearch, IconTrash, IconX } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import HeaderSearch from '../../../_com/header';
|
||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||
import mitraKolaborasi from '../../../_state/inovasi/mitra-kolaborasi';
|
||||
import { useDebouncedValue } from '@mantine/hooks';
|
||||
|
||||
function MitraKolaborasi() {
|
||||
const [search, setSearch] = useState('');
|
||||
@@ -56,7 +56,6 @@ function ListMitraKolaborasi({ search }: { search: string }) {
|
||||
mitraKolaborasi.delete.byId(selectedId);
|
||||
setModalHapus(false);
|
||||
setSelectedId(null);
|
||||
router.push('/admin/inovasi/kolaborasi-inovasi');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -192,7 +191,7 @@ function ListMitraKolaborasi({ search }: { search: string }) {
|
||||
setModalHapus(true);
|
||||
}}
|
||||
>
|
||||
<IconX size={16} />
|
||||
<IconTrash size={16} />
|
||||
</Button>
|
||||
</TableTd>
|
||||
<TableTd>
|
||||
|
||||
@@ -234,7 +234,6 @@ function ListJenisLayanan({ search }: { search: string }) {
|
||||
</Box>
|
||||
</Paper>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -248,7 +247,6 @@ function ListJenisLayanan({ search }: { search: string }) {
|
||||
radius="md"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,37 +20,53 @@ import {
|
||||
Text,
|
||||
Title,
|
||||
} from '@mantine/core';
|
||||
import { useDebouncedValue } from '@mantine/hooks';
|
||||
import {
|
||||
IconAlertTriangle,
|
||||
IconAmbulance,
|
||||
IconBook,
|
||||
IconBuilding,
|
||||
IconBuildingCommunity,
|
||||
IconCash,
|
||||
IconChartLine,
|
||||
IconChristmasTreeFilled,
|
||||
IconClipboard,
|
||||
IconClipboardTextFilled,
|
||||
IconDeviceImac,
|
||||
IconDroplet,
|
||||
IconFileText,
|
||||
IconFiretruck,
|
||||
IconFirstAidKit,
|
||||
IconHome,
|
||||
IconHomeEco,
|
||||
IconHospital,
|
||||
IconInfoCircle,
|
||||
IconLeaf,
|
||||
IconLifebuoy,
|
||||
IconMessageReport,
|
||||
IconPhoneCall,
|
||||
IconPlus,
|
||||
IconRecycle,
|
||||
IconRun,
|
||||
IconScale,
|
||||
IconSchool,
|
||||
IconSearch,
|
||||
IconShield,
|
||||
IconShieldFilled,
|
||||
IconShoppingCart,
|
||||
IconStethoscope,
|
||||
IconTent,
|
||||
IconTrash,
|
||||
IconTrashFilled,
|
||||
IconTree,
|
||||
IconTrendingUp,
|
||||
IconTrophy,
|
||||
IconTruck,
|
||||
IconTruckFilled,
|
||||
IconUsers
|
||||
} from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import HeaderSearch from '../../_com/header';
|
||||
import programKreatifState from '../../_state/inovasi/program-kreatif';
|
||||
import { useDebouncedValue } from '@mantine/hooks';
|
||||
|
||||
function ProgramKreatifDesa() {
|
||||
const [search, setSearch] = useState('');
|
||||
@@ -81,15 +97,16 @@ function ListProgramKreatifDesa({ search }: { search: string }) {
|
||||
const filteredData = data || [];
|
||||
|
||||
const iconMap: Record<string, React.FC<any>> = {
|
||||
// ===== Umum & Lingkungan =====
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruck,
|
||||
truck: IconTruckFilled,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboard,
|
||||
trash: IconTrash,
|
||||
clipboard: IconClipboardTextFilled,
|
||||
trash: IconTrashFilled,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
@@ -101,6 +118,30 @@ function ListProgramKreatifDesa({ search }: { search: string }) {
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
|
||||
// ===== Keamanan & Darurat =====
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
darurat: IconAlertTriangle,
|
||||
sar: IconLifebuoy,
|
||||
evakuasi: IconRun,
|
||||
keamanan: IconShield,
|
||||
teleponDarurat: IconPhoneCall,
|
||||
|
||||
// ===== Kesehatan =====
|
||||
rumahSakit: IconHospital,
|
||||
puskesmas: IconFirstAidKit,
|
||||
klinik: IconStethoscope,
|
||||
|
||||
// ===== Pemerintahan & Fasilitas =====
|
||||
bangunan: IconBuilding,
|
||||
kantorDesa: IconBuildingCommunity,
|
||||
administrasi: IconFileText,
|
||||
informasi: IconInfoCircle,
|
||||
pengaduan: IconMessageReport,
|
||||
layananPublik: IconUsers,
|
||||
book: IconBook
|
||||
};
|
||||
|
||||
if (loading || !data) {
|
||||
@@ -132,7 +173,7 @@ function ListProgramKreatifDesa({ search }: { search: string }) {
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
<Box visibleFrom="md" style={{ overflowX: 'auto' }}>
|
||||
<Box visibleFrom="md" style={{ overflowX: 'auto' }}>
|
||||
<Table
|
||||
highlightOnHover
|
||||
miw={0}
|
||||
|
||||
@@ -230,7 +230,6 @@ function ListKelahiran({ search }: { search: string }) {
|
||||
</Paper>
|
||||
|
||||
{/* Pagination */}
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -245,7 +244,6 @@ function ListKelahiran({ search }: { search: string }) {
|
||||
radius="md"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -222,7 +222,6 @@ function ListKematian({ search }: { search: string }) {
|
||||
</Paper>
|
||||
|
||||
{/* Pagination */}
|
||||
{totalPages > 1 && (
|
||||
<Center mt="lg">
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -235,7 +234,6 @@ function ListKematian({ search }: { search: string }) {
|
||||
radius="md"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -134,7 +134,6 @@ function ListKategoriPrestasi({ search }: { search: string }) {
|
||||
</TableTbody>
|
||||
</Table>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center mt="xl">
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -151,7 +150,6 @@ function ListKategoriPrestasi({ search }: { search: string }) {
|
||||
}}
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* MOBILE: Card */}
|
||||
@@ -194,7 +192,6 @@ function ListKategoriPrestasi({ search }: { search: string }) {
|
||||
))
|
||||
)}
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center py="lg">
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -211,7 +208,6 @@ function ListKategoriPrestasi({ search }: { search: string }) {
|
||||
}}
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
|
||||
@@ -73,9 +73,9 @@ function ListPrestasi({ search }: { search: string }) {
|
||||
|
||||
{/* Desktop Table */}
|
||||
<Box visibleFrom="md" style={{ overflowX: 'auto' }}>
|
||||
<Table highlightOnHover
|
||||
layout="fixed" // 🔥 PENTING
|
||||
withColumnBorders={false} striped verticalSpacing="sm" miw={800}>
|
||||
<Table highlightOnHover
|
||||
layout="fixed" // 🔥 PENTING
|
||||
withColumnBorders={false} striped verticalSpacing="sm" miw={800}>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh>Nama Prestasi</TableTh>
|
||||
@@ -177,17 +177,15 @@ function ListPrestasi({ search }: { search: string }) {
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center mt={{ base: 'md', md: 'lg' }}>
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={load}
|
||||
total={totalPages}
|
||||
withEdges
|
||||
size={isMobile ? 'xs' : 'sm'}
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
<Center mt={{ base: 'md', md: 'lg' }}>
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={load}
|
||||
total={totalPages}
|
||||
withEdges
|
||||
size={isMobile ? 'xs' : 'sm'}
|
||||
/>
|
||||
</Center>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,24 +4,45 @@ import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import {
|
||||
IconAlertTriangle,
|
||||
IconAmbulance,
|
||||
IconArrowBack,
|
||||
IconBook,
|
||||
IconBuilding,
|
||||
IconBuildingCommunity,
|
||||
IconCash,
|
||||
IconChartLine,
|
||||
IconChristmasTreeFilled,
|
||||
IconClipboard,
|
||||
IconClipboardTextFilled,
|
||||
IconDroplet,
|
||||
IconEdit,
|
||||
IconFileText,
|
||||
IconFiretruck,
|
||||
IconFirstAidKit,
|
||||
IconHome,
|
||||
IconHomeEco,
|
||||
IconHospital,
|
||||
IconInfoCircle,
|
||||
IconLeaf,
|
||||
IconLifebuoy,
|
||||
IconMessageReport,
|
||||
IconPhoneCall,
|
||||
IconRecycle,
|
||||
IconRun,
|
||||
IconScale,
|
||||
IconSchool,
|
||||
IconShield,
|
||||
IconShieldFilled,
|
||||
IconShoppingCart,
|
||||
IconStethoscope,
|
||||
IconTent,
|
||||
IconTrash,
|
||||
IconTrashFilled,
|
||||
IconTree,
|
||||
IconTrendingUp,
|
||||
IconTrophy,
|
||||
IconTruck,
|
||||
IconTruckFilled,
|
||||
IconUsers
|
||||
} from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import React, { useState } from 'react';
|
||||
@@ -36,24 +57,53 @@ function DetailDataLingkunganDesa() {
|
||||
const params = useParams();
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
|
||||
const iconMap: Record<string, React.FC<any>> = {
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruck,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboard,
|
||||
trash: IconTrash,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
};
|
||||
const iconMap: Record<string, React.FC<any>> = {
|
||||
// ===== Umum & Lingkungan =====
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruckFilled,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboardTextFilled,
|
||||
trash: IconTrashFilled,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
bantuan: IconCash,
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
|
||||
// ===== Keamanan & Darurat =====
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
darurat: IconAlertTriangle,
|
||||
sar: IconLifebuoy,
|
||||
evakuasi: IconRun,
|
||||
keamanan: IconShield,
|
||||
teleponDarurat: IconPhoneCall,
|
||||
|
||||
// ===== Kesehatan =====
|
||||
rumahSakit: IconHospital,
|
||||
puskesmas: IconFirstAidKit,
|
||||
klinik: IconStethoscope,
|
||||
|
||||
// ===== Pemerintahan & Fasilitas =====
|
||||
bangunan: IconBuilding,
|
||||
kantorDesa: IconBuildingCommunity,
|
||||
administrasi: IconFileText,
|
||||
informasi: IconInfoCircle,
|
||||
pengaduan: IconMessageReport,
|
||||
layananPublik: IconUsers,
|
||||
book: IconBook
|
||||
};
|
||||
|
||||
useShallowEffect(() => {
|
||||
stateDataLingkungan.findUnique.load(params?.id as string);
|
||||
|
||||
@@ -23,31 +23,43 @@ import {
|
||||
import {
|
||||
IconAlertTriangle,
|
||||
IconAmbulance,
|
||||
IconBook,
|
||||
IconBuilding,
|
||||
IconBuildingCommunity,
|
||||
IconCash,
|
||||
IconChartLine,
|
||||
IconChristmasTreeFilled,
|
||||
IconClipboardTextFilled,
|
||||
IconDeviceImacCog,
|
||||
IconDroplet,
|
||||
IconFileText,
|
||||
IconFiretruck,
|
||||
IconFirstAidKit,
|
||||
IconHome,
|
||||
IconHomeEco,
|
||||
IconHospital,
|
||||
IconInfoCircle,
|
||||
IconLeaf,
|
||||
IconLifebuoy,
|
||||
IconMessageReport,
|
||||
IconPhoneCall,
|
||||
IconPlus,
|
||||
IconRecycle,
|
||||
IconRun,
|
||||
IconScale,
|
||||
IconSchool,
|
||||
IconSearch,
|
||||
IconShield,
|
||||
IconShieldFilled,
|
||||
IconShoppingCart,
|
||||
IconStethoscope,
|
||||
IconTent,
|
||||
IconTrashFilled,
|
||||
IconTree,
|
||||
IconTrendingUp,
|
||||
IconTrophy,
|
||||
IconTruckFilled,
|
||||
IconUsers,
|
||||
} from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
@@ -84,34 +96,53 @@ function ListDataLingkunganDesa({ search }: { search: string }) {
|
||||
|
||||
const filteredData = data || [];
|
||||
|
||||
const iconMap: Record<string, React.FC<any>> = {
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruckFilled,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboardTextFilled,
|
||||
trash: IconTrashFilled,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
bantuan: IconCash,
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
rumahSakit: IconHospital,
|
||||
bangunan: IconBuilding,
|
||||
darurat: IconAlertTriangle
|
||||
};
|
||||
const iconMap: Record<string, React.FC<any>> = {
|
||||
// ===== Umum & Lingkungan =====
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruckFilled,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboardTextFilled,
|
||||
trash: IconTrashFilled,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
bantuan: IconCash,
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
|
||||
// ===== Keamanan & Darurat =====
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
darurat: IconAlertTriangle,
|
||||
sar: IconLifebuoy,
|
||||
evakuasi: IconRun,
|
||||
keamanan: IconShield,
|
||||
teleponDarurat: IconPhoneCall,
|
||||
|
||||
// ===== Kesehatan =====
|
||||
rumahSakit: IconHospital,
|
||||
puskesmas: IconFirstAidKit,
|
||||
klinik: IconStethoscope,
|
||||
|
||||
// ===== Pemerintahan & Fasilitas =====
|
||||
bangunan: IconBuilding,
|
||||
kantorDesa: IconBuildingCommunity,
|
||||
administrasi: IconFileText,
|
||||
informasi: IconInfoCircle,
|
||||
pengaduan: IconMessageReport,
|
||||
layananPublik: IconUsers,
|
||||
book: IconBook
|
||||
};
|
||||
|
||||
if (loading || !data) {
|
||||
return (
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||
import { IconAlertTriangle, IconAmbulance, IconBuilding, IconCash, IconChartLine, IconChristmasTreeFilled, IconClipboardTextFilled, IconDroplet, IconEdit, IconFiretruck, IconHome, IconHomeEco, IconHospital, IconLeaf, IconPlus, IconRecycle, IconScale, IconSchool, IconSearch, IconShieldFilled, IconShoppingCart, IconTent, IconTrashFilled, IconTree, IconTrendingUp, IconTrophy, IconTruckFilled } from '@tabler/icons-react';
|
||||
import { IconAlertTriangle, IconAmbulance, IconBook, IconBuilding, IconBuildingCommunity, IconCash, IconChartLine, IconChristmasTreeFilled, IconClipboardTextFilled, IconDroplet, IconEdit, IconFileText, IconFiretruck, IconFirstAidKit, IconHome, IconHomeEco, IconHospital, IconInfoCircle, IconLeaf, IconLifebuoy, IconMessageReport, IconPhoneCall, IconPlus, IconRecycle, IconRun, IconScale, IconSchool, IconSearch, IconShield, IconShieldFilled, IconShoppingCart, IconStethoscope, IconTent, IconTrashFilled, IconTree, IconTrendingUp, IconTrophy, IconTruckFilled, IconUsers } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React, { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
@@ -58,32 +58,51 @@ function ListPengelolaanSampahBankSampah({ search }: { search: string }) {
|
||||
const filteredData = data || []
|
||||
|
||||
const iconMap: Record<string, React.FC<{ size: number; style?: React.CSSProperties }>> = {
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruckFilled,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboardTextFilled,
|
||||
trash: IconTrashFilled,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
bantuan: IconCash,
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
rumahSakit: IconHospital,
|
||||
bangunan: IconBuilding,
|
||||
darurat: IconAlertTriangle,
|
||||
// ===== Umum & Lingkungan =====
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruckFilled,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboardTextFilled,
|
||||
trash: IconTrashFilled,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
bantuan: IconCash,
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
|
||||
// ===== Keamanan & Darurat =====
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
darurat: IconAlertTriangle,
|
||||
sar: IconLifebuoy,
|
||||
evakuasi: IconRun,
|
||||
keamanan: IconShield,
|
||||
teleponDarurat: IconPhoneCall,
|
||||
|
||||
// ===== Kesehatan =====
|
||||
rumahSakit: IconHospital,
|
||||
puskesmas: IconFirstAidKit,
|
||||
klinik: IconStethoscope,
|
||||
|
||||
// ===== Pemerintahan & Fasilitas =====
|
||||
bangunan: IconBuilding,
|
||||
kantorDesa: IconBuildingCommunity,
|
||||
administrasi: IconFileText,
|
||||
informasi: IconInfoCircle,
|
||||
pengaduan: IconMessageReport,
|
||||
layananPublik: IconUsers,
|
||||
book: IconBook
|
||||
};
|
||||
|
||||
if (loading || !data) {
|
||||
|
||||
@@ -6,12 +6,14 @@ import { useShallowEffect } from '@mantine/hooks';
|
||||
import {
|
||||
IconAlertTriangle,
|
||||
IconAmbulance,
|
||||
IconArrowBack, IconBuilding, IconCash, IconChartLine, IconChristmasTreeFilled, IconClipboard,
|
||||
IconArrowBack, IconBook, IconBuilding, IconBuildingCommunity, IconCash, IconChartLine, IconChristmasTreeFilled, IconClipboard,
|
||||
IconDroplet,
|
||||
IconEdit, IconFiretruck, IconHome, IconHomeEco, IconHospital, IconLeaf, IconRecycle, IconScale,
|
||||
IconEdit, IconFileText, IconFiretruck, IconFirstAidKit, IconHome, IconHomeEco, IconHospital, IconInfoCircle, IconLeaf, IconLifebuoy, IconMessageReport, IconPhoneCall, IconRecycle, IconRun, IconScale,
|
||||
IconSchool,
|
||||
IconShieldFilled, IconShoppingCart, IconTent, IconTrash, IconTree, IconTrendingUp,
|
||||
IconTrophy, IconTruck
|
||||
IconShield,
|
||||
IconShieldFilled, IconShoppingCart, IconStethoscope, IconTent, IconTrash, IconTree, IconTrendingUp,
|
||||
IconTrophy, IconTruck,
|
||||
IconUsers
|
||||
} from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import React, { useState } from 'react';
|
||||
@@ -28,31 +30,49 @@ function DetailProgramPenghijauan() {
|
||||
|
||||
const iconMap: Record<string, React.FC<any>> = {
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruck,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboard,
|
||||
trash: IconTrash,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
bantuan: IconCash,
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
rumahSakit: IconHospital,
|
||||
bangunan: IconBuilding,
|
||||
darurat: IconAlertTriangle
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruck,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboard,
|
||||
trash: IconTrash,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
bantuan: IconCash,
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
|
||||
// ===== Keamanan & Darurat =====
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
darurat: IconAlertTriangle,
|
||||
sar: IconLifebuoy,
|
||||
evakuasi: IconRun,
|
||||
keamanan: IconShield,
|
||||
teleponDarurat: IconPhoneCall,
|
||||
|
||||
// ===== Kesehatan =====
|
||||
rumahSakit: IconHospital,
|
||||
puskesmas: IconFirstAidKit,
|
||||
klinik: IconStethoscope,
|
||||
|
||||
// ===== Pemerintahan =====
|
||||
bangunan: IconBuilding,
|
||||
kantorDesa: IconBuildingCommunity,
|
||||
administrasi: IconFileText,
|
||||
informasi: IconInfoCircle,
|
||||
pengaduan: IconMessageReport,
|
||||
layananPublik: IconUsers,
|
||||
book: IconBook
|
||||
};
|
||||
|
||||
useShallowEffect(() => {
|
||||
@@ -113,7 +133,7 @@ function DetailProgramPenghijauan() {
|
||||
|
||||
<Box>
|
||||
<Text fz="lg" fw="bold">Ikon Program</Text>
|
||||
{iconMap[data?.icon] ? (
|
||||
{iconMap[data?.icon] ? (
|
||||
<Box title={data?.icon}>
|
||||
{React.createElement(iconMap[data.icon], { size: 28, color: colors['blue-button'] })}
|
||||
</Box>
|
||||
|
||||
@@ -23,31 +23,43 @@ import {
|
||||
import {
|
||||
IconAlertTriangle,
|
||||
IconAmbulance,
|
||||
IconBook,
|
||||
IconBuilding,
|
||||
IconBuildingCommunity,
|
||||
IconCash,
|
||||
IconChartLine,
|
||||
IconChristmasTreeFilled,
|
||||
IconClipboardTextFilled,
|
||||
IconDeviceImac,
|
||||
IconDroplet,
|
||||
IconFileText,
|
||||
IconFiretruck,
|
||||
IconFirstAidKit,
|
||||
IconHome,
|
||||
IconHomeEco,
|
||||
IconHospital,
|
||||
IconInfoCircle,
|
||||
IconLeaf,
|
||||
IconLifebuoy,
|
||||
IconMessageReport,
|
||||
IconPhoneCall,
|
||||
IconPlus,
|
||||
IconRecycle,
|
||||
IconRun,
|
||||
IconScale,
|
||||
IconSchool,
|
||||
IconSearch,
|
||||
IconShield,
|
||||
IconShieldFilled,
|
||||
IconShoppingCart,
|
||||
IconStethoscope,
|
||||
IconTent,
|
||||
IconTrashFilled,
|
||||
IconTree,
|
||||
IconTrendingUp,
|
||||
IconTrophy,
|
||||
IconTruckFilled,
|
||||
IconUsers,
|
||||
} from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
@@ -85,6 +97,7 @@ function ListProgramPenghijauan({ search }: { search: string }) {
|
||||
const filteredData = data || [];
|
||||
|
||||
const iconMap: Record<string, React.FC<any>> = {
|
||||
// ===== Umum & Lingkungan =====
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
@@ -105,12 +118,30 @@ function ListProgramPenghijauan({ search }: { search: string }) {
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
|
||||
// ===== Keamanan & Darurat =====
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
rumahSakit: IconHospital,
|
||||
bangunan: IconBuilding,
|
||||
darurat: IconAlertTriangle,
|
||||
sar: IconLifebuoy,
|
||||
evakuasi: IconRun,
|
||||
keamanan: IconShield,
|
||||
teleponDarurat: IconPhoneCall,
|
||||
|
||||
// ===== Kesehatan =====
|
||||
rumahSakit: IconHospital,
|
||||
puskesmas: IconFirstAidKit,
|
||||
klinik: IconStethoscope,
|
||||
|
||||
// ===== Pemerintahan & Fasilitas =====
|
||||
bangunan: IconBuilding,
|
||||
kantorDesa: IconBuildingCommunity,
|
||||
administrasi: IconFileText,
|
||||
informasi: IconInfoCircle,
|
||||
pengaduan: IconMessageReport,
|
||||
layananPublik: IconUsers,
|
||||
book: IconBook
|
||||
};
|
||||
|
||||
if (loading || !data) {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export default function serializeBigInt<T>(data: T): T {
|
||||
return JSON.parse(
|
||||
JSON.stringify(data, (_, value) =>
|
||||
typeof value === "bigint" ? value.toString() : value
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -65,7 +65,7 @@ const Utils = new Elysia({
|
||||
}).get("/version", async () => {
|
||||
const packageJson = await fs.readFile(
|
||||
path.join(ROOT, "package.json"),
|
||||
"utf-8"
|
||||
"utf-8",
|
||||
);
|
||||
const version = JSON.parse(packageJson).version;
|
||||
return { version };
|
||||
@@ -78,9 +78,9 @@ const ApiServer = new Elysia()
|
||||
.use(swagger({ path: "/api/docs" }))
|
||||
.use(
|
||||
staticPlugin({
|
||||
assets: process.env.WIBU_UPLOAD_DIR,
|
||||
assets: UPLOAD_DIR,
|
||||
prefix: "/uploads",
|
||||
})
|
||||
}),
|
||||
)
|
||||
.use(cors(corsConfig))
|
||||
.use(Utils)
|
||||
@@ -127,9 +127,9 @@ const ApiServer = new Elysia()
|
||||
query: t.Optional(
|
||||
t.Object({
|
||||
size: t.Optional(t.Number()),
|
||||
})
|
||||
}),
|
||||
),
|
||||
}
|
||||
},
|
||||
)
|
||||
.delete(
|
||||
"/img/:name",
|
||||
@@ -143,7 +143,7 @@ const ApiServer = new Elysia()
|
||||
params: t.Object({
|
||||
name: t.String(),
|
||||
}),
|
||||
}
|
||||
},
|
||||
)
|
||||
.get(
|
||||
"/imgs",
|
||||
@@ -161,9 +161,9 @@ const ApiServer = new Elysia()
|
||||
page: t.Number({ default: 1 }),
|
||||
count: t.Number({ default: 10 }),
|
||||
search: t.String({ default: "" }),
|
||||
})
|
||||
}),
|
||||
),
|
||||
}
|
||||
},
|
||||
)
|
||||
.post(
|
||||
"/upl-img",
|
||||
@@ -176,7 +176,7 @@ const ApiServer = new Elysia()
|
||||
title: t.String(),
|
||||
files: t.Files({ multiple: true }),
|
||||
}),
|
||||
}
|
||||
},
|
||||
)
|
||||
.post(
|
||||
"/upl-img-single",
|
||||
@@ -192,7 +192,7 @@ const ApiServer = new Elysia()
|
||||
name: t.String(),
|
||||
file: t.File(),
|
||||
}),
|
||||
}
|
||||
},
|
||||
)
|
||||
.post(
|
||||
"/upl-csv-single",
|
||||
@@ -204,7 +204,7 @@ const ApiServer = new Elysia()
|
||||
name: t.String(),
|
||||
file: t.File(),
|
||||
}),
|
||||
}
|
||||
},
|
||||
)
|
||||
.post(
|
||||
"/upl-csv",
|
||||
@@ -215,8 +215,8 @@ const ApiServer = new Elysia()
|
||||
body: t.Object({
|
||||
files: t.Files(),
|
||||
}),
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export const GET = ApiServer.handle;
|
||||
|
||||
@@ -40,6 +40,13 @@ function PengaduanMasyarakat() {
|
||||
};
|
||||
};
|
||||
|
||||
const resetAll = () => {
|
||||
resetForm();
|
||||
setFile(null);
|
||||
setPreviewImage(null);
|
||||
};
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!file) {
|
||||
return toast.error("Silahkan pilih file gambar terlebih dahulu")
|
||||
@@ -64,7 +71,7 @@ function PengaduanMasyarakat() {
|
||||
const success = await state.pengaduanMasyarakat.create.create()
|
||||
|
||||
if (success) {
|
||||
resetForm()
|
||||
resetAll()
|
||||
close()
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -190,7 +197,7 @@ function PengaduanMasyarakat() {
|
||||
</Group>
|
||||
</Dropzone>
|
||||
{previewImage ? (
|
||||
<Image alt="" src={previewImage} w={200} h={200} loading="lazy"/>
|
||||
<Image alt="" src={previewImage} w={200} h={200} loading="lazy" />
|
||||
) : (
|
||||
<Center w={200} h={200} bg={"gray"}>
|
||||
<IconImageInPicture />
|
||||
|
||||
@@ -124,7 +124,6 @@ function ListPencegahanKriminalitas({ search }: { search: string }) {
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -138,7 +137,6 @@ function ListPencegahanKriminalitas({ search }: { search: string }) {
|
||||
radius="lg"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -179,7 +179,6 @@ export default function Page() {
|
||||
))}
|
||||
</SimpleGrid>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -191,7 +190,6 @@ export default function Page() {
|
||||
mt="md"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
|
||||
<Stack gap="sm">
|
||||
<Flex align="center" gap="xs">
|
||||
|
||||
@@ -225,7 +225,6 @@ export default function Page() {
|
||||
))}
|
||||
</SimpleGrid>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -242,7 +241,6 @@ export default function Page() {
|
||||
}}
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Box px={{ base: "md", md: 100 }} py="xl">
|
||||
|
||||
@@ -127,7 +127,6 @@ function Page() {
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
@@ -138,7 +137,6 @@ function Page() {
|
||||
mt="lg"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import dataLingkunganDesaState from '@/app/admin/(dashboard)/_state/lingkungan/d
|
||||
import colors from '@/con/colors';
|
||||
import { Badge, Box, Center, Group, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Tooltip } from '@mantine/core';
|
||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||
import { Icon, IconChartLine, IconChristmasTreeFilled, IconClipboardTextFilled, IconDroplet, IconHome, IconHomeEco, IconLeaf, IconRecycle, IconScale, IconSearch, IconShieldFilled, IconTent, IconTrashFilled, IconTree, IconTrendingUp, IconTrophy, IconTruckFilled } from '@tabler/icons-react';
|
||||
import { Icon, IconAlertTriangle, IconAmbulance, IconBook, IconBuilding, IconBuildingCommunity, IconCash, IconChartLine, IconChristmasTreeFilled, IconClipboard, IconDroplet, IconFileText, IconFiretruck, IconFirstAidKit, IconHome, IconHomeEco, IconHospital, IconInfoCircle, IconLeaf, IconLifebuoy, IconMessageReport, IconPhoneCall, IconRecycle, IconRun, IconScale, IconSchool, IconSearch, IconShield, IconShieldFilled, IconShoppingCart, IconStethoscope, IconTent, IconTrash, IconTree, IconTrendingUp, IconTrophy, IconTruck, IconUsers } from '@tabler/icons-react';
|
||||
import React, { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||
@@ -21,24 +21,51 @@ function Page() {
|
||||
} = state
|
||||
|
||||
const iconMap: Record<string, Icon> = {
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruckFilled,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboardTextFilled,
|
||||
trash: IconTrashFilled,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruck,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboard,
|
||||
trash: IconTrash,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
bantuan: IconCash,
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
|
||||
};
|
||||
// ===== Keamanan & Darurat =====
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
darurat: IconAlertTriangle,
|
||||
sar: IconLifebuoy,
|
||||
evakuasi: IconRun,
|
||||
keamanan: IconShield,
|
||||
teleponDarurat: IconPhoneCall,
|
||||
|
||||
// ===== Kesehatan =====
|
||||
rumahSakit: IconHospital,
|
||||
puskesmas: IconFirstAidKit,
|
||||
klinik: IconStethoscope,
|
||||
|
||||
// ===== Pemerintahan =====
|
||||
bangunan: IconBuilding,
|
||||
kantorDesa: IconBuildingCommunity,
|
||||
administrasi: IconFileText,
|
||||
informasi: IconInfoCircle,
|
||||
pengaduan: IconMessageReport,
|
||||
layananPublik: IconUsers,
|
||||
book: IconBook
|
||||
};
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 6, debouncedSearch)
|
||||
|
||||
@@ -3,11 +3,11 @@ import pengelolaanSampahState from '@/app/admin/(dashboard)/_state/lingkungan/pe
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Center, Flex, Group, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||
import { Icon, IconChartLine, IconClipboardTextFilled, IconLeaf, IconRecycle, IconRoute, IconScale, IconSearch, IconTent, IconTrashFilled, IconTrophy, IconTruckFilled } from '@tabler/icons-react';
|
||||
import { Icon, IconAlertTriangle, IconAmbulance, IconBook, IconBuilding, IconBuildingCommunity, IconCash, IconChartLine, IconChristmasTreeFilled, IconClipboard, IconDroplet, IconFileText, IconFiretruck, IconFirstAidKit, IconHome, IconHomeEco, IconHospital, IconInfoCircle, IconLeaf, IconLifebuoy, IconMessageReport, IconPhoneCall, IconRecycle, IconRoute, IconRun, IconScale, IconSchool, IconSearch, IconShield, IconShieldFilled, IconShoppingCart, IconStethoscope, IconTent, IconTrash, IconTree, IconTrendingUp, IconTrophy, IconTruck, IconUsers } from '@tabler/icons-react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import React, { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
// Dynamically import the map component to avoid SSR issues with Leaflet
|
||||
const LeafletMultiMarkerMap = dynamic(
|
||||
@@ -42,16 +42,51 @@ function Page() {
|
||||
}, [page, debouncedSearch])
|
||||
|
||||
const iconMap: Record<string, Icon> = {
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruckFilled,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboardTextFilled,
|
||||
trash: IconTrashFilled,
|
||||
};
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruck,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboard,
|
||||
trash: IconTrash,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
bantuan: IconCash,
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
|
||||
// ===== Keamanan & Darurat =====
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
darurat: IconAlertTriangle,
|
||||
sar: IconLifebuoy,
|
||||
evakuasi: IconRun,
|
||||
keamanan: IconShield,
|
||||
teleponDarurat: IconPhoneCall,
|
||||
|
||||
// ===== Kesehatan =====
|
||||
rumahSakit: IconHospital,
|
||||
puskesmas: IconFirstAidKit,
|
||||
klinik: IconStethoscope,
|
||||
|
||||
// ===== Pemerintahan =====
|
||||
bangunan: IconBuilding,
|
||||
kantorDesa: IconBuildingCommunity,
|
||||
administrasi: IconFileText,
|
||||
informasi: IconInfoCircle,
|
||||
pengaduan: IconMessageReport,
|
||||
layananPublik: IconUsers,
|
||||
book: IconBook
|
||||
};
|
||||
|
||||
if (state.findMany.loading || !data) {
|
||||
return (
|
||||
|
||||
@@ -4,10 +4,21 @@ import programPenghijauanState from '@/app/admin/(dashboard)/_state/lingkungan/p
|
||||
import { Box, Button, Paper, Skeleton, Stack, Text, ThemeIcon } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import {
|
||||
IconArrowLeft, IconChartLine, IconChristmasTreeFilled, IconClipboard,
|
||||
IconHomeEco, IconLeaf, IconRecycle, IconScale,
|
||||
IconShieldFilled, IconTent, IconTrash,
|
||||
IconTrendingUp, IconTrophy, IconTruck
|
||||
IconAlertTriangle,
|
||||
IconAmbulance,
|
||||
IconArrowLeft, IconBook, IconBuilding, IconBuildingCommunity, IconCash, IconChartLine, IconChristmasTreeFilled, IconClipboard,
|
||||
IconDroplet,
|
||||
IconFileText,
|
||||
IconFiretruck,
|
||||
IconFirstAidKit,
|
||||
IconHome,
|
||||
IconHomeEco, IconHospital, IconInfoCircle, IconLeaf, IconLifebuoy, IconMessageReport, IconPhoneCall, IconRecycle, IconRun, IconScale,
|
||||
IconSchool,
|
||||
IconShield,
|
||||
IconShieldFilled, IconShoppingCart, IconStethoscope, IconTent, IconTrash,
|
||||
IconTree,
|
||||
IconTrendingUp, IconTrophy, IconTruck,
|
||||
IconUsers
|
||||
} from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import React from 'react';
|
||||
@@ -32,6 +43,37 @@ function Page() {
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
bantuan: IconCash,
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
|
||||
// ===== Keamanan & Darurat =====
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
darurat: IconAlertTriangle,
|
||||
sar: IconLifebuoy,
|
||||
evakuasi: IconRun,
|
||||
keamanan: IconShield,
|
||||
teleponDarurat: IconPhoneCall,
|
||||
|
||||
// ===== Kesehatan =====
|
||||
rumahSakit: IconHospital,
|
||||
puskesmas: IconFirstAidKit,
|
||||
klinik: IconStethoscope,
|
||||
|
||||
// ===== Pemerintahan =====
|
||||
bangunan: IconBuilding,
|
||||
kantorDesa: IconBuildingCommunity,
|
||||
administrasi: IconFileText,
|
||||
informasi: IconInfoCircle,
|
||||
pengaduan: IconMessageReport,
|
||||
layananPublik: IconUsers,
|
||||
book: IconBook
|
||||
};
|
||||
|
||||
useShallowEffect(() => {
|
||||
|
||||
@@ -4,11 +4,11 @@ import programPenghijauanState from '@/app/admin/(dashboard)/_state/lingkungan/p
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Center, Group, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
|
||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||
import { IconChartLine, IconChristmasTreeFilled, IconClipboardTextFilled, IconHomeEco, IconLeaf, IconRecycle, IconScale, IconSearch, IconShieldFilled, IconTent, IconTrashFilled, IconTrendingUp, IconTrophy, IconTruckFilled } from '@tabler/icons-react';
|
||||
import { IconAlertTriangle, IconAmbulance, IconBook, IconBuilding, IconBuildingCommunity, IconCash, IconChartLine, IconChristmasTreeFilled, IconClipboard, IconDroplet, IconFileText, IconFiretruck, IconFirstAidKit, IconHome, IconHomeEco, IconHospital, IconInfoCircle, IconLeaf, IconLifebuoy, IconMessageReport, IconPhoneCall, IconRecycle, IconRun, IconScale, IconSchool, IconSearch, IconShield, IconShieldFilled, IconShoppingCart, IconStethoscope, IconTent, IconTrash, IconTree, IconTrendingUp, IconTrophy, IconTruck, IconUsers } from '@tabler/icons-react';
|
||||
import { useTransitionRouter } from 'next-view-transitions';
|
||||
import React, { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||
import { useTransitionRouter } from 'next-view-transitions';
|
||||
|
||||
function Page() {
|
||||
const state = useProxy(programPenghijauanState);
|
||||
@@ -22,20 +22,51 @@ function Page() {
|
||||
}, [page, debouncedSearch]);
|
||||
|
||||
const iconMap: Record<string, any> = {
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruckFilled,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboardTextFilled,
|
||||
trash: IconTrashFilled,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
};
|
||||
ekowisata: IconLeaf,
|
||||
kompetisi: IconTrophy,
|
||||
wisata: IconTent,
|
||||
ekonomi: IconChartLine,
|
||||
sampah: IconRecycle,
|
||||
truck: IconTruck,
|
||||
scale: IconScale,
|
||||
clipboard: IconClipboard,
|
||||
trash: IconTrash,
|
||||
lingkunganSehat: IconHomeEco,
|
||||
sumberOksigen: IconChristmasTreeFilled,
|
||||
ekonomiBerkelanjutan: IconTrendingUp,
|
||||
mencegahBencana: IconShieldFilled,
|
||||
rumah: IconHome,
|
||||
pohon: IconTree,
|
||||
air: IconDroplet,
|
||||
bantuan: IconCash,
|
||||
pelatihan: IconSchool,
|
||||
subsidi: IconShoppingCart,
|
||||
layananKesehatan: IconHospital,
|
||||
|
||||
// ===== Keamanan & Darurat =====
|
||||
polisi: IconShieldFilled,
|
||||
ambulans: IconAmbulance,
|
||||
pemadam: IconFiretruck,
|
||||
darurat: IconAlertTriangle,
|
||||
sar: IconLifebuoy,
|
||||
evakuasi: IconRun,
|
||||
keamanan: IconShield,
|
||||
teleponDarurat: IconPhoneCall,
|
||||
|
||||
// ===== Kesehatan =====
|
||||
rumahSakit: IconHospital,
|
||||
puskesmas: IconFirstAidKit,
|
||||
klinik: IconStethoscope,
|
||||
|
||||
// ===== Pemerintahan =====
|
||||
bangunan: IconBuilding,
|
||||
kantorDesa: IconBuildingCommunity,
|
||||
administrasi: IconFileText,
|
||||
informasi: IconInfoCircle,
|
||||
pengaduan: IconMessageReport,
|
||||
layananPublik: IconUsers,
|
||||
book: IconBook
|
||||
};
|
||||
|
||||
if (loading || !data) {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user