Compare commits
3 Commits
nico/6-may
...
nico/13-ma
| Author | SHA1 | Date | |
|---|---|---|---|
| 2844132ea0 | |||
| e5889ca903 | |||
| 8a34a122d0 |
@@ -16,6 +16,7 @@
|
||||
"@cubejs-client/core": "^0.31.0",
|
||||
"@elysiajs/cors": "^1.2.0",
|
||||
"@elysiajs/eden": "^1.2.0",
|
||||
"@elysiajs/static": "^1.3.0",
|
||||
"@elysiajs/stream": "^1.1.0",
|
||||
"@elysiajs/swagger": "^1.2.0",
|
||||
"@mantine/carousel": "^7.16.2",
|
||||
|
||||
5
prisma/data/list-caraMemperolehInformasi.json
Normal file
5
prisma/data/list-caraMemperolehInformasi.json
Normal file
@@ -0,0 +1,5 @@
|
||||
[
|
||||
{"name": "Melihat/Membaca/Mendengarkan/Mencatat"},
|
||||
{"name": "Mendapatkan Salinan Informasi (Hardcopy)"},
|
||||
{"name": "Mendapatkan Salinan Informasi (Softcopy)"}
|
||||
]
|
||||
5
prisma/data/list-caraMemperolehSalinanInformasi.json
Normal file
5
prisma/data/list-caraMemperolehSalinanInformasi.json
Normal file
@@ -0,0 +1,5 @@
|
||||
[
|
||||
{ "name": "Mengambil Langsung" },
|
||||
{ "name": "Dikirim Via Post" },
|
||||
{ "name": "Dikirim Via Email" }
|
||||
]
|
||||
6
prisma/data/list-jenisInfromasi.json
Normal file
6
prisma/data/list-jenisInfromasi.json
Normal file
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{ "name": "Keuangan Desa" },
|
||||
{ "name": "Pembangunan Desa" },
|
||||
{ "name": "Data Demografi" },
|
||||
{ "name": "Lainnya" }
|
||||
]
|
||||
7
prisma/data/ppid/dasar-hukum-ppid/dasarhukumPPID.json
Normal file
7
prisma/data/ppid/dasar-hukum-ppid/dasarhukumPPID.json
Normal file
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"judul": "DASAR HUKUM PEMBENTUKAN PPID DESA DARMASABA",
|
||||
"content" : "<ul><li>UU Nomor 14 Tahun 2008 tentang Keterbukaan Informasi Publik</li><li>PP Nomor 61 Tahun 2010 tentang Pelaksanaan UU 14 Tahun 2008 tentang Keterbukaan Informasi Publik</li><li>Permendagri Nomor 3 Tahun 2017 tentang Pedoman Pengelolaan Pelayanan Informasi dan Dokumentasi di Lingkungan Kemendagri dan Pemerintah Daerah</li><li>Peraturan Komisi Informasi Nomor 1 Tahun 2010 tentang Standar Layanan Informasi Publik</li><li>Peraturan Komisi Informasi Nomor 1 Tahun 2010 tentang Standar Layanan Informasi Publik</li><li>Peraturan Bupati Badung No. 42 Tahun 2017 tentang Pedoman Pengelolaan Pelayanan Informasi Publik dan Dokumentasi di Lingkungan Pemerintah Kabupaten Badung</li><li>Keputusan Bupati Badung Nomor 99/049/HK/2019 tentang Pengelola Layanan Informasi dan Dokumentasi Kabupaten Badung</li><li>Keputusan Perbekel Darmasaba Nomor 101 Tahun 2019 tentang Penetapan Pelaksana Teknis/Administrasi Pengelola Layanan Informasi Dan Dokumentasi di Desa Punggul</li><li>Peraturan Perbekel Darmasaba Nomor 12 Tahun 2019 tentang Pedoman Pengelolaan Pelayanan Informasi Publik dan Dokumentasi di Lingkungan Pemerintah Desa Darmasaba</li></ul>"
|
||||
}
|
||||
]
|
||||
11
prisma/data/ppid/profile-ppid/profilePPid.json
Normal file
11
prisma/data/ppid/profile-ppid/profilePPid.json
Normal file
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"name": "I.B Surya Prabhawa Manuaba, S.H., M.H.",
|
||||
"biodata": "<p>I.B Surya Prabhawa Manuaba, S.H., M.H., adalah Perbekel Darmasaba periode 2021-2027, seorang advokat, pendiri Mantra Legal Consultants & Advocates, serta aktif di bidang musik dan akademis. Dia menempuh pendidikan hukum di Universitas Udayana dan Universitas Mahasaraswati Denpasar, serta memiliki pengalaman luas di berbagai organisasi dan kepemimpinan.</p>",
|
||||
"riwayat": "<ul> <li>2021 - 2027: Perbekel Desa Darmasaba</li> <li>2015 - Sekarang: Founder & Managing Director Mantra Legal Consultants & Advocates</li> <li>2020 - Sekarang: Founder Ugawa Record Music Studio</li> <li>2010 - 2016: Dosen Fakultas Hukum Universitas Mahasaraswati Denpasar</li> </ul>",
|
||||
"pengalaman": "<ul> <li>1996 – 1997: Ketua OSIS SMP Negeri 1 Abiansemal</li><li>1999 – 2000: Ketua OSIS SMA Negeri 1 Mengwi</li> <li>2008 – 2009: Ketua BEM Universitas Mahasaraswati Denpasar</li> <li>2008 – 2010: Ketua Sekaa Taruna Sila Dharma, Banjar Tengah, Desa Adat Tegal, Darmasaba</li> <li>2020 – Sekarang: Pengurus Young Lawyer Committee Peradi Denpasar</li> <li>2021 – Sekarang: Dewan Kehormatan Himpunan Pengusaha Muda Indonesia (HIPMI) Badung</li> <li>2023 – 2028: Komite Tetap Advokasi – Bidang Hukum dan Regulasi Kamar Dagang dan Industri Badung</li> </ul>",
|
||||
"unggulan": "<h3>Pemberdayaan Ekonomi dan UMKM</h3> <ul> <li>Pelatihan dan pendampingan UMKM lokal</li> <li>Program bantuan modal usaha bagi pelaku usaha kecil</li><li>Digitalisasi UMKM untuk meningkatkan pemasaran produk lokal</li></ul>",
|
||||
"imageUrl": "/assets/images/ppid/profile-ppid/perbekel.png"
|
||||
}
|
||||
]
|
||||
8
prisma/data/ppid/visi-misi-ppid/visimisiPPID.json
Normal file
8
prisma/data/ppid/visi-misi-ppid/visimisiPPID.json
Normal file
@@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"misi": "<ol><li>Meningkatkan pengelolaan dan pelayanan informasi yang berkualitas, benar dan bertanggung jawab.</li><li>Membangun dan mengembangkan sistem penyediaan dan layanan informasi.</li><li>Meningkatkan dan mengembangkan kompetensi dan kualitas SDM dalam bidang pelayanan informasi.</li><li>Mewujudkan keterbukaan informasi Pemerintah Desa Punggul dengan proses yang cepat, tepat, mudah dan sederhana.</li></ol>",
|
||||
"visi": "Memberikan pelayanan informasi yanng transparan dan akuntabel untuk memenuhi hak pemohon informasi sesuai dengan ketentuan peraturan perundang-undangan yang berlaku."
|
||||
|
||||
}
|
||||
]
|
||||
@@ -48,6 +48,43 @@ model AppMenuChild {
|
||||
}
|
||||
|
||||
//========================================= MENU PPID ========================================= //
|
||||
// ========================================= VISI MISI PPID ========================================= //
|
||||
model VisiMisiPPID {
|
||||
id String @id @default(cuid())
|
||||
visi String @db.Text
|
||||
misi String @db.Text
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
// ========================================= DASAR HUKUM PPID ========================================= //
|
||||
model DasarHukumPPID {
|
||||
id String @id @default(cuid())
|
||||
judul String @db.Text
|
||||
content String @db.Text
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
// ========================================= PROFILE PPID ========================================= //
|
||||
model ProfilePPID {
|
||||
id String @id @default(cuid())
|
||||
name String @db.Text
|
||||
biodata String @db.Text
|
||||
riwayat String @db.Text
|
||||
pengalaman String @db.Text
|
||||
unggulan String @db.Text
|
||||
imageUrl String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
// ========================================= DAFTAR INFORMASI PUBLIK ========================================= //
|
||||
model DaftarInformasiPublik {
|
||||
id String @id @default(cuid())
|
||||
@@ -61,7 +98,70 @@ model DaftarInformasiPublik {
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
//========================================= MENU PPID ========================================= //
|
||||
//=========================================PERMOHONAN INFORMASI PUBLIK========================= //
|
||||
model PermohonanInformasiPublik {
|
||||
id String @id @default(cuid())
|
||||
nomor Int @default(autoincrement())
|
||||
name String
|
||||
nik String
|
||||
notelp String
|
||||
alamat String
|
||||
email String
|
||||
jenisInformasiDiminta JenisInformasiDiminta? @relation(fields: [jenisInformasiDimintaId], references: [id])
|
||||
jenisInformasiDimintaId String?
|
||||
caraMemperolehInformasi CaraMemperolehInformasi? @relation(fields: [caraMemperolehInformasiId], references: [id])
|
||||
caraMemperolehInformasiId String?
|
||||
caraMemperolehSalinanInformasi CaraMemperolehSalinanInformasi? @relation(fields: [caraMemperolehSalinanInformasiId], references: [id])
|
||||
caraMemperolehSalinanInformasiId String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
model JenisInformasiDiminta {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
PermohonanInformasiPublik PermohonanInformasiPublik[]
|
||||
}
|
||||
|
||||
model CaraMemperolehInformasi {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
PermohonanInformasiPublik PermohonanInformasiPublik[]
|
||||
}
|
||||
|
||||
model CaraMemperolehSalinanInformasi {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
PermohonanInformasiPublik PermohonanInformasiPublik[]
|
||||
}
|
||||
|
||||
//=========================================PERMOHONAN INFORMASI KEBERATAN PUBLIK========================= //
|
||||
model FormulirPermohonanKeberatan {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
email String
|
||||
notelp String
|
||||
alasan String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime @default(now())
|
||||
isActive Boolean @default(true)
|
||||
}
|
||||
|
||||
// ========================================= IKM ========================================= //
|
||||
model IndeksKepuasanMasyarakat {
|
||||
id Int @id @default(autoincrement())
|
||||
|
||||
120
prisma/seed.ts
120
prisma/seed.ts
@@ -1,8 +1,14 @@
|
||||
import prisma from '@/lib/prisma'
|
||||
import categoryPengumuman from './data/category-pengumuman.json'
|
||||
import katagoryBerita from './data/katagory-berita.json'
|
||||
import caraMemperolehInformasi from './data/list-caraMemperolehInformasi.json'
|
||||
import caraMemperolehSalinanInformasi from './data/list-caraMemperolehSalinanInformasi.json'
|
||||
import jenisInformasiDiminta from './data/list-jenisInfromasi.json'
|
||||
import layanan from './data/list-layanan.json'
|
||||
import potensi from './data/list-potensi.json'
|
||||
import katagoryBerita from './data/katagory-berita.json'
|
||||
import categoryPengumuman from './data/category-pengumuman.json'
|
||||
import prisma from '@/lib/prisma';
|
||||
import profilePPID from './data/ppid/profile-ppid/profilePPid.json'
|
||||
import visiMisiPPID from './data/ppid/visi-misi-ppid/visimisiPPID.json'
|
||||
import dasarHukumPPID from './data/ppid/dasar-hukum-ppid/dasarhukumPPID.json'
|
||||
(async () => {
|
||||
for (const l of layanan) {
|
||||
await prisma.layanan.upsert({
|
||||
@@ -67,6 +73,114 @@ import prisma from '@/lib/prisma';
|
||||
}
|
||||
|
||||
console.log("category pengumuman success ...")
|
||||
|
||||
for (const j of jenisInformasiDiminta) {
|
||||
await prisma.jenisInformasiDiminta.upsert({
|
||||
where: {
|
||||
name: j.name
|
||||
},
|
||||
update: {
|
||||
name: j.name
|
||||
},
|
||||
create: {
|
||||
name: j.name
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log("jenis informasi diminta success ...")
|
||||
|
||||
for (const c of caraMemperolehInformasi) {
|
||||
await prisma.caraMemperolehInformasi.upsert({
|
||||
where: {
|
||||
name: c.name
|
||||
},
|
||||
update: {
|
||||
name: c.name
|
||||
},
|
||||
create: {
|
||||
name: c.name
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log("cara memperoleh informasi success ...")
|
||||
|
||||
for (const c of caraMemperolehSalinanInformasi) {
|
||||
await prisma.caraMemperolehSalinanInformasi.upsert({
|
||||
where: {
|
||||
name: c.name
|
||||
},
|
||||
update: {
|
||||
name: c.name
|
||||
},
|
||||
create: {
|
||||
name: c.name
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log("cara memperoleh salinan informasi success ...")
|
||||
|
||||
for (const c of profilePPID) {
|
||||
await prisma.profilePPID.upsert({
|
||||
where: {
|
||||
id: c.id
|
||||
},
|
||||
update: {
|
||||
name: c.name,
|
||||
biodata: c.biodata,
|
||||
riwayat: c.riwayat,
|
||||
pengalaman: c.pengalaman,
|
||||
unggulan: c.unggulan,
|
||||
imageUrl: c.imageUrl
|
||||
},
|
||||
create: {
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
biodata: c.biodata,
|
||||
riwayat: c.riwayat,
|
||||
pengalaman: c.pengalaman,
|
||||
unggulan: c.unggulan,
|
||||
imageUrl: c.imageUrl
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log("profile PPID success ...")
|
||||
|
||||
for (const v of visiMisiPPID) {
|
||||
await prisma.visiMisiPPID.upsert({
|
||||
where: {
|
||||
id: v.id,
|
||||
},
|
||||
update: {
|
||||
misi: v.misi,
|
||||
visi: v.visi
|
||||
},
|
||||
create: {
|
||||
id: v.id,
|
||||
misi: v.misi,
|
||||
visi: v.visi
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log("visi misi PPID success ...")
|
||||
|
||||
for (const v of dasarHukumPPID) {
|
||||
await prisma.dasarHukumPPID.upsert({
|
||||
where: {
|
||||
id: v.id,
|
||||
},
|
||||
update: {
|
||||
judul: v.judul,
|
||||
content: v.content
|
||||
},
|
||||
create: {
|
||||
id: v.id,
|
||||
judul: v.judul,
|
||||
content: v.content
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log("dasar hukum PPID success ...")
|
||||
|
||||
})().then(() => prisma.$disconnect()).catch((e) => {
|
||||
console.error(e)
|
||||
prisma.$disconnect()
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 275 KiB |
@@ -87,4 +87,4 @@ const stateDashboardBerita = proxy({
|
||||
berita,
|
||||
});
|
||||
|
||||
export default stateDashboardBerita;
|
||||
export default stateDashboardBerita;
|
||||
@@ -0,0 +1,82 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
judul: z.string().min(3, "Judul minimal 3 karakter"),
|
||||
content: z.string().min(3, "Content minimal 3 karakter"),
|
||||
});
|
||||
|
||||
type DasarHukumForm = Prisma.DasarHukumPPIDGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
judul: true;
|
||||
content: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const stateDasarHukumPPID = proxy({
|
||||
findById: {
|
||||
data: null as DasarHukumForm | null,
|
||||
loading: false,
|
||||
initialize() {
|
||||
stateDasarHukumPPID.findById.data = {
|
||||
id: '',
|
||||
judul: '',
|
||||
content: '',
|
||||
} as DasarHukumForm;
|
||||
},
|
||||
async load(id: string) {
|
||||
try {
|
||||
stateDasarHukumPPID.findById.loading = true;
|
||||
const res = await ApiFetch.api.ppid.dasarhukumppid["find-by-id"].get({
|
||||
query: { id },
|
||||
});
|
||||
if (res.status === 200) {
|
||||
stateDasarHukumPPID.findById.data = res.data?.data ?? null;
|
||||
} else {
|
||||
toast.error("Gagal mengambil data dasar hukum");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat mengambil data dasar hukum");
|
||||
} finally {
|
||||
stateDasarHukumPPID.findById.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
update: {
|
||||
loading: false,
|
||||
async save(data: DasarHukumForm) {
|
||||
const cek = templateForm.safeParse(data);
|
||||
if (!cek.success) {
|
||||
const errors = cek.error.issues
|
||||
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
||||
.join(", ");
|
||||
toast.error(`Form tidak valid: ${errors}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
stateDasarHukumPPID.update.loading = true;
|
||||
const res = await ApiFetch.api.ppid.dasarhukumppid["update"].post(data);
|
||||
if (res.status === 200) {
|
||||
toast.success("Data dasar hukum berhasil diubah");
|
||||
await stateDasarHukumPPID.findById.load(data.id);
|
||||
} else {
|
||||
toast.error("Gagal mengubah data dasar hukum");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat mengubah data dasar hukum");
|
||||
} finally {
|
||||
stateDasarHukumPPID.update.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default stateDasarHukumPPID;
|
||||
@@ -0,0 +1,120 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
nik: z.string().min(3, "NIK minimal 3 karakter"),
|
||||
notelp: z.string().min(3, "Nomor Telepon minimal 3 karakter"),
|
||||
alamat: z.string().min(3, "Alamat minimal 3 karakter"),
|
||||
email: z.string().min(3, "Email minimal 3 karakter"),
|
||||
jenisInformasiDimintaId: z.string().nonempty(),
|
||||
caraMemperolehInformasiId: z.string().nonempty(),
|
||||
caraMemperolehSalinanInformasiId: z.string().nonempty(),
|
||||
})
|
||||
|
||||
const jenisInformasiDiminta = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| null
|
||||
| Prisma.JenisInformasiDimintaGetPayload<{ omit: { isActive: true } }>[],
|
||||
async load(){
|
||||
const res = await ApiFetch.api.ppid.permohonaninformasipublik.jenisInformasi["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
jenisInformasiDiminta.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const caraMemperolehInformasi = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| null
|
||||
| Prisma.CaraMemperolehInformasiGetPayload<{ omit: { isActive: true } }>[],
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ppid.permohonaninformasipublik.memperolehInformasi["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
caraMemperolehInformasi.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const caraMemperolehSalinanInformasi = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| null
|
||||
| Prisma.CaraMemperolehSalinanInformasiGetPayload<{ omit: { isActive: true } }>[],
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ppid.permohonaninformasipublik.salinanInformasi["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
caraMemperolehSalinanInformasi.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
type PermohonanInformasiPublikForm = Prisma.PermohonanInformasiPublikGetPayload<{
|
||||
select: {
|
||||
name: true;
|
||||
nik: true;
|
||||
notelp: true;
|
||||
alamat: true;
|
||||
email: true;
|
||||
jenisInformasiDimintaId: true;
|
||||
caraMemperolehInformasiId: true;
|
||||
caraMemperolehSalinanInformasiId: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const permohonanInformasiPublikForm = proxy({
|
||||
create: {
|
||||
form: {} as PermohonanInformasiPublikForm,
|
||||
loading: false,
|
||||
async create(){
|
||||
const cek = templateForm.safeParse(permohonanInformasiPublikForm.create.form);
|
||||
if(!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
permohonanInformasiPublikForm.create.loading = true;
|
||||
const res = await ApiFetch.api.ppid.permohonaninformasipublik["create"].post(permohonanInformasiPublikForm.create.form);
|
||||
if (res.status === 200) {
|
||||
permohonanInformasiPublikForm.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
permohonanInformasiPublikForm.create.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PermohonanInformasiPublikGetPayload<{ omit: { isActive: true } }>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ppid.permohonaninformasipublik["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
permohonanInformasiPublikForm.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const statePermohonanInformasi = proxy({
|
||||
permohonanInformasiPublikForm,
|
||||
jenisInformasiDiminta,
|
||||
caraMemperolehInformasi,
|
||||
caraMemperolehSalinanInformasi
|
||||
})
|
||||
|
||||
export default statePermohonanInformasi;
|
||||
@@ -0,0 +1,68 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
email: z.string().min(3, "Email minimal 3 karakter"),
|
||||
notelp: z.string().min(3, "Nomor Telepon minimal 3 karakter"),
|
||||
alasan: z.string().min(3, "Alasan minimal 3 karakter"),
|
||||
})
|
||||
|
||||
type PermohonanKeberatanInformasiForm = Prisma.FormulirPermohonanKeberatanGetPayload<{
|
||||
select: {
|
||||
name: true;
|
||||
email: true;
|
||||
notelp: true;
|
||||
alasan: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const permohonanKeberatanInformasiForm = proxy({
|
||||
create: {
|
||||
form: {} as PermohonanKeberatanInformasiForm,
|
||||
loading: false,
|
||||
async create(){
|
||||
const cek = templateForm.safeParse(permohonanKeberatanInformasiForm.create.form);
|
||||
if(!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
permohonanKeberatanInformasiForm.create.loading = true;
|
||||
const res = await ApiFetch.api.ppid.permohonankeberataninformasipublik["create"].post(permohonanKeberatanInformasiForm.create.form);
|
||||
if (res.status === 200) {
|
||||
permohonanKeberatanInformasiForm.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
permohonanKeberatanInformasiForm.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.FormulirPermohonanKeberatanGetPayload<{omit: {isActive: true}}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ppid.permohonankeberataninformasipublik["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
permohonanKeberatanInformasiForm.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const statePermohonanKeberatan = proxy({
|
||||
permohonanKeberatanInformasiForm,
|
||||
})
|
||||
|
||||
export default statePermohonanKeberatan;
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
// Schema validasi form
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
biodata: z.string().min(3, "Biodata minimal 3 karakter"),
|
||||
riwayat: z.string().min(3, "Riwayat minimal 3 karakter"),
|
||||
pengalaman: z.string().min(3, "Pengalaman minimal 3 karakter"),
|
||||
unggulan: z.string().min(3, "Unggulan minimal 3 karakter"),
|
||||
});
|
||||
|
||||
// Type ambil dari Prisma
|
||||
type ProfilePPIDForm = Prisma.ProfilePPIDGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
name: true;
|
||||
biodata: true;
|
||||
riwayat: true;
|
||||
pengalaman: true;
|
||||
unggulan: true;
|
||||
imageUrl: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
// Proxy utama
|
||||
const stateProfilePPID = proxy({
|
||||
findById: {
|
||||
data: null as ProfilePPIDForm | null,
|
||||
loading: false,
|
||||
initialize() {
|
||||
stateProfilePPID.findById.data = {
|
||||
id: '',
|
||||
name: '',
|
||||
biodata: '',
|
||||
riwayat: '',
|
||||
pengalaman: '',
|
||||
unggulan: '',
|
||||
imageUrl:''
|
||||
} as ProfilePPIDForm;
|
||||
},
|
||||
async load(id: string) {
|
||||
try {
|
||||
stateProfilePPID.findById.loading = true;
|
||||
const res = await ApiFetch.api.ppid.profileppid["find-by-id"].get({
|
||||
query: { id },
|
||||
});
|
||||
if (res.status === 200) {
|
||||
stateProfilePPID.findById.data = res.data?.data ?? null;
|
||||
} else {
|
||||
toast.error("Gagal mengambil data profile");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat mengambil data profile");
|
||||
} finally {
|
||||
stateProfilePPID.findById.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
update: {
|
||||
loading: false,
|
||||
async save(data: ProfilePPIDForm) {
|
||||
const cek = templateForm.safeParse(data);
|
||||
if (!cek.success) {
|
||||
const errors = cek.error.issues
|
||||
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
||||
.join(", ");
|
||||
toast.error(`Form tidak valid: ${errors}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
stateProfilePPID.update.loading = true;
|
||||
const res = await ApiFetch.api.ppid.profileppid["update"].post(data);
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil update profile");
|
||||
await stateProfilePPID.findById.load(data.id);
|
||||
} else {
|
||||
toast.error("Gagal update profile");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat update profile");
|
||||
} finally {
|
||||
stateProfilePPID.update.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
uploadImage: {
|
||||
loading: false,
|
||||
async save(file: File, id: string) {
|
||||
if (!file || !id) {
|
||||
toast.error("File atau ID harus disertakan");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
stateProfilePPID.uploadImage.loading = true;
|
||||
|
||||
const form = new FormData();
|
||||
form.append("file", file);
|
||||
form.append("id", id);
|
||||
|
||||
const res = await ApiFetch.api.ppid.profileppid["edit-img"].post(form);
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil mengunggah gambar");
|
||||
await stateProfilePPID.findById.load(id);
|
||||
} else {
|
||||
toast.error("Gagal mengunggah gambar");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat mengunggah gambar");
|
||||
} finally {
|
||||
stateProfilePPID.uploadImage.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default stateProfilePPID;
|
||||
@@ -0,0 +1,81 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
misi: z.string().min(3, "Misi minimal 3 karakter"),
|
||||
visi: z.string().min(3, "Visi minimal 3 karakter"),
|
||||
});
|
||||
|
||||
type VisiMisiPPIDForm = Prisma.VisiMisiPPIDGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
misi: true;
|
||||
visi: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const stateVisiMisiPPID = proxy({
|
||||
findById: {
|
||||
data: null as VisiMisiPPIDForm | null,
|
||||
loading: false,
|
||||
initialize() {
|
||||
stateVisiMisiPPID.findById.data = {
|
||||
id: "",
|
||||
misi: "",
|
||||
visi: "",
|
||||
} as VisiMisiPPIDForm;
|
||||
},
|
||||
async load(id: string) {
|
||||
try {
|
||||
stateVisiMisiPPID.findById.loading = true;
|
||||
const res = await ApiFetch.api.ppid.visimisippid["find-by-id"].get({
|
||||
query: { id },
|
||||
});
|
||||
if (res.status === 200) {
|
||||
stateVisiMisiPPID.findById.data = res.data?.data ?? null;
|
||||
} else {
|
||||
toast.error("Gagal mengambil data visi misi");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat mengambil data visi misi");
|
||||
} finally {
|
||||
stateVisiMisiPPID.findById.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
loading: false,
|
||||
async save(data: VisiMisiPPIDForm) {
|
||||
const cek = templateForm.safeParse(data);
|
||||
if (!cek.success) {
|
||||
const errors = cek.error.issues
|
||||
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
||||
.join(", ");
|
||||
toast.error(`Form tidak valid: ${errors}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
stateVisiMisiPPID.update.loading = true;
|
||||
const res = await ApiFetch.api.ppid.visimisippid["update"].post(data);
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil update visi misi");
|
||||
await stateVisiMisiPPID.findById.load(data.id);
|
||||
} else {
|
||||
toast.error("Gagal update visi misi");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat update visi misi");
|
||||
} finally {
|
||||
stateVisiMisiPPID.update.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default stateVisiMisiPPID;
|
||||
@@ -10,9 +10,9 @@ import { BeritaEditor } from './_com/BeritaEditor';
|
||||
function Page() {
|
||||
return (
|
||||
<Stack>
|
||||
<SimpleGrid cols={2}>
|
||||
<BeritaList />
|
||||
<SimpleGrid cols={{base: 1, md: 2}}>
|
||||
<BeritaCreate />
|
||||
<BeritaList />
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
93
src/app/admin/(dashboard)/ppid/_com/PPIDTextEditor.tsx
Normal file
93
src/app/admin/(dashboard)/ppid/_com/PPIDTextEditor.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
'use client'
|
||||
import { Button, Stack } from '@mantine/core';
|
||||
import { Link, RichTextEditor } from '@mantine/tiptap';
|
||||
import Highlight from '@tiptap/extension-highlight';
|
||||
import SubScript from '@tiptap/extension-subscript';
|
||||
import Superscript from '@tiptap/extension-superscript';
|
||||
import TextAlign from '@tiptap/extension-text-align';
|
||||
import Underline from '@tiptap/extension-underline';
|
||||
import { useEditor } from '@tiptap/react';
|
||||
import StarterKit from '@tiptap/starter-kit';
|
||||
|
||||
|
||||
export function PPIDTextEditor({ onSubmit, onChange, showSubmit = true, initialContent = '', }: {
|
||||
onSubmit?: (val: string) => void,
|
||||
onChange: (val: string) => void,
|
||||
showSubmit?: boolean,
|
||||
initialContent?: string }) {
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
StarterKit,
|
||||
Underline,
|
||||
Link,
|
||||
Superscript,
|
||||
SubScript,
|
||||
Highlight,
|
||||
TextAlign.configure({ types: ['heading', 'paragraph'] }),
|
||||
],
|
||||
immediatelyRender: false,
|
||||
content: initialContent,
|
||||
onUpdate : ({editor}) => {
|
||||
onChange(editor.getHTML())
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<RichTextEditor editor={editor}>
|
||||
<RichTextEditor.Toolbar sticky stickyOffset={60}>
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Bold />
|
||||
<RichTextEditor.Italic />
|
||||
<RichTextEditor.Underline />
|
||||
<RichTextEditor.Strikethrough />
|
||||
<RichTextEditor.ClearFormatting />
|
||||
<RichTextEditor.Highlight />
|
||||
<RichTextEditor.Code />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.H1 />
|
||||
<RichTextEditor.H2 />
|
||||
<RichTextEditor.H3 />
|
||||
<RichTextEditor.H4 />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Blockquote />
|
||||
<RichTextEditor.Hr />
|
||||
<RichTextEditor.BulletList />
|
||||
<RichTextEditor.OrderedList />
|
||||
<RichTextEditor.Subscript />
|
||||
<RichTextEditor.Superscript />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Link />
|
||||
<RichTextEditor.Unlink />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.AlignLeft />
|
||||
<RichTextEditor.AlignCenter />
|
||||
<RichTextEditor.AlignJustify />
|
||||
<RichTextEditor.AlignRight />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Undo />
|
||||
<RichTextEditor.Redo />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
</RichTextEditor.Toolbar>
|
||||
|
||||
<RichTextEditor.Content />
|
||||
</RichTextEditor>
|
||||
{showSubmit && (
|
||||
<Button onClick={() => {
|
||||
if (!editor) return
|
||||
onSubmit?.(editor?.getHTML())
|
||||
}}>Submit</Button>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import { Box, Button, Group, SimpleGrid, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, TextInput, Title } from '@mantine/core';
|
||||
import { Box, Button, Group, Paper, SimpleGrid, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, TextInput, Title } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateDaftarInformasiPublik from '../../_state/ppid/daftar_informasi_publik/daftarInformasiPublik';
|
||||
@@ -20,35 +20,37 @@ function Page() {
|
||||
<Box>
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
||||
<Box>
|
||||
<Stack gap={"xs"}>
|
||||
<Title fw={"bold"} order={3}>Daftar Informasi Publik Desa Darmasaba</Title>
|
||||
<TextInput
|
||||
label="Jenis Informasi"
|
||||
placeholder="masukkan jenis informasi"
|
||||
onChange={(val) => {
|
||||
daftarInformasi.create.form.jenisInformasi = val.target.value
|
||||
}}
|
||||
/>
|
||||
<PPIDEditor
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
daftarInformasi.create.form.deskripsi = val
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Tanggal Publikasi"
|
||||
placeholder="masukkan tanggal publikasi"
|
||||
onChange={(val) => {
|
||||
daftarInformasi.create.form.tanggal = val.target.value
|
||||
}}
|
||||
/>
|
||||
<Group>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={submit}
|
||||
>Submit</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title fw={"bold"} order={3}>Daftar Informasi Publik Desa Darmasaba</Title>
|
||||
<TextInput
|
||||
label="Jenis Informasi"
|
||||
placeholder="masukkan jenis informasi"
|
||||
onChange={(val) => {
|
||||
daftarInformasi.create.form.jenisInformasi = val.target.value
|
||||
}}
|
||||
/>
|
||||
<PPIDEditor
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
daftarInformasi.create.form.deskripsi = val
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Tanggal Publikasi"
|
||||
placeholder="masukkan tanggal publikasi"
|
||||
onChange={(val) => {
|
||||
daftarInformasi.create.form.tanggal = val.target.value
|
||||
}}
|
||||
/>
|
||||
<Group>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={submit}
|
||||
>Submit</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
<Box>
|
||||
<ListDaftarInformasi />
|
||||
@@ -64,46 +66,48 @@ function ListDaftarInformasi() {
|
||||
listData.findMany.load()
|
||||
}, [])
|
||||
if (!listData.findMany.data) return <Stack>
|
||||
{Array.from({length: 10}).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
</Stack>
|
||||
return <Stack gap={"xs"}>
|
||||
<Title fw={"bold"} order={3}>List Daftar Informasi Publik Desa Darmasaba</Title>
|
||||
<Table
|
||||
suppressHydrationWarning
|
||||
striped
|
||||
highlightOnHover
|
||||
withTableBorder
|
||||
withColumnBorders
|
||||
bg={colors['white-1']}
|
||||
>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh>
|
||||
No
|
||||
</TableTh>
|
||||
<TableTh>
|
||||
Jenis Informasi
|
||||
</TableTh>
|
||||
<TableTh>
|
||||
Deskripsi
|
||||
</TableTh>
|
||||
<TableTh>
|
||||
Tanggal Publikasi
|
||||
</TableTh>
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>
|
||||
{listData.findMany.data?.map((item) => (
|
||||
<TableTr key={item.id}>
|
||||
<TableTd>{item.nomor}</TableTd>
|
||||
<TableTd>{item.jenisInformasi}</TableTd>
|
||||
<TableTd dangerouslySetInnerHTML={{ __html: item.deskripsi }}></TableTd>
|
||||
<TableTd>{item.tanggal}</TableTd>
|
||||
</TableTr>
|
||||
))}
|
||||
</TableTbody>
|
||||
</Table>
|
||||
</Stack>
|
||||
return <Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title fw={"bold"} order={3}>List Daftar Informasi Publik Desa Darmasaba</Title>
|
||||
<Table
|
||||
suppressHydrationWarning
|
||||
striped
|
||||
highlightOnHover
|
||||
withTableBorder
|
||||
withColumnBorders
|
||||
bg={colors['white-1']}
|
||||
>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh>
|
||||
No
|
||||
</TableTh>
|
||||
<TableTh>
|
||||
Jenis Informasi
|
||||
</TableTh>
|
||||
<TableTh>
|
||||
Deskripsi
|
||||
</TableTh>
|
||||
<TableTh>
|
||||
Tanggal Publikasi
|
||||
</TableTh>
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>
|
||||
{listData.findMany.data?.map((item) => (
|
||||
<TableTr key={item.id}>
|
||||
<TableTd>{item.nomor}</TableTd>
|
||||
<TableTd>{item.jenisInformasi}</TableTd>
|
||||
<TableTd dangerouslySetInnerHTML={{ __html: item.deskripsi }}></TableTd>
|
||||
<TableTd>{item.tanggal}</TableTd>
|
||||
</TableTr>
|
||||
))}
|
||||
</TableTbody>
|
||||
</Table>
|
||||
</Stack>
|
||||
</Paper>
|
||||
}
|
||||
|
||||
export default Page;
|
||||
|
||||
64
src/app/admin/(dashboard)/ppid/dasar-hukum/create/page.tsx
Normal file
64
src/app/admin/(dashboard)/ppid/dasar-hukum/create/page.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
'use client'
|
||||
import { Box, Button, Group, Stack, Text } from '@mantine/core';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateDasarHukumPPID from '../../../_state/ppid/dasar_hukum/dasarHukum';
|
||||
import dynamic from 'next/dynamic';
|
||||
import colors from '@/con/colors';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
|
||||
const PPIDTextEditor = dynamic(() => import('../../_com/PPIDTextEditor').then(mod => mod.PPIDTextEditor), {
|
||||
ssr: false,
|
||||
});
|
||||
function CreateDasarHukum() {
|
||||
const dasarHukumState = useProxy(stateDasarHukumPPID)
|
||||
useShallowEffect(() => {
|
||||
if (!dasarHukumState.findById.data) {
|
||||
dasarHukumState.findById.load(""); // biar masuk ke `findFirst` route kamu
|
||||
}
|
||||
}, []);
|
||||
|
||||
const submit = () => {
|
||||
if (dasarHukumState.findById.data?.judul && dasarHukumState.findById.data?.content) {
|
||||
dasarHukumState.update.save(dasarHukumState.findById.data)
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap={"xs"}>
|
||||
<Text fw={"bold"}>Judul</Text>
|
||||
<PPIDTextEditor
|
||||
showSubmit={false}
|
||||
key={`judul-${dasarHukumState.findById.data?.id ?? 'new'}`}
|
||||
onChange={(val) => {
|
||||
if (dasarHukumState.findById.data) {
|
||||
dasarHukumState.findById.data.judul = val
|
||||
}
|
||||
}}
|
||||
initialContent={dasarHukumState.findById.data?.judul ?? ''}
|
||||
/>
|
||||
<Text fw={"bold"}>Content</Text>
|
||||
<PPIDTextEditor
|
||||
showSubmit={false}
|
||||
key={`content-${dasarHukumState.findById.data?.id ?? 'baru'}`}
|
||||
onChange={(val) => {
|
||||
if (dasarHukumState.findById.data) {
|
||||
dasarHukumState.findById.data.content = val
|
||||
}
|
||||
}}
|
||||
initialContent={dasarHukumState.findById.data?.content ?? ''}
|
||||
/>
|
||||
<Group>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={submit}
|
||||
loading={dasarHukumState.update.loading}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default CreateDasarHukum;
|
||||
40
src/app/admin/(dashboard)/ppid/dasar-hukum/listData/page.tsx
Normal file
40
src/app/admin/(dashboard)/ppid/dasar-hukum/listData/page.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
'use client'
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateDasarHukumPPID from '../../../_state/ppid/dasar_hukum/dasarHukum';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { Box, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||
import colors from '@/con/colors';
|
||||
|
||||
function ListDataDasarHukum() {
|
||||
const dataList = useProxy(stateDasarHukumPPID)
|
||||
useShallowEffect(() => {
|
||||
dataList.findById.load("")
|
||||
}, [])
|
||||
|
||||
if(!dataList.findById.data) return <Stack>
|
||||
{Array.from({length: 10}).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
</Stack>
|
||||
|
||||
const dataArray = Array.isArray(dataList.findById.data)
|
||||
? dataList.findById.data
|
||||
: [dataList.findById.data];
|
||||
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'} radius={10}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>List Dasar Hukum PPID</Title>
|
||||
{dataArray.map((item) => (
|
||||
<Box key={item.id}>
|
||||
<Text fw={"bold"}>Judul</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.judul }}></Text>
|
||||
<Text fw={"bold"}>Content</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.content }}></Text>
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
export default ListDataDasarHukum;
|
||||
@@ -1,11 +1,24 @@
|
||||
import React from 'react';
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Paper, SimpleGrid, Stack, Title } from '@mantine/core';
|
||||
import CreateDasarHukum from './create/page';
|
||||
import ListDataDasarHukum from './listData/page';
|
||||
|
||||
function Page() {
|
||||
|
||||
return (
|
||||
<div>
|
||||
dasar-hukum
|
||||
</div>
|
||||
);
|
||||
<Stack gap={"xs"}>
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
||||
<Box>
|
||||
<Paper bg={colors['white-1']} p={'md'} radius={10}>
|
||||
<Title order={3}>Dasar Hukum PPID</Title>
|
||||
<CreateDasarHukum/>
|
||||
</Paper>
|
||||
</Box>
|
||||
<ListDataDasarHukum/>
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
'use client'
|
||||
import stateGrafikBerdasarkanJenisKelamin from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanJenisKelamin';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Flex, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { Box, Button, Center, Flex, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Cell, Pie, PieChart } from 'recharts';
|
||||
@@ -21,7 +21,7 @@ function GrafikBerdasarkanJenisKelamin() {
|
||||
if (data && data.length > 0) {
|
||||
const totalLaki = data.reduce((acc: number, cur: any) => acc + Number(cur.laki || 0), 0);
|
||||
const totalPerempuan = data.reduce((acc: number, cur: any) => acc + Number(cur.perempuan || 0), 0);
|
||||
|
||||
|
||||
setDonutData([
|
||||
{ name: 'Laki-laki', value: totalLaki, color: colors['blue-button'], key: 'laki-laki' },
|
||||
{ name: 'Perempuan', value: totalPerempuan, color: '#FF6384', key: 'perempuan' }
|
||||
@@ -44,15 +44,15 @@ function GrafikBerdasarkanJenisKelamin() {
|
||||
try {
|
||||
// Simpan data baru
|
||||
await grafikBerdasarkanJenisKelamin.create.create();
|
||||
|
||||
|
||||
// Muat ulang data
|
||||
await grafikBerdasarkanJenisKelamin.findMany.load();
|
||||
|
||||
|
||||
// Update chart dengan data baru
|
||||
if (grafikBerdasarkanJenisKelamin.findMany.data) {
|
||||
updateChartData(grafikBerdasarkanJenisKelamin.findMany.data);
|
||||
}
|
||||
|
||||
|
||||
// Reset form setelah submit
|
||||
grafikBerdasarkanJenisKelamin.create.form.laki = '';
|
||||
grafikBerdasarkanJenisKelamin.create.form.perempuan = '';
|
||||
@@ -64,72 +64,76 @@ function GrafikBerdasarkanJenisKelamin() {
|
||||
return (
|
||||
<Box>
|
||||
<Box py={15}>
|
||||
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Laki-laki"
|
||||
placeholder="masukkan jumlah laki-laki"
|
||||
value={grafikBerdasarkanJenisKelamin.create.form.laki}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanJenisKelamin.create.form.laki = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Perempuan"
|
||||
type="number"
|
||||
placeholder="masukkan jumlah perempuan"
|
||||
value={grafikBerdasarkanJenisKelamin.create.form.perempuan}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanJenisKelamin.create.form.perempuan = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
mt={10}
|
||||
bg={colors['blue-button']}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Laki-laki"
|
||||
placeholder="masukkan jumlah laki-laki"
|
||||
value={grafikBerdasarkanJenisKelamin.create.form.laki}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanJenisKelamin.create.form.laki = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Perempuan"
|
||||
type="number"
|
||||
placeholder="masukkan jumlah perempuan"
|
||||
value={grafikBerdasarkanJenisKelamin.create.form.perempuan}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanJenisKelamin.create.form.perempuan = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
mt={10}
|
||||
bg={colors['blue-button']}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
{/* Chart */}
|
||||
<Box>
|
||||
<Stack>
|
||||
<Title pb={10} order={3}>Grafik Berdasarkan Jenis Kelamin Responden</Title>
|
||||
{mounted && donutData.length > 0 && (
|
||||
<Box style={{ width: '100%', height: 'auto', minHeight: 900 }}>
|
||||
<Center>
|
||||
<PieChart
|
||||
width={1000} height={400}
|
||||
data={donutData}
|
||||
>
|
||||
|
||||
<Pie
|
||||
dataKey="value"
|
||||
nameKey="name"
|
||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||
<Stack>
|
||||
<Title pb={10} order={3}>Grafik Berdasarkan Jenis Kelamin Responden</Title>
|
||||
{mounted && donutData.length > 0 && (
|
||||
<Box style={{ width: '100%', height: 'auto', minHeight: 900 }}>
|
||||
<Center>
|
||||
<PieChart
|
||||
width={1000} height={400}
|
||||
data={donutData}
|
||||
innerRadius={120}
|
||||
outerRadius={160}
|
||||
label
|
||||
>
|
||||
{donutData.map((entry, index) => (
|
||||
<Cell key={`cell-${index}`} fill={entry.color} />
|
||||
))}
|
||||
</Pie>
|
||||
</PieChart>
|
||||
</Center>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#FF6384'} w={20} h={20} />
|
||||
<Text>Perempuan: {donutData.find((entry) => entry.name === 'Perempuan')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={colors['blue-button']} w={20} h={20} />
|
||||
<Text>Laki-laki: {donutData.find((entry) => entry.name === 'Laki-laki')?.value}</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
<Pie
|
||||
dataKey="value"
|
||||
nameKey="name"
|
||||
data={donutData}
|
||||
innerRadius={120}
|
||||
outerRadius={230}
|
||||
label={true}
|
||||
>
|
||||
{donutData.map((entry, index) => (
|
||||
<Cell key={`cell-${index}`} fill={entry.color} />
|
||||
))}
|
||||
</Pie>
|
||||
</PieChart>
|
||||
</Center>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#FF6384'} w={20} h={20} />
|
||||
<Text>Perempuan: {donutData.find((entry) => entry.name === 'Perempuan')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={colors['blue-button']} w={20} h={20} />
|
||||
<Text>Laki-laki: {donutData.find((entry) => entry.name === 'Laki-laki')?.value}</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import stateGrafikResponden from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanResponden';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Flex, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { Box, Button, Center, Flex, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { PieChart, Pie, Cell } from 'recharts';
|
||||
@@ -68,96 +68,103 @@ function GrafikBerdasarkanResponden() {
|
||||
return (
|
||||
<Box>
|
||||
<Box py={15}>
|
||||
<Title order={3}>Grafik Berdasarkan Responden</Title>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Sangat Baik"
|
||||
value={grafikBerdasarkanResponden.create.form.sangatbaik}
|
||||
placeholder="masukkan jumlah respon sangat baik"
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanResponden.create.form.sangatbaik = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Baik"
|
||||
value={grafikBerdasarkanResponden.create.form.baik}
|
||||
placeholder="masukkan jumlah respon baik"
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanResponden.create.form.baik = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Kurang Baik"
|
||||
value={grafikBerdasarkanResponden.create.form.kurangbaik}
|
||||
placeholder="masukkan jumlah respon kurang baik"
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanResponden.create.form.kurangbaik = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Tidak Baik"
|
||||
value={grafikBerdasarkanResponden.create.form.tidakbaik}
|
||||
placeholder="masukkan jumlah respon tidak baik"
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanResponden.create.form.tidakbaik = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
mt={10}
|
||||
bg={colors['blue-button']}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>Grafik Berdasarkan Responden</Title>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Sangat Baik"
|
||||
value={grafikBerdasarkanResponden.create.form.sangatbaik}
|
||||
placeholder="masukkan jumlah respon sangat baik"
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanResponden.create.form.sangatbaik = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Baik"
|
||||
value={grafikBerdasarkanResponden.create.form.baik}
|
||||
placeholder="masukkan jumlah respon baik"
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanResponden.create.form.baik = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Kurang Baik"
|
||||
value={grafikBerdasarkanResponden.create.form.kurangbaik}
|
||||
placeholder="masukkan jumlah respon kurang baik"
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanResponden.create.form.kurangbaik = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Tidak Baik"
|
||||
value={grafikBerdasarkanResponden.create.form.tidakbaik}
|
||||
placeholder="masukkan jumlah respon tidak baik"
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanResponden.create.form.tidakbaik = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<Group>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
{/* Chart */}
|
||||
<Box>
|
||||
<Stack>
|
||||
<Title pb={10} order={3}>Grafik Berdasarkan Responden</Title>
|
||||
{mounted && donutData.length > 0 && (
|
||||
<Box style={{ width: '100%', height: 'auto', minHeight: 900 }}>
|
||||
<Center>
|
||||
<PieChart
|
||||
width={1000} height={400}
|
||||
data={donutData}
|
||||
>
|
||||
<Pie
|
||||
dataKey="value"
|
||||
nameKey="name"
|
||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||
<Stack>
|
||||
<Title pb={10} order={3}>Grafik Berdasarkan Responden</Title>
|
||||
{mounted && donutData.length > 0 && (
|
||||
<Box style={{ width: '100%', height: 'auto', minHeight: 900 }}>
|
||||
<Center>
|
||||
<PieChart
|
||||
width={1000} height={400}
|
||||
data={donutData}
|
||||
innerRadius={120}
|
||||
outerRadius={160}
|
||||
label
|
||||
>
|
||||
{donutData.map((entry, index) => (
|
||||
<Cell key={`cell-${index}`} fill={entry.color} />
|
||||
))}
|
||||
</Pie>
|
||||
</PieChart>
|
||||
</Center>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={colors['blue-button']} w={20} h={20} />
|
||||
<Text>Sangat Baik: {donutData.find((entry) => entry.name === 'sangatbaik')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#10A85AFF'} w={20} h={20} />
|
||||
<Text>Baik: {donutData.find((entry) => entry.name === 'baik')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#B3AA12FF'} w={20} h={20} />
|
||||
<Text>Kurang Baik: {donutData.find((entry) => entry.name === 'kurangbaik')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#B21313FF'} w={20} h={20} />
|
||||
<Text>Tidak Baik: {donutData.find((entry) => entry.name === 'tidakbaik')?.value}</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
<Pie
|
||||
dataKey="value"
|
||||
nameKey="name"
|
||||
data={donutData}
|
||||
innerRadius={120}
|
||||
outerRadius={230}
|
||||
label={true}
|
||||
>
|
||||
{donutData.map((entry, index) => (
|
||||
<Cell key={`cell-${index}`} fill={entry.color} />
|
||||
))}
|
||||
</Pie>
|
||||
</PieChart>
|
||||
</Center>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={colors['blue-button']} w={20} h={20} />
|
||||
<Text>Sangat Baik: {donutData.find((entry) => entry.name === 'sangatbaik')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#10A85AFF'} w={20} h={20} />
|
||||
<Text>Baik: {donutData.find((entry) => entry.name === 'baik')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#B3AA12FF'} w={20} h={20} />
|
||||
<Text>Kurang Baik: {donutData.find((entry) => entry.name === 'kurangbaik')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#B21313FF'} w={20} h={20} />
|
||||
<Text>Tidak Baik: {donutData.find((entry) => entry.name === 'tidakbaik')?.value}</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Flex, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { Box, Button, Center, Flex, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateGrafikBerdasarkanUmur from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikBerdasarkanUmur';
|
||||
@@ -37,117 +37,125 @@ function GrafikBerdasarakanUmur() {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
const fetchData = async () => {
|
||||
await grafikBerdasarkanUmur.findMany.load();
|
||||
if (grafikBerdasarkanUmur.findMany.data) {
|
||||
updateChartData(grafikBerdasarkanUmur.findMany.data);
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
await grafikBerdasarkanUmur.create.create();
|
||||
const fetchData = async () => {
|
||||
await grafikBerdasarkanUmur.findMany.load();
|
||||
if (grafikBerdasarkanUmur.findMany.data) {
|
||||
updateChartData(grafikBerdasarkanUmur.findMany.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error submitting data:", error);
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
await grafikBerdasarkanUmur.create.create();
|
||||
await grafikBerdasarkanUmur.findMany.load();
|
||||
if (grafikBerdasarkanUmur.findMany.data) {
|
||||
updateChartData(grafikBerdasarkanUmur.findMany.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error submitting data:", error);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Box>
|
||||
<Box py={15}>
|
||||
<Title order={3}>Grafik Berdasarkan Umur Responden</Title>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Remaja"
|
||||
placeholder="masukkan jumlah responden remaja"
|
||||
value={grafikBerdasarkanUmur.create.form.remaja}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanUmur.create.form.remaja = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Dewasa"
|
||||
placeholder="masukkan jumlah responden dewasa"
|
||||
value={grafikBerdasarkanUmur.create.form.dewasa}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanUmur.create.form.dewasa = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Orangtua"
|
||||
placeholder="masukkan jumlah responden orangtua"
|
||||
value={grafikBerdasarkanUmur.create.form.orangtua}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanUmur.create.form.orangtua = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Lansia"
|
||||
placeholder="masukkan jumlah responden lansia"
|
||||
value={grafikBerdasarkanUmur.create.form.lansia}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanUmur.create.form.lansia = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
mt={10}
|
||||
bg={colors['blue-button']}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>Grafik Berdasarkan Umur Responden</Title>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Remaja"
|
||||
placeholder="masukkan jumlah responden remaja"
|
||||
value={grafikBerdasarkanUmur.create.form.remaja}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanUmur.create.form.remaja = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Dewasa"
|
||||
placeholder="masukkan jumlah responden dewasa"
|
||||
value={grafikBerdasarkanUmur.create.form.dewasa}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanUmur.create.form.dewasa = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Orangtua"
|
||||
placeholder="masukkan jumlah responden orangtua"
|
||||
value={grafikBerdasarkanUmur.create.form.orangtua}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanUmur.create.form.orangtua = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Lansia"
|
||||
placeholder="masukkan jumlah responden lansia"
|
||||
value={grafikBerdasarkanUmur.create.form.lansia}
|
||||
onChange={(val) => {
|
||||
grafikBerdasarkanUmur.create.form.lansia = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<Group>
|
||||
<Button
|
||||
mt={10}
|
||||
bg={colors['blue-button']}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
{/* Chart */}
|
||||
<Box>
|
||||
<Stack>
|
||||
<Title pb={10} order={3}>Grafik Berdasarkan Umur Responden</Title>
|
||||
{mounted && donutData.length > 0 && (
|
||||
<Box style={{ width: '100%', height: 'auto', minHeight: 900 }}>
|
||||
<Center>
|
||||
<PieChart
|
||||
width={1000} height={400}
|
||||
data={donutData}
|
||||
>
|
||||
<Pie
|
||||
dataKey="value"
|
||||
nameKey="name"
|
||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||
<Stack>
|
||||
<Title pb={10} order={3}>Grafik Berdasarkan Umur Responden</Title>
|
||||
{mounted && donutData.length > 0 && (
|
||||
<Box style={{ width: '100%', height: 'auto', minHeight: 900 }}>
|
||||
<Center>
|
||||
<PieChart
|
||||
width={1000} height={400}
|
||||
data={donutData}
|
||||
innerRadius={120}
|
||||
outerRadius={160}
|
||||
label
|
||||
>
|
||||
{donutData.map((entry, index) => (
|
||||
<Cell key={`cell-${index}`} fill={entry.color} />
|
||||
))}
|
||||
</Pie>
|
||||
</PieChart>
|
||||
</Center>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={colors['blue-button']} w={20} h={20} />
|
||||
<Text>17 - 25 tahun: {donutData.find((entry) => entry.name === 'remaja')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#D32711FF'} w={20} h={20} />
|
||||
<Text>26 - 45 tahun: {donutData.find((entry) => entry.name === 'dewasa')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#B46B04FF'} w={20} h={20} />
|
||||
<Text>46 - 60 tahun: {donutData.find((entry) => entry.name === 'orangtua')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#038617FF'} w={20} h={20} />
|
||||
<Text>di atas 60 tahun: {donutData.find((entry) => entry.name === 'lansia')?.value}</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
<Pie
|
||||
dataKey="value"
|
||||
nameKey="name"
|
||||
data={donutData}
|
||||
innerRadius={120}
|
||||
outerRadius={230}
|
||||
label={true}
|
||||
>
|
||||
{donutData.map((entry, index) => (
|
||||
<Cell key={`cell-${index}`} fill={entry.color} />
|
||||
))}
|
||||
</Pie>
|
||||
</PieChart>
|
||||
</Center>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={colors['blue-button']} w={20} h={20} />
|
||||
<Text>17 - 25 tahun: {donutData.find((entry) => entry.name === 'remaja')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#D32711FF'} w={20} h={20} />
|
||||
<Text>26 - 45 tahun: {donutData.find((entry) => entry.name === 'dewasa')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#B46B04FF'} w={20} h={20} />
|
||||
<Text>46 - 60 tahun: {donutData.find((entry) => entry.name === 'orangtua')?.value}</Text>
|
||||
</Flex>
|
||||
<Flex gap={"md"} align={"center"}>
|
||||
<Box bg={'#038617FF'} w={20} h={20} />
|
||||
<Text>di atas 60 tahun: {donutData.find((entry) => entry.name === 'lansia')?.value}</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
'use client'
|
||||
import stateGrafikHasilKepuasanMasyarakat from '@/app/admin/(dashboard)/_state/ppid/indeks_kepuasan_masyarakat/grafikHasilKepuasan';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, TextInput, Title } from '@mantine/core';
|
||||
import { Box, Button, Paper, Stack, TextInput, Title } from '@mantine/core';
|
||||
import { useMediaQuery, useShallowEffect } from '@mantine/hooks';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts';
|
||||
@@ -32,53 +32,61 @@ function GrafikHasilKepuasan() {
|
||||
return (
|
||||
<Box>
|
||||
<Box py={15}>
|
||||
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Label"
|
||||
placeholder="masukkan label"
|
||||
value={grafikHasilKepuasan.create.form.label}
|
||||
onChange={(val) => {
|
||||
grafikHasilKepuasan.create.form.label = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Jumlah Kepuasan"
|
||||
type="number"
|
||||
placeholder="masukkan jumlah kepuasan"
|
||||
value={grafikHasilKepuasan.create.form.kepuasan}
|
||||
onChange={(val) => {
|
||||
grafikHasilKepuasan.create.form.kepuasan = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
mt={10}
|
||||
bg={colors['blue-button']}
|
||||
onClick={async () => {
|
||||
await grafikHasilKepuasan.create.create();
|
||||
await grafikHasilKepuasan.findMany.load();
|
||||
if (grafikHasilKepuasan.findMany.data) {
|
||||
setChartData(grafikHasilKepuasan.findMany.data);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
<Paper bg={colors['white-1']} w={{ base: '100%', md: '50%' }} p={'md'}>
|
||||
<Stack>
|
||||
<Title order={3}>Grafik Hasil Kepuasan Masyarakat Terhadap Pelayanan Publik</Title>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Label"
|
||||
placeholder="masukkan label"
|
||||
value={grafikHasilKepuasan.create.form.label}
|
||||
onChange={(val) => {
|
||||
grafikHasilKepuasan.create.form.label = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label="Jumlah Kepuasan"
|
||||
type="number"
|
||||
placeholder="masukkan jumlah kepuasan"
|
||||
value={grafikHasilKepuasan.create.form.kepuasan}
|
||||
onChange={(val) => {
|
||||
grafikHasilKepuasan.create.form.kepuasan = val.currentTarget.value;
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
mt={10}
|
||||
bg={colors['blue-button']}
|
||||
onClick={async () => {
|
||||
await grafikHasilKepuasan.create.create();
|
||||
await grafikHasilKepuasan.findMany.load();
|
||||
if (grafikHasilKepuasan.findMany.data) {
|
||||
setChartData(grafikHasilKepuasan.findMany.data);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
{/* Chart */}
|
||||
<Box style={{ width: '100%', minWidth: 300, height: 400, minHeight: 300 }}>
|
||||
<Title pb={10} order={3}>Data Kepuasan Masyarakat</Title>
|
||||
{mounted && chartData.length > 0 && (
|
||||
<BarChart width={isMobile ? 450 : isTablet ? 600 : 900} height={380} data={chartData} >
|
||||
<XAxis dataKey="label" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Bar dataKey="kepuasan" fill={colors['blue-button']} name="Kepuasan" />
|
||||
</BarChart>
|
||||
)}
|
||||
<Paper style={{ width: '100%', minWidth: 300, height: 400, minHeight: 300 }} bg={colors['white-1']} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title pb={10} order={3}>Data Kepuasan Masyarakat</Title>
|
||||
{mounted && chartData.length > 0 && (
|
||||
<BarChart width={isMobile ? 300 : isTablet ? 600 : 900} height={380} data={chartData} >
|
||||
<XAxis dataKey="label" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Bar dataKey="kepuasan" fill={colors['blue-button']} name="Kepuasan" />
|
||||
</BarChart>
|
||||
)}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
</Box>
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Prisma } from '@prisma/client';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import statePermohonanInformasi from '../../_state/ppid/permohonan_informasi_publik/permohonanInformasiPublik';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { Group, Select, Skeleton } from '@mantine/core';
|
||||
|
||||
function JenisInformasi({ onChange }: {
|
||||
onChange: (value: Prisma.JenisInformasiDimintaGetPayload<{
|
||||
select: {
|
||||
id: true,
|
||||
name: true
|
||||
}
|
||||
}>) => void
|
||||
}) {
|
||||
const jenisInformasiState = useProxy(statePermohonanInformasi.jenisInformasiDiminta)
|
||||
useShallowEffect(() => {
|
||||
jenisInformasiState.findMany.load()
|
||||
}, [])
|
||||
|
||||
if (!jenisInformasiState.findMany.data) return <Skeleton h={40} />
|
||||
return (
|
||||
<Group>
|
||||
<Select
|
||||
placeholder='pilih jenis informasi'
|
||||
label={'select jenis informasi'}
|
||||
data={jenisInformasiState.findMany.data.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name
|
||||
}))}
|
||||
onChange={(v) => {
|
||||
const data = jenisInformasiState.findMany.data?.find((item) => item.id === v)
|
||||
if (!data) return
|
||||
onChange(data)
|
||||
}}
|
||||
/>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
export default JenisInformasi;
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Group, Select } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import statePermohonanInformasi from '../../_state/ppid/permohonan_informasi_publik/permohonanInformasiPublik';
|
||||
|
||||
function MemperolehInformasi({ onChange }: {
|
||||
onChange: (value: Prisma.CaraMemperolehInformasiGetPayload<{
|
||||
select: {
|
||||
id: true,
|
||||
name: true
|
||||
}
|
||||
}>) => void
|
||||
}) {
|
||||
const memperolehInformasiState = useProxy(statePermohonanInformasi.caraMemperolehInformasi)
|
||||
|
||||
useShallowEffect(() => {
|
||||
memperolehInformasiState.findMany.load()
|
||||
}, [])
|
||||
return (
|
||||
<Group>
|
||||
<Select
|
||||
placeholder='pilih katagori'
|
||||
label={"select katagori"}
|
||||
data={memperolehInformasiState.findMany.data?.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name
|
||||
}))} onChange={(v) => {
|
||||
const data = memperolehInformasiState.findMany.data?.find((item) => item.id === v)
|
||||
if (!data) return
|
||||
onChange(data)
|
||||
}} />
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
export default MemperolehInformasi;
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Group, Select, Skeleton } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import statePermohonanInformasi from '../../_state/ppid/permohonan_informasi_publik/permohonanInformasiPublik';
|
||||
|
||||
function MemperolehSalinan({ onChange }: {
|
||||
onChange: (value: Prisma.CaraMemperolehSalinanInformasiGetPayload<{
|
||||
select: {
|
||||
id: true,
|
||||
name: true
|
||||
}
|
||||
}>) => void
|
||||
}) {
|
||||
const memperolehSalinanInformasiState = useProxy(statePermohonanInformasi.caraMemperolehSalinanInformasi)
|
||||
useShallowEffect(() => {
|
||||
memperolehSalinanInformasiState.findMany.load()
|
||||
}, [])
|
||||
|
||||
if (!memperolehSalinanInformasiState.findMany.data) return <Skeleton h={40} />
|
||||
return (
|
||||
<Group>
|
||||
<Select
|
||||
placeholder='pilih salinan informasi'
|
||||
label={'select salinan informasi'}
|
||||
data={memperolehSalinanInformasiState.findMany.data.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name
|
||||
}))}
|
||||
onChange={(v) => {
|
||||
if (!v) return
|
||||
const selectedItem = memperolehSalinanInformasiState.findMany.data?.find(item => item.id === v)
|
||||
if (selectedItem) {
|
||||
onChange({
|
||||
id: selectedItem.id,
|
||||
name: selectedItem.name
|
||||
})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
export default MemperolehSalinan;
|
||||
@@ -1,11 +1,115 @@
|
||||
import React from 'react';
|
||||
'use client'
|
||||
import { Box, Button, Group, Paper, SimpleGrid, Stack, TextInput, Title } from '@mantine/core';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import statePermohonanInformasi from '../../_state/ppid/permohonan_informasi_publik/permohonanInformasiPublik';
|
||||
import JenisInformasi from './jenisInformasi';
|
||||
import MemperolehInformasi from './memperolehInformasi';
|
||||
import MemperolehSalinan from './memperolehSalinan';
|
||||
import colors from '@/con/colors';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<div>
|
||||
permohonan-informasi-publik
|
||||
</div>
|
||||
<Box>
|
||||
<Stack>
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
||||
<PermohonanInformasiPublikCreate />
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
function PermohonanInformasiPublikCreate() {
|
||||
const permohonanInformasiPublikState = useProxy(statePermohonanInformasi)
|
||||
const submitForms = () => {
|
||||
// Tambahkan log untuk debugging
|
||||
console.log("Form data sebelum submit:", {
|
||||
name: permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.name,
|
||||
nik: permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.nik,
|
||||
notelp: permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.notelp,
|
||||
alamat: permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.alamat,
|
||||
email: permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.email,
|
||||
jenisInformasiDimintaId: permohonanInformasiPublikState.jenisInformasiDiminta,
|
||||
caraMemperolehInformasiId: permohonanInformasiPublikState.caraMemperolehInformasi,
|
||||
caraMemperolehSalinanInformasiId: permohonanInformasiPublikState.caraMemperolehSalinanInformasi
|
||||
});
|
||||
|
||||
if (permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.name &&
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.nik &&
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.notelp &&
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.alamat &&
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.email &&
|
||||
permohonanInformasiPublikState.jenisInformasiDiminta &&
|
||||
permohonanInformasiPublikState.caraMemperolehInformasi &&
|
||||
permohonanInformasiPublikState.caraMemperolehSalinanInformasi) {
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.create()
|
||||
} else {
|
||||
console.log("Validasi gagal, form tidak lengkap");
|
||||
// Tampilkan pesan error ke pengguna di sini
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Box py={5}>
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack gap={"10"}>
|
||||
<Title order={3}>Permohonan Informasi Publik</Title>
|
||||
<TextInput
|
||||
label="Nama Lengkap"
|
||||
placeholder="masukkan nama lengkap"
|
||||
onChange={(val) => {
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.name = val.target.value
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="NIK"
|
||||
placeholder="masukkan NIK"
|
||||
onChange={(val) => {
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.nik = val.target.value
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="No.Telp"
|
||||
placeholder="masukkan no telp"
|
||||
onChange={(val) => {
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.notelp = val.target.value
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Alamat"
|
||||
placeholder="masukkan alamat"
|
||||
onChange={(val) => {
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.alamat = val.target.value
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Email"
|
||||
placeholder="masukkan email"
|
||||
onChange={(val) => {
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.email = val.target.value
|
||||
}}
|
||||
/>
|
||||
<JenisInformasi
|
||||
onChange={(val) => {
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.jenisInformasiDimintaId = val.id
|
||||
}}
|
||||
/>
|
||||
<MemperolehInformasi
|
||||
onChange={(val) => {
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.caraMemperolehInformasiId = val.id
|
||||
}}
|
||||
/>
|
||||
<MemperolehSalinan
|
||||
onChange={(val) => {
|
||||
permohonanInformasiPublikState.permohonanInformasiPublikForm.create.form.caraMemperolehSalinanInformasiId = val.id
|
||||
}}
|
||||
/>
|
||||
<Group>
|
||||
<Button onClick={submitForms}>Submit</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box >
|
||||
)
|
||||
}
|
||||
|
||||
export default Page;
|
||||
@@ -1,11 +1,98 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import statePermohonanKeberatan from '../../_state/ppid/permohonan_keberatan_informasi_publik/permohonanKeberatanInformasi';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<div>
|
||||
permohonan-keberatan-informasi-publik
|
||||
</div>
|
||||
<Box>
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
||||
<PermohonanKeberatanInformasiCreate />
|
||||
<PermohonanKeberatanInformasiList />
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function PermohonanKeberatanInformasiCreate() {
|
||||
const state = useProxy(statePermohonanKeberatan.permohonanKeberatanInformasiForm)
|
||||
const submit = () => {
|
||||
if (state.create.form.name && state.create.form.email && state.create.form.notelp && state.create.form.alasan) {
|
||||
state.create.create()
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Box py={10}>
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>Permohonan Keberatan Informasi Publik</Title>
|
||||
<TextInput
|
||||
label="Nama"
|
||||
placeholder="masukkan nama lengkap"
|
||||
onChange={(val) => {
|
||||
state.create.form.name = val.target.value
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Email"
|
||||
placeholder="masukkan email"
|
||||
onChange={(val) => {
|
||||
state.create.form.email = val.target.value
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Nomor Telepon"
|
||||
placeholder="masukkan nomor telepon"
|
||||
onChange={(val) => {
|
||||
state.create.form.notelp = val.target.value
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
label="Alasan Keberatan"
|
||||
placeholder="masukkan alasan keberatan"
|
||||
onChange={(val) => {
|
||||
state.create.form.alasan = val.target.value
|
||||
}}
|
||||
/>
|
||||
<Group>
|
||||
<Button onClick={submit} bg={colors['blue-button']}>Kirim Permohonan</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
function PermohonanKeberatanInformasiList() {
|
||||
const listState = useProxy(statePermohonanKeberatan.permohonanKeberatanInformasiForm)
|
||||
useShallowEffect(() => {
|
||||
listState.findMany.load()
|
||||
}, [])
|
||||
|
||||
if (!listState.findMany.data) return <Stack>
|
||||
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
</Stack>
|
||||
|
||||
return (
|
||||
<Box py={10}>
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>Permohonan Keberatan Informasi Publik</Title>
|
||||
{listState.findMany.data?.map((item) => (
|
||||
<Box key={item.id}>
|
||||
<Text>Nama: {item.name}</Text>
|
||||
<Text>Email: {item.email}</Text>
|
||||
<Text>Telepon: {item.notelp}</Text>
|
||||
<Text>Alasan: {item.alasan}</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page;
|
||||
|
||||
10
src/app/admin/(dashboard)/ppid/profile-ppid/_com/biodata.ts
Normal file
10
src/app/admin/(dashboard)/ppid/profile-ppid/_com/biodata.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
const biodata = {
|
||||
id: "1",
|
||||
name: "<p>I.B Surya Prabhawa Manuaba, S.H., M.H.</p>",
|
||||
biodata: "<h2>Biodata</h2> <p>....</p>",
|
||||
riwayat: "<h2>Riwayat Karir</h2> <ul>...</ul>",
|
||||
pengalaman: "<h2>Pengalaman Organisasi</h2> <ul>...</ul>",
|
||||
unggulan: "<h2>Program Kerja Unggulan</h2> <h3>...</h3>",
|
||||
}
|
||||
|
||||
export default biodata
|
||||
74
src/app/admin/(dashboard)/ppid/profile-ppid/biodata/page.tsx
Normal file
74
src/app/admin/(dashboard)/ppid/profile-ppid/biodata/page.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
'use client'
|
||||
import { Box, Group, Text } from '@mantine/core';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
|
||||
import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
|
||||
import { Dropzone, MIME_TYPES } from '@mantine/dropzone';
|
||||
import { IconUpload, IconX, IconPhoto } from '@tabler/icons-react';
|
||||
import ApiFetch from '@/lib/api-fetch';
|
||||
|
||||
|
||||
function Biodata() {
|
||||
const biodataState = useProxy(stateProfilePPID)
|
||||
const [loading, setLoading] = useState(false);
|
||||
return (<Box>
|
||||
<Text fw={"bold"}>Biodata</Text>
|
||||
<Dropzone
|
||||
mb={20}
|
||||
onDrop={async (droppedFiles) => {
|
||||
setLoading(true);
|
||||
for (const file of droppedFiles) {
|
||||
await ApiFetch.api.ppid.profileppid["edit-img"].post({
|
||||
file: file,
|
||||
id: biodataState.findById.data?.id,
|
||||
});
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
if (biodataState.findById.data?.id) {
|
||||
biodataState.findById.load(biodataState.findById.data.id);
|
||||
}
|
||||
}}
|
||||
accept={[MIME_TYPES.jpeg, MIME_TYPES.png, MIME_TYPES.webp]}
|
||||
loading={loading}
|
||||
>
|
||||
<Group justify="center" gap="md" mih={150} style={{ pointerEvents: 'none' }}>
|
||||
<Dropzone.Accept>
|
||||
<IconUpload size={50} stroke={1.5} />
|
||||
</Dropzone.Accept>
|
||||
<Dropzone.Reject>
|
||||
<IconX size={50} stroke={1.5} />
|
||||
</Dropzone.Reject>
|
||||
<Dropzone.Idle>
|
||||
<IconPhoto size={50} stroke={1.5} />
|
||||
</Dropzone.Idle>
|
||||
|
||||
<div>
|
||||
<Text size="xl" inline>
|
||||
Drag & drop gambar di sini atau klik untuk pilih file
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed" inline mt={7}>
|
||||
Maksimal ukuran file 5MB. Format: JPG, PNG, WebP
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Dropzone>
|
||||
<PPIDTextEditor
|
||||
key={biodataState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
if (biodataState.findById.data) {
|
||||
biodataState.findById.data.biodata = val;
|
||||
}
|
||||
}}
|
||||
initialContent={biodataState.findById.data?.biodata ?? ''}
|
||||
/>
|
||||
|
||||
</Box>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
export default Biodata;
|
||||
68
src/app/admin/(dashboard)/ppid/profile-ppid/listPage.tsx
Normal file
68
src/app/admin/(dashboard)/ppid/profile-ppid/listPage.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import colors from '@/con/colors';
|
||||
import { Stack, Skeleton, Paper, Title, Box, Text, Image } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateProfilePPID from '../../_state/ppid/profile_ppid/profile_PPID';
|
||||
|
||||
function ProfileList() {
|
||||
const allList = useProxy(stateProfilePPID)
|
||||
useShallowEffect(() => {
|
||||
allList.findById.load("1") // Assuming "1" is your default ID, adjust as needed
|
||||
}, [])
|
||||
|
||||
if (!allList.findById.data) return <Stack>
|
||||
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
</Stack>
|
||||
|
||||
const dataArray = Array.isArray(allList.findById.data)
|
||||
? allList.findById.data
|
||||
: [allList.findById.data];
|
||||
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>List Profile PPID</Title>
|
||||
{dataArray.map((item) => (
|
||||
<Box key={item.id}>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Gambar</Text>
|
||||
{item.imageUrl ? (
|
||||
<Image
|
||||
src={item.imageUrl}
|
||||
alt="Foto Profil"
|
||||
w={200}
|
||||
radius="md"
|
||||
/>
|
||||
) : (
|
||||
<Text c="dimmed">Belum ada foto</Text>
|
||||
)}
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Nama</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.name }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Biodata</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.biodata }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Riwayat</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.riwayat }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Pengalaman</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.pengalaman }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Program Kerja Unggulan</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.unggulan }}></Text>
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProfileList;
|
||||
@@ -1,11 +1,79 @@
|
||||
import React from 'react';
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import Biodata from './biodata/page';
|
||||
import PengalamanOrganisasi from './pengalaman_organisasi/page';
|
||||
import RiwayatKarir from './riwayat_karir/page';
|
||||
import ProgramKerjaUnggulan from './program_kerja_unggulan/page';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateProfilePPID from '../../_state/ppid/profile_ppid/profile_PPID';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import ProfileList from './listPage';
|
||||
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<div>
|
||||
profile-ppid
|
||||
</div>
|
||||
<Box>
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
||||
<ProfileCreate />
|
||||
<ProfileList />
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
function ProfileCreate() {
|
||||
const allState = useProxy(stateProfilePPID)
|
||||
|
||||
// Initialize data if it doesn't exist
|
||||
useShallowEffect(() => {
|
||||
if (!allState.findById.data) {
|
||||
allState.findById.initialize()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const submit = () => {
|
||||
if (
|
||||
allState.findById.data?.name &&
|
||||
allState.findById.data?.biodata &&
|
||||
allState.findById.data?.riwayat &&
|
||||
allState.findById.data?.pengalaman &&
|
||||
allState.findById.data?.unggulan
|
||||
) {
|
||||
allState.update.save(allState.findById.data)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'} radius={10}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>Profile PPID</Title>
|
||||
<TextInput
|
||||
label={<Text fw={"bold"}>Nama Perbekel</Text>}
|
||||
placeholder="masukkan nama perbekel"
|
||||
value={allState.findById.data?.name || ''}
|
||||
onChange={(val) => {
|
||||
if (allState.findById.data) {
|
||||
allState.findById.data.name = val.currentTarget.value
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Biodata />
|
||||
<RiwayatKarir />
|
||||
<PengalamanOrganisasi />
|
||||
<ProgramKerjaUnggulan />
|
||||
<Group>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={submit}
|
||||
loading={allState.update.loading}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,26 @@
|
||||
'use client'
|
||||
import { Box, Text } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
|
||||
import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
|
||||
|
||||
function PengalamanOrganisasi() {
|
||||
const pengalamanOrganisasiState = useProxy(stateProfilePPID)
|
||||
return (<Box>
|
||||
<Text fw={"bold"}>Pengalaman Organisasi</Text>
|
||||
<PPIDTextEditor
|
||||
key={pengalamanOrganisasiState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
if (pengalamanOrganisasiState.findById.data) {
|
||||
pengalamanOrganisasiState.findById.data.pengalaman = val;
|
||||
}
|
||||
}}
|
||||
initialContent={pengalamanOrganisasiState.findById.data?.pengalaman ?? ''}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default PengalamanOrganisasi;
|
||||
@@ -0,0 +1,26 @@
|
||||
'use client'
|
||||
import { Box, Text } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
|
||||
import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
|
||||
|
||||
function ProgramKerjaUnggulan() {
|
||||
const programKerjaUnggulanState = useProxy(stateProfilePPID)
|
||||
return (<Box>
|
||||
<Text fw={"bold"}>Program Kerja Unggulan</Text>
|
||||
<PPIDTextEditor
|
||||
key={programKerjaUnggulanState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
if (programKerjaUnggulanState.findById.data) {
|
||||
programKerjaUnggulanState.findById.data.unggulan = val;
|
||||
}
|
||||
}}
|
||||
initialContent={programKerjaUnggulanState.findById.data?.unggulan ?? ''}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProgramKerjaUnggulan;
|
||||
@@ -0,0 +1,33 @@
|
||||
'use client';
|
||||
|
||||
import { Box, Text } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import dynamic from 'next/dynamic';
|
||||
import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
|
||||
|
||||
// ini penting
|
||||
const PPIDTextEditor = dynamic(() => import('../../_com/PPIDTextEditor').then(mod => mod.PPIDTextEditor), {
|
||||
ssr: false, // disable server side rendering
|
||||
});
|
||||
function RiwayatKarir() {
|
||||
const riwayatKarirState = useProxy(stateProfilePPID);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Text fw={"bold"}>Riwayat Karir</Text>
|
||||
<PPIDTextEditor
|
||||
key={riwayatKarirState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
if (riwayatKarirState.findById.data) {
|
||||
riwayatKarirState.findById.data.riwayat = val;
|
||||
}
|
||||
}}
|
||||
initialContent={riwayatKarirState.findById.data?.riwayat ?? ''}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default RiwayatKarir;
|
||||
@@ -0,0 +1,26 @@
|
||||
'use client'
|
||||
import { Box, Text } from '@mantine/core';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
|
||||
import stateVisiMisiPPID from '../../../_state/ppid/visi_misi_ppid/visimisiPPID';
|
||||
|
||||
function MisiPPID() {
|
||||
const misiState = useProxy(stateVisiMisiPPID)
|
||||
return (
|
||||
<Box>
|
||||
<Text fw={"bold"}>Misi PPID</Text>
|
||||
<PPIDTextEditor
|
||||
key={misiState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
if(misiState.findById.data){
|
||||
misiState.findById.data.misi = val
|
||||
}
|
||||
}}
|
||||
initialContent={misiState.findById.data?.misi ?? ''}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default MisiPPID;
|
||||
@@ -1,11 +1,83 @@
|
||||
import React from 'react';
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, SimpleGrid, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateVisiMisiPPID from '../../_state/ppid/visi_misi_ppid/visimisiPPID';
|
||||
import MisiPPID from './misiPPID/page';
|
||||
import VisiPPID from './visiPPID/page';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<div>
|
||||
visi-misi-ppid
|
||||
</div>
|
||||
<Box>
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
||||
<VisiMisiPPIDCreate />
|
||||
<VisiMisiPPIDList />
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function VisiMisiPPIDCreate() {
|
||||
const visiMisi = useProxy(stateVisiMisiPPID)
|
||||
|
||||
useShallowEffect(() => {
|
||||
if(!visiMisi.findById.data){
|
||||
visiMisi.findById.initialize()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const submit = () => {
|
||||
if(visiMisi.findById.data?.misi && visiMisi.findById.data?.visi){
|
||||
visiMisi.update.save(visiMisi.findById.data)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'} radius={10}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>Visi Misi PPID</Title>
|
||||
<VisiPPID />
|
||||
<MisiPPID />
|
||||
<Group>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={submit}
|
||||
loading={visiMisi.update.loading}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
||||
function VisiMisiPPIDList() {
|
||||
const listVisiMisi = useProxy(stateVisiMisiPPID)
|
||||
useShallowEffect(() => {
|
||||
listVisiMisi.findById.load("1")
|
||||
}, [])
|
||||
|
||||
if(!listVisiMisi.findById.data) return <Stack>
|
||||
{Array.from({length: 10}).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
</Stack>
|
||||
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'} radius={10}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>List Visi Misi PPID</Title>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Visi PPID</Text>
|
||||
<Text dangerouslySetInnerHTML={{__html: listVisiMisi.findById.data?.visi}}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Misi PPID</Text>
|
||||
<Text dangerouslySetInnerHTML={{__html: listVisiMisi.findById.data?.misi}}></Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page;
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
'use client'
|
||||
import { Box, Text } from '@mantine/core';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
|
||||
import stateVisiMisiPPID from '../../../_state/ppid/visi_misi_ppid/visimisiPPID';
|
||||
|
||||
function VisiPPID() {
|
||||
const visiState = useProxy(stateVisiMisiPPID)
|
||||
return (
|
||||
<Box>
|
||||
<Text fw={"bold"}>Visi PPID</Text>
|
||||
<PPIDTextEditor
|
||||
key={visiState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
if(visiState.findById.data){
|
||||
visiState.findById.data.visi = val
|
||||
}
|
||||
}}
|
||||
initialContent={visiState.findById.data?.visi ?? ''}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default VisiPPID;
|
||||
33
src/app/api/[[...slugs]]/_lib/ppid/dasar_hukum/find-by-id.ts
Normal file
33
src/app/api/[[...slugs]]/_lib/ppid/dasar_hukum/find-by-id.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Context } from "elysia";
|
||||
|
||||
export default async function dasarHukumPPIDFindById(context: Context) {
|
||||
try {
|
||||
const id = context?.params?.slugs?.[0];
|
||||
|
||||
// If no ID provided, get the first profile
|
||||
if (!id) {
|
||||
const data = await prisma.dasarHukumPPID.findFirst();
|
||||
return {
|
||||
success: true,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
const data = await prisma.dasarHukumPPID.findUniqueOrThrow({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching profilePPID:", error);
|
||||
|
||||
return {
|
||||
success: false,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
};
|
||||
}
|
||||
}
|
||||
18
src/app/api/[[...slugs]]/_lib/ppid/dasar_hukum/index.ts
Normal file
18
src/app/api/[[...slugs]]/_lib/ppid/dasar_hukum/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import dasarHukumPPIDFindById from "./find-by-id";
|
||||
import dasarHukumPPIDUpdate from "./update";
|
||||
|
||||
const DasarHukumPPID = new Elysia({
|
||||
prefix: "/dasarhukumppid",
|
||||
tags: ["PPID/Dasar Hukum PPID"]
|
||||
})
|
||||
.get("/find-by-id", dasarHukumPPIDFindById)
|
||||
.post("/update", dasarHukumPPIDUpdate, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
judul: t.String(),
|
||||
content: t.String(),
|
||||
})
|
||||
})
|
||||
|
||||
export default DasarHukumPPID
|
||||
29
src/app/api/[[...slugs]]/_lib/ppid/dasar_hukum/update.ts
Normal file
29
src/app/api/[[...slugs]]/_lib/ppid/dasar_hukum/update.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
|
||||
type FormCreate = Prisma.DasarHukumPPIDGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
judul: true;
|
||||
content: true;
|
||||
}
|
||||
}>
|
||||
export default async function dasarHukumPPIDUpdate(context: Context) {
|
||||
const body = context.body as FormCreate;
|
||||
|
||||
await prisma.dasarHukumPPID.update({
|
||||
where: {
|
||||
id: body.id
|
||||
},
|
||||
data: {
|
||||
judul: body.judul,
|
||||
content: body.content,
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Dasar Hukum PPID Berhasil Dibuat",
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,28 @@ import GrafikHasilKepuasanMasyarakat from "./ikm/grafik_hasil_kepuasan_masyaraka
|
||||
import GrafikBerdasarkanJenisKelamin from "./ikm/grafik_berdasarkan_jenis_kelamin";
|
||||
import GrafikBerdasarkanResponden from "./ikm/grafik_responden";
|
||||
import GrafikBerdasarkanUmur from "./ikm/grafik_berdasarkan_umur";
|
||||
import PermohonanInformasiPublik from "./permohonan_informasi_publik";
|
||||
import PermohonanKeberatanInformasiPublik from "./permohonan_keberatan_informasi_publik";
|
||||
import ProfilePPID from "./profile_ppid";
|
||||
import VisiMisiPPID from "./visi_misi_ppid/visi_misi_ppid";
|
||||
import DasarHukumPPID from "./dasar_hukum";
|
||||
|
||||
|
||||
|
||||
|
||||
const PPID = new Elysia({ prefix: "/api/ppid", tags: ["PPID"] })
|
||||
.use(ProfilePPID)
|
||||
.use(DaftarInformasiPublik)
|
||||
.use(GrafikHasilKepuasanMasyarakat)
|
||||
.use(GrafikBerdasarkanJenisKelamin)
|
||||
.use(GrafikBerdasarkanResponden)
|
||||
.use(GrafikBerdasarkanUmur)
|
||||
.use(PermohonanInformasiPublik)
|
||||
.use(PermohonanKeberatanInformasiPublik)
|
||||
.use(VisiMisiPPID)
|
||||
.use(DasarHukumPPID)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
|
||||
type FormCreate = Prisma.PermohonanInformasiPublikGetPayload<{
|
||||
select: {
|
||||
name: true;
|
||||
nik: true;
|
||||
email: true;
|
||||
notelp: true;
|
||||
alamat: true;
|
||||
jenisInformasiDimintaId: true;
|
||||
caraMemperolehInformasiId: true;
|
||||
caraMemperolehSalinanInformasiId: true;
|
||||
}
|
||||
}>
|
||||
export default async function permohonanInformasiPublikCreate(context: Context) {
|
||||
const body = context.body as FormCreate;
|
||||
|
||||
await prisma.permohonanInformasiPublik.create({
|
||||
data: {
|
||||
name: body.name,
|
||||
nik: body.nik,
|
||||
email: body.email,
|
||||
notelp: body.notelp,
|
||||
alamat: body.alamat,
|
||||
jenisInformasiDimintaId: body.jenisInformasiDimintaId,
|
||||
caraMemperolehInformasiId: body.caraMemperolehInformasiId,
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Permohonan Informasi Publik Berhasil Dibuat",
|
||||
data: {
|
||||
...body,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export default async function permohonanInformasiPublikFindMany() {
|
||||
const res = await prisma.permohonanInformasiPublik.findMany();
|
||||
return {
|
||||
data: res,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import permohonanInformasiPublikCreate from "./create";
|
||||
import permohonanInformasiPublikFindMany from "./find-many";
|
||||
import jenisInformasiFindMany from "./jenisInformasi";
|
||||
import memperolehInformasiFindMany from "./memperolehInformasi";
|
||||
import salinanInformasiFindMany from "./salinanInformasi";
|
||||
|
||||
const PermohonanInformasiPublik = new Elysia({
|
||||
prefix: "/permohonaninformasipublik",
|
||||
tags: ["PPID/Permohonan Informasi Publik"]
|
||||
})
|
||||
.get("/jenisInformasi/find-many", jenisInformasiFindMany)
|
||||
.get("/memperolehInformasi/find-many", memperolehInformasiFindMany)
|
||||
.get("/salinanInformasi/find-many", salinanInformasiFindMany)
|
||||
.get("/find-many", permohonanInformasiPublikFindMany)
|
||||
.post("/create", permohonanInformasiPublikCreate, {
|
||||
body: t.Object({
|
||||
name: t.String(),
|
||||
nik: t.String(),
|
||||
notelp: t.String(),
|
||||
alamat: t.String(),
|
||||
email: t.String(),
|
||||
jenisInformasiDimintaId: t.Union([t.String(), t.Null()]),
|
||||
caraMemperolehInformasiId: t.Union([t.String(), t.Null()]),
|
||||
caraMemperolehSalinanInformasiId: t.Union([t.String(), t.Null()]),
|
||||
}),
|
||||
})
|
||||
|
||||
export default PermohonanInformasiPublik
|
||||
@@ -0,0 +1,8 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export default async function jenisInformasiFindMany() {
|
||||
const res = await prisma.jenisInformasiDiminta.findMany();
|
||||
return {
|
||||
data: res,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export default async function memperolehInformasiFindMany() {
|
||||
const res = await prisma.caraMemperolehInformasi.findMany();
|
||||
return {
|
||||
data: res,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export default async function salinanInformasiFindMany() {
|
||||
const res = await prisma.caraMemperolehSalinanInformasi.findMany();
|
||||
return {
|
||||
data: res,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
|
||||
type FormCreate = Prisma.FormulirPermohonanKeberatanGetPayload<{
|
||||
select: {
|
||||
name: true;
|
||||
email: true;
|
||||
notelp: true;
|
||||
alasan: true;
|
||||
}
|
||||
}>
|
||||
|
||||
export default async function permohonanKeberatanInformasiPublikCreate(context: Context) {
|
||||
const body = context.body as FormCreate;
|
||||
|
||||
await prisma.formulirPermohonanKeberatan.create({
|
||||
data: {
|
||||
name: body.name,
|
||||
email: body.email,
|
||||
notelp: body.notelp,
|
||||
alasan: body.alasan,
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Permohonan Keberatan Informasi Publik Berhasil Dibuat",
|
||||
data: {
|
||||
...body,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export default async function permohonanKeberatanInformasiPublikFindMany() {
|
||||
const res = await prisma.formulirPermohonanKeberatan.findMany();
|
||||
return {
|
||||
data: res,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import permohonanKeberatanInformasiPublikCreate from "./create";
|
||||
import permohonanKeberatanInformasiPublikFindMany from "./find-many";
|
||||
|
||||
const PermohonanKeberatanInformasiPublik = new Elysia({
|
||||
prefix: "/permohonankeberataninformasipublik",
|
||||
tags: ["PPID/Permohonan Keberatan Informasi Publik"],
|
||||
})
|
||||
.get("/find-many", permohonanKeberatanInformasiPublikFindMany)
|
||||
.post("/create", permohonanKeberatanInformasiPublikCreate, {
|
||||
body: t.Object({
|
||||
name: t.String(),
|
||||
email: t.String(),
|
||||
notelp: t.String(),
|
||||
alasan: t.String(),
|
||||
}),
|
||||
})
|
||||
|
||||
export default PermohonanKeberatanInformasiPublik;
|
||||
82
src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/edit-img.ts
Normal file
82
src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/edit-img.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Context } from "elysia";
|
||||
import { writeFile, unlink } from "fs/promises";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import { mkdir } from "fs/promises";
|
||||
|
||||
interface ProfilePPIDBody {
|
||||
id: string;
|
||||
file: Blob & { name: string; type: string };
|
||||
}
|
||||
|
||||
export default async function editImageProfilePPID(context: Context<{ body: ProfilePPIDBody }>) {
|
||||
const { id, file } = context.body;
|
||||
|
||||
if (!file || !id) {
|
||||
return {
|
||||
success: false,
|
||||
message: "File atau ID harus disertakan",
|
||||
};
|
||||
}
|
||||
|
||||
// Validasi ekstensi file
|
||||
const allowedTypes = ["image/jpeg", "image/png", "image/webp"];
|
||||
if (!allowedTypes.includes(file.type)) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Tipe file tidak diizinkan. Hanya JPG, PNG, atau WEBP",
|
||||
};
|
||||
}
|
||||
|
||||
const bytes = await file.arrayBuffer();
|
||||
const buffer = Buffer.from(bytes);
|
||||
const filename = `${id}_${Date.now()}_${file.name}`;
|
||||
const folderPath = path.resolve("public", "assets", "images", "ppid", "profile-ppid");
|
||||
|
||||
try {
|
||||
await mkdir(folderPath, { recursive: true });
|
||||
|
||||
console.log('Folder path:', folderPath);
|
||||
const filePath = path.join(folderPath, filename);
|
||||
console.log('File path:', filePath);
|
||||
|
||||
await writeFile(filePath, buffer);
|
||||
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Failed to write file to disk",
|
||||
};
|
||||
}
|
||||
|
||||
const imageUrl = `/assets/images/ppid/profile-ppid/${filename}`;
|
||||
|
||||
// Hapus file lama (opsional, kalau mau bersih)
|
||||
const oldData = await prisma.profilePPID.findUnique({ where: { id } });
|
||||
if (oldData?.imageUrl) {
|
||||
const oldPath = path.resolve("public", oldData.imageUrl.replace(/^\//, ""));
|
||||
if (fs.existsSync(oldPath)) {
|
||||
await unlink(oldPath).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
// Update DB
|
||||
await prisma.profilePPID.update({
|
||||
where: { id },
|
||||
data: { imageUrl },
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Gambar berhasil diunggah",
|
||||
url: imageUrl,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error uploading file:', error);
|
||||
return {
|
||||
success: false,
|
||||
message: "Gagal mengunggah gambar",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Context } from "elysia";
|
||||
|
||||
export default async function profilePPIDFindById(context: Context) {
|
||||
try {
|
||||
const id = context?.params?.slugs?.[0];
|
||||
|
||||
// If no ID provided, get the first profile
|
||||
if (!id) {
|
||||
const data = await prisma.profilePPID.findFirst();
|
||||
return {
|
||||
success: true,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
const data = await prisma.profilePPID.findUniqueOrThrow({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching profilePPID:", error);
|
||||
|
||||
return {
|
||||
success: false,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
};
|
||||
}
|
||||
}
|
||||
24
src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/index.ts
Normal file
24
src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/index.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import profilePPIDFindById from "./find-by-id";
|
||||
import profilePPIDUpdate from "./update";
|
||||
import editImageProfilePPID from "./edit-img";
|
||||
|
||||
const ProfilePPID = new Elysia({
|
||||
prefix: "/profileppid",
|
||||
tags: ["PPID/Profile PPID"]
|
||||
})
|
||||
.get("/find-by-id", profilePPIDFindById)
|
||||
.post("/update", profilePPIDUpdate, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
name: t.String(),
|
||||
biodata: t.String(),
|
||||
riwayat: t.String(),
|
||||
pengalaman: t.String(),
|
||||
unggulan: t.String(),
|
||||
})
|
||||
})
|
||||
.post("/edit-img", editImageProfilePPID)
|
||||
|
||||
|
||||
export default ProfilePPID;
|
||||
38
src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/update.ts
Normal file
38
src/app/api/[[...slugs]]/_lib/ppid/profile_ppid/update.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
|
||||
type FormCreate = Prisma.ProfilePPIDGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
name: true;
|
||||
biodata: true;
|
||||
riwayat: true;
|
||||
pengalaman: true;
|
||||
unggulan: true;
|
||||
}
|
||||
}>
|
||||
export default async function profilePPIDUpdate(context: Context) {
|
||||
const body = context.body as FormCreate;
|
||||
|
||||
await prisma.profilePPID.update({
|
||||
where: {
|
||||
id: body.id
|
||||
},
|
||||
data: {
|
||||
name: body.name,
|
||||
biodata: body.biodata,
|
||||
riwayat: body.riwayat,
|
||||
pengalaman: body.pengalaman,
|
||||
unggulan: body.unggulan,
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Profile PPID Berhasil Dibuat",
|
||||
data: {
|
||||
...body,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Context } from "elysia";
|
||||
|
||||
export default async function visimisiPPIDFindById(context: Context) {
|
||||
try {
|
||||
const id = context?.params?.slugs?.[0];
|
||||
|
||||
// If no ID provided, get the first profile
|
||||
if (!id) {
|
||||
const data = await prisma.visiMisiPPID.findFirst();
|
||||
return {
|
||||
success: true,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
const data = await prisma.visiMisiPPID.findUniqueOrThrow({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching visiPPID:", error);
|
||||
|
||||
return {
|
||||
success: false,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import Elysia from "elysia";
|
||||
import visimisiPPIDFindById from "./find-by-id";
|
||||
import visimisiPPIDUpdate from "./update";
|
||||
import { t } from "elysia";
|
||||
|
||||
const VisiMisiPPID = new Elysia({
|
||||
prefix: "/visimisippid",
|
||||
tags: ["PPID/Visi Misi PPID"]
|
||||
})
|
||||
.get("/find-by-id", visimisiPPIDFindById)
|
||||
.post("/update", visimisiPPIDUpdate, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
misi: t.String(),
|
||||
visi: t.String(),
|
||||
})
|
||||
})
|
||||
|
||||
export default VisiMisiPPID
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
|
||||
type FormCreate = Prisma.VisiMisiPPIDGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
misi: true;
|
||||
visi: true;
|
||||
}
|
||||
}>
|
||||
export default async function visimisiPPIDUpdate(context: Context) {
|
||||
const body = context.body as FormCreate;
|
||||
|
||||
await prisma.visiMisiPPID.update({
|
||||
where: {
|
||||
id: body.id
|
||||
},
|
||||
data: {
|
||||
misi: body.misi,
|
||||
visi: body.visi,
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Visi PPID Berhasil Diupdate",
|
||||
data: {
|
||||
...body,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { staticPlugin } from '@elysiajs/static'
|
||||
import cors, { HTTPMethod } from "@elysiajs/cors";
|
||||
import swagger from "@elysiajs/swagger";
|
||||
import { Elysia, t } from "elysia";
|
||||
@@ -22,7 +23,7 @@ if (!process.env.WIBU_UPLOAD_DIR)
|
||||
throw new Error("WIBU_UPLOAD_DIR is not defined");
|
||||
|
||||
const UPLOAD_DIR = path.join(ROOT, process.env.WIBU_UPLOAD_DIR);
|
||||
const UPLOAD_DIR_IMAGE = path.join(UPLOAD_DIR, "image");
|
||||
const UPLOAD_DIR_IMAGE = path.join(UPLOAD_DIR, "public", "assets", "images", "ppid", "profile-ppid");
|
||||
|
||||
// create uploads dir
|
||||
fs.mkdir(UPLOAD_DIR, {
|
||||
@@ -62,6 +63,10 @@ const Utils = new Elysia({
|
||||
|
||||
const ApiServer = new Elysia()
|
||||
.use(swagger({ path: "/api/docs" }))
|
||||
.use(staticPlugin({
|
||||
prefix: '/', // biar bisa akses dari root URL
|
||||
assets: './public'
|
||||
}))
|
||||
.use(cors(corsConfig))
|
||||
.use(PPID)
|
||||
.use(Kesehatan)
|
||||
|
||||
@@ -1,9 +1,37 @@
|
||||
'use client'
|
||||
import stateProfilePPID from '@/app/admin/(dashboard)/_state/ppid/profile_ppid/profile_PPID';
|
||||
import colors from '@/con/colors';
|
||||
import { Stack, Box, Text, Paper, Flex, Image, Divider, Center, SimpleGrid, List, ListItem } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { Box, Center, Divider, Flex, Image, List, Paper, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||
|
||||
function Page() {
|
||||
const allList = useProxy(stateProfilePPID)
|
||||
useShallowEffect(() => {
|
||||
allList.findById.load("1") // Assuming "1" is your default ID, adjust as needed
|
||||
}, [])
|
||||
|
||||
if (!allList.findById.data) return <Stack bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Skeleton style={{backgroundColor: colors.Bg}} h={40} />
|
||||
</Box>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Skeleton h={80} />
|
||||
</Box>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
{Array.from({ length: 10 }).map((v, k) =>
|
||||
<Skeleton key={k} h={40} />
|
||||
)}
|
||||
</Paper>
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
const dataArray = Array.isArray(allList.findById.data)
|
||||
? allList.findById.data
|
||||
: [allList.findById.data];
|
||||
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
@@ -14,101 +42,78 @@ function Page() {
|
||||
Profil Singkat PPID Desa Darmasaba
|
||||
</Text>
|
||||
</Box>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Flex align={"center"} gap={50}>
|
||||
<Image src={"/api/img/darmasaba-icon.png"} h={{ base: 80, md: 150 }} alt='' />
|
||||
<Text fz={{ base: "1.4rem", md: "2rem", lg: "2.5rem", xl: "3rem" }} fw={'bold'}>PROFIL PIMPINAN BADAN PUBLIK DESA DARMASABA </Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
<Divider my={"md"} />
|
||||
{/* biodata perbekel */}
|
||||
<Box px={{base: 0, md: 50}} pb={30}>
|
||||
<SimpleGrid
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 1,
|
||||
lg: 1,
|
||||
xl: 2,
|
||||
}}
|
||||
>
|
||||
<Box px={{ base: 0, md: 50 }}>
|
||||
<Paper bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
||||
<Stack gap={0}>
|
||||
<Center>
|
||||
<Image pt={{ base: 0, md: 90 }} src={"/api/img/perbekel.png"} w={{ base: 250, md: 355 }} alt='' />
|
||||
</Center>
|
||||
<Paper
|
||||
bg={colors['blue-button']}
|
||||
py={30}
|
||||
className="glass3"
|
||||
px={{ base: 20, md: 20 }}
|
||||
{dataArray.map((item) => (
|
||||
<Box key={item.id} px={{ base: "md", md: 100 }}>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Flex align={"center"} gap={50}>
|
||||
<Image src={"/api/img/darmasaba-icon.png"} h={{ base: 80, md: 150 }} alt='' />
|
||||
<Text fz={{ base: "1.4rem", md: "2rem", lg: "2.5rem", xl: "3rem" }} fw={'bold'}>PROFIL PIMPINAN BADAN PUBLIK DESA DARMASABA </Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
<Divider my={"md"} />
|
||||
{/* biodata perbekel */}
|
||||
<Box px={{ base: 0, md: 50 }} pb={30}>
|
||||
<SimpleGrid
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 1,
|
||||
lg: 1,
|
||||
xl: 2,
|
||||
}}
|
||||
>
|
||||
<Box px={{ base: 0, md: 50 }}>
|
||||
<Paper bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
||||
<Stack gap={0}>
|
||||
<Center>
|
||||
<Image pt={{ base: 0, md: 90 }} src={item.imageUrl ? `${item.imageUrl}?t=${Date.now()}` : "/api/img/perbekel.png"} w={{ base: 250, md: 355 }} alt='' />
|
||||
</Center>
|
||||
<Paper
|
||||
bg={colors['blue-button']}
|
||||
py={30}
|
||||
className="glass3"
|
||||
px={{ base: 20, md: 20 }}
|
||||
|
||||
>
|
||||
<Text ta={"center"} c={colors['white-1']} fw={"bolder"} fz={{ base: "1.5rem", md: "2.125rem", lg: "2.25rem", xl: "1.5rem" }}>
|
||||
I.B. Surya Prabhawa Manuaba,
|
||||
</Text>
|
||||
<Text ta={"center"} c={colors['white-1']} fw={"bolder"} fz={{ base: "1.5rem", md: "2.125rem", lg: "2.25rem", xl: "1.5rem" }}>
|
||||
S.H.,M.H.,NL.P.
|
||||
</Text>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
<Box>
|
||||
<Box>
|
||||
<Text fz={{ base: "1.125rem", md: "1.375rem", lg: "1.75rem", xl: "2rem" }} fw={'bold'}>Biodata</Text>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"}>I.B Surya Prabhawa Manuaba, S.H., M.H., adalah Perbekel Darmasaba periode 2021-2027, seorang advokat, pendiri Mantra Legal Consultants & Advocates, serta aktif di bidang musik dan akademis.</Text>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"}>Dia menempuh pendidikan hukum di Universitas Udayana dan Universitas Mahasaraswati Denpasar, serta memiliki pengalaman luas di berbagai organisasi dan kepemimpinan.</Text>
|
||||
>
|
||||
<Text ta={"center"} c={colors['white-1']} fw={"bolder"} fz={{ base: "1.5rem", md: "2.125rem", lg: "2.25rem", xl: "1.5rem" }}>
|
||||
{item.name}
|
||||
</Text>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fz={{ base: "1.125rem", md: "1.375rem", lg: "1.75rem", xl: "2rem" }} fw={'bold'}>Riwayat Karir</Text>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} >2021 - 2027: Perbekel Desa Darmasaba</Text>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} >2015 - Sekarang: Founder & Managing Director Mantra Legal Consultants & Advocates</Text>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} >2020 - Sekarang: Founder Ugawa Record Music Studio</Text>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} >2010 - 2016: Dosen Fakultas Hukum Universitas Mahasaraswati Denpasar</Text>
|
||||
<Box>
|
||||
<Text fz={{ base: "1.125rem", md: "1.375rem", lg: "1.75rem", xl: "2rem" }} fw={'bold'}>Biodata</Text>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: item.biodata }} />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fz={{ base: "1.125rem", md: "1.375rem", lg: "1.75rem", xl: "2rem" }} fw={'bold'}>Riwayat Karir</Text>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} dangerouslySetInnerHTML={{ __html: item.riwayat }} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
<Box pb={30}>
|
||||
<Text fz={{ base: "1.125rem", md: "1.375rem", lg: "1.75rem", xl: "2rem" }} fw={'bold'}>Pengalaman Organisasi</Text>
|
||||
<List>
|
||||
<Box px={20}>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"}>1996 - 1997: Ketua OSIS SMP Negeri 1 Abiansemal</ListItem>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"}>1999 - 2000: Ketua OSIS SMA Negeri 1 Mengwi</ListItem>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"}>2008 - 2009: Ketua BEM Universitas Mahasaraswati Denpasar</ListItem>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} >2008 - 2010: Ketua Sekaa Taruna Sila Dharma, Banjar Tengah, Desa Adat Tegal, Darmasaba</ListItem>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} >2020 - Sekarang: Pengurus Young Lawyer Committee Peradi Denpasar</ListItem>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} >2021 - Sekarang: Dewan Kehormatan Himpunan Pengusaha Muda Indonesia (HIPMI) Badung</ListItem>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} >2023 - 2028: Komite Tetap Advokasi - Bidang Hukum dan Regulasi Kamar Dagang dan Industri Badung</ListItem>
|
||||
</Box>
|
||||
</List>
|
||||
</Box>
|
||||
<Box pb={20}>
|
||||
<Text pb={20} fz={{ base: "1.125rem", md: "1.375rem", lg: "1.75rem", xl: "2rem" }} fw={'bold'}>Program Kerja Unggulan</Text>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} fw={'bold'}>Pemberdayaan Ekonomi dan UMKM</Text>
|
||||
<List>
|
||||
<Box px={20}>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"}>Pelatihan dan pendampingan UMKM lokal</ListItem>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"}>Program bantuan modal usaha bagi pelaku usaha kecil</ListItem>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"}>Digitalisasi UMKM untuk meningkatkan pemasaran produk lokal</ListItem>
|
||||
</Box>
|
||||
</List>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} fw={'bold'}>Peningkatan Infrastruktur Desa</Text>
|
||||
<List>
|
||||
<Box px={20}>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"}>Pembangunan dan perbaikan jalan desa</ListItem>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"}>Penyediaan fasilitas umum dan ruang terbuka hijau</ListItem>
|
||||
<ListItem fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"}>Optimalisasi layanan publik berbasis digital</ListItem>
|
||||
</Box>
|
||||
</List>
|
||||
</Box>
|
||||
</Paper>
|
||||
</Box>
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
<Box pb={30}>
|
||||
<Text fz={{ base: "1.125rem", md: "1.375rem", lg: "1.75rem", xl: "2rem" }} fw={'bold'}>Pengalaman Organisasi</Text>
|
||||
<List>
|
||||
<Box px={20}>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: item.pengalaman }} />
|
||||
</Box>
|
||||
</List>
|
||||
</Box>
|
||||
<Box pb={20}>
|
||||
<Text fz={{ base: "1.125rem", md: "1.375rem", lg: "1.75rem", xl: "2rem" }} fw={'bold'}>Program Kerja Unggulan</Text>
|
||||
<List>
|
||||
<Box px={20}>
|
||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem", xl: "1.5rem" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: item.unggulan }} />
|
||||
</Box>
|
||||
</List>
|
||||
</Box>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,54 +1,60 @@
|
||||
'use client'
|
||||
import stateVisiMisiPPID from '@/app/admin/(dashboard)/_state/ppid/visi_misi_ppid/visimisiPPID';
|
||||
import colors from '@/con/colors';
|
||||
import { Stack, Box, Paper, Text, Image, Center, ListItem, List } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { Box, Center, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||
|
||||
function Page() {
|
||||
const allList = useProxy(stateVisiMisiPPID)
|
||||
useShallowEffect(() => {
|
||||
allList.findById.load("1") // Assuming "1" is your default ID, adjust as needed
|
||||
}, [])
|
||||
|
||||
if (!allList.findById.data) return <Stack>
|
||||
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
</Stack>
|
||||
|
||||
const dataArray = Array.isArray(allList.findById.data)
|
||||
? allList.findById.data
|
||||
: [allList.findById.data];
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
<Box pb={30}>
|
||||
<Center>
|
||||
<Image src={"/api/img/darmasaba-icon.png"} w={{ base: 100, md: 150 }} alt='' />
|
||||
</Center>
|
||||
<Text ta={"center"} fz={{ base: "h2", md: "2.5rem" }} fw={"bold"}>
|
||||
MOTO PPID DESA DARMASABA
|
||||
</Text>
|
||||
<Text ta={"center"} fz={{ base: "h4", md: "h3" }} >
|
||||
MEMBERIKAN INFORMASI YANG CEPAT, MUDAH, TEPAT DAN TRANSPARAN
|
||||
</Text>
|
||||
</Box>
|
||||
<Box px={{ base: 20, md: 50 }} pb={30}>
|
||||
<Text ta={"center"} fz={{ base: "h3", md: "h2" }} fw={"bold"}>
|
||||
VISI PPID
|
||||
</Text>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"}>
|
||||
Memberikan pelayanan informasi yanng transparan dan akuntabel untuk memenuhi hak pemohon informasi
|
||||
sesuai dengan ketentuan peraturan perundang-undangan yang berlaku.
|
||||
</Text>
|
||||
</Box>
|
||||
<Box px={{ base: 20, md: 50 }}>
|
||||
<Text ta={"center"} fz={{ base: "h3", md: "h2" }} fw={"bold"}>
|
||||
MISI PPID
|
||||
</Text>
|
||||
<Box >
|
||||
<List type='ordered'>
|
||||
<ListItem fz={{ base: "md", md: "h3" }} ta={"justify"}>Meningkatkan pengelolaan dan pelayanan informasi yang berkualitas, benar dan bertanggung jawab</ListItem>
|
||||
<ListItem fz={{ base: "md", md: "h3" }} ta={"justify"}>Membangun dan mengembangkan sistem penyediaan dan layanan informasi.</ListItem>
|
||||
<ListItem fz={{ base: "md", md: "h3" }} ta={"justify"}>Meningkatkan dan mengembangkan kompetensi dan kualitas SDM dalam bidang pelayanan informasi.</ListItem>
|
||||
<ListItem fz={{ base: "md", md: "h3" }} >Mewujudkan keterbukaan informasi Pemerintah Desa Punggul dengan proses yang cepat, tepat, mudah
|
||||
dan sederhana.</ListItem>
|
||||
</List>
|
||||
{dataArray.map((item) => (
|
||||
<Box key={item.id} px={{ base: "md", md: 100 }}>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
<Box pb={30}>
|
||||
<Center>
|
||||
<Image src={"/api/img/darmasaba-icon.png"} w={{ base: 100, md: 150 }} alt='' />
|
||||
</Center>
|
||||
<Text ta={"center"} fz={{ base: "h2", md: "2.5rem" }} fw={"bold"}>
|
||||
MOTO PPID DESA DARMASABA
|
||||
</Text>
|
||||
<Text ta={"center"} fz={{ base: "h4", md: "h3" }} >
|
||||
MEMBERIKAN INFORMASI YANG CEPAT, MUDAH, TEPAT DAN TRANSPARAN
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
<Box px={{ base: 20, md: 50 }} pb={30}>
|
||||
<Text ta={"center"} fz={{ base: "h3", md: "h2" }} fw={"bold"}>
|
||||
VISI PPID
|
||||
</Text>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: item.visi }} />
|
||||
</Box>
|
||||
<Box px={{ base: 20, md: 50 }}>
|
||||
<Text ta={"center"} fz={{ base: "h3", md: "h2" }} fw={"bold"}>
|
||||
MISI PPID
|
||||
</Text>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: item.misi }} />
|
||||
</Box>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { AppServer } from '@/app/api/[[...slugs]]/route'
|
||||
import { treaty } from '@elysiajs/eden'
|
||||
const ApiFetch = treaty<AppServer>(process.env.NEXT_PUBLIC_WIBU_URL || 'localhost:3000')
|
||||
|
||||
const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || 'localhost:3000'
|
||||
const ApiFetch = treaty<AppServer>(BASE_URL)
|
||||
|
||||
export default ApiFetch
|
||||
Reference in New Issue
Block a user