From f7fd9be255b0be0e2f35b5aaff90081efa268b17 Mon Sep 17 00:00:00 2001 From: nico Date: Fri, 3 Oct 2025 10:17:06 +0800 Subject: [PATCH] QC User & Admin Responsive : Menu Kesehatan - Ekonomi --- .../layanan/pelayanaPendudukNonPermanen.json | 2 +- .../layanan/pelayananPerizinanBerusaha.json | 2 +- prisma/schema.prisma | 2 + .../(dashboard)/_state/desa/layananDesa.ts | 37 ++--- .../_state/ekonomi/pasar-desa/pasar-desa.ts | 38 +++++ .../kesehatan/kontak-darurat/kontakDarurat.ts | 4 + .../{edit => [id]}/page.tsx | 0 .../pelayanan_penduduk_non_permanent/page.tsx | 2 +- .../{edit => [id]}/page.tsx | 96 ++++++------ .../pelayanan_perizinan_berusaha/page.tsx | 41 ++++- .../[id]/edit/page.tsx | 50 +++--- .../[id]/edit/page.tsx | 26 ++-- .../create/page.tsx | 4 +- .../produk-pasar-desa/[id]/edit/page.tsx | 11 ++ .../produk-pasar-desa/[id]/page.tsx | 5 + .../produk-pasar-desa/create/page.tsx | 10 ++ .../[id]/edit/page.tsx | 13 +- .../laporan-publik/[id]/edit/page.tsx | 24 +-- .../[id]/edit/page.tsx | 25 +-- .../pencegahan-kriminalitas/create/page.tsx | 20 +-- .../keamanan/pencegahan-kriminalitas/page.tsx | 4 +- .../fasilitas_kesehatan/page.tsx | 4 +- .../info-wabah-penyakit/[id]/edit/page.tsx | 18 +-- .../info-wabah-penyakit/[id]/page.tsx | 2 +- .../info-wabah-penyakit/create/page.tsx | 18 +-- .../kontak-darurat/[id]/edit/page.tsx | 10 ++ .../kesehatan/kontak-darurat/[id]/page.tsx | 5 + .../kesehatan/kontak-darurat/create/page.tsx | 12 ++ .../program-kesehatan/[id]/edit/page.tsx | 11 +- .../kesehatan/program-kesehatan/[id]/page.tsx | 2 +- .../program-kesehatan/create/page.tsx | 20 +-- .../_lib/ekonomi/pasar-desa/create.ts | 8 +- .../_lib/ekonomi/pasar-desa/index.ts | 2 + .../pasar-desa/kategori-produk/findManyAll.ts | 49 ++++++ .../pasar-desa/kategori-produk/index.ts | 2 + .../_lib/ekonomi/pasar-desa/updt.ts | 2 + .../kontak-darurat-keamanan/findMany.ts | 1 + .../kontak-item/findMany.ts | 1 + .../_lib/kesehatan/kontak-darurat/create.ts | 2 + .../_lib/kesehatan/kontak-darurat/index.ts | 2 + .../_lib/kesehatan/kontak-darurat/updt.ts | 3 + .../(pages)/ekonomi/pasar-desa/page.tsx | 8 +- .../page.tsx | 2 +- .../(pages)/keamanan/kontak-darurat/page.tsx | 142 ++++++++++++------ .../keamanan/pencegahan-kriminalitas/page.tsx | 6 +- .../(pages)/keamanan/polsek-terdekat/page.tsx | 39 ++++- .../polsek-terdekat/semua-polsek/page.tsx | 6 +- .../fasilitas-kesehatan-page/[id]/page.tsx | 3 +- .../jadwal-kegiatan-page/page.tsx | 6 +- .../info-wabah-penyakit/[id]/page.tsx | 85 +++++++++++ .../kesehatan/info-wabah-penyakit/page.tsx | 69 ++++----- .../(pages)/kesehatan/kontak-darurat/page.tsx | 71 +++++---- .../kesehatan/penanganan-darurat/page.tsx | 41 +++-- .../(pages)/kesehatan/posyandu/page.tsx | 15 +- .../kesehatan/program-kesehatan/page.tsx | 43 +++--- 55 files changed, 754 insertions(+), 372 deletions(-) rename src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/{edit => [id]}/page.tsx (100%) rename src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/{edit => [id]}/page.tsx (67%) create mode 100644 src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/kategori-produk/findManyAll.ts create mode 100644 src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/[id]/page.tsx diff --git a/prisma/data/desa/layanan/pelayanaPendudukNonPermanen.json b/prisma/data/desa/layanan/pelayanaPendudukNonPermanen.json index 2259bea4..d39b6e98 100644 --- a/prisma/data/desa/layanan/pelayanaPendudukNonPermanen.json +++ b/prisma/data/desa/layanan/pelayanaPendudukNonPermanen.json @@ -1,6 +1,6 @@ [ { - "id": "1", + "id": "edit", "name": "Pelayanan Penduduk Non-Permanent", "deskripsi": "

Surat Keterangan Penduduk Non-Permanent adalah dokumen yang dikeluarkan oleh pihak berwenang untuk memberikan keterangan bahwa seseorang atau kelompok orang memiliki status penduduk non-permanent di suatu wilayah. Dokumen ini biasanya digunakan untuk keperluan administratif atau legal, seperti mendapatkan akses ke layanan kesehatan, pendidikan, atau pelayanan publik lainnya.

" } diff --git a/prisma/data/desa/layanan/pelayananPerizinanBerusaha.json b/prisma/data/desa/layanan/pelayananPerizinanBerusaha.json index 8df36cf0..42e7ab7a 100644 --- a/prisma/data/desa/layanan/pelayananPerizinanBerusaha.json +++ b/prisma/data/desa/layanan/pelayananPerizinanBerusaha.json @@ -1,6 +1,6 @@ [ { - "id": "1", + "id": "edit", "name": "Pelayanan Perizinan Berusaha Berbasis Risiko Melalui Sistem ONLINE SINGLE SUBMISSION (OSS)", "deskripsi": "

Penyelenggaraan Perizinan Berusaha Berbasis Risiko melalui Sistem Online Single Submission (OSS) merupakan pelaksanaan Undang-Undang Nomor 11 Tahun 2020 Tentang Cipta Kerja. OSS Berbasis Risiko wajib digunakan oleh Pelaku Usaha, Kementerian/Lembaga, Pemerintah Daerah, Administrator Kawasan Ekonomi Khusus (KEK), dan Badan Pengusahaan Kawasan Perdagangan Bebas Pelabuhan Bebas (KPBPB).Berdasarkan Peraturan Pemerintah Nomor 5 Tahun 2021 terdapat 1.702 kegiatan usaha yang terdiri atas 1.349 Klasifikasi Baku Lapangan Usaha Indonesia (KBLI) yang sudah diimplementasikan dalam Sistem OSS Berbasis Risiko.

", "link" : "https://oss.go.id/" diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 54166bfc..5ee3472a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1167,6 +1167,7 @@ model KontakDarurat { deskripsi String image FileStorage @relation(fields: [imageId], references: [id]) imageId String + whatsapp String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime @default(now()) @@ -1340,6 +1341,7 @@ model PasarDesa { harga Int rating Float alamatUsaha String + kontak String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime @default(now()) diff --git a/src/app/admin/(dashboard)/_state/desa/layananDesa.ts b/src/app/admin/(dashboard)/_state/desa/layananDesa.ts index b11b67a8..a0a39410 100644 --- a/src/app/admin/(dashboard)/_state/desa/layananDesa.ts +++ b/src/app/admin/(dashboard)/_state/desa/layananDesa.ts @@ -581,33 +581,24 @@ const pelayananPerizinanBerusaha = proxy({ findById: { data: null as pelayananPerizinanBerusahaForm | null, loading: false, - initialize() { - pelayananPerizinanBerusaha.findById.data = { - id: "", - name: "", - deskripsi: "", - link: "", - } as pelayananPerizinanBerusahaForm; - }, async load(id: string) { try { - pelayananPerizinanBerusaha.findById.loading = true; - const res = await fetch( - `/api/desa/layanan/pelayananperizinanberusaha/${id}` - ); - if (res.ok) { - const data = await res.json(); - pelayananPerizinanBerusaha.findById.data = data.data ?? null; - } else { - console.error( - "Failed to fetch pelayanan perizinan berusaha:", - res.statusText - ); - pelayananPerizinanBerusaha.findById.data = null; + this.loading = true; + const response = await fetch(`/api/desa/layanan/pelayananperizinanberusaha/${id}`); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); } + const result = await response.json(); + if (result?.success) { + this.data = result.data; // Make sure this matches your API response structure + } + return result?.data || null; } catch (error) { - console.error("Error fetching pelayanan perizinan berusaha:", error); - pelayananPerizinanBerusaha.findById.data = null; + console.error('Error loading data:', error); + toast.error('Gagal memuat data'); + return null; + } finally { + this.loading = false; } }, }, diff --git a/src/app/admin/(dashboard)/_state/ekonomi/pasar-desa/pasar-desa.ts b/src/app/admin/(dashboard)/_state/ekonomi/pasar-desa/pasar-desa.ts index e5cfb7e0..21d8e7b4 100644 --- a/src/app/admin/(dashboard)/_state/ekonomi/pasar-desa/pasar-desa.ts +++ b/src/app/admin/(dashboard)/_state/ekonomi/pasar-desa/pasar-desa.ts @@ -12,6 +12,7 @@ const templatePasarDesaForm = z.object({ imageId: z.string().min(1, "Gambar wajib dipilih"), rating: z.number().min(1, "Rating minimal 1"), kategoriId: z.array(z.string()).min(1, "Minimal pilih satu kategori"), + kontak: z.string().min(1, "Kontak wajib diisi"), }); const defaultPasarDesaForm = { @@ -21,6 +22,7 @@ const defaultPasarDesaForm = { imageId: "", rating: 0, kategoriId: [] as string[], + kontak: "", }; const pasarDesa = proxy({ @@ -188,6 +190,7 @@ const pasarDesa = proxy({ imageId: data.imageId, rating: data.rating, kategoriId: data.kategoriId, + kontak: data.kontak, }; return data; } else { @@ -225,6 +228,7 @@ const pasarDesa = proxy({ imageId: this.form.imageId, rating: this.form.rating, kategoriId: this.form.kategoriId, + kontak: this.form.kontak, }), }); if (!response.ok) { @@ -336,6 +340,40 @@ const kategoriProduk = proxy({ } }, }, + // ✅ Versi findManyAll (ambil semua tanpa pagination) + findManyAll: { + data: null as + | Prisma.KategoriProdukGetPayload<{ + omit: { isActive: true }; + }>[] + | null, + loading: false, + search: "", + load: async (search = "") => { + kategoriProduk.findManyAll.loading = true; + kategoriProduk.findManyAll.search = search; + + try { + const query: any = {}; + if (search) query.search = search; + + const res = await ApiFetch.api.ekonomi.kategoriproduk["find-many-all"].get({ + query, + }); + + if (res.status === 200 && res.data?.success) { + kategoriProduk.findManyAll.data = res.data.data ?? []; + } else { + kategoriProduk.findManyAll.data = []; + } + } catch (err) { + console.error("Gagal fetch kategori produk (all):", err); + kategoriProduk.findManyAll.data = []; + } finally { + kategoriProduk.findManyAll.loading = false; + } + }, + }, findUnique: { data: null as Prisma.KategoriProdukGetPayload<{ omit: { isActive: true }; diff --git a/src/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat.ts b/src/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat.ts index 8f96d2e2..85480912 100644 --- a/src/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat.ts +++ b/src/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat.ts @@ -9,12 +9,14 @@ const templateForm = z.object({ name: z.string().min(3, "Judul minimal 3 karakter"), deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"), imageId: z.string().nonempty(), + whatsapp: z.string().min(10, "Whatsapp minimal 10 karakter"), }); const defaultForm = { name: "", deskripsi: "", imageId: "", + whatsapp: "", }; const kontakDarurat = proxy({ @@ -171,6 +173,7 @@ const kontakDarurat = proxy({ name: data.name, deskripsi: data.deskripsi, imageId: data.imageId, + whatsapp: data.whatsapp, }; return data; // Return the loaded data } else { @@ -207,6 +210,7 @@ const kontakDarurat = proxy({ name: this.form.name, deskripsi: this.form.deskripsi, imageId: this.form.imageId, + whatsapp: this.form.whatsapp, }), } ); diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/edit/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/[id]/page.tsx similarity index 100% rename from src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/edit/page.tsx rename to src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/[id]/page.tsx diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/page.tsx index bb7df689..e2c6f3e8 100644 --- a/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/page.tsx +++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_penduduk_non_permanent/page.tsx @@ -59,7 +59,7 @@ function PelayananPendudukNonPermanent() { radius="md" onClick={() => router.push( - '/admin/desa/layanan/pelayanan_penduduk_non_permanent/edit' + `/admin/desa/layanan/pelayanan_penduduk_non_permanent/${data.id}` ) } > diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/edit/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/[id]/page.tsx similarity index 67% rename from src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/edit/page.tsx rename to src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/[id]/page.tsx index ca194879..e8f4a8b6 100644 --- a/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/edit/page.tsx +++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/[id]/page.tsx @@ -1,5 +1,6 @@ /* eslint-disable react-hooks/exhaustive-deps */ 'use client' + import EditEditor from '@/app/admin/(dashboard)/_com/editEditor'; import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa'; import colors from '@/con/colors'; @@ -8,6 +9,7 @@ import { Button, Group, Paper, + Skeleton, Stack, TextInput, Title, @@ -21,66 +23,82 @@ import { useProxy } from 'valtio/utils'; function EditPelayananPerizinanBerusaha() { const router = useRouter(); - const params = useParams(); - const statePerizinanBerusaha = useProxy( - stateLayananDesa.pelayananPerizinanBerusaha - ); + const params = useParams<{ id: string }>(); + const id = params?.id; // ini langsung string + const state = useProxy(stateLayananDesa.pelayananPerizinanBerusaha); + const [loading, setLoading] = useState(true); const [formData, setFormData] = useState({ + id: '', name: '', deskripsi: '', link: '', }); - // load data pertama kali + // Load data detail useEffect(() => { - const loadPelayananPerizinan = async () => { - const id = params?.id as string; - if (!id) return; + if (!id) { + toast.error("ID tidak valid"); + return; + } + + const loadData = async () => { try { - const data = await statePerizinanBerusaha.update.load(id); + setLoading(true); + const data = await state.findById.load(id); if (data) { setFormData({ - name: data.name || '', - deskripsi: data.deskripsi || '', - link: data.link || '', + id: data.id, + name: data.name || "", + deskripsi: data.deskripsi || "", + link: data.link || "", }); + } else { + toast.error("Data tidak ditemukan"); } } catch (error) { - console.error('Error loading pelayanan perizinan berusaha:', error); - toast.error('Gagal memuat data pelayanan perizinan berusaha'); + console.error("Error loading data:", error); + toast.error("Gagal memuat data"); + } finally { + setLoading(false); } }; - loadPelayananPerizinan(); - }, [params?.id]); + + loadData(); + }, [id]); + const handleChange = (field: keyof typeof formData) => - (value: string) => { - setFormData((prev) => ({ - ...prev, - [field]: value, - })); - }; + (value: string) => { + setFormData((prev) => ({ + ...prev, + [field]: value, + })); + }; const handleSubmit = async () => { - const { name, deskripsi, link } = formData; - if (statePerizinanBerusaha.findById.data) { - const updatedData = { - ...statePerizinanBerusaha.findById.data, - name, - deskripsi, - link, - }; - await statePerizinanBerusaha.update.update(updatedData); + try { + await state.update.update(formData); router.push('/admin/desa/layanan/pelayanan_perizinan_berusaha'); + } catch (error) { + console.error('Error updating pelayanan perizinan berusaha:', error); + toast.error('Terjadi kesalahan saat update data'); } }; + if (loading) { + return ( + + + + ); + } + return ( - {/* Header Section */} + {/* Header */} diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/page.tsx index 64439514..70f2e731 100644 --- a/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/page.tsx +++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_perizinan_berusaha/page.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ 'use client' import colors from '@/con/colors'; import { @@ -19,35 +20,58 @@ import { Tooltip, } from '@mantine/core'; import { IconEdit } from '@tabler/icons-react'; -import { useRouter } from 'next/navigation'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import stateLayananDesa from '../../../_state/desa/layananDesa'; import { useProxy } from 'valtio/utils'; -import { useShallowEffect } from '@mantine/hooks'; +import { useRouter } from 'next/navigation'; function PerizinanBerusaha() { const router = useRouter(); const pelayananPerizinanBerusaha = useProxy( stateLayananDesa.pelayananPerizinanBerusaha ); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(''); const [active, setActive] = useState(1); const nextStep = () => setActive((current) => (current < 6 ? current + 1 : current)); const prevStep = () => setActive((current) => (current > 0 ? current - 1 : current)); - useShallowEffect(() => { - pelayananPerizinanBerusaha.findById.load('1'); + useEffect(() => { + const loadData = async () => { + try { + setLoading(true); + // You should get the ID from your router query or params + const id = '1'; // Replace with actual ID or get from URL params + await pelayananPerizinanBerusaha.findById.load(id); + } catch (err) { + setError('Gagal memuat data'); + console.error('Error:', err); + } finally { + setLoading(false); + } + }; + + loadData(); }, []); - if (!pelayananPerizinanBerusaha.findById.data) { + if (loading) { return ( - + ); } + if (error || !pelayananPerizinanBerusaha.findById.data) { + return ( +
+ {error || 'Data tidak ditemukan'} +
+ ); + } + const data = pelayananPerizinanBerusaha.findById.data; return ( @@ -69,7 +93,7 @@ function PerizinanBerusaha() { radius="md" onClick={() => router.push( - '/admin/desa/layanan/pelayanan_perizinan_berusaha/edit' + `/admin/desa/layanan/pelayanan_perizinan_berusaha/${data.id}` ) } > @@ -183,3 +207,4 @@ function PerizinanBerusaha() { } export default PerizinanBerusaha; + diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/[id]/edit/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/[id]/edit/page.tsx index 700b66d2..092eadcd 100644 --- a/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/[id]/edit/page.tsx +++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_surat_keterangan/[id]/edit/page.tsx @@ -44,39 +44,37 @@ function EditSuratKeterangan() { const [previewImage2, setPreviewImage2] = useState(null); // load data awal -useEffect(() => { - const loadSurat = async () => { - const id = params?.id as string; - if (!id) return; + useEffect(() => { + const loadSurat = async () => { + const id = params?.id as string; + if (!id) return; + + try { + const data = await stateSurat.edit.load(id); + if (!data) return; - try { - const data = await stateSurat.edit.load(id); - if (data) { - // merge style -> isi hanya field kosong setFormData((prev) => ({ ...prev, - name: prev.name || data.name || '', - deskripsi: prev.deskripsi || data.deskripsi || '', - imageId: prev.imageId || data.imageId || '', - image2Id: prev.image2Id || data.image2Id || '', + ...{ + name: prev.name || data.name || "", + deskripsi: prev.deskripsi || data.deskripsi || "", + imageId: prev.imageId || data.imageId || "", + image2Id: prev.image2Id || data.image2Id || "", + }, })); - if (data.image?.link && !previewImage) { - setPreviewImage(data.image.link); - } - if (data.image2?.link && !previewImage2) { - setPreviewImage2(data.image2.link); - } + if (data.image?.link && !previewImage) setPreviewImage(data.image.link); + if (data.image2?.link && !previewImage2) setPreviewImage2(data.image2.link); + } catch (error) { + console.error("Error loading surat:", error); + toast.error("Gagal memuat data surat"); } - } catch (error) { - console.error("Error loading surat:", error); - toast.error("Gagal memuat data surat"); - } - }; + }; + + loadSurat(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [params?.id]); - loadSurat(); - // eslint-disable-next-line react-hooks/exhaustive-deps -}, [params?.id]); // handler untuk submit diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/[id]/edit/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/[id]/edit/page.tsx index 868f14d7..27b89bdb 100644 --- a/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/[id]/edit/page.tsx +++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/[id]/edit/page.tsx @@ -8,17 +8,15 @@ import { Group, Paper, Stack, - Text, TextInput, Title, - Tooltip, + Tooltip } from '@mantine/core'; import { IconArrowBack } from '@tabler/icons-react'; import { useParams, useRouter } from 'next/navigation'; -import { useEffect, useState, useCallback } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { toast } from 'react-toastify'; import { useProxy } from 'valtio/utils'; -import EditEditor from '@/app/admin/(dashboard)/_com/editEditor'; function EditPelayananTelunjukSakti() { const stateTelunjukDesa = useProxy(stateLayananDesa.pelayananTelunjukSaktiDesa); @@ -111,21 +109,19 @@ function EditPelayananTelunjukSakti() { required /> - {/* Deskripsi pakai editor */} - - - Deskripsi - - handleChange('deskripsi', htmlContent)} - /> - + {/* Deskripsi */} + handleChange('deskripsi', e.target.value)} + label="Judul Link" + placeholder="Masukkan judul link" + required + /> {/* Link */} handleChange('link', e.target.value)} /> diff --git a/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/create/page.tsx b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/create/page.tsx index 5b2d330a..2fd23ace 100644 --- a/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/create/page.tsx +++ b/src/app/admin/(dashboard)/desa/layanan/pelayanan_telunjuk_sakti_desa/create/page.tsx @@ -82,8 +82,8 @@ function CreatePelayananTelunjukDesa() { onChange={(val) => { stateTelunjukDesa.create.form.deskripsi = val.target.value; }} - label="Deskripsi" - placeholder="Masukkan deskripsi pelayanan" + label="Judul Link" + placeholder="Masukkan judul link" required /> diff --git a/src/app/admin/(dashboard)/ekonomi/pasar-desa/produk-pasar-desa/[id]/edit/page.tsx b/src/app/admin/(dashboard)/ekonomi/pasar-desa/produk-pasar-desa/[id]/edit/page.tsx index 8dca19a0..5c96dea4 100644 --- a/src/app/admin/(dashboard)/ekonomi/pasar-desa/produk-pasar-desa/[id]/edit/page.tsx +++ b/src/app/admin/(dashboard)/ekonomi/pasar-desa/produk-pasar-desa/[id]/edit/page.tsx @@ -31,6 +31,7 @@ type FormData = { imageId: string; rating: number; kategoriId: string[]; + kontak: string; }; function EditPasarDesa() { @@ -47,6 +48,7 @@ function EditPasarDesa() { imageId: '', rating: 0, kategoriId: [], + kontak: '', }); // load data awal @@ -67,6 +69,7 @@ function EditPasarDesa() { imageId: data.imageId || '', rating: data.rating || 0, kategoriId: data.KategoriToPasar?.map((k: any) => k.kategoriId) || [], + kontak: data.kontak || '', }); if (data.image?.link) setPreviewImage(data.image.link); } @@ -228,6 +231,14 @@ function EditPasarDesa() { required /> + handleChange('kontak', e.target.value)} + required + /> + {data.alamatUsaha || '-'}
+ + Kontak + {data.kontak || '-'} + + Gambar {data.image?.link ? ( diff --git a/src/app/admin/(dashboard)/ekonomi/pasar-desa/produk-pasar-desa/create/page.tsx b/src/app/admin/(dashboard)/ekonomi/pasar-desa/produk-pasar-desa/create/page.tsx index 53b8e2e6..7423f6f0 100644 --- a/src/app/admin/(dashboard)/ekonomi/pasar-desa/produk-pasar-desa/create/page.tsx +++ b/src/app/admin/(dashboard)/ekonomi/pasar-desa/produk-pasar-desa/create/page.tsx @@ -41,6 +41,7 @@ export default function CreatePasarDesa() { imageId: '', rating: 0, kategoriId: [], + kontak: '', }; setPreviewImage(null); setFile(null); @@ -184,6 +185,15 @@ export default function CreatePasarDesa() { onChange={(e) => (statePasar.pasarDesa.create.form.alamatUsaha = e.target.value)} /> + {/* Kontak */} + (statePasar.pasarDesa.create.form.kontak = e.target.value)} + /> + {/* Kategori Produk */} ({ - value: v.id, - label: v.nama, - })) + value: v.id, + label: v.nama, + })) : [] } clearable diff --git a/src/app/admin/(dashboard)/keamanan/laporan-publik/[id]/edit/page.tsx b/src/app/admin/(dashboard)/keamanan/laporan-publik/[id]/edit/page.tsx index 17c68fb6..f52bd6c1 100644 --- a/src/app/admin/(dashboard)/keamanan/laporan-publik/[id]/edit/page.tsx +++ b/src/app/admin/(dashboard)/keamanan/laporan-publik/[id]/edit/page.tsx @@ -48,27 +48,29 @@ function EditLaporanPublik() { const loadLaporanPublik = async () => { const id = params?.id as string; if (!id) return; - + try { const data = await stateLaporan.edit.load(id); if (data) { - setFormData({ - judul: data.judul || '', - lokasi: data.lokasi || '', - tanggalWaktu: data.tanggalWaktu || '', - status: data.status || '', - penanganan: data.penanganan?.[0]?.deskripsi || '', - kronologi: data.kronologi || '', - }); + setFormData((prev) => ({ + ...prev, + judul: data.judul ?? prev.judul, + lokasi: data.lokasi ?? prev.lokasi, + tanggalWaktu: data.tanggalWaktu ?? prev.tanggalWaktu, + status: (data.status as Status) ?? prev.status, + penanganan: data.penanganan?.[0]?.deskripsi ?? prev.penanganan, + kronologi: data.kronologi ?? prev.kronologi, + })); } } catch (error) { - console.error('Error loading laporan publik:', error); + console.error("Error loading laporan publik:", error); toast.error("Gagal mengambil data laporan publik"); } }; - + loadLaporanPublik(); }, [params?.id, stateLaporan.edit]); + const handleChange = (field: string, value: string | Status) => { setFormData((prev) => ({ ...prev, [field]: value })); diff --git a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/[id]/edit/page.tsx b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/[id]/edit/page.tsx index 9918b93e..de2e39aa 100644 --- a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/[id]/edit/page.tsx +++ b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/[id]/edit/page.tsx @@ -10,6 +10,7 @@ import { Group, Paper, Stack, + Text, TextInput, Title, Tooltip, @@ -61,9 +62,9 @@ function EditPencegahanKriminalitas() { const handleChange = (field: keyof typeof formData) => - (e: React.ChangeEvent) => { - setFormData((prev) => ({ ...prev, [field]: e.target.value })); - }; + (e: React.ChangeEvent) => { + setFormData((prev) => ({ ...prev, [field]: e.target.value })); + }; const handleSubmit = async () => { const converted = convertYoutubeUrlToEmbed(formData.linkVideo); @@ -128,13 +129,17 @@ function EditPencegahanKriminalitas() { required /> - + + + Deskripsi + + + setFormData((prev) => ({ ...prev, deskripsiSingkat: val })) + } + /> + diff --git a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/create/page.tsx b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/create/page.tsx index a22e001f..89b189fc 100644 --- a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/create/page.tsx +++ b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/create/page.tsx @@ -90,15 +90,17 @@ function CreatePencegahanKriminalitas() { /> {/* Deskripsi Singkat */} - <TextInput - label="Deskripsi Singkat" - placeholder="Masukkan deskripsi singkat" - defaultValue={kriminalitasState.create.form.deskripsiSingkat} - onChange={(e) => { - kriminalitasState.create.form.deskripsiSingkat = e.currentTarget.value; - }} - required - /> + <Box> + <Text fw="bold" fz="sm" mb={6}> + Deskripsi Singkat + </Text> + <CreateEditor + value={kriminalitasState.create.form.deskripsiSingkat} + onChange={(val) => { + kriminalitasState.create.form.deskripsiSingkat = val; + }} + /> + </Box> {/* Deskripsi Panjang */} <Box> diff --git a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/page.tsx b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/page.tsx index 45db4790..be9eefc9 100644 --- a/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/page.tsx +++ b/src/app/admin/(dashboard)/keamanan/pencegahan-kriminalitas/page.tsx @@ -105,9 +105,11 @@ function ListPencegahanKriminalitas({ search }: { search: string }) { data.map((item) => ( <TableTr key={item.id}> <TableTd> - <Text fw={500} truncate="end" lineClamp={1}> + <Box w={200}> + <Text fw={500} truncate="end" lineClamp={1}> {item.judul} </Text> + </Box> </TableTd> <TableTd> <Box w={200}> diff --git a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/page.tsx b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/page.tsx index 9c9e3f1e..8c554c6a 100644 --- a/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/data-kesehatan-warga/fasilitas_kesehatan/page.tsx @@ -127,7 +127,9 @@ function ListFasilitasKesehatan({ search }: { search: string }) { </TableTd> <TableTd> <Box w={150}> - {item.tarifdanlayanan?.layanan || '-'} + <Text truncate="end" lineClamp={1}> + {item.tarifdanlayanan?.layanan || '-'} + </Text> </Box> </TableTd> <TableTd> diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/edit/page.tsx index 3c7a0744..6d751dd5 100644 --- a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/edit/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/edit/page.tsx @@ -140,15 +140,15 @@ function EditInfoWabahPenyakit() { required /> - <TextInput - value={formData.deskripsiSingkat} - onChange={(e: ChangeEvent<HTMLInputElement>) => - updateField('deskripsiSingkat', e.target.value) - } - label="Deskripsi Singkat" - placeholder="Masukkan deskripsi singkat" - required - /> + <Box> + <Text fz="sm" fw="bold"> + Deskripsi Singkat + </Text> + <EditEditor + value={formData.deskripsiSingkat} + onChange={(val) => updateField('deskripsiSingkat', val)} + /> + </Box> <Box> <Text fz="sm" fw="bold"> diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/page.tsx index 0fe252f3..03fda087 100644 --- a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/[id]/page.tsx @@ -84,7 +84,7 @@ function DetailInfoWabahPenyakit() { <Box> <Text fz="lg" fw="bold">Deskripsi Singkat</Text> - <Text fz="md" c="dimmed" style={{ wordBreak: "break-word", whiteSpace: "normal" }}>{data.deskripsiSingkat || '-'}</Text> + <Text fz="md" c="dimmed" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: data.deskripsiSingkat }} /> </Box> <Box> diff --git a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/create/page.tsx index adb5eecc..06a0d39c 100644 --- a/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/create/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/info-wabah-penyakit/create/page.tsx @@ -100,15 +100,15 @@ function CreateInfoWabahPenyakit() { required /> - <TextInput - defaultValue={infoWabahPenyakitState.create.form.deskripsiSingkat} - onChange={(val) => { - infoWabahPenyakitState.create.form.deskripsiSingkat = val.target.value; - }} - label={<Text fz="sm" fw="bold">Deskripsi Singkat</Text>} - placeholder="Masukkan deskripsi singkat" - required - /> + <Box> + <Text fz="sm" fw="bold">Deskripsi Singkat</Text> + <CreateEditor + value={infoWabahPenyakitState.create.form.deskripsiSingkat} + onChange={(val) => { + infoWabahPenyakitState.create.form.deskripsiSingkat = val; + }} + /> + </Box> <Box> <Text fz="sm" fw="bold">Deskripsi</Text> diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/edit/page.tsx index 4e0660c6..8ede9489 100644 --- a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/edit/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/edit/page.tsx @@ -33,6 +33,7 @@ function EditKontakDarurat() { name: '', deskripsi: '', imageId: '', + whatsapp: '', }); const [loading, setLoading] = useState(true); @@ -49,6 +50,7 @@ function EditKontakDarurat() { name: data.name || '', deskripsi: data.deskripsi || '', imageId: data.imageId || '', + whatsapp: data.whatsapp || '', }); if (data?.image?.link) setPreviewImage(data.image.link); } @@ -124,6 +126,14 @@ function EditKontakDarurat() { required /> + <TextInput + value={formData.whatsapp} + onChange={(e) => setFormData(prev => ({ ...prev, whatsapp: e.target.value }))} + label="Whatsapp" + placeholder="Masukkan whatsapp" + required + /> + <Box> <Text fz="sm" fw="bold">Deskripsi</Text> <EditEditor diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/page.tsx index e257cb6e..628338cb 100644 --- a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/[id]/page.tsx @@ -72,6 +72,11 @@ function DetailKontakDarurat() { <Text fz="md" c="dimmed">{data.name || '-'}</Text> </Box> + <Box> + <Text fz="lg" fw="bold">Whatsapp</Text> + <Text fz="md" c="dimmed">{data.whatsapp || '-'}</Text> + </Box> + <Box> <Text fz="lg" fw="bold">Deskripsi</Text> <Text diff --git a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/create/page.tsx index 85596d33..65a84277 100644 --- a/src/app/admin/(dashboard)/kesehatan/kontak-darurat/create/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/kontak-darurat/create/page.tsx @@ -38,6 +38,7 @@ function CreateKontakDarurat() { name: '', deskripsi: '', imageId: '', + whatsapp: '', }; setPreviewImage(null); setFile(null); @@ -105,6 +106,17 @@ function CreateKontakDarurat() { required /> + <TextInput + type='number' + defaultValue={kontakDaruratState.create.form.whatsapp} + onChange={(val) => { + kontakDaruratState.create.form.whatsapp = val.target.value; + }} + label={<Text fz="sm" fw="bold">Whatsapp</Text>} + placeholder="Masukkan whatsapp" + required + /> + <Box> <Text fz="sm" fw="bold">Deskripsi</Text> <CreateEditor diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/edit/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/edit/page.tsx index 68846a04..1f0dcbec 100644 --- a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/edit/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/edit/page.tsx @@ -117,7 +117,6 @@ function EditProgramKesehatan() { <Stack gap="md"> {[ { label: 'Judul', key: 'name', placeholder: 'Masukkan judul' }, - { label: 'Deskripsi Singkat', key: 'deskripsiSingkat', placeholder: 'Masukkan deskripsi singkat' }, ].map((field) => ( <TextInput key={field.key} @@ -129,6 +128,16 @@ function EditProgramKesehatan() { /> ))} + <Box> + <Text fz="sm" fw="bold" mb={6}> + Deskripsi Singkat + </Text> + <EditEditor + value={formData.deskripsiSingkat} + onChange={(val) => handleChange('deskripsiSingkat', val)} + /> + </Box> + <Box> <Text fz="sm" fw="bold" mb={6}> Deskripsi diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/page.tsx index 9749c14f..5a36bca6 100644 --- a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/[id]/page.tsx @@ -73,7 +73,7 @@ function DetailProgramKesehatan() { <Box> <Text fz="lg" fw="bold">Deskripsi Singkat</Text> - <Text fz="md" c="dimmed" style={{ wordBreak: "break-word", whiteSpace: "normal" }}>{data?.deskripsiSingkat || '-'}</Text> + <Text fz="md" c="dimmed" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: data?.deskripsiSingkat || '-' }} /> </Box> <Box> diff --git a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/create/page.tsx b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/create/page.tsx index c529868f..35d642df 100644 --- a/src/app/admin/(dashboard)/kesehatan/program-kesehatan/create/page.tsx +++ b/src/app/admin/(dashboard)/kesehatan/program-kesehatan/create/page.tsx @@ -101,15 +101,17 @@ function CreateProgramKesehatan() { required /> - <TextInput - defaultValue={programKesehatanState.create.form.deskripsiSingkat} - onChange={(val) => { - programKesehatanState.create.form.deskripsiSingkat = val.target.value; - }} - label="Deskripsi Singkat" - placeholder="Masukkan deskripsi singkat" - required - /> + <Box> + <Title order={6} mb={6}> + Deskripsi Singkat + + { + programKesehatanState.create.form.deskripsiSingkat = val; + }} + /> + diff --git a/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/create.ts b/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/create.ts index 4751abcc..7ddd3be7 100644 --- a/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/create.ts +++ b/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/create.ts @@ -7,7 +7,9 @@ type FormCreate = { alamatUsaha: string; imageId: string; rating: number; - kategoriId: string[]; // Array of KategoriProduk IDs + kategoriId: string[]; + kontak: string; + // Array of KategoriProduk IDs }; export default async function pasarDesaCreate(context: Context) { @@ -28,7 +30,9 @@ export default async function pasarDesaCreate(context: Context) { alamatUsaha: body.alamatUsaha, imageId: body.imageId, rating: Number(body.rating), - kategoriProdukId: body.kategoriId[0], // Use the first category as the main one + kategoriProdukId: body.kategoriId[0], + kontak: body.kontak + // Use the first category as the main one }, }); diff --git a/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/index.ts b/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/index.ts index dc8e413e..6731abb2 100644 --- a/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/index.ts +++ b/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/index.ts @@ -37,6 +37,7 @@ const PasarDesa = new Elysia({ imageId: t.String(), rating: t.Number(), kategoriId: t.Array(t.String()), + kontak: t.String(), }), } ) @@ -79,6 +80,7 @@ const PasarDesa = new Elysia({ imageId: t.String(), rating: t.Number(), kategoriId: t.Array(t.String()), + kontak: t.String(), }), } ); diff --git a/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/kategori-produk/findManyAll.ts b/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/kategori-produk/findManyAll.ts new file mode 100644 index 00000000..3373f148 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/kategori-produk/findManyAll.ts @@ -0,0 +1,49 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +// /api/berita/findManyAll.ts +import prisma from "@/lib/prisma"; +import { Context } from "elysia"; + +async function kategoriProdukFindManyAll(context: Context) { + // Ambil query search (opsional) + const search2 = (context.query.search as string) || ""; + + // Buat where clause + const where: any = { isActive: true }; + + if (search2) { + where.OR = [ + { nama: { contains: search2, mode: "insensitive" } }, + { + KategoriToPasar: { + some: { + kategori: { + nama: { contains: search2, mode: "insensitive" }, + }, + }, + }, + }, + ]; + } + + try { + const data = await prisma.kategoriProduk.findMany({ + where, + orderBy: { createdAt: "desc" }, + }); + + return { + success: true, + message: "Berhasil ambil semua kategori produk", + data, + total: data.length, + }; + } catch (e) { + console.error("Error di findManyAll:", e); + return { + success: false, + message: "Gagal mengambil data kategori produk", + }; + } +} + +export default kategoriProdukFindManyAll; diff --git a/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/kategori-produk/index.ts b/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/kategori-produk/index.ts index c8729849..5777098b 100644 --- a/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/kategori-produk/index.ts +++ b/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/kategori-produk/index.ts @@ -5,12 +5,14 @@ import kategoriProdukDelete from "./del"; import kategoriProdukCreate from "./create"; import kategoriProdukUpdate from "./updt"; import { t } from "elysia"; +import kategoriProdukFindManyAll from "./findManyAll"; const KategoriProduk = new Elysia({ prefix: "/kategoriproduk", tags: ["Ekonomi/Kategori Produk"], }) .get("/find-many", kategoriProdukFindMany) + .get("/find-many-all", kategoriProdukFindManyAll) .get("/:id", async (context) => { const response = await kategoriProdukFindUnique(context); return response; diff --git a/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/updt.ts b/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/updt.ts index 71e2417d..7acac5cd 100644 --- a/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/updt.ts +++ b/src/app/api/[[...slugs]]/_lib/ekonomi/pasar-desa/updt.ts @@ -9,6 +9,7 @@ type FormUpdate = { imageId: string; rating: number; kategoriId: string[]; // Array of KategoriProduk IDs + kontak: string; }; export default async function pasarDesaUpdate(context: Context) { @@ -31,6 +32,7 @@ export default async function pasarDesaUpdate(context: Context) { alamatUsaha: body.alamatUsaha, imageId: body.imageId, rating: Number(body.rating), + kontak: body.kontak }, }); diff --git a/src/app/api/[[...slugs]]/_lib/keamanan/kontak-darurat-keamanan/findMany.ts b/src/app/api/[[...slugs]]/_lib/keamanan/kontak-darurat-keamanan/findMany.ts index 6fa611d6..4b5944c9 100644 --- a/src/app/api/[[...slugs]]/_lib/keamanan/kontak-darurat-keamanan/findMany.ts +++ b/src/app/api/[[...slugs]]/_lib/keamanan/kontak-darurat-keamanan/findMany.ts @@ -23,6 +23,7 @@ export default async function kontakDaruratKeamananFindMany(context: Context) { try { const [data, total] = await Promise.all([ prisma.kontakDaruratKeamanan.findMany({ + where, include: { kontakItems: { include: { diff --git a/src/app/api/[[...slugs]]/_lib/keamanan/kontak-darurat-keamanan/kontak-item/findMany.ts b/src/app/api/[[...slugs]]/_lib/keamanan/kontak-darurat-keamanan/kontak-item/findMany.ts index 2580ff95..add090ca 100644 --- a/src/app/api/[[...slugs]]/_lib/keamanan/kontak-darurat-keamanan/kontak-item/findMany.ts +++ b/src/app/api/[[...slugs]]/_lib/keamanan/kontak-darurat-keamanan/kontak-item/findMany.ts @@ -25,6 +25,7 @@ export default async function kontakItemFindMany(context: Context) { skip, take: limit, orderBy: { createdAt: "desc" }, + where, }), prisma.kontakItem.count({ where }), ]); diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/create.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/create.ts index 8c5be87d..2e4ccdea 100644 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/create.ts +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/create.ts @@ -7,6 +7,7 @@ type FormCreate = Prisma.KontakDaruratGetPayload<{ name: true; deskripsi: true; imageId: true; + whatsapp: true; }; }>; export default async function kontakDaruratCreate(context: Context) { @@ -17,6 +18,7 @@ export default async function kontakDaruratCreate(context: Context) { name: body.name, deskripsi: body.deskripsi, imageId: body.imageId, + whatsapp: body.whatsapp, } }) return { diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/index.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/index.ts index a5162b83..44c43af2 100644 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/index.ts +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/index.ts @@ -14,6 +14,7 @@ const KontakDarurat = new Elysia({ name: t.String(), deskripsi: t.String(), imageId: t.String(), + whatsapp: t.String(), }) }) .get("/find-many", kontakDaruratFindMany) @@ -33,6 +34,7 @@ const KontakDarurat = new Elysia({ name: t.String(), deskripsi: t.String(), imageId: t.String(), + whatsapp: t.String(), }) } ) diff --git a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/updt.ts b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/updt.ts index bc9d7922..f61c6ffc 100644 --- a/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/updt.ts +++ b/src/app/api/[[...slugs]]/_lib/kesehatan/kontak-darurat/updt.ts @@ -10,6 +10,7 @@ type FormUpdate = Prisma.KontakDaruratGetPayload<{ name: true; deskripsi: true; imageId: true; + whatsapp: true; } }> export default async function kontakDaruratUpdate(context: Context) { @@ -21,6 +22,7 @@ export default async function kontakDaruratUpdate(context: Context) { name, deskripsi, imageId, + whatsapp, } = body; if(!id) { @@ -75,6 +77,7 @@ export default async function kontakDaruratUpdate(context: Context) { name, deskripsi, imageId, + whatsapp, } }) diff --git a/src/app/darmasaba/(pages)/ekonomi/pasar-desa/page.tsx b/src/app/darmasaba/(pages)/ekonomi/pasar-desa/page.tsx index ef19511f..38dad38f 100644 --- a/src/app/darmasaba/(pages)/ekonomi/pasar-desa/page.tsx +++ b/src/app/darmasaba/(pages)/ekonomi/pasar-desa/page.tsx @@ -3,7 +3,7 @@ import pasarDesaState from '@/app/admin/(dashboard)/_state/ekonomi/pasar-desa/pa import colors from '@/con/colors'; import { Box, Center, Flex, Grid, GridCol, Image, Pagination, Paper, Select, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core'; import { useDebouncedValue, useShallowEffect } from '@mantine/hooks'; -import { IconMapPinFilled, IconSearch, IconShoppingCartFilled, IconStarFilled } from '@tabler/icons-react'; +import { IconBrandWhatsapp, IconMapPinFilled, IconSearch, IconStarFilled } from '@tabler/icons-react'; import { motion } from 'motion/react'; import { useRouter } from 'next/navigation'; import { useState } from 'react'; @@ -25,7 +25,7 @@ function Page() { } = state.findMany useShallowEffect(() => { - pasarDesaState.kategoriProduk.findMany.load() + pasarDesaState.kategoriProduk.findManyAll.load() }, []) // Filter data based on selected category @@ -105,7 +105,7 @@ function Page() { return ( <Stack key={k}> <motion.div - onClick={() => router.push('https://www.whatsapp.com/?lang=id')} + onClick={() => router.push(`https://wa.me/${v.kontak?.replace(/\D/g, '')}`)} whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.8 }} > @@ -132,7 +132,7 @@ function Page() { <Text fz={'sm'} ml={2}>{v.alamatUsaha}</Text> </Flex> </Box> - <IconShoppingCartFilled size={20} color={colors['blue-button']} /> + <IconBrandWhatsapp size={20} color={colors['blue-button']} /> </Flex> </Paper> </motion.div> diff --git a/src/app/darmasaba/(pages)/keamanan/keamanan-lingkungan-pecalang-patwal/page.tsx b/src/app/darmasaba/(pages)/keamanan/keamanan-lingkungan-pecalang-patwal/page.tsx index 238b41ef..90081bfa 100644 --- a/src/app/darmasaba/(pages)/keamanan/keamanan-lingkungan-pecalang-patwal/page.tsx +++ b/src/app/darmasaba/(pages)/keamanan/keamanan-lingkungan-pecalang-patwal/page.tsx @@ -56,7 +56,7 @@ function Page() { <GridCol span={{ base: 12, md: 3 }}> <TextInput radius={"lg"} - placeholder='Cari Puskesmas' + placeholder='Cari Keamanan Lingkungan' value={search} onChange={(e) => setSearch(e.target.value)} leftSection={<IconSearch size={20} />} diff --git a/src/app/darmasaba/(pages)/keamanan/kontak-darurat/page.tsx b/src/app/darmasaba/(pages)/keamanan/kontak-darurat/page.tsx index c416ce92..c3020560 100644 --- a/src/app/darmasaba/(pages)/keamanan/kontak-darurat/page.tsx +++ b/src/app/darmasaba/(pages)/keamanan/kontak-darurat/page.tsx @@ -34,6 +34,52 @@ function Page() { ); } + if (data.length === 0) { + return ( + <Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}> + <Box px={{ base: 'md', md: 100 }}> + <BackButton /> + </Box> + <Group px={{ base: 'md', md: 100 }} justify={'space-between'} align='center'> + <Box> + <Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}> + Kontak Darurat + </Text> + <Text fz={{ base: "h4", md: "h3" }} > + Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung. + </Text> + </Box> + <TextInput + placeholder='Cari kontak darurat, nama, atau nomor...' + leftSection={<IconSearch size={20} />} + value={search} + onChange={(e) => setSearch(e.currentTarget.value)} + /> + </Group> + <Box px={{ base: "md", md: 100 }}> + <Stack gap={'lg'}> + <Paper p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}> + <Flex justify={'center'} gap={'lg'} align={'center'}> + <Avatar radius={"xl"} size={'lg'} bg={colors['BG-trans']}> + <IconPhoneCall size={30} color={colors["blue-button"]} /> + </Avatar> + <Box> + <Text ta={'center'} c={colors['blue-button']} py={10} fz={{ base: "md", md: "h4" }} fw={"bold"} > + Nomor Darurat Utama + </Text> + <Text ta={'center'} fw={"bold"} fz={'h2'} c={colors["blue-button"]}>112</Text> + </Box> + </Flex> + </Paper> + </Stack> + </Box> + <Center> + <Text fz={"h1"} c={colors["blue-button"]} fw={"bold"}>Tidak ada kontak darurat yang ditemukan</Text> + </Center> + </Stack> + ); + } + return ( <Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}> <Box px={{ base: 'md', md: 100 }}> @@ -76,57 +122,63 @@ function Page() { <SimpleGrid cols={{ base: 1, md: 2 }} spacing="xl"> {/* Layanan Darurat */} {data.map((item) => ( - <Paper + <a key={item.id} - p="lg" - radius="md" - bg={colors['white-trans-1']} + href={`tel:${item.kontakItems[0]?.kontakItem?.nomorTelepon || '112'}`} + style={{ textDecoration: 'none' }} > - <Group pb="md" align="center"> - <Avatar radius="xl" size="lg" bg={colors['BG-trans']}> - {item.icon && ( - <IconMapper - name={item.icon as IconKey} - size={32} - color={colors['blue-button']} - /> - )} - </Avatar> - <Text fw="bold" fz={{ base: "lg", md: "xl" }} c={colors["blue-button"]}> - {item.nama} - </Text> - </Group> + <Paper - {/* Kontak Items */} - {item.kontakItems?.map((kontak) => ( - <Paper - key={kontak.id} - p="lg" - bg={colors['BG-trans']} - radius="md" - shadow="xs" - mt="sm" - > - <Group align="center" justify="space-between"> - <Group align="center"> - {kontak.kontakItem?.icon && ( - <IconMapper - name={kontak.kontakItem.icon as IconKey} - size={24} - color={colors['blue-button']} - /> - )} + p="lg" + radius="md" + bg={colors['white-trans-1']} + > + <Group pb="md" align="center"> + <Avatar radius="xl" size="lg" bg={colors['BG-trans']}> + {item.icon && ( + <IconMapper + name={item.icon as IconKey} + size={32} + color={colors['blue-button']} + /> + )} + </Avatar> + <Text fw="bold" fz={{ base: "lg", md: "xl" }} c={colors["blue-button"]}> + {item.nama} + </Text> + </Group> + + {/* Kontak Items */} + {item.kontakItems?.map((kontak) => ( + <Paper + key={kontak.id} + p="lg" + bg={colors['BG-trans']} + radius="md" + shadow="xs" + mt="sm" + > + <Group align="center" justify="space-between"> + <Group align="center"> + {kontak.kontakItem?.icon && ( + <IconMapper + name={kontak.kontakItem.icon as IconKey} + size={24} + color={colors['blue-button']} + /> + )} + <Text fw="bold" fz={{ base: "sm", md: "md" }} c={colors["blue-button"]}> + {kontak.kontakItem?.nama} + </Text> + </Group> <Text fw="bold" fz={{ base: "sm", md: "md" }} c={colors["blue-button"]}> - {kontak.kontakItem?.nama} + {kontak.kontakItem?.nomorTelepon} </Text> </Group> - <Text fw="bold" fz={{ base: "sm", md: "md" }} c={colors["blue-button"]}> - {kontak.kontakItem?.nomorTelepon} - </Text> - </Group> - </Paper> - ))} - </Paper> + </Paper> + ))} + </Paper> + </a> ))} </SimpleGrid> <Center> diff --git a/src/app/darmasaba/(pages)/keamanan/pencegahan-kriminalitas/page.tsx b/src/app/darmasaba/(pages)/keamanan/pencegahan-kriminalitas/page.tsx index 4cec3203..3492cf0f 100644 --- a/src/app/darmasaba/(pages)/keamanan/pencegahan-kriminalitas/page.tsx +++ b/src/app/darmasaba/(pages)/keamanan/pencegahan-kriminalitas/page.tsx @@ -2,7 +2,7 @@ 'use client' import pencegahanKriminalitasState from '@/app/admin/(dashboard)/_state/keamanan/pencegahan-kriminalitas'; import colors from '@/con/colors'; -import { ActionIcon, Box, Button, Center, Paper, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core'; +import { Box, Button, Center, Paper, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core'; import { useShallowEffect } from '@mantine/hooks'; import { IconArrowRight } from '@tabler/icons-react'; import { useTransitionRouter } from 'next-view-transitions'; @@ -63,7 +63,7 @@ function Page() { <Stack pt={30} gap="lg"> {data.length > 0 ? ( data.map((item) => ( - <ActionIcon key={item.id} variant='transparent' onClick={() => router.push(`/darmasaba/keamanan/pencegahan-kriminalitas/${item.id}`)}> + <a key={item.id} href={`/darmasaba/keamanan/pencegahan-kriminalitas/${item.id}`}> <Paper p="md" bg={colors['blue-button']} radius="md" shadow="sm"> <Stack gap={"xs"}> <Text fz="h3" c={colors['white-1']}> @@ -71,7 +71,7 @@ function Page() { </Text> </Stack> </Paper> - </ActionIcon> + </a> )) ) : ( <Text color="dimmed"> diff --git a/src/app/darmasaba/(pages)/keamanan/polsek-terdekat/page.tsx b/src/app/darmasaba/(pages)/keamanan/polsek-terdekat/page.tsx index dcfb262e..39daf22e 100644 --- a/src/app/darmasaba/(pages)/keamanan/polsek-terdekat/page.tsx +++ b/src/app/darmasaba/(pages)/keamanan/polsek-terdekat/page.tsx @@ -20,10 +20,41 @@ function Page() { } = state; useEffect(() => { - if (!data && !loading) { - load(); - } - }, [data, loading]); + load(); + }, []); + + // kalau masih loading + if (loading) { + return ( + <Stack py={10}> + <Skeleton h={500} /> + </Stack> + ); + } + + // kalau data kosong + if (!data) { + return ( + <Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}> + <Box px={{ base: 'md', md: 100 }}> + <BackButton /> + </Box> + <Box pb={10} px={{ base: 20, md: 100 }}> + <Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}> + Kantor Polisi Terdekat + </Text> + <Text pb={15} fz={'h4'} > + Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung + </Text> + </Box> + <Center py="xl"> + <Text fz="lg" fw="bold" c="red"> + Data Polsek tidak ada + </Text> + </Center> + </Stack > + ); + } return ( <Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}> diff --git a/src/app/darmasaba/(pages)/keamanan/polsek-terdekat/semua-polsek/page.tsx b/src/app/darmasaba/(pages)/keamanan/polsek-terdekat/semua-polsek/page.tsx index 47886d21..1ccaa2f0 100644 --- a/src/app/darmasaba/(pages)/keamanan/polsek-terdekat/semua-polsek/page.tsx +++ b/src/app/darmasaba/(pages)/keamanan/polsek-terdekat/semua-polsek/page.tsx @@ -8,10 +8,12 @@ import React, { useState } from 'react'; import { useProxy } from 'valtio/utils'; import BackButton from '../../../desa/layanan/_com/BackButto'; import { useRouter } from 'next/navigation'; +import { useDebouncedValue } from '@mantine/hooks'; function Page() { const state = useProxy(polsekTerdekatState); const [search, setSearch] = useState(''); + const [debouncedSearch] = useDebouncedValue(search, 500); // 500ms delay const router = useRouter() const { @@ -23,8 +25,8 @@ function Page() { } = state.findMany; useShallowEffect(() => { - load(page, 3, search) - }, [page, search]) + load(page, 3, debouncedSearch) + }, [page, debouncedSearch]) if (loading || !data) { return ( diff --git a/src/app/darmasaba/(pages)/kesehatan/data-kesehatan-warga/fasilitas-kesehatan-page/[id]/page.tsx b/src/app/darmasaba/(pages)/kesehatan/data-kesehatan-warga/fasilitas-kesehatan-page/[id]/page.tsx index 70042d4d..0e525094 100644 --- a/src/app/darmasaba/(pages)/kesehatan/data-kesehatan-warga/fasilitas-kesehatan-page/[id]/page.tsx +++ b/src/app/darmasaba/(pages)/kesehatan/data-kesehatan-warga/fasilitas-kesehatan-page/[id]/page.tsx @@ -39,10 +39,9 @@ function Page() { const nama = data?.name || 'Fasilitas Kesehatan'; const prosedur = data?.prosedurpendaftaran.content || ''; - console.log("Prosedur:", data?.prosedurpendaftaran); const alamat = data?.informasiumum?.alamat || '-'; const jam = data?.informasiumum?.jamOperasional || '-'; - const layananUnggulan = data?.layananunggulan || ''; + const layananUnggulan = data?.layananunggulan?.content || ''; const tenaga = data?.dokterdantenagamedis || null; const fasilitasPendukungHtml = data?.fasilitaspendukung?.content || ''; const tarif = (data?.tarifdanlayanan as TarifDanLayanan) || null; diff --git a/src/app/darmasaba/(pages)/kesehatan/data-kesehatan-warga/jadwal-kegiatan-page/page.tsx b/src/app/darmasaba/(pages)/kesehatan/data-kesehatan-warga/jadwal-kegiatan-page/page.tsx index da57f97c..c50eeed3 100644 --- a/src/app/darmasaba/(pages)/kesehatan/data-kesehatan-warga/jadwal-kegiatan-page/page.tsx +++ b/src/app/darmasaba/(pages)/kesehatan/data-kesehatan-warga/jadwal-kegiatan-page/page.tsx @@ -53,7 +53,11 @@ function JadwalKegiatanPage() { {item.informasijadwalkegiatan.name} </Text> <Text fw={600} fz="sm" c={colors['blue-button']}> - {item.informasijadwalkegiatan.tanggal} + {new Date(item.informasijadwalkegiatan.tanggal).toLocaleDateString('id-ID', { + day: '2-digit', + month: 'long', + year: 'numeric' + })} </Text> </Group> diff --git a/src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/[id]/page.tsx b/src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/[id]/page.tsx new file mode 100644 index 00000000..040a3cba --- /dev/null +++ b/src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/[id]/page.tsx @@ -0,0 +1,85 @@ +'use client' +import infoWabahPenyakit from '@/app/admin/(dashboard)/_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit'; +import colors from '@/con/colors'; +import { Box, Button, Image, Paper, Skeleton, Stack, Text } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; + + +function DetailInfoWabahPenyakitUser() { + const state = useProxy(infoWabahPenyakit); + const router = useRouter(); + const params = useParams(); + + useShallowEffect(() => { + state.findUnique.load(params?.id as string); + }, []); + + if (!state.findUnique.data) { + return ( + <Stack py={10}> + <Skeleton height={400} radius="md" /> + </Stack> + ); + } + + const data = state.findUnique.data; + + return ( + <Box py={10}> + {/* Tombol Back */} + <Button + variant="subtle" + onClick={() => router.back()} + leftSection={<IconArrowBack size={22} color={colors['blue-button']} />} + mb={15} + > + Kembali + </Button> + + {/* Wrapper Detail */} + <Paper + withBorder + w="100%" + bg={colors['white-1']} + p="lg" + radius="md" + shadow="sm" + > + <Stack gap="lg"> + {/* Judul */} + <Text fz="xl" fw="bold" c={colors['blue-button']} ta="center"> + {data.name || 'Kontak Darurat'} + </Text> + + {/* Gambar */} + {data.image?.link && ( + <Image + src={data.image.link} + alt={data.name} + radius="md" + maw={400} + mx="auto" + loading="lazy" + /> + )} + + {/* Deskripsi */} + <Box> + <Text fz="lg" fw="bold">Deskripsi</Text> + <Text + fz="md" + c="dimmed" + dangerouslySetInnerHTML={{ __html: data.deskripsiLengkap || '-' }} + style={{ wordBreak: "break-word", whiteSpace: "normal" }} + /> + </Box> + </Stack> + </Paper> + </Box> + ); +} + +export default DetailInfoWabahPenyakitUser; diff --git a/src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/page.tsx b/src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/page.tsx index d57913e3..d95545e3 100644 --- a/src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/page.tsx +++ b/src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/page.tsx @@ -2,10 +2,14 @@ import infoWabahPenyakit from '@/app/admin/(dashboard)/_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit'; import colors from '@/con/colors'; import { + Badge, Box, + Button, Center, + Divider, Grid, GridCol, + Group, Image, Pagination, Paper, @@ -13,27 +17,25 @@ import { Skeleton, Stack, Text, - TextInput, - Badge, - HoverCard, - Divider, - Group, + TextInput } from '@mantine/core'; -import { useShallowEffect } from '@mantine/hooks'; -import { IconSearch, IconInfoCircle } from '@tabler/icons-react'; +import { useDebouncedValue, useShallowEffect } from '@mantine/hooks'; +import { IconInfoCircle, IconSearch } from '@tabler/icons-react'; import { useState } from 'react'; import { useProxy } from 'valtio/utils'; import BackButton from '../../desa/layanan/_com/BackButto'; +import { useTransitionRouter } from 'next-view-transitions'; function Page() { const state = useProxy(infoWabahPenyakit); + const router = useTransitionRouter(); const [search, setSearch] = useState(''); - + const [debouncedSearch] = useDebouncedValue(search, 500) const { data, page, totalPages, loading, load } = state.findMany; useShallowEffect(() => { - load(page, 3, search); - }, [page, search]); + load(page, 3, debouncedSearch); + }, [page, debouncedSearch]); if (loading || !data) { return ( @@ -125,28 +127,9 @@ function Page() { <Text fz="sm" lh={1.5}> {v.deskripsiSingkat} </Text> - <HoverCard shadow="md" position="bottom" radius="md" width={300}> - <HoverCard.Target> - <Text - fz="sm" - fw={500} - c={colors['blue-button']} - style={{ cursor: 'pointer' }} - > - Lihat detail lengkap - </Text> - </HoverCard.Target> - <HoverCard.Dropdown> - <Text - fz="sm" - lh={1.6} - dangerouslySetInnerHTML={{ - __html: v.deskripsiLengkap, - }} - style={{wordBreak: "break-word", whiteSpace: "normal"}} - /> - </HoverCard.Dropdown> - </HoverCard> + <Button variant="light" radius="md" size="md" onClick={() => router.push(`/admin/kesehatan/info-wabah-penyakit/${v.id}`)}> + Selengkapnya + </Button> </Stack> </Paper> ))} @@ -154,17 +137,17 @@ function Page() { )} </Box> - - <Center> - <Pagination - value={page} - onChange={(newPage) => load(newPage)} - total={totalPages} - radius="xl" - size="md" - mt="lg" - /> - </Center> + + <Center> + <Pagination + value={page} + onChange={(newPage) => load(newPage)} + total={totalPages} + radius="xl" + size="md" + mt="lg" + /> + </Center> </Stack> ); diff --git a/src/app/darmasaba/(pages)/kesehatan/kontak-darurat/page.tsx b/src/app/darmasaba/(pages)/kesehatan/kontak-darurat/page.tsx index 216cd3d8..24238344 100644 --- a/src/app/darmasaba/(pages)/kesehatan/kontak-darurat/page.tsx +++ b/src/app/darmasaba/(pages)/kesehatan/kontak-darurat/page.tsx @@ -1,9 +1,9 @@ 'use client' -import { useState } from 'react'; -import { useProxy } from 'valtio/utils'; -import { useShallowEffect } from '@mantine/hooks'; +import kontakDarurat from '@/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat'; +import colors from '@/con/colors'; import { Box, + Button, Center, Grid, GridCol, @@ -15,23 +15,24 @@ import { Stack, Text, TextInput, - Tooltip, - Badge, + Tooltip } from '@mantine/core'; -import { IconSearch, IconPhone } from '@tabler/icons-react'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconBrandWhatsapp, IconSearch } from '@tabler/icons-react'; +import { useState } from 'react'; +import { useProxy } from 'valtio/utils'; import BackButton from '../../desa/layanan/_com/BackButto'; -import kontakDarurat from '@/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat'; -import colors from '@/con/colors'; +import { useDebouncedValue } from '@mantine/hooks'; function Page() { const state = useProxy(kontakDarurat); const [search, setSearch] = useState(''); - + const [debouncedSearch] = useDebouncedValue(search, 500) const { data, page, totalPages, loading, load } = state.findMany; useShallowEffect(() => { - load(page, 6, search); - }, [page, search]); + load(page, 3, debouncedSearch); + }, [page, debouncedSearch]); if (loading || !data) { return ( @@ -113,16 +114,16 @@ function Page() { {v.name} </Text> <Text fz="sm" c="dimmed" ta="center" lineClamp={3}> - <span style={{wordBreak: "break-word", whiteSpace: "normal"}} dangerouslySetInnerHTML={{ __html: v.deskripsi }} /> + <span style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: v.deskripsi }} /> </Text> - <Badge - color="blue" - leftSection={<IconPhone size={14} />} - variant="light" - mt="sm" - > - Panggil Sekarang - </Badge> + <Button + variant="light" + leftSection={<IconBrandWhatsapp size={18} />} + component="a" + href={`https://wa.me/${v.whatsapp.replace(/\D/g, '')}`} + target="_blank" + aria-label="Hubungi WhatsApp" + >WhatsApp</Button> </Stack> </Paper> ))} @@ -130,22 +131,20 @@ function Page() { )} </Box> - {totalPages > 1 && ( - <Center mt="xl"> - <Pagination - value={page} - onChange={(newPage) => load(newPage, 6, search)} - total={totalPages} - radius="xl" - size="md" - styles={{ - control: { - borderRadius: '999px', - }, - }} - /> - </Center> - )} + <Center mt="xl"> + <Pagination + value={page} + onChange={(newPage) => load(newPage, 3, search)} + total={totalPages} + size="lg" + radius="xl" + styles={{ + control: { + border: `1px solid ${colors['blue-button']}`, + }, + }} + /> + </Center> </Stack> ); } diff --git a/src/app/darmasaba/(pages)/kesehatan/penanganan-darurat/page.tsx b/src/app/darmasaba/(pages)/kesehatan/penanganan-darurat/page.tsx index 264edec7..3e3d3e10 100644 --- a/src/app/darmasaba/(pages)/kesehatan/penanganan-darurat/page.tsx +++ b/src/app/darmasaba/(pages)/kesehatan/penanganan-darurat/page.tsx @@ -17,7 +17,7 @@ import { TextInput, Tooltip } from '@mantine/core' -import { useShallowEffect } from '@mantine/hooks' +import { useDebouncedValue, useShallowEffect } from '@mantine/hooks' import { IconSearch } from '@tabler/icons-react' import { useState } from 'react' import { useProxy } from 'valtio/utils' @@ -26,12 +26,12 @@ import BackButton from '../../desa/layanan/_com/BackButto' function Page() { const state = useProxy(penangananDarurat) const [search, setSearch] = useState('') - + const [debouncedSearch] = useDebouncedValue(search, 500) const { data, page, totalPages, loading, load } = state.findMany useShallowEffect(() => { - load(page, 6, search) - }, [page, search]) + load(page, 3, debouncedSearch) + }, [page, debouncedSearch]) if (loading || !data) { return ( @@ -127,7 +127,7 @@ function Page() { c="dimmed" lineClamp={4} dangerouslySetInnerHTML={{ __html: v.deskripsi }} - style={{wordBreak: "break-word", whiteSpace: "normal"}} + style={{ wordBreak: "break-word", whiteSpace: "normal" }} /> </Box> </Stack> @@ -141,22 +141,21 @@ function Page() { )} </Box> - {totalPages > 1 && ( - <Center mt="xl"> - <Pagination - value={page} - onChange={(newPage) => load(newPage, 6, search)} - total={totalPages} - size="lg" - radius="xl" - styles={{ - control: { - border: `1px solid ${colors['blue-button']}`, - }, - }} - /> - </Center> - )} + <Center mt="xl"> + <Pagination + value={page} + onChange={(newPage) => load(newPage, 3, search)} + total={totalPages} + size="lg" + radius="xl" + styles={{ + control: { + border: `1px solid ${colors['blue-button']}`, + }, + }} + /> + </Center> + </Stack> ) } diff --git a/src/app/darmasaba/(pages)/kesehatan/posyandu/page.tsx b/src/app/darmasaba/(pages)/kesehatan/posyandu/page.tsx index 36fb6ee2..d94d031c 100644 --- a/src/app/darmasaba/(pages)/kesehatan/posyandu/page.tsx +++ b/src/app/darmasaba/(pages)/kesehatan/posyandu/page.tsx @@ -26,6 +26,16 @@ export default function Page() { ); } + if (data.length === 0) { + return ( + <Box py="xl" px={{ base: "md", md: 100 }}> + <Text fz="lg" fw="bold" c={colors["blue-button"]}> + Tidak ada posyandu yang ditemukan + </Text> + </Box> + ); + } + return ( <Stack pos="relative" bg={colors.Bg} py="xl" gap="xl"> <Box px={{ base: "md", md: 100 }}> @@ -111,10 +121,11 @@ export default function Page() { <IconCalendar size={18} stroke={1.5} /> <Text fz="sm" c="dimmed"> Jadwal:{" "} - <span style={{wordBreak: "break-word", whiteSpace: "normal"}} dangerouslySetInnerHTML={{ __html: v.jadwalPelayanan }} /> + <span style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: v.jadwalPelayanan }} /> </Text> </Flex> <Spoiler + key={`spoiler-${v.id}`} maxHeight={70} showLabel="Lihat selengkapnya" hideLabel="Sembunyikan" @@ -124,7 +135,7 @@ export default function Page() { fz="sm" lh={1.5} dangerouslySetInnerHTML={{ __html: v.deskripsi }} - style={{wordBreak: "break-word", whiteSpace: "normal"}} + style={{ wordBreak: "break-word", whiteSpace: "normal" }} /> </Spoiler> </Stack> diff --git a/src/app/darmasaba/(pages)/kesehatan/program-kesehatan/page.tsx b/src/app/darmasaba/(pages)/kesehatan/program-kesehatan/page.tsx index d92f71cb..458a9fa3 100644 --- a/src/app/darmasaba/(pages)/kesehatan/program-kesehatan/page.tsx +++ b/src/app/darmasaba/(pages)/kesehatan/program-kesehatan/page.tsx @@ -30,7 +30,7 @@ import BackButton from "../../desa/layanan/_com/BackButto"; import { useProxy } from "valtio/utils"; import programKesehatan from "@/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan"; import { useState } from "react"; -import { useShallowEffect } from "@mantine/hooks"; +import { useDebouncedValue, useShallowEffect } from "@mantine/hooks"; import { useRouter } from "next/navigation"; const manfaatProgram = [ @@ -58,11 +58,12 @@ export default function Page() { const state = useProxy(programKesehatan); const router = useRouter(); const [search, setSearch] = useState(""); + const [debouncedSearch] = useDebouncedValue(search, 500); // 500ms delay const { data, page, totalPages, loading, load } = state.findMany; useShallowEffect(() => { - load(page, 3, search); - }, [page, search]); + load(page, 3, debouncedSearch); + }, [page, debouncedSearch]); if (loading || !data) { return ( @@ -125,14 +126,18 @@ export default function Page() { className="hover-scale" > <Stack gap="md"> - <Image - src={v.image?.link} - alt={v.name} - radius="xl" - height={180} - fit="cover" - loading="lazy" - /> + <Box h={180} w="100%"> + <Image + src={v.image?.link} + alt={v.name} + radius="xl" + w="100%" + h="100%" + fit="cover" + loading="lazy" + /> + </Box> + <Box px="lg" pb="lg"> <Text fw="bold" @@ -147,7 +152,7 @@ export default function Page() { c="dimmed" lineClamp={3} dangerouslySetInnerHTML={{ __html: v.deskripsi }} - style={{wordBreak: "break-word", whiteSpace: "normal"}} + style={{ wordBreak: "break-word", whiteSpace: "normal" }} /> <Group justify="space-between" mt="md"> <Group gap="xs"> @@ -155,13 +160,13 @@ export default function Page() { <Text size="sm"> {v.createdAt ? new Date(v.createdAt).toLocaleDateString( - "id-ID", - { - day: "numeric", - month: "long", - year: "numeric", - } - ) + "id-ID", + { + day: "numeric", + month: "long", + year: "numeric", + } + ) : "Tanggal tidak tersedia"} </Text> </Group>