Compare commits
25 Commits
nico/6-okt
...
nico/7-nov
| Author | SHA1 | Date | |
|---|---|---|---|
| 417a8937f5 | |||
| db8909b9ed | |||
| f66a46f645 | |||
| fb57698dc9 | |||
| d128313e71 | |||
| 7b4bb1e58e | |||
| 0befe6a3f2 | |||
| a6663bbcee | |||
| ed371bd0d9 | |||
| f82c7b86e0 | |||
| b5d6585cd5 | |||
| aa98359ef7 | |||
| 0ff0d5234a | |||
| 827c1c191a | |||
| fb596f9033 | |||
| 9055b40769 | |||
| bbf13c1cf7 | |||
| 75bf0652b1 | |||
| 0b574406e2 | |||
| ccf39bc778 | |||
| 3c21f7742c | |||
| a158241c0b | |||
| 80c5dc6361 | |||
| 8ad38fc907 | |||
| d601b2fee3 |
18
package.json
18
package.json
@@ -3,9 +3,9 @@
|
|||||||
"version": "0.1.5",
|
"version": "0.1.5",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun --bun next dev --hostname 0.0.0.0",
|
"dev": "next dev",
|
||||||
"build": "bun --bun next build",
|
"build": "next build",
|
||||||
"start": "bun --bun next start"
|
"start": "next start"
|
||||||
},
|
},
|
||||||
"prisma": {
|
"prisma": {
|
||||||
"seed": "bun run prisma/seed.ts"
|
"seed": "bun run prisma/seed.ts"
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
"@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",
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
"@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",
|
||||||
@@ -43,6 +45,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",
|
"adm-zip": "^0.5.16",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
@@ -52,9 +55,11 @@
|
|||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
|
"dotenv": "^17.2.3",
|
||||||
"elysia": "^1.3.5",
|
"elysia": "^1.3.5",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel": "^8.6.0",
|
||||||
"embla-carousel-react": "^7.1.0",
|
"embla-carousel-autoplay": "^8.6.0",
|
||||||
|
"embla-carousel-react": "^8.6.0",
|
||||||
"extract-zip": "^2.0.1",
|
"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",
|
||||||
@@ -71,17 +76,20 @@
|
|||||||
"next": "^15.5.2",
|
"next": "^15.5.2",
|
||||||
"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-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",
|
"sharp": "^0.34.3",
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
[
|
[
|
||||||
{ "name": "Semua" },
|
|
||||||
{ "name": "Pemerintahan" },
|
{ "name": "Pemerintahan" },
|
||||||
{ "name": "Pembangunan" },
|
{ "name": "Pembangunan" },
|
||||||
{ "name": "Ekonomi" },
|
{ "name": "Ekonomi" },
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": "650e8400-e29b-41d4-a716-446655440001",
|
|
||||||
"atasanId": "550e8400-e29b-41d4-a716-446655440001",
|
|
||||||
"bawahanId": "550e8400-e29b-41d4-a716-446655440002",
|
|
||||||
"tipe": "Langsung Melapor"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
91
prisma/data/ekonomi/struktur-organisasi/pegawai-bumdes.json
Normal file
91
prisma/data/ekonomi/struktur-organisasi/pegawai-bumdes.json
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": "550e8400-e29b-41d4-a716-446655440001",
|
|
||||||
"namaLengkap": "Budi Santoso",
|
|
||||||
"gelarAkademik": "S.IP",
|
|
||||||
"tanggalMasuk": "2020-01-01T00:00:00.000Z",
|
|
||||||
"email": "budi@desa.id",
|
|
||||||
"telepon": "081234567891",
|
|
||||||
"alamat": "Jl. Raya Desa No. 1",
|
|
||||||
"posisiId": "kepala_desa",
|
|
||||||
"isActive": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "550e8400-e29b-41d4-a716-446655440002",
|
|
||||||
"namaLengkap": "Ani Lestari",
|
|
||||||
"gelarAkademik": "S.Pd",
|
|
||||||
"tanggalMasuk": "2020-02-01T00:00:00.000Z",
|
|
||||||
"email": "ani@desa.id",
|
|
||||||
"telepon": "081234567892",
|
|
||||||
"alamat": "Jl. Raya Desa No. 2",
|
|
||||||
"posisiId": "sekretaris_desa",
|
|
||||||
"isActive": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"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,16 +1,4 @@
|
|||||||
[
|
[
|
||||||
{
|
|
||||||
"id": "cmds8w2q60002vnbe6i8qhkuo",
|
|
||||||
"name": "Telephone Desa Darmasaba",
|
|
||||||
"iconUrl": "081239580000",
|
|
||||||
"imageId": "cmff3nv180003vn6h5jvedidq"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cmds8z7u20005vnbegyyvnbk0",
|
|
||||||
"name": "Email Desa Darmasaba",
|
|
||||||
"iconUrl": "desadarmasaba@badungkab.go.id",
|
|
||||||
"imageId": "cmff3ll130001vn6hkhls3f5y"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "cmds9023u0008vnbe3oxmhwyf",
|
"id": "cmds9023u0008vnbe3oxmhwyf",
|
||||||
"name": "Desa Darmasaba",
|
"name": "Desa Darmasaba",
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[
|
||||||
|
{ "nama": "Kebersihan" },
|
||||||
|
{ "nama": "Infrastruktur" },
|
||||||
|
{ "nama": "Sosial" },
|
||||||
|
{ "nama": "Lingkungan" }
|
||||||
|
]
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
[
|
||||||
|
{ "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,6 +1,6 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "550e8400-e29b-41d4-a716-446655440001",
|
"id": "cmgewz4gt000704ib91i3f169",
|
||||||
"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": "550e8400-e29b-41d4-a716-446655440002",
|
"id": "cmgewxfvw000004ibee5013f4",
|
||||||
"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": "550e8400-e29b-41d4-a716-446655440006",
|
"id": "cmgewxvqw000104ibgm5l8fzs",
|
||||||
"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": "550e8400-e29b-41d4-a716-446655440011",
|
"id": "cmgewy1g9000204ib2n7hbx0i",
|
||||||
"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": "550e8400-e29b-41d4-a716-446655440012",
|
"id": "cmgewybah000304ibgqhn1gm2",
|
||||||
"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": "550e8400-e29b-41d4-a716-446655440017",
|
"id": "cmgewygqz000404ib20sv8nvg",
|
||||||
"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": "550e8400-e29b-41d4-a716-446655440018",
|
"id": "cmgewyos1000504ibcu8o2gyk",
|
||||||
"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": "550e8400-e29b-41d4-a716-446655440021",
|
"id": "cmgewyxk7000604ib8djs3i6c",
|
||||||
"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",
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ model FileStorage {
|
|||||||
PelayananSuratKeteranganImage PelayananSuratKeterangan[] @relation("PelayananSuratKeteranganImage")
|
PelayananSuratKeteranganImage PelayananSuratKeterangan[] @relation("PelayananSuratKeteranganImage")
|
||||||
PelayananSuratKeteranganImage2 PelayananSuratKeterangan[] @relation("PelayananSuratKeteranganImage2")
|
PelayananSuratKeteranganImage2 PelayananSuratKeterangan[] @relation("PelayananSuratKeteranganImage2")
|
||||||
PasarDesa PasarDesa[]
|
PasarDesa PasarDesa[]
|
||||||
Pegawai Pegawai[]
|
PegawaiBumDes PegawaiBumDes[]
|
||||||
DesaDigital DesaDigital[]
|
DesaDigital DesaDigital[]
|
||||||
InfoTekno InfoTekno[]
|
InfoTekno InfoTekno[]
|
||||||
PengaduanMasyarakat PengaduanMasyarakat[]
|
PengaduanMasyarakat PengaduanMasyarakat[]
|
||||||
@@ -101,6 +101,7 @@ model FileStorage {
|
|||||||
MitraKolaborasi MitraKolaborasi[]
|
MitraKolaborasi MitraKolaborasi[]
|
||||||
|
|
||||||
ArtikelKesehatan ArtikelKesehatan[]
|
ArtikelKesehatan ArtikelKesehatan[]
|
||||||
|
StrukturBumDes StrukturBumDes[]
|
||||||
}
|
}
|
||||||
|
|
||||||
//========================================= MENU LANDING PAGE ========================================= //
|
//========================================= MENU LANDING PAGE ========================================= //
|
||||||
@@ -142,7 +143,7 @@ model MediaSosial {
|
|||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
//========================================= PROFILE ========================================= //
|
//========================================= DESA ANTI KORUPSI ========================================= //
|
||||||
model DesaAntiKorupsi {
|
model DesaAntiKorupsi {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String @unique
|
name String @unique
|
||||||
@@ -286,49 +287,51 @@ 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)
|
isActive Boolean @default(true)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
parent PosisiOrganisasiPPID? @relation("Parent", fields: [parentId], references: [id])
|
parent PosisiOrganisasiPPID? @relation("Parent", fields: [parentId], references: [id])
|
||||||
children PosisiOrganisasiPPID[] @relation("Parent")
|
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 @db.Uuid
|
pegawaiId String
|
||||||
hubunganOrganisasiId String @db.Uuid
|
hubunganOrganisasiId String
|
||||||
posisiOrganisasi PosisiOrganisasi @relation(fields: [posisiOrganisasiId], references: [id])
|
posisiOrganisasi PosisiOrganisasiPPID @relation(fields: [posisiOrganisasiId], references: [id])
|
||||||
pegawai Pegawai @relation(fields: [pegawaiId], references: [id])
|
pegawai PegawaiPPID @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 ========================================= //
|
||||||
@@ -850,7 +853,7 @@ 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
|
||||||
@@ -1394,79 +1397,67 @@ model LowonganPekerjaan {
|
|||||||
|
|
||||||
// ========================================= STRUKTUR ORGANISASI ========================================= //
|
// ========================================= STRUKTUR ORGANISASI ========================================= //
|
||||||
|
|
||||||
model PosisiOrganisasi {
|
model StrukturBumDes {
|
||||||
id String @id @default(uuid()) @db.VarChar(50)
|
id String @id @default(cuid())
|
||||||
nama String @db.VarChar(100)
|
name String @db.Text
|
||||||
deskripsi String? @db.Text
|
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||||
hierarki Int
|
imageId String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
pegawai Pegawai[]
|
updatedAt DateTime @updatedAt
|
||||||
strukturOrganisasi StrukturOrganisasi[] // Relasi balik
|
deletedAt DateTime @default(now())
|
||||||
StrukturOrganisasiPPID StrukturOrganisasiPPID[]
|
isActive Boolean @default(true)
|
||||||
isActive Boolean @default(true)
|
PosisiOrganisasiBumDes PosisiOrganisasiBumDes? @relation(fields: [posisiOrganisasiBumDesId], references: [id])
|
||||||
createdAt DateTime @default(now())
|
posisiOrganisasiBumDesId String?
|
||||||
updatedAt DateTime @updatedAt
|
PegawaiBumDes PegawaiBumDes? @relation(fields: [pegawaiBumDesId], references: [id])
|
||||||
|
pegawaiBumDesId String?
|
||||||
@@map("posisi_organisasi")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model Pegawai {
|
model PosisiOrganisasiBumDes {
|
||||||
id String @id @default(uuid()) @db.Uuid
|
id String @id @default(cuid())
|
||||||
namaLengkap String @db.VarChar(255)
|
nama String @db.VarChar(100)
|
||||||
gelarAkademik String? @db.VarChar(100)
|
deskripsi String? @db.Text
|
||||||
image FileStorage? @relation(fields: [imageId], references: [id])
|
hierarki Int
|
||||||
imageId String?
|
pegawai PegawaiBumDes[]
|
||||||
tanggalMasuk DateTime? @db.Date
|
strukturOrganisasi StrukturBumDes[] // Relasi balik
|
||||||
email String? @unique @db.VarChar(255)
|
parentId String?
|
||||||
telepon String? @db.VarChar(20)
|
isActive Boolean @default(true)
|
||||||
alamat String? @db.Text
|
createdAt DateTime @default(now())
|
||||||
posisiId String @db.VarChar(50)
|
updatedAt DateTime @updatedAt
|
||||||
isActive Boolean @default(true)
|
parent PosisiOrganisasiBumDes? @relation("Parent", fields: [parentId], references: [id])
|
||||||
createdAt DateTime @default(now())
|
children PosisiOrganisasiBumDes[] @relation("Parent")
|
||||||
updatedAt DateTime @updatedAt
|
StrukturOrganisasiBumDes StrukturOrganisasiBumDes[]
|
||||||
|
|
||||||
posisi PosisiOrganisasi @relation(fields: [posisiId], references: [id])
|
|
||||||
|
|
||||||
sebagaiAtasan HubunganOrganisasi[] @relation("AtasanToBawahan")
|
|
||||||
sebagaiBawahan HubunganOrganisasi[] @relation("BawahanToAtasan")
|
|
||||||
|
|
||||||
strukturOrganisasi StrukturOrganisasi[] // Relasi balik
|
|
||||||
StrukturOrganisasiPPID StrukturOrganisasiPPID[]
|
|
||||||
|
|
||||||
@@map("pegawai")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model HubunganOrganisasi {
|
model PegawaiBumDes {
|
||||||
id String @id @default(uuid()) @db.Uuid
|
id String @id @default(cuid())
|
||||||
atasanId String @db.Uuid
|
namaLengkap String @db.VarChar(255)
|
||||||
bawahanId String @db.Uuid
|
gelarAkademik String? @db.VarChar(100)
|
||||||
tipe String? @db.VarChar(50)
|
image FileStorage? @relation(fields: [imageId], references: [id])
|
||||||
|
imageId String?
|
||||||
atasan Pegawai @relation("AtasanToBawahan", fields: [atasanId], references: [id])
|
tanggalMasuk DateTime? @db.Date
|
||||||
bawahan Pegawai @relation("BawahanToAtasan", fields: [bawahanId], references: [id])
|
email String? @unique @db.VarChar(255)
|
||||||
|
telepon String? @db.VarChar(20)
|
||||||
strukturOrganisasi StrukturOrganisasi[] // Relasi balik
|
alamat String? @db.Text
|
||||||
|
posisiId String @db.VarChar(50)
|
||||||
@@unique([atasanId, bawahanId])
|
isActive Boolean @default(true)
|
||||||
@@map("hubungan_organisasi")
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
posisi PosisiOrganisasiBumDes @relation(fields: [posisiId], references: [id])
|
||||||
|
strukturOrganisasi StrukturBumDes[] // Relasi balik
|
||||||
|
StrukturOrganisasiBumDes StrukturOrganisasiBumDes[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model StrukturOrganisasi {
|
model StrukturOrganisasiBumDes {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
posisiOrganisasiId String @db.VarChar(50)
|
posisiOrganisasiId String @db.VarChar(50)
|
||||||
pegawaiId String @db.Uuid
|
pegawaiId String
|
||||||
hubunganOrganisasiId String @db.Uuid
|
hubunganOrganisasiId String
|
||||||
|
posisiOrganisasi PosisiOrganisasiBumDes @relation(fields: [posisiOrganisasiId], references: [id])
|
||||||
posisiOrganisasi PosisiOrganisasi @relation(fields: [posisiOrganisasiId], references: [id])
|
pegawai PegawaiBumDes @relation(fields: [pegawaiId], references: [id])
|
||||||
pegawai Pegawai @relation(fields: [pegawaiId], references: [id])
|
createdAt DateTime @default(now())
|
||||||
hubunganOrganisasi HubunganOrganisasi @relation(fields: [hubunganOrganisasiId], references: [id])
|
updatedAt DateTime @updatedAt
|
||||||
|
deletedAt DateTime?
|
||||||
createdAt DateTime @default(now())
|
isActive Boolean @default(true)
|
||||||
updatedAt DateTime @updatedAt
|
|
||||||
deletedAt DateTime?
|
|
||||||
isActive Boolean @default(true)
|
|
||||||
|
|
||||||
@@map("struktur_organisasi")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================= PROGRAM KEMISKINAN ========================================= //
|
// ========================================= PROGRAM KEMISKINAN ========================================= //
|
||||||
@@ -1615,7 +1606,7 @@ model Pembiayaan {
|
|||||||
ApbDesa ApbDesa[] @relation("ApbDesaPembiayaan")
|
ApbDesa ApbDesa[] @relation("ApbDesaPembiayaan")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================= INOVASI ========================================= //
|
// ========================================= MENU INOVASI ========================================= //
|
||||||
// ========================================= DESA DIGITAL / SMART VILLAGE ========================================= //
|
// ========================================= DESA DIGITAL / SMART VILLAGE ========================================= //
|
||||||
model DesaDigital {
|
model DesaDigital {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
@@ -2096,6 +2087,9 @@ 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 {
|
||||||
@@ -2108,6 +2102,31 @@ 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 ========================================= //
|
// ========================================= USER ========================================= //
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
|
|||||||
111
prisma/seed.ts
111
prisma/seed.ts
@@ -31,14 +31,14 @@ import sejarahDesa from "./data/desa/profile/sejarah_desa.json";
|
|||||||
import visiMisiDesa from "./data/desa/profile/visi_misi_desa.json";
|
import visiMisiDesa from "./data/desa/profile/visi_misi_desa.json";
|
||||||
import detailDataPengangguran from "./data/ekonomi/jumlah-pengangguran/detail-data-pengangguran.json";
|
import detailDataPengangguran from "./data/ekonomi/jumlah-pengangguran/detail-data-pengangguran.json";
|
||||||
import kategoriProduk from "./data/ekonomi/pasar-desa/kategori-produk.json";
|
import kategoriProduk from "./data/ekonomi/pasar-desa/kategori-produk.json";
|
||||||
import hubunganOrganisasi from "./data/ekonomi/struktur-organisasi/hubungan-organisasi.json";
|
import pegawai from "./data/ekonomi/struktur-organisasi/pegawai-bumdes.json";
|
||||||
import pegawai from "./data/ekonomi/struktur-organisasi/pegawai.json";
|
import posisiOrganisasi from "./data/ekonomi/struktur-organisasi/posisi-organisasi-bumdes.json";
|
||||||
import posisiOrganisasi from "./data/ekonomi/struktur-organisasi/posisi-organisasi.json";
|
import kategoriBerita from "./data/desa/berita/kategori-berita.json";
|
||||||
import kategoriBerita from "./data/kategori-berita.json";
|
|
||||||
import contohEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/contoh-kegiatan-di-desa-darmasaba.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 materiEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/materi-edukasi-yang-diberikan.json";
|
||||||
import tujuanEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/tujuan-edukasi-lingkungan.json";
|
import tujuanEdukasiLingkungan from "./data/lingkungan/edukasi-lingkungan/tujuan-edukasi-lingkungan.json";
|
||||||
import bentukKonservasiBerdasarkanAdat from "./data/lingkungan/konservasi-adat-bali/bentuk-konservasi.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 filosofiTriHita from "./data/lingkungan/konservasi-adat-bali/filosofi-tri-hita.json";
|
||||||
import nilaiKonservasiAdat from "./data/lingkungan/konservasi-adat-bali/nilai-konservasi-adat.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";
|
||||||
@@ -56,6 +56,7 @@ import tujuanProgram from "./data/pendidikan/program-pendidikan-anak/tujuan-prog
|
|||||||
import roles from "./data/user/roles.json";
|
import roles from "./data/user/roles.json";
|
||||||
import users from "./data/user/users.json";
|
import users from "./data/user/users.json";
|
||||||
import fileStorage from "./data/file-storage.json";
|
import fileStorage from "./data/file-storage.json";
|
||||||
|
import jenjangPendidikan from "./data/pendidikan/info-sekolah/jenjang-pendidikan.json";
|
||||||
import seedAssets from "./seed_assets";
|
import seedAssets from "./seed_assets";
|
||||||
import { safeSeedUnique } from "./safeseedUnique";
|
import { safeSeedUnique } from "./safeseedUnique";
|
||||||
|
|
||||||
@@ -807,28 +808,34 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
}
|
}
|
||||||
console.log("kategori produk success ...");
|
console.log("kategori produk success ...");
|
||||||
|
|
||||||
for (const p of posisiOrganisasi) {
|
const flattenedPosisiBumdes = posisiOrganisasi.flat();
|
||||||
await prisma.posisiOrganisasi.upsert({
|
|
||||||
where: {
|
// ✅ Urutkan berdasarkan hierarki
|
||||||
id: p.id,
|
const sortedPosisiBumdes = flattenedPosisiBumdes.sort((a, b) => a.hierarki - b.hierarki);
|
||||||
},
|
|
||||||
update: {
|
for (const p of sortedPosisiBumdes) {
|
||||||
nama: p.nama,
|
console.log(`Seeding: ${p.nama} (id: ${p.id}, parent: ${p.parentId})`);
|
||||||
deskripsi: p.deskripsi,
|
|
||||||
hierarki: p.hierarki,
|
if (p.parentId) {
|
||||||
},
|
const parentExists = flattenedPosisi.some((pos) => pos.id === p.parentId);
|
||||||
create: {
|
if (!parentExists) {
|
||||||
id: p.id,
|
console.warn(
|
||||||
nama: p.nama,
|
`⚠️ Parent tidak ditemukan: ${p.parentId} untuk ${p.nama}`
|
||||||
deskripsi: p.deskripsi,
|
);
|
||||||
hierarki: p.hierarki,
|
continue;
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await prisma.posisiOrganisasiBumDes.upsert({
|
||||||
|
where: { id: p.id },
|
||||||
|
update: p,
|
||||||
|
create: p,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log("posisi organisasi success ...");
|
console.log("posisi organisasi berhasil");
|
||||||
|
|
||||||
for (const p of pegawai) {
|
for (const p of pegawai) {
|
||||||
await prisma.pegawai.upsert({
|
await prisma.pegawaiBumDes.upsert({
|
||||||
where: {
|
where: {
|
||||||
id: p.id,
|
id: p.id,
|
||||||
},
|
},
|
||||||
@@ -857,26 +864,6 @@ 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: {
|
||||||
@@ -900,6 +887,30 @@ 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: {
|
||||||
@@ -1154,6 +1165,22 @@ import { safeSeedUnique } from "./safeseedUnique";
|
|||||||
"✅ 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
|
// seed assets
|
||||||
await seedAssets();
|
await seedAssets();
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 378 KiB |
@@ -75,17 +75,18 @@ const berita = proxy({
|
|||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
search: "",
|
||||||
load: async (page = 1, limit = 10, search = "", kategori = "") => {
|
load: async (page = 1, limit = 10, search = "", kategori = "") => {
|
||||||
berita.findMany.loading = true; // ✅ Akses langsung via nama path
|
const startTime = Date.now();
|
||||||
|
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;
|
||||||
if (kategori) query.kategori = kategori;
|
if (kategori) query.kategori = kategori;
|
||||||
|
|
||||||
const res = await ApiFetch.api.desa.berita["find-many"].get({ query });
|
const res = await ApiFetch.api.desa.berita["find-many"].get({ query });
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
if (res.status === 200 && res.data?.success) {
|
||||||
berita.findMany.data = res.data.data ?? [];
|
berita.findMany.data = res.data.data ?? [];
|
||||||
berita.findMany.totalPages = res.data.totalPages ?? 1;
|
berita.findMany.totalPages = res.data.totalPages ?? 1;
|
||||||
@@ -98,9 +99,16 @@ const berita = proxy({
|
|||||||
berita.findMany.data = [];
|
berita.findMany.data = [];
|
||||||
berita.findMany.totalPages = 1;
|
berita.findMany.totalPages = 1;
|
||||||
} finally {
|
} finally {
|
||||||
berita.findMany.loading = false;
|
// pastikan minimal 300ms sebelum loading = false (biar UX smooth)
|
||||||
|
const elapsed = Date.now() - startTime;
|
||||||
|
const minDelay = 300;
|
||||||
|
const delay = elapsed < minDelay ? minDelay - elapsed : 0;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
berita.findMany.loading = false;
|
||||||
|
}, delay);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
findUnique: {
|
findUnique: {
|
||||||
|
|||||||
@@ -1,9 +1,173 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { proxy } from "valtio";
|
|
||||||
import { z } from "zod";
|
|
||||||
import { toast } from "react-toastify";
|
|
||||||
import ApiFetch from "@/lib/api-fetch";
|
import ApiFetch from "@/lib/api-fetch";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
import { proxy } from "valtio";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
const templateForm = z.object({
|
||||||
|
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||||
|
imageId: z.string().min(1, "Gambar wajib dipilih"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultForm = {
|
||||||
|
name: "",
|
||||||
|
imageId: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
type 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"),
|
||||||
@@ -30,9 +194,7 @@ const posisiOrganisasi = proxy({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
const res = await ApiFetch.api.ekonomi['struktur-organisasi']['posisi-organisasi']['create'].post(this.form);
|
||||||
"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();
|
||||||
@@ -52,6 +214,29 @@ 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 },
|
||||||
@@ -165,17 +350,17 @@ const posisiOrganisasi = proxy({
|
|||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
search: "",
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
load: async (page = 1, limit?: number, search = "") => {
|
||||||
posisiOrganisasi.findMany.loading = true; // ✅ Akses langsung via nama path
|
const appliedLimit = limit ?? 10;
|
||||||
posisiOrganisasi.findMany.page = page;
|
posisiOrganisasi.findMany.page = page;
|
||||||
posisiOrganisasi.findMany.search = search;
|
posisiOrganisasi.findMany.search = search;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query: any = { page, limit };
|
const query: any = { page, limit: appliedLimit };
|
||||||
if (search) query.search = search;
|
if (search) query.search = search;
|
||||||
|
|
||||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"]["posisi-organisasi"]["find-many"].get({ query });
|
const res = await ApiFetch.api.ekonomi['struktur-organisasi']['posisi-organisasi']['find-many'].get({ query });
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
if (res.status === 200 && res.data?.success) {
|
||||||
posisiOrganisasi.findMany.data = res.data.data ?? [];
|
posisiOrganisasi.findMany.data = res.data.data ?? [];
|
||||||
posisiOrganisasi.findMany.totalPages = res.data.totalPages ?? 1;
|
posisiOrganisasi.findMany.totalPages = res.data.totalPages ?? 1;
|
||||||
@@ -192,7 +377,42 @@ const posisiOrganisasi = proxy({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
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) {
|
||||||
|
console.error("Error loading posisiOrganisasi:", error);
|
||||||
|
posisiOrganisasi.findManyAll.data = [];
|
||||||
|
} finally {
|
||||||
|
posisiOrganisasi.findManyAll.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
delete: {
|
delete: {
|
||||||
loading: false,
|
loading: false,
|
||||||
async byId(id: string) {
|
async byId(id: string) {
|
||||||
@@ -231,12 +451,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().optional(),
|
gelarAkademik: z.string().min(1, "Gelar Akademik wajib diisi"),
|
||||||
imageId: z.string().nullable().optional(),
|
imageId: z.string().min(1, "Gambar wajib dipilih"),
|
||||||
tanggalMasuk: z.string().optional(), // ISO format
|
tanggalMasuk: z.string().min(1, "Tanggal masuk wajib diisi"), // ISO format
|
||||||
email: z.string().email("Email tidak valid").optional(),
|
email: z.string().email("Email tidak valid").optional(),
|
||||||
telepon: z.string().optional(),
|
telepon: z.string().min(1, "Telepom wajib diisi"),
|
||||||
alamat: z.string().optional(),
|
alamat: z.string().min(1, "Alamat wajib diisi"),
|
||||||
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),
|
||||||
});
|
});
|
||||||
@@ -267,9 +487,9 @@ const pegawai = proxy({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
pegawai.create.loading = true;
|
pegawai.create.loading = true;
|
||||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
const res = await ApiFetch.api.ekonomi['struktur-organisasi'].pegawai['create'].post(
|
||||||
"pegawai"
|
pegawai.create.form
|
||||||
]["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();
|
||||||
@@ -286,45 +506,56 @@ const pegawai = proxy({
|
|||||||
},
|
},
|
||||||
|
|
||||||
// In struktur-organisasi.ts
|
// In struktur-organisasi.ts
|
||||||
findMany: {
|
findMany: {
|
||||||
data: null as any[] | null,
|
data: null as
|
||||||
page: 1,
|
| Prisma.PegawaiBumDesGetPayload<{
|
||||||
totalPages: 1,
|
include: {
|
||||||
total: 0,
|
image: true;
|
||||||
loading: false,
|
posisi: true;
|
||||||
load: async (page = 1, limit = 10) => { // Change to arrow function
|
};
|
||||||
pegawai.findMany.loading = true; // Use the full path to access the property
|
}>[]
|
||||||
pegawai.findMany.page = page;
|
| null,
|
||||||
try {
|
page: 1,
|
||||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
totalPages: 1,
|
||||||
"pegawai"
|
total: 0,
|
||||||
]["find-many"].get({
|
loading: false,
|
||||||
query: { page, limit },
|
search: "",
|
||||||
});
|
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;
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
const res = await ApiFetch.api.ekonomi['struktur-organisasi'].pegawai['find-many'].get({
|
||||||
pegawai.findMany.data = res.data.data || [];
|
query,
|
||||||
pegawai.findMany.total = res.data.total || 0;
|
});
|
||||||
pegawai.findMany.totalPages = res.data.totalPages || 1;
|
|
||||||
} else {
|
if (res.status === 200 && res.data?.success) {
|
||||||
console.error("Failed to load pegawai:", res.data?.message);
|
pegawai.findMany.data = res.data.data || [];
|
||||||
|
pegawai.findMany.total = res.data.total || 0;
|
||||||
|
pegawai.findMany.totalPages = res.data.totalPages || 1;
|
||||||
|
} else {
|
||||||
|
console.error("Failed to load pegawai:", res.data?.message);
|
||||||
|
pegawai.findMany.data = [];
|
||||||
|
pegawai.findMany.total = 0;
|
||||||
|
pegawai.findMany.totalPages = 1;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading pegawai:", error);
|
||||||
pegawai.findMany.data = [];
|
pegawai.findMany.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.PegawaiGetPayload<{
|
| (Prisma.PegawaiBumDesGetPayload<{
|
||||||
include: { posisi: true; image: true };
|
include: { posisi: true; image: true };
|
||||||
}> & { isActive: boolean })
|
}> & { isActive: boolean })
|
||||||
| null,
|
| null,
|
||||||
@@ -350,12 +581,9 @@ findMany: {
|
|||||||
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(
|
const res = await fetch(`/api/ekonomi/struktur-organisasi/pegawai/del/${id}`, {
|
||||||
`/api/ekonomi/struktur-organisasi/pegawai/del/${id}`,
|
method: "DELETE",
|
||||||
{
|
});
|
||||||
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");
|
||||||
@@ -372,6 +600,31 @@ findMany: {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
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 },
|
||||||
@@ -384,15 +637,12 @@ findMany: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(`/api/ekonomi/struktur-organisasi/pegawai/${id}`, {
|
||||||
`/api/ekonomi/struktur-organisasi/pegawai/${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}`);
|
||||||
@@ -503,299 +753,10 @@ findMany: {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Schema Zod untuk form validasi
|
const stateStrukturBumDes = proxy({
|
||||||
const templateHubunganOrganisasiForm = z.object({
|
stateStruktur,
|
||||||
atasanId: z.string().min(1, "Atasan wajib dipilih"),
|
|
||||||
bawahanId: z.string().min(1, "Bawahan wajib dipilih"),
|
|
||||||
tipe: z.string().optional(),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Default form state
|
|
||||||
const defaultHubunganOrganisasiForm = {
|
|
||||||
atasanId: "",
|
|
||||||
bawahanId: "",
|
|
||||||
tipe: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
// ====================== STATE ===========================
|
|
||||||
const hubunganOrganisasi = proxy({
|
|
||||||
create: {
|
|
||||||
form: { ...defaultHubunganOrganisasiForm },
|
|
||||||
loading: false,
|
|
||||||
async create() {
|
|
||||||
const cek = templateHubunganOrganisasiForm.safeParse(
|
|
||||||
hubunganOrganisasi.create.form
|
|
||||||
);
|
|
||||||
if (!cek.success) {
|
|
||||||
const err = `[${cek.error.issues
|
|
||||||
.map((v) => `${v.path.join(".")}: ${v.message}`)
|
|
||||||
.join("\n")}]`;
|
|
||||||
return toast.error(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
hubunganOrganisasi.create.loading = true;
|
|
||||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
|
||||||
"hubungan-organisasi"
|
|
||||||
]["create"].post(hubunganOrganisasi.create.form);
|
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
|
||||||
hubunganOrganisasi.findMany.load();
|
|
||||||
return toast.success("Berhasil menambahkan hubungan organisasi");
|
|
||||||
} else {
|
|
||||||
return toast.error(res.data?.message || "Gagal menambahkan data");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Gagal create:", error);
|
|
||||||
toast.error("Terjadi kesalahan saat menambahkan");
|
|
||||||
} finally {
|
|
||||||
hubunganOrganisasi.create.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
findMany: {
|
|
||||||
data: null as Array<{
|
|
||||||
id: string;
|
|
||||||
atasanId: string;
|
|
||||||
bawahanId: string;
|
|
||||||
tipe?: string | null;
|
|
||||||
atasan: {
|
|
||||||
id: string;
|
|
||||||
namaLengkap: string;
|
|
||||||
gelarAkademik: string | null;
|
|
||||||
imageId: string | null;
|
|
||||||
tanggalMasuk: Date | null;
|
|
||||||
email: string | null;
|
|
||||||
telepon: string | null;
|
|
||||||
alamat: string | null;
|
|
||||||
posisiId: string;
|
|
||||||
isActive: boolean;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
};
|
|
||||||
bawahan: {
|
|
||||||
id: string;
|
|
||||||
namaLengkap: string;
|
|
||||||
gelarAkademik: string | null;
|
|
||||||
imageId: string | null;
|
|
||||||
tanggalMasuk: Date | null;
|
|
||||||
email: string | null;
|
|
||||||
telepon: string | null;
|
|
||||||
alamat: string | null;
|
|
||||||
posisiId: string;
|
|
||||||
isActive: boolean;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
};
|
|
||||||
}> | null,
|
|
||||||
|
|
||||||
async load() {
|
|
||||||
try {
|
|
||||||
const res = await ApiFetch.api.ekonomi["struktur-organisasi"][
|
|
||||||
"hubungan-organisasi"
|
|
||||||
]["find-many"].get();
|
|
||||||
|
|
||||||
if (res.status === 200) {
|
|
||||||
hubunganOrganisasi.findMany.data = (res.data?.data ?? []).map(
|
|
||||||
(item: any) => ({
|
|
||||||
...item,
|
|
||||||
atasan: item.atasan
|
|
||||||
? {
|
|
||||||
...item.atasan,
|
|
||||||
isActive: item.atasan.isActive ?? item.atasan.aktif ?? true,
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
bawahan: item.bawahan
|
|
||||||
? {
|
|
||||||
...item.bawahan,
|
|
||||||
isActive:
|
|
||||||
item.bawahan.isActive ?? item.bawahan.aktif ?? true,
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
hubunganOrganisasi.findMany.data = [];
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Fetch list error:", error);
|
|
||||||
toast.error("Gagal memuat data hubungan organisasi");
|
|
||||||
hubunganOrganisasi.findMany.data = [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
findUnique: {
|
|
||||||
data: null as {
|
|
||||||
id: string;
|
|
||||||
atasanId: string;
|
|
||||||
bawahanId: string;
|
|
||||||
tipe?: string | null;
|
|
||||||
atasan?: {
|
|
||||||
id: string;
|
|
||||||
namaLengkap: string;
|
|
||||||
gelarAkademik: string | null;
|
|
||||||
imageId: string;
|
|
||||||
tanggalMasuk: Date | null;
|
|
||||||
email: string | null;
|
|
||||||
telepon: string | null;
|
|
||||||
alamat: string | null;
|
|
||||||
posisiId: string;
|
|
||||||
aktif: boolean;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
};
|
|
||||||
bawahan?: {
|
|
||||||
id: string;
|
|
||||||
namaLengkap: string;
|
|
||||||
gelarAkademik: string | null;
|
|
||||||
imageId: string;
|
|
||||||
tanggalMasuk: Date | null;
|
|
||||||
email: string | null;
|
|
||||||
telepon: string | null;
|
|
||||||
alamat: string | null;
|
|
||||||
posisiId: string;
|
|
||||||
aktif: boolean;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
};
|
|
||||||
} | null,
|
|
||||||
|
|
||||||
async load(id: string) {
|
|
||||||
try {
|
|
||||||
const res = await fetch(
|
|
||||||
`/api/ekonomi/struktur-organisasi/hubungan-organisasi/${id}`
|
|
||||||
);
|
|
||||||
const result = await res.json();
|
|
||||||
|
|
||||||
if (res.ok && result?.success) {
|
|
||||||
hubunganOrganisasi.findUnique.data = result.data;
|
|
||||||
} else {
|
|
||||||
hubunganOrganisasi.findUnique.data = null;
|
|
||||||
toast.error(result?.message || "Gagal mengambil data");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Find unique error:", error);
|
|
||||||
hubunganOrganisasi.findUnique.data = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
edit: {
|
|
||||||
id: "",
|
|
||||||
form: { ...defaultHubunganOrganisasiForm },
|
|
||||||
loading: false,
|
|
||||||
|
|
||||||
async load(id: string) {
|
|
||||||
if (!id) return toast.warn("ID tidak valid");
|
|
||||||
|
|
||||||
try {
|
|
||||||
const res = await fetch(
|
|
||||||
`/api/ekonomi/struktur-organisasi/hubungan-organisasi/${id}`
|
|
||||||
);
|
|
||||||
const result = await res.json();
|
|
||||||
|
|
||||||
if (res.ok && result?.success) {
|
|
||||||
const data = result.data;
|
|
||||||
this.id = data.id;
|
|
||||||
this.form = {
|
|
||||||
atasanId: data.atasanId,
|
|
||||||
bawahanId: data.bawahanId,
|
|
||||||
tipe: data.tipe || "",
|
|
||||||
};
|
|
||||||
return data;
|
|
||||||
} else {
|
|
||||||
throw new Error(result?.message || "Gagal memuat data");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error loading:", error);
|
|
||||||
toast.error(
|
|
||||||
error instanceof Error ? error.message : "Gagal memuat data"
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async update() {
|
|
||||||
const cek = templateHubunganOrganisasiForm.safeParse(this.form);
|
|
||||||
if (!cek.success) {
|
|
||||||
const err = `[${cek.error.issues
|
|
||||||
.map((v) => `${v.path.join(".")}: ${v.message}`)
|
|
||||||
.join("\n")}]`;
|
|
||||||
return toast.error(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.loading = true;
|
|
||||||
const res = await fetch(
|
|
||||||
`/api/ekonomi/struktur-organisasi/hubungan-organisasi/${this.id}`,
|
|
||||||
{
|
|
||||||
method: "PUT",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(this.form),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = await res.json();
|
|
||||||
if (res.ok && result.success) {
|
|
||||||
await hubunganOrganisasi.findMany.load();
|
|
||||||
toast.success("Berhasil mengupdate hubungan organisasi");
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
throw new Error(result?.message || "Gagal mengupdate");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Update error:", error);
|
|
||||||
toast.error(error instanceof Error ? error.message : "Gagal update");
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
hubunganOrganisasi.edit.id = "";
|
|
||||||
hubunganOrganisasi.edit.form = { ...defaultHubunganOrganisasiForm };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
delete: {
|
|
||||||
loading: false,
|
|
||||||
async byId(id: string) {
|
|
||||||
if (!id) return toast.warn("ID tidak valid");
|
|
||||||
|
|
||||||
try {
|
|
||||||
hubunganOrganisasi.delete.loading = true;
|
|
||||||
const res = await fetch(
|
|
||||||
`/api/ekonomi/struktur-organisasi/hubungan-organisasi/del/${id}`,
|
|
||||||
{
|
|
||||||
method: "DELETE",
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = await res.json();
|
|
||||||
if (res.ok && result?.success) {
|
|
||||||
toast.success("Hubungan organisasi berhasil dihapus");
|
|
||||||
hubunganOrganisasi.findMany.load();
|
|
||||||
} else {
|
|
||||||
toast.error(result?.message || "Gagal menghapus hubungan organisasi");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Delete error:", error);
|
|
||||||
toast.error("Terjadi kesalahan saat menghapus");
|
|
||||||
} finally {
|
|
||||||
hubunganOrganisasi.delete.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const strukturorganisasiState = proxy({
|
|
||||||
posisiOrganisasi,
|
posisiOrganisasi,
|
||||||
pegawai,
|
pegawai,
|
||||||
hubunganOrganisasi,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default strukturorganisasiState;
|
export default stateStrukturBumDes;
|
||||||
|
|||||||
@@ -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(1, "Nama minimal 1 karakter"),
|
name: z.string().min(5, "Nama minimal 5 karakter"),
|
||||||
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
|
deskripsi: z.string().min(5, "Deskripsi minimal 5 karakter"),
|
||||||
slug: z.string().min(1, "Deskripsi singkat minimal 1 karakter"),
|
slug: z.string().min(5, "Deskripsi singkat minimal 5 karakter"),
|
||||||
icon: z.string().min(1, "Icon minimal 1 karakter"),
|
icon: z.string().min(1, "Icon minimal 1 karakter"),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -29,26 +29,33 @@ 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`;
|
||||||
return toast.error(err);
|
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();
|
||||||
return toast.success("success create");
|
toast.success("success create");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
console.log(res);
|
|
||||||
return toast.error("failed create");
|
toast.error("failed create");
|
||||||
|
return false;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log((error as Error).message);
|
console.error((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,
|
||||||
|
|||||||
@@ -93,6 +93,34 @@ const sdgsDesa = proxy({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
findManyAll: {
|
||||||
|
data: null as any[] | null,
|
||||||
|
loading: false,
|
||||||
|
load: async () => { // Change to arrow function
|
||||||
|
sdgsDesa.findManyAll.loading = true; // Use the full path to access the property
|
||||||
|
try {
|
||||||
|
const query: any = {};
|
||||||
|
|
||||||
|
const res = await ApiFetch.api.landingpage.sdgsdesa[
|
||||||
|
"findManyAll"
|
||||||
|
].get({
|
||||||
|
query,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.status === 200 && res.data?.success) {
|
||||||
|
sdgsDesa.findManyAll.data = res.data.data || [];
|
||||||
|
} else {
|
||||||
|
console.error("Failed to load media sosial:", res.data?.message);
|
||||||
|
sdgsDesa.findManyAll.data = [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading media sosial:", error);
|
||||||
|
sdgsDesa.findManyAll.data = [];
|
||||||
|
} finally {
|
||||||
|
sdgsDesa.findManyAll.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
findUnique: {
|
findUnique: {
|
||||||
data: null as Prisma.SdgsDesaGetPayload<{
|
data: null as Prisma.SdgsDesaGetPayload<{
|
||||||
include: {
|
include: {
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ const keunggulanProgram = proxy({
|
|||||||
].post(keunggulanProgram.create.form);
|
].post(keunggulanProgram.create.form);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
keunggulanProgram.findMany.load();
|
keunggulanProgram.findMany.load();
|
||||||
return toast.success("Data Berhasil Dibuat, Silahkan Menunggu Konfirmasi dari Admin di WhatsApp");
|
return toast.success("Data Berhasil Dibuat");
|
||||||
}
|
}
|
||||||
console.log(res);
|
console.log(res);
|
||||||
return toast.error("failed create");
|
return toast.error("failed create");
|
||||||
|
|||||||
@@ -55,46 +55,95 @@ const dataPerpustakaan = proxy({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
findMany: {
|
findMany: {
|
||||||
data: null as
|
data: null as
|
||||||
| Prisma.DataPerpustakaanGetPayload<{
|
| Prisma.DataPerpustakaanGetPayload<{
|
||||||
include: {
|
include: {
|
||||||
image: true;
|
image: true;
|
||||||
kategori: true;
|
kategori: true;
|
||||||
};
|
};
|
||||||
}>[]
|
}>[]
|
||||||
| null,
|
| null,
|
||||||
page: 1,
|
page: 1,
|
||||||
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 = "") => {
|
||||||
dataPerpustakaan.findMany.loading = true; // ✅ Akses langsung via nama path
|
const startTime = Date.now();
|
||||||
dataPerpustakaan.findMany.page = page;
|
dataPerpustakaan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||||
dataPerpustakaan.findMany.search = search;
|
dataPerpustakaan.findMany.page = page;
|
||||||
|
dataPerpustakaan.findMany.search = search;
|
||||||
try {
|
|
||||||
const query: any = { page, limit };
|
try {
|
||||||
if (search) query.search = search;
|
const query: any = { page, limit };
|
||||||
if (kategori) query.kategori = kategori;
|
if (search) query.search = search;
|
||||||
|
if (kategori) query.kategori = kategori;
|
||||||
const res = await ApiFetch.api.pendidikan.perpustakaandigital.dataperpustakaan["findMany"].get({ query });
|
|
||||||
|
const res =
|
||||||
if (res.status === 200 && res.data?.success) {
|
await ApiFetch.api.pendidikan.perpustakaandigital.dataperpustakaan[
|
||||||
dataPerpustakaan.findMany.data = res.data.data ?? [];
|
"findMany"
|
||||||
dataPerpustakaan.findMany.totalPages = res.data.totalPages ?? 1;
|
].get({ query });
|
||||||
} else {
|
|
||||||
dataPerpustakaan.findMany.data = [];
|
if (res.status === 200 && res.data?.success) {
|
||||||
dataPerpustakaan.findMany.totalPages = 1;
|
dataPerpustakaan.findMany.data = res.data.data ?? [];
|
||||||
}
|
dataPerpustakaan.findMany.totalPages = res.data.totalPages ?? 1;
|
||||||
} catch (err) {
|
} else {
|
||||||
console.error("Gagal fetch data perpustakaan paginated:", err);
|
|
||||||
dataPerpustakaan.findMany.data = [];
|
dataPerpustakaan.findMany.data = [];
|
||||||
dataPerpustakaan.findMany.totalPages = 1;
|
dataPerpustakaan.findMany.totalPages = 1;
|
||||||
} finally {
|
|
||||||
dataPerpustakaan.findMany.loading = false;
|
|
||||||
}
|
}
|
||||||
},
|
} catch (err) {
|
||||||
|
console.error("Gagal fetch data perpustakaan paginated:", err);
|
||||||
|
dataPerpustakaan.findMany.data = [];
|
||||||
|
dataPerpustakaan.findMany.totalPages = 1;
|
||||||
|
} finally {
|
||||||
|
// pastikan minimal 300ms sebelum loading = false (biar UX smooth)
|
||||||
|
const elapsed = Date.now() - startTime;
|
||||||
|
const minDelay = 300;
|
||||||
|
const delay = elapsed < minDelay ? minDelay - elapsed : 0;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
dataPerpustakaan.findMany.loading = false;
|
||||||
|
}, delay);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
findManyAll: {
|
||||||
|
data: null as
|
||||||
|
| Prisma.DataPerpustakaanGetPayload<{
|
||||||
|
include: {
|
||||||
|
image: true;
|
||||||
|
kategori: true;
|
||||||
|
};
|
||||||
|
}>[]
|
||||||
|
| null,
|
||||||
|
loading: false,
|
||||||
|
search: "",
|
||||||
|
load: async (search = "", kategori = "") => {
|
||||||
|
dataPerpustakaan.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||||
|
dataPerpustakaan.findMany.search = search;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const query: any = {};
|
||||||
|
if (search) query.search = search;
|
||||||
|
if (kategori) query.kategori = kategori;
|
||||||
|
|
||||||
|
const res =
|
||||||
|
await ApiFetch.api.pendidikan.perpustakaandigital.dataperpustakaan[
|
||||||
|
"findManyAll"
|
||||||
|
].get({ query });
|
||||||
|
|
||||||
|
if (res.status === 200 && res.data?.success) {
|
||||||
|
dataPerpustakaan.findManyAll.data = res.data.data ?? [];
|
||||||
|
} else {
|
||||||
|
dataPerpustakaan.findManyAll.data = [];
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Gagal fetch data perpustakaan paginated:", err);
|
||||||
|
dataPerpustakaan.findManyAll.data = [];
|
||||||
|
} finally {
|
||||||
|
dataPerpustakaan.findManyAll.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
findUnique: {
|
findUnique: {
|
||||||
data: null as Prisma.DataPerpustakaanGetPayload<{
|
data: null as Prisma.DataPerpustakaanGetPayload<{
|
||||||
include: {
|
include: {
|
||||||
@@ -321,17 +370,20 @@ const kategoriBuku = proxy({
|
|||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
loading: false,
|
loading: false,
|
||||||
search: "",
|
search: "",
|
||||||
load: async (page = 1, limit = 10, search = "") => {
|
load: async (page = 1, limit = 10, search = "") => {
|
||||||
kategoriBuku.findMany.loading = true; // ✅ Akses langsung via nama path
|
kategoriBuku.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||||
kategoriBuku.findMany.page = page;
|
kategoriBuku.findMany.page = page;
|
||||||
kategoriBuku.findMany.search = search;
|
kategoriBuku.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;
|
||||||
|
|
||||||
const res = await ApiFetch.api.pendidikan.perpustakaandigital.kategoribuku["findMany"].get({ query });
|
const res =
|
||||||
|
await ApiFetch.api.pendidikan.perpustakaandigital.kategoribuku[
|
||||||
|
"findMany"
|
||||||
|
].get({ query });
|
||||||
|
|
||||||
if (res.status === 200 && res.data?.success) {
|
if (res.status === 200 && res.data?.success) {
|
||||||
kategoriBuku.findMany.data = res.data.data ?? [];
|
kategoriBuku.findMany.data = res.data.data ?? [];
|
||||||
kategoriBuku.findMany.totalPages = res.data.totalPages ?? 1;
|
kategoriBuku.findMany.totalPages = res.data.totalPages ?? 1;
|
||||||
@@ -514,9 +566,319 @@ const kategoriBuku = proxy({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const templatePeminjamanBuku = z.object({
|
||||||
|
nama: z.string().min(1, "Nama harus diisi"),
|
||||||
|
noTelp: z.string().min(1, "No Telp harus diisi"),
|
||||||
|
alamat: z.string().min(1, "Alamat harus diisi"),
|
||||||
|
bukuId: z.string().min(1, "Buku ID harus diisi"),
|
||||||
|
tanggalPinjam: z.string().min(1, "Tanggal Pinjam harus diisi"),
|
||||||
|
batasKembali: z.string().min(1, "Batas Kembali harus diisi"),
|
||||||
|
tanggalKembali: z.string().min(1, "Tanggal Kembali harus diisi"),
|
||||||
|
catatan: z.string().min(1, "Catatan harus diisi"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultPeminjamanBuku = {
|
||||||
|
nama: "",
|
||||||
|
noTelp: "",
|
||||||
|
alamat: "",
|
||||||
|
bukuId: "",
|
||||||
|
tanggalPinjam: "",
|
||||||
|
batasKembali: "",
|
||||||
|
tanggalKembali: "",
|
||||||
|
catatan: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
interface FormEditData {
|
||||||
|
nama: string;
|
||||||
|
noTelp: string;
|
||||||
|
alamat: string;
|
||||||
|
bukuId: string;
|
||||||
|
buku?: {
|
||||||
|
id: string;
|
||||||
|
judul: string;
|
||||||
|
};
|
||||||
|
tanggalPinjam: string;
|
||||||
|
batasKembali: string;
|
||||||
|
tanggalKembali: string;
|
||||||
|
catatan: string;
|
||||||
|
status: "Dipinjam" | "Dikembalikan" | "Terlambat" | "Dibatalkan";
|
||||||
|
}
|
||||||
|
|
||||||
|
const editForm: FormEditData = {
|
||||||
|
nama: "",
|
||||||
|
noTelp: "",
|
||||||
|
alamat: "",
|
||||||
|
bukuId: "",
|
||||||
|
tanggalPinjam: "",
|
||||||
|
batasKembali: "",
|
||||||
|
tanggalKembali: "",
|
||||||
|
catatan: "",
|
||||||
|
status: "Dipinjam",
|
||||||
|
};
|
||||||
|
|
||||||
|
const peminjamanBuku = proxy({
|
||||||
|
create: {
|
||||||
|
form: { ...defaultPeminjamanBuku },
|
||||||
|
loading: false,
|
||||||
|
async create() {
|
||||||
|
const cek = templatePeminjamanBuku.safeParse(peminjamanBuku.create.form);
|
||||||
|
if (!cek.success) {
|
||||||
|
const err = `[${cek.error.issues
|
||||||
|
.map((v) => `${v.path.join(".")}`)
|
||||||
|
.join("\n")}] required`;
|
||||||
|
return toast.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
peminjamanBuku.create.loading = true;
|
||||||
|
const res =
|
||||||
|
await ApiFetch.api.pendidikan.perpustakaandigital.peminjamanbuku[
|
||||||
|
"create"
|
||||||
|
].post(peminjamanBuku.create.form);
|
||||||
|
if (res.status === 200) {
|
||||||
|
peminjamanBuku.findMany.load();
|
||||||
|
return toast.success("Data Peminjaman Buku Berhasil Dibuat");
|
||||||
|
}
|
||||||
|
console.log(res);
|
||||||
|
return toast.error("failed create");
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
return toast.error("failed create");
|
||||||
|
} finally {
|
||||||
|
peminjamanBuku.create.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
findMany: {
|
||||||
|
data: [] as Prisma.PeminjamanBukuGetPayload<{
|
||||||
|
include: {
|
||||||
|
buku: true;
|
||||||
|
};
|
||||||
|
}>[],
|
||||||
|
page: 1,
|
||||||
|
totalPages: 1,
|
||||||
|
loading: false,
|
||||||
|
search: "",
|
||||||
|
load: async (page = 1, limit = 10, search = "") => {
|
||||||
|
peminjamanBuku.findMany.loading = true; // ✅ Akses langsung via nama path
|
||||||
|
peminjamanBuku.findMany.page = page;
|
||||||
|
peminjamanBuku.findMany.search = search;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const query: any = { page, limit };
|
||||||
|
if (search) query.search = search;
|
||||||
|
|
||||||
|
const res =
|
||||||
|
await ApiFetch.api.pendidikan.perpustakaandigital.peminjamanbuku[
|
||||||
|
"findMany"
|
||||||
|
].get({ query });
|
||||||
|
|
||||||
|
if (res.status === 200 && res.data?.success) {
|
||||||
|
peminjamanBuku.findMany.data = res.data.data ?? [];
|
||||||
|
peminjamanBuku.findMany.totalPages = res.data.totalPages ?? 1;
|
||||||
|
} else {
|
||||||
|
peminjamanBuku.findMany.data = [];
|
||||||
|
peminjamanBuku.findMany.totalPages = 1;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Gagal fetch data peminjaman buku paginated:", err);
|
||||||
|
peminjamanBuku.findMany.data = [];
|
||||||
|
peminjamanBuku.findMany.totalPages = 1;
|
||||||
|
} finally {
|
||||||
|
peminjamanBuku.findMany.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
findUnique: {
|
||||||
|
data: null as Prisma.PeminjamanBukuGetPayload<{
|
||||||
|
include: {
|
||||||
|
buku: true;
|
||||||
|
};
|
||||||
|
}> | null,
|
||||||
|
loading: false,
|
||||||
|
async load(id: string) {
|
||||||
|
try {
|
||||||
|
const res = await fetch(
|
||||||
|
`/api/pendidikan/perpustakaandigital/peminjamanbuku/${id}`
|
||||||
|
);
|
||||||
|
if (res.ok) {
|
||||||
|
const data = await res.json();
|
||||||
|
peminjamanBuku.findUnique.data = data.data ?? null;
|
||||||
|
} else {
|
||||||
|
console.error("Failed to fetch data", res.status, res.statusText);
|
||||||
|
peminjamanBuku.findUnique.data = null;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching data:", error);
|
||||||
|
peminjamanBuku.findUnique.data = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
loading: false,
|
||||||
|
async delete(id: string) {
|
||||||
|
if (!id) return toast.warn("ID tidak valid");
|
||||||
|
|
||||||
|
try {
|
||||||
|
peminjamanBuku.delete.loading = true;
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/pendidikan/perpustakaandigital/peminjamanbuku/del/${id}`,
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (response.ok && result?.success) {
|
||||||
|
toast.success(
|
||||||
|
result.message || "Data Peminjaman Buku berhasil dihapus"
|
||||||
|
);
|
||||||
|
await peminjamanBuku.findMany.load(); // refresh list
|
||||||
|
} else {
|
||||||
|
toast.error(
|
||||||
|
result?.message || "Gagal menghapus Data Peminjaman Buku"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Gagal delete:", error);
|
||||||
|
toast.error("Terjadi kesalahan saat menghapus Data Peminjaman Buku");
|
||||||
|
} finally {
|
||||||
|
peminjamanBuku.delete.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
id: "",
|
||||||
|
form: { ...editForm },
|
||||||
|
loading: false,
|
||||||
|
async load(id: string) {
|
||||||
|
if (!id) {
|
||||||
|
toast.warn("ID tidak valid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/pendidikan/perpustakaandigital/peminjamanbuku/${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,
|
||||||
|
noTelp: data.noTelp,
|
||||||
|
alamat: data.alamat,
|
||||||
|
bukuId: data.bukuId,
|
||||||
|
tanggalPinjam: data.tanggalPinjam,
|
||||||
|
batasKembali: data.batasKembali,
|
||||||
|
tanggalKembali: data.tanggalKembali,
|
||||||
|
catatan: data.catatan,
|
||||||
|
status: data.status,
|
||||||
|
};
|
||||||
|
return data; // Return the loaded data
|
||||||
|
} else {
|
||||||
|
throw new Error(result?.message || "Gagal memuat data");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading peminjaman buku:", error);
|
||||||
|
toast.error(
|
||||||
|
error instanceof Error ? error.message : "Gagal memuat data"
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async update() {
|
||||||
|
const cek = templatePeminjamanBuku.safeParse(peminjamanBuku.update.form);
|
||||||
|
if (!cek.success) {
|
||||||
|
const err = `[${cek.error.issues
|
||||||
|
.map((v) => `${v.path.join(".")}`)
|
||||||
|
.join("\n")}] required`;
|
||||||
|
toast.error(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
peminjamanBuku.update.loading = true;
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/pendidikan/perpustakaandigital/peminjamanbuku/${this.id}`,
|
||||||
|
{
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
nama: this.form.nama,
|
||||||
|
noTelp: this.form.noTelp,
|
||||||
|
alamat: this.form.alamat,
|
||||||
|
bukuId: this.form.bukuId,
|
||||||
|
tanggalPinjam: this.form.tanggalPinjam,
|
||||||
|
batasKembali: this.form.batasKembali,
|
||||||
|
tanggalKembali: this.form.tanggalKembali,
|
||||||
|
catatan: this.form.catatan,
|
||||||
|
status: this.form.status,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorData = await response.json().catch(() => ({}));
|
||||||
|
throw new Error(
|
||||||
|
errorData.message || `HTTP error! status: ${response.status}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
toast.success("Berhasil update data peminjaman buku");
|
||||||
|
await peminjamanBuku.findMany.load(); // refresh list
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
result.message || "Gagal update data peminjaman buku"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating data peminjaman buku:", error);
|
||||||
|
toast.error(
|
||||||
|
error instanceof Error
|
||||||
|
? error.message
|
||||||
|
: "Terjadi kesalahan saat update data peminjaman buku"
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
peminjamanBuku.update.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
reset() {
|
||||||
|
peminjamanBuku.update.id = "";
|
||||||
|
peminjamanBuku.update.form = { ...editForm };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const perpustakaanDigitalState = proxy({
|
const perpustakaanDigitalState = proxy({
|
||||||
dataPerpustakaan,
|
dataPerpustakaan,
|
||||||
kategoriBuku,
|
kategoriBuku,
|
||||||
|
peminjamanBuku,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default perpustakaanDigitalState;
|
export default perpustakaanDigitalState;
|
||||||
|
|||||||
@@ -561,9 +561,48 @@ const pegawai = proxy({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
findManyAll: {
|
||||||
|
data: null as
|
||||||
|
| Prisma.PegawaiPPIDGetPayload<{
|
||||||
|
include: {
|
||||||
|
image: true;
|
||||||
|
posisi: true;
|
||||||
|
};
|
||||||
|
}>[]
|
||||||
|
| null,
|
||||||
|
loading: false,
|
||||||
|
search: "",
|
||||||
|
load: async (search = "") => {
|
||||||
|
// Change to arrow function
|
||||||
|
pegawai.findManyAll.loading = true; // Use the full path to access the property
|
||||||
|
pegawai.findManyAll.search = search;
|
||||||
|
try {
|
||||||
|
const query: any = { search };
|
||||||
|
if (search) query.search = search;
|
||||||
|
|
||||||
|
const res = await ApiFetch.api.ppid.strukturppid.pegawai[
|
||||||
|
"find-many-all"
|
||||||
|
].get({
|
||||||
|
query,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.status === 200 && res.data?.success) {
|
||||||
|
pegawai.findManyAll.data = res.data.data || [];
|
||||||
|
} else {
|
||||||
|
console.error("Failed to load pegawai:", res.data?.message);
|
||||||
|
pegawai.findManyAll.data = [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading pegawai:", error);
|
||||||
|
pegawai.findManyAll.data = [];
|
||||||
|
} finally {
|
||||||
|
pegawai.findManyAll.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
findUnique: {
|
findUnique: {
|
||||||
data: null as
|
data: null as
|
||||||
| (Prisma.PegawaiGetPayload<{
|
| (Prisma.PegawaiPPIDGetPayload<{
|
||||||
include: { posisi: true; image: true };
|
include: { posisi: true; image: true };
|
||||||
}> & { isActive: boolean })
|
}> & { isActive: boolean })
|
||||||
| null,
|
| null,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||||
|
import { IconBuildingStore, IconFileText, IconSparkles, IconUsers, IconUsersPlus } from '@tabler/icons-react';
|
||||||
import { usePathname, useRouter } from 'next/navigation';
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { IconFileText, IconBuildingStore, IconSparkles, IconUsers, IconUsersPlus } from '@tabler/icons-react';
|
|
||||||
|
|
||||||
function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -14,36 +14,31 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
|||||||
label: "Pelayanan Surat Keterangan",
|
label: "Pelayanan Surat Keterangan",
|
||||||
value: "pelayanansuratketerangan",
|
value: "pelayanansuratketerangan",
|
||||||
href: "/admin/desa/layanan/pelayanan_surat_keterangan",
|
href: "/admin/desa/layanan/pelayanan_surat_keterangan",
|
||||||
icon: <IconFileText size={18} stroke={1.8} />,
|
icon: <IconFileText size={18} stroke={1.8} />
|
||||||
tooltip: "Layanan terkait surat keterangan resmi desa"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Pelayanan Perizinan Berusaha",
|
label: "Pelayanan Perizinan Berusaha",
|
||||||
value: "pelayananperizinanusaha",
|
value: "pelayananperizinanusaha",
|
||||||
href: "/admin/desa/layanan/pelayanan_perizinan_berusaha",
|
href: "/admin/desa/layanan/pelayanan_perizinan_berusaha",
|
||||||
icon: <IconBuildingStore size={18} stroke={1.8} />,
|
icon: <IconBuildingStore size={18} stroke={1.8} />
|
||||||
tooltip: "Layanan untuk izin usaha masyarakat"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Pelayanan Telunjuk Sakti Desa",
|
label: "Pelayanan Telunjuk Sakti Desa",
|
||||||
value: "pelayanantelunjuksaktidesa",
|
value: "pelayanantelunjuksaktidesa",
|
||||||
href: "/admin/desa/layanan/pelayanan_telunjuk_sakti_desa",
|
href: "/admin/desa/layanan/pelayanan_telunjuk_sakti_desa",
|
||||||
icon: <IconSparkles size={18} stroke={1.8} />,
|
icon: <IconSparkles size={18} stroke={1.8} />
|
||||||
tooltip: "Layanan inovasi khusus desa"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Pelayanan Penduduk Non-Permanent",
|
label: "Pelayanan Penduduk Non-Permanent",
|
||||||
value: "pelayanannonpermanent",
|
value: "pelayanannonpermanent",
|
||||||
href: "/admin/desa/layanan/pelayanan_penduduk_non_permanent",
|
href: "/admin/desa/layanan/pelayanan_penduduk_non_permanent",
|
||||||
icon: <IconUsers size={18} stroke={1.8} />,
|
icon: <IconUsers size={18} stroke={1.8} />
|
||||||
tooltip: "Pendataan penduduk non-permanent"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Ajukan Permohonan",
|
label: "Ajukan Permohonan",
|
||||||
value: "ajukanpermohonan",
|
value: "ajukanpermohonan",
|
||||||
href: "/admin/desa/layanan/ajukan_permohonan",
|
href: "/admin/desa/layanan/ajukan_permohonan",
|
||||||
icon: <IconUsersPlus size={18} stroke={1.8} />,
|
icon: <IconUsersPlus size={18} stroke={1.8} />
|
||||||
tooltip: "Ajukan permohonan"
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -91,14 +86,8 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tabs.map((tab, i) => (
|
{tabs.map((tab, i) => (
|
||||||
<Tooltip
|
|
||||||
key={i}
|
|
||||||
label={tab.tooltip}
|
|
||||||
position="bottom"
|
|
||||||
withArrow
|
|
||||||
transitionProps={{ transition: 'pop', duration: 200 }}
|
|
||||||
>
|
|
||||||
<TabsTab
|
<TabsTab
|
||||||
|
key={i}
|
||||||
value={tab.value}
|
value={tab.value}
|
||||||
leftSection={tab.icon}
|
leftSection={tab.icon}
|
||||||
style={{
|
style={{
|
||||||
@@ -109,7 +98,6 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
|||||||
>
|
>
|
||||||
{tab.label}
|
{tab.label}
|
||||||
</TabsTab>
|
</TabsTab>
|
||||||
</Tooltip>
|
|
||||||
))}
|
))}
|
||||||
</TabsList>
|
</TabsList>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||||
|
import { IconCategory, IconNews } from '@tabler/icons-react';
|
||||||
import { usePathname, useRouter } from 'next/navigation';
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { IconNews, IconCategory } from '@tabler/icons-react';
|
|
||||||
|
|
||||||
function LayoutTabsBerita({ children }: { children: React.ReactNode }) {
|
function LayoutTabsBerita({ children }: { children: React.ReactNode }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -15,15 +15,13 @@ function LayoutTabsBerita({ children }: { children: React.ReactNode }) {
|
|||||||
label: "List Berita",
|
label: "List Berita",
|
||||||
value: "list_berita",
|
value: "list_berita",
|
||||||
href: "/admin/desa/berita/list-berita",
|
href: "/admin/desa/berita/list-berita",
|
||||||
icon: <IconNews size={18} stroke={1.8} />,
|
icon: <IconNews size={18} stroke={1.8} />
|
||||||
tooltip: "Lihat dan kelola semua berita desa"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Kategori Berita",
|
label: "Kategori Berita",
|
||||||
value: "kategori_berita",
|
value: "kategori_berita",
|
||||||
href: "/admin/desa/berita/kategori-berita",
|
href: "/admin/desa/berita/kategori-berita",
|
||||||
icon: <IconCategory size={18} stroke={1.8} />,
|
icon: <IconCategory size={18} stroke={1.8} />
|
||||||
tooltip: "Kelola kategori berita desa"
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -71,46 +69,39 @@ function LayoutTabsBerita({ children }: { children: React.ReactNode }) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tabs.map((tab, i) => (
|
{tabs.map((tab, i) => (
|
||||||
<Tooltip
|
<TabsTab
|
||||||
key={i}
|
key={i}
|
||||||
label={tab.tooltip}
|
value={tab.value}
|
||||||
position="bottom"
|
leftSection={tab.icon}
|
||||||
withArrow
|
style={{
|
||||||
transitionProps={{ transition: 'pop', duration: 200 }}
|
fontWeight: 600,
|
||||||
|
fontSize: "0.9rem",
|
||||||
|
transition: "all 0.2s ease",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<TabsTab
|
{tab.label}
|
||||||
value={tab.value}
|
</TabsTab>
|
||||||
leftSection={tab.icon}
|
|
||||||
style={{
|
|
||||||
fontWeight: 600,
|
|
||||||
fontSize: "0.9rem",
|
|
||||||
transition: "all 0.2s ease",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{tab.label}
|
|
||||||
</TabsTab>
|
|
||||||
</Tooltip>
|
|
||||||
))}
|
))}
|
||||||
</TabsList>
|
</TabsList>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|
||||||
{tabs.map((tab, i) => (
|
{tabs.map((tab, i) => (
|
||||||
<TabsPanel
|
<TabsPanel
|
||||||
key={i}
|
key={i}
|
||||||
value={tab.value}
|
value={tab.value}
|
||||||
style={{
|
style={{
|
||||||
padding: "1.5rem",
|
padding: "1.5rem",
|
||||||
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
|
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
|
||||||
borderRadius: "1rem",
|
borderRadius: "1rem",
|
||||||
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
|
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Konten dummy, bisa diganti sesuai routing */}
|
{/* Konten dummy, bisa diganti sesuai routing */}
|
||||||
<>{children}</>
|
<>{children}</>
|
||||||
</TabsPanel>
|
</TabsPanel>
|
||||||
))}
|
))}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Stack>
|
</Stack >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -77,7 +76,6 @@ function EditKategoriBerita() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Back Button + Title */}
|
{/* Back Button + Title */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -86,7 +84,6 @@ function EditKategoriBerita() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Kategori Berita
|
Edit Kategori Berita
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -35,7 +34,6 @@ function CreateKategoriBerita() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header dengan back button */}
|
{/* Header dengan back button */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -44,7 +42,6 @@ function CreateKategoriBerita() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Kategori Berita
|
Tambah Kategori Berita
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -86,7 +85,6 @@ function ListKategoriBerita({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>Daftar Kategori Berita</Title>
|
<Title order={4}>Daftar Kategori Berita</Title>
|
||||||
<Tooltip label="Tambah Kategori Berita" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconPlus size={18} />}
|
leftSection={<IconPlus size={18} />}
|
||||||
color="blue"
|
color="blue"
|
||||||
@@ -97,7 +95,6 @@ function ListKategoriBerita({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
Tambah Baru
|
Tambah Baru
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
@@ -123,7 +120,6 @@ function ListKategoriBerita({ search }: { search: string }) {
|
|||||||
</Text>
|
</Text>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
<TableTd>
|
<TableTd>
|
||||||
<Tooltip label="Edit Kategori Berita" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="light"
|
variant="light"
|
||||||
color="green"
|
color="green"
|
||||||
@@ -135,10 +131,8 @@ function ListKategoriBerita({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
<IconEdit size={18} />
|
<IconEdit size={18} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</TableTd>
|
</TableTd>
|
||||||
<TableTd>
|
<TableTd>
|
||||||
<Tooltip label="Hapus Kategori Berita" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="light"
|
variant="light"
|
||||||
color="red"
|
color="red"
|
||||||
@@ -150,7 +144,6 @@ function ListKategoriBerita({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
<IconTrash size={18} />
|
<IconTrash size={18} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</TableTd>
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { Dropzone } from "@mantine/dropzone";
|
import { Dropzone } from "@mantine/dropzone";
|
||||||
import {
|
import {
|
||||||
@@ -116,7 +115,6 @@ function EditBerita() {
|
|||||||
<Box px={{ base: "sm", md: "lg" }} py="md">
|
<Box px={{ base: "sm", md: "lg" }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -125,7 +123,6 @@ function EditBerita() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Berita
|
Edit Berita
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useProxy } from 'valtio/utils';
|
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
import colors from '@/con/colors';
|
|
||||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||||
import stateDashboardBerita from '@/app/admin/(dashboard)/_state/desa/berita';
|
import stateDashboardBerita from '@/app/admin/(dashboard)/_state/desa/berita';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
|
||||||
function DetailBerita() {
|
function DetailBerita() {
|
||||||
const beritaState = useProxy(stateDashboardBerita);
|
const beritaState = useProxy(stateDashboardBerita);
|
||||||
@@ -111,7 +111,6 @@ function DetailBerita() {
|
|||||||
|
|
||||||
{/* Action Button */}
|
{/* Action Button */}
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<Tooltip label="Hapus Berita" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="red"
|
color="red"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -124,9 +123,7 @@ function DetailBerita() {
|
|||||||
>
|
>
|
||||||
<IconTrash size={20} />
|
<IconTrash size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip label="Edit Berita" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="green"
|
color="green"
|
||||||
onClick={() => router.push(`/admin/desa/berita/list-berita/${data.id}/edit`)}
|
onClick={() => router.push(`/admin/desa/berita/list-berita/${data.id}/edit`)}
|
||||||
@@ -136,7 +133,6 @@ function DetailBerita() {
|
|||||||
>
|
>
|
||||||
<IconEdit size={20} />
|
<IconEdit size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { Dropzone } from '@mantine/dropzone';
|
import { Dropzone } from '@mantine/dropzone';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
@@ -73,7 +72,6 @@ export default function CreateBerita() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header dengan tombol kembali */}
|
{/* Header dengan tombol kembali */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -82,7 +80,6 @@ export default function CreateBerita() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Berita
|
Tambah Berita
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
|
import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
|
||||||
@@ -68,7 +67,6 @@ function ListBerita({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>Daftar Berita</Title>
|
<Title order={4}>Daftar Berita</Title>
|
||||||
<Tooltip label="Tambah Berita" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconCircleDashedPlus size={18} />}
|
leftSection={<IconCircleDashedPlus size={18} />}
|
||||||
color="blue"
|
color="blue"
|
||||||
@@ -77,7 +75,6 @@ function ListBerita({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
Tambah Baru
|
Tambah Baru
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useShallowEffect } from "@mantine/hooks";
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
import { IconSearch, IconTrash, IconX } from "@tabler/icons-react";
|
import { IconSearch, IconTrash, IconX } from "@tabler/icons-react";
|
||||||
@@ -103,7 +102,6 @@ export default function ListImage() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Group justify="space-between" align="center" pt="xs">
|
<Group justify="space-between" align="center" pt="xs">
|
||||||
<Tooltip label="Hapus foto" withArrow>
|
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
color="red"
|
color="red"
|
||||||
@@ -116,7 +114,6 @@ export default function ListImage() {
|
|||||||
>
|
>
|
||||||
<IconTrash size={18} />
|
<IconTrash size={18} />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||||
|
import { IconPhoto, IconVideo } from '@tabler/icons-react';
|
||||||
import { usePathname, useRouter } from 'next/navigation';
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { IconPhoto, IconVideo } from '@tabler/icons-react';
|
|
||||||
|
|
||||||
function LayoutTabsGallery({ children }: { children: React.ReactNode }) {
|
function LayoutTabsGallery({ children }: { children: React.ReactNode }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -14,15 +14,13 @@ function LayoutTabsGallery({ children }: { children: React.ReactNode }) {
|
|||||||
label: "Foto",
|
label: "Foto",
|
||||||
value: "foto",
|
value: "foto",
|
||||||
href: "/admin/desa/gallery/foto",
|
href: "/admin/desa/gallery/foto",
|
||||||
icon: <IconPhoto size={18} stroke={1.8} />,
|
icon: <IconPhoto size={18} stroke={1.8} />
|
||||||
tooltip: "Kelola foto-foto galeri desa"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Video",
|
label: "Video",
|
||||||
value: "video",
|
value: "video",
|
||||||
href: "/admin/desa/gallery/video",
|
href: "/admin/desa/gallery/video",
|
||||||
icon: <IconVideo size={18} stroke={1.8} />,
|
icon: <IconVideo size={18} stroke={1.8} />
|
||||||
tooltip: "Kelola video galeri desa"
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -70,25 +68,18 @@ function LayoutTabsGallery({ children }: { children: React.ReactNode }) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tabs.map((tab, i) => (
|
{tabs.map((tab, i) => (
|
||||||
<Tooltip
|
<TabsTab
|
||||||
key={i}
|
key={i}
|
||||||
label={tab.tooltip}
|
value={tab.value}
|
||||||
position="bottom"
|
leftSection={tab.icon}
|
||||||
withArrow
|
style={{
|
||||||
transitionProps={{ transition: 'pop', duration: 200 }}
|
fontWeight: 600,
|
||||||
|
fontSize: "0.9rem",
|
||||||
|
transition: "all 0.2s ease",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<TabsTab
|
{tab.label}
|
||||||
value={tab.value}
|
</TabsTab>
|
||||||
leftSection={tab.icon}
|
|
||||||
style={{
|
|
||||||
fontWeight: 600,
|
|
||||||
fontSize: "0.9rem",
|
|
||||||
transition: "all 0.2s ease",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{tab.label}
|
|
||||||
</TabsTab>
|
|
||||||
</Tooltip>
|
|
||||||
))}
|
))}
|
||||||
</TabsList>
|
</TabsList>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|||||||
@@ -10,12 +10,11 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState, useCallback } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import { convertYoutubeUrlToEmbed } from '../../../lib/youtube-utils';
|
import { convertYoutubeUrlToEmbed } from '../../../lib/youtube-utils';
|
||||||
@@ -89,7 +88,6 @@ function EditVideo() {
|
|||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -98,7 +96,6 @@ function EditVideo() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Video
|
Edit Video
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||||
import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery';
|
import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Group, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
import { Box, Button, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -111,7 +111,6 @@ function DetailVideo() {
|
|||||||
|
|
||||||
{/* Tombol Aksi */}
|
{/* Tombol Aksi */}
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<Tooltip label="Hapus Video" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="red"
|
color="red"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -124,9 +123,7 @@ function DetailVideo() {
|
|||||||
>
|
>
|
||||||
<IconTrash size={20} />
|
<IconTrash size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip label="Edit Video" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="green"
|
color="green"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -138,7 +135,6 @@ function DetailVideo() {
|
|||||||
>
|
>
|
||||||
<IconEdit size={20} />
|
<IconEdit size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -51,7 +50,6 @@ function CreateVideo() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header Back Button + Title */}
|
{/* Header Back Button + Title */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -60,7 +58,6 @@ function CreateVideo() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Video
|
Tambah Video
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconDeviceImac, IconPlus, IconSearch } from '@tabler/icons-react';
|
import { IconDeviceImac, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||||
@@ -74,7 +73,6 @@ function ListVideo({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>Daftar Video</Title>
|
<Title order={4}>Daftar Video</Title>
|
||||||
<Tooltip label="Tambah Video Baru" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconPlus size={18} />}
|
leftSection={<IconPlus size={18} />}
|
||||||
color="blue"
|
color="blue"
|
||||||
@@ -83,7 +81,6 @@ function ListVideo({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
Tambah Baru
|
Tambah Baru
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
<Box style={{ overflowX: "auto" }}>
|
<Box style={{ overflowX: "auto" }}>
|
||||||
<Table highlightOnHover>
|
<Table highlightOnHover>
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ import {
|
|||||||
Select,
|
Select,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -87,11 +86,9 @@ function EditAjukanPermohonan() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Back Button */}
|
{/* Back Button */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Ajukan Permohonan
|
Edit Ajukan Permohonan
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||||
@@ -121,7 +120,6 @@ function DetailAjukanPermohonan() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<Tooltip label="Hapus Surat" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="red"
|
color="red"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -135,9 +133,7 @@ function DetailAjukanPermohonan() {
|
|||||||
>
|
>
|
||||||
<IconTrash size={20} />
|
<IconTrash size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip label="Edit Surat" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="green"
|
color="green"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -151,7 +147,6 @@ function DetailAjukanPermohonan() {
|
|||||||
>
|
>
|
||||||
<IconEdit size={20} />
|
<IconEdit size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -83,7 +82,6 @@ function EditPelayananPendudukNonPermanent() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -92,7 +90,6 @@ function EditPelayananPendudukNonPermanent() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Pelayanan Penduduk Non Permanent
|
Edit Pelayanan Penduduk Non Permanent
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ import {
|
|||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconEdit } from '@tabler/icons-react';
|
import { IconEdit } from '@tabler/icons-react';
|
||||||
@@ -27,7 +26,7 @@ function PelayananPendudukNonPermanent() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
pelayananPendudukNonPermanen.findById.load('1');
|
pelayananPendudukNonPermanen.findById.load('edit');
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!pelayananPendudukNonPermanen.findById.data) {
|
if (!pelayananPendudukNonPermanen.findById.data) {
|
||||||
@@ -51,7 +50,6 @@ function PelayananPendudukNonPermanent() {
|
|||||||
</Title>
|
</Title>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 1 }}>
|
<GridCol span={{ base: 12, md: 1 }}>
|
||||||
<Tooltip label="Edit Data Pelayanan" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
c="green"
|
c="green"
|
||||||
variant="light"
|
variant="light"
|
||||||
@@ -65,7 +63,6 @@ function PelayananPendudukNonPermanent() {
|
|||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ import {
|
|||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -100,7 +99,6 @@ function EditPelayananPerizinanBerusaha() {
|
|||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -109,7 +107,6 @@ function EditPelayananPerizinanBerusaha() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Pelayanan Perizinan Berusaha
|
Edit Pelayanan Perizinan Berusaha
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -16,14 +16,13 @@ import {
|
|||||||
StepperCompleted,
|
StepperCompleted,
|
||||||
StepperStep,
|
StepperStep,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconEdit } from '@tabler/icons-react';
|
import { IconEdit } from '@tabler/icons-react';
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import stateLayananDesa from '../../../_state/desa/layananDesa';
|
|
||||||
import { useProxy } from 'valtio/utils';
|
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import stateLayananDesa from '../../../_state/desa/layananDesa';
|
||||||
|
|
||||||
function PerizinanBerusaha() {
|
function PerizinanBerusaha() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -43,7 +42,7 @@ function PerizinanBerusaha() {
|
|||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
// You should get the ID from your router query or params
|
// You should get the ID from your router query or params
|
||||||
const id = '1'; // Replace with actual ID or get from URL params
|
const id = 'edit'; // Replace with actual ID or get from URL params
|
||||||
await pelayananPerizinanBerusaha.findById.load(id);
|
await pelayananPerizinanBerusaha.findById.load(id);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError('Gagal memuat data');
|
setError('Gagal memuat data');
|
||||||
@@ -85,7 +84,6 @@ function PerizinanBerusaha() {
|
|||||||
</Title>
|
</Title>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 1 }}>
|
<GridCol span={{ base: 12, md: 1 }}>
|
||||||
<Tooltip label="Edit Data Perizinan" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
c="green"
|
c="green"
|
||||||
variant="light"
|
variant="light"
|
||||||
@@ -99,7 +97,6 @@ function PerizinanBerusaha() {
|
|||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@@ -12,13 +12,12 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { Dropzone } from '@mantine/dropzone';
|
import { Dropzone } from '@mantine/dropzone';
|
||||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState, useCallback } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
@@ -112,11 +111,9 @@ function EditSuratKeterangan() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Back Button */}
|
{/* Back Button */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Surat Keterangan
|
Edit Surat Keterangan
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||||
@@ -142,7 +141,6 @@ function DetailSuratKeterangan() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<Tooltip label="Hapus Surat" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="red"
|
color="red"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -156,9 +154,7 @@ function DetailSuratKeterangan() {
|
|||||||
>
|
>
|
||||||
<IconTrash size={20} />
|
<IconTrash size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip label="Edit Surat" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="green"
|
color="green"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -172,7 +168,6 @@ function DetailSuratKeterangan() {
|
|||||||
>
|
>
|
||||||
<IconEdit size={20} />
|
<IconEdit size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { Dropzone } from '@mantine/dropzone';
|
import { Dropzone } from '@mantine/dropzone';
|
||||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||||
@@ -85,11 +84,9 @@ function CreateSuratKeterangan() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Surat Keterangan
|
Tambah Surat Keterangan
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -82,7 +81,6 @@ function ListSuratKeterangan({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>List Surat Keterangan</Title>
|
<Title order={4}>List Surat Keterangan</Title>
|
||||||
<Tooltip label="Tambah Surat Keterangan" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconPlus size={18} />}
|
leftSection={<IconPlus size={18} />}
|
||||||
color="blue"
|
color="blue"
|
||||||
@@ -93,7 +91,6 @@ function ListSuratKeterangan({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
Tambah Baru
|
Tambah Baru
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
<Box style={{ overflowX: "auto" }}>
|
<Box style={{ overflowX: "auto" }}>
|
||||||
<Table highlightOnHover>
|
<Table highlightOnHover>
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -81,11 +80,9 @@ function EditPelayananTelunjukSakti() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Back Button + Title */}
|
{/* Back Button + Title */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Pelayanan Telunjuk Sakti Desa
|
Edit Pelayanan Telunjuk Sakti Desa
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||||
@@ -130,7 +129,6 @@ function DetailPelayananTelunjukSakti() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<Tooltip label="Hapus Layanan" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="red"
|
color="red"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -144,9 +142,7 @@ function DetailPelayananTelunjukSakti() {
|
|||||||
>
|
>
|
||||||
<IconTrash size={20} />
|
<IconTrash size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip label="Edit Layanan" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="green"
|
color="green"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -160,7 +156,6 @@ function DetailPelayananTelunjukSakti() {
|
|||||||
>
|
>
|
||||||
<IconEdit size={20} />
|
<IconEdit size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -45,11 +44,9 @@ function CreatePelayananTelunjukDesa() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Pelayanan Telunjuk Sakti Desa
|
Tambah Pelayanan Telunjuk Sakti Desa
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -1,159 +1,3 @@
|
|||||||
// /* eslint-disable react-hooks/exhaustive-deps */
|
|
||||||
// 'use client'
|
|
||||||
// import colors from '@/con/colors';
|
|
||||||
// import { Box, Button, Center, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
|
|
||||||
// import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
|
|
||||||
// import { useRouter } from 'next/navigation';
|
|
||||||
// import { useEffect, useMemo, useState } from 'react';
|
|
||||||
// import { useProxy } from 'valtio/utils';
|
|
||||||
// import HeaderSearch from '../../../_com/header';
|
|
||||||
// import JudulList from '../../../_com/judulList';
|
|
||||||
// import stateLayananDesa from '../../../_state/desa/layananDesa';
|
|
||||||
|
|
||||||
// function PelayananTelunjukSakti() {
|
|
||||||
// const [search, setSearch] = useState("");
|
|
||||||
// return (
|
|
||||||
// <Box>
|
|
||||||
// <HeaderSearch
|
|
||||||
// title='Posisi Organisasi'
|
|
||||||
// placeholder='pencarian'
|
|
||||||
// searchIcon={<IconSearch size={20} />}
|
|
||||||
// value={search}
|
|
||||||
// onChange={(e) => setSearch(e.currentTarget.value)}
|
|
||||||
// />
|
|
||||||
// <ListPelayananTelunjukSakti search={search} />
|
|
||||||
// </Box>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function ListPelayananTelunjukSakti({ search }: { search: string }) {
|
|
||||||
// const telunjukSaktiState = useProxy(stateLayananDesa.pelayananTelunjukSaktiDesa)
|
|
||||||
// const router = useRouter()
|
|
||||||
|
|
||||||
// const {
|
|
||||||
// data,
|
|
||||||
// page,
|
|
||||||
// totalPages,
|
|
||||||
// loading,
|
|
||||||
// load,
|
|
||||||
// } = telunjukSaktiState.findMany;
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// load(page, 10)
|
|
||||||
// }, [])
|
|
||||||
|
|
||||||
// const filteredData = useMemo(() => {
|
|
||||||
// if (!data) return [];
|
|
||||||
// return data.filter(item => {
|
|
||||||
// const keyword = search.toLowerCase();
|
|
||||||
// return (
|
|
||||||
// item.name?.toLowerCase().includes(keyword) ||
|
|
||||||
// item.link?.toLowerCase().includes(keyword) ||
|
|
||||||
// item.deskripsi?.toLowerCase().includes(keyword)
|
|
||||||
// );
|
|
||||||
// })
|
|
||||||
// .sort((a, b) => a.posisi?.hierarki - b.posisi?.hierarki);
|
|
||||||
// }, [data, search]);
|
|
||||||
|
|
||||||
// if (loading || !data) {
|
|
||||||
// return (
|
|
||||||
// <Stack py={10}>
|
|
||||||
// <Skeleton height={300} />
|
|
||||||
// </Stack>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (data.length === 0) {
|
|
||||||
// return (
|
|
||||||
// <Box py={10}>
|
|
||||||
// <Paper bg={colors['white-1']} p={'md'}>
|
|
||||||
// <JudulList
|
|
||||||
// title='List Pelayanan Telunjuk Sakti Desa'
|
|
||||||
// href='/admin/desa/layanan/pelayanan_telunjuk_sakti_desa/create'
|
|
||||||
// />
|
|
||||||
// <Table striped withTableBorder withRowBorders>
|
|
||||||
// <TableThead>
|
|
||||||
// <TableTr>
|
|
||||||
// <TableTh>Nama</TableTh>
|
|
||||||
// <TableTh>Link</TableTh>
|
|
||||||
// <TableTh>Detail</TableTh>
|
|
||||||
// </TableTr>
|
|
||||||
// </TableThead>
|
|
||||||
// <TableTbody>
|
|
||||||
// <TableTr>
|
|
||||||
// <TableTd colSpan={3}>
|
|
||||||
// <Text fz={"sm"} color="gray.5">
|
|
||||||
// Tidak ada data
|
|
||||||
// </Text>
|
|
||||||
// </TableTd>
|
|
||||||
// </TableTr>
|
|
||||||
// </TableTbody>
|
|
||||||
// </Table>
|
|
||||||
// </Paper>
|
|
||||||
// </Box>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <Box py={10}>
|
|
||||||
// <Paper bg={colors['white-1']} p={'md'}>
|
|
||||||
// <JudulList
|
|
||||||
// title='List Pelayanan Telunjuk Sakti Desa'
|
|
||||||
// href='/admin/desa/layanan/pelayanan_telunjuk_sakti_desa/create'
|
|
||||||
// />
|
|
||||||
// <Table striped withTableBorder withRowBorders>
|
|
||||||
// <TableThead>
|
|
||||||
// <TableTr>
|
|
||||||
// <TableTh>Nama</TableTh>
|
|
||||||
// <TableTh>Link</TableTh>
|
|
||||||
// <TableTh>Detail</TableTh>
|
|
||||||
// </TableTr>
|
|
||||||
// </TableThead>
|
|
||||||
// <TableTbody>
|
|
||||||
// {filteredData.map((item) => (
|
|
||||||
// <TableTr key={item.id}>
|
|
||||||
// <TableTd>
|
|
||||||
// <Box w={100}>
|
|
||||||
// <Text truncate="end" lineClamp={1} fz={"sm"} dangerouslySetInnerHTML={{ __html: item.name }} />
|
|
||||||
// </Box>
|
|
||||||
// </TableTd>
|
|
||||||
// <TableTd>
|
|
||||||
// <Box w={100}>
|
|
||||||
// <a href={item.link} target="_blank" rel="noopener noreferrer">
|
|
||||||
// <Text dangerouslySetInnerHTML={{ __html: item.deskripsi }} truncate="end" fz={"sm"} />
|
|
||||||
// </a>
|
|
||||||
// </Box>
|
|
||||||
// </TableTd>
|
|
||||||
// <TableTd>
|
|
||||||
// <Text>
|
|
||||||
// <Button onClick={() => router.push(`/admin/desa/layanan/pelayanan_telunjuk_sakti_desa/${item.id}`)}>
|
|
||||||
// <IconDeviceImac size={20} />
|
|
||||||
// </Button>
|
|
||||||
// </Text>
|
|
||||||
// </TableTd>
|
|
||||||
// </TableTr>
|
|
||||||
// ))}
|
|
||||||
// </TableTbody>
|
|
||||||
// </Table>
|
|
||||||
// </Paper>
|
|
||||||
// <Center>
|
|
||||||
// <Pagination
|
|
||||||
// value={page}
|
|
||||||
// onChange={(newPage) => {
|
|
||||||
// load(newPage, 10);
|
|
||||||
// window.scrollTo(0, 0);
|
|
||||||
// }}
|
|
||||||
// total={totalPages}
|
|
||||||
// mt="md"
|
|
||||||
// mb="md"
|
|
||||||
// />
|
|
||||||
// </Center>
|
|
||||||
// </Box>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export default PelayananTelunjukSakti;
|
|
||||||
|
|
||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
@@ -174,8 +18,7 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -225,7 +68,6 @@ function ListPelayananTelunjukSakti({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>Daftar Pelayanan Telunjuk Sakti</Title>
|
<Title order={4}>Daftar Pelayanan Telunjuk Sakti</Title>
|
||||||
<Tooltip label="Tambah Layanan" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconPlus size={18} />}
|
leftSection={<IconPlus size={18} />}
|
||||||
color="blue"
|
color="blue"
|
||||||
@@ -236,7 +78,6 @@ function ListPelayananTelunjukSakti({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
Tambah Baru
|
Tambah Baru
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
<Table highlightOnHover style={{ minWidth: '700px' }}>
|
<Table highlightOnHover style={{ minWidth: '700px' }}>
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { Dropzone } from '@mantine/dropzone';
|
import { Dropzone } from '@mantine/dropzone';
|
||||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||||
@@ -102,11 +101,9 @@ function EditPenghargaan() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Tombol Back + Title */}
|
{/* Tombol Back + Title */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Penghargaan
|
Edit Penghargaan
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import React, { useState } from 'react';
|
import colors from '@/con/colors';
|
||||||
import penghargaanState from '../../../_state/desa/penghargaan';
|
|
||||||
import { useProxy } from 'valtio/utils';
|
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
@@ -12,12 +8,15 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import colors from '@/con/colors';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||||
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||||
|
import penghargaanState from '../../../_state/desa/penghargaan';
|
||||||
|
|
||||||
function DetailPenghargaan() {
|
function DetailPenghargaan() {
|
||||||
const statePenghargaan = useProxy(penghargaanState);
|
const statePenghargaan = useProxy(penghargaanState);
|
||||||
@@ -127,34 +126,30 @@ function DetailPenghargaan() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Group gap="sm" mt={10}>
|
<Group gap="sm" mt={10}>
|
||||||
<Tooltip label="Hapus Penghargaan" withArrow position="top">
|
<Button
|
||||||
<Button
|
color="red"
|
||||||
color="red"
|
onClick={() => {
|
||||||
onClick={() => {
|
setSelectedId(data.id);
|
||||||
setSelectedId(data.id);
|
setModalHapus(true);
|
||||||
setModalHapus(true);
|
}}
|
||||||
}}
|
variant="light"
|
||||||
variant="light"
|
radius="md"
|
||||||
radius="md"
|
size="md"
|
||||||
size="md"
|
>
|
||||||
>
|
<IconTrash size={20} />
|
||||||
<IconTrash size={20} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip label="Edit Penghargaan" withArrow position="top">
|
<Button
|
||||||
<Button
|
color="green"
|
||||||
color="green"
|
onClick={() =>
|
||||||
onClick={() =>
|
router.push(`/admin/desa/penghargaan/${data.id}/edit`)
|
||||||
router.push(`/admin/desa/penghargaan/${data.id}/edit`)
|
}
|
||||||
}
|
variant="light"
|
||||||
variant="light"
|
radius="md"
|
||||||
radius="md"
|
size="md"
|
||||||
size="md"
|
>
|
||||||
>
|
<IconEdit size={20} />
|
||||||
<IconEdit size={20} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { Dropzone } from '@mantine/dropzone';
|
import { Dropzone } from '@mantine/dropzone';
|
||||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||||
@@ -66,11 +65,9 @@ function CreatePenghargaan() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Penghargaan
|
Tambah Penghargaan
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -69,7 +68,6 @@ function ListPenghargaan({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>List Penghargaan</Title>
|
<Title order={4}>List Penghargaan</Title>
|
||||||
<Tooltip label="Tambah Penghargaan" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconPlus size={18} />}
|
leftSection={<IconPlus size={18} />}
|
||||||
color="blue"
|
color="blue"
|
||||||
@@ -78,7 +76,6 @@ function ListPenghargaan({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
Tambah Baru
|
Tambah Baru
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
<Table highlightOnHover>
|
<Table highlightOnHover>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||||
|
import { IconCategory, IconListDetails } from '@tabler/icons-react';
|
||||||
import { usePathname, useRouter } from 'next/navigation';
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { IconListDetails, IconCategory } from '@tabler/icons-react';
|
|
||||||
|
|
||||||
function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -14,15 +14,13 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
|||||||
label: "List Pengumuman",
|
label: "List Pengumuman",
|
||||||
value: "listpengumuman",
|
value: "listpengumuman",
|
||||||
href: "/admin/desa/pengumuman/list-pengumuman",
|
href: "/admin/desa/pengumuman/list-pengumuman",
|
||||||
icon: <IconListDetails size={18} stroke={1.8} />,
|
icon: <IconListDetails size={18} stroke={1.8} />
|
||||||
tooltip: "Lihat semua daftar pengumuman"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Kategori Pengumuman",
|
label: "Kategori Pengumuman",
|
||||||
value: "kategoripengumuman",
|
value: "kategoripengumuman",
|
||||||
href: "/admin/desa/pengumuman/kategori-pengumuman",
|
href: "/admin/desa/pengumuman/kategori-pengumuman",
|
||||||
icon: <IconCategory size={18} stroke={1.8} />,
|
icon: <IconCategory size={18} stroke={1.8} />
|
||||||
tooltip: "Kelola kategori pengumuman"
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -70,19 +68,18 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tabs.map((tab, i) => (
|
{tabs.map((tab, i) => (
|
||||||
<Tooltip key={i} label={tab.tooltip} position="bottom" withArrow transitionProps={{ transition: 'pop', duration: 200 }}>
|
<TabsTab
|
||||||
<TabsTab
|
key={i}
|
||||||
value={tab.value}
|
value={tab.value}
|
||||||
leftSection={tab.icon}
|
leftSection={tab.icon}
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontSize: "0.9rem",
|
fontSize: "0.9rem",
|
||||||
transition: "all 0.2s ease",
|
transition: "all 0.2s ease",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tab.label}
|
{tab.label}
|
||||||
</TabsTab>
|
</TabsTab>
|
||||||
</Tooltip>
|
|
||||||
))}
|
))}
|
||||||
</TabsList>
|
</TabsList>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -74,7 +73,6 @@ function EditKategoriPengumuman() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -83,7 +81,6 @@ function EditKategoriPengumuman() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Kategori Pengumuman
|
Edit Kategori Pengumuman
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -35,7 +34,6 @@ function CreateKategoriPengumuman() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header dengan back button */}
|
{/* Header dengan back button */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -44,7 +42,6 @@ function CreateKategoriPengumuman() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Kategori Pengumuman
|
Tambah Kategori Pengumuman
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import {
|
import {
|
||||||
Box, Button, Center, Paper, Skeleton, Stack,
|
Box, Button, Center,
|
||||||
|
Pagination,
|
||||||
|
Paper, Skeleton, Stack,
|
||||||
Table, TableTbody, TableTd, TableTh, TableThead, TableTr,
|
Table, TableTbody, TableTd, TableTh, TableThead, TableTr,
|
||||||
Text, Title, Tooltip, Pagination
|
Text, Title
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconEdit, IconSearch, IconTrash, IconPlus } from '@tabler/icons-react';
|
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
@@ -66,16 +68,14 @@ function ListKategoriPengumuman({ search }: { search: string }) {
|
|||||||
<Stack>
|
<Stack>
|
||||||
<Box style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 15 }}>
|
<Box style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 15 }}>
|
||||||
<Title order={4}>List Kategori Pengumuman</Title>
|
<Title order={4}>List Kategori Pengumuman</Title>
|
||||||
<Tooltip label="Tambah Kategori Pengumuman" withArrow>
|
<Button
|
||||||
<Button
|
leftSection={<IconPlus size={18} />}
|
||||||
leftSection={<IconPlus size={18} />}
|
color="blue"
|
||||||
color="blue"
|
variant="light"
|
||||||
variant="light"
|
onClick={() => router.push('/admin/desa/pengumuman/kategori-pengumuman/create')}
|
||||||
onClick={() => router.push('/admin/desa/pengumuman/kategori-pengumuman/create')}
|
>
|
||||||
>
|
Tambah Baru
|
||||||
Tambah Baru
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
@@ -99,29 +99,25 @@ function ListKategoriPengumuman({ search }: { search: string }) {
|
|||||||
<Text truncate lineClamp={1}>{item.name}</Text>
|
<Text truncate lineClamp={1}>{item.name}</Text>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
<TableTd>
|
<TableTd>
|
||||||
<Tooltip label="Edit Kategori Pengumuman" withArrow>
|
<Button
|
||||||
<Button
|
variant='light'
|
||||||
variant='light'
|
color='green'
|
||||||
color='green'
|
onClick={() => router.push(`/admin/desa/pengumuman/kategori-pengumuman/${item.id}`)}
|
||||||
onClick={() => router.push(`/admin/desa/pengumuman/kategori-pengumuman/${item.id}`)}
|
>
|
||||||
>
|
<IconEdit size={20} />
|
||||||
<IconEdit size={20} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</TableTd>
|
</TableTd>
|
||||||
<TableTd>
|
<TableTd>
|
||||||
<Tooltip label="Hapus Kategori Pengumuman" withArrow>
|
<Button
|
||||||
<Button
|
variant='light'
|
||||||
variant='light'
|
color='red'
|
||||||
color='red'
|
disabled={listDataState.delete.loading}
|
||||||
disabled={listDataState.delete.loading}
|
onClick={() => {
|
||||||
onClick={() => {
|
setSelectedId(item.id)
|
||||||
setSelectedId(item.id)
|
setModalHapus(true)
|
||||||
setModalHapus(true)
|
}}>
|
||||||
}}>
|
<IconTrash size={20} />
|
||||||
<IconTrash size={20} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</TableTd>
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { IconArrowBack } from "@tabler/icons-react";
|
import { IconArrowBack } from "@tabler/icons-react";
|
||||||
import { useParams, useRouter } from "next/navigation";
|
import { useParams, useRouter } from "next/navigation";
|
||||||
@@ -85,16 +84,14 @@ function EditPengumuman() {
|
|||||||
return (
|
return (
|
||||||
<Box px={{ base: "sm", md: "lg" }} py="md">
|
<Box px={{ base: "sm", md: "lg" }} py="md">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button
|
||||||
<Button
|
variant="subtle"
|
||||||
variant="subtle"
|
onClick={() => router.back()}
|
||||||
onClick={() => router.back()}
|
p="xs"
|
||||||
p="xs"
|
radius="md"
|
||||||
radius="md"
|
>
|
||||||
>
|
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Pengumuman
|
Edit Pengumuman
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||||
|
import stateDesaPengumuman from '@/app/admin/(dashboard)/_state/desa/pengumuman';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
@@ -8,16 +10,13 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||||
import { useRouter, useParams } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
|
||||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
|
||||||
import stateDesaPengumuman from '@/app/admin/(dashboard)/_state/desa/pengumuman';
|
|
||||||
|
|
||||||
export default function DetailPengumuman() {
|
export default function DetailPengumuman() {
|
||||||
const pengumumanState = useProxy(stateDesaPengumuman);
|
const pengumumanState = useProxy(stateDesaPengumuman);
|
||||||
@@ -117,7 +116,6 @@ export default function DetailPengumuman() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<Tooltip label="Hapus Pengumuman" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="red"
|
color="red"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -130,9 +128,7 @@ export default function DetailPengumuman() {
|
|||||||
>
|
>
|
||||||
<IconTrash size={20} />
|
<IconTrash size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip label="Edit Pengumuman" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="green"
|
color="green"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -146,7 +142,6 @@ export default function DetailPengumuman() {
|
|||||||
>
|
>
|
||||||
<IconEdit size={20} />
|
<IconEdit size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
@@ -47,11 +46,9 @@ function CreatePengumuman() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Pengumuman
|
Tambah Pengumuman
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
|
import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
|
||||||
@@ -69,16 +68,14 @@ function ListPengumuman({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>Daftar Pengumuman</Title>
|
<Title order={4}>Daftar Pengumuman</Title>
|
||||||
<Tooltip label="Tambah Pengumuman" withArrow>
|
<Button
|
||||||
<Button
|
leftSection={<IconCircleDashedPlus size={18} />}
|
||||||
leftSection={<IconCircleDashedPlus size={18} />}
|
color="blue"
|
||||||
color="blue"
|
variant="light"
|
||||||
variant="light"
|
onClick={() => router.push('/admin/desa/pengumuman/list-pengumuman/create')}
|
||||||
onClick={() => router.push('/admin/desa/pengumuman/list-pengumuman/create')}
|
>
|
||||||
>
|
Tambah Baru
|
||||||
Tambah Baru
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
<Table highlightOnHover style={{ minWidth: '700px' }}>
|
<Table highlightOnHover style={{ minWidth: '700px' }}>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||||
import { IconCategory, IconListCheck } from '@tabler/icons-react';
|
import { IconCategory, IconListCheck } from '@tabler/icons-react';
|
||||||
import { usePathname, useRouter } from 'next/navigation';
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
@@ -14,15 +14,13 @@ function LayoutTabsPotensi({ children }: { children: React.ReactNode }) {
|
|||||||
label: "List Potensi",
|
label: "List Potensi",
|
||||||
value: "list_potensi",
|
value: "list_potensi",
|
||||||
href: "/admin/desa/potensi/list-potensi",
|
href: "/admin/desa/potensi/list-potensi",
|
||||||
icon: <IconListCheck size={18} stroke={1.8} />,
|
icon: <IconListCheck size={18} stroke={1.8} />
|
||||||
tooltip: "Lihat semua potensi desa"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Kategori Potensi",
|
label: "Kategori Potensi",
|
||||||
value: "kategori_potensi",
|
value: "kategori_potensi",
|
||||||
href: "/admin/desa/potensi/kategori-potensi",
|
href: "/admin/desa/potensi/kategori-potensi",
|
||||||
icon: <IconCategory size={18} stroke={1.8} />,
|
icon: <IconCategory size={18} stroke={1.8} />
|
||||||
tooltip: "Kelola kategori potensi"
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -70,19 +68,18 @@ function LayoutTabsPotensi({ children }: { children: React.ReactNode }) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tabs.map((tab, i) => (
|
{tabs.map((tab, i) => (
|
||||||
<Tooltip key={i} label={tab.tooltip} position="bottom" withArrow transitionProps={{ transition: 'pop', duration: 200 }}>
|
<TabsTab
|
||||||
<TabsTab
|
key={i}
|
||||||
value={tab.value}
|
value={tab.value}
|
||||||
leftSection={tab.icon}
|
leftSection={tab.icon}
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontSize: "0.9rem",
|
fontSize: "0.9rem",
|
||||||
transition: "all 0.2s ease",
|
transition: "all 0.2s ease",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tab.label}
|
{tab.label}
|
||||||
</TabsTab>
|
</TabsTab>
|
||||||
</Tooltip>
|
|
||||||
))}
|
))}
|
||||||
</TabsList>
|
</TabsList>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -76,7 +75,6 @@ function EditKategoriPotensi() {
|
|||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -85,7 +83,6 @@ function EditKategoriPotensi() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Kategori Potensi
|
Edit Kategori Potensi
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -35,7 +34,6 @@ function CreateKategoriPotensi() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header dengan back button */}
|
{/* Header dengan back button */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -44,7 +42,6 @@ function CreateKategoriPotensi() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Kategori Potensi
|
Tambah Kategori Potensi
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Center, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title, Tooltip, Pagination, Group } from '@mantine/core';
|
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||||
import { IconEdit, IconSearch, IconTrash, IconPlus } from '@tabler/icons-react';
|
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import HeaderSearch from '../../../_com/header';
|
import HeaderSearch from '../../../_com/header';
|
||||||
import potensiDesaState from '../../../_state/desa/potensi';
|
|
||||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||||
|
import potensiDesaState from '../../../_state/desa/potensi';
|
||||||
|
|
||||||
function KategoriPotensi() {
|
function KategoriPotensi() {
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
@@ -62,7 +62,6 @@ function ListKategoriPotensi({ search }: { search: string }) {
|
|||||||
<Stack>
|
<Stack>
|
||||||
<Group justify="space-between">
|
<Group justify="space-between">
|
||||||
<Title order={4}>List Kategori Potensi</Title>
|
<Title order={4}>List Kategori Potensi</Title>
|
||||||
<Tooltip label="Tambah Kategori Potensi" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconPlus size={18} />}
|
leftSection={<IconPlus size={18} />}
|
||||||
color="blue"
|
color="blue"
|
||||||
@@ -71,7 +70,6 @@ function ListKategoriPotensi({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
Tambah Baru
|
Tambah Baru
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { Dropzone } from "@mantine/dropzone";
|
import { Dropzone } from "@mantine/dropzone";
|
||||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from "@tabler/icons-react";
|
import { IconArrowBack, IconPhoto, IconUpload, IconX } from "@tabler/icons-react";
|
||||||
@@ -122,7 +121,6 @@ function EditPotensi() {
|
|||||||
return (
|
return (
|
||||||
<Box px={{ base: "sm", md: "lg" }} py="md">
|
<Box px={{ base: "sm", md: "lg" }} py="md">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -131,7 +129,6 @@ function EditPotensi() {
|
|||||||
>
|
>
|
||||||
<IconArrowBack color={colors["blue-button"]} size={24} />
|
<IconArrowBack color={colors["blue-button"]} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Potensi Desa
|
Edit Potensi Desa
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
|
||||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
|
||||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
|
||||||
import { useRouter, useParams } from 'next/navigation';
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { useProxy } from 'valtio/utils';
|
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
|
||||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||||
import potensiDesaState from '@/app/admin/(dashboard)/_state/desa/potensi';
|
import potensiDesaState from '@/app/admin/(dashboard)/_state/desa/potensi';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||||
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
export default function DetailPotensi() {
|
export default function DetailPotensi() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -108,7 +108,6 @@ export default function DetailPotensi() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<Tooltip label="Hapus Potensi" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="red"
|
color="red"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -121,9 +120,7 @@ export default function DetailPotensi() {
|
|||||||
>
|
>
|
||||||
<IconTrash size={20} />
|
<IconTrash size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip label="Edit Potensi" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="green"
|
color="green"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -135,7 +132,6 @@ export default function DetailPotensi() {
|
|||||||
>
|
>
|
||||||
<IconEdit size={20} />
|
<IconEdit size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -14,8 +14,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { Dropzone } from '@mantine/dropzone';
|
import { Dropzone } from '@mantine/dropzone';
|
||||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||||
@@ -72,11 +71,9 @@ function CreatePotensi() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Potensi Desa
|
Tambah Potensi Desa
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -76,7 +75,6 @@ function ListPotensi({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>Daftar Potensi Desa</Title>
|
<Title order={4}>Daftar Potensi Desa</Title>
|
||||||
<Tooltip label="Tambah Potensi" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconPlus size={18} />}
|
leftSection={<IconPlus size={18} />}
|
||||||
color="blue"
|
color="blue"
|
||||||
@@ -85,7 +83,6 @@ function ListPotensi({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
Tambah Baru
|
Tambah Baru
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
<Box style={{ overflowX: "auto" }}>
|
<Box style={{ overflowX: "auto" }}>
|
||||||
<Table highlightOnHover style={{ minWidth: '700px' }}>
|
<Table highlightOnHover style={{ minWidth: '700px' }}>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
|
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||||
|
import { IconCalendar, IconUser, IconUsers } from '@tabler/icons-react';
|
||||||
import { usePathname, useRouter } from 'next/navigation';
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { IconUser, IconUsers, IconCalendar } from '@tabler/icons-react';
|
|
||||||
|
|
||||||
function LayoutTabsDetail({ children }: { children: React.ReactNode }) {
|
function LayoutTabsDetail({ children }: { children: React.ReactNode }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -14,22 +14,19 @@ function LayoutTabsDetail({ children }: { children: React.ReactNode }) {
|
|||||||
label: "Profile Desa",
|
label: "Profile Desa",
|
||||||
value: "profiledesa",
|
value: "profiledesa",
|
||||||
href: "/admin/desa/profile/profile-desa",
|
href: "/admin/desa/profile/profile-desa",
|
||||||
icon: <IconUser size={18} stroke={1.8} />,
|
icon: <IconUser size={18} stroke={1.8} />
|
||||||
tooltip: "Lihat dan kelola profil desa"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Profile Perbekel",
|
label: "Profile Perbekel",
|
||||||
value: "profileperbekel",
|
value: "profileperbekel",
|
||||||
href: "/admin/desa/profile/profile-perbekel",
|
href: "/admin/desa/profile/profile-perbekel",
|
||||||
icon: <IconUsers size={18} stroke={1.8} />,
|
icon: <IconUsers size={18} stroke={1.8} />
|
||||||
tooltip: "Kelola data Perbekel"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Profile Perbekel Dari Masa Ke Masa",
|
label: "Profile Perbekel Dari Masa Ke Masa",
|
||||||
value: "profile-perbekel-dari-masa-ke-masa",
|
value: "profile-perbekel-dari-masa-ke-masa",
|
||||||
href: "/admin/desa/profile/profile-perbekel-dari-masa-ke-masa",
|
href: "/admin/desa/profile/profile-perbekel-dari-masa-ke-masa",
|
||||||
icon: <IconCalendar size={18} stroke={1.8} />,
|
icon: <IconCalendar size={18} stroke={1.8} />
|
||||||
tooltip: "Riwayat Perbekel dari masa ke masa"
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -76,42 +73,41 @@ function LayoutTabsDetail({ children }: { children: React.ReactNode }) {
|
|||||||
paddingInline: "0.5rem", // ✅ biar nggak nempel ke tepi
|
paddingInline: "0.5rem", // ✅ biar nggak nempel ke tepi
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tabs.map((tab, i) => (
|
|
||||||
<Tooltip key={i} label={tab.tooltip} position="bottom" withArrow transitionProps={{ transition: 'pop', duration: 200 }}>
|
|
||||||
<TabsTab
|
|
||||||
value={tab.value}
|
|
||||||
leftSection={tab.icon}
|
|
||||||
style={{
|
|
||||||
fontWeight: 600,
|
|
||||||
fontSize: "0.9rem",
|
|
||||||
transition: "all 0.2s ease",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{tab.label}
|
|
||||||
</TabsTab>
|
|
||||||
</Tooltip>
|
|
||||||
))}
|
|
||||||
</TabsList>
|
|
||||||
</ScrollArea>
|
|
||||||
|
|
||||||
{tabs.map((tab, i) => (
|
{tabs.map((tab, i) => (
|
||||||
<TabsPanel
|
<TabsTab
|
||||||
key={i}
|
key={i}
|
||||||
value={tab.value}
|
value={tab.value}
|
||||||
|
leftSection={tab.icon}
|
||||||
style={{
|
style={{
|
||||||
padding: "1.5rem",
|
fontWeight: 600,
|
||||||
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
|
fontSize: "0.9rem",
|
||||||
borderRadius: "1rem",
|
transition: "all 0.2s ease",
|
||||||
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Konten dummy, bisa diganti sesuai routing */}
|
{tab.label}
|
||||||
<>{children}</>
|
</TabsTab>
|
||||||
</TabsPanel>
|
|
||||||
))}
|
))}
|
||||||
</Tabs>
|
</TabsList>
|
||||||
</Stack>
|
</ScrollArea>
|
||||||
);
|
|
||||||
|
{tabs.map((tab, i) => (
|
||||||
|
<TabsPanel
|
||||||
|
key={i}
|
||||||
|
value={tab.value}
|
||||||
|
style={{
|
||||||
|
padding: "1.5rem",
|
||||||
|
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
|
||||||
|
borderRadius: "1rem",
|
||||||
|
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Konten dummy, bisa diganti sesuai routing */}
|
||||||
|
<>{children}</>
|
||||||
|
</TabsPanel>
|
||||||
|
))}
|
||||||
|
</Tabs>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LayoutTabsDetail;
|
export default LayoutTabsDetail;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
|
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||||
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
@@ -99,11 +99,9 @@ function Page() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">Edit Lambang Desa</Title>
|
<Title order={4} ml="sm" c="dark">Edit Lambang Desa</Title>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
|||||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import ApiFetch from '@/lib/api-fetch';
|
import ApiFetch from '@/lib/api-fetch';
|
||||||
import { Box, Button, Group, Image, Paper, SimpleGrid, Stack, Text, TextInput, Title, Tooltip, Center, Alert } from '@mantine/core';
|
import { Alert, Box, Button, Center, Group, Image, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||||
import { Dropzone } from '@mantine/dropzone';
|
import { Dropzone } from '@mantine/dropzone';
|
||||||
import { IconArrowBack, IconPhoto, IconUpload, IconX, IconAlertCircle } from '@tabler/icons-react';
|
import { IconAlertCircle, IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
@@ -161,11 +161,9 @@ function Page() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">Edit Maskot Desa</Title>
|
<Title order={4} ml="sm" c="dark">Edit Maskot Desa</Title>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
|
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||||
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
@@ -100,11 +100,9 @@ function Page() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">Edit Sejarah Desa</Title>
|
<Title order={4} ml="sm" c="dark">Edit Sejarah Desa</Title>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, Title, Tooltip } from '@mantine/core';
|
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, Title } from '@mantine/core';
|
||||||
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
@@ -100,11 +100,11 @@ function Page() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Button>
|
||||||
<Title order={4} ml="sm" c="dark">Edit Visi Misi Desa</Title>
|
<Title order={4} ml="sm" c="dark">Edit Visi Misi Desa</Title>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Card, Center, Divider, Grid, GridCol, Image, Paper, SimpleGrid, Stack, Text, Title, Tooltip } from '@mantine/core';
|
import { Box, Button, Card, Center, Divider, Grid, GridCol, Image, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useSnapshot } from 'valtio';
|
|
||||||
import stateProfileDesa from '../../../_state/desa/profile';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
import { IconEdit } from '@tabler/icons-react';
|
import { IconEdit } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useSnapshot } from 'valtio';
|
||||||
|
import stateProfileDesa from '../../../_state/desa/profile';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -37,7 +37,6 @@ function Page() {
|
|||||||
<Title order={3} c={colors['blue-button']}>Preview Sejarah Desa</Title>
|
<Title order={3} c={colors['blue-button']}>Preview Sejarah Desa</Title>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 1 }}>
|
<GridCol span={{ base: 12, md: 1 }}>
|
||||||
<Tooltip label="Edit Sejarah Desa" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
c="green"
|
c="green"
|
||||||
variant="light"
|
variant="light"
|
||||||
@@ -47,7 +46,6 @@ function Page() {
|
|||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
@@ -84,7 +82,6 @@ function Page() {
|
|||||||
<Title order={3} c={colors['blue-button']}>Preview Visi Misi Desa</Title>
|
<Title order={3} c={colors['blue-button']}>Preview Visi Misi Desa</Title>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 1 }}>
|
<GridCol span={{ base: 12, md: 1 }}>
|
||||||
<Tooltip label="Edit Visi Misi Desa" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
c="green"
|
c="green"
|
||||||
variant="light"
|
variant="light"
|
||||||
@@ -94,7 +91,6 @@ function Page() {
|
|||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
@@ -134,7 +130,6 @@ function Page() {
|
|||||||
<Title order={3} c={colors['blue-button']}>Preview Lambang Desa</Title>
|
<Title order={3} c={colors['blue-button']}>Preview Lambang Desa</Title>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 1 }}>
|
<GridCol span={{ base: 12, md: 1 }}>
|
||||||
<Tooltip label="Edit Lambang Desa" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
c="green"
|
c="green"
|
||||||
variant="light"
|
variant="light"
|
||||||
@@ -144,7 +139,6 @@ function Page() {
|
|||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
@@ -181,7 +175,6 @@ function Page() {
|
|||||||
<Title order={3} c={colors['blue-button']}>Preview Maskot Desa</Title>
|
<Title order={3} c={colors['blue-button']}>Preview Maskot Desa</Title>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 1 }}>
|
<GridCol span={{ base: 12, md: 1 }}>
|
||||||
<Tooltip label="Edit Maskot Desa" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
c="green"
|
c="green"
|
||||||
variant="light"
|
variant="light"
|
||||||
@@ -191,7 +184,6 @@ function Page() {
|
|||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { Dropzone } from '@mantine/dropzone';
|
import { Dropzone } from '@mantine/dropzone';
|
||||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||||
@@ -97,11 +96,9 @@ function EditPerbekelDariMasaKeMasa() {
|
|||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Perbekel Dari Masa Ke Masa
|
Edit Perbekel Dari Masa Ke Masa
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
|
||||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
|
import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -98,7 +98,6 @@ function DetailPerbekelDariMasa() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<Tooltip label="Hapus Perbekel" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="red"
|
color="red"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -111,9 +110,7 @@ function DetailPerbekelDariMasa() {
|
|||||||
>
|
>
|
||||||
<IconX size={20} />
|
<IconX size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip label="Edit Perbekel" withArrow position="top">
|
|
||||||
<Button
|
<Button
|
||||||
color="green"
|
color="green"
|
||||||
onClick={() => router.push(`/admin/desa/profile/profile-perbekel-dari-masa-ke-masa/${data.id}/edit`)}
|
onClick={() => router.push(`/admin/desa/profile/profile-perbekel-dari-masa-ke-masa/${data.id}/edit`)}
|
||||||
@@ -123,7 +120,6 @@ function DetailPerbekelDariMasa() {
|
|||||||
>
|
>
|
||||||
<IconEdit size={20} />
|
<IconEdit size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import ApiFetch from '@/lib/api-fetch';
|
import ApiFetch from '@/lib/api-fetch';
|
||||||
import { Box, Button, Group, Image, Paper, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
|
import { Box, Button, Group, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||||
import { Dropzone } from '@mantine/dropzone';
|
import { Dropzone } from '@mantine/dropzone';
|
||||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -50,11 +50,9 @@ function CreatePerbekelDariMasaKeMasa() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Back button + Title */}
|
{/* Back button + Title */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Create Perbekel Dari Masa Ke Masa
|
Create Perbekel Dari Masa Ke Masa
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title, Tooltip } from '@mantine/core';
|
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -49,7 +49,6 @@ function ListPerbekelDariMasaKeMasa({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||||
<Group justify='space-between' mb="md">
|
<Group justify='space-between' mb="md">
|
||||||
<Title order={4}>List Perbekel Dari Masa Ke Masa</Title>
|
<Title order={4}>List Perbekel Dari Masa Ke Masa</Title>
|
||||||
<Tooltip label="Tambah Perbekel Baru" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconPlus size={18} />}
|
leftSection={<IconPlus size={18} />}
|
||||||
color="blue"
|
color="blue"
|
||||||
@@ -58,7 +57,6 @@ function ListPerbekelDariMasaKeMasa({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
Tambah Baru
|
Tambah Baru
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Box style={{ overflowX: "auto" }}>
|
<Box style={{ overflowX: "auto" }}>
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
|||||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import ApiFetch from '@/lib/api-fetch';
|
import ApiFetch from '@/lib/api-fetch';
|
||||||
import { Box, Button, Center, Group, Image, Paper, Stack, Text, Title, Tooltip } from '@mantine/core';
|
import { Box, Button, Center, Group, Image, Paper, Stack, Text, Title } from '@mantine/core';
|
||||||
import { Dropzone } from '@mantine/dropzone';
|
import { Dropzone } from '@mantine/dropzone';
|
||||||
import { IconArrowBack, IconPhoto, IconUpload, IconX, IconImageInPicture } from '@tabler/icons-react';
|
import { IconArrowBack, IconImageInPicture, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
@@ -101,11 +101,9 @@ function ProfilePerbekel() {
|
|||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
|
||||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Profil Perbekel
|
Edit Profil Perbekel
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Center, Divider, Grid, GridCol, Image, Paper, Skeleton, Stack, Text, Title, Tooltip } from '@mantine/core';
|
import { Box, Button, Center, Divider, Grid, GridCol, Image, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { IconEdit } from '@tabler/icons-react';
|
import { IconEdit } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
@@ -36,7 +36,6 @@ function Page() {
|
|||||||
<Title order={3} c={colors['blue-button']}>Preview Profil PPID</Title>
|
<Title order={3} c={colors['blue-button']}>Preview Profil PPID</Title>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 1 }}>
|
<GridCol span={{ base: 12, md: 1 }}>
|
||||||
<Tooltip label="Edit Profil Perbekel" withArrow>
|
|
||||||
<Button
|
<Button
|
||||||
c="green"
|
c="green"
|
||||||
variant="light"
|
variant="light"
|
||||||
@@ -46,7 +45,6 @@ function Page() {
|
|||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@@ -2,23 +2,22 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import {
|
import {
|
||||||
|
ScrollArea,
|
||||||
Stack,
|
Stack,
|
||||||
Tabs,
|
Tabs,
|
||||||
TabsList,
|
TabsList,
|
||||||
TabsPanel,
|
TabsPanel,
|
||||||
TabsTab,
|
TabsTab,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
ScrollArea,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { usePathname, useRouter } from 'next/navigation';
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import {
|
import {
|
||||||
IconFileAnalytics,
|
|
||||||
IconCoins,
|
IconCoins,
|
||||||
|
IconFileAnalytics,
|
||||||
IconShoppingCart,
|
IconShoppingCart,
|
||||||
IconWallet,
|
IconWallet,
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
|
||||||
function LayoutTabs({ children }: { children: React.ReactNode }) {
|
function LayoutTabs({ children }: { children: React.ReactNode }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -29,29 +28,25 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
|
|||||||
label: "APB Desa",
|
label: "APB Desa",
|
||||||
value: "apbdesa",
|
value: "apbdesa",
|
||||||
href: "/admin/ekonomi/PADesa-pendapatan-asli-desa/apbdesa",
|
href: "/admin/ekonomi/PADesa-pendapatan-asli-desa/apbdesa",
|
||||||
icon: <IconFileAnalytics size={18} stroke={1.8} />,
|
icon: <IconFileAnalytics size={18} stroke={1.8} />
|
||||||
tooltip: "Lihat ringkasan Anggaran Pendapatan dan Belanja Desa",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Pendapatan",
|
label: "Pendapatan",
|
||||||
value: "pendapatan",
|
value: "pendapatan",
|
||||||
href: "/admin/ekonomi/PADesa-pendapatan-asli-desa/pendapatan",
|
href: "/admin/ekonomi/PADesa-pendapatan-asli-desa/pendapatan",
|
||||||
icon: <IconCoins size={18} stroke={1.8} />,
|
icon: <IconCoins size={18} stroke={1.8} />,
|
||||||
tooltip: "Kelola data pendapatan desa",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Belanja",
|
label: "Belanja",
|
||||||
value: "belanja",
|
value: "belanja",
|
||||||
href: "/admin/ekonomi/PADesa-pendapatan-asli-desa/belanja",
|
href: "/admin/ekonomi/PADesa-pendapatan-asli-desa/belanja",
|
||||||
icon: <IconShoppingCart size={18} stroke={1.8} />,
|
icon: <IconShoppingCart size={18} stroke={1.8} />,
|
||||||
tooltip: "Atur data belanja desa",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Pembiayaan",
|
label: "Pembiayaan",
|
||||||
value: "pembiayaan",
|
value: "pembiayaan",
|
||||||
href: "/admin/ekonomi/PADesa-pendapatan-asli-desa/pembiayaan",
|
href: "/admin/ekonomi/PADesa-pendapatan-asli-desa/pembiayaan",
|
||||||
icon: <IconWallet size={18} stroke={1.8} />,
|
icon: <IconWallet size={18} stroke={1.8} />,
|
||||||
tooltip: "Kelola data pembiayaan desa",
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -104,26 +99,19 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tabs.map((tab, i) => (
|
{tabs.map((tab, i) => (
|
||||||
<Tooltip
|
<TabsTab
|
||||||
key={i}
|
key={i}
|
||||||
label={tab.tooltip}
|
value={tab.value}
|
||||||
position="bottom"
|
leftSection={tab.icon}
|
||||||
withArrow
|
style={{
|
||||||
transitionProps={{ transition: "pop", duration: 200 }}
|
fontWeight: 600,
|
||||||
|
fontSize: "0.9rem",
|
||||||
|
transition: "all 0.2s ease",
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<TabsTab
|
{tab.label}
|
||||||
value={tab.value}
|
</TabsTab>
|
||||||
leftSection={tab.icon}
|
|
||||||
style={{
|
|
||||||
fontWeight: 600,
|
|
||||||
fontSize: "0.9rem",
|
|
||||||
transition: "all 0.2s ease",
|
|
||||||
flexShrink: 0,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{tab.label}
|
|
||||||
</TabsTab>
|
|
||||||
</Tooltip>
|
|
||||||
))}
|
))}
|
||||||
</TabsList>
|
</TabsList>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|||||||
@@ -6,15 +6,14 @@ import colors from '@/con/colors';
|
|||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
|
Group,
|
||||||
MultiSelect,
|
MultiSelect,
|
||||||
Paper,
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
Group,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
@@ -88,16 +87,14 @@ function EditAPBDesa() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button
|
||||||
<Button
|
variant="subtle"
|
||||||
variant="subtle"
|
onClick={() => router.back()}
|
||||||
onClick={() => router.back()}
|
p="xs"
|
||||||
p="xs"
|
radius="md"
|
||||||
radius="md"
|
>
|
||||||
>
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit APB Desa
|
Edit APB Desa
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||||
@@ -159,36 +158,32 @@ function DetailAPBDesa() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Group gap="sm" mt={10}>
|
<Group gap="sm" mt={10}>
|
||||||
<Tooltip label="Hapus APB Desa" withArrow position="top">
|
<Button
|
||||||
<Button
|
color="red"
|
||||||
color="red"
|
onClick={() => {
|
||||||
onClick={() => {
|
setSelectedId(data.id);
|
||||||
setSelectedId(data.id);
|
setModalHapus(true);
|
||||||
setModalHapus(true);
|
}}
|
||||||
}}
|
variant="light"
|
||||||
variant="light"
|
radius="md"
|
||||||
radius="md"
|
size="md"
|
||||||
size="md"
|
>
|
||||||
>
|
<IconTrash size={20} />
|
||||||
<IconTrash size={20} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip label="Edit APB Desa" withArrow position="top">
|
<Button
|
||||||
<Button
|
color="green"
|
||||||
color="green"
|
onClick={() =>
|
||||||
onClick={() =>
|
router.push(
|
||||||
router.push(
|
`/admin/ekonomi/PADesa-pendapatan-asli-desa/apbdesa/${data.id}/edit`
|
||||||
`/admin/ekonomi/PADesa-pendapatan-asli-desa/apbdesa/${data.id}/edit`
|
)
|
||||||
)
|
}
|
||||||
}
|
variant="light"
|
||||||
variant="light"
|
radius="md"
|
||||||
radius="md"
|
size="md"
|
||||||
size="md"
|
>
|
||||||
>
|
<IconEdit size={20} />
|
||||||
<IconEdit size={20} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
@@ -43,11 +42,9 @@ function CreateAPBDesa() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah APB Desa
|
Tambah APB Desa
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Center,
|
Center,
|
||||||
Group,
|
Group,
|
||||||
Paper,
|
|
||||||
Pagination,
|
Pagination,
|
||||||
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Table,
|
Table,
|
||||||
@@ -15,8 +15,7 @@ import {
|
|||||||
TableTh,
|
TableTh,
|
||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||||
@@ -82,20 +81,18 @@ function ListAPBDesa({ search }: { search: string }) {
|
|||||||
<Text fw={600} fz="lg">
|
<Text fw={600} fz="lg">
|
||||||
List APB Desa
|
List APB Desa
|
||||||
</Text>
|
</Text>
|
||||||
<Tooltip label="Tambah APB Desa" withArrow>
|
<Button
|
||||||
<Button
|
leftSection={<IconPlus size={18} />}
|
||||||
leftSection={<IconPlus size={18} />}
|
color="blue"
|
||||||
color="blue"
|
variant="light"
|
||||||
variant="light"
|
onClick={() =>
|
||||||
onClick={() =>
|
router.push(
|
||||||
router.push(
|
"/admin/ekonomi/PADesa-pendapatan-asli-desa/apbdesa/create"
|
||||||
"/admin/ekonomi/PADesa-pendapatan-asli-desa/apbdesa/create"
|
)
|
||||||
)
|
}
|
||||||
}
|
>
|
||||||
>
|
Tambah Baru
|
||||||
Tambah Baru
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
<Box style={{ overflowX: "auto" }}>
|
<Box style={{ overflowX: "auto" }}>
|
||||||
<Table highlightOnHover>
|
<Table highlightOnHover>
|
||||||
@@ -138,20 +135,18 @@ function ListAPBDesa({ search }: { search: string }) {
|
|||||||
)}
|
)}
|
||||||
</TableTd>
|
</TableTd>
|
||||||
<TableTd>
|
<TableTd>
|
||||||
<Tooltip label="Lihat Detail" withArrow>
|
<Button
|
||||||
<Button
|
variant="light"
|
||||||
variant="light"
|
color="green"
|
||||||
color="green"
|
onClick={() =>
|
||||||
onClick={() =>
|
router.push(
|
||||||
router.push(
|
`/admin/ekonomi/PADesa-pendapatan-asli-desa/apbdesa/${item.id}`
|
||||||
`/admin/ekonomi/PADesa-pendapatan-asli-desa/apbdesa/${item.id}`
|
)
|
||||||
)
|
}
|
||||||
}
|
>
|
||||||
>
|
<IconDeviceImacCog size={20} />
|
||||||
<IconDeviceImacCog size={20} />
|
<Text ml={5}>Detail</Text>
|
||||||
<Text ml={5}>Detail</Text>
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</TableTd>
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -90,16 +89,14 @@ function EditBelanja() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button
|
||||||
<Button
|
variant="subtle"
|
||||||
variant="subtle"
|
onClick={() => router.back()}
|
||||||
onClick={() => router.back()}
|
p="xs"
|
||||||
p="xs"
|
radius="md"
|
||||||
radius="md"
|
>
|
||||||
>
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Jenis Belanja
|
Edit Jenis Belanja
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -10,13 +10,12 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useProxy } from 'valtio/utils';
|
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function CreateBelanja() {
|
function CreateBelanja() {
|
||||||
const belanjaState = useProxy(PendapatanAsliDesa.belanja);
|
const belanjaState = useProxy(PendapatanAsliDesa.belanja);
|
||||||
@@ -57,16 +56,14 @@ function CreateBelanja() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header dengan back button */}
|
{/* Header dengan back button */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button
|
||||||
<Button
|
variant="subtle"
|
||||||
variant="subtle"
|
onClick={() => router.back()}
|
||||||
onClick={() => router.back()}
|
p="xs"
|
||||||
p="xs"
|
radius="md"
|
||||||
radius="md"
|
>
|
||||||
>
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Jenis Belanja
|
Tambah Jenis Belanja
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
@@ -96,18 +95,16 @@ function ListBelanja({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>Daftar Belanja</Title>
|
<Title order={4}>Daftar Belanja</Title>
|
||||||
<Tooltip label="Tambah Belanja" withArrow>
|
<Button
|
||||||
<Button
|
leftSection={<IconPlus size={18} />}
|
||||||
leftSection={<IconPlus size={18} />}
|
color="blue"
|
||||||
color="blue"
|
variant="light"
|
||||||
variant="light"
|
onClick={() =>
|
||||||
onClick={() =>
|
router.push('/admin/ekonomi/PADesa-pendapatan-asli-desa/belanja/create')
|
||||||
router.push('/admin/ekonomi/PADesa-pendapatan-asli-desa/belanja/create')
|
}
|
||||||
}
|
>
|
||||||
>
|
Tambah Baru
|
||||||
Tambah Baru
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
@@ -138,34 +135,30 @@ function ListBelanja({ search }: { search: string }) {
|
|||||||
</TableTd>
|
</TableTd>
|
||||||
<TableTd>
|
<TableTd>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<Tooltip label="Edit" withArrow>
|
<Button
|
||||||
<Button
|
size="xs"
|
||||||
size="xs"
|
variant="light"
|
||||||
variant="light"
|
color="green"
|
||||||
color="green"
|
onClick={() =>
|
||||||
onClick={() =>
|
router.push(
|
||||||
router.push(
|
`/admin/ekonomi/PADesa-pendapatan-asli-desa/belanja/${item.id}`
|
||||||
`/admin/ekonomi/PADesa-pendapatan-asli-desa/belanja/${item.id}`
|
)
|
||||||
)
|
}
|
||||||
}
|
>
|
||||||
>
|
<IconEdit size={16} />
|
||||||
<IconEdit size={16} />
|
</Button>
|
||||||
</Button>
|
<Button
|
||||||
</Tooltip>
|
size="xs"
|
||||||
<Tooltip label="Hapus" withArrow>
|
variant="light"
|
||||||
<Button
|
color="red"
|
||||||
size="xs"
|
disabled={belanjaState.delete.loading}
|
||||||
variant="light"
|
onClick={() => {
|
||||||
color="red"
|
setSelectedId(item.id);
|
||||||
disabled={belanjaState.delete.loading}
|
setModalHapus(true);
|
||||||
onClick={() => {
|
}}
|
||||||
setSelectedId(item.id);
|
>
|
||||||
setModalHapus(true);
|
<IconTrash size={16} />
|
||||||
}}
|
</Button>
|
||||||
>
|
|
||||||
<IconTrash size={16} />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -87,16 +86,14 @@ function EditPembiayaan() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button
|
||||||
<Button
|
variant="subtle"
|
||||||
variant="subtle"
|
onClick={() => router.back()}
|
||||||
onClick={() => router.back()}
|
p="xs"
|
||||||
p="xs"
|
radius="md"
|
||||||
radius="md"
|
>
|
||||||
>
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Jenis Pembiayaan
|
Edit Jenis Pembiayaan
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import React from 'react';
|
|
||||||
import { useProxy } from 'valtio/utils';
|
|
||||||
import PendapatanAsliDesa from '@/app/admin/(dashboard)/_state/ekonomi/PADesa';
|
import PendapatanAsliDesa from '@/app/admin/(dashboard)/_state/ekonomi/PADesa';
|
||||||
import { useRouter } from 'next/navigation';
|
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
@@ -10,13 +7,14 @@ import {
|
|||||||
Group,
|
Group,
|
||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
Title,
|
|
||||||
TextInput,
|
|
||||||
Text,
|
Text,
|
||||||
Tooltip,
|
TextInput,
|
||||||
|
Title
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function CreatePembiayaan() {
|
function CreatePembiayaan() {
|
||||||
const pembiayaanState = useProxy(PendapatanAsliDesa.pembiayaan);
|
const pembiayaanState = useProxy(PendapatanAsliDesa.pembiayaan);
|
||||||
@@ -57,16 +55,14 @@ function CreatePembiayaan() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button
|
||||||
<Button
|
variant="subtle"
|
||||||
variant="subtle"
|
onClick={() => router.back()}
|
||||||
onClick={() => router.back()}
|
p="xs"
|
||||||
p="xs"
|
radius="md"
|
||||||
radius="md"
|
>
|
||||||
>
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Jenis Pembiayaan
|
Tambah Jenis Pembiayaan
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
import colors from '@/con/colors';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Center,
|
Center,
|
||||||
Group,
|
Group,
|
||||||
|
Pagination,
|
||||||
Paper,
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
@@ -14,19 +16,16 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
Pagination,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import React, { useState } from 'react';
|
|
||||||
import HeaderSearch from '../../../_com/header';
|
|
||||||
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
|
||||||
import PendapatanAsliDesa from '../../../_state/ekonomi/PADesa';
|
|
||||||
import { useProxy } from 'valtio/utils';
|
|
||||||
import { useRouter } from 'next/navigation';
|
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import colors from '@/con/colors';
|
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import HeaderSearch from '../../../_com/header';
|
||||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||||
|
import PendapatanAsliDesa from '../../../_state/ekonomi/PADesa';
|
||||||
|
|
||||||
function Pembiayaan() {
|
function Pembiayaan() {
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
@@ -95,18 +94,16 @@ function ListPembiayaan({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>Daftar Pembiayaan</Title>
|
<Title order={4}>Daftar Pembiayaan</Title>
|
||||||
<Tooltip label="Tambah Pembiayaan" withArrow>
|
<Button
|
||||||
<Button
|
leftSection={<IconPlus size={18} />}
|
||||||
leftSection={<IconPlus size={18} />}
|
color="blue"
|
||||||
color="blue"
|
variant="light"
|
||||||
variant="light"
|
onClick={() =>
|
||||||
onClick={() =>
|
router.push('/admin/ekonomi/PADesa-pendapatan-asli-desa/pembiayaan/create')
|
||||||
router.push('/admin/ekonomi/PADesa-pendapatan-asli-desa/pembiayaan/create')
|
}
|
||||||
}
|
>
|
||||||
>
|
Tambah Baru
|
||||||
Tambah Baru
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -94,16 +93,14 @@ function EditPendapatan() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header with Back Button */}
|
{/* Header with Back Button */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button
|
||||||
<Button
|
variant="subtle"
|
||||||
variant="subtle"
|
onClick={() => router.back()}
|
||||||
onClick={() => router.back()}
|
p="xs"
|
||||||
p="xs"
|
radius="md"
|
||||||
radius="md"
|
>
|
||||||
>
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Jenis Pendapatan
|
Edit Jenis Pendapatan
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -49,16 +48,14 @@ function CreatePendapatan() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header dengan tombol back + judul */}
|
{/* Header dengan tombol back + judul */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button
|
||||||
<Button
|
variant="subtle"
|
||||||
variant="subtle"
|
onClick={() => router.back()}
|
||||||
onClick={() => router.back()}
|
p="xs"
|
||||||
p="xs"
|
radius="md"
|
||||||
radius="md"
|
>
|
||||||
>
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Jenis Pendapatan
|
Tambah Jenis Pendapatan
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
@@ -96,18 +95,16 @@ function ListPendapatan({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>Daftar Pendapatan</Title>
|
<Title order={4}>Daftar Pendapatan</Title>
|
||||||
<Tooltip label="Tambah Pendapatan Baru" withArrow>
|
<Button
|
||||||
<Button
|
leftSection={<IconPlus size={18} />}
|
||||||
leftSection={<IconPlus size={18} />}
|
color="blue"
|
||||||
color="blue"
|
variant="light"
|
||||||
variant="light"
|
onClick={() =>
|
||||||
onClick={() =>
|
router.push('/admin/ekonomi/PADesa-pendapatan-asli-desa/pendapatan/create')
|
||||||
router.push('/admin/ekonomi/PADesa-pendapatan-asli-desa/pendapatan/create')
|
}
|
||||||
}
|
>
|
||||||
>
|
Tambah Baru
|
||||||
Tambah Baru
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
|
|||||||
@@ -9,12 +9,11 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState, useCallback } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import demografiPekerjaan from '../../../_state/ekonomi/demografi-pekerjaan';
|
import demografiPekerjaan from '../../../_state/ekonomi/demografi-pekerjaan';
|
||||||
@@ -96,16 +95,14 @@ export default function EditDemografiPekerjaan() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button
|
||||||
<Button
|
variant="subtle"
|
||||||
variant="subtle"
|
onClick={() => router.back()}
|
||||||
onClick={() => router.back()}
|
p="xs"
|
||||||
p="xs"
|
radius="md"
|
||||||
radius="md"
|
>
|
||||||
>
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Edit Demografi Pekerjaan
|
Edit Demografi Pekerjaan
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Stack,
|
Stack,
|
||||||
TextInput,
|
TextInput,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowBack } from '@tabler/icons-react';
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -49,16 +48,14 @@ function CreateDemografiPekerjaan() {
|
|||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
<Button
|
||||||
<Button
|
variant="subtle"
|
||||||
variant="subtle"
|
onClick={() => router.back()}
|
||||||
onClick={() => router.back()}
|
p="xs"
|
||||||
p="xs"
|
radius="md"
|
||||||
radius="md"
|
>
|
||||||
>
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={4} ml="sm" c="dark">
|
||||||
Tambah Demografi Pekerjaan
|
Tambah Demografi Pekerjaan
|
||||||
</Title>
|
</Title>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { BarChart } from '@mantine/charts';
|
import { BarChart } from '@mantine/charts';
|
||||||
@@ -5,7 +6,9 @@ import {
|
|||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Center,
|
Center,
|
||||||
|
Flex,
|
||||||
Group,
|
Group,
|
||||||
|
Pagination,
|
||||||
Paper,
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
@@ -16,10 +19,7 @@ import {
|
|||||||
TableThead,
|
TableThead,
|
||||||
TableTr,
|
TableTr,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title
|
||||||
Tooltip,
|
|
||||||
Pagination,
|
|
||||||
Flex,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
@@ -85,7 +85,7 @@ function ListDemografiPekerjaan({ search }: { search: string }) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
setChartData(
|
setChartData(
|
||||||
data.map((item) => ({
|
data.map((item: any) => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
pekerjaan: item.pekerjaan,
|
pekerjaan: item.pekerjaan,
|
||||||
lakiLaki: Number(item.lakiLaki),
|
lakiLaki: Number(item.lakiLaki),
|
||||||
@@ -110,16 +110,14 @@ function ListDemografiPekerjaan({ search }: { search: string }) {
|
|||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb="md">
|
||||||
<Title order={4}>List Demografi Pekerjaan</Title>
|
<Title order={4}>List Demografi Pekerjaan</Title>
|
||||||
<Tooltip label="Tambah Data Pekerjaan" withArrow>
|
<Button
|
||||||
<Button
|
leftSection={<IconPlus size={18} />}
|
||||||
leftSection={<IconPlus size={18} />}
|
color="blue"
|
||||||
color="blue"
|
variant="light"
|
||||||
variant="light"
|
onClick={() => router.push('/admin/ekonomi/demografi-pekerjaan/create')}
|
||||||
onClick={() => router.push('/admin/ekonomi/demografi-pekerjaan/create')}
|
>
|
||||||
>
|
Tambah Baru
|
||||||
Tambah Baru
|
</Button>
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user