Compare commits

...

12 Commits

Author SHA1 Message Date
f5d68d4982 UI Admin Menu Desa Sub Menu Profile 2025-05-15 17:47:43 +08:00
2844132ea0 Profile PPID, Visi Misi, dan Dasar Hukum 2025-05-13 17:54:23 +08:00
e5889ca903 ProfilePPID bagian Profile, VisiMisiPPD sudah ada seed dan bisa di edit 2025-05-13 11:51:48 +08:00
8a34a122d0 Tambahan Di menu PPID 2025-05-09 10:35:30 +08:00
795c79dd5f Tambahan Admin Di Menu PPID 2025-05-06 13:57:33 +08:00
a8556aacb7 Fix Eror Admin Persentase & Grafik 2025-05-02 16:08:30 +08:00
ea7de13d28 Admin Dashboard Bagian Data Kesehatan 2025-04-30 16:31:18 +08:00
e9d94cfa83 Ngerjain Tabs Jadwal Kegiatan di Data Kesehatan 2025-04-29 11:01:09 +08:00
3f5d607e83 Sudah Dibuatkan Inputan Data Di Data Kesehatan Warga Fasilitas Kesehatan 2025-04-28 10:21:59 +08:00
d575c9c792 Create & Read Data :
* Menu Desa : Berita & Pengumuman
* Kesehatan : Data Kesehatan Warga => Fasilitas Kesehatan
2025-04-25 10:24:52 +08:00
9a6f8dc7f6 Membuat database menu desa: Berita & Pengummuman 2025-04-22 21:48:01 +08:00
7b0fb9332e Dashboard Admin 2025-04-21 17:49:13 +08:00
295 changed files with 12303 additions and 758 deletions

BIN
bun.lockb

Binary file not shown.

View File

@@ -1,6 +1,6 @@
{
"name": "desa-darmasaba",
"version": "0.1.1",
"version": "0.1.2",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
@@ -16,19 +16,30 @@
"@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",
"@mantine/charts": "^7.17.1",
"@mantine/core": "^7.16.2",
"@mantine/core": "^7.17.4",
"@mantine/dates": "^7.17.4",
"@mantine/dropzone": "^7.17.0",
"@mantine/hooks": "^7.16.2",
"@mantine/hooks": "^7.17.4",
"@mantine/tiptap": "^7.17.4",
"@paljs/types": "^8.1.0",
"@prisma/client": "^6.3.1",
"@tabler/icons-react": "^3.30.0",
"@tiptap/extension-highlight": "^2.11.7",
"@tiptap/extension-link": "^2.11.7",
"@tiptap/extension-subscript": "^2.11.7",
"@tiptap/extension-superscript": "^2.11.7",
"@tiptap/extension-text-align": "^2.11.7",
"@tiptap/extension-underline": "^2.11.7",
"@tiptap/pm": "^2.11.7",
"@tiptap/react": "^2.11.7",
"@tiptap/starter-kit": "^2.11.7",
"@types/bun": "^1.2.2",
"@types/lodash": "^4.17.15",
"@types/lodash": "^4.17.16",
"add": "^2.0.6",
"animate.css": "^4.1.1",
"bun": "^1.2.2",
@@ -37,22 +48,27 @@
"elysia": "^1.2.12",
"embla-carousel-autoplay": "^8.5.2",
"embla-carousel-react": "^7.1.0",
"form-data": "^4.0.2",
"framer-motion": "^12.4.1",
"get-port": "^7.1.0",
"jotai": "^2.12.3",
"lodash": "^4.17.21",
"motion": "^12.4.1",
"nanoid": "^5.1.0",
"nanoid": "^5.1.5",
"next": "15.1.6",
"next-view-transitions": "^0.3.4",
"node-fetch": "^3.3.2",
"p-limit": "^6.2.0",
"prisma": "^6.3.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-simple-toasts": "^6.1.0",
"react-toastify": "^11.0.5",
"readdirp": "^4.1.1",
"recharts": "2",
"recharts": "^2.15.3",
"swr": "^2.3.2",
"valtio": "^2.1.3"
"valtio": "^2.1.3",
"zod": "^3.24.3"
},
"devDependencies": {
"@eslint/eslintrc": "^3",

View File

@@ -0,0 +1,8 @@
[
{ "name": "Sosial & Kesehatan" },
{ "name": "Ekonomi & UMKM" },
{ "name": "Pendidikan & Kepemudaan" },
{ "name": "Lingkungan & Bencana" },
{ "name": "Adat & Budaya" },
{ "name": "Digitalisasi Desa" }
]

View File

@@ -0,0 +1,9 @@
[
{
"id": "1",
"biodata": "<p>I.B Surya Prabhawa Manuaba, S.H., M.H., adalah Perbekel Darmasaba periode 2021-2027, seorang advokat, pendiri Mantra Legal Consultants & Advocates, serta aktif di bidang musik dan akademis. Dia menempuh pendidikan hukum di Universitas Udayana dan Universitas Mahasaraswati Denpasar serta memiliki pengalaman luas di berbagai organisasi dan kepemimpinan.</p>",
"pengalaman": "<ul><li>2021 - 2027: Perbekel Desa Darmasaba</li><li>2015 - Sekarang: Founder & Managing Director Mantra Legal Consultants & Advocates</li><li>2020 - Sekarang: Founder Ugawa Record Music Studio</li><li>2010 - 2016: Dosen Fakultas Hukum Universitas Mahasaraswati Denpasar</li></ul>",
"pengalamanOrganisasi": "<ul> <li>1996 1997: Ketua OSIS SMP Negeri 1 Abiansemal</li><li>1999 2000: Ketua OSIS SMA Negeri 1 Mengwi</li> <li>2008 2009: Ketua BEM Universitas Mahasaraswati Denpasar</li> <li>2008 2010: Ketua Sekaa Taruna Sila Dharma, Banjar Tengah, Desa Adat Tegal, Darmasaba</li> <li>2020 Sekarang: Pengurus Young Lawyer Committee Peradi Denpasar</li> <li>2021 Sekarang: Dewan Kehormatan Himpunan Pengusaha Muda Indonesia (HIPMI) Badung</li> <li>2023 2028: Komite Tetap Advokasi Bidang Hukum dan Regulasi Kamar Dagang dan Industri Badung</li> </ul>",
"programUnggulan": "<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>"
}
]

View File

@@ -0,0 +1,11 @@
[
{
"id": "1",
"sejarah" : "<p>Asal usul nama Darmasaba tertuang dalam lontar Usada Bali. Seperti di tulis dalam monografi Desa Darmasaba tahun 1980 silam, nama Darmasaba berkaitan dengan keturunan Danghyang Nirarta diceritakan, Sang kawi-wiku asal Daha (Jawa Timur) itu memiliki cucu bernama Ida Pedanda Sakti Manuaba yang tigggal di Desa Kendran Tegalalang Gianyar. Merasa tidak disenangi sang ayah, Ida Pedanda Sakti Manuaba pergi mengembara bersama dua orang pengiringnya. Pengembaraan sang pendeta sampai di pura Sarin Buana di Jimbaran. Saat mengadakan semedi di tempat ini sang pendeta melihat sinar api. Yang sangat jauh di utara. Timbul keinginan Ida Pedanda Manuaba untuk mengunjungi tempat itu. Sampailah sang Pedanda di pura Batan Bila Peguyangan. Disini Ida Pedanda Manuaba singgah menghadap Ida Pedanda Budha yang tinggal disana. Selanjutnya, kedua pendeta bersama-sama menuju arah utara dan singgah di Taman Cang Ana, sebuah taman milik Arya Lanang Blusung. Di tempat ini kedua pendeta bersama-sama melaksanakan semedi dan menetap untuk sementara waktu.</p>",
"visi" : "<p>Mewujudkan Desa Darmasaba yang sejahtera, unggul, religius, berbudaya, dan aman dengan berlandaskan Tri Hita Karana</p>",
"misi" : "<ul><li>Memperkokoh kerukunan hidup masyarakat dalam jalinan adat, budaya, olahraga, dan agama.</li><li>Meningkatkan kualitas pelayanan publik dengan menerapkan teknologi informasi dan komunikasi terintegrasi.</li><li>Meningkatkan tata kelola pemerintah desa dengan menerapkan prinsip good governance dan good clean government.</li><li>Meningkatkan kualitas pendidikan, kesehatan, Keluarga Berencana serta pengelolaan kependudukan.</li><li>Memperkuat usaha mikro kecil dan menengah (UMKM) dan BUMDesa sebagai pilar ekonomi masyarakat.</li><li>Mewujudkan tatanan kehidupan bermasyarakat yang menjunjung tinggi penegakan hukum dan HAM.</li><li>Meningkatkan perlindungan dan pengelolaan terhadap sumber daya alam dan lingkungan hidup.</li><li>Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa.</li><li>Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata.</li></ul>",
"lambang" : "<ul><li>Memperkokoh kerukunan hidup masyarakat dalam jalinan adat, budaya, olahraga, dan agama.</li><li>Meningkatkan kualitas pelayanan publik dengan menerapkan teknologi informasi dan komunikasi terintegrasi.</li><li>Meningkatkan tata kelola pemerintah desa dengan menerapkan prinsip good governance dan good clean government.</li><li>Meningkatkan kualitas pendidikan, kesehatan, Keluarga Berencana serta pengelolaan kependudukan.</li><li>Memperkuat usaha mikro kecil dan menengah (UMKM) dan BUMDesa sebagai pilar ekonomi masyarakat.</li><li>Mewujudkan tatanan kehidupan bermasyarakat yang menjunjung tinggi penegakan hukum dan HAM.</li><li>Meningkatkan perlindungan dan pengelolaan terhadap sumber daya alam dan lingkungan hidup.</li><li>Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa.</li><li>Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata.</li><li>Memperkuat daya saing desa melalui peningkatan mutu sumber daya manusia dan infrastruktur desa berbasis potensi desa.</li><li>Meningkatkan sinergisitas potensi budaya, pertanian dalam arti luas dan pariwisata.</li></ul>",
"maskot" : "<p>Pudak adalah bunga dari tanaman sejenis pandan (Pandanaceae). Bentuk bunga ini tersusun dalam beberapa lapisan, terbungkus oleh kelopak warna putih (semacam daun lonjong) yang ujungnya meruncing.</p><p>Bunga Pudak berwarna kuning dan akan terlihat jika kelopak atau pelepahnya telah mekar. Kekhasan dari bunga pudak, yaitu mempunyai aroma wangi yang semerbak nan lembut (tidak menyengat), dan dapat menebar keharuman sepanjang pagi atau pun sore hari. Tanaman ini dapat tumbuh di sepanjang pantai, aliran sungai, di atas batu-batu karang, dan juga di tanah ladang.</p><p>Dalam Kamus Jawa Kuna- Indonesia kata “Pudak” berarti bunga pandan atau Pandanus Moschatus (Mardiwarsito: 1981: 442). Selain itu bunga pudak juga dapat disebut ketaka atau ketaki (Mardiwarsito, 1981: 276). Sedangkan kata “Sategal” berasal dari kata dasar “Tegal” yang berarti ladang (Mardiwarsito, 1981: 593). Jadi Pudak Sategal dapat diartikan sebagai satu ladang luas yang dipenuhi bunga pudak dan menabar keharuman.</p><p>Pada sebuah kesempatan, Ida Pedanda Putu Pemaron menjelaskan mengenai makna dari istilah Pudak Sategal dengan sebuah analogi bahwa, sekuntum bunga pudak memiliki aroma wangi atau keharuman yang sangat kuat, apalagi jika satu ladang penuh bunga pudak, maka dapat dipastikan aroma keharumannya akan membumbung menyebar ke segala penjuru (Wawancara, 18 Mei 2019 di Geria Putra Mandara Kenderan, Tegallalang). “Pudak” ialah sebuah bunga yang memiliki aroma wangi atau keharuman yang semerbak, lembut, dan khas.</p><p>Garapan Tari Maskot Desa Darmasaba Sekar Pudak diwujudkan ke dalam bentuk tari kreasi yang ditarikan secara berkelompok dengan jumlah lima orang penari perempuan (putri).</p><p>Pemilihan penari perempuan dimaksudkan untuk mempresentasikan keindahan, keluwesan, dan keharuman dari bunga pudak. Sedangkan penetapan jumlah penari lima orang didasarkan atas pertimbangan kebutuhan koreografi agar dapat membentuk desain-desain komposisi lantai yang menarik dan dinamis, baik ketika ditarikan di area panggung yang luas atau pun area panggung yang kecil. Penyajian tari maskot ini dirancang dengan durasi waktu 9 menit.</p>",
"profilPerbekelId" : "1"
}
]

View File

@@ -0,0 +1,9 @@
[
{ "name": "Semua" },
{ "name": "Pemerintahan" },
{ "name": "Pembangunan" },
{ "name": "Ekonomi" },
{ "name": "Sosial" },
{ "name": "Budaya" },
{ "name": "Teknologi" }
]

View File

@@ -0,0 +1,5 @@
[
{"name": "Melihat/Membaca/Mendengarkan/Mencatat"},
{"name": "Mendapatkan Salinan Informasi (Hardcopy)"},
{"name": "Mendapatkan Salinan Informasi (Softcopy)"}
]

View File

@@ -0,0 +1,5 @@
[
{ "name": "Mengambil Langsung" },
{ "name": "Dikirim Via Post" },
{ "name": "Dikirim Via Email" }
]

View File

@@ -0,0 +1,6 @@
[
{ "name": "Keuangan Desa" },
{ "name": "Pembangunan Desa" },
{ "name": "Data Demografi" },
{ "name": "Lainnya" }
]

View File

@@ -0,0 +1,8 @@
[
{
"id": "1",
"jenisInformasi": "Peraturan Desa",
"deskripsi": "Dokumen yang berisi kebijakan dan regulasi desa",
"tanggal": "15 Januari 2024"
}
]

View 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>"
}
]

View 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"
}
]

View 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."
}
]

View File

