Compare commits
59 Commits
nico/7-aug
...
nico/19-se
| Author | SHA1 | Date | |
|---|---|---|---|
| 0fc47c28ff | |||
| 8e25c91e85 | |||
| 068d8b1077 | |||
| 9f72e94557 | |||
| 79ad39fc55 | |||
| 39e1e7b575 | |||
| 4ceea5203f | |||
| a5d841bb6b | |||
| 6a7bd386ae | |||
| a9d98895bb | |||
| 75475dc62e | |||
| b39800a475 | |||
| 797713ef49 | |||
| 8817b937b1 | |||
| 2adf60f9eb | |||
| fa9601e126 | |||
| 7ae83788b4 | |||
| 22ec8d942d | |||
| 9f9a0fb451 | |||
| b6d6583e77 | |||
| a8fd715822 | |||
| f9530c32eb | |||
| f15ef5a275 | |||
| 3a726a3334 | |||
| b21e1f0c2e | |||
| f63249327d | |||
| bb8dab05ba | |||
| 3081e426bd | |||
| 8a275c2a32 | |||
| 8469ebd2e1 | |||
| 760ba4b6d2 | |||
| 20d4c90e60 | |||
| fafbb12a08 | |||
| 01aa0da5cc | |||
| b580978f8e | |||
| 1c01397c0d | |||
| 90a6605efd | |||
| c22d865283 | |||
| 49067f0218 | |||
| d79425d529 | |||
| 4491d23bea | |||
| 1e154ced86 | |||
| bcc51aec12 | |||
| 8d15563f15 | |||
| d7a592c635 | |||
| 5e137ba658 | |||
| c99416c7f8 | |||
| 212e2db1fb | |||
| b8a45bc451 | |||
| 0777b00a7d | |||
| a035039b2c | |||
| a6832cad40 | |||
| a1d55e2b0a | |||
| c1583c21b1 | |||
| 2fe8b8ce1a | |||
| 5cbf7810bc | |||
| b3bf6b0327 | |||
| a65529cb23 | |||
| afc7bced44 |
2
.gitignore
vendored
@@ -48,3 +48,5 @@ next-env.d.ts
|
||||
|
||||
.env.*
|
||||
|
||||
*.tar.gz
|
||||
|
||||
|
||||
15
package.json
@@ -3,11 +3,9 @@
|
||||
"version": "0.1.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"prisma:seed": "bun run prisma/seed.ts"
|
||||
"dev": "bun --bun next dev",
|
||||
"build": "bun --bun next build",
|
||||
"start": "bun --bun next start"
|
||||
},
|
||||
"prisma": {
|
||||
"seed": "bun run prisma/seed.ts"
|
||||
@@ -57,6 +55,8 @@
|
||||
"form-data": "^4.0.2",
|
||||
"framer-motion": "^12.23.5",
|
||||
"get-port": "^7.1.0",
|
||||
"iron-session": "^8.0.4",
|
||||
"jose": "^6.1.0",
|
||||
"jotai": "^2.12.3",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"leaflet": "^1.9.4",
|
||||
@@ -64,7 +64,7 @@
|
||||
"lodash": "^4.17.21",
|
||||
"motion": "^12.4.1",
|
||||
"nanoid": "^5.1.5",
|
||||
"next": "15.1.6",
|
||||
"next": "^15.5.2",
|
||||
"next-view-transitions": "^0.3.4",
|
||||
"node-fetch": "^3.3.2",
|
||||
"p-limit": "^6.2.0",
|
||||
@@ -73,15 +73,18 @@
|
||||
"prisma": "^6.3.1",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-international-phone": "^4.6.0",
|
||||
"react-leaflet": "^5.0.0",
|
||||
"react-simple-toasts": "^6.1.0",
|
||||
"react-toastify": "^11.0.5",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"readdirp": "^4.1.1",
|
||||
"recharts": "^2.15.3",
|
||||
"sharp": "^0.34.3",
|
||||
"swr": "^2.3.2",
|
||||
"uuid": "^11.1.0",
|
||||
"valtio": "^2.1.3",
|
||||
"zlib": "^1.0.5",
|
||||
"zod": "^3.24.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,51 +1,99 @@
|
||||
[
|
||||
{
|
||||
"month": "Jan",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 160,
|
||||
"educatedUnemployment": 95,
|
||||
"uneducatedUnemployment": 65,
|
||||
"percentageChange": null
|
||||
},
|
||||
{
|
||||
"month": "Feb",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 155,
|
||||
"educatedUnemployment": 90,
|
||||
"uneducatedUnemployment": 65,
|
||||
"percentageChange": -3.1
|
||||
},
|
||||
{
|
||||
"month": "Mar",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 150,
|
||||
"educatedUnemployment": 88,
|
||||
"uneducatedUnemployment": 62,
|
||||
"percentageChange": -3.2
|
||||
},
|
||||
{
|
||||
"month": "Apr",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 148,
|
||||
"educatedUnemployment": 85,
|
||||
"uneducatedUnemployment": 63,
|
||||
"percentageChange": -1.3
|
||||
},
|
||||
{
|
||||
"month": "Mei",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 145,
|
||||
"educatedUnemployment": 82,
|
||||
"uneducatedUnemployment": 63,
|
||||
"percentageChange": -2.0
|
||||
},
|
||||
{
|
||||
"month": "Jun",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 140,
|
||||
"educatedUnemployment": 80,
|
||||
"uneducatedUnemployment": 60,
|
||||
"percentageChange": -3.4
|
||||
}
|
||||
]
|
||||
{
|
||||
"month": "Jan",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 160,
|
||||
"educatedUnemployment": 95,
|
||||
"uneducatedUnemployment": 65,
|
||||
"percentageChange": 0.0
|
||||
},
|
||||
{
|
||||
"month": "Feb",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 158,
|
||||
"educatedUnemployment": 93,
|
||||
"uneducatedUnemployment": 65,
|
||||
"percentageChange": -1.25
|
||||
},
|
||||
{
|
||||
"month": "Mar",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 155,
|
||||
"educatedUnemployment": 91,
|
||||
"uneducatedUnemployment": 64,
|
||||
"percentageChange": -1.90
|
||||
},
|
||||
{
|
||||
"month": "Apr",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 152,
|
||||
"educatedUnemployment": 89,
|
||||
"uneducatedUnemployment": 63,
|
||||
"percentageChange": -1.94
|
||||
},
|
||||
{
|
||||
"month": "Mei",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 150,
|
||||
"educatedUnemployment": 88,
|
||||
"uneducatedUnemployment": 62,
|
||||
"percentageChange": -1.32
|
||||
},
|
||||
{
|
||||
"month": "Jun",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 148,
|
||||
"educatedUnemployment": 87,
|
||||
"uneducatedUnemployment": 61,
|
||||
"percentageChange": -1.33
|
||||
},
|
||||
{
|
||||
"month": "Jul",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 145,
|
||||
"educatedUnemployment": 85,
|
||||
"uneducatedUnemployment": 60,
|
||||
"percentageChange": -2.03
|
||||
},
|
||||
{
|
||||
"month": "Agu",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 142,
|
||||
"educatedUnemployment": 84,
|
||||
"uneducatedUnemployment": 58,
|
||||
"percentageChange": -2.07
|
||||
},
|
||||
{
|
||||
"month": "Sep",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 140,
|
||||
"educatedUnemployment": 83,
|
||||
"uneducatedUnemployment": 57,
|
||||
"percentageChange": -1.41
|
||||
},
|
||||
{
|
||||
"month": "Okt",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 138,
|
||||
"educatedUnemployment": 82,
|
||||
"uneducatedUnemployment": 56,
|
||||
"percentageChange": -1.43
|
||||
},
|
||||
{
|
||||
"month": "Nov",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 135,
|
||||
"educatedUnemployment": 80,
|
||||
"uneducatedUnemployment": 55,
|
||||
"percentageChange": -2.17
|
||||
},
|
||||
{
|
||||
"month": "Des",
|
||||
"year": 2025,
|
||||
"totalUnemployment": 132,
|
||||
"educatedUnemployment": 78,
|
||||
"uneducatedUnemployment": 54,
|
||||
"percentageChange": -2.22
|
||||
}
|
||||
]
|
||||
|
||||
137
prisma/data/file-storage.json
Normal file
@@ -0,0 +1,137 @@
|
||||
[
|
||||
{
|
||||
"id": "cmff0rr4z0002vn0twp333m2",
|
||||
"name": "S6RIjFaPvdQm3oq4rM4X9-desktop.webp",
|
||||
"realName": "bares.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/S6RIjFaPvdQm3oq4rM4X9-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff0tnf00003vn0t3kgzi0u0",
|
||||
"name": "_pVNEmThU5ICGa8gv3gh_-desktop.webp",
|
||||
"realName": "bicara-darma.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/_pVNEmThU5ICGa8gv3gh_-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff0uykf0004vn0trmmxpgfh",
|
||||
"name": "bv6rdKvjxkkjUSGLQ0lvB-desktop.webp",
|
||||
"realName": "daves.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/bv6rdKvjxkkjUSGLQ0lvB-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff0z34f0005vn0tjtvq519p",
|
||||
"name": "Z4hWaV04CvoE20MjccQsV-desktop.webp",
|
||||
"realName": "mangan.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/Z4hWaV04CvoE20MjccQsV-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff38cyq000bvn0t9f01cz3f",
|
||||
"name": "LvLAtOqWojx4sn6NjJWB9-desktop.webp",
|
||||
"realName": "gelah-melah.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/LvLAtOqWojx4sn6NjJWB9-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff0zqvd0007vn0tv6o5hjcq",
|
||||
"name": "gR2mcvAQVgJ2-rM5coYJj-desktop.webp",
|
||||
"realName": "inovasi-desa-darmasaba.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/gR2mcvAQVgJ2-rM5coYJj-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff1013m0008vn0th7t0d64d",
|
||||
"name": "JpL-9F8-IGztMn8E2ce02-desktop.webp",
|
||||
"realName": "pdkt.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/JpL-9F8-IGztMn8E2ce02-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff10cwq0009vn0tse8dzu3j",
|
||||
"name": "bxAk4AsGbJTC705_IVdes-desktop.webp",
|
||||
"realName": "sajjiana-dharma-raksaka.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/bxAk4AsGbJTC705_IVdes-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff2w5ly000avn0telhct71k",
|
||||
"name": "Vbj_osnMJUkGEQGDTLwV--desktop.webp",
|
||||
"realName": "perbekel.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/Vbj_osnMJUkGEQGDTLwV--desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff3joae0000vn6h8sgs0ilg",
|
||||
"name": "7hox9spUxj56hY_EBYLnj-desktop.webp",
|
||||
"realName": "youtube.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/7hox9spUxj56hY_EBYLnj-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff3ll130001vn6hkhls3f5y",
|
||||
"name": "ChihV7_1eS-AGtSg9UwMv-desktop.webp",
|
||||
"realName": "gmail.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/ChihV7_1eS-AGtSg9UwMv-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff3mtat0002vn6hs8vyyhdd",
|
||||
"name": "z8v9ZREwOJHKGIRYauROt-desktop.webp",
|
||||
"realName": "facebook.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/z8v9ZREwOJHKGIRYauROt-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff3nv180003vn6h5jvedidq",
|
||||
"name": "BLjMxTKoCNE31uOURR3IU-desktop.webp",
|
||||
"realName": "telephone-call.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/BLjMxTKoCNE31uOURR3IU-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff3oouh0004vn6hd94brzv9",
|
||||
"name": "hkJYAeTNWK_vYaYS20w3I-desktop.webp",
|
||||
"realName": "instagram.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/hkJYAeTNWK_vYaYS20w3I-desktop.webp",
|
||||
"category": "image"
|
||||
},
|
||||
{
|
||||
"id": "cmff3q12g0005vn6h5ojov2qa",
|
||||
"name": "6XEoZ9SFu59COpil03Gya-desktop.webp",
|
||||
"realName": "tiktok.png",
|
||||
"path": "uploads/images",
|
||||
"mimeType": "image/webp",
|
||||
"link": "/api/fileStorage/findUnique/6XEoZ9SFu59COpil03Gya-desktop.webp",
|
||||
"category": "image"
|
||||
}
|
||||
]
|
||||
@@ -3,126 +3,108 @@
|
||||
"id": "cmds9h9ko000pvnberdjnx64b",
|
||||
"name": "1.1 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PERENCANAAN, PELAKSANAAN, PENATAUSAHAAN DAN PERTANGGUNG JAWABAN APBDES BESERTA IMPLEMENTASINYA",
|
||||
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PERENCANAAN, PELAKSANAAN, PENATAUSAHAAN DAN PERTANGGUNG JAWABAN APBDES BESERTA IMPLEMENTASINYA</p>",
|
||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh"
|
||||
},
|
||||
{
|
||||
"id": "cmds9sjmz000svnbesv2133of",
|
||||
"name": "1.2 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP MENGENAI MEKANISME EVALUASI KINERJA PERANGKAT DESA",
|
||||
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP MENGENAI MEKANISME EVALUASI KINERJA PERANGKAT DESA</p>",
|
||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh"
|
||||
},
|
||||
{
|
||||
"id": "cmds9tcpi000vvnbev3ebtlnt",
|
||||
"name": "1.3 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PENGENDALIAN GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN",
|
||||
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PENGENDALIAN GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN</p>",
|
||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh"
|
||||
},
|
||||
{
|
||||
"id": "cmds9twvj000yvnbep0pq8dzf",
|
||||
"name": "1.4 PERJANJIAN KERJA SAMA ANTARA PELAKSANA KEGIATAN ANGGARAN DENGAN PIHAK PENYEDIA, DAN TELAH MELALUI PROSES PENGADAAN BARANG/JASA DI DESA",
|
||||
"deskripsi": "<p>PERJANJIAN KERJA SAMA ANTARA PELAKSANA KEGIATAN ANGGARAN DENGAN PIHAK PENYEDIA, DAN TELAH MELALUI PROSES PENGADAAN BARANG/JASA DI DESA</p>",
|
||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh"
|
||||
},
|
||||
{
|
||||
"id": "cmds9ugap0011vnbe118yv871",
|
||||
"name": "1.5 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PAKTA INTEGRITAS DAN SEJENISNYA",
|
||||
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PAKTA INTEGRITAS DAN SEJENISNYA</p>",
|
||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh"
|
||||
},
|
||||
{
|
||||
"id": "cmdsa35310014vnbe6qy6l1rz",
|
||||
"name": "2.1 ADANYA KEGIATAN PENGAWASAN DAN EVALUASI KINERJA PERANGKAT DESA",
|
||||
"deskripsi": "<p>ADANYA KEGIATAN PENGAWASAN DAN EVALUASI KINERJA PERANGKAT DESA</p>",
|
||||
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm"
|
||||
},
|
||||
{
|
||||
"id": "cmdsa46590017vnbepp3noso1",
|
||||
"name": "2.2 ADANYA TINDAK LANJUT HASIL PEMBINAAN, PETUNJUK, ARAH, PENGAWASAN, DAN PEMERIKSAAN DARI PEMERINTAH PUSAT/DAERAH",
|
||||
"deskripsi": "<p>ADANYA TINDAK LANJUT HASIL PEMBINAAN, PETUNJUK, ARAH, PENGAWASAN, DAN PEMERIKSAAN DARI PEMERINTAH PUSAT/DAERAH</p>",
|
||||
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm"
|
||||
},
|
||||
{
|
||||
"id": "cmdsa5m7z001avnbe4cvfrcz0",
|
||||
"name": "2.3 TIDAK ADANYA APARATUR DESA DALAM 3(TIGA) TAHUN TERAKHIR YANG TERJERAT TINDAKAN PIDANA KORUPSI",
|
||||
"deskripsi": "<p>TIDAK ADANYA APARATUR DESA DALAM 3(TIGA) TAHUN TERAKHIR YANG TERJERAT TINDAKAN PIDANA KORUPSI</p>",
|
||||
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm"
|
||||
},
|
||||
{
|
||||
"id": "cmdsa8q5q001dvnbemch8j24x",
|
||||
"name": "3.1 ADANYA LAYANAN PENGADUAN BAGI MASYARAKAT",
|
||||
"deskripsi": "<p>ADANYA LAYANAN PENGADUAN BAGI MASYARAKAT</p>",
|
||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl"
|
||||
},
|
||||
{
|
||||
"id": "cmdsa9lbi001gvnbequn2ba7m",
|
||||
"name": "3.2 ADANYA SURVEY KEPUASAN MASYARAKAT (SKM) TERHADAP LAYANAN PEMERINTAH DESA",
|
||||
"deskripsi": "<p>ADANYA SURVEY KEPUASAN MASYARAKAT (SKM) TERHADAP LAYANAN PEMERINTAH DESA</p>",
|
||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl"
|
||||
},
|
||||
{
|
||||
"id": "cmdsaa7aq001jvnbeizh04e67",
|
||||
"name": "3.3 ADANYA KETERBUKAAN AKSES MASYARAKAT TERHADAP INFORMASI LAYANAN PEMERINTAH DESA (KESEHATAN, PENDIDIKAN, SOSIAL, LINGKUNGAN, TRANTIBUMLINMAS, PEKERJAAN UMUM) PEMBANGUNAN, KEPENDUDUKAN, KEUANGAN, DAN PELAYANAN LAINNYA",
|
||||
"deskripsi": "<p>ADANYA KETERBUKAAN AKSES MASYARAKAT TERHADAP INFORMASI LAYANAN PEMERINTAH DESA (KESEHATAN, PENDIDIKAN, SOSIAL, LINGKUNGAN, TRANTIBUMLINMAS, PEKERJAAN UMUM) PEMBANGUNAN, KEPENDUDUKAN, KEUANGAN, DAN PELAYANAN LAINNYA</p>",
|
||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl"
|
||||
},
|
||||
{
|
||||
"id": "cmdsaaw8d001mvnbek3tfefrk",
|
||||
"name": "3.4 ADANYA MEDIA INFORMASI TENTANG APBDES DI BALAI DESA DAN/ATAU TEMPAT LAIN YANG MUDAH DIAKSES OLEH MASYARAKAT",
|
||||
"deskripsi": "<p>ADANYA MEDIA INFORMASI TENTANG APBDES DI BALAI DESA DAN/ATAU TEMPAT LAIN YANG MUDAH DIAKSES OLEH MASYARAKAT</p>",
|
||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl"
|
||||
},
|
||||
{
|
||||
"id": "cmdsabhif001pvnbepm06hry6",
|
||||
"name": "3.5 ADANYA MAKLUMAT PELAYANAN",
|
||||
"deskripsi": "<p>ADANYA MAKLUMAT PELAYANAN</p>",
|
||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl"
|
||||
},
|
||||
{
|
||||
"id": "cmdsag40b001svnbe7krq9khc",
|
||||
"name": "4.1 ADANYA PARTISIPASI DAN KETERLIBATAN MASYARAKAT DALAM PENYUSUNAN RKP DESA",
|
||||
"deskripsi": "<p>ADANYA PARTISIPASI DAN KETERLIBATAN MASYARAKAT DALAM PENYUSUNAN RKP DESA</p>",
|
||||
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv"
|
||||
},
|
||||
{
|
||||
"id": "cmdsagkaf001vvnbejo26w8sa",
|
||||
"name": "4.2 ADANYA KESADARAN MASYARAKAT DALAM MENCEGAH TERJADINYA PRAKTIK GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN",
|
||||
"deskripsi": "<p>ADANYA KESADARAN MASYARAKAT DALAM MENCEGAH TERJADINYA PRAKTIK GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN</p>",
|
||||
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv"
|
||||
},
|
||||
{
|
||||
"id": "cmdsah4qe001yvnbeiy3mwrvb",
|
||||
"name": "4.3 ADANYA KETERLIBATAN LEMBAGA KEMASYARAKATAN DALAM PELAKSANAAN PEMBANGUNAN DESA",
|
||||
"deskripsi": "<p>ADANYA KETERLIBATAN LEMBAGA KEMASYARAKATAN DALAM PELAKSANAAN PEMBANGUNAN DESA</p>",
|
||||
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv"
|
||||
},
|
||||
{
|
||||
"id": "cmdsak5vn0021vnbemg86aab4",
|
||||
"name": "5.1 ADANYA BUDAYA LOKAL/HUKUM ADAT YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI",
|
||||
"deskripsi": "<p>ADANYA BUDAYA LOKAL/HUKUM ADAT YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI</p>",
|
||||
"kategoriId": "cmds9govb000mvnbesq8b4y99",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9govb000mvnbesq8b4y99"
|
||||
},
|
||||
{
|
||||
"id": "cmdsalc800024vnbezgulhgrb",
|
||||
"name": "5.2 ADANYA TOKOH MASYARAKAT, TOKOH AGAMA, TOKOH ADAT, TOKOH PEMUDA, DAN KAUM PEREMPUAN YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI",
|
||||
"deskripsi": "<p>ADANYA TOKOH MASYARAKAT, TOKOH AGAMA, TOKOH ADAT, TOKOH PEMUDA, DAN KAUM PEREMPUAN YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI</p>",
|
||||
"kategoriId": "cmds9govb000mvnbesq8b4y99",
|
||||
"fileId": ""
|
||||
"kategoriId": "cmds9govb000mvnbesq8b4y99"
|
||||
}
|
||||
]
|
||||
@@ -2,31 +2,37 @@
|
||||
{
|
||||
"id": "cmds8w2q60002vnbe6i8qhkuo",
|
||||
"name": "Telephone Desa Darmasaba",
|
||||
"iconUrl": "081239580000"
|
||||
"iconUrl": "081239580000",
|
||||
"imageId": "cmff3nv180003vn6h5jvedidq"
|
||||
},
|
||||
{
|
||||
"id": "cmds8z7u20005vnbegyyvnbk0",
|
||||
"name": "Email Desa Darmasaba",
|
||||
"iconUrl": "desadarmasaba@badungkab.go.id"
|
||||
"iconUrl": "desadarmasaba@badungkab.go.id",
|
||||
"imageId": "cmff3ll130001vn6hkhls3f5y"
|
||||
},
|
||||
{
|
||||
"id": "cmds9023u0008vnbe3oxmhwyf",
|
||||
"name": "Desa Darmasaba",
|
||||
"iconUrl": "https://www.youtube.com/channel/UCtPw9WOQO7d2HIKzKgel4Xg"
|
||||
"iconUrl": "https://www.youtube.com/channel/UCtPw9WOQO7d2HIKzKgel4Xg",
|
||||
"imageId": "cmff3joae0000vn6h8sgs0ilg"
|
||||
},
|
||||
{
|
||||
"id": "cmds90oul000bvnbe2bqkptoi",
|
||||
"name": "Pemerintah Desa Darmasaba",
|
||||
"iconUrl": "https://www.facebook.com/DarmasabaDesaku"
|
||||
"iconUrl": "https://www.facebook.com/DarmasabaDesaku",
|
||||
"imageId": "cmff3mtat0002vn6hs8vyyhdd"
|
||||
},
|
||||
{
|
||||
"id": "cmds91i4e000evnbe8gtf1gub",
|
||||
"name": "ddarmasaba",
|
||||
"iconUrl": "https://www.instagram.com/ddarmasaba/"
|
||||
"iconUrl": "https://www.instagram.com/ddarmasaba/",
|
||||
"imageId": "cmff3oouh0004vn6hd94brzv9"
|
||||
},
|
||||
{
|
||||
"id": "cmds92de5000hvnbemlu6sq5x",
|
||||
"name": "desa.darmasaba",
|
||||
"iconUrl": "https://www.tiktok.com/@desa.darmasaba?is_from_webapp=1&sender_device=pc"
|
||||
"iconUrl": "https://www.tiktok.com/@desa.darmasaba?is_from_webapp=1&sender_device=pc",
|
||||
"imageId": "cmff3q12g0005vn6h5ojov2qa"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
{
|
||||
"id": "edit",
|
||||
"name": "I.B Surya Prabhawa Manuaba, S.H., M.H.",
|
||||
"position": "Perbekel Darmasaba periode 2021-2027"
|
||||
"position": "Perbekel Darmasaba periode 2021-2027",
|
||||
"imageId": "cmff2w5ly000avn0telhct71k"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,50 +1,51 @@
|
||||
[
|
||||
{
|
||||
"id": "cmdr7039z0002vn5rttctt9hn",
|
||||
"name": "Davest",
|
||||
"description": "Darmasaba Village Festval",
|
||||
"link": "https://darmasaba.desa.id/berita/55862-rakor-davest-2024"
|
||||
},
|
||||
{
|
||||
"id": "cmdr755pf0005vn5rp8tyuubw",
|
||||
"name": "Dmangan",
|
||||
"description": "Darmasaba Aman Pangan",
|
||||
"link": "https://darmasaba.desa.id/berita/61452-kader-d-mangan-berhasil-meraih-prestasi-dalam-ajang-lomba-banjar-bali-quis-bbq-tahun-2024"
|
||||
"link": "https://darmasaba.desa.id/berita/61452-kader-d-mangan-berhasil-meraih-prestasi-dalam-ajang-lomba-banjar-bali-quis-bbq-tahun-2024",
|
||||
"imageId" : "cmff0z34f0005vn0tjtvq519p"
|
||||
},
|
||||
{
|
||||
"id": "cmdr76nqk0008vn5rdddvcxnr",
|
||||
"name": "Bicara Darmasaba",
|
||||
"description": "Bicara Darmasaba",
|
||||
"link": "https://darmasaba.desa.id/berita/42506-bicara-darmasaba"
|
||||
"link": "https://darmasaba.desa.id/berita/42506-bicara-darmasaba",
|
||||
"imageId" : "cmff0tnf00003vn0t3kgzi0u0"
|
||||
},
|
||||
{
|
||||
"id": "cmdr77vbw000bvn5rvpmoq31s",
|
||||
"name": "Bares",
|
||||
"description": "Darmasaba Recycling Stock/Exchange",
|
||||
"link": "http://darmasaba.desa.id/berita/56722-bares"
|
||||
"link": "http://darmasaba.desa.id/berita/56722-bares",
|
||||
"imageId" : "cmff0rr4z0002vn0twp333m2"
|
||||
},
|
||||
{
|
||||
"id": "cmdr7bxtp000evn5rmy85wihx",
|
||||
"name": "Sajjana Dharma Raksaka",
|
||||
"description": "Sajjana Dharma Raksaka",
|
||||
"link": "https://ppid.badungkab.go.id/storage/dokumen/5RS9dldGkrgzMQq6bKdZsqsVRHI8gffWv4PGfb3r.pdf"
|
||||
"link": "https://ppid.badungkab.go.id/storage/dokumen/5RS9dldGkrgzMQq6bKdZsqsVRHI8gffWv4PGfb3r.pdf",
|
||||
"imageId" : "cmff10cwq0009vn0tse8dzu3j"
|
||||
},
|
||||
{
|
||||
"id": "cmdr7dlnk000hvn5r9lur3z35",
|
||||
"name": "PDKT",
|
||||
"description": "Perangkat Desa Kuat Teknologi",
|
||||
"link": "https://darmasaba.desa.id/berita/53752-p-d-k-t"
|
||||
"link": "https://darmasaba.desa.id/berita/53752-p-d-k-t",
|
||||
"imageId" : "cmff1013m0008vn0th7t0d64d"
|
||||
},
|
||||
{
|
||||
"id": "cmdr7ftob000mvn5rfhgdtg8v",
|
||||
"name": "GM",
|
||||
"description": "Galah Melah",
|
||||
"link": "https://darmasaba.desa.id/berita/52880-galah-melah"
|
||||
"link": "https://darmasaba.desa.id/berita/52880-galah-melah",
|
||||
"imageId" : "cmff38cyq000bvn0t9f01cz3f"
|
||||
},
|
||||
{
|
||||
"id": "cmdr7glue000pvn5r6onzslju",
|
||||
"name": "Inovasi Desa Darmasaba",
|
||||
"description": "Inovasi Desa Darmasaba",
|
||||
"link": "https://darmasaba.desa.id/produk-lokal-desa"
|
||||
"link": "https://darmasaba.desa.id/produk-lokal-desa",
|
||||
"imageId" : "cmff0zqvd0007vn0tv6o5hjcq"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"jenisInformasi": "Peraturan Desa",
|
||||
"deskripsi": "Dokumen yang berisi kebijakan dan regulasi desa",
|
||||
"tanggal": "15 Januari 2024"
|
||||
"id": "cmeppcwzk0000vn5exmudcipd",
|
||||
"jenisInformasi": "Potensi Desa",
|
||||
"deskripsi": "<p>“Potensi desa adalah segenap sumber daya alam dan sumber daya manusia yang dimiliki desa sebagai modal dasar yang perlu dikelola dan dikembangkan bagi kelangsungan dan perkembangan desa. Adapun potensi yang dimiliki Desa Darmasaba yaitu:</p><ol><li><p>TPS3R Pudak Mesari</p></li><li><p>Bumdes Pudak Mesari</p></li><li><p>Pertanian</p></li><li><p>Jogging Track Tegeh Aban, Karang Gadon dan Munduk Uma Desa</p></li><li><p>Taman Beji Cengana</p></li><li><p>Dam Tanah Putih</p></li><li><p>Gumuh Sari Water Park</p></li><li><p>UMKM</p></li><li><p>Kawasan Kuliner</p></li><li><p>IKM berbasis Pengolahan Pangan</p></li><li><p>Genteng</p></li><li><p>Peternakan Ikan Lele</p></li><li><p>Pemotongan Daging”</p></li></ol>",
|
||||
"tanggal": "2021-05-25"
|
||||
},
|
||||
{
|
||||
"id": "cmeppieay0001vn5e8qe658ub",
|
||||
"jenisInformasi": "Layanan Surat Keterangan Desa",
|
||||
"deskripsi": "<p>“Desa Darmasaba menyediakan berbagai jenis layanan surat keterangan untuk kebutuhan administratif, antara lain:</p><ul><li><p>Surat Keterangan Domisili Organisasi</p></li><li><p>Surat Keterangan Penghasilan</p></li><li><p>Surat Keterangan Tidak Mampu</p></li><li><p>Surat Keterangan Kelahiran</p></li><li><p>Surat Keterangan Usaha</p></li><li><p>Surat Keterangan Tempat Usaha</p></li><li><p>Surat Keterangan Belum Kawin</p></li><li><p>Surat Keterangan Kelakuan Baik (Pengantar SKCK)</p></li><li><p>Surat Keterangan Kematian</p></li><li><p>Surat Keterangan Perbedaan Biodata Diri</p></li><li><p>Surat Keterangan Yatim/Piatu/Yatim Piatu<br>Untuk surat keterangan lainnya, masyarakat dapat berkonsultasi langsung ke kantor Perbekel Darmasaba.”<br><em>(Sumber: Laman Layanan Desa Darmasaba)</em></p></li></ul>",
|
||||
"tanggal": "2025-02-21"
|
||||
}
|
||||
]
|
||||
10
prisma/data/ppid/ikm/jenis-kelamin/jenis-kelamin.json
Normal file
@@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"id": "cme8bt5o5000007lb9xp11unb",
|
||||
"name": "Laki-laki"
|
||||
},
|
||||
{
|
||||
"id": "cme8btctl000107lbh2hocgg8",
|
||||
"name": "Perempuan"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"id": "cme8buup6000207lb54q9b0az",
|
||||
"name": "Sangat Baik"
|
||||
},
|
||||
{
|
||||
"id": "cme8bv15o000307lbft9b0vzy",
|
||||
"name": "Baik"
|
||||
},
|
||||
{
|
||||
"id": "cme8bvjvu000507lbgfsveog6",
|
||||
"name": "Kurang Baik"
|
||||
},
|
||||
{
|
||||
"id": "cme8bvvm6000607lbh6rn2ubm",
|
||||
"name": "Sangat Kurang Baik"
|
||||
}
|
||||
]
|
||||
14
prisma/data/ppid/ikm/umur-responden/umur-responden.json
Normal file
@@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"id": "cme8bwgwu000707lbawc6fz3a",
|
||||
"name": "Muda"
|
||||
},
|
||||
{
|
||||
"id": "cme8hnx09000b07jl3ipifb1k",
|
||||
"name": "Dewasa"
|
||||
},
|
||||
{
|
||||
"id": "cme8ho7dv000c07jlc7lr4b4w",
|
||||
"name": "Lansia"
|
||||
}
|
||||
]
|
||||
@@ -1,6 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": "cmdpm429r0000vnndkcwslt0h",
|
||||
"name": "warga"
|
||||
}
|
||||
]
|
||||
29
prisma/data/user/roles.json
Normal file
@@ -0,0 +1,29 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"name": "ADMIN DESA",
|
||||
"description": "Administrator Desa",
|
||||
"permissions": ["manage_users", "manage_content", "view_reports"],
|
||||
"isActive": true,
|
||||
"createdAt": "2025-09-01T00:00:00.000Z",
|
||||
"updatedAt": "2025-09-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "ADMIN KESEHATAN",
|
||||
"description": "Administrator Bidang Kesehatan",
|
||||
"permissions": ["manage_health_data", "view_reports"],
|
||||
"isActive": true,
|
||||
"createdAt": "2025-09-01T00:00:00.000Z",
|
||||
"updatedAt": "2025-09-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"name": "ADMIN SEKOLAH",
|
||||
"description": "Administrator Sekolah",
|
||||
"permissions": ["manage_school_data", "view_reports"],
|
||||
"isActive": true,
|
||||
"createdAt": "2025-09-01T00:00:00.000Z",
|
||||
"updatedAt": "2025-09-01T00:00:00.000Z"
|
||||
}
|
||||
]
|
||||
32
prisma/data/user/users.json
Normal file
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"nama": "Admin Desa",
|
||||
"nomor": "089647037426",
|
||||
"roleId": "1",
|
||||
"isActive": true,
|
||||
"lastLogin": "2025-08-31T10:00:00.000Z",
|
||||
"createdAt": "2025-09-01T00:00:00.000Z",
|
||||
"updatedAt": "2025-09-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"nama": "Admin Kesehatan",
|
||||
"nomor": "082339004198",
|
||||
"roleId": "2",
|
||||
"isActive": true,
|
||||
"lastLogin": null,
|
||||
"createdAt": "2025-09-01T00:00:00.000Z",
|
||||
"updatedAt": "2025-09-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"nama": "Admin Sekolah",
|
||||
"nomor": "085237157222",
|
||||
"roleId": "3",
|
||||
"isActive": true,
|
||||
"lastLogin": null,
|
||||
"createdAt": "2025-09-01T00:00:00.000Z",
|
||||
"updatedAt": "2025-09-01T00:00:00.000Z"
|
||||
}
|
||||
]
|
||||
@@ -50,23 +50,22 @@ model AppMenuChild {
|
||||
// ========================================= FILE STORAGE ========================================= //
|
||||
|
||||
model FileStorage {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
realName String
|
||||
path String
|
||||
mimeType String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
isActive Boolean @default(true)
|
||||
link String
|
||||
category String // "image" / "document" / "other"
|
||||
Berita Berita[]
|
||||
PotensiDesa PotensiDesa[]
|
||||
Posyandu Posyandu[]
|
||||
StrukturPPID StrukturPPID[]
|
||||
GalleryFoto GalleryFoto[]
|
||||
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
realName String
|
||||
path String
|
||||
mimeType String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
isActive Boolean @default(true)
|
||||
link String
|
||||
category String // "image" / "document" / "other"
|
||||
Berita Berita[]
|
||||
PotensiDesa PotensiDesa[]
|
||||
Posyandu Posyandu[]
|
||||
StrukturPPID StrukturPPID[]
|
||||
GalleryFoto GalleryFoto[]
|
||||
Pelapor Pelapor[]
|
||||
Penghargaan Penghargaan[]
|
||||
ProfileDesaImage ProfileDesaImage[]
|
||||
@@ -82,11 +81,8 @@ model FileStorage {
|
||||
PelayananSuratKeteranganImage PelayananSuratKeterangan[] @relation("PelayananSuratKeteranganImage")
|
||||
PelayananSuratKeteranganImage2 PelayananSuratKeterangan[] @relation("PelayananSuratKeteranganImage2")
|
||||
PasarDesa PasarDesa[]
|
||||
KontakDaruratKeamanan KontakDaruratKeamanan[]
|
||||
KontakItem KontakItem[]
|
||||
Pegawai Pegawai[]
|
||||
DesaDigital DesaDigital[]
|
||||
KolaborasiInovasi KolaborasiInovasi[]
|
||||
InfoTekno InfoTekno[]
|
||||
PengaduanMasyarakat PengaduanMasyarakat[]
|
||||
KegiatanDesa KegiatanDesa[]
|
||||
@@ -94,14 +90,17 @@ model FileStorage {
|
||||
PejabatDesa PejabatDesa[]
|
||||
MediaSosial MediaSosial[]
|
||||
DesaAntiKorupsi DesaAntiKorupsi[]
|
||||
SDGSDesa SDGSDesa[]
|
||||
SDGSDesa SdgsDesa[]
|
||||
APBDesImage APBDes[] @relation("APBDesImage")
|
||||
APBDesFile APBDes[] @relation("APBDesFile")
|
||||
PrestasiDesa PrestasiDesa[]
|
||||
DataPerpustakaan DataPerpustakaan[]
|
||||
PegawaiPPID PegawaiPPID[]
|
||||
PerbekelDariMasaKeMasa PerbekelDariMasaKeMasa[]
|
||||
|
||||
DataPerpustakaan DataPerpustakaan[]
|
||||
MitraKolaborasi MitraKolaborasi[]
|
||||
|
||||
PegawaiPPID PegawaiPPID[]
|
||||
ArtikelKesehatan ArtikelKesehatan[]
|
||||
}
|
||||
|
||||
//========================================= MENU LANDING PAGE ========================================= //
|
||||
@@ -169,9 +168,9 @@ model KategoriDesaAntiKorupsi {
|
||||
}
|
||||
|
||||
//========================================= SDGS Desa ========================================= //
|
||||
model SDGSDesa {
|
||||
model SdgsDesa {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
name String
|
||||
jumlah String
|
||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||
imageId String?
|
||||
@@ -184,7 +183,7 @@ model SDGSDesa {
|
||||
//========================================= APBDes ========================================= //
|
||||
model APBDes {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
name String
|
||||
jumlah String
|
||||
image FileStorage? @relation("APBDesImage", fields: [imageId], references: [id])
|
||||
imageId String?
|
||||
@@ -199,12 +198,12 @@ model APBDes {
|
||||
//========================================= PRESTASI DESA ========================================= //
|
||||
model PrestasiDesa {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
name String
|
||||
deskripsi String @db.Text
|
||||
kategori KategoriPrestasiDesa @relation(fields: [kategoriId], references: [id])
|
||||
kategoriId String
|
||||
image FileStorage @relation(fields: [imageId], references: [id])
|
||||
imageId String
|
||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||
imageId String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
@@ -221,6 +220,53 @@ model KategoriPrestasiDesa {
|
||||
PrestasiDesa PrestasiDesa[]
|
||||
}
|
||||
|
||||
//========================================= INDEKS KEPUASAAN MASYARAKAT ========================================= //
|
||||
model Responden {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
tanggal DateTime @db.Date // misal: 2025-05-01
|
||||
jenisKelamin JenisKelaminResponden @relation(fields: [jenisKelaminId], references: [id])
|
||||
jenisKelaminId String
|
||||
rating PilihanRatingResponden @relation(fields: [ratingId], references: [id])
|
||||
ratingId String
|
||||
kelompokUmur UmurResponden @relation(fields: [kelompokUmurId], references: [id])
|
||||
kelompokUmurId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model JenisKelaminResponden {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
Responden Responden[]
|
||||
}
|
||||
|
||||
model PilihanRatingResponden {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
Responden Responden[]
|
||||
}
|
||||
|
||||
model UmurResponden {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
Responden Responden[]
|
||||
}
|
||||
|
||||
//========================================= MENU PPID ========================================= //
|
||||
|
||||
//========================================= STRUKTUR PPID ========================================= //
|
||||
@@ -247,6 +293,9 @@ model PosisiOrganisasiPPID {
|
||||
pegawai PegawaiPPID[]
|
||||
strukturOrganisasi StrukturPPID[] // Relasi balik
|
||||
parentId String?
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
parent PosisiOrganisasiPPID? @relation("Parent", fields: [parentId], references: [id])
|
||||
children PosisiOrganisasiPPID[] @relation("Parent")
|
||||
}
|
||||
@@ -508,6 +557,19 @@ model ProfilPerbekel {
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model PerbekelDariMasaKeMasa {
|
||||
id String @id @default(cuid())
|
||||
nama String @db.Text
|
||||
periode String @db.Text
|
||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||
imageId String?
|
||||
daerah String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
// ========================================= BERITA ========================================= //
|
||||
model Berita {
|
||||
id String @id @default(cuid())
|
||||
@@ -853,26 +915,56 @@ model PendaftaranJadwalKegiatan {
|
||||
|
||||
// ========================================= PERSENTASE KELAHIRAN & KEMATIAN ========================================= //
|
||||
model DataKematian_Kelahiran {
|
||||
id String @id @default(cuid())
|
||||
tahun String
|
||||
kematianKasar String
|
||||
kematianBayi String
|
||||
kelahiranKasar String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
id String @id @default(cuid())
|
||||
kematian Kematian @relation(fields: [kematianId], references: [id])
|
||||
kematianId String
|
||||
kelahiran Kelahiran @relation(fields: [kelahiranId], references: [id])
|
||||
kelahiranId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model Kelahiran {
|
||||
id String @id @default(cuid())
|
||||
nama String
|
||||
tanggal DateTime
|
||||
jenisKelamin String
|
||||
alamat String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
DataKematian_Kelahiran DataKematian_Kelahiran[]
|
||||
}
|
||||
|
||||
model Kematian {
|
||||
id String @id @default(cuid())
|
||||
nama String
|
||||
tanggal DateTime
|
||||
jenisKelamin String
|
||||
alamat String
|
||||
penyebab String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
DataKematian_Kelahiran DataKematian_Kelahiran[]
|
||||
}
|
||||
|
||||
// ========================================= GRAFIK KEPUASAN ========================================= //
|
||||
model GrafikKepuasan {
|
||||
id String @id @default(cuid())
|
||||
label String
|
||||
jumlah String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
id String @id @default(cuid())
|
||||
nama String
|
||||
tanggal DateTime
|
||||
jenisKelamin String
|
||||
alamat String
|
||||
penyakit String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
// ========================================= ARTIKEL KESEHATAN ========================================= //
|
||||
@@ -880,8 +972,10 @@ model ArtikelKesehatan {
|
||||
id String @id @default(cuid())
|
||||
title String
|
||||
content String
|
||||
introduction Introduction @relation(fields: [introductionId], references: [id])
|
||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||
imageId String?
|
||||
introductionId String
|
||||
introduction Introduction @relation(fields: [introductionId], references: [id])
|
||||
symptom Symptom @relation(fields: [symptomId], references: [id])
|
||||
symptomId String
|
||||
prevention Prevention @relation(fields: [preventionId], references: [id])
|
||||
@@ -969,16 +1063,17 @@ model DoctorSign {
|
||||
|
||||
// ========================================= POSYANDU ========================================= //
|
||||
model Posyandu {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
nomor String
|
||||
deskripsi String
|
||||
image FileStorage @relation(fields: [imageId], references: [id])
|
||||
imageId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
nomor String
|
||||
deskripsi String
|
||||
jadwalPelayanan String
|
||||
image FileStorage @relation(fields: [imageId], references: [id])
|
||||
imageId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
// ========================================= PUSKESMAS ========================================= //
|
||||
@@ -1123,71 +1218,51 @@ model LayananPolsek {
|
||||
|
||||
// ========================================= KONTAK DARURAT ========================================= //
|
||||
model KontakDaruratKeamanan {
|
||||
id String @id @default(uuid())
|
||||
nama String // contoh: "Layanan Darurat", "Fasilitas Kesehatan"
|
||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||
imageId String?
|
||||
kontakItems KontakItem[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
id String @id @default(uuid())
|
||||
nama String
|
||||
icon String
|
||||
kategori KontakItem @relation(fields: [kategoriId], references: [id])
|
||||
kategoriId String
|
||||
kontakItems KontakDaruratToItem[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model KontakItem {
|
||||
id String @id @default(uuid())
|
||||
nama String // contoh: "Polisi", "Ambulans", "Puskesmas Darmasaba"
|
||||
nomorTelepon String
|
||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||
imageId String?
|
||||
kategori KontakDaruratKeamanan @relation(fields: [kategoriId], references: [id])
|
||||
kategoriId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
id String @id @default(uuid())
|
||||
nama String
|
||||
nomorTelepon String
|
||||
icon String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
KontakDaruratToItem KontakDaruratToItem[]
|
||||
KontakDaruratKeamanan KontakDaruratKeamanan[]
|
||||
}
|
||||
|
||||
model KontakDaruratToItem {
|
||||
id String @id @default(uuid())
|
||||
kontakDaruratId String
|
||||
kontakItemId String
|
||||
kontakDarurat KontakDaruratKeamanan @relation(fields: [kontakDaruratId], references: [id])
|
||||
kontakItem KontakItem @relation(fields: [kontakItemId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
// ========================================= PENCEGAHAN KRIMINALITAS ========================================= //
|
||||
model PencegahanKriminalitas {
|
||||
id String @id @default(cuid())
|
||||
programKeamanan ProgramKeamanan @relation(fields: [programKeamananId], references: [id])
|
||||
programKeamananId String
|
||||
tipsKeamanan TipsKeamanan @relation(fields: [tipsKeamananId], references: [id])
|
||||
tipsKeamananId String
|
||||
videoKeamanan VideoKeamanan @relation(fields: [videoKeamananId], references: [id])
|
||||
videoKeamananId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model ProgramKeamanan {
|
||||
id String @id @default(cuid())
|
||||
nama String // contoh: "Ronda Malam"
|
||||
deskripsi String? // jika mau tambahkan info detail
|
||||
slug String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
PencegahanKriminalitas PencegahanKriminalitas[]
|
||||
}
|
||||
|
||||
model TipsKeamanan {
|
||||
id String @id @default(cuid())
|
||||
judul String
|
||||
konten String
|
||||
slug String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
PencegahanKriminalitas PencegahanKriminalitas[]
|
||||
}
|
||||
|
||||
model VideoKeamanan {
|
||||
id String @id @default(cuid())
|
||||
judul String
|
||||
deskripsi String?
|
||||
videoUrl String // link youtube atau embed url
|
||||
slug String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
PencegahanKriminalitas PencegahanKriminalitas[]
|
||||
id String @id @default(cuid())
|
||||
judul String
|
||||
deskripsi String
|
||||
deskripsiSingkat String
|
||||
linkVideo String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
// ========================================= LAPORAN PUBLIK ========================================= //
|
||||
@@ -1196,11 +1271,13 @@ model LaporanPublik {
|
||||
judul String
|
||||
lokasi String
|
||||
tanggalWaktu DateTime
|
||||
status StatusLaporan
|
||||
status StatusLaporan @default(Proses)
|
||||
penanganan PenangananLaporanPublik[]
|
||||
kronologi String? // Optional, bisa diisi detail kronologi
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model PenangananLaporanPublik {
|
||||
@@ -1308,6 +1385,9 @@ model PosisiOrganisasi {
|
||||
pegawai Pegawai[]
|
||||
strukturOrganisasi StrukturOrganisasi[] // Relasi balik
|
||||
StrukturOrganisasiPPID StrukturOrganisasiPPID[]
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("posisi_organisasi")
|
||||
}
|
||||
@@ -1376,7 +1456,7 @@ model ProgramKemiskinan {
|
||||
id String @id @default(uuid())
|
||||
nama String
|
||||
deskripsi String
|
||||
ikonUrl String?
|
||||
icon String
|
||||
isActive Boolean @default(true)
|
||||
statistikId String? @unique
|
||||
statistik StatistikKemiskinan? @relation(fields: [statistikId], references: [id])
|
||||
@@ -1546,18 +1626,27 @@ model ProgramKreatif {
|
||||
|
||||
// ========================================= KOLABORASI INOVASI ========================================= //
|
||||
model KolaborasiInovasi {
|
||||
id String @id @default(cuid())
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
tahun Int
|
||||
slug String @db.Text //deskripsi singkat
|
||||
deskripsi String @db.Text //deskripsi panjang
|
||||
slug String @db.Text //deskripsi singkat
|
||||
deskripsi String @db.Text //deskripsi panjang
|
||||
kolaborator String
|
||||
image FileStorage @relation(fields: [imageId], references: [id])
|
||||
imageId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model MitraKolaborasi {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||
imageId String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
// ========================================= INFO TEKHNOLOGI TEPAT GUNA ========================================= //
|
||||
@@ -2001,26 +2090,66 @@ model KategoriBuku {
|
||||
DataPerpustakaan DataPerpustakaan[]
|
||||
}
|
||||
|
||||
// ========================================= USER ========================================= //
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
nama String
|
||||
email String @unique
|
||||
password String
|
||||
role Role @relation(fields: [roleId], references: [id])
|
||||
roleId String
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
id String @id @default(cuid())
|
||||
username String
|
||||
nomor String @unique
|
||||
role Role @relation(fields: [roleId], references: [id])
|
||||
roleId String @default("1")
|
||||
instansi String?
|
||||
UserSession UserSession? // Nama instansi (Puskesmas, Sekolah, dll)
|
||||
isActive Boolean @default(true)
|
||||
lastLogin DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
}
|
||||
|
||||
model Role {
|
||||
id String @id @default(cuid())
|
||||
name String @unique // ADMIN_DESA, ADMIN_KESEHATAN, ADMIN_SEKOLAH
|
||||
description String?
|
||||
permissions Json // Menyimpan permission dalam format JSON
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
users User[]
|
||||
|
||||
@@map("roles")
|
||||
}
|
||||
|
||||
model KodeOtp {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
User User[]
|
||||
nomor String
|
||||
otp Int
|
||||
}
|
||||
|
||||
// Tabel untuk menyimpan permission
|
||||
model Permission {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
description String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("permissions")
|
||||
}
|
||||
|
||||
model UserSession {
|
||||
id String @id @default(cuid())
|
||||
token String
|
||||
expires DateTime?
|
||||
active Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
User User @relation(fields: [userId], references: [id])
|
||||
userId String @unique
|
||||
}
|
||||
|
||||
// ========================================= DATA PENDIDIKAN ========================================= //
|
||||
|
||||
519
prisma/seed.ts
@@ -1,65 +1,160 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import prisma from "@/lib/prisma";
|
||||
import profilePejabatDesa from "./data/landing-page/profile/profile.json";
|
||||
import penghargaan from "./data/landing-page/penghargaan/penghargaan.json";
|
||||
import programInovasi from "./data/landing-page/profile/programInovasi.json";
|
||||
import mediaSosial from "./data/landing-page/profile/mediaSosial.json";
|
||||
import desaAntiKorupsi from "./data/landing-page/desa-anti-korupsi/desaantiKorpusi.json";
|
||||
import kategoriDesaAntiKorupsi from "./data/landing-page/desa-anti-korupsi/kategoriDesaAntiKorupsi.json";
|
||||
import sdgsDesa from "./data/landing-page/sdgs-desa/sdgs-desa.json";
|
||||
import apbdes from "./data/landing-page/apbdes/apbdes.json";
|
||||
import pelayananSuratKeterangan from "./data/desa/layanan/pelayananSuratKeterangan.json";
|
||||
import categoryPengumuman from "./data/category-pengumuman.json";
|
||||
import kategoriBerita from "./data/kategori-berita.json";
|
||||
import caraMemperolehInformasi from "./data/list-caraMemperolehInformasi.json";
|
||||
import caraMemperolehSalinanInformasi from "./data/list-caraMemperolehSalinanInformasi.json";
|
||||
import jenisInformasiDiminta from "./data/list-jenisInfromasi.json";
|
||||
import layanan from "./data/list-layanan.json";
|
||||
import potensi from "./data/list-potensi.json";
|
||||
import dasarHukumPPID from "./data/ppid/dasar-hukum-ppid/dasarhukumPPID.json";
|
||||
import kategoriPrestasiDesa from "./data/landing-page/prestasi-desa/kategori-prestasi.json";
|
||||
import prestasiDesa from "./data/landing-page/prestasi-desa/prestasi-desa.json";
|
||||
import penghargaan from "./data/landing-page/penghargaan/penghargaan.json";
|
||||
import profilePPID from "./data/ppid/profile-ppid/profilePPid.json";
|
||||
import pegawaiPPID from "./data/ppid/struktur-ppid/pegawai-PPID.json";
|
||||
import posisiOrganisasiPPID from "./data/ppid/struktur-ppid/posisi-organisasi-PPID.json";
|
||||
import visiMisiPPID from "./data/ppid/visi-misi-ppid/visimisiPPID.json";
|
||||
import dasarHukumPPID from "./data/ppid/dasar-hukum-ppid/dasarhukumPPID.json";
|
||||
import jenisKelamin from "./data/ppid/ikm/jenis-kelamin/jenis-kelamin.json";
|
||||
import daftarInformasiPublik from "./data/ppid/daftar-informasi-publik-desa-darmasaba/daftarInformasi.json";
|
||||
import pilihanRatingResponden from "./data/ppid/ikm/pilihan-rating-responden/rating-responden.json";
|
||||
import umurResponden from "./data/ppid/ikm/umur-responden/umur-responden.json";
|
||||
import categoryPengumuman from "./data/category-pengumuman.json";
|
||||
import pelayananPerizinanBerusaha from "./data/desa/layanan/pelayananPerizinanBerusaha.json";
|
||||
import pelayananSuratKeterangan from "./data/desa/layanan/pelayananSuratKeterangan.json";
|
||||
import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSaktiDesa.json";
|
||||
import pelayananPendudukNonPermanen from "./data/desa/layanan/pelayanaPendudukNonPermanen.json";
|
||||
import sejarahDesa from "./data/desa/profile/sejarah_desa.json";
|
||||
import visiMisiDesa from "./data/desa/profile/visi_misi_desa.json";
|
||||
import lambangDesa from "./data/desa/profile/lambang_desa.json";
|
||||
import maskotDesa from "./data/desa/profile/maskot_desa.json";
|
||||
import profilPerbekel from "./data/desa/profile/profil_perbekel.json";
|
||||
import sejarahDesa from "./data/desa/profile/sejarah_desa.json";
|
||||
import visiMisiDesa from "./data/desa/profile/visi_misi_desa.json";
|
||||
import detailDataPengangguran from "./data/ekonomi/jumlah-pengangguran/detail-data-pengangguran.json";
|
||||
import kategoriProduk from "./data/ekonomi/pasar-desa/kategori-produk.json";
|
||||
import hubunganOrganisasi from "./data/ekonomi/struktur-organisasi/hubungan-organisasi.json";
|
||||
import posisiOrganisasi from "./data/ekonomi/struktur-organisasi/posisi-organisasi.json";
|
||||
import pegawai from "./data/ekonomi/struktur-organisasi/pegawai.json";
|
||||
import detailDataPengangguran from "./data/ekonomi/jumlah-pengangguran/detail-data-pengangguran.json";
|
||||
import tujuanEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/tujuan-edukasi-lingkungan.json";
|
||||
import materiEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/materi-edukasi-yang-diberikan.json";
|
||||
import posisiOrganisasi from "./data/ekonomi/struktur-organisasi/posisi-organisasi.json";
|
||||
import kategoriBerita from "./data/kategori-berita.json";
|
||||
import contohEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/contoh-kegiatan-di-desa-darmasaba.json";
|
||||
import nilaiKonservasiAdat from "./data/lingkungan/konservasi-adat-bali/nilai-konservasi-adat.json";
|
||||
import materiEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/materi-edukasi-yang-diberikan.json";
|
||||
import tujuanEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/tujuan-edukasi-lingkungan.json";
|
||||
import bentukKonservasiBerdasarkanAdat from "./data/lingkungan/konservasi-adat-bali/bentuk-konservasi.json";
|
||||
import filosofiTriHita from "./data/lingkungan/konservasi-adat-bali/filosofi-tri-hita.json";
|
||||
import tujuanProgram from "./data/pendidikan/program-pendidikan-anak/tujuan-program.json";
|
||||
import nilaiKonservasiAdat from "./data/lingkungan/konservasi-adat-bali/nilai-konservasi-adat.json";
|
||||
import caraMemperolehInformasi from "./data/list-caraMemperolehInformasi.json";
|
||||
import caraMemperolehSalinanInformasi from "./data/list-caraMemperolehSalinanInformasi.json";
|
||||
import jenisInformasiDiminta from "./data/list-jenisInfromasi.json";
|
||||
import potensi from "./data/list-potensi.json";
|
||||
import fasilitasBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan.json";
|
||||
import lokasiJadwalBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal.json";
|
||||
import tujuanBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/tujuan-bimbingan-belajar-desa.json";
|
||||
import jenisProgramYangDiselenggarakan from "./data/pendidikan/pendidikan-non-formal/jenis-program-yang-diselenggarakan.json";
|
||||
import tempatKegiatan from "./data/pendidikan/pendidikan-non-formal/tempat-kegiatan.json";
|
||||
import tujuanProgram2 from "./data/pendidikan/pendidikan-non-formal/tujuan-program2.json";
|
||||
import programUnggulan from "./data/pendidikan/program-pendidikan-anak/program-unggulan.json";
|
||||
import tujuanBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/tujuan-bimbingan-belajar-desa.json";
|
||||
import lokasiJadwalBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal.json";
|
||||
import fasilitasBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan.json";
|
||||
import tempatKegiatan from "./data/pendidikan/pendidikan-non-formal/tempat-kegiatan.json";
|
||||
import jenisProgramYangDiselenggarakan from "./data/pendidikan/pendidikan-non-formal/jenis-program-yang-diselenggarakan.json";
|
||||
import posisiOrganisasiPPID from "./data/ppid/struktur-ppid/posisi-organisasi-PPID.json";
|
||||
import pegawaiPPID from "./data/ppid/struktur-ppid/pegawai-PPID.json";
|
||||
import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSaktiDesa.json";
|
||||
import tujuanProgram from "./data/pendidikan/program-pendidikan-anak/tujuan-program.json";
|
||||
import roles from "./data/user/roles.json";
|
||||
import users from "./data/user/users.json";
|
||||
import fileStorage from "./data/file-storage.json";
|
||||
|
||||
(async () => {
|
||||
// =========== USER & ROLE ===========
|
||||
// In your seed.ts
|
||||
// =========== ROLES ===========
|
||||
console.log("🔄 Seeding roles...");
|
||||
for (const r of roles) {
|
||||
await prisma.role.upsert({
|
||||
where: { id: r.id },
|
||||
update: {
|
||||
name: r.name,
|
||||
description: r.description,
|
||||
permissions: r.permissions,
|
||||
isActive: r.isActive,
|
||||
},
|
||||
create: {
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
description: r.description,
|
||||
permissions: r.permissions,
|
||||
isActive: r.isActive,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Roles seeded");
|
||||
|
||||
// =========== USERS ===========
|
||||
console.log("🔄 Seeding users...");
|
||||
for (const u of users) {
|
||||
// First verify the role exists
|
||||
const roleExists = await prisma.role.findUnique({
|
||||
where: { id: u.roleId },
|
||||
});
|
||||
|
||||
if (!roleExists) {
|
||||
console.error(`❌ Role with id ${u.roleId} not found for user ${u.nama}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
await prisma.user.upsert({
|
||||
where: { id: u.id },
|
||||
update: {
|
||||
username: u.nama,
|
||||
nomor: u.nomor,
|
||||
roleId: u.roleId,
|
||||
isActive: u.isActive,
|
||||
},
|
||||
create: {
|
||||
id: u.id,
|
||||
username: u.nama,
|
||||
nomor: u.nomor,
|
||||
roleId: u.roleId,
|
||||
isActive: u.isActive,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ Users seeded");
|
||||
|
||||
// =========== FILE STORAGE ===========
|
||||
console.log("🔄 Seeding file storage...");
|
||||
for (const f of fileStorage) {
|
||||
await prisma.fileStorage.upsert({
|
||||
where: { id: f.id },
|
||||
update: {
|
||||
name: f.name,
|
||||
realName: f.realName,
|
||||
path: f.path,
|
||||
mimeType: f.mimeType,
|
||||
link: f.link,
|
||||
category: f.category,
|
||||
},
|
||||
create: {
|
||||
id: f.id,
|
||||
name: f.name,
|
||||
realName: f.realName,
|
||||
path: f.path,
|
||||
mimeType: f.mimeType,
|
||||
link: f.link,
|
||||
category: f.category,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ File storage seeded");
|
||||
// =========== LANDING PAGE ===========
|
||||
// =========== PROFILE ===========
|
||||
// =========== SUBMENU PROFILE ===========
|
||||
// =========== PROFILE PEJABAT DESA ===========
|
||||
for (const p of profilePejabatDesa) {
|
||||
await prisma.pejabatDesa.upsert({
|
||||
where: { id: p.id },
|
||||
update: {
|
||||
name: p.name,
|
||||
position: p.position,
|
||||
imageId: p.imageId,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
position: p.position,
|
||||
imageId: p.imageId,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -69,18 +164,35 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
|
||||
// =========== PROGRAM INOVASI ===========
|
||||
for (const p of programInovasi) {
|
||||
let imageId: string | null = null;
|
||||
|
||||
if (p.imageId) {
|
||||
const imageExists = await prisma.fileStorage.findUnique({
|
||||
where: { id: p.imageId },
|
||||
});
|
||||
|
||||
if (imageExists) {
|
||||
imageId = p.imageId;
|
||||
} else {
|
||||
console.warn(
|
||||
`⚠️ imageId ${p.imageId} tidak ditemukan untuk ProgramInovasi ${p.name}`
|
||||
);
|
||||
}
|
||||
}
|
||||
await prisma.programInovasi.upsert({
|
||||
where: { id: p.id },
|
||||
update: {
|
||||
name: p.name,
|
||||
description: p.description,
|
||||
link: p.link,
|
||||
imageId: p.imageId,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
description: p.description,
|
||||
link: p.link,
|
||||
imageId: p.imageId,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -93,16 +205,102 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
update: {
|
||||
name: p.name,
|
||||
iconUrl: p.iconUrl,
|
||||
imageId: p.imageId,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
iconUrl: p.iconUrl,
|
||||
imageId: p.imageId,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("media sosial success ...");
|
||||
|
||||
// =========== SUBMENU DESA ANTI KORUPSI ===========
|
||||
// =========== KATEGORI DESA ANTI KORUPSI ===========
|
||||
for (const k of kategoriDesaAntiKorupsi) {
|
||||
await prisma.kategoriDesaAntiKorupsi.upsert({
|
||||
where: { id: k.id },
|
||||
update: {
|
||||
name: k.name,
|
||||
},
|
||||
create: {
|
||||
id: k.id,
|
||||
name: k.name,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("kategori desa anti korupsi success ...");
|
||||
|
||||
// =========== DESA ANTI KORUPSI ===========
|
||||
for (const p of desaAntiKorupsi) {
|
||||
await prisma.desaAntiKorupsi.upsert({
|
||||
where: { id: p.id },
|
||||
update: {
|
||||
name: p.name,
|
||||
deskripsi: p.deskripsi,
|
||||
kategoriId: p.kategoriId,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
deskripsi: p.deskripsi,
|
||||
kategoriId: p.kategoriId,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("desa anti korupsi success ...");
|
||||
|
||||
// =========== KATEGORI DESA ANTI KORUPSI ===========
|
||||
for (const p of kategoriDesaAntiKorupsi) {
|
||||
await prisma.kategoriDesaAntiKorupsi.upsert({
|
||||
where: { id: p.id },
|
||||
update: {
|
||||
name: p.name,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("desa anti korupsi success ...");
|
||||
|
||||
// =========== KATEGORI PRESTASI DESA===========
|
||||
for (const c of kategoriPrestasiDesa) {
|
||||
await prisma.kategoriPrestasiDesa.upsert({
|
||||
where: { id: c.id },
|
||||
update: {
|
||||
name: c.name,
|
||||
},
|
||||
create: {
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("kategori prestasi desa success ...");
|
||||
|
||||
// =========== PRESTASI DESA===========
|
||||
for (const p of prestasiDesa) {
|
||||
await prisma.prestasiDesa.upsert({
|
||||
where: { id: p.id },
|
||||
update: {
|
||||
name: p.name,
|
||||
deskripsi: p.deskripsi,
|
||||
kategoriId: p.kategoriId,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
deskripsi: p.deskripsi,
|
||||
kategoriId: p.kategoriId,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("prestasi desa success ...");
|
||||
|
||||
// =========== PENGHARGAAN ===========
|
||||
for (const p of penghargaan) {
|
||||
await prisma.penghargaan.upsert({
|
||||
@@ -122,8 +320,8 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
}
|
||||
console.log("penghargaan success ...");
|
||||
|
||||
// =========== LAYANAN DESA ===========
|
||||
for (const p of pelayananSuratKeterangan) {
|
||||
// =========== LAYANAN DESA ===========
|
||||
for (const p of pelayananSuratKeterangan) {
|
||||
await prisma.pelayananSuratKeterangan.upsert({
|
||||
where: { id: p.id },
|
||||
update: {
|
||||
@@ -157,30 +355,10 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
}
|
||||
console.log("pelayanan surat keterangan success ...");
|
||||
|
||||
// =========== LAYANAN ===========
|
||||
for (const l of layanan) {
|
||||
await prisma.layanan.upsert({
|
||||
where: {
|
||||
name: l.name,
|
||||
},
|
||||
update: {
|
||||
name: l.name,
|
||||
},
|
||||
create: {
|
||||
name: l.name,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("layanan success ...");
|
||||
|
||||
// =========== SDGSDesa ===========
|
||||
for (const l of sdgsDesa) {
|
||||
await prisma.sDGSDesa.upsert({
|
||||
where: {
|
||||
name: l.name,
|
||||
jumlah: l.jumlah,
|
||||
},
|
||||
await prisma.sdgsDesa.upsert({
|
||||
where: { id: l.id },
|
||||
update: {
|
||||
name: l.name,
|
||||
jumlah: l.jumlah,
|
||||
@@ -198,8 +376,7 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
for (const l of apbdes) {
|
||||
await prisma.aPBDes.upsert({
|
||||
where: {
|
||||
name: l.name,
|
||||
jumlah: l.jumlah,
|
||||
id: l.id,
|
||||
},
|
||||
update: {
|
||||
name: l.name,
|
||||
@@ -214,6 +391,9 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
|
||||
console.log("sdgs desa success ...");
|
||||
|
||||
// =========== MENU DESA ===========
|
||||
// =========== SUBMENU PROFILE ===========
|
||||
// =========== SEJARAH DESA ===========
|
||||
for (const l of sejarahDesa) {
|
||||
await prisma.sejarahDesa.upsert({
|
||||
where: {
|
||||
@@ -233,6 +413,7 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
|
||||
console.log("sejarah desa success ...");
|
||||
|
||||
// =========== MASKOT DESA ===========
|
||||
for (const l of maskotDesa) {
|
||||
await prisma.maskotDesa.upsert({
|
||||
where: {
|
||||
@@ -252,6 +433,7 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
|
||||
console.log("maskot desa success ...");
|
||||
|
||||
// =========== LAMBANG DESA ===========
|
||||
for (const l of lambangDesa) {
|
||||
await prisma.lambangDesa.upsert({
|
||||
where: {
|
||||
@@ -271,6 +453,7 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
|
||||
console.log("lambang desa success ...");
|
||||
|
||||
// =========== PROFIL PERBEKEL ===========
|
||||
for (const c of profilPerbekel) {
|
||||
await prisma.profilPerbekel.upsert({
|
||||
where: { id: c.id },
|
||||
@@ -295,6 +478,7 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
"✅ profilePerbekel seeded without imageId (editable later via UI)"
|
||||
);
|
||||
|
||||
// =========== VISI MISI DESA ===========
|
||||
for (const l of visiMisiDesa) {
|
||||
await prisma.visiMisiDesa.upsert({
|
||||
where: {
|
||||
@@ -314,63 +498,134 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
|
||||
console.log("visi misi desa success ...");
|
||||
|
||||
// Flatten the nested array structure for posisiOrganisasiPPID
|
||||
const flattenedPosisiOrganisasiPPID = posisiOrganisasiPPID.flat();
|
||||
// =========== MENU PPID ===========
|
||||
// =========== SUBMENU PROFILE PPID ===========
|
||||
for (const c of profilePPID) {
|
||||
await prisma.profilePPID.upsert({
|
||||
where: { id: c.id },
|
||||
update: {
|
||||
name: c.name,
|
||||
biodata: c.biodata,
|
||||
riwayat: c.riwayat,
|
||||
pengalaman: c.pengalaman,
|
||||
unggulan: c.unggulan,
|
||||
// imageId tidak di-update
|
||||
},
|
||||
create: {
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
biodata: c.biodata,
|
||||
riwayat: c.riwayat,
|
||||
pengalaman: c.pengalaman,
|
||||
unggulan: c.unggulan,
|
||||
// imageId tidak di-create
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ profilePPID seeded without imageId (editable later via UI)");
|
||||
|
||||
// =========== SUBMENU STRUKTUR PPID ===========
|
||||
// =========== POSISI ORGANISASI PPID ===========
|
||||
|
||||
const flattenedPosisi = posisiOrganisasiPPID.flat();
|
||||
|
||||
// ✅ Urutkan berdasarkan hierarki
|
||||
const sortedPosisi = flattenedPosisi.sort((a, b) => a.hierarki - b.hierarki);
|
||||
|
||||
for (const p of sortedPosisi) {
|
||||
console.log(`Seeding: ${p.nama} (id: ${p.id}, parent: ${p.parentId})`);
|
||||
|
||||
if (p.parentId) {
|
||||
const parentExists = flattenedPosisi.some((pos) => pos.id === p.parentId);
|
||||
if (!parentExists) {
|
||||
console.warn(
|
||||
`⚠️ Parent tidak ditemukan: ${p.parentId} untuk ${p.nama}`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (const p of flattenedPosisiOrganisasiPPID) {
|
||||
await prisma.posisiOrganisasiPPID.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
nama: p.nama,
|
||||
deskripsi: p.deskripsi,
|
||||
hierarki: p.hierarki,
|
||||
parentId: p.parentId,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
nama: p.nama,
|
||||
deskripsi: p.deskripsi,
|
||||
hierarki: p.hierarki,
|
||||
parentId: p.parentId,
|
||||
},
|
||||
where: { id: p.id },
|
||||
update: p,
|
||||
create: p,
|
||||
});
|
||||
}
|
||||
console.log("posisi organisasi success ...");
|
||||
console.log("posisi organisasi berhasil");
|
||||
|
||||
// Flatten the nested array structure for pegawaiPPID
|
||||
const flattenedPegawaiPPID = pegawaiPPID.flat();
|
||||
|
||||
for (const p of flattenedPegawaiPPID) {
|
||||
// =========== PEGAWAI PPID ===========
|
||||
const flattenedPegawai = pegawaiPPID.flat();
|
||||
for (const p of flattenedPegawai) {
|
||||
await prisma.pegawaiPPID.upsert({
|
||||
where: { id: p.id },
|
||||
update: p,
|
||||
create: p,
|
||||
});
|
||||
}
|
||||
console.log("pegawai berhasil");
|
||||
|
||||
// =========== SUBMENU VISI MISI PPID ===========
|
||||
|
||||
for (const v of visiMisiPPID) {
|
||||
await prisma.visiMisiPPID.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
id: v.id,
|
||||
},
|
||||
update: {
|
||||
namaLengkap: p.namaLengkap,
|
||||
tanggalMasuk: new Date(p.tanggalMasuk),
|
||||
email: p.email,
|
||||
gelarAkademik: p.gelarAkademik,
|
||||
telepon: p.telepon,
|
||||
alamat: p.alamat,
|
||||
posisiId: p.posisiId,
|
||||
isActive: p.isActive,
|
||||
misi: v.misi,
|
||||
visi: v.visi,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
namaLengkap: p.namaLengkap,
|
||||
tanggalMasuk: new Date(p.tanggalMasuk),
|
||||
email: p.email,
|
||||
gelarAkademik: p.gelarAkademik,
|
||||
telepon: p.telepon,
|
||||
alamat: p.alamat,
|
||||
posisiId: p.posisiId,
|
||||
isActive: p.isActive,
|
||||
id: v.id,
|
||||
misi: v.misi,
|
||||
visi: v.visi,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("pegawai success ...");
|
||||
console.log("visi misi PPID success ...");
|
||||
|
||||
// =========== SUBMENU DASAR HUKUM PPID ===========
|
||||
for (const v of dasarHukumPPID) {
|
||||
await prisma.dasarHukumPPID.upsert({
|
||||
where: {
|
||||
id: v.id,
|
||||
},
|
||||
update: {
|
||||
judul: v.judul,
|
||||
content: v.content,
|
||||
},
|
||||
create: {
|
||||
id: v.id,
|
||||
judul: v.judul,
|
||||
content: v.content,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("dasar hukum PPID success ...");
|
||||
|
||||
// =========== SUBMENU DAFTAR INFORMASI PUBLIK PPID ===========
|
||||
for (const v of daftarInformasiPublik) {
|
||||
// Convert string date to Date object
|
||||
const tanggal = new Date(v.tanggal);
|
||||
|
||||
await prisma.daftarInformasiPublik.upsert({
|
||||
where: {
|
||||
id: v.id,
|
||||
},
|
||||
update: {
|
||||
jenisInformasi: v.jenisInformasi,
|
||||
deskripsi: v.deskripsi,
|
||||
tanggal: tanggal,
|
||||
},
|
||||
create: {
|
||||
id: v.id,
|
||||
jenisInformasi: v.jenisInformasi,
|
||||
deskripsi: v.deskripsi,
|
||||
tanggal: tanggal,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("daftar informasi publik PPID success ...");
|
||||
|
||||
for (const l of pelayananPerizinanBerusaha) {
|
||||
await prisma.pelayananPerizinanBerusaha.upsert({
|
||||
@@ -504,65 +759,53 @@ import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSak
|
||||
}
|
||||
console.log("cara memperoleh salinan informasi success ...");
|
||||
|
||||
for (const c of profilePPID) {
|
||||
await prisma.profilePPID.upsert({
|
||||
where: { id: c.id },
|
||||
update: {
|
||||
name: c.name,
|
||||
biodata: c.biodata,
|
||||
riwayat: c.riwayat,
|
||||
pengalaman: c.pengalaman,
|
||||
unggulan: c.unggulan,
|
||||
// imageId tidak di-update
|
||||
},
|
||||
create: {
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
biodata: c.biodata,
|
||||
riwayat: c.riwayat,
|
||||
pengalaman: c.pengalaman,
|
||||
unggulan: c.unggulan,
|
||||
// imageId tidak di-create
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ profilePPID seeded without imageId (editable later via UI)");
|
||||
|
||||
for (const v of visiMisiPPID) {
|
||||
await prisma.visiMisiPPID.upsert({
|
||||
for (const j of jenisKelamin) {
|
||||
await prisma.jenisKelaminResponden.upsert({
|
||||
where: {
|
||||
id: v.id,
|
||||
id: j.id,
|
||||
},
|
||||
update: {
|
||||
misi: v.misi,
|
||||
visi: v.visi,
|
||||
name: j.name,
|
||||
},
|
||||
create: {
|
||||
id: v.id,
|
||||
misi: v.misi,
|
||||
visi: v.visi,
|
||||
id: j.id,
|
||||
name: j.name,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("visi misi PPID success ...");
|
||||
console.log("jenis kelamin responden success ...");
|
||||
|
||||
for (const v of dasarHukumPPID) {
|
||||
await prisma.dasarHukumPPID.upsert({
|
||||
for (const r of pilihanRatingResponden) {
|
||||
await prisma.pilihanRatingResponden.upsert({
|
||||
where: {
|
||||
id: v.id,
|
||||
id: r.id,
|
||||
},
|
||||
update: {
|
||||
judul: v.judul,
|
||||
content: v.content,
|
||||
name: r.name,
|
||||
},
|
||||
create: {
|
||||
id: v.id,
|
||||
judul: v.judul,
|
||||
content: v.content,
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("dasar hukum PPID success ...");
|
||||
console.log("pilihan rating responden success ...");
|
||||
|
||||
for (const u of umurResponden) {
|
||||
await prisma.umurResponden.upsert({
|
||||
where: {
|
||||
id: u.id,
|
||||
},
|
||||
update: {
|
||||
name: u.name,
|
||||
},
|
||||
create: {
|
||||
id: u.id,
|
||||
name: u.name,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("umur responden success ...");
|
||||
|
||||
for (const k of kategoriProduk) {
|
||||
await prisma.kategoriProduk.upsert({
|
||||
|
||||
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
BIN
public/chatbot-removebg-preview.png
Normal file
|
After Width: | Height: | Size: 303 KiB |
|
Before Width: | Height: | Size: 275 KiB After Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 275 KiB |
@@ -23,6 +23,7 @@ export default function SpashScreen() {
|
||||
<Paper p={"md"} miw={320}>
|
||||
<Flex>
|
||||
<Image
|
||||
loading="lazy"
|
||||
src={images["darmasaba-icon"]}
|
||||
alt="darmasaba"
|
||||
w={100}
|
||||
|
||||
62
src/app/admin/(dashboard)/_com/LeafletMultiMarkerMap.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
'use client';
|
||||
|
||||
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
|
||||
import { LatLngExpression } from 'leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import L from 'leaflet';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
type MarkerData = {
|
||||
position: [number, number];
|
||||
popup: string;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
center: [number, number];
|
||||
markers: MarkerData[];
|
||||
zoom?: number;
|
||||
scrollWheelZoom?: boolean;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
export default function LeafletMultiMarkerMap({
|
||||
center,
|
||||
markers,
|
||||
zoom = 13,
|
||||
scrollWheelZoom = true,
|
||||
className = '',
|
||||
style = { height: '100%', width: '100%', zIndex: 0 },
|
||||
}: Props) {
|
||||
// Fix for default marker icons in Next.js
|
||||
useEffect(() => {
|
||||
delete (L.Icon.Default.prototype as any)._getIconUrl;
|
||||
L.Icon.Default.mergeOptions({
|
||||
iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png',
|
||||
iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png',
|
||||
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png',
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={className} style={style}>
|
||||
<MapContainer
|
||||
center={center as LatLngExpression}
|
||||
zoom={zoom}
|
||||
scrollWheelZoom={scrollWheelZoom}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
{markers.map((marker, index) => (
|
||||
<Marker key={index} position={marker.position as LatLngExpression}>
|
||||
<Popup>{marker.popup}</Popup>
|
||||
</Marker>
|
||||
))}
|
||||
</MapContainer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
100
src/app/admin/(dashboard)/_com/iconMap.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import {
|
||||
IconLeaf,
|
||||
IconTrophy,
|
||||
IconTent,
|
||||
IconChartLine,
|
||||
IconRecycle,
|
||||
IconTruck,
|
||||
IconScale,
|
||||
IconClipboard,
|
||||
IconTrash,
|
||||
IconHomeEco,
|
||||
IconChristmasTreeFilled,
|
||||
IconTrendingUp,
|
||||
IconShieldFilled,
|
||||
IconHome,
|
||||
IconTree,
|
||||
IconDroplet,
|
||||
IconCash,
|
||||
IconSchool,
|
||||
IconShoppingCart,
|
||||
IconHospital,
|
||||
IconAmbulance,
|
||||
IconFiretruck,
|
||||
IconBuilding,
|
||||
IconAlertTriangle,
|
||||
} from '@tabler/icons-react'
|
||||
|
||||
export type IconKey =
|
||||
| 'ekowisata'
|
||||
| 'kompetisi'
|
||||
| 'wisata'
|
||||
| 'ekonomi'
|
||||
| 'sampah'
|
||||
| 'truck'
|
||||
| 'scale'
|
||||
| 'clipboard'
|
||||
| 'trash'
|
||||
| 'lingkunganSehat'
|
||||
| 'sumberOksigen'
|
||||
| 'ekonomiBerkelanjutan'
|
||||
| 'mencegahBencana'
|
||||
| 'rumah'
|
||||
| 'pohon'
|
||||
| 'air'
|
||||
| 'bantuan'
|
||||
| 'pelatihan'
|
||||
| 'subsidi'
|
||||
| 'layananKesehatan'
|
||||
| 'polisi'
|
||||
| 'ambulans'
|
||||
| 'pemadam'
|
||||
| 'rumahSakit'
|
||||
| 'bangunan'
|
||||
| 'darurat'
|
||||
|
||||
|
||||
const iconMap: Record<IconKey, 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
|
||||
}
|
||||
|
||||
type Props = {
|
||||
name: IconKey
|
||||
size?: number
|
||||
color?: string
|
||||
}
|
||||
|
||||
export const IconMapper: React.FC<Props> = ({ name, size = 24, color }) => {
|
||||
const IconComponent = iconMap[name]
|
||||
if (!IconComponent) return null
|
||||
return <IconComponent size={size} color={color} />
|
||||
}
|
||||
@@ -3,16 +3,24 @@
|
||||
|
||||
import { Box, rem, Select } from '@mantine/core';
|
||||
import {
|
||||
IconAlertTriangle,
|
||||
IconAmbulance,
|
||||
IconBuilding,
|
||||
IconCash,
|
||||
IconChartLine,
|
||||
IconChristmasTreeFilled,
|
||||
IconClipboardTextFilled,
|
||||
IconDroplet,
|
||||
IconFiretruck,
|
||||
IconHome,
|
||||
IconHomeEco,
|
||||
IconHospital,
|
||||
IconLeaf,
|
||||
IconRecycle,
|
||||
IconScale,
|
||||
IconSchool,
|
||||
IconShieldFilled,
|
||||
IconShoppingCart,
|
||||
IconTent,
|
||||
IconTrashFilled,
|
||||
IconTree,
|
||||
@@ -32,13 +40,23 @@ const iconMap = {
|
||||
scale: { label: 'Scale', icon: IconScale },
|
||||
clipboard: { label: 'Clipboard', icon: IconClipboardTextFilled },
|
||||
trash: { label: 'Trash', icon: IconTrashFilled },
|
||||
lingkunganSehat: {label: 'Lingkungan Sehat', icon: IconHomeEco},
|
||||
sumberOksigen: {label: 'Sumber Oksigen', icon: IconChristmasTreeFilled},
|
||||
ekonomiBerkelanjutan: {label: 'Ekonomi Berkelanjutan', icon: IconTrendingUp},
|
||||
mencegahBencana: {label: 'Mencegah Bencana', icon: IconShieldFilled},
|
||||
rumah: {label: 'Rumah', icon: IconHome},
|
||||
pohon: {label: 'Pohon', icon: IconTree},
|
||||
air: {label: 'Air', icon: IconDroplet}
|
||||
lingkunganSehat: { label: 'Lingkungan Sehat', icon: IconHomeEco },
|
||||
sumberOksigen: { label: 'Sumber Oksigen', icon: IconChristmasTreeFilled },
|
||||
ekonomiBerkelanjutan: { label: 'Ekonomi Berkelanjutan', icon: IconTrendingUp },
|
||||
mencegahBencana: { label: 'Mencegah Bencana', icon: IconShieldFilled },
|
||||
rumah: { label: 'Rumah', icon: IconHome },
|
||||
pohon: { label: 'Pohon', icon: IconTree },
|
||||
air: { label: 'Air', icon: IconDroplet },
|
||||
bantuan: { label: 'Bantuan', icon: IconCash },
|
||||
pelatihan: { label: 'Pelatihan', icon: IconSchool },
|
||||
subsidi: { label: 'Subsidi', icon: IconShoppingCart },
|
||||
layananKesehatan: { label: 'Layanan Kesehatan', icon: IconHospital },
|
||||
polisi: { label: 'Polisi', icon: IconShieldFilled },
|
||||
ambulans: { label: 'Ambulans', icon: IconAmbulance },
|
||||
pemadam: { label: 'Pemadam', icon: IconFiretruck },
|
||||
rumahSakit: { label: 'Rumah Sakit', icon: IconHospital },
|
||||
bangunan: { label: 'Bangunan', icon: IconBuilding },
|
||||
darurat: { label: 'Darurat', icon: IconAlertTriangle },
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -2,22 +2,30 @@
|
||||
|
||||
import { Box, rem, Select } from '@mantine/core';
|
||||
import {
|
||||
IconAmbulance,
|
||||
IconCash,
|
||||
IconChartLine,
|
||||
IconChristmasTreeFilled,
|
||||
IconClipboardTextFilled,
|
||||
IconDroplet,
|
||||
IconFiretruck,
|
||||
IconHome,
|
||||
IconHomeEco,
|
||||
IconHospital,
|
||||
IconLeaf,
|
||||
IconRecycle,
|
||||
IconScale,
|
||||
IconSchool,
|
||||
IconShieldFilled,
|
||||
IconShoppingCart,
|
||||
IconTent,
|
||||
IconTrashFilled,
|
||||
IconTree,
|
||||
IconTrendingUp,
|
||||
IconTrophy,
|
||||
IconTruckFilled,
|
||||
IconBuilding,
|
||||
IconAlertTriangle
|
||||
} from '@tabler/icons-react';
|
||||
|
||||
const iconMap = {
|
||||
@@ -36,7 +44,17 @@ const iconMap = {
|
||||
mencegahBencana: {label: 'Mencegah Bencana', icon: IconShieldFilled},
|
||||
rumah: {label: 'Rumah', icon: IconHome},
|
||||
pohon: {label: 'Pohon', icon: IconTree},
|
||||
air: {label: 'Air', icon: IconDroplet}
|
||||
air: {label: 'Air', icon: IconDroplet},
|
||||
bantuan: {label: 'Bantuan', icon: IconCash},
|
||||
pelatihan: {label: 'Pelatihan', icon: IconSchool},
|
||||
subsidi: {label: 'Subsidi', icon: IconShoppingCart},
|
||||
layananKesehatan: {label: 'Layanan Kesehatan', icon: IconHospital},
|
||||
polisi: {label: 'Polisi', icon: IconShieldFilled},
|
||||
ambulans: {label: 'Ambulans', icon: IconAmbulance},
|
||||
pemadam: {label: 'Pemadam', icon: IconFiretruck},
|
||||
rumahSakit: {label: 'Rumah Sakit', icon: IconHospital},
|
||||
bangunan: {label: 'Bangunan', icon: IconBuilding},
|
||||
darurat: {label: 'Darurat', icon: IconAlertTriangle},
|
||||
};
|
||||
|
||||
type IconKey = keyof typeof iconMap;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -58,6 +59,8 @@ const berita = proxy({
|
||||
},
|
||||
},
|
||||
|
||||
// State untuk berita utama (hanya 1)
|
||||
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.BeritaGetPayload<{
|
||||
@@ -70,38 +73,43 @@ const berita = proxy({
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
|
||||
async load(page = 1, limit = 10) {
|
||||
berita.findMany.loading = true;
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "", kategori = "") => {
|
||||
berita.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
berita.findMany.page = page;
|
||||
berita.findMany.search = search;
|
||||
|
||||
try {
|
||||
const res = await ApiFetch.api.desa.berita["find-many"].get({
|
||||
query: {
|
||||
page,
|
||||
limit,
|
||||
},
|
||||
});
|
||||
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
if (kategori) query.kategori = kategori;
|
||||
|
||||
const res = await ApiFetch.api.desa.berita["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
berita.findMany.data = res.data.data ?? [];
|
||||
berita.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
berita.findMany.data = [];
|
||||
berita.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch berita paginated:", err);
|
||||
berita.findMany.data = [];
|
||||
berita.findMany.totalPages = 1;
|
||||
} finally {
|
||||
berita.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
findUnique: {
|
||||
data: null as
|
||||
| Prisma.BeritaGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
kategoriBerita: true;
|
||||
};
|
||||
}> | null,
|
||||
data: null as Prisma.BeritaGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
kategoriBerita: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/desa/berita/${id}`);
|
||||
@@ -109,11 +117,11 @@ const berita = proxy({
|
||||
const data = await res.json();
|
||||
berita.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error('Failed to fetch berita:', res.statusText);
|
||||
console.error("Failed to fetch berita:", res.statusText);
|
||||
berita.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching berita:', error);
|
||||
console.error("Error fetching berita:", error);
|
||||
berita.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
@@ -127,14 +135,14 @@ const berita = proxy({
|
||||
berita.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/desa/berita/delete/${id}`, {
|
||||
method: 'DELETE',
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Berita berhasil dihapus");
|
||||
await berita.findMany.load(); // refresh list
|
||||
@@ -159,21 +167,21 @@ const berita = proxy({
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/desa/berita/${id}`, {
|
||||
method: 'GET',
|
||||
method: "GET",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
@@ -190,7 +198,9 @@ const berita = proxy({
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading berita:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Gagal memuat data");
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
@@ -204,14 +214,14 @@ const berita = proxy({
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
berita.edit.loading = true;
|
||||
|
||||
|
||||
const response = await fetch(`/api/desa/berita/${this.id}`, {
|
||||
method: 'PUT',
|
||||
method: "PUT",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
judul: this.form.judul,
|
||||
@@ -221,14 +231,16 @@ const berita = proxy({
|
||||
imageId: this.form.imageId,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
|
||||
if (result.success) {
|
||||
toast.success("Berhasil update berita");
|
||||
await berita.findMany.load(); // refresh list
|
||||
@@ -238,7 +250,11 @@ const berita = proxy({
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating berita:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Terjadi kesalahan saat update berita");
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update berita"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
berita.edit.loading = false;
|
||||
@@ -258,21 +274,22 @@ const berita = proxy({
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
async load() {
|
||||
// findFirst.load()
|
||||
async load(kategori?: string) {
|
||||
this.loading = true;
|
||||
try {
|
||||
const res = await ApiFetch.api.desa.berita["find-first"].get();
|
||||
const res = await ApiFetch.api.desa.berita["find-first"].get({
|
||||
query: kategori ? { kategori } : {},
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
// Add type assertion to ensure type safety
|
||||
berita.findFirst.data = res.data.data as Prisma.BeritaGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
kategoriBerita: true;
|
||||
};
|
||||
}> | null;
|
||||
this.data = res.data.data || null;
|
||||
} else {
|
||||
this.data = null;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch berita terbaru:", err);
|
||||
this.data = null;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
@@ -286,7 +303,7 @@ const berita = proxy({
|
||||
};
|
||||
}>[],
|
||||
loading: false,
|
||||
|
||||
|
||||
async load() {
|
||||
try {
|
||||
this.loading = true;
|
||||
@@ -300,7 +317,7 @@ const berita = proxy({
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
//=============== Kategori Berita ===============
|
||||
@@ -328,10 +345,9 @@ const kategoriBerita = proxy({
|
||||
|
||||
try {
|
||||
kategoriBerita.create.loading = true;
|
||||
const res =
|
||||
await ApiFetch.api.desa.kategoriberita[
|
||||
"create"
|
||||
].post(kategoriBerita.create.form);
|
||||
const res = await ApiFetch.api.desa.kategoriberita["create"].post(
|
||||
kategoriBerita.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
kategoriBerita.findMany.load();
|
||||
return toast.success("Data Kategori Berita Berhasil Dibuat");
|
||||
@@ -352,14 +368,37 @@ const kategoriBerita = proxy({
|
||||
isActive: true;
|
||||
};
|
||||
}>[],
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
async load() {
|
||||
const res =
|
||||
await ApiFetch.api.desa.kategoriberita[
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
kategoriBerita.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
kategoriBerita.findMany.page = page;
|
||||
kategoriBerita.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.desa.kategoriberita[
|
||||
"findMany"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
kategoriBerita.findMany.data = res.data?.data ?? [];
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kategoriBerita.findMany.data = res.data.data ?? [];
|
||||
kategoriBerita.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
kategoriBerita.findMany.data = [];
|
||||
kategoriBerita.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch kategori berita paginated:", err);
|
||||
kategoriBerita.findMany.data = [];
|
||||
kategoriBerita.findMany.totalPages = 1;
|
||||
} finally {
|
||||
kategoriBerita.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -372,9 +411,7 @@ const kategoriBerita = proxy({
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/desa/kategoriberita/${id}`
|
||||
);
|
||||
const res = await fetch(`/api/desa/kategoriberita/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
kategoriBerita.findUnique.data = data.data ?? null;
|
||||
@@ -396,15 +433,12 @@ const kategoriBerita = proxy({
|
||||
try {
|
||||
kategoriBerita.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/desa/kategoriberita/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
const response = await fetch(`/api/desa/kategoriberita/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
@@ -414,7 +448,9 @@ const kategoriBerita = proxy({
|
||||
);
|
||||
await kategoriBerita.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus Data Kategori Berita");
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus Data Kategori Berita"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
@@ -435,15 +471,12 @@ const kategoriBerita = proxy({
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/desa/kategoriberita/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
const response = await fetch(`/api/desa/kategoriberita/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
@@ -481,18 +514,15 @@ const kategoriBerita = proxy({
|
||||
try {
|
||||
kategoriBerita.update.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/desa/kategoriberita/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
}),
|
||||
}
|
||||
);
|
||||
const response = await fetch(`/api/desa/kategoriberita/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
@@ -508,7 +538,9 @@ const kategoriBerita = proxy({
|
||||
await kategoriBerita.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update data kategori berita");
|
||||
throw new Error(
|
||||
result.message || "Gagal update data kategori berita"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating data kategori berita:", error);
|
||||
@@ -529,7 +561,6 @@ const kategoriBerita = proxy({
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
// 5. State global
|
||||
const stateDashboardBerita = proxy({
|
||||
kategoriBerita,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -68,10 +69,34 @@ const foto = proxy({
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.gallery.foto["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
foto.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
foto.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
foto.findMany.page = page;
|
||||
foto.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.desa.gallery.foto["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
foto.findMany.data = res.data.data ?? [];
|
||||
foto.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
foto.findMany.data = [];
|
||||
foto.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch foto paginated:", err);
|
||||
foto.findMany.data = [];
|
||||
foto.findMany.totalPages = 1;
|
||||
} finally {
|
||||
foto.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -215,6 +240,28 @@ const foto = proxy({
|
||||
foto.update.form = { ...defaultFormFoto };
|
||||
},
|
||||
},
|
||||
findRecent: {
|
||||
data: [] as Prisma.GalleryFotoGetPayload<{
|
||||
include: {
|
||||
imageGalleryFoto: true;
|
||||
};
|
||||
}>[],
|
||||
loading: false,
|
||||
|
||||
async load() {
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await ApiFetch.api.desa.gallery.foto["find-recent"].get();
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
this.data = res.data.data ?? [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal fetch foto recent:", error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const video = proxy({
|
||||
@@ -257,10 +304,34 @@ const video = proxy({
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.gallery.video["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
video.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
video.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
video.findMany.page = page;
|
||||
video.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.desa.gallery.video["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
video.findMany.data = res.data.data ?? [];
|
||||
video.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
video.findMany.data = [];
|
||||
video.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch video paginated:", err);
|
||||
video.findMany.data = [];
|
||||
video.findMany.totalPages = 1;
|
||||
} finally {
|
||||
video.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -30,7 +30,6 @@ const templateTelunjukSaktiDesaForm = z.object({
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
});
|
||||
|
||||
|
||||
const templatePelayananPerizinanBerusaha = z.object({
|
||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
@@ -72,7 +71,6 @@ const pelayananPendudukNonPermanenForm = {
|
||||
deskripsi: "",
|
||||
};
|
||||
|
||||
|
||||
const suratKeterangan = proxy({
|
||||
create: {
|
||||
form: { ...suratKeteranganForm },
|
||||
@@ -113,16 +111,21 @@ const suratKeterangan = proxy({
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||
suratKeterangan.findMany.loading = true; // Use the full path to access the property
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
// Change to arrow function
|
||||
suratKeterangan.findMany.loading = true; // Use the full path to access the property
|
||||
suratKeterangan.findMany.page = page;
|
||||
suratKeterangan.findMany.search = search;
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
const res = await ApiFetch.api.desa.layanan.pelayanansuratketerangan[
|
||||
"find-many"
|
||||
].get({
|
||||
query: { page, limit },
|
||||
query,
|
||||
});
|
||||
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
suratKeterangan.findMany.data = res.data.data || [];
|
||||
suratKeterangan.findMany.total = res.data.total || 0;
|
||||
@@ -341,28 +344,34 @@ const pelayananTelunjukSaktiDesa = proxy({
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||
pelayananTelunjukSaktiDesa.findMany.loading = true; // Use the full path to access the property
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
// Change to arrow function
|
||||
pelayananTelunjukSaktiDesa.findMany.loading = true; // Use the full path to access the property
|
||||
pelayananTelunjukSaktiDesa.findMany.page = page;
|
||||
pelayananTelunjukSaktiDesa.findMany.search = search;
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
const res = await ApiFetch.api.desa.layanan.pelayanantelunjuksaktidesa[
|
||||
"find-many"
|
||||
].get({
|
||||
query: { page, limit },
|
||||
query,
|
||||
});
|
||||
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pelayananTelunjukSaktiDesa.findMany.data = res.data.data || [];
|
||||
pelayananTelunjukSaktiDesa.findMany.total = res.data.total || 0;
|
||||
pelayananTelunjukSaktiDesa.findMany.totalPages = res.data.totalPages || 1;
|
||||
pelayananTelunjukSaktiDesa.findMany.totalPages =
|
||||
res.data.totalPages || 1;
|
||||
} else {
|
||||
console.error("Failed to load telunjuk sakti desa:", res.data?.message);
|
||||
console.error("Failed to load surat keterangan:", res.data?.message);
|
||||
pelayananTelunjukSaktiDesa.findMany.data = [];
|
||||
pelayananTelunjukSaktiDesa.findMany.total = 0;
|
||||
pelayananTelunjukSaktiDesa.findMany.totalPages = 1;
|
||||
suratKeterangan.findMany.total = 0;
|
||||
suratKeterangan.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading telunjuk sakti desa:", error);
|
||||
console.error("Error loading surat keterangan:", error);
|
||||
pelayananTelunjukSaktiDesa.findMany.data = [];
|
||||
pelayananTelunjukSaktiDesa.findMany.total = 0;
|
||||
pelayananTelunjukSaktiDesa.findMany.totalPages = 1;
|
||||
@@ -410,7 +419,9 @@ const pelayananTelunjukSaktiDesa = proxy({
|
||||
);
|
||||
const result = await response.json();
|
||||
if (response.ok) {
|
||||
toast.success(result.message || "Telunjuk Sakti Desa berhasil dihapus");
|
||||
toast.success(
|
||||
result.message || "Telunjuk Sakti Desa berhasil dihapus"
|
||||
);
|
||||
await pelayananTelunjukSaktiDesa.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result.message || "Gagal menghapus telunjuk sakti desa");
|
||||
@@ -501,7 +512,9 @@ const pelayananTelunjukSaktiDesa = proxy({
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success(result.message || "Telunjuk Sakti Desa berhasil diupdate");
|
||||
toast.success(
|
||||
result.message || "Telunjuk Sakti Desa berhasil diupdate"
|
||||
);
|
||||
await pelayananTelunjukSaktiDesa.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
@@ -522,7 +535,7 @@ const pelayananTelunjukSaktiDesa = proxy({
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
const pelayananPerizinanBerusaha = proxy({
|
||||
findById: {
|
||||
@@ -596,9 +609,7 @@ const pelayananPerizinanBerusaha = proxy({
|
||||
} catch (error) {
|
||||
console.error("Error fetching pelayanan perizinan berusaha:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal memuat data"
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
@@ -713,9 +724,7 @@ const pelayananPendudukNonPermanen = proxy({
|
||||
} catch (error) {
|
||||
console.error("Error fetching pelayanan penduduk non permanen:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal memuat data"
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -56,16 +56,21 @@ const penghargaanState = proxy({
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||
penghargaanState.findMany.loading = true; // Use the full path to access the property
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
// Change to arrow function
|
||||
penghargaanState.findMany.loading = true; // Use the full path to access the property
|
||||
penghargaanState.findMany.page = page;
|
||||
penghargaanState.findMany.search = search;
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
const res = await ApiFetch.api.desa.penghargaan[
|
||||
"find-many"
|
||||
].get({
|
||||
query: { page, limit },
|
||||
query,
|
||||
});
|
||||
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
penghargaanState.findMany.data = res.data.data || [];
|
||||
penghargaanState.findMany.total = res.data.total || 0;
|
||||
|
||||
@@ -5,6 +5,256 @@ import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateKategoriPengumuman = z.object({
|
||||
name: z.string().min(1, "Nama harus diisi"),
|
||||
});
|
||||
|
||||
const defaultKategoriPengumuman = {
|
||||
name: "",
|
||||
};
|
||||
|
||||
const category = proxy({
|
||||
create: {
|
||||
form: { ...defaultKategoriPengumuman },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateKategoriPengumuman.safeParse(category.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
category.create.loading = true;
|
||||
const res = await ApiFetch.api.desa.kategoripengumuman["create"].post(
|
||||
category.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
category.findMany.load();
|
||||
return toast.success("Data Kategori Pengumuman Berhasil Dibuat");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return toast.error("failed create");
|
||||
} finally {
|
||||
category.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: [] as (Prisma.CategoryPengumumanGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}> & {
|
||||
_count: {
|
||||
pengumumans: number;
|
||||
};
|
||||
})[],
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => { // Change to arrow function
|
||||
category.findMany.loading = true; // Use the full path to access the property
|
||||
category.findMany.page = page;
|
||||
category.findMany.search = search;
|
||||
try {
|
||||
const res = await ApiFetch.api.desa.kategoripengumuman[
|
||||
"findMany"
|
||||
].get({
|
||||
query: { page, limit },
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
category.findMany.data = res.data.data || [];
|
||||
category.findMany.total = res.data.total || 0;
|
||||
category.findMany.totalPages = res.data.totalPages || 1;
|
||||
} else {
|
||||
console.error("Failed to load potensi desa:", res.data?.message);
|
||||
category.findMany.data = [];
|
||||
category.findMany.total = 0;
|
||||
category.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading potensi desa:", error);
|
||||
category.findMany.data = [];
|
||||
category.findMany.total = 0;
|
||||
category.findMany.totalPages = 1;
|
||||
} finally {
|
||||
category.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.CategoryPengumumanGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/desa/kategoripengumuman/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
category.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
category.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
category.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async delete(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
category.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/desa/kategoripengumuman/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Data Kategori Pengumuman berhasil dihapus"
|
||||
);
|
||||
await category.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus Data Kategori Pengumuman"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error(
|
||||
"Terjadi kesalahan saat menghapus Data Kategori Pengumuman"
|
||||
);
|
||||
} finally {
|
||||
category.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultKategoriPengumuman },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/desa/kategoripengumuman/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading kategori pengumuman:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = templateKategoriPengumuman.safeParse(category.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
category.update.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/desa/kategoripengumuman/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
toast.success("Berhasil update data kategori pengumuman");
|
||||
await category.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(
|
||||
result.message || "Gagal update data kategori pengumuman"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating data kategori pengumuman:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update data kategori pengumuman"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
category.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
category.update.id = "";
|
||||
category.update.form = { ...defaultKategoriPengumuman };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const templateFormPengumuman = z.object({
|
||||
judul: z.string().min(3, "Judul minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
@@ -12,33 +262,15 @@ const templateFormPengumuman = z.object({
|
||||
categoryPengumumanId: z.string().nonempty(),
|
||||
});
|
||||
|
||||
const category = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| null
|
||||
| Prisma.CategoryPengumumanGetPayload<{ omit: { isActive: true } }>[],
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.pengumuman.category[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
category.findMany.data = (res.data?.data as any) ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
type PengumumanForm = Prisma.PengumumanGetPayload<{
|
||||
select: {
|
||||
judul: true;
|
||||
deskripsi: true;
|
||||
content: true;
|
||||
categoryPengumumanId: true;
|
||||
};
|
||||
}>;
|
||||
const defaultForm = {
|
||||
judul: "",
|
||||
deskripsi: "",
|
||||
content: "",
|
||||
categoryPengumumanId: "",
|
||||
};
|
||||
const pengumuman = proxy({
|
||||
create: {
|
||||
form: {} as PengumumanForm,
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateFormPengumuman.safeParse(pengumuman.create.form);
|
||||
@@ -74,11 +306,35 @@ const pengumuman = proxy({
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.pengumuman["find-many"].get();
|
||||
console.log(res);
|
||||
if (res.status === 200) {
|
||||
pengumuman.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "", kategori = "") => {
|
||||
pengumuman.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
pengumuman.findMany.page = page;
|
||||
pengumuman.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
if (kategori) query.kategori = kategori;
|
||||
|
||||
const res = await ApiFetch.api.desa.pengumuman["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pengumuman.findMany.data = res.data.data ?? [];
|
||||
pengumuman.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
pengumuman.findMany.data = [];
|
||||
pengumuman.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch pengumuman paginated:", err);
|
||||
pengumuman.findMany.data = [];
|
||||
pengumuman.findMany.totalPages = 1;
|
||||
} finally {
|
||||
pengumuman.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -112,7 +368,7 @@ const pengumuman = proxy({
|
||||
try {
|
||||
pengumuman.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/desa/pengumuman/delete/${id}`, {
|
||||
const response = await fetch(`/api/desa/pengumuman/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -135,9 +391,9 @@ const pengumuman = proxy({
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
edit: {
|
||||
id: "",
|
||||
form: {} as PengumumanForm,
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
@@ -153,6 +409,7 @@ const pengumuman = proxy({
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
@@ -168,20 +425,21 @@ const pengumuman = proxy({
|
||||
content: data.content,
|
||||
categoryPengumumanId: data.categoryPengumumanId || "",
|
||||
};
|
||||
return data;
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal mengambil data pengumuman");
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat mengambil data pengumuman");
|
||||
} finally {
|
||||
pengumuman.update.loading = false;
|
||||
console.error("Error loading pengumuman:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateFormPengumuman.safeParse(pengumuman.update.form);
|
||||
const cek = templateFormPengumuman.safeParse(pengumuman.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
@@ -191,7 +449,7 @@ const pengumuman = proxy({
|
||||
}
|
||||
|
||||
try {
|
||||
pengumuman.update.loading = true;
|
||||
pengumuman.edit.loading = true;
|
||||
|
||||
const response = await fetch(`/api/desa/pengumuman/${this.id}`, {
|
||||
method: "PUT",
|
||||
@@ -202,7 +460,7 @@ const pengumuman = proxy({
|
||||
judul: this.form.judul,
|
||||
deskripsi: this.form.deskripsi,
|
||||
content: this.form.content,
|
||||
categoryPengumumanId: this.form.categoryPengumumanId,
|
||||
categoryPengumumanId: this.form.categoryPengumumanId || null,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -231,9 +489,14 @@ const pengumuman = proxy({
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
pengumuman.update.loading = false;
|
||||
pengumuman.edit.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
reset() {
|
||||
pengumuman.edit.id = "";
|
||||
pengumuman.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
findFirst: {
|
||||
data: null as Prisma.PengumumanGetPayload<{
|
||||
|
||||
@@ -56,9 +56,11 @@ const potensiDesa = proxy({
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => { // Change to arrow function
|
||||
potensiDesa.findMany.loading = true; // Use the full path to access the property
|
||||
potensiDesa.findMany.page = page;
|
||||
potensiDesa.findMany.search = search;
|
||||
try {
|
||||
const res = await ApiFetch.api.desa.potensi[
|
||||
"find-many"
|
||||
@@ -298,11 +300,34 @@ const kategoriPotensi = proxy({
|
||||
isActive: true;
|
||||
};
|
||||
}>[],
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.kategoripotensi["findMany"].get();
|
||||
if (res.status === 200) {
|
||||
kategoriPotensi.findMany.data = res.data?.data ?? [];
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
kategoriPotensi.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
kategoriPotensi.findMany.page = page;
|
||||
kategoriPotensi.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.desa.kategoripotensi["findMany"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kategoriPotensi.findMany.data = res.data.data ?? [];
|
||||
kategoriPotensi.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
kategoriPotensi.findMany.data = [];
|
||||
kategoriPotensi.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch kategori potensi paginated:", err);
|
||||
kategoriPotensi.findMany.data = [];
|
||||
kategoriPotensi.findMany.totalPages = 1;
|
||||
} finally {
|
||||
kategoriPotensi.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
|
||||
// ========================================= SEJARAH DESA ========================================= //
|
||||
const sejarahDesaForm = z.object({
|
||||
@@ -106,16 +108,13 @@ const sejarahDesa = proxy({
|
||||
this.error = null;
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/desa/profile/sejarah/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(this.form),
|
||||
}
|
||||
);
|
||||
const response = await fetch(`/api/desa/profile/sejarah/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(this.form),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
@@ -409,16 +408,13 @@ const lambangDesa = proxy({
|
||||
this.error = null;
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/desa/profile/lambang/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(this.form),
|
||||
}
|
||||
);
|
||||
const response = await fetch(`/api/desa/profile/lambang/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(this.form),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
@@ -588,14 +584,11 @@ const maskotDesa = proxy({
|
||||
this.error = null;
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/desa/profile/maskot/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(this.form),
|
||||
}
|
||||
);
|
||||
const response = await fetch(`/api/desa/profile/maskot/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(this.form),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
@@ -818,12 +811,247 @@ const profilPerbekel = proxy({
|
||||
},
|
||||
});
|
||||
|
||||
//========================================= MANTAN PERBEKEL ========================================= //
|
||||
const mantanPerbekelForm = z.object({
|
||||
nama: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
daerah: z.string().min(3, "Daerah minimal 3 karakter"),
|
||||
periode: z.string().min(3, "Periode minimal 3 karakter"),
|
||||
imageId: z.string().min(1, "Gambar wajib dipilih"),
|
||||
});
|
||||
|
||||
const mantanPerbekelDefaultForm = {
|
||||
nama: "",
|
||||
daerah: "",
|
||||
periode: "",
|
||||
imageId: "",
|
||||
};
|
||||
|
||||
const mantanPerbekel = proxy({
|
||||
create: {
|
||||
form: { ...mantanPerbekelDefaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = mantanPerbekelForm.safeParse(mantanPerbekel.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
mantanPerbekel.create.loading = true;
|
||||
const res = await ApiFetch.api.desa.mantanperbekel["create"].post(
|
||||
mantanPerbekel.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
mantanPerbekel.findMany.load();
|
||||
return toast.success("Foto berhasil disimpan!");
|
||||
}
|
||||
return toast.error("Gagal menyimpan foto");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
mantanPerbekel.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
mantanPerbekel.create.form = { ...mantanPerbekelDefaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PerbekelDariMasaKeMasaGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
mantanPerbekel.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
mantanPerbekel.findMany.page = page;
|
||||
mantanPerbekel.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.desa.mantanperbekel["findMany"].get({
|
||||
query,
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
mantanPerbekel.findMany.data = res.data.data ?? [];
|
||||
mantanPerbekel.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
mantanPerbekel.findMany.data = [];
|
||||
mantanPerbekel.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch mantan perbekel paginated:", err);
|
||||
mantanPerbekel.findMany.data = [];
|
||||
mantanPerbekel.findMany.totalPages = 1;
|
||||
} finally {
|
||||
mantanPerbekel.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PerbekelDariMasaKeMasaGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/desa/mantanperbekel/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
mantanPerbekel.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch mantan perbekel:", res.statusText);
|
||||
mantanPerbekel.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching mantan perbekel:", error);
|
||||
mantanPerbekel.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
mantanPerbekel.delete.loading = true;
|
||||
const response = await fetch(`/api/desa/mantanperbekel/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const result = await response.json();
|
||||
if (response.ok) {
|
||||
toast.success(result.message || "Mantan perbekel berhasil dihapus");
|
||||
await mantanPerbekel.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result.message || "Gagal menghapus mantan perbekel");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus mantan perbekel");
|
||||
} finally {
|
||||
mantanPerbekel.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...mantanPerbekelDefaultForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(`/api/desa/mantanperbekel/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
nama: data.nama,
|
||||
daerah: data.daerah,
|
||||
periode: data.periode,
|
||||
imageId: data.imageId || "",
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading foto:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = mantanPerbekelForm.safeParse(mantanPerbekel.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
mantanPerbekel.update.loading = true;
|
||||
const response = await fetch(`/api/desa/mantanperbekel/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: this.form.nama,
|
||||
daerah: this.form.daerah,
|
||||
periode: this.form.periode,
|
||||
imageId: this.form.imageId,
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success(result.message || "Mantan perbekel berhasil diupdate");
|
||||
await mantanPerbekel.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate mantan perbekel");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating mantan perbekel:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal mengupdate mantan perbekel"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
mantanPerbekel.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
mantanPerbekel.update.id = "";
|
||||
mantanPerbekel.update.form = { ...mantanPerbekelDefaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const stateProfileDesa = proxy({
|
||||
lambangDesa,
|
||||
maskotDesa,
|
||||
profilPerbekel,
|
||||
visiMisiDesa,
|
||||
sejarahDesa,
|
||||
mantanPerbekel,
|
||||
});
|
||||
|
||||
export default stateProfileDesa;
|
||||
|
||||
@@ -7,9 +7,13 @@ import { z } from "zod";
|
||||
|
||||
const templateApbDesa = z.object({
|
||||
tahun: z.number().min(4, "Tahun minimal 4 karakter"),
|
||||
pembiayaanIds: z.array(z.string().uuid()).nonempty("Pilih minimal 1 pembiayaan"),
|
||||
pembiayaanIds: z
|
||||
.array(z.string().uuid())
|
||||
.nonempty("Pilih minimal 1 pembiayaan"),
|
||||
belanjaIds: z.array(z.string().uuid()).nonempty("Pilih minimal 1 belanja"),
|
||||
pendapatanIds: z.array(z.string().uuid()).nonempty("Pilih minimal 1 pendapatan"),
|
||||
pendapatanIds: z
|
||||
.array(z.string().uuid())
|
||||
.nonempty("Pilih minimal 1 pendapatan"),
|
||||
});
|
||||
|
||||
const ApbDesaDefaultForm = {
|
||||
@@ -54,32 +58,46 @@ const ApbDesa = proxy({
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.ApbDesaGetPayload<{
|
||||
include: {
|
||||
pendapatan: true;
|
||||
belanja: true;
|
||||
pembiayaan: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
data: null as
|
||||
| Prisma.ApbDesaGetPayload<{
|
||||
include: {
|
||||
pendapatan: true;
|
||||
belanja: true;
|
||||
pembiayaan: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
async load() {
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
ApbDesa.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
ApbDesa.findMany.page = page;
|
||||
ApbDesa.findMany.search = search;
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.apbdesa[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
this.data = res.data?.data ?? [];
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
ApbDesa.findMany.data = res.data.data ?? [];
|
||||
ApbDesa.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
toast.error(res.data?.message || "Gagal mengambil APB Desa");
|
||||
ApbDesa.findMany.data = [];
|
||||
ApbDesa.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Find many error:", error);
|
||||
toast.error("Gagal mengambil APB Desa");
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch APB Desa paginated:", err);
|
||||
ApbDesa.findMany.data = [];
|
||||
ApbDesa.findMany.totalPages = 1;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
ApbDesa.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -106,13 +124,13 @@ const ApbDesa = proxy({
|
||||
throw new Error("Gagal mengambil APB Desa");
|
||||
}
|
||||
const result = await response.json();
|
||||
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.message || "Gagal memuat APB Desa");
|
||||
}
|
||||
|
||||
|
||||
const data = result.data;
|
||||
|
||||
|
||||
this.id = id;
|
||||
this.form = {
|
||||
tahun: data.tahun || 0,
|
||||
@@ -120,7 +138,7 @@ const ApbDesa = proxy({
|
||||
belanjaIds: data.belanja?.map((b: any) => b.id) || [],
|
||||
pembiayaanIds: data.pembiayaan?.map((p: any) => p.id) || [],
|
||||
};
|
||||
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error loading APB Desa:", error);
|
||||
@@ -189,7 +207,7 @@ const ApbDesa = proxy({
|
||||
data: null as Prisma.ApbDesaGetPayload<{
|
||||
include: { pendapatan: true; belanja: true; pembiayaan: true };
|
||||
}> | null,
|
||||
|
||||
|
||||
async load(id: string) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
@@ -199,11 +217,11 @@ const ApbDesa = proxy({
|
||||
throw new Error("Gagal mengambil detail APB Desa");
|
||||
}
|
||||
const result = await response.json();
|
||||
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.message || "Gagal mengambil data");
|
||||
}
|
||||
|
||||
|
||||
this.data = result.data; // ✅ fix utama di sini
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
@@ -264,34 +282,32 @@ const pendapatan = proxy({
|
||||
data: null as any[] | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => {
|
||||
// Change to arrow function
|
||||
pendapatan.findMany.loading = true; // Use the full path to access the property
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
pendapatan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
pendapatan.findMany.page = page;
|
||||
pendapatan.findMany.search = search;
|
||||
|
||||
try {
|
||||
const res =
|
||||
await ApiFetch.api.ekonomi.pendapatanaslidesa.pendapatanasli[
|
||||
"find-many"
|
||||
].get({
|
||||
query: { page, limit },
|
||||
});
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.pendapatanasli[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pendapatan.findMany.data = res.data.data || [];
|
||||
pendapatan.findMany.total = res.data.total || 0;
|
||||
pendapatan.findMany.totalPages = res.data.totalPages || 1;
|
||||
pendapatan.findMany.data = res.data.data ?? [];
|
||||
pendapatan.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
console.error("Failed to load pendapatan:", res.data?.message);
|
||||
pendapatan.findMany.data = [];
|
||||
pendapatan.findMany.total = 0;
|
||||
pendapatan.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading pendapatan:", error);
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch pendapatan asli desa paginated:", err);
|
||||
pendapatan.findMany.data = [];
|
||||
pendapatan.findMany.total = 0;
|
||||
pendapatan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
pendapatan.findMany.loading = false;
|
||||
@@ -308,12 +324,15 @@ const pendapatan = proxy({
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/pendapatanasli/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/pendapatanasli/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
@@ -349,16 +368,19 @@ const pendapatan = proxy({
|
||||
|
||||
try {
|
||||
pendapatan.update.loading = true;
|
||||
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/pendapatanasli/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
value: this.form.value,
|
||||
}),
|
||||
});
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/pendapatanasli/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
value: this.form.value,
|
||||
}),
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
@@ -495,23 +517,37 @@ const belanja = proxy({
|
||||
name: string;
|
||||
value: number;
|
||||
}>,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
async load() {
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
belanja.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
belanja.findMany.page = page;
|
||||
belanja.findMany.search = search;
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.belanja[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
this.data = res.data?.data ?? [];
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
belanja.findMany.data = res.data.data ?? [];
|
||||
belanja.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
toast.error(res.data?.message || "Gagal mengambil Belanja");
|
||||
belanja.findMany.data = [];
|
||||
belanja.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Find many error:", error);
|
||||
toast.error("Gagal mengambil Belanja");
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch Belanja paginated:", err);
|
||||
belanja.findMany.data = [];
|
||||
belanja.findMany.totalPages = 1;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
belanja.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -525,12 +561,15 @@ const belanja = proxy({
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/belanja/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/belanja/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
@@ -566,16 +605,19 @@ const belanja = proxy({
|
||||
|
||||
try {
|
||||
belanja.update.loading = true;
|
||||
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/belanja/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
value: this.form.value,
|
||||
}),
|
||||
});
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/belanja/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
value: this.form.value,
|
||||
}),
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
@@ -710,23 +752,37 @@ const pembiayaan = proxy({
|
||||
name: string;
|
||||
value: number;
|
||||
}>,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
async load() {
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
pembiayaan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
pembiayaan.findMany.page = page;
|
||||
pembiayaan.findMany.search = search;
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.pembiayaan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
this.data = res.data?.data ?? [];
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pembiayaan.findMany.data = res.data.data ?? [];
|
||||
pembiayaan.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
toast.error(res.data?.message || "Gagal mengambil Pembiayaan");
|
||||
pembiayaan.findMany.data = [];
|
||||
pembiayaan.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Find many error:", error);
|
||||
toast.error("Gagal mengambil Pembiayaan");
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch Pembiayaan paginated:", err);
|
||||
pembiayaan.findMany.data = [];
|
||||
pembiayaan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
pembiayaan.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -740,12 +796,15 @@ const pembiayaan = proxy({
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/pembiayaan/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/pembiayaan/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
@@ -781,16 +840,19 @@ const pembiayaan = proxy({
|
||||
|
||||
try {
|
||||
pembiayaan.update.loading = true;
|
||||
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/pembiayaan/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
value: this.form.value,
|
||||
}),
|
||||
});
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/pembiayaan/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
value: this.form.value,
|
||||
}),
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -71,12 +72,37 @@ const demografiPekerjaan = proxy({
|
||||
omit: { isActive: true };
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ekonomi.demografipekerjaan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
demografiPekerjaan.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
demografiPekerjaan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
demografiPekerjaan.findMany.page = page;
|
||||
demografiPekerjaan.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.demografipekerjaan[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
demografiPekerjaan.findMany.data = res.data.data ?? [];
|
||||
demografiPekerjaan.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
demografiPekerjaan.findMany.data = [];
|
||||
demografiPekerjaan.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch demografi pekerjaan paginated:", err);
|
||||
demografiPekerjaan.findMany.data = [];
|
||||
demografiPekerjaan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
demografiPekerjaan.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -194,4 +220,4 @@ const demografiPekerjaan = proxy({
|
||||
},
|
||||
},
|
||||
});
|
||||
export default demografiPekerjaan
|
||||
export default demografiPekerjaan;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -69,16 +70,37 @@ const jumlahPendudukMiskin = proxy({
|
||||
select: { id: true; year: true; totalPoorPopulation: true };
|
||||
}>[]
|
||||
| null,
|
||||
loading: false,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ekonomi.jumlahpendudukmiskin[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
jumlahPendudukMiskin.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
jumlahPendudukMiskin.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
jumlahPendudukMiskin.findMany.page = page;
|
||||
jumlahPendudukMiskin.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.jumlahpendudukmiskin["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
jumlahPendudukMiskin.findMany.data = res.data.data ?? [];
|
||||
jumlahPendudukMiskin.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
jumlahPendudukMiskin.findMany.data = [];
|
||||
jumlahPendudukMiskin.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch jumlah penduduk miskin paginated:", err);
|
||||
jumlahPendudukMiskin.findMany.data = [];
|
||||
jumlahPendudukMiskin.findMany.totalPages = 1;
|
||||
} finally {
|
||||
jumlahPendudukMiskin.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.GrafikJumlahPendudukMiskinGetPayload<{
|
||||
select: { id: true; year: true; totalPoorPopulation: true };
|
||||
|
||||
@@ -15,7 +15,8 @@ const templateJumlahPengngguran = z.object({
|
||||
uneducatedUnemployment: z
|
||||
.number()
|
||||
.min(1, "Pengangguran tidak pendidikan harus diisi"),
|
||||
percentageChange: z.number().min(0, "Persentase perubahan harus diisi"),
|
||||
percentageChange: z.number({ invalid_type_error: "Persentase perubahan harus angka" }),
|
||||
|
||||
});
|
||||
|
||||
type JumlahPengangguran = {
|
||||
@@ -29,7 +30,7 @@ type JumlahPengangguran = {
|
||||
|
||||
const jumlahPengangguranForm: JumlahPengangguran = {
|
||||
month: "",
|
||||
year: 0,
|
||||
year: new Date().getFullYear(), // Default to current year
|
||||
totalUnemployment: 0,
|
||||
educatedUnemployment: 0,
|
||||
uneducatedUnemployment: 0,
|
||||
@@ -60,13 +61,21 @@ const jumlahPengangguran = proxy({
|
||||
form: jumlahPengangguranForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateJumlahPengngguran.safeParse(
|
||||
jumlahPengangguran.create.form
|
||||
);
|
||||
// Ensure all number fields are actual numbers
|
||||
const formData = {
|
||||
...jumlahPengangguran.create.form,
|
||||
year: Number(jumlahPengangguran.create.form.year) || new Date().getFullYear(),
|
||||
totalUnemployment: Number(jumlahPengangguran.create.form.totalUnemployment) || 0,
|
||||
educatedUnemployment: Number(jumlahPengangguran.create.form.educatedUnemployment) || 0,
|
||||
uneducatedUnemployment: Number(jumlahPengangguran.create.form.uneducatedUnemployment) || 0,
|
||||
percentageChange: Number(jumlahPengangguran.create.form.percentageChange) || 0,
|
||||
};
|
||||
|
||||
const cek = templateJumlahPengngguran.safeParse(formData);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
.map((v) => `${v.path.join(".")} (${v.message})`)
|
||||
.join("\n")}]`;
|
||||
toast.error(err);
|
||||
return null;
|
||||
}
|
||||
@@ -78,7 +87,7 @@ const jumlahPengangguran = proxy({
|
||||
].post(jumlahPengangguran.create.form);
|
||||
|
||||
if (res.status === 200) {
|
||||
const id = res.data?.data?.id;
|
||||
const id = res.data?.id;
|
||||
if (id) {
|
||||
toast.success("Success create");
|
||||
jumlahPengangguran.create.form = { ...jumlahPengangguranForm };
|
||||
@@ -103,16 +112,40 @@ const jumlahPengangguran = proxy({
|
||||
omit: { isActive: true };
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res =
|
||||
await ApiFetch.api.ekonomi.jumlahpengangguran.detaildatapengangguran[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
jumlahPengangguran.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
jumlahPengangguran.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
jumlahPengangguran.findMany.page = page;
|
||||
jumlahPengangguran.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.jumlahpengangguran.detaildatapengangguran[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
jumlahPengangguran.findMany.data = res.data.data ?? [];
|
||||
jumlahPengangguran.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
jumlahPengangguran.findMany.data = [];
|
||||
jumlahPengangguran.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch jumlah pengangguran paginated:", err);
|
||||
jumlahPengangguran.findMany.data = [];
|
||||
jumlahPengangguran.findMany.totalPages = 1;
|
||||
} finally {
|
||||
jumlahPengangguran.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
findUnique: {
|
||||
data: null as Prisma.DetailDataPengangguranGetPayload<{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -61,13 +62,39 @@ const lowonganKerjaState = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.LowonganPekerjaanGetPayload<{
|
||||
omit: { isActive: true };
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ekonomi.lowongankerja["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
lowonganKerjaState.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
lowonganKerjaState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
lowonganKerjaState.findMany.page = page;
|
||||
lowonganKerjaState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.lowongankerja["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
lowonganKerjaState.findMany.data = res.data.data ?? [];
|
||||
lowonganKerjaState.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
lowonganKerjaState.findMany.data = [];
|
||||
lowonganKerjaState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch lowongan kerja paginated:", err);
|
||||
lowonganKerjaState.findMany.data = [];
|
||||
lowonganKerjaState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
lowonganKerjaState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -53,22 +54,47 @@ const pasarDesa = proxy({
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<
|
||||
Prisma.PasarDesaGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
KategoriToPasar: {
|
||||
include: {
|
||||
kategori: true;
|
||||
data: null as
|
||||
| Prisma.PasarDesaGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
KategoriToPasar: {
|
||||
include: {
|
||||
kategori: true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}>
|
||||
> | null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ekonomi.pasardesa["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
pasarDesa.findMany.data = res.data?.data ?? [];
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "", categoryId?: string) => {
|
||||
pasarDesa.findMany.loading = true;
|
||||
pasarDesa.findMany.page = page;
|
||||
pasarDesa.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
if (categoryId) query.categoryId = categoryId;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.pasardesa["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pasarDesa.findMany.data = res.data.data ?? [];
|
||||
pasarDesa.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
pasarDesa.findMany.data = [];
|
||||
pasarDesa.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch keamanan lingkungan paginated:", err);
|
||||
pasarDesa.findMany.data = [];
|
||||
pasarDesa.findMany.totalPages = 1;
|
||||
} finally {
|
||||
pasarDesa.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -272,14 +298,41 @@ const kategoriProduk = proxy({
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<{
|
||||
id: string;
|
||||
nama: string;
|
||||
}> | null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ekonomi.kategoriproduk["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
kategoriProduk.findMany.data = res.data?.data ?? [];
|
||||
data: null as
|
||||
| Prisma.KategoriProdukGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search2: "",
|
||||
load: async (page = 1, limit = 10, search2 = "") => {
|
||||
kategoriProduk.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
kategoriProduk.findMany.page = page;
|
||||
kategoriProduk.findMany.search2 = search2;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search2) query.search2 = search2;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.kategoriproduk["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kategoriProduk.findMany.data = res.data.data ?? [];
|
||||
kategoriProduk.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
kategoriProduk.findMany.data = [];
|
||||
kategoriProduk.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch kategori produk paginated:", err);
|
||||
kategoriProduk.findMany.data = [];
|
||||
kategoriProduk.findMany.totalPages = 1;
|
||||
} finally {
|
||||
kategoriProduk.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -7,22 +8,21 @@ import { z } from "zod";
|
||||
const templateForm = z.object({
|
||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||
ikonUrl: z.string().optional(),
|
||||
icon: z.string().min(1, "Icon minimal 1 karakter"),
|
||||
statistik: z.object({
|
||||
tahun: z.string().min(1, "Tahun minimal 1 karakter"),
|
||||
jumlah: z.string().min(1, "Jumlah minimal 1 karakter"),
|
||||
})
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
nama: "",
|
||||
deskripsi: "",
|
||||
ikonUrl: "",
|
||||
icon: "",
|
||||
statistik: {
|
||||
tahun: "",
|
||||
jumlah: ""
|
||||
}
|
||||
jumlah: "",
|
||||
},
|
||||
};
|
||||
|
||||
const programKemiskinanState = proxy({
|
||||
@@ -64,12 +64,35 @@ const programKemiskinanState = proxy({
|
||||
};
|
||||
}>[],
|
||||
loading: false,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ekonomi.programkemiskinan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
programKemiskinanState.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
programKemiskinanState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
programKemiskinanState.findMany.page = page;
|
||||
programKemiskinanState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.programkemiskinan[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
programKemiskinanState.findMany.data = res.data.data ?? [];
|
||||
programKemiskinanState.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
programKemiskinanState.findMany.data = [];
|
||||
programKemiskinanState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch program kemiskinan paginated:", err);
|
||||
programKemiskinanState.findMany.data = [];
|
||||
programKemiskinanState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
programKemiskinanState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -125,7 +148,7 @@ const programKemiskinanState = proxy({
|
||||
this.form = {
|
||||
nama: data.nama,
|
||||
deskripsi: data.deskripsi,
|
||||
ikonUrl: data.ikonUrl || "",
|
||||
icon: data.icon,
|
||||
statistik: {
|
||||
tahun: data.statistik.tahun,
|
||||
jumlah: data.statistik.jumlah,
|
||||
@@ -166,7 +189,7 @@ const programKemiskinanState = proxy({
|
||||
body: JSON.stringify({
|
||||
nama: this.form.nama,
|
||||
deskripsi: this.form.deskripsi,
|
||||
ikonUrl: this.form.ikonUrl,
|
||||
icon: this.form.icon,
|
||||
statistik: {
|
||||
tahun: this.form.statistik.tahun,
|
||||
jumlah: this.form.statistik.jumlah,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -76,13 +77,37 @@ const grafikSektorUnggulan = proxy({
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ekonomi.sektourunggulandesa[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
grafikSektorUnggulan.findMany.data = res.data?.data ?? [];
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
grafikSektorUnggulan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
grafikSektorUnggulan.findMany.page = page;
|
||||
grafikSektorUnggulan.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.sektourunggulandesa[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
grafikSektorUnggulan.findMany.data = res.data.data ?? [];
|
||||
grafikSektorUnggulan.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
grafikSektorUnggulan.findMany.data = [];
|
||||
grafikSektorUnggulan.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch sektor unggulan desa paginated:", err);
|
||||
grafikSektorUnggulan.findMany.data = [];
|
||||
grafikSektorUnggulan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
grafikSektorUnggulan.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -161,18 +161,34 @@ const posisiOrganisasi = proxy({
|
||||
deskripsi: string | null;
|
||||
hierarki: number;
|
||||
}>,
|
||||
async load() {
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
posisiOrganisasi.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
posisiOrganisasi.findMany.page = page;
|
||||
posisiOrganisasi.findMany.search = search;
|
||||
|
||||
try {
|
||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
||||
"posisi-organisasi"
|
||||
]["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
// The API now returns the id field, so we can use it directly
|
||||
this.data = res.data?.data ?? [];
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"]["posisi-organisasi"]["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
posisiOrganisasi.findMany.data = res.data.data ?? [];
|
||||
posisiOrganisasi.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
posisiOrganisasi.findMany.data = [];
|
||||
posisiOrganisasi.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Find many error:", error);
|
||||
this.data = [];
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch posisi organisasi paginated:", err);
|
||||
posisiOrganisasi.findMany.data = [];
|
||||
posisiOrganisasi.findMany.totalPages = 1;
|
||||
} finally {
|
||||
posisiOrganisasi.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -75,16 +76,37 @@ const grafikBerdasarkanUsiaKerjaNganggur = proxy({
|
||||
omit: { isActive: true };
|
||||
}>[]
|
||||
| null,
|
||||
loading: false,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ekonomi.grafikusiakerjayangmenganggur[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.page = page;
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.grafikusiakerjayangmenganggur["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.data = res.data.data ?? [];
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.data = [];
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch grafik berdasarkan usia kerja yang menganggur paginated:", err);
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.data = [];
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.totalPages = 1;
|
||||
} finally {
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.GrafikMenganggurBerdasarkanUsiaGetPayload<{
|
||||
omit: { isActive: true };
|
||||
@@ -259,15 +281,36 @@ const grafikBerdasarkanPendidikan = proxy({
|
||||
omit: { isActive: true };
|
||||
}>[]
|
||||
| null,
|
||||
loading: false,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ekonomi.grafikmenganggurberdasarkanpendidikan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
grafikBerdasarkanPendidikan.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
grafikBerdasarkanPendidikan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
grafikBerdasarkanPendidikan.findMany.page = page;
|
||||
grafikBerdasarkanPendidikan.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.ekonomi.grafikmenganggurberdasarkanpendidikan["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
grafikBerdasarkanPendidikan.findMany.data = res.data.data ?? [];
|
||||
grafikBerdasarkanPendidikan.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
grafikBerdasarkanPendidikan.findMany.data = [];
|
||||
grafikBerdasarkanPendidikan.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch grafik berdasarkan pendidikan paginated:", err);
|
||||
grafikBerdasarkanPendidikan.findMany.data = [];
|
||||
grafikBerdasarkanPendidikan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
grafikBerdasarkanPendidikan.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.GrafikMenganggurBerdasarkanPendidikanGetPayload<{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -61,10 +62,37 @@ const ajukanIdeInovatifState = proxy({
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.inovasi.ajukanideinovatif["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
ajukanIdeInovatifState.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
ajukanIdeInovatifState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
ajukanIdeInovatifState.findMany.page = page;
|
||||
ajukanIdeInovatifState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.ajukanideinovatif[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
ajukanIdeInovatifState.findMany.data = res.data.data ?? [];
|
||||
ajukanIdeInovatifState.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
ajukanIdeInovatifState.findMany.data = [];
|
||||
ajukanIdeInovatifState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch ajukan ide inovatif paginated:", err);
|
||||
ajukanIdeInovatifState.findMany.data = [];
|
||||
ajukanIdeInovatifState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
ajukanIdeInovatifState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -97,16 +125,21 @@ const ajukanIdeInovatifState = proxy({
|
||||
|
||||
try {
|
||||
ajukanIdeInovatifState.delete.loading = true;
|
||||
const response = await fetch(`/api/inovasi/ajukanideinovatif/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const response = await fetch(
|
||||
`/api/inovasi/ajukanideinovatif/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
toast.success(result.message || "Ajukan Ide Inovatif berhasil dihapus");
|
||||
toast.success(
|
||||
result.message || "Ajukan Ide Inovatif berhasil dihapus"
|
||||
);
|
||||
await ajukanIdeInovatifState.findMany.load();
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus ajukan ide inovatif");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -55,10 +56,34 @@ const desaDigitalState = proxy({
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.inovasi.desadigital["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
desaDigitalState.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
desaDigitalState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
desaDigitalState.findMany.page = page;
|
||||
desaDigitalState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.inovasi.desadigital["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
desaDigitalState.findMany.data = res.data.data ?? [];
|
||||
desaDigitalState.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
desaDigitalState.findMany.data = [];
|
||||
desaDigitalState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch desa digital paginated:", err);
|
||||
desaDigitalState.findMany.data = [];
|
||||
desaDigitalState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
desaDigitalState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -55,10 +56,34 @@ const infoTeknoState = proxy({
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.inovasi.infotekno["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
infoTeknoState.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
infoTeknoState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
infoTeknoState.findMany.page = page;
|
||||
infoTeknoState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.inovasi.infotekno["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
infoTeknoState.findMany.data = res.data.data ?? [];
|
||||
infoTeknoState.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
infoTeknoState.findMany.data = [];
|
||||
infoTeknoState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch info teknologi paginated:", err);
|
||||
infoTeknoState.findMany.data = [];
|
||||
infoTeknoState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
infoTeknoState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -6,12 +6,11 @@ import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
tahun: z.number().min(4, "Tahun minimal 4 karakter"),
|
||||
slug: z.string().min(1, "Deskripsi singkat minimal 1 karakter"),
|
||||
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||
kolaborator: z.string().min(1, "Kolaborator minimal 1 karakter"),
|
||||
imageId: z.string().min(1, "Image ID minimal 1 karakter"),
|
||||
name: z.string().min(1, "Nama kolaborasi inovasi harus diisi"),
|
||||
tahun: z.number().min(1900, "Tahun tidak valid").max(new Date().getFullYear() + 1, "Tahun tidak boleh lebih dari tahun depan"),
|
||||
slug: z.string().min(1, "Slug harus dihasilkan otomatis"),
|
||||
deskripsi: z.string().min(1, "Deskripsi harus diisi"),
|
||||
kolaborator: z.string().min(1, "Kolaborator harus diisi"),
|
||||
})
|
||||
|
||||
const defaultForm = {
|
||||
@@ -20,7 +19,6 @@ const defaultForm = {
|
||||
slug: "",
|
||||
deskripsi: "",
|
||||
kolaborator: "",
|
||||
imageId: "",
|
||||
}
|
||||
|
||||
const kolaborasiInovasiState = proxy({
|
||||
@@ -28,27 +26,37 @@ const kolaborasiInovasiState = proxy({
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(kolaborasiInovasiState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
// Validate form
|
||||
const validation = templateForm.safeParse(kolaborasiInovasiState.create.form);
|
||||
if (!validation.success) {
|
||||
const errorMessages = validation.error.issues
|
||||
.map(issue => `- ${issue.path.join('.')}: ${issue.message}`)
|
||||
.join('\n');
|
||||
return toast.error(`Validasi gagal:\n${errorMessages}`);
|
||||
}
|
||||
|
||||
kolaborasiInovasiState.create.loading = true;
|
||||
|
||||
const res = await ApiFetch.api.inovasi.kolaborasiinovasi["create"].post(
|
||||
kolaborasiInovasiState.create.form
|
||||
);
|
||||
|
||||
if (res.status === 200) {
|
||||
kolaborasiInovasiState.findMany.load();
|
||||
return toast.success("success create");
|
||||
await kolaborasiInovasiState.findMany.load();
|
||||
return { success: true, data: res.data };
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
|
||||
console.error('Create failed:', res);
|
||||
toast.error(res.data?.message || "Gagal menyimpan data");
|
||||
return { success: false, error: res.data };
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
console.error('Error in create:', error);
|
||||
toast.error("Terjadi kesalahan saat menyimpan data");
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
};
|
||||
} finally {
|
||||
kolaborasiInovasiState.create.loading = false;
|
||||
}
|
||||
@@ -60,13 +68,21 @@ const kolaborasiInovasiState = proxy({
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => {
|
||||
// Change to arrow function
|
||||
kolaborasiInovasiState.findMany.loading = true; // Use the full path to access the property
|
||||
search: "",
|
||||
year: "",
|
||||
load: async (page = 1, limit = 10, search = "", year?: string) => {
|
||||
kolaborasiInovasiState.findMany.loading = true;
|
||||
kolaborasiInovasiState.findMany.page = page;
|
||||
kolaborasiInovasiState.findMany.search = search;
|
||||
kolaborasiInovasiState.findMany.year = year || "";
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
if (year) query.year = year;
|
||||
|
||||
const res = await ApiFetch.api.inovasi.kolaborasiinovasi["find-many"].get({
|
||||
query: { page, limit },
|
||||
query,
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
@@ -124,7 +140,6 @@ const kolaborasiInovasiState = proxy({
|
||||
slug: data.slug,
|
||||
deskripsi: data.deskripsi,
|
||||
kolaborator: data.kolaborator,
|
||||
imageId: data.imageId,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
@@ -179,7 +194,7 @@ const kolaborasiInovasiState = proxy({
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.KolaborasiInovasiGetPayload<{
|
||||
include: { image: true };
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -54,19 +55,20 @@ const administrasiOnline = proxy({
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<
|
||||
Prisma.AdministrasiOnlineGetPayload<{
|
||||
include: {
|
||||
jenisLayanan: true;
|
||||
};
|
||||
}>
|
||||
> | null,
|
||||
Prisma.AdministrasiOnlineGetPayload<{
|
||||
include: {
|
||||
jenisLayanan: true;
|
||||
};
|
||||
}>
|
||||
> | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
|
||||
async load(page = 1, limit = 10) {
|
||||
search: "",
|
||||
async load(page = 1, limit = 10, search = "") {
|
||||
administrasiOnline.findMany.loading = true;
|
||||
administrasiOnline.findMany.page = page;
|
||||
administrasiOnline.findMany.search = search;
|
||||
try {
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.administrasionline[
|
||||
@@ -75,6 +77,7 @@ const administrasiOnline = proxy({
|
||||
query: {
|
||||
page,
|
||||
limit,
|
||||
search,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -91,10 +94,10 @@ const administrasiOnline = proxy({
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.AdministrasiOnlineGetPayload<{
|
||||
include: {
|
||||
jenisLayanan: true;
|
||||
};
|
||||
}> | null,
|
||||
include: {
|
||||
jenisLayanan: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
@@ -199,13 +202,37 @@ const jenisLayanan = proxy({
|
||||
nama: string;
|
||||
deskripsi: string;
|
||||
}> | null,
|
||||
async load() {
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.administrasionline.jenislayanan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
jenisLayanan.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
jenisLayanan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
jenisLayanan.findMany.page = page;
|
||||
jenisLayanan.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.administrasionline.jenislayanan[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
jenisLayanan.findMany.data = res.data.data ?? [];
|
||||
jenisLayanan.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
jenisLayanan.findMany.data = [];
|
||||
jenisLayanan.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch jenis layanan paginated:", err);
|
||||
jenisLayanan.findMany.data = [];
|
||||
jenisLayanan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
jenisLayanan.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -403,7 +430,9 @@ const templatePengaduanMasyarakatForm = z.object({
|
||||
nik: z.string().min(1, "NIK minimal 1 karakter"),
|
||||
judulPengaduan: z.string().min(1, "Judul pengaduan minimal 1 karakter"),
|
||||
lokasiKejadian: z.string().min(1, "Lokasi kejadian minimal 1 karakter"),
|
||||
deskripsiPengaduan: z.string().min(1, "Deskripsi pengaduan minimal 1 karakter"),
|
||||
deskripsiPengaduan: z
|
||||
.string()
|
||||
.min(1, "Deskripsi pengaduan minimal 1 karakter"),
|
||||
jenisPengaduanId: z.string().min(1, "Jenis pengaduan minimal 1 karakter"),
|
||||
imageId: z.string().min(1, "Image minimal 1 karakter"),
|
||||
});
|
||||
@@ -455,37 +484,42 @@ const pengaduanMasyarakat = proxy({
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<
|
||||
Prisma.PengaduanMasyarakatGetPayload<{
|
||||
include: {
|
||||
jenisPengaduan: true;
|
||||
image: true;
|
||||
};
|
||||
}>
|
||||
> | null,
|
||||
Prisma.PengaduanMasyarakatGetPayload<{
|
||||
include: {
|
||||
jenisPengaduan: true;
|
||||
image: true;
|
||||
};
|
||||
}>
|
||||
> | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
|
||||
async load(page = 1, limit = 10) {
|
||||
pengaduanMasyarakat.findMany.loading = true;
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
pengaduanMasyarakat.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
pengaduanMasyarakat.findMany.page = page;
|
||||
pengaduanMasyarakat.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.pengaduanmasyarakat[
|
||||
"find-many"
|
||||
].get({
|
||||
query: {
|
||||
page,
|
||||
limit,
|
||||
},
|
||||
});
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pengaduanMasyarakat.findMany.data = res.data.data ?? [];
|
||||
pengaduanMasyarakat.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
pengaduanMasyarakat.findMany.data = [];
|
||||
pengaduanMasyarakat.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch pengaduan masyarakat paginated:", err);
|
||||
pengaduanMasyarakat.findMany.data = [];
|
||||
pengaduanMasyarakat.findMany.totalPages = 1;
|
||||
} finally {
|
||||
pengaduanMasyarakat.findMany.loading = false;
|
||||
}
|
||||
@@ -493,11 +527,11 @@ const pengaduanMasyarakat = proxy({
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PengaduanMasyarakatGetPayload<{
|
||||
include: {
|
||||
jenisPengaduan: true;
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
include: {
|
||||
jenisPengaduan: true;
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
@@ -507,7 +541,10 @@ const pengaduanMasyarakat = proxy({
|
||||
const data = await res.json();
|
||||
pengaduanMasyarakat.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch pengaduan masyarakat:", res.statusText);
|
||||
console.error(
|
||||
"Failed to fetch pengaduan masyarakat:",
|
||||
res.statusText
|
||||
);
|
||||
pengaduanMasyarakat.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -542,7 +579,9 @@ const pengaduanMasyarakat = proxy({
|
||||
);
|
||||
await pengaduanMasyarakat.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus pengaduan masyarakat");
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus pengaduan masyarakat"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
@@ -567,7 +606,9 @@ const jenisPengaduan = proxy({
|
||||
form: { ...defaultJenisPengaduanForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateJenisPengaduanForm.safeParse(jenisPengaduan.create.form);
|
||||
const cek = templateJenisPengaduanForm.safeParse(
|
||||
jenisPengaduan.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
@@ -598,13 +639,37 @@ const jenisPengaduan = proxy({
|
||||
id: string;
|
||||
nama: string;
|
||||
}> | null,
|
||||
async load() {
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.pengaduanmasyarakat.jenispengaduan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
jenisPengaduan.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
jenisPengaduan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
jenisPengaduan.findMany.page = page;
|
||||
jenisPengaduan.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.pengaduanmasyarakat.jenispengaduan[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
jenisPengaduan.findMany.data = res.data.data ?? [];
|
||||
jenisPengaduan.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
jenisPengaduan.findMany.data = [];
|
||||
jenisPengaduan.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch jenis pengaduan paginated:", err);
|
||||
jenisPengaduan.findMany.data = [];
|
||||
jenisPengaduan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
jenisPengaduan.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -693,7 +758,7 @@ const jenisPengaduan = proxy({
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
nama: data.nama
|
||||
nama: data.nama,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
@@ -709,7 +774,9 @@ const jenisPengaduan = proxy({
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateJenisPengaduanForm.safeParse(jenisPengaduan.edit.form);
|
||||
const cek = templateJenisPengaduanForm.safeParse(
|
||||
jenisPengaduan.edit.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
@@ -759,7 +826,9 @@ const jenisPengaduan = proxy({
|
||||
await jenisPengaduan.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate jenis pengaduan");
|
||||
throw new Error(
|
||||
result.message || "Gagal mengupdate jenis pengaduan"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
// If JSON parsing fails, try to get the response text for better error messages
|
||||
@@ -792,7 +861,6 @@ const jenisPengaduan = proxy({
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
const layananonlineDesa = proxy({
|
||||
administrasiOnline,
|
||||
jenisLayanan,
|
||||
|
||||
229
src/app/admin/(dashboard)/_state/inovasi/mitra-kolaborasi.ts
Normal file
@@ -0,0 +1,229 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const mitraKolaborasiForm = z.object({
|
||||
name: z.string().min(1, { message: "Name is required" }),
|
||||
imageId: z.string().nonempty(),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
name: "",
|
||||
imageId: "",
|
||||
};
|
||||
|
||||
const mitraKolaborasi = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = mitraKolaborasiForm.safeParse(mitraKolaborasi.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
mitraKolaborasi.create.loading = true;
|
||||
const res = await ApiFetch.api.inovasi.mitrakolaborasi["create"].post(
|
||||
mitraKolaborasi.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
mitraKolaborasi.findMany.load();
|
||||
return toast.success("mitraKolaborasi berhasil disimpan!");
|
||||
}
|
||||
return toast.error("Gagal menyimpan mitraKolaborasi");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
mitraKolaborasi.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
mitraKolaborasi.create.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.MitraKolaborasiGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
mitraKolaborasi.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
mitraKolaborasi.findMany.page = page;
|
||||
mitraKolaborasi.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.inovasi.mitrakolaborasi["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
mitraKolaborasi.findMany.data = res.data.data ?? [];
|
||||
mitraKolaborasi.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
mitraKolaborasi.findMany.data = [];
|
||||
mitraKolaborasi.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch mitraKolaborasi paginated:", err);
|
||||
mitraKolaborasi.findMany.data = [];
|
||||
mitraKolaborasi.findMany.totalPages = 1;
|
||||
} finally {
|
||||
mitraKolaborasi.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.MitraKolaborasiGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/inovasi/mitrakolaborasi/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
mitraKolaborasi.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch mitraKolaborasi:", res.statusText);
|
||||
mitraKolaborasi.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching mitraKolaborasi:", error);
|
||||
mitraKolaborasi.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
mitraKolaborasi.delete.loading = true;
|
||||
const response = await fetch(`/api/inovasi/mitrakolaborasi/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const result = await response.json();
|
||||
if (response.ok) {
|
||||
toast.success(result.message || "mitraKolaborasi berhasil dihapus");
|
||||
await mitraKolaborasi.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result.message || "Gagal menghapus mitraKolaborasi");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus mitraKolaborasi");
|
||||
} finally {
|
||||
mitraKolaborasi.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(`/api/inovasi/mitrakolaborasi/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
imageId: data.imageId,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading mitraKolaborasi:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = mitraKolaborasiForm.safeParse(mitraKolaborasi.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
mitraKolaborasi.update.loading = true;
|
||||
const response = await fetch(`/api/inovasi/mitrakolaborasi/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
imageId: this.form.imageId,
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success(result.message || "mitraKolaborasi berhasil diupdate");
|
||||
await mitraKolaborasi.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate mitraKolaborasi");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating mitraKolaborasi:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal mengupdate mitraKolaborasi"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
mitraKolaborasi.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
mitraKolaborasi.update.id = "";
|
||||
mitraKolaborasi.update.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default mitraKolaborasi;
|
||||
@@ -54,34 +54,32 @@ const programKreatifState = proxy({
|
||||
data: null as any[] | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => {
|
||||
// Change to arrow function
|
||||
programKreatifState.findMany.loading = true; // Use the full path to access the property
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
programKreatifState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
programKreatifState.findMany.page = page;
|
||||
programKreatifState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const res = await ApiFetch.api.inovasi.programkreatif["find-many"].get({
|
||||
query: { page, limit },
|
||||
});
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.inovasi.programkreatif[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
programKreatifState.findMany.data = res.data.data || [];
|
||||
programKreatifState.findMany.total = res.data.total || 0;
|
||||
programKreatifState.findMany.totalPages = res.data.totalPages || 1;
|
||||
programKreatifState.findMany.data = res.data.data ?? [];
|
||||
programKreatifState.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to load grafik berdasarkan jenis kelamin:",
|
||||
res.data?.message
|
||||
);
|
||||
programKreatifState.findMany.data = [];
|
||||
programKreatifState.findMany.total = 0;
|
||||
programKreatifState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading grafik berdasarkan jenis kelamin:", error);
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch program kreatif paginated:", err);
|
||||
programKreatifState.findMany.data = [];
|
||||
programKreatifState.findMany.total = 0;
|
||||
programKreatifState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
programKreatifState.findMany.loading = false;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -53,15 +54,39 @@ const keamananLingkunganState = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.KeamananLingkunganGetPayload<{
|
||||
include: { image: true };
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.keamanan.keamananlingkungan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
keamananLingkunganState.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
keamananLingkunganState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
keamananLingkunganState.findMany.page = page;
|
||||
keamananLingkunganState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.keamanan.keamananlingkungan["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
keamananLingkunganState.findMany.data = res.data.data ?? [];
|
||||
keamananLingkunganState.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
keamananLingkunganState.findMany.data = [];
|
||||
keamananLingkunganState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch keamanan lingkungan paginated:", err);
|
||||
keamananLingkunganState.findMany.data = [];
|
||||
keamananLingkunganState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
keamananLingkunganState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -6,26 +7,14 @@ import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
imageId: z.string().nonempty(),
|
||||
kontakItems: z.array(
|
||||
z.object({
|
||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
nomorTelepon: z.string().min(1, "Nomor Telepon minimal 1 karakter"),
|
||||
imageId: z.string().nonempty(),
|
||||
})
|
||||
),
|
||||
icon: z.string().nonempty(),
|
||||
kategoriId: z.array(z.string()).min(1, "Minimal pilih satu kategori"),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
nama: "",
|
||||
imageId: "",
|
||||
kontakItems: [
|
||||
{
|
||||
nama: "",
|
||||
nomorTelepon: "",
|
||||
imageId: "",
|
||||
},
|
||||
],
|
||||
icon: "",
|
||||
kategoriId: [] as string[],
|
||||
};
|
||||
|
||||
const kontakDaruratKeamananState = proxy({
|
||||
@@ -61,20 +50,49 @@ const kontakDaruratKeamananState = proxy({
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.KontakDaruratKeamananGetPayload<{
|
||||
include: {
|
||||
kontakItems: true;
|
||||
image: true;
|
||||
data: null as Array<
|
||||
Prisma.KontakDaruratKeamananGetPayload<{
|
||||
include: {
|
||||
kategori: true;
|
||||
kontakItems: {
|
||||
include: {
|
||||
kontakItem: true;
|
||||
};
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.keamanan.kontakdaruratkeamanan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
kontakDaruratKeamananState.findMany.data = res.data?.data ?? [];
|
||||
};
|
||||
}>
|
||||
> | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
kontakDaruratKeamananState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
kontakDaruratKeamananState.findMany.page = page;
|
||||
kontakDaruratKeamananState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.keamanan.kontakdaruratkeamanan[
|
||||
"findMany"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kontakDaruratKeamananState.findMany.data = res.data.data ?? [];
|
||||
kontakDaruratKeamananState.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
kontakDaruratKeamananState.findMany.data = [];
|
||||
kontakDaruratKeamananState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch kontak darurat paginated:", err);
|
||||
kontakDaruratKeamananState.findMany.data = [];
|
||||
kontakDaruratKeamananState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
kontakDaruratKeamananState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -83,10 +101,10 @@ const kontakDaruratKeamananState = proxy({
|
||||
include: {
|
||||
kontakItems: {
|
||||
include: {
|
||||
image: true;
|
||||
kontakItem: true;
|
||||
};
|
||||
};
|
||||
image: true;
|
||||
kategori: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
@@ -168,14 +186,9 @@ const kontakDaruratKeamananState = proxy({
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
nama: data.nama,
|
||||
imageId: data.imageId,
|
||||
kontakItems: [
|
||||
{
|
||||
nama: data.kontakItems.nama,
|
||||
nomorTelepon: data.kontakItems.nomorTelepon,
|
||||
imageId: data.kontakItems.imageId,
|
||||
},
|
||||
],
|
||||
icon: data.icon || "",
|
||||
kategoriId:
|
||||
data.kontakItems?.map((item: any) => item.kontakItemId) || [],
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
@@ -212,14 +225,8 @@ const kontakDaruratKeamananState = proxy({
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: this.form.nama,
|
||||
imageId: this.form.imageId,
|
||||
kontakItems: [
|
||||
{
|
||||
nama: this.form.kontakItems[0].nama,
|
||||
nomorTelepon: this.form.kontakItems[0].nomorTelepon,
|
||||
imageId: this.form.kontakItems[0].imageId,
|
||||
},
|
||||
],
|
||||
icon: this.form.icon,
|
||||
kategoriId: this.form.kategoriId,
|
||||
}),
|
||||
}
|
||||
);
|
||||
@@ -256,4 +263,242 @@ const kontakDaruratKeamananState = proxy({
|
||||
},
|
||||
});
|
||||
|
||||
export default kontakDaruratKeamananState;
|
||||
const templateFormItem = z.object({
|
||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
nomorTelepon: z.string().min(1, "Nomor Telepon minimal 1 karakter"),
|
||||
icon: z.string().nonempty(),
|
||||
});
|
||||
|
||||
const defaultFormItem = {
|
||||
nama: "",
|
||||
nomorTelepon: "",
|
||||
icon: "",
|
||||
};
|
||||
|
||||
const kontakDaruratItem = proxy({
|
||||
create: {
|
||||
form: { ...defaultFormItem },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateFormItem.safeParse(kontakDaruratItem.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
kontakDaruratItem.create.loading = true;
|
||||
const res = await ApiFetch.api.keamanan.kontakitem["create"].post(
|
||||
kontakDaruratItem.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
kontakDaruratItem.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
kontakDaruratItem.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<
|
||||
Prisma.KontakItemGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}>
|
||||
> | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
kontakDaruratItem.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
kontakDaruratItem.findMany.page = page;
|
||||
kontakDaruratItem.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.keamanan.kontakitem["find-many"].get({
|
||||
query,
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kontakDaruratItem.findMany.data = res.data.data ?? [];
|
||||
kontakDaruratItem.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
kontakDaruratItem.findMany.data = [];
|
||||
kontakDaruratItem.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch kontak darurat paginated:", err);
|
||||
kontakDaruratItem.findMany.data = [];
|
||||
kontakDaruratItem.findMany.totalPages = 1;
|
||||
} finally {
|
||||
kontakDaruratItem.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.KontakItemGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/keamanan/kontakitem/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
kontakDaruratItem.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
kontakDaruratItem.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
kontakDaruratItem.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
kontakDaruratItem.delete.loading = true;
|
||||
const response = await fetch(`/api/keamanan/kontakitem/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Kontak item berhasil dihapus");
|
||||
await kontakDaruratItem.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus kontak item");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus kontak item");
|
||||
} finally {
|
||||
kontakDaruratItem.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultFormItem },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/keamanan/kontakitem/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
nama: data.nama,
|
||||
nomorTelepon: data.nomorTelepon,
|
||||
icon: data.icon,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading kontak darurat:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateFormItem.safeParse(kontakDaruratItem.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
kontakDaruratItem.update.loading = true;
|
||||
const response = await fetch(`/api/keamanan/kontakitem/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: this.form.nama,
|
||||
nomorTelepon: this.form.nomorTelepon,
|
||||
icon: this.form.icon,
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success("Berhasil update kontak item");
|
||||
await kontakDaruratItem.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate kontak item");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating kontak item:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal mengupdate kontak item"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
kontakDaruratItem.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
kontakDaruratItem.update.id = "";
|
||||
kontakDaruratItem.update.form = { ...defaultFormItem };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const kontakDarurat = proxy({
|
||||
kontakDaruratKeamananState,
|
||||
kontakDaruratItem,
|
||||
});
|
||||
|
||||
export default kontakDarurat;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -10,12 +11,24 @@ const templateForm = z.object({
|
||||
judul: z.string().min(3, "Judul minimal 3 karakter"),
|
||||
lokasi: z.string().min(3, "Lokasi minimal 3 karakter"),
|
||||
tanggalWaktu: z.string().min(3, "Tanggal Waktu minimal 3 karakter"),
|
||||
status: z.enum(["Selesai", "Proses", "Gagal"]),
|
||||
penanganan: z.string(),
|
||||
kronologi: z.string().optional(),
|
||||
});
|
||||
|
||||
interface FormData {
|
||||
judul: string;
|
||||
lokasi: string;
|
||||
tanggalWaktu: string;
|
||||
kronologi: string;
|
||||
}
|
||||
|
||||
const defaultForm: FormData = {
|
||||
judul: "",
|
||||
lokasi: "",
|
||||
tanggalWaktu: new Date().toISOString(),
|
||||
kronologi: "",
|
||||
};
|
||||
|
||||
interface FormEditData {
|
||||
judul: string;
|
||||
lokasi: string;
|
||||
tanggalWaktu: string;
|
||||
@@ -24,15 +37,16 @@ interface FormData {
|
||||
kronologi: string;
|
||||
}
|
||||
|
||||
const defaultForm: FormData = {
|
||||
const editForm: FormEditData = {
|
||||
judul: "",
|
||||
lokasi: "",
|
||||
tanggalWaktu: new Date().toISOString(),
|
||||
kronologi: "",
|
||||
status: "Proses",
|
||||
penanganan: "",
|
||||
kronologi: "",
|
||||
};
|
||||
|
||||
|
||||
const laporanPublikState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
@@ -97,13 +111,37 @@ const laporanPublikState = proxy({
|
||||
include: { penanganan: true };
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.keamanan.laporanpublik["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
laporanPublikState.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
laporanPublikState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
laporanPublikState.findMany.page = page;
|
||||
laporanPublikState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.keamanan.laporanpublik["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
laporanPublikState.findMany.data = res.data.data ?? [];
|
||||
laporanPublikState.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
laporanPublikState.findMany.data = [];
|
||||
laporanPublikState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch laporan publik paginated:", err);
|
||||
laporanPublikState.findMany.data = [];
|
||||
laporanPublikState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
laporanPublikState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.LaporanPublikGetPayload<{
|
||||
include: { penanganan: true };
|
||||
@@ -160,7 +198,7 @@ const laporanPublikState = proxy({
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultForm },
|
||||
form: { ...editForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
@@ -266,7 +304,7 @@ const laporanPublikState = proxy({
|
||||
},
|
||||
reset() {
|
||||
laporanPublikState.edit.id = "";
|
||||
laporanPublikState.edit.form = { ...defaultForm };
|
||||
laporanPublikState.edit.form = { ...editForm };
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -5,45 +6,17 @@ import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
pencegahanKriminalitas: z.object({
|
||||
programKeamanan: z.object({
|
||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||
slug: z.string().min(1, "Slug minimal 1 karakter"),
|
||||
}),
|
||||
tipsKeamanan: z.object({
|
||||
judul: z.string().min(1, "Judul minimal 1 karakter"),
|
||||
konten: z.string().min(1, "Konten minimal 1 karakter"),
|
||||
slug: z.string().min(1, "Slug minimal 1 karakter"),
|
||||
}),
|
||||
videoKeamanan: z.object({
|
||||
judul: z.string().min(1, "Judul minimal 1 karakter"),
|
||||
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||
videoUrl: z.string().min(1, "Video URL minimal 1 karakter"),
|
||||
slug: z.string().min(1, "Slug minimal 1 karakter"),
|
||||
}),
|
||||
}),
|
||||
judul: z.string().min(1, "Judul minimal 1 karakter"),
|
||||
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||
deskripsiSingkat: z.string().min(1, "Deskripsi singkat minimal 1 karakter"),
|
||||
linkVideo: z.string().min(1, "Link video minimal 1 karakter"),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
pencegahanKriminalitas: {
|
||||
programKeamanan: {
|
||||
nama: "",
|
||||
deskripsi: "",
|
||||
slug: "",
|
||||
},
|
||||
tipsKeamanan: {
|
||||
judul: "",
|
||||
konten: "",
|
||||
slug: "",
|
||||
},
|
||||
videoKeamanan: {
|
||||
judul: "",
|
||||
deskripsi: "",
|
||||
videoUrl: "",
|
||||
slug: "",
|
||||
},
|
||||
},
|
||||
judul: "",
|
||||
deskripsi: "",
|
||||
deskripsiSingkat: "",
|
||||
linkVideo: "",
|
||||
};
|
||||
|
||||
const pencegahanKriminalitasState = proxy({
|
||||
@@ -64,7 +37,7 @@ const pencegahanKriminalitasState = proxy({
|
||||
pencegahanKriminalitasState.create.loading = true;
|
||||
const res = await ApiFetch.api.keamanan.pencegahankriminalitas[
|
||||
"create"
|
||||
].post(pencegahanKriminalitasState.create.form.pencegahanKriminalitas);
|
||||
].post(pencegahanKriminalitasState.create.form);
|
||||
if (res.status === 200) {
|
||||
pencegahanKriminalitasState.findMany.load();
|
||||
return toast.success("success create");
|
||||
@@ -81,29 +54,46 @@ const pencegahanKriminalitasState = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PencegahanKriminalitasGetPayload<{
|
||||
include: {
|
||||
programKeamanan: true;
|
||||
tipsKeamanan: true;
|
||||
videoKeamanan: true;
|
||||
};
|
||||
omit: { isActive: true };
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.keamanan.pencegahankriminalitas[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
pencegahanKriminalitasState.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
pencegahanKriminalitasState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
pencegahanKriminalitasState.findMany.page = page;
|
||||
pencegahanKriminalitasState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.keamanan.pencegahankriminalitas[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pencegahanKriminalitasState.findMany.data = res.data.data ?? [];
|
||||
pencegahanKriminalitasState.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
pencegahanKriminalitasState.findMany.data = [];
|
||||
pencegahanKriminalitasState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch pencegahan kriminalitas paginated:", err);
|
||||
pencegahanKriminalitasState.findMany.data = [];
|
||||
pencegahanKriminalitasState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
pencegahanKriminalitasState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PencegahanKriminalitasGetPayload<{
|
||||
include: {
|
||||
programKeamanan: true;
|
||||
tipsKeamanan: true;
|
||||
videoKeamanan: true;
|
||||
};
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
@@ -122,6 +112,30 @@ const pencegahanKriminalitasState = proxy({
|
||||
}
|
||||
},
|
||||
},
|
||||
findFirst: {
|
||||
data: null as Prisma.PencegahanKriminalitasGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
loading: false,
|
||||
// findFirst.load()
|
||||
async load() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const res = await ApiFetch.api.keamanan.pencegahankriminalitas["find-first"].get();
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
this.data = res.data.data || null;
|
||||
} else {
|
||||
this.data = null;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch pencegahan kriminalitas terbaru:", err);
|
||||
this.data = null;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
@@ -187,24 +201,10 @@ const pencegahanKriminalitasState = proxy({
|
||||
const data = result.data;
|
||||
pencegahanKriminalitasState.update.id = data.id;
|
||||
pencegahanKriminalitasState.update.form = {
|
||||
pencegahanKriminalitas: {
|
||||
programKeamanan: {
|
||||
nama: data.programKeamanan.nama,
|
||||
deskripsi: data.programKeamanan.deskripsi,
|
||||
slug: data.programKeamanan.slug,
|
||||
},
|
||||
tipsKeamanan: {
|
||||
judul: data.tipsKeamanan.judul,
|
||||
konten: data.tipsKeamanan.konten,
|
||||
slug: data.tipsKeamanan.slug,
|
||||
},
|
||||
videoKeamanan: {
|
||||
judul: data.videoKeamanan.judul,
|
||||
deskripsi: data.videoKeamanan.deskripsi,
|
||||
videoUrl: data.videoKeamanan.videoUrl,
|
||||
slug: data.videoKeamanan.slug,
|
||||
},
|
||||
},
|
||||
judul: data.judul,
|
||||
deskripsi: data.deskripsi,
|
||||
deskripsiSingkat: data.deskripsiSingkat,
|
||||
linkVideo: data.linkVideo,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
@@ -240,40 +240,11 @@ const pencegahanKriminalitasState = proxy({
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
pencegahanKriminalitas: {
|
||||
programKeamanan: {
|
||||
nama: pencegahanKriminalitasState.update.form
|
||||
.pencegahanKriminalitas.programKeamanan.nama,
|
||||
deskripsi:
|
||||
pencegahanKriminalitasState.update.form
|
||||
.pencegahanKriminalitas.programKeamanan.deskripsi,
|
||||
slug: pencegahanKriminalitasState.update.form
|
||||
.pencegahanKriminalitas.programKeamanan.slug,
|
||||
},
|
||||
tipsKeamanan: {
|
||||
judul:
|
||||
pencegahanKriminalitasState.update.form
|
||||
.pencegahanKriminalitas.tipsKeamanan.judul,
|
||||
konten:
|
||||
pencegahanKriminalitasState.update.form
|
||||
.pencegahanKriminalitas.tipsKeamanan.konten,
|
||||
slug: pencegahanKriminalitasState.update.form
|
||||
.pencegahanKriminalitas.tipsKeamanan.slug,
|
||||
},
|
||||
videoKeamanan: {
|
||||
judul:
|
||||
pencegahanKriminalitasState.update.form
|
||||
.pencegahanKriminalitas.videoKeamanan.judul,
|
||||
deskripsi:
|
||||
pencegahanKriminalitasState.update.form
|
||||
.pencegahanKriminalitas.videoKeamanan.deskripsi,
|
||||
videoUrl:
|
||||
pencegahanKriminalitasState.update.form
|
||||
.pencegahanKriminalitas.videoKeamanan.videoUrl,
|
||||
slug: pencegahanKriminalitasState.update.form
|
||||
.pencegahanKriminalitas.videoKeamanan.slug,
|
||||
},
|
||||
},
|
||||
judul: pencegahanKriminalitasState.update.form.judul,
|
||||
deskripsi: pencegahanKriminalitasState.update.form.deskripsi,
|
||||
deskripsiSingkat:
|
||||
pencegahanKriminalitasState.update.form.deskripsiSingkat,
|
||||
linkVideo: pencegahanKriminalitasState.update.form.linkVideo,
|
||||
}),
|
||||
}
|
||||
);
|
||||
@@ -311,4 +282,4 @@ const pencegahanKriminalitasState = proxy({
|
||||
},
|
||||
},
|
||||
});
|
||||
export default pencegahanKriminalitasState;
|
||||
export default pencegahanKriminalitasState;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -63,13 +64,41 @@ const polsekTerdekatState = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PolsekTerdekatGetPayload<{
|
||||
include: { layananPolsek: true };
|
||||
include: {
|
||||
layananPolsek: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.keamanan.polsekterdekat["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
polsekTerdekatState.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
polsekTerdekatState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
polsekTerdekatState.findMany.page = page;
|
||||
polsekTerdekatState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.keamanan.polsekterdekat["find-many"].get(
|
||||
{ query }
|
||||
);
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
polsekTerdekatState.findMany.data = res.data.data ?? [];
|
||||
polsekTerdekatState.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
polsekTerdekatState.findMany.data = [];
|
||||
polsekTerdekatState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch polsek terdekat paginated:", err);
|
||||
polsekTerdekatState.findMany.data = [];
|
||||
polsekTerdekatState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
polsekTerdekatState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -237,6 +266,29 @@ const polsekTerdekatState = proxy({
|
||||
polsekTerdekatState.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
findFirst: {
|
||||
data: null as Prisma.PolsekTerdekatGetPayload<{
|
||||
include: {
|
||||
layananPolsek: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
load: async () => { // Changed to arrow function
|
||||
polsekTerdekatState.findFirst.loading = true;
|
||||
try {
|
||||
const res = await ApiFetch.api.keamanan.polsekterdekat["find-first"].get();
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
polsekTerdekatState.findFirst.data = res.data.data || null;
|
||||
} else {
|
||||
polsekTerdekatState.findFirst.data = null;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch polsek terdekat terbaru:", err);
|
||||
} finally {
|
||||
polsekTerdekatState.findFirst.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default polsekTerdekatState;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -53,15 +54,39 @@ const tipsKeamananState = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.MenuTipsKeamananGetPayload<{
|
||||
include: { image: true };
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.keamanan.menutipskeamanan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
tipsKeamananState.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
tipsKeamananState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
tipsKeamananState.findMany.page = page;
|
||||
tipsKeamananState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.keamanan.menutipskeamanan["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
tipsKeamananState.findMany.data = res.data.data ?? [];
|
||||
tipsKeamananState.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
tipsKeamananState.findMany.data = [];
|
||||
tipsKeamananState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch menu tips keamanan paginated:", err);
|
||||
tipsKeamananState.findMany.data = [];
|
||||
tipsKeamananState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
tipsKeamananState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -31,11 +31,13 @@ const templateForm = z.object({
|
||||
doctorSign: z.object({
|
||||
content: z.string().min(1, "Content harus diisi"),
|
||||
}),
|
||||
imageId: z.string().min(1, "Image ID harus diisi"),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
title: "",
|
||||
content: "",
|
||||
imageId: "",
|
||||
introduction: {
|
||||
content: "",
|
||||
},
|
||||
@@ -59,6 +61,7 @@ const defaultForm = {
|
||||
doctorSign: {
|
||||
content: "",
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
const artikelKesehatanState = proxy({
|
||||
@@ -112,30 +115,42 @@ const artikelKesehatanState = proxy({
|
||||
firstaid: true;
|
||||
mythvsfact: true;
|
||||
doctorsign: true;
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
async load() {
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
artikelKesehatanState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
artikelKesehatanState.findMany.page = page;
|
||||
artikelKesehatanState.findMany.search = search;
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await (ApiFetch.api.kesehatan as any)["artikel-kesehatan"][
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan["artikel-kesehatan"][
|
||||
"find-many"
|
||||
].get();
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200) {
|
||||
this.data = res.data?.data ?? [];
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
artikelKesehatanState.findMany.data =
|
||||
res.data.data ?? [];
|
||||
artikelKesehatanState.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
toast.error("Gagal memuat data artikel kesehatan");
|
||||
artikelKesehatanState.findMany.data = [];
|
||||
artikelKesehatanState.findMany.totalPages = 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
} catch (err) {
|
||||
toast.error("Terjadi error saat load data");
|
||||
console.error("LOAD ERROR:", err);
|
||||
throw err;
|
||||
console.error("Gagal fetch artikel kesehatan paginated:", err);
|
||||
artikelKesehatanState.findMany.data = [];
|
||||
artikelKesehatanState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
artikelKesehatanState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -148,6 +163,7 @@ const artikelKesehatanState = proxy({
|
||||
firstaid: true;
|
||||
mythvsfact: true;
|
||||
doctorsign: true;
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
@@ -202,6 +218,7 @@ const artikelKesehatanState = proxy({
|
||||
doctorSign: {
|
||||
content: data.doctorsign.content,
|
||||
},
|
||||
imageId: data.imageId,
|
||||
};
|
||||
},
|
||||
async submit() {
|
||||
@@ -242,6 +259,7 @@ const artikelKesehatanState = proxy({
|
||||
doctorSign: {
|
||||
content: artikelKesehatanState.edit.form.doctorSign.content,
|
||||
},
|
||||
imageId: artikelKesehatanState.edit.form.imageId,
|
||||
};
|
||||
|
||||
const res = await fetch(
|
||||
@@ -280,12 +298,9 @@ const artikelKesehatanState = proxy({
|
||||
async byId(id: string) {
|
||||
try {
|
||||
artikelKesehatanState.delete.loading = true;
|
||||
const res = await fetch(
|
||||
`/api/kesehatan/artikel-kesehatan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
}
|
||||
);
|
||||
const res = await fetch(`/api/kesehatan/artikel-kesehatan/del/${id}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
|
||||
const result = await res.json();
|
||||
if (res.ok && result.success) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
//fasilitas kesehatan aja
|
||||
// Validasi form
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(1, "Nama harus diisi"),
|
||||
@@ -61,7 +62,7 @@ const defaultForm = {
|
||||
},
|
||||
};
|
||||
|
||||
const fasilitasKesehatanState = proxy({
|
||||
const fasilitasKesehatan = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
@@ -86,7 +87,7 @@ const fasilitasKesehatanState = proxy({
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil menambahkan fasilitas kesehatan");
|
||||
this.resetForm();
|
||||
await fasilitasKesehatanState.findMany.load();
|
||||
await fasilitasKesehatan.findMany.load();
|
||||
return res.data;
|
||||
}
|
||||
} catch (err: any) {
|
||||
@@ -102,7 +103,6 @@ const fasilitasKesehatanState = proxy({
|
||||
this.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.FasilitasKesehatanGetPayload<{
|
||||
@@ -116,27 +116,38 @@ const fasilitasKesehatanState = proxy({
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
async load() {
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
fasilitasKesehatanState.fasilitasKesehatan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
fasilitasKesehatanState.fasilitasKesehatan.findMany.page = page;
|
||||
fasilitasKesehatanState.fasilitasKesehatan.findMany.search = search;
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await (ApiFetch.api.kesehatan as any)[
|
||||
"fasilitas-kesehatan"
|
||||
]["find-many"].get();
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
if (res.status === 200) {
|
||||
this.data = res.data?.data ?? [];
|
||||
const res = await ApiFetch.api.kesehatan["fasilitas-kesehatan"][
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
fasilitasKesehatanState.fasilitasKesehatan.findMany.data =
|
||||
res.data.data ?? [];
|
||||
fasilitasKesehatanState.fasilitasKesehatan.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
toast.error("Gagal memuat data fasilitas kesehatan");
|
||||
fasilitasKesehatanState.fasilitasKesehatan.findMany.data = [];
|
||||
fasilitasKesehatanState.fasilitasKesehatan.findMany.totalPages = 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
} catch (err) {
|
||||
toast.error("Terjadi error saat load data");
|
||||
console.error("LOAD ERROR:", err);
|
||||
throw err;
|
||||
console.error("Gagal fetch fasilitas kesehatan paginated:", err);
|
||||
fasilitasKesehatanState.fasilitasKesehatan.findMany.data = [];
|
||||
fasilitasKesehatanState.fasilitasKesehatan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
fasilitasKesehatanState.fasilitasKesehatan.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -156,7 +167,7 @@ const fasilitasKesehatanState = proxy({
|
||||
const res = await fetch(`/api/kesehatan/fasilitas-kesehatan/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
fasilitasKesehatanState.findUnique.data = data.data ?? null;
|
||||
fasilitasKesehatan.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
toast.error("Gagal load data fasilitas kesehatan");
|
||||
}
|
||||
@@ -176,8 +187,8 @@ const fasilitasKesehatanState = proxy({
|
||||
const result = await res.json();
|
||||
const data = result.data;
|
||||
|
||||
fasilitasKesehatanState.edit.id = data.id;
|
||||
fasilitasKesehatanState.edit.form = {
|
||||
fasilitasKesehatan.edit.id = data.id;
|
||||
fasilitasKesehatan.edit.form = {
|
||||
name: data.name,
|
||||
informasiUmum: {
|
||||
fasilitas: data.informasiumum.fasilitas,
|
||||
@@ -205,7 +216,7 @@ const fasilitasKesehatanState = proxy({
|
||||
};
|
||||
},
|
||||
async submit() {
|
||||
const cek = templateForm.safeParse(fasilitasKesehatanState.edit.form);
|
||||
const cek = templateForm.safeParse(fasilitasKesehatan.edit.form);
|
||||
if (!cek.success) {
|
||||
const errMsg = cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}: ${v.message}`)
|
||||
@@ -215,42 +226,38 @@ const fasilitasKesehatanState = proxy({
|
||||
}
|
||||
|
||||
try {
|
||||
fasilitasKesehatanState.edit.loading = true;
|
||||
fasilitasKesehatan.edit.loading = true;
|
||||
const payload = {
|
||||
name: fasilitasKesehatanState.edit.form.name,
|
||||
name: fasilitasKesehatan.edit.form.name,
|
||||
informasiUmum: {
|
||||
fasilitas:
|
||||
fasilitasKesehatanState.edit.form.informasiUmum.fasilitas,
|
||||
alamat: fasilitasKesehatanState.edit.form.informasiUmum.alamat,
|
||||
fasilitas: fasilitasKesehatan.edit.form.informasiUmum.fasilitas,
|
||||
alamat: fasilitasKesehatan.edit.form.informasiUmum.alamat,
|
||||
jamOperasional:
|
||||
fasilitasKesehatanState.edit.form.informasiUmum.jamOperasional,
|
||||
fasilitasKesehatan.edit.form.informasiUmum.jamOperasional,
|
||||
},
|
||||
layananUnggulan: {
|
||||
content: fasilitasKesehatanState.edit.form.layananUnggulan.content,
|
||||
content: fasilitasKesehatan.edit.form.layananUnggulan.content,
|
||||
},
|
||||
dokterdanTenagaMedis: {
|
||||
name: fasilitasKesehatanState.edit.form.dokterdanTenagaMedis.name,
|
||||
name: fasilitasKesehatan.edit.form.dokterdanTenagaMedis.name,
|
||||
specialist:
|
||||
fasilitasKesehatanState.edit.form.dokterdanTenagaMedis.specialist,
|
||||
jadwal:
|
||||
fasilitasKesehatanState.edit.form.dokterdanTenagaMedis.jadwal,
|
||||
fasilitasKesehatan.edit.form.dokterdanTenagaMedis.specialist,
|
||||
jadwal: fasilitasKesehatan.edit.form.dokterdanTenagaMedis.jadwal,
|
||||
},
|
||||
fasilitasPendukung: {
|
||||
content:
|
||||
fasilitasKesehatanState.edit.form.fasilitasPendukung.content,
|
||||
content: fasilitasKesehatan.edit.form.fasilitasPendukung.content,
|
||||
},
|
||||
prosedurPendaftaran: {
|
||||
content:
|
||||
fasilitasKesehatanState.edit.form.prosedurPendaftaran.content,
|
||||
content: fasilitasKesehatan.edit.form.prosedurPendaftaran.content,
|
||||
},
|
||||
tarifDanLayanan: {
|
||||
layanan: fasilitasKesehatanState.edit.form.tarifDanLayanan.layanan,
|
||||
tarif: fasilitasKesehatanState.edit.form.tarifDanLayanan.tarif,
|
||||
layanan: fasilitasKesehatan.edit.form.tarifDanLayanan.layanan,
|
||||
tarif: fasilitasKesehatan.edit.form.tarifDanLayanan.tarif,
|
||||
},
|
||||
};
|
||||
|
||||
const res = await fetch(
|
||||
`/api/kesehatan/fasilitas-kesehatan/${fasilitasKesehatanState.edit.id}`,
|
||||
`/api/kesehatan/fasilitas-kesehatan/${fasilitasKesehatan.edit.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -264,7 +271,7 @@ const fasilitasKesehatanState = proxy({
|
||||
}
|
||||
|
||||
toast.success("Berhasil update fasilitas kesehatan");
|
||||
await fasilitasKesehatanState.findMany.load();
|
||||
await fasilitasKesehatan.findMany.load();
|
||||
return true;
|
||||
} catch (err) {
|
||||
toast.error(
|
||||
@@ -272,37 +279,297 @@ const fasilitasKesehatanState = proxy({
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
fasilitasKesehatanState.edit.loading = false;
|
||||
fasilitasKesehatan.edit.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
fasilitasKesehatanState.edit.id = "";
|
||||
fasilitasKesehatanState.edit.form = { ...defaultForm };
|
||||
fasilitasKesehatan.edit.id = "";
|
||||
fasilitasKesehatan.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string){
|
||||
async byId(id: string) {
|
||||
try {
|
||||
fasilitasKesehatanState.delete.loading = true;
|
||||
const res = await fetch(`/api/kesehatan/fasilitas-kesehatan/del/${id}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
fasilitasKesehatan.delete.loading = true;
|
||||
const res = await fetch(
|
||||
`/api/kesehatan/fasilitas-kesehatan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
}
|
||||
);
|
||||
|
||||
const result = await res.json();
|
||||
if (res.ok && result.success) {
|
||||
toast.success("Fasilitas kesehatan berhasil dihapus");
|
||||
await fasilitasKesehatanState.findMany.load();
|
||||
await fasilitasKesehatan.findMany.load();
|
||||
} else {
|
||||
toast.error(result.message || "Gagal menghapus");
|
||||
}
|
||||
} catch {
|
||||
toast.error("Terjadi kesalahan saat menghapus");
|
||||
} finally {
|
||||
fasilitasKesehatanState.delete.loading = false;
|
||||
fasilitasKesehatan.delete.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
//dokter & tenaga medis
|
||||
const templateDokterForm = z.object({
|
||||
name: z.string().min(1, "Nama tidak boleh kosong"),
|
||||
specialist: z.string().min(1, "Spesialis tidak boleh kosong"),
|
||||
jadwal: z.string().min(1, "Jadwal tidak boleh kosong"),
|
||||
});
|
||||
|
||||
const defaultDokterForm = {
|
||||
name: "",
|
||||
specialist: "",
|
||||
jadwal: "",
|
||||
};
|
||||
|
||||
const dokter = proxy({
|
||||
create: {
|
||||
create: {
|
||||
form: defaultDokterForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateDokterForm.safeParse(dokter.create.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
dokter.create.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.doktertenagamedis[
|
||||
"create"
|
||||
].post(dokter.create.create.form);
|
||||
|
||||
if (res.status === 200) {
|
||||
const id = res.data?.data;
|
||||
if (id) {
|
||||
toast.success("Success create");
|
||||
dokter.create.create.form = { ...defaultDokterForm };
|
||||
dokter.findMany.load();
|
||||
return id;
|
||||
}
|
||||
}
|
||||
toast.error("failed create");
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
return null;
|
||||
} finally {
|
||||
dokter.create.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.DokterdanTenagaMedisGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
dokter.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
dokter.findMany.page = page;
|
||||
dokter.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.doktertenagamedis[
|
||||
"findMany"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
dokter.findMany.data = res.data.data ?? [];
|
||||
dokter.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
dokter.findMany.data = [];
|
||||
dokter.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch dokter tenaga medis paginated:", err);
|
||||
dokter.findMany.data = [];
|
||||
dokter.findMany.totalPages = 1;
|
||||
} finally {
|
||||
dokter.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.DokterdanTenagaMedisGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/kesehatan/doktertenagamedis/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
dokter.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to fetch dokter dan tenaga medis",
|
||||
res.statusText
|
||||
);
|
||||
dokter.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching dokter dan tenaga medis", error);
|
||||
dokter.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultDokterForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/kesehatan/doktertenagamedis/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
specialist: data.specialist,
|
||||
jadwal: data.jadwal,
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading dokter dan tenaga medis:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
const formData = {
|
||||
name: this.form.name,
|
||||
specialist: this.form.specialist,
|
||||
jadwal: this.form.jadwal,
|
||||
};
|
||||
|
||||
const cek = templateDokterForm.safeParse(formData);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await fetch(`/api/kesehatan/doktertenagamedis/${id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(formData),
|
||||
});
|
||||
|
||||
const result = await res.json();
|
||||
|
||||
if (!res.ok || !result?.success) {
|
||||
throw new Error(result?.message || "Gagal update data");
|
||||
}
|
||||
|
||||
toast.success("Berhasil update data!");
|
||||
await dokter.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Update error:", error);
|
||||
toast.error("Gagal update data dokter dan tenaga medis");
|
||||
throw error;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) {
|
||||
return toast.warn("ID tidak valid");
|
||||
}
|
||||
try {
|
||||
dokter.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/kesehatan/doktertenagamedis/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Dokter dan tenaga medis berhasil dihapus"
|
||||
);
|
||||
await dokter.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus dokter dan tenaga medis"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus dokter dan tenaga medis");
|
||||
} finally {
|
||||
dokter.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const fasilitasKesehatanState = proxy({
|
||||
fasilitasKesehatan,
|
||||
dokter,
|
||||
});
|
||||
|
||||
export default fasilitasKesehatanState;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -5,20 +6,19 @@ import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateGrafikKepuasan = z.object({
|
||||
label: z.string().min(2, "Label harus diisi"),
|
||||
jumlah: z.string().min(1, "Jumlah harus diisi"),
|
||||
nama: z.string().min(2, "Nama harus diisi"),
|
||||
tanggal: z.string().min(1, "Tanggal harus diisi"),
|
||||
jenisKelamin: z.string().min(1, "Jenis kelamin harus diisi"),
|
||||
alamat: z.string().min(1, "Alamat harus diisi"),
|
||||
penyakit: z.string().min(1, "Penyakit harus diisi"),
|
||||
});
|
||||
|
||||
type GrafikKepuasan = Prisma.GrafikKepuasanGetPayload<{
|
||||
select: {
|
||||
label: true;
|
||||
jumlah: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const defaultForm: GrafikKepuasan = {
|
||||
label: "",
|
||||
jumlah: ""
|
||||
const defaultForm = {
|
||||
nama: "",
|
||||
tanggal: "",
|
||||
jenisKelamin: "",
|
||||
alamat: "",
|
||||
penyakit: "",
|
||||
};
|
||||
|
||||
const grafikkepuasan = proxy({
|
||||
@@ -36,16 +36,15 @@ const grafikkepuasan = proxy({
|
||||
}
|
||||
try {
|
||||
grafikkepuasan.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.grafikkepuasan["create"].post(grafikkepuasan.create.form);
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.grafikkepuasan["create"].post(
|
||||
grafikkepuasan.create.form
|
||||
);
|
||||
|
||||
if (res.status === 200) {
|
||||
const id = res.data?.data?.id;
|
||||
const id = res.data?.data;
|
||||
if (id) {
|
||||
toast.success("Success create");
|
||||
grafikkepuasan.create.form = {
|
||||
label: "",
|
||||
jumlah: "",
|
||||
};
|
||||
grafikkepuasan.create.form = { ...defaultForm };
|
||||
grafikkepuasan.findMany.load();
|
||||
return id;
|
||||
}
|
||||
@@ -62,21 +61,49 @@ const grafikkepuasan = proxy({
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.GrafikKepuasanGetPayload<{ omit: { isActive: true } }>[]
|
||||
| Prisma.GrafikKepuasanGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.grafikkepuasan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
grafikkepuasan.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
grafikkepuasan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
grafikkepuasan.findMany.page = page;
|
||||
grafikkepuasan.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.grafikkepuasan[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
grafikkepuasan.findMany.data = res.data.data ?? [];
|
||||
grafikkepuasan.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
grafikkepuasan.findMany.data = [];
|
||||
grafikkepuasan.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch berita paginated:", err);
|
||||
grafikkepuasan.findMany.data = [];
|
||||
grafikkepuasan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
grafikkepuasan.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.GrafikKepuasanGetPayload<{
|
||||
omit: { isActive: true }
|
||||
}> | null,
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/kesehatan/grafikkepuasan/${id}`);
|
||||
@@ -95,88 +122,137 @@ const grafikkepuasan = proxy({
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: {...defaultForm},
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async byId() {
|
||||
},
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
const cek = templateGrafikKepuasan.safeParse(grafikkepuasan.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
this.loading = true;
|
||||
const response = await fetch(`/api/kesehatan/grafikkepuasan/${id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(this.form),
|
||||
});
|
||||
const result = await response.json();
|
||||
|
||||
if (!response.ok || !result?.success) {
|
||||
throw new Error(result?.message || "Gagal update data");
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
toast.success("Berhasil update data!");
|
||||
try {
|
||||
const response = await fetch(`/api/kesehatan/grafikkepuasan/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
// ✅ Optional: refresh list kalau kamu langsung ke halaman list
|
||||
await grafikkepuasan.findMany.load();
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Error update data:", error);
|
||||
toast.error("Gagal update data grafik kepuasan");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) {
|
||||
return toast.warn("ID tidak valid");
|
||||
}
|
||||
try {
|
||||
grafikkepuasan.delete.loading = true;
|
||||
const result = await response.json();
|
||||
|
||||
const response = await fetch(`/api/kesehatan/grafikkepuasan/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Grafik kepuasan berhasil dihapus"
|
||||
);
|
||||
await grafikkepuasan.findMany.load(); // refresh list
|
||||
} else {
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
nama: data.nama,
|
||||
tanggal: data.tanggal,
|
||||
jenisKelamin: data.jenisKelamin,
|
||||
alamat: data.alamat,
|
||||
penyakit: data.penyakit,
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading grafik kepuasan:", error);
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus grafik kepuasan"
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus grafik kepuasan");
|
||||
} finally {
|
||||
grafikkepuasan.delete.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
const formData = {
|
||||
nama: this.form.nama,
|
||||
tanggal: this.form.tanggal,
|
||||
jenisKelamin: this.form.jenisKelamin,
|
||||
alamat: this.form.alamat,
|
||||
penyakit: this.form.penyakit,
|
||||
};
|
||||
|
||||
const cek = templateGrafikKepuasan.safeParse(formData);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await fetch(`/api/kesehatan/grafikkepuasan/${id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(formData),
|
||||
});
|
||||
|
||||
const result = await res.json();
|
||||
|
||||
if (!res.ok || !result?.success) {
|
||||
throw new Error(result?.message || "Gagal update data");
|
||||
}
|
||||
|
||||
toast.success("Berhasil update data!");
|
||||
await grafikkepuasan.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Update error:", error);
|
||||
toast.error("Gagal update data grafik kepuasan");
|
||||
throw error;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) {
|
||||
return toast.warn("ID tidak valid");
|
||||
}
|
||||
try {
|
||||
grafikkepuasan.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/kesehatan/grafikkepuasan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Grafik kepuasan berhasil dihapus");
|
||||
await grafikkepuasan.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus grafik kepuasan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus grafik kepuasan");
|
||||
} finally {
|
||||
grafikkepuasan.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default grafikkepuasan;
|
||||
|
||||
@@ -120,27 +120,36 @@ const jadwalkegiatanState = proxy({
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
async load() {
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
jadwalkegiatanState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
jadwalkegiatanState.findMany.page = page;
|
||||
jadwalkegiatanState.findMany.search = search;
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await (ApiFetch.api.kesehatan as any)[
|
||||
"jadwal-kegiatan"
|
||||
]["find-many"].get();
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
if (res.status === 200) {
|
||||
this.data = res.data?.data ?? [];
|
||||
const res = await ApiFetch.api.kesehatan["jadwal-kegiatan"][
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
jadwalkegiatanState.findMany.data = res.data.data ?? [];
|
||||
jadwalkegiatanState.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
toast.error("Gagal memuat data jadwal kegiatan");
|
||||
jadwalkegiatanState.findMany.data = [];
|
||||
jadwalkegiatanState.findMany.totalPages = 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
} catch (err) {
|
||||
toast.error("Terjadi error saat load data");
|
||||
console.error("LOAD ERROR:", err);
|
||||
throw err;
|
||||
console.error("Gagal fetch jadwal kegiatan paginated:", err);
|
||||
jadwalkegiatanState.findMany.data = [];
|
||||
jadwalkegiatanState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
jadwalkegiatanState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -227,29 +236,42 @@ const jadwalkegiatanState = proxy({
|
||||
content: jadwalkegiatanState.edit.form.content,
|
||||
informasiJadwalKegiatan: {
|
||||
name: jadwalkegiatanState.edit.form.informasiJadwalKegiatan.name,
|
||||
tanggal: jadwalkegiatanState.edit.form.informasiJadwalKegiatan.tanggal,
|
||||
tanggal:
|
||||
jadwalkegiatanState.edit.form.informasiJadwalKegiatan.tanggal,
|
||||
waktu: jadwalkegiatanState.edit.form.informasiJadwalKegiatan.waktu,
|
||||
lokasi: jadwalkegiatanState.edit.form.informasiJadwalKegiatan.lokasi,
|
||||
lokasi:
|
||||
jadwalkegiatanState.edit.form.informasiJadwalKegiatan.lokasi,
|
||||
},
|
||||
layananJadwalKegiatan: {
|
||||
content: jadwalkegiatanState.edit.form.layananJadwalKegiatan.content,
|
||||
content:
|
||||
jadwalkegiatanState.edit.form.layananJadwalKegiatan.content,
|
||||
},
|
||||
deskripsiJadwalKegiatan: {
|
||||
deskripsi: jadwalkegiatanState.edit.form.deskripsiJadwalKegiatan.deskripsi,
|
||||
deskripsi:
|
||||
jadwalkegiatanState.edit.form.deskripsiJadwalKegiatan.deskripsi,
|
||||
},
|
||||
syaratKetentuanJadwalKegiatan: {
|
||||
content: jadwalkegiatanState.edit.form.syaratKetentuanJadwalKegiatan.content,
|
||||
content:
|
||||
jadwalkegiatanState.edit.form.syaratKetentuanJadwalKegiatan
|
||||
.content,
|
||||
},
|
||||
dokumenJadwalKegiatan: {
|
||||
content: jadwalkegiatanState.edit.form.dokumenJadwalKegiatan.content,
|
||||
content:
|
||||
jadwalkegiatanState.edit.form.dokumenJadwalKegiatan.content,
|
||||
},
|
||||
pendaftaranJadwalKegiatan: {
|
||||
name: jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.name,
|
||||
tanggal: jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.tanggal,
|
||||
namaOrangtua: jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.namaOrangtua,
|
||||
nomor: jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.nomor,
|
||||
alamat: jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.alamat,
|
||||
catatan: jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.catatan,
|
||||
tanggal:
|
||||
jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.tanggal,
|
||||
namaOrangtua:
|
||||
jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan
|
||||
.namaOrangtua,
|
||||
nomor:
|
||||
jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.nomor,
|
||||
alamat:
|
||||
jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.alamat,
|
||||
catatan:
|
||||
jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.catatan,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -286,7 +308,7 @@ const jadwalkegiatanState = proxy({
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string){
|
||||
async byId(id: string) {
|
||||
try {
|
||||
jadwalkegiatanState.delete.loading = true;
|
||||
const res = await fetch(`/api/kesehatan/jadwal-kegiatan/del/${id}`, {
|
||||
@@ -305,7 +327,7 @@ const jadwalkegiatanState = proxy({
|
||||
} finally {
|
||||
jadwalkegiatanState.delete.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(1, "Name minimal 1 karakter"),
|
||||
tanggal: z.string().min(1, "Tanggal minimal 1 karakter"),
|
||||
namaOrangtua: z.string().min(1, "Nama Orangtua minimal 1 karakter"),
|
||||
nomor: z.string().min(1, "Nomor minimal 1 karakter"),
|
||||
alamat: z.string().min(1, "Alamat minimal 1 karakter"),
|
||||
catatan: z.string().min(1, "Catatan minimal 1 karakter"),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
name: "",
|
||||
tanggal: "",
|
||||
namaOrangtua: "",
|
||||
nomor: "",
|
||||
alamat: "",
|
||||
catatan: "",
|
||||
};
|
||||
|
||||
const pendaftaranJadwalKegiatanState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async submit() {
|
||||
const cek = templateForm.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const errMsg = cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}: ${v.message}`)
|
||||
.join("\n");
|
||||
toast.error(errMsg);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const payload = { ...this.form };
|
||||
|
||||
const res = await (ApiFetch.api.kesehatan as any)[
|
||||
"pendaftaran-jadwal-kegiatan"
|
||||
].create.post(payload);
|
||||
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil menambahkan jadwal kegiatan");
|
||||
this.resetForm();
|
||||
await pendaftaranJadwalKegiatanState.findMany.load();
|
||||
return res.data;
|
||||
}
|
||||
} catch (err: any) {
|
||||
const msg = err?.message || "Terjadi kesalahan saat mengirim data";
|
||||
toast.error(msg);
|
||||
console.error("SUBMIT ERROR:", err);
|
||||
return null;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
this.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PendaftaranJadwalKegiatanGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
pendaftaranJadwalKegiatanState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
pendaftaranJadwalKegiatanState.findMany.page = page;
|
||||
pendaftaranJadwalKegiatanState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan["pendaftaran-jadwal-kegiatan"][
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pendaftaranJadwalKegiatanState.findMany.data = res.data.data ?? [];
|
||||
pendaftaranJadwalKegiatanState.findMany.totalPages =
|
||||
res.data.totalPages ?? 1;
|
||||
} else {
|
||||
pendaftaranJadwalKegiatanState.findMany.data = [];
|
||||
pendaftaranJadwalKegiatanState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(
|
||||
"Gagal fetch pendaftaran jadwal kegiatan paginated:",
|
||||
err
|
||||
);
|
||||
pendaftaranJadwalKegiatanState.findMany.data = [];
|
||||
pendaftaranJadwalKegiatanState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
pendaftaranJadwalKegiatanState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PendaftaranJadwalKegiatanGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/kesehatan/pendaftaran-jadwal-kegiatan/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
pendaftaranJadwalKegiatanState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
pendaftaranJadwalKegiatanState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
pendaftaranJadwalKegiatanState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
pendaftaranJadwalKegiatanState.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/kesehatan/pendaftaran-jadwal-kegiatan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Pendaftaran jadwal kegiatan berhasil dihapus"
|
||||
);
|
||||
await pendaftaranJadwalKegiatanState.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus pendaftaran jadwal kegiatan"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error(
|
||||
"Terjadi kesalahan saat menghapus pendaftaran jadwal kegiatan"
|
||||
);
|
||||
} finally {
|
||||
pendaftaranJadwalKegiatanState.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/kesehatan/pendaftaran-jadwal-kegiatan/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
tanggal: data.tanggal,
|
||||
namaOrangtua: data.namaOrangtua,
|
||||
nomor: data.nomor,
|
||||
alamat: data.alamat,
|
||||
catatan: data.catatan,
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading pendaftaran jadwal kegiatan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(pendaftaranJadwalKegiatanState.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
pendaftaranJadwalKegiatanState.edit.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/kesehatan/pendaftaran-jadwal-kegiatan/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
tanggal: this.form.tanggal,
|
||||
namaOrangtua: this.form.namaOrangtua,
|
||||
nomor: this.form.nomor,
|
||||
alamat: this.form.alamat,
|
||||
catatan: this.form.catatan,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
toast.success("Berhasil update pendaftaran jadwal kegiatan");
|
||||
await pendaftaranJadwalKegiatanState.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update pendaftaran jadwal kegiatan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating pendaftaran jadwal kegiatan:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update pendaftaran jadwal kegiatan"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
pendaftaranJadwalKegiatanState.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
pendaftaranJadwalKegiatanState.edit.id = "";
|
||||
pendaftaranJadwalKegiatanState.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default pendaftaranJadwalKegiatanState;
|
||||
@@ -1,10 +1,13 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templatePersentase = z.object({
|
||||
//persentase kelahiran kematian
|
||||
|
||||
const templatePersentaseKelahiran = z.object({
|
||||
tahun: z.string().min(4, "Tahun harus diisi"),
|
||||
kematianKasar: z.string().min(1, "Kematian kasar harus diisi"),
|
||||
kelahiranKasar: z.string().min(1, "Kelahiran kasar harus diisi"),
|
||||
@@ -13,18 +16,14 @@ const templatePersentase = z.object({
|
||||
|
||||
type Persentase = Prisma.DataKematian_KelahiranGetPayload<{
|
||||
select: {
|
||||
tahun: true;
|
||||
kematianKasar: true;
|
||||
kelahiranKasar: true;
|
||||
kematianBayi: true;
|
||||
kematianId: true;
|
||||
kelahiranId: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const defaultForm: Persentase = {
|
||||
tahun: "",
|
||||
kematianKasar: "",
|
||||
kelahiranKasar: "",
|
||||
kematianBayi: "",
|
||||
kematianId: "",
|
||||
kelahiranId: "",
|
||||
};
|
||||
|
||||
const persentasekelahiran = proxy({
|
||||
@@ -32,7 +31,9 @@ const persentasekelahiran = proxy({
|
||||
form: defaultForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templatePersentase.safeParse(persentasekelahiran.create.form);
|
||||
const cek = templatePersentaseKelahiran.safeParse(
|
||||
persentasekelahiran.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
@@ -47,7 +48,7 @@ const persentasekelahiran = proxy({
|
||||
].post(persentasekelahiran.create.form);
|
||||
|
||||
if (res.status === 200) {
|
||||
const id = res.data?.data?.id;
|
||||
const id = res.data?.data;
|
||||
if (id) {
|
||||
toast.success("Success create");
|
||||
persentasekelahiran.create.form = { ...defaultForm };
|
||||
@@ -69,21 +70,51 @@ const persentasekelahiran = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.DataKematian_KelahiranGetPayload<{
|
||||
omit: { isActive: true };
|
||||
include: {
|
||||
kematian: true;
|
||||
kelahiran: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.persentasekelahiran[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
persentasekelahiran.findMany.data = res.data?.data ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
persentasekelahiran.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
persentasekelahiran.findMany.page = page;
|
||||
persentasekelahiran.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.persentasekelahiran[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
persentasekelahiran.findMany.data = res.data.data ?? [];
|
||||
persentasekelahiran.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
persentasekelahiran.findMany.data = [];
|
||||
persentasekelahiran.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch berita paginated:", err);
|
||||
persentasekelahiran.findMany.data = [];
|
||||
persentasekelahiran.findMany.totalPages = 1;
|
||||
} finally {
|
||||
persentasekelahiran.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.DataKematian_KelahiranGetPayload<{
|
||||
omit: { isActive: true };
|
||||
include: {
|
||||
kematian: true;
|
||||
kelahiran: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
@@ -114,13 +145,11 @@ const persentasekelahiran = proxy({
|
||||
}
|
||||
|
||||
const formData = {
|
||||
tahun: this.form.tahun,
|
||||
kematianKasar: this.form.kematianKasar,
|
||||
kelahiranKasar: this.form.kelahiranKasar,
|
||||
kematianBayi: this.form.kematianBayi,
|
||||
kematianId: this.form.kematianId,
|
||||
kelahiranId: this.form.kelahiranId,
|
||||
};
|
||||
|
||||
const cek = templatePersentase.safeParse(formData);
|
||||
const cek = templatePersentaseKelahiran.safeParse(formData);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
@@ -197,4 +226,521 @@ const persentasekelahiran = proxy({
|
||||
},
|
||||
});
|
||||
|
||||
export default persentasekelahiran;
|
||||
// data kelahiran
|
||||
|
||||
const templateKelahiran = z.object({
|
||||
nama: z.string().min(1, "Nama harus diisi"),
|
||||
tanggal: z.string().min(4, "Tahun harus diisi"),
|
||||
jenisKelamin: z.string().min(1, "Jenis kelamin harus diisi"),
|
||||
alamat: z.string().min(1, "Alamat harus diisi"),
|
||||
});
|
||||
|
||||
const defaultKelahiran = {
|
||||
nama: "",
|
||||
tanggal: "",
|
||||
jenisKelamin: "",
|
||||
alamat: "",
|
||||
};
|
||||
|
||||
const kelahiran = proxy({
|
||||
create: {
|
||||
form: { ...defaultKelahiran }, // ✅ ini kunci fix-nya
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateKelahiran.safeParse(kelahiran.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
kelahiran.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.kelahiran["create"].post(
|
||||
kelahiran.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
kelahiran.findMany.load();
|
||||
return toast.success("Kelahiran berhasil disimpan!");
|
||||
}
|
||||
|
||||
return toast.error("Gagal menyimpan kelahiran");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
kelahiran.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
kelahiran.create.form = { ...defaultKelahiran };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.KelahiranGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
kelahiran.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
kelahiran.findMany.page = page;
|
||||
kelahiran.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.kelahiran["findMany"].get({
|
||||
query,
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kelahiran.findMany.data = res.data.data ?? [];
|
||||
kelahiran.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
kelahiran.findMany.data = [];
|
||||
kelahiran.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch kelahiran paginated:", err);
|
||||
kelahiran.findMany.data = [];
|
||||
kelahiran.findMany.totalPages = 1;
|
||||
} finally {
|
||||
kelahiran.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.KelahiranGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/kesehatan/kelahiran/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
kelahiran.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch kelahiran:", res.statusText);
|
||||
kelahiran.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching kelahiran:", error);
|
||||
kelahiran.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
kelahiran.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/kesehatan/kelahiran/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Kelahiran berhasil dihapus");
|
||||
await kelahiran.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus kelahiran");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus kelahiran");
|
||||
} finally {
|
||||
kelahiran.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultKelahiran },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/kesehatan/kelahiran/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
nama: data.nama,
|
||||
tanggal: data.tanggal,
|
||||
jenisKelamin: data.jenisKelamin,
|
||||
alamat: data.alamat,
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading data kelahiran:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateKelahiran.safeParse(kelahiran.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
kelahiran.edit.loading = true;
|
||||
|
||||
const response = await fetch(`/api/kesehatan/kelahiran/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: this.form.nama,
|
||||
tanggal: this.form.tanggal,
|
||||
jenisKelamin: this.form.jenisKelamin,
|
||||
alamat: this.form.alamat,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
toast.success("Berhasil update data kelahiran");
|
||||
await kelahiran.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update data kelahiran");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating data kelahiran:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update data kelahiran"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
kelahiran.edit.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
reset() {
|
||||
kelahiran.edit.id = "";
|
||||
kelahiran.edit.form = { ...defaultKelahiran };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
// data kematian
|
||||
|
||||
const templateKematian = z.object({
|
||||
nama: z.string().min(1, "Nama harus diisi"),
|
||||
tanggal: z.string().min(4, "Tahun harus diisi"),
|
||||
jenisKelamin: z.string().min(1, "Jenis kelamin harus diisi"),
|
||||
alamat: z.string().min(1, "Alamat harus diisi"),
|
||||
penyebab: z.string().min(1, "Penyebab harus diisi"),
|
||||
});
|
||||
|
||||
const defaultKematian = {
|
||||
nama: "",
|
||||
tanggal: "",
|
||||
jenisKelamin: "",
|
||||
alamat: "",
|
||||
penyebab: "",
|
||||
};
|
||||
|
||||
const kematian = proxy({
|
||||
create: {
|
||||
form: { ...defaultKematian }, // ✅ ini kunci fix-nya
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateKematian.safeParse(kematian.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
kematian.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.kematian["create"].post(
|
||||
kematian.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
kematian.findMany.load();
|
||||
return toast.success("Kematian berhasil disimpan!");
|
||||
}
|
||||
|
||||
return toast.error("Gagal menyimpan kematian");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
kematian.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
kematian.create.form = { ...defaultKematian };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.KematianGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
kematian.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
kematian.findMany.page = page;
|
||||
kematian.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.kematian["findMany"].get({
|
||||
query,
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kematian.findMany.data = res.data.data ?? [];
|
||||
kematian.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
kematian.findMany.data = [];
|
||||
kematian.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch kematian paginated:", err);
|
||||
kematian.findMany.data = [];
|
||||
kematian.findMany.totalPages = 1;
|
||||
} finally {
|
||||
kematian.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.KematianGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/kesehatan/kematian/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
kematian.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch kematian:", res.statusText);
|
||||
kematian.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching kematian:", error);
|
||||
kematian.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
kematian.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/kesehatan/kematian/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Kematian berhasil dihapus");
|
||||
await kematian.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus kematian");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus kematian");
|
||||
} finally {
|
||||
kematian.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultKematian },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/kesehatan/kematian/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
nama: data.nama,
|
||||
tanggal: data.tanggal,
|
||||
jenisKelamin: data.jenisKelamin,
|
||||
alamat: data.alamat,
|
||||
penyebab: data.penyebab,
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading data kematian:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateKematian.safeParse(kematian.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
kematian.edit.loading = true;
|
||||
|
||||
const response = await fetch(`/api/kesehatan/kematian/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: this.form.nama,
|
||||
tanggal: this.form.tanggal,
|
||||
jenisKelamin: this.form.jenisKelamin,
|
||||
alamat: this.form.alamat,
|
||||
penyebab: this.form.penyebab,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
toast.success("Berhasil update data kematian");
|
||||
await kematian.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update data kematian");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating data kematian:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update data kematian"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
kematian.edit.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
reset() {
|
||||
kematian.edit.id = "";
|
||||
kematian.edit.form = { ...defaultKematian };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const persentaseKelahiranKematian = proxy({
|
||||
persentasekelahiran,
|
||||
kelahiran,
|
||||
kematian
|
||||
});
|
||||
|
||||
export default persentaseKelahiranKematian;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -20,17 +21,41 @@ const defaultForm = {
|
||||
|
||||
const infoWabahPenyakit = proxy({
|
||||
findMany: {
|
||||
data: [] as Prisma.InfoWabahPenyakitGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[],
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.infowabahpenyakit[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
infoWabahPenyakit.findMany.data = res.data?.data ?? [];
|
||||
data: null as
|
||||
| Prisma.InfoWabahPenyakitGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
infoWabahPenyakit.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
infoWabahPenyakit.findMany.page = page;
|
||||
infoWabahPenyakit.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.infowabahpenyakit["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
infoWabahPenyakit.findMany.data = res.data.data ?? [];
|
||||
infoWabahPenyakit.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
infoWabahPenyakit.findMany.data = [];
|
||||
infoWabahPenyakit.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch info wabah penyakit paginated:", err);
|
||||
infoWabahPenyakit.findMany.data = [];
|
||||
infoWabahPenyakit.findMany.totalPages = 1;
|
||||
} finally {
|
||||
infoWabahPenyakit.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -5,204 +6,241 @@ import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(3, "Judul minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
imageId: z.string().nonempty(),
|
||||
})
|
||||
|
||||
const defaultForm = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
imageId: "",
|
||||
}
|
||||
|
||||
const kontakDarurat = proxy({
|
||||
findMany: {
|
||||
data: [] as Prisma.KontakDaruratGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[],
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.kontakdarurat[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
kontakDarurat.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
create:{
|
||||
form: {...defaultForm},
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(kontakDarurat.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
kontakDarurat.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.kontakdarurat[
|
||||
"create"
|
||||
].post(kontakDarurat.create.form);
|
||||
if (res.status === 200) {
|
||||
kontakDarurat.findMany.load();
|
||||
return toast.success("Kontak Darurat berhasil disimpan!");
|
||||
}
|
||||
|
||||
return toast.error("Gagal menyimpan kontak darurat");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
kontakDarurat.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
kontakDarurat.create.form = {...defaultForm};
|
||||
}
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.KontakDaruratGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/kesehatan/kontakdarurat/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
kontakDarurat.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
kontakDarurat.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
kontakDarurat.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
try {
|
||||
kontakDarurat.delete.loading = true;
|
||||
const response = await fetch(`/api/kesehatan/kontakdarurat/del/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Kontak darurat berhasil dihapus");
|
||||
await kontakDarurat.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus kontak darurat");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus kontak darurat");
|
||||
} finally {
|
||||
kontakDarurat.delete.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/kesehatan/kontakdarurat/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
deskripsi: data.deskripsi,
|
||||
imageId: data.imageId,
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching kontak darurat:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Gagal memuat data");
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(kontakDarurat.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
kontakDarurat.edit.loading = true;
|
||||
const response = await fetch(`/api/kesehatan/kontakdarurat/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
deskripsi: this.form.deskripsi,
|
||||
imageId: this.form.imageId,
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success(result.message || "Kontak darurat berhasil diupdate");
|
||||
await kontakDarurat.findMany.load();
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update kontak darurat");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal update:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Terjadi kesalahan saat mengupdate kontak darurat");
|
||||
return false;
|
||||
} finally {
|
||||
kontakDarurat.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
kontakDarurat.edit.id = "";
|
||||
kontakDarurat.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
name: z.string().min(3, "Judul minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
imageId: z.string().nonempty(),
|
||||
});
|
||||
|
||||
export default kontakDarurat
|
||||
const defaultForm = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
imageId: "",
|
||||
};
|
||||
|
||||
const kontakDarurat = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.KontakDaruratGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
kontakDarurat.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
kontakDarurat.findMany.page = page;
|
||||
kontakDarurat.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.kontakdarurat[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kontakDarurat.findMany.data = res.data.data ?? [];
|
||||
kontakDarurat.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
kontakDarurat.findMany.data = [];
|
||||
kontakDarurat.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch kontak darurat paginated:", err);
|
||||
kontakDarurat.findMany.data = [];
|
||||
kontakDarurat.findMany.totalPages = 1;
|
||||
} finally {
|
||||
kontakDarurat.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(kontakDarurat.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
kontakDarurat.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.kontakdarurat["create"].post(
|
||||
kontakDarurat.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
kontakDarurat.findMany.load();
|
||||
return toast.success("Kontak Darurat berhasil disimpan!");
|
||||
}
|
||||
|
||||
return toast.error("Gagal menyimpan kontak darurat");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
kontakDarurat.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
kontakDarurat.create.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.KontakDaruratGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/kesehatan/kontakdarurat/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
kontakDarurat.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
kontakDarurat.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
kontakDarurat.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
try {
|
||||
kontakDarurat.delete.loading = true;
|
||||
const response = await fetch(`/api/kesehatan/kontakdarurat/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Kontak darurat berhasil dihapus");
|
||||
await kontakDarurat.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus kontak darurat");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus kontak darurat");
|
||||
} finally {
|
||||
kontakDarurat.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/kesehatan/kontakdarurat/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
deskripsi: data.deskripsi,
|
||||
imageId: data.imageId,
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching kontak darurat:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(kontakDarurat.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
kontakDarurat.edit.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/kesehatan/kontakdarurat/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
deskripsi: this.form.deskripsi,
|
||||
imageId: this.form.imageId,
|
||||
}),
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success(result.message || "Kontak darurat berhasil diupdate");
|
||||
await kontakDarurat.findMany.load();
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update kontak darurat");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal update:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat mengupdate kontak darurat"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
kontakDarurat.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
kontakDarurat.edit.id = "";
|
||||
kontakDarurat.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default kontakDarurat;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -17,21 +18,45 @@ const defaultForm = {
|
||||
}
|
||||
|
||||
const penangananDarurat = proxy({
|
||||
findMany: {
|
||||
data: [] as Prisma.PenangananDaruratGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[],
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.penanganandarurat[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
penangananDarurat.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PenangananDaruratGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
penangananDarurat.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
penangananDarurat.findMany.page = page;
|
||||
penangananDarurat.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.penanganandarurat["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
penangananDarurat.findMany.data = res.data.data ?? [];
|
||||
penangananDarurat.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
penangananDarurat.findMany.data = [];
|
||||
penangananDarurat.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch berita paginated:", err);
|
||||
penangananDarurat.findMany.data = [];
|
||||
penangananDarurat.findMany.totalPages = 1;
|
||||
} finally {
|
||||
penangananDarurat.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
create:{
|
||||
form: {...defaultForm},
|
||||
loading: false,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -9,6 +10,7 @@ const templateForm = z.object({
|
||||
nomor: z.string().min(1, { message: "Nomor is required" }),
|
||||
deskripsi: z.string().min(1, { message: "Deskripsi is required" }),
|
||||
imageId: z.string().nonempty(),
|
||||
jadwalPelayanan: z.string().min(1, { message: "Jadwal Pelayanan is required" }),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
@@ -16,6 +18,7 @@ const defaultForm = {
|
||||
nomor: "",
|
||||
deskripsi: "",
|
||||
imageId: "",
|
||||
jadwalPelayanan: "",
|
||||
};
|
||||
|
||||
const posyandustate = proxy({
|
||||
@@ -50,19 +53,43 @@ const posyandustate = proxy({
|
||||
}
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PosyanduGetPayload<{
|
||||
include: {
|
||||
data: null as
|
||||
| Prisma.PosyanduGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
posyandustate.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
posyandustate.findMany.page = page;
|
||||
posyandustate.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.posyandu["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
posyandustate.findMany.data = res.data.data ?? [];
|
||||
posyandustate.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
posyandustate.findMany.data = [];
|
||||
posyandustate.findMany.totalPages = 1;
|
||||
}
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.posyandu["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
posyandustate.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch posyandu paginated:", err);
|
||||
posyandustate.findMany.data = [];
|
||||
posyandustate.findMany.totalPages = 1;
|
||||
} finally {
|
||||
posyandustate.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as
|
||||
@@ -148,6 +175,7 @@ const posyandustate = proxy({
|
||||
nomor: data.nomor,
|
||||
deskripsi: data.deskripsi,
|
||||
imageId: data.imageId || "",
|
||||
jadwalPelayanan: data.jadwalPelayanan || "",
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
@@ -181,6 +209,7 @@ const posyandustate = proxy({
|
||||
nomor: this.form.nomor,
|
||||
deskripsi: this.form.deskripsi,
|
||||
imageId: this.form.imageId,
|
||||
jadwalPelayanan: this.form.jadwalPelayanan,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -20,17 +21,43 @@ const defaultForm = {
|
||||
|
||||
const programKesehatan = proxy({
|
||||
findMany: {
|
||||
data: [] as Prisma.ProgramKesehatanGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[],
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.programkesehatan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
programKesehatan.findMany.data = res.data?.data ?? [];
|
||||
data: null as
|
||||
| Prisma.ProgramKesehatanGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
programKesehatan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
programKesehatan.findMany.page = page;
|
||||
programKesehatan.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.programkesehatan[
|
||||
"find-many"
|
||||
].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
programKesehatan.findMany.data = res.data.data ?? [];
|
||||
programKesehatan.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
programKesehatan.findMany.data = [];
|
||||
programKesehatan.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch berita paginated:", err);
|
||||
programKesehatan.findMany.data = [];
|
||||
programKesehatan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
programKesehatan.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -97,12 +124,15 @@ const programKesehatan = proxy({
|
||||
try {
|
||||
programKesehatan.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/kesehatan/programkesehatan/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const response = await fetch(
|
||||
`/api/kesehatan/programkesehatan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
if (response.ok && result?.success) {
|
||||
@@ -156,57 +186,70 @@ const programKesehatan = proxy({
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching program kesehatan:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Gagal memuat data");
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(programKesehatan.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
const cek = templateForm.safeParse(programKesehatan.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
programKesehatan.edit.loading = true;
|
||||
const response = await fetch(`/api/kesehatan/programkesehatan/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
deskripsiSingkat: this.form.deskripsiSingkat,
|
||||
deskripsi: this.form.deskripsi,
|
||||
imageId: this.form.imageId,
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success(result.message || "Program kesehatan berhasil diupdate");
|
||||
await programKesehatan.findMany.load();
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update program kesehatan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal update:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Terjadi kesalahan saat mengupdate program kesehatan");
|
||||
return false;
|
||||
} finally {
|
||||
programKesehatan.edit.loading = false;
|
||||
try {
|
||||
programKesehatan.edit.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/kesehatan/programkesehatan/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
deskripsiSingkat: this.form.deskripsiSingkat,
|
||||
deskripsi: this.form.deskripsi,
|
||||
imageId: this.form.imageId,
|
||||
}),
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success(
|
||||
result.message || "Program kesehatan berhasil diupdate"
|
||||
);
|
||||
await programKesehatan.findMany.load();
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update program kesehatan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal update:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat mengupdate program kesehatan"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
programKesehatan.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
programKesehatan.edit.id = "";
|
||||
programKesehatan.edit.form = { ...defaultForm };
|
||||
programKesehatan.edit.id = "";
|
||||
programKesehatan.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -163,13 +164,43 @@ const puskesmasState = proxy({
|
||||
},
|
||||
|
||||
findMany: {
|
||||
data: null as Prisma.PuskesmasGetPayload<{
|
||||
include: { image: true; jam: true; kontak: true };
|
||||
}>[] | null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.puskesmas["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
puskesmasState.findMany.data = res.data?.data ?? [];
|
||||
data: null as
|
||||
| Prisma.PuskesmasGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
jam: true;
|
||||
kontak: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
puskesmasState.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||
puskesmasState.findMany.page = page;
|
||||
puskesmasState.findMany.search = search;
|
||||
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.kesehatan.puskesmas["find-many"].get({ query });
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
puskesmasState.findMany.data = res.data.data ?? [];
|
||||
puskesmasState.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
} else {
|
||||
puskesmasState.findMany.data = [];
|
||||
puskesmasState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch berita paginated:", err);
|
||||
puskesmasState.findMany.data = [];
|
||||
puskesmasState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
puskesmasState.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
@@ -50,18 +51,50 @@ const apbdes = proxy({
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<
|
||||
Prisma.APBDesGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
file: true;
|
||||
};
|
||||
}>
|
||||
> | null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.landingpage.apbdes["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
apbdes.findMany.data = res.data?.data ?? [];
|
||||
data: null as
|
||||
| Prisma.APBDesGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
file: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => { // Change to arrow function
|
||||
apbdes.findMany.loading = true; // Use the full path to access the property
|
||||
apbdes.findMany.page = page;
|
||||
apbdes.findMany.search = search;
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.landingpage.apbdes[
|
||||
"findMany"
|
||||
].get({
|
||||
query
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
apbdes.findMany.data = res.data.data || [];
|
||||
apbdes.findMany.total = res.data.total || 0;
|
||||
apbdes.findMany.totalPages = res.data.totalPages || 1;
|
||||
} else {
|
||||
console.error("Failed to load pegawai:", res.data?.message);
|
||||
apbdes.findMany.data = [];
|
||||
apbdes.findMany.total = 0;
|
||||
apbdes.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading pegawai:", error);
|
||||
apbdes.findMany.data = [];
|
||||
apbdes.findMany.total = 0;
|
||||
apbdes.findMany.totalPages = 1;
|
||||
} finally {
|
||||
apbdes.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -60,16 +60,22 @@ const desaAntikorupsi = proxy({
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||
desaAntikorupsi.findMany.loading = true; // Use the full path to access the property
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
// Change to arrow function
|
||||
desaAntikorupsi.findMany.loading = true; // Use the full path to access the property
|
||||
desaAntikorupsi.findMany.page = page;
|
||||
desaAntikorupsi.findMany.search = search;
|
||||
try {
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.landingpage.desaantikorupsi[
|
||||
"findMany"
|
||||
].get({
|
||||
query: { page, limit },
|
||||
query,
|
||||
});
|
||||
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
desaAntikorupsi.findMany.data = res.data.data || [];
|
||||
desaAntikorupsi.findMany.total = res.data.total || 0;
|
||||
@@ -305,20 +311,25 @@ const kategoriDesaAntiKorupsi = proxy({
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||
kategoriDesaAntiKorupsi.findMany.loading = true; // Use the full path to access the property
|
||||
search: "",
|
||||
load: async (page = 1, limit = 10, search = "") => {
|
||||
// Change to arrow function
|
||||
kategoriDesaAntiKorupsi.findMany.loading = true; // Use the full path to access the property
|
||||
kategoriDesaAntiKorupsi.findMany.page = page;
|
||||
kategoriDesaAntiKorupsi.findMany.search = search;
|
||||
try {
|
||||
const res = await ApiFetch.api.landingpage.kategoridak[
|
||||
"findMany"
|
||||
].get({
|
||||
query: { page, limit },
|
||||
const query: any = { page, limit };
|
||||
if (search) query.search = search;
|
||||
|
||||
const res = await ApiFetch.api.landingpage.kategoridak["findMany"].get({
|
||||
query,
|
||||
});
|
||||
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kategoriDesaAntiKorupsi.findMany.data = res.data.data || [];
|
||||
kategoriDesaAntiKorupsi.findMany.total = res.data.total || 0;
|
||||
kategoriDesaAntiKorupsi.findMany.totalPages = res.data.totalPages || 1;
|
||||
kategoriDesaAntiKorupsi.findMany.totalPages =
|
||||
res.data.totalPages || 1;
|
||||
} else {
|
||||
console.error("Failed to load media sosial:", res.data?.message);
|
||||
kategoriDesaAntiKorupsi.findMany.data = [];
|
||||
@@ -363,27 +374,30 @@ const kategoriDesaAntiKorupsi = proxy({
|
||||
try {
|
||||
kategoriDesaAntiKorupsi.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/landingpage/kategoridak/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
const response = await fetch(`/api/landingpage/kategoridak/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Kategori desa anti korupsi berhasil dihapus");
|
||||
toast.success(
|
||||
result.message || "Kategori desa anti korupsi berhasil dihapus"
|
||||
);
|
||||
await kategoriDesaAntiKorupsi.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus kategori desa anti korupsi");
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus kategori desa anti korupsi"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus kategori desa anti korupsi");
|
||||
toast.error(
|
||||
"Terjadi kesalahan saat menghapus kategori desa anti korupsi"
|
||||
);
|
||||
} finally {
|
||||
kategoriDesaAntiKorupsi.delete.loading = false;
|
||||
}
|
||||
|
||||
834
src/app/admin/(dashboard)/_state/landing-page/indeks-kepuasan.ts
Normal file
@@ -0,0 +1,834 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
// Template form responden
|
||||
|
||||
const templateResponden = z.object({
|
||||
name: z.string().min(1, "Nama harus diisi"),
|
||||
tanggal: z.string().min(1, "Tanggal harus diisi"),
|
||||
jenisKelaminId: z.string().min(1, "Jenis kelamin harus diisi"),
|
||||
ratingId: z.string().min(1, "Rating harus diisi"),
|
||||
kelompokUmurId: z.string().min(1, "Kelompok umur harus diisi"),
|
||||
});
|
||||
|
||||
const defaultFormResponden = {
|
||||
name: "",
|
||||
tanggal: "",
|
||||
jenisKelaminId: "",
|
||||
ratingId: "",
|
||||
kelompokUmurId: "",
|
||||
};
|
||||
|
||||
const responden = proxy({
|
||||
create: {
|
||||
form: { ...defaultFormResponden },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateResponden.safeParse(responden.create.form);
|
||||
if (!cek.success) {
|
||||
const err = cek.error.issues.map((i) => i.message).join("\n");
|
||||
toast.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
responden.create.loading = true;
|
||||
const res = await ApiFetch.api.landingpage.responden["create"].post(
|
||||
responden.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
toast.success("Responden berhasil ditambahkan");
|
||||
await responden.findMany.load();
|
||||
} else {
|
||||
toast.error(res.data?.message ?? "Gagal tambah responden");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal create:", error);
|
||||
toast.error("Terjadi kesalahan saat menambahkan responden");
|
||||
} finally {
|
||||
responden.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as any[] | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => {
|
||||
// Change to arrow function
|
||||
responden.findMany.loading = true; // Use the full path to access the property
|
||||
responden.findMany.page = page;
|
||||
try {
|
||||
const res = await ApiFetch.api.landingpage.responden["findMany"].get({
|
||||
query: { page, limit },
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
responden.findMany.data = res.data.data || [];
|
||||
responden.findMany.total = res.data.total || 0;
|
||||
responden.findMany.totalPages = res.data.totalPages || 1;
|
||||
} else {
|
||||
console.error("Failed to load responden:", res.data?.message);
|
||||
responden.findMany.data = [];
|
||||
responden.findMany.total = 0;
|
||||
responden.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading responden:", error);
|
||||
responden.findMany.data = [];
|
||||
responden.findMany.total = 0;
|
||||
responden.findMany.totalPages = 1;
|
||||
} finally {
|
||||
responden.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.RespondenGetPayload<{
|
||||
include: {
|
||||
jenisKelamin: true;
|
||||
rating: true;
|
||||
kelompokUmur: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/landingpage/responden/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
responden.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
responden.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading responden:", error);
|
||||
responden.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultFormResponden },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
responden.update.loading = true;
|
||||
|
||||
const response = await fetch(`/api/landingpage/responden/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
tanggal: data.tanggal,
|
||||
jenisKelaminId: data.jenisKelaminId,
|
||||
ratingId: data.ratingId,
|
||||
kelompokUmurId: data.kelompokUmurId,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading responden:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
} finally {
|
||||
responden.update.loading = false;
|
||||
}
|
||||
},
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
const cek = templateResponden.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return null;
|
||||
}
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await fetch(`/api/landingpage/responden/${id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
tanggal: this.form.tanggal,
|
||||
jenisKelaminId: this.form.jenisKelaminId,
|
||||
ratingId: this.form.ratingId,
|
||||
kelompokUmurId: this.form.kelompokUmurId,
|
||||
}),
|
||||
});
|
||||
const result = await response.json();
|
||||
if (!response.ok || !result?.success) {
|
||||
throw new Error(result?.message || "Gagal update data");
|
||||
}
|
||||
toast.success("Berhasil update data!");
|
||||
await responden.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Error update data:", error);
|
||||
toast.error("Gagal update data responden");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
responden.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/landingpage/responden/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "responden berhasil dihapus");
|
||||
await responden.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus responden");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus responden");
|
||||
} finally {
|
||||
responden.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Template form jenis kelamin responden
|
||||
const templateJenisKelaminResponden = z.object({
|
||||
name: z.string().min(1, "Nama harus diisi"),
|
||||
});
|
||||
|
||||
const defaultFormJenisKelaminResponden = {
|
||||
name: "",
|
||||
};
|
||||
|
||||
const jenisKelaminResponden = proxy({
|
||||
create: {
|
||||
form: { ...defaultFormJenisKelaminResponden },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateJenisKelaminResponden.safeParse(
|
||||
jenisKelaminResponden.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = cek.error.issues.map((i) => i.message).join("\n");
|
||||
toast.error(err);
|
||||
return;
|
||||
}
|
||||
jenisKelaminResponden.create.loading = true;
|
||||
try {
|
||||
jenisKelaminResponden.create.loading = true;
|
||||
const res = await ApiFetch.api.landingpage.jeniskelaminresponden[
|
||||
"create"
|
||||
].post(jenisKelaminResponden.create.form);
|
||||
if (res.status === 200) {
|
||||
toast.success("Jenis kelamin responden berhasil ditambahkan");
|
||||
await jenisKelaminResponden.findMany.load();
|
||||
} else {
|
||||
toast.error(
|
||||
res.data?.message ?? "Gagal tambah jenis kelamin responden"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal create:", error);
|
||||
toast.error(
|
||||
"Terjadi kesalahan saat menambahkan jenis kelamin responden"
|
||||
);
|
||||
} finally {
|
||||
jenisKelaminResponden.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as any[] | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => {
|
||||
// Change to arrow function
|
||||
jenisKelaminResponden.findMany.loading = true; // Use the full path to access the property
|
||||
jenisKelaminResponden.findMany.page = page;
|
||||
try {
|
||||
const res = await ApiFetch.api.landingpage.jeniskelaminresponden[
|
||||
"findMany"
|
||||
].get({
|
||||
query: { page, limit },
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
jenisKelaminResponden.findMany.data = res.data.data || [];
|
||||
jenisKelaminResponden.findMany.total = res.data.total || 0;
|
||||
jenisKelaminResponden.findMany.totalPages = res.data.totalPages || 1;
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to load jenis kelamin responden:",
|
||||
res.data?.message
|
||||
);
|
||||
jenisKelaminResponden.findMany.data = [];
|
||||
jenisKelaminResponden.findMany.total = 0;
|
||||
jenisKelaminResponden.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading jenis kelamin responden:", error);
|
||||
jenisKelaminResponden.findMany.data = [];
|
||||
jenisKelaminResponden.findMany.total = 0;
|
||||
jenisKelaminResponden.findMany.totalPages = 1;
|
||||
} finally {
|
||||
jenisKelaminResponden.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.JenisKelaminRespondenGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/landingpage/jeniskelaminresponden/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
jenisKelaminResponden.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
jenisKelaminResponden.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading jenis kelamin responden:", error);
|
||||
jenisKelaminResponden.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultFormJenisKelaminResponden },
|
||||
loading: false,
|
||||
async byId() {
|
||||
// Method implementation if needed
|
||||
},
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
const cek = templateJenisKelaminResponden.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return null;
|
||||
}
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/landingpage/jeniskelaminresponden/${id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(this.form),
|
||||
}
|
||||
);
|
||||
const result = await response.json();
|
||||
if (!response.ok || !result?.success) {
|
||||
throw new Error(result?.message || "Gagal update data");
|
||||
}
|
||||
toast.success("Berhasil update data!");
|
||||
await jenisKelaminResponden.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Error update data:", error);
|
||||
toast.error("Gagal update data jenis kelamin responden");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
jenisKelaminResponden.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/landingpage/jeniskelaminresponden/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "jenis kelamin responden berhasil dihapus"
|
||||
);
|
||||
await jenisKelaminResponden.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus jenis kelamin responden"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus jenis kelamin responden");
|
||||
} finally {
|
||||
jenisKelaminResponden.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Template form pilihan rating responden
|
||||
|
||||
const templatePilihanRatingResponden = z.object({
|
||||
name: z.string().min(1, "Nama harus diisi"),
|
||||
});
|
||||
|
||||
const defaultFormPilihanRatingResponden = {
|
||||
name: "",
|
||||
};
|
||||
|
||||
const pilihanRatingResponden = proxy({
|
||||
create: {
|
||||
form: { ...defaultFormPilihanRatingResponden },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templatePilihanRatingResponden.safeParse(
|
||||
pilihanRatingResponden.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = cek.error.issues.map((i) => i.message).join("\n");
|
||||
toast.error(err);
|
||||
return;
|
||||
}
|
||||
pilihanRatingResponden.create.loading = true;
|
||||
try {
|
||||
pilihanRatingResponden.create.loading = true;
|
||||
const res = await ApiFetch.api.landingpage.pilihanratingresponden[
|
||||
"create"
|
||||
].post(pilihanRatingResponden.create.form);
|
||||
if (res.status === 200) {
|
||||
toast.success("Jenis kelamin responden berhasil ditambahkan");
|
||||
await pilihanRatingResponden.findMany.load();
|
||||
} else {
|
||||
toast.error(
|
||||
res.data?.message ?? "Gagal tambah jenis kelamin responden"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal create:", error);
|
||||
toast.error(
|
||||
"Terjadi kesalahan saat menambahkan jenis kelamin responden"
|
||||
);
|
||||
} finally {
|
||||
pilihanRatingResponden.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as any[] | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => {
|
||||
// Change to arrow function
|
||||
pilihanRatingResponden.findMany.loading = true; // Use the full path to access the property
|
||||
pilihanRatingResponden.findMany.page = page;
|
||||
try {
|
||||
const res = await ApiFetch.api.landingpage.pilihanratingresponden[
|
||||
"findMany"
|
||||
].get({
|
||||
query: { page, limit },
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pilihanRatingResponden.findMany.data = res.data.data || [];
|
||||
pilihanRatingResponden.findMany.total = res.data.total || 0;
|
||||
pilihanRatingResponden.findMany.totalPages = res.data.totalPages || 1;
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to load pilihan rating responden:",
|
||||
res.data?.message
|
||||
);
|
||||
pilihanRatingResponden.findMany.data = [];
|
||||
pilihanRatingResponden.findMany.total = 0;
|
||||
pilihanRatingResponden.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading pilihan rating responden:", error);
|
||||
pilihanRatingResponden.findMany.data = [];
|
||||
pilihanRatingResponden.findMany.total = 0;
|
||||
pilihanRatingResponden.findMany.totalPages = 1;
|
||||
} finally {
|
||||
pilihanRatingResponden.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PilihanRatingRespondenGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/landingpage/pilihanratingresponden/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
pilihanRatingResponden.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
pilihanRatingResponden.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading pilihan rating responden:", error);
|
||||
pilihanRatingResponden.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultFormPilihanRatingResponden },
|
||||
loading: false,
|
||||
async byId() {
|
||||
// Method implementation if needed
|
||||
},
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
const cek = templatePilihanRatingResponden.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return null;
|
||||
}
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/landingpage/pilihanratingresponden/${id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(this.form),
|
||||
}
|
||||
);
|
||||
const result = await response.json();
|
||||
if (!response.ok || !result?.success) {
|
||||
throw new Error(result?.message || "Gagal update data");
|
||||
}
|
||||
toast.success("Berhasil update data!");
|
||||
await pilihanRatingResponden.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Error update data:", error);
|
||||
toast.error("Gagal update data pilihan rating responden");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
pilihanRatingResponden.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/landingpage/pilihanratingresponden/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "pilihan rating responden berhasil dihapus"
|
||||
);
|
||||
await pilihanRatingResponden.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus pilihan rating responden"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus pilihan rating responden");
|
||||
} finally {
|
||||
pilihanRatingResponden.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Template form kelompok umur responden
|
||||
|
||||
const templateKelompokUmurResponden = z.object({
|
||||
name: z.string().min(1, "Nama harus diisi"),
|
||||
});
|
||||
|
||||
const defaultFormKelompokUmurResponden = {
|
||||
name: "",
|
||||
};
|
||||
|
||||
const kelompokUmurResponden = proxy({
|
||||
create: {
|
||||
form: { ...defaultFormKelompokUmurResponden },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateKelompokUmurResponden.safeParse(
|
||||
kelompokUmurResponden.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = cek.error.issues.map((i) => i.message).join("\n");
|
||||
toast.error(err);
|
||||
return;
|
||||
}
|
||||
kelompokUmurResponden.create.loading = true;
|
||||
try {
|
||||
kelompokUmurResponden.create.loading = true;
|
||||
const res = await ApiFetch.api.landingpage.umurresponden["create"].post(
|
||||
kelompokUmurResponden.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
toast.success("Kelompok umur responden berhasil ditambahkan");
|
||||
await kelompokUmurResponden.findMany.load();
|
||||
} else {
|
||||
toast.error(
|
||||
res.data?.message ?? "Gagal tambah kelompok umur responden"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal create:", error);
|
||||
toast.error(
|
||||
"Terjadi kesalahan saat menambahkan kelompok umur responden"
|
||||
);
|
||||
} finally {
|
||||
kelompokUmurResponden.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as any[] | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => {
|
||||
// Change to arrow function
|
||||
kelompokUmurResponden.findMany.loading = true; // Use the full path to access the property
|
||||
kelompokUmurResponden.findMany.page = page;
|
||||
try {
|
||||
const res = await ApiFetch.api.landingpage.umurresponden[
|
||||
"findMany"
|
||||
].get({
|
||||
query: { page, limit },
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kelompokUmurResponden.findMany.data = res.data.data || [];
|
||||
kelompokUmurResponden.findMany.total = res.data.total || 0;
|
||||
kelompokUmurResponden.findMany.totalPages = res.data.totalPages || 1;
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to load kelompok umur responden:",
|
||||
res.data?.message
|
||||
);
|
||||
kelompokUmurResponden.findMany.data = [];
|
||||
kelompokUmurResponden.findMany.total = 0;
|
||||
kelompokUmurResponden.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading kelompok umur responden:", error);
|
||||
kelompokUmurResponden.findMany.data = [];
|
||||
kelompokUmurResponden.findMany.total = 0;
|
||||
kelompokUmurResponden.findMany.totalPages = 1;
|
||||
} finally {
|
||||
kelompokUmurResponden.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.UmurRespondenGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/landingpage/umurresponden/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
kelompokUmurResponden.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
kelompokUmurResponden.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading kelompok umur responden:", error);
|
||||
kelompokUmurResponden.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultFormKelompokUmurResponden },
|
||||
loading: false,
|
||||
async byId() {
|
||||
// Method implementation if needed
|
||||
},
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
const cek = templateKelompokUmurResponden.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return null;
|
||||
}
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await fetch(`/api/landingpage/umurresponden/${id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(this.form),
|
||||
});
|
||||
const result = await response.json();
|
||||
if (!response.ok || !result?.success) {
|
||||
throw new Error(result?.message || "Gagal update data");
|
||||
}
|
||||
toast.success("Berhasil update data!");
|
||||
await kelompokUmurResponden.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Error update data:", error);
|
||||
toast.error("Gagal update data kelompok umur responden");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
kelompokUmurResponden.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/landingpage/umurresponden/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "kelompok umur responden berhasil dihapus"
|
||||
);
|
||||
await kelompokUmurResponden.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus kelompok umur responden"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus kelompok umur responden");
|
||||
} finally {
|
||||
kelompokUmurResponden.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const indeksKepuasanState = proxy({
|
||||
responden,
|
||||
kelompokUmurResponden,
|
||||
jenisKelaminResponden,
|
||||
pilihanRatingResponden
|
||||
})
|
||||
|
||||
export default indeksKepuasanState
|
||||