Compare commits
1 Commits
nico/15-de
...
nico/test-
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c59d7b4fb |
5
.gitignore
vendored
@@ -41,9 +41,6 @@ next-env.d.ts
|
|||||||
# uploads
|
# uploads
|
||||||
/uploads
|
/uploads
|
||||||
|
|
||||||
# download
|
|
||||||
/download
|
|
||||||
|
|
||||||
# cache
|
# cache
|
||||||
/cache
|
/cache
|
||||||
|
|
||||||
@@ -51,5 +48,3 @@ next-env.d.ts
|
|||||||
|
|
||||||
.env.*
|
.env.*
|
||||||
|
|
||||||
*.tar.gz
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
experimental: {},
|
|
||||||
allowedDevOrigins: [
|
|
||||||
"http://192.168.1.82:3000", // buat akses dari HP/device lain
|
|
||||||
"http://localhost:3000", // akses lokal
|
|
||||||
],
|
|
||||||
async headers() {
|
async headers() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
|||||||
30
package.json
@@ -3,9 +3,11 @@
|
|||||||
"version": "0.1.5",
|
"version": "0.1.5",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev --turbopack",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start"
|
"start": "next start",
|
||||||
|
"lint": "next lint",
|
||||||
|
"prisma:seed": "bun run prisma/seed.ts"
|
||||||
},
|
},
|
||||||
"prisma": {
|
"prisma": {
|
||||||
"seed": "bun run prisma/seed.ts"
|
"seed": "bun run prisma/seed.ts"
|
||||||
@@ -19,7 +21,6 @@
|
|||||||
"@elysiajs/static": "^1.3.0",
|
"@elysiajs/static": "^1.3.0",
|
||||||
"@elysiajs/stream": "^1.1.0",
|
"@elysiajs/stream": "^1.1.0",
|
||||||
"@elysiajs/swagger": "^1.2.0",
|
"@elysiajs/swagger": "^1.2.0",
|
||||||
"@emotion/react": "^11.14.0",
|
|
||||||
"@mantine/carousel": "^7.16.2",
|
"@mantine/carousel": "^7.16.2",
|
||||||
"@mantine/charts": "^7.17.1",
|
"@mantine/charts": "^7.17.1",
|
||||||
"@mantine/core": "^7.17.4",
|
"@mantine/core": "^7.17.4",
|
||||||
@@ -27,7 +28,6 @@
|
|||||||
"@mantine/dropzone": "^8.1.1",
|
"@mantine/dropzone": "^8.1.1",
|
||||||
"@mantine/form": "^8.1.0",
|
"@mantine/form": "^8.1.0",
|
||||||
"@mantine/hooks": "^7.17.4",
|
"@mantine/hooks": "^7.17.4",
|
||||||
"@mantine/modals": "^8.3.6",
|
|
||||||
"@mantine/tiptap": "^7.17.4",
|
"@mantine/tiptap": "^7.17.4",
|
||||||
"@paljs/types": "^8.1.0",
|
"@paljs/types": "^8.1.0",
|
||||||
"@prisma/client": "^6.3.1",
|
"@prisma/client": "^6.3.1",
|
||||||
@@ -41,32 +41,22 @@
|
|||||||
"@tiptap/pm": "^2.11.7",
|
"@tiptap/pm": "^2.11.7",
|
||||||
"@tiptap/react": "^2.11.7",
|
"@tiptap/react": "^2.11.7",
|
||||||
"@tiptap/starter-kit": "^2.11.7",
|
"@tiptap/starter-kit": "^2.11.7",
|
||||||
"@types/adm-zip": "^0.5.7",
|
|
||||||
"@types/bun": "^1.2.2",
|
"@types/bun": "^1.2.2",
|
||||||
"@types/leaflet": "^1.9.20",
|
"@types/leaflet": "^1.9.20",
|
||||||
"@types/lodash": "^4.17.16",
|
"@types/lodash": "^4.17.16",
|
||||||
"@types/nodemailer": "^7.0.2",
|
|
||||||
"add": "^2.0.6",
|
"add": "^2.0.6",
|
||||||
"adm-zip": "^0.5.16",
|
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"bcryptjs": "^3.0.2",
|
"bcryptjs": "^3.0.2",
|
||||||
"bun": "^1.2.2",
|
"bun": "^1.2.2",
|
||||||
"chart.js": "^4.4.8",
|
"chart.js": "^4.4.8",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"colors": "^1.4.0",
|
|
||||||
"date-fns": "^4.1.0",
|
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"dotenv": "^17.2.3",
|
|
||||||
"elysia": "^1.3.5",
|
"elysia": "^1.3.5",
|
||||||
"embla-carousel": "^8.6.0",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-autoplay": "^8.6.0",
|
"embla-carousel-react": "^7.1.0",
|
||||||
"embla-carousel-react": "^8.6.0",
|
|
||||||
"extract-zip": "^2.0.1",
|
|
||||||
"form-data": "^4.0.2",
|
"form-data": "^4.0.2",
|
||||||
"framer-motion": "^12.23.5",
|
"framer-motion": "^12.23.5",
|
||||||
"get-port": "^7.1.0",
|
"get-port": "^7.1.0",
|
||||||
"iron-session": "^8.0.4",
|
|
||||||
"jose": "^6.1.0",
|
|
||||||
"jotai": "^2.12.3",
|
"jotai": "^2.12.3",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
@@ -74,30 +64,24 @@
|
|||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"motion": "^12.4.1",
|
"motion": "^12.4.1",
|
||||||
"nanoid": "^5.1.5",
|
"nanoid": "^5.1.5",
|
||||||
"next": "^15.5.2",
|
"next": "15.1.6",
|
||||||
"next-view-transitions": "^0.3.4",
|
"next-view-transitions": "^0.3.4",
|
||||||
"node-fetch": "^3.3.2",
|
"node-fetch": "^3.3.2",
|
||||||
"nodemailer": "^7.0.10",
|
|
||||||
"p-limit": "^6.2.0",
|
"p-limit": "^6.2.0",
|
||||||
"primeicons": "^7.0.0",
|
"primeicons": "^7.0.0",
|
||||||
"primereact": "^10.9.6",
|
"primereact": "^10.9.6",
|
||||||
"prisma": "^6.3.1",
|
"prisma": "^6.3.1",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-exif-orientation-img": "^0.1.5",
|
|
||||||
"react-international-phone": "^4.6.0",
|
|
||||||
"react-leaflet": "^5.0.0",
|
"react-leaflet": "^5.0.0",
|
||||||
"react-simple-toasts": "^6.1.0",
|
"react-simple-toasts": "^6.1.0",
|
||||||
"react-toastify": "^11.0.5",
|
"react-toastify": "^11.0.5",
|
||||||
"react-transition-group": "^4.4.5",
|
"react-transition-group": "^4.4.5",
|
||||||
"react-zoom-pan-pinch": "^3.7.0",
|
|
||||||
"readdirp": "^4.1.1",
|
"readdirp": "^4.1.1",
|
||||||
"recharts": "^2.15.3",
|
"recharts": "^2.15.3",
|
||||||
"sharp": "^0.34.3",
|
|
||||||
"swr": "^2.3.2",
|
"swr": "^2.3.2",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
"valtio": "^2.1.3",
|
"valtio": "^2.1.3",
|
||||||
"zlib": "^1.0.5",
|
|
||||||
"zod": "^3.24.3"
|
"zod": "^3.24.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: {
|
plugins: {
|
||||||
'postcss-preset-mantine': {},
|
'postcss-preset-mantine': {},
|
||||||
'postcss-simple-vars': {
|
'postcss-simple-vars': {
|
||||||
variables: {
|
variables: {
|
||||||
/* Mobile first */
|
'mantine-breakpoint-xs': '36em',
|
||||||
'mantine-breakpoint-xs': '30em', // 480px → mobile kecil–normal
|
'mantine-breakpoint-sm': '48em',
|
||||||
'mantine-breakpoint-sm': '48em', // 768px → tablet / mobile landscape
|
'mantine-breakpoint-md': '62em',
|
||||||
'mantine-breakpoint-md': '64em', // 1024px → laptop & desktop kecil
|
'mantine-breakpoint-lg': '75em',
|
||||||
'mantine-breakpoint-lg': '80em', // 1280px → desktop standar
|
'mantine-breakpoint-xl': '88em',
|
||||||
'mantine-breakpoint-xl': '90em', // 1440px+ → desktop besar
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
};
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "edit",
|
"id": "1",
|
||||||
"name": "Pelayanan Penduduk Non-Permanent",
|
"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>"
|
"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>"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "edit",
|
"id": "1",
|
||||||
"name": "Pelayanan Perizinan Berusaha Berbasis Risiko Melalui Sistem ONLINE SINGLE SUBMISSION (OSS)",
|
"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>",
|
"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/"
|
"link" : "https://oss.go.id/"
|
||||||
|
|||||||
@@ -47,7 +47,9 @@
|
|||||||
{
|
{
|
||||||
"id" : "cmdxy754q000svniiiz8oqyo0",
|
"id" : "cmdxy754q000svniiiz8oqyo0",
|
||||||
"name" : "Surat Keterangan Belum Kawin",
|
"name" : "Surat Keterangan Belum Kawin",
|
||||||
"deskripsi" : "<p>Persyaratan Dokumen :</p><ul><li><p>Pengantar Kelian Banjar Dinas di Wilayah Masing - masing</p></li><li><p>Fotocopy KTP atau Kartu Keluarga</p></li><li><p>Khusus bagi yang berstatus duda atau janda melampirkan fotocopy akta cerai atau dokumen pendukung lainnya</p></li></ul><p>Alur Pelayanan :</p>"
|
"deskripsi" : "<p>Persyaratan Dokumen :</p><ul><li><p>Pengantar Kelian Banjar Dinas di Wilayah Masing - masing</p></li><li><p>Fotocopy KTP atau Kartu Keluarga</p></li><li><p>Khusus bagi yang berstatus duda atau janda melampirkan fotocopy akta cerai atau dokumen pendukung lainnya</p></li></ul><p>Alur Pelayanan :</p>",
|
||||||
|
"imageId" : "cmeilibnt000007i66s5f73ss",
|
||||||
|
"image2Id" : "cmeilvjmp000007kz9kll5bd2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id" : "cmdxy8pi2000wvnii48fc1sxd",
|
"id" : "cmdxy8pi2000wvnii48fc1sxd",
|
||||||
|
|||||||
@@ -1,99 +1,51 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"month": "Jan",
|
"month": "Jan",
|
||||||
"year": 2025,
|
"year": 2025,
|
||||||
"totalUnemployment": 160,
|
"totalUnemployment": 160,
|
||||||
"educatedUnemployment": 95,
|
"educatedUnemployment": 95,
|
||||||
"uneducatedUnemployment": 65,
|
"uneducatedUnemployment": 65,
|
||||||
"percentageChange": 0.0
|
"percentageChange": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"month": "Feb",
|
"month": "Feb",
|
||||||
"year": 2025,
|
"year": 2025,
|
||||||
"totalUnemployment": 158,
|
"totalUnemployment": 155,
|
||||||
"educatedUnemployment": 93,
|
"educatedUnemployment": 90,
|
||||||
"uneducatedUnemployment": 65,
|
"uneducatedUnemployment": 65,
|
||||||
"percentageChange": -1.25
|
"percentageChange": -3.1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"month": "Mar",
|
"month": "Mar",
|
||||||
"year": 2025,
|
"year": 2025,
|
||||||
"totalUnemployment": 155,
|
"totalUnemployment": 150,
|
||||||
"educatedUnemployment": 91,
|
"educatedUnemployment": 88,
|
||||||
"uneducatedUnemployment": 64,
|
"uneducatedUnemployment": 62,
|
||||||
"percentageChange": -1.90
|
"percentageChange": -3.2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"month": "Apr",
|
"month": "Apr",
|
||||||
"year": 2025,
|
"year": 2025,
|
||||||
"totalUnemployment": 152,
|
"totalUnemployment": 148,
|
||||||
"educatedUnemployment": 89,
|
"educatedUnemployment": 85,
|
||||||
"uneducatedUnemployment": 63,
|
"uneducatedUnemployment": 63,
|
||||||
"percentageChange": -1.94
|
"percentageChange": -1.3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"month": "Mei",
|
"month": "Mei",
|
||||||
"year": 2025,
|
"year": 2025,
|
||||||
"totalUnemployment": 150,
|
"totalUnemployment": 145,
|
||||||
"educatedUnemployment": 88,
|
"educatedUnemployment": 82,
|
||||||
"uneducatedUnemployment": 62,
|
"uneducatedUnemployment": 63,
|
||||||
"percentageChange": -1.32
|
"percentageChange": -2.0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"month": "Jun",
|
"month": "Jun",
|
||||||
"year": 2025,
|
"year": 2025,
|
||||||
"totalUnemployment": 148,
|
"totalUnemployment": 140,
|
||||||
"educatedUnemployment": 87,
|
"educatedUnemployment": 80,
|
||||||
"uneducatedUnemployment": 61,
|
"uneducatedUnemployment": 60,
|
||||||
"percentageChange": -1.33
|
"percentageChange": -3.4
|
||||||
},
|
}
|
||||||
{
|
]
|
||||||
"month": "Jul",
|
|
||||||
"year": 2025,
|
|
||||||
"totalUnemployment": 145,
|
|
||||||
"educatedUnemployment": 85,
|
|
||||||
"uneducatedUnemployment": 60,
|
|
||||||
"percentageChange": -2.03
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"month": "Agu",
|
|
||||||
"year": 2025,
|
|
||||||
"totalUnemployment": 142,
|
|
||||||
"educatedUnemployment": 84,
|
|
||||||
"uneducatedUnemployment": 58,
|
|
||||||
"percentageChange": -2.07
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"month": "Sep",
|
|
||||||
"year": 2025,
|
|
||||||
"totalUnemployment": 140,
|
|
||||||
"educatedUnemployment": 83,
|
|
||||||
"uneducatedUnemployment": 57,
|
|
||||||
"percentageChange": -1.41
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"month": "Okt",
|
|
||||||
"year": 2025,
|
|
||||||
"totalUnemployment": 138,
|
|
||||||
"educatedUnemployment": 82,
|
|
||||||
"uneducatedUnemployment": 56,
|
|
||||||
"percentageChange": -1.43
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"month": "Nov",
|
|
||||||
"year": 2025,
|
|
||||||
"totalUnemployment": 135,
|
|
||||||
"educatedUnemployment": 80,
|
|
||||||
"uneducatedUnemployment": 55,
|
|
||||||
"percentageChange": -2.17
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"month": "Des",
|
|
||||||
"year": 2025,
|
|
||||||
"totalUnemployment": 132,
|
|
||||||
"educatedUnemployment": 78,
|
|
||||||
"uneducatedUnemployment": 54,
|
|
||||||
"percentageChange": -2.22
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": "cmgewz4gt000704ib91i3f169",
|
|
||||||
"namaLengkap": "Ida Bagus Surya Prabhawa Manuaba, S.H.,M.H., NL.P.",
|
|
||||||
"gelarAkademik": "S.H.,M.H.,NL.P.",
|
|
||||||
"tanggalMasuk": "2020-01-01T00:00:00.000Z",
|
|
||||||
"email": "bagus@desa.id",
|
|
||||||
"telepon": "081234567891",
|
|
||||||
"alamat": "Jl. Raya Desa No. 1",
|
|
||||||
"posisiId": "kepala_desa",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmgewxfvw000004ibee5013f4",
|
|
||||||
"namaLengkap": "I Ketut Suwanta",
|
|
||||||
"gelarAkademik": "S.Pt",
|
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
|
||||||
"email": "suwanta@desa.id",
|
|
||||||
"telepon": "081234567892",
|
|
||||||
"alamat": "Jl. Raya Desa No. 2",
|
|
||||||
"posisiId": "sekretaris_desa",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmgewxvqw000104ibgm5l8fzs",
|
|
||||||
"namaLengkap": "Ni Wayan Supardiati",
|
|
||||||
"gelarAkademik": "S.Pd",
|
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
|
||||||
"email": "supardiati@desa.id",
|
|
||||||
"telepon": "081234567892",
|
|
||||||
"alamat": "Jl. Raya Desa No. 2",
|
|
||||||
"posisiId": "kaur_keuangan",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmgewy1g9000204ib2n7hbx0i",
|
|
||||||
"namaLengkap": "I Wayan Agus Juni Artha Saputra",
|
|
||||||
"gelarAkademik": "S.T.",
|
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
|
||||||
"email": "agus@desa.id",
|
|
||||||
"telepon": "081234567892",
|
|
||||||
"alamat": "Jl. Raya Desa No. 2",
|
|
||||||
"posisiId": "kadus_banjar_dinas_menesa",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmgewybah000304ibgqhn1gm2",
|
|
||||||
"namaLengkap": "I Wayan Sueca",
|
|
||||||
"gelarAkademik": "S.H.",
|
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
|
||||||
"email": "sueca@desa.id",
|
|
||||||
"telepon": "081234567893",
|
|
||||||
"alamat": "Jl. Raya Desa No. 2",
|
|
||||||
"posisiId": "kadus_banjar_dinas_darmasaba",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmgewygqz000404ib20sv8nvg",
|
|
||||||
"namaLengkap": "Si Gede Ketut Astawa",
|
|
||||||
"gelarAkademik": "S.T.",
|
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
|
||||||
"email": "astawa@desa.id",
|
|
||||||
"telepon": "081234567893",
|
|
||||||
"alamat": "Jl. Raya Desa No. 2",
|
|
||||||
"posisiId": "kadus_banjar_dinas_bucu",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmgewyos1000504ibcu8o2gyk",
|
|
||||||
"namaLengkap": "I Kadek Arya Minarta",
|
|
||||||
"gelarAkademik": "S.T.",
|
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
|
||||||
"email": "minarta@desa.id",
|
|
||||||
"telepon": "081234567893",
|
|
||||||
"alamat": "Jl. Raya Desa No. 2",
|
|
||||||
"posisiId": "kadus_banjar_dinas_gulingan",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmgewyxk7000604ib8djs3i6c",
|
|
||||||
"namaLengkap": "I Gede Andika Pradnya Diputra",
|
|
||||||
"gelarAkademik": "S.E.",
|
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
|
||||||
"email": "diputra@desa.id",
|
|
||||||
"telepon": "081234567893",
|
|
||||||
"alamat": "Jl. Raya Desa No. 2",
|
|
||||||
"posisiId": "kadus_banjar_dinas_taman",
|
|
||||||
"isActive": true
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
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
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
[
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"id": "kepala_desa",
|
|
||||||
"nama": "Kepala Desa",
|
|
||||||
"deskripsi": "Pemimpin desa Darmasaba",
|
|
||||||
"hierarki": 1,
|
|
||||||
"parentId": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kepala_urusan",
|
|
||||||
"nama": "Kepala Urusan",
|
|
||||||
"deskripsi": "Pemimpin urusan desa Darmasaba",
|
|
||||||
"hierarki": 2,
|
|
||||||
"parentId": "kepala_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sekretaris_desa",
|
|
||||||
"nama": "Sekretaris Desa",
|
|
||||||
"deskripsi": "Pengelola administrasi desa",
|
|
||||||
"hierarki": 2,
|
|
||||||
"parentId": "kepala_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kaur_keuangan",
|
|
||||||
"nama": "Kaur Keuangan",
|
|
||||||
"deskripsi": "Pengelola keuangan desa",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "kaur_umum"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kaur_perencanaan",
|
|
||||||
"nama": "Kaur Perencanaan",
|
|
||||||
"deskripsi": "Penyusun program kerja desa",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "kaur_umum"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kaur_umum",
|
|
||||||
"nama": "Kaur Umum & TU",
|
|
||||||
"deskripsi": "Pelayanan umum dan administrasi",
|
|
||||||
"hierarki": 2,
|
|
||||||
"parentId": "kepala_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kasi_pemerintahan",
|
|
||||||
"nama": "Kasi Pemerintahan",
|
|
||||||
"deskripsi": "Urusan pemerintahan dan keamanan",
|
|
||||||
"hierarki": 2,
|
|
||||||
"parentId": "kepala_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kasi_pelayanan",
|
|
||||||
"nama": "Kasi Pelayanan",
|
|
||||||
"deskripsi": "Urusan pelayanan masyarakat",
|
|
||||||
"hierarki": 2,
|
|
||||||
"parentId": "kepala_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kasi_kesejahteraan",
|
|
||||||
"nama": "Kasi Kesejahteraan",
|
|
||||||
"deskripsi": "Urusan sosial dan kesejahteraan",
|
|
||||||
"hierarki": 2,
|
|
||||||
"parentId": "kepala_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_cabe",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Cabe",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Dinas Cabe",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_menesa",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Menesa",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Menesa",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_penenjoan",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Penenjoan",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Dinas Penenjoan",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_telanga",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Telanga",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Dinas Telanga",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_tengah",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Tengah",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Dinas Tengah",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_baler_pasar",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Baler Pasar",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Dinas Baler Pasar",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_bucu",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Bucu",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Dinas Bucu",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_gulingan",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Gulingan",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Dinas Gulingan",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_bersih",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Bersih",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Dinas Bersih",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_umahanyar",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Umahanyar",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Dinas Umahanyar",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_taman",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Taman",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Dinas Taman",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "kadus_banjar_dinas_darmasaba",
|
|
||||||
"nama": "Kepala Dusun Banjar Dinas Darmasaba",
|
|
||||||
"deskripsi": "Pimpinan wilayah Banjar Dinas Darmasaba",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "staf_desa",
|
|
||||||
"nama": "Staf Desa",
|
|
||||||
"deskripsi": "Staf Desa",
|
|
||||||
"hierarki": 3,
|
|
||||||
"parentId": "sekretaris_desa"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
@@ -1,137 +1,29 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "cmff0rr4z0002vn0twp333m2",
|
"id": "cmeijzdwk000207lb2u4u96wn",
|
||||||
"name": "S6RIjFaPvdQm3oq4rM4X9-desktop.webp",
|
"name": "foto_kades",
|
||||||
"realName": "bares.png",
|
"realName": "kades.jpg",
|
||||||
"path": "uploads/images",
|
"path": "uploads/images/kades.jpg",
|
||||||
"mimeType": "image/webp",
|
"mimeType": "image/jpeg",
|
||||||
"link": "/api/fileStorage/findUnique/S6RIjFaPvdQm3oq4rM4X9-desktop.webp",
|
"link": "https://drive.google.com/file/d/18C_kzKfEWvsGepAHASb2FIwXyyrzMdu2",
|
||||||
"category": "image"
|
"category": "image"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmff0tnf00003vn0t3kgzi0u0",
|
"id": "cmeilibnt000007i66s5f73ss",
|
||||||
"name": "_pVNEmThU5ICGa8gv3gh_-desktop.webp",
|
"name": "surat-keterangan-belum-kawin",
|
||||||
"realName": "bicara-darma.png",
|
"realName": "surat-keterangan-belum-kawin.jpg",
|
||||||
"path": "uploads/images",
|
"path": "uploads/images/surat-keterangan-belum-kawin.jpg",
|
||||||
"mimeType": "image/webp",
|
"mimeType": "image/jpeg",
|
||||||
"link": "/api/fileStorage/findUnique/_pVNEmThU5ICGa8gv3gh_-desktop.webp",
|
"link": "https://drive.google.com/file/d/1S6p1gSlgf5fRt6f3UOtB7r3MIHQ4-BlU",
|
||||||
"category": "image"
|
"category": "image"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmff0uykf0004vn0trmmxpgfh",
|
"id": "cmeilvjmp000007kz9kll5bd2",
|
||||||
"name": "bv6rdKvjxkkjUSGLQ0lvB-desktop.webp",
|
"name": "skema-surat-keterangan-belum-kawin",
|
||||||
"realName": "daves.png",
|
"realName": "skema-surat-keterangan-belum-kawin.jpg",
|
||||||
"path": "uploads/images",
|
"path": "uploads/images/skema-surat-keterangan-belum-kawin.jpg",
|
||||||
"mimeType": "image/webp",
|
"mimeType": "image/jpeg",
|
||||||
"link": "/api/fileStorage/findUnique/bv6rdKvjxkkjUSGLQ0lvB-desktop.webp",
|
"link": "https://drive.google.com/file/d/1vTXobCipplsNj21BefDuEDTHsb-CbyAz",
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff0z34f0005vn0tjtvq519p",
|
|
||||||
"name": "Z4hWaV04CvoE20MjccQsV-desktop.webp",
|
|
||||||
"realName": "mangan.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/Z4hWaV04CvoE20MjccQsV-desktop.webp",
|
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff38cyq000bvn0t9f01cz3f",
|
|
||||||
"name": "LvLAtOqWojx4sn6NjJWB9-desktop.webp",
|
|
||||||
"realName": "gelah-melah.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/LvLAtOqWojx4sn6NjJWB9-desktop.webp",
|
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff0zqvd0007vn0tv6o5hjcq",
|
|
||||||
"name": "gR2mcvAQVgJ2-rM5coYJj-desktop.webp",
|
|
||||||
"realName": "inovasi-desa-darmasaba.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/gR2mcvAQVgJ2-rM5coYJj-desktop.webp",
|
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff1013m0008vn0th7t0d64d",
|
|
||||||
"name": "JpL-9F8-IGztMn8E2ce02-desktop.webp",
|
|
||||||
"realName": "pdkt.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/JpL-9F8-IGztMn8E2ce02-desktop.webp",
|
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff10cwq0009vn0tse8dzu3j",
|
|
||||||
"name": "bxAk4AsGbJTC705_IVdes-desktop.webp",
|
|
||||||
"realName": "sajjiana-dharma-raksaka.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/bxAk4AsGbJTC705_IVdes-desktop.webp",
|
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff2w5ly000avn0telhct71k",
|
|
||||||
"name": "Vbj_osnMJUkGEQGDTLwV--desktop.webp",
|
|
||||||
"realName": "perbekel.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/Vbj_osnMJUkGEQGDTLwV--desktop.webp",
|
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff3joae0000vn6h8sgs0ilg",
|
|
||||||
"name": "7hox9spUxj56hY_EBYLnj-desktop.webp",
|
|
||||||
"realName": "youtube.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/7hox9spUxj56hY_EBYLnj-desktop.webp",
|
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff3ll130001vn6hkhls3f5y",
|
|
||||||
"name": "ChihV7_1eS-AGtSg9UwMv-desktop.webp",
|
|
||||||
"realName": "gmail.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/ChihV7_1eS-AGtSg9UwMv-desktop.webp",
|
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff3mtat0002vn6hs8vyyhdd",
|
|
||||||
"name": "z8v9ZREwOJHKGIRYauROt-desktop.webp",
|
|
||||||
"realName": "facebook.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/z8v9ZREwOJHKGIRYauROt-desktop.webp",
|
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff3nv180003vn6h5jvedidq",
|
|
||||||
"name": "BLjMxTKoCNE31uOURR3IU-desktop.webp",
|
|
||||||
"realName": "telephone-call.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/BLjMxTKoCNE31uOURR3IU-desktop.webp",
|
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff3oouh0004vn6hd94brzv9",
|
|
||||||
"name": "hkJYAeTNWK_vYaYS20w3I-desktop.webp",
|
|
||||||
"realName": "instagram.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/hkJYAeTNWK_vYaYS20w3I-desktop.webp",
|
|
||||||
"category": "image"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmff3q12g0005vn6h5ojov2qa",
|
|
||||||
"name": "6XEoZ9SFu59COpil03Gya-desktop.webp",
|
|
||||||
"realName": "tiktok.png",
|
|
||||||
"path": "uploads/images",
|
|
||||||
"mimeType": "image/webp",
|
|
||||||
"link": "/api/fileStorage/findUnique/6XEoZ9SFu59COpil03Gya-desktop.webp",
|
|
||||||
"category": "image"
|
"category": "image"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
[
|
[
|
||||||
|
{ "name": "Semua" },
|
||||||
{ "name": "Pemerintahan" },
|
{ "name": "Pemerintahan" },
|
||||||
{ "name": "Pembangunan" },
|
{ "name": "Pembangunan" },
|
||||||
{ "name": "Ekonomi" },
|
{ "name": "Ekonomi" },
|
||||||
@@ -3,108 +3,126 @@
|
|||||||
"id": "cmds9h9ko000pvnberdjnx64b",
|
"id": "cmds9h9ko000pvnberdjnx64b",
|
||||||
"name": "1.1 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PERENCANAAN, PELAKSANAAN, PENATAUSAHAAN DAN PERTANGGUNG JAWABAN APBDES BESERTA IMPLEMENTASINYA",
|
"name": "1.1 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PERENCANAAN, PELAKSANAAN, PENATAUSAHAAN DAN PERTANGGUNG JAWABAN APBDES BESERTA IMPLEMENTASINYA",
|
||||||
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PERENCANAAN, PELAKSANAAN, PENATAUSAHAAN DAN PERTANGGUNG JAWABAN APBDES BESERTA IMPLEMENTASINYA</p>",
|
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PERENCANAAN, PELAKSANAAN, PENATAUSAHAAN DAN PERTANGGUNG JAWABAN APBDES BESERTA IMPLEMENTASINYA</p>",
|
||||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh"
|
"kategoriId": "cmds9es2o000ivnbe1o0swrvh",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmds9sjmz000svnbesv2133of",
|
"id": "cmds9sjmz000svnbesv2133of",
|
||||||
"name": "1.2 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP MENGENAI MEKANISME EVALUASI KINERJA PERANGKAT DESA",
|
"name": "1.2 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP MENGENAI MEKANISME EVALUASI KINERJA PERANGKAT DESA",
|
||||||
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP MENGENAI MEKANISME EVALUASI KINERJA PERANGKAT DESA</p>",
|
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP MENGENAI MEKANISME EVALUASI KINERJA PERANGKAT DESA</p>",
|
||||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh"
|
"kategoriId": "cmds9es2o000ivnbe1o0swrvh",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmds9tcpi000vvnbev3ebtlnt",
|
"id": "cmds9tcpi000vvnbev3ebtlnt",
|
||||||
"name": "1.3 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PENGENDALIAN GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN",
|
"name": "1.3 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PENGENDALIAN GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN",
|
||||||
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PENGENDALIAN GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN</p>",
|
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PENGENDALIAN GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN</p>",
|
||||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh"
|
"kategoriId": "cmds9es2o000ivnbe1o0swrvh",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmds9twvj000yvnbep0pq8dzf",
|
"id": "cmds9twvj000yvnbep0pq8dzf",
|
||||||
"name": "1.4 PERJANJIAN KERJA SAMA ANTARA PELAKSANA KEGIATAN ANGGARAN DENGAN PIHAK PENYEDIA, DAN TELAH MELALUI PROSES PENGADAAN BARANG/JASA DI DESA",
|
"name": "1.4 PERJANJIAN KERJA SAMA ANTARA PELAKSANA KEGIATAN ANGGARAN DENGAN PIHAK PENYEDIA, DAN TELAH MELALUI PROSES PENGADAAN BARANG/JASA DI DESA",
|
||||||
"deskripsi": "<p>PERJANJIAN KERJA SAMA ANTARA PELAKSANA KEGIATAN ANGGARAN DENGAN PIHAK PENYEDIA, DAN TELAH MELALUI PROSES PENGADAAN BARANG/JASA DI DESA</p>",
|
"deskripsi": "<p>PERJANJIAN KERJA SAMA ANTARA PELAKSANA KEGIATAN ANGGARAN DENGAN PIHAK PENYEDIA, DAN TELAH MELALUI PROSES PENGADAAN BARANG/JASA DI DESA</p>",
|
||||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh"
|
"kategoriId": "cmds9es2o000ivnbe1o0swrvh",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmds9ugap0011vnbe118yv871",
|
"id": "cmds9ugap0011vnbe118yv871",
|
||||||
"name": "1.5 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PAKTA INTEGRITAS DAN SEJENISNYA",
|
"name": "1.5 ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PAKTA INTEGRITAS DAN SEJENISNYA",
|
||||||
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PAKTA INTEGRITAS DAN SEJENISNYA</p>",
|
"deskripsi": "<p>ADANYA PERDES/KEPUTUSAN KEPALA DESA/SOP TENTANG PAKTA INTEGRITAS DAN SEJENISNYA</p>",
|
||||||
"kategoriId": "cmds9es2o000ivnbe1o0swrvh"
|
"kategoriId": "cmds9es2o000ivnbe1o0swrvh",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsa35310014vnbe6qy6l1rz",
|
"id": "cmdsa35310014vnbe6qy6l1rz",
|
||||||
"name": "2.1 ADANYA KEGIATAN PENGAWASAN DAN EVALUASI KINERJA PERANGKAT DESA",
|
"name": "2.1 ADANYA KEGIATAN PENGAWASAN DAN EVALUASI KINERJA PERANGKAT DESA",
|
||||||
"deskripsi": "<p>ADANYA KEGIATAN PENGAWASAN DAN EVALUASI KINERJA PERANGKAT DESA</p>",
|
"deskripsi": "<p>ADANYA KEGIATAN PENGAWASAN DAN EVALUASI KINERJA PERANGKAT DESA</p>",
|
||||||
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm"
|
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsa46590017vnbepp3noso1",
|
"id": "cmdsa46590017vnbepp3noso1",
|
||||||
"name": "2.2 ADANYA TINDAK LANJUT HASIL PEMBINAAN, PETUNJUK, ARAH, PENGAWASAN, DAN PEMERIKSAAN DARI PEMERINTAH PUSAT/DAERAH",
|
"name": "2.2 ADANYA TINDAK LANJUT HASIL PEMBINAAN, PETUNJUK, ARAH, PENGAWASAN, DAN PEMERIKSAAN DARI PEMERINTAH PUSAT/DAERAH",
|
||||||
"deskripsi": "<p>ADANYA TINDAK LANJUT HASIL PEMBINAAN, PETUNJUK, ARAH, PENGAWASAN, DAN PEMERIKSAAN DARI PEMERINTAH PUSAT/DAERAH</p>",
|
"deskripsi": "<p>ADANYA TINDAK LANJUT HASIL PEMBINAAN, PETUNJUK, ARAH, PENGAWASAN, DAN PEMERIKSAAN DARI PEMERINTAH PUSAT/DAERAH</p>",
|
||||||
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm"
|
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsa5m7z001avnbe4cvfrcz0",
|
"id": "cmdsa5m7z001avnbe4cvfrcz0",
|
||||||
"name": "2.3 TIDAK ADANYA APARATUR DESA DALAM 3(TIGA) TAHUN TERAKHIR YANG TERJERAT TINDAKAN PIDANA KORUPSI",
|
"name": "2.3 TIDAK ADANYA APARATUR DESA DALAM 3(TIGA) TAHUN TERAKHIR YANG TERJERAT TINDAKAN PIDANA KORUPSI",
|
||||||
"deskripsi": "<p>TIDAK ADANYA APARATUR DESA DALAM 3(TIGA) TAHUN TERAKHIR YANG TERJERAT TINDAKAN PIDANA KORUPSI</p>",
|
"deskripsi": "<p>TIDAK ADANYA APARATUR DESA DALAM 3(TIGA) TAHUN TERAKHIR YANG TERJERAT TINDAKAN PIDANA KORUPSI</p>",
|
||||||
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm"
|
"kategoriId": "cmds9f2ua000jvnbeksu1sfwm",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsa8q5q001dvnbemch8j24x",
|
"id": "cmdsa8q5q001dvnbemch8j24x",
|
||||||
"name": "3.1 ADANYA LAYANAN PENGADUAN BAGI MASYARAKAT",
|
"name": "3.1 ADANYA LAYANAN PENGADUAN BAGI MASYARAKAT",
|
||||||
"deskripsi": "<p>ADANYA LAYANAN PENGADUAN BAGI MASYARAKAT</p>",
|
"deskripsi": "<p>ADANYA LAYANAN PENGADUAN BAGI MASYARAKAT</p>",
|
||||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl"
|
"kategoriId": "cmds9fr73000kvnbe6w281dcl",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsa9lbi001gvnbequn2ba7m",
|
"id": "cmdsa9lbi001gvnbequn2ba7m",
|
||||||
"name": "3.2 ADANYA SURVEY KEPUASAN MASYARAKAT (SKM) TERHADAP LAYANAN PEMERINTAH DESA",
|
"name": "3.2 ADANYA SURVEY KEPUASAN MASYARAKAT (SKM) TERHADAP LAYANAN PEMERINTAH DESA",
|
||||||
"deskripsi": "<p>ADANYA SURVEY KEPUASAN MASYARAKAT (SKM) TERHADAP LAYANAN PEMERINTAH DESA</p>",
|
"deskripsi": "<p>ADANYA SURVEY KEPUASAN MASYARAKAT (SKM) TERHADAP LAYANAN PEMERINTAH DESA</p>",
|
||||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl"
|
"kategoriId": "cmds9fr73000kvnbe6w281dcl",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsaa7aq001jvnbeizh04e67",
|
"id": "cmdsaa7aq001jvnbeizh04e67",
|
||||||
"name": "3.3 ADANYA KETERBUKAAN AKSES MASYARAKAT TERHADAP INFORMASI LAYANAN PEMERINTAH DESA (KESEHATAN, PENDIDIKAN, SOSIAL, LINGKUNGAN, TRANTIBUMLINMAS, PEKERJAAN UMUM) PEMBANGUNAN, KEPENDUDUKAN, KEUANGAN, DAN PELAYANAN LAINNYA",
|
"name": "3.3 ADANYA KETERBUKAAN AKSES MASYARAKAT TERHADAP INFORMASI LAYANAN PEMERINTAH DESA (KESEHATAN, PENDIDIKAN, SOSIAL, LINGKUNGAN, TRANTIBUMLINMAS, PEKERJAAN UMUM) PEMBANGUNAN, KEPENDUDUKAN, KEUANGAN, DAN PELAYANAN LAINNYA",
|
||||||
"deskripsi": "<p>ADANYA KETERBUKAAN AKSES MASYARAKAT TERHADAP INFORMASI LAYANAN PEMERINTAH DESA (KESEHATAN, PENDIDIKAN, SOSIAL, LINGKUNGAN, TRANTIBUMLINMAS, PEKERJAAN UMUM) PEMBANGUNAN, KEPENDUDUKAN, KEUANGAN, DAN PELAYANAN LAINNYA</p>",
|
"deskripsi": "<p>ADANYA KETERBUKAAN AKSES MASYARAKAT TERHADAP INFORMASI LAYANAN PEMERINTAH DESA (KESEHATAN, PENDIDIKAN, SOSIAL, LINGKUNGAN, TRANTIBUMLINMAS, PEKERJAAN UMUM) PEMBANGUNAN, KEPENDUDUKAN, KEUANGAN, DAN PELAYANAN LAINNYA</p>",
|
||||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl"
|
"kategoriId": "cmds9fr73000kvnbe6w281dcl",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsaaw8d001mvnbek3tfefrk",
|
"id": "cmdsaaw8d001mvnbek3tfefrk",
|
||||||
"name": "3.4 ADANYA MEDIA INFORMASI TENTANG APBDES DI BALAI DESA DAN/ATAU TEMPAT LAIN YANG MUDAH DIAKSES OLEH MASYARAKAT",
|
"name": "3.4 ADANYA MEDIA INFORMASI TENTANG APBDES DI BALAI DESA DAN/ATAU TEMPAT LAIN YANG MUDAH DIAKSES OLEH MASYARAKAT",
|
||||||
"deskripsi": "<p>ADANYA MEDIA INFORMASI TENTANG APBDES DI BALAI DESA DAN/ATAU TEMPAT LAIN YANG MUDAH DIAKSES OLEH MASYARAKAT</p>",
|
"deskripsi": "<p>ADANYA MEDIA INFORMASI TENTANG APBDES DI BALAI DESA DAN/ATAU TEMPAT LAIN YANG MUDAH DIAKSES OLEH MASYARAKAT</p>",
|
||||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl"
|
"kategoriId": "cmds9fr73000kvnbe6w281dcl",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsabhif001pvnbepm06hry6",
|
"id": "cmdsabhif001pvnbepm06hry6",
|
||||||
"name": "3.5 ADANYA MAKLUMAT PELAYANAN",
|
"name": "3.5 ADANYA MAKLUMAT PELAYANAN",
|
||||||
"deskripsi": "<p>ADANYA MAKLUMAT PELAYANAN</p>",
|
"deskripsi": "<p>ADANYA MAKLUMAT PELAYANAN</p>",
|
||||||
"kategoriId": "cmds9fr73000kvnbe6w281dcl"
|
"kategoriId": "cmds9fr73000kvnbe6w281dcl",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsag40b001svnbe7krq9khc",
|
"id": "cmdsag40b001svnbe7krq9khc",
|
||||||
"name": "4.1 ADANYA PARTISIPASI DAN KETERLIBATAN MASYARAKAT DALAM PENYUSUNAN RKP DESA",
|
"name": "4.1 ADANYA PARTISIPASI DAN KETERLIBATAN MASYARAKAT DALAM PENYUSUNAN RKP DESA",
|
||||||
"deskripsi": "<p>ADANYA PARTISIPASI DAN KETERLIBATAN MASYARAKAT DALAM PENYUSUNAN RKP DESA</p>",
|
"deskripsi": "<p>ADANYA PARTISIPASI DAN KETERLIBATAN MASYARAKAT DALAM PENYUSUNAN RKP DESA</p>",
|
||||||
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv"
|
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsagkaf001vvnbejo26w8sa",
|
"id": "cmdsagkaf001vvnbejo26w8sa",
|
||||||
"name": "4.2 ADANYA KESADARAN MASYARAKAT DALAM MENCEGAH TERJADINYA PRAKTIK GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN",
|
"name": "4.2 ADANYA KESADARAN MASYARAKAT DALAM MENCEGAH TERJADINYA PRAKTIK GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN",
|
||||||
"deskripsi": "<p>ADANYA KESADARAN MASYARAKAT DALAM MENCEGAH TERJADINYA PRAKTIK GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN</p>",
|
"deskripsi": "<p>ADANYA KESADARAN MASYARAKAT DALAM MENCEGAH TERJADINYA PRAKTIK GRATIFIKASI, SUAP DAN KONFLIK KEPENTINGAN</p>",
|
||||||
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv"
|
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsah4qe001yvnbeiy3mwrvb",
|
"id": "cmdsah4qe001yvnbeiy3mwrvb",
|
||||||
"name": "4.3 ADANYA KETERLIBATAN LEMBAGA KEMASYARAKATAN DALAM PELAKSANAAN PEMBANGUNAN DESA",
|
"name": "4.3 ADANYA KETERLIBATAN LEMBAGA KEMASYARAKATAN DALAM PELAKSANAAN PEMBANGUNAN DESA",
|
||||||
"deskripsi": "<p>ADANYA KETERLIBATAN LEMBAGA KEMASYARAKATAN DALAM PELAKSANAAN PEMBANGUNAN DESA</p>",
|
"deskripsi": "<p>ADANYA KETERLIBATAN LEMBAGA KEMASYARAKATAN DALAM PELAKSANAAN PEMBANGUNAN DESA</p>",
|
||||||
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv"
|
"kategoriId": "cmds9g5ow000lvnbel3rkkwrv",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsak5vn0021vnbemg86aab4",
|
"id": "cmdsak5vn0021vnbemg86aab4",
|
||||||
"name": "5.1 ADANYA BUDAYA LOKAL/HUKUM ADAT YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI",
|
"name": "5.1 ADANYA BUDAYA LOKAL/HUKUM ADAT YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI",
|
||||||
"deskripsi": "<p>ADANYA BUDAYA LOKAL/HUKUM ADAT YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI</p>",
|
"deskripsi": "<p>ADANYA BUDAYA LOKAL/HUKUM ADAT YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI</p>",
|
||||||
"kategoriId": "cmds9govb000mvnbesq8b4y99"
|
"kategoriId": "cmds9govb000mvnbesq8b4y99",
|
||||||
|
"fileId": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdsalc800024vnbezgulhgrb",
|
"id": "cmdsalc800024vnbezgulhgrb",
|
||||||
"name": "5.2 ADANYA TOKOH MASYARAKAT, TOKOH AGAMA, TOKOH ADAT, TOKOH PEMUDA, DAN KAUM PEREMPUAN YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI",
|
"name": "5.2 ADANYA TOKOH MASYARAKAT, TOKOH AGAMA, TOKOH ADAT, TOKOH PEMUDA, DAN KAUM PEREMPUAN YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI",
|
||||||
"deskripsi": "<p>ADANYA TOKOH MASYARAKAT, TOKOH AGAMA, TOKOH ADAT, TOKOH PEMUDA, DAN KAUM PEREMPUAN YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI</p>",
|
"deskripsi": "<p>ADANYA TOKOH MASYARAKAT, TOKOH AGAMA, TOKOH ADAT, TOKOH PEMUDA, DAN KAUM PEREMPUAN YANG MENDORONG UPAYA PENCEGAHAN TINDAK PIDANA KORUPSI</p>",
|
||||||
"kategoriId": "cmds9govb000mvnbesq8b4y99"
|
"kategoriId": "cmds9govb000mvnbesq8b4y99",
|
||||||
|
"fileId": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -1,26 +1,32 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"id": "cmds8w2q60002vnbe6i8qhkuo",
|
||||||
|
"name": "Telephone Desa Darmasaba",
|
||||||
|
"iconUrl": "081239580000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cmds8z7u20005vnbegyyvnbk0",
|
||||||
|
"name": "Email Desa Darmasaba",
|
||||||
|
"iconUrl": "desadarmasaba@badungkab.go.id"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "cmds9023u0008vnbe3oxmhwyf",
|
"id": "cmds9023u0008vnbe3oxmhwyf",
|
||||||
"name": "Desa Darmasaba",
|
"name": "Desa Darmasaba",
|
||||||
"iconUrl": "https://www.youtube.com/channel/UCtPw9WOQO7d2HIKzKgel4Xg",
|
"iconUrl": "https://www.youtube.com/channel/UCtPw9WOQO7d2HIKzKgel4Xg"
|
||||||
"imageId": "cmff3joae0000vn6h8sgs0ilg"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmds90oul000bvnbe2bqkptoi",
|
"id": "cmds90oul000bvnbe2bqkptoi",
|
||||||
"name": "Pemerintah Desa Darmasaba",
|
"name": "Pemerintah Desa Darmasaba",
|
||||||
"iconUrl": "https://www.facebook.com/DarmasabaDesaku",
|
"iconUrl": "https://www.facebook.com/DarmasabaDesaku"
|
||||||
"imageId": "cmff3mtat0002vn6hs8vyyhdd"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmds91i4e000evnbe8gtf1gub",
|
"id": "cmds91i4e000evnbe8gtf1gub",
|
||||||
"name": "ddarmasaba",
|
"name": "ddarmasaba",
|
||||||
"iconUrl": "https://www.instagram.com/ddarmasaba/",
|
"iconUrl": "https://www.instagram.com/ddarmasaba/"
|
||||||
"imageId": "cmff3oouh0004vn6hd94brzv9"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmds92de5000hvnbemlu6sq5x",
|
"id": "cmds92de5000hvnbemlu6sq5x",
|
||||||
"name": "desa.darmasaba",
|
"name": "desa.darmasaba",
|
||||||
"iconUrl": "https://www.tiktok.com/@desa.darmasaba?is_from_webapp=1&sender_device=pc",
|
"iconUrl": "https://www.tiktok.com/@desa.darmasaba?is_from_webapp=1&sender_device=pc"
|
||||||
"imageId": "cmff3q12g0005vn6h5ojov2qa"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
{
|
{
|
||||||
"id": "edit",
|
"id": "edit",
|
||||||
"name": "I.B Surya Prabhawa Manuaba, S.H., M.H.",
|
"name": "I.B Surya Prabhawa Manuaba, S.H., M.H.",
|
||||||
"position": "Perbekel Darmasaba periode 2021-2027",
|
"position": "Perbekel Darmasaba periode 2021-2027"
|
||||||
"imageId": "cmff2w5ly000avn0telhct71k"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,51 +1,50 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"id": "cmdr7039z0002vn5rttctt9hn",
|
||||||
|
"name": "Davest",
|
||||||
|
"description": "Darmasaba Village Festval",
|
||||||
|
"link": "https://darmasaba.desa.id/berita/55862-rakor-davest-2024"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdr755pf0005vn5rp8tyuubw",
|
"id": "cmdr755pf0005vn5rp8tyuubw",
|
||||||
"name": "Dmangan",
|
"name": "Dmangan",
|
||||||
"description": "Darmasaba Aman Pangan",
|
"description": "Darmasaba Aman Pangan",
|
||||||
"link": "https://darmasaba.desa.id/berita/61452-kader-d-mangan-berhasil-meraih-prestasi-dalam-ajang-lomba-banjar-bali-quis-bbq-tahun-2024",
|
"link": "https://darmasaba.desa.id/berita/61452-kader-d-mangan-berhasil-meraih-prestasi-dalam-ajang-lomba-banjar-bali-quis-bbq-tahun-2024"
|
||||||
"imageId" : "cmff0z34f0005vn0tjtvq519p"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdr76nqk0008vn5rdddvcxnr",
|
"id": "cmdr76nqk0008vn5rdddvcxnr",
|
||||||
"name": "Bicara Darmasaba",
|
"name": "Bicara Darmasaba",
|
||||||
"description": "Bicara Darmasaba",
|
"description": "Bicara Darmasaba",
|
||||||
"link": "https://darmasaba.desa.id/berita/42506-bicara-darmasaba",
|
"link": "https://darmasaba.desa.id/berita/42506-bicara-darmasaba"
|
||||||
"imageId" : "cmff0tnf00003vn0t3kgzi0u0"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdr77vbw000bvn5rvpmoq31s",
|
"id": "cmdr77vbw000bvn5rvpmoq31s",
|
||||||
"name": "Bares",
|
"name": "Bares",
|
||||||
"description": "Darmasaba Recycling Stock/Exchange",
|
"description": "Darmasaba Recycling Stock/Exchange",
|
||||||
"link": "http://darmasaba.desa.id/berita/56722-bares",
|
"link": "http://darmasaba.desa.id/berita/56722-bares"
|
||||||
"imageId" : "cmff0rr4z0002vn0twp333m2"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdr7bxtp000evn5rmy85wihx",
|
"id": "cmdr7bxtp000evn5rmy85wihx",
|
||||||
"name": "Sajjana Dharma Raksaka",
|
"name": "Sajjana Dharma Raksaka",
|
||||||
"description": "Sajjana Dharma Raksaka",
|
"description": "Sajjana Dharma Raksaka",
|
||||||
"link": "https://ppid.badungkab.go.id/storage/dokumen/5RS9dldGkrgzMQq6bKdZsqsVRHI8gffWv4PGfb3r.pdf",
|
"link": "https://ppid.badungkab.go.id/storage/dokumen/5RS9dldGkrgzMQq6bKdZsqsVRHI8gffWv4PGfb3r.pdf"
|
||||||
"imageId" : "cmff10cwq0009vn0tse8dzu3j"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdr7dlnk000hvn5r9lur3z35",
|
"id": "cmdr7dlnk000hvn5r9lur3z35",
|
||||||
"name": "PDKT",
|
"name": "PDKT",
|
||||||
"description": "Perangkat Desa Kuat Teknologi",
|
"description": "Perangkat Desa Kuat Teknologi",
|
||||||
"link": "https://darmasaba.desa.id/berita/53752-p-d-k-t",
|
"link": "https://darmasaba.desa.id/berita/53752-p-d-k-t"
|
||||||
"imageId" : "cmff1013m0008vn0th7t0d64d"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdr7ftob000mvn5rfhgdtg8v",
|
"id": "cmdr7ftob000mvn5rfhgdtg8v",
|
||||||
"name": "GM",
|
"name": "GM",
|
||||||
"description": "Galah Melah",
|
"description": "Galah Melah",
|
||||||
"link": "https://darmasaba.desa.id/berita/52880-galah-melah",
|
"link": "https://darmasaba.desa.id/berita/52880-galah-melah"
|
||||||
"imageId" : "cmff38cyq000bvn0t9f01cz3f"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmdr7glue000pvn5r6onzslju",
|
"id": "cmdr7glue000pvn5r6onzslju",
|
||||||
"name": "Inovasi Desa Darmasaba",
|
"name": "Inovasi Desa Darmasaba",
|
||||||
"description": "Inovasi Desa Darmasaba",
|
"description": "Inovasi Desa Darmasaba",
|
||||||
"link": "https://darmasaba.desa.id/produk-lokal-desa",
|
"link": "https://darmasaba.desa.id/produk-lokal-desa"
|
||||||
"imageId" : "cmff0zqvd0007vn0tv6o5hjcq"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
[
|
|
||||||
{ "nama": "Kebersihan" },
|
|
||||||
{ "nama": "Infrastruktur" },
|
|
||||||
{ "nama": "Sosial" },
|
|
||||||
{ "nama": "Lingkungan" }
|
|
||||||
]
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
[
|
|
||||||
{ "id": "cmghqwjs4000404l8c5uvc300", "nama": "PAUD" },
|
|
||||||
{ "id": "cmghqwjs4000404l8c5uvc301", "nama": "TK" },
|
|
||||||
{ "id": "cmghqwjs4000404l8c5uvc302", "nama": "SD" },
|
|
||||||
{ "id": "cmghqwjs4000404l8c5uvc303", "nama": "SMP" },
|
|
||||||
{ "id": "cmghqwjs4000404l8c5uvc304", "nama": "SMA" },
|
|
||||||
{ "id": "cmghqwjs4000404l8c5uvc305", "nama": "SMK" }
|
|
||||||
]
|
|
||||||
|
|
||||||
@@ -1,14 +1,8 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "cmeppcwzk0000vn5exmudcipd",
|
"id": "1",
|
||||||
"jenisInformasi": "Potensi Desa",
|
"jenisInformasi": "Peraturan Desa",
|
||||||
"deskripsi": "<p>“Potensi desa adalah segenap sumber daya alam dan sumber daya manusia yang dimiliki desa sebagai modal dasar yang perlu dikelola dan dikembangkan bagi kelangsungan dan perkembangan desa. Adapun potensi yang dimiliki Desa Darmasaba yaitu:</p><ol><li><p>TPS3R Pudak Mesari</p></li><li><p>Bumdes Pudak Mesari</p></li><li><p>Pertanian</p></li><li><p>Jogging Track Tegeh Aban, Karang Gadon dan Munduk Uma Desa</p></li><li><p>Taman Beji Cengana</p></li><li><p>Dam Tanah Putih</p></li><li><p>Gumuh Sari Water Park</p></li><li><p>UMKM</p></li><li><p>Kawasan Kuliner</p></li><li><p>IKM berbasis Pengolahan Pangan</p></li><li><p>Genteng</p></li><li><p>Peternakan Ikan Lele</p></li><li><p>Pemotongan Daging”</p></li></ol>",
|
"deskripsi": "Dokumen yang berisi kebijakan dan regulasi desa",
|
||||||
"tanggal": "2021-05-25"
|
"tanggal": "15 Januari 2024"
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmeppieay0001vn5e8qe658ub",
|
|
||||||
"jenisInformasi": "Layanan Surat Keterangan Desa",
|
|
||||||
"deskripsi": "<p>“Desa Darmasaba menyediakan berbagai jenis layanan surat keterangan untuk kebutuhan administratif, antara lain:</p><ul><li><p>Surat Keterangan Domisili Organisasi</p></li><li><p>Surat Keterangan Penghasilan</p></li><li><p>Surat Keterangan Tidak Mampu</p></li><li><p>Surat Keterangan Kelahiran</p></li><li><p>Surat Keterangan Usaha</p></li><li><p>Surat Keterangan Tempat Usaha</p></li><li><p>Surat Keterangan Belum Kawin</p></li><li><p>Surat Keterangan Kelakuan Baik (Pengantar SKCK)</p></li><li><p>Surat Keterangan Kematian</p></li><li><p>Surat Keterangan Perbedaan Biodata Diri</p></li><li><p>Surat Keterangan Yatim/Piatu/Yatim Piatu<br>Untuk surat keterangan lainnya, masyarakat dapat berkonsultasi langsung ke kantor Perbekel Darmasaba.”<br><em>(Sumber: Laman Layanan Desa Darmasaba)</em></p></li></ul>",
|
|
||||||
"tanggal": "2025-02-21"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
"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>",
|
"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>",
|
"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>",
|
"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>"
|
"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>",
|
||||||
|
"imageId": "cmeijzdwk000207lb2u4u96wn"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "cmgewz4gt000704ib91i3f169",
|
"id": "550e8400-e29b-41d4-a716-446655440001",
|
||||||
"namaLengkap": "Ida Bagus Surya Prabhawa Manuaba, S.H.,M.H., NL.P.",
|
"namaLengkap": "Ida Bagus Surya Prabhawa Manuaba, S.H.,M.H., NL.P.",
|
||||||
"gelarAkademik": "S.H.,M.H.,NL.P.",
|
"gelarAkademik": "S.H.,M.H.,NL.P.",
|
||||||
"tanggalMasuk": "2020-01-01T00:00:00.000Z",
|
"tanggalMasuk": "2020-01-01T00:00:00.000Z",
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
"isActive": true
|
"isActive": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmgewxfvw000004ibee5013f4",
|
"id": "550e8400-e29b-41d4-a716-446655440002",
|
||||||
"namaLengkap": "I Ketut Suwanta",
|
"namaLengkap": "I Ketut Suwanta",
|
||||||
"gelarAkademik": "S.Pt",
|
"gelarAkademik": "S.Pt",
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
"isActive": true
|
"isActive": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmgewxvqw000104ibgm5l8fzs",
|
"id": "550e8400-e29b-41d4-a716-446655440006",
|
||||||
"namaLengkap": "Ni Wayan Supardiati",
|
"namaLengkap": "Ni Wayan Supardiati",
|
||||||
"gelarAkademik": "S.Pd",
|
"gelarAkademik": "S.Pd",
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
"isActive": true
|
"isActive": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmgewy1g9000204ib2n7hbx0i",
|
"id": "550e8400-e29b-41d4-a716-446655440011",
|
||||||
"namaLengkap": "I Wayan Agus Juni Artha Saputra",
|
"namaLengkap": "I Wayan Agus Juni Artha Saputra",
|
||||||
"gelarAkademik": "S.T.",
|
"gelarAkademik": "S.T.",
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
"isActive": true
|
"isActive": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmgewybah000304ibgqhn1gm2",
|
"id": "550e8400-e29b-41d4-a716-446655440012",
|
||||||
"namaLengkap": "I Wayan Sueca",
|
"namaLengkap": "I Wayan Sueca",
|
||||||
"gelarAkademik": "S.H.",
|
"gelarAkademik": "S.H.",
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
"isActive": true
|
"isActive": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmgewygqz000404ib20sv8nvg",
|
"id": "550e8400-e29b-41d4-a716-446655440017",
|
||||||
"namaLengkap": "Si Gede Ketut Astawa",
|
"namaLengkap": "Si Gede Ketut Astawa",
|
||||||
"gelarAkademik": "S.T.",
|
"gelarAkademik": "S.T.",
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
"isActive": true
|
"isActive": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmgewyos1000504ibcu8o2gyk",
|
"id": "550e8400-e29b-41d4-a716-446655440018",
|
||||||
"namaLengkap": "I Kadek Arya Minarta",
|
"namaLengkap": "I Kadek Arya Minarta",
|
||||||
"gelarAkademik": "S.T.",
|
"gelarAkademik": "S.T.",
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
"isActive": true
|
"isActive": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cmgewyxk7000604ib8djs3i6c",
|
"id": "550e8400-e29b-41d4-a716-446655440021",
|
||||||
"namaLengkap": "I Gede Andika Pradnya Diputra",
|
"namaLengkap": "I Gede Andika Pradnya Diputra",
|
||||||
"gelarAkademik": "S.E.",
|
"gelarAkademik": "S.E.",
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
||||||
|
|||||||
6
prisma/data/user/role.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "cmdpm429r0000vnndkcwslt0h",
|
||||||
|
"name": "warga"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": "0",
|
|
||||||
"name": "DEVELOPER",
|
|
||||||
"description": "Developer",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "1",
|
|
||||||
"name": "SUPER ADMIN",
|
|
||||||
"description": "Administrator",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "2",
|
|
||||||
"name": "ADMIN DESA",
|
|
||||||
"description": "Administrator Desa",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "3",
|
|
||||||
"name": "ADMIN KESEHATAN",
|
|
||||||
"description": "Administrator Bidang Kesehatan",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "4",
|
|
||||||
"name": "ADMIN PENDIDIKAN",
|
|
||||||
"description": "Administrator Bidang Pendidikan",
|
|
||||||
"isActive": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": "cmie1o0zh0002vn132vtzg7hh",
|
|
||||||
"username": "SuperAdmin-Nico",
|
|
||||||
"nomor": "6289647037426",
|
|
||||||
"roleId": 0,
|
|
||||||
"isActive": true,
|
|
||||||
"sessionInvalid": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
// helpers/safeSeedUnique.ts
|
|
||||||
import { PrismaClient } from "@prisma/client";
|
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper generic buat seed dengan upsert aman
|
|
||||||
*/
|
|
||||||
export async function safeSeedUnique<T extends keyof PrismaClient>(
|
|
||||||
model: T,
|
|
||||||
where: Record<string, any>,
|
|
||||||
data: Record<string, any>
|
|
||||||
) {
|
|
||||||
const m = prisma[model];
|
|
||||||
|
|
||||||
if (!m) throw new Error(`Model ${String(model)} tidak ditemukan di PrismaClient`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// @ts-expect-error upsert dynamic
|
|
||||||
await m.upsert({
|
|
||||||
where,
|
|
||||||
update: data,
|
|
||||||
create: { ...where, ...data },
|
|
||||||
});
|
|
||||||
console.log(`✅ Seeded ${String(model)} -> ${JSON.stringify(where)}`);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`❌ Gagal seed ${String(model)} -> ${JSON.stringify(where)}`, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -81,8 +81,11 @@ model FileStorage {
|
|||||||
PelayananSuratKeteranganImage PelayananSuratKeterangan[] @relation("PelayananSuratKeteranganImage")
|
PelayananSuratKeteranganImage PelayananSuratKeterangan[] @relation("PelayananSuratKeteranganImage")
|
||||||
PelayananSuratKeteranganImage2 PelayananSuratKeterangan[] @relation("PelayananSuratKeteranganImage2")
|
PelayananSuratKeteranganImage2 PelayananSuratKeterangan[] @relation("PelayananSuratKeteranganImage2")
|
||||||
PasarDesa PasarDesa[]
|
PasarDesa PasarDesa[]
|
||||||
PegawaiBumDes PegawaiBumDes[]
|
KontakDaruratKeamanan KontakDaruratKeamanan[]
|
||||||
|
KontakItem KontakItem[]
|
||||||
|
Pegawai Pegawai[]
|
||||||
DesaDigital DesaDigital[]
|
DesaDigital DesaDigital[]
|
||||||
|
KolaborasiInovasi KolaborasiInovasi[]
|
||||||
InfoTekno InfoTekno[]
|
InfoTekno InfoTekno[]
|
||||||
PengaduanMasyarakat PengaduanMasyarakat[]
|
PengaduanMasyarakat PengaduanMasyarakat[]
|
||||||
KegiatanDesa KegiatanDesa[]
|
KegiatanDesa KegiatanDesa[]
|
||||||
@@ -90,18 +93,13 @@ model FileStorage {
|
|||||||
PejabatDesa PejabatDesa[]
|
PejabatDesa PejabatDesa[]
|
||||||
MediaSosial MediaSosial[]
|
MediaSosial MediaSosial[]
|
||||||
DesaAntiKorupsi DesaAntiKorupsi[]
|
DesaAntiKorupsi DesaAntiKorupsi[]
|
||||||
SDGSDesa SdgsDesa[]
|
SDGSDesa SDGSDesa[]
|
||||||
APBDesImage APBDes[] @relation("APBDesImage")
|
APBDesImage APBDes[] @relation("APBDesImage")
|
||||||
APBDesFile APBDes[] @relation("APBDesFile")
|
APBDesFile APBDes[] @relation("APBDesFile")
|
||||||
PrestasiDesa PrestasiDesa[]
|
PrestasiDesa PrestasiDesa[]
|
||||||
DataPerpustakaan DataPerpustakaan[]
|
DataPerpustakaan DataPerpustakaan[]
|
||||||
PegawaiPPID PegawaiPPID[]
|
PegawaiPPID PegawaiPPID[]
|
||||||
PerbekelDariMasaKeMasa PerbekelDariMasaKeMasa[]
|
PerbekelDariMasaKeMasa PerbekelDariMasaKeMasa[]
|
||||||
|
|
||||||
MitraKolaborasi MitraKolaborasi[]
|
|
||||||
|
|
||||||
ArtikelKesehatan ArtikelKesehatan[]
|
|
||||||
StrukturBumDes StrukturBumDes[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//========================================= MENU LANDING PAGE ========================================= //
|
//========================================= MENU LANDING PAGE ========================================= //
|
||||||
@@ -136,7 +134,6 @@ model MediaSosial {
|
|||||||
name String
|
name String
|
||||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||||
imageId String?
|
imageId String?
|
||||||
icon String?
|
|
||||||
iconUrl String? @db.VarChar(255)
|
iconUrl String? @db.VarChar(255)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
@@ -144,7 +141,7 @@ model MediaSosial {
|
|||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
//========================================= DESA ANTI KORUPSI ========================================= //
|
//========================================= PROFILE ========================================= //
|
||||||
model DesaAntiKorupsi {
|
model DesaAntiKorupsi {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String @unique
|
name String @unique
|
||||||
@@ -170,9 +167,9 @@ model KategoriDesaAntiKorupsi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//========================================= SDGS Desa ========================================= //
|
//========================================= SDGS Desa ========================================= //
|
||||||
model SdgsDesa {
|
model SDGSDesa {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String
|
name String @unique
|
||||||
jumlah String
|
jumlah String
|
||||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||||
imageId String?
|
imageId String?
|
||||||
@@ -185,55 +182,27 @@ model SdgsDesa {
|
|||||||
//========================================= APBDes ========================================= //
|
//========================================= APBDes ========================================= //
|
||||||
model APBDes {
|
model APBDes {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
tahun Int?
|
name String @unique
|
||||||
name String? // misalnya: "APBDes Tahun 2025"
|
jumlah String
|
||||||
deskripsi String?
|
|
||||||
jumlah String? // total keseluruhan (opsional, bisa juga dihitung dari items)
|
|
||||||
items APBDesItem[]
|
|
||||||
image FileStorage? @relation("APBDesImage", fields: [imageId], references: [id])
|
image FileStorage? @relation("APBDesImage", fields: [imageId], references: [id])
|
||||||
imageId String?
|
imageId String?
|
||||||
file FileStorage? @relation("APBDesFile", fields: [fileId], references: [id])
|
file FileStorage? @relation("APBDesFile", fields: [fileId], references: [id])
|
||||||
fileId String?
|
fileId String?
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deletedAt DateTime? // opsional, tidak perlu default now()
|
deletedAt DateTime @default(now())
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
model APBDesItem {
|
|
||||||
id String @id @default(cuid())
|
|
||||||
kode String // contoh: "4", "4.1", "4.1.2"
|
|
||||||
uraian String // nama item, contoh: "Pendapatan Asli Desa", "Hasil Usaha"
|
|
||||||
anggaran Float // dalam satuan Rupiah (bisa DECIMAL di DB, tapi Float umum di TS/JS)
|
|
||||||
realisasi Float
|
|
||||||
selisih Float // realisasi - anggaran
|
|
||||||
persentase Float
|
|
||||||
tipe String? // (realisasi / anggaran) * 100
|
|
||||||
level Int // 1 = kelompok utama, 2 = sub-kelompok, 3 = detail
|
|
||||||
parentId String? // untuk relasi hierarki
|
|
||||||
parent APBDesItem? @relation("APBDesItemParent", fields: [parentId], references: [id])
|
|
||||||
children APBDesItem[] @relation("APBDesItemParent")
|
|
||||||
apbdesId String
|
|
||||||
apbdes APBDes @relation(fields: [apbdesId], references: [id])
|
|
||||||
createdAt DateTime @default(now())
|
|
||||||
updatedAt DateTime @updatedAt
|
|
||||||
deletedAt DateTime?
|
|
||||||
isActive Boolean @default(true)
|
|
||||||
|
|
||||||
@@index([kode])
|
|
||||||
@@index([level])
|
|
||||||
@@index([apbdesId])
|
|
||||||
}
|
|
||||||
|
|
||||||
//========================================= PRESTASI DESA ========================================= //
|
//========================================= PRESTASI DESA ========================================= //
|
||||||
model PrestasiDesa {
|
model PrestasiDesa {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String
|
name String @unique
|
||||||
deskripsi String @db.Text
|
deskripsi String @db.Text
|
||||||
kategori KategoriPrestasiDesa @relation(fields: [kategoriId], references: [id])
|
kategori KategoriPrestasiDesa @relation(fields: [kategoriId], references: [id])
|
||||||
kategoriId String
|
kategoriId String
|
||||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
image FileStorage @relation(fields: [imageId], references: [id])
|
||||||
imageId String?
|
imageId String
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deletedAt DateTime @default(now())
|
deletedAt DateTime @default(now())
|
||||||
@@ -254,7 +223,7 @@ model KategoriPrestasiDesa {
|
|||||||
model Responden {
|
model Responden {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String @unique
|
name String @unique
|
||||||
tanggal DateTime @db.Date // misal: 2025-05-01
|
tanggal String // misal: 2025-05-01
|
||||||
jenisKelamin JenisKelaminResponden @relation(fields: [jenisKelaminId], references: [id])
|
jenisKelamin JenisKelaminResponden @relation(fields: [jenisKelaminId], references: [id])
|
||||||
jenisKelaminId String
|
jenisKelaminId String
|
||||||
rating PilihanRatingResponden @relation(fields: [ratingId], references: [id])
|
rating PilihanRatingResponden @relation(fields: [ratingId], references: [id])
|
||||||
@@ -316,51 +285,46 @@ model StrukturPPID {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model PosisiOrganisasiPPID {
|
model PosisiOrganisasiPPID {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
nama String @db.VarChar(100)
|
nama String @db.VarChar(100)
|
||||||
deskripsi String? @db.Text
|
deskripsi String? @db.Text
|
||||||
hierarki Int
|
hierarki Int
|
||||||
pegawai PegawaiPPID[]
|
pegawai PegawaiPPID[]
|
||||||
strukturOrganisasi StrukturPPID[] // Relasi balik
|
strukturOrganisasi StrukturPPID[] // Relasi balik
|
||||||
parentId String?
|
parentId String?
|
||||||
isActive Boolean @default(true)
|
parent PosisiOrganisasiPPID? @relation("Parent", fields: [parentId], references: [id])
|
||||||
createdAt DateTime @default(now())
|
children PosisiOrganisasiPPID[] @relation("Parent")
|
||||||
updatedAt DateTime @updatedAt
|
|
||||||
parent PosisiOrganisasiPPID? @relation("Parent", fields: [parentId], references: [id])
|
|
||||||
children PosisiOrganisasiPPID[] @relation("Parent")
|
|
||||||
StrukturOrganisasiPPID StrukturOrganisasiPPID[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model PegawaiPPID {
|
model PegawaiPPID {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
namaLengkap String @db.VarChar(255)
|
namaLengkap String @db.VarChar(255)
|
||||||
gelarAkademik String? @db.VarChar(100)
|
gelarAkademik String? @db.VarChar(100)
|
||||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||||
imageId String?
|
imageId String?
|
||||||
tanggalMasuk DateTime? @db.Date
|
tanggalMasuk DateTime? @db.Date
|
||||||
email String? @unique @db.VarChar(255)
|
email String? @unique @db.VarChar(255)
|
||||||
telepon String? @db.VarChar(20)
|
telepon String? @db.VarChar(20)
|
||||||
alamat String? @db.Text
|
alamat String? @db.Text
|
||||||
posisiId String @db.VarChar(50)
|
posisiId String @db.VarChar(50)
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
posisi PosisiOrganisasiPPID @relation(fields: [posisiId], references: [id])
|
posisi PosisiOrganisasiPPID @relation(fields: [posisiId], references: [id])
|
||||||
strukturOrganisasi StrukturPPID[] // Relasi balik
|
strukturOrganisasi StrukturPPID[] // Relasi balik
|
||||||
StrukturOrganisasiPPID StrukturOrganisasiPPID[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model StrukturOrganisasiPPID {
|
model StrukturOrganisasiPPID {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
posisiOrganisasiId String @db.VarChar(50)
|
posisiOrganisasiId String @db.VarChar(50)
|
||||||
pegawaiId String
|
pegawaiId String @db.Uuid
|
||||||
hubunganOrganisasiId String
|
hubunganOrganisasiId String @db.Uuid
|
||||||
posisiOrganisasi PosisiOrganisasiPPID @relation(fields: [posisiOrganisasiId], references: [id])
|
posisiOrganisasi PosisiOrganisasi @relation(fields: [posisiOrganisasiId], references: [id])
|
||||||
pegawai PegawaiPPID @relation(fields: [pegawaiId], references: [id])
|
pegawai Pegawai @relation(fields: [pegawaiId], references: [id])
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deletedAt DateTime?
|
deletedAt DateTime?
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================= VISI MISI PPID ========================================= //
|
// ========================================= VISI MISI PPID ========================================= //
|
||||||
@@ -704,18 +668,17 @@ model GalleryVideo {
|
|||||||
|
|
||||||
// ========================================= LAYANAN DESA ========================================= //
|
// ========================================= LAYANAN DESA ========================================= //
|
||||||
model PelayananSuratKeterangan {
|
model PelayananSuratKeterangan {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String
|
name String
|
||||||
deskripsi String @db.Text
|
deskripsi String @db.Text
|
||||||
image FileStorage? @relation("PelayananSuratKeteranganImage", fields: [imageId], references: [id])
|
image FileStorage? @relation("PelayananSuratKeteranganImage", fields: [imageId], references: [id])
|
||||||
imageId String?
|
imageId String?
|
||||||
image2 FileStorage? @relation("PelayananSuratKeteranganImage2", fields: [image2Id], references: [id])
|
image2 FileStorage? @relation("PelayananSuratKeteranganImage2", fields: [image2Id], references: [id])
|
||||||
image2Id String?
|
image2Id String?
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deletedAt DateTime @default(now())
|
deletedAt DateTime @default(now())
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
AjukanPermohonan AjukanPermohonan[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model PelayananTelunjukSaktiDesa {
|
model PelayananTelunjukSaktiDesa {
|
||||||
@@ -750,20 +713,6 @@ model PelayananPendudukNonPermanen {
|
|||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
model AjukanPermohonan {
|
|
||||||
id String @id @default(cuid())
|
|
||||||
nama String
|
|
||||||
nik String
|
|
||||||
alamat String
|
|
||||||
nomorKk String
|
|
||||||
kategori PelayananSuratKeterangan @relation(fields: [kategoriId], references: [id])
|
|
||||||
kategoriId String
|
|
||||||
createdAt DateTime @default(now())
|
|
||||||
updatedAt DateTime @updatedAt
|
|
||||||
deletedAt DateTime @default(now())
|
|
||||||
isActive Boolean @default(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================= PENGHARGAAN ========================================= //
|
// ========================================= PENGHARGAAN ========================================= //
|
||||||
model Penghargaan {
|
model Penghargaan {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
@@ -783,22 +732,24 @@ model Penghargaan {
|
|||||||
|
|
||||||
// ========================================= FASILITAS KESEHATAN ========================================= //
|
// ========================================= FASILITAS KESEHATAN ========================================= //
|
||||||
model FasilitasKesehatan {
|
model FasilitasKesehatan {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String
|
name String
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deletedAt DateTime @default(now())
|
deletedAt DateTime @default(now())
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
informasiumum InformasiUmum @relation(fields: [informasiUmumId], references: [id])
|
informasiumum InformasiUmum @relation(fields: [informasiUmumId], references: [id])
|
||||||
informasiUmumId String
|
informasiUmumId String
|
||||||
layananunggulan LayananUnggulan @relation(fields: [layananUnggulanId], references: [id])
|
layananunggulan LayananUnggulan @relation(fields: [layananUnggulanId], references: [id])
|
||||||
layananUnggulanId String
|
layananUnggulanId String
|
||||||
dokterdantenagamedis DokterdanTenagaMedis[] @relation("Dokter")
|
dokterdantenagamedis DokterdanTenagaMedis @relation(fields: [dokterdanTenagaMedisId], references: [id])
|
||||||
fasilitaspendukung FasilitasPendukung @relation(fields: [fasilitasPendukungId], references: [id])
|
dokterdanTenagaMedisId String
|
||||||
fasilitasPendukungId String
|
fasilitaspendukung FasilitasPendukung @relation(fields: [fasilitasPendukungId], references: [id])
|
||||||
prosedurpendaftaran ProsedurPendaftaran @relation(fields: [prosedurPendaftaranId], references: [id])
|
fasilitasPendukungId String
|
||||||
prosedurPendaftaranId String
|
prosedurpendaftaran ProsedurPendaftaran @relation(fields: [prosedurPendaftaranId], references: [id])
|
||||||
tarifdanlayanan TarifDanLayanan[] @relation("Tarif")
|
prosedurPendaftaranId String
|
||||||
|
tarifdanlayanan TarifDanLayanan @relation(fields: [tarifDanLayananId], references: [id])
|
||||||
|
tarifDanLayananId String
|
||||||
}
|
}
|
||||||
|
|
||||||
model InformasiUmum {
|
model InformasiUmum {
|
||||||
@@ -824,20 +775,15 @@ model LayananUnggulan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model DokterdanTenagaMedis {
|
model DokterdanTenagaMedis {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String
|
name String
|
||||||
specialist String
|
specialist String
|
||||||
jadwal String
|
jadwal String
|
||||||
jadwalLibur String?
|
createdAt DateTime @default(now())
|
||||||
jamBukaOperasional String?
|
updatedAt DateTime @updatedAt
|
||||||
jamTutupOperasional String?
|
deletedAt DateTime @default(now())
|
||||||
jamBukaLibur String?
|
isActive Boolean @default(true)
|
||||||
jamTutupLibur String?
|
FasilitasKesehatan FasilitasKesehatan[]
|
||||||
createdAt DateTime @default(now())
|
|
||||||
updatedAt DateTime @updatedAt
|
|
||||||
deletedAt DateTime @default(now())
|
|
||||||
isActive Boolean @default(true)
|
|
||||||
FasilitasKesehatan FasilitasKesehatan[] @relation("Dokter")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model FasilitasPendukung {
|
model FasilitasPendukung {
|
||||||
@@ -868,7 +814,7 @@ model TarifDanLayanan {
|
|||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deletedAt DateTime @default(now())
|
deletedAt DateTime @default(now())
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
FasilitasKesehatan FasilitasKesehatan[] @relation("Tarif")
|
FasilitasKesehatan FasilitasKesehatan[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================= JADWAL KEGIATAN ========================================= //
|
// ========================================= JADWAL KEGIATAN ========================================= //
|
||||||
@@ -885,8 +831,8 @@ model JadwalKegiatan {
|
|||||||
syaratKetentuanJadwalKegiatanId String
|
syaratKetentuanJadwalKegiatanId String
|
||||||
dokumenjadwalkegiatan DokumenJadwalKegiatan @relation(fields: [dokumenJadwalKegiatanId], references: [id])
|
dokumenjadwalkegiatan DokumenJadwalKegiatan @relation(fields: [dokumenJadwalKegiatanId], references: [id])
|
||||||
dokumenJadwalKegiatanId String
|
dokumenJadwalKegiatanId String
|
||||||
pendaftaranjadwalkegiatan PendaftaranJadwalKegiatan? @relation(fields: [pendaftaranJadwalKegiatanId], references: [id])
|
pendaftaranjadwalkegiatan PendaftaranJadwalKegiatan @relation(fields: [pendaftaranJadwalKegiatanId], references: [id])
|
||||||
pendaftaranJadwalKegiatanId String?
|
pendaftaranJadwalKegiatanId String
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deletedAt DateTime @default(now())
|
deletedAt DateTime @default(now())
|
||||||
@@ -1022,10 +968,8 @@ model ArtikelKesehatan {
|
|||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
title String
|
title String
|
||||||
content String
|
content String
|
||||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
|
||||||
imageId String?
|
|
||||||
introductionId String
|
|
||||||
introduction Introduction @relation(fields: [introductionId], references: [id])
|
introduction Introduction @relation(fields: [introductionId], references: [id])
|
||||||
|
introductionId String
|
||||||
symptom Symptom @relation(fields: [symptomId], references: [id])
|
symptom Symptom @relation(fields: [symptomId], references: [id])
|
||||||
symptomId String
|
symptomId String
|
||||||
prevention Prevention @relation(fields: [preventionId], references: [id])
|
prevention Prevention @relation(fields: [preventionId], references: [id])
|
||||||
@@ -1202,7 +1146,6 @@ model KontakDarurat {
|
|||||||
deskripsi String
|
deskripsi String
|
||||||
image FileStorage @relation(fields: [imageId], references: [id])
|
image FileStorage @relation(fields: [imageId], references: [id])
|
||||||
imageId String
|
imageId String
|
||||||
whatsapp String
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deletedAt DateTime @default(now())
|
deletedAt DateTime @default(now())
|
||||||
@@ -1269,51 +1212,71 @@ model LayananPolsek {
|
|||||||
|
|
||||||
// ========================================= KONTAK DARURAT ========================================= //
|
// ========================================= KONTAK DARURAT ========================================= //
|
||||||
model KontakDaruratKeamanan {
|
model KontakDaruratKeamanan {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
nama String
|
nama String // contoh: "Layanan Darurat", "Fasilitas Kesehatan"
|
||||||
icon String
|
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||||
kategori KontakItem @relation(fields: [kategoriId], references: [id])
|
imageId String?
|
||||||
kategoriId String
|
kontakItems KontakItem[]
|
||||||
kontakItems KontakDaruratToItem[]
|
createdAt DateTime @default(now())
|
||||||
createdAt DateTime @default(now())
|
updatedAt DateTime @updatedAt
|
||||||
updatedAt DateTime @updatedAt
|
|
||||||
deletedAt DateTime?
|
|
||||||
isActive Boolean @default(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model KontakItem {
|
model KontakItem {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
nama String
|
nama String // contoh: "Polisi", "Ambulans", "Puskesmas Darmasaba"
|
||||||
nomorTelepon String
|
nomorTelepon String
|
||||||
icon String
|
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||||
createdAt DateTime @default(now())
|
imageId String?
|
||||||
updatedAt DateTime @updatedAt
|
kategori KontakDaruratKeamanan @relation(fields: [kategoriId], references: [id])
|
||||||
deletedAt DateTime @default(now())
|
kategoriId String
|
||||||
isActive Boolean @default(true)
|
createdAt DateTime @default(now())
|
||||||
KontakDaruratToItem KontakDaruratToItem[]
|
updatedAt DateTime @updatedAt
|
||||||
KontakDaruratKeamanan KontakDaruratKeamanan[]
|
|
||||||
}
|
|
||||||
|
|
||||||
model KontakDaruratToItem {
|
|
||||||
id String @id @default(uuid())
|
|
||||||
kontakDaruratId String
|
|
||||||
kontakItemId String
|
|
||||||
kontakDarurat KontakDaruratKeamanan @relation(fields: [kontakDaruratId], references: [id])
|
|
||||||
kontakItem KontakItem @relation(fields: [kontakItemId], references: [id])
|
|
||||||
createdAt DateTime @default(now())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================= PENCEGAHAN KRIMINALITAS ========================================= //
|
// ========================================= PENCEGAHAN KRIMINALITAS ========================================= //
|
||||||
model PencegahanKriminalitas {
|
model PencegahanKriminalitas {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
judul String
|
programKeamanan ProgramKeamanan @relation(fields: [programKeamananId], references: [id])
|
||||||
deskripsi String
|
programKeamananId String
|
||||||
deskripsiSingkat String
|
tipsKeamanan TipsKeamanan @relation(fields: [tipsKeamananId], references: [id])
|
||||||
linkVideo String
|
tipsKeamananId String
|
||||||
createdAt DateTime @default(now())
|
videoKeamanan VideoKeamanan @relation(fields: [videoKeamananId], references: [id])
|
||||||
updatedAt DateTime @updatedAt
|
videoKeamananId String
|
||||||
deletedAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
isActive Boolean @default(true)
|
updatedAt DateTime @updatedAt
|
||||||
|
deletedAt DateTime @default(now())
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
model ProgramKeamanan {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
nama String // contoh: "Ronda Malam"
|
||||||
|
deskripsi String? // jika mau tambahkan info detail
|
||||||
|
slug String @unique
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
PencegahanKriminalitas PencegahanKriminalitas[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model TipsKeamanan {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
judul String
|
||||||
|
konten String
|
||||||
|
slug String
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
PencegahanKriminalitas PencegahanKriminalitas[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model VideoKeamanan {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
judul String
|
||||||
|
deskripsi String?
|
||||||
|
videoUrl String // link youtube atau embed url
|
||||||
|
slug String
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
PencegahanKriminalitas PencegahanKriminalitas[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================= LAPORAN PUBLIK ========================================= //
|
// ========================================= LAPORAN PUBLIK ========================================= //
|
||||||
@@ -1322,13 +1285,11 @@ model LaporanPublik {
|
|||||||
judul String
|
judul String
|
||||||
lokasi String
|
lokasi String
|
||||||
tanggalWaktu DateTime
|
tanggalWaktu DateTime
|
||||||
status StatusLaporan @default(Proses)
|
status StatusLaporan
|
||||||
penanganan PenangananLaporanPublik[]
|
penanganan PenangananLaporanPublik[]
|
||||||
kronologi String? // Optional, bisa diisi detail kronologi
|
kronologi String? // Optional, bisa diisi detail kronologi
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deletedAt DateTime @default(now())
|
|
||||||
isActive Boolean @default(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model PenangananLaporanPublik {
|
model PenangananLaporanPublik {
|
||||||
@@ -1376,7 +1337,6 @@ model PasarDesa {
|
|||||||
harga Int
|
harga Int
|
||||||
rating Float
|
rating Float
|
||||||
alamatUsaha String
|
alamatUsaha String
|
||||||
kontak String
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deletedAt DateTime @default(now())
|
deletedAt DateTime @default(now())
|
||||||
@@ -1419,7 +1379,6 @@ model LowonganPekerjaan {
|
|||||||
gaji String
|
gaji String
|
||||||
deskripsi String
|
deskripsi String
|
||||||
kualifikasi String
|
kualifikasi String
|
||||||
notelp String
|
|
||||||
tanggalPosting DateTime @default(now())
|
tanggalPosting DateTime @default(now())
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
@@ -1429,67 +1388,76 @@ model LowonganPekerjaan {
|
|||||||
|
|
||||||
// ========================================= STRUKTUR ORGANISASI ========================================= //
|
// ========================================= STRUKTUR ORGANISASI ========================================= //
|
||||||
|
|
||||||
model StrukturBumDes {
|
model PosisiOrganisasi {
|
||||||
id String @id @default(cuid())
|
id String @id @default(uuid()) @db.VarChar(50)
|
||||||
name String @db.Text
|
nama String @db.VarChar(100)
|
||||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
deskripsi String? @db.Text
|
||||||
imageId String?
|
hierarki Int
|
||||||
createdAt DateTime @default(now())
|
|
||||||
updatedAt DateTime @updatedAt
|
pegawai Pegawai[]
|
||||||
deletedAt DateTime @default(now())
|
strukturOrganisasi StrukturOrganisasi[] // Relasi balik
|
||||||
isActive Boolean @default(true)
|
StrukturOrganisasiPPID StrukturOrganisasiPPID[]
|
||||||
PosisiOrganisasiBumDes PosisiOrganisasiBumDes? @relation(fields: [posisiOrganisasiBumDesId], references: [id])
|
|
||||||
posisiOrganisasiBumDesId String?
|
@@map("posisi_organisasi")
|
||||||
PegawaiBumDes PegawaiBumDes? @relation(fields: [pegawaiBumDesId], references: [id])
|
|
||||||
pegawaiBumDesId String?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model PosisiOrganisasiBumDes {
|
model Pegawai {
|
||||||
id String @id @default(cuid())
|
id String @id @default(uuid()) @db.Uuid
|
||||||
nama String @db.VarChar(100)
|
namaLengkap String @db.VarChar(255)
|
||||||
deskripsi String? @db.Text
|
gelarAkademik String? @db.VarChar(100)
|
||||||
hierarki Int
|
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||||
pegawai PegawaiBumDes[]
|
imageId String?
|
||||||
strukturOrganisasi StrukturBumDes[] // Relasi balik
|
tanggalMasuk DateTime? @db.Date
|
||||||
parentId String?
|
email String? @unique @db.VarChar(255)
|
||||||
isActive Boolean @default(true)
|
telepon String? @db.VarChar(20)
|
||||||
createdAt DateTime @default(now())
|
alamat String? @db.Text
|
||||||
updatedAt DateTime @updatedAt
|
posisiId String @db.VarChar(50)
|
||||||
parent PosisiOrganisasiBumDes? @relation("Parent", fields: [parentId], references: [id])
|
isActive Boolean @default(true)
|
||||||
children PosisiOrganisasiBumDes[] @relation("Parent")
|
createdAt DateTime @default(now())
|
||||||
StrukturOrganisasiBumDes StrukturOrganisasiBumDes[]
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
posisi PosisiOrganisasi @relation(fields: [posisiId], references: [id])
|
||||||
|
|
||||||
|
sebagaiAtasan HubunganOrganisasi[] @relation("AtasanToBawahan")
|
||||||
|
sebagaiBawahan HubunganOrganisasi[] @relation("BawahanToAtasan")
|
||||||
|
|
||||||
|
strukturOrganisasi StrukturOrganisasi[] // Relasi balik
|
||||||
|
StrukturOrganisasiPPID StrukturOrganisasiPPID[]
|
||||||
|
|
||||||
|
@@map("pegawai")
|
||||||
}
|
}
|
||||||
|
|
||||||
model PegawaiBumDes {
|
model HubunganOrganisasi {
|
||||||
id String @id @default(cuid())
|
id String @id @default(uuid()) @db.Uuid
|
||||||
namaLengkap String @db.VarChar(255)
|
atasanId String @db.Uuid
|
||||||
gelarAkademik String? @db.VarChar(100)
|
bawahanId String @db.Uuid
|
||||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
tipe String? @db.VarChar(50)
|
||||||
imageId String?
|
|
||||||
tanggalMasuk DateTime? @db.Date
|
atasan Pegawai @relation("AtasanToBawahan", fields: [atasanId], references: [id])
|
||||||
email String? @unique @db.VarChar(255)
|
bawahan Pegawai @relation("BawahanToAtasan", fields: [bawahanId], references: [id])
|
||||||
telepon String? @db.VarChar(20)
|
|
||||||
alamat String? @db.Text
|
strukturOrganisasi StrukturOrganisasi[] // Relasi balik
|
||||||
posisiId String @db.VarChar(50)
|
|
||||||
isActive Boolean @default(true)
|
@@unique([atasanId, bawahanId])
|
||||||
createdAt DateTime @default(now())
|
@@map("hubungan_organisasi")
|
||||||
updatedAt DateTime @updatedAt
|
|
||||||
posisi PosisiOrganisasiBumDes @relation(fields: [posisiId], references: [id])
|
|
||||||
strukturOrganisasi StrukturBumDes[] // Relasi balik
|
|
||||||
StrukturOrganisasiBumDes StrukturOrganisasiBumDes[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model StrukturOrganisasiBumDes {
|
model StrukturOrganisasi {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
posisiOrganisasiId String @db.VarChar(50)
|
posisiOrganisasiId String @db.VarChar(50)
|
||||||
pegawaiId String
|
pegawaiId String @db.Uuid
|
||||||
hubunganOrganisasiId String
|
hubunganOrganisasiId String @db.Uuid
|
||||||
posisiOrganisasi PosisiOrganisasiBumDes @relation(fields: [posisiOrganisasiId], references: [id])
|
|
||||||
pegawai PegawaiBumDes @relation(fields: [pegawaiId], references: [id])
|
posisiOrganisasi PosisiOrganisasi @relation(fields: [posisiOrganisasiId], references: [id])
|
||||||
createdAt DateTime @default(now())
|
pegawai Pegawai @relation(fields: [pegawaiId], references: [id])
|
||||||
updatedAt DateTime @updatedAt
|
hubunganOrganisasi HubunganOrganisasi @relation(fields: [hubunganOrganisasiId], references: [id])
|
||||||
deletedAt DateTime?
|
|
||||||
isActive Boolean @default(true)
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
deletedAt DateTime?
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
|
||||||
|
@@map("struktur_organisasi")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================= PROGRAM KEMISKINAN ========================================= //
|
// ========================================= PROGRAM KEMISKINAN ========================================= //
|
||||||
@@ -1497,7 +1465,7 @@ model ProgramKemiskinan {
|
|||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
nama String
|
nama String
|
||||||
deskripsi String
|
deskripsi String
|
||||||
icon String
|
ikonUrl String?
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
statistikId String? @unique
|
statistikId String? @unique
|
||||||
statistik StatistikKemiskinan? @relation(fields: [statistikId], references: [id])
|
statistik StatistikKemiskinan? @relation(fields: [statistikId], references: [id])
|
||||||
@@ -1638,7 +1606,7 @@ model Pembiayaan {
|
|||||||
ApbDesa ApbDesa[] @relation("ApbDesaPembiayaan")
|
ApbDesa ApbDesa[] @relation("ApbDesaPembiayaan")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================= MENU INOVASI ========================================= //
|
// ========================================= INOVASI ========================================= //
|
||||||
// ========================================= DESA DIGITAL / SMART VILLAGE ========================================= //
|
// ========================================= DESA DIGITAL / SMART VILLAGE ========================================= //
|
||||||
model DesaDigital {
|
model DesaDigital {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
@@ -1667,27 +1635,18 @@ model ProgramKreatif {
|
|||||||
|
|
||||||
// ========================================= KOLABORASI INOVASI ========================================= //
|
// ========================================= KOLABORASI INOVASI ========================================= //
|
||||||
model KolaborasiInovasi {
|
model KolaborasiInovasi {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String
|
name String
|
||||||
tahun Int
|
tahun Int
|
||||||
slug String @db.Text //deskripsi singkat
|
slug String @db.Text //deskripsi singkat
|
||||||
deskripsi String @db.Text //deskripsi panjang
|
deskripsi String @db.Text //deskripsi panjang
|
||||||
kolaborator String
|
kolaborator String
|
||||||
createdAt DateTime @default(now())
|
image FileStorage @relation(fields: [imageId], references: [id])
|
||||||
updatedAt DateTime @updatedAt
|
imageId String
|
||||||
deletedAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
isActive Boolean @default(true)
|
updatedAt DateTime @updatedAt
|
||||||
}
|
deletedAt DateTime @default(now())
|
||||||
|
isActive Boolean @default(true)
|
||||||
model MitraKolaborasi {
|
|
||||||
id String @id @default(cuid())
|
|
||||||
name String
|
|
||||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
|
||||||
imageId String?
|
|
||||||
createdAt DateTime @default(now())
|
|
||||||
updatedAt DateTime @updatedAt
|
|
||||||
deletedAt DateTime @default(now())
|
|
||||||
isActive Boolean @default(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================= INFO TEKHNOLOGI TEPAT GUNA ========================================= //
|
// ========================================= INFO TEKHNOLOGI TEPAT GUNA ========================================= //
|
||||||
@@ -1974,28 +1933,23 @@ model KeunggulanProgram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model BeasiswaPendaftar {
|
model BeasiswaPendaftar {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
namaLengkap String
|
namaLengkap String
|
||||||
nis String?
|
nik String @unique
|
||||||
kelas String?
|
|
||||||
jenisKelamin JenisKelamin
|
|
||||||
alamatDomisili String?
|
|
||||||
tempatLahir String
|
tempatLahir String
|
||||||
tanggalLahir DateTime
|
tanggalLahir DateTime
|
||||||
namaOrtu String?
|
jenisKelamin JenisKelamin
|
||||||
nik String @unique
|
kewarganegaraan String
|
||||||
pekerjaanOrtu String?
|
agama Agama
|
||||||
penghasilan String?
|
alamatKTP String
|
||||||
|
alamatDomisili String?
|
||||||
noHp String
|
noHp String
|
||||||
kewarganegaraan String?
|
email String @unique
|
||||||
agama Agama?
|
statusPernikahan StatusPernikahan
|
||||||
alamatKTP String?
|
|
||||||
email String? @unique
|
|
||||||
statusPernikahan StatusPernikahan?
|
|
||||||
ukuranBaju UkuranBaju?
|
ukuranBaju UkuranBaju?
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
enum JenisKelamin {
|
enum JenisKelamin {
|
||||||
@@ -2124,9 +2078,6 @@ model DataPerpustakaan {
|
|||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
deletedAt DateTime @default(now())
|
deletedAt DateTime @default(now())
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
|
|
||||||
// relasi baru ke peminjaman
|
|
||||||
peminjamanBuku PeminjamanBuku[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model KategoriBuku {
|
model KategoriBuku {
|
||||||
@@ -2139,100 +2090,26 @@ model KategoriBuku {
|
|||||||
DataPerpustakaan DataPerpustakaan[]
|
DataPerpustakaan DataPerpustakaan[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model PeminjamanBuku {
|
|
||||||
id String @id @default(cuid())
|
|
||||||
nama String
|
|
||||||
noTelp String
|
|
||||||
alamat String
|
|
||||||
bukuId String
|
|
||||||
tanggalPinjam DateTime @default(now())
|
|
||||||
batasKembali DateTime // tenggat waktu pengembalian
|
|
||||||
tanggalKembali DateTime? // diisi saat dikembalikan
|
|
||||||
status StatusPeminjaman @default(Dipinjam)
|
|
||||||
catatan String? // opsional, misal: kondisi buku
|
|
||||||
buku DataPerpustakaan @relation(fields: [bukuId], references: [id])
|
|
||||||
createdAt DateTime @default(now())
|
|
||||||
updatedAt DateTime @updatedAt
|
|
||||||
deletedAt DateTime @default(now())
|
|
||||||
isActive Boolean @default(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
enum StatusPeminjaman {
|
|
||||||
Dipinjam
|
|
||||||
Dikembalikan
|
|
||||||
Terlambat
|
|
||||||
Dibatalkan
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================= USER ========================================= //
|
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
id String @id @default(cuid())
|
|
||||||
username String
|
|
||||||
nomor String @unique
|
|
||||||
roleId String @default("2")
|
|
||||||
isActive Boolean @default(false)
|
|
||||||
sessionInvalid Boolean @default(false)
|
|
||||||
lastLogin DateTime?
|
|
||||||
createdAt DateTime @default(now())
|
|
||||||
updatedAt DateTime @default(now()) @updatedAt
|
|
||||||
permissions Json?
|
|
||||||
sessions UserSession[] // ✅ Relasi one-to-many
|
|
||||||
role Role @relation(fields: [roleId], references: [id])
|
|
||||||
menuAccesses UserMenuAccess[]
|
|
||||||
|
|
||||||
@@map("users")
|
|
||||||
}
|
|
||||||
|
|
||||||
model Role {
|
|
||||||
id String @id @default(cuid())
|
|
||||||
name String @unique // ADMIN_DESA, ADMIN_KESEHATAN, ADMIN_SEKOLAH
|
|
||||||
description String?
|
|
||||||
permissions Json?
|
|
||||||
isActive Boolean @default(true)
|
|
||||||
createdAt DateTime @default(now())
|
|
||||||
updatedAt DateTime @updatedAt
|
|
||||||
deletedAt DateTime?
|
|
||||||
users User[]
|
|
||||||
|
|
||||||
@@map("roles")
|
|
||||||
}
|
|
||||||
|
|
||||||
model KodeOtp {
|
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
|
nama String
|
||||||
|
email String @unique
|
||||||
|
password String
|
||||||
|
role Role @relation(fields: [roleId], references: [id])
|
||||||
|
roleId String
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
nomor String
|
|
||||||
otp Int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model UserSession {
|
model Role {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
token String @db.Text // ✅ JWT bisa panjang
|
name String
|
||||||
expiresAt DateTime // ✅ Ubah jadi expiresAt (konsisten)
|
|
||||||
active Boolean @default(true)
|
|
||||||
createdAt DateTime @default(now())
|
|
||||||
updatedAt DateTime @default(now()) @updatedAt
|
|
||||||
|
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
||||||
userId String // ✅ HAPUS @unique - user bisa punya multiple sessions
|
|
||||||
|
|
||||||
@@index([userId]) // ✅ Index untuk query cepat
|
|
||||||
@@index([token]) // ✅ Index untuk verify cepat
|
|
||||||
@@map("user_sessions")
|
|
||||||
}
|
|
||||||
|
|
||||||
model UserMenuAccess {
|
|
||||||
id String @id @default(cuid())
|
|
||||||
userId String
|
|
||||||
menuId String // ID menu (misal: "Landing Page", "Kesehatan")
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
deletedAt DateTime @default(now())
|
||||||
user User @relation(fields: [userId], references: [id])
|
isActive Boolean @default(true)
|
||||||
|
User User[]
|
||||||
@@unique([userId, menuId]) // Satu user tidak bisa punya akses menu yang sama dua kali
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================= DATA PENDIDIKAN ========================================= //
|
// ========================================= DATA PENDIDIKAN ========================================= //
|
||||||
|
|||||||
654
prisma/seed.ts
@@ -1,182 +1,96 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
||||||
import prisma from "@/lib/prisma";
|
import prisma from "@/lib/prisma";
|
||||||
|
import fs from "fs/promises";
|
||||||
|
import path from "path";
|
||||||
import profilePejabatDesa from "./data/landing-page/profile/profile.json";
|
import profilePejabatDesa from "./data/landing-page/profile/profile.json";
|
||||||
|
import penghargaan from "./data/landing-page/penghargaan/penghargaan.json";
|
||||||
import programInovasi from "./data/landing-page/profile/programInovasi.json";
|
import programInovasi from "./data/landing-page/profile/programInovasi.json";
|
||||||
import mediaSosial from "./data/landing-page/profile/mediaSosial.json";
|
import mediaSosial from "./data/landing-page/profile/mediaSosial.json";
|
||||||
import desaAntiKorupsi from "./data/landing-page/desa-anti-korupsi/desaantiKorpusi.json";
|
|
||||||
import kategoriDesaAntiKorupsi from "./data/landing-page/desa-anti-korupsi/kategoriDesaAntiKorupsi.json";
|
|
||||||
import sdgsDesa from "./data/landing-page/sdgs-desa/sdgs-desa.json";
|
import sdgsDesa from "./data/landing-page/sdgs-desa/sdgs-desa.json";
|
||||||
import apbdes from "./data/landing-page/apbdes/apbdes.json";
|
import apbdes from "./data/landing-page/apbdes/apbdes.json";
|
||||||
import kategoriPrestasiDesa from "./data/landing-page/prestasi-desa/kategori-prestasi.json";
|
|
||||||
import prestasiDesa from "./data/landing-page/prestasi-desa/prestasi-desa.json";
|
|
||||||
import penghargaan from "./data/landing-page/penghargaan/penghargaan.json";
|
|
||||||
import profilePPID from "./data/ppid/profile-ppid/profilePPid.json";
|
|
||||||
import pegawaiPPID from "./data/ppid/struktur-ppid/pegawai-PPID.json";
|
|
||||||
import posisiOrganisasiPPID from "./data/ppid/struktur-ppid/posisi-organisasi-PPID.json";
|
|
||||||
import visiMisiPPID from "./data/ppid/visi-misi-ppid/visimisiPPID.json";
|
|
||||||
import dasarHukumPPID from "./data/ppid/dasar-hukum-ppid/dasarhukumPPID.json";
|
|
||||||
import jenisKelamin from "./data/ppid/ikm/jenis-kelamin/jenis-kelamin.json";
|
|
||||||
import daftarInformasiPublik from "./data/ppid/daftar-informasi-publik-desa-darmasaba/daftarInformasi.json";
|
|
||||||
import pilihanRatingResponden from "./data/ppid/ikm/pilihan-rating-responden/rating-responden.json";
|
|
||||||
import umurResponden from "./data/ppid/ikm/umur-responden/umur-responden.json";
|
|
||||||
import categoryPengumuman from "./data/category-pengumuman.json";
|
|
||||||
import pelayananPerizinanBerusaha from "./data/desa/layanan/pelayananPerizinanBerusaha.json";
|
|
||||||
import pelayananSuratKeterangan from "./data/desa/layanan/pelayananSuratKeterangan.json";
|
import pelayananSuratKeterangan from "./data/desa/layanan/pelayananSuratKeterangan.json";
|
||||||
import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSaktiDesa.json";
|
import categoryPengumuman from "./data/category-pengumuman.json";
|
||||||
import pelayananPendudukNonPermanen from "./data/desa/layanan/pelayanaPendudukNonPermanen.json";
|
import kategoriBerita from "./data/kategori-berita.json";
|
||||||
import lambangDesa from "./data/desa/profile/lambang_desa.json";
|
|
||||||
import maskotDesa from "./data/desa/profile/maskot_desa.json";
|
|
||||||
import profilPerbekel from "./data/desa/profile/profil_perbekel.json";
|
|
||||||
import sejarahDesa from "./data/desa/profile/sejarah_desa.json";
|
|
||||||
import visiMisiDesa from "./data/desa/profile/visi_misi_desa.json";
|
|
||||||
import detailDataPengangguran from "./data/ekonomi/jumlah-pengangguran/detail-data-pengangguran.json";
|
|
||||||
import kategoriProduk from "./data/ekonomi/pasar-desa/kategori-produk.json";
|
|
||||||
import pegawai from "./data/ekonomi/struktur-organisasi/pegawai-bumdes.json";
|
|
||||||
import posisiOrganisasi from "./data/ekonomi/struktur-organisasi/posisi-organisasi-bumdes.json";
|
|
||||||
import kategoriBerita from "./data/desa/berita/kategori-berita.json";
|
|
||||||
import contohEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/contoh-kegiatan-di-desa-darmasaba.json";
|
|
||||||
import materiEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/materi-edukasi-yang-diberikan.json";
|
|
||||||
import tujuanEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/tujuan-edukasi-lingkungan.json";
|
|
||||||
import bentukKonservasiBerdasarkanAdat from "./data/lingkungan/konservasi-adat-bali/bentuk-konservasi.json";
|
|
||||||
import kategoriKegiatanData from "./data/lingkungan/gotong-royong/kategori-gotong-royong.json";
|
|
||||||
import filosofiTriHita from "./data/lingkungan/konservasi-adat-bali/filosofi-tri-hita.json";
|
|
||||||
import nilaiKonservasiAdat from "./data/lingkungan/konservasi-adat-bali/nilai-konservasi-adat.json";
|
|
||||||
import caraMemperolehInformasi from "./data/list-caraMemperolehInformasi.json";
|
import caraMemperolehInformasi from "./data/list-caraMemperolehInformasi.json";
|
||||||
import caraMemperolehSalinanInformasi from "./data/list-caraMemperolehSalinanInformasi.json";
|
import caraMemperolehSalinanInformasi from "./data/list-caraMemperolehSalinanInformasi.json";
|
||||||
import jenisInformasiDiminta from "./data/list-jenisInfromasi.json";
|
import jenisInformasiDiminta from "./data/list-jenisInfromasi.json";
|
||||||
|
import layanan from "./data/list-layanan.json";
|
||||||
import potensi from "./data/list-potensi.json";
|
import potensi from "./data/list-potensi.json";
|
||||||
import fasilitasBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan.json";
|
import dasarHukumPPID from "./data/ppid/dasar-hukum-ppid/dasarhukumPPID.json";
|
||||||
import lokasiJadwalBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal.json";
|
import profilePPID from "./data/ppid/profile-ppid/profilePPid.json";
|
||||||
import tujuanBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/tujuan-bimbingan-belajar-desa.json";
|
import visiMisiPPID from "./data/ppid/visi-misi-ppid/visimisiPPID.json";
|
||||||
import jenisProgramYangDiselenggarakan from "./data/pendidikan/pendidikan-non-formal/jenis-program-yang-diselenggarakan.json";
|
import jenisKelamin from "./data/ppid/ikm/jenis-kelamin/jenis-kelamin.json";
|
||||||
import tempatKegiatan from "./data/pendidikan/pendidikan-non-formal/tempat-kegiatan.json";
|
import pilihanRatingResponden from "./data/ppid/ikm/pilihan-rating-responden/rating-responden.json";
|
||||||
|
import umurResponden from "./data/ppid/ikm/umur-responden/umur-responden.json";
|
||||||
|
import 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";
|
||||||
|
import tujuanProgram from "./data/pendidikan/program-pendidikan-anak/tujuan-program.json";
|
||||||
import tujuanProgram2 from "./data/pendidikan/pendidikan-non-formal/tujuan-program2.json";
|
import tujuanProgram2 from "./data/pendidikan/pendidikan-non-formal/tujuan-program2.json";
|
||||||
import programUnggulan from "./data/pendidikan/program-pendidikan-anak/program-unggulan.json";
|
import programUnggulan from "./data/pendidikan/program-pendidikan-anak/program-unggulan.json";
|
||||||
import tujuanProgram from "./data/pendidikan/program-pendidikan-anak/tujuan-program.json";
|
import tujuanBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/tujuan-bimbingan-belajar-desa.json";
|
||||||
import roles from "./data/user/roles.json";
|
import lokasiJadwalBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/lokasi-dan-jadwal.json";
|
||||||
import fileStorage from "./data/file-storage.json";
|
import fasilitasBimbinganBelajarDesa from "./data/pendidikan/bimbingan-belajar-desa/fasilitas-yang-disediakan.json";
|
||||||
import jenjangPendidikan from "./data/pendidikan/info-sekolah/jenjang-pendidikan.json";
|
import tempatKegiatan from "./data/pendidikan/pendidikan-non-formal/tempat-kegiatan.json";
|
||||||
import seedAssets from "./seed_assets";
|
import jenisProgramYangDiselenggarakan from "./data/pendidikan/pendidikan-non-formal/jenis-program-yang-diselenggarakan.json";
|
||||||
import users from "./data/user/users.json";
|
import posisiOrganisasiPPID from "./data/ppid/struktur-ppid/posisi-organisasi-PPID.json";
|
||||||
import { safeSeedUnique } from "./safeseedUnique";
|
import pegawaiPPID from "./data/ppid/struktur-ppid/pegawai-PPID.json";
|
||||||
|
import pelayananTelunjukSaktiDesa from "./data/desa/layanan/pelayananTelunjukSaktiDesa.json";
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
console.log("🔄 Seeding roles...");
|
//seed file storage
|
||||||
|
const filePath = path.join(__dirname, "data/file-storage.json");
|
||||||
|
const rawData = await fs.readFile(filePath, "utf-8");
|
||||||
|
const files = JSON.parse(rawData);
|
||||||
|
|
||||||
for (const r of roles) {
|
console.log(`Seeding ${files.length} file(s) into FileStorage...`);
|
||||||
try {
|
|
||||||
// ✅ Destructure to remove permissions if exists
|
|
||||||
const { permissions, ...roleData } = r as any;
|
|
||||||
|
|
||||||
await safeSeedUnique(
|
for (const file of files) {
|
||||||
"role",
|
await prisma.fileStorage.upsert({
|
||||||
{ name: roleData.name },
|
where: { name: file.name },
|
||||||
{
|
update: {},
|
||||||
id: roleData.id,
|
create: {
|
||||||
name: roleData.name,
|
id: file.id,
|
||||||
description: roleData.description,
|
name: file.name,
|
||||||
permissions: roleData.permissions || {}, // ✅ Include permissions
|
realName: file.realName,
|
||||||
isActive: roleData.isActive,
|
path: file.path,
|
||||||
}
|
link: file.link,
|
||||||
);
|
category: file.category,
|
||||||
console.log(`✅ Seeded role -> ${roleData.name}`);
|
mimeType: file.mimeType,
|
||||||
} catch (error: any) {
|
isActive: file.isActive ?? true,
|
||||||
if (error.code === "P2002") {
|
},
|
||||||
console.warn(`⚠️ Role already exists (skipping): ${r.name}`);
|
});
|
||||||
} else {
|
|
||||||
console.error(`❌ Failed to seed role ${r.name}:`, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
console.log("✅ Roles seeding completed");
|
|
||||||
|
|
||||||
// =========== USER ===========
|
console.log("✅ Seeding selesai!");
|
||||||
console.log("🔄 Seeding users...");
|
|
||||||
for (const u of users) {
|
|
||||||
try {
|
|
||||||
// Verify role exists first
|
|
||||||
const roleExists = await prisma.role.findUnique({
|
|
||||||
where: { id: u.roleId.toString() },
|
|
||||||
select: { id: true }, // Only select id to minimize query
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!roleExists) {
|
|
||||||
console.error(
|
|
||||||
`❌ Role with id ${u.roleId} not found for user ${u.username}`
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
await safeSeedUnique(
|
|
||||||
"user",
|
|
||||||
{ id: u.id },
|
|
||||||
{
|
|
||||||
username: u.username,
|
|
||||||
nomor: u.nomor,
|
|
||||||
roleId: u.roleId.toString(),
|
|
||||||
isActive: u.isActive,
|
|
||||||
sessionInvalid: false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
console.log(`✅ Seeded user -> ${u.username}`);
|
|
||||||
} catch (error: any) {
|
|
||||||
if (error.code === "P2003") {
|
|
||||||
console.error(
|
|
||||||
`❌ Foreign key constraint failed for user ${u.username}: Role ${u.roleId} does not exist`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
console.error(`❌ Failed to seed user ${u.username}:`, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log("✅ Users seeding completed");
|
|
||||||
|
|
||||||
// =========== FILE STORAGE ===========
|
|
||||||
console.log("🔄 Seeding file storage...");
|
|
||||||
for (const f of fileStorage) {
|
|
||||||
try {
|
|
||||||
await prisma.fileStorage.upsert({
|
|
||||||
where: { id: f.id },
|
|
||||||
update: {
|
|
||||||
name: f.name,
|
|
||||||
realName: f.realName,
|
|
||||||
path: f.path,
|
|
||||||
mimeType: f.mimeType,
|
|
||||||
link: f.link,
|
|
||||||
category: f.category,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
id: f.id,
|
|
||||||
name: f.name,
|
|
||||||
realName: f.realName,
|
|
||||||
path: f.path,
|
|
||||||
mimeType: f.mimeType,
|
|
||||||
link: f.link,
|
|
||||||
category: f.category,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error(`❌ Failed to seed file storage ${f.name}:`, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log("✅ File storage seeded");
|
|
||||||
// =========== LANDING PAGE ===========
|
// =========== LANDING PAGE ===========
|
||||||
// =========== SUBMENU PROFILE ===========
|
// =========== PROFILE ===========
|
||||||
// =========== PROFILE PEJABAT DESA ===========
|
|
||||||
for (const p of profilePejabatDesa) {
|
for (const p of profilePejabatDesa) {
|
||||||
await prisma.pejabatDesa.upsert({
|
await prisma.pejabatDesa.upsert({
|
||||||
where: { id: p.id },
|
where: { id: p.id },
|
||||||
update: {
|
update: {
|
||||||
name: p.name,
|
name: p.name,
|
||||||
position: p.position,
|
position: p.position,
|
||||||
imageId: p.imageId,
|
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
id: p.id,
|
id: p.id,
|
||||||
name: p.name,
|
name: p.name,
|
||||||
position: p.position,
|
position: p.position,
|
||||||
imageId: p.imageId,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -186,35 +100,18 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
|
|
||||||
// =========== PROGRAM INOVASI ===========
|
// =========== PROGRAM INOVASI ===========
|
||||||
for (const p of programInovasi) {
|
for (const p of programInovasi) {
|
||||||
let imageId: string | null = null;
|
|
||||||
|
|
||||||
if (p.imageId) {
|
|
||||||
const imageExists = await prisma.fileStorage.findUnique({
|
|
||||||
where: { id: p.imageId },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (imageExists) {
|
|
||||||
imageId = p.imageId;
|
|
||||||
} else {
|
|
||||||
console.warn(
|
|
||||||
`⚠️ imageId ${p.imageId} tidak ditemukan untuk ProgramInovasi ${p.name}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await prisma.programInovasi.upsert({
|
await prisma.programInovasi.upsert({
|
||||||
where: { id: p.id },
|
where: { id: p.id },
|
||||||
update: {
|
update: {
|
||||||
name: p.name,
|
name: p.name,
|
||||||
description: p.description,
|
description: p.description,
|
||||||
link: p.link,
|
link: p.link,
|
||||||
imageId: p.imageId,
|
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
id: p.id,
|
id: p.id,
|
||||||
name: p.name,
|
name: p.name,
|
||||||
description: p.description,
|
description: p.description,
|
||||||
link: p.link,
|
link: p.link,
|
||||||
imageId: p.imageId,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -227,102 +124,16 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
update: {
|
update: {
|
||||||
name: p.name,
|
name: p.name,
|
||||||
iconUrl: p.iconUrl,
|
iconUrl: p.iconUrl,
|
||||||
imageId: p.imageId,
|
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
id: p.id,
|
id: p.id,
|
||||||
name: p.name,
|
name: p.name,
|
||||||
iconUrl: p.iconUrl,
|
iconUrl: p.iconUrl,
|
||||||
imageId: p.imageId,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log("media sosial success ...");
|
console.log("media sosial success ...");
|
||||||
|
|
||||||
// =========== SUBMENU DESA ANTI KORUPSI ===========
|
|
||||||
// =========== KATEGORI DESA ANTI KORUPSI ===========
|
|
||||||
for (const k of kategoriDesaAntiKorupsi) {
|
|
||||||
await prisma.kategoriDesaAntiKorupsi.upsert({
|
|
||||||
where: { id: k.id },
|
|
||||||
update: {
|
|
||||||
name: k.name,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
id: k.id,
|
|
||||||
name: k.name,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log("kategori desa anti korupsi success ...");
|
|
||||||
|
|
||||||
// =========== DESA ANTI KORUPSI ===========
|
|
||||||
for (const p of desaAntiKorupsi) {
|
|
||||||
await prisma.desaAntiKorupsi.upsert({
|
|
||||||
where: { id: p.id },
|
|
||||||
update: {
|
|
||||||
name: p.name,
|
|
||||||
deskripsi: p.deskripsi,
|
|
||||||
kategoriId: p.kategoriId,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
id: p.id,
|
|
||||||
name: p.name,
|
|
||||||
deskripsi: p.deskripsi,
|
|
||||||
kategoriId: p.kategoriId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log("desa anti korupsi success ...");
|
|
||||||
|
|
||||||
// =========== KATEGORI DESA ANTI KORUPSI ===========
|
|
||||||
for (const p of kategoriDesaAntiKorupsi) {
|
|
||||||
await prisma.kategoriDesaAntiKorupsi.upsert({
|
|
||||||
where: { id: p.id },
|
|
||||||
update: {
|
|
||||||
name: p.name,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
id: p.id,
|
|
||||||
name: p.name,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log("desa anti korupsi success ...");
|
|
||||||
|
|
||||||
// =========== KATEGORI PRESTASI DESA===========
|
|
||||||
for (const c of kategoriPrestasiDesa) {
|
|
||||||
await prisma.kategoriPrestasiDesa.upsert({
|
|
||||||
where: { id: c.id },
|
|
||||||
update: {
|
|
||||||
name: c.name,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
id: c.id,
|
|
||||||
name: c.name,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log("kategori prestasi desa success ...");
|
|
||||||
|
|
||||||
// =========== PRESTASI DESA===========
|
|
||||||
for (const p of prestasiDesa) {
|
|
||||||
await prisma.prestasiDesa.upsert({
|
|
||||||
where: { id: p.id },
|
|
||||||
update: {
|
|
||||||
name: p.name,
|
|
||||||
deskripsi: p.deskripsi,
|
|
||||||
kategoriId: p.kategoriId,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
id: p.id,
|
|
||||||
name: p.name,
|
|
||||||
deskripsi: p.deskripsi,
|
|
||||||
kategoriId: p.kategoriId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log("prestasi desa success ...");
|
|
||||||
|
|
||||||
// =========== PENGHARGAAN ===========
|
// =========== PENGHARGAAN ===========
|
||||||
for (const p of penghargaan) {
|
for (const p of penghargaan) {
|
||||||
await prisma.penghargaan.upsert({
|
await prisma.penghargaan.upsert({
|
||||||
@@ -344,16 +155,26 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
|
|
||||||
// =========== LAYANAN DESA ===========
|
// =========== LAYANAN DESA ===========
|
||||||
for (const p of pelayananSuratKeterangan) {
|
for (const p of pelayananSuratKeterangan) {
|
||||||
|
// Skip if required image references don't exist
|
||||||
|
if (!p.imageId || !p.image2Id) {
|
||||||
|
console.warn(`Skipping ${p.name} due to missing image references`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
await prisma.pelayananSuratKeterangan.upsert({
|
await prisma.pelayananSuratKeterangan.upsert({
|
||||||
where: { id: p.id },
|
where: { id: p.id },
|
||||||
update: {
|
update: {
|
||||||
name: p.name,
|
name: p.name,
|
||||||
deskripsi: p.deskripsi,
|
deskripsi: p.deskripsi,
|
||||||
|
imageId: p.imageId,
|
||||||
|
image2Id: p.image2Id,
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
id: p.id,
|
id: p.id,
|
||||||
name: p.name,
|
name: p.name,
|
||||||
deskripsi: p.deskripsi,
|
deskripsi: p.deskripsi,
|
||||||
|
imageId: p.imageId,
|
||||||
|
image2Id: p.image2Id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -377,16 +198,35 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
}
|
}
|
||||||
console.log("pelayanan surat keterangan success ...");
|
console.log("pelayanan surat keterangan success ...");
|
||||||
|
|
||||||
|
// =========== LAYANAN ===========
|
||||||
|
for (const l of layanan) {
|
||||||
|
await prisma.layanan.upsert({
|
||||||
|
where: {
|
||||||
|
name: l.name,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
name: l.name,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
name: l.name,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("layanan success ...");
|
||||||
|
|
||||||
// =========== SDGSDesa ===========
|
// =========== SDGSDesa ===========
|
||||||
for (const l of sdgsDesa) {
|
for (const l of sdgsDesa) {
|
||||||
await prisma.sdgsDesa.upsert({
|
await prisma.sDGSDesa.upsert({
|
||||||
where: { id: l.id },
|
where: {
|
||||||
|
name: l.name,
|
||||||
|
jumlah: l.jumlah,
|
||||||
|
},
|
||||||
update: {
|
update: {
|
||||||
name: l.name,
|
name: l.name,
|
||||||
jumlah: l.jumlah,
|
jumlah: l.jumlah,
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
id: l.id,
|
|
||||||
name: l.name,
|
name: l.name,
|
||||||
jumlah: l.jumlah,
|
jumlah: l.jumlah,
|
||||||
},
|
},
|
||||||
@@ -399,7 +239,8 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
for (const l of apbdes) {
|
for (const l of apbdes) {
|
||||||
await prisma.aPBDes.upsert({
|
await prisma.aPBDes.upsert({
|
||||||
where: {
|
where: {
|
||||||
id: l.id,
|
name: l.name,
|
||||||
|
jumlah: l.jumlah,
|
||||||
},
|
},
|
||||||
update: {
|
update: {
|
||||||
name: l.name,
|
name: l.name,
|
||||||
@@ -414,9 +255,6 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
|
|
||||||
console.log("sdgs desa success ...");
|
console.log("sdgs desa success ...");
|
||||||
|
|
||||||
// =========== MENU DESA ===========
|
|
||||||
// =========== SUBMENU PROFILE ===========
|
|
||||||
// =========== SEJARAH DESA ===========
|
|
||||||
for (const l of sejarahDesa) {
|
for (const l of sejarahDesa) {
|
||||||
await prisma.sejarahDesa.upsert({
|
await prisma.sejarahDesa.upsert({
|
||||||
where: {
|
where: {
|
||||||
@@ -436,7 +274,6 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
|
|
||||||
console.log("sejarah desa success ...");
|
console.log("sejarah desa success ...");
|
||||||
|
|
||||||
// =========== MASKOT DESA ===========
|
|
||||||
for (const l of maskotDesa) {
|
for (const l of maskotDesa) {
|
||||||
await prisma.maskotDesa.upsert({
|
await prisma.maskotDesa.upsert({
|
||||||
where: {
|
where: {
|
||||||
@@ -456,7 +293,6 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
|
|
||||||
console.log("maskot desa success ...");
|
console.log("maskot desa success ...");
|
||||||
|
|
||||||
// =========== LAMBANG DESA ===========
|
|
||||||
for (const l of lambangDesa) {
|
for (const l of lambangDesa) {
|
||||||
await prisma.lambangDesa.upsert({
|
await prisma.lambangDesa.upsert({
|
||||||
where: {
|
where: {
|
||||||
@@ -476,7 +312,6 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
|
|
||||||
console.log("lambang desa success ...");
|
console.log("lambang desa success ...");
|
||||||
|
|
||||||
// =========== PROFIL PERBEKEL ===========
|
|
||||||
for (const c of profilPerbekel) {
|
for (const c of profilPerbekel) {
|
||||||
await prisma.profilPerbekel.upsert({
|
await prisma.profilPerbekel.upsert({
|
||||||
where: { id: c.id },
|
where: { id: c.id },
|
||||||
@@ -501,7 +336,6 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
"✅ profilePerbekel seeded without imageId (editable later via UI)"
|
"✅ profilePerbekel seeded without imageId (editable later via UI)"
|
||||||
);
|
);
|
||||||
|
|
||||||
// =========== VISI MISI DESA ===========
|
|
||||||
for (const l of visiMisiDesa) {
|
for (const l of visiMisiDesa) {
|
||||||
await prisma.visiMisiDesa.upsert({
|
await prisma.visiMisiDesa.upsert({
|
||||||
where: {
|
where: {
|
||||||
@@ -521,35 +355,6 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
|
|
||||||
console.log("visi misi desa success ...");
|
console.log("visi misi desa success ...");
|
||||||
|
|
||||||
// =========== MENU PPID ===========
|
|
||||||
// =========== SUBMENU PROFILE PPID ===========
|
|
||||||
for (const c of profilePPID) {
|
|
||||||
await prisma.profilePPID.upsert({
|
|
||||||
where: { id: c.id },
|
|
||||||
update: {
|
|
||||||
name: c.name,
|
|
||||||
biodata: c.biodata,
|
|
||||||
riwayat: c.riwayat,
|
|
||||||
pengalaman: c.pengalaman,
|
|
||||||
unggulan: c.unggulan,
|
|
||||||
// imageId tidak di-update
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
id: c.id,
|
|
||||||
name: c.name,
|
|
||||||
biodata: c.biodata,
|
|
||||||
riwayat: c.riwayat,
|
|
||||||
pengalaman: c.pengalaman,
|
|
||||||
unggulan: c.unggulan,
|
|
||||||
// imageId tidak di-create
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log("✅ profilePPID seeded without imageId (editable later via UI)");
|
|
||||||
|
|
||||||
// =========== SUBMENU STRUKTUR PPID ===========
|
|
||||||
// =========== POSISI ORGANISASI PPID ===========
|
|
||||||
|
|
||||||
const flattenedPosisi = posisiOrganisasiPPID.flat();
|
const flattenedPosisi = posisiOrganisasiPPID.flat();
|
||||||
|
|
||||||
// ✅ Urutkan berdasarkan hierarki
|
// ✅ Urutkan berdasarkan hierarki
|
||||||
@@ -574,106 +379,18 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
create: p,
|
create: p,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log("posisi organisasi berhasil");
|
console.log("✅ Posisi organisasi berhasil");
|
||||||
|
|
||||||
// =========== PEGAWAI PPID ===========
|
// 2. Seed Pegawai
|
||||||
console.log("🔄 Seeding pegawai PPID...");
|
|
||||||
const flattenedPegawai = pegawaiPPID.flat();
|
const flattenedPegawai = pegawaiPPID.flat();
|
||||||
|
|
||||||
// Check for duplicate emails
|
|
||||||
const emails = new Set();
|
|
||||||
for (const p of flattenedPegawai) {
|
for (const p of flattenedPegawai) {
|
||||||
if (emails.has(p.email)) {
|
await prisma.pegawaiPPID.upsert({
|
||||||
console.warn(`⚠️ Duplicate email found in pegawaiPPID: ${p.email}`);
|
where: { id: p.id },
|
||||||
}
|
update: p,
|
||||||
emails.add(p.email);
|
create: p,
|
||||||
}
|
|
||||||
|
|
||||||
for (const p of flattenedPegawai) {
|
|
||||||
try {
|
|
||||||
await prisma.pegawaiPPID.upsert({
|
|
||||||
where: { id: p.id },
|
|
||||||
update: p,
|
|
||||||
create: p,
|
|
||||||
});
|
|
||||||
console.log(`✅ Seeded pegawai PPID -> ${p.namaLengkap}`);
|
|
||||||
} catch (error: any) {
|
|
||||||
if (error.code === "P2002") {
|
|
||||||
console.warn(
|
|
||||||
`⚠️ Pegawai PPID with duplicate email (skipping): ${p.email}`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
console.error(
|
|
||||||
`❌ Failed to seed pegawai PPID ${p.namaLengkap}:`,
|
|
||||||
error.message
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log("✅ pegawai PPID seeding completed");
|
|
||||||
|
|
||||||
// =========== SUBMENU VISI MISI PPID ===========
|
|
||||||
|
|
||||||
for (const v of visiMisiPPID) {
|
|
||||||
await prisma.visiMisiPPID.upsert({
|
|
||||||
where: {
|
|
||||||
id: v.id,
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
misi: v.misi,
|
|
||||||
visi: v.visi,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
id: v.id,
|
|
||||||
misi: v.misi,
|
|
||||||
visi: v.visi,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log("visi misi PPID success ...");
|
console.log("✅ Pegawai berhasil");
|
||||||
|
|
||||||
// =========== SUBMENU DASAR HUKUM PPID ===========
|
|
||||||
for (const v of dasarHukumPPID) {
|
|
||||||
await prisma.dasarHukumPPID.upsert({
|
|
||||||
where: {
|
|
||||||
id: v.id,
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
judul: v.judul,
|
|
||||||
content: v.content,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
id: v.id,
|
|
||||||
judul: v.judul,
|
|
||||||
content: v.content,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log("dasar hukum PPID success ...");
|
|
||||||
|
|
||||||
// =========== SUBMENU DAFTAR INFORMASI PUBLIK PPID ===========
|
|
||||||
for (const v of daftarInformasiPublik) {
|
|
||||||
// Convert string date to Date object
|
|
||||||
const tanggal = new Date(v.tanggal);
|
|
||||||
|
|
||||||
await prisma.daftarInformasiPublik.upsert({
|
|
||||||
where: {
|
|
||||||
id: v.id,
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
jenisInformasi: v.jenisInformasi,
|
|
||||||
deskripsi: v.deskripsi,
|
|
||||||
tanggal: tanggal,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
id: v.id,
|
|
||||||
jenisInformasi: v.jenisInformasi,
|
|
||||||
deskripsi: v.deskripsi,
|
|
||||||
tanggal: tanggal,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log("daftar informasi publik PPID success ...");
|
|
||||||
|
|
||||||
for (const l of pelayananPerizinanBerusaha) {
|
for (const l of pelayananPerizinanBerusaha) {
|
||||||
await prisma.pelayananPerizinanBerusaha.upsert({
|
await prisma.pelayananPerizinanBerusaha.upsert({
|
||||||
@@ -807,6 +524,48 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
}
|
}
|
||||||
console.log("cara memperoleh salinan informasi success ...");
|
console.log("cara memperoleh salinan informasi success ...");
|
||||||
|
|
||||||
|
for (const c of profilePPID) {
|
||||||
|
await prisma.profilePPID.upsert({
|
||||||
|
where: { id: c.id },
|
||||||
|
update: {
|
||||||
|
name: c.name,
|
||||||
|
biodata: c.biodata,
|
||||||
|
riwayat: c.riwayat,
|
||||||
|
pengalaman: c.pengalaman,
|
||||||
|
unggulan: c.unggulan,
|
||||||
|
imageId: c.imageId,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
id: c.id,
|
||||||
|
name: c.name,
|
||||||
|
biodata: c.biodata,
|
||||||
|
riwayat: c.riwayat,
|
||||||
|
pengalaman: c.pengalaman,
|
||||||
|
unggulan: c.unggulan,
|
||||||
|
imageId: c.imageId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.log("✅ profilePPID seeded without imageId (editable later via UI)");
|
||||||
|
|
||||||
|
for (const v of visiMisiPPID) {
|
||||||
|
await prisma.visiMisiPPID.upsert({
|
||||||
|
where: {
|
||||||
|
id: v.id,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
misi: v.misi,
|
||||||
|
visi: v.visi,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
id: v.id,
|
||||||
|
misi: v.misi,
|
||||||
|
visi: v.visi,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.log("visi misi PPID success ...");
|
||||||
|
|
||||||
for (const j of jenisKelamin) {
|
for (const j of jenisKelamin) {
|
||||||
await prisma.jenisKelaminResponden.upsert({
|
await prisma.jenisKelaminResponden.upsert({
|
||||||
where: {
|
where: {
|
||||||
@@ -855,6 +614,24 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
}
|
}
|
||||||
console.log("umur responden success ...");
|
console.log("umur responden success ...");
|
||||||
|
|
||||||
|
for (const v of dasarHukumPPID) {
|
||||||
|
await prisma.dasarHukumPPID.upsert({
|
||||||
|
where: {
|
||||||
|
id: v.id,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
judul: v.judul,
|
||||||
|
content: v.content,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
id: v.id,
|
||||||
|
judul: v.judul,
|
||||||
|
content: v.content,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.log("dasar hukum PPID success ...");
|
||||||
|
|
||||||
for (const k of kategoriProduk) {
|
for (const k of kategoriProduk) {
|
||||||
await prisma.kategoriProduk.upsert({
|
await prisma.kategoriProduk.upsert({
|
||||||
where: {
|
where: {
|
||||||
@@ -871,36 +648,28 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
}
|
}
|
||||||
console.log("kategori produk success ...");
|
console.log("kategori produk success ...");
|
||||||
|
|
||||||
const flattenedPosisiBumdes = posisiOrganisasi.flat();
|
for (const p of posisiOrganisasi) {
|
||||||
|
await prisma.posisiOrganisasi.upsert({
|
||||||
// ✅ Urutkan berdasarkan hierarki
|
where: {
|
||||||
const sortedPosisiBumdes = flattenedPosisiBumdes.sort(
|
id: p.id,
|
||||||
(a, b) => a.hierarki - b.hierarki
|
},
|
||||||
);
|
update: {
|
||||||
|
nama: p.nama,
|
||||||
for (const p of sortedPosisiBumdes) {
|
deskripsi: p.deskripsi,
|
||||||
console.log(`Seeding: ${p.nama} (id: ${p.id}, parent: ${p.parentId})`);
|
hierarki: p.hierarki,
|
||||||
|
},
|
||||||
if (p.parentId) {
|
create: {
|
||||||
const parentExists = flattenedPosisi.some((pos) => pos.id === p.parentId);
|
id: p.id,
|
||||||
if (!parentExists) {
|
nama: p.nama,
|
||||||
console.warn(
|
deskripsi: p.deskripsi,
|
||||||
`⚠️ Parent tidak ditemukan: ${p.parentId} untuk ${p.nama}`
|
hierarki: p.hierarki,
|
||||||
);
|
},
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await prisma.posisiOrganisasiBumDes.upsert({
|
|
||||||
where: { id: p.id },
|
|
||||||
update: p,
|
|
||||||
create: p,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log("posisi organisasi berhasil");
|
console.log("posisi organisasi success ...");
|
||||||
|
|
||||||
for (const p of pegawai) {
|
for (const p of pegawai) {
|
||||||
await prisma.pegawaiBumDes.upsert({
|
await prisma.pegawai.upsert({
|
||||||
where: {
|
where: {
|
||||||
id: p.id,
|
id: p.id,
|
||||||
},
|
},
|
||||||
@@ -929,6 +698,26 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
}
|
}
|
||||||
console.log("pegawai success ...");
|
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) {
|
for (const d of detailDataPengangguran) {
|
||||||
await prisma.detailDataPengangguran.upsert({
|
await prisma.detailDataPengangguran.upsert({
|
||||||
where: {
|
where: {
|
||||||
@@ -952,30 +741,6 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
}
|
}
|
||||||
console.log("📊 detailDataPengangguran success ...");
|
console.log("📊 detailDataPengangguran success ...");
|
||||||
|
|
||||||
// =========== KATEGORI GOTONG ROYONG ===========
|
|
||||||
// Add IDs to the kategoriKegiatan data
|
|
||||||
const kategoriKegiatan = kategoriKegiatanData.map((k, index) => ({
|
|
||||||
...k,
|
|
||||||
id: `kategori-${index + 1}`,
|
|
||||||
}));
|
|
||||||
|
|
||||||
for (const k of kategoriKegiatan) {
|
|
||||||
await prisma.kategoriKegiatan.upsert({
|
|
||||||
where: {
|
|
||||||
id: k.id,
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
nama: k.nama,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
id: k.id,
|
|
||||||
nama: k.nama,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("kategori kegiatan success ...");
|
|
||||||
|
|
||||||
for (const e of tujuanEdukasiLingkungan) {
|
for (const e of tujuanEdukasiLingkungan) {
|
||||||
await prisma.tujuanEdukasiLingkungan.upsert({
|
await prisma.tujuanEdukasiLingkungan.upsert({
|
||||||
where: {
|
where: {
|
||||||
@@ -1229,25 +994,6 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
console.log(
|
console.log(
|
||||||
"✅ fasilitas bimbingan belajar desa seeded (editable later via UI)"
|
"✅ fasilitas bimbingan belajar desa seeded (editable later via UI)"
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const j of jenjangPendidikan) {
|
|
||||||
await prisma.jenjangPendidikan.upsert({
|
|
||||||
where: {
|
|
||||||
id: j.id || undefined,
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
nama: j.nama,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
nama: j.nama,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("✅ Jenjang Pendidikan seeded successfully");
|
|
||||||
|
|
||||||
// seed assets
|
|
||||||
await seedAssets();
|
|
||||||
})()
|
})()
|
||||||
.then(() => prisma.$disconnect())
|
.then(() => prisma.$disconnect())
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
|
|||||||
@@ -1,118 +0,0 @@
|
|||||||
// prisma/seedAssets.ts
|
|
||||||
import fs from "fs/promises";
|
|
||||||
import path from "path";
|
|
||||||
import sharp from "sharp";
|
|
||||||
import fetch from "node-fetch";
|
|
||||||
import AdmZip from "adm-zip";
|
|
||||||
import prisma from "@/lib/prisma";
|
|
||||||
|
|
||||||
const UPLOADS_DIR =
|
|
||||||
process.env.WIBU_UPLOAD_DIR || path.join(process.cwd(), "uploads");
|
|
||||||
|
|
||||||
// --- Helper: deteksi kategori file ---
|
|
||||||
function detectCategory(filename: string): "image" | "document" | "other" {
|
|
||||||
const ext = path.extname(filename).toLowerCase();
|
|
||||||
if ([".jpg", ".jpeg", ".png", ".webp"].includes(ext)) return "image";
|
|
||||||
if ([".pdf", ".doc", ".docx"].includes(ext)) return "document";
|
|
||||||
return "other";
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Helper: recursive walk dir ---
|
|
||||||
async function walkDir(dir: string, fileList: string[] = []): Promise<string[]> {
|
|
||||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
||||||
|
|
||||||
for (const entry of entries) {
|
|
||||||
const fullPath = path.join(dir, entry.name);
|
|
||||||
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
if (entry.name === "__MACOSX") continue; // skip folder sampah
|
|
||||||
await walkDir(fullPath, fileList);
|
|
||||||
} else {
|
|
||||||
if (entry.name.startsWith(".") || entry.name === ".DS_Store") continue; // skip file sampah
|
|
||||||
fileList.push(fullPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileList;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function seedAssets() {
|
|
||||||
console.log("🚀 Seeding assets...");
|
|
||||||
|
|
||||||
// 1. Download zip
|
|
||||||
const url =
|
|
||||||
"https://cld-dkr-makuro-seafile.wibudev.com/f/ffd5a548a04f47939474/?dl=1";
|
|
||||||
const res = await fetch(url);
|
|
||||||
if (!res.ok) throw new Error(`Gagal download assets: ${res.statusText}`);
|
|
||||||
const buffer = Buffer.from(await res.arrayBuffer());
|
|
||||||
|
|
||||||
// 2. Extract zip ke folder tmp
|
|
||||||
const extractDir = path.join(process.cwd(), "tmp_assets");
|
|
||||||
await fs.rm(extractDir, { recursive: true, force: true });
|
|
||||||
await fs.mkdir(extractDir, { recursive: true });
|
|
||||||
|
|
||||||
const zip = new AdmZip(buffer);
|
|
||||||
zip.extractAllTo(extractDir, true);
|
|
||||||
|
|
||||||
// 3. Cari semua file valid (recursive)
|
|
||||||
const files = await walkDir(extractDir);
|
|
||||||
|
|
||||||
// 4. Loop tiap file & simpan
|
|
||||||
for (const filePath of files) {
|
|
||||||
const entryName = path.basename(filePath);
|
|
||||||
const category = detectCategory(entryName);
|
|
||||||
|
|
||||||
let finalName = entryName;
|
|
||||||
let mimeType = "application/octet-stream";
|
|
||||||
let targetPath = "";
|
|
||||||
|
|
||||||
if (category === "image") {
|
|
||||||
const fileBaseName = path.parse(entryName).name;
|
|
||||||
finalName = `${fileBaseName}.webp`;
|
|
||||||
targetPath = path.join(UPLOADS_DIR, "images", finalName);
|
|
||||||
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
||||||
await sharp(filePath).webp({ quality: 80 }).toFile(targetPath);
|
|
||||||
mimeType = "image/webp";
|
|
||||||
} else if (category === "document") {
|
|
||||||
targetPath = path.join(UPLOADS_DIR, "documents", entryName);
|
|
||||||
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
||||||
await fs.copyFile(filePath, targetPath);
|
|
||||||
mimeType = "application/pdf";
|
|
||||||
} else {
|
|
||||||
targetPath = path.join(UPLOADS_DIR, "other", entryName);
|
|
||||||
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
||||||
await fs.copyFile(filePath, targetPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Simpan ke DB
|
|
||||||
await prisma.fileStorage.create({
|
|
||||||
data: {
|
|
||||||
name: finalName,
|
|
||||||
realName: entryName,
|
|
||||||
path: targetPath,
|
|
||||||
mimeType,
|
|
||||||
link: `/uploads/${category}/${finalName}`,
|
|
||||||
category,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`📂 saved: ${category}/${finalName}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. Cleanup
|
|
||||||
await fs.rm(extractDir, { recursive: true, force: true });
|
|
||||||
|
|
||||||
console.log("✅ Selesai seed assets!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Auto run kalau dipanggil langsung ---
|
|
||||||
if (import.meta.main) {
|
|
||||||
seedAssets()
|
|
||||||
.catch((err) => {
|
|
||||||
console.error("❌ Error seeding assets:", err);
|
|
||||||
process.exit(1);
|
|
||||||
})
|
|
||||||
.finally(async () => {
|
|
||||||
await prisma.$disconnect();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
BIN
public/assets/images/perbekel.png
Normal file
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 446 KiB |
|
Before Width: | Height: | Size: 303 KiB |
|
Before Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 378 KiB After Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 195 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 275 KiB |
@@ -23,7 +23,6 @@ export default function SpashScreen() {
|
|||||||
<Paper p={"md"} miw={320}>
|
<Paper p={"md"} miw={320}>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Image
|
<Image
|
||||||
loading="lazy"
|
|
||||||
src={images["darmasaba-icon"]}
|
src={images["darmasaba-icon"]}
|
||||||
alt="darmasaba"
|
alt="darmasaba"
|
||||||
w={100}
|
w={100}
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
'use client';
|
|
||||||
|
|
||||||
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
|
|
||||||
import { LatLngExpression } from 'leaflet';
|
|
||||||
import 'leaflet/dist/leaflet.css';
|
|
||||||
import L from 'leaflet';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
type MarkerData = {
|
|
||||||
position: [number, number];
|
|
||||||
popup: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
center: [number, number];
|
|
||||||
markers: MarkerData[];
|
|
||||||
zoom?: number;
|
|
||||||
scrollWheelZoom?: boolean;
|
|
||||||
className?: string;
|
|
||||||
style?: React.CSSProperties;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function LeafletMultiMarkerMap({
|
|
||||||
center,
|
|
||||||
markers,
|
|
||||||
zoom = 13,
|
|
||||||
scrollWheelZoom = true,
|
|
||||||
className = '',
|
|
||||||
style = { height: '100%', width: '100%', zIndex: 0 },
|
|
||||||
}: Props) {
|
|
||||||
// Fix for default marker icons in Next.js
|
|
||||||
useEffect(() => {
|
|
||||||
delete (L.Icon.Default.prototype as any)._getIconUrl;
|
|
||||||
L.Icon.Default.mergeOptions({
|
|
||||||
iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png',
|
|
||||||
iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png',
|
|
||||||
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png',
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={className} style={style}>
|
|
||||||
<MapContainer
|
|
||||||
center={center as LatLngExpression}
|
|
||||||
zoom={zoom}
|
|
||||||
scrollWheelZoom={scrollWheelZoom}
|
|
||||||
style={{ height: '100%', width: '100%' }}
|
|
||||||
>
|
|
||||||
<TileLayer
|
|
||||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
|
||||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
|
||||||
/>
|
|
||||||
{markers.map((marker, index) => (
|
|
||||||
<Marker key={index} position={marker.position as LatLngExpression}>
|
|
||||||
<Popup>{marker.popup}</Popup>
|
|
||||||
</Marker>
|
|
||||||
))}
|
|
||||||
</MapContainer>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ import Underline from '@tiptap/extension-underline';
|
|||||||
import TextAlign from '@tiptap/extension-text-align';
|
import TextAlign from '@tiptap/extension-text-align';
|
||||||
import Superscript from '@tiptap/extension-superscript';
|
import Superscript from '@tiptap/extension-superscript';
|
||||||
import SubScript from '@tiptap/extension-subscript';
|
import SubScript from '@tiptap/extension-subscript';
|
||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
type CreateEditorProps = {
|
type CreateEditorProps = {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -33,13 +32,6 @@ export default function CreateEditor({ value, onChange }: CreateEditorProps) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 👇 Tambahkan efek untuk sinkronisasi value dari luar (resetForm)
|
|
||||||
useEffect(() => {
|
|
||||||
if (editor && value !== editor.getHTML()) {
|
|
||||||
editor.commands.setContent(value || '');
|
|
||||||
}
|
|
||||||
}, [value, editor]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RichTextEditor editor={editor}>
|
<RichTextEditor editor={editor}>
|
||||||
<RichTextEditor.Toolbar sticky stickyOffset="var(--docs-header-height)">
|
<RichTextEditor.Toolbar sticky stickyOffset="var(--docs-header-height)">
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ export default function EditEditor({ value, onChange }: EditEditorProps) {
|
|||||||
editor.off('update', updateHandler);
|
editor.off('update', updateHandler);
|
||||||
};
|
};
|
||||||
}, [editor, onChange]);
|
}, [editor, onChange]);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RichTextEditor editor={editor}>
|
<RichTextEditor editor={editor}>
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
'use client'
|
|
||||||
|
|
||||||
import React from 'react'
|
|
||||||
import {
|
|
||||||
IconLeaf,
|
|
||||||
IconTrophy,
|
|
||||||
IconTent,
|
|
||||||
IconChartLine,
|
|
||||||
IconRecycle,
|
|
||||||
IconTruck,
|
|
||||||
IconScale,
|
|
||||||
IconClipboard,
|
|
||||||
IconTrash,
|
|
||||||
IconHomeEco,
|
|
||||||
IconChristmasTreeFilled,
|
|
||||||
IconTrendingUp,
|
|
||||||
IconShieldFilled,
|
|
||||||
IconHome,
|
|
||||||
IconTree,
|
|
||||||
IconDroplet,
|
|
||||||
IconCash,
|
|
||||||
IconSchool,
|
|
||||||
IconShoppingCart,
|
|
||||||
IconHospital,
|
|
||||||
IconAmbulance,
|
|
||||||
IconFiretruck,
|
|
||||||
IconBuilding,
|
|
||||||
IconAlertTriangle,
|
|
||||||
} from '@tabler/icons-react'
|
|
||||||
|
|
||||||
export type IconKey =
|
|
||||||
| 'ekowisata'
|
|
||||||
| 'kompetisi'
|
|
||||||
| 'wisata'
|
|
||||||
| 'ekonomi'
|
|
||||||
| 'sampah'
|
|
||||||
| 'truck'
|
|
||||||
| 'scale'
|
|
||||||
| 'clipboard'
|
|
||||||
| 'trash'
|
|
||||||
| 'lingkunganSehat'
|
|
||||||
| 'sumberOksigen'
|
|
||||||
| 'ekonomiBerkelanjutan'
|
|
||||||
| 'mencegahBencana'
|
|
||||||
| 'rumah'
|
|
||||||
| 'pohon'
|
|
||||||
| 'air'
|
|
||||||
| 'bantuan'
|
|
||||||
| 'pelatihan'
|
|
||||||
| 'subsidi'
|
|
||||||
| 'layananKesehatan'
|
|
||||||
| 'polisi'
|
|
||||||
| 'ambulans'
|
|
||||||
| 'pemadam'
|
|
||||||
| 'rumahSakit'
|
|
||||||
| 'bangunan'
|
|
||||||
| 'darurat'
|
|
||||||
|
|
||||||
|
|
||||||
const iconMap: Record<IconKey, React.FC<any>> = {
|
|
||||||
ekowisata: IconLeaf,
|
|
||||||
kompetisi: IconTrophy,
|
|
||||||
wisata: IconTent,
|
|
||||||
ekonomi: IconChartLine,
|
|
||||||
sampah: IconRecycle,
|
|
||||||
truck: IconTruck,
|
|
||||||
scale: IconScale,
|
|
||||||
clipboard: IconClipboard,
|
|
||||||
trash: IconTrash,
|
|
||||||
lingkunganSehat: IconHomeEco,
|
|
||||||
sumberOksigen: IconChristmasTreeFilled,
|
|
||||||
ekonomiBerkelanjutan: IconTrendingUp,
|
|
||||||
mencegahBencana: IconShieldFilled,
|
|
||||||
rumah: IconHome,
|
|
||||||
pohon: IconTree,
|
|
||||||
air: IconDroplet,
|
|
||||||
bantuan: IconCash,
|
|
||||||
pelatihan: IconSchool,
|
|
||||||
subsidi: IconShoppingCart,
|
|
||||||
layananKesehatan: IconHospital,
|
|
||||||
polisi: IconShieldFilled,
|
|
||||||
ambulans: IconAmbulance,
|
|
||||||
pemadam: IconFiretruck,
|
|
||||||
rumahSakit: IconHospital,
|
|
||||||
bangunan: IconBuilding,
|
|
||||||
darurat: IconAlertTriangle
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
name: IconKey
|
|
||||||
size?: number
|
|
||||||
color?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export const IconMapper: React.FC<Props> = ({ name, size = 24, color }) => {
|
|
||||||
const IconComponent = iconMap[name]
|
|
||||||
if (!IconComponent) return null
|
|
||||||
return <IconComponent size={size} color={color} />
|
|
||||||
}
|
|
||||||
@@ -3,24 +3,16 @@
|
|||||||
|
|
||||||
import { Box, rem, Select } from '@mantine/core';
|
import { Box, rem, Select } from '@mantine/core';
|
||||||
import {
|
import {
|
||||||
IconAlertTriangle,
|
|
||||||
IconAmbulance,
|
|
||||||
IconBuilding,
|
|
||||||
IconCash,
|
|
||||||
IconChartLine,
|
IconChartLine,
|
||||||
IconChristmasTreeFilled,
|
IconChristmasTreeFilled,
|
||||||
IconClipboardTextFilled,
|
IconClipboardTextFilled,
|
||||||
IconDroplet,
|
IconDroplet,
|
||||||
IconFiretruck,
|
|
||||||
IconHome,
|
IconHome,
|
||||||
IconHomeEco,
|
IconHomeEco,
|
||||||
IconHospital,
|
|
||||||
IconLeaf,
|
IconLeaf,
|
||||||
IconRecycle,
|
IconRecycle,
|
||||||
IconScale,
|
IconScale,
|
||||||
IconSchool,
|
|
||||||
IconShieldFilled,
|
IconShieldFilled,
|
||||||
IconShoppingCart,
|
|
||||||
IconTent,
|
IconTent,
|
||||||
IconTrashFilled,
|
IconTrashFilled,
|
||||||
IconTree,
|
IconTree,
|
||||||
@@ -40,23 +32,13 @@ const iconMap = {
|
|||||||
scale: { label: 'Scale', icon: IconScale },
|
scale: { label: 'Scale', icon: IconScale },
|
||||||
clipboard: { label: 'Clipboard', icon: IconClipboardTextFilled },
|
clipboard: { label: 'Clipboard', icon: IconClipboardTextFilled },
|
||||||
trash: { label: 'Trash', icon: IconTrashFilled },
|
trash: { label: 'Trash', icon: IconTrashFilled },
|
||||||
lingkunganSehat: { label: 'Lingkungan Sehat', icon: IconHomeEco },
|
lingkunganSehat: {label: 'Lingkungan Sehat', icon: IconHomeEco},
|
||||||
sumberOksigen: { label: 'Sumber Oksigen', icon: IconChristmasTreeFilled },
|
sumberOksigen: {label: 'Sumber Oksigen', icon: IconChristmasTreeFilled},
|
||||||
ekonomiBerkelanjutan: { label: 'Ekonomi Berkelanjutan', icon: IconTrendingUp },
|
ekonomiBerkelanjutan: {label: 'Ekonomi Berkelanjutan', icon: IconTrendingUp},
|
||||||
mencegahBencana: { label: 'Mencegah Bencana', icon: IconShieldFilled },
|
mencegahBencana: {label: 'Mencegah Bencana', icon: IconShieldFilled},
|
||||||
rumah: { label: 'Rumah', icon: IconHome },
|
rumah: {label: 'Rumah', icon: IconHome},
|
||||||
pohon: { label: 'Pohon', icon: IconTree },
|
pohon: {label: 'Pohon', icon: IconTree},
|
||||||
air: { label: 'Air', icon: IconDroplet },
|
air: {label: 'Air', icon: IconDroplet}
|
||||||
bantuan: { label: 'Bantuan', icon: IconCash },
|
|
||||||
pelatihan: { label: 'Pelatihan', icon: IconSchool },
|
|
||||||
subsidi: { label: 'Subsidi', icon: IconShoppingCart },
|
|
||||||
layananKesehatan: { label: 'Layanan Kesehatan', icon: IconHospital },
|
|
||||||
polisi: { label: 'Polisi', icon: IconShieldFilled },
|
|
||||||
ambulans: { label: 'Ambulans', icon: IconAmbulance },
|
|
||||||
pemadam: { label: 'Pemadam', icon: IconFiretruck },
|
|
||||||
rumahSakit: { label: 'Rumah Sakit', icon: IconHospital },
|
|
||||||
bangunan: { label: 'Bangunan', icon: IconBuilding },
|
|
||||||
darurat: { label: 'Darurat', icon: IconAlertTriangle },
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +1,23 @@
|
|||||||
'use client';
|
'use client'
|
||||||
|
|
||||||
import { Box, Group, rem, Select, SelectProps } from '@mantine/core';
|
import { Box, rem, Select } from '@mantine/core';
|
||||||
import {
|
import {
|
||||||
IconAmbulance,
|
|
||||||
IconCash,
|
|
||||||
IconChartLine,
|
IconChartLine,
|
||||||
IconChristmasTreeFilled,
|
IconChristmasTreeFilled,
|
||||||
IconClipboardTextFilled,
|
IconClipboardTextFilled,
|
||||||
IconDroplet,
|
IconDroplet,
|
||||||
IconFiretruck,
|
|
||||||
IconHome,
|
IconHome,
|
||||||
IconHomeEco,
|
IconHomeEco,
|
||||||
IconHospital,
|
|
||||||
IconLeaf,
|
IconLeaf,
|
||||||
IconRecycle,
|
IconRecycle,
|
||||||
IconScale,
|
IconScale,
|
||||||
IconSchool,
|
|
||||||
IconShieldFilled,
|
IconShieldFilled,
|
||||||
IconShoppingCart,
|
|
||||||
IconTent,
|
IconTent,
|
||||||
IconTrashFilled,
|
IconTrashFilled,
|
||||||
IconTree,
|
IconTree,
|
||||||
IconTrendingUp,
|
IconTrendingUp,
|
||||||
IconTrophy,
|
IconTrophy,
|
||||||
IconTruckFilled,
|
IconTruckFilled,
|
||||||
IconBuilding,
|
|
||||||
IconAlertTriangle,
|
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
|
|
||||||
const iconMap = {
|
const iconMap = {
|
||||||
@@ -38,26 +30,16 @@ const iconMap = {
|
|||||||
scale: { label: 'Scale', icon: IconScale },
|
scale: { label: 'Scale', icon: IconScale },
|
||||||
clipboard: { label: 'Clipboard', icon: IconClipboardTextFilled },
|
clipboard: { label: 'Clipboard', icon: IconClipboardTextFilled },
|
||||||
trash: { label: 'Trash', icon: IconTrashFilled },
|
trash: { label: 'Trash', icon: IconTrashFilled },
|
||||||
lingkunganSehat: { label: 'Lingkungan Sehat', icon: IconHomeEco },
|
lingkunganSehat: {label: 'Lingkungan Sehat', icon: IconHomeEco},
|
||||||
sumberOksigen: { label: 'Sumber Oksigen', icon: IconChristmasTreeFilled },
|
sumberOksigen: {label: 'Sumber Oksigen', icon: IconChristmasTreeFilled},
|
||||||
ekonomiBerkelanjutan: { label: 'Ekonomi Berkelanjutan', icon: IconTrendingUp },
|
ekonomiBerkelanjutan: {label: 'Ekonomi Berkelanjutan', icon: IconTrendingUp},
|
||||||
mencegahBencana: { label: 'Mencegah Bencana', icon: IconShieldFilled },
|
mencegahBencana: {label: 'Mencegah Bencana', icon: IconShieldFilled},
|
||||||
rumah: { label: 'Rumah', icon: IconHome },
|
rumah: {label: 'Rumah', icon: IconHome},
|
||||||
pohon: { label: 'Pohon', icon: IconTree },
|
pohon: {label: 'Pohon', icon: IconTree},
|
||||||
air: { label: 'Air', icon: IconDroplet },
|
air: {label: 'Air', icon: IconDroplet}
|
||||||
bantuan: { label: 'Bantuan', icon: IconCash },
|
|
||||||
pelatihan: { label: 'Pelatihan', icon: IconSchool },
|
|
||||||
subsidi: { label: 'Subsidi', icon: IconShoppingCart },
|
|
||||||
layananKesehatan: { label: 'Layanan Kesehatan', icon: IconHospital },
|
|
||||||
polisi: { label: 'Polisi', icon: IconShieldFilled },
|
|
||||||
ambulans: { label: 'Ambulans', icon: IconAmbulance },
|
|
||||||
pemadam: { label: 'Pemadam', icon: IconFiretruck },
|
|
||||||
rumahSakit: { label: 'Rumah Sakit', icon: IconHospital },
|
|
||||||
bangunan: { label: 'Bangunan', icon: IconBuilding },
|
|
||||||
darurat: { label: 'Darurat', icon: IconAlertTriangle },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IconKey = keyof typeof iconMap;
|
type IconKey = keyof typeof iconMap;
|
||||||
|
|
||||||
const iconList = Object.entries(iconMap).map(([value, data]) => ({
|
const iconList = Object.entries(iconMap).map(([value, data]) => ({
|
||||||
value,
|
value,
|
||||||
@@ -67,52 +49,44 @@ const iconList = Object.entries(iconMap).map(([value, data]) => ({
|
|||||||
export default function SelectIconProgramEdit({
|
export default function SelectIconProgramEdit({
|
||||||
onChange,
|
onChange,
|
||||||
value,
|
value,
|
||||||
...props
|
|
||||||
}: {
|
}: {
|
||||||
onChange: (value: IconKey | '') => void;
|
onChange: (value: IconKey) => void;
|
||||||
value: IconKey | '';
|
value: IconKey;
|
||||||
} & Omit<SelectProps, 'onChange' | 'value' | 'data'>) {
|
}) {
|
||||||
|
const IconComponent = iconMap[value]?.icon || null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box maw={300}>
|
<Box maw={300}>
|
||||||
<Select
|
<Select
|
||||||
placeholder="Pilih ikon"
|
placeholder="Pilih ikon"
|
||||||
value={value || ''}
|
value={value}
|
||||||
onChange={(val: string | null) => {
|
onChange={(value) => {
|
||||||
if (val) {
|
if (value) onChange(value as IconKey);
|
||||||
onChange(val as IconKey);
|
|
||||||
} else {
|
|
||||||
onChange('');
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
data={iconList}
|
data={iconList}
|
||||||
renderOption={({ option }) => {
|
|
||||||
const Icon = iconMap[option.value as IconKey]?.icon;
|
|
||||||
return (
|
|
||||||
<Group gap="sm">
|
|
||||||
{Icon && <Icon size={18} stroke={1.5} />}
|
|
||||||
{option.label}
|
|
||||||
</Group>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
leftSection={
|
leftSection={
|
||||||
value && iconMap[value as IconKey] ? (
|
IconComponent && (
|
||||||
<Box ml={-4}>
|
<Box>
|
||||||
{(() => {
|
<IconComponent size={24} stroke={1.5} />
|
||||||
const Icon = iconMap[value as IconKey].icon;
|
|
||||||
return <Icon size={20} stroke={1.5} />;
|
|
||||||
})()}
|
|
||||||
</Box>
|
</Box>
|
||||||
) : null
|
)
|
||||||
}
|
}
|
||||||
searchable
|
withCheckIcon={false}
|
||||||
|
searchable={false}
|
||||||
|
rightSectionWidth={0}
|
||||||
styles={{
|
styles={{
|
||||||
input: {
|
input: {
|
||||||
paddingLeft: 40,
|
textAlign: 'left',
|
||||||
fontSize: rem(16),
|
fontSize: rem(16),
|
||||||
|
paddingLeft: 40,
|
||||||
|
},
|
||||||
|
section: {
|
||||||
|
left: 10,
|
||||||
|
right: 'auto',
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
{...props}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { Box, Image, Select, rem } from '@mantine/core';
|
|
||||||
|
|
||||||
const sosmedMap = {
|
|
||||||
facebook: { label: 'Facebook', src: '/assets/images/sosmed/facebook.png' },
|
|
||||||
instagram: { label: 'Instagram', src: '/assets/images/sosmed/instagram.png' },
|
|
||||||
tiktok: { label: 'Tiktok', src: '/assets/images/sosmed/tiktok.png' },
|
|
||||||
youtube: { label: 'YouTube', src: '/assets/images/sosmed/youtube.png' },
|
|
||||||
whatsapp: { label: 'WhatsApp', src: '/assets/images/sosmed/whatsapp.png' },
|
|
||||||
gmail: { label: 'Gmail', src: '/assets/images/sosmed/gmail.png' },
|
|
||||||
telegram: { label: 'Telegram', src: '/assets/images/sosmed/telegram.png' },
|
|
||||||
x: { label: 'X (Twitter)', src: '/assets/images/sosmed/x-twitter.png' },
|
|
||||||
telephone: { label: 'Telephone', src: '/assets/images/sosmed/telephone-call.png' },
|
|
||||||
custom: { label: 'Custom Icon', src: null },
|
|
||||||
};
|
|
||||||
|
|
||||||
type SosmedKey = keyof typeof sosmedMap;
|
|
||||||
|
|
||||||
const sosmedList = Object.entries(sosmedMap).map(([value, item]) => ({
|
|
||||||
value,
|
|
||||||
label: item.label,
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default function SelectSosialMedia({
|
|
||||||
value,
|
|
||||||
onChange,
|
|
||||||
}: {
|
|
||||||
value: SosmedKey;
|
|
||||||
onChange: (value: SosmedKey) => void;
|
|
||||||
}) {
|
|
||||||
const selected = value;
|
|
||||||
const selectedImage = sosmedMap[selected]?.src;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box maw={300}>
|
|
||||||
<Select
|
|
||||||
placeholder="Pilih sosial media"
|
|
||||||
value={selected}
|
|
||||||
data={sosmedList}
|
|
||||||
searchable={false}
|
|
||||||
withCheckIcon={false}
|
|
||||||
onChange={(val) => val && onChange(val as SosmedKey)}
|
|
||||||
styles={{
|
|
||||||
input: {
|
|
||||||
textAlign: 'left',
|
|
||||||
fontSize: rem(16),
|
|
||||||
paddingLeft: 36,
|
|
||||||
},
|
|
||||||
section: {
|
|
||||||
left: 10,
|
|
||||||
right: 'auto',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* 🔥 PREVIEW DIPISAH DI LUAR SELECT */}
|
|
||||||
{selectedImage && (
|
|
||||||
<Box mt="md">
|
|
||||||
<Image
|
|
||||||
alt=""
|
|
||||||
src={selectedImage}
|
|
||||||
radius="md"
|
|
||||||
style={{
|
|
||||||
width: 120,
|
|
||||||
height: 120,
|
|
||||||
objectFit: 'contain',
|
|
||||||
border: '1px solid #eee',
|
|
||||||
padding: 8,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { Box, Select } from '@mantine/core';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
|
|
||||||
export const sosmedMap = {
|
|
||||||
facebook: { label: 'Facebook', src: '/assets/images/sosmed/facebook.png' },
|
|
||||||
instagram: { label: 'Instagram', src: '/assets/images/sosmed/instagram.png' },
|
|
||||||
tiktok: { label: 'Tiktok', src: '/assets/images/sosmed/tiktok.png' },
|
|
||||||
youtube: { label: 'YouTube', src: '/assets/images/sosmed/youtube.png' },
|
|
||||||
whatsapp: { label: 'WhatsApp', src: '/assets/images/sosmed/whatsapp.png' },
|
|
||||||
gmail: { label: 'Gmail', src: '/assets/images/sosmed/gmail.png' },
|
|
||||||
telegram: { label: 'Telegram', src: '/assets/images/sosmed/telegram.png' },
|
|
||||||
x: { label: 'X (Twitter)', src: '/assets/images/sosmed/x-twitter.png' },
|
|
||||||
telephone: { label: 'Telephone', src: '/assets/images/sosmed/telephone-call.png' },
|
|
||||||
custom: { label: 'Custom Icon', src: null },
|
|
||||||
};
|
|
||||||
|
|
||||||
type SosmedKey = keyof typeof sosmedMap;
|
|
||||||
|
|
||||||
const sosmedList = Object.entries(sosmedMap).map(([value, item]) => ({
|
|
||||||
value,
|
|
||||||
label: item.label,
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default function SelectSocialMediaEdit({
|
|
||||||
value,
|
|
||||||
onChange,
|
|
||||||
}: {
|
|
||||||
value: string;
|
|
||||||
onChange: (val: SosmedKey) => void;
|
|
||||||
}) {
|
|
||||||
const [selected, setSelected] = useState<SosmedKey>('facebook');
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (value && sosmedMap[value as SosmedKey]) {
|
|
||||||
setSelected(value as SosmedKey);
|
|
||||||
}
|
|
||||||
}, [value]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<Select
|
|
||||||
label="Jenis Media Sosial"
|
|
||||||
value={selected}
|
|
||||||
data={sosmedList}
|
|
||||||
searchable={false}
|
|
||||||
onChange={(val) => {
|
|
||||||
if (!val) return;
|
|
||||||
setSelected(val as SosmedKey);
|
|
||||||
onChange(val as SosmedKey);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -74,12 +74,11 @@ const berita = proxy({
|
|||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
search: "",
|
||||||
load: async (page = 1, limit = 10, search = "", kategori = "") => {
|
load: async (page = 1, limit = 10, search = "", kategori = "") => {
|
||||||
const startTime = Date.now();
|
berita.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||||
berita.findMany.loading = true;
|
|
||||||
berita.findMany.page = page;
|
berita.findMany.page = page;
|
||||||
berita.findMany.search = search;
|
berita.findMany.search = search;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit };
|
const query: any = { page, limit };
|
||||||
if (search) query.search = search;
|
if (search) query.search = search;
|
||||||
@@ -99,16 +98,9 @@ const berita = proxy({
|
|||||||
berita.findMany.data = [];
|
berita.findMany.data = [];
|
||||||
berita.findMany.totalPages = 1;
|
berita.findMany.totalPages = 1;
|
||||||
} finally {
|
} finally {
|
||||||
// pastikan minimal 300ms sebelum loading = false (biar UX smooth)
|
berita.findMany.loading = false;
|
||||||
const elapsed = Date.now() - startTime;
|
|
||||||
const minDelay = 300;
|
|
||||||
const delay = elapsed < minDelay ? minDelay - elapsed : 0;
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
berita.findMany.loading = false;
|
|
||||||
}, delay);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
findUnique: {
|
findUnique: {
|
||||||
@@ -376,37 +368,11 @@ const kategoriBerita = proxy({
|
|||||||
isActive: true;
|
isActive: true;
|
||||||
};
|
};
|
||||||
}>[],
|
}>[],
|
||||||
page: 1,
|
|
||||||
totalPages: 1,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
async load() {
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
const res = await ApiFetch.api.desa.kategoriberita["findMany"].get();
|
||||||
kategoriBerita.findMany.loading = true; // ✅ Akses langsung via nama path
|
if (res.status === 200) {
|
||||||
kategoriBerita.findMany.page = page;
|
kategoriBerita.findMany.data = res.data?.data ?? [];
|
||||||
kategoriBerita.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.desa.kategoriberita[
|
|
||||||
"findMany"
|
|
||||||
].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
kategoriBerita.findMany.data = res.data.data ?? [];
|
|
||||||
kategoriBerita.findMany.totalPages =
|
|
||||||
res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
kategoriBerita.findMany.data = [];
|
|
||||||
kategoriBerita.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch kategori berita paginated:", err);
|
|
||||||
kategoriBerita.findMany.data = [];
|
|
||||||
kategoriBerita.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
kategoriBerita.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const templateTelunjukSaktiDesaForm = z.object({
|
|||||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const templatePelayananPerizinanBerusaha = z.object({
|
const templatePelayananPerizinanBerusaha = z.object({
|
||||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||||
@@ -71,21 +72,6 @@ const pelayananPendudukNonPermanenForm = {
|
|||||||
deskripsi: "",
|
deskripsi: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
const templateAjukanForm = z.object({
|
|
||||||
nama: z.string().min(1).max(5000),
|
|
||||||
nik: z.string().min(1).max(5000),
|
|
||||||
alamat: z.string().min(1).max(5000),
|
|
||||||
nomorKk: z.string().min(1).max(5000),
|
|
||||||
kategoriId: z.string().min(1).max(5000),
|
|
||||||
});
|
|
||||||
|
|
||||||
const defaultAjukanForm = {
|
|
||||||
nama: "",
|
|
||||||
nik: "",
|
|
||||||
alamat: "",
|
|
||||||
nomorKk: "",
|
|
||||||
kategoriId: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
const suratKeterangan = proxy({
|
const suratKeterangan = proxy({
|
||||||
create: {
|
create: {
|
||||||
@@ -127,21 +113,16 @@ const suratKeterangan = proxy({
|
|||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
total: 0,
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
suratKeterangan.findMany.loading = true; // Use the full path to access the property
|
||||||
// Change to arrow function
|
|
||||||
suratKeterangan.findMany.loading = true; // Use the full path to access the property
|
|
||||||
suratKeterangan.findMany.page = page;
|
suratKeterangan.findMany.page = page;
|
||||||
suratKeterangan.findMany.search = search;
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
const res = await ApiFetch.api.desa.layanan.pelayanansuratketerangan[
|
const res = await ApiFetch.api.desa.layanan.pelayanansuratketerangan[
|
||||||
"find-many"
|
"find-many"
|
||||||
].get({
|
].get({
|
||||||
query,
|
query: { page, limit },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
if (res.status === 200 && res.data?.success) {
|
||||||
suratKeterangan.findMany.data = res.data.data || [];
|
suratKeterangan.findMany.data = res.data.data || [];
|
||||||
suratKeterangan.findMany.total = res.data.total || 0;
|
suratKeterangan.findMany.total = res.data.total || 0;
|
||||||
@@ -162,30 +143,6 @@ const suratKeterangan = proxy({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
findManyAll: {
|
|
||||||
data: null as Prisma.PelayananSuratKeteranganGetPayload<{
|
|
||||||
omit: { isActive: true };
|
|
||||||
}>[] | null,
|
|
||||||
loading: false,
|
|
||||||
load: async () => {
|
|
||||||
suratKeterangan.findManyAll.loading = true;
|
|
||||||
try {
|
|
||||||
const res = await ApiFetch.api.desa.layanan.pelayanansuratketerangan["findManyAll"].get();
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
suratKeterangan.findManyAll.data = res.data.data || [];
|
|
||||||
} else {
|
|
||||||
suratKeterangan.findManyAll.data = [];
|
|
||||||
console.error("Failed to load surat keterangan all:", res.data?.message);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error loading surat keterangan all:", error);
|
|
||||||
suratKeterangan.findManyAll.data = [];
|
|
||||||
} finally {
|
|
||||||
suratKeterangan.findManyAll.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
findUnique: {
|
findUnique: {
|
||||||
data: null as Prisma.PelayananSuratKeteranganGetPayload<{
|
data: null as Prisma.PelayananSuratKeteranganGetPayload<{
|
||||||
include: {
|
include: {
|
||||||
@@ -384,34 +341,28 @@ const pelayananTelunjukSaktiDesa = proxy({
|
|||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
total: 0,
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
pelayananTelunjukSaktiDesa.findMany.loading = true; // Use the full path to access the property
|
||||||
// Change to arrow function
|
|
||||||
pelayananTelunjukSaktiDesa.findMany.loading = true; // Use the full path to access the property
|
|
||||||
pelayananTelunjukSaktiDesa.findMany.page = page;
|
pelayananTelunjukSaktiDesa.findMany.page = page;
|
||||||
pelayananTelunjukSaktiDesa.findMany.search = search;
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
const res = await ApiFetch.api.desa.layanan.pelayanantelunjuksaktidesa[
|
const res = await ApiFetch.api.desa.layanan.pelayanantelunjuksaktidesa[
|
||||||
"find-many"
|
"find-many"
|
||||||
].get({
|
].get({
|
||||||
query,
|
query: { page, limit },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
if (res.status === 200 && res.data?.success) {
|
||||||
pelayananTelunjukSaktiDesa.findMany.data = res.data.data || [];
|
pelayananTelunjukSaktiDesa.findMany.data = res.data.data || [];
|
||||||
pelayananTelunjukSaktiDesa.findMany.total = res.data.total || 0;
|
pelayananTelunjukSaktiDesa.findMany.total = res.data.total || 0;
|
||||||
pelayananTelunjukSaktiDesa.findMany.totalPages =
|
pelayananTelunjukSaktiDesa.findMany.totalPages = res.data.totalPages || 1;
|
||||||
res.data.totalPages || 1;
|
|
||||||
} else {
|
} else {
|
||||||
console.error("Failed to load surat keterangan:", res.data?.message);
|
console.error("Failed to load telunjuk sakti desa:", res.data?.message);
|
||||||
pelayananTelunjukSaktiDesa.findMany.data = [];
|
pelayananTelunjukSaktiDesa.findMany.data = [];
|
||||||
suratKeterangan.findMany.total = 0;
|
pelayananTelunjukSaktiDesa.findMany.total = 0;
|
||||||
suratKeterangan.findMany.totalPages = 1;
|
pelayananTelunjukSaktiDesa.findMany.totalPages = 1;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error loading surat keterangan:", error);
|
console.error("Error loading telunjuk sakti desa:", error);
|
||||||
pelayananTelunjukSaktiDesa.findMany.data = [];
|
pelayananTelunjukSaktiDesa.findMany.data = [];
|
||||||
pelayananTelunjukSaktiDesa.findMany.total = 0;
|
pelayananTelunjukSaktiDesa.findMany.total = 0;
|
||||||
pelayananTelunjukSaktiDesa.findMany.totalPages = 1;
|
pelayananTelunjukSaktiDesa.findMany.totalPages = 1;
|
||||||
@@ -459,9 +410,7 @@ const pelayananTelunjukSaktiDesa = proxy({
|
|||||||
);
|
);
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
toast.success(
|
toast.success(result.message || "Telunjuk Sakti Desa berhasil dihapus");
|
||||||
result.message || "Telunjuk Sakti Desa berhasil dihapus"
|
|
||||||
);
|
|
||||||
await pelayananTelunjukSaktiDesa.findMany.load(); // refresh list
|
await pelayananTelunjukSaktiDesa.findMany.load(); // refresh list
|
||||||
} else {
|
} else {
|
||||||
toast.error(result.message || "Gagal menghapus telunjuk sakti desa");
|
toast.error(result.message || "Gagal menghapus telunjuk sakti desa");
|
||||||
@@ -552,9 +501,7 @@ const pelayananTelunjukSaktiDesa = proxy({
|
|||||||
}
|
}
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
toast.success(
|
toast.success(result.message || "Telunjuk Sakti Desa berhasil diupdate");
|
||||||
result.message || "Telunjuk Sakti Desa berhasil diupdate"
|
|
||||||
);
|
|
||||||
await pelayananTelunjukSaktiDesa.findMany.load(); // refresh list
|
await pelayananTelunjukSaktiDesa.findMany.load(); // refresh list
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -575,30 +522,39 @@ const pelayananTelunjukSaktiDesa = proxy({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const pelayananPerizinanBerusaha = proxy({
|
const pelayananPerizinanBerusaha = proxy({
|
||||||
findById: {
|
findById: {
|
||||||
data: null as pelayananPerizinanBerusahaForm | null,
|
data: null as pelayananPerizinanBerusahaForm | null,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
initialize() {
|
||||||
|
pelayananPerizinanBerusaha.findById.data = {
|
||||||
|
id: "",
|
||||||
|
name: "",
|
||||||
|
deskripsi: "",
|
||||||
|
link: "",
|
||||||
|
} as pelayananPerizinanBerusahaForm;
|
||||||
|
},
|
||||||
async load(id: string) {
|
async load(id: string) {
|
||||||
try {
|
try {
|
||||||
this.loading = true;
|
pelayananPerizinanBerusaha.findById.loading = true;
|
||||||
const response = await fetch(`/api/desa/layanan/pelayananperizinanberusaha/${id}`);
|
const res = await fetch(
|
||||||
if (!response.ok) {
|
`/api/desa/layanan/pelayananperizinanberusaha/${id}`
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
const result = await response.json();
|
|
||||||
if (result?.success) {
|
|
||||||
this.data = result.data; // Make sure this matches your API response structure
|
|
||||||
}
|
|
||||||
return result?.data || null;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading data:', error);
|
console.error("Error fetching pelayanan perizinan berusaha:", error);
|
||||||
toast.error('Gagal memuat data');
|
pelayananPerizinanBerusaha.findById.data = null;
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -640,7 +596,9 @@ const pelayananPerizinanBerusaha = proxy({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching pelayanan perizinan berusaha:", error);
|
console.error("Error fetching pelayanan perizinan berusaha:", error);
|
||||||
toast.error(
|
toast.error(
|
||||||
error instanceof Error ? error.message : "Gagal memuat data"
|
error instanceof Error
|
||||||
|
? error.message
|
||||||
|
: "Gagal memuat data"
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -755,7 +713,9 @@ const pelayananPendudukNonPermanen = proxy({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching pelayanan penduduk non permanen:", error);
|
console.error("Error fetching pelayanan penduduk non permanen:", error);
|
||||||
toast.error(
|
toast.error(
|
||||||
error instanceof Error ? error.message : "Gagal memuat data"
|
error instanceof Error
|
||||||
|
? error.message
|
||||||
|
: "Gagal memuat data"
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -800,250 +760,11 @@ const pelayananPendudukNonPermanen = proxy({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const ajukanPermohonan = proxy({
|
|
||||||
create: {
|
|
||||||
form: { ...defaultAjukanForm },
|
|
||||||
loading: false,
|
|
||||||
async create() {
|
|
||||||
const cek = templateAjukanForm.safeParse(
|
|
||||||
ajukanPermohonan.create.form
|
|
||||||
);
|
|
||||||
if (!cek.success) {
|
|
||||||
const err = `[${cek.error.issues
|
|
||||||
.map((v) => `${v.path.join(".")}`)
|
|
||||||
.join("\n")}] required`;
|
|
||||||
return toast.error(err);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
ajukanPermohonan.create.loading = true;
|
|
||||||
const res = await ApiFetch.api.desa.ajukanpermohonan[
|
|
||||||
"create"
|
|
||||||
].post(ajukanPermohonan.create.form);
|
|
||||||
if (res.status === 200) {
|
|
||||||
ajukanPermohonan.findMany.load();
|
|
||||||
return toast.success("Ajukan permohonan berhasil disimpan!");
|
|
||||||
}
|
|
||||||
return toast.error("Gagal menyimpan ajukan permohonan");
|
|
||||||
} catch (error) {
|
|
||||||
console.log((error as Error).message);
|
|
||||||
} finally {
|
|
||||||
ajukanPermohonan.create.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resetForm() {
|
|
||||||
ajukanPermohonan.create.form = { ...defaultAjukanForm };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
findMany: {
|
|
||||||
data: null as Prisma.AjukanPermohonanGetPayload<{
|
|
||||||
include: {
|
|
||||||
kategori: true;
|
|
||||||
};
|
|
||||||
}>[] | null,
|
|
||||||
page: 1,
|
|
||||||
totalPages: 1,
|
|
||||||
total: 0,
|
|
||||||
loading: false,
|
|
||||||
search: "",
|
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
|
||||||
// Change to arrow function
|
|
||||||
ajukanPermohonan.findMany.loading = true; // Use the full path to access the property
|
|
||||||
ajukanPermohonan.findMany.page = page;
|
|
||||||
ajukanPermohonan.findMany.search = search;
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
const res = await ApiFetch.api.desa.ajukanpermohonan[
|
|
||||||
"findMany"
|
|
||||||
].get({
|
|
||||||
query,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
ajukanPermohonan.findMany.data = res.data.data || [];
|
|
||||||
ajukanPermohonan.findMany.total = res.data.total || 0;
|
|
||||||
ajukanPermohonan.findMany.totalPages = res.data.totalPages || 1;
|
|
||||||
} else {
|
|
||||||
console.error("Failed to load ajukan permohonan:", res.data?.message);
|
|
||||||
ajukanPermohonan.findMany.data = [];
|
|
||||||
ajukanPermohonan.findMany.total = 0;
|
|
||||||
ajukanPermohonan.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error loading ajukan permohonan:", error);
|
|
||||||
ajukanPermohonan.findMany.data = [];
|
|
||||||
ajukanPermohonan.findMany.total = 0;
|
|
||||||
ajukanPermohonan.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
ajukanPermohonan.findMany.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
findUnique: {
|
|
||||||
data: null as Prisma.AjukanPermohonanGetPayload<{
|
|
||||||
include: {
|
|
||||||
kategori: true;
|
|
||||||
}
|
|
||||||
}> | null,
|
|
||||||
async load(id: string) {
|
|
||||||
try {
|
|
||||||
const res = await fetch(
|
|
||||||
`/api/desa/ajukanpermohonan/${id}`
|
|
||||||
);
|
|
||||||
if (res.ok) {
|
|
||||||
const data = await res.json();
|
|
||||||
ajukanPermohonan.findUnique.data = data.data ?? null;
|
|
||||||
} else {
|
|
||||||
console.error("Failed to fetch ajukan permohonan:", res.statusText);
|
|
||||||
ajukanPermohonan.findUnique.data = null;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching ajukan permohonan:", error);
|
|
||||||
ajukanPermohonan.findUnique.data = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
delete: {
|
|
||||||
loading: false,
|
|
||||||
async byId(id: string) {
|
|
||||||
if (!id) return toast.warn("ID tidak valid");
|
|
||||||
try {
|
|
||||||
ajukanPermohonan.delete.loading = true;
|
|
||||||
const response = await fetch(
|
|
||||||
`/api/desa/ajukanpermohonan/del/${id}`,
|
|
||||||
{
|
|
||||||
method: "DELETE",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const result = await response.json();
|
|
||||||
if (response.ok) {
|
|
||||||
toast.success(result.message || "Ajukan permohonan berhasil dihapus");
|
|
||||||
await ajukanPermohonan.findMany.load(); // refresh list
|
|
||||||
} else {
|
|
||||||
toast.error(result.message || "Gagal menghapus ajukan permohonan");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Gagal delete:", error);
|
|
||||||
toast.error("Terjadi kesalahan saat menghapus ajukan permohonan");
|
|
||||||
} finally {
|
|
||||||
ajukanPermohonan.delete.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
edit: {
|
|
||||||
id: "",
|
|
||||||
form: { ...defaultAjukanForm },
|
|
||||||
loading: false,
|
|
||||||
|
|
||||||
async load(id: string) {
|
|
||||||
if (!id) {
|
|
||||||
toast.warn("ID tidak valid");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`/api/desa/ajukanpermohonan/${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,
|
|
||||||
nik: data.nik,
|
|
||||||
alamat: data.alamat,
|
|
||||||
nomorKk: data.nomorKk,
|
|
||||||
kategoriId: data.kategoriId,
|
|
||||||
};
|
|
||||||
return data;
|
|
||||||
} else {
|
|
||||||
throw new Error(result.message || "Gagal memuat data");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching ajukan permohonan:", error);
|
|
||||||
toast.error(
|
|
||||||
error instanceof Error ? error.message : "Gagal memuat data"
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async update() {
|
|
||||||
const cek = templateAjukanForm.safeParse(
|
|
||||||
ajukanPermohonan.edit.form
|
|
||||||
);
|
|
||||||
if (!cek.success) {
|
|
||||||
const err = `[${cek.error.issues
|
|
||||||
.map((v) => `${v.path.join(".")}`)
|
|
||||||
.join("\n")}] required`;
|
|
||||||
return toast.error(err);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
ajukanPermohonan.edit.loading = true;
|
|
||||||
const response = await fetch(
|
|
||||||
`/api/desa/ajukanpermohonan/${this.id}`,
|
|
||||||
{
|
|
||||||
method: "PUT",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
nama: this.form.nama,
|
|
||||||
nik: this.form.nik,
|
|
||||||
alamat: this.form.alamat,
|
|
||||||
nomorKk: this.form.nomorKk,
|
|
||||||
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(result.message || "Ajukan permohonan berhasil diupdate");
|
|
||||||
await ajukanPermohonan.findMany.load(); // refresh list
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
throw new Error(
|
|
||||||
result.message || "Gagal mengupdate ajukan permohonan"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error updating ajukan permohonan:", error);
|
|
||||||
toast.error(
|
|
||||||
error instanceof Error
|
|
||||||
? error.message
|
|
||||||
: "Terjadi kesalahan saat update ajukan permohonan"
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
ajukanPermohonan.edit.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const stateLayananDesa = proxy({
|
const stateLayananDesa = proxy({
|
||||||
suratKeterangan,
|
suratKeterangan,
|
||||||
pelayananPerizinanBerusaha,
|
pelayananPerizinanBerusaha,
|
||||||
pelayananTelunjukSaktiDesa,
|
pelayananTelunjukSaktiDesa,
|
||||||
pelayananPendudukNonPermanen,
|
pelayananPendudukNonPermanen,
|
||||||
ajukanPermohonan,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default stateLayananDesa;
|
export default stateLayananDesa;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const penghargaanState = proxy({
|
|||||||
);
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
penghargaanState.findMany.load();
|
penghargaanState.findMany.load();
|
||||||
return toast.success("Sukses menambahkan");
|
return toast.success("success create");
|
||||||
}
|
}
|
||||||
console.log(res);
|
console.log(res);
|
||||||
return toast.error("failed create");
|
return toast.error("failed create");
|
||||||
@@ -56,21 +56,16 @@ const penghargaanState = proxy({
|
|||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
total: 0,
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
penghargaanState.findMany.loading = true; // Use the full path to access the property
|
||||||
// Change to arrow function
|
|
||||||
penghargaanState.findMany.loading = true; // Use the full path to access the property
|
|
||||||
penghargaanState.findMany.page = page;
|
penghargaanState.findMany.page = page;
|
||||||
penghargaanState.findMany.search = search;
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
const res = await ApiFetch.api.desa.penghargaan[
|
const res = await ApiFetch.api.desa.penghargaan[
|
||||||
"find-many"
|
"find-many"
|
||||||
].get({
|
].get({
|
||||||
query,
|
query: { page, limit },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
if (res.status === 200 && res.data?.success) {
|
||||||
penghargaanState.findMany.data = res.data.data || [];
|
penghargaanState.findMany.data = res.data.data || [];
|
||||||
penghargaanState.findMany.total = res.data.total || 0;
|
penghargaanState.findMany.total = res.data.total || 0;
|
||||||
|
|||||||
@@ -55,39 +55,11 @@ const category = proxy({
|
|||||||
pengumumans: number;
|
pengumumans: number;
|
||||||
};
|
};
|
||||||
})[],
|
})[],
|
||||||
page: 1,
|
|
||||||
totalPages: 1,
|
|
||||||
total: 0,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
async load() {
|
||||||
load: async (page = 1, limit = 10, search = "") => { // Change to arrow function
|
const res = await ApiFetch.api.desa.kategoripengumuman["findMany"].get();
|
||||||
category.findMany.loading = true; // Use the full path to access the property
|
if (res.status === 200) {
|
||||||
category.findMany.page = page;
|
category.findMany.data = res.data?.data ?? [];
|
||||||
category.findMany.search = search;
|
|
||||||
try {
|
|
||||||
const res = await ApiFetch.api.desa.kategoripengumuman[
|
|
||||||
"findMany"
|
|
||||||
].get({
|
|
||||||
query: { page, limit },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
category.findMany.data = res.data.data || [];
|
|
||||||
category.findMany.total = res.data.total || 0;
|
|
||||||
category.findMany.totalPages = res.data.totalPages || 1;
|
|
||||||
} else {
|
|
||||||
console.error("Failed to load potensi desa:", res.data?.message);
|
|
||||||
category.findMany.data = [];
|
|
||||||
category.findMany.total = 0;
|
|
||||||
category.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error loading potensi desa:", error);
|
|
||||||
category.findMany.data = [];
|
|
||||||
category.findMany.total = 0;
|
|
||||||
category.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
category.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -287,7 +259,7 @@ const pengumuman = proxy({
|
|||||||
);
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
pengumuman.findMany.load();
|
pengumuman.findMany.load();
|
||||||
return toast.success("Sukses menambahkan");
|
return toast.success("success create");
|
||||||
}
|
}
|
||||||
console.log(res);
|
console.log(res);
|
||||||
return toast.error("failed create");
|
return toast.error("failed create");
|
||||||
|
|||||||
@@ -56,11 +56,9 @@ const potensiDesa = proxy({
|
|||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
total: 0,
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||||
load: async (page = 1, limit = 10, search = "") => { // Change to arrow function
|
|
||||||
potensiDesa.findMany.loading = true; // Use the full path to access the property
|
potensiDesa.findMany.loading = true; // Use the full path to access the property
|
||||||
potensiDesa.findMany.page = page;
|
potensiDesa.findMany.page = page;
|
||||||
potensiDesa.findMany.search = search;
|
|
||||||
try {
|
try {
|
||||||
const res = await ApiFetch.api.desa.potensi[
|
const res = await ApiFetch.api.desa.potensi[
|
||||||
"find-many"
|
"find-many"
|
||||||
@@ -300,34 +298,11 @@ const kategoriPotensi = proxy({
|
|||||||
isActive: true;
|
isActive: true;
|
||||||
};
|
};
|
||||||
}>[],
|
}>[],
|
||||||
page: 1,
|
|
||||||
totalPages: 1,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
async load() {
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
const res = await ApiFetch.api.desa.kategoripotensi["findMany"].get();
|
||||||
kategoriPotensi.findMany.loading = true; // ✅ Akses langsung via nama path
|
if (res.status === 200) {
|
||||||
kategoriPotensi.findMany.page = page;
|
kategoriPotensi.findMany.data = res.data?.data ?? [];
|
||||||
kategoriPotensi.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.desa.kategoripotensi["findMany"].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
kategoriPotensi.findMany.data = res.data.data ?? [];
|
|
||||||
kategoriPotensi.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
kategoriPotensi.findMany.data = [];
|
|
||||||
kategoriPotensi.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch kategori potensi paginated:", err);
|
|
||||||
kategoriPotensi.findMany.data = [];
|
|
||||||
kategoriPotensi.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
kategoriPotensi.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,13 +7,9 @@ import { z } from "zod";
|
|||||||
|
|
||||||
const templateApbDesa = z.object({
|
const templateApbDesa = z.object({
|
||||||
tahun: z.number().min(4, "Tahun minimal 4 karakter"),
|
tahun: z.number().min(4, "Tahun minimal 4 karakter"),
|
||||||
pembiayaanIds: z
|
pembiayaanIds: z.array(z.string().uuid()).nonempty("Pilih minimal 1 pembiayaan"),
|
||||||
.array(z.string().uuid())
|
|
||||||
.nonempty("Pilih minimal 1 pembiayaan"),
|
|
||||||
belanjaIds: z.array(z.string().uuid()).nonempty("Pilih minimal 1 belanja"),
|
belanjaIds: z.array(z.string().uuid()).nonempty("Pilih minimal 1 belanja"),
|
||||||
pendapatanIds: z
|
pendapatanIds: z.array(z.string().uuid()).nonempty("Pilih minimal 1 pendapatan"),
|
||||||
.array(z.string().uuid())
|
|
||||||
.nonempty("Pilih minimal 1 pendapatan"),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const ApbDesaDefaultForm = {
|
const ApbDesaDefaultForm = {
|
||||||
@@ -58,81 +54,35 @@ const ApbDesa = proxy({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
findMany: {
|
findMany: {
|
||||||
data: null as
|
data: null as
|
||||||
| Prisma.ApbDesaGetPayload<{
|
| Prisma.ApbDesaGetPayload<{
|
||||||
include: {
|
include: {
|
||||||
pendapatan: true;
|
pendapatan: true;
|
||||||
belanja: true;
|
belanja: true;
|
||||||
pembiayaan: true;
|
pembiayaan: true;
|
||||||
};
|
};
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
|
||||||
totalPages: 1,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
async load() {
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
|
||||||
ApbDesa.findMany.loading = true; // ✅ Akses langsung via nama path
|
|
||||||
ApbDesa.findMany.page = page;
|
|
||||||
ApbDesa.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.apbdesa[
|
|
||||||
"find-many"
|
|
||||||
].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
ApbDesa.findMany.data = res.data.data ?? [];
|
|
||||||
ApbDesa.findMany.totalPages =
|
|
||||||
res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
ApbDesa.findMany.data = [];
|
|
||||||
ApbDesa.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch APB Desa paginated:", err);
|
|
||||||
ApbDesa.findMany.data = [];
|
|
||||||
ApbDesa.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
ApbDesa.findMany.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
findFirst: {
|
|
||||||
data: null as Prisma.ApbDesaGetPayload<{
|
|
||||||
include: { pendapatan: true; belanja: true; pembiayaan: true };
|
|
||||||
}> | null,
|
|
||||||
loading: false,
|
|
||||||
async load(params?: Record<string, any>) {
|
|
||||||
try {
|
try {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
||||||
// ✅ request ke endpoint find-first
|
|
||||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.apbdesa[
|
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.apbdesa[
|
||||||
"find-first"
|
"find-many"
|
||||||
].get({ query: params || {} });
|
].get();
|
||||||
|
if (res.status === 200) {
|
||||||
if (res.status === 200 && res.data?.success) {
|
this.data = res.data?.data ?? [];
|
||||||
this.data = res.data.data ?? null;
|
|
||||||
} else {
|
} else {
|
||||||
this.data = null;
|
toast.error(res.data?.message || "Gagal mengambil APB Desa");
|
||||||
toast.error(res.data?.message || "Gagal memuat data pertama APB Desa");
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error findFirst APB Desa:", error);
|
console.error("Find many error:", error);
|
||||||
toast.error("Gagal memuat data APB Desa pertama");
|
toast.error("Gagal mengambil APB Desa");
|
||||||
this.data = null;
|
|
||||||
} finally {
|
} finally {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
reset() {
|
},
|
||||||
this.data = null;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: {
|
update: {
|
||||||
id: "",
|
id: "",
|
||||||
form: { ...ApbDesaDefaultForm },
|
form: { ...ApbDesaDefaultForm },
|
||||||
@@ -156,13 +106,13 @@ const ApbDesa = proxy({
|
|||||||
throw new Error("Gagal mengambil APB Desa");
|
throw new Error("Gagal mengambil APB Desa");
|
||||||
}
|
}
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
throw new Error(result.message || "Gagal memuat APB Desa");
|
throw new Error(result.message || "Gagal memuat APB Desa");
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = result.data;
|
const data = result.data;
|
||||||
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.form = {
|
this.form = {
|
||||||
tahun: data.tahun || 0,
|
tahun: data.tahun || 0,
|
||||||
@@ -170,7 +120,7 @@ const ApbDesa = proxy({
|
|||||||
belanjaIds: data.belanja?.map((b: any) => b.id) || [],
|
belanjaIds: data.belanja?.map((b: any) => b.id) || [],
|
||||||
pembiayaanIds: data.pembiayaan?.map((p: any) => p.id) || [],
|
pembiayaanIds: data.pembiayaan?.map((p: any) => p.id) || [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error loading APB Desa:", error);
|
console.error("Error loading APB Desa:", error);
|
||||||
@@ -239,7 +189,7 @@ const ApbDesa = proxy({
|
|||||||
data: null as Prisma.ApbDesaGetPayload<{
|
data: null as Prisma.ApbDesaGetPayload<{
|
||||||
include: { pendapatan: true; belanja: true; pembiayaan: true };
|
include: { pendapatan: true; belanja: true; pembiayaan: true };
|
||||||
}> | null,
|
}> | null,
|
||||||
|
|
||||||
async load(id: string) {
|
async load(id: string) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
@@ -249,11 +199,11 @@ const ApbDesa = proxy({
|
|||||||
throw new Error("Gagal mengambil detail APB Desa");
|
throw new Error("Gagal mengambil detail APB Desa");
|
||||||
}
|
}
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
throw new Error(result.message || "Gagal mengambil data");
|
throw new Error(result.message || "Gagal mengambil data");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.data = result.data; // ✅ fix utama di sini
|
this.data = result.data; // ✅ fix utama di sini
|
||||||
return result.data;
|
return result.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -314,32 +264,34 @@ const pendapatan = proxy({
|
|||||||
data: null as any[] | null,
|
data: null as any[] | null,
|
||||||
page: 1,
|
page: 1,
|
||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
load: async (page = 1, limit = 10) => {
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
// Change to arrow function
|
||||||
pendapatan.findMany.loading = true; // ✅ Akses langsung via nama path
|
pendapatan.findMany.loading = true; // Use the full path to access the property
|
||||||
pendapatan.findMany.page = page;
|
pendapatan.findMany.page = page;
|
||||||
pendapatan.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit };
|
const res =
|
||||||
if (search) query.search = search;
|
await ApiFetch.api.ekonomi.pendapatanaslidesa.pendapatanasli[
|
||||||
|
"find-many"
|
||||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.pendapatanasli[
|
].get({
|
||||||
"find-many"
|
query: { page, limit },
|
||||||
].get({ query });
|
});
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
if (res.status === 200 && res.data?.success) {
|
||||||
pendapatan.findMany.data = res.data.data ?? [];
|
pendapatan.findMany.data = res.data.data || [];
|
||||||
pendapatan.findMany.totalPages =
|
pendapatan.findMany.total = res.data.total || 0;
|
||||||
res.data.totalPages ?? 1;
|
pendapatan.findMany.totalPages = res.data.totalPages || 1;
|
||||||
} else {
|
} else {
|
||||||
|
console.error("Failed to load pendapatan:", res.data?.message);
|
||||||
pendapatan.findMany.data = [];
|
pendapatan.findMany.data = [];
|
||||||
|
pendapatan.findMany.total = 0;
|
||||||
pendapatan.findMany.totalPages = 1;
|
pendapatan.findMany.totalPages = 1;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (error) {
|
||||||
console.error("Gagal fetch pendapatan asli desa paginated:", err);
|
console.error("Error loading pendapatan:", error);
|
||||||
pendapatan.findMany.data = [];
|
pendapatan.findMany.data = [];
|
||||||
|
pendapatan.findMany.total = 0;
|
||||||
pendapatan.findMany.totalPages = 1;
|
pendapatan.findMany.totalPages = 1;
|
||||||
} finally {
|
} finally {
|
||||||
pendapatan.findMany.loading = false;
|
pendapatan.findMany.loading = false;
|
||||||
@@ -356,15 +308,12 @@ const pendapatan = proxy({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/pendapatanasli/${id}`, {
|
||||||
`/api/ekonomi/pendapatanaslidesa/pendapatanasli/${id}`,
|
method: "GET",
|
||||||
{
|
headers: {
|
||||||
method: "GET",
|
"Content-Type": "application/json",
|
||||||
headers: {
|
},
|
||||||
"Content-Type": "application/json",
|
});
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
@@ -400,19 +349,16 @@ const pendapatan = proxy({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
pendapatan.update.loading = true;
|
pendapatan.update.loading = true;
|
||||||
const response = await fetch(
|
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/pendapatanasli/${this.id}`, {
|
||||||
`/api/ekonomi/pendapatanaslidesa/pendapatanasli/${this.id}`,
|
method: "PUT",
|
||||||
{
|
headers: {
|
||||||
method: "PUT",
|
"Content-Type": "application/json",
|
||||||
headers: {
|
},
|
||||||
"Content-Type": "application/json",
|
body: JSON.stringify({
|
||||||
},
|
name: this.form.name,
|
||||||
body: JSON.stringify({
|
value: this.form.value,
|
||||||
name: this.form.name,
|
}),
|
||||||
value: this.form.value,
|
});
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json().catch(() => ({}));
|
const errorData = await response.json().catch(() => ({}));
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -549,37 +495,23 @@ const belanja = proxy({
|
|||||||
name: string;
|
name: string;
|
||||||
value: number;
|
value: number;
|
||||||
}>,
|
}>,
|
||||||
page: 1,
|
|
||||||
totalPages: 1,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
async load() {
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
|
||||||
belanja.findMany.loading = true; // ✅ Akses langsung via nama path
|
|
||||||
belanja.findMany.page = page;
|
|
||||||
belanja.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit };
|
this.loading = true;
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.belanja[
|
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.belanja[
|
||||||
"find-many"
|
"find-many"
|
||||||
].get({ query });
|
].get();
|
||||||
|
if (res.status === 200) {
|
||||||
if (res.status === 200 && res.data?.success) {
|
this.data = res.data?.data ?? [];
|
||||||
belanja.findMany.data = res.data.data ?? [];
|
|
||||||
belanja.findMany.totalPages =
|
|
||||||
res.data.totalPages ?? 1;
|
|
||||||
} else {
|
} else {
|
||||||
belanja.findMany.data = [];
|
toast.error(res.data?.message || "Gagal mengambil Belanja");
|
||||||
belanja.findMany.totalPages = 1;
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (error) {
|
||||||
console.error("Gagal fetch Belanja paginated:", err);
|
console.error("Find many error:", error);
|
||||||
belanja.findMany.data = [];
|
toast.error("Gagal mengambil Belanja");
|
||||||
belanja.findMany.totalPages = 1;
|
|
||||||
} finally {
|
} finally {
|
||||||
belanja.findMany.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -593,15 +525,12 @@ const belanja = proxy({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/belanja/${id}`, {
|
||||||
`/api/ekonomi/pendapatanaslidesa/belanja/${id}`,
|
method: "GET",
|
||||||
{
|
headers: {
|
||||||
method: "GET",
|
"Content-Type": "application/json",
|
||||||
headers: {
|
},
|
||||||
"Content-Type": "application/json",
|
});
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
@@ -637,19 +566,16 @@ const belanja = proxy({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
belanja.update.loading = true;
|
belanja.update.loading = true;
|
||||||
const response = await fetch(
|
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/belanja/${this.id}`, {
|
||||||
`/api/ekonomi/pendapatanaslidesa/belanja/${this.id}`,
|
method: "PUT",
|
||||||
{
|
headers: {
|
||||||
method: "PUT",
|
"Content-Type": "application/json",
|
||||||
headers: {
|
},
|
||||||
"Content-Type": "application/json",
|
body: JSON.stringify({
|
||||||
},
|
name: this.form.name,
|
||||||
body: JSON.stringify({
|
value: this.form.value,
|
||||||
name: this.form.name,
|
}),
|
||||||
value: this.form.value,
|
});
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json().catch(() => ({}));
|
const errorData = await response.json().catch(() => ({}));
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -784,37 +710,23 @@ const pembiayaan = proxy({
|
|||||||
name: string;
|
name: string;
|
||||||
value: number;
|
value: number;
|
||||||
}>,
|
}>,
|
||||||
page: 1,
|
|
||||||
totalPages: 1,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
async load() {
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
|
||||||
pembiayaan.findMany.loading = true; // ✅ Akses langsung via nama path
|
|
||||||
pembiayaan.findMany.page = page;
|
|
||||||
pembiayaan.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit };
|
this.loading = true;
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.pembiayaan[
|
const res = await ApiFetch.api.ekonomi.pendapatanaslidesa.pembiayaan[
|
||||||
"find-many"
|
"find-many"
|
||||||
].get({ query });
|
].get();
|
||||||
|
if (res.status === 200) {
|
||||||
if (res.status === 200 && res.data?.success) {
|
this.data = res.data?.data ?? [];
|
||||||
pembiayaan.findMany.data = res.data.data ?? [];
|
|
||||||
pembiayaan.findMany.totalPages =
|
|
||||||
res.data.totalPages ?? 1;
|
|
||||||
} else {
|
} else {
|
||||||
pembiayaan.findMany.data = [];
|
toast.error(res.data?.message || "Gagal mengambil Pembiayaan");
|
||||||
pembiayaan.findMany.totalPages = 1;
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (error) {
|
||||||
console.error("Gagal fetch Pembiayaan paginated:", err);
|
console.error("Find many error:", error);
|
||||||
pembiayaan.findMany.data = [];
|
toast.error("Gagal mengambil Pembiayaan");
|
||||||
pembiayaan.findMany.totalPages = 1;
|
|
||||||
} finally {
|
} finally {
|
||||||
pembiayaan.findMany.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -828,15 +740,12 @@ const pembiayaan = proxy({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/pembiayaan/${id}`, {
|
||||||
`/api/ekonomi/pendapatanaslidesa/pembiayaan/${id}`,
|
method: "GET",
|
||||||
{
|
headers: {
|
||||||
method: "GET",
|
"Content-Type": "application/json",
|
||||||
headers: {
|
},
|
||||||
"Content-Type": "application/json",
|
});
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
@@ -872,19 +781,16 @@ const pembiayaan = proxy({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
pembiayaan.update.loading = true;
|
pembiayaan.update.loading = true;
|
||||||
const response = await fetch(
|
const response = await fetch(`/api/ekonomi/pendapatanaslidesa/pembiayaan/${this.id}`, {
|
||||||
`/api/ekonomi/pendapatanaslidesa/pembiayaan/${this.id}`,
|
method: "PUT",
|
||||||
{
|
headers: {
|
||||||
method: "PUT",
|
"Content-Type": "application/json",
|
||||||
headers: {
|
},
|
||||||
"Content-Type": "application/json",
|
body: JSON.stringify({
|
||||||
},
|
name: this.form.name,
|
||||||
body: JSON.stringify({
|
value: this.form.value,
|
||||||
name: this.form.name,
|
}),
|
||||||
value: this.form.value,
|
});
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json().catch(() => ({}));
|
const errorData = await response.json().catch(() => ({}));
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
@@ -49,7 +48,7 @@ const demografiPekerjaan = proxy({
|
|||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const id = res.data?.data?.id;
|
const id = res.data?.data?.id;
|
||||||
if (id) {
|
if (id) {
|
||||||
toast.success("Sukses menambahkan");
|
toast.success("Success create");
|
||||||
demografiPekerjaan.create.form = { ...defaultForm };
|
demografiPekerjaan.create.form = { ...defaultForm };
|
||||||
demografiPekerjaan.findMany.load();
|
demografiPekerjaan.findMany.load();
|
||||||
return id;
|
return id;
|
||||||
@@ -72,37 +71,12 @@ const demografiPekerjaan = proxy({
|
|||||||
omit: { isActive: true };
|
omit: { isActive: true };
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
async load() {
|
||||||
totalPages: 1,
|
const res = await ApiFetch.api.ekonomi.demografipekerjaan[
|
||||||
loading: false,
|
"find-many"
|
||||||
search: "",
|
].get();
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
if (res.status === 200) {
|
||||||
demografiPekerjaan.findMany.loading = true; // ✅ Akses langsung via nama path
|
demografiPekerjaan.findMany.data = res.data?.data ?? [];
|
||||||
demografiPekerjaan.findMany.page = page;
|
|
||||||
demografiPekerjaan.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.demografipekerjaan[
|
|
||||||
"find-many"
|
|
||||||
].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
demografiPekerjaan.findMany.data = res.data.data ?? [];
|
|
||||||
demografiPekerjaan.findMany.totalPages =
|
|
||||||
res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
demografiPekerjaan.findMany.data = [];
|
|
||||||
demografiPekerjaan.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch demografi pekerjaan paginated:", err);
|
|
||||||
demografiPekerjaan.findMany.data = [];
|
|
||||||
demografiPekerjaan.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
demografiPekerjaan.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -220,4 +194,4 @@ const demografiPekerjaan = proxy({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
export default demografiPekerjaan;
|
export default demografiPekerjaan
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
@@ -47,7 +46,7 @@ const jumlahPendudukMiskin = proxy({
|
|||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const id = res.data?.data?.id;
|
const id = res.data?.data?.id;
|
||||||
if (id) {
|
if (id) {
|
||||||
toast.success("Sukses menambahkan");
|
toast.success("Success create");
|
||||||
jumlahPendudukMiskin.create.form = {
|
jumlahPendudukMiskin.create.form = {
|
||||||
year: 0,
|
year: 0,
|
||||||
totalPoorPopulation: 0,
|
totalPoorPopulation: 0,
|
||||||
@@ -70,37 +69,16 @@ const jumlahPendudukMiskin = proxy({
|
|||||||
select: { id: true; year: true; totalPoorPopulation: true };
|
select: { id: true; year: true; totalPoorPopulation: true };
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
loading: false,
|
||||||
totalPages: 1,
|
async load() {
|
||||||
loading: false,
|
const res = await ApiFetch.api.ekonomi.jumlahpendudukmiskin[
|
||||||
search: "",
|
"find-many"
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
].get();
|
||||||
jumlahPendudukMiskin.findMany.loading = true; // ✅ Akses langsung via nama path
|
if (res.status === 200) {
|
||||||
jumlahPendudukMiskin.findMany.page = page;
|
jumlahPendudukMiskin.findMany.data = res.data?.data ?? [];
|
||||||
jumlahPendudukMiskin.findMany.search = search;
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.jumlahpendudukmiskin["find-many"].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
jumlahPendudukMiskin.findMany.data = res.data.data ?? [];
|
|
||||||
jumlahPendudukMiskin.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
jumlahPendudukMiskin.findMany.data = [];
|
|
||||||
jumlahPendudukMiskin.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch jumlah penduduk miskin paginated:", err);
|
|
||||||
jumlahPendudukMiskin.findMany.data = [];
|
|
||||||
jumlahPendudukMiskin.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
jumlahPendudukMiskin.findMany.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
findUnique: {
|
findUnique: {
|
||||||
data: null as Prisma.GrafikJumlahPendudukMiskinGetPayload<{
|
data: null as Prisma.GrafikJumlahPendudukMiskinGetPayload<{
|
||||||
select: { id: true; year: true; totalPoorPopulation: true };
|
select: { id: true; year: true; totalPoorPopulation: true };
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ const templateJumlahPengngguran = z.object({
|
|||||||
uneducatedUnemployment: z
|
uneducatedUnemployment: z
|
||||||
.number()
|
.number()
|
||||||
.min(1, "Pengangguran tidak pendidikan harus diisi"),
|
.min(1, "Pengangguran tidak pendidikan harus diisi"),
|
||||||
percentageChange: z.number({ invalid_type_error: "Persentase perubahan harus angka" }),
|
percentageChange: z.number().min(0, "Persentase perubahan harus diisi"),
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
type JumlahPengangguran = {
|
type JumlahPengangguran = {
|
||||||
@@ -30,7 +29,7 @@ type JumlahPengangguran = {
|
|||||||
|
|
||||||
const jumlahPengangguranForm: JumlahPengangguran = {
|
const jumlahPengangguranForm: JumlahPengangguran = {
|
||||||
month: "",
|
month: "",
|
||||||
year: new Date().getFullYear(), // Default to current year
|
year: 0,
|
||||||
totalUnemployment: 0,
|
totalUnemployment: 0,
|
||||||
educatedUnemployment: 0,
|
educatedUnemployment: 0,
|
||||||
uneducatedUnemployment: 0,
|
uneducatedUnemployment: 0,
|
||||||
@@ -61,21 +60,13 @@ const jumlahPengangguran = proxy({
|
|||||||
form: jumlahPengangguranForm,
|
form: jumlahPengangguranForm,
|
||||||
loading: false,
|
loading: false,
|
||||||
async create() {
|
async create() {
|
||||||
// Ensure all number fields are actual numbers
|
const cek = templateJumlahPengngguran.safeParse(
|
||||||
const formData = {
|
jumlahPengangguran.create.form
|
||||||
...jumlahPengangguran.create.form,
|
);
|
||||||
year: Number(jumlahPengangguran.create.form.year) || new Date().getFullYear(),
|
|
||||||
totalUnemployment: Number(jumlahPengangguran.create.form.totalUnemployment) || 0,
|
|
||||||
educatedUnemployment: Number(jumlahPengangguran.create.form.educatedUnemployment) || 0,
|
|
||||||
uneducatedUnemployment: Number(jumlahPengangguran.create.form.uneducatedUnemployment) || 0,
|
|
||||||
percentageChange: Number(jumlahPengangguran.create.form.percentageChange) || 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
const cek = templateJumlahPengngguran.safeParse(formData);
|
|
||||||
if (!cek.success) {
|
if (!cek.success) {
|
||||||
const err = `[${cek.error.issues
|
const err = `[${cek.error.issues
|
||||||
.map((v) => `${v.path.join(".")} (${v.message})`)
|
.map((v) => `${v.path.join(".")}`)
|
||||||
.join("\n")}]`;
|
.join("\n")}] required`;
|
||||||
toast.error(err);
|
toast.error(err);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -87,9 +78,9 @@ const jumlahPengangguran = proxy({
|
|||||||
].post(jumlahPengangguran.create.form);
|
].post(jumlahPengangguran.create.form);
|
||||||
|
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const id = res.data?.id;
|
const id = res.data?.data?.id;
|
||||||
if (id) {
|
if (id) {
|
||||||
toast.success("Sukses menambahkan");
|
toast.success("Success create");
|
||||||
jumlahPengangguran.create.form = { ...jumlahPengangguranForm };
|
jumlahPengangguran.create.form = { ...jumlahPengangguranForm };
|
||||||
jumlahPengangguran.findMany.load();
|
jumlahPengangguran.findMany.load();
|
||||||
return id;
|
return id;
|
||||||
@@ -112,40 +103,16 @@ const jumlahPengangguran = proxy({
|
|||||||
omit: { isActive: true };
|
omit: { isActive: true };
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
async load() {
|
||||||
totalPages: 1,
|
const res =
|
||||||
loading: false,
|
await ApiFetch.api.ekonomi.jumlahpengangguran.detaildatapengangguran[
|
||||||
search: "",
|
"find-many"
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
].get();
|
||||||
jumlahPengangguran.findMany.loading = true; // ✅ Akses langsung via nama path
|
if (res.status === 200) {
|
||||||
jumlahPengangguran.findMany.page = page;
|
jumlahPengangguran.findMany.data = res.data?.data ?? [];
|
||||||
jumlahPengangguran.findMany.search = search;
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.jumlahpengangguran.detaildatapengangguran[
|
|
||||||
"find-many"
|
|
||||||
].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
jumlahPengangguran.findMany.data = res.data.data ?? [];
|
|
||||||
jumlahPengangguran.findMany.totalPages =
|
|
||||||
res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
jumlahPengangguran.findMany.data = [];
|
|
||||||
jumlahPengangguran.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch jumlah pengangguran paginated:", err);
|
|
||||||
jumlahPengangguran.findMany.data = [];
|
|
||||||
jumlahPengangguran.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
jumlahPengangguran.findMany.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
findUnique: {
|
findUnique: {
|
||||||
data: null as Prisma.DetailDataPengangguranGetPayload<{
|
data: null as Prisma.DetailDataPengangguranGetPayload<{
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
@@ -13,7 +12,6 @@ const templateForm = z.object({
|
|||||||
gaji: z.string(),
|
gaji: z.string(),
|
||||||
deskripsi: z.string(),
|
deskripsi: z.string(),
|
||||||
kualifikasi: z.string(),
|
kualifikasi: z.string(),
|
||||||
notelp: z.string(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultForm = {
|
const defaultForm = {
|
||||||
@@ -24,7 +22,6 @@ const defaultForm = {
|
|||||||
gaji: "",
|
gaji: "",
|
||||||
deskripsi: "",
|
deskripsi: "",
|
||||||
kualifikasi: "",
|
kualifikasi: "",
|
||||||
notelp: "",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const lowonganKerjaState = proxy({
|
const lowonganKerjaState = proxy({
|
||||||
@@ -47,7 +44,7 @@ const lowonganKerjaState = proxy({
|
|||||||
);
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
lowonganKerjaState.create.loading = false;
|
lowonganKerjaState.create.loading = false;
|
||||||
return toast.success("Sukses menambahkan");
|
return toast.success("success create");
|
||||||
}
|
}
|
||||||
console.log(res);
|
console.log(res);
|
||||||
return toast.error("failed create");
|
return toast.error("failed create");
|
||||||
@@ -64,39 +61,13 @@ const lowonganKerjaState = proxy({
|
|||||||
findMany: {
|
findMany: {
|
||||||
data: null as
|
data: null as
|
||||||
| Prisma.LowonganPekerjaanGetPayload<{
|
| Prisma.LowonganPekerjaanGetPayload<{
|
||||||
omit: {
|
omit: { isActive: true };
|
||||||
isActive: true;
|
|
||||||
};
|
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
async load() {
|
||||||
totalPages: 1,
|
const res = await ApiFetch.api.ekonomi.lowongankerja["find-many"].get();
|
||||||
loading: false,
|
if (res.status === 200) {
|
||||||
search: "",
|
lowonganKerjaState.findMany.data = res.data?.data ?? [];
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
|
||||||
lowonganKerjaState.findMany.loading = true; // ✅ Akses langsung via nama path
|
|
||||||
lowonganKerjaState.findMany.page = page;
|
|
||||||
lowonganKerjaState.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.lowongankerja["find-many"].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
lowonganKerjaState.findMany.data = res.data.data ?? [];
|
|
||||||
lowonganKerjaState.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
lowonganKerjaState.findMany.data = [];
|
|
||||||
lowonganKerjaState.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch lowongan kerja paginated:", err);
|
|
||||||
lowonganKerjaState.findMany.data = [];
|
|
||||||
lowonganKerjaState.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
lowonganKerjaState.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -181,7 +152,6 @@ const lowonganKerjaState = proxy({
|
|||||||
gaji: data.gaji,
|
gaji: data.gaji,
|
||||||
deskripsi: data.deskripsi,
|
deskripsi: data.deskripsi,
|
||||||
kualifikasi: data.kualifikasi,
|
kualifikasi: data.kualifikasi,
|
||||||
notelp: data.notelp,
|
|
||||||
};
|
};
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
@@ -221,7 +191,6 @@ const lowonganKerjaState = proxy({
|
|||||||
gaji: this.form.gaji,
|
gaji: this.form.gaji,
|
||||||
deskripsi: this.form.deskripsi,
|
deskripsi: this.form.deskripsi,
|
||||||
kualifikasi: this.form.kualifikasi,
|
kualifikasi: this.form.kualifikasi,
|
||||||
notelp: this.form.notelp,
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
@@ -12,7 +11,6 @@ const templatePasarDesaForm = z.object({
|
|||||||
imageId: z.string().min(1, "Gambar wajib dipilih"),
|
imageId: z.string().min(1, "Gambar wajib dipilih"),
|
||||||
rating: z.number().min(1, "Rating minimal 1"),
|
rating: z.number().min(1, "Rating minimal 1"),
|
||||||
kategoriId: z.array(z.string()).min(1, "Minimal pilih satu kategori"),
|
kategoriId: z.array(z.string()).min(1, "Minimal pilih satu kategori"),
|
||||||
kontak: z.string().min(1, "Kontak wajib diisi"),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultPasarDesaForm = {
|
const defaultPasarDesaForm = {
|
||||||
@@ -22,7 +20,6 @@ const defaultPasarDesaForm = {
|
|||||||
imageId: "",
|
imageId: "",
|
||||||
rating: 0,
|
rating: 0,
|
||||||
kategoriId: [] as string[],
|
kategoriId: [] as string[],
|
||||||
kontak: "",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const pasarDesa = proxy({
|
const pasarDesa = proxy({
|
||||||
@@ -56,47 +53,22 @@ const pasarDesa = proxy({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
findMany: {
|
findMany: {
|
||||||
data: null as
|
data: null as Array<
|
||||||
| Prisma.PasarDesaGetPayload<{
|
Prisma.PasarDesaGetPayload<{
|
||||||
include: {
|
include: {
|
||||||
image: true;
|
image: true;
|
||||||
KategoriToPasar: {
|
KategoriToPasar: {
|
||||||
include: {
|
include: {
|
||||||
kategori: true;
|
kategori: true;
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}>[]
|
};
|
||||||
| null,
|
}>
|
||||||
page: 1,
|
> | null,
|
||||||
totalPages: 1,
|
async load() {
|
||||||
loading: false,
|
const res = await ApiFetch.api.ekonomi.pasardesa["find-many"].get();
|
||||||
search: "",
|
if (res.status === 200) {
|
||||||
load: async (page = 1, limit = 10, search = "", categoryId?: string) => {
|
pasarDesa.findMany.data = res.data?.data ?? [];
|
||||||
pasarDesa.findMany.loading = true;
|
|
||||||
pasarDesa.findMany.page = page;
|
|
||||||
pasarDesa.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
if (categoryId) query.categoryId = categoryId;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.pasardesa["find-many"].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
pasarDesa.findMany.data = res.data.data ?? [];
|
|
||||||
pasarDesa.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
pasarDesa.findMany.data = [];
|
|
||||||
pasarDesa.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch keamanan lingkungan paginated:", err);
|
|
||||||
pasarDesa.findMany.data = [];
|
|
||||||
pasarDesa.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
pasarDesa.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -190,7 +162,6 @@ const pasarDesa = proxy({
|
|||||||
imageId: data.imageId,
|
imageId: data.imageId,
|
||||||
rating: data.rating,
|
rating: data.rating,
|
||||||
kategoriId: data.kategoriId,
|
kategoriId: data.kategoriId,
|
||||||
kontak: data.kontak,
|
|
||||||
};
|
};
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
@@ -228,7 +199,6 @@ const pasarDesa = proxy({
|
|||||||
imageId: this.form.imageId,
|
imageId: this.form.imageId,
|
||||||
rating: this.form.rating,
|
rating: this.form.rating,
|
||||||
kategoriId: this.form.kategoriId,
|
kategoriId: this.form.kategoriId,
|
||||||
kontak: this.form.kontak,
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -302,75 +272,14 @@ const kategoriProduk = proxy({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
findMany: {
|
findMany: {
|
||||||
data: null as
|
data: null as Array<{
|
||||||
| Prisma.KategoriProdukGetPayload<{
|
id: string;
|
||||||
omit: {
|
nama: string;
|
||||||
isActive: true;
|
}> | null,
|
||||||
};
|
async load() {
|
||||||
}>[]
|
const res = await ApiFetch.api.ekonomi.kategoriproduk["find-many"].get();
|
||||||
| null,
|
if (res.status === 200) {
|
||||||
page: 1,
|
kategoriProduk.findMany.data = res.data?.data ?? [];
|
||||||
totalPages: 1,
|
|
||||||
loading: false,
|
|
||||||
search2: "",
|
|
||||||
load: async (page = 1, limit = 10, search2 = "") => {
|
|
||||||
kategoriProduk.findMany.loading = true; // ✅ Akses langsung via nama path
|
|
||||||
kategoriProduk.findMany.page = page;
|
|
||||||
kategoriProduk.findMany.search2 = search2;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search2) query.search2 = search2;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.kategoriproduk["find-many"].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
kategoriProduk.findMany.data = res.data.data ?? [];
|
|
||||||
kategoriProduk.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
kategoriProduk.findMany.data = [];
|
|
||||||
kategoriProduk.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch kategori produk paginated:", err);
|
|
||||||
kategoriProduk.findMany.data = [];
|
|
||||||
kategoriProduk.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
kategoriProduk.findMany.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// ✅ Versi findManyAll (ambil semua tanpa pagination)
|
|
||||||
findManyAll: {
|
|
||||||
data: null as
|
|
||||||
| Prisma.KategoriProdukGetPayload<{
|
|
||||||
omit: { isActive: true };
|
|
||||||
}>[]
|
|
||||||
| null,
|
|
||||||
loading: false,
|
|
||||||
search: "",
|
|
||||||
load: async (search = "") => {
|
|
||||||
kategoriProduk.findManyAll.loading = true;
|
|
||||||
kategoriProduk.findManyAll.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = {};
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.kategoriproduk["find-many-all"].get({
|
|
||||||
query,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
kategoriProduk.findManyAll.data = res.data.data ?? [];
|
|
||||||
} else {
|
|
||||||
kategoriProduk.findManyAll.data = [];
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch kategori produk (all):", err);
|
|
||||||
kategoriProduk.findManyAll.data = [];
|
|
||||||
} finally {
|
|
||||||
kategoriProduk.findManyAll.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
@@ -8,21 +7,22 @@ import { z } from "zod";
|
|||||||
const templateForm = z.object({
|
const templateForm = z.object({
|
||||||
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
nama: z.string().min(1, "Nama minimal 1 karakter"),
|
||||||
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||||
icon: z.string().min(1, "Icon minimal 1 karakter"),
|
ikonUrl: z.string().optional(),
|
||||||
statistik: z.object({
|
statistik: z.object({
|
||||||
tahun: z.string().min(1, "Tahun minimal 1 karakter"),
|
tahun: z.string().min(1, "Tahun minimal 1 karakter"),
|
||||||
jumlah: z.string().min(1, "Jumlah minimal 1 karakter"),
|
jumlah: z.string().min(1, "Jumlah minimal 1 karakter"),
|
||||||
}),
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultForm = {
|
const defaultForm = {
|
||||||
nama: "",
|
nama: "",
|
||||||
deskripsi: "",
|
deskripsi: "",
|
||||||
icon: "",
|
ikonUrl: "",
|
||||||
statistik: {
|
statistik: {
|
||||||
tahun: "",
|
tahun: "",
|
||||||
jumlah: "",
|
jumlah: ""
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const programKemiskinanState = proxy({
|
const programKemiskinanState = proxy({
|
||||||
@@ -45,7 +45,7 @@ const programKemiskinanState = proxy({
|
|||||||
);
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
programKemiskinanState.findMany.load();
|
programKemiskinanState.findMany.load();
|
||||||
return toast.success("Sukses menambahkan");
|
return toast.success("success create");
|
||||||
}
|
}
|
||||||
console.log(res);
|
console.log(res);
|
||||||
return toast.error("failed create");
|
return toast.error("failed create");
|
||||||
@@ -64,35 +64,12 @@ const programKemiskinanState = proxy({
|
|||||||
};
|
};
|
||||||
}>[],
|
}>[],
|
||||||
loading: false,
|
loading: false,
|
||||||
page: 1,
|
async load() {
|
||||||
totalPages: 1,
|
const res = await ApiFetch.api.ekonomi.programkemiskinan[
|
||||||
search: "",
|
"find-many"
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
].get();
|
||||||
programKemiskinanState.findMany.loading = true; // ✅ Akses langsung via nama path
|
if (res.status === 200) {
|
||||||
programKemiskinanState.findMany.page = page;
|
programKemiskinanState.findMany.data = res.data?.data ?? [];
|
||||||
programKemiskinanState.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.programkemiskinan[
|
|
||||||
"find-many"
|
|
||||||
].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
programKemiskinanState.findMany.data = res.data.data ?? [];
|
|
||||||
programKemiskinanState.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
programKemiskinanState.findMany.data = [];
|
|
||||||
programKemiskinanState.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch program kemiskinan paginated:", err);
|
|
||||||
programKemiskinanState.findMany.data = [];
|
|
||||||
programKemiskinanState.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
programKemiskinanState.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -148,7 +125,7 @@ const programKemiskinanState = proxy({
|
|||||||
this.form = {
|
this.form = {
|
||||||
nama: data.nama,
|
nama: data.nama,
|
||||||
deskripsi: data.deskripsi,
|
deskripsi: data.deskripsi,
|
||||||
icon: data.icon,
|
ikonUrl: data.ikonUrl || "",
|
||||||
statistik: {
|
statistik: {
|
||||||
tahun: data.statistik.tahun,
|
tahun: data.statistik.tahun,
|
||||||
jumlah: data.statistik.jumlah,
|
jumlah: data.statistik.jumlah,
|
||||||
@@ -189,7 +166,7 @@ const programKemiskinanState = proxy({
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
nama: this.form.nama,
|
nama: this.form.nama,
|
||||||
deskripsi: this.form.deskripsi,
|
deskripsi: this.form.deskripsi,
|
||||||
icon: this.form.icon,
|
ikonUrl: this.form.ikonUrl,
|
||||||
statistik: {
|
statistik: {
|
||||||
tahun: this.form.statistik.tahun,
|
tahun: this.form.statistik.tahun,
|
||||||
jumlah: this.form.statistik.jumlah,
|
jumlah: this.form.statistik.jumlah,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
@@ -46,7 +45,7 @@ const grafikSektorUnggulan = proxy({
|
|||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const id = res.data?.data?.id;
|
const id = res.data?.data?.id;
|
||||||
if (id) {
|
if (id) {
|
||||||
toast.success("Sukses menambahkan");
|
toast.success("Success create");
|
||||||
grafikSektorUnggulan.create.form = {
|
grafikSektorUnggulan.create.form = {
|
||||||
name: "",
|
name: "",
|
||||||
description: "",
|
description: "",
|
||||||
@@ -77,37 +76,13 @@ const grafikSektorUnggulan = proxy({
|
|||||||
};
|
};
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
|
||||||
totalPages: 1,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
async load() {
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
const res = await ApiFetch.api.ekonomi.sektourunggulandesa[
|
||||||
grafikSektorUnggulan.findMany.loading = true; // ✅ Akses langsung via nama path
|
"find-many"
|
||||||
grafikSektorUnggulan.findMany.page = page;
|
].get();
|
||||||
grafikSektorUnggulan.findMany.search = search;
|
if (res.status === 200) {
|
||||||
|
grafikSektorUnggulan.findMany.data = res.data?.data ?? [];
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.sektourunggulandesa[
|
|
||||||
"find-many"
|
|
||||||
].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
grafikSektorUnggulan.findMany.data = res.data.data ?? [];
|
|
||||||
grafikSektorUnggulan.findMany.totalPages =
|
|
||||||
res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
grafikSektorUnggulan.findMany.data = [];
|
|
||||||
grafikSektorUnggulan.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch sektor unggulan desa paginated:", err);
|
|
||||||
grafikSektorUnggulan.findMany.data = [];
|
|
||||||
grafikSektorUnggulan.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
grafikSektorUnggulan.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,173 +1,9 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* 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 { proxy } from "valtio";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
const templateForm = z.object({
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
import { Prisma } from "@prisma/client";
|
||||||
imageId: z.string().min(1, "Gambar wajib dipilih"),
|
|
||||||
});
|
|
||||||
|
|
||||||
const defaultForm = {
|
|
||||||
name: "",
|
|
||||||
imageId: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
type StrukturBumDesForm = Prisma.StrukturBumDesGetPayload<{
|
|
||||||
select: {
|
|
||||||
id: true;
|
|
||||||
name: true;
|
|
||||||
imageId: true;
|
|
||||||
image?: {
|
|
||||||
select: {
|
|
||||||
link: true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}>;
|
|
||||||
|
|
||||||
const stateStruktur = proxy({
|
|
||||||
struktur: {
|
|
||||||
data: null as StrukturBumDesForm | null,
|
|
||||||
loading: false,
|
|
||||||
error: null as string | null,
|
|
||||||
|
|
||||||
async load(id: string) {
|
|
||||||
if (!id) {
|
|
||||||
toast.warn("ID tidak valid");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/api/ekonomi/struktur-organisasi/${id}`);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
this.data = result.data;
|
|
||||||
return result.data;
|
|
||||||
} else {
|
|
||||||
throw new Error(result.message || "Gagal mengambil data struktur");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
const errorMessage = (error as Error).message;
|
|
||||||
this.error = errorMessage;
|
|
||||||
console.error("Load struktur error:", errorMessage);
|
|
||||||
toast.error("Terjadi kesalahan saat mengambil data struktur");
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
this.data = null;
|
|
||||||
this.error = null;
|
|
||||||
this.loading = false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
editStruktur: {
|
|
||||||
id: "",
|
|
||||||
form: { ...defaultForm },
|
|
||||||
loading: false,
|
|
||||||
error: null as string | null,
|
|
||||||
isReadOnly: false,
|
|
||||||
|
|
||||||
initialize(strukturData: StrukturBumDesForm) {
|
|
||||||
this.id = strukturData.id;
|
|
||||||
this.isReadOnly = false;
|
|
||||||
this.form = {
|
|
||||||
name: strukturData.name || "",
|
|
||||||
imageId: strukturData.imageId || "",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
updateField(field: keyof typeof defaultForm, value: string) {
|
|
||||||
this.form[field] = value;
|
|
||||||
},
|
|
||||||
|
|
||||||
async submit() {
|
|
||||||
const validation = templateForm.safeParse(this.form);
|
|
||||||
|
|
||||||
if (!validation.success) {
|
|
||||||
const errors = validation.error.issues
|
|
||||||
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
|
||||||
.join(", ");
|
|
||||||
toast.error(`Form tidak valid: ${errors}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/api/ekonomi/struktur-organisasi/${this.id}`, {
|
|
||||||
method: "PUT",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(this.form),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const errorData = await response.json().catch(() => ({}));
|
|
||||||
throw new Error(
|
|
||||||
errorData.message || `HTTP error! status: ${response.status}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
toast.success("Berhasil update struktur");
|
|
||||||
await stateStruktur.struktur.load(this.id);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
throw new Error(result.message || "Gagal update struktur");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
const errorMessage = (error as Error).message;
|
|
||||||
this.error = errorMessage;
|
|
||||||
console.error("Update struktur error:", errorMessage);
|
|
||||||
toast.error("Terjadi kesalahan saat update struktur");
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
this.id = "";
|
|
||||||
this.form = { ...defaultForm };
|
|
||||||
this.error = null;
|
|
||||||
this.loading = false;
|
|
||||||
this.isReadOnly = false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
async loadForEdit(id: string) {
|
|
||||||
const strukturData = await this.struktur.load(id);
|
|
||||||
if (strukturData) {
|
|
||||||
this.editStruktur.initialize(strukturData);
|
|
||||||
}
|
|
||||||
return strukturData;
|
|
||||||
},
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
this.struktur.reset();
|
|
||||||
this.editStruktur.reset();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const templatePosisiOrganisasi = z.object({
|
const templatePosisiOrganisasi = z.object({
|
||||||
nama: z.string().min(1, "Nama harus diisi"),
|
nama: z.string().min(1, "Nama harus diisi"),
|
||||||
@@ -194,7 +30,9 @@ const posisiOrganisasi = proxy({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
const res = await ApiFetch.api.ekonomi['struktur-organisasi']['posisi-organisasi']['create'].post(this.form);
|
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
||||||
|
"posisi-organisasi"
|
||||||
|
]["create"].post(this.form);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
toast.success("Berhasil menambahkan posisi organisasi");
|
toast.success("Berhasil menambahkan posisi organisasi");
|
||||||
posisiOrganisasi.findMany.load();
|
posisiOrganisasi.findMany.load();
|
||||||
@@ -214,29 +52,6 @@ const posisiOrganisasi = proxy({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
findUnique: {
|
|
||||||
data: null as Prisma.StrukturOrganisasiBumDesGetPayload<{
|
|
||||||
omit: { isActive: true };
|
|
||||||
}> | null,
|
|
||||||
async load(id: string) {
|
|
||||||
try {
|
|
||||||
const res = await fetch(
|
|
||||||
`/api/ekonomi/struktur-organisasi/posisi-organisasi/${id}`
|
|
||||||
);
|
|
||||||
if (res.ok) {
|
|
||||||
const data = await res.json();
|
|
||||||
posisiOrganisasi.findUnique.data = data.data ?? null;
|
|
||||||
} else {
|
|
||||||
console.error("Failed to fetch posisiOrganisasi:", res.statusText);
|
|
||||||
posisiOrganisasi.findUnique.data = null;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching posisiOrganisasi:", error);
|
|
||||||
posisiOrganisasi.findUnique.data = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
edit: {
|
edit: {
|
||||||
id: "",
|
id: "",
|
||||||
form: { ...posisiOrganisasiDefaultForm },
|
form: { ...posisiOrganisasiDefaultForm },
|
||||||
@@ -346,73 +161,22 @@ const posisiOrganisasi = proxy({
|
|||||||
deskripsi: string | null;
|
deskripsi: string | null;
|
||||||
hierarki: number;
|
hierarki: number;
|
||||||
}>,
|
}>,
|
||||||
page: 1,
|
async load() {
|
||||||
totalPages: 1,
|
|
||||||
loading: false,
|
|
||||||
search: "",
|
|
||||||
load: async (page = 1, limit?: number, search = "") => {
|
|
||||||
const appliedLimit = limit ?? 10;
|
|
||||||
posisiOrganisasi.findMany.page = page;
|
|
||||||
posisiOrganisasi.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit: appliedLimit };
|
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
||||||
if (search) query.search = search;
|
"posisi-organisasi"
|
||||||
|
]["find-many"].get();
|
||||||
const res = await ApiFetch.api.ekonomi['struktur-organisasi']['posisi-organisasi']['find-many'].get({ query });
|
if (res.status === 200) {
|
||||||
|
// The API now returns the id field, so we can use it directly
|
||||||
if (res.status === 200 && res.data?.success) {
|
this.data = res.data?.data ?? [];
|
||||||
posisiOrganisasi.findMany.data = res.data.data ?? [];
|
|
||||||
posisiOrganisasi.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
posisiOrganisasi.findMany.data = [];
|
|
||||||
posisiOrganisasi.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch posisi organisasi paginated:", err);
|
|
||||||
posisiOrganisasi.findMany.data = [];
|
|
||||||
posisiOrganisasi.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
posisiOrganisasi.findMany.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
findManyAll: {
|
|
||||||
data: [] as Array<{
|
|
||||||
id: string;
|
|
||||||
nama: string;
|
|
||||||
deskripsi: string | null;
|
|
||||||
hierarki: number;
|
|
||||||
}>,
|
|
||||||
loading: false,
|
|
||||||
search: "",
|
|
||||||
load: async (search = "") => {
|
|
||||||
// Change to arrow function
|
|
||||||
posisiOrganisasi.findManyAll.loading = true; // Use the full path to access the property
|
|
||||||
posisiOrganisasi.findManyAll.search = search;
|
|
||||||
try {
|
|
||||||
const query: any = { search };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi['struktur-organisasi']['posisi-organisasi']['find-many-all'].get({
|
|
||||||
query,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
posisiOrganisasi.findManyAll.data = res.data.data || [];
|
|
||||||
|
|
||||||
} else {
|
|
||||||
console.error("Failed to load posisiOrganisasi:", res.data?.message);
|
|
||||||
posisiOrganisasi.findManyAll.data = [];
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error loading posisiOrganisasi:", error);
|
console.error("Find many error:", error);
|
||||||
posisiOrganisasi.findManyAll.data = [];
|
this.data = [];
|
||||||
} finally {
|
|
||||||
posisiOrganisasi.findManyAll.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
delete: {
|
delete: {
|
||||||
loading: false,
|
loading: false,
|
||||||
async byId(id: string) {
|
async byId(id: string) {
|
||||||
@@ -451,12 +215,12 @@ const posisiOrganisasi = proxy({
|
|||||||
|
|
||||||
const templatePegawai = z.object({
|
const templatePegawai = z.object({
|
||||||
namaLengkap: z.string().min(1, "Nama wajib diisi"),
|
namaLengkap: z.string().min(1, "Nama wajib diisi"),
|
||||||
gelarAkademik: z.string().min(1, "Gelar Akademik wajib diisi"),
|
gelarAkademik: z.string().optional(),
|
||||||
imageId: z.string().min(1, "Gambar wajib dipilih"),
|
imageId: z.string().nullable().optional(),
|
||||||
tanggalMasuk: z.string().min(1, "Tanggal masuk wajib diisi"), // ISO format
|
tanggalMasuk: z.string().optional(), // ISO format
|
||||||
email: z.string().email("Email tidak valid").optional(),
|
email: z.string().email("Email tidak valid").optional(),
|
||||||
telepon: z.string().min(1, "Telepom wajib diisi"),
|
telepon: z.string().optional(),
|
||||||
alamat: z.string().min(1, "Alamat wajib diisi"),
|
alamat: z.string().optional(),
|
||||||
posisiId: z.string().min(1, "Posisi wajib diisi"),
|
posisiId: z.string().min(1, "Posisi wajib diisi"),
|
||||||
isActive: z.boolean().default(true),
|
isActive: z.boolean().default(true),
|
||||||
});
|
});
|
||||||
@@ -487,9 +251,9 @@ const pegawai = proxy({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
pegawai.create.loading = true;
|
pegawai.create.loading = true;
|
||||||
const res = await ApiFetch.api.ekonomi['struktur-organisasi'].pegawai['create'].post(
|
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
||||||
pegawai.create.form
|
"pegawai"
|
||||||
);
|
]["create"].post(pegawai.create.form);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
toast.success("Pegawai berhasil ditambahkan");
|
toast.success("Pegawai berhasil ditambahkan");
|
||||||
await pegawai.findMany.load();
|
await pegawai.findMany.load();
|
||||||
@@ -506,56 +270,45 @@ const pegawai = proxy({
|
|||||||
},
|
},
|
||||||
|
|
||||||
// In struktur-organisasi.ts
|
// In struktur-organisasi.ts
|
||||||
findMany: {
|
findMany: {
|
||||||
data: null as
|
data: null as any[] | null,
|
||||||
| Prisma.PegawaiBumDesGetPayload<{
|
page: 1,
|
||||||
include: {
|
totalPages: 1,
|
||||||
image: true;
|
total: 0,
|
||||||
posisi: true;
|
loading: false,
|
||||||
};
|
load: async (page = 1, limit = 10) => { // Change to arrow function
|
||||||
}>[]
|
pegawai.findMany.loading = true; // Use the full path to access the property
|
||||||
| null,
|
pegawai.findMany.page = page;
|
||||||
page: 1,
|
try {
|
||||||
totalPages: 1,
|
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
||||||
total: 0,
|
"pegawai"
|
||||||
loading: false,
|
]["find-many"].get({
|
||||||
search: "",
|
query: { page, limit },
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
});
|
||||||
// Change to arrow function
|
|
||||||
pegawai.findMany.loading = true; // Use the full path to access the property
|
|
||||||
pegawai.findMany.page = page;
|
|
||||||
pegawai.findMany.search = search;
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi['struktur-organisasi'].pegawai['find-many'].get({
|
if (res.status === 200 && res.data?.success) {
|
||||||
query,
|
pegawai.findMany.data = res.data.data || [];
|
||||||
});
|
pegawai.findMany.total = res.data.total || 0;
|
||||||
|
pegawai.findMany.totalPages = res.data.totalPages || 1;
|
||||||
if (res.status === 200 && res.data?.success) {
|
} else {
|
||||||
pegawai.findMany.data = res.data.data || [];
|
console.error("Failed to load pegawai:", res.data?.message);
|
||||||
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.data = [];
|
||||||
pegawai.findMany.total = 0;
|
pegawai.findMany.total = 0;
|
||||||
pegawai.findMany.totalPages = 1;
|
pegawai.findMany.totalPages = 1;
|
||||||
} finally {
|
|
||||||
pegawai.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
} 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: {
|
findUnique: {
|
||||||
data: null as
|
data: null as
|
||||||
| (Prisma.PegawaiBumDesGetPayload<{
|
| (Prisma.PegawaiGetPayload<{
|
||||||
include: { posisi: true; image: true };
|
include: { posisi: true; image: true };
|
||||||
}> & { isActive: boolean })
|
}> & { isActive: boolean })
|
||||||
| null,
|
| null,
|
||||||
@@ -581,9 +334,12 @@ const pegawai = proxy({
|
|||||||
if (!id) return toast.warn("ID tidak valid");
|
if (!id) return toast.warn("ID tidak valid");
|
||||||
try {
|
try {
|
||||||
pegawai.delete.loading = true;
|
pegawai.delete.loading = true;
|
||||||
const res = await fetch(`/api/ekonomi/struktur-organisasi/pegawai/del/${id}`, {
|
const res = await fetch(
|
||||||
method: "DELETE",
|
`/api/ekonomi/struktur-organisasi/pegawai/del/${id}`,
|
||||||
});
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
}
|
||||||
|
);
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
toast.success(json.message ?? "Berhasil hapus pegawai");
|
toast.success(json.message ?? "Berhasil hapus pegawai");
|
||||||
@@ -600,31 +356,6 @@ const pegawai = proxy({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
nonActive: {
|
|
||||||
loading: false,
|
|
||||||
async byId(id: string) {
|
|
||||||
if (!id) return toast.warn("ID tidak valid");
|
|
||||||
try {
|
|
||||||
pegawai.nonActive.loading = true;
|
|
||||||
const res = await fetch(`/api/ekonomi/struktur-organisasi/pegawai/non-active/${id}`, {
|
|
||||||
method: "DELETE", // biasanya nonActive pakai PATCH
|
|
||||||
});
|
|
||||||
const json = await res.json();
|
|
||||||
if (res.ok) {
|
|
||||||
toast.success(json.message ?? "Pegawai berhasil dinonaktifkan");
|
|
||||||
await pegawai.findMany.load(); // refresh data
|
|
||||||
} else {
|
|
||||||
toast.error(json.message ?? "Gagal menonaktifkan pegawai");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Gagal nonActive:", error);
|
|
||||||
toast.error("Terjadi kesalahan saat menonaktifkan pegawai");
|
|
||||||
} finally {
|
|
||||||
pegawai.nonActive.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
edit: {
|
edit: {
|
||||||
id: "",
|
id: "",
|
||||||
form: { ...pegawaiDefaultForm },
|
form: { ...pegawaiDefaultForm },
|
||||||
@@ -637,12 +368,15 @@ const pegawai = proxy({
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/ekonomi/struktur-organisasi/pegawai/${id}`, {
|
const response = await fetch(
|
||||||
method: "GET",
|
`/api/ekonomi/struktur-organisasi/pegawai/${id}`,
|
||||||
headers: {
|
{
|
||||||
"Content-Type": "application/json",
|
method: "GET",
|
||||||
},
|
headers: {
|
||||||
});
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
@@ -753,10 +487,299 @@ const pegawai = proxy({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const stateStrukturBumDes = proxy({
|
// Schema Zod untuk form validasi
|
||||||
stateStruktur,
|
const templateHubunganOrganisasiForm = z.object({
|
||||||
posisiOrganisasi,
|
atasanId: z.string().min(1, "Atasan wajib dipilih"),
|
||||||
pegawai,
|
bawahanId: z.string().min(1, "Bawahan wajib dipilih"),
|
||||||
|
tipe: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default stateStrukturBumDes;
|
// 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;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
@@ -51,7 +50,7 @@ const grafikBerdasarkanUsiaKerjaNganggur = proxy({
|
|||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const id = res.data?.data?.id;
|
const id = res.data?.data?.id;
|
||||||
if (id) {
|
if (id) {
|
||||||
toast.success("Sukses menambahkan");
|
toast.success("Success create");
|
||||||
grafikBerdasarkanUsiaKerjaNganggur.create.form = {
|
grafikBerdasarkanUsiaKerjaNganggur.create.form = {
|
||||||
usia18_25: "",
|
usia18_25: "",
|
||||||
usia26_35: "",
|
usia26_35: "",
|
||||||
@@ -76,37 +75,16 @@ const grafikBerdasarkanUsiaKerjaNganggur = proxy({
|
|||||||
omit: { isActive: true };
|
omit: { isActive: true };
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
loading: false,
|
||||||
totalPages: 1,
|
async load() {
|
||||||
loading: false,
|
const res = await ApiFetch.api.ekonomi.grafikusiakerjayangmenganggur[
|
||||||
search: "",
|
"find-many"
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
].get();
|
||||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.loading = true; // ✅ Akses langsung via nama path
|
if (res.status === 200) {
|
||||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.page = page;
|
grafikBerdasarkanUsiaKerjaNganggur.findMany.data = res.data?.data ?? [];
|
||||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.search = search;
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.grafikusiakerjayangmenganggur["find-many"].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.data = res.data.data ?? [];
|
|
||||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.data = [];
|
|
||||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch grafik berdasarkan usia kerja yang menganggur paginated:", err);
|
|
||||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.data = [];
|
|
||||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
grafikBerdasarkanUsiaKerjaNganggur.findMany.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
findUnique: {
|
findUnique: {
|
||||||
data: null as Prisma.GrafikMenganggurBerdasarkanUsiaGetPayload<{
|
data: null as Prisma.GrafikMenganggurBerdasarkanUsiaGetPayload<{
|
||||||
omit: { isActive: true };
|
omit: { isActive: true };
|
||||||
@@ -255,7 +233,7 @@ const grafikBerdasarkanPendidikan = proxy({
|
|||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const id = res.data?.data?.id;
|
const id = res.data?.data?.id;
|
||||||
if (id) {
|
if (id) {
|
||||||
toast.success("Sukses menambahkan");
|
toast.success("Success create");
|
||||||
grafikBerdasarkanPendidikan.create.form = {
|
grafikBerdasarkanPendidikan.create.form = {
|
||||||
SD: "",
|
SD: "",
|
||||||
SMP: "",
|
SMP: "",
|
||||||
@@ -281,36 +259,15 @@ const grafikBerdasarkanPendidikan = proxy({
|
|||||||
omit: { isActive: true };
|
omit: { isActive: true };
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
loading: false,
|
||||||
totalPages: 1,
|
async load() {
|
||||||
loading: false,
|
const res = await ApiFetch.api.ekonomi.grafikmenganggurberdasarkanpendidikan[
|
||||||
search: "",
|
"find-many"
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
].get();
|
||||||
grafikBerdasarkanPendidikan.findMany.loading = true; // ✅ Akses langsung via nama path
|
if (res.status === 200) {
|
||||||
grafikBerdasarkanPendidikan.findMany.page = page;
|
grafikBerdasarkanPendidikan.findMany.data = res.data?.data ?? [];
|
||||||
grafikBerdasarkanPendidikan.findMany.search = search;
|
}
|
||||||
|
},
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi.grafikmenganggurberdasarkanpendidikan["find-many"].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
grafikBerdasarkanPendidikan.findMany.data = res.data.data ?? [];
|
|
||||||
grafikBerdasarkanPendidikan.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
grafikBerdasarkanPendidikan.findMany.data = [];
|
|
||||||
grafikBerdasarkanPendidikan.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch grafik berdasarkan pendidikan paginated:", err);
|
|
||||||
grafikBerdasarkanPendidikan.findMany.data = [];
|
|
||||||
grafikBerdasarkanPendidikan.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
grafikBerdasarkanPendidikan.findMany.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
findUnique: {
|
findUnique: {
|
||||||
data: null as Prisma.GrafikMenganggurBerdasarkanPendidikanGetPayload<{
|
data: null as Prisma.GrafikMenganggurBerdasarkanPendidikanGetPayload<{
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
@@ -62,37 +61,10 @@ const ajukanIdeInovatifState = proxy({
|
|||||||
};
|
};
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
async load() {
|
||||||
totalPages: 1,
|
const res = await ApiFetch.api.inovasi.ajukanideinovatif["find-many"].get();
|
||||||
loading: false,
|
if (res.status === 200) {
|
||||||
search: "",
|
ajukanIdeInovatifState.findMany.data = res.data?.data ?? [];
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
|
||||||
ajukanIdeInovatifState.findMany.loading = true; // ✅ Akses langsung via nama path
|
|
||||||
ajukanIdeInovatifState.findMany.page = page;
|
|
||||||
ajukanIdeInovatifState.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res =
|
|
||||||
await ApiFetch.api.inovasi.ajukanideinovatif[
|
|
||||||
"find-many"
|
|
||||||
].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
ajukanIdeInovatifState.findMany.data = res.data.data ?? [];
|
|
||||||
ajukanIdeInovatifState.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
ajukanIdeInovatifState.findMany.data = [];
|
|
||||||
ajukanIdeInovatifState.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch ajukan ide inovatif paginated:", err);
|
|
||||||
ajukanIdeInovatifState.findMany.data = [];
|
|
||||||
ajukanIdeInovatifState.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
ajukanIdeInovatifState.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -125,21 +97,16 @@ const ajukanIdeInovatifState = proxy({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
ajukanIdeInovatifState.delete.loading = true;
|
ajukanIdeInovatifState.delete.loading = true;
|
||||||
const response = await fetch(
|
const response = await fetch(`/api/inovasi/ajukanideinovatif/del/${id}`, {
|
||||||
`/api/inovasi/ajukanideinovatif/del/${id}`,
|
method: "DELETE",
|
||||||
{
|
headers: {
|
||||||
method: "DELETE",
|
"Content-Type": "application/json",
|
||||||
headers: {
|
},
|
||||||
"Content-Type": "application/json",
|
});
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
toast.success(
|
toast.success(result.message || "Ajukan Ide Inovatif berhasil dihapus");
|
||||||
result.message || "Ajukan Ide Inovatif berhasil dihapus"
|
|
||||||
);
|
|
||||||
await ajukanIdeInovatifState.findMany.load();
|
await ajukanIdeInovatifState.findMany.load();
|
||||||
} else {
|
} else {
|
||||||
toast.error(result?.message || "Gagal menghapus ajukan ide inovatif");
|
toast.error(result?.message || "Gagal menghapus ajukan ide inovatif");
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
@@ -37,7 +36,7 @@ const desaDigitalState = proxy({
|
|||||||
);
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
desaDigitalState.findMany.load();
|
desaDigitalState.findMany.load();
|
||||||
return toast.success("Sukses menambahkan");
|
return toast.success("success create");
|
||||||
}
|
}
|
||||||
console.log(res);
|
console.log(res);
|
||||||
return toast.error("failed create");
|
return toast.error("failed create");
|
||||||
@@ -56,34 +55,10 @@ const desaDigitalState = proxy({
|
|||||||
};
|
};
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
async load() {
|
||||||
totalPages: 1,
|
const res = await ApiFetch.api.inovasi.desadigital["find-many"].get();
|
||||||
loading: false,
|
if (res.status === 200) {
|
||||||
search: "",
|
desaDigitalState.findMany.data = res.data?.data ?? [];
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
|
||||||
desaDigitalState.findMany.loading = true; // ✅ Akses langsung via nama path
|
|
||||||
desaDigitalState.findMany.page = page;
|
|
||||||
desaDigitalState.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.inovasi.desadigital["find-many"].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
desaDigitalState.findMany.data = res.data.data ?? [];
|
|
||||||
desaDigitalState.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
desaDigitalState.findMany.data = [];
|
|
||||||
desaDigitalState.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch desa digital paginated:", err);
|
|
||||||
desaDigitalState.findMany.data = [];
|
|
||||||
desaDigitalState.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
desaDigitalState.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
@@ -37,7 +36,7 @@ const infoTeknoState = proxy({
|
|||||||
);
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
infoTeknoState.findMany.load();
|
infoTeknoState.findMany.load();
|
||||||
return toast.success("Sukses menambahkan");
|
return toast.success("success create");
|
||||||
}
|
}
|
||||||
console.log(res);
|
console.log(res);
|
||||||
return toast.error("failed create");
|
return toast.error("failed create");
|
||||||
@@ -56,34 +55,10 @@ const infoTeknoState = proxy({
|
|||||||
};
|
};
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
async load() {
|
||||||
totalPages: 1,
|
const res = await ApiFetch.api.inovasi.infotekno["find-many"].get();
|
||||||
loading: false,
|
if (res.status === 200) {
|
||||||
search: "",
|
infoTeknoState.findMany.data = res.data?.data ?? [];
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
|
||||||
infoTeknoState.findMany.loading = true; // ✅ Akses langsung via nama path
|
|
||||||
infoTeknoState.findMany.page = page;
|
|
||||||
infoTeknoState.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.inovasi.infotekno["find-many"].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
infoTeknoState.findMany.data = res.data.data ?? [];
|
|
||||||
infoTeknoState.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
infoTeknoState.findMany.data = [];
|
|
||||||
infoTeknoState.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch info teknologi paginated:", err);
|
|
||||||
infoTeknoState.findMany.data = [];
|
|
||||||
infoTeknoState.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
infoTeknoState.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,11 +6,12 @@ import { proxy } from "valtio";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
const templateForm = z.object({
|
const templateForm = z.object({
|
||||||
name: z.string().min(1, "Nama kolaborasi inovasi harus diisi"),
|
name: z.string().min(1, "Nama minimal 1 karakter"),
|
||||||
tahun: z.number().min(1900, "Tahun tidak valid").max(new Date().getFullYear() + 1, "Tahun tidak boleh lebih dari tahun depan"),
|
tahun: z.number().min(4, "Tahun minimal 4 karakter"),
|
||||||
slug: z.string().min(1, "Slug harus dihasilkan otomatis"),
|
slug: z.string().min(1, "Deskripsi singkat minimal 1 karakter"),
|
||||||
deskripsi: z.string().min(1, "Deskripsi harus diisi"),
|
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||||
kolaborator: z.string().min(1, "Kolaborator harus diisi"),
|
kolaborator: z.string().min(1, "Kolaborator minimal 1 karakter"),
|
||||||
|
imageId: z.string().min(1, "Image ID minimal 1 karakter"),
|
||||||
})
|
})
|
||||||
|
|
||||||
const defaultForm = {
|
const defaultForm = {
|
||||||
@@ -19,6 +20,7 @@ const defaultForm = {
|
|||||||
slug: "",
|
slug: "",
|
||||||
deskripsi: "",
|
deskripsi: "",
|
||||||
kolaborator: "",
|
kolaborator: "",
|
||||||
|
imageId: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
const kolaborasiInovasiState = proxy({
|
const kolaborasiInovasiState = proxy({
|
||||||
@@ -26,37 +28,27 @@ const kolaborasiInovasiState = proxy({
|
|||||||
form: { ...defaultForm },
|
form: { ...defaultForm },
|
||||||
loading: false,
|
loading: false,
|
||||||
async create() {
|
async create() {
|
||||||
try {
|
const cek = templateForm.safeParse(kolaborasiInovasiState.create.form);
|
||||||
// Validate form
|
if (!cek.success) {
|
||||||
const validation = templateForm.safeParse(kolaborasiInovasiState.create.form);
|
const err = `[${cek.error.issues
|
||||||
if (!validation.success) {
|
.map((v) => `${v.path.join(".")}`)
|
||||||
const errorMessages = validation.error.issues
|
.join("\n")}] required`;
|
||||||
.map(issue => `- ${issue.path.join('.')}: ${issue.message}`)
|
return toast.error(err);
|
||||||
.join('\n');
|
}
|
||||||
return toast.error(`Validasi gagal:\n${errorMessages}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
kolaborasiInovasiState.create.loading = true;
|
kolaborasiInovasiState.create.loading = true;
|
||||||
|
|
||||||
const res = await ApiFetch.api.inovasi.kolaborasiinovasi["create"].post(
|
const res = await ApiFetch.api.inovasi.kolaborasiinovasi["create"].post(
|
||||||
kolaborasiInovasiState.create.form
|
kolaborasiInovasiState.create.form
|
||||||
);
|
);
|
||||||
|
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
await kolaborasiInovasiState.findMany.load();
|
kolaborasiInovasiState.findMany.load();
|
||||||
return { success: true, data: res.data };
|
return toast.success("success create");
|
||||||
}
|
}
|
||||||
|
console.log(res);
|
||||||
console.error('Create failed:', res);
|
return toast.error("failed create");
|
||||||
toast.error(res.data?.message || "Gagal menyimpan data");
|
|
||||||
return { success: false, error: res.data };
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error in create:', error);
|
console.log((error as Error).message);
|
||||||
toast.error("Terjadi kesalahan saat menyimpan data");
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: error instanceof Error ? error.message : 'Unknown error'
|
|
||||||
};
|
|
||||||
} finally {
|
} finally {
|
||||||
kolaborasiInovasiState.create.loading = false;
|
kolaborasiInovasiState.create.loading = false;
|
||||||
}
|
}
|
||||||
@@ -68,21 +60,13 @@ const kolaborasiInovasiState = proxy({
|
|||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
total: 0,
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
load: async (page = 1, limit = 10) => {
|
||||||
year: "",
|
// Change to arrow function
|
||||||
load: async (page = 1, limit = 10, search = "", year?: string) => {
|
kolaborasiInovasiState.findMany.loading = true; // Use the full path to access the property
|
||||||
kolaborasiInovasiState.findMany.loading = true;
|
|
||||||
kolaborasiInovasiState.findMany.page = page;
|
kolaborasiInovasiState.findMany.page = page;
|
||||||
kolaborasiInovasiState.findMany.search = search;
|
|
||||||
kolaborasiInovasiState.findMany.year = year || "";
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
if (year) query.year = year;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.inovasi.kolaborasiinovasi["find-many"].get({
|
const res = await ApiFetch.api.inovasi.kolaborasiinovasi["find-many"].get({
|
||||||
query,
|
query: { page, limit },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
if (res.status === 200 && res.data?.success) {
|
||||||
@@ -140,6 +124,7 @@ const kolaborasiInovasiState = proxy({
|
|||||||
slug: data.slug,
|
slug: data.slug,
|
||||||
deskripsi: data.deskripsi,
|
deskripsi: data.deskripsi,
|
||||||
kolaborator: data.kolaborator,
|
kolaborator: data.kolaborator,
|
||||||
|
imageId: data.imageId,
|
||||||
};
|
};
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
@@ -194,7 +179,7 @@ const kolaborasiInovasiState = proxy({
|
|||||||
},
|
},
|
||||||
findUnique: {
|
findUnique: {
|
||||||
data: null as Prisma.KolaborasiInovasiGetPayload<{
|
data: null as Prisma.KolaborasiInovasiGetPayload<{
|
||||||
omit: { isActive: true };
|
include: { image: true };
|
||||||
}> | null,
|
}> | null,
|
||||||
async load(id: string) {
|
async load(id: string) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
@@ -55,20 +54,19 @@ const administrasiOnline = proxy({
|
|||||||
},
|
},
|
||||||
findMany: {
|
findMany: {
|
||||||
data: null as Array<
|
data: null as Array<
|
||||||
Prisma.AdministrasiOnlineGetPayload<{
|
Prisma.AdministrasiOnlineGetPayload<{
|
||||||
include: {
|
include: {
|
||||||
jenisLayanan: true;
|
jenisLayanan: true;
|
||||||
};
|
};
|
||||||
}>
|
}>
|
||||||
> | null,
|
> | null,
|
||||||
page: 1,
|
page: 1,
|
||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
|
||||||
async load(page = 1, limit = 10, search = "") {
|
async load(page = 1, limit = 10) {
|
||||||
administrasiOnline.findMany.loading = true;
|
administrasiOnline.findMany.loading = true;
|
||||||
administrasiOnline.findMany.page = page;
|
administrasiOnline.findMany.page = page;
|
||||||
administrasiOnline.findMany.search = search;
|
|
||||||
try {
|
try {
|
||||||
const res =
|
const res =
|
||||||
await ApiFetch.api.inovasi.layananonlinedesa.administrasionline[
|
await ApiFetch.api.inovasi.layananonlinedesa.administrasionline[
|
||||||
@@ -77,7 +75,6 @@ const administrasiOnline = proxy({
|
|||||||
query: {
|
query: {
|
||||||
page,
|
page,
|
||||||
limit,
|
limit,
|
||||||
search,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -94,10 +91,10 @@ const administrasiOnline = proxy({
|
|||||||
},
|
},
|
||||||
findUnique: {
|
findUnique: {
|
||||||
data: null as Prisma.AdministrasiOnlineGetPayload<{
|
data: null as Prisma.AdministrasiOnlineGetPayload<{
|
||||||
include: {
|
include: {
|
||||||
jenisLayanan: true;
|
jenisLayanan: true;
|
||||||
};
|
};
|
||||||
}> | null,
|
}> | null,
|
||||||
async load(id: string) {
|
async load(id: string) {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
@@ -202,37 +199,13 @@ const jenisLayanan = proxy({
|
|||||||
nama: string;
|
nama: string;
|
||||||
deskripsi: string;
|
deskripsi: string;
|
||||||
}> | null,
|
}> | null,
|
||||||
page: 1,
|
async load() {
|
||||||
totalPages: 1,
|
const res =
|
||||||
loading: false,
|
await ApiFetch.api.inovasi.layananonlinedesa.administrasionline.jenislayanan[
|
||||||
search: "",
|
"find-many"
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
].get();
|
||||||
jenisLayanan.findMany.loading = true; // ✅ Akses langsung via nama path
|
if (res.status === 200) {
|
||||||
jenisLayanan.findMany.page = page;
|
jenisLayanan.findMany.data = res.data?.data ?? [];
|
||||||
jenisLayanan.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res =
|
|
||||||
await ApiFetch.api.inovasi.layananonlinedesa.administrasionline.jenislayanan[
|
|
||||||
"find-many"
|
|
||||||
].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
jenisLayanan.findMany.data = res.data.data ?? [];
|
|
||||||
jenisLayanan.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
jenisLayanan.findMany.data = [];
|
|
||||||
jenisLayanan.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch jenis layanan paginated:", err);
|
|
||||||
jenisLayanan.findMany.data = [];
|
|
||||||
jenisLayanan.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
jenisLayanan.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -430,9 +403,7 @@ const templatePengaduanMasyarakatForm = z.object({
|
|||||||
nik: z.string().min(1, "NIK minimal 1 karakter"),
|
nik: z.string().min(1, "NIK minimal 1 karakter"),
|
||||||
judulPengaduan: z.string().min(1, "Judul pengaduan minimal 1 karakter"),
|
judulPengaduan: z.string().min(1, "Judul pengaduan minimal 1 karakter"),
|
||||||
lokasiKejadian: z.string().min(1, "Lokasi kejadian minimal 1 karakter"),
|
lokasiKejadian: z.string().min(1, "Lokasi kejadian minimal 1 karakter"),
|
||||||
deskripsiPengaduan: z
|
deskripsiPengaduan: z.string().min(1, "Deskripsi pengaduan minimal 1 karakter"),
|
||||||
.string()
|
|
||||||
.min(1, "Deskripsi pengaduan minimal 1 karakter"),
|
|
||||||
jenisPengaduanId: z.string().min(1, "Jenis pengaduan minimal 1 karakter"),
|
jenisPengaduanId: z.string().min(1, "Jenis pengaduan minimal 1 karakter"),
|
||||||
imageId: z.string().min(1, "Image minimal 1 karakter"),
|
imageId: z.string().min(1, "Image minimal 1 karakter"),
|
||||||
});
|
});
|
||||||
@@ -484,42 +455,37 @@ const pengaduanMasyarakat = proxy({
|
|||||||
},
|
},
|
||||||
findMany: {
|
findMany: {
|
||||||
data: null as Array<
|
data: null as Array<
|
||||||
Prisma.PengaduanMasyarakatGetPayload<{
|
Prisma.PengaduanMasyarakatGetPayload<{
|
||||||
include: {
|
include: {
|
||||||
jenisPengaduan: true;
|
jenisPengaduan: true;
|
||||||
image: true;
|
image: true;
|
||||||
};
|
};
|
||||||
}>
|
}>
|
||||||
> | null,
|
> | null,
|
||||||
page: 1,
|
page: 1,
|
||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
async load(page = 1, limit = 10) {
|
||||||
pengaduanMasyarakat.findMany.loading = true; // ✅ Akses langsung via nama path
|
pengaduanMasyarakat.findMany.loading = true;
|
||||||
pengaduanMasyarakat.findMany.page = page;
|
pengaduanMasyarakat.findMany.page = page;
|
||||||
pengaduanMasyarakat.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res =
|
const res =
|
||||||
await ApiFetch.api.inovasi.layananonlinedesa.pengaduanmasyarakat[
|
await ApiFetch.api.inovasi.layananonlinedesa.pengaduanmasyarakat[
|
||||||
"find-many"
|
"find-many"
|
||||||
].get({ query });
|
].get({
|
||||||
|
query: {
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
if (res.status === 200 && res.data?.success) {
|
||||||
pengaduanMasyarakat.findMany.data = res.data.data ?? [];
|
pengaduanMasyarakat.findMany.data = res.data.data ?? [];
|
||||||
pengaduanMasyarakat.findMany.totalPages = res.data.totalPages ?? 1;
|
pengaduanMasyarakat.findMany.totalPages = res.data.totalPages ?? 1;
|
||||||
} else {
|
|
||||||
pengaduanMasyarakat.findMany.data = [];
|
|
||||||
pengaduanMasyarakat.findMany.totalPages = 1;
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Gagal fetch pengaduan masyarakat paginated:", err);
|
console.error("Gagal fetch pengaduan masyarakat paginated:", err);
|
||||||
pengaduanMasyarakat.findMany.data = [];
|
|
||||||
pengaduanMasyarakat.findMany.totalPages = 1;
|
|
||||||
} finally {
|
} finally {
|
||||||
pengaduanMasyarakat.findMany.loading = false;
|
pengaduanMasyarakat.findMany.loading = false;
|
||||||
}
|
}
|
||||||
@@ -527,11 +493,11 @@ const pengaduanMasyarakat = proxy({
|
|||||||
},
|
},
|
||||||
findUnique: {
|
findUnique: {
|
||||||
data: null as Prisma.PengaduanMasyarakatGetPayload<{
|
data: null as Prisma.PengaduanMasyarakatGetPayload<{
|
||||||
include: {
|
include: {
|
||||||
jenisPengaduan: true;
|
jenisPengaduan: true;
|
||||||
image: true;
|
image: true;
|
||||||
};
|
};
|
||||||
}> | null,
|
}> | null,
|
||||||
async load(id: string) {
|
async load(id: string) {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
@@ -541,10 +507,7 @@ const pengaduanMasyarakat = proxy({
|
|||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
pengaduanMasyarakat.findUnique.data = data.data ?? null;
|
pengaduanMasyarakat.findUnique.data = data.data ?? null;
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
console.error("Failed to fetch pengaduan masyarakat:", res.statusText);
|
||||||
"Failed to fetch pengaduan masyarakat:",
|
|
||||||
res.statusText
|
|
||||||
);
|
|
||||||
pengaduanMasyarakat.findUnique.data = null;
|
pengaduanMasyarakat.findUnique.data = null;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -579,9 +542,7 @@ const pengaduanMasyarakat = proxy({
|
|||||||
);
|
);
|
||||||
await pengaduanMasyarakat.findMany.load(); // refresh list
|
await pengaduanMasyarakat.findMany.load(); // refresh list
|
||||||
} else {
|
} else {
|
||||||
toast.error(
|
toast.error(result?.message || "Gagal menghapus pengaduan masyarakat");
|
||||||
result?.message || "Gagal menghapus pengaduan masyarakat"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Gagal delete:", error);
|
console.error("Gagal delete:", error);
|
||||||
@@ -606,9 +567,7 @@ const jenisPengaduan = proxy({
|
|||||||
form: { ...defaultJenisPengaduanForm },
|
form: { ...defaultJenisPengaduanForm },
|
||||||
loading: false,
|
loading: false,
|
||||||
async create() {
|
async create() {
|
||||||
const cek = templateJenisPengaduanForm.safeParse(
|
const cek = templateJenisPengaduanForm.safeParse(jenisPengaduan.create.form);
|
||||||
jenisPengaduan.create.form
|
|
||||||
);
|
|
||||||
if (!cek.success) {
|
if (!cek.success) {
|
||||||
const err = `[${cek.error.issues
|
const err = `[${cek.error.issues
|
||||||
.map((v) => `${v.path.join(".")}`)
|
.map((v) => `${v.path.join(".")}`)
|
||||||
@@ -639,37 +598,13 @@ const jenisPengaduan = proxy({
|
|||||||
id: string;
|
id: string;
|
||||||
nama: string;
|
nama: string;
|
||||||
}> | null,
|
}> | null,
|
||||||
page: 1,
|
async load() {
|
||||||
totalPages: 1,
|
const res =
|
||||||
loading: false,
|
await ApiFetch.api.inovasi.layananonlinedesa.pengaduanmasyarakat.jenispengaduan[
|
||||||
search: "",
|
"find-many"
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
].get();
|
||||||
jenisPengaduan.findMany.loading = true; // ✅ Akses langsung via nama path
|
if (res.status === 200) {
|
||||||
jenisPengaduan.findMany.page = page;
|
jenisPengaduan.findMany.data = res.data?.data ?? [];
|
||||||
jenisPengaduan.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res =
|
|
||||||
await ApiFetch.api.inovasi.layananonlinedesa.pengaduanmasyarakat.jenispengaduan[
|
|
||||||
"find-many"
|
|
||||||
].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
jenisPengaduan.findMany.data = res.data.data ?? [];
|
|
||||||
jenisPengaduan.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
jenisPengaduan.findMany.data = [];
|
|
||||||
jenisPengaduan.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch jenis pengaduan paginated:", err);
|
|
||||||
jenisPengaduan.findMany.data = [];
|
|
||||||
jenisPengaduan.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
jenisPengaduan.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -758,7 +693,7 @@ const jenisPengaduan = proxy({
|
|||||||
const data = result.data;
|
const data = result.data;
|
||||||
this.id = data.id;
|
this.id = data.id;
|
||||||
this.form = {
|
this.form = {
|
||||||
nama: data.nama,
|
nama: data.nama
|
||||||
};
|
};
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
@@ -774,9 +709,7 @@ const jenisPengaduan = proxy({
|
|||||||
},
|
},
|
||||||
|
|
||||||
async update() {
|
async update() {
|
||||||
const cek = templateJenisPengaduanForm.safeParse(
|
const cek = templateJenisPengaduanForm.safeParse(jenisPengaduan.edit.form);
|
||||||
jenisPengaduan.edit.form
|
|
||||||
);
|
|
||||||
if (!cek.success) {
|
if (!cek.success) {
|
||||||
const err = `[${cek.error.issues
|
const err = `[${cek.error.issues
|
||||||
.map((v) => `${v.path.join(".")}`)
|
.map((v) => `${v.path.join(".")}`)
|
||||||
@@ -826,9 +759,7 @@ const jenisPengaduan = proxy({
|
|||||||
await jenisPengaduan.findMany.load(); // refresh list
|
await jenisPengaduan.findMany.load(); // refresh list
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(result.message || "Gagal mengupdate jenis pengaduan");
|
||||||
result.message || "Gagal mengupdate jenis pengaduan"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// If JSON parsing fails, try to get the response text for better error messages
|
// If JSON parsing fails, try to get the response text for better error messages
|
||||||
@@ -861,6 +792,7 @@ const jenisPengaduan = proxy({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const layananonlineDesa = proxy({
|
const layananonlineDesa = proxy({
|
||||||
administrasiOnline,
|
administrasiOnline,
|
||||||
jenisLayanan,
|
jenisLayanan,
|
||||||
|
|||||||
@@ -1,229 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
|
||||||
import { Prisma } from "@prisma/client";
|
|
||||||
import { toast } from "react-toastify";
|
|
||||||
import { proxy } from "valtio";
|
|
||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
const mitraKolaborasiForm = z.object({
|
|
||||||
name: z.string().min(1, { message: "Name is required" }),
|
|
||||||
imageId: z.string().nonempty(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const defaultForm = {
|
|
||||||
name: "",
|
|
||||||
imageId: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
const mitraKolaborasi = proxy({
|
|
||||||
create: {
|
|
||||||
form: { ...defaultForm },
|
|
||||||
loading: false,
|
|
||||||
async create() {
|
|
||||||
const cek = mitraKolaborasiForm.safeParse(mitraKolaborasi.create.form);
|
|
||||||
if (!cek.success) {
|
|
||||||
const err = `[${cek.error.issues
|
|
||||||
.map((v) => `${v.path.join(".")}`)
|
|
||||||
.join("\n")}] required`;
|
|
||||||
return toast.error(err);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
mitraKolaborasi.create.loading = true;
|
|
||||||
const res = await ApiFetch.api.inovasi.mitrakolaborasi["create"].post(
|
|
||||||
mitraKolaborasi.create.form
|
|
||||||
);
|
|
||||||
if (res.status === 200) {
|
|
||||||
mitraKolaborasi.findMany.load();
|
|
||||||
return toast.success("mitraKolaborasi berhasil disimpan!");
|
|
||||||
}
|
|
||||||
return toast.error("Gagal menyimpan mitraKolaborasi");
|
|
||||||
} catch (error) {
|
|
||||||
console.log((error as Error).message);
|
|
||||||
} finally {
|
|
||||||
mitraKolaborasi.create.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resetForm() {
|
|
||||||
mitraKolaborasi.create.form = { ...defaultForm };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
findMany: {
|
|
||||||
data: null as
|
|
||||||
| Prisma.MitraKolaborasiGetPayload<{
|
|
||||||
include: {
|
|
||||||
image: true;
|
|
||||||
};
|
|
||||||
}>[]
|
|
||||||
| null,
|
|
||||||
page: 1,
|
|
||||||
totalPages: 1,
|
|
||||||
loading: false,
|
|
||||||
search: "",
|
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
|
||||||
mitraKolaborasi.findMany.loading = true; // ✅ Akses langsung via nama path
|
|
||||||
mitraKolaborasi.findMany.page = page;
|
|
||||||
mitraKolaborasi.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
|
||||||
if (search) query.search = search;
|
|
||||||
|
|
||||||
const res = await ApiFetch.api.inovasi.mitrakolaborasi["find-many"].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
mitraKolaborasi.findMany.data = res.data.data ?? [];
|
|
||||||
mitraKolaborasi.findMany.totalPages = res.data.totalPages ?? 1;
|
|
||||||
} else {
|
|
||||||
mitraKolaborasi.findMany.data = [];
|
|
||||||
mitraKolaborasi.findMany.totalPages = 1;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Gagal fetch mitraKolaborasi paginated:", err);
|
|
||||||
mitraKolaborasi.findMany.data = [];
|
|
||||||
mitraKolaborasi.findMany.totalPages = 1;
|
|
||||||
} finally {
|
|
||||||
mitraKolaborasi.findMany.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
findUnique: {
|
|
||||||
data: null as Prisma.MitraKolaborasiGetPayload<{
|
|
||||||
include: {
|
|
||||||
image: true;
|
|
||||||
};
|
|
||||||
}> | null,
|
|
||||||
async load(id: string) {
|
|
||||||
try {
|
|
||||||
const res = await fetch(`/api/inovasi/mitrakolaborasi/${id}`);
|
|
||||||
if (res.ok) {
|
|
||||||
const data = await res.json();
|
|
||||||
mitraKolaborasi.findUnique.data = data.data ?? null;
|
|
||||||
} else {
|
|
||||||
console.error("Failed to fetch mitraKolaborasi:", res.statusText);
|
|
||||||
mitraKolaborasi.findUnique.data = null;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching mitraKolaborasi:", error);
|
|
||||||
mitraKolaborasi.findUnique.data = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
delete: {
|
|
||||||
loading: false,
|
|
||||||
async byId(id: string) {
|
|
||||||
if (!id) return toast.warn("ID tidak valid");
|
|
||||||
try {
|
|
||||||
mitraKolaborasi.delete.loading = true;
|
|
||||||
const response = await fetch(`/api/inovasi/mitrakolaborasi/del/${id}`, {
|
|
||||||
method: "DELETE",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const result = await response.json();
|
|
||||||
if (response.ok) {
|
|
||||||
toast.success(result.message || "mitraKolaborasi berhasil dihapus");
|
|
||||||
await mitraKolaborasi.findMany.load(); // refresh list
|
|
||||||
} else {
|
|
||||||
toast.error(result.message || "Gagal menghapus mitraKolaborasi");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Gagal delete:", error);
|
|
||||||
toast.error("Terjadi kesalahan saat menghapus mitraKolaborasi");
|
|
||||||
} finally {
|
|
||||||
mitraKolaborasi.delete.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
id: "",
|
|
||||||
form: { ...defaultForm },
|
|
||||||
loading: false,
|
|
||||||
async load(id: string) {
|
|
||||||
if (!id) {
|
|
||||||
toast.warn("ID tidak valid");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/api/inovasi/mitrakolaborasi/${id}`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
const result = await response.json();
|
|
||||||
if (result?.success) {
|
|
||||||
const data = result.data;
|
|
||||||
this.id = data.id;
|
|
||||||
this.form = {
|
|
||||||
name: data.name,
|
|
||||||
imageId: data.imageId,
|
|
||||||
};
|
|
||||||
return data;
|
|
||||||
} else {
|
|
||||||
throw new Error(result.message || "Gagal memuat data");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error loading mitraKolaborasi:", error);
|
|
||||||
toast.error(
|
|
||||||
error instanceof Error ? error.message : "Gagal memuat data"
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async update() {
|
|
||||||
const cek = mitraKolaborasiForm.safeParse(mitraKolaborasi.update.form);
|
|
||||||
if (!cek.success) {
|
|
||||||
const err = `[${cek.error.issues
|
|
||||||
.map((v) => `${v.path.join(".")}`)
|
|
||||||
.join("\n")}] required`;
|
|
||||||
toast.error(err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
mitraKolaborasi.update.loading = true;
|
|
||||||
const response = await fetch(`/api/inovasi/mitrakolaborasi/${this.id}`, {
|
|
||||||
method: "PUT",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
name: this.form.name,
|
|
||||||
imageId: this.form.imageId,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
const errorData = await response.json().catch(() => ({}));
|
|
||||||
throw new Error(
|
|
||||||
errorData.message || `HTTP error! status: ${response.status}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const result = await response.json();
|
|
||||||
if (result.success) {
|
|
||||||
toast.success(result.message || "mitraKolaborasi berhasil diupdate");
|
|
||||||
await mitraKolaborasi.findMany.load(); // refresh list
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
throw new Error(result.message || "Gagal mengupdate mitraKolaborasi");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error updating mitraKolaborasi:", error);
|
|
||||||
toast.error(
|
|
||||||
error instanceof Error ? error.message : "Gagal mengupdate mitraKolaborasi"
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
mitraKolaborasi.update.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
reset() {
|
|
||||||
mitraKolaborasi.update.id = "";
|
|
||||||
mitraKolaborasi.update.form = { ...defaultForm };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default mitraKolaborasi;
|
|
||||||
@@ -6,9 +6,9 @@ import { proxy } from "valtio";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
const templateForm = z.object({
|
const templateForm = z.object({
|
||||||
name: z.string().min(5, "Nama minimal 5 karakter"),
|
name: z.string().min(1, "Nama minimal 1 karakter"),
|
||||||
deskripsi: z.string().min(5, "Deskripsi minimal 5 karakter"),
|
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
||||||
slug: z.string().min(5, "Deskripsi singkat minimal 5 karakter"),
|
slug: z.string().min(1, "Deskripsi singkat minimal 1 karakter"),
|
||||||
icon: z.string().min(1, "Icon minimal 1 karakter"),
|
icon: z.string().min(1, "Icon minimal 1 karakter"),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -29,64 +29,59 @@ const programKreatifState = proxy({
|
|||||||
const err = `[${cek.error.issues
|
const err = `[${cek.error.issues
|
||||||
.map((v) => `${v.path.join(".")}`)
|
.map((v) => `${v.path.join(".")}`)
|
||||||
.join("\n")}] required`;
|
.join("\n")}] required`;
|
||||||
toast.error(err);
|
return toast.error(err);
|
||||||
return false; // ⬅️ ini penting
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
programKreatifState.create.loading = true;
|
programKreatifState.create.loading = true;
|
||||||
const res = await ApiFetch.api.inovasi.programkreatif["create"].post(
|
const res = await ApiFetch.api.inovasi.programkreatif["create"].post(
|
||||||
programKreatifState.create.form
|
programKreatifState.create.form
|
||||||
);
|
);
|
||||||
|
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
programKreatifState.findMany.load();
|
programKreatifState.findMany.load();
|
||||||
toast.success("Sukses menambahkan");
|
return toast.success("success create");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
console.log(res);
|
||||||
toast.error("failed create");
|
return toast.error("failed create");
|
||||||
return false;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error((error as Error).message);
|
console.log((error as Error).message);
|
||||||
toast.error("Terjadi kesalahan saat create");
|
|
||||||
return false;
|
|
||||||
} finally {
|
} finally {
|
||||||
programKreatifState.create.loading = false;
|
programKreatifState.create.loading = false;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
findMany: {
|
findMany: {
|
||||||
data: null as any[] | null,
|
data: null as any[] | null,
|
||||||
page: 1,
|
page: 1,
|
||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
load: async (page = 1, limit = 10) => {
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
// Change to arrow function
|
||||||
programKreatifState.findMany.loading = true; // ✅ Akses langsung via nama path
|
programKreatifState.findMany.loading = true; // Use the full path to access the property
|
||||||
programKreatifState.findMany.page = page;
|
programKreatifState.findMany.page = page;
|
||||||
programKreatifState.findMany.search = search;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit };
|
const res = await ApiFetch.api.inovasi.programkreatif["find-many"].get({
|
||||||
if (search) query.search = search;
|
query: { page, limit },
|
||||||
|
});
|
||||||
const res = await ApiFetch.api.inovasi.programkreatif[
|
|
||||||
"find-many"
|
|
||||||
].get({ query });
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
if (res.status === 200 && res.data?.success) {
|
||||||
programKreatifState.findMany.data = res.data.data ?? [];
|
programKreatifState.findMany.data = res.data.data || [];
|
||||||
programKreatifState.findMany.totalPages =
|
programKreatifState.findMany.total = res.data.total || 0;
|
||||||
res.data.totalPages ?? 1;
|
programKreatifState.findMany.totalPages = res.data.totalPages || 1;
|
||||||
} else {
|
} else {
|
||||||
|
console.error(
|
||||||
|
"Failed to load grafik berdasarkan jenis kelamin:",
|
||||||
|
res.data?.message
|
||||||
|
);
|
||||||
programKreatifState.findMany.data = [];
|
programKreatifState.findMany.data = [];
|
||||||
|
programKreatifState.findMany.total = 0;
|
||||||
programKreatifState.findMany.totalPages = 1;
|
programKreatifState.findMany.totalPages = 1;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (error) {
|
||||||
console.error("Gagal fetch program kreatif paginated:", err);
|
console.error("Error loading grafik berdasarkan jenis kelamin:", error);
|
||||||
programKreatifState.findMany.data = [];
|
programKreatifState.findMany.data = [];
|
||||||
|
programKreatifState.findMany.total = 0;
|
||||||
programKreatifState.findMany.totalPages = 1;
|
programKreatifState.findMany.totalPages = 1;
|
||||||
} finally {
|
} finally {
|
||||||
programKreatifState.findMany.loading = false;
|
programKreatifState.findMany.loading = false;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const keamananLingkunganState = proxy({
|
|||||||
].post(keamananLingkunganState.create.form);
|
].post(keamananLingkunganState.create.form);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
keamananLingkunganState.findMany.load();
|
keamananLingkunganState.findMany.load();
|
||||||
return toast.success("Sukses menambahkan");
|
return toast.success("success create");
|
||||||
}
|
}
|
||||||
console.log(res);
|
console.log(res);
|
||||||
return toast.error("failed create");
|
return toast.error("failed create");
|
||||||
|
|||||||