@@ -0,0 +1,355 @@
-- CreateTable
CREATE TABLE "Layanan" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
CONSTRAINT "Layanan_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Potensi" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
CONSTRAINT "Potensi_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "LandingPage_Layanan" (
"id" TEXT NOT NULL,
"deksripsi" TEXT NOT NULL,
CONSTRAINT "LandingPage_Layanan_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "AppMenu" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"link" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
CONSTRAINT "AppMenu_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "AppMenuChild" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"link" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"appMenuId" TEXT,
CONSTRAINT "AppMenuChild_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Berita" (
"id" TEXT NOT NULL,
"judul" TEXT NOT NULL,
"deskripsi" TEXT NOT NULL,
"image" TEXT NOT NULL,
"content" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"katagoryBeritaId" TEXT,
CONSTRAINT "Berita_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "KatagoryBerita" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
CONSTRAINT "KatagoryBerita_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Pengumuman" (
"id" TEXT NOT NULL,
"judul" TEXT NOT NULL,
"deskripsi" TEXT NOT NULL,
"content" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"categoryPengumumanId" TEXT,
CONSTRAINT "Pengumuman_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "CategoryPengumuman" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
CONSTRAINT "CategoryPengumuman_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Images" (
"id" TEXT NOT NULL,
"url" TEXT NOT NULL,
"label" TEXT NOT NULL DEFAULT 'null',
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Images_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Videos" (
"id" TEXT NOT NULL,
"url" TEXT NOT NULL,
"label" TEXT NOT NULL DEFAULT 'null',
"active" BOOLEAN NOT NULL DEFAULT true,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Videos_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "GalleryFoto" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"image" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"imagesId" TEXT,
CONSTRAINT "GalleryFoto_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "GalleryVideo" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"video" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
"videosId" TEXT,
CONSTRAINT "GalleryVideo_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "DataKematian_Kelahiran" (
"id" SERIAL NOT NULL,
"tahun" TEXT NOT NULL,
"kematianKasar" TEXT NOT NULL,
"kematianBayi" TEXT NOT NULL,
"kelahiranKasar" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "DataKematian_Kelahiran_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "FasilitasKesehatan" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
CONSTRAINT "FasilitasKesehatan_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "InformasiUmum" (
"id" TEXT NOT NULL,
"fasilitas" TEXT NOT NULL,
"alamat" TEXT NOT NULL,
"jamOperasional" TEXT NOT NULL,
"fasilitasKesehatanId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
CONSTRAINT "InformasiUmum_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "LayananUnggulan" (
"id" TEXT NOT NULL,
"content" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
CONSTRAINT "LayananUnggulan_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "DokterdanTenagaMedis" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
CONSTRAINT "DokterdanTenagaMedis_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "FasilitasPendukung" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
CONSTRAINT "FasilitasPendukung_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ProsedurPendaftaran" (
"id" TEXT NOT NULL,
"content" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deletedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"isActive" BOOLEAN NOT NULL DEFAULT true,
CONSTRAINT "ProsedurPendaftaran_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "_FasilitasKesehatanToLayananUnggulan" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL,
CONSTRAINT "_FasilitasKesehatanToLayananUnggulan_AB_pkey" PRIMARY KEY ("A","B")
);
-- CreateTable
CREATE TABLE "_FasilitasKesehatanToFasilitasPendukung" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL,
CONSTRAINT "_FasilitasKesehatanToFasilitasPendukung_AB_pkey" PRIMARY KEY ("A","B")
);
-- CreateTable
CREATE TABLE "_FasilitasKesehatanToProsedurPendaftaran" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL,
CONSTRAINT "_FasilitasKesehatanToProsedurPendaftaran_AB_pkey" PRIMARY KEY ("A","B")
);
-- CreateTable
CREATE TABLE "_DokterdanTenagaMedisToFasilitasKesehatan" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL,
CONSTRAINT "_DokterdanTenagaMedisToFasilitasKesehatan_AB_pkey" PRIMARY KEY ("A","B")
);
-- CreateIndex
CREATE UNIQUE INDEX "Layanan_name_key" ON "Layanan"("name");
-- CreateIndex
CREATE UNIQUE INDEX "Potensi_name_key" ON "Potensi"("name");
-- CreateIndex
CREATE UNIQUE INDEX "AppMenu_name_key" ON "AppMenu"("name");
-- CreateIndex
CREATE UNIQUE INDEX "AppMenuChild_name_key" ON "AppMenuChild"("name");
-- CreateIndex
CREATE UNIQUE INDEX "KatagoryBerita_name_key" ON "KatagoryBerita"("name");
-- CreateIndex
CREATE UNIQUE INDEX "CategoryPengumuman_name_key" ON "CategoryPengumuman"("name");
-- CreateIndex
CREATE UNIQUE INDEX "GalleryFoto_imagesId_key" ON "GalleryFoto"("imagesId");
-- CreateIndex
CREATE UNIQUE INDEX "GalleryVideo_videosId_key" ON "GalleryVideo"("videosId");
-- CreateIndex
CREATE INDEX "_FasilitasKesehatanToLayananUnggulan_B_index" ON "_FasilitasKesehatanToLayananUnggulan"("B");
-- CreateIndex
CREATE INDEX "_FasilitasKesehatanToFasilitasPendukung_B_index" ON "_FasilitasKesehatanToFasilitasPendukung"("B");
-- CreateIndex
CREATE INDEX "_FasilitasKesehatanToProsedurPendaftaran_B_index" ON "_FasilitasKesehatanToProsedurPendaftaran"("B");
-- CreateIndex
CREATE INDEX "_DokterdanTenagaMedisToFasilitasKesehatan_B_index" ON "_DokterdanTenagaMedisToFasilitasKesehatan"("B");
-- AddForeignKey
ALTER TABLE "AppMenuChild" ADD CONSTRAINT "AppMenuChild_appMenuId_fkey" FOREIGN KEY ("appMenuId") REFERENCES "AppMenu"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Berita" ADD CONSTRAINT "Berita_katagoryBeritaId_fkey" FOREIGN KEY ("katagoryBeritaId") REFERENCES "KatagoryBerita"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Pengumuman" ADD CONSTRAINT "Pengumuman_categoryPengumumanId_fkey" FOREIGN KEY ("categoryPengumumanId") REFERENCES "CategoryPengumuman"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "GalleryFoto" ADD CONSTRAINT "GalleryFoto_imagesId_fkey" FOREIGN KEY ("imagesId") REFERENCES "Images"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "GalleryVideo" ADD CONSTRAINT "GalleryVideo_videosId_fkey" FOREIGN KEY ("videosId") REFERENCES "Videos"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "InformasiUmum" ADD CONSTRAINT "InformasiUmum_fasilitasKesehatanId_fkey" FOREIGN KEY ("fasilitasKesehatanId") REFERENCES "FasilitasKesehatan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_FasilitasKesehatanToLayananUnggulan" ADD CONSTRAINT "_FasilitasKesehatanToLayananUnggulan_A_fkey" FOREIGN KEY ("A") REFERENCES "FasilitasKesehatan"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_FasilitasKesehatanToLayananUnggulan" ADD CONSTRAINT "_FasilitasKesehatanToLayananUnggulan_B_fkey" FOREIGN KEY ("B") REFERENCES "LayananUnggulan"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_FasilitasKesehatanToFasilitasPendukung" ADD CONSTRAINT "_FasilitasKesehatanToFasilitasPendukung_A_fkey" FOREIGN KEY ("A") REFERENCES "FasilitasKesehatan"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_FasilitasKesehatanToFasilitasPendukung" ADD CONSTRAINT "_FasilitasKesehatanToFasilitasPendukung_B_fkey" FOREIGN KEY ("B") REFERENCES "FasilitasPendukung"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_FasilitasKesehatanToProsedurPendaftaran" ADD CONSTRAINT "_FasilitasKesehatanToProsedurPendaftaran_A_fkey" FOREIGN KEY ("A") REFERENCES "FasilitasKesehatan"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_FasilitasKesehatanToProsedurPendaftaran" ADD CONSTRAINT "_FasilitasKesehatanToProsedurPendaftaran_B_fkey" FOREIGN KEY ("B") REFERENCES "ProsedurPendaftaran"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_DokterdanTenagaMedisToFasilitasKesehatan" ADD CONSTRAINT "_DokterdanTenagaMedisToFasilitasKesehatan_A_fkey" FOREIGN KEY ("A") REFERENCES "DokterdanTenagaMedis"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_DokterdanTenagaMedisToFasilitasKesehatan" ADD CONSTRAINT "_DokterdanTenagaMedisToFasilitasKesehatan_B_fkey" FOREIGN KEY ("B") REFERENCES "FasilitasKesehatan"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "postgresql"

View File

