Compare commits
100 Commits
nico/10-ju
...
nico/18-ju
| Author | SHA1 | Date | |
|---|---|---|---|
| 9dfcda7687 | |||
| e2f75ff3ad | |||
| f05a096633 | |||
| 9c55869aa6 | |||
| 6e5d45fa20 | |||
| e5373b4823 | |||
| 928cd048c0 | |||
| 41f54772e9 | |||
| cd343badb2 | |||
| 4025771a4d | |||
| 7439eb7687 | |||
| 49a1084099 | |||
| cde6c91cd4 | |||
| 55433128a9 | |||
| e8ad74d118 | |||
| 99c1fd1004 | |||
| 03c0523194 | |||
| ae328f40a0 | |||
| 6e109ffe00 | |||
| c4aea568e9 | |||
| 1c8104ee69 | |||
| 4baffe95f3 | |||
| cb52701f47 | |||
| 2bc9b2f3c6 | |||
| 7b2b306849 | |||
| d328f64d86 | |||
| 119275b95c | |||
| 124dfb8160 | |||
| 46c79b8ded | |||
| d105293149 | |||
| adcbe3aa3d | |||
| bffe648802 | |||
| 7e95d5fbb4 | |||
| 2725c2c064 | |||
| be189df37c | |||
| c0b941395d | |||
| a2e25a3e3a | |||
| d86824a943 | |||
| c823462a47 | |||
| 4f97c01501 | |||
| 0fd47e3e94 | |||
| b92a974dcd | |||
| 10361770b4 | |||
| aec2f5094a | |||
| 72d39b020a | |||
| 51d67736ef | |||
| 406c6f3c9f | |||
| 1c5e4410c4 | |||
| 4724b7473d | |||
| 32a75bcb01 | |||
| c5fc4f4cea | |||
| 9f39eb41ab | |||
| 81ea18cb07 | |||
| dd7ce6943d | |||
| ee10f339e9 | |||
| 02462b2c19 | |||
| 41181d4cb3 | |||
| 6d5b8dcf64 | |||
| 924be5b11b | |||
| 21085ce342 | |||
| 88784f00f6 | |||
| 4f6cc66b7c | |||
| 456342851b | |||
| 4683034cd7 | |||
| 37de71a75a | |||
| 27fa7ac0fc | |||
| fc08b2e790 | |||
| 4a5524ce88 | |||
| 899883ca2a | |||
| 10ecc13ad7 | |||
| 58f538425c | |||
| fa922c7127 | |||
| 45acdba93f | |||
| d2f53ff69b | |||
| 40f0294595 | |||
| cb8d561467 | |||
| 85a0cb6d56 | |||
| 6ed0246cea | |||
| af726043bd | |||
| f4888b53ab | |||
| f7437708c0 | |||
| 7bf5ee69d5 | |||
| e03b071b00 | |||
| 8ded234991 | |||
| 1462e1d256 | |||
| a1c2821153 | |||
| 4f2c565b2e | |||
| c4adc9bb22 | |||
| 9d572f82c3 | |||
| 452692f314 | |||
| 5010677bc8 | |||
| 7af3fbff2d | |||
| 34ca736dda | |||
| 3b61f54509 | |||
| fbe0c19d22 | |||
| f8914ab78f | |||
| 8f3ee2f831 | |||
| ddf0ca62c4 | |||
| f8cdd3abdd | |||
| 64bc739496 |
16
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "desa-darmasaba",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack",
|
||||
@@ -15,15 +15,15 @@
|
||||
"dependencies": {
|
||||
"@cubejs-client/core": "^0.31.0",
|
||||
"@elysiajs/cors": "^1.2.0",
|
||||
"@elysiajs/eden": "^1.2.0",
|
||||
"@elysiajs/eden": "^1.3.2",
|
||||
"@elysiajs/static": "^1.3.0",
|
||||
"@elysiajs/stream": "^1.1.0",
|
||||
"@elysiajs/swagger": "^1.2.0",
|
||||
"@mantine/carousel": "^7.16.2",
|
||||
"@mantine/charts": "^7.17.1",
|
||||
"@mantine/core": "^7.17.4",
|
||||
"@mantine/dates": "^7.17.4",
|
||||
"@mantine/dropzone": "^7.17.0",
|
||||
"@mantine/dates": "^8.1.0",
|
||||
"@mantine/dropzone": "^8.1.1",
|
||||
"@mantine/form": "^8.1.0",
|
||||
"@mantine/hooks": "^7.17.4",
|
||||
"@mantine/tiptap": "^7.17.4",
|
||||
@@ -40,19 +40,22 @@
|
||||
"@tiptap/react": "^2.11.7",
|
||||
"@tiptap/starter-kit": "^2.11.7",
|
||||
"@types/bun": "^1.2.2",
|
||||
"@types/leaflet": "^1.9.20",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"add": "^2.0.6",
|
||||
"animate.css": "^4.1.1",
|
||||
"bun": "^1.2.2",
|
||||
"chart.js": "^4.4.8",
|
||||
"dayjs": "^1.11.13",
|
||||
"elysia": "^1.2.12",
|
||||
"elysia": "^1.3.5",
|
||||
"embla-carousel-autoplay": "^8.5.2",
|
||||
"embla-carousel-react": "^7.1.0",
|
||||
"form-data": "^4.0.2",
|
||||
"framer-motion": "^12.4.1",
|
||||
"framer-motion": "^12.23.5",
|
||||
"get-port": "^7.1.0",
|
||||
"jotai": "^2.12.3",
|
||||
"leaflet": "^1.9.4",
|
||||
"list": "^2.0.19",
|
||||
"lodash": "^4.17.21",
|
||||
"motion": "^12.4.1",
|
||||
"nanoid": "^5.1.5",
|
||||
@@ -63,6 +66,7 @@
|
||||
"prisma": "^6.3.1",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-leaflet": "^5.0.0",
|
||||
"react-simple-toasts": "^6.1.0",
|
||||
"react-toastify": "^11.0.5",
|
||||
"readdirp": "^4.1.1",
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Pelayanan Penduduk Non-Permanent",
|
||||
"deskripsi": "<p>Surat Keterangan Penduduk Non-Permanent adalah dokumen yang dikeluarkan oleh pihak berwenang untuk memberikan keterangan bahwa seseorang atau kelompok orang memiliki status penduduk non-permanent di suatu wilayah. Dokumen ini biasanya digunakan untuk keperluan administratif atau legal, seperti mendapatkan akses ke layanan kesehatan, pendidikan, atau pelayanan publik lainnya.</p>"
|
||||
}
|
||||
]
|
||||
8
prisma/data/desa/layanan/pelayananPerizinanBerusaha.json
Normal file
@@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Pelayanan Perizinan Berusaha Berbasis Risiko Melalui Sistem ONLINE SINGLE SUBMISSION (OSS)",
|
||||
"deskripsi": "<p>Penyelenggaraan Perizinan Berusaha Berbasis Risiko melalui Sistem Online Single Submission (OSS) merupakan pelaksanaan Undang-Undang Nomor 11 Tahun 2020 Tentang Cipta Kerja. OSS Berbasis Risiko wajib digunakan oleh Pelaku Usaha, Kementerian/Lembaga, Pemerintah Daerah, Administrator Kawasan Ekonomi Khusus (KEK), dan Badan Pengusahaan Kawasan Perdagangan Bebas Pelabuhan Bebas (KPBPB).Berdasarkan Peraturan Pemerintah Nomor 5 Tahun 2021 terdapat 1.702 kegiatan usaha yang terdiri atas 1.349 Klasifikasi Baku Lapangan Usaha Indonesia (KBLI) yang sudah diimplementasikan dalam Sistem OSS Berbasis Risiko.</p>",
|
||||
"link" : "https://oss.go.id/"
|
||||
}
|
||||
]
|
||||
7
prisma/data/desa/profile/lambang_desa.json
Normal file
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "edit",
|
||||
"judul": "Lambang Desa",
|
||||
"deskripsi" : "<ul><li>Memperkokoh kerukunan hidup masyarakat dalam jalinan adat, budaya, olahraga, dan agama.</li><li>Meningkatkan kualitas pelayanan publik dengan menerapkan teknologi informasi dan komunikasi terintegrasi.</li><li>Meningkatkan tata kelola pemerintah desa dengan menerapkan prinsip good governance dan good clean government.</li><li>Meningkatkan kualitas pendidikan, kesehatan, Keluarga Berencana serta pengelolaan kependudukan.</li><li>Memperkuat usaha mikro kecil dan menengah (UMKM) dan BUMDesa sebagai pilar ekonomi masyarakat.</li><li>Mewujudkan tatanan kehidupan bermasyarakat yang menjunjung tinggi penegakan hukum dan HAM.</li><li>Meningkatkan perlindungan dan pengelolaan terhadap sumber daya alam dan lingkungan hidup.</li><li>Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa.</li><li>Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata.</li><li>Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa.</li><li>Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata.</li></ul>"
|
||||
}
|
||||
]
|
||||
7
prisma/data/desa/profile/maskot_desa.json
Normal file
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "edit",
|
||||
"judul": "Maskot Desa",
|
||||
"deskripsi" : "<p>Pudak adalah bunga dari tanaman sejenis pandan (Pandanaceae). Bentuk bunga ini tersusun dalam beberapa lapisan, terbungkus oleh kelopak warna putih (semacam daun lonjong) yang ujungnya meruncing.</p><p>Bunga Pudak berwarna kuning dan akan terlihat jika kelopak atau pelepahnya telah mekar. Kekhasan dari bunga pudak, yaitu mempunyai aroma wangi yang semerbak nan lembut (tidak menyengat), dan dapat menebar keharuman sepanjang pagi atau pun sore hari. Tanaman ini dapat tumbuh di sepanjang pantai, aliran sungai, di atas batu-batu karang, dan juga di tanah ladang.</p><p>Dalam Kamus Jawa Kuna- Indonesia kata “Pudak” berarti bunga pandan atau Pandanus Moschatus (Mardiwarsito: 1981: 442). Selain itu bunga pudak juga dapat disebut ketaka atau ketaki (Mardiwarsito, 1981: 276). Sedangkan kata “Sategal” berasal dari kata dasar “Tegal” yang berarti ladang (Mardiwarsito, 1981: 593). Jadi Pudak Sategal dapat diartikan sebagai satu ladang luas yang dipenuhi bunga pudak dan menabar keharuman.</p><p>Pada sebuah kesempatan, Ida Pedanda Putu Pemaron menjelaskan mengenai makna dari istilah Pudak Sategal dengan sebuah analogi bahwa, sekuntum bunga pudak memiliki aroma wangi atau keharuman yang sangat kuat, apalagi jika satu ladang penuh bunga pudak, maka dapat dipastikan aroma keharumannya akan membumbung menyebar ke segala penjuru (Wawancara, 18 Mei 2019 di Geria Putra Mandara Kenderan, Tegallalang). “Pudak” ialah sebuah bunga yang memiliki aroma wangi atau keharuman yang semerbak, lembut, dan khas.</p><p>Garapan Tari Maskot Desa Darmasaba Sekar Pudak diwujudkan ke dalam bentuk tari kreasi yang ditarikan secara berkelompok dengan jumlah lima orang penari perempuan (putri).</p><p>Pemilihan penari perempuan dimaksudkan untuk mempresentasikan keindahan, keluwesan, dan keharuman dari bunga pudak. Sedangkan penetapan jumlah penari lima orang didasarkan atas pertimbangan kebutuhan koreografi agar dapat membentuk desain-desain komposisi lantai yang menarik dan dinamis, baik ketika ditarikan di area panggung yang luas atau pun area panggung yang kecil. Penyajian tari maskot ini dirancang dengan durasi waktu 9 menit.</p>"
|
||||
}
|
||||
]
|
||||
@@ -1,6 +1,6 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"id": "edit",
|
||||
"biodata": "<p>I.B Surya Prabhawa Manuaba, S.H., M.H., adalah Perbekel Darmasaba periode 2021-2027, seorang advokat, pendiri Mantra Legal Consultants & Advocates, serta aktif di bidang musik dan akademis. Dia menempuh pendidikan hukum di Universitas Udayana dan Universitas Mahasaraswati Denpasar serta memiliki pengalaman luas di berbagai organisasi dan kepemimpinan.</p>",
|
||||
"pengalaman": "<ul><li>2021 - 2027: Perbekel Desa Darmasaba</li><li>2015 - Sekarang: Founder & Managing Director Mantra Legal Consultants & Advocates</li><li>2020 - Sekarang: Founder Ugawa Record Music Studio</li><li>2010 - 2016: Dosen Fakultas Hukum Universitas Mahasaraswati Denpasar</li></ul>",
|
||||
"pengalamanOrganisasi": "<ul> <li>1996 – 1997: Ketua OSIS SMP Negeri 1 Abiansemal</li><li>1999 – 2000: Ketua OSIS SMA Negeri 1 Mengwi</li> <li>2008 – 2009: Ketua BEM Universitas Mahasaraswati Denpasar</li> <li>2008 – 2010: Ketua Sekaa Taruna Sila Dharma, Banjar Tengah, Desa Adat Tegal, Darmasaba</li> <li>2020 – Sekarang: Pengurus Young Lawyer Committee Peradi Denpasar</li> <li>2021 – Sekarang: Dewan Kehormatan Himpunan Pengusaha Muda Indonesia (HIPMI) Badung</li> <li>2023 – 2028: Komite Tetap Advokasi – Bidang Hukum dan Regulasi Kamar Dagang dan Industri Badung</li> </ul>",
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"sejarah" : "<p>Asal – usul nama Darmasaba tertuang dalam lontar Usada Bali. Seperti di tulis dalam monografi Desa Darmasaba tahun 1980 silam, nama Darmasaba berkaitan dengan keturunan Danghyang Nirarta diceritakan, Sang kawi-wiku asal Daha (Jawa Timur) itu memiliki cucu bernama Ida Pedanda Sakti Manuaba yang tigggal di Desa Kendran Tegalalang Gianyar. Merasa tidak disenangi sang ayah, Ida Pedanda Sakti Manuaba pergi mengembara bersama dua orang pengiringnya. Pengembaraan sang pendeta sampai di pura Sarin Buana di Jimbaran. Saat mengadakan semedi di tempat ini sang pendeta melihat sinar api. Yang sangat jauh di utara. Timbul keinginan Ida Pedanda Manuaba untuk mengunjungi tempat itu. Sampailah sang Pedanda di pura Batan Bila Peguyangan. Disini Ida Pedanda Manuaba singgah menghadap Ida Pedanda Budha yang tinggal disana. Selanjutnya, kedua pendeta bersama-sama menuju arah utara dan singgah di Taman Cang Ana, sebuah taman milik Arya Lanang Blusung. Di tempat ini kedua pendeta bersama-sama melaksanakan semedi dan menetap untuk sementara waktu.</p>",
|
||||
"visi" : "<p>Mewujudkan Desa Darmasaba yang sejahtera, unggul, religius, berbudaya, dan aman dengan berlandaskan Tri Hita Karana</p>",
|
||||
"misi" : "<ul><li>Memperkokoh kerukunan hidup masyarakat dalam jalinan adat, budaya, olahraga, dan agama.</li><li>Meningkatkan kualitas pelayanan publik dengan menerapkan teknologi informasi dan komunikasi terintegrasi.</li><li>Meningkatkan tata kelola pemerintah desa dengan menerapkan prinsip good governance dan good clean government.</li><li>Meningkatkan kualitas pendidikan, kesehatan, Keluarga Berencana serta pengelolaan kependudukan.</li><li>Memperkuat usaha mikro kecil dan menengah (UMKM) dan BUMDesa sebagai pilar ekonomi masyarakat.</li><li>Mewujudkan tatanan kehidupan bermasyarakat yang menjunjung tinggi penegakan hukum dan HAM.</li><li>Meningkatkan perlindungan dan pengelolaan terhadap sumber daya alam dan lingkungan hidup.</li><li>Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa.</li><li>Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata.</li></ul>",
|
||||
"lambang" : "<ul><li>Memperkokoh kerukunan hidup masyarakat dalam jalinan adat, budaya, olahraga, dan agama.</li><li>Meningkatkan kualitas pelayanan publik dengan menerapkan teknologi informasi dan komunikasi terintegrasi.</li><li>Meningkatkan tata kelola pemerintah desa dengan menerapkan prinsip good governance dan good clean government.</li><li>Meningkatkan kualitas pendidikan, kesehatan, Keluarga Berencana serta pengelolaan kependudukan.</li><li>Memperkuat usaha mikro kecil dan menengah (UMKM) dan BUMDesa sebagai pilar ekonomi masyarakat.</li><li>Mewujudkan tatanan kehidupan bermasyarakat yang menjunjung tinggi penegakan hukum dan HAM.</li><li>Meningkatkan perlindungan dan pengelolaan terhadap sumber daya alam dan lingkungan hidup.</li><li>Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa.</li><li>Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata.</li><li>Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa.</li><li>Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata.</li></ul>",
|
||||
"maskot" : "<p>Pudak adalah bunga dari tanaman sejenis pandan (Pandanaceae). Bentuk bunga ini tersusun dalam beberapa lapisan, terbungkus oleh kelopak warna putih (semacam daun lonjong) yang ujungnya meruncing.</p><p>Bunga Pudak berwarna kuning dan akan terlihat jika kelopak atau pelepahnya telah mekar. Kekhasan dari bunga pudak, yaitu mempunyai aroma wangi yang semerbak nan lembut (tidak menyengat), dan dapat menebar keharuman sepanjang pagi atau pun sore hari. Tanaman ini dapat tumbuh di sepanjang pantai, aliran sungai, di atas batu-batu karang, dan juga di tanah ladang.</p><p>Dalam Kamus Jawa Kuna- Indonesia kata “Pudak” berarti bunga pandan atau Pandanus Moschatus (Mardiwarsito: 1981: 442). Selain itu bunga pudak juga dapat disebut ketaka atau ketaki (Mardiwarsito, 1981: 276). Sedangkan kata “Sategal” berasal dari kata dasar “Tegal” yang berarti ladang (Mardiwarsito, 1981: 593). Jadi Pudak Sategal dapat diartikan sebagai satu ladang luas yang dipenuhi bunga pudak dan menabar keharuman.</p><p>Pada sebuah kesempatan, Ida Pedanda Putu Pemaron menjelaskan mengenai makna dari istilah Pudak Sategal dengan sebuah analogi bahwa, sekuntum bunga pudak memiliki aroma wangi atau keharuman yang sangat kuat, apalagi jika satu ladang penuh bunga pudak, maka dapat dipastikan aroma keharumannya akan membumbung menyebar ke segala penjuru (Wawancara, 18 Mei 2019 di Geria Putra Mandara Kenderan, Tegallalang). “Pudak” ialah sebuah bunga yang memiliki aroma wangi atau keharuman yang semerbak, lembut, dan khas.</p><p>Garapan Tari Maskot Desa Darmasaba Sekar Pudak diwujudkan ke dalam bentuk tari kreasi yang ditarikan secara berkelompok dengan jumlah lima orang penari perempuan (putri).</p><p>Pemilihan penari perempuan dimaksudkan untuk mempresentasikan keindahan, keluwesan, dan keharuman dari bunga pudak. Sedangkan penetapan jumlah penari lima orang didasarkan atas pertimbangan kebutuhan koreografi agar dapat membentuk desain-desain komposisi lantai yang menarik dan dinamis, baik ketika ditarikan di area panggung yang luas atau pun area panggung yang kecil. Penyajian tari maskot ini dirancang dengan durasi waktu 9 menit.</p>",
|
||||
"profilPerbekelId" : "1"
|
||||
}
|
||||
]
|
||||
7
prisma/data/desa/profile/sejarah_desa.json
Normal file
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "edit",
|
||||
"judul": "Sejarah Desa",
|
||||
"deskripsi": "<p>Asal – usul nama Darmasaba tertuang dalam lontar Usada Bali. Seperti di tulis dalam monografi Desa Darmasaba tahun 1980 silam, nama Darmasaba berkaitan dengan keturunan Danghyang Nirarta diceritakan, Sang kawi-wiku asal Daha (Jawa Timur) itu memiliki cucu bernama Ida Pedanda Sakti Manuaba yang tigggal di Desa Kendran Tegalalang Gianyar. Merasa tidak disenangi sang ayah, Ida Pedanda Sakti Manuaba pergi mengembara bersama dua orang pengiringnya. Pengembaraan sang pendeta sampai di pura Sarin Buana di Jimbaran. Saat mengadakan semedi di tempat ini sang pendeta melihat sinar api. Yang sangat jauh di utara. Timbul keinginan Ida Pedanda Manuaba untuk mengunjungi tempat itu. Sampailah sang Pedanda di pura Batan Bila Peguyangan. Disini Ida Pedanda Manuaba singgah menghadap Ida Pedanda Budha yang tinggal disana. Selanjutnya, kedua pendeta bersama-sama menuju arah utara dan singgah di Taman Cang Ana, sebuah taman milik Arya Lanang Blusung. Di tempat ini kedua pendeta bersama-sama melaksanakan semedi dan menetap untuk sementara waktu.</p>"
|
||||
}
|
||||
]
|
||||
7
prisma/data/desa/profile/visi_misi_desa.json
Normal file
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id" : "edit",
|
||||
"visi" : "<p>Mewujudkan Desa Darmasaba yang sejahtera, unggul, religius, berbudaya, dan aman dengan berlandaskan Tri Hita Karana</p>",
|
||||
"misi" : "<ul><li>Memperkokoh kerukunan hidup masyarakat dalam jalinan adat, budaya, olahraga, dan agama.</li><li>Meningkatkan kualitas pelayanan publik dengan menerapkan teknologi informasi dan komunikasi terintegrasi.</li><li>Meningkatkan tata kelola pemerintah desa dengan menerapkan prinsip good governance dan good clean government.</li><li>Meningkatkan kualitas pendidikan, kesehatan, Keluarga Berencana serta pengelolaan kependudukan.</li><li>Memperkuat usaha mikro kecil dan menengah (UMKM) dan BUMDesa sebagai pilar ekonomi masyarakat.</li><li>Mewujudkan tatanan kehidupan bermasyarakat yang menjunjung tinggi penegakan hukum dan HAM.</li><li>Meningkatkan perlindungan dan pengelolaan terhadap sumber daya alam dan lingkungan hidup.</li><li>Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa.</li><li>Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata.</li></ul>"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,51 @@
|
||||
[
|
||||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
|
||||
10
prisma/data/ekonomi/pasar-desa/kategori-produk.json
Normal file
@@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"id": "4b95bge6-012e-5ged-9552-4d8g65d44959",
|
||||
"nama": "Makanan"
|
||||
},
|
||||
{
|
||||
"id": "5c06chf7-123f-6hfe-0663-5e9h76e55060",
|
||||
"nama": "Minuman"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"id": "650e8400-e29b-41d4-a716-446655440001",
|
||||
"atasanId": "550e8400-e29b-41d4-a716-446655440001",
|
||||
"bawahanId": "550e8400-e29b-41d4-a716-446655440002",
|
||||
"tipe": "Langsung Melapor"
|
||||
}
|
||||
]
|
||||
24
prisma/data/ekonomi/struktur-organisasi/pegawai.json
Normal file
@@ -0,0 +1,24 @@
|
||||
[
|
||||
{
|
||||
"id": "550e8400-e29b-41d4-a716-446655440001",
|
||||
"namaLengkap": "Budi Santoso",
|
||||
"gelarAkademik": "S.IP",
|
||||
"tanggalMasuk": "2020-01-01T00:00:00.000Z",
|
||||
"email": "budi@desa.id",
|
||||
"telepon": "081234567891",
|
||||
"alamat": "Jl. Raya Desa No. 1",
|
||||
"posisiId": "kepala_desa",
|
||||
"isActive": true
|
||||
},
|
||||
{
|
||||
"id": "550e8400-e29b-41d4-a716-446655440002",
|
||||
"namaLengkap": "Ani Lestari",
|
||||
"gelarAkademik": "S.Pd",
|
||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
||||
"email": "ani@desa.id",
|
||||
"telepon": "081234567892",
|
||||
"alamat": "Jl. Raya Desa No. 2",
|
||||
"posisiId": "sekretaris_desa",
|
||||
"isActive": true
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{
|
||||
"id": "kepala_desa",
|
||||
"nama": "Kepala Desa",
|
||||
"deskripsi": "Kepala Desa",
|
||||
"hierarki": 1
|
||||
},
|
||||
{
|
||||
"id": "sekretaris_desa",
|
||||
"nama": "Sekretaris Desa",
|
||||
"deskripsi": "Sekretaris Desa",
|
||||
"hierarki": 2
|
||||
},
|
||||
{
|
||||
"id": "bendahara_desa",
|
||||
"nama": "Bendahara Desa",
|
||||
"deskripsi": "Bendahara Desa",
|
||||
"hierarki": 3
|
||||
},
|
||||
{
|
||||
"id": "staff_umum",
|
||||
"nama": "Staff Umum",
|
||||
"deskripsi": "Staff Umum",
|
||||
"hierarki": 4
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "edit",
|
||||
"judul": "Contoh Kegiatan di Desa Darmasaba",
|
||||
"deskripsi": "<ul><li><p>Pelatihan membuat kompos dari sampah rumah tangga</p></li><li><p>Gerakan Jumat Bersih rutin</p></li><li><p>Workshop membuat ecobrick</p></li><li><p>Lomba kebersihan antar banjar</p></li><li><p>Sosialisasi lingkungan di sekolah dan posyandu</p></li></ul>"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "edit",
|
||||
"judul": "Materi Edukasi yang Diberikan",
|
||||
"deskripsi": "<ul><li><p>Pengelolaan Sampah (Pilah sampah organik dan anorganik)</p></li><li><p>Pencegahan pencemaran lingkungan (air, udara, dan tanah)</p></li><li><p>Pemanfaatan lahan hijau dan penghijauan desa</p></li><li><p>Daur ulang dan kreatifitas dari sampah</p></li><li><p>Bahaya pembakaran sampah sembarangan</p></li></ul>"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "edit",
|
||||
"judul": "Tujuan Edukasi Lingkungan",
|
||||
"deskripsi": "<ul><li><p>Meningkatkan kesadaran masyarakat tentang pentingnya lingkungan bersih dan sehat</p></li><li><p>Mendorong partisipasi warga dalam kegiatan pengelolaan sampah, penghijauan, dan konservasi</p></li><li><p>Mengurangi dampak negatif terhadap lingkungan dari kegiatan manusia</p></li><li><p>Membentuk generasi muda yang peduli terhadap isu-isu lingkungan</p></li></ul>"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "edit",
|
||||
"judul": "Bentuk Konservasi Berdasarkan Adat",
|
||||
"deskripsi": "<ul><li><p>Pelestarian Hutan Adat seperti Alas Pala Sangeh atau Wana Kerthi</p></li><li><p>Subak: Sistem pengelolaan irigasi tradisional yang menjunjung kebersamaan dan keberlanjutan</p></li><li><p>Hari Raya Tumpek Uduh: Perayaan khusus untuk menghormati pohon dan tumbuhan</p></li><li><p>Perarem dan Awig-Awig: Aturan adat desa yang mengatur larangan menebang pohon sembarangan, membuang limbah ke sungai, dll.</p></li><li><p>Ritual penyucian alam seperti Melasti, Piodalan Segara, dan lainnya</p></li></ul>"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "edit",
|
||||
"judul": "Filosofi Tri Hita Karuna",
|
||||
"deskripsi": "<ul><li><p>Parahyangan: Hubungan manusia dengan Tuhan</p></li><li><p>Pawongan: Hubungan antar manusia</p></li><li><p>Palemahan: Hubungan manusia dengan alam</p></li></ul>"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "edit",
|
||||
"judul": "Nilai Konservasi Adat",
|
||||
"deskripsi": "<ul><li><p>Menjaga keseimbangan ekosistem</p></li><li><p>Melestarikan spiritualitas lokal dan kesucian alam</p></li><li><p>Menumbuhkan kesadaran kolektif untuk hidup selaras dengan lingkungan</p></li><li><p>Menjaga keberlangsungan sumber daya alam untuk generasi mendatang</p></li></ul>"
|
||||
}
|
||||
]
|
||||
@@ -1,11 +1,10 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"id": "edit",
|
||||
"name": "I.B Surya Prabhawa Manuaba, S.H., M.H.",
|
||||
"biodata": "<p>I.B Surya Prabhawa Manuaba, S.H., M.H., adalah Perbekel Darmasaba periode 2021-2027, seorang advokat, pendiri Mantra Legal Consultants & Advocates, serta aktif di bidang musik dan akademis. Dia menempuh pendidikan hukum di Universitas Udayana dan Universitas Mahasaraswati Denpasar, serta memiliki pengalaman luas di berbagai organisasi dan kepemimpinan.</p>",
|
||||
"riwayat": "<ul> <li>2021 - 2027: Perbekel Desa Darmasaba</li> <li>2015 - Sekarang: Founder & Managing Director Mantra Legal Consultants & Advocates</li> <li>2020 - Sekarang: Founder Ugawa Record Music Studio</li> <li>2010 - 2016: Dosen Fakultas Hukum Universitas Mahasaraswati Denpasar</li> </ul>",
|
||||
"pengalaman": "<ul> <li>1996 – 1997: Ketua OSIS SMP Negeri 1 Abiansemal</li><li>1999 – 2000: Ketua OSIS SMA Negeri 1 Mengwi</li> <li>2008 – 2009: Ketua BEM Universitas Mahasaraswati Denpasar</li> <li>2008 – 2010: Ketua Sekaa Taruna Sila Dharma, Banjar Tengah, Desa Adat Tegal, Darmasaba</li> <li>2020 – Sekarang: Pengurus Young Lawyer Committee Peradi Denpasar</li> <li>2021 – Sekarang: Dewan Kehormatan Himpunan Pengusaha Muda Indonesia (HIPMI) Badung</li> <li>2023 – 2028: Komite Tetap Advokasi – Bidang Hukum dan Regulasi Kamar Dagang dan Industri Badung</li> </ul>",
|
||||
"unggulan": "<h3>Pemberdayaan Ekonomi dan UMKM</h3> <ul> <li>Pelatihan dan pendampingan UMKM lokal</li> <li>Program bantuan modal usaha bagi pelaku usaha kecil</li><li>Digitalisasi UMKM untuk meningkatkan pemasaran produk lokal</li></ul>",
|
||||
"imageUrl": "/uploads/seeded-images/profile-ppid/perbekel.png"
|
||||
"unggulan": "<h3>Pemberdayaan Ekonomi dan UMKM</h3> <ul> <li>Pelatihan dan pendampingan UMKM lokal</li> <li>Program bantuan modal usaha bagi pelaku usaha kecil</li><li>Digitalisasi UMKM untuk meningkatkan pemasaran produk lokal</li></ul>"
|
||||
}
|
||||
]
|
||||
|
||||
6
prisma/data/ppid/struktur-ppid/strukturPPID.json
Normal file
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{
|
||||
"id" : "1",
|
||||
"name" : "Struktur PPID"
|
||||
}
|
||||
]
|
||||
193
prisma/migrations/20250616155255_16_jun/migration.sql
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `nomor` on the `DaftarInformasiPublik` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `image` on the `GalleryFoto` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `video` on the `GalleryVideo` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `videosId` on the `GalleryVideo` table. All the data in the column will be lost.
|
||||
- The primary key for the `IndeksKepuasanMasyarakat` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- You are about to drop the column `profilPerbekelId` on the `ProfileDesa` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `imageUrl` on the `ProfilePPID` table. All the data in the column will be lost.
|
||||
- You are about to drop the `Images` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `Videos` table. If the table is not empty, all the data it contains will be lost.
|
||||
- Added the required column `deskripsi` to the `GalleryFoto` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `deskripsi` to the `GalleryVideo` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `linkVideo` to the `GalleryVideo` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "GalleryFoto" DROP CONSTRAINT "GalleryFoto_imagesId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "GalleryVideo" DROP CONSTRAINT "GalleryVideo_videosId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "ProfileDesa" DROP CONSTRAINT "ProfileDesa_profilPerbekelId_fkey";
|
||||
|
||||
-- DropIndex
|
||||
DROP INDEX "GalleryVideo_videosId_key";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "DaftarInformasiPublik" DROP COLUMN "nomor";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "GalleryFoto" DROP COLUMN "image",
|
||||
ADD COLUMN "deskripsi" TEXT NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "GalleryVideo" DROP COLUMN "video",
|
||||
DROP COLUMN "videosId",
|
||||
ADD COLUMN "deskripsi" TEXT NOT NULL,
|
||||
ADD COLUMN "linkVideo" TEXT NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "IndeksKepuasanMasyarakat" DROP CONSTRAINT "IndeksKepuasanMasyarakat_pkey",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||
ADD CONSTRAINT "IndeksKepuasanMasyarakat_pkey" PRIMARY KEY ("id");
|
||||
DROP SEQUENCE "IndeksKepuasanMasyarakat_id_seq";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "ProfileDesa" DROP COLUMN "profilPerbekelId";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "ProfilePPID" DROP COLUMN "imageUrl",
|
||||
ADD COLUMN "imageId" TEXT;
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "Images";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "Videos";
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "StrukturPPID" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"imageId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "StrukturPPID_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ProfileDesaImage" (
|
||||
"id" TEXT NOT NULL,
|
||||
"label" TEXT NOT NULL,
|
||||
"profileDesaId" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "ProfileDesaImage_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PelayananSuratKeterangan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "PelayananSuratKeterangan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PelayananTelunjukSaktiDesa" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"link" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "PelayananTelunjukSaktiDesa_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PelayananPerizinanBerusaha" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"link" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "PelayananPerizinanBerusaha_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PelayananPendudukNonPermanen" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "PelayananPendudukNonPermanen_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Penghargaan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"juara" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "Penghargaan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Posyandu" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"nomor" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "Posyandu_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "StrukturPPID" ADD CONSTRAINT "StrukturPPID_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ProfilePPID" ADD CONSTRAINT "ProfilePPID_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ProfileDesaImage" ADD CONSTRAINT "ProfileDesaImage_profileDesaId_fkey" FOREIGN KEY ("profileDesaId") REFERENCES "ProfileDesa"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ProfileDesaImage" ADD CONSTRAINT "ProfileDesaImage_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "GalleryFoto" ADD CONSTRAINT "GalleryFoto_imagesId_fkey" FOREIGN KEY ("imagesId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PelayananSuratKeterangan" ADD CONSTRAINT "PelayananSuratKeterangan_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Penghargaan" ADD CONSTRAINT "Penghargaan_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Posyandu" ADD CONSTRAINT "Posyandu_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
78
prisma/migrations/20250617083234_17jun/migration.sql
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `profileDesaId` on the `ProfileDesaImage` table. All the data in the column will be lost.
|
||||
- You are about to drop the `ProfileDesa` table. If the table is not empty, all the data it contains will be lost.
|
||||
- Added the required column `maskotDesaId` to the `ProfileDesaImage` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "ProfileDesaImage" DROP CONSTRAINT "ProfileDesaImage_profileDesaId_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "ProfilPerbekel" ADD COLUMN "imageId" TEXT;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "ProfileDesaImage" DROP COLUMN "profileDesaId",
|
||||
ADD COLUMN "maskotDesaId" TEXT NOT NULL;
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "ProfileDesa";
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "SejarahDesa" (
|
||||
"id" TEXT NOT NULL,
|
||||
"judul" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "SejarahDesa_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "VisiMisiDesa" (
|
||||
"id" TEXT NOT NULL,
|
||||
"visi" TEXT NOT NULL,
|
||||
"misi" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "VisiMisiDesa_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LambangDesa" (
|
||||
"id" TEXT NOT NULL,
|
||||
"judul" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "LambangDesa_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "MaskotDesa" (
|
||||
"id" TEXT NOT NULL,
|
||||
"judul" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "MaskotDesa_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ProfileDesaImage" ADD CONSTRAINT "ProfileDesaImage_maskotDesaId_fkey" FOREIGN KEY ("maskotDesaId") REFERENCES "MaskotDesa"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ProfilPerbekel" ADD CONSTRAINT "ProfilPerbekel_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
139
prisma/migrations/20250624034125_24_jun2025/migration.sql
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- The primary key for the `DataKematian_Kelahiran` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "DataKematian_Kelahiran" DROP CONSTRAINT "DataKematian_Kelahiran_pkey",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||
ADD CONSTRAINT "DataKematian_Kelahiran_pkey" PRIMARY KEY ("id");
|
||||
DROP SEQUENCE "DataKematian_Kelahiran_id_seq";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "ProfilePPID" ADD COLUMN "imageUrl" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Puskesmas" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"alamat" TEXT NOT NULL,
|
||||
"jamId" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"kontakId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "Puskesmas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "JamOperasional" (
|
||||
"id" TEXT NOT NULL,
|
||||
"workDays" TEXT NOT NULL,
|
||||
"weekDays" TEXT NOT NULL,
|
||||
"holiday" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "JamOperasional_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KontakPuskesmas" (
|
||||
"id" TEXT NOT NULL,
|
||||
"kontakPuskesmas" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"facebook" TEXT NOT NULL,
|
||||
"kontakUGD" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "KontakPuskesmas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ProgramKesehatan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"deskripsiSingkat" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "ProgramKesehatan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PenangananDarurat" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "PenangananDarurat_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KontakDarurat" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "KontakDarurat_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "InfoWabahPenyakit" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"deskripsiSingkat" TEXT NOT NULL,
|
||||
"deskripsiLengkap" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "InfoWabahPenyakit_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Puskesmas" ADD CONSTRAINT "Puskesmas_jamId_fkey" FOREIGN KEY ("jamId") REFERENCES "JamOperasional"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Puskesmas" ADD CONSTRAINT "Puskesmas_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Puskesmas" ADD CONSTRAINT "Puskesmas_kontakId_fkey" FOREIGN KEY ("kontakId") REFERENCES "KontakPuskesmas"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ProgramKesehatan" ADD CONSTRAINT "ProgramKesehatan_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PenangananDarurat" ADD CONSTRAINT "PenangananDarurat_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "KontakDarurat" ADD CONSTRAINT "KontakDarurat_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "InfoWabahPenyakit" ADD CONSTRAINT "InfoWabahPenyakit_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
12
prisma/migrations/20250624061829_24jun2025_2/migration.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- The primary key for the `GrafikKepuasan` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "GrafikKepuasan" DROP CONSTRAINT "GrafikKepuasan_pkey",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||
ADD CONSTRAINT "GrafikKepuasan_pkey" PRIMARY KEY ("id");
|
||||
DROP SEQUENCE "GrafikKepuasan_id_seq";
|
||||
96
prisma/migrations/20250625035558_25jun2025_1/migration.sql
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the `_DokterdanTenagaMedisToFasilitasKesehatan` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `_FasilitasKesehatanToFasilitasPendukung` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `_FasilitasKesehatanToInformasiUmum` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `_FasilitasKesehatanToLayananUnggulan` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `_FasilitasKesehatanToProsedurPendaftaran` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `_FasilitasKesehatanToTarifDanLayanan` table. If the table is not empty, all the data it contains will be lost.
|
||||
- Added the required column `dokterdanTenagaMedisId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `fasilitasPendukungId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `informasiUmumId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `layananUnggulanId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `prosedurPendaftaranId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `tarifDanLayananId` to the `FasilitasKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_DokterdanTenagaMedisToFasilitasKesehatan" DROP CONSTRAINT "_DokterdanTenagaMedisToFasilitasKesehatan_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_DokterdanTenagaMedisToFasilitasKesehatan" DROP CONSTRAINT "_DokterdanTenagaMedisToFasilitasKesehatan_B_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_FasilitasKesehatanToFasilitasPendukung" DROP CONSTRAINT "_FasilitasKesehatanToFasilitasPendukung_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_FasilitasKesehatanToFasilitasPendukung" DROP CONSTRAINT "_FasilitasKesehatanToFasilitasPendukung_B_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_FasilitasKesehatanToInformasiUmum" DROP CONSTRAINT "_FasilitasKesehatanToInformasiUmum_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_FasilitasKesehatanToInformasiUmum" DROP CONSTRAINT "_FasilitasKesehatanToInformasiUmum_B_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_FasilitasKesehatanToLayananUnggulan" DROP CONSTRAINT "_FasilitasKesehatanToLayananUnggulan_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_FasilitasKesehatanToLayananUnggulan" DROP CONSTRAINT "_FasilitasKesehatanToLayananUnggulan_B_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_FasilitasKesehatanToProsedurPendaftaran" DROP CONSTRAINT "_FasilitasKesehatanToProsedurPendaftaran_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_FasilitasKesehatanToProsedurPendaftaran" DROP CONSTRAINT "_FasilitasKesehatanToProsedurPendaftaran_B_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_FasilitasKesehatanToTarifDanLayanan" DROP CONSTRAINT "_FasilitasKesehatanToTarifDanLayanan_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_FasilitasKesehatanToTarifDanLayanan" DROP CONSTRAINT "_FasilitasKesehatanToTarifDanLayanan_B_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "FasilitasKesehatan" ADD COLUMN "dokterdanTenagaMedisId" TEXT NOT NULL,
|
||||
ADD COLUMN "fasilitasPendukungId" TEXT NOT NULL,
|
||||
ADD COLUMN "informasiUmumId" TEXT NOT NULL,
|
||||
ADD COLUMN "layananUnggulanId" TEXT NOT NULL,
|
||||
ADD COLUMN "prosedurPendaftaranId" TEXT NOT NULL,
|
||||
ADD COLUMN "tarifDanLayananId" TEXT NOT NULL;
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_DokterdanTenagaMedisToFasilitasKesehatan";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_FasilitasKesehatanToFasilitasPendukung";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_FasilitasKesehatanToInformasiUmum";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_FasilitasKesehatanToLayananUnggulan";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_FasilitasKesehatanToProsedurPendaftaran";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_FasilitasKesehatanToTarifDanLayanan";
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_informasiUmumId_fkey" FOREIGN KEY ("informasiUmumId") REFERENCES "InformasiUmum"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_layananUnggulanId_fkey" FOREIGN KEY ("layananUnggulanId") REFERENCES "LayananUnggulan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_dokterdanTenagaMedisId_fkey" FOREIGN KEY ("dokterdanTenagaMedisId") REFERENCES "DokterdanTenagaMedis"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_fasilitasPendukungId_fkey" FOREIGN KEY ("fasilitasPendukungId") REFERENCES "FasilitasPendukung"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_prosedurPendaftaranId_fkey" FOREIGN KEY ("prosedurPendaftaranId") REFERENCES "ProsedurPendaftaran"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "FasilitasKesehatan" ADD CONSTRAINT "FasilitasKesehatan_tarifDanLayananId_fkey" FOREIGN KEY ("tarifDanLayananId") REFERENCES "TarifDanLayanan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
32
prisma/migrations/20250625085706_25_jun_25_2/migration.sql
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- The primary key for the `DataKematian_Kelahiran` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- The `id` column on the `DataKematian_Kelahiran` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||
- The primary key for the `GrafikKepuasan` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- The `id` column on the `GrafikKepuasan` table would be dropped and recreated. This will lead to data loss if there is data in the column.
|
||||
- A unique constraint covering the columns `[uuid]` on the table `DataKematian_Kelahiran` will be added. If there are existing duplicate values, this will fail.
|
||||
- A unique constraint covering the columns `[uuid]` on the table `GrafikKepuasan` will be added. If there are existing duplicate values, this will fail.
|
||||
- The required column `uuid` was added to the `DataKematian_Kelahiran` table with a prisma-level default value. This is not possible if the table is not empty. Please add this column as optional, then populate it before making it required.
|
||||
- The required column `uuid` was added to the `GrafikKepuasan` table with a prisma-level default value. This is not possible if the table is not empty. Please add this column as optional, then populate it before making it required.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "DataKematian_Kelahiran" DROP CONSTRAINT "DataKematian_Kelahiran_pkey",
|
||||
ADD COLUMN "uuid" TEXT NOT NULL,
|
||||
DROP COLUMN "id",
|
||||
ADD COLUMN "id" SERIAL NOT NULL,
|
||||
ADD CONSTRAINT "DataKematian_Kelahiran_pkey" PRIMARY KEY ("id");
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "GrafikKepuasan" DROP CONSTRAINT "GrafikKepuasan_pkey",
|
||||
ADD COLUMN "uuid" TEXT NOT NULL,
|
||||
DROP COLUMN "id",
|
||||
ADD COLUMN "id" SERIAL NOT NULL,
|
||||
ADD CONSTRAINT "GrafikKepuasan_pkey" PRIMARY KEY ("id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "DataKematian_Kelahiran_uuid_key" ON "DataKematian_Kelahiran"("uuid");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "GrafikKepuasan_uuid_key" ON "GrafikKepuasan"("uuid");
|
||||
92
prisma/migrations/20250626061909_26_jun_25_01/migration.sql
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- The primary key for the `ArtikelKesehatan` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- The primary key for the `DoctorSign` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- The primary key for the `FirstAid` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- The primary key for the `Introduction` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- The primary key for the `MythVsFact` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- The primary key for the `Prevention` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- The primary key for the `Symptom` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- Added the required column `deskripsiJadwalKegiatanId` to the `JadwalKegiatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `dokumenJadwalKegiatanId` to the `JadwalKegiatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `informasiJadwalKegiatanId` to the `JadwalKegiatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `layananJadwalKegiatanId` to the `JadwalKegiatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `pendaftaranJadwalKegiatanId` to the `JadwalKegiatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `syaratKetentuanJadwalKegiatanId` to the `JadwalKegiatan` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "ArtikelKesehatan" DROP CONSTRAINT "ArtikelKesehatan_pkey",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||
ADD CONSTRAINT "ArtikelKesehatan_pkey" PRIMARY KEY ("id");
|
||||
DROP SEQUENCE "ArtikelKesehatan_id_seq";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "DoctorSign" DROP CONSTRAINT "DoctorSign_pkey",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||
ADD CONSTRAINT "DoctorSign_pkey" PRIMARY KEY ("id");
|
||||
DROP SEQUENCE "DoctorSign_id_seq";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "FirstAid" DROP CONSTRAINT "FirstAid_pkey",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||
ADD CONSTRAINT "FirstAid_pkey" PRIMARY KEY ("id");
|
||||
DROP SEQUENCE "FirstAid_id_seq";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Introduction" DROP CONSTRAINT "Introduction_pkey",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||
ADD CONSTRAINT "Introduction_pkey" PRIMARY KEY ("id");
|
||||
DROP SEQUENCE "Introduction_id_seq";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "JadwalKegiatan" ADD COLUMN "deskripsiJadwalKegiatanId" TEXT NOT NULL,
|
||||
ADD COLUMN "dokumenJadwalKegiatanId" TEXT NOT NULL,
|
||||
ADD COLUMN "informasiJadwalKegiatanId" TEXT NOT NULL,
|
||||
ADD COLUMN "layananJadwalKegiatanId" TEXT NOT NULL,
|
||||
ADD COLUMN "pendaftaranJadwalKegiatanId" TEXT NOT NULL,
|
||||
ADD COLUMN "syaratKetentuanJadwalKegiatanId" TEXT NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "MythVsFact" DROP CONSTRAINT "MythVsFact_pkey",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||
ADD CONSTRAINT "MythVsFact_pkey" PRIMARY KEY ("id");
|
||||
DROP SEQUENCE "MythVsFact_id_seq";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Prevention" DROP CONSTRAINT "Prevention_pkey",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||
ADD CONSTRAINT "Prevention_pkey" PRIMARY KEY ("id");
|
||||
DROP SEQUENCE "Prevention_id_seq";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Symptom" DROP CONSTRAINT "Symptom_pkey",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||
ADD CONSTRAINT "Symptom_pkey" PRIMARY KEY ("id");
|
||||
DROP SEQUENCE "Symptom_id_seq";
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "JadwalKegiatan" ADD CONSTRAINT "JadwalKegiatan_informasiJadwalKegiatanId_fkey" FOREIGN KEY ("informasiJadwalKegiatanId") REFERENCES "InformasiJadwalKegiatan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "JadwalKegiatan" ADD CONSTRAINT "JadwalKegiatan_deskripsiJadwalKegiatanId_fkey" FOREIGN KEY ("deskripsiJadwalKegiatanId") REFERENCES "DeskripsiJadwalKegiatan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "JadwalKegiatan" ADD CONSTRAINT "JadwalKegiatan_layananJadwalKegiatanId_fkey" FOREIGN KEY ("layananJadwalKegiatanId") REFERENCES "LayananJadwalKegiatan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "JadwalKegiatan" ADD CONSTRAINT "JadwalKegiatan_syaratKetentuanJadwalKegiatanId_fkey" FOREIGN KEY ("syaratKetentuanJadwalKegiatanId") REFERENCES "SyaratKetentuanJadwalKegiatan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "JadwalKegiatan" ADD CONSTRAINT "JadwalKegiatan_dokumenJadwalKegiatanId_fkey" FOREIGN KEY ("dokumenJadwalKegiatanId") REFERENCES "DokumenJadwalKegiatan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "JadwalKegiatan" ADD CONSTRAINT "JadwalKegiatan_pendaftaranJadwalKegiatanId_fkey" FOREIGN KEY ("pendaftaranJadwalKegiatanId") REFERENCES "PendaftaranJadwalKegiatan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- The primary key for the `DataKematian_Kelahiran` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- You are about to drop the column `uuid` on the `DataKematian_Kelahiran` table. All the data in the column will be lost.
|
||||
- The primary key for the `GrafikKepuasan` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- You are about to drop the column `uuid` on the `GrafikKepuasan` table. All the data in the column will be lost.
|
||||
- A unique constraint covering the columns `[id]` on the table `DataKematian_Kelahiran` will be added. If there are existing duplicate values, this will fail.
|
||||
- A unique constraint covering the columns `[id]` on the table `GrafikKepuasan` will be added. If there are existing duplicate values, this will fail.
|
||||
- Added the required column `doctorSignId` to the `ArtikelKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `firstAidId` to the `ArtikelKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `introductionId` to the `ArtikelKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `mythVsFactId` to the `ArtikelKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `preventionId` to the `ArtikelKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `symptomId` to the `ArtikelKesehatan` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- DropIndex
|
||||
DROP INDEX "DataKematian_Kelahiran_uuid_key";
|
||||
|
||||
-- DropIndex
|
||||
DROP INDEX "GrafikKepuasan_uuid_key";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "ArtikelKesehatan" ADD COLUMN "doctorSignId" TEXT NOT NULL,
|
||||
ADD COLUMN "firstAidId" TEXT NOT NULL,
|
||||
ADD COLUMN "introductionId" TEXT NOT NULL,
|
||||
ADD COLUMN "mythVsFactId" TEXT NOT NULL,
|
||||
ADD COLUMN "preventionId" TEXT NOT NULL,
|
||||
ADD COLUMN "symptomId" TEXT NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "DataKematian_Kelahiran" DROP CONSTRAINT "DataKematian_Kelahiran_pkey",
|
||||
DROP COLUMN "uuid",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT;
|
||||
DROP SEQUENCE "DataKematian_Kelahiran_id_seq";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "GrafikKepuasan" DROP CONSTRAINT "GrafikKepuasan_pkey",
|
||||
DROP COLUMN "uuid",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT;
|
||||
DROP SEQUENCE "GrafikKepuasan_id_seq";
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "DataKematian_Kelahiran_id_key" ON "DataKematian_Kelahiran"("id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "GrafikKepuasan_id_key" ON "GrafikKepuasan"("id");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtikelKesehatan" ADD CONSTRAINT "ArtikelKesehatan_introductionId_fkey" FOREIGN KEY ("introductionId") REFERENCES "Introduction"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtikelKesehatan" ADD CONSTRAINT "ArtikelKesehatan_symptomId_fkey" FOREIGN KEY ("symptomId") REFERENCES "Symptom"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtikelKesehatan" ADD CONSTRAINT "ArtikelKesehatan_preventionId_fkey" FOREIGN KEY ("preventionId") REFERENCES "Prevention"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtikelKesehatan" ADD CONSTRAINT "ArtikelKesehatan_firstAidId_fkey" FOREIGN KEY ("firstAidId") REFERENCES "FirstAid"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtikelKesehatan" ADD CONSTRAINT "ArtikelKesehatan_mythVsFactId_fkey" FOREIGN KEY ("mythVsFactId") REFERENCES "MythVsFact"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ArtikelKesehatan" ADD CONSTRAINT "ArtikelKesehatan_doctorSignId_fkey" FOREIGN KEY ("doctorSignId") REFERENCES "DoctorSign"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
201
prisma/migrations/20250630030216_nico_30_jun_25_1/migration.sql
Normal file
@@ -0,0 +1,201 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "StatusLaporan" AS ENUM ('SELESAI', 'PROSES', 'GAGAL');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "DataKematian_Kelahiran" ADD CONSTRAINT "DataKematian_Kelahiran_pkey" PRIMARY KEY ("id");
|
||||
|
||||
-- DropIndex
|
||||
DROP INDEX "DataKematian_Kelahiran_id_key";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "GrafikKepuasan" ADD CONSTRAINT "GrafikKepuasan_pkey" PRIMARY KEY ("id");
|
||||
|
||||
-- DropIndex
|
||||
DROP INDEX "GrafikKepuasan_id_key";
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KeamananLingkungan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"imageId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "KeamananLingkungan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PolsekTerdekat" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"jarakKeDesa" TEXT NOT NULL,
|
||||
"alamat" TEXT NOT NULL,
|
||||
"nomorTelepon" TEXT NOT NULL,
|
||||
"jamOperasional" TEXT NOT NULL,
|
||||
"embedMapUrl" TEXT NOT NULL,
|
||||
"namaTempatMaps" TEXT NOT NULL,
|
||||
"alamatMaps" TEXT NOT NULL,
|
||||
"linkPetunjukArah" TEXT NOT NULL,
|
||||
"layananPolsekId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "PolsekTerdekat_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LayananPolsek" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "LayananPolsek_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KontakDaruratKeamanan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"kontak" TEXT NOT NULL,
|
||||
"icon" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "KontakDaruratKeamanan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PencegahanKriminalitas" (
|
||||
"id" TEXT NOT NULL,
|
||||
"programKeamananId" TEXT NOT NULL,
|
||||
"tipsKeamananId" TEXT NOT NULL,
|
||||
"videoKeamananId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "PencegahanKriminalitas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ProgramKeamanan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"deskripsi" TEXT,
|
||||
"slug" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "ProgramKeamanan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "TipsKeamanan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"judul" TEXT NOT NULL,
|
||||
"konten" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "TipsKeamanan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "VideoKeamanan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"judul" TEXT NOT NULL,
|
||||
"deskripsi" TEXT,
|
||||
"videoUrl" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "VideoKeamanan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LaporanPublik" (
|
||||
"id" TEXT NOT NULL,
|
||||
"judul" TEXT NOT NULL,
|
||||
"lokasi" TEXT NOT NULL,
|
||||
"tanggalWaktu" TIMESTAMP(3) NOT NULL,
|
||||
"status" "StatusLaporan" NOT NULL,
|
||||
"kronologi" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "LaporanPublik_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PenangananLaporanPublik" (
|
||||
"id" TEXT NOT NULL,
|
||||
"laporanId" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "PenangananLaporanPublik_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Pelapor" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"alamat" TEXT NOT NULL,
|
||||
"nomorTelepon" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "Pelapor_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "MenuTipsKeamanan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"judul" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"imageId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "MenuTipsKeamanan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ProgramKeamanan_slug_key" ON "ProgramKeamanan"("slug");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "KeamananLingkungan" ADD CONSTRAINT "KeamananLingkungan_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PolsekTerdekat" ADD CONSTRAINT "PolsekTerdekat_layananPolsekId_fkey" FOREIGN KEY ("layananPolsekId") REFERENCES "LayananPolsek"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PencegahanKriminalitas" ADD CONSTRAINT "PencegahanKriminalitas_programKeamananId_fkey" FOREIGN KEY ("programKeamananId") REFERENCES "ProgramKeamanan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PencegahanKriminalitas" ADD CONSTRAINT "PencegahanKriminalitas_tipsKeamananId_fkey" FOREIGN KEY ("tipsKeamananId") REFERENCES "TipsKeamanan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PencegahanKriminalitas" ADD CONSTRAINT "PencegahanKriminalitas_videoKeamananId_fkey" FOREIGN KEY ("videoKeamananId") REFERENCES "VideoKeamanan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PenangananLaporanPublik" ADD CONSTRAINT "PenangananLaporanPublik_laporanId_fkey" FOREIGN KEY ("laporanId") REFERENCES "LaporanPublik"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Pelapor" ADD CONSTRAINT "Pelapor_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "MenuTipsKeamanan" ADD CONSTRAINT "MenuTipsKeamanan_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "LayananPolsek" ALTER COLUMN "deletedAt" DROP NOT NULL,
|
||||
ALTER COLUMN "deletedAt" DROP DEFAULT;
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `deletedAt` on the `KontakDarurat` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `deskripsi` on the `KontakDarurat` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `imageId` on the `KontakDarurat` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `isActive` on the `KontakDarurat` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `name` on the `KontakDarurat` table. All the data in the column will be lost.
|
||||
- Added the required column `nama` to the `KontakDarurat` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "KontakDarurat" DROP CONSTRAINT "KontakDarurat_imageId_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "KontakDarurat" DROP COLUMN "deletedAt",
|
||||
DROP COLUMN "deskripsi",
|
||||
DROP COLUMN "imageId",
|
||||
DROP COLUMN "isActive",
|
||||
DROP COLUMN "name",
|
||||
ADD COLUMN "icon" TEXT,
|
||||
ADD COLUMN "nama" TEXT NOT NULL,
|
||||
ADD COLUMN "urutan" INTEGER;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KontakItem" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"nomorTelepon" TEXT NOT NULL,
|
||||
"icon" TEXT,
|
||||
"kategoriId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "KontakItem_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PasarDesa" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"harga" INTEGER NOT NULL,
|
||||
"satuan" TEXT NOT NULL,
|
||||
"alamat" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"rating" DOUBLE PRECISION NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"kategoriId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "PasarDesa_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KategoriMakanan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "KategoriMakanan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "KontakItem" ADD CONSTRAINT "KontakItem_kategoriId_fkey" FOREIGN KEY ("kategoriId") REFERENCES "KontakDarurat"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PasarDesa" ADD CONSTRAINT "PasarDesa_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PasarDesa" ADD CONSTRAINT "PasarDesa_kategoriId_fkey" FOREIGN KEY ("kategoriId") REFERENCES "KategoriMakanan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `icon` on the `KontakDarurat` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `nama` on the `KontakDarurat` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `urutan` on the `KontakDarurat` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `deletedAt` on the `KontakDaruratKeamanan` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `isActive` on the `KontakDaruratKeamanan` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `kontak` on the `KontakDaruratKeamanan` table. All the data in the column will be lost.
|
||||
- Added the required column `deskripsi` to the `KontakDarurat` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `imageId` to the `KontakDarurat` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `name` to the `KontakDarurat` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "KontakItem" DROP CONSTRAINT "KontakItem_kategoriId_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "KontakDarurat" DROP COLUMN "icon",
|
||||
DROP COLUMN "nama",
|
||||
DROP COLUMN "urutan",
|
||||
ADD COLUMN "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "deskripsi" TEXT NOT NULL,
|
||||
ADD COLUMN "imageId" TEXT NOT NULL,
|
||||
ADD COLUMN "isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
ADD COLUMN "name" TEXT NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "KontakDaruratKeamanan" DROP COLUMN "deletedAt",
|
||||
DROP COLUMN "isActive",
|
||||
DROP COLUMN "kontak",
|
||||
ADD COLUMN "urutan" INTEGER;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "KontakDarurat" ADD CONSTRAINT "KontakDarurat_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "KontakItem" ADD CONSTRAINT "KontakItem_kategoriId_fkey" FOREIGN KEY ("kategoriId") REFERENCES "KontakDaruratKeamanan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
85
prisma/migrations/20250703070556_3_jul_2025_1/migration.sql
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- The values [SELESAI,PROSES,GAGAL] on the enum `StatusLaporan` will be removed. If these variants are still used in the database, this will fail.
|
||||
- You are about to drop the column `icon` on the `KontakDaruratKeamanan` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `urutan` on the `KontakDaruratKeamanan` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `icon` on the `KontakItem` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterEnum
|
||||
BEGIN;
|
||||
CREATE TYPE "StatusLaporan_new" AS ENUM ('Selesai', 'Proses', 'Gagal');
|
||||
ALTER TABLE "LaporanPublik" ALTER COLUMN "status" TYPE "StatusLaporan_new" USING ("status"::text::"StatusLaporan_new");
|
||||
ALTER TYPE "StatusLaporan" RENAME TO "StatusLaporan_old";
|
||||
ALTER TYPE "StatusLaporan_new" RENAME TO "StatusLaporan";
|
||||
DROP TYPE "StatusLaporan_old";
|
||||
COMMIT;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "KontakDaruratKeamanan" DROP COLUMN "icon",
|
||||
DROP COLUMN "urutan",
|
||||
ADD COLUMN "imageId" TEXT;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "KontakItem" DROP COLUMN "icon",
|
||||
ADD COLUMN "imageId" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LowonganPekerjaan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"posisi" TEXT NOT NULL,
|
||||
"namaPerusahaan" TEXT NOT NULL,
|
||||
"lokasi" TEXT NOT NULL,
|
||||
"tipePekerjaan" TEXT NOT NULL,
|
||||
"gaji" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"kualifikasi" TEXT NOT NULL,
|
||||
"tanggalPosting" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "LowonganPekerjaan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ProgramKemiskinan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"ikonUrl" TEXT,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"statistikId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "ProgramKemiskinan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "StatistikKemiskinan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tahun" INTEGER NOT NULL,
|
||||
"jumlah" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "StatistikKemiskinan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ProgramKemiskinan_statistikId_key" ON "ProgramKemiskinan"("statistikId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "StatistikKemiskinan_tahun_key" ON "StatistikKemiskinan"("tahun");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "KontakDaruratKeamanan" ADD CONSTRAINT "KontakDaruratKeamanan_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "KontakItem" ADD CONSTRAINT "KontakItem_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ProgramKemiskinan" ADD CONSTRAINT "ProgramKemiskinan_statistikId_fkey" FOREIGN KEY ("statistikId") REFERENCES "StatistikKemiskinan"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `alamat` on the `PasarDesa` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `deletedAt` on the `PasarDesa` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `isActive` on the `PasarDesa` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `kategoriId` on the `PasarDesa` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `satuan` on the `PasarDesa` table. All the data in the column will be lost.
|
||||
- You are about to drop the `KategoriMakanan` table. If the table is not empty, all the data it contains will be lost.
|
||||
- Added the required column `alamatUsaha` to the `PasarDesa` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "PasarDesa" DROP CONSTRAINT "PasarDesa_imageId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "PasarDesa" DROP CONSTRAINT "PasarDesa_kategoriId_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "PasarDesa" DROP COLUMN "alamat",
|
||||
DROP COLUMN "deletedAt",
|
||||
DROP COLUMN "isActive",
|
||||
DROP COLUMN "kategoriId",
|
||||
DROP COLUMN "satuan",
|
||||
ADD COLUMN "alamatUsaha" TEXT NOT NULL,
|
||||
ALTER COLUMN "imageId" DROP NOT NULL;
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "KategoriMakanan";
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KategoriProduk" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "KategoriProduk_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_ProdukToKategori" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_ProdukToKategori_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_ProdukToKategori_B_index" ON "_ProdukToKategori"("B");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PasarDesa" ADD CONSTRAINT "PasarDesa_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ProdukToKategori" ADD CONSTRAINT "_ProdukToKategori_A_fkey" FOREIGN KEY ("A") REFERENCES "KategoriProduk"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ProdukToKategori" ADD CONSTRAINT "_ProdukToKategori_B_fkey" FOREIGN KEY ("B") REFERENCES "PasarDesa"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the `_ProdukToKategori` table. If the table is not empty, all the data it contains will be lost.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_ProdukToKategori" DROP CONSTRAINT "_ProdukToKategori_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_ProdukToKategori" DROP CONSTRAINT "_ProdukToKategori_B_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "KategoriProduk" ADD COLUMN "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "isActive" BOOLEAN NOT NULL DEFAULT true;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "PasarDesa" ADD COLUMN "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "isActive" BOOLEAN NOT NULL DEFAULT true;
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_ProdukToKategori";
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KategoriToPasar" (
|
||||
"id" TEXT NOT NULL,
|
||||
"kategoriId" TEXT NOT NULL,
|
||||
"pasarDesaId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "KategoriToPasar_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "KategoriToPasar" ADD CONSTRAINT "KategoriToPasar_kategoriId_fkey" FOREIGN KEY ("kategoriId") REFERENCES "KategoriProduk"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "KategoriToPasar" ADD CONSTRAINT "KategoriToPasar_pasarDesaId_fkey" FOREIGN KEY ("pasarDesaId") REFERENCES "PasarDesa"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
11
prisma/migrations/20250704091225_4_jul_2025/migration.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- Added the required column `kategoriProdukId` to the `PasarDesa` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "PasarDesa" ADD COLUMN "kategoriProdukId" TEXT NOT NULL;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PasarDesa" ADD CONSTRAINT "PasarDesa_kategoriProdukId_fkey" FOREIGN KEY ("kategoriProdukId") REFERENCES "KategoriProduk"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,78 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "posisi_organisasi" (
|
||||
"id" VARCHAR(50) NOT NULL,
|
||||
"nama" VARCHAR(100) NOT NULL,
|
||||
"deskripsi" TEXT,
|
||||
"hierarki" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "posisi_organisasi_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "pegawai" (
|
||||
"id" UUID NOT NULL,
|
||||
"namaLengkap" VARCHAR(255) NOT NULL,
|
||||
"gelarAkademik" VARCHAR(100),
|
||||
"imageId" TEXT,
|
||||
"tanggalMasuk" DATE,
|
||||
"email" VARCHAR(255),
|
||||
"telepon" VARCHAR(20),
|
||||
"alamat" TEXT,
|
||||
"posisiId" VARCHAR(50) NOT NULL,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "pegawai_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "hubungan_organisasi" (
|
||||
"id" UUID NOT NULL,
|
||||
"atasanId" UUID NOT NULL,
|
||||
"bawahanId" UUID NOT NULL,
|
||||
"tipe" VARCHAR(50),
|
||||
|
||||
CONSTRAINT "hubungan_organisasi_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "struktur_organisasi" (
|
||||
"id" TEXT NOT NULL,
|
||||
"posisiOrganisasiId" VARCHAR(50) NOT NULL,
|
||||
"pegawaiId" UUID NOT NULL,
|
||||
"hubunganOrganisasiId" UUID NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "struktur_organisasi_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "pegawai_email_key" ON "pegawai"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "hubungan_organisasi_atasanId_bawahanId_key" ON "hubungan_organisasi"("atasanId", "bawahanId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "pegawai" ADD CONSTRAINT "pegawai_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "pegawai" ADD CONSTRAINT "pegawai_posisiId_fkey" FOREIGN KEY ("posisiId") REFERENCES "posisi_organisasi"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "hubungan_organisasi" ADD CONSTRAINT "hubungan_organisasi_atasanId_fkey" FOREIGN KEY ("atasanId") REFERENCES "pegawai"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "hubungan_organisasi" ADD CONSTRAINT "hubungan_organisasi_bawahanId_fkey" FOREIGN KEY ("bawahanId") REFERENCES "pegawai"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "struktur_organisasi" ADD CONSTRAINT "struktur_organisasi_posisiOrganisasiId_fkey" FOREIGN KEY ("posisiOrganisasiId") REFERENCES "posisi_organisasi"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "struktur_organisasi" ADD CONSTRAINT "struktur_organisasi_pegawaiId_fkey" FOREIGN KEY ("pegawaiId") REFERENCES "pegawai"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "struktur_organisasi" ADD CONSTRAINT "struktur_organisasi_hubunganOrganisasiId_fkey" FOREIGN KEY ("hubunganOrganisasiId") REFERENCES "hubungan_organisasi"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,77 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "GrafikMenganggurBerdasarkanUsia" (
|
||||
"id" TEXT NOT NULL,
|
||||
"usia18_25" TEXT NOT NULL,
|
||||
"usia26_35" TEXT NOT NULL,
|
||||
"usia36_45" TEXT NOT NULL,
|
||||
"usia46_keatas" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "GrafikMenganggurBerdasarkanUsia_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "GrafikMenganggurBerdasarkanPendidikan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"SD" TEXT NOT NULL,
|
||||
"SMP" TEXT NOT NULL,
|
||||
"SMA" TEXT NOT NULL,
|
||||
"D3" TEXT NOT NULL,
|
||||
"S1" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "GrafikMenganggurBerdasarkanPendidikan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "GrafikJumlahPendudukMiskin" (
|
||||
"id" UUID NOT NULL,
|
||||
"year" INTEGER NOT NULL,
|
||||
"totalPoorPopulation" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "GrafikJumlahPendudukMiskin_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "SektorUnggulanDesa" (
|
||||
"id" UUID NOT NULL,
|
||||
"name" VARCHAR(100) NOT NULL,
|
||||
"description" TEXT,
|
||||
"value" DOUBLE PRECISION,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "SektorUnggulanDesa_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "DataDemografiPekerjaan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"pekerjaan" TEXT NOT NULL,
|
||||
"lakiLaki" INTEGER NOT NULL,
|
||||
"perempuan" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "DataDemografiPekerjaan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "GrafikJumlahPendudukMiskin_year_key" ON "GrafikJumlahPendudukMiskin"("year");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "SektorUnggulanDesa_name_key" ON "SektorUnggulanDesa"("name");
|
||||
@@ -0,0 +1,19 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "DetailDataPengangguran" (
|
||||
"id" UUID NOT NULL,
|
||||
"month" VARCHAR(20) NOT NULL,
|
||||
"year" INTEGER NOT NULL,
|
||||
"totalUnemployment" INTEGER NOT NULL,
|
||||
"educatedUnemployment" INTEGER NOT NULL,
|
||||
"uneducatedUnemployment" INTEGER NOT NULL,
|
||||
"percentageChange" DOUBLE PRECISION,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "DetailDataPengangguran_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "DetailDataPengangguran_month_year_key" ON "DetailDataPengangguran"("month", "year");
|
||||
133
prisma/migrations/20250710032516_nico_10_jul_25_1/migration.sql
Normal file
@@ -0,0 +1,133 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "ApbDesa" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tahun" INTEGER NOT NULL,
|
||||
"pendapatanId" TEXT NOT NULL,
|
||||
"belanjaId" TEXT NOT NULL,
|
||||
"pembiayaanId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "ApbDesa_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Pendapatan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"value" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "Pendapatan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Belanja" (
|
||||
"id" TEXT NOT NULL,
|
||||
"penyelenggaraan" INTEGER NOT NULL,
|
||||
"pelaksanaanPembangunan" INTEGER NOT NULL,
|
||||
"pembinaanMasyarakat" INTEGER NOT NULL,
|
||||
"pemberdayaanMasyarakat" INTEGER NOT NULL,
|
||||
"penanggulanganBencana" INTEGER NOT NULL,
|
||||
"total" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "Belanja_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Pembiayaan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"silpa" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "Pembiayaan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KlasifikasiBelanja" (
|
||||
"id" TEXT NOT NULL,
|
||||
"jenis" TEXT NOT NULL,
|
||||
"persen" DOUBLE PRECISION NOT NULL,
|
||||
"total" INTEGER NOT NULL,
|
||||
"apbDesaId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "KlasifikasiBelanja_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "RincianBelanja" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"jumlah" INTEGER NOT NULL,
|
||||
"klasifikasiBelanjaId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "RincianBelanja_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KegiatanSubak" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"jumlah" INTEGER NOT NULL,
|
||||
"apbDesaId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "KegiatanSubak_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_ApbDesaToKegiatanSubak" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_ApbDesaToKegiatanSubak_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_BelanjaToKlasifikasiBelanja" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_BelanjaToKlasifikasiBelanja_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_KlasifikasiBelanjaToRincianBelanja" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_KlasifikasiBelanjaToRincianBelanja_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_ApbDesaToKegiatanSubak_B_index" ON "_ApbDesaToKegiatanSubak"("B");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_BelanjaToKlasifikasiBelanja_B_index" ON "_BelanjaToKlasifikasiBelanja"("B");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_KlasifikasiBelanjaToRincianBelanja_B_index" ON "_KlasifikasiBelanjaToRincianBelanja"("B");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ApbDesa" ADD CONSTRAINT "ApbDesa_pendapatanId_fkey" FOREIGN KEY ("pendapatanId") REFERENCES "Pendapatan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ApbDesa" ADD CONSTRAINT "ApbDesa_belanjaId_fkey" FOREIGN KEY ("belanjaId") REFERENCES "Belanja"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ApbDesa" ADD CONSTRAINT "ApbDesa_pembiayaanId_fkey" FOREIGN KEY ("pembiayaanId") REFERENCES "Pembiayaan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ApbDesaToKegiatanSubak" ADD CONSTRAINT "_ApbDesaToKegiatanSubak_A_fkey" FOREIGN KEY ("A") REFERENCES "ApbDesa"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ApbDesaToKegiatanSubak" ADD CONSTRAINT "_ApbDesaToKegiatanSubak_B_fkey" FOREIGN KEY ("B") REFERENCES "KegiatanSubak"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_BelanjaToKlasifikasiBelanja" ADD CONSTRAINT "_BelanjaToKlasifikasiBelanja_A_fkey" FOREIGN KEY ("A") REFERENCES "Belanja"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_BelanjaToKlasifikasiBelanja" ADD CONSTRAINT "_BelanjaToKlasifikasiBelanja_B_fkey" FOREIGN KEY ("B") REFERENCES "KlasifikasiBelanja"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_KlasifikasiBelanjaToRincianBelanja" ADD CONSTRAINT "_KlasifikasiBelanjaToRincianBelanja_A_fkey" FOREIGN KEY ("A") REFERENCES "KlasifikasiBelanja"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_KlasifikasiBelanjaToRincianBelanja" ADD CONSTRAINT "_KlasifikasiBelanjaToRincianBelanja_B_fkey" FOREIGN KEY ("B") REFERENCES "RincianBelanja"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `pelaksanaanPembangunan` on the `Belanja` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `pemberdayaanMasyarakat` on the `Belanja` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `pembinaanMasyarakat` on the `Belanja` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `penanggulanganBencana` on the `Belanja` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `penyelenggaraan` on the `Belanja` table. All the data in the column will be lost.
|
||||
- Added the required column `name` to the `Belanja` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `updatedAt` to the `Belanja` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `value` to the `Belanja` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `total` to the `Pendapatan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `updatedAt` to the `Pendapatan` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Belanja" DROP COLUMN "pelaksanaanPembangunan",
|
||||
DROP COLUMN "pemberdayaanMasyarakat",
|
||||
DROP COLUMN "pembinaanMasyarakat",
|
||||
DROP COLUMN "penanggulanganBencana",
|
||||
DROP COLUMN "penyelenggaraan",
|
||||
ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
ADD COLUMN "name" TEXT NOT NULL,
|
||||
ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
ADD COLUMN "value" INTEGER NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Pendapatan" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
ADD COLUMN "total" INTEGER NOT NULL,
|
||||
ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL;
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `total` on the `Belanja` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `total` on the `Pendapatan` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Belanja" DROP COLUMN "total";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Pendapatan" DROP COLUMN "total";
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `silpa` on the `Pembiayaan` table. All the data in the column will be lost.
|
||||
- Added the required column `name` to the `Pembiayaan` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `value` to the `Pembiayaan` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Pembiayaan" DROP COLUMN "silpa",
|
||||
ADD COLUMN "name" TEXT NOT NULL,
|
||||
ADD COLUMN "value" INTEGER NOT NULL;
|
||||
245
prisma/migrations/20250715072239_nico_15_jul_25_1/migration.sql
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `belanjaId` on the `ApbDesa` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `pembiayaanId` on the `ApbDesa` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `pendapatanId` on the `ApbDesa` table. All the data in the column will be lost.
|
||||
- You are about to drop the `KegiatanSubak` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `KlasifikasiBelanja` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `RincianBelanja` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `_ApbDesaToKegiatanSubak` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `_BelanjaToKlasifikasiBelanja` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `_KlasifikasiBelanjaToRincianBelanja` table. If the table is not empty, all the data it contains will be lost.
|
||||
- Changed the type of `tanggal` on the `DaftarInformasiPublik` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required.
|
||||
- Added the required column `updatedAt` to the `Pembiayaan` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "ApbDesa" DROP CONSTRAINT "ApbDesa_belanjaId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "ApbDesa" DROP CONSTRAINT "ApbDesa_pembiayaanId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "ApbDesa" DROP CONSTRAINT "ApbDesa_pendapatanId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_ApbDesaToKegiatanSubak" DROP CONSTRAINT "_ApbDesaToKegiatanSubak_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_ApbDesaToKegiatanSubak" DROP CONSTRAINT "_ApbDesaToKegiatanSubak_B_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_BelanjaToKlasifikasiBelanja" DROP CONSTRAINT "_BelanjaToKlasifikasiBelanja_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_BelanjaToKlasifikasiBelanja" DROP CONSTRAINT "_BelanjaToKlasifikasiBelanja_B_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_KlasifikasiBelanjaToRincianBelanja" DROP CONSTRAINT "_KlasifikasiBelanjaToRincianBelanja_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_KlasifikasiBelanjaToRincianBelanja" DROP CONSTRAINT "_KlasifikasiBelanjaToRincianBelanja_B_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "ApbDesa" DROP COLUMN "belanjaId",
|
||||
DROP COLUMN "pembiayaanId",
|
||||
DROP COLUMN "pendapatanId",
|
||||
ADD COLUMN "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "isActive" BOOLEAN NOT NULL DEFAULT true;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "DaftarInformasiPublik" DROP COLUMN "tanggal",
|
||||
ADD COLUMN "tanggal" DATE NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Pembiayaan" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL;
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "KegiatanSubak";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "KlasifikasiBelanja";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "RincianBelanja";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_ApbDesaToKegiatanSubak";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_BelanjaToKlasifikasiBelanja";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_KlasifikasiBelanjaToRincianBelanja";
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "DesaDigital" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "DesaDigital_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ProgramKreatif" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"icon" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "ProgramKreatif_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KolaborasiInovasi" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"tahun" INTEGER NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"kolaborator" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "KolaborasiInovasi_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "InfoTekno" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "InfoTekno_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "AjukanIdeInovatif" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"alamat" TEXT NOT NULL,
|
||||
"namaIde" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"masalah" TEXT NOT NULL,
|
||||
"benefit" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "AjukanIdeInovatif_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "AdministrasiOnline" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"alamat" TEXT NOT NULL,
|
||||
"nomorTelepon" TEXT NOT NULL,
|
||||
"jenisLayananId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "AdministrasiOnline_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "JenisLayanan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"deskripsi" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "JenisLayanan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_ApbDesaPembiayaan" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_ApbDesaPembiayaan_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_ApbDesaBelanja" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_ApbDesaBelanja_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_ApbDesaPendapatan" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_ApbDesaPendapatan_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_ApbDesaPembiayaan_B_index" ON "_ApbDesaPembiayaan"("B");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_ApbDesaBelanja_B_index" ON "_ApbDesaBelanja"("B");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_ApbDesaPendapatan_B_index" ON "_ApbDesaPendapatan"("B");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "DesaDigital" ADD CONSTRAINT "DesaDigital_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "KolaborasiInovasi" ADD CONSTRAINT "KolaborasiInovasi_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "InfoTekno" ADD CONSTRAINT "InfoTekno_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "AdministrasiOnline" ADD CONSTRAINT "AdministrasiOnline_jenisLayananId_fkey" FOREIGN KEY ("jenisLayananId") REFERENCES "JenisLayanan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ApbDesaPembiayaan" ADD CONSTRAINT "_ApbDesaPembiayaan_A_fkey" FOREIGN KEY ("A") REFERENCES "ApbDesa"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ApbDesaPembiayaan" ADD CONSTRAINT "_ApbDesaPembiayaan_B_fkey" FOREIGN KEY ("B") REFERENCES "Pembiayaan"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ApbDesaBelanja" ADD CONSTRAINT "_ApbDesaBelanja_A_fkey" FOREIGN KEY ("A") REFERENCES "ApbDesa"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ApbDesaBelanja" ADD CONSTRAINT "_ApbDesaBelanja_B_fkey" FOREIGN KEY ("B") REFERENCES "Belanja"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ApbDesaPendapatan" ADD CONSTRAINT "_ApbDesaPendapatan_A_fkey" FOREIGN KEY ("A") REFERENCES "ApbDesa"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ApbDesaPendapatan" ADD CONSTRAINT "_ApbDesaPendapatan_B_fkey" FOREIGN KEY ("B") REFERENCES "Pendapatan"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,67 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "PengaduanMasyarakat" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"nomorTelepon" TEXT NOT NULL,
|
||||
"nik" TEXT NOT NULL,
|
||||
"judulPengaduan" TEXT NOT NULL,
|
||||
"lokasiKejadian" TEXT NOT NULL,
|
||||
"imageId" TEXT NOT NULL,
|
||||
"deskripsiPengaduan" TEXT NOT NULL,
|
||||
"jenisPengaduanId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "PengaduanMasyarakat_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "JenisPengaduan" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "JenisPengaduan_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PengelolaanSampah" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"icon" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "PengelolaanSampah_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KeteranganBankSampahTerdekat" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"alamat" TEXT NOT NULL,
|
||||
"namaTempatMaps" TEXT NOT NULL,
|
||||
"linkPetunjukArah" TEXT NOT NULL,
|
||||
"lat" DOUBLE PRECISION NOT NULL,
|
||||
"lng" DOUBLE PRECISION NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "KeteranganBankSampahTerdekat_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PengaduanMasyarakat" ADD CONSTRAINT "PengaduanMasyarakat_imageId_fkey" FOREIGN KEY ("imageId") REFERENCES "FileStorage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PengaduanMasyarakat" ADD CONSTRAINT "PengaduanMasyarakat_jenisPengaduanId_fkey" FOREIGN KEY ("jenisPengaduanId") REFERENCES "JenisPengaduan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
1259
prisma/schema.prisma
|
Before Width: | Height: | Size: 275 KiB |
397
prisma/seed.ts
@@ -9,6 +9,26 @@ import potensi from "./data/list-potensi.json";
|
||||
import dasarHukumPPID from "./data/ppid/dasar-hukum-ppid/dasarhukumPPID.json";
|
||||
import profilePPID from "./data/ppid/profile-ppid/profilePPid.json";
|
||||
import visiMisiPPID from "./data/ppid/visi-misi-ppid/visimisiPPID.json";
|
||||
import strukturPPID from "./data/ppid/struktur-ppid/strukturPPID.json";
|
||||
import pelayananPerizinanBerusaha from "./data/desa/layanan/pelayananPerizinanBerusaha.json";
|
||||
import pelayananPendudukNonPermanen from "./data/desa/layanan/pelayanaPendudukNonPermanen.json";
|
||||
import sejarahDesa from "./data/desa/profile/sejarah_desa.json";
|
||||
import visiMisiDesa from "./data/desa/profile/visi_misi_desa.json";
|
||||
import lambangDesa from "./data/desa/profile/lambang_desa.json";
|
||||
import maskotDesa from "./data/desa/profile/maskot_desa.json";
|
||||
import profilPerbekel from "./data/desa/profile/profil_perbekel.json";
|
||||
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 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 bentukKonservasiBerdasarkanAdat from './data/lingkungan/konservasi-adat-bali/bentuk-konservasi.json';
|
||||
import filosofiTriHita from './data/lingkungan/konservasi-adat-bali/filosofi-tri-hita.json';
|
||||
|
||||
|
||||
(async () => {
|
||||
for (const l of layanan) {
|
||||
@@ -27,6 +47,159 @@ import visiMisiPPID from "./data/ppid/visi-misi-ppid/visimisiPPID.json";
|
||||
|
||||
console.log("layanan success ...");
|
||||
|
||||
for (const l of sejarahDesa) {
|
||||
await prisma.sejarahDesa.upsert({
|
||||
where: {
|
||||
id: l.id,
|
||||
},
|
||||
update: {
|
||||
judul: l.judul,
|
||||
deskripsi: l.deskripsi,
|
||||
},
|
||||
create: {
|
||||
id: l.id,
|
||||
judul: l.judul,
|
||||
deskripsi: l.deskripsi,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("sejarah desa success ...");
|
||||
|
||||
for (const l of maskotDesa) {
|
||||
await prisma.maskotDesa.upsert({
|
||||
where: {
|
||||
id: l.id,
|
||||
},
|
||||
update: {
|
||||
judul: l.judul,
|
||||
deskripsi: l.deskripsi,
|
||||
},
|
||||
create: {
|
||||
id: l.id,
|
||||
judul: l.judul,
|
||||
deskripsi: l.deskripsi,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("maskot desa success ...");
|
||||
|
||||
for (const l of lambangDesa) {
|
||||
await prisma.lambangDesa.upsert({
|
||||
where: {
|
||||
id: l.id,
|
||||
},
|
||||
update: {
|
||||
judul: l.judul,
|
||||
deskripsi: l.deskripsi,
|
||||
},
|
||||
create: {
|
||||
id: l.id,
|
||||
judul: l.judul,
|
||||
deskripsi: l.deskripsi,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("lambang desa success ...");
|
||||
|
||||
for (const c of profilPerbekel) {
|
||||
await prisma.profilPerbekel.upsert({
|
||||
where: { id: c.id },
|
||||
update: {
|
||||
biodata: c.biodata,
|
||||
pengalaman: c.pengalaman,
|
||||
pengalamanOrganisasi: c.pengalamanOrganisasi,
|
||||
programUnggulan: c.programUnggulan,
|
||||
// imageId tidak di-update
|
||||
},
|
||||
create: {
|
||||
id: c.id,
|
||||
biodata: c.biodata,
|
||||
pengalaman: c.pengalaman,
|
||||
pengalamanOrganisasi: c.pengalamanOrganisasi,
|
||||
programUnggulan: c.programUnggulan,
|
||||
// imageId tidak di-create
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("✅ profilePerbekel seeded without imageId (editable later via UI)");
|
||||
|
||||
for (const l of visiMisiDesa) {
|
||||
await prisma.visiMisiDesa.upsert({
|
||||
where: {
|
||||
id: l.id,
|
||||
},
|
||||
update: {
|
||||
visi: l.visi,
|
||||
misi: l.misi,
|
||||
},
|
||||
create: {
|
||||
id: l.id,
|
||||
visi: l.visi,
|
||||
misi: l.misi,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("visi misi desa success ...");
|
||||
|
||||
for (const l of pelayananPerizinanBerusaha) {
|
||||
await prisma.pelayananPerizinanBerusaha.upsert({
|
||||
where: {
|
||||
id: l.id,
|
||||
},
|
||||
update: {
|
||||
name: l.name,
|
||||
deskripsi: l.deskripsi,
|
||||
link: l.link,
|
||||
},
|
||||
create: {
|
||||
id: l.id,
|
||||
name: l.name,
|
||||
deskripsi: l.deskripsi,
|
||||
link: l.link,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("pelayanan perizinan berusaha success ...");
|
||||
|
||||
for (const l of pelayananPendudukNonPermanen) {
|
||||
await prisma.pelayananPendudukNonPermanen.upsert({
|
||||
where: {
|
||||
id: l.id,
|
||||
},
|
||||
update: {
|
||||
name: l.name,
|
||||
deskripsi: l.deskripsi,
|
||||
},
|
||||
create: {
|
||||
id: l.id,
|
||||
name: l.name,
|
||||
deskripsi: l.deskripsi,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("pelayanan penduduk non permanen success ...");
|
||||
|
||||
for (const s of strukturPPID) {
|
||||
await prisma.strukturPPID.upsert({
|
||||
where: {
|
||||
id: s.id,
|
||||
},
|
||||
update: {
|
||||
name: s.name,
|
||||
},
|
||||
create: {
|
||||
id: s.id,
|
||||
name: s.name,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("struktur ppid success ...");
|
||||
|
||||
for (const p of potensi) {
|
||||
await prisma.potensi.upsert({
|
||||
where: {
|
||||
@@ -180,6 +353,230 @@ import visiMisiPPID from "./data/ppid/visi-misi-ppid/visimisiPPID.json";
|
||||
}
|
||||
console.log("dasar hukum PPID success ...");
|
||||
|
||||
for (const k of kategoriProduk) {
|
||||
await prisma.kategoriProduk.upsert({
|
||||
where: {
|
||||
id: k.id,
|
||||
},
|
||||
update: {
|
||||
nama: k.nama,
|
||||
},
|
||||
create: {
|
||||
id: k.id,
|
||||
nama: k.nama,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("kategori produk success ...");
|
||||
|
||||
|
||||
for (const p of posisiOrganisasi) {
|
||||
await prisma.posisiOrganisasi.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
nama: p.nama,
|
||||
deskripsi: p.deskripsi,
|
||||
hierarki: p.hierarki,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
nama: p.nama,
|
||||
deskripsi: p.deskripsi,
|
||||
hierarki: p.hierarki,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("posisi organisasi success ...");
|
||||
|
||||
for (const p of pegawai) {
|
||||
await prisma.pegawai.upsert({
|
||||
where: {
|
||||
id: p.id,
|
||||
},
|
||||
update: {
|
||||
namaLengkap: p.namaLengkap,
|
||||
gelarAkademik: p.gelarAkademik,
|
||||
tanggalMasuk: new Date(p.tanggalMasuk),
|
||||
email: p.email,
|
||||
telepon: p.telepon,
|
||||
alamat: p.alamat,
|
||||
posisiId: p.posisiId,
|
||||
isActive: p.isActive,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
namaLengkap: p.namaLengkap,
|
||||
gelarAkademik: p.gelarAkademik,
|
||||
tanggalMasuk: new Date(p.tanggalMasuk),
|
||||
email: p.email,
|
||||
telepon: p.telepon,
|
||||
alamat: p.alamat,
|
||||
posisiId: p.posisiId,
|
||||
isActive: p.isActive,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("pegawai success ...");
|
||||
|
||||
for (const p of hubunganOrganisasi) {
|
||||
await prisma.hubunganOrganisasi.upsert({
|
||||
where: {
|
||||
atasanId_bawahanId: {
|
||||
atasanId: p.atasanId,
|
||||
bawahanId: p.bawahanId,
|
||||
},
|
||||
},
|
||||
update: {
|
||||
tipe: p.tipe,
|
||||
},
|
||||
create: {
|
||||
atasanId: p.atasanId,
|
||||
bawahanId: p.bawahanId,
|
||||
tipe: p.tipe,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("hubungan organisasi success ...");
|
||||
|
||||
for (const d of detailDataPengangguran) {
|
||||
await prisma.detailDataPengangguran.upsert({
|
||||
where: {
|
||||
month_year: { month: d.month, year: d.year },
|
||||
},
|
||||
update: {
|
||||
totalUnemployment: d.totalUnemployment,
|
||||
educatedUnemployment: d.educatedUnemployment,
|
||||
uneducatedUnemployment: d.uneducatedUnemployment,
|
||||
percentageChange: d.percentageChange,
|
||||
},
|
||||
create: {
|
||||
month: d.month,
|
||||
year: d.year,
|
||||
totalUnemployment: d.totalUnemployment,
|
||||
educatedUnemployment: d.educatedUnemployment,
|
||||
uneducatedUnemployment: d.uneducatedUnemployment,
|
||||
percentageChange: d.percentageChange,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("📊 detailDataPengangguran success ...");
|
||||
|
||||
for (const e of tujuanEdukasiLingkungan) {
|
||||
await prisma.tujuanEdukasiLingkungan.upsert({
|
||||
where: {
|
||||
id: e.id,
|
||||
},
|
||||
update: {
|
||||
judul: e.judul,
|
||||
deskripsi: e.deskripsi,
|
||||
},
|
||||
create: {
|
||||
id: e.id,
|
||||
judul: e.judul,
|
||||
deskripsi: e.deskripsi,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("tujuan edukasi lingkungan success ...");
|
||||
|
||||
for (const m of materiEdukasiLingkungan) {
|
||||
await prisma.materiEdukasiLingkungan.upsert({
|
||||
where: {
|
||||
id: m.id,
|
||||
},
|
||||
update: {
|
||||
judul: m.judul,
|
||||
deskripsi: m.deskripsi,
|
||||
},
|
||||
create: {
|
||||
id: m.id,
|
||||
judul: m.judul,
|
||||
deskripsi: m.deskripsi,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("materi edukasi lingkungan success ...");
|
||||
|
||||
for (const c of contohEdukasiLingkungan) {
|
||||
await prisma.contohEdukasiLingkungan.upsert({
|
||||
where: {
|
||||
id: c.id,
|
||||
},
|
||||
update: {
|
||||
judul: c.judul,
|
||||
deskripsi: c.deskripsi,
|
||||
},
|
||||
create: {
|
||||
id: c.id,
|
||||
judul: c.judul,
|
||||
deskripsi: c.deskripsi,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("contoh edukasi lingkungan success ...");
|
||||
|
||||
for (const f of filosofiTriHita) {
|
||||
await prisma.filosofiTriHita.upsert({
|
||||
where: {
|
||||
id: f.id,
|
||||
},
|
||||
update: {
|
||||
judul: f.judul,
|
||||
deskripsi: f.deskripsi,
|
||||
},
|
||||
create: {
|
||||
id: f.id,
|
||||
judul: f.judul,
|
||||
deskripsi: f.deskripsi,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("filosofi tri hita success ...");
|
||||
|
||||
for (const b of bentukKonservasiBerdasarkanAdat) {
|
||||
await prisma.bentukKonservasiBerdasarkanAdat.upsert({
|
||||
where: {
|
||||
id: b.id,
|
||||
},
|
||||
update: {
|
||||
judul: b.judul,
|
||||
deskripsi: b.deskripsi,
|
||||
},
|
||||
create: {
|
||||
id: b.id,
|
||||
judul: b.judul,
|
||||
deskripsi: b.deskripsi,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("bentuk konservasi berdasarkan adat success ...");
|
||||
|
||||
|
||||
for (const n of nilaiKonservasiAdat) {
|
||||
await prisma.nilaiKonservasiAdat.upsert({
|
||||
where: {
|
||||
id: n.id,
|
||||
},
|
||||
update: {
|
||||
judul: n.judul,
|
||||
deskripsi: n.deskripsi,
|
||||
},
|
||||
create: {
|
||||
id: n.id,
|
||||
judul: n.judul,
|
||||
deskripsi: n.deskripsi,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("nilai konservasi adat success ...");
|
||||
|
||||
})()
|
||||
.then(() => prisma.$disconnect())
|
||||
|
||||
BIN
public/Share.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
public/bagikanPostingan.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
public/bungapudak.png
Normal file
|
After Width: | Height: | Size: 221 KiB |
BIN
public/darmasaba-icon.png
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
public/klimakstari.png
Normal file
|
After Width: | Height: | Size: 217 KiB |
BIN
public/pa-desa.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
public/pohonpudak.png
Normal file
|
After Width: | Height: | Size: 253 KiB |
|
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 195 KiB |
BIN
public/sematkan.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
public/struktur_ppid.png
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
public/tarisekar.png
Normal file
|
After Width: | Height: | Size: 208 KiB |
BIN
public/video.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
@@ -1,22 +1,37 @@
|
||||
import React from 'react';
|
||||
import { Grid, GridCol, Paper, TextInput, Title } from '@mantine/core';
|
||||
import { IconSearch } from '@tabler/icons-react'; // Sesuaikan jika kamu pakai icon lain
|
||||
import { IconSearch } from '@tabler/icons-react';
|
||||
import colors from '@/con/colors';
|
||||
|
||||
type HeaderSearchProps = {
|
||||
title: string;
|
||||
placeholder?: string;
|
||||
searchIcon?: React.ReactNode;
|
||||
value?: string;
|
||||
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
};
|
||||
|
||||
const HeaderSearch = ({ title = "", placeholder = "pencarian", searchIcon = <IconSearch size={20} /> }: { title: string, placeholder?: string, searchIcon?: React.ReactNode }) => {
|
||||
const HeaderSearch = ({
|
||||
title = "",
|
||||
placeholder = "pencarian",
|
||||
searchIcon = <IconSearch size={20} />,
|
||||
value,
|
||||
onChange,
|
||||
}: HeaderSearchProps) => {
|
||||
return (
|
||||
<Grid>
|
||||
<Grid mb={10}>
|
||||
<GridCol span={{ base: 12, md: 9 }}>
|
||||
<Title order={3}>{title}</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 3 }}>
|
||||
<Paper radius={"lg"} bg={colors['white-1']}>
|
||||
<Paper radius="lg" bg={colors['white-1']}>
|
||||
<TextInput
|
||||
radius="lg"
|
||||
placeholder={placeholder}
|
||||
leftSection={searchIcon}
|
||||
w="100%"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</Paper>
|
||||
</GridCol>
|
||||
@@ -24,4 +39,4 @@ const HeaderSearch = ({ title = "", placeholder = "pencarian", searchIcon = <Ico
|
||||
);
|
||||
};
|
||||
|
||||
export default HeaderSearch;
|
||||
export default HeaderSearch;
|
||||
|
||||
@@ -5,31 +5,50 @@ import { IconCircleDashedPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React from 'react';
|
||||
|
||||
const JudulListTab = ({ title = "", href = "#", placeholder = "pencarian", searchIcon = <IconSearch size={20} /> }) => {
|
||||
type JudulListTabProps = {
|
||||
title: string;
|
||||
href: string;
|
||||
placeholder: string;
|
||||
searchIcon: React.ReactNode;
|
||||
value?: string;
|
||||
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const JudulListTab = ({
|
||||
title = "",
|
||||
href = "#",
|
||||
placeholder = "pencarian",
|
||||
searchIcon = <IconSearch size={20} />,
|
||||
value,
|
||||
onChange
|
||||
}: JudulListTabProps) => {
|
||||
const router = useRouter();
|
||||
|
||||
const handleNavigate = () => {
|
||||
router.push(href);
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Grid mb={10}>
|
||||
<GridCol span={{ base: 12, md: 8 }}>
|
||||
<Text fz={{base: "md", md: "xl"}} fw={"bold"}>{title}</Text>
|
||||
<Text fz={{ base: "md", md: "xl" }} fw={"bold"}>{title}</Text>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 9, md: 3}} ta="right">
|
||||
<GridCol span={{ base: 9, md: 3 }} ta="right">
|
||||
<Paper radius={"lg"} bg={colors['white-1']}>
|
||||
<TextInput
|
||||
radius="lg"
|
||||
placeholder={placeholder}
|
||||
leftSection={searchIcon}
|
||||
w="100%"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</Paper>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 3, md: 1}} ta="right">
|
||||
<GridCol span={{ base: 3, md: 1 }} ta="right">
|
||||
<Button onClick={handleNavigate} bg={colors['blue-button']}>
|
||||
<IconCircleDashedPlus size={25} />
|
||||
</Button>
|
||||
59
src/app/admin/(dashboard)/_com/leafletMapCreate.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
'use client';
|
||||
|
||||
import { MapContainer, TileLayer, Marker, useMapEvents } from 'react-leaflet';
|
||||
import { useEffect, useState } from 'react';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import L, { LeafletMouseEvent } from 'leaflet';
|
||||
|
||||
type Props = {
|
||||
defaultCenter: { lat: number; lng: number };
|
||||
onSelect?: (pos: { lat: number; lng: number }) => void;
|
||||
readOnly?: boolean;
|
||||
};
|
||||
|
||||
export default function LeafletMap({ defaultCenter, onSelect, readOnly = false }: Props) {
|
||||
const [markerPos, setMarkerPos] = useState(defaultCenter);
|
||||
|
||||
useEffect(() => {
|
||||
// Aman di sini, karena ini hanya jalan di client
|
||||
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',
|
||||
});
|
||||
}, []);
|
||||
|
||||
function LocationMarker() {
|
||||
useMapEvents({
|
||||
click(e: LeafletMouseEvent) {
|
||||
if (readOnly) return;
|
||||
|
||||
const { lat, lng } = e.latlng;
|
||||
setMarkerPos({ lat, lng });
|
||||
onSelect?.({ lat, lng });
|
||||
},
|
||||
});
|
||||
|
||||
return <Marker position={markerPos} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<MapContainer
|
||||
center={defaultCenter}
|
||||
zoom={16}
|
||||
scrollWheelZoom
|
||||
style={{ height: '100%', width: '100%', zIndex: 0 }}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="https://osm.org/copyright">OpenStreetMap</a>'
|
||||
url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
|
||||
/>
|
||||
<LocationMarker />
|
||||
</MapContainer>
|
||||
);
|
||||
}
|
||||
62
src/app/admin/(dashboard)/_com/leafletMapEdit.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
'use client';
|
||||
|
||||
import { MapContainer, TileLayer, Marker, useMapEvents } from 'react-leaflet';
|
||||
import { useState, useEffect } from 'react';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import L, { LeafletMouseEvent } from 'leaflet';
|
||||
|
||||
type Props = {
|
||||
initialPosition: { lat: number; lng: number };
|
||||
onChange: (pos: { lat: number; lng: number }) => void;
|
||||
};
|
||||
|
||||
export default function LeafletMapEdit({ initialPosition, onChange }: Props) {
|
||||
const [markerPos, setMarkerPos] = useState(initialPosition);
|
||||
|
||||
// ✅ Pastikan icon config cuma jalan di client
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
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',
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setMarkerPos(initialPosition);
|
||||
}, [initialPosition]);
|
||||
|
||||
function LocationMarker() {
|
||||
useMapEvents({
|
||||
click(e: LeafletMouseEvent) {
|
||||
const { lat, lng } = e.latlng;
|
||||
setMarkerPos({ lat, lng });
|
||||
onChange({ lat, lng });
|
||||
},
|
||||
});
|
||||
|
||||
return <Marker position={markerPos} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<MapContainer
|
||||
center={markerPos}
|
||||
zoom={16}
|
||||
scrollWheelZoom
|
||||
style={{ height: '100%', width: '100%', zIndex: 0 }}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="https://osm.org/copyright">OpenStreetMap</a>'
|
||||
url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
|
||||
/>
|
||||
<LocationMarker />
|
||||
</MapContainer>
|
||||
);
|
||||
}
|
||||
@@ -21,7 +21,7 @@ export function ModalKonfirmasiHapus({
|
||||
<Modal
|
||||
opened={opened}
|
||||
onClose={onClose}
|
||||
title="Konfirmasi Hapus"
|
||||
title={<Text fw={"bold"} fz={"xl"}>Konfirmasi Hapus</Text>}
|
||||
centered
|
||||
>
|
||||
<Text mb="md">{text}</Text>
|
||||
|
||||
98
src/app/admin/(dashboard)/_com/selectIcon.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
|
||||
import { Box, rem, Select } from '@mantine/core';
|
||||
import {
|
||||
IconChartLine,
|
||||
IconChristmasTreeFilled,
|
||||
IconClipboardTextFilled,
|
||||
IconDroplet,
|
||||
IconHome,
|
||||
IconHomeEco,
|
||||
IconLeaf,
|
||||
IconRecycle,
|
||||
IconScale,
|
||||
IconShieldFilled,
|
||||
IconTent,
|
||||
IconTrashFilled,
|
||||
IconTree,
|
||||
IconTrendingUp,
|
||||
IconTrophy,
|
||||
IconTruckFilled,
|
||||
} from '@tabler/icons-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
const iconMap = {
|
||||
ekowisata: { label: 'Ekowisata', icon: IconLeaf },
|
||||
kompetisi: { label: 'Kompetisi', icon: IconTrophy },
|
||||
wisata: { label: 'Wisata', icon: IconTent },
|
||||
ekonomi: { label: 'Ekonomi', icon: IconChartLine },
|
||||
sampah: { label: 'Sampah', icon: IconRecycle },
|
||||
truck: { label: 'Truck', icon: IconTruckFilled },
|
||||
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}
|
||||
|
||||
};
|
||||
|
||||
type IconKey = keyof typeof iconMap;
|
||||
|
||||
const iconList = Object.entries(iconMap).map(([value, data]) => ({
|
||||
value,
|
||||
label: data.label,
|
||||
}));
|
||||
|
||||
export default function SelectIconProgram(
|
||||
{ onChange }: { onChange: (value: IconKey) => void }) {
|
||||
const [selectedIcon, setSelectedIcon] = useState<IconKey>('ekowisata');
|
||||
const IconComponent = iconMap[selectedIcon]?.icon || null;
|
||||
|
||||
// Push default icon ke state saat render awal
|
||||
useEffect(() => {
|
||||
onChange(selectedIcon);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box maw={300}>
|
||||
<Select
|
||||
placeholder="Pilih ikon"
|
||||
value={selectedIcon}
|
||||
onChange={(value) => {
|
||||
if (value) {
|
||||
setSelectedIcon(value as IconKey);
|
||||
onChange(value as IconKey);
|
||||
}
|
||||
}}
|
||||
data={iconList}
|
||||
leftSection={
|
||||
IconComponent && (
|
||||
<Box>
|
||||
<IconComponent size={24} stroke={1.5} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
withCheckIcon={false}
|
||||
searchable={false}
|
||||
rightSectionWidth={0}
|
||||
styles={{
|
||||
input: {
|
||||
textAlign: 'left',
|
||||
fontSize: rem(16),
|
||||
paddingLeft: 40,
|
||||
},
|
||||
section: {
|
||||
left: 10,
|
||||
right: 'auto',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
92
src/app/admin/(dashboard)/_com/selectIconEdit.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
'use client'
|
||||
|
||||
import { Box, rem, Select } from '@mantine/core';
|
||||
import {
|
||||
IconChartLine,
|
||||
IconChristmasTreeFilled,
|
||||
IconClipboardTextFilled,
|
||||
IconDroplet,
|
||||
IconHome,
|
||||
IconHomeEco,
|
||||
IconLeaf,
|
||||
IconRecycle,
|
||||
IconScale,
|
||||
IconShieldFilled,
|
||||
IconTent,
|
||||
IconTrashFilled,
|
||||
IconTree,
|
||||
IconTrendingUp,
|
||||
IconTrophy,
|
||||
IconTruckFilled,
|
||||
} from '@tabler/icons-react';
|
||||
|
||||
const iconMap = {
|
||||
ekowisata: { label: 'Ekowisata', icon: IconLeaf },
|
||||
kompetisi: { label: 'Kompetisi', icon: IconTrophy },
|
||||
wisata: { label: 'Wisata', icon: IconTent },
|
||||
ekonomi: { label: 'Ekonomi', icon: IconChartLine },
|
||||
sampah: { label: 'Sampah', icon: IconRecycle },
|
||||
truck: { label: 'Truck', icon: IconTruckFilled },
|
||||
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}
|
||||
};
|
||||
|
||||
type IconKey = keyof typeof iconMap;
|
||||
|
||||
const iconList = Object.entries(iconMap).map(([value, data]) => ({
|
||||
value,
|
||||
label: data.label,
|
||||
}));
|
||||
|
||||
export default function SelectIconProgramEdit({
|
||||
onChange,
|
||||
value,
|
||||
}: {
|
||||
onChange: (value: IconKey) => void;
|
||||
value: IconKey;
|
||||
}) {
|
||||
const IconComponent = iconMap[value]?.icon || null;
|
||||
|
||||
return (
|
||||
<Box maw={300}>
|
||||
<Select
|
||||
placeholder="Pilih ikon"
|
||||
value={value}
|
||||
onChange={(value) => {
|
||||
if (value) onChange(value as IconKey);
|
||||
}}
|
||||
data={iconList}
|
||||
leftSection={
|
||||
IconComponent && (
|
||||
<Box>
|
||||
<IconComponent size={24} stroke={1.5} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
withCheckIcon={false}
|
||||
searchable={false}
|
||||
rightSectionWidth={0}
|
||||
styles={{
|
||||
input: {
|
||||
textAlign: 'left',
|
||||
fontSize: rem(16),
|
||||
paddingLeft: 40,
|
||||
},
|
||||
section: {
|
||||
left: 10,
|
||||
right: 'auto',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -80,13 +80,33 @@ const berita = proxy({
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.berita["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
berita.findMany.data = (res.data?.data ) ?? [];
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
|
||||
async load(page = 1, limit = 10) {
|
||||
berita.findMany.loading = true;
|
||||
berita.findMany.page = page;
|
||||
try {
|
||||
const res = await ApiFetch.api.desa.berita["find-many"].get({
|
||||
query: {
|
||||
page,
|
||||
limit,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
berita.findMany.data = res.data.data ?? [];
|
||||
berita.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch berita paginated:", err);
|
||||
} finally {
|
||||
berita.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
findUnique: {
|
||||
data: null as
|
||||
| Prisma.BeritaGetPayload<{
|
||||
@@ -243,6 +263,59 @@ const berita = proxy({
|
||||
berita.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
findFirst: {
|
||||
data: null as Prisma.BeritaGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
kategoriBerita: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
async load() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const res = await ApiFetch.api.desa.berita["find-first"].get();
|
||||
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;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch berita terbaru:", err);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findRecent: {
|
||||
data: [] as Prisma.BeritaGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
kategoriBerita: true;
|
||||
};
|
||||
}>[],
|
||||
loading: false,
|
||||
|
||||
async load() {
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await ApiFetch.api.desa.berita["find-recent"].get();
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
this.data = res.data.data ?? [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal fetch berita recent:", error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
415
src/app/admin/(dashboard)/_state/desa/gallery.ts
Normal file
@@ -0,0 +1,415 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const fotoForm = z.object({
|
||||
name: z.string().min(1, { message: "Name is required" }),
|
||||
deskripsi: z.string().min(1, { message: "Deskripsi is required" }),
|
||||
imagesId: z.string().nonempty(),
|
||||
});
|
||||
|
||||
const videoForm = z.object({
|
||||
name: z.string().min(1, { message: "Name is required" }),
|
||||
deskripsi: z.string().min(1, { message: "Deskripsi is required" }),
|
||||
linkVideo: z.string().min(1, { message: "Link video is required" }),
|
||||
});
|
||||
|
||||
const defaultFormFoto = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
imagesId: "",
|
||||
};
|
||||
|
||||
const defaultFormVideo = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
linkVideo: "",
|
||||
};
|
||||
|
||||
const foto = proxy({
|
||||
create: {
|
||||
form: { ...defaultFormFoto },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = fotoForm.safeParse(foto.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
foto.create.loading = true;
|
||||
const res = await ApiFetch.api.desa.gallery.foto["create"].post(
|
||||
foto.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
foto.findMany.load();
|
||||
return toast.success("Foto berhasil disimpan!");
|
||||
}
|
||||
return toast.error("Gagal menyimpan foto");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
foto.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
foto.create.form = { ...defaultFormFoto };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.GalleryFotoGetPayload<{
|
||||
include: {
|
||||
imageGalleryFoto: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.gallery.foto["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
foto.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.GalleryFotoGetPayload<{
|
||||
include: {
|
||||
imageGalleryFoto: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/desa/gallery/foto/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
foto.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch foto:", res.statusText);
|
||||
foto.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching foto:", error);
|
||||
foto.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
foto.delete.loading = true;
|
||||
const response = await fetch(`/api/desa/gallery/foto/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const result = await response.json();
|
||||
if (response.ok) {
|
||||
toast.success(result.message || "Foto berhasil dihapus");
|
||||
await foto.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result.message || "Gagal menghapus foto");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus foto");
|
||||
} finally {
|
||||
foto.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultFormFoto },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(`/api/desa/gallery/foto/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
deskripsi: data.deskripsi,
|
||||
imagesId: data.imagesId || "",
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading foto:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = fotoForm.safeParse(foto.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
foto.update.loading = true;
|
||||
const response = await fetch(`/api/desa/gallery/foto/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
deskripsi: this.form.deskripsi,
|
||||
imagesId: this.form.imagesId,
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success(result.message || "Foto berhasil diupdate");
|
||||
await foto.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate foto");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating foto:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal mengupdate foto"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
foto.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
foto.update.id = "";
|
||||
foto.update.form = { ...defaultFormFoto };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const video = proxy({
|
||||
create: {
|
||||
form: { ...defaultFormVideo },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = videoForm.safeParse(video.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
video.create.loading = true;
|
||||
const res = await ApiFetch.api.desa.gallery.video["create"].post(
|
||||
video.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
video.findMany.load();
|
||||
return toast.success("Video berhasil disimpan!");
|
||||
}
|
||||
return toast.error("Gagal menyimpan video");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
video.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
video.create.form = { ...defaultFormVideo };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.GalleryVideoGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.gallery.video["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
video.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.GalleryVideoGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/desa/gallery/video/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
video.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch video:", res.statusText);
|
||||
video.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching video:", error);
|
||||
video.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
video.delete.loading = true;
|
||||
const response = await fetch(`/api/desa/gallery/video/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const result = await response.json();
|
||||
if (response.ok) {
|
||||
toast.success(result.message || "Video berhasil dihapus");
|
||||
await video.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus video");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus video");
|
||||
} finally {
|
||||
video.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultFormVideo },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(`/api/desa/gallery/video/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
deskripsi: data.deskripsi,
|
||||
linkVideo: data.linkVideo,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading video:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = videoForm.safeParse(video.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
video.update.loading = true;
|
||||
const response = await fetch(`/api/desa/gallery/video/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
deskripsi: this.form.deskripsi,
|
||||
linkVideo: this.form.linkVideo,
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success(result.message || "Video berhasil diupdate");
|
||||
await video.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate video");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating video:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal mengupdate video"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
video.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
video.update.id = "";
|
||||
video.update.form = { ...defaultFormVideo };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const stateGallery = proxy({
|
||||
foto,
|
||||
video,
|
||||
});
|
||||
|
||||
export default stateGallery;
|
||||
718
src/app/admin/(dashboard)/_state/desa/layananDesa.ts
Normal file
@@ -0,0 +1,718 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateSuratKeteranganForm = z.object({
|
||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
imageId: z.string().nonempty(),
|
||||
});
|
||||
|
||||
const suratKeteranganForm = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
imageId: "",
|
||||
};
|
||||
|
||||
const telunjukSaktiDesaForm = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
link: "",
|
||||
};
|
||||
|
||||
const templateTelunjukSaktiDesaForm = z.object({
|
||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
});
|
||||
|
||||
|
||||
const templatePelayananPerizinanBerusaha = z.object({
|
||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
link: z.string().min(3, "Link minimal 3 karakter"),
|
||||
});
|
||||
|
||||
type pelayananPerizinanBerusahaForm =
|
||||
Prisma.PelayananPerizinanBerusahaGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
name: true;
|
||||
deskripsi: true;
|
||||
link: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const pelayananPerizinanBerusahaForm = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
link: "",
|
||||
};
|
||||
|
||||
const templatePelayananPendudukNonPermanen = z.object({
|
||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
});
|
||||
|
||||
type pelayananPendudukNonPermanenForm =
|
||||
Prisma.PelayananPendudukNonPermanenGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
name: true;
|
||||
deskripsi: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const pelayananPendudukNonPermanenForm = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
};
|
||||
|
||||
|
||||
const suratKeterangan = proxy({
|
||||
create: {
|
||||
form: { ...suratKeteranganForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateSuratKeteranganForm.safeParse(
|
||||
suratKeterangan.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
suratKeterangan.create.loading = true;
|
||||
const res = await ApiFetch.api.desa.layanan.pelayanansuratketerangan[
|
||||
"create"
|
||||
].post(suratKeterangan.create.form);
|
||||
if (res.status === 200) {
|
||||
suratKeterangan.findMany.load();
|
||||
return toast.success("Surat Keterangan berhasil disimpan!");
|
||||
}
|
||||
return toast.error("Gagal menyimpan surat keterangan");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
suratKeterangan.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
suratKeterangan.create.form = { ...suratKeteranganForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: [] as Prisma.PelayananSuratKeteranganGetPayload<{
|
||||
include: { image: true };
|
||||
}>[],
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.layanan.pelayanansuratketerangan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
suratKeterangan.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PelayananSuratKeteranganGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/desa/layanan/pelayanansuratketerangan/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
suratKeterangan.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch surat keterangan:", res.statusText);
|
||||
suratKeterangan.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching surat keterangan:", error);
|
||||
suratKeterangan.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
suratKeterangan.delete.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/desa/layanan/pelayanansuratketerangan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
const result = await response.json();
|
||||
if (response.ok) {
|
||||
toast.success(result.message || "Surat Keterangan berhasil dihapus");
|
||||
await suratKeterangan.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result.message || "Gagal menghapus surat keterangan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus surat keterangan");
|
||||
} finally {
|
||||
suratKeterangan.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...suratKeteranganForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/desa/layanan/pelayanansuratketerangan/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
deskripsi: data.deskripsi,
|
||||
imageId: data.imageId || "",
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching surat keterangan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = templateSuratKeteranganForm.safeParse(
|
||||
suratKeterangan.edit.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
suratKeterangan.edit.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/desa/layanan/pelayanansuratketerangan/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
deskripsi: this.form.deskripsi,
|
||||
imageId: this.form.imageId,
|
||||
}),
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success(result.message || "Surat Keterangan berhasil diupdate");
|
||||
await suratKeterangan.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(
|
||||
result.message || "Gagal mengupdate surat keterangan"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating surat keterangan:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update surat keterangan"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
suratKeterangan.edit.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const pelayananTelunjukSaktiDesa = proxy({
|
||||
create: {
|
||||
form: { ...telunjukSaktiDesaForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateTelunjukSaktiDesaForm.safeParse(
|
||||
pelayananTelunjukSaktiDesa.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
pelayananTelunjukSaktiDesa.create.loading = true;
|
||||
const res = await ApiFetch.api.desa.layanan.pelayanantelunjuksaktidesa[
|
||||
"create"
|
||||
].post(pelayananTelunjukSaktiDesa.create.form);
|
||||
if (res.status === 200) {
|
||||
pelayananTelunjukSaktiDesa.findMany.load();
|
||||
return toast.success("Telunjuk Sakti Desa berhasil disimpan!");
|
||||
}
|
||||
return toast.error("Gagal menyimpan telunjuk sakti desa");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
pelayananTelunjukSaktiDesa.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
pelayananTelunjukSaktiDesa.create.form = { ...telunjukSaktiDesaForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: [] as Prisma.PelayananTelunjukSaktiDesaGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}>[],
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.layanan.pelayanantelunjuksaktidesa[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
pelayananTelunjukSaktiDesa.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PelayananTelunjukSaktiDesaGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/desa/layanan/pelayanantelunjuksaktidesa/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
pelayananTelunjukSaktiDesa.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch telunjuk sakti desa:", res.statusText);
|
||||
pelayananTelunjukSaktiDesa.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching telunjuk sakti desa:", error);
|
||||
pelayananTelunjukSaktiDesa.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
pelayananTelunjukSaktiDesa.delete.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/desa/layanan/pelayanantelunjuksaktidesa/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
const result = await response.json();
|
||||
if (response.ok) {
|
||||
toast.success(result.message || "Telunjuk Sakti Desa berhasil dihapus");
|
||||
await pelayananTelunjukSaktiDesa.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result.message || "Gagal menghapus telunjuk sakti desa");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus telunjuk sakti desa");
|
||||
} finally {
|
||||
pelayananTelunjukSaktiDesa.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...telunjukSaktiDesaForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/desa/layanan/pelayanantelunjuksaktidesa/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
deskripsi: data.deskripsi,
|
||||
link: data.link,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching telunjuk sakti desa:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = templateTelunjukSaktiDesaForm.safeParse(
|
||||
pelayananTelunjukSaktiDesa.edit.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
pelayananTelunjukSaktiDesa.edit.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/desa/layanan/pelayanantelunjuksaktidesa/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
deskripsi: this.form.deskripsi,
|
||||
link: this.form.link,
|
||||
}),
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success(result.message || "Telunjuk Sakti Desa berhasil diupdate");
|
||||
await pelayananTelunjukSaktiDesa.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(
|
||||
result.message || "Gagal mengupdate telunjuk sakti desa"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating telunjuk sakti desa:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update telunjuk sakti desa"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
pelayananTelunjukSaktiDesa.edit.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const pelayananPerizinanBerusaha = proxy({
|
||||
findById: {
|
||||
data: null as pelayananPerizinanBerusahaForm | null,
|
||||
loading: false,
|
||||
initialize() {
|
||||
pelayananPerizinanBerusaha.findById.data = {
|
||||
id: "",
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
link: "",
|
||||
} as pelayananPerizinanBerusahaForm;
|
||||
},
|
||||
async load(id: string) {
|
||||
try {
|
||||
pelayananPerizinanBerusaha.findById.loading = true;
|
||||
const res = await fetch(
|
||||
`/api/desa/layanan/pelayananperizinanberusaha/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
pelayananPerizinanBerusaha.findById.data = data.data ?? null;
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to fetch pelayanan perizinan berusaha:",
|
||||
res.statusText
|
||||
);
|
||||
pelayananPerizinanBerusaha.findById.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching pelayanan perizinan berusaha:", error);
|
||||
pelayananPerizinanBerusaha.findById.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...pelayananPerizinanBerusahaForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak boleh kosong");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/desa/layanan/pelayananperizinanberusaha/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
pelayananPerizinanBerusaha.update.id = data.id;
|
||||
pelayananPerizinanBerusaha.update.form = {
|
||||
name: data.name,
|
||||
deskripsi: data.deskripsi,
|
||||
link: data.link,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching pelayanan perizinan berusaha:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update(data: pelayananPerizinanBerusahaForm) {
|
||||
const cek = templatePelayananPerizinanBerusaha.safeParse(data);
|
||||
if (!cek.success) {
|
||||
const errors = cek.error.issues
|
||||
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
||||
.join(", ");
|
||||
toast.error(`Form tidak valid: ${errors}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
pelayananPerizinanBerusaha.update.loading = true;
|
||||
const res = await fetch(
|
||||
`/api/desa/layanan/pelayananperizinanberusaha/${data.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
}
|
||||
);
|
||||
if (res.ok) {
|
||||
toast.success("Pelayanan perizinan berusaha berhasil diupdate");
|
||||
await pelayananPerizinanBerusaha.findById.load(data.id);
|
||||
} else {
|
||||
toast.error("Gagal mengupdate pelayanan perizinan berusaha");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating pelayanan perizinan berusaha:", error);
|
||||
toast.error(
|
||||
"Terjadi kesalahan saat mengupdate pelayanan perizinan berusaha"
|
||||
);
|
||||
} finally {
|
||||
pelayananPerizinanBerusaha.update.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const pelayananPendudukNonPermanen = proxy({
|
||||
findById: {
|
||||
data: null as pelayananPendudukNonPermanenForm | null,
|
||||
loading: false,
|
||||
initialize() {
|
||||
pelayananPendudukNonPermanen.findById.data = {
|
||||
id: "",
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
} as pelayananPendudukNonPermanenForm;
|
||||
},
|
||||
async load(id: string) {
|
||||
try {
|
||||
pelayananPendudukNonPermanen.findById.loading = true;
|
||||
const res = await fetch(
|
||||
`/api/desa/layanan/pelayananpenduduknonpermanen/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
pelayananPendudukNonPermanen.findById.data = data.data ?? null;
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to fetch pelayanan penduduk non permanen:",
|
||||
res.statusText
|
||||
);
|
||||
pelayananPendudukNonPermanen.findById.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching pelayanan penduduk non permanen:", error);
|
||||
pelayananPendudukNonPermanen.findById.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...pelayananPendudukNonPermanenForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak boleh kosong");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/desa/layanan/pelayananpenduduknonpermanen/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
pelayananPendudukNonPermanen.update.id = data.id;
|
||||
pelayananPendudukNonPermanen.update.form = {
|
||||
name: data.name,
|
||||
deskripsi: data.deskripsi,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching pelayanan penduduk non permanen:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update(data: pelayananPendudukNonPermanenForm) {
|
||||
const cek = templatePelayananPendudukNonPermanen.safeParse(data);
|
||||
if (!cek.success) {
|
||||
const errors = cek.error.issues
|
||||
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
||||
.join(", ");
|
||||
toast.error(`Form tidak valid: ${errors}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
pelayananPendudukNonPermanen.update.loading = true;
|
||||
const res = await fetch(
|
||||
`/api/desa/layanan/pelayananpenduduknonpermanen/${data.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
}
|
||||
);
|
||||
if (res.ok) {
|
||||
toast.success("Pelayanan penduduk non permanen berhasil diupdate");
|
||||
await pelayananPendudukNonPermanen.findById.load(data.id);
|
||||
} else {
|
||||
toast.error("Gagal mengupdate pelayanan penduduk non permanen");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating pelayanan penduduk non permanen:", error);
|
||||
toast.error(
|
||||
"Terjadi kesalahan saat mengupdate pelayanan penduduk non permanen"
|
||||
);
|
||||
} finally {
|
||||
pelayananPendudukNonPermanen.update.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const stateLayananDesa = proxy({
|
||||
suratKeterangan,
|
||||
pelayananPerizinanBerusaha,
|
||||
pelayananTelunjukSaktiDesa,
|
||||
pelayananPendudukNonPermanen,
|
||||
});
|
||||
|
||||
export default stateLayananDesa;
|
||||
221
src/app/admin/(dashboard)/_state/desa/penghargaan.ts
Normal file
@@ -0,0 +1,221 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
juara: z.string().min(1).max(50),
|
||||
deskripsi: z.string().min(1).max(5000),
|
||||
imageId: z.string().min(1).max(50),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
name: "",
|
||||
juara: "",
|
||||
deskripsi: "",
|
||||
imageId: "",
|
||||
};
|
||||
|
||||
const penghargaanState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(penghargaanState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
penghargaanState.create.loading = true;
|
||||
const res = await ApiFetch.api.desa.penghargaan["create"].post(
|
||||
penghargaanState.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
penghargaanState.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
penghargaanState.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PenghargaanGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.penghargaan["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
penghargaanState.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PenghargaanGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/desa/penghargaan/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
penghargaanState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
penghargaanState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading penghargaan:", error);
|
||||
penghargaanState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
penghargaanState.delete.loading = true;
|
||||
const response = await fetch(`/api/desa/penghargaan/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
toast.success(result.message || "Penghargaan berhasil dihapus");
|
||||
await penghargaanState.findMany.load();
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus penghargaan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat menghapus penghargaan");
|
||||
} finally {
|
||||
penghargaanState.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/desa/penghargaan/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
juara: data.juara,
|
||||
deskripsi: data.deskripsi,
|
||||
imageId: data.imageId,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading penghargaan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(penghargaanState.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
penghargaanState.edit.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/desa/penghargaan/${penghargaanState.edit.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: this.form.name,
|
||||
juara: this.form.juara,
|
||||
deskripsi: this.form.deskripsi,
|
||||
imageId: this.form.imageId,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success("Berhasil update penghargaan");
|
||||
await penghargaanState.findMany.load();
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal update penghargaan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating penghargaan:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update penghargaan"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
penghargaanState.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
penghargaanState.edit.id = "";
|
||||
penghargaanState.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
export default penghargaanState;
|
||||
@@ -68,11 +68,11 @@ const pengumuman = proxy({
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PengumumanGetPayload<{
|
||||
include: {
|
||||
| Prisma.PengumumanGetPayload<{
|
||||
include: {
|
||||
CategoryPengumuman: true;
|
||||
}
|
||||
}>[]
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.pengumuman["find-many"].get();
|
||||
@@ -82,30 +82,28 @@ const pengumuman = proxy({
|
||||
}
|
||||
},
|
||||
},
|
||||
// findUnique: {
|
||||
// data: null as
|
||||
// | Prisma.PengumumanGetPayload<{
|
||||
// include: {
|
||||
// CategoryPengumuman: true;
|
||||
// }
|
||||
// }>
|
||||
// | null,
|
||||
// async load(id: string) {
|
||||
// try {
|
||||
// const res = await fetch(`/api/desa/pengumuman/${id}`);
|
||||
// if (res.ok) {
|
||||
// const data = await res.json();
|
||||
// pengumuman.findUnique.data = data.data ?? null;
|
||||
// } else {
|
||||
// console.error('Failed to fetch pengumuman:', res.statusText);
|
||||
// pengumuman.findUnique.data = null;
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.error('Error fetching pengumuman:', error);
|
||||
// pengumuman.findUnique.data = null;
|
||||
// }
|
||||
// },
|
||||
// },
|
||||
findUnique: {
|
||||
data: null as Prisma.PengumumanGetPayload<{
|
||||
include: {
|
||||
CategoryPengumuman: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/desa/pengumuman/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
pengumuman.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch pengumuman:", res.statusText);
|
||||
pengumuman.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching pengumuman:", error);
|
||||
pengumuman.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
@@ -237,6 +235,55 @@ const pengumuman = proxy({
|
||||
}
|
||||
},
|
||||
},
|
||||
findFirst: {
|
||||
data: null as Prisma.PengumumanGetPayload<{
|
||||
include: {
|
||||
CategoryPengumuman: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
async load() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const res = await ApiFetch.api.desa.pengumuman["find-first"].get();
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
// Add type assertion to ensure type safety
|
||||
pengumuman.findFirst.data = res.data
|
||||
.data as Prisma.PengumumanGetPayload<{
|
||||
include: {
|
||||
CategoryPengumuman: true;
|
||||
};
|
||||
}> | null;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch pengumuman terbaru:", err);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findRecent: {
|
||||
data: [] as Prisma.PengumumanGetPayload<{
|
||||
include: {
|
||||
CategoryPengumuman: true;
|
||||
};
|
||||
}>[],
|
||||
loading: false,
|
||||
|
||||
async load() {
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await ApiFetch.api.desa.pengumuman["find-recent"].get();
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
this.data = res.data.data ?? [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal fetch pengumuman recent:", error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const stateDesaPengumuman = proxy({
|
||||
|
||||
@@ -6,7 +6,7 @@ import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
deskripsi: z.string().min(1).max(50),
|
||||
deskripsi: z.string().min(1).max(5000),
|
||||
kategori: z.string().min(1).max(50),
|
||||
imageId: z.string().min(1).max(50),
|
||||
content: z.string().min(1).max(5000),
|
||||
|
||||
887
src/app/admin/(dashboard)/_state/ekonomi/PADesa.ts
Normal file
@@ -0,0 +1,887 @@
|
||||
/* 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 templateApbDesa = z.object({
|
||||
tahun: z.number().min(4, "Tahun minimal 4 karakter"),
|
||||
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"),
|
||||
});
|
||||
|
||||
const ApbDesaDefaultForm = {
|
||||
tahun: 0,
|
||||
pendapatanIds: [] as string[],
|
||||
belanjaIds: [] as string[],
|
||||
pembiayaanIds: [] as string[],
|
||||
};
|
||||
|
||||
const ApbDesa = proxy({
|
||||
create: {
|
||||
form: { ...ApbDesaDefaultForm },
|
||||
loading: false,
|
||||
async submit() {
|
||||
const cek = templateApbDesa.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = cek.error.issues.map((v) => v.message).join("\n");
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.apbdesa[
|
||||
"create"
|
||||
].post(this.form);
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil menambahkan APB Desa");
|
||||
ApbDesa.findMany.load();
|
||||
this.reset();
|
||||
} else {
|
||||
toast.error(res.data?.message || "Gagal menambahkan APB Desa");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Create error:", error);
|
||||
toast.error("Gagal menambahkan APB Desa");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
this.form = { ...ApbDesaDefaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.ApbDesaGetPayload<{
|
||||
include: {
|
||||
pendapatan: true;
|
||||
belanja: true;
|
||||
pembiayaan: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
loading: false,
|
||||
async load() {
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.apbdesa[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
this.data = res.data?.data ?? [];
|
||||
} else {
|
||||
toast.error(res.data?.message || "Gagal mengambil APB Desa");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Find many error:", error);
|
||||
toast.error("Gagal mengambil APB Desa");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...ApbDesaDefaultForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/apbdesa/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
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,
|
||||
pendapatanIds: data.pendapatan?.map((p: any) => p.id) || [],
|
||||
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);
|
||||
toast.error("Gagal memuat data APB Desa");
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
try {
|
||||
this.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/apbdesa/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(this.form),
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error("Gagal memperbarui APB Desa");
|
||||
}
|
||||
const data = await response.json();
|
||||
toast.success("APB Desa berhasil diperbarui");
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error updating APB Desa:", error);
|
||||
toast.error("Gagal memperbarui APB Desa");
|
||||
throw error;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
this.id = "";
|
||||
this.form = { ...ApbDesaDefaultForm };
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
try {
|
||||
this.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/apbdesa/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error("Gagal menghapus APB Desa");
|
||||
}
|
||||
toast.success("APB Desa berhasil dihapus");
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Error deleting APB Desa:", error);
|
||||
toast.error("Gagal menghapus APB Desa");
|
||||
return false;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.ApbDesaGetPayload<{
|
||||
include: { pendapatan: true; belanja: true; pembiayaan: true };
|
||||
}> | null,
|
||||
|
||||
async load(id: string) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/apbdesa/${id}`
|
||||
);
|
||||
if (!response.ok) {
|
||||
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) {
|
||||
console.error("Error loading APB Desa detail:", error);
|
||||
toast.error("Gagal memuat detail APB Desa");
|
||||
return null;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const templatePendapatan = z.object({
|
||||
name: z.string().min(2, "Nama harus diisi"),
|
||||
value: z.number().int().positive("Nilai harus angka positif"),
|
||||
});
|
||||
|
||||
const PendapatanDefaultForm = {
|
||||
name: "",
|
||||
value: 0,
|
||||
};
|
||||
|
||||
const pendapatan = proxy({
|
||||
create: {
|
||||
form: { ...PendapatanDefaultForm },
|
||||
loading: false,
|
||||
async submit() {
|
||||
const cek = templatePendapatan.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = cek.error.issues.map((v) => v.message).join("\n");
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const res =
|
||||
await ApiFetch.api.ekonomi.pendapatanaslidesa.pendapatanasli[
|
||||
"create"
|
||||
].post(this.form);
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil menambahkan Pendapatan Asli");
|
||||
pendapatan.findMany.load();
|
||||
this.reset();
|
||||
} else {
|
||||
toast.error(res.data?.message || "Gagal menambahkan Pendapatan Asli");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Create error:", error);
|
||||
toast.error("Gagal menambahkan Pendapatan Asli");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
this.form = { ...PendapatanDefaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
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
|
||||
pendapatan.findMany.page = page;
|
||||
try {
|
||||
const res =
|
||||
await ApiFetch.api.ekonomi.pendapatanaslidesa.pendapatanasli[
|
||||
"find-many"
|
||||
].get({
|
||||
query: { page, limit },
|
||||
});
|
||||
|
||||
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;
|
||||
} 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);
|
||||
pendapatan.findMany.data = [];
|
||||
pendapatan.findMany.total = 0;
|
||||
pendapatan.findMany.totalPages = 1;
|
||||
} finally {
|
||||
pendapatan.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...PendapatanDefaultForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
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}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
value: data.value,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading pendapatan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templatePendapatan.safeParse(pendapatan.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
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,
|
||||
}),
|
||||
});
|
||||
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 pendapatan");
|
||||
await pendapatan.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate pendapatan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating pendapatan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal mengupdate pendapatan"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
pendapatan.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
pendapatan.update.id = "";
|
||||
pendapatan.update.form = { ...PendapatanDefaultForm };
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
pendapatan.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/pendapatanasli/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Pendapatan Asli berhasil dihapus");
|
||||
await pendapatan.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus Pendapatan Asli");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus Pendapatan Asli");
|
||||
} finally {
|
||||
pendapatan.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PendapatanGetPayload<{
|
||||
select: { isActive: boolean };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/pendapatanasli/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const json = await res.json();
|
||||
pendapatan.findUnique.data = json.data
|
||||
? {
|
||||
...json.data,
|
||||
isActive: json.data.isActive ?? true, // Fallback ke aktif:true jika tidak ada data
|
||||
}
|
||||
: null;
|
||||
} else {
|
||||
pendapatan.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const templateBelanja = z.object({
|
||||
name: z.string().min(2, "Nama harus diisi"),
|
||||
value: z.number().int().positive("Nilai harus angka positif"),
|
||||
});
|
||||
|
||||
const BelanjaDefaultForm = {
|
||||
name: "",
|
||||
value: 0,
|
||||
};
|
||||
|
||||
const belanja = proxy({
|
||||
create: {
|
||||
form: { ...BelanjaDefaultForm },
|
||||
loading: false,
|
||||
async submit() {
|
||||
const cek = templateBelanja.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = cek.error.issues.map((v) => v.message).join("\n");
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.belanja[
|
||||
"create"
|
||||
].post(this.form);
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil menambahkan Belanja");
|
||||
belanja.findMany.load();
|
||||
this.reset();
|
||||
} else {
|
||||
toast.error(res.data?.message || "Gagal menambahkan Belanja");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Create error:", error);
|
||||
toast.error("Gagal menambahkan Belanja");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
this.form = { ...BelanjaDefaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: [] as Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
value: number;
|
||||
}>,
|
||||
loading: false,
|
||||
async load() {
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.belanja[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
this.data = res.data?.data ?? [];
|
||||
} else {
|
||||
toast.error(res.data?.message || "Gagal mengambil Belanja");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Find many error:", error);
|
||||
toast.error("Gagal mengambil Belanja");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...BelanjaDefaultForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
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}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
value: data.value,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading belanja:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateBelanja.safeParse(belanja.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
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,
|
||||
}),
|
||||
});
|
||||
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 belanja");
|
||||
await belanja.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate belanja");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating belanja:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal mengupdate belanja"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
belanja.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
belanja.update.id = "";
|
||||
belanja.update.form = { ...BelanjaDefaultForm };
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
belanja.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/belanja/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Belanja berhasil dihapus");
|
||||
await belanja.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus Belanja");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus Belanja");
|
||||
} finally {
|
||||
belanja.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.BelanjaGetPayload<{
|
||||
select: { isActive: boolean };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
const res = await fetch(`/api/ekonomi/pendapatanaslidesa/belanja/${id}`);
|
||||
if (res.ok) {
|
||||
const json = await res.json();
|
||||
belanja.findUnique.data = json.data
|
||||
? {
|
||||
...json.data,
|
||||
isActive: json.data.isActive ?? true, // Fallback ke aktif:true jika tidak ada data
|
||||
}
|
||||
: null;
|
||||
} else {
|
||||
belanja.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const templatePembiayaan = z.object({
|
||||
name: z.string().min(2, "Nama harus diisi"),
|
||||
value: z.number().int().positive("Nilai harus angka positif"),
|
||||
});
|
||||
|
||||
const PembiayaanDefaultForm = {
|
||||
name: "",
|
||||
value: 0,
|
||||
};
|
||||
|
||||
const pembiayaan = proxy({
|
||||
create: {
|
||||
form: { ...PembiayaanDefaultForm },
|
||||
loading: false,
|
||||
async submit() {
|
||||
const cek = templatePembiayaan.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = cek.error.issues.map((v) => v.message).join("\n");
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.pembiayaan[
|
||||
"create"
|
||||
].post(this.form);
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil menambahkan Pembiayaan");
|
||||
pembiayaan.findMany.load();
|
||||
this.reset();
|
||||
} else {
|
||||
toast.error(res.data?.message || "Gagal menambahkan Pembiayaan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Create error:", error);
|
||||
toast.error("Gagal menambahkan Pembiayaan");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
this.form = { ...PembiayaanDefaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: [] as Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
value: number;
|
||||
}>,
|
||||
loading: false,
|
||||
async load() {
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.pembiayaan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
this.data = res.data?.data ?? [];
|
||||
} else {
|
||||
toast.error(res.data?.message || "Gagal mengambil Pembiayaan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Find many error:", error);
|
||||
toast.error("Gagal mengambil Pembiayaan");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...PembiayaanDefaultForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
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}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
value: data.value,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading pembiayaan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templatePembiayaan.safeParse(pembiayaan.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
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,
|
||||
}),
|
||||
});
|
||||
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 pembiayaan");
|
||||
await pembiayaan.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate pembiayaan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating pembiayaan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal mengupdate pembiayaan"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
pembiayaan.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
pembiayaan.update.id = "";
|
||||
pembiayaan.update.form = { ...PembiayaanDefaultForm };
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
pembiayaan.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/pembiayaan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Pembiayaan berhasil dihapus");
|
||||
await pembiayaan.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus Pembiayaan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus Pembiayaan");
|
||||
} finally {
|
||||
pembiayaan.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PembiayaanGetPayload<{
|
||||
select: { isActive: boolean };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/pendapatanaslidesa/pembiayaan/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const json = await res.json();
|
||||
pembiayaan.findUnique.data = json.data
|
||||
? {
|
||||
...json.data,
|
||||
isActive: json.data.isActive ?? true, // Fallback ke aktif:true jika tidak ada data
|
||||
}
|
||||
: null;
|
||||
} else {
|
||||
pembiayaan.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const PendapatanAsliDesa = proxy({
|
||||
ApbDesa,
|
||||
belanja,
|
||||
pembiayaan,
|
||||
pendapatan,
|
||||
});
|
||||
|
||||
export default PendapatanAsliDesa;
|
||||
197
src/app/admin/(dashboard)/_state/ekonomi/demografi-pekerjaan.ts
Normal file
@@ -0,0 +1,197 @@
|
||||
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 templateDemografiPekerjaan = z.object({
|
||||
pekerjaan: z.string().min(1, "Pekerjaan harus diisi"),
|
||||
lakiLaki: z.number().min(1, "Laki - Laki harus diisi"),
|
||||
perempuan: z.number().min(1, "Perempuan harus diisi"),
|
||||
});
|
||||
|
||||
type DemografiPekerjaan = Prisma.DataDemografiPekerjaanGetPayload<{
|
||||
select: {
|
||||
pekerjaan: true;
|
||||
lakiLaki: true;
|
||||
perempuan: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const defaultForm: DemografiPekerjaan = {
|
||||
pekerjaan: "",
|
||||
lakiLaki: 0,
|
||||
perempuan: 0,
|
||||
};
|
||||
|
||||
const demografiPekerjaan = proxy({
|
||||
create: {
|
||||
form: defaultForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateDemografiPekerjaan.safeParse(
|
||||
demografiPekerjaan.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
demografiPekerjaan.create.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.demografipekerjaan[
|
||||
"create"
|
||||
].post(demografiPekerjaan.create.form);
|
||||
|
||||
if (res.status === 200) {
|
||||
const id = res.data?.data?.id;
|
||||
if (id) {
|
||||
toast.success("Success create");
|
||||
demografiPekerjaan.create.form = { ...defaultForm };
|
||||
demografiPekerjaan.findMany.load();
|
||||
return id;
|
||||
}
|
||||
}
|
||||
toast.error("failed create");
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
return null;
|
||||
} finally {
|
||||
demografiPekerjaan.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.DataDemografiPekerjaanGetPayload<{
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
findUnique: {
|
||||
data: null as Prisma.DataDemografiPekerjaanGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/ekonomi/demografipekerjaan/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
demografiPekerjaan.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch demografiPekerjaan:", res.statusText);
|
||||
demografiPekerjaan.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching demografiPekerjaan:", error);
|
||||
demografiPekerjaan.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
const formData = {
|
||||
pekerjaan: this.form.pekerjaan,
|
||||
lakiLaki: this.form.lakiLaki,
|
||||
perempuan: this.form.perempuan,
|
||||
};
|
||||
|
||||
const cek = templateDemografiPekerjaan.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/ekonomi/demografipekerjaan/${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 demografiPekerjaan.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Update error:", error);
|
||||
toast.error("Gagal update data demografi pekerjaan");
|
||||
throw error;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
demografiPekerjaan.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/demografipekerjaan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Demografi pekerjaan berhasil dihapus"
|
||||
);
|
||||
await demografiPekerjaan.findMany.load();
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus demografi pekerjaan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus persentase kelahiran");
|
||||
} finally {
|
||||
demografiPekerjaan.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
export default demografiPekerjaan
|
||||
@@ -0,0 +1,180 @@
|
||||
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 templateJumlahPendudukMiskin = z.object({
|
||||
year: z.number().min(1, "Data tahun harus diisi"),
|
||||
totalPoorPopulation: z.number().min(1, "Data total penduduk miskin harus diisi"),
|
||||
});
|
||||
|
||||
type JumlahPendudukMiskin = Prisma.GrafikJumlahPendudukMiskinGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
year: true;
|
||||
totalPoorPopulation: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const defaultForm: Omit<JumlahPendudukMiskin, 'id'> & { id?: string } = {
|
||||
year: 0,
|
||||
totalPoorPopulation: 0,
|
||||
};
|
||||
|
||||
const jumlahPendudukMiskin = proxy({
|
||||
create: {
|
||||
form: defaultForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateJumlahPendudukMiskin.safeParse(
|
||||
jumlahPendudukMiskin.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
jumlahPendudukMiskin.create.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.jumlahpendudukmiskin[
|
||||
"create"
|
||||
].post(jumlahPendudukMiskin.create.form);
|
||||
if (res.status === 200) {
|
||||
const id = res.data?.data?.id;
|
||||
if (id) {
|
||||
toast.success("Success create");
|
||||
jumlahPendudukMiskin.create.form = {
|
||||
year: 0,
|
||||
totalPoorPopulation: 0,
|
||||
};
|
||||
jumlahPendudukMiskin.findMany.load();
|
||||
return id;
|
||||
}
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
jumlahPendudukMiskin.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.GrafikJumlahPendudukMiskinGetPayload<{
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.GrafikJumlahPendudukMiskinGetPayload<{
|
||||
select: { id: true; year: true; totalPoorPopulation: true; };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/jumlahpendudukmiskin/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
jumlahPendudukMiskin.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
jumlahPendudukMiskin.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading grafik jumlah penduduk miskin:", error);
|
||||
jumlahPendudukMiskin.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: {...defaultForm},
|
||||
loading: false,
|
||||
async byId() {
|
||||
// Method implementation if needed
|
||||
},
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
const cek = templateJumlahPendudukMiskin.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues.map((v) => (v.path as string[]).join(".")).join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return null;
|
||||
}
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/jumlahpendudukmiskin/${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 jumlahPendudukMiskin.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Error update data grafik jumlah penduduk miskin:", error);
|
||||
toast.error("Gagal update data grafik jumlah penduduk miskin");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
jumlahPendudukMiskin.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/ekonomi/jumlahpendudukmiskin/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Grafik jumlah penduduk miskin berhasil dihapus");
|
||||
await jumlahPendudukMiskin.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus grafik jumlah penduduk miskin");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete grafik jumlah penduduk miskin:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus grafik jumlah penduduk miskin");
|
||||
} finally {
|
||||
jumlahPendudukMiskin.delete.loading = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
export default jumlahPendudukMiskin
|
||||
|
||||
|
||||
243
src/app/admin/(dashboard)/_state/ekonomi/jumlah-pengangguran.ts
Normal file
@@ -0,0 +1,243 @@
|
||||
/* 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 templateJumlahPengngguran = z.object({
|
||||
month: z.string().min(1, "Bulan harus diisi"),
|
||||
year: z.number().min(1, "Tahun harus diisi"),
|
||||
totalUnemployment: z.number().min(1, "Total pengangguran harus diisi"),
|
||||
educatedUnemployment: z
|
||||
.number()
|
||||
.min(1, "Pengangguran pendidikan harus diisi"),
|
||||
uneducatedUnemployment: z
|
||||
.number()
|
||||
.min(1, "Pengangguran tidak pendidikan harus diisi"),
|
||||
percentageChange: z.number().min(0, "Persentase perubahan harus diisi"),
|
||||
});
|
||||
|
||||
type JumlahPengangguran = {
|
||||
month: string;
|
||||
year: number;
|
||||
totalUnemployment: number;
|
||||
educatedUnemployment: number;
|
||||
uneducatedUnemployment: number;
|
||||
percentageChange: number;
|
||||
};
|
||||
|
||||
const jumlahPengangguranForm: JumlahPengangguran = {
|
||||
month: "",
|
||||
year: 0,
|
||||
totalUnemployment: 0,
|
||||
educatedUnemployment: 0,
|
||||
uneducatedUnemployment: 0,
|
||||
percentageChange: 0,
|
||||
};
|
||||
|
||||
const jumlahPengangguran = proxy({
|
||||
findByMonthYear: {
|
||||
data: null as any,
|
||||
loading: false,
|
||||
load: async ({ month, year }: { month: string; year: number }) => {
|
||||
jumlahPengangguran.findByMonthYear.loading = true;
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/jumlahpengangguran/detaildatapengangguran/month/${month}/year/${year}`
|
||||
);
|
||||
const json = await res.json();
|
||||
jumlahPengangguran.findByMonthYear.data = json.data;
|
||||
return json.data;
|
||||
} catch (err) {
|
||||
console.error("Gagal ambil data bulan/tahun:", err);
|
||||
} finally {
|
||||
jumlahPengangguran.findByMonthYear.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
create: {
|
||||
form: jumlahPengangguranForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateJumlahPengngguran.safeParse(
|
||||
jumlahPengangguran.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
jumlahPengangguran.create.loading = true;
|
||||
const res =
|
||||
await ApiFetch.api.ekonomi.jumlahpengangguran.detaildatapengangguran[
|
||||
"create"
|
||||
].post(jumlahPengangguran.create.form);
|
||||
|
||||
if (res.status === 200) {
|
||||
const id = res.data?.data?.id;
|
||||
if (id) {
|
||||
toast.success("Success create");
|
||||
jumlahPengangguran.create.form = { ...jumlahPengangguranForm };
|
||||
jumlahPengangguran.findMany.load();
|
||||
return id;
|
||||
}
|
||||
}
|
||||
toast.error("failed create");
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
return null;
|
||||
} finally {
|
||||
jumlahPengangguran.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.DetailDataPengangguranGetPayload<{
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
findUnique: {
|
||||
data: null as Prisma.DetailDataPengangguranGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/jumlahpengangguran/detaildatapengangguran/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
jumlahPengangguran.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch jumlahPengangguran:", res.statusText);
|
||||
jumlahPengangguran.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching jumlahPengangguran:", error);
|
||||
jumlahPengangguran.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...jumlahPengangguranForm },
|
||||
loading: false,
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
const formData = {
|
||||
month: this.form.month,
|
||||
year: this.form.year,
|
||||
totalUnemployment: this.form.totalUnemployment,
|
||||
educatedUnemployment: this.form.educatedUnemployment,
|
||||
uneducatedUnemployment: this.form.uneducatedUnemployment,
|
||||
percentageChange: this.form.percentageChange,
|
||||
};
|
||||
|
||||
const cek = templateJumlahPengngguran.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/ekonomi/jumlahpengangguran/detaildatapengangguran/${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 jumlahPengangguran.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Update error:", error);
|
||||
toast.error("Gagal update data jumlah pengangguran");
|
||||
throw error;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
jumlahPengangguran.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/jumlahpengangguran/detaildatapengangguran/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Jumlah pengangguran berhasil dihapus"
|
||||
);
|
||||
await jumlahPengangguran.findMany.load();
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus jumlah pengangguran");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus jumlah pengangguran");
|
||||
} finally {
|
||||
jumlahPengangguran.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const jumlahPengangguranState = proxy({
|
||||
jumlahPengangguran,
|
||||
});
|
||||
|
||||
export default jumlahPengangguranState;
|
||||
225
src/app/admin/(dashboard)/_state/ekonomi/lowongan-kerja.ts
Normal file
@@ -0,0 +1,225 @@
|
||||
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({
|
||||
posisi: z.string(),
|
||||
namaPerusahaan: z.string(),
|
||||
lokasi: z.string(),
|
||||
tipePekerjaan: z.string(),
|
||||
gaji: z.string(),
|
||||
deskripsi: z.string(),
|
||||
kualifikasi: z.string(),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
posisi: "",
|
||||
namaPerusahaan: "",
|
||||
lokasi: "",
|
||||
tipePekerjaan: "",
|
||||
gaji: "",
|
||||
deskripsi: "",
|
||||
kualifikasi: "",
|
||||
};
|
||||
|
||||
const lowonganKerjaState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(lowonganKerjaState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
lowonganKerjaState.create.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.lowongankerja["create"].post(
|
||||
lowonganKerjaState.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
lowonganKerjaState.create.loading = false;
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
lowonganKerjaState.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
lowonganKerjaState.create.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.LowonganPekerjaanGetPayload<{
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.LowonganPekerjaanGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/ekonomi/lowongankerja/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
lowonganKerjaState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
lowonganKerjaState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
lowonganKerjaState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
lowonganKerjaState.delete.loading = true;
|
||||
const response = await fetch(`/api/ekonomi/lowongankerja/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Lowongan kerja berhasil dihapus");
|
||||
await lowonganKerjaState.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus lowongan kerja");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error deleting data:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus lowongan kerja");
|
||||
} finally {
|
||||
lowonganKerjaState.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/ekonomi/lowongankerja/${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 = {
|
||||
posisi: data.posisi,
|
||||
namaPerusahaan: data.namaPerusahaan,
|
||||
lokasi: data.lokasi,
|
||||
tipePekerjaan: data.tipePekerjaan,
|
||||
gaji: data.gaji,
|
||||
deskripsi: data.deskripsi,
|
||||
kualifikasi: data.kualifikasi,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(
|
||||
result?.message || "Gagal memuat data lowongan kerja"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(lowonganKerjaState.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
lowonganKerjaState.update.loading = true;
|
||||
const response = await fetch(`/api/ekonomi/lowongankerja/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
posisi: this.form.posisi,
|
||||
namaPerusahaan: this.form.namaPerusahaan,
|
||||
lokasi: this.form.lokasi,
|
||||
tipePekerjaan: this.form.tipePekerjaan,
|
||||
gaji: this.form.gaji,
|
||||
deskripsi: this.form.deskripsi,
|
||||
kualifikasi: this.form.kualifikasi,
|
||||
}),
|
||||
});
|
||||
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 lowongan kerja");
|
||||
await lowonganKerjaState.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update lowongan kerja");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating data:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Terjadi kesalahan saat mengupdate lowongan kerja");
|
||||
return false;
|
||||
} finally {
|
||||
lowonganKerjaState.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
lowonganKerjaState.update.id = "";
|
||||
lowonganKerjaState.update.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default lowonganKerjaState;
|
||||
@@ -0,0 +1,468 @@
|
||||
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 templatePasarDesaForm = z.object({
|
||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
harga: z.number().min(1, "Harga minimal 1"),
|
||||
alamatUsaha: z.string().min(1, "Alamat minimal 1 karakter"),
|
||||
imageId: z.string().min(1, "Gambar wajib dipilih"),
|
||||
rating: z.number().min(1, "Rating minimal 1"),
|
||||
kategoriId: z.array(z.string()).min(1, "Minimal pilih satu kategori"),
|
||||
});
|
||||
|
||||
const defaultPasarDesaForm = {
|
||||
nama: "",
|
||||
harga: 0,
|
||||
alamatUsaha: "",
|
||||
imageId: "",
|
||||
rating: 0,
|
||||
kategoriId: [] as string[],
|
||||
};
|
||||
|
||||
const pasarDesa = proxy({
|
||||
create: {
|
||||
form: { ...defaultPasarDesaForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templatePasarDesaForm.safeParse(pasarDesa.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
pasarDesa.create.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.pasardesa["create"].post(
|
||||
pasarDesa.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
pasarDesa.findMany.load();
|
||||
return toast.success("Data berhasil ditambahkan");
|
||||
}
|
||||
return toast.error("Gagal menambahkan data");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error("Gagal menambahkan data");
|
||||
} finally {
|
||||
pasarDesa.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PasarDesaGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
KategoriToPasar: {
|
||||
include: {
|
||||
kategori: true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/ekonomi/pasardesa/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
pasarDesa.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
pasarDesa.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
pasarDesa.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
pasarDesa.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/ekonomi/pasardesa/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Pasar desa berhasil dihapus");
|
||||
await pasarDesa.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus pasar desa");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus pasar desa");
|
||||
} finally {
|
||||
pasarDesa.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultPasarDesaForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/ekonomi/pasardesa/${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,
|
||||
harga: data.harga,
|
||||
alamatUsaha: data.alamatUsaha,
|
||||
imageId: data.imageId,
|
||||
rating: data.rating,
|
||||
kategoriId: data.kategoriId,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading pasar desa:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templatePasarDesaForm.safeParse(pasarDesa.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
pasarDesa.edit.loading = true;
|
||||
const response = await fetch(`/api/ekonomi/pasardesa/${this.id}`, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: this.form.nama,
|
||||
harga: this.form.harga,
|
||||
alamatUsaha: this.form.alamatUsaha,
|
||||
imageId: this.form.imageId,
|
||||
rating: this.form.rating,
|
||||
kategoriId: this.form.kategoriId,
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
toast.success("Berhasil update pasar desa");
|
||||
await pasarDesa.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate pasar desa");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating pasar desa:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal mengupdate pasar desa"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
pasarDesa.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
pasarDesa.edit.id = "";
|
||||
pasarDesa.edit.form = { ...defaultPasarDesaForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// ========================================= KATEGORI PRODUK ========================================= //
|
||||
const kategoriProdukForm = z.object({
|
||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
});
|
||||
|
||||
const kategoriProdukDefaultForm = {
|
||||
nama: "",
|
||||
};
|
||||
|
||||
const kategoriProduk = proxy({
|
||||
create: {
|
||||
form: { ...kategoriProdukDefaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = kategoriProdukForm.safeParse(kategoriProduk.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
kategoriProduk.create.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.kategoriproduk["create"].post(
|
||||
kategoriProduk.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
kategoriProduk.findMany.load();
|
||||
return toast.success("Data berhasil ditambahkan");
|
||||
}
|
||||
return toast.error("Gagal menambahkan data");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error("Gagal menambahkan data");
|
||||
} finally {
|
||||
kategoriProduk.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.KategoriProdukGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/ekonomi/kategoriproduk/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
kategoriProduk.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
kategoriProduk.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
kategoriProduk.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
kategoriProduk.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/ekonomi/kategoriproduk/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Kategori produk berhasil dihapus");
|
||||
await kategoriProduk.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus kategori produk");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus kategori produk");
|
||||
} finally {
|
||||
kategoriProduk.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...kategoriProdukDefaultForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/ekonomi/kategoriproduk/${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,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading kategori produk:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = kategoriProdukForm.safeParse(kategoriProduk.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
kategoriProduk.edit.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/kategoriproduk/${kategoriProduk.edit.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: kategoriProduk.edit.form.nama,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
// Clone the response to avoid 'body already read' error
|
||||
const responseClone = response.clone();
|
||||
|
||||
try {
|
||||
const result = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
console.error(
|
||||
"Update failed with status:",
|
||||
response.status,
|
||||
"Response:",
|
||||
result
|
||||
);
|
||||
throw new Error(
|
||||
result?.message ||
|
||||
`Gagal mengupdate kategori produk (${response.status})`
|
||||
);
|
||||
}
|
||||
|
||||
if (result.success) {
|
||||
toast.success(
|
||||
result.message || "Berhasil memperbarui kategori produk"
|
||||
);
|
||||
await kategoriProduk.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(
|
||||
result.message || "Gagal mengupdate kategori produk"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
// If JSON parsing fails, try to get the response text for better error messages
|
||||
try {
|
||||
const text = await responseClone.text();
|
||||
console.error("Error response text:", text);
|
||||
throw new Error(`Gagal memproses respons dari server: ${text}`);
|
||||
} catch (textError) {
|
||||
console.error("Error parsing response as text:", textError);
|
||||
console.error("Original error:", error);
|
||||
throw new Error("Gagal memproses respons dari server");
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating kategori produk:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal mengupdate kategori produk"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
kategoriProduk.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
kategoriProduk.edit.id = "";
|
||||
kategoriProduk.edit.form = { ...kategoriProdukDefaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const pasarDesaState = proxy({
|
||||
pasarDesa,
|
||||
kategoriProduk,
|
||||
});
|
||||
export default pasarDesaState;
|
||||
249
src/app/admin/(dashboard)/_state/ekonomi/program-kemiskinan.ts
Normal file
@@ -0,0 +1,249 @@
|
||||
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({
|
||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||
ikonUrl: z.string().optional(),
|
||||
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: "",
|
||||
statistik: {
|
||||
tahun: "",
|
||||
jumlah: ""
|
||||
}
|
||||
};
|
||||
|
||||
const programKemiskinanState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(programKemiskinanState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
programKemiskinanState.create.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.programkemiskinan["create"].post(
|
||||
programKemiskinanState.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
programKemiskinanState.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return toast.error("failed create");
|
||||
} finally {
|
||||
programKemiskinanState.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: [] as Prisma.ProgramKemiskinanGetPayload<{
|
||||
include: {
|
||||
statistik: true;
|
||||
};
|
||||
}>[],
|
||||
loading: false,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ekonomi.programkemiskinan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
programKemiskinanState.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.ProgramKemiskinanGetPayload<{
|
||||
include: {
|
||||
statistik: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/ekonomi/programkemiskinan/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
programKemiskinanState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
programKemiskinanState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
programKemiskinanState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
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/ekonomi/programkemiskinan/${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,
|
||||
deskripsi: data.deskripsi,
|
||||
ikonUrl: data.ikonUrl || "",
|
||||
statistik: {
|
||||
tahun: data.statistik.tahun,
|
||||
jumlah: data.statistik.jumlah,
|
||||
},
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading program kemiskinan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(programKemiskinanState.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
programKemiskinanState.update.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/programkemiskinan/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: this.form.nama,
|
||||
deskripsi: this.form.deskripsi,
|
||||
ikonUrl: this.form.ikonUrl,
|
||||
statistik: {
|
||||
tahun: this.form.statistik.tahun,
|
||||
jumlah: this.form.statistik.jumlah,
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
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 program kemiskinan");
|
||||
await programKemiskinanState.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update program kemiskinan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating program kemiskinan:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update program kemiskinan"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
programKemiskinanState.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
programKemiskinanState.update.id = "";
|
||||
programKemiskinanState.update.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async delete(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
programKemiskinanState.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/programkemiskinan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Program kemiskinan berhasil dihapus"
|
||||
);
|
||||
await programKemiskinanState.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus program kemiskinan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus program kemiskinan");
|
||||
} finally {
|
||||
programKemiskinanState.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default programKemiskinanState;
|
||||
202
src/app/admin/(dashboard)/_state/ekonomi/sektor-unggulan-desa.ts
Normal file
@@ -0,0 +1,202 @@
|
||||
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 templateGrafikSektorUnggulan = z.object({
|
||||
name: z.string().min(2, "Nama harus diisi"),
|
||||
description: z.string().min(2, "Deskripsi harus diisi"),
|
||||
value: z.number().min(1, "Nilai harus diisi"),
|
||||
});
|
||||
|
||||
interface SektorUnggulanForm {
|
||||
id?: string;
|
||||
name: string;
|
||||
description: string;
|
||||
value: number;
|
||||
}
|
||||
|
||||
const defaultForm: SektorUnggulanForm = {
|
||||
name: "",
|
||||
description: "",
|
||||
value: 0,
|
||||
};
|
||||
|
||||
const grafikSektorUnggulan = proxy({
|
||||
create: {
|
||||
form: defaultForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateGrafikSektorUnggulan.safeParse(
|
||||
grafikSektorUnggulan.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
grafikSektorUnggulan.create.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.sektourunggulandesa[
|
||||
"create"
|
||||
].post(grafikSektorUnggulan.create.form);
|
||||
if (res.status === 200) {
|
||||
const id = res.data?.data?.id;
|
||||
if (id) {
|
||||
toast.success("Success create");
|
||||
grafikSektorUnggulan.create.form = {
|
||||
name: "",
|
||||
description: "",
|
||||
value: 0,
|
||||
};
|
||||
grafikSektorUnggulan.findMany.load();
|
||||
return id;
|
||||
}
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
grafikSektorUnggulan.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.SektorUnggulanDesaGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
name: true;
|
||||
description: true;
|
||||
value: true;
|
||||
createdAt: true;
|
||||
updatedAt: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
loading: false,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ekonomi.sektourunggulandesa[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
grafikSektorUnggulan.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.SektorUnggulanDesaGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
name: true;
|
||||
description: true;
|
||||
value: true;
|
||||
createdAt: true;
|
||||
updatedAt: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/ekonomi/sektourunggulandesa/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
grafikSektorUnggulan.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
grafikSektorUnggulan.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading grafik sektor unggulan desa:", error);
|
||||
grafikSektorUnggulan.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async byId() {
|
||||
// Method implementation if needed
|
||||
},
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
const cek = templateGrafikSektorUnggulan.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/ekonomi/sektourunggulandesa/${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 grafikSektorUnggulan.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Error update data:", error);
|
||||
toast.error("Gagal update data grafik sektor unggulan desa");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
grafikSektorUnggulan.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/sektourunggulandesa/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Grafik sektor unggulan desa berhasil dihapus"
|
||||
);
|
||||
await grafikSektorUnggulan.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus grafik sektor unggulan desa"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error(
|
||||
"Terjadi kesalahan saat menghapus grafik sektor unggulan desa"
|
||||
);
|
||||
} finally {
|
||||
grafikSektorUnggulan.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
export default grafikSektorUnggulan;
|
||||
@@ -0,0 +1,785 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
import { toast } from "react-toastify";
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
|
||||
const templatePosisiOrganisasi = z.object({
|
||||
nama: z.string().min(1, "Nama harus diisi"),
|
||||
deskripsi: z.string().optional(),
|
||||
hierarki: z.number().int().positive("Hierarki harus angka positif"),
|
||||
});
|
||||
|
||||
const posisiOrganisasiDefaultForm = {
|
||||
nama: "",
|
||||
deskripsi: "",
|
||||
hierarki: 0,
|
||||
};
|
||||
|
||||
const posisiOrganisasi = proxy({
|
||||
create: {
|
||||
form: { ...posisiOrganisasiDefaultForm },
|
||||
loading: false,
|
||||
async submit() {
|
||||
const cek = templatePosisiOrganisasi.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = cek.error.issues.map((v) => v.message).join("\n");
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
||||
"posisi-organisasi"
|
||||
]["create"].post(this.form);
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil menambahkan posisi organisasi");
|
||||
posisiOrganisasi.findMany.load();
|
||||
this.reset();
|
||||
} else {
|
||||
toast.error(res.data?.message || "Gagal menambahkan posisi");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Create error:", error);
|
||||
toast.error("Terjadi kesalahan saat menambahkan posisi");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
this.form = { ...posisiOrganisasiDefaultForm };
|
||||
},
|
||||
},
|
||||
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...posisiOrganisasiDefaultForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/struktur-organisasi/posisi-organisasi/${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,
|
||||
deskripsi: data.deskripsi,
|
||||
hierarki: data.hierarki,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading posisi organisasi:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = templatePosisiOrganisasi.safeParse(this.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/ekonomi/struktur-organisasi/posisi-organisasi/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: this.form.nama,
|
||||
deskripsi: this.form.deskripsi,
|
||||
hierarki: this.form.hierarki,
|
||||
}),
|
||||
}
|
||||
);
|
||||
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 posisi organisasi");
|
||||
await posisiOrganisasi.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(
|
||||
result.message || "Gagal mengupdate posisi organisasi"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating posisi organisasi:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal mengupdate posisi organisasi"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
this.id = "";
|
||||
this.form = { ...posisiOrganisasiDefaultForm };
|
||||
},
|
||||
},
|
||||
|
||||
findMany: {
|
||||
data: [] as Array<{
|
||||
id: string;
|
||||
nama: string;
|
||||
deskripsi: string | null;
|
||||
hierarki: number;
|
||||
}>,
|
||||
async load() {
|
||||
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 ?? [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Find many error:", error);
|
||||
this.data = [];
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
posisiOrganisasi.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/struktur-organisasi/posisi-organisasi/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Posisi organisasi berhasil dihapus");
|
||||
await posisiOrganisasi.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus posisi organisasi");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus posisi organisasi");
|
||||
} finally {
|
||||
posisiOrganisasi.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const templatePegawai = z.object({
|
||||
namaLengkap: z.string().min(1, "Nama wajib diisi"),
|
||||
gelarAkademik: z.string().optional(),
|
||||
imageId: z.string().nullable().optional(),
|
||||
tanggalMasuk: z.string().optional(), // ISO format
|
||||
email: z.string().email("Email tidak valid").optional(),
|
||||
telepon: z.string().optional(),
|
||||
alamat: z.string().optional(),
|
||||
posisiId: z.string().min(1, "Posisi wajib diisi"),
|
||||
isActive: z.boolean().default(true),
|
||||
});
|
||||
|
||||
const pegawaiDefaultForm = {
|
||||
namaLengkap: "",
|
||||
gelarAkademik: "",
|
||||
imageId: "",
|
||||
tanggalMasuk: "",
|
||||
email: "",
|
||||
telepon: "",
|
||||
alamat: "",
|
||||
posisiId: "",
|
||||
isActive: true,
|
||||
};
|
||||
|
||||
const pegawai = proxy({
|
||||
create: {
|
||||
form: { ...pegawaiDefaultForm },
|
||||
loading: false,
|
||||
async submit() {
|
||||
const cek = templatePegawai.safeParse(pegawai.create.form);
|
||||
if (!cek.success) {
|
||||
const err = cek.error.issues.map((i) => i.message).join("\n");
|
||||
toast.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
pegawai.create.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
||||
"pegawai"
|
||||
]["create"].post(pegawai.create.form);
|
||||
if (res.status === 200) {
|
||||
toast.success("Pegawai berhasil ditambahkan");
|
||||
await pegawai.findMany.load();
|
||||
} else {
|
||||
toast.error(res.data?.message ?? "Gagal tambah pegawai");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal create:", error);
|
||||
toast.error("Terjadi kesalahan saat menambahkan pegawai");
|
||||
} finally {
|
||||
pegawai.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// In struktur-organisasi.ts
|
||||
findMany: {
|
||||
data: null as any[] | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
total: 0,
|
||||
loading: false,
|
||||
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||
pegawai.findMany.loading = true; // Use the full path to access the property
|
||||
pegawai.findMany.page = page;
|
||||
try {
|
||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
||||
"pegawai"
|
||||
]["find-many"].get({
|
||||
query: { page, limit },
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pegawai.findMany.data = res.data.data || [];
|
||||
pegawai.findMany.total = res.data.total || 0;
|
||||
pegawai.findMany.totalPages = res.data.totalPages || 1;
|
||||
} else {
|
||||
console.error("Failed to load pegawai:", res.data?.message);
|
||||
pegawai.findMany.data = [];
|
||||
pegawai.findMany.total = 0;
|
||||
pegawai.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading pegawai:", error);
|
||||
pegawai.findMany.data = [];
|
||||
pegawai.findMany.total = 0;
|
||||
pegawai.findMany.totalPages = 1;
|
||||
} finally {
|
||||
pegawai.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as
|
||||
| (Prisma.PegawaiGetPayload<{
|
||||
include: { posisi: true; image: true };
|
||||
}> & { isActive: boolean })
|
||||
| null,
|
||||
async load(id: string) {
|
||||
const res = await fetch(`/api/ekonomi/struktur-organisasi/pegawai/${id}`);
|
||||
if (res.ok) {
|
||||
const json = await res.json();
|
||||
pegawai.findUnique.data = json.data
|
||||
? {
|
||||
...json.data,
|
||||
isActive: json.data.isActive ?? json.data.aktif ?? true, // Fallback ke aktif:true jika tidak ada data
|
||||
}
|
||||
: null;
|
||||
} else {
|
||||
pegawai.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
pegawai.delete.loading = true;
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/struktur-organisasi/pegawai/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
}
|
||||
);
|
||||
const json = await res.json();
|
||||
if (res.ok) {
|
||||
toast.success(json.message ?? "Berhasil hapus pegawai");
|
||||
await pegawai.findMany.load();
|
||||
} else {
|
||||
toast.error(json.message ?? "Gagal hapus pegawai");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus");
|
||||
} finally {
|
||||
pegawai.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...pegawaiDefaultForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/struktur-organisasi/pegawai/${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 = {
|
||||
namaLengkap: data.namaLengkap,
|
||||
gelarAkademik: data.gelarAkademik,
|
||||
imageId: data.imageId,
|
||||
tanggalMasuk: data.tanggalMasuk,
|
||||
email: data.email,
|
||||
telepon: data.telepon,
|
||||
alamat: data.alamat,
|
||||
posisiId: data.posisiId,
|
||||
isActive: data.isActive,
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading berita:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async submit() {
|
||||
const cek = templatePegawai.safeParse(pegawai.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
pegawai.edit.loading = true;
|
||||
|
||||
// Format tanggalMasuk to ISO string if it exists
|
||||
const formattedTanggalMasuk = this.form.tanggalMasuk
|
||||
? new Date(this.form.tanggalMasuk).toISOString()
|
||||
: undefined;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/ekonomi/struktur-organisasi/pegawai/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: this.id,
|
||||
namaLengkap: this.form.namaLengkap,
|
||||
gelarAkademik: this.form.gelarAkademik,
|
||||
imageId: this.form.imageId || null,
|
||||
tanggalMasuk: formattedTanggalMasuk,
|
||||
email: this.form.email,
|
||||
telepon: this.form.telepon,
|
||||
alamat: this.form.alamat,
|
||||
posisiId: this.form.posisiId,
|
||||
isActive: this.form.isActive,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
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 pegawai");
|
||||
await pegawai.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update pegawai");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating pegawai:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update pegawai"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
pegawai.edit.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
reset() {
|
||||
pegawai.edit.id = "";
|
||||
pegawai.edit.form = { ...pegawaiDefaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Schema Zod untuk form validasi
|
||||
const templateHubunganOrganisasiForm = z.object({
|
||||
atasanId: z.string().min(1, "Atasan wajib dipilih"),
|
||||
bawahanId: z.string().min(1, "Bawahan wajib dipilih"),
|
||||
tipe: z.string().optional(),
|
||||
});
|
||||
|
||||
// Default form state
|
||||
const defaultHubunganOrganisasiForm = {
|
||||
atasanId: "",
|
||||
bawahanId: "",
|
||||
tipe: "",
|
||||
};
|
||||
|
||||
// ====================== STATE ===========================
|
||||
const hubunganOrganisasi = proxy({
|
||||
create: {
|
||||
form: { ...defaultHubunganOrganisasiForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateHubunganOrganisasiForm.safeParse(
|
||||
hubunganOrganisasi.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}: ${v.message}`)
|
||||
.join("\n")}]`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
hubunganOrganisasi.create.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
||||
"hubungan-organisasi"
|
||||
]["create"].post(hubunganOrganisasi.create.form);
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
hubunganOrganisasi.findMany.load();
|
||||
return toast.success("Berhasil menambahkan hubungan organisasi");
|
||||
} else {
|
||||
return toast.error(res.data?.message || "Gagal menambahkan data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal create:", error);
|
||||
toast.error("Terjadi kesalahan saat menambahkan");
|
||||
} finally {
|
||||
hubunganOrganisasi.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<{
|
||||
id: string;
|
||||
atasanId: string;
|
||||
bawahanId: string;
|
||||
tipe?: string | null;
|
||||
atasan: {
|
||||
id: string;
|
||||
namaLengkap: string;
|
||||
gelarAkademik: string | null;
|
||||
imageId: string | null;
|
||||
tanggalMasuk: Date | null;
|
||||
email: string | null;
|
||||
telepon: string | null;
|
||||
alamat: string | null;
|
||||
posisiId: string;
|
||||
isActive: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
bawahan: {
|
||||
id: string;
|
||||
namaLengkap: string;
|
||||
gelarAkademik: string | null;
|
||||
imageId: string | null;
|
||||
tanggalMasuk: Date | null;
|
||||
email: string | null;
|
||||
telepon: string | null;
|
||||
alamat: string | null;
|
||||
posisiId: string;
|
||||
isActive: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
}> | null,
|
||||
|
||||
async load() {
|
||||
try {
|
||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
||||
"hubungan-organisasi"
|
||||
]["find-many"].get();
|
||||
|
||||
if (res.status === 200) {
|
||||
hubunganOrganisasi.findMany.data = (res.data?.data ?? []).map(
|
||||
(item: any) => ({
|
||||
...item,
|
||||
atasan: item.atasan
|
||||
? {
|
||||
...item.atasan,
|
||||
isActive: item.atasan.isActive ?? item.atasan.aktif ?? true,
|
||||
}
|
||||
: null,
|
||||
bawahan: item.bawahan
|
||||
? {
|
||||
...item.bawahan,
|
||||
isActive:
|
||||
item.bawahan.isActive ?? item.bawahan.aktif ?? true,
|
||||
}
|
||||
: null,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
hubunganOrganisasi.findMany.data = [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fetch list error:", error);
|
||||
toast.error("Gagal memuat data hubungan organisasi");
|
||||
hubunganOrganisasi.findMany.data = [];
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
findUnique: {
|
||||
data: null as {
|
||||
id: string;
|
||||
atasanId: string;
|
||||
bawahanId: string;
|
||||
tipe?: string | null;
|
||||
atasan?: {
|
||||
id: string;
|
||||
namaLengkap: string;
|
||||
gelarAkademik: string | null;
|
||||
imageId: string;
|
||||
tanggalMasuk: Date | null;
|
||||
email: string | null;
|
||||
telepon: string | null;
|
||||
alamat: string | null;
|
||||
posisiId: string;
|
||||
aktif: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
bawahan?: {
|
||||
id: string;
|
||||
namaLengkap: string;
|
||||
gelarAkademik: string | null;
|
||||
imageId: string;
|
||||
tanggalMasuk: Date | null;
|
||||
email: string | null;
|
||||
telepon: string | null;
|
||||
alamat: string | null;
|
||||
posisiId: string;
|
||||
aktif: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
} | null,
|
||||
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/struktur-organisasi/hubungan-organisasi/${id}`
|
||||
);
|
||||
const result = await res.json();
|
||||
|
||||
if (res.ok && result?.success) {
|
||||
hubunganOrganisasi.findUnique.data = result.data;
|
||||
} else {
|
||||
hubunganOrganisasi.findUnique.data = null;
|
||||
toast.error(result?.message || "Gagal mengambil data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Find unique error:", error);
|
||||
hubunganOrganisasi.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultHubunganOrganisasiForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/struktur-organisasi/hubungan-organisasi/${id}`
|
||||
);
|
||||
const result = await res.json();
|
||||
|
||||
if (res.ok && result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
atasanId: data.atasanId,
|
||||
bawahanId: data.bawahanId,
|
||||
tipe: data.tipe || "",
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateHubunganOrganisasiForm.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}: ${v.message}`)
|
||||
.join("\n")}]`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/struktur-organisasi/hubungan-organisasi/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(this.form),
|
||||
}
|
||||
);
|
||||
|
||||
const result = await res.json();
|
||||
if (res.ok && result.success) {
|
||||
await hubunganOrganisasi.findMany.load();
|
||||
toast.success("Berhasil mengupdate hubungan organisasi");
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal mengupdate");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Update error:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Gagal update");
|
||||
return false;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
reset() {
|
||||
hubunganOrganisasi.edit.id = "";
|
||||
hubunganOrganisasi.edit.form = { ...defaultHubunganOrganisasiForm };
|
||||
},
|
||||
},
|
||||
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
hubunganOrganisasi.delete.loading = true;
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/struktur-organisasi/hubungan-organisasi/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
}
|
||||
);
|
||||
|
||||
const result = await res.json();
|
||||
if (res.ok && result?.success) {
|
||||
toast.success("Hubungan organisasi berhasil dihapus");
|
||||
hubunganOrganisasi.findMany.load();
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus hubungan organisasi");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Delete error:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus");
|
||||
} finally {
|
||||
hubunganOrganisasi.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const strukturorganisasiState = proxy({
|
||||
posisiOrganisasi,
|
||||
pegawai,
|
||||
hubunganOrganisasi,
|
||||
});
|
||||
|
||||
export default strukturorganisasiState;
|
||||
376
src/app/admin/(dashboard)/_state/ekonomi/usia-kerja-nganggur.ts
Normal file
@@ -0,0 +1,376 @@
|
||||
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 templateGrafikUsiaKerjaYangMenganggur = z.object({
|
||||
usia18_25: z.string().min(1, "Data usia 18-25 harus diisi"),
|
||||
usia26_35: z.string().min(1, "Data usia 26-35 harus diisi"),
|
||||
usia36_45: z.string().min(1, "Data usia 36-45 harus diisi"),
|
||||
usia46_keatas: z.string().min(1, "Data usia 46 keatas harus diisi"),
|
||||
});
|
||||
|
||||
type GrafikUsiaKerjaYangMenganggur = Prisma.GrafikMenganggurBerdasarkanUsiaGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
usia18_25: true;
|
||||
usia26_35: true;
|
||||
usia36_45: true;
|
||||
usia46_keatas: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const defaultForm: Omit<GrafikUsiaKerjaYangMenganggur, 'id'> & { id?: string } = {
|
||||
usia18_25: "",
|
||||
usia26_35: "",
|
||||
usia36_45: "",
|
||||
usia46_keatas: "",
|
||||
};
|
||||
|
||||
const grafikBerdasarkanUsiaKerjaNganggur = proxy({
|
||||
create: {
|
||||
form: defaultForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateGrafikUsiaKerjaYangMenganggur.safeParse(
|
||||
grafikBerdasarkanUsiaKerjaNganggur.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
grafikBerdasarkanUsiaKerjaNganggur.create.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.grafikusiakerjayangmenganggur[
|
||||
"create"
|
||||
].post(grafikBerdasarkanUsiaKerjaNganggur.create.form);
|
||||
if (res.status === 200) {
|
||||
const id = res.data?.data?.id;
|
||||
if (id) {
|
||||
toast.success("Success create");
|
||||
grafikBerdasarkanUsiaKerjaNganggur.create.form = {
|
||||
usia18_25: "",
|
||||
usia26_35: "",
|
||||
usia36_45: "",
|
||||
usia46_keatas: "",
|
||||
};
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.load();
|
||||
return id;
|
||||
}
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
grafikBerdasarkanUsiaKerjaNganggur.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.GrafikMenganggurBerdasarkanUsiaGetPayload<{
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.GrafikMenganggurBerdasarkanUsiaGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/grafikusiakerjayangmenganggur/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading grafik berdasarkan usia kerja yang menganggur:", error);
|
||||
grafikBerdasarkanUsiaKerjaNganggur.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: {...defaultForm},
|
||||
loading: false,
|
||||
async byId() {
|
||||
// Method implementation if needed
|
||||
},
|
||||
async submit() {
|
||||
const id = this.id;
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
const cek = templateGrafikUsiaKerjaYangMenganggur.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/ekonomi/grafikusiakerjayangmenganggur/${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 grafikBerdasarkanUsiaKerjaNganggur.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Error update data:", error);
|
||||
toast.error("Gagal update data grafik berdasarkan usia kerja yang menganggur");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
grafikBerdasarkanUsiaKerjaNganggur.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/ekonomi/grafikusiakerjayangmenganggur/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Grafik berdasarkan usia kerja yang menganggur berhasil dihapus");
|
||||
await grafikBerdasarkanUsiaKerjaNganggur.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus grafik berdasarkan usia kerja yang menganggur");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus grafik berdasarkan usia kerja yang menganggur");
|
||||
} finally {
|
||||
grafikBerdasarkanUsiaKerjaNganggur.delete.loading = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
const templateGrafikBerpendidikanYangMenganggur = z.object({
|
||||
SD: z.string().min(1, "Data SD harus diisi"),
|
||||
SMP: z.string().min(1, "Data SMP harus diisi"),
|
||||
SMA: z.string().min(1, "Data SMA harus diisi"),
|
||||
D3: z.string().min(1, "Data D3 harus diisi"),
|
||||
S1: z.string().min(1, "Data S1 harus diisi"),
|
||||
});
|
||||
|
||||
type GrafikBerpendidikanYangMenganggur = Prisma.GrafikMenganggurBerdasarkanPendidikanGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
SD: true;
|
||||
SMP: true;
|
||||
SMA: true;
|
||||
D3: true;
|
||||
S1: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const defaultFormBerpendidikan: Omit<GrafikBerpendidikanYangMenganggur, 'id'> & { id?: string } = {
|
||||
SD: "",
|
||||
SMP: "",
|
||||
SMA: "",
|
||||
D3: "",
|
||||
S1: "",
|
||||
};
|
||||
|
||||
const grafikBerdasarkanPendidikan = proxy({
|
||||
create: {
|
||||
form: defaultFormBerpendidikan,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateGrafikBerpendidikanYangMenganggur.safeParse(
|
||||
grafikBerdasarkanPendidikan.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
grafikBerdasarkanPendidikan.create.loading = true;
|
||||
const res = await ApiFetch.api.ekonomi.grafikmenganggurberdasarkanpendidikan[
|
||||
"create"
|
||||
].post(grafikBerdasarkanPendidikan.create.form);
|
||||
if (res.status === 200) {
|
||||
const id = res.data?.data?.id;
|
||||
if (id) {
|
||||
toast.success("Success create");
|
||||
grafikBerdasarkanPendidikan.create.form = {
|
||||
SD: "",
|
||||
SMP: "",
|
||||
SMA: "",
|
||||
D3: "",
|
||||
S1: "",
|
||||
};
|
||||
grafikBerdasarkanPendidikan.findMany.load();
|
||||
return id;
|
||||
}
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
grafikBerdasarkanPendidikan.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.GrafikMenganggurBerdasarkanPendidikanGetPayload<{
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.GrafikMenganggurBerdasarkanPendidikanGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/ekonomi/grafikmenganggurberdasarkanpendidikan/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
grafikBerdasarkanPendidikan.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
grafikBerdasarkanPendidikan.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading grafik berdasarkan usia kerja yang menganggur:", error);
|
||||
grafikBerdasarkanPendidikan.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: {...defaultFormBerpendidikan},
|
||||
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 = templateGrafikBerpendidikanYangMenganggur.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/ekonomi/grafikmenganggurberdasarkanpendidikan/${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 grafikBerdasarkanPendidikan.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Error update data:", error);
|
||||
toast.error("Gagal update data grafik berdasarkan pendidikan yang menganggur");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
grafikBerdasarkanPendidikan.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/ekonomi/grafikmenganggurberdasarkanpendidikan/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Grafik berdasarkan pendidikan yang menganggur berhasil dihapus");
|
||||
await grafikBerdasarkanPendidikan.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus grafik berdasarkan pendidikan yang menganggur");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus grafik berdasarkan pendidikan yang menganggur");
|
||||
} finally {
|
||||
grafikBerdasarkanPendidikan.delete.loading = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
const grafikNganggur = proxy({
|
||||
grafikBerdasarkanUsiaKerjaNganggur,
|
||||
grafikBerdasarkanPendidikan
|
||||
})
|
||||
|
||||
export default grafikNganggur;
|
||||
123
src/app/admin/(dashboard)/_state/inovasi/ajukan-ide-inovatif.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
deskripsi: z.string().min(1).max(5000),
|
||||
alamat: z.string().min(1).max(5000),
|
||||
namaIde: z.string().min(1).max(5000),
|
||||
masalah: z.string().min(1).max(5000),
|
||||
benefit: z.string().min(1).max(5000),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
alamat: "",
|
||||
namaIde: "",
|
||||
masalah: "",
|
||||
benefit: "",
|
||||
};
|
||||
|
||||
const ajukanIdeInovatifState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(ajukanIdeInovatifState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
ajukanIdeInovatifState.create.loading = true;
|
||||
const res = await ApiFetch.api.inovasi.ajukanideinovatif["create"].post(
|
||||
ajukanIdeInovatifState.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
ajukanIdeInovatifState.findMany.load();
|
||||
return toast.success("Ajukan Ide Inovatif berhasil di kirim");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
ajukanIdeInovatifState.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.AjukanIdeInovatifGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.inovasi.ajukanideinovatif["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
ajukanIdeInovatifState.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.AjukanIdeInovatifGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/inovasi/ajukanideinovatif/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
ajukanIdeInovatifState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
ajukanIdeInovatifState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading ajukan ide inovatif:", error);
|
||||
ajukanIdeInovatifState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
ajukanIdeInovatifState.delete.loading = true;
|
||||
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");
|
||||
await ajukanIdeInovatifState.findMany.load();
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus ajukan ide inovatif");
|
||||
}
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat menghapus ajukan ide inovatif");
|
||||
} finally {
|
||||
ajukanIdeInovatifState.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
export default ajukanIdeInovatifState;
|
||||
216
src/app/admin/(dashboard)/_state/inovasi/desa-digital.ts
Normal file
@@ -0,0 +1,216 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
deskripsi: z.string().min(1).max(5000),
|
||||
imageId: z.string().min(1).max(50),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
imageId: "",
|
||||
};
|
||||
|
||||
const desaDigitalState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(desaDigitalState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
desaDigitalState.create.loading = true;
|
||||
const res = await ApiFetch.api.inovasi.desadigital["create"].post(
|
||||
desaDigitalState.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
desaDigitalState.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
desaDigitalState.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.DesaDigitalGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.inovasi.desadigital["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
desaDigitalState.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.DesaDigitalGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/inovasi/desadigital/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
desaDigitalState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
desaDigitalState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading desa digital:", error);
|
||||
desaDigitalState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
desaDigitalState.delete.loading = true;
|
||||
const response = await fetch(`/api/inovasi/desadigital/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
toast.success(result.message || "Desa Digital berhasil dihapus");
|
||||
await desaDigitalState.findMany.load();
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus desa digital");
|
||||
}
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat menghapus desa digital");
|
||||
} finally {
|
||||
desaDigitalState.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/inovasi/desadigital/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
deskripsi: data.deskripsi,
|
||||
imageId: data.imageId,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading desa digital:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(desaDigitalState.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
desaDigitalState.edit.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/inovasi/desadigital/${desaDigitalState.edit.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("Berhasil update desa digital");
|
||||
await desaDigitalState.findMany.load();
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal update desa digital");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating desa digital:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update desa digital"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
desaDigitalState.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
desaDigitalState.edit.id = "";
|
||||
desaDigitalState.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
export default desaDigitalState;
|
||||
216
src/app/admin/(dashboard)/_state/inovasi/info-tekno.ts
Normal file
@@ -0,0 +1,216 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
deskripsi: z.string().min(1).max(5000),
|
||||
imageId: z.string().min(1).max(50),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
imageId: "",
|
||||
};
|
||||
|
||||
const infoTeknoState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(infoTeknoState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
infoTeknoState.create.loading = true;
|
||||
const res = await ApiFetch.api.inovasi.infotekno["create"].post(
|
||||
infoTeknoState.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
infoTeknoState.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
infoTeknoState.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.InfoTeknoGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.inovasi.infotekno["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
infoTeknoState.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.InfoTeknoGetPayload<{
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/inovasi/infotekno/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
infoTeknoState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
infoTeknoState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading desa digital:", error);
|
||||
infoTeknoState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
infoTeknoState.delete.loading = true;
|
||||
const response = await fetch(`/api/inovasi/infotekno/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
toast.success(result.message || "Info Tekno berhasil dihapus");
|
||||
await infoTeknoState.findMany.load();
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus info tekno");
|
||||
}
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat menghapus info tekno");
|
||||
} finally {
|
||||
infoTeknoState.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/inovasi/infotekno/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
name: data.name,
|
||||
deskripsi: data.deskripsi,
|
||||
imageId: data.imageId,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading info tekno:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(infoTeknoState.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
infoTeknoState.edit.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/inovasi/infotekno/${infoTeknoState.edit.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("Berhasil update info tekno");
|
||||
await infoTeknoState.findMany.load();
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal update info tekno");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating info tekno:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update info tekno"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
infoTeknoState.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
infoTeknoState.edit.id = "";
|
||||
infoTeknoState.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
export default infoTeknoState;
|
||||
234
src/app/admin/(dashboard)/_state/inovasi/kolaborasi-inovasi.ts
Normal file
@@ -0,0 +1,234 @@
|
||||
/* 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, "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"),
|
||||
})
|
||||
|
||||
const defaultForm = {
|
||||
name: "",
|
||||
tahun: 0,
|
||||
slug: "",
|
||||
deskripsi: "",
|
||||
kolaborator: "",
|
||||
imageId: "",
|
||||
}
|
||||
|
||||
const kolaborasiInovasiState = proxy({
|
||||
create: {
|
||||
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 {
|
||||
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");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
kolaborasiInovasiState.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
|
||||
kolaborasiInovasiState.findMany.loading = true; // Use the full path to access the property
|
||||
kolaborasiInovasiState.findMany.page = page;
|
||||
try {
|
||||
const res = await ApiFetch.api.inovasi.kolaborasiinovasi["find-many"].get({
|
||||
query: { page, limit },
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
kolaborasiInovasiState.findMany.data = res.data.data || [];
|
||||
kolaborasiInovasiState.findMany.total = res.data.total || 0;
|
||||
kolaborasiInovasiState.findMany.totalPages = res.data.totalPages || 1;
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to load grafik berdasarkan jenis kelamin:",
|
||||
res.data?.message
|
||||
);
|
||||
kolaborasiInovasiState.findMany.data = [];
|
||||
kolaborasiInovasiState.findMany.total = 0;
|
||||
kolaborasiInovasiState.findMany.totalPages = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading grafik berdasarkan jenis kelamin:", error);
|
||||
kolaborasiInovasiState.findMany.data = [];
|
||||
kolaborasiInovasiState.findMany.total = 0;
|
||||
kolaborasiInovasiState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
kolaborasiInovasiState.findMany.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/kolaborasiinovasi/${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,
|
||||
tahun: data.tahun,
|
||||
slug: data.slug,
|
||||
deskripsi: data.deskripsi,
|
||||
kolaborator: data.kolaborator,
|
||||
imageId: data.imageId,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal mengambil data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading kolaborasi inovasi:", 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 cek = templateForm.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/inovasi/kolaborasiinovasi/${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 kolaborasiInovasiState.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Error update data:", error);
|
||||
toast.error("Gagal update data kolaborasi inovasi");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.KolaborasiInovasiGetPayload<{
|
||||
include: { image: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/inovasi/kolaborasiinovasi/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
kolaborasiInovasiState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
kolaborasiInovasiState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading kolaborasi inovasi:", error);
|
||||
kolaborasiInovasiState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
kolaborasiInovasiState.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/inovasi/kolaborasiinovasi/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Kolaborasi inovasi berhasil dihapus");
|
||||
await kolaborasiInovasiState.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus kolaborasi inovasi");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus kolaborasi inovasi");
|
||||
} finally {
|
||||
kolaborasiInovasiState.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default kolaborasiInovasiState;
|
||||
|
||||
803
src/app/admin/(dashboard)/_state/inovasi/layanan-online-desa.ts
Normal file
@@ -0,0 +1,803 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
// ========================================= ADMINISTRASI ONLINE ========================================= //
|
||||
const templateAdministrasiOnlineForm = z.object({
|
||||
name: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
alamat: z.string().min(1, "Alamat minimal 1 karakter"),
|
||||
nomorTelepon: z.string().min(1, "Nomor telepon minimal 1 karakter"),
|
||||
jenisLayananId: z.string().min(1, "Jenis layanan minimal 1 karakter"),
|
||||
});
|
||||
|
||||
const defaultAdministrasiOnlineForm = {
|
||||
name: "",
|
||||
alamat: "",
|
||||
nomorTelepon: "",
|
||||
jenisLayananId: "",
|
||||
};
|
||||
|
||||
const administrasiOnline = proxy({
|
||||
create: {
|
||||
form: { ...defaultAdministrasiOnlineForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateAdministrasiOnlineForm.safeParse(
|
||||
administrasiOnline.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
administrasiOnline.create.loading = true;
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.administrasionline[
|
||||
"create"
|
||||
].post(administrasiOnline.create.form);
|
||||
if (res.status === 200) {
|
||||
administrasiOnline.findMany.load();
|
||||
return toast.success("Data berhasil ditambahkan");
|
||||
}
|
||||
return toast.error("Gagal menambahkan data");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error("Gagal menambahkan data");
|
||||
} finally {
|
||||
administrasiOnline.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<
|
||||
Prisma.AdministrasiOnlineGetPayload<{
|
||||
include: {
|
||||
jenisLayanan: true;
|
||||
};
|
||||
}>
|
||||
> | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
|
||||
async load(page = 1, limit = 10) {
|
||||
administrasiOnline.findMany.loading = true;
|
||||
administrasiOnline.findMany.page = page;
|
||||
try {
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.administrasionline[
|
||||
"find-many"
|
||||
].get({
|
||||
query: {
|
||||
page,
|
||||
limit,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
administrasiOnline.findMany.data = res.data.data ?? [];
|
||||
administrasiOnline.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch administrasi online paginated:", err);
|
||||
} finally {
|
||||
administrasiOnline.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.AdministrasiOnlineGetPayload<{
|
||||
include: {
|
||||
jenisLayanan: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/administrasionline/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
administrasiOnline.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch administrasi online:", res.statusText);
|
||||
administrasiOnline.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching administrasi online:", error);
|
||||
administrasiOnline.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
administrasiOnline.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/administrasionline/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Administrasi online berhasil dihapus"
|
||||
);
|
||||
await administrasiOnline.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus administrasi online");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus administrasi online");
|
||||
} finally {
|
||||
administrasiOnline.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// ========================================= JENIS LAYANAN ========================================= //
|
||||
const templateJenisLayananForm = z.object({
|
||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||
});
|
||||
|
||||
const defaultJenisLayananForm = {
|
||||
nama: "",
|
||||
deskripsi: "",
|
||||
};
|
||||
|
||||
const jenisLayanan = proxy({
|
||||
create: {
|
||||
form: { ...defaultJenisLayananForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateJenisLayananForm.safeParse(jenisLayanan.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
jenisLayanan.create.loading = true;
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.administrasionline.jenislayanan[
|
||||
"create"
|
||||
].post(jenisLayanan.create.form);
|
||||
if (res.status === 200) {
|
||||
jenisLayanan.findMany.load();
|
||||
return toast.success("Data berhasil ditambahkan");
|
||||
}
|
||||
return toast.error("Gagal menambahkan data");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error("Gagal menambahkan data");
|
||||
} finally {
|
||||
jenisLayanan.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<{
|
||||
id: string;
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.JenisLayananGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/administrasionline/jenislayanan/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
jenisLayanan.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
jenisLayanan.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
jenisLayanan.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
jenisLayanan.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/administrasionline/jenislayanan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Jenis layanan berhasil dihapus");
|
||||
await jenisLayanan.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus jenis layanan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus jenis layanan");
|
||||
} finally {
|
||||
jenisLayanan.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultJenisLayananForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/administrasionline/jenislayanan/${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,
|
||||
deskripsi: data.deskripsi,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading jenis layanan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateJenisLayananForm.safeParse(jenisLayanan.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
jenisLayanan.edit.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/administrasionline/jenislayanan/${jenisLayanan.edit.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: jenisLayanan.edit.form.nama,
|
||||
deskripsi: jenisLayanan.edit.form.deskripsi,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
// Clone the response to avoid 'body already read' error
|
||||
const responseClone = response.clone();
|
||||
|
||||
try {
|
||||
const result = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
console.error(
|
||||
"Update failed with status:",
|
||||
response.status,
|
||||
"Response:",
|
||||
result
|
||||
);
|
||||
throw new Error(
|
||||
result?.message ||
|
||||
`Gagal mengupdate jenis layanan (${response.status})`
|
||||
);
|
||||
}
|
||||
|
||||
if (result.success) {
|
||||
toast.success(
|
||||
result.message || "Berhasil memperbarui jenis layanan"
|
||||
);
|
||||
await jenisLayanan.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate jenis layanan");
|
||||
}
|
||||
} catch (error) {
|
||||
// If JSON parsing fails, try to get the response text for better error messages
|
||||
try {
|
||||
const text = await responseClone.text();
|
||||
console.error("Error response text:", text);
|
||||
throw new Error(`Gagal memproses respons dari server: ${text}`);
|
||||
} catch (textError) {
|
||||
console.error("Error parsing response as text:", textError);
|
||||
console.error("Original error:", error);
|
||||
throw new Error("Gagal memproses respons dari server");
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating jenis layanan:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal mengupdate jenis layanan"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
jenisLayanan.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
jenisLayanan.edit.id = "";
|
||||
jenisLayanan.edit.form = { ...defaultJenisLayananForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// ========================================= PENGADUAN MASYARAKAT ========================================= //
|
||||
const templatePengaduanMasyarakatForm = z.object({
|
||||
name: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
email: z.string().min(1, "Alamat minimal 1 karakter"),
|
||||
nomorTelepon: z.string().min(1, "Nomor telepon minimal 1 karakter"),
|
||||
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"),
|
||||
jenisPengaduanId: z.string().min(1, "Jenis pengaduan minimal 1 karakter"),
|
||||
imageId: z.string().min(1, "Image minimal 1 karakter"),
|
||||
});
|
||||
|
||||
const defaultPengaduanMasyarakatForm = {
|
||||
name: "",
|
||||
email: "",
|
||||
nomorTelepon: "",
|
||||
nik: "",
|
||||
judulPengaduan: "",
|
||||
lokasiKejadian: "",
|
||||
deskripsiPengaduan: "",
|
||||
jenisPengaduanId: "",
|
||||
imageId: "",
|
||||
};
|
||||
|
||||
const pengaduanMasyarakat = proxy({
|
||||
create: {
|
||||
form: { ...defaultPengaduanMasyarakatForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templatePengaduanMasyarakatForm.safeParse(
|
||||
pengaduanMasyarakat.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
pengaduanMasyarakat.create.loading = true;
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.pengaduanmasyarakat[
|
||||
"create"
|
||||
].post(pengaduanMasyarakat.create.form);
|
||||
if (res.status === 200) {
|
||||
pengaduanMasyarakat.findMany.load();
|
||||
return toast.success("Data berhasil ditambahkan");
|
||||
}
|
||||
return toast.error("Gagal menambahkan data");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error("Gagal menambahkan data");
|
||||
} finally {
|
||||
pengaduanMasyarakat.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<
|
||||
Prisma.PengaduanMasyarakatGetPayload<{
|
||||
include: {
|
||||
jenisPengaduan: true;
|
||||
image: true;
|
||||
};
|
||||
}>
|
||||
> | null,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
loading: false,
|
||||
|
||||
async load(page = 1, limit = 10) {
|
||||
pengaduanMasyarakat.findMany.loading = true;
|
||||
pengaduanMasyarakat.findMany.page = page;
|
||||
try {
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.pengaduanmasyarakat[
|
||||
"find-many"
|
||||
].get({
|
||||
query: {
|
||||
page,
|
||||
limit,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status === 200 && res.data?.success) {
|
||||
pengaduanMasyarakat.findMany.data = res.data.data ?? [];
|
||||
pengaduanMasyarakat.findMany.totalPages = res.data.totalPages ?? 1;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Gagal fetch pengaduan masyarakat paginated:", err);
|
||||
} finally {
|
||||
pengaduanMasyarakat.findMany.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PengaduanMasyarakatGetPayload<{
|
||||
include: {
|
||||
jenisPengaduan: true;
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/pengaduanmasyarakat/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
pengaduanMasyarakat.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch pengaduan masyarakat:", res.statusText);
|
||||
pengaduanMasyarakat.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching pengaduan masyarakat:", error);
|
||||
pengaduanMasyarakat.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
pengaduanMasyarakat.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/pengaduanmasyarakat/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Pengaduan masyarakat berhasil dihapus"
|
||||
);
|
||||
await pengaduanMasyarakat.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus pengaduan masyarakat");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus pengaduan masyarakat");
|
||||
} finally {
|
||||
pengaduanMasyarakat.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
// ========================================= JENIS PENGADUAN ========================================= //
|
||||
const templateJenisPengaduanForm = z.object({
|
||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
});
|
||||
|
||||
const defaultJenisPengaduanForm = {
|
||||
nama: "",
|
||||
};
|
||||
|
||||
const jenisPengaduan = proxy({
|
||||
create: {
|
||||
form: { ...defaultJenisPengaduanForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateJenisPengaduanForm.safeParse(jenisPengaduan.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
jenisPengaduan.create.loading = true;
|
||||
const res =
|
||||
await ApiFetch.api.inovasi.layananonlinedesa.pengaduanmasyarakat.jenispengaduan[
|
||||
"create"
|
||||
].post(jenisPengaduan.create.form);
|
||||
if (res.status === 200) {
|
||||
jenisPengaduan.findMany.load();
|
||||
return toast.success("Data berhasil ditambahkan");
|
||||
}
|
||||
return toast.error("Gagal menambahkan data");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error("Gagal menambahkan data");
|
||||
} finally {
|
||||
jenisPengaduan.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as Array<{
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.JenisPengaduanGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/pengaduanmasyarakat/jenispengaduan/${id}`
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
jenisPengaduan.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
jenisPengaduan.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
jenisPengaduan.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
jenisPengaduan.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/pengaduanmasyarakat/jenispengaduan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Jenis pengduan berhasil dihapus");
|
||||
await jenisPengaduan.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus jenis pengaduan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus jenis pengaduan");
|
||||
} finally {
|
||||
jenisPengaduan.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultJenisPengaduanForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/pengaduanmasyarakat/jenispengaduan/${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
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading jenis pengaduan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateJenisPengaduanForm.safeParse(jenisPengaduan.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
jenisPengaduan.edit.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/inovasi/layananonlinedesa/pengaduanmasyarakat/jenispengaduan/${jenisPengaduan.edit.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: jenisPengaduan.edit.form.nama,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
// Clone the response to avoid 'body already read' error
|
||||
const responseClone = response.clone();
|
||||
|
||||
try {
|
||||
const result = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
console.error(
|
||||
"Update failed with status:",
|
||||
response.status,
|
||||
"Response:",
|
||||
result
|
||||
);
|
||||
throw new Error(
|
||||
result?.message ||
|
||||
`Gagal mengupdate jenis pengaduan (${response.status})`
|
||||
);
|
||||
}
|
||||
|
||||
if (result.success) {
|
||||
toast.success(
|
||||
result.message || "Berhasil memperbarui jenis pengaduan"
|
||||
);
|
||||
await jenisPengaduan.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
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
|
||||
try {
|
||||
const text = await responseClone.text();
|
||||
console.error("Error response text:", text);
|
||||
throw new Error(`Gagal memproses respons dari server: ${text}`);
|
||||
} catch (textError) {
|
||||
console.error("Error parsing response as text:", textError);
|
||||
console.error("Original error:", error);
|
||||
throw new Error("Gagal memproses respons dari server");
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating jenis pengaduan:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal mengupdate jenis pengaduan"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
jenisPengaduan.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
jenisPengaduan.edit.id = "";
|
||||
jenisPengaduan.edit.form = { ...defaultJenisPengaduanForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
const layananonlineDesa = proxy({
|
||||
administrasiOnline,
|
||||
jenisLayanan,
|
||||
pengaduanMasyarakat,
|
||||
jenisPengaduan,
|
||||
});
|
||||
|
||||
export default layananonlineDesa;
|
||||
227
src/app/admin/(dashboard)/_state/inovasi/program-kreatif.ts
Normal file
@@ -0,0 +1,227 @@
|
||||
/* 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, "Nama minimal 1 karakter"),
|
||||
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||
slug: z.string().min(1, "Deskripsi singkat minimal 1 karakter"),
|
||||
icon: z.string().min(1, "Icon minimal 1 karakter"),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
slug: "",
|
||||
icon: "",
|
||||
};
|
||||
|
||||
const programKreatifState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(programKreatifState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
programKreatifState.create.loading = true;
|
||||
const res = await ApiFetch.api.inovasi.programkreatif["create"].post(
|
||||
programKreatifState.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
programKreatifState.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
programKreatifState.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
|
||||
programKreatifState.findMany.loading = true; // Use the full path to access the property
|
||||
programKreatifState.findMany.page = page;
|
||||
try {
|
||||
const res = await ApiFetch.api.inovasi.programkreatif["find-many"].get({
|
||||
query: { page, limit },
|
||||
});
|
||||
|
||||
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;
|
||||
} 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);
|
||||
programKreatifState.findMany.data = [];
|
||||
programKreatifState.findMany.total = 0;
|
||||
programKreatifState.findMany.totalPages = 1;
|
||||
} finally {
|
||||
programKreatifState.findMany.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/programkreatif/${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,
|
||||
slug: data.slug,
|
||||
icon: data.icon,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal mengambil data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading program kreatif:", 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 cek = templateForm.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/inovasi/programkreatif/${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 programKreatifState.findMany.load();
|
||||
return result.data;
|
||||
} catch (error) {
|
||||
console.error("Error update data:", error);
|
||||
toast.error("Gagal update data program kreatif");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.ProgramKreatifGetPayload<{
|
||||
omit: { isActive: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/inovasi/programkreatif/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
programKreatifState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
programKreatifState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading program kreatif:", error);
|
||||
programKreatifState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
programKreatifState.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/inovasi/programkreatif/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Program kreatif berhasil dihapus");
|
||||
await programKreatifState.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus program kreatif");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus program kreatif");
|
||||
} finally {
|
||||
programKreatifState.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default programKreatifState;
|
||||
232
src/app/admin/(dashboard)/_state/keamanan/keamanan-lingkungan.ts
Normal file
@@ -0,0 +1,232 @@
|
||||
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(3, "Nama minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
imageId: z.string().nonempty(),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
name: "",
|
||||
deskripsi: "",
|
||||
imageId: "",
|
||||
};
|
||||
|
||||
const keamananLingkunganState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(keamananLingkunganState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
keamananLingkunganState.create.loading = true;
|
||||
const res = await ApiFetch.api.keamanan.keamananlingkungan[
|
||||
"create"
|
||||
].post(keamananLingkunganState.create.form);
|
||||
if (res.status === 200) {
|
||||
keamananLingkunganState.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
keamananLingkunganState.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
keamananLingkunganState.create.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.KeamananLingkunganGetPayload<{
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.KeamananLingkunganGetPayload<{
|
||||
include: { image: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/keamanan/keamananlingkungan/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
keamananLingkunganState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
keamananLingkunganState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
keamananLingkunganState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
keamananLingkunganState.delete.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/keamanan/keamananlingkungan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Keamanan ingkungan berhasil dihapus"
|
||||
);
|
||||
await keamananLingkunganState.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus keamanan ingkungan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus keamanan ingkungan");
|
||||
} finally {
|
||||
keamananLingkunganState.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/keamanan/keamananlingkungan/${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 loading keamanan lingkungan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(keamananLingkunganState.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
keamananLingkunganState.edit.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/keamanan/keamananlingkungan/${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("Berhasil update keamanan lingkungan");
|
||||
await keamananLingkunganState.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update keamanan lingkungan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating keamanan lingkungan:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update keamanan lingkungan"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
keamananLingkunganState.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
keamananLingkunganState.edit.id = "";
|
||||
keamananLingkunganState.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default keamananLingkunganState;
|
||||
@@ -0,0 +1,259 @@
|
||||
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({
|
||||
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(),
|
||||
})
|
||||
),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
nama: "",
|
||||
imageId: "",
|
||||
kontakItems: [
|
||||
{
|
||||
nama: "",
|
||||
nomorTelepon: "",
|
||||
imageId: "",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const kontakDaruratKeamananState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(
|
||||
kontakDaruratKeamananState.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
kontakDaruratKeamananState.create.loading = true;
|
||||
const res = await ApiFetch.api.keamanan.kontakdaruratkeamanan[
|
||||
"create"
|
||||
].post(kontakDaruratKeamananState.create.form);
|
||||
if (res.status === 200) {
|
||||
kontakDaruratKeamananState.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
kontakDaruratKeamananState.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.KontakDaruratKeamananGetPayload<{
|
||||
include: {
|
||||
kontakItems: true;
|
||||
image: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.keamanan.kontakdaruratkeamanan[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
kontakDaruratKeamananState.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.KontakDaruratKeamananGetPayload<{
|
||||
include: {
|
||||
kontakItems: {
|
||||
include: {
|
||||
image: true;
|
||||
};
|
||||
};
|
||||
image: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/keamanan/kontakdaruratkeamanan/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
kontakDaruratKeamananState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
kontakDaruratKeamananState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
kontakDaruratKeamananState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
kontakDaruratKeamananState.delete.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/keamanan/kontakdaruratkeamanan/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 kontakDaruratKeamananState.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 {
|
||||
kontakDaruratKeamananState.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/keamanan/kontakdaruratkeamanan/${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,
|
||||
imageId: data.imageId,
|
||||
kontakItems: [
|
||||
{
|
||||
nama: data.kontakItems.nama,
|
||||
nomorTelepon: data.kontakItems.nomorTelepon,
|
||||
imageId: data.kontakItems.imageId,
|
||||
},
|
||||
],
|
||||
};
|
||||
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 = templateForm.safeParse(
|
||||
kontakDaruratKeamananState.update.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
kontakDaruratKeamananState.update.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/keamanan/kontakdaruratkeamanan/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
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,
|
||||
},
|
||||
],
|
||||
}),
|
||||
}
|
||||
);
|
||||
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 darurat");
|
||||
await kontakDaruratKeamananState.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate kontak darurat");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating kontak darurat:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal mengupdate kontak darurat"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
kontakDaruratKeamananState.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
kontakDaruratKeamananState.update.id = "";
|
||||
kontakDaruratKeamananState.update.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default kontakDaruratKeamananState;
|
||||
273
src/app/admin/(dashboard)/_state/keamanan/laporan-publik.ts
Normal file
@@ -0,0 +1,273 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
export type Status = "Selesai" | "Proses" | "Gagal";
|
||||
|
||||
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;
|
||||
status: Status;
|
||||
penanganan: string;
|
||||
kronologi: string;
|
||||
}
|
||||
|
||||
const defaultForm: FormData = {
|
||||
judul: "",
|
||||
lokasi: "",
|
||||
tanggalWaktu: new Date().toISOString(),
|
||||
status: "Proses",
|
||||
penanganan: "",
|
||||
kronologi: "",
|
||||
};
|
||||
|
||||
const laporanPublikState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(laporanPublikState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
laporanPublikState.create.loading = true;
|
||||
|
||||
// Ensure we have a valid date
|
||||
if (!laporanPublikState.create.form.tanggalWaktu) {
|
||||
return toast.error("Tanggal laporan harus diisi");
|
||||
}
|
||||
|
||||
// Format the data before sending
|
||||
const formData = {
|
||||
...laporanPublikState.create.form,
|
||||
// Ensure the date is in the correct format for the API
|
||||
tanggalWaktu: new Date(laporanPublikState.create.form.tanggalWaktu).toISOString()
|
||||
};
|
||||
|
||||
console.log("Sending form data:", formData); // Debug log
|
||||
|
||||
const res = await ApiFetch.api.keamanan.laporanpublik["create"].post(
|
||||
formData
|
||||
);
|
||||
|
||||
if (res.error) {
|
||||
console.error("API Error:", res.error);
|
||||
throw new Error("Failed to create laporan publik");
|
||||
}
|
||||
|
||||
if (res.status === 200) {
|
||||
laporanPublikState.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.error("Error creating laporan publik:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Gagal membuat laporan publik");
|
||||
throw error; // Re-throw to be handled by the caller
|
||||
} finally {
|
||||
laporanPublikState.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
laporanPublikState.create.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.LaporanPublikGetPayload<{
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.LaporanPublikGetPayload<{
|
||||
include: { penanganan: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/keamanan/laporanpublik/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
laporanPublikState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
laporanPublikState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
laporanPublikState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
laporanPublikState.findUnique.data = null;
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
laporanPublikState.delete.loading = true;
|
||||
const response = await fetch(`/api/keamanan/laporanpublik/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Laporan publik berhasil dihapus"
|
||||
);
|
||||
await laporanPublikState.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus laporan publik");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus laporan publik");
|
||||
} finally {
|
||||
laporanPublikState.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/keamanan/laporanpublik/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
judul: data.judul,
|
||||
lokasi: data.lokasi,
|
||||
tanggalWaktu: data.tanggalWaktu,
|
||||
status: data.status,
|
||||
penanganan: data.penanganan,
|
||||
kronologi: data.kronologi,
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading keamanan lingkungan:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(laporanPublikState.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
toast.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
laporanPublikState.edit.loading = true;
|
||||
|
||||
const response = await fetch(
|
||||
`/api/keamanan/laporanpublik/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
judul: this.form.judul,
|
||||
lokasi: this.form.lokasi,
|
||||
tanggalWaktu: this.form.tanggalWaktu,
|
||||
status: this.form.status,
|
||||
penanganan: this.form.penanganan,
|
||||
kronologi: this.form.kronologi,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
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 laporan publik");
|
||||
await laporanPublikState.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update laporan publik");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating laporan publik:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Terjadi kesalahan saat update laporan publik"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
laporanPublikState.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
laporanPublikState.edit.id = "";
|
||||
laporanPublikState.edit.form = { ...defaultForm };
|
||||
},
|
||||
}
|
||||
});
|
||||
export default laporanPublikState;
|
||||
@@ -0,0 +1,314 @@
|
||||
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({
|
||||
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"),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
pencegahanKriminalitas: {
|
||||
programKeamanan: {
|
||||
nama: "",
|
||||
deskripsi: "",
|
||||
slug: "",
|
||||
},
|
||||
tipsKeamanan: {
|
||||
judul: "",
|
||||
konten: "",
|
||||
slug: "",
|
||||
},
|
||||
videoKeamanan: {
|
||||
judul: "",
|
||||
deskripsi: "",
|
||||
videoUrl: "",
|
||||
slug: "",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const pencegahanKriminalitasState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(
|
||||
pencegahanKriminalitasState.create.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
pencegahanKriminalitasState.create.loading = true;
|
||||
const res = await ApiFetch.api.keamanan.pencegahankriminalitas[
|
||||
"create"
|
||||
].post(pencegahanKriminalitasState.create.form.pencegahanKriminalitas);
|
||||
if (res.status === 200) {
|
||||
pencegahanKriminalitasState.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
pencegahanKriminalitasState.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PencegahanKriminalitasGetPayload<{
|
||||
include: {
|
||||
programKeamanan: true;
|
||||
tipsKeamanan: true;
|
||||
videoKeamanan: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.keamanan.pencegahankriminalitas[
|
||||
"find-many"
|
||||
].get();
|
||||
if (res.status === 200) {
|
||||
pencegahanKriminalitasState.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PencegahanKriminalitasGetPayload<{
|
||||
include: {
|
||||
programKeamanan: true;
|
||||
tipsKeamanan: true;
|
||||
videoKeamanan: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/keamanan/pencegahankriminalitas/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
pencegahanKriminalitasState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
pencegahanKriminalitasState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
pencegahanKriminalitasState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
pencegahanKriminalitasState.delete.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/keamanan/pencegahankriminalitas/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(
|
||||
result.message || "Pencegahan kriminalitas berhasil dihapus"
|
||||
);
|
||||
await pencegahanKriminalitasState.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(
|
||||
result?.message || "Gagal menghapus pencegahan kriminalitas"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus pencegahan kriminalitas");
|
||||
} finally {
|
||||
pencegahanKriminalitasState.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) {
|
||||
toast.warn("ID tidak valid");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
pencegahanKriminalitasState.update.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/keamanan/pencegahankriminalitas/${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;
|
||||
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,
|
||||
},
|
||||
},
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal update:", error);
|
||||
toast.error(
|
||||
"Terjadi kesalahan saat mengupdate pencegahan kriminalitas"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(
|
||||
pencegahanKriminalitasState.update.form
|
||||
);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
pencegahanKriminalitasState.update.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/keamanan/pencegahankriminalitas/${pencegahanKriminalitasState.update.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"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,
|
||||
},
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
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 pencegahan kriminalitas");
|
||||
await pencegahanKriminalitasState.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(
|
||||
result.message || "Gagal mengupdate pencegahan kriminalitas"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal update:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal mengupdate pencegahan kriminalitas"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
pencegahanKriminalitasState.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
pencegahanKriminalitasState.update.id = "";
|
||||
pencegahanKriminalitasState.update.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
export default pencegahanKriminalitasState;
|
||||
242
src/app/admin/(dashboard)/_state/keamanan/polsek-terdekat.ts
Normal file
@@ -0,0 +1,242 @@
|
||||
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({
|
||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||
jarakKeDesa: z.string().min(1, "Jarak minimal 1 karakter"),
|
||||
alamat: z.string().min(1, "Alamat minimal 1 karakter"),
|
||||
nomorTelepon: z.string().min(1, "Nomor Telepon minimal 1 karakter"),
|
||||
jamOperasional: z.string().min(1, "Jam Operasional minimal 1 karakter"),
|
||||
embedMapUrl: z.string().min(1, "Embed Map Url minimal 1 karakter"),
|
||||
namaTempatMaps: z.string().min(1, "Nama Tempat Maps minimal 1 karakter"),
|
||||
alamatMaps: z.string().min(1, "Alamat Maps minimal 1 karakter"),
|
||||
linkPetunjukArah: z.string().min(1, "Link Petunjuk Arah minimal 1 karakter"),
|
||||
layananPolsekId: z.string().min(1, "Layanan Polsek Id minimal 1 karakter"),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
nama: "",
|
||||
jarakKeDesa: "",
|
||||
alamat: "",
|
||||
nomorTelepon: "",
|
||||
jamOperasional: "",
|
||||
embedMapUrl: "",
|
||||
namaTempatMaps: "",
|
||||
alamatMaps: "",
|
||||
linkPetunjukArah: "",
|
||||
layananPolsekId: "",
|
||||
};
|
||||
|
||||
const polsekTerdekatState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(polsekTerdekatState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
polsekTerdekatState.create.loading = true;
|
||||
const res = await ApiFetch.api.keamanan.polsekterdekat["create"].post(
|
||||
polsekTerdekatState.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
polsekTerdekatState.findMany.load();
|
||||
return toast.success("Data berhasil ditambahkan");
|
||||
}
|
||||
return toast.error("Gagal menambahkan data");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error("Gagal menambahkan data");
|
||||
} finally {
|
||||
polsekTerdekatState.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PolsekTerdekatGetPayload<{
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.PolsekTerdekatGetPayload<{
|
||||
include: { layananPolsek: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/keamanan/polsekterdekat/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
polsekTerdekatState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
polsekTerdekatState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
polsekTerdekatState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
|
||||
try {
|
||||
polsekTerdekatState.delete.loading = true;
|
||||
|
||||
const response = await fetch(`/api/keamanan/polsekterdekat/del/${id}`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Polsek terdekat berhasil dihapus");
|
||||
await polsekTerdekatState.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus polsek terdekat");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Gagal delete:", error);
|
||||
toast.error("Terjadi kesalahan saat menghapus polsek terdekat");
|
||||
} finally {
|
||||
polsekTerdekatState.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/keamanan/polsekterdekat/${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,
|
||||
jarakKeDesa: data.jarakKeDesa,
|
||||
alamat: data.alamat,
|
||||
nomorTelepon: data.nomorTelepon,
|
||||
jamOperasional: data.jamOperasional,
|
||||
embedMapUrl: data.embedMapUrl,
|
||||
namaTempatMaps: data.namaTempatMaps,
|
||||
alamatMaps: data.alamatMaps,
|
||||
linkPetunjukArah: data.linkPetunjukArah,
|
||||
layananPolsekId: data.layananPolsekId,
|
||||
};
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading polsek terdekat:", error);
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Gagal memuat data"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(polsekTerdekatState.edit.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
polsekTerdekatState.edit.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/keamanan/polsekterdekat/${this.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: this.form.nama,
|
||||
jarakKeDesa: this.form.jarakKeDesa,
|
||||
alamat: this.form.alamat,
|
||||
nomorTelepon: this.form.nomorTelepon,
|
||||
jamOperasional: this.form.jamOperasional,
|
||||
embedMapUrl: this.form.embedMapUrl,
|
||||
namaTempatMaps: this.form.namaTempatMaps,
|
||||
alamatMaps: this.form.alamatMaps,
|
||||
linkPetunjukArah: this.form.linkPetunjukArah,
|
||||
layananPolsekId: this.form.layananPolsekId,
|
||||
}),
|
||||
}
|
||||
);
|
||||
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 polsek terdekat");
|
||||
await polsekTerdekatState.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal mengupdate polsek terdekat");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating polsek terdekat:", error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Gagal mengupdate polsek terdekat"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
polsekTerdekatState.edit.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
polsekTerdekatState.edit.id = "";
|
||||
polsekTerdekatState.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default polsekTerdekatState;
|
||||
212
src/app/admin/(dashboard)/_state/keamanan/tips-keamanan.ts
Normal file
@@ -0,0 +1,212 @@
|
||||
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({
|
||||
judul: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
imageId: z.string().nonempty(),
|
||||
});
|
||||
|
||||
const defaultForm = {
|
||||
judul: "",
|
||||
deskripsi: "",
|
||||
imageId: "",
|
||||
};
|
||||
|
||||
const tipsKeamananState = proxy({
|
||||
create: {
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(tipsKeamananState.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
tipsKeamananState.create.loading = true;
|
||||
const res = await ApiFetch.api.keamanan.menutipskeamanan["create"].post(
|
||||
tipsKeamananState.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
tipsKeamananState.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res);
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
tipsKeamananState.create.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
tipsKeamananState.create.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.MenuTipsKeamananGetPayload<{
|
||||
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 ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.MenuTipsKeamananGetPayload<{
|
||||
include: { image: true };
|
||||
}> | null,
|
||||
async load(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/keamanan/menutipskeamanan/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
tipsKeamananState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
console.error("Failed to fetch data", res.status, res.statusText);
|
||||
tipsKeamananState.findUnique.data = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
tipsKeamananState.findUnique.data = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
tipsKeamananState.delete.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/keamanan/menutipskeamanan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
const result = await response.json();
|
||||
if (response.ok && result?.success) {
|
||||
toast.success(result.message || "Tips keamanan berhasil dihapus");
|
||||
await tipsKeamananState.findMany.load(); // refresh list
|
||||
} else {
|
||||
toast.error(result?.message || "Gagal menghapus tips keamanan");
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error("Terjadi kesalahan saat menghapus tips keamanan");
|
||||
console.error("Gagal delete:", error);
|
||||
} finally {
|
||||
tipsKeamananState.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
id: "",
|
||||
loading: false,
|
||||
form: { ...defaultForm },
|
||||
|
||||
async load(id: string) {
|
||||
if (!id) return toast.warn("ID tidak valid");
|
||||
try {
|
||||
tipsKeamananState.update.loading = true;
|
||||
const response = await fetch(`/api/keamanan/menutipskeamanan/${id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result?.success) {
|
||||
const data = result.data;
|
||||
this.id = data.id;
|
||||
this.form = {
|
||||
judul: data.judul,
|
||||
deskripsi: data.deskripsi,
|
||||
imageId: data.imageId || "",
|
||||
};
|
||||
return data; // Return the loaded data
|
||||
} else {
|
||||
throw new Error(result?.message || "Gagal memuat data");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
toast.error("Gagal memuat data");
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async update() {
|
||||
const cek = templateForm.safeParse(tipsKeamananState.update.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
tipsKeamananState.update.loading = true;
|
||||
const response = await fetch(
|
||||
`/api/keamanan/menutipskeamanan/${tipsKeamananState.update.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
judul: this.form.judul,
|
||||
deskripsi: this.form.deskripsi,
|
||||
imageId: this.form.imageId,
|
||||
}),
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(
|
||||
errorData.message || `HTTP error! status: ${response.status}`
|
||||
);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
toast.success("Berhasil update tips keamanan");
|
||||
await tipsKeamananState.findMany.load(); // refresh list
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.message || "Gagal update tips keamanan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating data:", error);
|
||||
toast.error("Gagal update data");
|
||||
return false;
|
||||
} finally {
|
||||
tipsKeamananState.update.loading = false;
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
tipsKeamananState.update.id = "";
|
||||
tipsKeamananState.update.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
});
|
||||
export default tipsKeamananState;
|
||||
@@ -1,339 +1,306 @@
|
||||
/* 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";
|
||||
|
||||
/* Introduction */
|
||||
const templateIntroduction = z.object({
|
||||
content: z.string().min(3, "Content minimal 3 karakter"),
|
||||
})
|
||||
const templateForm = z.object({
|
||||
title: z.string().min(1, "Judul harus diisi"),
|
||||
content: z.string().min(1, "Content harus diisi"),
|
||||
introduction: z.object({
|
||||
content: z.string().min(1, "Content harus diisi"),
|
||||
}),
|
||||
symptom: z.object({
|
||||
title: z.string().min(1, "Judul harus diisi"),
|
||||
content: z.string().min(1, "Content harus diisi"),
|
||||
}),
|
||||
prevention: z.object({
|
||||
title: z.string().min(1, "Judul harus diisi"),
|
||||
content: z.string().min(1, "Content harus diisi"),
|
||||
}),
|
||||
firstAid: z.object({
|
||||
title: z.string().min(1, "Judul harus diisi"),
|
||||
content: z.string().min(1, "Content harus diisi"),
|
||||
}),
|
||||
mythVsFact: z.object({
|
||||
title: z.string().min(1, "Judul harus diisi"),
|
||||
mitos: z.string().min(1, "Mitos harus diisi"),
|
||||
fakta: z.string().min(1, "Fakta harus diisi"),
|
||||
}),
|
||||
doctorSign: z.object({
|
||||
content: z.string().min(1, "Content harus diisi"),
|
||||
}),
|
||||
});
|
||||
|
||||
type Introduction = Prisma.IntroductionGetPayload<{
|
||||
select: {
|
||||
content: true;
|
||||
};
|
||||
}>;
|
||||
const defaultForm = {
|
||||
title: "",
|
||||
content: "",
|
||||
introduction: {
|
||||
content: "",
|
||||
},
|
||||
symptom: {
|
||||
title: "",
|
||||
content: "",
|
||||
},
|
||||
prevention: {
|
||||
title: "",
|
||||
content: "",
|
||||
},
|
||||
firstAid: {
|
||||
title: "",
|
||||
content: "",
|
||||
},
|
||||
mythVsFact: {
|
||||
title: "",
|
||||
mitos: "",
|
||||
fakta: "",
|
||||
},
|
||||
doctorSign: {
|
||||
content: "",
|
||||
},
|
||||
};
|
||||
|
||||
const introduction = proxy({
|
||||
const artikelKesehatanState = proxy({
|
||||
create: {
|
||||
form: {} as Introduction,
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateIntroduction.safeParse(introduction.create.form);
|
||||
async submit() {
|
||||
const cek = templateForm.safeParse(this.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
const errMsg = cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}: ${v.message}`)
|
||||
.join("\n");
|
||||
toast.error(errMsg);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
introduction.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.introduction["create"].post(introduction.create.form);
|
||||
this.loading = true;
|
||||
const payload = { ...this.form };
|
||||
|
||||
const res = await (ApiFetch.api.kesehatan as any)[
|
||||
"artikel-kesehatan"
|
||||
].create.post(payload);
|
||||
|
||||
if (res.status === 200) {
|
||||
introduction.findMany.load();
|
||||
return toast.success("success create");
|
||||
toast.success("Berhasil menambahkan artikel kesehatan");
|
||||
this.resetForm();
|
||||
await artikelKesehatanState.findMany.load();
|
||||
return res.data;
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} catch (err: any) {
|
||||
const msg = err?.message || "Terjadi kesalahan saat mengirim data";
|
||||
toast.error(msg);
|
||||
console.error("SUBMIT ERROR:", err);
|
||||
return null;
|
||||
} finally {
|
||||
introduction.create.loading = false;
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.IntroductionGetPayload<{ omit: { isActive: true } }>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.introduction["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
introduction.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
/* ======================================================================= */
|
||||
|
||||
/* symptom */
|
||||
const templateSymptom = z.object({
|
||||
title: z.string().min(3, "Title minimal 3 karakter"),
|
||||
content: z.string().min(3, "Content minimal 3 karakter"),
|
||||
})
|
||||
|
||||
type Symptom = Prisma.SymptomGetPayload<{
|
||||
select: {
|
||||
title: true;
|
||||
content: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const symptom = proxy({
|
||||
create: {
|
||||
form: {} as Symptom,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateSymptom.safeParse(symptom.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
symptom.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.symptom["create"].post(symptom.create.form);
|
||||
if (res.status === 200) {
|
||||
symptom.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
symptom.create.loading = false;
|
||||
}
|
||||
resetForm() {
|
||||
this.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.SymptomGetPayload<{ omit: { isActive: true } }>[]
|
||||
| Prisma.ArtikelKesehatanGetPayload<{
|
||||
include: {
|
||||
introduction: true;
|
||||
symptom: true;
|
||||
prevention: true;
|
||||
firstaid: true;
|
||||
mythvsfact: true;
|
||||
doctorsign: true;
|
||||
};
|
||||
}>[]
|
||||
| null,
|
||||
loading: false,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.symptom["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
symptom.findMany.data = res.data?.data ?? [];
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await (ApiFetch.api.kesehatan as any)["artikel-kesehatan"][
|
||||
"find-many"
|
||||
].get();
|
||||
|
||||
if (res.status === 200) {
|
||||
this.data = res.data?.data ?? [];
|
||||
} else {
|
||||
toast.error("Gagal memuat data artikel kesehatan");
|
||||
}
|
||||
|
||||
return res;
|
||||
} catch (err) {
|
||||
toast.error("Terjadi error saat load data");
|
||||
console.error("LOAD ERROR:", err);
|
||||
throw err;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findUnique: {
|
||||
data: null as Prisma.ArtikelKesehatanGetPayload<{
|
||||
include: {
|
||||
introduction: true;
|
||||
symptom: true;
|
||||
prevention: true;
|
||||
firstaid: true;
|
||||
mythvsfact: true;
|
||||
doctorsign: true;
|
||||
};
|
||||
}> | null,
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
const res = await fetch(`/api/kesehatan/artikel-kesehatan/${id}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
artikelKesehatanState.findUnique.data = data.data ?? null;
|
||||
} else {
|
||||
toast.error("Gagal load data artikel kesehatan");
|
||||
}
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
id: "",
|
||||
form: { ...defaultForm },
|
||||
loading: false,
|
||||
async load(id: string) {
|
||||
const res = await fetch(`/api/kesehatan/artikel-kesehatan/${id}`);
|
||||
if (!res.ok) {
|
||||
toast.error("Gagal load data artikel kesehatan");
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await res.json();
|
||||
const data = result.data;
|
||||
|
||||
artikelKesehatanState.edit.id = data.id;
|
||||
artikelKesehatanState.edit.form = {
|
||||
title: data.title,
|
||||
content: data.content,
|
||||
introduction: {
|
||||
content: data.introduction.content,
|
||||
},
|
||||
symptom: {
|
||||
title: data.symptom.title,
|
||||
content: data.symptom.content,
|
||||
},
|
||||
prevention: {
|
||||
title: data.prevention.title,
|
||||
content: data.prevention.content,
|
||||
},
|
||||
firstAid: {
|
||||
title: data.firstaid.title,
|
||||
content: data.firstaid.content,
|
||||
},
|
||||
mythVsFact: {
|
||||
title: data.mythvsfact.title,
|
||||
mitos: data.mythvsfact.mitos,
|
||||
fakta: data.mythvsfact.fakta,
|
||||
},
|
||||
doctorSign: {
|
||||
content: data.doctorsign.content,
|
||||
},
|
||||
};
|
||||
},
|
||||
async submit() {
|
||||
const cek = templateForm.safeParse(artikelKesehatanState.edit.form);
|
||||
if (!cek.success) {
|
||||
const errMsg = cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}: ${v.message}`)
|
||||
.join("\n");
|
||||
toast.error(errMsg);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
artikelKesehatanState.edit.loading = true;
|
||||
const payload = {
|
||||
title: artikelKesehatanState.edit.form.title,
|
||||
content: artikelKesehatanState.edit.form.content,
|
||||
introduction: {
|
||||
content: artikelKesehatanState.edit.form.introduction.content,
|
||||
},
|
||||
symptom: {
|
||||
title: artikelKesehatanState.edit.form.symptom.title,
|
||||
content: artikelKesehatanState.edit.form.symptom.content,
|
||||
},
|
||||
prevention: {
|
||||
title: artikelKesehatanState.edit.form.prevention.title,
|
||||
content: artikelKesehatanState.edit.form.prevention.content,
|
||||
},
|
||||
firstAid: {
|
||||
title: artikelKesehatanState.edit.form.firstAid.title,
|
||||
content: artikelKesehatanState.edit.form.firstAid.content,
|
||||
},
|
||||
mythVsFact: {
|
||||
title: artikelKesehatanState.edit.form.mythVsFact.title,
|
||||
mitos: artikelKesehatanState.edit.form.mythVsFact.mitos,
|
||||
fakta: artikelKesehatanState.edit.form.mythVsFact.fakta,
|
||||
},
|
||||
doctorSign: {
|
||||
content: artikelKesehatanState.edit.form.doctorSign.content,
|
||||
},
|
||||
};
|
||||
|
||||
const res = await fetch(
|
||||
`/api/kesehatan/artikel-kesehatan/${artikelKesehatanState.edit.id}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload),
|
||||
}
|
||||
);
|
||||
|
||||
if (!res.ok) {
|
||||
const error = await res.json();
|
||||
throw new Error(error.message || "Update gagal");
|
||||
}
|
||||
|
||||
toast.success("Berhasil update artikel kesehatan");
|
||||
await artikelKesehatanState.findMany.load();
|
||||
return true;
|
||||
} catch (err) {
|
||||
toast.error(
|
||||
err instanceof Error ? err.message : "Terjadi kesalahan saat update"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
artikelKesehatanState.edit.loading = false;
|
||||
}
|
||||
},
|
||||
resetForm() {
|
||||
artikelKesehatanState.edit.id = "";
|
||||
artikelKesehatanState.edit.form = { ...defaultForm };
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
loading: false,
|
||||
async byId(id: string) {
|
||||
try {
|
||||
artikelKesehatanState.delete.loading = true;
|
||||
const res = await fetch(
|
||||
`/api/kesehatan/artikel-kesehatan/del/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
}
|
||||
);
|
||||
|
||||
const result = await res.json();
|
||||
if (res.ok && result.success) {
|
||||
toast.success("Artikel kesehatan berhasil dihapus");
|
||||
await artikelKesehatanState.findMany.load();
|
||||
} else {
|
||||
toast.error(result.message || "Gagal menghapus");
|
||||
}
|
||||
} catch {
|
||||
toast.error("Terjadi kesalahan saat menghapus");
|
||||
} finally {
|
||||
artikelKesehatanState.delete.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
/* ======================================================================= */
|
||||
|
||||
/* Prevention */
|
||||
const templatePrevention = z.object({
|
||||
title: z.string().min(3, "Title minimal 3 karakter"),
|
||||
content: z.string().min(3, "Content minimal 3 karakter"),
|
||||
})
|
||||
|
||||
type Prevention = Prisma.PreventionGetPayload<{
|
||||
select: {
|
||||
title: true;
|
||||
content: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const prevention = proxy({
|
||||
create: {
|
||||
form: {} as Prevention,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templatePrevention.safeParse(prevention.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
prevention.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.prevention["create"].post(prevention.create.form);
|
||||
if (res.status === 200) {
|
||||
prevention.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
prevention.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PreventionGetPayload<{ omit: { isActive: true } }>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.prevention["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
prevention.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
/* ======================================================================= */
|
||||
|
||||
/* First Aid */
|
||||
const templateFirstAid = z.object({
|
||||
title: z.string().min(3, "Title minimal 3 karakter"),
|
||||
content: z.string().min(3, "Content minimal 3 karakter"),
|
||||
})
|
||||
|
||||
type FirstAid = Prisma.FirstAidGetPayload<{
|
||||
select: {
|
||||
title: true;
|
||||
content: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const firstAid = proxy({
|
||||
create: {
|
||||
form: {} as FirstAid,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateFirstAid.safeParse(firstAid.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
firstAid.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.firstaid["create"].post(firstAid.create.form);
|
||||
if (res.status === 200) {
|
||||
firstAid.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
firstAid.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.FirstAidGetPayload<{ omit: { isActive: true } }>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.firstaid["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
firstAid.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
/* ======================================================================= */
|
||||
|
||||
/* Myth vs Fact */
|
||||
const templateMythFact = z.object({
|
||||
title: z.string().min(3, "Title minimal 3 karakter"),
|
||||
mitos: z.string().min(3, "Mitos minimal 3 karakter"),
|
||||
fakta: z.string().min(3, "Fakta minimal 3 karakter"),
|
||||
})
|
||||
|
||||
type MythFact = Prisma.MythVsFactGetPayload<{
|
||||
select: {
|
||||
title: true;
|
||||
mitos: true;
|
||||
fakta: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const mythFact = proxy({
|
||||
create: {
|
||||
form: {} as MythFact,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateMythFact.safeParse(mythFact.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
mythFact.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.mythvsfact["create"].post(mythFact.create.form);
|
||||
if (res.status === 200) {
|
||||
mythFact.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
mythFact.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.MythVsFactGetPayload<{ omit: { isActive: true } }>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.mythvsfact["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
mythFact.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
/* ======================================================================= */
|
||||
|
||||
/* Doctor Sign */
|
||||
const templateDoctorSign = z.object({
|
||||
content: z.string().min(3, "Content minimal 3 karakter"),
|
||||
})
|
||||
|
||||
type DoctorSign = Prisma.DoctorSignGetPayload<{
|
||||
select: {
|
||||
content: true
|
||||
}
|
||||
}>
|
||||
|
||||
const doctorSign = proxy({
|
||||
create: {
|
||||
form: {} as DoctorSign,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateDoctorSign.safeParse(doctorSign.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
doctorSign.create.loading = true;
|
||||
const res = await ApiFetch.api.kesehatan.doctor_sign["create"].post(doctorSign.create.form);
|
||||
if (res.status === 200) {
|
||||
doctorSign.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
doctorSign.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.DoctorSignGetPayload<{ omit: { isActive: true } }>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.kesehatan.doctor_sign["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
doctorSign.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
const stateArtikelKesehatan = proxy({
|
||||
introduction,
|
||||
symptom,
|
||||
prevention,
|
||||
firstAid,
|
||||
mythFact,
|
||||
doctorSign
|
||||
})
|
||||
|
||||
export default stateArtikelKesehatan
|
||||
export default artikelKesehatanState;
|
||||
|
||||