Fix QC Kak Inno : tanggal 14 Oktober
Fitur Search bisa digunakan di 6 Menu, sisa 3 Menu Lagi
This commit is contained in:
@@ -66,7 +66,7 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
|
|||||||
return (
|
return (
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<Title order={2} fw={700} style={{ color: "#1A1B1E" }}>
|
<Title order={2} fw={700} style={{ color: "#1A1B1E" }}>
|
||||||
Profil Desa
|
Profile Desa
|
||||||
</Title>
|
</Title>
|
||||||
|
|
||||||
<Tabs
|
<Tabs
|
||||||
|
|||||||
@@ -304,6 +304,403 @@ export default async function searchFindMany(context: Context) {
|
|||||||
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========================================= LAYANAN DESA ========================================= //
|
||||||
|
if (type === "pelayananSuratKeterangan") {
|
||||||
|
const data = await prisma.pelayananSuratKeterangan.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "pelayananPerizinanBerusaha") {
|
||||||
|
const data = await prisma.pelayananPerizinanBerusaha.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "pelayananTelunjukSaktiDesa") {
|
||||||
|
const data = await prisma.pelayananTelunjukSaktiDesa.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "pelayananPendudukNonPermanen") {
|
||||||
|
const data = await prisma.pelayananPendudukNonPermanen.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= PENGHARGAAN ========================================= //
|
||||||
|
if (type === "penghargaan") {
|
||||||
|
const data = await prisma.penghargaan.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= MENU KESEHATAN ========================================= //
|
||||||
|
// ========================================= POSYANDU ========================================= //
|
||||||
|
if (type === "posyandu") {
|
||||||
|
const data = await prisma.posyandu.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
// ========================================= DATA KESEHATAN WARGA ========================================= //
|
||||||
|
// ========================================= FASILITAS KESEHATAN ========================================= //
|
||||||
|
if (type === "fasilitasKesehatan") {
|
||||||
|
const data = await prisma.fasilitasKesehatan.findMany({
|
||||||
|
where: {
|
||||||
|
name: { contains: query, mode: "insensitive" },
|
||||||
|
informasiumum: { fasilitas: { contains: query, mode: "insensitive" } },
|
||||||
|
layananunggulan: { content: { contains: query, mode: "insensitive" } },
|
||||||
|
dokterdantenagamedis: {
|
||||||
|
name: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
fasilitaspendukung: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
prosedurpendaftaran: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
tarifdanlayanan: { layanan: { contains: query, mode: "insensitive" } },
|
||||||
|
},
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= JADWAL KEGIATAN ========================================= //
|
||||||
|
if (type === "jadwalKegiatan") {
|
||||||
|
const data = await prisma.jadwalKegiatan.findMany({
|
||||||
|
where: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
informasijadwalkegiatan: {
|
||||||
|
name: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
deskripsijadwalkegiatan: {
|
||||||
|
deskripsi: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
layananjadwalkegiatan: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
syaratketentuanjadwalkegiatan: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
dokumenjadwalkegiatan: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
pendaftaranjadwalkegiatan: {
|
||||||
|
name: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= ARTIKEL KESEHATAN ========================================= //
|
||||||
|
if (type === "artikelKesehatan") {
|
||||||
|
const data = await prisma.artikelKesehatan.findMany({
|
||||||
|
where: {
|
||||||
|
title: { contains: query, mode: "insensitive" },
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
introduction: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
symptom: {
|
||||||
|
title: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
prevention: {
|
||||||
|
title: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
firstaid: {
|
||||||
|
title: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
mythvsfact: {
|
||||||
|
title: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
doctorsign: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= PUSKESMAS ========================================= //
|
||||||
|
if (type === "puskesmas") {
|
||||||
|
const data = await prisma.puskesmas.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= PROGRAM KESEHATAN ========================================= //
|
||||||
|
if (type === "programKesehatan") {
|
||||||
|
const data = await prisma.programKesehatan.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= PENANGANAN DARURAT ========================================= //
|
||||||
|
if (type === "penangananDarurat") {
|
||||||
|
const data = await prisma.penangananDarurat.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= KONTAK DARURAT ========================================= //
|
||||||
|
if (type === "kontakDarurat") {
|
||||||
|
const data = await prisma.kontakDarurat.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= INFO WABAH PENYAKIT ========================================= //
|
||||||
|
if (type === "infoWabahPenyakit") {
|
||||||
|
const data = await prisma.infoWabahPenyakit.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= MENU KEAMANAN ========================================= //
|
||||||
|
// ========================================= KEAMANAN LINGKUNGAN ========================================= //
|
||||||
|
if (type === "keamananLingkungan") {
|
||||||
|
const data = await prisma.keamananLingkungan.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= POLSEK TERDEKAT ========================================= //
|
||||||
|
if (type === "polsekTerdekat") {
|
||||||
|
const data = await prisma.polsekTerdekat.findMany({
|
||||||
|
where: { nama: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= KONTAK DARURAT ========================================= //
|
||||||
|
if (type === "kontakDaruratKeamanan") {
|
||||||
|
const data = await prisma.kontakDaruratKeamanan.findMany({
|
||||||
|
where: { nama: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= PENCEGAHAN KRIMINALITAS ========================================= //
|
||||||
|
if (type === "pencegahanKriminalitas") {
|
||||||
|
const data = await prisma.pencegahanKriminalitas.findMany({
|
||||||
|
where: { judul: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= LAPORAN PUBLIK ========================================= //
|
||||||
|
if (type === "laporanPublik") {
|
||||||
|
const data = await prisma.laporanPublik.findMany({
|
||||||
|
where: { judul: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= TIPS KEAMANAN ========================================= //
|
||||||
|
if (type === "tipsKeamanan") {
|
||||||
|
const data = await prisma.menuTipsKeamanan.findMany({
|
||||||
|
where: { judul: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= MENU EKONOMI ========================================= //
|
||||||
|
// ========================================= PASAR DESA ========================================= //
|
||||||
|
if (type === "pasarDesa") {
|
||||||
|
const data = await prisma.pasarDesa.findMany({
|
||||||
|
where: { nama: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= LOWONGAN KERJA LOKAL ========================================= //
|
||||||
|
if (type === "lowonganKerjaLokal") {
|
||||||
|
const data = await prisma.lowonganPekerjaan.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ posisi: { contains: query, mode: "insensitive" } },
|
||||||
|
{ namaPerusahaan: { contains: query, mode: "insensitive" } },
|
||||||
|
{ lokasi: { contains: query, mode: "insensitive" } },
|
||||||
|
{ tipePekerjaan: { contains: query, mode: "insensitive" } },
|
||||||
|
{ gaji: { contains: query, mode: "insensitive" } },
|
||||||
|
{ deskripsi: { contains: query, mode: "insensitive" } },
|
||||||
|
{ kualifikasi: { contains: query, mode: "insensitive" } },
|
||||||
|
{ notelp: { contains: query, mode: "insensitive" } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
// ========================================= STRUKTUR ORGANISASI ========================================= //
|
||||||
|
if (type === "strukturOrganisasi") {
|
||||||
|
const data = await prisma.strukturBumDes.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ name: { contains: query, mode: "insensitive" } },
|
||||||
|
{ PosisiOrganisasiBumDes: { nama: { contains: query, mode: "insensitive" } } },
|
||||||
|
{ PegawaiBumDes: { namaLengkap: { contains: query, mode: "insensitive" } } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= JUMLAH PENDUDUK USIA KERJA YANG MENGANGGUR ========================================= //
|
||||||
|
if (type === "jumlahPendudukUsiaKerjaYangMenganggurUsia") {
|
||||||
|
const data = await prisma.grafikMenganggurBerdasarkanUsia.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ usia18_25: { contains: query, mode: "insensitive" } },
|
||||||
|
{ usia26_35: { contains: query, mode: "insensitive" } },
|
||||||
|
{ usia36_45: { contains: query, mode: "insensitive" } },
|
||||||
|
{ usia46_keatas: { contains: query, mode: "insensitive" } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= JUMLAH PENDUDUK USIA KERJA YANG MENGANGGUR ========================================= //
|
||||||
|
if (type === "jumlahPendudukUsiaKerjaYangMenganggurPendidikan") {
|
||||||
|
const data = await prisma.grafikMenganggurBerdasarkanPendidikan.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ SD: { contains: query, mode: "insensitive" } },
|
||||||
|
{ SMP: { contains: query, mode: "insensitive" } },
|
||||||
|
{ SMA: { contains: query, mode: "insensitive" } },
|
||||||
|
{ D3: { contains: query, mode: "insensitive" } },
|
||||||
|
{ S1: { contains: query, mode: "insensitive" } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= JUMLAH PENDUDUK MISKIN ========================================= //
|
||||||
|
if (type === "jumlahPendudukMiskin") {
|
||||||
|
const data = await prisma.grafikJumlahPendudukMiskin.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
// Convert year to string for partial matching
|
||||||
|
...(isNaN(Number(query)) ? [] : [
|
||||||
|
{ year: { equals: Number(query) } }
|
||||||
|
]),
|
||||||
|
// Convert totalPoorPopulation to string for partial matching
|
||||||
|
...(isNaN(Number(query)) ? [] : [
|
||||||
|
{ totalPoorPopulation: { equals: Number(query) } }
|
||||||
|
])
|
||||||
|
].filter(Boolean), // Remove any empty arrays from the spread
|
||||||
|
},
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
// ========================================= PROGRAM KEMISKINAN ========================================= //
|
||||||
|
if (type === "programKemiskinan") {
|
||||||
|
const data = await prisma.programKemiskinan.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ nama: { contains: query, mode: "insensitive" } },
|
||||||
|
{ deskripsi: { contains: query, mode: "insensitive" } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ========================================= SEKTOR UNGGULAN DESA ========================================= //
|
||||||
|
if (type === "sektorUnggulanDesa") {
|
||||||
|
const data = await prisma.sektorUnggulanDesa.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ name: { contains: query, mode: "insensitive" } },
|
||||||
|
{ description: { contains: query, mode: "insensitive" } }
|
||||||
|
],
|
||||||
|
},
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================= DEMOGRAFI PEKERJAAN ========================================= //
|
||||||
|
if (type === "demografiPekerjaan") {
|
||||||
|
const data = await prisma.dataDemografiPekerjaan.findMany({
|
||||||
|
where: { pekerjaan: { contains: query, mode: "insensitive" } },
|
||||||
|
skip,
|
||||||
|
take: limitNum,
|
||||||
|
});
|
||||||
|
return { data, nextPage: data.length < limitNum ? null : pageNum + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
// 🌍 GLOBAL SEARCH — cari di beberapa modul sekaligus
|
// 🌍 GLOBAL SEARCH — cari di beberapa modul sekaligus
|
||||||
const [
|
const [
|
||||||
pejabatdesa,
|
pejabatdesa,
|
||||||
@@ -337,8 +734,32 @@ export default async function searchFindMany(context: Context) {
|
|||||||
pelayananSuratKeterangan,
|
pelayananSuratKeterangan,
|
||||||
pelayananPerizinanBerusaha,
|
pelayananPerizinanBerusaha,
|
||||||
pelayananTelunjukSaktiDesa,
|
pelayananTelunjukSaktiDesa,
|
||||||
pelayananPendudukNonPermanent,
|
pelayananPendudukNonPermanen,
|
||||||
penghargaan
|
penghargaan,
|
||||||
|
posyandu,
|
||||||
|
fasilitasKesehatan,
|
||||||
|
jadwalKegiatan,
|
||||||
|
artikelKesehatan,
|
||||||
|
puskesmas,
|
||||||
|
programKesehatan,
|
||||||
|
penangananDarurat,
|
||||||
|
kontakDarurat,
|
||||||
|
infoWabahPenyakit,
|
||||||
|
keamananLingkungan,
|
||||||
|
polsekTerdekat,
|
||||||
|
kontakDaruratKeamanan,
|
||||||
|
pencegahanKriminalitas,
|
||||||
|
laporanPublik,
|
||||||
|
tipsKeamanan,
|
||||||
|
pasarDesa,
|
||||||
|
lowonganKerjaLokal,
|
||||||
|
strukturOrganisasi,
|
||||||
|
jumlahPendudukUsiaKerjaYangMenganggurUsia,
|
||||||
|
jumlahPendudukUsiaKerjaYangMenganggurPendidikan,
|
||||||
|
jumlahPendudukMiskin,
|
||||||
|
programKemiskinan,
|
||||||
|
sektorUnggulanDesa,
|
||||||
|
demografiPekerjaan,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
prisma.pejabatDesa.findMany({
|
prisma.pejabatDesa.findMany({
|
||||||
where: { name: { contains: query, mode: "insensitive" } },
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
@@ -486,6 +907,197 @@ export default async function searchFindMany(context: Context) {
|
|||||||
where: { name: { contains: query, mode: "insensitive" } },
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
take: limitNum,
|
take: limitNum,
|
||||||
}),
|
}),
|
||||||
|
prisma.posyandu.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.fasilitasKesehatan.findMany({
|
||||||
|
where: {
|
||||||
|
name: { contains: query, mode: "insensitive" },
|
||||||
|
informasiumum: { fasilitas: { contains: query, mode: "insensitive" } },
|
||||||
|
layananunggulan: { content: { contains: query, mode: "insensitive" } },
|
||||||
|
dokterdantenagamedis: {
|
||||||
|
name: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
fasilitaspendukung: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
prosedurpendaftaran: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
tarifdanlayanan: { layanan: { contains: query, mode: "insensitive" } },
|
||||||
|
},
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.jadwalKegiatan.findMany({
|
||||||
|
where: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
informasijadwalkegiatan: {
|
||||||
|
name: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
deskripsijadwalkegiatan: {
|
||||||
|
deskripsi: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
layananjadwalkegiatan: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
syaratketentuanjadwalkegiatan: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
dokumenjadwalkegiatan: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
pendaftaranjadwalkegiatan: {
|
||||||
|
name: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.artikelKesehatan.findMany({
|
||||||
|
where: {
|
||||||
|
title: { contains: query, mode: "insensitive" },
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
introduction: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
symptom: {
|
||||||
|
title: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
prevention: {
|
||||||
|
title: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
firstaid: {
|
||||||
|
title: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
mythvsfact: {
|
||||||
|
title: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
doctorsign: {
|
||||||
|
content: { contains: query, mode: "insensitive" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.puskesmas.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.programKesehatan.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.penangananDarurat.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.kontakDarurat.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.infoWabahPenyakit.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.keamananLingkungan.findMany({
|
||||||
|
where: { name: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.polsekTerdekat.findMany({
|
||||||
|
where: { nama: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.kontakDaruratKeamanan.findMany({
|
||||||
|
where: { nama: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.pencegahanKriminalitas.findMany({
|
||||||
|
where: { judul: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.laporanPublik.findMany({
|
||||||
|
where: { judul: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.menuTipsKeamanan.findMany({
|
||||||
|
where: { judul: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.pasarDesa.findMany({
|
||||||
|
where: { nama: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.lowonganPekerjaan.findMany({
|
||||||
|
where: { posisi: { contains: query, mode: "insensitive" } },
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.strukturBumDes.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ name: { contains: query, mode: "insensitive" } },
|
||||||
|
{ PosisiOrganisasiBumDes: { nama: { contains: query, mode: "insensitive" } } },
|
||||||
|
{ PegawaiBumDes: { namaLengkap: { contains: query, mode: "insensitive" } } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.grafikMenganggurBerdasarkanUsia.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ usia18_25: { contains: query, mode: "insensitive" } },
|
||||||
|
{ usia26_35: { contains: query, mode: "insensitive" } },
|
||||||
|
{ usia36_45: { contains: query, mode: "insensitive" } },
|
||||||
|
{ usia46_keatas: { contains: query, mode: "insensitive" } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.grafikMenganggurBerdasarkanPendidikan.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ SD: { contains: query, mode: "insensitive" } },
|
||||||
|
{ SMP: { contains: query, mode: "insensitive" } },
|
||||||
|
{ SMA: { contains: query, mode: "insensitive" } },
|
||||||
|
{ D3: { contains: query, mode: "insensitive" } },
|
||||||
|
{ S1: { contains: query, mode: "insensitive" } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.grafikJumlahPendudukMiskin.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
...(isNaN(Number(query)) ? [] : [
|
||||||
|
{ year: { equals: Number(query) } },
|
||||||
|
{ totalPoorPopulation: { equals: Number(query) } }
|
||||||
|
])
|
||||||
|
].filter(Boolean),
|
||||||
|
},
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.programKemiskinan.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ nama: { contains: query, mode: "insensitive" } },
|
||||||
|
{ deskripsi: { contains: query, mode: "insensitive" } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.sektorUnggulanDesa.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ name: { contains: query, mode: "insensitive" } },
|
||||||
|
{ description: { contains: query, mode: "insensitive" } }
|
||||||
|
],
|
||||||
|
},
|
||||||
|
take: limitNum,
|
||||||
|
}),
|
||||||
|
prisma.dataDemografiPekerjaan.findMany({
|
||||||
|
where: {
|
||||||
|
pekerjaan: { contains: query, mode: "insensitive" }
|
||||||
|
},
|
||||||
|
take: limitNum,
|
||||||
|
})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -527,11 +1139,48 @@ export default async function searchFindMany(context: Context) {
|
|||||||
...pengumuman.map((b) => ({ type: "pengumuman", ...b })),
|
...pengumuman.map((b) => ({ type: "pengumuman", ...b })),
|
||||||
...galleryFoto.map((b) => ({ type: "galleryFoto", ...b })),
|
...galleryFoto.map((b) => ({ type: "galleryFoto", ...b })),
|
||||||
...galleryVideo.map((b) => ({ type: "galleryVideo", ...b })),
|
...galleryVideo.map((b) => ({ type: "galleryVideo", ...b })),
|
||||||
...pelayananSuratKeterangan.map((b) => ({ type: "pelayananSuratKeterangan", ...b })),
|
...pelayananSuratKeterangan.map((b) => ({
|
||||||
...pelayananPerizinanBerusaha.map((b) => ({ type: "pelayananPerizinanBerusaha", ...b })),
|
type: "pelayananSuratKeterangan",
|
||||||
...pelayananTelunjukSaktiDesa.map((b) => ({ type: "pelayananTelunjukSaktiDesa", ...b })),
|
...b,
|
||||||
...pelayananPendudukNonPermanent.map((b) => ({ type: "pelayananPendudukNonPermanent", ...b })),
|
})),
|
||||||
|
...pelayananPerizinanBerusaha.map((b) => ({
|
||||||
|
type: "pelayananPerizinanBerusaha",
|
||||||
|
...b,
|
||||||
|
})),
|
||||||
|
...pelayananTelunjukSaktiDesa.map((b) => ({
|
||||||
|
type: "pelayananTelunjukSaktiDesa",
|
||||||
|
...b,
|
||||||
|
})),
|
||||||
|
...pelayananPendudukNonPermanen.map((b) => ({
|
||||||
|
type: "pelayananPendudukNonPermanen",
|
||||||
|
...b,
|
||||||
|
})),
|
||||||
...penghargaan.map((b) => ({ type: "penghargaan", ...b })),
|
...penghargaan.map((b) => ({ type: "penghargaan", ...b })),
|
||||||
|
...posyandu.map((b) => ({ type: "posyandu", ...b })),
|
||||||
|
...fasilitasKesehatan.map((b) => ({ type: "fasilitasKesehatan", ...b })),
|
||||||
|
...jadwalKegiatan.map((b) => ({ type: "jadwalKegiatan", ...b })),
|
||||||
|
...artikelKesehatan.map((b) => ({ type: "artikelKesehatan", ...b })),
|
||||||
|
...puskesmas.map((b) => ({ type: "puskesmas", ...b })),
|
||||||
|
...programKesehatan.map((b) => ({ type: "programKesehatan", ...b })),
|
||||||
|
...penangananDarurat.map((b) => ({ type: "penangananDarurat", ...b })),
|
||||||
|
...kontakDarurat.map((b) => ({ type: "kontakDarurat", ...b })),
|
||||||
|
...infoWabahPenyakit.map((b) => ({ type: "infoWabahPenyakit", ...b })),
|
||||||
|
...keamananLingkungan.map((b) => ({ type: "keamananLingkungan", ...b })),
|
||||||
|
...polsekTerdekat.map((b) => ({ type: "polsekTerdekat", ...b })),
|
||||||
|
...kontakDaruratKeamanan.map((b) => ({ type: "kontakDaruratKeamanan", ...b })),
|
||||||
|
...pencegahanKriminalitas.map((b) => ({ type: "pencegahanKriminalitas", ...b })),
|
||||||
|
...laporanPublik.map((b) => ({ type: "laporanPublik", ...b })),
|
||||||
|
...tipsKeamanan.map((b) => ({ type: "tipsKeamanan", ...b })),
|
||||||
|
...pasarDesa.map((b) => ({ type: "pasarDesa", ...b })),
|
||||||
|
...lowonganKerjaLokal.map((b) => ({ type: "lowonganKerjaLokal", ...b })),
|
||||||
|
...strukturOrganisasi.map((b) => ({ type: "strukturOrganisasi", ...b })),
|
||||||
|
...jumlahPendudukUsiaKerjaYangMenganggurUsia.map((b) => ({ type: "jumlahPendudukUsiaKerjaYangMenganggurUsia", ...b })),
|
||||||
|
...jumlahPendudukUsiaKerjaYangMenganggurPendidikan.map((b) => ({ type: "jumlahPendudukUsiaKerjaYangMenganggurPendidikan", ...b })),
|
||||||
|
...jumlahPendudukMiskin.map((b) => ({ type: "jumlahPendudukMiskin", ...b })),
|
||||||
|
...programKemiskinan.map((b) => ({ type: "programKemiskinan", ...b })),
|
||||||
|
...sektorUnggulanDesa.map((b) => ({ type: "sektorUnggulanDesa", ...b })),
|
||||||
|
...demografiPekerjaan.map((b) => ({ type: "demografiPekerjaan", ...b })),
|
||||||
|
|
||||||
],
|
],
|
||||||
nextPage: null, // bisa dibuat lebih kompleks kalau perlu
|
nextPage: null, // bisa dibuat lebih kompleks kalau perlu
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
'use client';
|
'use client';
|
||||||
import { proxy, subscribe } from 'valtio';
|
import { proxy } from 'valtio';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import ApiFetch from '@/lib/api-fetch';
|
import ApiFetch from '@/lib/api-fetch';
|
||||||
|
|
||||||
interface SearchResult {
|
interface SearchResult {
|
||||||
type?: string; // optional biar gak error
|
type?: string;
|
||||||
id: string | number;
|
id: string | number;
|
||||||
title?: string;
|
title?: string;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
@@ -21,10 +21,13 @@ const searchState = proxy({
|
|||||||
loading: false,
|
loading: false,
|
||||||
|
|
||||||
async fetch() {
|
async fetch() {
|
||||||
if (!searchState.query) return;
|
if (!searchState.query) {
|
||||||
|
searchState.results = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
searchState.loading = true;
|
searchState.loading = true;
|
||||||
|
|
||||||
try {
|
|
||||||
const res = await ApiFetch.api.search.findMany.get({
|
const res = await ApiFetch.api.search.findMany.get({
|
||||||
query: {
|
query: {
|
||||||
query: searchState.query,
|
query: searchState.query,
|
||||||
@@ -34,23 +37,14 @@ const searchState = proxy({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = (res.data?.data || []).map((item: any) => ({
|
|
||||||
type: item.type ?? 'unknown', // pastikan selalu ada type
|
|
||||||
...item,
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (searchState.page === 1) {
|
if (searchState.page === 1) {
|
||||||
searchState.results = data;
|
searchState.results = res.data?.data || [];
|
||||||
} else {
|
} else {
|
||||||
searchState.results.push(...data);
|
searchState.results.push(...(res.data?.data || []));
|
||||||
}
|
}
|
||||||
|
|
||||||
searchState.nextPage = res.data?.nextPage || null;
|
searchState.nextPage = res.data?.nextPage || null;
|
||||||
} catch (e) {
|
|
||||||
console.error('Search fetch error:', e);
|
|
||||||
} finally {
|
|
||||||
searchState.loading = false;
|
searchState.loading = false;
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async next() {
|
async next() {
|
||||||
@@ -60,15 +54,95 @@ const searchState = proxy({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 🔁 Auto debounce search trigger
|
// 🕒 debounce-nya tetap kita export biar bisa dipanggil manual
|
||||||
const debouncedFetch = debounce(() => {
|
export const debouncedFetch = debounce(() => {
|
||||||
if (!searchState.query) return;
|
|
||||||
searchState.page = 1;
|
searchState.page = 1;
|
||||||
searchState.fetch();
|
searchState.fetch();
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
subscribe(searchState, () => {
|
|
||||||
debouncedFetch();
|
|
||||||
});
|
|
||||||
|
|
||||||
export default searchState;
|
export default searchState;
|
||||||
|
|
||||||
|
|
||||||
|
// 'use client';
|
||||||
|
// import { proxy, subscribe } from 'valtio';
|
||||||
|
// import { debounce } from 'lodash';
|
||||||
|
// import ApiFetch from '@/lib/api-fetch';
|
||||||
|
|
||||||
|
// interface SearchResult {
|
||||||
|
// type?: string;
|
||||||
|
// id: string | number;
|
||||||
|
// title?: string;
|
||||||
|
// [key: string]: any;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const searchState = proxy({
|
||||||
|
// query: '',
|
||||||
|
// page: 1,
|
||||||
|
// limit: 10,
|
||||||
|
// type: '', // kosong = global search
|
||||||
|
// results: [] as SearchResult[],
|
||||||
|
// nextPage: null as number | null,
|
||||||
|
// loading: false,
|
||||||
|
|
||||||
|
// // --- fetch utama ---
|
||||||
|
// async fetch() {
|
||||||
|
// if (!searchState.query.trim()) {
|
||||||
|
// // 🧹 kalau query kosong, kosongin data dan stop
|
||||||
|
// searchState.results = [];
|
||||||
|
// searchState.nextPage = null;
|
||||||
|
// searchState.loading = false;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// searchState.loading = true;
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// const res = await ApiFetch.api.search.findMany.get({
|
||||||
|
// query: {
|
||||||
|
// query: searchState.query,
|
||||||
|
// page: searchState.page,
|
||||||
|
// limit: searchState.limit,
|
||||||
|
// type: searchState.type,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const newData = res.data?.data || [];
|
||||||
|
|
||||||
|
// // Kalau ini page pertama, replace data
|
||||||
|
// if (searchState.page === 1) {
|
||||||
|
// searchState.results = newData;
|
||||||
|
// } else {
|
||||||
|
// // Kalau page berikutnya, append data
|
||||||
|
// searchState.results = [...searchState.results, ...newData];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// searchState.nextPage = res.data?.nextPage || null;
|
||||||
|
// } catch (err) {
|
||||||
|
// console.error('Search fetch error:', err);
|
||||||
|
// } finally {
|
||||||
|
// searchState.loading = false;
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
|
||||||
|
// // --- load next page (infinite scroll) ---
|
||||||
|
// async next() {
|
||||||
|
// if (!searchState.nextPage || searchState.loading) return;
|
||||||
|
// searchState.page = searchState.nextPage;
|
||||||
|
// await searchState.fetch();
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // --- debounce agar gak fetch tiap ketik ---
|
||||||
|
// const debouncedFetch = debounce(() => {
|
||||||
|
// // reset pagination setiap query berubah
|
||||||
|
// searchState.page = 1;
|
||||||
|
// searchState.fetch();
|
||||||
|
// }, 500);
|
||||||
|
|
||||||
|
// // --- auto trigger setiap query berubah ---
|
||||||
|
// subscribe(searchState, () => {
|
||||||
|
// // kalau query berubah, jalankan debounce fetch
|
||||||
|
// debouncedFetch();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// export default searchState;
|
||||||
|
|||||||
@@ -10,16 +10,18 @@ import ProfilPerbekel from './ui/profilPerbekel';
|
|||||||
// import LembagaDesa from './ui/lembagaDesa';
|
// import LembagaDesa from './ui/lembagaDesa';
|
||||||
import MotoDesa from './ui/motoDesa';
|
import MotoDesa from './ui/motoDesa';
|
||||||
import SemuaPerbekel from './ui/semuaPerbekel';
|
import SemuaPerbekel from './ui/semuaPerbekel';
|
||||||
|
import ScrollToTopButton from '@/app/darmasaba/_com/scrollToTopButton';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
return (
|
return (
|
||||||
|
<Box>
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Container w={{ base: "100%", md: "50%" }}>
|
<Container w={{ base: "100%", md: "50%" }}>
|
||||||
<Stack align='center' gap={0}>
|
<Stack align='center' gap={0}>
|
||||||
<Text fz={{base: "h1", md: "2.5rem"}} c={colors["blue-button"]} fw={"bold"}>
|
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
||||||
Profile Desa
|
Profile Desa
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -32,9 +34,12 @@ function Page() {
|
|||||||
<MaskotDesa />
|
<MaskotDesa />
|
||||||
<ProfilPerbekel />
|
<ProfilPerbekel />
|
||||||
<MotoDesa />
|
<MotoDesa />
|
||||||
<SemuaPerbekel/>
|
<SemuaPerbekel />
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
{/* Tombol Scroll ke Atas */}
|
||||||
|
<ScrollToTopButton />
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { BarChart as MantineBarChart } from '@mantine/charts';
|
import { BarChart as MantineBarChart } from '@mantine/charts';
|
||||||
import { Box, Center, ColorSwatch, Flex, Paper, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
|
import { Box, Center, ColorSwatch, Flex, Paper, SimpleGrid, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
@@ -107,20 +107,7 @@ function Page() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||||
<Box pb={30}>
|
<Box pb={30}>
|
||||||
<Flex pb={30} justify={'flex-end'} gap={'xl'} align={'center'}>
|
<Title order={2} mb="md">Data Kematian dan Kelahiran</Title>
|
||||||
<Box>
|
|
||||||
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
|
|
||||||
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Angka Kematian</Text>
|
|
||||||
<ColorSwatch color="#EF3E3E" size={30} />
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
|
|
||||||
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Angka Kelahiran</Text>
|
|
||||||
<ColorSwatch color="#3290CA" size={30} />
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
|
||||||
{chartData.length === 0 ? (
|
{chartData.length === 0 ? (
|
||||||
<Text c="dimmed" ta="center" py="xl">
|
<Text c="dimmed" ta="center" py="xl">
|
||||||
Belum ada data yang tersedia untuk ditampilkan
|
Belum ada data yang tersedia untuk ditampilkan
|
||||||
@@ -150,6 +137,20 @@ function Page() {
|
|||||||
</Center>
|
</Center>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
<Flex pb={30} justify={'center'} gap={'xl'} align={'center'}>
|
||||||
|
<Box>
|
||||||
|
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
|
||||||
|
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Angka Kematian</Text>
|
||||||
|
<ColorSwatch color="#EF3E3E" size={30} />
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
|
||||||
|
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Angka Kelahiran</Text>
|
||||||
|
<ColorSwatch color="#3290CA" size={30} />
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -163,11 +164,11 @@ function Page() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Fasilitas Kesehatan */}
|
{/* Fasilitas Kesehatan */}
|
||||||
<FasilitasKesehatan/>
|
<FasilitasKesehatan />
|
||||||
{/* Jadwal Kegiatan */}
|
{/* Jadwal Kegiatan */}
|
||||||
<JadwalKegiatan/>
|
<JadwalKegiatan />
|
||||||
{/* Artikel Kesehatan */}
|
{/* Artikel Kesehatan */}
|
||||||
<ArtikelKesehatanPage/>
|
<ArtikelKesehatanPage />
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -12,10 +12,9 @@ import {
|
|||||||
SimpleGrid,
|
SimpleGrid,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconDownload, IconSend2 } from '@tabler/icons-react';
|
import { IconSend2 } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
@@ -150,23 +149,6 @@ function Page() {
|
|||||||
</Paper>
|
</Paper>
|
||||||
))}
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
|
|
||||||
<Center pb={30}>
|
|
||||||
<Tooltip label="Unduh dokumen tata cara permohonan" withArrow>
|
|
||||||
<Button
|
|
||||||
fz="sm"
|
|
||||||
size="md"
|
|
||||||
radius="md"
|
|
||||||
bg={colors['blue-button']}
|
|
||||||
leftSection={
|
|
||||||
<IconDownload size={20} color={colors['white-1']} />
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Unduh Tata Cara
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Center>
|
|
||||||
|
|
||||||
<Group justify="center">
|
<Group justify="center">
|
||||||
<Paper
|
<Paper
|
||||||
p="xl"
|
p="xl"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useShallowEffect } from '@mantine/hooks';
|
|||||||
import { IconBuildingCommunity, IconTargetArrow, IconTimeline, IconUser } from '@tabler/icons-react';
|
import { IconBuildingCommunity, IconTargetArrow, IconTimeline, IconUser } from '@tabler/icons-react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
import ScrollToTopButton from '@/app/darmasaba/_com/scrollToTopButton';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const allList = useProxy(stateProfilePPID)
|
const allList = useProxy(stateProfilePPID)
|
||||||
@@ -36,6 +37,7 @@ function Page() {
|
|||||||
: [allList.profile.data]
|
: [allList.profile.data]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<Box>
|
||||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="22">
|
<Stack pos="relative" bg={colors.Bg} py="xl" gap="22">
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
@@ -88,14 +90,14 @@ function Page() {
|
|||||||
<IconUser size={28} />
|
<IconUser size={28} />
|
||||||
<Text fz={{ base: "1.25rem", md: "1.5rem" }} fw="bold">Biografi</Text>
|
<Text fz={{ base: "1.25rem", md: "1.5rem" }} fw="bold">Biografi</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem" }} ta="justify" dangerouslySetInnerHTML={{ __html: item.biodata }} style={{wordBreak: "break-word", whiteSpace: "normal"}} />
|
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem" }} ta="justify" dangerouslySetInnerHTML={{ __html: item.biodata }} style={{ wordBreak: "break-word", whiteSpace: "normal" }} />
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
<Flex align="center" gap="sm" mb="sm">
|
<Flex align="center" gap="sm" mb="sm">
|
||||||
<IconTimeline size={28} />
|
<IconTimeline size={28} />
|
||||||
<Text fz={{ base: "1.25rem", md: "1.5rem" }} fw="bold">Riwayat Karir</Text>
|
<Text fz={{ base: "1.25rem", md: "1.5rem" }} fw="bold">Riwayat Karir</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem" }} dangerouslySetInnerHTML={{ __html: item.riwayat }} style={{wordBreak: "break-word", whiteSpace: "normal"}} />
|
<Text fz={{ base: "1rem", md: "1.125rem", lg: "1.25rem" }} dangerouslySetInnerHTML={{ __html: item.riwayat }} style={{ wordBreak: "break-word", whiteSpace: "normal" }} />
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -109,7 +111,7 @@ function Page() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
<List spacing="xs" size="sm">
|
<List spacing="xs" size="sm">
|
||||||
<Box px={20}>
|
<Box px={20}>
|
||||||
<Text fz={{ base: "1rem", md: "1.125rem" }} ta="justify" dangerouslySetInnerHTML={{ __html: item.pengalaman }} style={{wordBreak: "break-word", whiteSpace: "normal"}} />
|
<Text fz={{ base: "1rem", md: "1.125rem" }} ta="justify" dangerouslySetInnerHTML={{ __html: item.pengalaman }} style={{ wordBreak: "break-word", whiteSpace: "normal" }} />
|
||||||
</Box>
|
</Box>
|
||||||
</List>
|
</List>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -121,7 +123,7 @@ function Page() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
<List spacing="xs" size="sm">
|
<List spacing="xs" size="sm">
|
||||||
<Box px={20}>
|
<Box px={20}>
|
||||||
<Text fz={{ base: "1rem", md: "1.125rem" }} ta="justify" dangerouslySetInnerHTML={{ __html: item.unggulan }} style={{wordBreak: "break-word", whiteSpace: "normal"}} />
|
<Text fz={{ base: "1rem", md: "1.125rem" }} ta="justify" dangerouslySetInnerHTML={{ __html: item.unggulan }} style={{ wordBreak: "break-word", whiteSpace: "normal" }} />
|
||||||
</Box>
|
</Box>
|
||||||
</List>
|
</List>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -129,6 +131,9 @@ function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
{/* Tombol Scroll ke Atas */}
|
||||||
|
<ScrollToTopButton />
|
||||||
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
157
src/app/darmasaba/(pages)/ppid/struktur-ppid/[id]/page.tsx
Normal file
157
src/app/darmasaba/(pages)/ppid/struktur-ppid/[id]/page.tsx
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
'use client';
|
||||||
|
import stateStrukturPPID from '@/app/admin/(dashboard)/_state/ppid/struktur_ppid/struktur_PPID';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Divider,
|
||||||
|
Group,
|
||||||
|
Image,
|
||||||
|
Paper,
|
||||||
|
Skeleton,
|
||||||
|
Stack,
|
||||||
|
Text,
|
||||||
|
Title,
|
||||||
|
} from '@mantine/core';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IconArrowBack } from '@tabler/icons-react';
|
||||||
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
|
function DetailPegawaiUser() {
|
||||||
|
const statePegawai = useProxy(stateStrukturPPID.pegawai);
|
||||||
|
const params = useParams();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
stateStrukturPPID.posisiOrganisasi.findMany.load();
|
||||||
|
statePegawai.findUnique.load(params?.id as string);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
if (!statePegawai.findUnique.data) {
|
||||||
|
return (
|
||||||
|
<Stack py="lg">
|
||||||
|
<Skeleton height={500} radius="md" />
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = statePegawai.findUnique.data;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box px={{ base: 'sm', md: 'lg' }} py="xl">
|
||||||
|
{/* Back button */}
|
||||||
|
<Group mb="lg">
|
||||||
|
<Box
|
||||||
|
onClick={() => router.back()}
|
||||||
|
style={{
|
||||||
|
cursor: 'pointer',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 8,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconArrowBack size={22} color={colors['blue-button']} />
|
||||||
|
<Text c={colors['blue-button']} fw={500}>
|
||||||
|
Kembali
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
</Group>
|
||||||
|
|
||||||
|
<Paper
|
||||||
|
w={{ base: '100%', md: '70%' }}
|
||||||
|
mx="auto"
|
||||||
|
p="xl"
|
||||||
|
radius="lg"
|
||||||
|
shadow="sm"
|
||||||
|
bg="white"
|
||||||
|
style={{
|
||||||
|
border: '1px solid #eaeaea',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack align="center" gap="md">
|
||||||
|
{/* Foto Profil */}
|
||||||
|
<Image
|
||||||
|
src={data.image?.link || '/placeholder-profile.png'}
|
||||||
|
alt={data.namaLengkap || 'Foto Profil'}
|
||||||
|
w={160}
|
||||||
|
h={160}
|
||||||
|
radius={100}
|
||||||
|
fit="cover"
|
||||||
|
style={{ border: `2px solid ${colors['blue-button']}` }}
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Nama & Jabatan */}
|
||||||
|
<Stack align="center" gap={2}>
|
||||||
|
<Title order={3} fw={700} c={colors['blue-button']}>
|
||||||
|
{data.namaLengkap || '-'} {data.gelarAkademik || ''}
|
||||||
|
</Title>
|
||||||
|
<Text fz="sm" c="dimmed">
|
||||||
|
{data.posisi?.nama || 'Posisi tidak tersedia'}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Divider my="lg" />
|
||||||
|
|
||||||
|
{/* Informasi Detail */}
|
||||||
|
<Stack gap="md">
|
||||||
|
<InfoRow label="Email" value={data.email} />
|
||||||
|
<InfoRow label="Telepon" value={data.telepon} />
|
||||||
|
<InfoRow label="Alamat" value={data.alamat} multiline />
|
||||||
|
<InfoRow
|
||||||
|
label="Tanggal Masuk"
|
||||||
|
value={
|
||||||
|
data.tanggalMasuk
|
||||||
|
? new Date(data.tanggalMasuk).toLocaleDateString('id-ID', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
})
|
||||||
|
: '-'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<InfoRow
|
||||||
|
label="Status"
|
||||||
|
value={data.isActive ? 'Aktif' : 'Tidak Aktif'}
|
||||||
|
valueColor={data.isActive ? 'green' : 'red'}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Komponen kecil untuk menampilkan baris informasi */
|
||||||
|
function InfoRow({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
valueColor,
|
||||||
|
multiline = false,
|
||||||
|
}: {
|
||||||
|
label: string;
|
||||||
|
value?: string | null;
|
||||||
|
valueColor?: string;
|
||||||
|
multiline?: boolean;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Text fz="sm" fw={600} c="dark">
|
||||||
|
{label}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
fz="sm"
|
||||||
|
c={valueColor || 'dimmed'}
|
||||||
|
style={{
|
||||||
|
whiteSpace: multiline ? 'normal' : 'nowrap',
|
||||||
|
wordBreak: 'break-word',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{value || '-'}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DetailPegawaiUser;
|
||||||
@@ -1,129 +1,8 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
// /* eslint-disable react-hooks/exhaustive-deps */
|
|
||||||
// /* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
// 'use client'
|
|
||||||
// import stateStrukturPPID from '@/app/admin/(dashboard)/_state/ppid/struktur_ppid/struktur_PPID';
|
|
||||||
// import colors from '@/con/colors';
|
|
||||||
// import { Box, Image, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
|
|
||||||
// import { OrganizationChart } from 'primereact/organizationchart';
|
|
||||||
// import { useEffect } from 'react';
|
|
||||||
// import { useProxy } from 'valtio/utils';
|
|
||||||
// import BackButton from '../../desa/layanan/_com/BackButto';
|
|
||||||
|
|
||||||
// function Page() {
|
|
||||||
// return (
|
|
||||||
// <Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
|
||||||
// <Box px={{ base: 'md', md: 100 }}>
|
|
||||||
// <BackButton />
|
|
||||||
// </Box>
|
|
||||||
// <Title ta={"center"} fz={{ base: "2rem", md: "2.5rem", lg: "3rem", xl: "3.5rem" }} c={colors["blue-button"]} fw={"bold"}>Struktur PPID</Title>
|
|
||||||
// <StrukturOrganisasiPPID />
|
|
||||||
|
|
||||||
// </Stack>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function StrukturOrganisasiPPID() {
|
|
||||||
// const stateOrganisasi = useProxy(stateStrukturPPID.pegawai)
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// stateOrganisasi.findMany.load()
|
|
||||||
// }, [])
|
|
||||||
|
|
||||||
// if (!stateOrganisasi.findMany.data || stateOrganisasi.findMany.data.length === 0) {
|
|
||||||
// return (
|
|
||||||
// <Stack py={10}>
|
|
||||||
// <Skeleton h={500} />
|
|
||||||
// </Stack>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Step 1: Group pegawai berdasarkan posisiId
|
|
||||||
// const posisiMap = new Map<string, any>();
|
|
||||||
|
|
||||||
// for (const pegawai of stateOrganisasi.findMany.data) {
|
|
||||||
// const posisiId = pegawai.posisi.id;
|
|
||||||
// if (!posisiMap.has(posisiId)) {
|
|
||||||
// posisiMap.set(posisiId, {
|
|
||||||
// ...pegawai.posisi,
|
|
||||||
// pegawaiList: [],
|
|
||||||
// children: []
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// posisiMap.get(posisiId)!.pegawaiList.push(pegawai);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// // Step 2: Buat struktur pohon berdasarkan parentId
|
|
||||||
// const root: any[] = [];
|
|
||||||
|
|
||||||
// posisiMap.forEach((posisi) => {
|
|
||||||
// if (posisi.parentId) {
|
|
||||||
// const parent = posisiMap.get(posisi.parentId);
|
|
||||||
// if (parent) {
|
|
||||||
// parent.children.push(posisi);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// root.push(posisi);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // Step 3: Ubah struktur ke format OrganizationChart
|
|
||||||
// function toOrgChartFormat(node: any): any {
|
|
||||||
// return {
|
|
||||||
// expanded: true,
|
|
||||||
// type: 'person',
|
|
||||||
// styleClass: 'p-person',
|
|
||||||
// data: {
|
|
||||||
// name: node.pegawaiList?.[0]?.namaLengkap || 'Tidak ada pegawai',
|
|
||||||
// status: node.nama,
|
|
||||||
// image: node.pegawaiList?.[0]?.image?.link || '/img/default.png'
|
|
||||||
// },
|
|
||||||
// children: node.children.map(toOrgChartFormat)
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// const chartData = root.map(toOrgChartFormat);
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <Box py={10}>
|
|
||||||
// <Paper bg={colors.grey} p="md" style={{ overflowX: 'auto' }}>
|
|
||||||
// <OrganizationChart style={{ color: colors['blue-button'] }} value={chartData} nodeTemplate={nodeTemplate} />
|
|
||||||
// </Paper>
|
|
||||||
// </Box>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// function nodeTemplate(node: any) {
|
|
||||||
// const imageSrc = node?.data?.image || '/img/default.png';
|
|
||||||
// const name = node?.data?.name || 'Tanpa Nama';
|
|
||||||
// const status = node?.data?.status || 'Tidak ada deskripsi';
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <Stack pos={"relative"} py={"xl"} gap={"22"}>
|
|
||||||
// <Stack align="center" gap={4}>
|
|
||||||
// <Image
|
|
||||||
// src={imageSrc}
|
|
||||||
// alt={name}
|
|
||||||
// radius="xl"
|
|
||||||
// w={120}
|
|
||||||
// h={120}
|
|
||||||
// fit="cover"
|
|
||||||
// />
|
|
||||||
// <Text fw={600} ta="center">{name}</Text>
|
|
||||||
// <Text size="sm" c="dimmed" ta="center">{status}</Text>
|
|
||||||
// </Stack>
|
|
||||||
// </Stack>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export default Page;
|
|
||||||
|
|
||||||
'use client'
|
'use client'
|
||||||
import stateStrukturPPID from '@/app/admin/(dashboard)/_state/ppid/struktur_ppid/struktur_PPID'
|
import stateStrukturPPID from '@/app/admin/(dashboard)/_state/ppid/struktur_ppid/struktur_PPID'
|
||||||
|
import colors from '@/con/colors'
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
@@ -145,7 +24,8 @@ import { OrganizationChart } from 'primereact/organizationchart'
|
|||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useProxy } from 'valtio/utils'
|
import { useProxy } from 'valtio/utils'
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto'
|
import BackButton from '../../desa/layanan/_com/BackButto'
|
||||||
import colors from '@/con/colors'
|
import { useTransitionRouter } from 'next-view-transitions'
|
||||||
|
import ScrollToTopButton from '@/app/darmasaba/_com/scrollToTopButton'
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
@@ -180,12 +60,16 @@ export default function Page() {
|
|||||||
<StrukturOrganisasiPPID />
|
<StrukturOrganisasiPPID />
|
||||||
</Box>
|
</Box>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
|
{/* Tombol Scroll ke Atas */}
|
||||||
|
<ScrollToTopButton />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function StrukturOrganisasiPPID() {
|
function StrukturOrganisasiPPID() {
|
||||||
const stateOrganisasi: any = useProxy(stateStrukturPPID.pegawai)
|
const stateOrganisasi: any = useProxy(stateStrukturPPID.pegawai)
|
||||||
|
const router = useTransitionRouter()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
void stateOrganisasi.findMany.load()
|
void stateOrganisasi.findMany.load()
|
||||||
@@ -292,19 +176,21 @@ function StrukturOrganisasiPPID() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
function toOrgChartFormat(node: any): any {
|
function toOrgChartFormat(node: any): any {
|
||||||
|
const pegawai = node.pegawaiList?.[0];
|
||||||
return {
|
return {
|
||||||
expanded: true,
|
expanded: true,
|
||||||
type: 'person',
|
type: 'person',
|
||||||
styleClass: 'p-person',
|
styleClass: 'p-person',
|
||||||
data: {
|
data: {
|
||||||
name: node.pegawaiList?.[0]?.namaLengkap || 'Belum ditugaskan',
|
id: pegawai?.id || null, // tambahin ini bro
|
||||||
|
name: pegawai?.namaLengkap || 'Belum ditugaskan',
|
||||||
title: node.nama || 'Tanpa jabatan',
|
title: node.nama || 'Tanpa jabatan',
|
||||||
image: node.pegawaiList?.[0]?.image?.link || '/img/default.png',
|
image: pegawai?.image?.link || '/img/default.png',
|
||||||
description: node.deskripsi || '',
|
description: node.deskripsi || '',
|
||||||
positionId: node.id || null,
|
positionId: node.id || null,
|
||||||
},
|
},
|
||||||
children: node.children?.map(toOrgChartFormat) || [],
|
children: node.children?.map(toOrgChartFormat) || [],
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const chartData = root.map(toOrgChartFormat)
|
const chartData = root.map(toOrgChartFormat)
|
||||||
@@ -322,19 +208,20 @@ function StrukturOrganisasiPPID() {
|
|||||||
>
|
>
|
||||||
<OrganizationChart
|
<OrganizationChart
|
||||||
value={chartData}
|
value={chartData}
|
||||||
nodeTemplate={nodeTemplate}
|
nodeTemplate={(node) => nodeTemplate(node, router)}
|
||||||
/>
|
/>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeTemplate(node: any) {
|
function nodeTemplate(node: any, router: ReturnType<typeof useTransitionRouter>) {
|
||||||
const imageSrc = node?.data?.image || '/img/default.png'
|
const imageSrc = node?.data?.image || '/img/default.png'
|
||||||
const name = node?.data?.name || 'Tanpa Nama'
|
const name = node?.data?.name || 'Tanpa Nama'
|
||||||
const title = node?.data?.title || 'Tanpa Jabatan'
|
const title = node?.data?.title || 'Tanpa Jabatan'
|
||||||
const description = node?.data?.description || ''
|
const description = node?.data?.description || ''
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Transition mounted transition="pop" duration={240}>
|
<Transition mounted transition="pop" duration={240}>
|
||||||
{(styles) => (
|
{(styles) => (
|
||||||
@@ -374,19 +261,17 @@ function nodeTemplate(node: any) {
|
|||||||
<Text size="xs" c="dimmed" mt={8} lineClamp={3}>
|
<Text size="xs" c="dimmed" mt={8} lineClamp={3}>
|
||||||
{description || 'Belum ada deskripsi.'}
|
{description || 'Belum ada deskripsi.'}
|
||||||
</Text>
|
</Text>
|
||||||
<Tooltip label="Kembali ke struktur organisasi" withArrow position="bottom">
|
<Tooltip label="Lihat Detail" withArrow position="bottom">
|
||||||
<Button
|
<Button
|
||||||
variant="light"
|
variant="light"
|
||||||
size="xs"
|
size="xs"
|
||||||
mt="md"
|
mt="md"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const id = node?.data?.positionId
|
const id = node?.data?.id
|
||||||
if (id && (window as any).scrollTo) {
|
router.push(`/darmasaba/ppid/struktur-ppid/${id}`)
|
||||||
;(window as any).scrollTo({ top: 0, behavior: 'smooth' })
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Kembali
|
Lihat Detail
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -394,6 +279,3 @@ function nodeTemplate(node: any) {
|
|||||||
</Transition>
|
</Transition>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ function Page() {
|
|||||||
<Text
|
<Text
|
||||||
fz={{ base: 'md', md: 'lg' }}
|
fz={{ base: 'md', md: 'lg' }}
|
||||||
lh={1.7}
|
lh={1.7}
|
||||||
ta="justify"
|
ta="center"
|
||||||
dangerouslySetInnerHTML={{ __html: item.visi }}
|
dangerouslySetInnerHTML={{ __html: item.visi }}
|
||||||
style={{wordBreak: "break-word", whiteSpace: "normal"}}
|
style={{wordBreak: "break-word", whiteSpace: "normal"}}
|
||||||
/>
|
/>
|
||||||
@@ -88,7 +88,7 @@ function Page() {
|
|||||||
<Text
|
<Text
|
||||||
fz={{ base: 'md', md: 'lg' }}
|
fz={{ base: 'md', md: 'lg' }}
|
||||||
lh={1.7}
|
lh={1.7}
|
||||||
ta="justify"
|
ta="center"
|
||||||
dangerouslySetInnerHTML={{ __html: item.misi }}
|
dangerouslySetInnerHTML={{ __html: item.misi }}
|
||||||
style={{wordBreak: "break-word", whiteSpace: "normal"}}
|
style={{wordBreak: "break-word", whiteSpace: "normal"}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,20 +1,63 @@
|
|||||||
|
import { useRef, useState, useEffect } from 'react';
|
||||||
import stateNav from "@/state/state-nav";
|
import stateNav from "@/state/state-nav";
|
||||||
import { Container, Stack, Tooltip } from "@mantine/core";
|
import { Container, Stack, ActionIcon, Box } from "@mantine/core";
|
||||||
|
import { IconX } from '@tabler/icons-react';
|
||||||
import GlobalSearch from "./globalSearch";
|
import GlobalSearch from "./globalSearch";
|
||||||
|
|
||||||
export function NavbarSearch() {
|
export function NavbarSearch() {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
// Close when clicking outside
|
||||||
|
useEffect(() => {
|
||||||
|
function handleClickOutside(event: MouseEvent) {
|
||||||
|
if (containerRef.current && !containerRef.current.contains(event.target as Node)) {
|
||||||
|
setIsOpen(false);
|
||||||
|
stateNav.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add event listener
|
||||||
|
document.addEventListener('mousedown', handleClickOutside);
|
||||||
|
return () => {
|
||||||
|
// Clean up
|
||||||
|
document.removeEventListener('mousedown', handleClickOutside);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<Box
|
||||||
|
ref={containerRef}
|
||||||
|
style={{ position: 'relative' }}
|
||||||
|
>
|
||||||
<Container
|
<Container
|
||||||
w={{ base: "100%", md: "80%" }}
|
w={{ base: "100%", md: "80%" }}
|
||||||
fluid
|
fluid
|
||||||
py="xl"
|
py="xl"
|
||||||
onMouseLeave={stateNav.clear}
|
|
||||||
>
|
>
|
||||||
<Stack pt="xl">
|
<Stack pt="xl">
|
||||||
<Tooltip label="Type to search across the site" position="bottom-start" withArrow>
|
<Box style={{ position: 'relative' }}>
|
||||||
<GlobalSearch />
|
<GlobalSearch />
|
||||||
</Tooltip>
|
{isOpen && (
|
||||||
|
<ActionIcon
|
||||||
|
onClick={() => {
|
||||||
|
setIsOpen(false);
|
||||||
|
stateNav.clear();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
right: 10,
|
||||||
|
top: '50%',
|
||||||
|
transform: 'translateY(-50%)',
|
||||||
|
zIndex: 1000
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconX size={16} />
|
||||||
|
</ActionIcon>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Container>
|
</Container>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,53 +1,17 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import { TextInput, Loader, Stack, Box, Text } from '@mantine/core';
|
import searchState, { debouncedFetch } from '@/app/api/[[...slugs]]/_lib/search/searchState';
|
||||||
import { useSnapshot } from 'valtio';
|
import { Box, Center, Loader, Stack, Text, TextInput } from '@mantine/core';
|
||||||
import { useRouter } from 'next/navigation';
|
import { IconX } from '@tabler/icons-react';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import searchState from '@/app/api/[[...slugs]]/_lib/search/searchState';
|
import { useSnapshot } from 'valtio';
|
||||||
|
import getDetailUrl from './searchUrl';
|
||||||
|
|
||||||
// Mapping type ke URL
|
|
||||||
const getDetailUrl = (item: { type?: string; id: string | number; [key: string]: unknown }) => {
|
|
||||||
const { type, id, kategori } = item;
|
|
||||||
|
|
||||||
const typeUrlMap: Record<string, string> = {
|
|
||||||
programinovasi: `/darmasaba/program-inovasi/${id}`,
|
|
||||||
desaantikorupsi: '/darmasaba/desa-anti-korupsi',
|
|
||||||
sdgsdesa: '/darmasaba/sdgs-desa',
|
|
||||||
apbdes: '/darmasaba/apbdes',
|
|
||||||
prestasidesa: '/darmasaba/prestasi-desa',
|
|
||||||
pejabatdesa: '/darmasaba/profile/pejabat-desa',
|
|
||||||
strukturppid: '/darmasaba/ppid/struktur-ppid',
|
|
||||||
visimisippid: '/darmasaba/ppid/visi-misi',
|
|
||||||
dasarhukumppid: '/darmasaba/ppid/dasar-hukum',
|
|
||||||
profileppid: '/darmasaba/ppid/profile',
|
|
||||||
daftarinformasipublik: '/darmasaba/ppid/daftar-informasi-publik',
|
|
||||||
perbekeldarmasaba: '/darmasaba/desa/profile',
|
|
||||||
berita: `/darmasaba/desa/berita/${kategori}/${id}`,
|
|
||||||
pengumuman: `/darmasaba/desa/pengumuman/${kategori}/${id}`,
|
|
||||||
sejarahdesa: '/darmasaba/desa/profile',
|
|
||||||
visimisidesa: '/darmasaba/desa/profile',
|
|
||||||
lambangdesa: '/darmasaba/desa/profile',
|
|
||||||
maskotdesa: '/darmasaba/desa/profile',
|
|
||||||
profilperbekel: '/darmasaba/desa/profile',
|
|
||||||
potensi: '/darmasaba/desa/potensi-desa',
|
|
||||||
galleryFoto: '/darmasaba/desa/gallery/foto',
|
|
||||||
galleryVideo: '/darmasaba/desa/gallery/video',
|
|
||||||
pelayananSuratKeterangan: '/darmasaba/desa/layanan',
|
|
||||||
pelayananPerizinanBerusaha: '/darmasaba/desa/layanan',
|
|
||||||
pelayananTelunjukSaktiDesa: '/darmasaba/desa/layanan',
|
|
||||||
pelayananPendudukNonPermanent: '/darmasaba/desa/layanan',
|
|
||||||
penghargaan: '/darmasaba/desa/penghargaan',
|
|
||||||
};
|
|
||||||
|
|
||||||
return type ? typeUrlMap[type] || '/darmasaba' : '/darmasaba';
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default function GlobalSearch() {
|
export default function GlobalSearch() {
|
||||||
const snap = useSnapshot(searchState);
|
const snap = useSnapshot(searchState);
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
// Infinite scroll listener
|
// Infinite scroll
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleScroll = () => {
|
const handleScroll = () => {
|
||||||
const bottom =
|
const bottom =
|
||||||
@@ -59,13 +23,32 @@ export default function GlobalSearch() {
|
|||||||
}, [snap.loading]);
|
}, [snap.loading]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack maw={800} mx="auto">
|
||||||
|
{/* 🔍 Search input */}
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder="Cari apapun..."
|
placeholder="Cari apapun..."
|
||||||
value={snap.query}
|
value={snap.query}
|
||||||
onChange={(e) => (searchState.query = e.currentTarget.value)}
|
onChange={(e) => (
|
||||||
|
searchState.query = e.currentTarget.value,
|
||||||
|
debouncedFetch()
|
||||||
|
)}
|
||||||
|
radius="xl"
|
||||||
|
rightSection={
|
||||||
|
snap.query ? (
|
||||||
|
<IconX
|
||||||
|
size={16}
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
onClick={() => {
|
||||||
|
searchState.query = '';
|
||||||
|
searchState.results = [];
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : undefined
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* 📄 Hasil pencarian */}
|
||||||
|
<div style={{ maxHeight: '400px', overflowY: 'auto' }}>
|
||||||
{snap.results.map((item, i) => (
|
{snap.results.map((item, i) => (
|
||||||
<Box
|
<Box
|
||||||
key={i}
|
key={i}
|
||||||
@@ -74,12 +57,16 @@ export default function GlobalSearch() {
|
|||||||
borderBottom: '1px solid #eee',
|
borderBottom: '1px solid #eee',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
transition: 'background 0.2s',
|
transition: 'background 0.2s',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
maxWidth: '100%'
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => (e.currentTarget.style.background = '#f5f5f5')}
|
onMouseEnter={(e) => (e.currentTarget.style.background = '#f5f5f5')}
|
||||||
onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}
|
onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const url = getDetailUrl(item);
|
const url = getDetailUrl(item);
|
||||||
router.push(url);
|
window.location.href = url;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text size="sm" fw={500}>
|
<Text size="sm" fw={500}>
|
||||||
@@ -90,8 +77,15 @@ export default function GlobalSearch() {
|
|||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
{snap.loading && <Loader size="sm" />}
|
{/* ⏳ Loader di bawah hasil */}
|
||||||
|
{snap.loading && (
|
||||||
|
<Center py="md">
|
||||||
|
<Loader size="sm" />
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ function Penghargaan() {
|
|||||||
variant="gradient"
|
variant="gradient"
|
||||||
gradient={{ from: "cyan", to: "blue", deg: 60 }}
|
gradient={{ from: "cyan", to: "blue", deg: 60 }}
|
||||||
>
|
>
|
||||||
Penghargaan & Prestasi Desa
|
Penghargaan Desa
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
|
|||||||
36
src/app/darmasaba/_com/scrollToTopButton.tsx
Normal file
36
src/app/darmasaba/_com/scrollToTopButton.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
'use client'
|
||||||
|
import { useWindowScroll } from '@mantine/hooks';
|
||||||
|
import { ActionIcon, Transition } from '@mantine/core';
|
||||||
|
import { IconArrowUp } from '@tabler/icons-react';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
|
||||||
|
function ScrollToTopButton() {
|
||||||
|
const [scroll, scrollTo] = useWindowScroll();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Transition
|
||||||
|
mounted={scroll.y > 300}
|
||||||
|
transition="slide-up"
|
||||||
|
duration={300}
|
||||||
|
timingFunction="ease"
|
||||||
|
>
|
||||||
|
{(styles) => (
|
||||||
|
<ActionIcon
|
||||||
|
style={styles}
|
||||||
|
size="xl"
|
||||||
|
radius="xl"
|
||||||
|
variant="filled"
|
||||||
|
color={colors['blue-button']}
|
||||||
|
onClick={() => scrollTo({ y: 0 })}
|
||||||
|
pos="fixed"
|
||||||
|
bottom={24}
|
||||||
|
right={24}
|
||||||
|
aria-label="Kembali ke atas"
|
||||||
|
>
|
||||||
|
<IconArrowUp size={20} />
|
||||||
|
</ActionIcon>
|
||||||
|
)}
|
||||||
|
</Transition>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default ScrollToTopButton
|
||||||
60
src/app/darmasaba/_com/searchUrl.tsx
Normal file
60
src/app/darmasaba/_com/searchUrl.tsx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
const getDetailUrl = (item: { type?: string; id: string | number; [key: string]: unknown }) => {
|
||||||
|
const { type, id, kategori } = item;
|
||||||
|
const typeUrlMap: Record<string, string> = {
|
||||||
|
programinovasi: `/darmasaba/program-inovasi/${id}`,
|
||||||
|
desaantikorupsi: '/darmasaba/desa-anti-korupsi',
|
||||||
|
sdgsdesa: '/darmasaba/sdgs-desa',
|
||||||
|
apbdes: '/darmasaba/apbdes',
|
||||||
|
prestasidesa: '/darmasaba/prestasi-desa',
|
||||||
|
pejabatdesa: '/darmasaba/profile/pejabat-desa',
|
||||||
|
strukturppid: '/darmasaba/ppid/struktur-ppid',
|
||||||
|
visimisippid: '/darmasaba/ppid/visi-misi',
|
||||||
|
dasarhukumppid: '/darmasaba/ppid/dasar-hukum',
|
||||||
|
profileppid: '/darmasaba/ppid/profile',
|
||||||
|
daftarinformasipublik: '/darmasaba/ppid/daftar-informasi-publik',
|
||||||
|
perbekeldarmasaba: '/darmasaba/desa/profile',
|
||||||
|
berita: `/darmasaba/desa/berita/${kategori}/${id}`,
|
||||||
|
pengumuman: `/darmasaba/desa/pengumuman/${kategori}/${id}`,
|
||||||
|
sejarahdesa: '/darmasaba/desa/profile',
|
||||||
|
visimisidesa: '/darmasaba/desa/profile',
|
||||||
|
lambangdesa: '/darmasaba/desa/profile',
|
||||||
|
maskotdesa: '/darmasaba/desa/profile',
|
||||||
|
profilperbekel: '/darmasaba/desa/profile',
|
||||||
|
potensi: '/darmasaba/desa/potensi-desa',
|
||||||
|
galleryFoto: '/darmasaba/desa/gallery/foto',
|
||||||
|
galleryVideo: '/darmasaba/desa/gallery/video',
|
||||||
|
pelayananSuratKeterangan: '/darmasaba/desa/layanan',
|
||||||
|
pelayananPerizinanBerusaha: '/darmasaba/desa/layanan',
|
||||||
|
pelayananTelunjukSaktiDesa: '/darmasaba/desa/layanan',
|
||||||
|
pelayananPendudukNonPermanent: '/darmasaba/desa/layanan',
|
||||||
|
penghargaan: '/darmasaba/desa/penghargaan',
|
||||||
|
posyandu: '/darmasaba/kesehatan/posyandu',
|
||||||
|
fasilitasKesehatan: '/darmasaba/kesehatan/data-kesehatan-warga',
|
||||||
|
jadwalKegiatan: '/darmasaba/kesehatan/data-kesehatan-warga',
|
||||||
|
artikelKesehatan: '/darmasaba/kesehatan/data-kesehatan-warga',
|
||||||
|
puskesmas: '/darmasaba/kesehatan/puskesmas',
|
||||||
|
programKesehatan: '/darmasaba/kesehatan/program-kesehatan',
|
||||||
|
penangananDarurat: '/darmasaba/kesehatan/penanganan-darurat',
|
||||||
|
kontakDarurat: '/darmasaba/kesehatan/kontak-darurat',
|
||||||
|
infoWabahPenyakit: '/darmasaba/kesehatan/info-wabah-penyakit',
|
||||||
|
keamananLingkungan: '/darmasaba/keamanan/keamanan-lingkungan-pecalang-patwal',
|
||||||
|
polsekTerdekat: '/darmasaba/keamanan/polsek-terdekat',
|
||||||
|
kontakDaruratKeamanan: '/darmasaba/keamanan/kontak-darurat',
|
||||||
|
pencegahanKriminalitas: '/darmasaba/keamanan/pencegahan-kriminalitas',
|
||||||
|
laporanPublik: '/darmasaba/keamanan/laporan-publik',
|
||||||
|
tipsKeamanan: '/darmasaba/keamanan/tips-keamanan',
|
||||||
|
pasarDesa: '/darmasaba/ekonomi/pasar-desa',
|
||||||
|
lowonganKerjaLokal: '/darmasaba/ekonomi/lowongan-kerja-lokal',
|
||||||
|
strukturOrganisasi: '/darmasaba/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa',
|
||||||
|
jumlahPendudukUsiaKerjaYangMenganggurUsia: '/darmasaba/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur',
|
||||||
|
jumlahPendudukUsiaKerjaYangMenganggurPendidikan: '/darmasaba/ekonomi/jumlah-penduduk-usia-kerja-yang-menganggur',
|
||||||
|
jumlahPendudukMiskin: '/darmasaba/ekonomi/jumlah-penduduk-miskin',
|
||||||
|
programKemiskinan: '/darmasaba/ekonomi/program-kemiskinan',
|
||||||
|
sektorUnggulanDesa: '/darmasaba/ekonomi/sektor-unggulan-desa',
|
||||||
|
demografiPekerjaan: '/darmasaba/ekonomi/demografi-pekerjaan',
|
||||||
|
};
|
||||||
|
|
||||||
|
return typeUrlMap[type || ''] || '/darmasaba';
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getDetailUrl;
|
||||||
@@ -8,13 +8,15 @@ import colors from "@/con/colors";
|
|||||||
import SDGS from "./_com/main-page/sdgs";
|
import SDGS from "./_com/main-page/sdgs";
|
||||||
// import ApiFetch from "@/lib/api-fetch";
|
// import ApiFetch from "@/lib/api-fetch";
|
||||||
|
|
||||||
import { Stack } from "@mantine/core";
|
import { Box, Stack } from "@mantine/core";
|
||||||
import Apbdes from "./_com/main-page/apbdes";
|
import Apbdes from "./_com/main-page/apbdes";
|
||||||
import Prestasi from "./_com/main-page/prestasi";
|
import Prestasi from "./_com/main-page/prestasi";
|
||||||
|
import ScrollToTopButton from "./_com/scrollToTopButton";
|
||||||
|
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
|
<Box>
|
||||||
<Stack bg={colors.grey[1]} gap={"4rem"}>
|
<Stack bg={colors.grey[1]} gap={"4rem"}>
|
||||||
<LandingPage />
|
<LandingPage />
|
||||||
<Penghargaan />
|
<Penghargaan />
|
||||||
@@ -24,7 +26,10 @@ export default function Page() {
|
|||||||
<Kepuasan />
|
<Kepuasan />
|
||||||
<SDGS />
|
<SDGS />
|
||||||
<Apbdes />
|
<Apbdes />
|
||||||
<Prestasi/>
|
<Prestasi />
|
||||||
</Stack>
|
</Stack>
|
||||||
|
{/* Tombol Scroll ke Atas */}
|
||||||
|
<ScrollToTopButton />
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user