@@ -17,3 +17,567 @@ model Potensi {
name String @unique
}
model LandingPage_Layanan {
id String @id @default(cuid())
deksripsi String
}
// ========================================= APPMENU ========================================= //
model AppMenu {
id String @id @default(cuid())
name String @unique
link String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
AppMenuChild AppMenuChild[]
}
// ========================================= APPMENUCHILD ========================================= //
model AppMenuChild {
id String @id @default(cuid())
name String @unique
link String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
AppMenu AppMenu? @relation(fields: [appMenuId], references: [id])
appMenuId String?
}
//========================================= 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())
nomor Int @default(autoincrement())
jenisInformasi String
deskripsi String
tanggal String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
//=========================================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())
label String
kepuasan String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model GrafikBerdasarkanJenisKelamin {
id String @id @default(cuid())
perempuan String
laki String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model GrafikBerdasarkanResponden {
id String @id @default(cuid())
sangatbaik String
baik String
kurangbaik String
tidakbaik String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model GrafikBerdasarkanUmur {
id String @id @default(cuid())
remaja String
dewasa String
orangtua String
lansia String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
// ========================================= MENU DESA ========================================= //
// ========================================= PROFILE DESA ========================================= //
model ProfileDesa {
id String @id @default(cuid())
sejarah String @db.Text
visi String @db.Text
misi String @db.Text
lambang String @db.Text
maskot String @db.Text
ProfilPerbekel ProfilPerbekel? @relation(fields: [profilPerbekelId], references: [id])
profilPerbekelId String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model ProfilPerbekel {
id String @id @default(cuid())
biodata String @db.Text
pengalaman String @db.Text
pengalamanOrganisasi String @db.Text
programUnggulan String @db.Text
ProfileDesa ProfileDesa[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
// ========================================= BERITA ========================================= //
model Berita {
id String @id @default(cuid())
judul String
deskripsi String
image String
content String @db.Text
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
KatagoryBerita KatagoryBerita? @relation(fields: [katagoryBeritaId], references: [id])
katagoryBeritaId String?
}
model KatagoryBerita {
id String @id @default(cuid())
name String @unique
beritas Berita[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
// ========================================= PENGUMUMAN ========================================= //
model Pengumuman {
id String @id @default(cuid())
judul String
deskripsi String
content String @db.Text
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
CategoryPengumuman CategoryPengumuman? @relation(fields: [categoryPengumumanId], references: [id])
categoryPengumumanId String?
}
model CategoryPengumuman {
id String @id @default(cuid())
name String @unique
pengumumans Pengumuman[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
// ========================================= IMAGES ========================================= //
model Images {
id String @id @default(cuid())
url String
label String @default("null")
active Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
GalleryFoto GalleryFoto[]
}
// ========================================= VIDEOS ========================================= //
model Videos {
id String @id @default(cuid())
url String
label String @default("null")
active Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
GalleryVideo GalleryVideo[]
}
// ========================================= GALLERY ========================================= //
model GalleryFoto {
id String @id @default(cuid())
name String
image String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
imagesId String? @unique
imageGalleryFoto Images? @relation(fields: [imagesId], references: [id])
}
model GalleryVideo {
id String @id @default(cuid())
name String
video String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
videosId String? @unique
videosGalleryVideo Videos? @relation(fields: [videosId], references: [id])
}
// ========================================= MENU KESEHATAN ========================================= //
// ========================================= DATA KESEHATAN WARGA ========================================= //
// ========================================= FASILITAS KESEHATAN ========================================= //
model FasilitasKesehatan {
id String @id @default(cuid())
name String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
InformasiUmum InformasiUmum[]
LayananUnggulan LayananUnggulan[]
DokterdanTenagaMedis DokterdanTenagaMedis[]
FasilitasPendukung FasilitasPendukung[]
ProsedurPendaftaran ProsedurPendaftaran[]
TarifDanLayanan TarifDanLayanan[]
}
model InformasiUmum {
id String @id @default(cuid())
fasilitas String
alamat String
jamOperasional String
FasilitasKesehatan FasilitasKesehatan[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model LayananUnggulan {
id String @id @default(cuid())
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
FasilitasKesehatan FasilitasKesehatan[]
}
model DokterdanTenagaMedis {
id String @id @default(cuid())
name String
specialist String
jadwal String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
FasilitasKesehatan FasilitasKesehatan[]
}
model FasilitasPendukung {
id String @id @default(cuid())
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
FasilitasKesehatan FasilitasKesehatan[]
}
model ProsedurPendaftaran {
id String @id @default(cuid())
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
FasilitasKesehatan FasilitasKesehatan[]
}
model TarifDanLayanan {
id String @id @default(cuid())
layanan String
tarif String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
FasilitasKesehatan FasilitasKesehatan[]
}
// ========================================= JADWAL KEGIATAN ========================================= //
model JadwalKegiatan {
id String @id @default(cuid())
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model InformasiJadwalKegiatan {
id String @id @default(cuid())
name String
tanggal String
waktu String
lokasi String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model DeskripsiJadwalKegiatan {
id String @id @default(cuid())
deskripsi String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model LayananJadwalKegiatan {
id String @id @default(cuid())
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model SyaratKetentuanJadwalKegiatan {
id String @id @default(cuid())
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model DokumenJadwalKegiatan {
id String @id @default(cuid())
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model PendaftaranJadwalKegiatan {
id String @id @default(cuid())
name String
tanggal String
namaOrangtua String
nomor String
alamat String
catatan String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
// ========================================= PERSENTASE KELAHIRAN & KEMATIAN ========================================= //
model DataKematian_Kelahiran {
id Int @id @default(autoincrement())
tahun String
kematianKasar String
kematianBayi String
kelahiranKasar String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
// ========================================= GRAFIK KEPUASAN ========================================= //
model GrafikKepuasan {
id Int @id @default(autoincrement())
label String
jumlah String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
// ========================================= ARTIKEL KESEHATAN ========================================= //
model ArtikelKesehatan {
id Int @id @default(autoincrement())
title String
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model Introduction {
id Int @id @default(autoincrement())
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model Symptom {
id Int @id @default(autoincrement())
title String
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model Prevention {
id Int @id @default(autoincrement())
title String
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model FirstAid {
id Int @id @default(autoincrement())
title String
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model MythVsFact {
id Int @id @default(autoincrement())
title String
mitos String
fakta String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}
model DoctorSign {
id Int @id @default(autoincrement())
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())
isActive Boolean @default(true)
}

View File

@@ -1,7 +1,17 @@
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 prisma from '@/lib/prisma';
; (async () => {
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'
import profileDesa from './data/desa/profile/profile_desa.json'
import profilePerbekel from './data/desa/profile/profil_perbekel.json'
(async () => {
for (const l of layanan) {
await prisma.layanan.upsert({
where: {
@@ -33,6 +43,194 @@ import prisma from '@/lib/prisma';
}
console.log("potensi success ...")
for (const k of katagoryBerita) {
await prisma.katagoryBerita.upsert({
where: {
name: k.name
},
update: {
name: k.name
},
create: {
name: k.name
}
})
}
console.log("katagory berita success ...")
for (const c of categoryPengumuman) {
await prisma.categoryPengumuman.upsert({
where: {
name: c.name
},
update: {
name: c.name
},
create: {
name: c.name
}
})
}
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 ...")
for (const v of profileDesa) {
await prisma.profileDesa.upsert({
where: {
id: v.id,
},
update: {
sejarah: v.sejarah,
visi: v.visi,
misi: v.misi,
lambang: v.lambang,
maskot: v.maskot,
profilPerbekelId: v.profilPerbekelId
},
create: {
id: v.id,
sejarah: v.sejarah,
visi: v.visi,
misi: v.misi,
lambang: v.lambang,
maskot: v.maskot,
profilPerbekelId: v.profilPerbekelId
}
})
}
console.log("profile desa success ...")
for (const v of profilePerbekel) {
await prisma.profilPerbekel.upsert({
where: {
id: v.id,
},
update: {
biodata: v.biodata,
pengalaman: v.pengalaman,
pengalamanOrganisasi: v.pengalamanOrganisasi,
programUnggulan: v.programUnggulan
},
create: {
id: v.id,
biodata: v.biodata,
pengalaman: v.pengalaman,
pengalamanOrganisasi: v.pengalamanOrganisasi,
programUnggulan: v.programUnggulan
}
})
}
console.log("profile perbekel success ...")
})().then(() => prisma.$disconnect()).catch((e) => {
console.error(e)
prisma.$disconnect()

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

View File

@@ -0,0 +1,90 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import ApiFetch from "@/lib/api-fetch";
import { Prisma } from "@prisma/client";
import { toast } from "react-toastify";
import { proxy } from "valtio";
import { z } from "zod";
const templateForm = z.object({
judul: z.string().min(3, "Judul minimal 3 karakter"),
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
image: z.string().url().min(3, "Image minimal 3 karakter"),
content: z.string().min(3, "Content minimal 3 karakter"),
katagoryBeritaId: z.string().nonempty(),
});
const category = proxy({
findMany: {
data: null as
| null
| Prisma.KatagoryBeritaGetPayload<{ omit: { isActive: true } }>[],
async load() {
const res = await ApiFetch.api.desa.berita.category["find-many"].get();
if (res.status === 200) {
category.findMany.data = res.data?.data ?? [];
}
},
},
});
type BeritaForm = Prisma.BeritaGetPayload<{
select: {
judul: true;
deskripsi: true;
image: true;
content: true;
katagoryBeritaId: true;
};
}>;
const berita = proxy({
create: {
form: {} as BeritaForm,
loading: false,
async create() {
berita.create.form.image =
"https://www.shutterstock.com/image-vector/lower-news-live-streaming-breaking-600nw-2535984111.jpg";
const cek = templateForm.safeParse(berita.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
berita.create.loading = true;
const res = await ApiFetch.api.desa.berita["create"].post(
berita.create.form
);
if (res.status === 200) {
berita.findMany.load();
return toast.success("succes create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
berita.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.BeritaGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.desa.berita["find-many"].get();
if (res.status === 200) {
berita.findMany.data = (res.data?.data as any) ?? [];
}
},
},
});
const stateDashboardBerita = proxy({
category,
berita,
});
export default stateDashboardBerita;

View File

@@ -0,0 +1,83 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import ApiFetch from "@/lib/api-fetch"
import { Prisma } from "@prisma/client"
import { toast } from "react-toastify"
import { proxy } from "valtio"
import { z } from "zod"
const templateFormPengumuman = z.object({
judul: z.string().min(3, "Judul minimal 3 karakter"),
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
content: z.string().min(3, "Content minimal 3 karakter"),
categoryPengumumanId: z.string().nonempty(),
})
const category = proxy ({
findMany: {
data: null as
| null
| Prisma.CategoryPengumumanGetPayload<{ omit: { isActive: true } }>[],
async load() {
const res = await ApiFetch.api.desa.pengumuman.category["find-many"].get();
if (res.status === 200) {
category.findMany.data = res.data?.data as any ?? [];
}
}
}
})
type PengumumanForm = Prisma.PengumumanGetPayload<{
select: {
judul: true;
deskripsi: true;
content: true;
categoryPengumumanId: true;
}
}>
const pengumuman = proxy({
create: {
form: {} as PengumumanForm,
loading: false,
async create() {
const cek = templateFormPengumuman.safeParse(pengumuman.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
pengumuman.create.loading = true;
const res = await ApiFetch.api.desa.pengumuman["create"].post(pengumuman.create.form)
if (res.status === 200) {
pengumuman.findMany.load();
return toast.success("success create");
}
console.log(res)
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally{
pengumuman.create.loading = false;
}
}
},
findMany: {
data: null as
| Prisma.PengumumanGetPayload<{omit: {isActive: true}}>[]
| null,
async load () {
const res = await ApiFetch.api.desa.pengumuman["find-many"].get();
console.log(res)
if (res.status === 200) {
pengumuman.findMany.data = res.data?.data ?? [];
}
}
}
})
const stateDesaPengumuman = proxy({
category,
pengumuman
})
export default stateDesaPengumuman

View File

@@ -0,0 +1,339 @@
import ApiFetch from "@/lib/api-fetch";
import { Prisma } from "@prisma/client";
import { toast } from "react-toastify";
import { proxy } from "valtio";
import { z } from "zod";
/* Introduction */
const templateIntroduction = z.object({
content: z.string().min(3, "Content minimal 3 karakter"),
})
type Introduction = Prisma.IntroductionGetPayload<{
select: {
content: true;
};
}>;
const introduction = proxy({
create: {
form: {} as Introduction,
loading: false,
async create() {
const cek = templateIntroduction.safeParse(introduction.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
introduction.create.loading = true;
const res = await ApiFetch.api.kesehatan.introduction["create"].post(introduction.create.form);
if (res.status === 200) {
introduction.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
introduction.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.IntroductionGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.introduction["find-many"].get();
if (res.status === 200) {
introduction.findMany.data = res.data?.data ?? [];
}
}
}
});
/* ======================================================================= */
/* symptom */
const templateSymptom = z.object({
title: z.string().min(3, "Title minimal 3 karakter"),
content: z.string().min(3, "Content minimal 3 karakter"),
})
type Symptom = Prisma.SymptomGetPayload<{
select: {
title: true;
content: true;
};
}>;
const symptom = proxy({
create: {
form: {} as Symptom,
loading: false,
async create() {
const cek = templateSymptom.safeParse(symptom.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
symptom.create.loading = true;
const res = await ApiFetch.api.kesehatan.symptom["create"].post(symptom.create.form);
if (res.status === 200) {
symptom.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
symptom.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.SymptomGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.symptom["find-many"].get();
if (res.status === 200) {
symptom.findMany.data = res.data?.data ?? [];
}
},
},
});
/* ======================================================================= */
/* Prevention */
const templatePrevention = z.object({
title: z.string().min(3, "Title minimal 3 karakter"),
content: z.string().min(3, "Content minimal 3 karakter"),
})
type Prevention = Prisma.PreventionGetPayload<{
select: {
title: true;
content: true;
};
}>;
const prevention = proxy({
create: {
form: {} as Prevention,
loading: false,
async create() {
const cek = templatePrevention.safeParse(prevention.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
prevention.create.loading = true;
const res = await ApiFetch.api.kesehatan.prevention["create"].post(prevention.create.form);
if (res.status === 200) {
prevention.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
prevention.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.PreventionGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.prevention["find-many"].get();
if (res.status === 200) {
prevention.findMany.data = res.data?.data ?? [];
}
},
},
});
/* ======================================================================= */
/* First Aid */
const templateFirstAid = z.object({
title: z.string().min(3, "Title minimal 3 karakter"),
content: z.string().min(3, "Content minimal 3 karakter"),
})
type FirstAid = Prisma.FirstAidGetPayload<{
select: {
title: true;
content: true;
};
}>;
const firstAid = proxy({
create: {
form: {} as FirstAid,
loading: false,
async create() {
const cek = templateFirstAid.safeParse(firstAid.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
firstAid.create.loading = true;
const res = await ApiFetch.api.kesehatan.firstaid["create"].post(firstAid.create.form);
if (res.status === 200) {
firstAid.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
firstAid.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.FirstAidGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.firstaid["find-many"].get();
if (res.status === 200) {
firstAid.findMany.data = res.data?.data ?? [];
}
},
},
})
/* ======================================================================= */
/* Myth vs Fact */
const templateMythFact = z.object({
title: z.string().min(3, "Title minimal 3 karakter"),
mitos: z.string().min(3, "Mitos minimal 3 karakter"),
fakta: z.string().min(3, "Fakta minimal 3 karakter"),
})
type MythFact = Prisma.MythVsFactGetPayload<{
select: {
title: true;
mitos: true;
fakta: true;
};
}>;
const mythFact = proxy({
create: {
form: {} as MythFact,
loading: false,
async create() {
const cek = templateMythFact.safeParse(mythFact.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
mythFact.create.loading = true;
const res = await ApiFetch.api.kesehatan.mythvsfact["create"].post(mythFact.create.form);
if (res.status === 200) {
mythFact.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
mythFact.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.MythVsFactGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.mythvsfact["find-many"].get();
if (res.status === 200) {
mythFact.findMany.data = res.data?.data ?? [];
}
},
},
})
/* ======================================================================= */
/* Doctor Sign */
const templateDoctorSign = z.object({
content: z.string().min(3, "Content minimal 3 karakter"),
})
type DoctorSign = Prisma.DoctorSignGetPayload<{
select: {
content: true
}
}>
const doctorSign = proxy({
create: {
form: {} as DoctorSign,
loading: false,
async create() {
const cek = templateDoctorSign.safeParse(doctorSign.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
doctorSign.create.loading = true;
const res = await ApiFetch.api.kesehatan.doctor_sign["create"].post(doctorSign.create.form);
if (res.status === 200) {
doctorSign.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
doctorSign.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.DoctorSignGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.doctor_sign["find-many"].get();
if (res.status === 200) {
doctorSign.findMany.data = res.data?.data ?? [];
}
},
},
})
/* ======================================================================= */
const stateArtikelKesehatan = proxy({
introduction,
symptom,
prevention,
firstAid,
mythFact,
doctorSign
})
export default stateArtikelKesehatan

View File

@@ -0,0 +1,333 @@
import ApiFetch from "@/lib/api-fetch";
import { Prisma } from "@prisma/client";
import { toast } from "react-toastify";
import { proxy } from "valtio";
import { z } from "zod";
/* Informasi Umum */
const templateInformasiUmum = z.object({
fasilitas: z.string().min(3, "Fasilitas minimal 3 karakter"),
alamat: z.string().min(3, "Alamat minimal 3 karakter"),
jamOperasional: z.string().min(3, "Jam Operasional minimal 3 karakter"),
});
type InfromasiUmum = Prisma.InformasiUmumGetPayload<{
select: {
fasilitas: true;
alamat: true;
jamOperasional: true;
};
}>;
const informasiumum = proxy({
create: {
form: {} as InfromasiUmum,
loading: false,
async create() {
const cek = templateInformasiUmum.safeParse(informasiumum.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
informasiumum.create.loading = true;
const res = await ApiFetch.api.kesehatan.informasiumum["create"].post(
informasiumum.create.form
);
if (res.status === 200) {
informasiumum.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
informasiumum.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.InformasiUmumGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.
informasiumum["find-many"].get();
if (res.status === 200) {
informasiumum.findMany.data = res.data?.data ?? [];
}
},
},
});
/* ======================================================================= */
/* Layanan Unggulan */
const templateLayananUnggulanForm = z.object({
content: z.string().min(3, "Content minimal 3 karakter"),
});
type LayananUnggulan = Prisma.LayananUnggulanGetPayload<{
select: {
content: true;
};
}>;
const layananunggulan = proxy({
create: {
form: {} as LayananUnggulan,
loading: false,
async create() {
const cek = templateLayananUnggulanForm.safeParse(layananunggulan.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
layananunggulan.create.loading = true;
const res = await ApiFetch.api.kesehatan.layananunggulan["create"].post(
layananunggulan.create.form
);
if (res.status === 200) {
layananunggulan.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
layananunggulan.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.LayananUnggulanGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.
layananunggulan["find-many"].get();
if (res.status === 200) {
layananunggulan.findMany.data = res.data?.data ?? [];
}
},
},
})
/* ======================================================================= */
/* Dokter dan Tenaga Medis */
const templateDokterdanTenagaMedis = z.object({
name: z.string().min(3, "Name minimal 3 karakter"),
specialist: z.string().min(3, "Specialist minimal 3 karakter"),
jadwal: z.string().min(3, "Jadwal minimal 3 karakter"),
})
type DokterdanTenagaMedis = Prisma.DokterdanTenagaMedisGetPayload<{
select: {
name: true;
specialist: true;
jadwal: true;
};
}>;
const dokterdantenagamedis = proxy({
create: {
form: {} as DokterdanTenagaMedis,
loading: false,
async create() {
const cek = templateDokterdanTenagaMedis.safeParse(dokterdantenagamedis.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
dokterdantenagamedis.create.loading = true;
const res = await ApiFetch.api.kesehatan.dokterdantenagamedis["create"].post(dokterdantenagamedis.create.form);
if (res.status === 200) {
dokterdantenagamedis.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
dokterdantenagamedis.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.DokterdanTenagaMedisGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.dokterdantenagamedis["find-many"].get();
if (res.status === 200) {
dokterdantenagamedis.findMany.data = res.data?.data ?? [];
}
},
},
})
/* ======================================================================= */
/* Fasilitas Pendukung */
const templateFasilitasPendukung = z.object({
content: z.string().min(3, "Content minimal 3 karakter"),
})
type FasilitasPendukung = Prisma.FasilitasPendukungGetPayload<{
select: {
content: true;
};
}>;
const fasilitaspendukung = proxy({
create: {
form: {} as FasilitasPendukung,
loading: false,
async create() {
const cek = templateFasilitasPendukung.safeParse(fasilitaspendukung.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
fasilitaspendukung.create.loading = true;
const res = await ApiFetch.api.kesehatan.fasilitaspendukung["create"].post(fasilitaspendukung.create.form);
if (res.status === 200) {
fasilitaspendukung.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
fasilitaspendukung.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.FasilitasPendukungGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.
fasilitaspendukung["find-many"].get();
if (res.status === 200) {
fasilitaspendukung.findMany.data = res.data?.data ?? [];
}
},
},
})
/* ======================================================================= */
/* Tarif dan Layanan */
const templateTarifDanLayanan = z.object({
layanan: z.string().min(3, "Layanan minimal 3 karakter"),
tarif: z.string().min(3, "Tarif minimal 3 karakter"),
})
const tarifdanlayanan = proxy({
create: {
form: {} as Prisma.TarifDanLayananGetPayload<{ select: { layanan: true; tarif: true } }>,
loading: false,
async create() {
const cek = templateTarifDanLayanan.safeParse(tarifdanlayanan.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
tarifdanlayanan.create.loading = true;
const res = await ApiFetch.api.kesehatan.tarifdanlayanan["create"].post(tarifdanlayanan.create.form);
if (res.status === 200) {
tarifdanlayanan.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
tarifdanlayanan.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.TarifDanLayananGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.
tarifdanlayanan["find-many"].get();
if (res.status === 200) {
tarifdanlayanan.findMany.data = res.data?.data ?? [];
}
},
},
})
/* ======================================================================= */
/* Prosedur Pendaftaran */
const templateProsedurPendaftaran = z.object({
content: z.string().min(3, "Content minimal 3 karakter"),
})
const prosedurpendaftaran = proxy({
create: {
form: {} as Prisma.ProsedurPendaftaranGetPayload<{ select: { content: true } }>,
loading: false,
async create() {
const cek = templateProsedurPendaftaran.safeParse(prosedurpendaftaran.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
prosedurpendaftaran.create.loading = true;
const res = await ApiFetch.api.kesehatan.prosedurpendaftaran["create"].post(prosedurpendaftaran.create.form);
if (res.status === 200) {
prosedurpendaftaran.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
prosedurpendaftaran.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.ProsedurPendaftaranGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.
prosedurpendaftaran["find-many"].get();
if (res.status === 200) {
prosedurpendaftaran.findMany.data = res.data?.data ?? [];
}
},
},
})
const stateFasilitasKesehatan = proxy({
informasiumum,
layananunggulan,
dokterdantenagamedis,
fasilitaspendukung,
tarifdanlayanan,
prosedurpendaftaran
})
export default stateFasilitasKesehatan

View File

@@ -0,0 +1,76 @@
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 templateGrafikKepuasan = z.object({
label: z.string().min(2, "Label harus diisi"),
jumlah: z.string().min(2, "Jumlah harus diisi"),
});
type GrafikKepuasan = Prisma.GrafikKepuasanGetPayload<{
select: {
label: true;
jumlah: true;
};
}>;
const defaultForm: GrafikKepuasan = {
label: "",
jumlah: ""
};
const grafikkepuasan = proxy({
create: {
form: defaultForm,
loading: false,
async create() {
const cek = templateGrafikKepuasan.safeParse(grafikkepuasan.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
grafikkepuasan.create.loading = true;
const res = await ApiFetch.api.kesehatan.grafikkepuasan["create"].post(
grafikkepuasan.create.form
);
if (res.status === 200) {
grafikkepuasan.create.form = {
label: "",
jumlah: ""
};
grafikkepuasan.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
grafikkepuasan.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.GrafikKepuasanGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.grafikkepuasan[
"find-many"
].get();
if (res.status === 200) {
grafikkepuasan.findMany.data = res.data?.data ?? [];
}
},
},
});
const stategrafikKepuasan = proxy({
grafikkepuasan,
});
export default stategrafikKepuasan;

View File

@@ -0,0 +1,366 @@
import ApiFetch from "@/lib/api-fetch";
import { Prisma } from "@prisma/client";
import { toast } from "react-toastify";
import { proxy } from "valtio";
import { z } from "zod";
/* Informasi Kegiatan */
const templateInformasiKegiatan = z.object({
name: z.string().min(3, "Name minimal 3 karakter"),
tanggal: z.string().min(3, "Tanggal minimal 3 karakter"),
waktu: z.string().min(3, "Waktu minimal 3 karakter"),
lokasi: z.string().min(3, "Lokasi minimal 3 karakter"),
});
type InformasiKegiatan = Prisma.InformasiJadwalKegiatanGetPayload<{
select: {
name: true;
tanggal: true;
waktu: true;
lokasi: true;
};
}>;
const informasiKegiatan = proxy({
create: {
form: {} as InformasiKegiatan,
loading: false,
async create() {
const cek = templateInformasiKegiatan.safeParse(
informasiKegiatan.create.form
);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
informasiKegiatan.create.loading = true;
const res = await ApiFetch.api.kesehatan.informasiJadwalKegiatan[
"create"
].post(informasiKegiatan.create.form);
if (res.status === 200) {
informasiKegiatan.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
informasiKegiatan.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.InformasiJadwalKegiatanGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.informasiJadwalKegiatan[
"find-many"
].get();
if (res.status === 200) {
informasiKegiatan.findMany.data = res.data?.data ?? [];
}
},
},
});
/* ======================================================================= */
/* Deskripsi Kegiatan */
const templateDeskripsiKegiatan = z.object({
deskripsi: z.string().min(3, "Content minimal 3 karakter"),
});
type DeskripsiKegiatan = Prisma.DeskripsiJadwalKegiatanGetPayload<{
select: { deskripsi: true };
}>;
const deskripsiKegiatan = proxy({
create: {
form: {} as DeskripsiKegiatan,
loading: false,
async create() {
const cek = templateDeskripsiKegiatan.safeParse(
deskripsiKegiatan.create.form
);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
deskripsiKegiatan.create.loading = true;
const res = await ApiFetch.api.kesehatan.deskripsikegiatan[
"create"
].post(deskripsiKegiatan.create.form);
if (res.status === 200) {
deskripsiKegiatan.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
deskripsiKegiatan.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.DeskripsiJadwalKegiatanGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.deskripsikegiatan[
"find-many"
].get();
if (res.status === 200) {
deskripsiKegiatan.findMany.data = res.data?.data ?? [];
}
},
},
});
/* ======================================================================= */
/* Layanan Tersedia */
const templateLayananTersedia = z.object({
content: z.string().min(3, "Content minimal 3 karakter"),
});
type LayananTersedia = Prisma.LayananJadwalKegiatanGetPayload<{
select: { content: true };
}>;
const layanantersedia = proxy({
create: {
form: {} as LayananTersedia,
loading: false,
async create() {
const cek = templateLayananTersedia.safeParse(
layanantersedia.create.form
);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
layanantersedia.create.loading = true;
const res = await ApiFetch.api.kesehatan.layanantersedia["create"].post(
layanantersedia.create.form
);
if (res.status === 200) {
layanantersedia.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
layanantersedia.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.LayananJadwalKegiatanGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.layanantersedia[
"find-many"
].get();
if (res.status === 200) {
layanantersedia.findMany.data = res.data?.data ?? [];
}
},
},
});
/* ======================================================================= */
/* Syarat dan Ketentuan */
const templateSyaratKetentuan = z.object({
content: z.string().min(3, "Content minimal 3 karakter"),
});
type SyaratKetentuan = Prisma.SyaratKetentuanJadwalKegiatanGetPayload<{
select: { content: true };
}>;
const syaratketentuan = proxy({
create: {
form: {} as SyaratKetentuan,
loading: false,
async create() {
const cek = templateSyaratKetentuan.safeParse(
syaratketentuan.create.form
);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
syaratketentuan.create.loading = true;
const res = await ApiFetch.api.kesehatan.syaratketentuan[
"create"
].post(syaratketentuan.create.form);
if (res.status === 200) {
syaratketentuan.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
syaratketentuan.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.SyaratKetentuanJadwalKegiatanGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.syaratketentuan[
"find-many"
].get();
if (res.status === 200) {
syaratketentuan.findMany.data = res.data?.data ?? [];
}
},
},
});
/* ======================================================================= */
/* Dokumen Yang Diperlukan */
const templateDokumenDiperlukan = z.object({
content: z.string().min(3, "Content minimal 3 karakter"),
});
type DokumenDiperlukan = Prisma.DokumenJadwalKegiatanGetPayload<{
select: { content: true };
}>;
const dokumenjadwalkegiatan = proxy({
create: {
form: {} as DokumenDiperlukan,
loading: false,
async create() {
const cek = templateDokumenDiperlukan.safeParse(
dokumenjadwalkegiatan.create.form
);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
dokumenjadwalkegiatan.create.loading = true;
const res = await ApiFetch.api.kesehatan.dokumendiperlukan[
"create"
].post(dokumenjadwalkegiatan.create.form);
if (res.status === 200) {
dokumenjadwalkegiatan.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
dokumenjadwalkegiatan.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.DokumenJadwalKegiatanGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.dokumendiperlukan[
"find-many"
].get();
if (res.status === 200) {
dokumenjadwalkegiatan.findMany.data = res.data?.data ?? [];
}
},
},
});
/* ======================================================================= */
/* Pendaftaran */
const templatePendaftaran = z.object({
name: z.string().min(3, "Nama minimal 3 karakter"),
tanggal: z.string().min(1),
namaOrangtua: z.string().min(3, "Nama minimal 3 karakter"),
nomor: z.string().min(9, "Nama minimal 9 karakter"),
alamat: z.string().min(7, "Alamat minimal 7 karakter"),
catatan: z.string().min(3, "Catatan minimal 3 karakter"),
})
type Pendaftaran = Prisma.PendaftaranJadwalKegiatanGetPayload<{
select: {
name: true;
tanggal: true;
namaOrangtua: true;
nomor: true;
alamat: true;
catatan: true;
}
}>
const pendaftaranjadwal = proxy({
create: {
form: {} as Pendaftaran,
loading: false,
async create() {
const cek = templatePendaftaran.safeParse(pendaftaranjadwal.create.form);
if(!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
pendaftaranjadwal.create.loading = true;
const res = await ApiFetch.api.kesehatan.pendaftaranJadwalKegiatan["create"].post(
pendaftaranjadwal.create.form);
if (res.status === 200) {
pendaftaranjadwal.findMany.load();
return toast.success("success create")
}
return toast.error("failed create")
} catch (error) {
console.log((error as Error).message)
} finally {
pendaftaranjadwal.create.loading = false;
}
}
},
findMany: {
data: null as
| Prisma.PendaftaranJadwalKegiatanGetPayload<{omit: {isActive: true}}>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.
pendaftaranJadwalKegiatan["find-many"].get();
if(res.status === 200) {
pendaftaranjadwal.findMany.data = res.data?.data ?? [];
}
}
}
})
const stateJadwalKegiatan = proxy({
informasiKegiatan,
deskripsiKegiatan,
layanantersedia,
syaratketentuan,
dokumenjadwalkegiatan,
pendaftaranjadwal
});
export default stateJadwalKegiatan;

View File

@@ -0,0 +1,84 @@
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 templatePersentase = z.object({
tahun: z.string().min(4, "Tahun harus diisi"),
kematianKasar: z.string().min(2, "Kematian kasar harus diisi"),
kelahiranKasar: z.string().min(2, "Kelahiran kasar harus diisi"),
kematianBayi: z.string().min(2, "Kematian bayi harus diisi"),
});
type Persentase = Prisma.DataKematian_KelahiranGetPayload<{
select: {
tahun: true;
kematianKasar: true;
kelahiranKasar: true;
kematianBayi: true;
};
}>;
const defaultForm: Persentase = {
tahun: "",
kematianKasar: "",
kelahiranKasar: "",
kematianBayi: "",
};
const persentasekelahiran = proxy({
create: {
form: defaultForm,
loading: false,
async create() {
const cek = templatePersentase.safeParse(persentasekelahiran.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
persentasekelahiran.create.loading = true;
const res = await ApiFetch.api.kesehatan.persentasekelahiran[
"create"
].post(persentasekelahiran.create.form);
if (res.status === 200) {
persentasekelahiran.create.form = {
tahun: "",
kematianKasar: "",
kelahiranKasar: "",
kematianBayi: "",
};
persentasekelahiran.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
persentasekelahiran.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.DataKematian_KelahiranGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.kesehatan.persentasekelahiran[
"find-many"
].get();
if (res.status === 200) {
persentasekelahiran.findMany.data = res.data?.data ?? [];
}
},
},
});
const statePersentase = proxy({
persentasekelahiran,
});
export default statePersentase;

View File

@@ -0,0 +1,65 @@
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 templateDaftarInformasi = z.object({
jenisInformasi: z.string().min(3, "Jenis Informasi minimal 3 karakter"),
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
tanggal: z.string().min(3, "Tanggal minimal 3 karakter"),
})
type DaftarInformasi = Prisma.DaftarInformasiPublikGetPayload<{
select: {
jenisInformasi: true;
deskripsi: true;
tanggal: true;
};
}>;
const daftarInformasi = proxy({
create: {
form: {} as DaftarInformasi,
loading: false,
async create() {
const cek = templateDaftarInformasi.safeParse(daftarInformasi.create.form);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
daftarInformasi.create.loading = true;
const res = await ApiFetch.api.ppid.daftarinformasipublik["create"].post(daftarInformasi.create.form);
if (res.status === 200) {
daftarInformasi.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
daftarInformasi.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.DaftarInformasiPublikGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.ppid.daftarinformasipublik["find-many"].get();
if (res.status === 200) {
daftarInformasi.findMany.data = res.data?.data ?? [];
}
}
}
});
const stateDaftarInformasiPublik = proxy({
daftarInformasi
})
export default stateDaftarInformasiPublik;

View File

@@ -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;

View File

@@ -0,0 +1,77 @@
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 templateGrafikJenisKelamin = z.object({
laki: z.string().min(2, "Data laki-laki harus diisi"),
perempuan: z.string().min(2, "Data perempuan harus diisi"),
});
type GrafikJenisKelamin = Prisma.GrafikBerdasarkanJenisKelaminGetPayload<{
select: {
laki: true;
perempuan: true;
};
}>;
const defaultForm: GrafikJenisKelamin = {
laki: "",
perempuan: "",
};
const grafikBerdasarkanJenisKelamin = proxy({
create: {
form: defaultForm,
loading: false,
async create() {
const cek = templateGrafikJenisKelamin.safeParse(
grafikBerdasarkanJenisKelamin.create.form
);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
grafikBerdasarkanJenisKelamin.create.loading = true;
const res = await ApiFetch.api.ppid.grafikberdasarkanjeniskelamin[
"create"
].post(grafikBerdasarkanJenisKelamin.create.form);
if (res.status === 200) {
grafikBerdasarkanJenisKelamin.create.form = defaultForm;
grafikBerdasarkanJenisKelamin.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
grafikBerdasarkanJenisKelamin.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.GrafikBerdasarkanJenisKelaminGetPayload<{
omit: { isActive: true };
}>[]
| null,
loading: false,
async load() {
const res = await ApiFetch.api.ppid.grafikberdasarkanjeniskelamin[
"find-many"
].get();
if (res.status === 200) {
grafikBerdasarkanJenisKelamin.findMany.data = res.data?.data ?? [];
}
},
},
});
const stateGrafikBerdasarkanJenisKelamin = proxy({
grafikBerdasarkanJenisKelamin,
});
export default stateGrafikBerdasarkanJenisKelamin;

View File

@@ -0,0 +1,84 @@
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 templateGrafikResponden = z.object({
sangatbaik: z.string().min(1, "Data sangat baik harus diisi"),
baik: z.string().min(1, "Data baik harus diisi"),
kurangbaik: z.string().min(1, "Data kurang baik harus diisi"),
tidakbaik: z.string().min(1, "Data tidak baik harus diisi"),
});
type GrafikResponden = Prisma.GrafikBerdasarkanRespondenGetPayload<{
select: {
sangatbaik: true;
baik: true;
kurangbaik: true;
tidakbaik: true;
};
}>;
const defaultForm: GrafikResponden = {
sangatbaik: "",
baik: "",
kurangbaik: "",
tidakbaik: "",
};
const grafikBerdasarkanResponden = proxy({
create: {
form: defaultForm,
loading: false,
async create() {
const cek = templateGrafikResponden.safeParse(
grafikBerdasarkanResponden.create.form
);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
grafikBerdasarkanResponden.create.loading = true;
const res = await ApiFetch.api.ppid.grafikberdasarkanresponden[
"create"
].post(grafikBerdasarkanResponden.create.form);
if (res.status === 200) {
grafikBerdasarkanResponden.create.form = defaultForm;
grafikBerdasarkanResponden.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
grafikBerdasarkanResponden.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.GrafikBerdasarkanRespondenGetPayload<{
omit: { isActive: true };
}>[]
| null,
loading: false,
async load() {
const res = await ApiFetch.api.ppid.grafikberdasarkanresponden[
"find-many"
].get();
if (res.status === 200) {
grafikBerdasarkanResponden.findMany.data = res.data?.data ?? [];
}
},
},
});
const stateGrafikResponden = proxy({
grafikBerdasarkanResponden,
});
export default stateGrafikResponden;

View File

@@ -0,0 +1,84 @@
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 templateGrafikUmur = z.object({
remaja: z.string().min(2, "Data remaja harus diisi"),
dewasa: z.string().min(2, "Data dewasa harus diisi"),
orangtua: z.string().min(2, "Data orangtua harus diisi"),
lansia: z.string().min(2, "Data lansia harus diisi"),
});
type GrafikUmur = Prisma.GrafikBerdasarkanUmurGetPayload<{
select: {
remaja: true;
dewasa: true;
orangtua: true;
lansia: true;
};
}>;
const defaultForm: GrafikUmur = {
remaja: "",
dewasa: "",
orangtua: "",
lansia: "",
};
const grafikBerdasarkanUmur = proxy({
create: {
form: defaultForm,
loading: false,
async create() {
const cek = templateGrafikUmur.safeParse(
grafikBerdasarkanUmur.create.form
);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
grafikBerdasarkanUmur.create.loading = true;
const res = await ApiFetch.api.ppid.grafikberdasarkanumur[
"create"
].post(grafikBerdasarkanUmur.create.form);
if (res.status === 200) {
grafikBerdasarkanUmur.create.form = defaultForm;
grafikBerdasarkanUmur.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
grafikBerdasarkanUmur.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.GrafikBerdasarkanUmurGetPayload<{
omit: { isActive: true };
}>[]
| null,
loading: false,
async load() {
const res = await ApiFetch.api.ppid.grafikberdasarkanumur[
"find-many"
].get();
if (res.status === 200) {
grafikBerdasarkanUmur.findMany.data = res.data?.data ?? [];
}
},
},
})
const stateGrafikBerdasarkanUmur = proxy({
grafikBerdasarkanUmur,
})
export default stateGrafikBerdasarkanUmur;

View File

@@ -0,0 +1,76 @@
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 templateGrafikHasilKepuasanMasyarakat = z.object({
label: z.string().min(2, "Label harus diisi"),
kepuasan: z.string().min(2, "Kepuasan harus diisi"),
});
type GrafikHasilKepuasanMasyarakat = Prisma.IndeksKepuasanMasyarakatGetPayload<{
select: {
label: true;
kepuasan: true;
};
}>;
const defaultForm: GrafikHasilKepuasanMasyarakat = {
label: "",
kepuasan: "",
};
const grafikHasilKepuasanMasyarakat = proxy({
create: {
form: defaultForm,
loading: false,
async create() {
const cek = templateGrafikHasilKepuasanMasyarakat.safeParse(
grafikHasilKepuasanMasyarakat.create.form
);
if (!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
grafikHasilKepuasanMasyarakat.create.loading = true;
const res = await ApiFetch.api.ppid.grafikhasilkepuasamanmasyarakat["create"].post(
grafikHasilKepuasanMasyarakat.create.form
);
if (res.status === 200) {
grafikHasilKepuasanMasyarakat.create.form = {
label: "",
kepuasan: ""
};
grafikHasilKepuasanMasyarakat.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
grafikHasilKepuasanMasyarakat.create.loading = false;
}
},
},
findMany: {
data: null as
| Prisma.IndeksKepuasanMasyarakatGetPayload<{ omit: { isActive: true } }>[]
| null,
async load() {
const res = await ApiFetch.api.ppid.grafikhasilkepuasamanmasyarakat["find-many"].get();
if (res.status === 200) {
grafikHasilKepuasanMasyarakat.findMany.data = res.data?.data ?? [];
}
}
}
});
const stateGrafikHasilKepuasanMasyarakat = proxy({
grafikHasilKepuasanMasyarakat,
});
export default stateGrafikHasilKepuasanMasyarakat;

View File

@@ -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";
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 ?? [];
}
}
}
})
console.log(caraMemperolehSalinanInformasi)
type PermohonanInformasiPublikForm = Prisma.PermohonanInformasiPublikGetPayload<{
select: {
name: true;
nik: true;
notelp: true;
alamat: true;
email: true;
jenisInformasiDimintaId: true;
caraMemperolehInformasiId: true;
caraMemperolehSalinanInformasiId: true;
};
}>;
const statepermohonanInformasiPublik = proxy({
create: {
form: {} as PermohonanInformasiPublikForm,
loading: false,
async create(){
const cek = templateForm.safeParse(statepermohonanInformasiPublik.create.form);
if(!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
statepermohonanInformasiPublik.create.loading = true;
const res = await ApiFetch.api.ppid.permohonaninformasipublik["create"].post(statepermohonanInformasiPublik.create.form);
if (res.status === 200) {
statepermohonanInformasiPublik.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
statepermohonanInformasiPublik.create.loading = false;
}
}
},
findMany: {
data: null as
| Prisma.PermohonanInformasiPublikGetPayload<{ include: {
caraMemperolehSalinanInformasi: true,
jenisInformasiDiminta: true,
caraMemperolehInformasi: true,
} }>[]
| null,
async load() {
const res = await ApiFetch.api.ppid.permohonaninformasipublik["find-many"].get();
if (res.status === 200) {
statepermohonanInformasiPublik.findMany.data = res.data?.data ?? [];
}
}
}
})
const statepermohonanInformasiPublikForm = proxy({
statepermohonanInformasiPublik,
jenisInformasiDiminta,
caraMemperolehInformasi,
caraMemperolehSalinanInformasi,
})
export default statepermohonanInformasiPublikForm;

View File

@@ -0,0 +1,64 @@
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 permohonanKeberatanInformasi = proxy({
create: {
form: {} as PermohonanKeberatanInformasiForm,
loading: false,
async create(){
const cek = templateForm.safeParse(permohonanKeberatanInformasi.create.form);
if(!cek.success) {
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
return toast.error(err);
}
try {
permohonanKeberatanInformasi.create.loading = true;
const res = await ApiFetch.api.ppid.permohonankeberataninformasipublik["create"].post(permohonanKeberatanInformasi.create.form);
if (res.status === 200) {
permohonanKeberatanInformasi.findMany.load();
return toast.success("success create");
}
return toast.error("failed create");
} catch (error) {
console.log((error as Error).message);
} finally {
permohonanKeberatanInformasi.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) {
permohonanKeberatanInformasi.findMany.data = res.data?.data ?? [];
}
}
}
});
export default permohonanKeberatanInformasi;

View File

@@ -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;

View File

@@ -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;

View File

@@ -0,0 +1,93 @@
'use client'
import colors from '@/con/colors';
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';
const content =
'<h2 style="text-align: center;">Welcome to Mantine rich text editor</h2><p><code>RichTextEditor</code> component focuses on usability and is designed to be as simple as possible to bring a familiar editing experience to regular users. <code>RichTextEditor</code> is based on <a href="https://tiptap.dev/" rel="noopener noreferrer" target="_blank">Tiptap.dev</a> and supports all of its features:</p><ul><li>General text formatting: <strong>bold</strong>, <em>italic</em>, <u>underline</u>, <s>strike-through</s> </li><li>Headings (h1-h6)</li><li>Sub and super scripts (<sup>&lt;sup /&gt;</sup> and <sub>&lt;sub /&gt;</sub> tags)</li><li>Ordered and bullet lists</li><li>Text align&nbsp;</li><li>And all <a href="https://tiptap.dev/extensions" target="_blank" rel="noopener noreferrer">other extensions</a></li></ul>';
export function DesaEditor({showSubmit = true} : {
showSubmit: boolean
}) {
const editor = useEditor({
extensions: [
StarterKit,
Underline,
Link,
Superscript,
SubScript,
Highlight,
TextAlign.configure({ types: ['heading', 'paragraph'] }),
],
immediatelyRender: false,
content,
});
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
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
)}
</Stack>
);
}

View File

@@ -0,0 +1,95 @@
'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';
function DesaEditorText({ 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>
);
}
export default DesaEditorText;

View File

@@ -0,0 +1,91 @@
'use client'
import { RichTextEditor, Link } from '@mantine/tiptap';
import { useEditor } from '@tiptap/react';
import Highlight from '@tiptap/extension-highlight';
import StarterKit from '@tiptap/starter-kit';
import Underline from '@tiptap/extension-underline';
import TextAlign from '@tiptap/extension-text-align';
import Superscript from '@tiptap/extension-superscript';
import SubScript from '@tiptap/extension-subscript';
import { Button, Stack } from '@mantine/core';
const content =
'<h2 style="text-align: center;">Welcome to Mantine rich text editor</h2><p><code>RichTextEditor</code> component focuses on usability and is designed to be as simple as possible to bring a familiar editing experience to regular users. <code>RichTextEditor</code> is based on <a href="https://tiptap.dev/" rel="noopener noreferrer" target="_blank">Tiptap.dev</a> and supports all of its features:</p><ul><li>General text formatting: <strong>bold</strong>, <em>italic</em>, <u>underline</u>, <s>strike-through</s> </li><li>Headings (h1-h6)</li><li>Sub and super scripts (<sup>&lt;sup /&gt;</sup> and <sub>&lt;sub /&gt;</sub> tags)</li><li>Ordered and bullet lists</li><li>Text align&nbsp;</li><li>And all <a href="https://tiptap.dev/extensions" target="_blank" rel="noopener noreferrer">other extensions</a></li></ul>';
export function BeritaEditor({ onSubmit }: { onSubmit: (val: string) => void }) {
const editor = useEditor({
extensions: [
StarterKit,
Underline,
Link,
Superscript,
SubScript,
Highlight,
TextAlign.configure({ types: ['heading', 'paragraph'] }),
],
content,
immediatelyRender: false
});
if (!editor) {
return null;
}
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>
<Button onClick={() => {
if (!editor) return
onSubmit(editor?.getHTML())
}}>Submit</Button>
</Stack>
);
}

View File

@@ -0,0 +1,88 @@
'use client'
import { Center, Group, Select, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { Prisma } from '@prisma/client';
import { IconImageInPicture } from '@tabler/icons-react';
import { useProxy } from 'valtio/utils';
import stateDashboardBerita from '../../_state/desa/berita';
import { BeritaEditor } from './_com/BeritaEditor';
function Page() {
return (
<Stack>
<SimpleGrid cols={{base: 1, md: 2}}>
<BeritaCreate />
<BeritaList />
</SimpleGrid>
</Stack>
);
}
function BeritaList() {
const beritaState = useProxy(stateDashboardBerita)
useShallowEffect(() => {
beritaState.berita.findMany.load()
}, [])
if (!beritaState.berita.findMany.data) return <Stack>
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
</Stack>
return <Stack>
<Text>News List</Text>
{beritaState.berita.findMany.data?.map((item) => (
<Text key={item.id}>{item.judul}</Text>
))}
</Stack>
}
function BeritaCreate() {
const beritaState = useProxy(stateDashboardBerita)
return <Stack gap={"md"}>
<Text>Create Some News</Text>
<SelectCategory onChange={(val) => {
beritaState.berita.create.form.katagoryBeritaId = val.id
}} />
<TextInput onChange={(val) => {
beritaState.berita.create.form.judul = val.target.value
}} label={"Judul"} placeholder='masukkan judul' />
<TextInput onChange={(val) => {
beritaState.berita.create.form.deskripsi = val.target.value
}} label={"Deskripsi"} placeholder='masukkan deskripsi' />
<Center w={200} h={200} bg={"gray"}>
<IconImageInPicture />
</Center>
<BeritaEditor onSubmit={(val) => {
beritaState.berita.create.form.content = val
beritaState.berita.create.create()
}} />
</Stack>
}
function SelectCategory({ onChange }: {
onChange: (value: Prisma.KatagoryBeritaGetPayload<{
select: {
name: true,
id: true
}
}>) => void
}) {
const beritaState = useProxy(stateDashboardBerita)
useShallowEffect(() => {
beritaState.category.findMany.load()
}, [])
if (!beritaState.category.findMany.data) return <Skeleton h={40} />
return <Group>
<Select placeholder='pilih katagori' label={"select katagori"} data={beritaState.category.findMany.data.map((item) => ({
value: item.id,
label: item.name
}))} onChange={(v) => {
const data = beritaState.category.findMany.data?.find((item) => item.id === v)
if (!data) return
onChange(data)
}} />
</Group>
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Gallery
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Layanan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Penghargaan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,89 @@
'use client'
import { Group, Select, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
import React from 'react';
import { useProxy } from 'valtio/utils';
import stateDesaPengumuman from '../../_state/desa/pengumuman';
import { useShallowEffect } from '@mantine/hooks';
import { Prisma } from '@prisma/client';
import { BeritaEditor } from '../berita/_com/BeritaEditor';
function Page() {
return (
<Stack>
<SimpleGrid cols={{
base: 1, md: 2
}}>
<PengumumanList />
<PengumumanCreate />
</SimpleGrid>
</Stack>
);
}
function PengumumanList() {
const pengumumanState = useProxy(stateDesaPengumuman)
useShallowEffect(() => {
pengumumanState.pengumuman.findMany.load()
}, [])
if (!pengumumanState.pengumuman.findMany.data) return <Stack>
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
</Stack>
return <Stack>
<Text>Announcement List</Text>
{pengumumanState.pengumuman.findMany.data?.map((item) => (
<Text key={item.id}>{item.judul}</Text>
))}
</Stack>;
}
function PengumumanCreate() {
const pengumumanState = useProxy(stateDesaPengumuman)
return <Stack gap={"md"}>
<Text>Create Some Announcement</Text>
<SelectCategory onChange={(val) => {
pengumumanState.pengumuman.create.form.categoryPengumumanId = val.id
}} />
<TextInput onChange={(val) => {
pengumumanState.pengumuman.create.form.judul = val.target.value
}} label={"Judul"} placeholder='masukkan judul' />
<TextInput onChange={(val) => {
pengumumanState.pengumuman.create.form.deskripsi = val.target.value
}} label={"Deskripsi"} placeholder='masukkan deskripsi' />
<BeritaEditor onSubmit={(val) => {
pengumumanState.pengumuman.create.form.content = val
pengumumanState.pengumuman.create.create()
}} />
</Stack>
}
function SelectCategory({ onChange }: {
onChange: (value: Prisma.CategoryPengumumanGetPayload<{
select: {
name: true,
id: true
}
}>) => void
}) {
const pengumumanState = useProxy(stateDesaPengumuman)
useShallowEffect(() => {
pengumumanState.category.findMany.load()
}, [])
if (!pengumumanState.category.findMany.data) return <Skeleton h={40} />
return <Group>
{/* {JSON.stringify(pengumumanState.category.findMany.data)} */}
<Select placeholder='pilih kategori' label={"select katagori"} data={pengumumanState.category.findMany.data.map((item) => ({
value: item.id,
label: item.name
}))} onChange={(v) => {
const data = pengumumanState.category.findMany.data?.find((item) => item.id === v)
if (!data) return
onChange(data)
}}
/>
</Group>
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
Potensi
</div>
);
}
export default Page;

View File

@@ -0,0 +1,53 @@
import colors from '@/con/colors';
import { Stack, Title, Tabs, TabsList, TabsTab, TabsPanel } from '@mantine/core';
import React from 'react';
import SejarahDesa from './ui/sejarah_desa/page';
import VisiMisiDesa from './ui/visi_misi_desa/page';
import LambangDesa from './ui/lambang_desa/page';
import MaskotDesa from './ui/maskot_desa/page';
import ProfilePerbekel from './ui/profile_perbekel/page';
function Page() {
return (
<Stack >
<Title order={3}>Profile Desa</Title>
<Tabs color={colors['blue-button']} variant='pills' defaultValue={"Sejarah Desa"}>
<TabsList p={"xs"} bg={"#BBC8E7FF"}>
<TabsTab value="Sejarah Desa">
Sejarah Desa
</TabsTab>
<TabsTab value="Visi Misi Desa">
Visi Misi Desa
</TabsTab>
<TabsTab value="Lambang Desa">
Lambang Desa
</TabsTab>
<TabsTab value="Maskot Desa">
Maskot Desa
</TabsTab>
<TabsTab value="Profile Perbekel">
Profile Perbekel
</TabsTab>
</TabsList>
<TabsPanel value="Sejarah Desa">
<SejarahDesa/>
</TabsPanel>
<TabsPanel value="Visi Misi Desa">
<VisiMisiDesa/>
</TabsPanel>
<TabsPanel value="Lambang Desa">
<LambangDesa/>
</TabsPanel>
<TabsPanel value="Maskot Desa">
<MaskotDesa/>
</TabsPanel>
<TabsPanel value="Profile Perbekel">
<ProfilePerbekel/>
</TabsPanel>
</Tabs>
</Stack>
);
}
export default Page;

View File

@@ -0,0 +1,39 @@
import colors from '@/con/colors';
import { Box, SimpleGrid, Paper, Stack, Title, Group, Button, Text } from '@mantine/core';
import React from 'react';
import { DesaEditor } from '../../../_com/desaEditor';
function LambangDesa() {
return (
<Box py={10}>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Lambang Desa</Title>
<Text fw={"bold"}>Deskripsi Lambang Desa</Text>
<DesaEditor showSubmit={false} />
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Lambang Desa</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
</Box>
);
}
export default LambangDesa;

View File

@@ -0,0 +1,39 @@
import colors from '@/con/colors';
import { Box, SimpleGrid, Paper, Stack, Title, Group, Button, Text } from '@mantine/core';
import React from 'react';
import { DesaEditor } from '../../../_com/desaEditor';
function MaskotDesa() {
return (
<Box py={10}>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Maskot Desa</Title>
<Text fw={"bold"}>Deskripsi Maskot Desa</Text>
<DesaEditor showSubmit={false} />
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Maskot Desa</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
</Box>
);
}
export default MaskotDesa;

View File

@@ -0,0 +1,49 @@
import colors from '@/con/colors';
import { Box, SimpleGrid, Paper, Stack, Title, Group, Button, TextInput, Text } from '@mantine/core';
import React from 'react';
import { DesaEditor } from '../../../_com/desaEditor';
function ProfilePerbekel() {
return (
<Box py={10}>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Profil Perbekel</Title>
<TextInput
label="Nama Perbekel"
placeholder="masukkan nama perbekel"
/>
<Text fz={"sm"} fw={"bold"}>Biodata</Text>
<DesaEditor showSubmit={false} />
<Text fz={"sm"} fw={"bold"}>Pengalaman</Text>
<DesaEditor showSubmit={false} />
<Text fz={"sm"} fw={"bold"}>Pengalaman Organisasi</Text>
<DesaEditor showSubmit={false} />
<Text fz={"sm"} fw={"bold"}>Program Unggulan</Text>
<DesaEditor showSubmit={false} />
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Profil Perbekel</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
</Box>
);
}
export default ProfilePerbekel;

View File

@@ -0,0 +1,38 @@
import colors from '@/con/colors';
import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
import { DesaEditor } from '../../../_com/desaEditor';
function SejarahDesa() {
return (
<Box py={10}>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Sejarah Desa</Title>
<Text fw={"bold"}>Deskripsi Sejarah Desa</Text>
<DesaEditor showSubmit={false}/>
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Sejarah Desa</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
</Box>
);
}
export default SejarahDesa;

View File

@@ -0,0 +1,64 @@
import colors from '@/con/colors';
import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
import { DesaEditor } from '../../../_com/desaEditor';
function VisiMisiDesa() {
return (
<Box py={10}>
<SimpleGrid cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Visi Desa</Title>
<Text fw={"bold"}>Deskripsi Visi Desa</Text>
<DesaEditor showSubmit={false} />
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Visi Desa</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
<SimpleGrid py={30} cols={{ base: 1, md: 2 }}>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>Misi Desa</Title>
<Text fw={"bold"}>Deskripsi Misi Desa</Text>
<DesaEditor showSubmit={false}/>
<Group>
<Button
mt={10}
bg={colors['blue-button']}
>
Submit
</Button>
</Group>
</Stack>
</Paper>
</Box>
<Box>
<Paper bg={colors['white-1']} p={'md'}>
<Stack>
<Title order={3}>List Misi Desa</Title>
</Stack>
</Paper>
</Box>
</SimpleGrid>
</Box>
);
}
export default VisiMisiDesa;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
PADesa-pendapatan-asli-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
demografi-pekerjaan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
jumlah-penduduk-miskin-2024-2025
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
jumlah-penduduk-usia-kerja-yang-menganggur
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
jumlah-pengangguran-2024-2025
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
lowongan-kerja-lokal
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
pasar-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
program-kemiskinan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
sektor-unggulan-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
struktur-organisasi-dan-sk-pengurus-bumdesa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
ajukan-ide-inovatif
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
desa-digital-smart-village
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
info-teknologi-tepat-guna
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
kolaborasi-inovasi
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
layanan-online-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
program-kreatif-desa
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
keamanan-lingkungan-pecalang-patwal
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
kontak-darurat
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
laporan-publik
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
pencegahan-kriminalitas
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
polsek-terdekat
</div>
);
}
export default Page;

View File

@@ -0,0 +1,11 @@
import React from 'react';
function Page() {
return (
<div>
tips-keamanan
</div>
);
}
export default Page;

View File

@@ -0,0 +1,80 @@
'use client'
import { RichTextEditor, Link } from '@mantine/tiptap';
import { useEditor } from '@tiptap/react';
import Highlight from '@tiptap/extension-highlight';
import StarterKit from '@tiptap/starter-kit';
import Underline from '@tiptap/extension-underline';
import TextAlign from '@tiptap/extension-text-align';
import Superscript from '@tiptap/extension-superscript';
import SubScript from '@tiptap/extension-subscript';
const content =
'<h2 style="text-align: center;">Welcome to Mantine rich text editor</h2><p><code>RichTextEditor</code> component focuses on usability and is designed to be as simple as possible to bring a familiar editing experience to regular users. <code>RichTextEditor</code> is based on <a href="https://tiptap.dev/" rel="noopener noreferrer" target="_blank">Tiptap.dev</a> and supports all of its features:</p><ul><li>General text formatting: <strong>bold</strong>, <em>italic</em>, <u>underline</u>, <s>strike-through</s> </li><li>Headings (h1-h6)</li><li>Sub and super scripts (<sup>&lt;sup /&gt;</sup> and <sub>&lt;sub /&gt;</sub> tags)</li><li>Ordered and bullet lists</li><li>Text align&nbsp;</li><li>And all <a href="https://tiptap.dev/extensions" target="_blank" rel="noopener noreferrer">other extensions</a></li></ul>';
function TextEditor() {
const editor = useEditor({
extensions: [
StarterKit,
Underline,
Link,
Superscript,
SubScript,
Highlight,
TextAlign.configure({ types: ['heading', 'paragraph'] }),
],
immediatelyRender: false,
content,
});
return (
<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>
);
}
export default TextEditor

View File

@@ -0,0 +1,94 @@
'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';
const content =
'<h2 style="text-align: center;">Welcome to Mantine rich text editor</h2><p><code>RichTextEditor</code> component focuses on usability and is designed to be as simple as possible to bring a familiar editing experience to regular users. <code>RichTextEditor</code> is based on <a href="https://tiptap.dev/" rel="noopener noreferrer" target="_blank">Tiptap.dev</a> and supports all of its features:</p><ul><li>General text formatting: <strong>bold</strong>, <em>italic</em>, <u>underline</u>, <s>strike-through</s> </li><li>Headings (h1-h6)</li><li>Sub and super scripts (<sup>&lt;sup /&gt;</sup> and <sub>&lt;sub /&gt;</sub> tags)</li><li>Ordered and bullet lists</li><li>Text align&nbsp;</li><li>And all <a href="https://tiptap.dev/extensions" target="_blank" rel="noopener noreferrer">other extensions</a></li></ul>';
export function KesehatanEditor({ onSubmit, onChange, showSubmit = true }: {
onSubmit?: (val: string) => void,
onChange: (val: string) => void,
showSubmit?: boolean }) {
const editor = useEditor({
extensions: [
StarterKit,
Underline,
Link,
Superscript,
SubScript,
Highlight,
TextAlign.configure({ types: ['heading', 'paragraph'] }),
],
immediatelyRender: false,
content,
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>
);
}

View File

@@ -0,0 +1,23 @@
'use client'
import { Box, Text } from '@mantine/core';
import React from 'react';
import { KesehatanEditor } from '../../../_com/kesehatanEditor';
import { useProxy } from 'valtio/utils';
import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
function DoctorSignUI() {
const doctorSign = useProxy(stateArtikelKesehatan.doctorSign)
return (
<Box>
<Text fw={"bold"}>Kapan Harus ke Dokter</Text>
<KesehatanEditor
showSubmit={false}
onChange={(val) => {
doctorSign.create.form.content = val
}}
/>
</Box>
);
}
export default DoctorSignUI;

View File

@@ -0,0 +1,29 @@
'use client'
import { Box, Text, TextInput } from '@mantine/core';
import React from 'react';
import { useProxy } from 'valtio/utils';
import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
import { KesehatanEditor } from '../../../_com/kesehatanEditor';
function FirstAidUI() {
const firstAidState = useProxy(stateArtikelKesehatan.firstAid)
return (
<Box>
<TextInput
label={<Text fw={"bold"}>Title Pertolongan Pertama</Text>}
placeholder="Masukkan title"
onChange={(val) => {
firstAidState.create.form.title = val.target.value
}}
/>
<KesehatanEditor
showSubmit={false}
onChange={(val) => {
firstAidState.create.form.content = val
}}
/>
</Box>
);
}
export default FirstAidUI;

View File

@@ -0,0 +1,23 @@
'use client'
import { Box, Text } from '@mantine/core';
import React from 'react';
import { useProxy } from 'valtio/utils';
import { KesehatanEditor } from '../../../_com/kesehatanEditor';
import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
function IntoductionUI() {
const introduction = useProxy(stateArtikelKesehatan.introduction)
return (
<Box py={10}>
<Text fw={"bold"}>Pendahuluan</Text>
<KesehatanEditor
showSubmit={false}
onChange={(val) => {
introduction.create.form.content = val;
}}
/>
</Box>
);
}
export default IntoductionUI;

View File

@@ -0,0 +1,35 @@
'use client'
import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
import { Box, Text, TextInput } from '@mantine/core';
import { useProxy } from 'valtio/utils';
function MythFactUI() {
const mythFact = useProxy(stateArtikelKesehatan.mythFact)
return (
<Box py={10}>
<TextInput
label={<Text fw={"bold"}>Title Pertolongan Pertama Penyakit</Text>}
placeholder="Masukkan title"
onChange={(val) => {
mythFact.create.form.title = val.target.value
}}
/>
<TextInput
label={<Text fw={"bold"}>Mitos</Text>}
placeholder="Masukkan mitos"
onChange={(val) => {
mythFact.create.form.mitos = val.target.value
}}
/>
<TextInput
label={<Text fw={"bold"}>Fakta</Text>}
placeholder="Masukkan fakta"
onChange={(val) => {
mythFact.create.form.fakta = val.target.value
}}
/>
</Box>
);
}
export default MythFactUI;

View File

@@ -0,0 +1,149 @@
'use client'
import { Box, Button, Center, SimpleGrid, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
import IntoductionUI from './introduction/page';
import SymptomUI from './symptom/page';
import PreventionUI from './prevention/page';
import MythFactUI from './mythVsfact/page';
import DoctorSignUI from './doctor_sign/page';
import { useProxy } from 'valtio/utils';
import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
import FirstAidUI from './first_aid/page';
import { useShallowEffect } from '@mantine/hooks';
import colors from '@/con/colors';
function ArtikelKesehatan() {
const state = useProxy(stateArtikelKesehatan)
const submitAllForms = () => {
if (state.introduction.create.form.content) {
state.introduction.create.create()
}
if (state.symptom.create.form.title && state.symptom.create.form.content) {
state.symptom.create.create()
}
if (state.prevention.create.form.title && state.prevention.create.form.content) {
state.prevention.create.create()
}
if (state.firstAid.create.form.title && state.firstAid.create.form.content) {
state.firstAid.create.create()
}
if (state.mythFact.create.form.title && state.mythFact.create.form.mitos && state.mythFact.create.form.fakta) {
state.mythFact.create.create()
}
if (state.doctorSign.create.form.content) {
state.doctorSign.create.create()
}
}
return (
<Stack py={10}>
<SimpleGrid cols={{
base: 1, md: 2
}}>
<Box >
<Title order={3}>Artikel Kesehatan</Title>
<IntoductionUI />
<SymptomUI />
<PreventionUI />
<FirstAidUI />
<MythFactUI />
<DoctorSignUI />
<Button mt={10} onClick={submitAllForms}>Submit</Button>
</Box>
<Box>
<Title order={3}>List Artikel Kesehatan</Title>
<AllList />
</Box>
</SimpleGrid>
</Stack>
);
}
function AllList() {
const listState = useProxy(stateArtikelKesehatan)
useShallowEffect(() => {
listState.introduction.findMany.load();
listState.symptom.findMany.load();
listState.prevention.findMany.load();
listState.firstAid.findMany.load();
listState.mythFact.findMany.load();
listState.doctorSign.findMany.load();
}, [])
if (!listState.introduction.findMany.data
|| !listState.symptom.findMany.data
|| !listState.prevention.findMany.data
|| !listState.firstAid.findMany.data
|| !listState.mythFact.findMany.data
|| !listState.doctorSign.findMany.data
) return <Stack>
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
</Stack>
return <Stack>
<Title order={4}>Intoduction</Title>
{listState.introduction.findMany.data?.map((item) => (
<Box key={item.id}>
<Text dangerouslySetInnerHTML={{ __html: item.content }}></Text>
</Box>
))}
{/* Symptom */}
{listState.symptom.findMany.data?.map((item) => (
<Box key={item.id}>
<Title order={4}>{item.title}</Title>
<Text dangerouslySetInnerHTML={{ __html: item.content }}></Text>
</Box>
))}
{/* Prevention */}
{listState.prevention.findMany.data?.map((item) => (
<Box key={item.id}>
<Title order={4}>{item.title}</Title>
<Text dangerouslySetInnerHTML={{ __html: item.content }}></Text>
</Box>
))}
{/* First Aid */}
{listState.firstAid.findMany.data?.map((item) => (
<Box key={item.id}>
<Title order={4}>{item.title}</Title>
<Text dangerouslySetInnerHTML={{ __html: item.content }}></Text>
</Box>
))}
{/* Myth Fact */}
{listState.mythFact.findMany.data?.map((item) => (
<Box key={item.id}>
<Title order={4}>{item.title}</Title>
<Table
striped
highlightOnHover
withTableBorder
withColumnBorders
bg={colors['white-1']}
>
<TableThead >
<TableTr >
<TableTh >
<Center>Mitos</Center>
</TableTh>
<TableTh >
<Center>Fakta</Center>
</TableTh>
</TableTr>
</TableThead>
<TableTbody >
<TableTr>
<TableTd ta="center">{item.mitos}</TableTd>
<TableTd ta="center">{item.fakta}</TableTd>
</TableTr>
</TableTbody>
</Table>
</Box>
))}
{/* Doctor Sign */}
<Title order={4}>Kapan Harus Ke Dokter?</Title>
{listState.doctorSign.findMany.data?.map((item) => (
<Box key={item.id}>
<Text dangerouslySetInnerHTML={{ __html: item.content }}/>
</Box>
))}
</Stack>
}
export default ArtikelKesehatan;

View File

@@ -0,0 +1,30 @@
'use client'
import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
import { Box, Text, TextInput } from '@mantine/core';
import React from 'react';
import { useProxy } from 'valtio/utils';
import { KesehatanEditor } from '../../../_com/kesehatanEditor';
function PreventionUI() {
const preventionState = useProxy(stateArtikelKesehatan.prevention)
return (
<Box py={10}>
<TextInput
mb={10}
label={<Text fw={"bold"}>Title Pencegahan Penyakit</Text>}
placeholder="Masukkan title"
onChange={(val) => {
preventionState.create.form.title = val.target.value
}}
/>
<KesehatanEditor
showSubmit={false}
onChange={(val) => {
preventionState.create.form.content = val
}}
/>
</Box>
);
}
export default PreventionUI;

View File

@@ -0,0 +1,29 @@
'use client'
import stateArtikelKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
import { Box, Text, TextInput } from '@mantine/core';
import { useProxy } from 'valtio/utils';
import { KesehatanEditor } from '../../../_com/kesehatanEditor';
function SymptomUI() {
const symptomState = useProxy(stateArtikelKesehatan.symptom)
return (
<Box py={10}>
<TextInput
mb={10}
label={<Text fw={"bold"}>Title Gejala Penyakit</Text>}
placeholder='masukkan title'
onChange={(val) => {
symptomState.create.form.title = val.target.value
}}
/>
<KesehatanEditor
showSubmit={false}
onChange={(val) => {
symptomState.create.form.content = val
}}
/>
</Box>
);
}
export default SymptomUI;

View File

@@ -0,0 +1,89 @@
import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import colors from '@/con/colors';
import { Center, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import _ from 'lodash';
import { useProxy } from 'valtio/utils';
function DokterdanTenagaMedisList() {
const kesehatanState = useProxy(stateFasilitasKesehatan.dokterdantenagamedis);
useShallowEffect(() => {
kesehatanState.findMany.load();
}, []);
// Penanganan kasus ketika tidak ada data
if (_.isEmpty(kesehatanState.findMany.data)) {
return (
<Stack>
<Table
striped
highlightOnHover
withTableBorder
withColumnBorders
bg={colors['white-1']}
>
<TableThead>
<TableTr>
<TableTh>
<Center>Nama</Center>
</TableTh>
<TableTh>
<Center>Specialist</Center>
</TableTh>
<TableTh >
<Center>Jadwal</Center>
</TableTh>
</TableTr>
</TableThead>
<TableTbody >
<TableTr >
<TableTd colSpan={3}>
<Center>
<Text>Tidak ada data</Text>
</Center>
</TableTd>
</TableTr>
</TableTbody>
</Table>
</Stack>
);
}
return (
<Stack>
<Table
striped
highlightOnHover
withTableBorder
withColumnBorders
bg={colors['white-1']}
>
<TableThead >
<TableTr >
<TableTh >
<Center>Nama</Center>
</TableTh>
<TableTh >
<Center>Specialist</Center>
</TableTh>
<TableTh >
<Center>Jadwal</Center>
</TableTh>
</TableTr>
</TableThead>
<TableTbody >
{kesehatanState.findMany.data?.map((item) => (
<TableTr key={item.id}>
<TableTd ta="center">{item.name}</TableTd>
<TableTd ta="center">Specialist {item.specialist}</TableTd>
<TableTd ta="center">{item.jadwal}</TableTd>
</TableTr>
))}
</TableTbody>
</Table>
</Stack>
);
}
export default DokterdanTenagaMedisList;

View File

@@ -0,0 +1,36 @@
import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import { Box, Text, TextInput } from '@mantine/core';
import { useProxy } from 'valtio/utils';
function DokterDanTenagaMedis() {
const dokterdantenagamedisState = useProxy(stateFasilitasKesehatan.dokterdantenagamedis)
return (
<Box>
<Text fw={"bold"}>Dokter & Tenaga Medis</Text>
<TextInput
label="Nama Dokter"
placeholder='masukkan nama dokter'
onChange={(val) => {
dokterdantenagamedisState.create.form.name = val.target.value
}}
/>
<TextInput
label="Specialist"
placeholder='masukkan specialist'
onChange={(val) => {
dokterdantenagamedisState.create.form.specialist = val.target.value
}}
/>
<TextInput
mb={10}
label="Jadwal"
placeholder='masukkan jadwal'
onChange={(val) => {
dokterdantenagamedisState.create.form.jadwal = val.target.value
}}
/>
</Box>
);
}
export default DokterDanTenagaMedis;

View File

@@ -0,0 +1,21 @@
import { Box, Stack, Text } from '@mantine/core';
import React from 'react';
import { useProxy } from 'valtio/utils';
import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import { useShallowEffect } from '@mantine/hooks';
function FasilitasPendukungList() {
const fasilitaspendukungState = useProxy(stateFasilitasKesehatan.fasilitaspendukung)
useShallowEffect(() => {
fasilitaspendukungState.findMany.load()
}, [])
return <Stack>
{fasilitaspendukungState.findMany.data?.map((item) => (
<Box key={item.id}>
<Text dangerouslySetInnerHTML={{__html: item.content}}/>
</Box>
))}
</Stack>
}
export default FasilitasPendukungList;

View File

@@ -0,0 +1,18 @@
import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import { Box, Text } from '@mantine/core';
import { useProxy } from 'valtio/utils';
import { KesehatanEditor } from '../../../_com/kesehatanEditor';
function FasilitasPendukung() {
const fasilitaspendukungState = useProxy(stateFasilitasKesehatan.fasilitaspendukung)
return <Box>
<Text fw={"bold"}>Fasilitas Pendukung</Text>
<KesehatanEditor
showSubmit={false}
onChange={(val) => {
fasilitaspendukungState.create.form.content = val;
}} />
</Box>
}
export default FasilitasPendukung;

View File

@@ -0,0 +1,35 @@
'use client'
import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import { Box, Text, TextInput } from '@mantine/core';
import { useProxy } from 'valtio/utils';
function InformasiUmum() {
const infromasiState = useProxy(stateFasilitasKesehatan.informasiumum)
return<Box>
<Text fw={"bold"}>Informasi Umum</Text>
<TextInput
label="Fasilitas"
placeholder='masukkan nama fasilitas kesehatan'
onChange={(val) => {
infromasiState.create.form.fasilitas = val.target.value
}}
/>
<TextInput
label="Alamat"
placeholder='masukkan alamat'
onChange={(val) => {
infromasiState.create.form.alamat = val.target.value
}}
/>
<TextInput
mb={10}
label="Jam Operasional"
placeholder='masukkan jam operasional'
onChange={(val) => {
infromasiState.create.form.jamOperasional = val.target.value
}}
/>
</Box>
}
export default InformasiUmum;

View File

@@ -0,0 +1,20 @@
'use client'
import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import { Box, Text } from '@mantine/core';
import { useProxy } from 'valtio/utils';
import { KesehatanEditor } from '../../../_com/kesehatanEditor';
function LayananUnggulan() {
const informasiumumState = useProxy(stateFasilitasKesehatan.layananunggulan)
return <Box>
<Text fw={"bold"}>Layanan Unggulan</Text>
<KesehatanEditor
showSubmit={false}
onChange={(val) => {
informasiumumState.create.form.content = val;
}} />
</Box>
;
}
export default LayananUnggulan;

View File

@@ -0,0 +1,241 @@
"use client"
import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import colors from '@/con/colors';
import { Box, Button, Center, SimpleGrid, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { useProxy } from 'valtio/utils';
import DokterDanTenagaMedis from './dokterdantenagamedis/page';
import FasilitasPendukung from './fasilitas_pendukung/page';
import InformasiUmum from './informasi_umum/page';
import LayananUnggulan from './layanan_unggulan/page';
import ProsedurPendaftaran from './prosedurpendaftaran/page';
import TarifDanLayanan from './tarifdanlayanan/page';
function FasilitasKesehatan() {
const allState = useProxy(stateFasilitasKesehatan)
const submitAllForms = () => {
if (allState.informasiumum.create.form.fasilitas &&
allState.informasiumum.create.form.alamat &&
allState.informasiumum.create.form.jamOperasional) {
allState.informasiumum.create.create()
}
if (allState.layananunggulan.create.form.content) {
allState.layananunggulan.create.create();
}
if (allState.dokterdantenagamedis.create.form.name &&
allState.dokterdantenagamedis.create.form.specialist &&
allState.dokterdantenagamedis.create.form.jadwal) {
allState.dokterdantenagamedis.create.create()
}
if (allState.fasilitaspendukung.create.form.content) {
allState.fasilitaspendukung.create.create();
}
if (allState.tarifdanlayanan.create.form.tarif &&
allState.tarifdanlayanan.create.form.layanan) {
allState.tarifdanlayanan.create.create()
}
if (allState.prosedurpendaftaran.create.form.content) {
allState.prosedurpendaftaran.create.create();
}
// refreshListData();
// resetAllForms();
}
// const refreshListData = () => {
// allState.informasiumum.findMany.load();
// allState.layananunggulan.findMany.load();
// allState.dokterdantenagamedis.findMany.load();
// allState.fasilitaspendukung.findMany.load();
// allState.tarifdanlayanan.findMany.load();
// allState.prosedurpendaftaran.findMany.load();
// }
// const resetAllForms = () => {
// allState.informasiumum.create.form = {
// fasilitas: '',
// alamat: '',
// jamOperasional: ''
// };
// allState.layananunggulan.create.form = {
// content: ''
// };
// allState.dokterdantenagamedis.create.form = {
// name: '',
// specialist: '',
// jadwal: ''
// };
// allState.fasilitaspendukung.create.form = {
// content: ''
// };
// allState.tarifdanlayanan.create.form = {
// tarif: '',
// layanan: ''
// };
// allState.prosedurpendaftaran.create.form = {
// content: ''
// };
// }
return (
<Stack py={10}>
<SimpleGrid cols={{
base: 1, md: 2
}}>
<Box>
<Stack gap={'xs'}>
<Title order={3}>Fasilitas Kesehatan</Title>
{/* Informasi Umum */}
<InformasiUmum />
{/* Layanan Unggulan */}
<LayananUnggulan />
{/* Dokter & Tenaga Medis */}
<DokterDanTenagaMedis />
{/* Fasilitas Pendukung */}
<FasilitasPendukung />
{/* Tarif & Layanan */}
<TarifDanLayanan />
{/* Prosedur Pendaftaran */}
<ProsedurPendaftaran />
<Button onClick={submitAllForms}>Submit</Button>
</Stack>
</Box>
<Box>
<Stack gap={"xs"}>
<Title order={3}>List Fasilitas Kesehatan</Title>
<AllList />
</Stack>
</Box>
</SimpleGrid>
</Stack>
);
}
function AllList() {
const allListState = useProxy(stateFasilitasKesehatan)
useShallowEffect(() => {
allListState.informasiumum.findMany.load();
allListState.layananunggulan.findMany.load();
allListState.dokterdantenagamedis.findMany.load();
allListState.fasilitaspendukung.findMany.load();
allListState.tarifdanlayanan.findMany.load();
allListState.prosedurpendaftaran.findMany.load();
}, [])
if (!allListState.informasiumum.findMany.data
|| !allListState.layananunggulan.findMany.data
|| !allListState.dokterdantenagamedis.findMany.data
|| !allListState.fasilitaspendukung.findMany.data
|| !allListState.tarifdanlayanan.findMany.data
|| !allListState.prosedurpendaftaran.findMany.data
) return <Stack>
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
</Stack>
return <Stack>
<Title order={4}>Informasi Umum</Title>
{allListState.informasiumum.findMany.data?.map((item) => (
<Box key={item.id}>
<Text>{item.fasilitas}</Text>
<Text>{item.alamat}</Text>
<Text>{item.jamOperasional}</Text>
</Box>
))}
<Title order={4}>Layanan Unggulan</Title>
{allListState.layananunggulan.findMany.data?.map((item) => (
<Box key={item.id}>
<Text dangerouslySetInnerHTML={{ __html: item.content }} />
</Box>
))}
<Title order={4}>Dokter & Tenaga Medis</Title>
<Table
striped
highlightOnHover
withTableBorder
withColumnBorders
bg={colors['white-1']}
>
<TableThead >
<TableTr >
<TableTh >
<Center>Nama</Center>
</TableTh>
<TableTh >
<Center>Specialist</Center>
</TableTh>
<TableTh >
<Center>Jadwal</Center>
</TableTh>
</TableTr>
</TableThead>
<TableTbody >
{allListState.dokterdantenagamedis.findMany.data?.map((item) => (
<TableTr key={item.id}>
<TableTd ta="center">{item.name}</TableTd>
<TableTd ta="center">Specialist {item.specialist}</TableTd>
<TableTd ta="center">{item.jadwal}</TableTd>
</TableTr>
))}
</TableTbody>
</Table>
<Title order={4}>Fasilitas Pendukung</Title>
{allListState.fasilitaspendukung.findMany.data?.map((item) => (
<Box key={item.id}>
<Text dangerouslySetInnerHTML={{ __html: item.content }} />
</Box>
))}
<Title order={4}>Tarif & Layanan</Title>
<Table
suppressHydrationWarning
striped
highlightOnHover
withTableBorder
withColumnBorders
bg={colors['white-1']}
>
<TableThead>
<TableTr>
<TableTh>
Layanan
</TableTh>
<TableTh>
Tarif
</TableTh>
</TableTr>
</TableThead>
<TableTbody>
{allListState.tarifdanlayanan.findMany.data?.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.layanan}</TableTd>
<TableTd>Rp.{item.tarif}</TableTd>
</TableTr>
))}
</TableTbody>
</Table>
<Title order={4}>Prosedur Pendaftaran</Title>
{allListState.prosedurpendaftaran.findMany.data?.map((item) => (
<Box key={item.id}>
<Text dangerouslySetInnerHTML={{__html: item.content}}/>
</Box>
))}
</Stack>
}
export default FasilitasKesehatan;

View File

@@ -0,0 +1,25 @@
import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import { Box, Skeleton, Stack, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { useProxy } from 'valtio/utils';
function ListProsedurPendaftaran() {
const prosedurpendaftaranState = useProxy(stateFasilitasKesehatan.prosedurpendaftaran)
useShallowEffect(() => {
prosedurpendaftaranState.findMany.load()
}, [])
if (!prosedurpendaftaranState.findMany.data)return<Stack>
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
</Stack>
return <Stack>
{prosedurpendaftaranState.findMany.data?.map((item) => (
<Box key={item.id}>
<Text dangerouslySetInnerHTML={{__html: item.content}}/>
</Box>
))}
</Stack>
}
export default ListProsedurPendaftaran;

View File

@@ -0,0 +1,19 @@
import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import { Box, Text } from '@mantine/core';
import { useProxy } from 'valtio/utils';
import { KesehatanEditor } from '../../../_com/kesehatanEditor';
function ProsedurPendaftaran() {
const prosedurpendaftaranState = useProxy(stateFasilitasKesehatan.prosedurpendaftaran)
return <Box>
<Text fw={"bold"}>Prosedur Pendaftaran</Text>
<KesehatanEditor
showSubmit={false}
onChange={(val) => {
prosedurpendaftaranState.create.form.content = val;
}} />
</Box>
}
export default ProsedurPendaftaran;

View File

@@ -0,0 +1,82 @@
import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import colors from '@/con/colors';
import { Center, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import _ from 'lodash';
import { useProxy } from 'valtio/utils';
function TarifDanLayananList() {
const tarifdanlayanan = useProxy(stateFasilitasKesehatan.tarifdanlayanan)
useShallowEffect(() => {
tarifdanlayanan.findMany.load()
}, [])
if (_.isEmpty(tarifdanlayanan.findMany.data)) {
return (
<Stack>
<Table
striped
highlightOnHover
withTableBorder
withColumnBorders
bg={colors['white-1']}
>
<TableThead>
<TableTr>
<TableTh>
<Center>Nama</Center>
</TableTh>
<TableTh>
<Center>Specialist</Center>
</TableTh>
<TableTh >
<Center>Jadwal</Center>
</TableTh>
</TableTr>
</TableThead>
<TableTbody >
<TableTr >
<TableTd colSpan={3}>
<Center>
<Text>Tidak ada data</Text>
</Center>
</TableTd>
</TableTr>
</TableTbody>
</Table>
</Stack>
);
}
return <Stack>
<Table
suppressHydrationWarning
striped
highlightOnHover
withTableBorder
withColumnBorders
bg={colors['white-1']}
>
<TableThead>
<TableTr>
<TableTh>
Layanan
</TableTh>
<TableTh>
Tarif
</TableTh>
</TableTr>
</TableThead>
<TableTbody>
{tarifdanlayanan.findMany.data?.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.layanan}</TableTd>
<TableTd>Rp.{item.tarif}</TableTd>
</TableTr>
))}
</TableTbody>
</Table>
</Stack>
}
export default TarifDanLayananList;

View File

@@ -0,0 +1,27 @@
import stateFasilitasKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import { Box, Text, TextInput } from '@mantine/core';
import { useProxy } from 'valtio/utils';
function TarifDanLayanan() {
const tarifdanlayanan = useProxy(stateFasilitasKesehatan.tarifdanlayanan)
return <Box>
<Text fw={"bold"}>Tarif & Layanan</Text>
<TextInput
label="Tarif"
placeholder='masukkan tarif'
onChange={(val) => {
tarifdanlayanan.create.form.tarif = val.target.value
}}
/>
<TextInput
mb={10}
label="Layanan"
placeholder='masukkan layanan'
onChange={(val) => {
tarifdanlayanan.create.form.layanan = val.target.value
}}
/>
</Box>
}
export default TarifDanLayanan;

View File

@@ -0,0 +1,90 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
'use client'
import stategrafikKepuasan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/grafikKepuasan';
import colors from '@/con/colors';
import { Box, Button, Group, Stack, TextInput, Title } from '@mantine/core';
import { useMediaQuery, useShallowEffect } from '@mantine/hooks';
import { useEffect, useState } from 'react';
import { Bar, BarChart, Legend, Tooltip, XAxis, YAxis } from 'recharts';
import { useProxy } from 'valtio/utils';
function GrafikHasilKepuasan() {
const grafikkepuasan = useProxy(stategrafikKepuasan.grafikkepuasan)
const [mounted, setMounted] = useState(false);
const isTablet = useMediaQuery('(max-width: 1024px)')
const isMobile = useMediaQuery('(max-width: 768px)')
const [chartData, setChartData] = useState<any[]>([])
useShallowEffect(() => {
const fetchData = async () => {
await grafikkepuasan.findMany.load();
if (grafikkepuasan.findMany.data && grafikkepuasan.findMany.data.length > 0) {
setChartData(grafikkepuasan.findMany.data);
}
};
fetchData();
}, []);
useEffect(() => {
setMounted(true); // setelah komponen siap di client
}, []);
if (!mounted) {
return null; // Jangan render apa-apa dulu sebelum mounted
}
return (
<Stack gap={"xs"}>
<Title order={3}>Grafik Hasil Kepuasan</Title>
<Box>
<TextInput
w={{ base: '100%', md: '50%' }}
label="Label"
placeholder='Masukkan label yang diinginkan'
value={grafikkepuasan.create.form.label}
onChange={(val) => {
grafikkepuasan.create.form.label = val.currentTarget.value
}}
/>
<TextInput
w={{ base: '100%', md: '50%' }}
label="Jumlah Penderita"
type='number'
placeholder='Masukkan jumlah penderita'
value={grafikkepuasan.create.form.jumlah}
onChange={(val) => {
grafikkepuasan.create.form.jumlah = val.currentTarget.value
}}
/>
</Box>
<Group>
<Button mt={10}
onClick={async () => {
await grafikkepuasan.create.create();
await grafikkepuasan.findMany.load();
if (grafikkepuasan.findMany.data) {
setChartData(grafikkepuasan.findMany.data);
}
}}
>Submit</Button>
</Group>
<Box h={400} w={{ base: "100%", md: "80%" }}>
<Title py={15} order={3}>Data Kelahiran & Kematian</Title>
<BarChart
width={isMobile ? 450 : isTablet ? 600 : 900}
height={380}
data={chartData}
>
<XAxis dataKey="label" />
<YAxis />
<Tooltip />
<Legend />
<Bar dataKey="jumlah" fill={colors['blue-button']} name="Jumlah" />
</BarChart>
</Box>
</Stack>
);
}
export default GrafikHasilKepuasan;

View File

@@ -0,0 +1,21 @@
import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
import { Box, Text } from '@mantine/core';
import { useProxy } from 'valtio/utils';
import { KesehatanEditor } from '../../../_com/kesehatanEditor';
function DeskripsiKegiatan() {
const deskripsiKegiatanState = useProxy(stateJadwalKegiatan.deskripsiKegiatan)
return (
<Box>
<Text pt={10} fw={"bold"}>Deskripsi Kegiatan</Text>
<KesehatanEditor
showSubmit={false}
onChange={(val) => {
deskripsiKegiatanState.create.form.deskripsi = val
}}
/>
</Box>
);
}
export default DeskripsiKegiatan;

View File

@@ -0,0 +1,23 @@
import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
import { Box, Text } from '@mantine/core';
import { useProxy } from 'valtio/utils';
import { KesehatanEditor } from '../../../_com/kesehatanEditor';
function DokumenYangDiperlukan() {
const dokumenDiperlukan = useProxy(stateJadwalKegiatan.dokumenjadwalkegiatan)
return (
<Box>
<Text pt={10} fw={"bold"}>Dokumen Yang Diperlukan</Text>
<KesehatanEditor
showSubmit={false}
onChange={(val)=> {
dokumenDiperlukan.create.form.content = val;
}}
/>
</Box>
);
}
export default DokumenYangDiperlukan;

View File

@@ -0,0 +1,42 @@
import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
import { Box, Text, TextInput } from '@mantine/core';
import { useProxy } from 'valtio/utils';
function InformasiKegiatan() {
const informasiKegiatanState = useProxy(stateJadwalKegiatan.informasiKegiatan)
return (
<Box>
<Text pt={10} fw={"bold"}>Informasi Kegiatan</Text>
<TextInput
label="Nama Kegiatan"
placeholder="Masukkan nama kegiatan"
onChange={(val) => {
informasiKegiatanState.create.form.name = val.target.value
}}
/>
<TextInput
label="Tanggal"
placeholder="Masukkan tanggal kegiatan"
onChange={(val) => {
informasiKegiatanState.create.form.tanggal = val.target.value
}}
/>
<TextInput
label="Waktu"
placeholder="Masukkan waktu kegiatan"
onChange={(val) => {
informasiKegiatanState.create.form.waktu = val.target.value
}}
/>
<TextInput
label="Lokasi"
placeholder="Masukkan lokasi kegiatan"
onChange={(val) => {
informasiKegiatanState.create.form.lokasi = val.target.value
}}
/>
</Box>
);
}
export default InformasiKegiatan;

View File

@@ -0,0 +1,21 @@
import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
import { Box, Text } from '@mantine/core';
import { useProxy } from 'valtio/utils';
import { KesehatanEditor } from '../../../_com/kesehatanEditor';
function LayananTersedia() {
const layananTersediaState = useProxy(stateJadwalKegiatan.layanantersedia)
return (
<Box>
<Text pt={10} fw={"bold"}>Layanan Yang Tersedia</Text>
<KesehatanEditor
showSubmit={false}
onChange={(val) => {
layananTersediaState.create.form.content = val;
}}
/>
</Box>
);
}
export default LayananTersedia;

View File

@@ -0,0 +1,173 @@
'use client'
import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
import { Box, Button, SimpleGrid, Skeleton, Stack, Text, Title } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { useProxy } from 'valtio/utils';
import DeskripsiKegiatan from './deskripsi_kegiatan/page';
import DokumenYangDiperlukan from './dokumen_yang_diperlukan/page';
import InformasiKegiatan from './informasi_kegiatan/page';
import LayananTersedia from './layanan_yang_tersedia/page';
import Pendaftaran from './pendaftaran/page';
import SyaratDanKetentuan from './syarat_dan_ketentuan/page';
function JadwalKegiatan() {
const allState = useProxy(stateJadwalKegiatan)
const submitAllForms = () => {
if (allState.informasiKegiatan.create.form.name &&
allState.informasiKegiatan.create.form.tanggal &&
allState.informasiKegiatan.create.form.waktu &&
allState.informasiKegiatan.create.form.lokasi) {
allState.informasiKegiatan.create.create()
}
if (allState.deskripsiKegiatan.create.form.deskripsi) {
allState.deskripsiKegiatan.create.create();
}
if (allState.layanantersedia.create.form.content) {
allState.layanantersedia.create.create();
}
if (allState.syaratketentuan.create.form.content) {
allState.syaratketentuan.create.create();
}
if (allState.dokumenjadwalkegiatan.create.form.content) {
allState.dokumenjadwalkegiatan.create.create();
}
if (allState.pendaftaranjadwal.create.form.name &&
allState.pendaftaranjadwal.create.form.tanggal &&
allState.pendaftaranjadwal.create.form.namaOrangtua &&
allState.pendaftaranjadwal.create.form.nomor &&
allState.pendaftaranjadwal.create.form.alamat &&
allState.pendaftaranjadwal.create.form.catatan
) {
allState.pendaftaranjadwal.create.create();
}
}
return (
<Stack py={10}>
<SimpleGrid cols={{
base: 1, md: 2
}}>
<Box>
<Title order={3}>Jadwal Kegiatan</Title>
<InformasiKegiatan />
<DeskripsiKegiatan />
<LayananTersedia />
<SyaratDanKetentuan />
<DokumenYangDiperlukan />
<Pendaftaran />
<Button mt={10} onClick={submitAllForms}>
Submit
</Button>
</Box>
<Box>
<Title order={3}>List Jadwal Kegiatan</Title>
<AllList />
</Box>
</SimpleGrid>
</Stack>
);
}
function AllList() {
const allList = useProxy(stateJadwalKegiatan)
useShallowEffect(() => {
allList.informasiKegiatan.findMany.load()
allList.deskripsiKegiatan.findMany.load()
allList.layanantersedia.findMany.load()
allList.syaratketentuan.findMany.load()
allList.dokumenjadwalkegiatan.findMany.load()
allList.pendaftaranjadwal.findMany.load()
}, [])
const isLoading = !allList.informasiKegiatan.findMany.data ||
!allList.deskripsiKegiatan.findMany.data ||
!allList.layanantersedia.findMany.data ||
!allList.syaratketentuan.findMany.data ||
!allList.dokumenjadwalkegiatan.findMany.data ||
!allList.pendaftaranjadwal.findMany.data
if (isLoading) {
return (
<Stack>
<Title order={4}>Informasi Kegiatan</Title>
{Array.from({ length: 10 }).map((_, k) => <Skeleton key={k} h={40} />)}
</Stack>
);
}
return (
<Stack>
<Title order={4}>Informasi Kegiatan</Title>
{allList.informasiKegiatan.findMany.data?.map((item) => {
return (
<Box key={item.id}>
<Text>{item.name}</Text>
<Text>{item.tanggal}</Text>
<Text>{item.waktu}</Text>
<Text>{item.lokasi}</Text>
</Box>
)
})}
<Title order={4}>Deskripsi Kegiatan</Title>
{allList.deskripsiKegiatan.findMany.data?.map((item) => {
return (
<Box key={item.id}>
<Text dangerouslySetInnerHTML={{ __html: item.deskripsi }} />
</Box>
)
})}
<Title order={4}>Layanan Yang Tersedia</Title>
{allList.layanantersedia.findMany.data?.map((item) => {
return (
<Box key={item.id}>
<Text dangerouslySetInnerHTML={{ __html: item.content }} />
</Box>
)
})}
<Title order={4}>Syarat dan Ketentuan</Title>
{allList.syaratketentuan.findMany.data?.map((item) => {
return (
<Box key={item.id}>
<Text dangerouslySetInnerHTML={{ __html: item.content }} />
</Box>
)
})}
<Title order={4}>Dokumen Yang Diperlukan</Title>
{allList.dokumenjadwalkegiatan.findMany.data?.map((item) => {
return (
<Box key={item.id}>
<Text dangerouslySetInnerHTML={{ __html: item.content }} />
</Box>
)
})}
<Title order={4}>Pendaftaran</Title>
{allList.pendaftaranjadwal.findMany.data?.map((item) => {
return (
<Box key={item.id}>
<Text>{item.name}</Text>
<Text>{item.tanggal}</Text>
<Text>{item.namaOrangtua}</Text>
<Text>{item.nomor}</Text>
<Text>{item.alamat}</Text>
<Text>{item.catatan}</Text>
</Box>
)
})}
</Stack>
)
}
export default JadwalKegiatan;

View File

@@ -0,0 +1,58 @@
'use client'
import stateJadwalKegiatan from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
import { Box, Text, Textarea, TextInput } from '@mantine/core';
import { useProxy } from 'valtio/utils';
function Pendaftaran() {
const pendaftaran = useProxy(stateJadwalKegiatan.pendaftaranjadwal)
return (
<Box>
<Text pt={10} fw={"bold"}>Pendaftaran</Text>
<TextInput
label='Nama Balita'
placeholder='Masukkan nama balita'
onChange={(val) => {
pendaftaran.create.form.name = val.target.value
}}
/>
<TextInput
label='Tanggal'
placeholder='Masukkan tanggal'
onChange={(val) => {
pendaftaran.create.form.tanggal = val.target.value
}}
/>
<TextInput
label='Nama Orang Tua / Wali'
placeholder='Masukkan nama orang tua / wali'
onChange={(val) => {
pendaftaran.create.form.namaOrangtua = val.target.value
}}
/>
<TextInput
label='No. Telepon'
placeholder='Masukkan no. telepon'
onChange={(val) => {
pendaftaran.create.form.nomor = val.target.value
}}
/>
<TextInput
label='Alamat'
placeholder='Masukkan alamat'
onChange={(val) => {
pendaftaran.create.form.alamat = val.target.value
}}
/>
<Textarea
label='Catatan Khusus (Opsional)'
placeholder='Masukkan catatan khusus'
onChange={(val) => {
pendaftaran.create.form.catatan = val.target.value
}}
/>
</Box>
);
}
export default Pendaftaran;

Some files were not shown because too many files have changed in this diff Show More