Fix UI Mobile User & Admin Menu Kesehatan, QC Menu Kesehatan

This commit is contained in:
2025-09-25 10:40:47 +08:00
parent 3e4a7a1c0a
commit cac146471a
32 changed files with 381 additions and 523 deletions

View File

@@ -850,8 +850,8 @@ model JadwalKegiatan {
syaratKetentuanJadwalKegiatanId String
dokumenjadwalkegiatan DokumenJadwalKegiatan @relation(fields: [dokumenJadwalKegiatanId], references: [id])
dokumenJadwalKegiatanId String
pendaftaranjadwalkegiatan PendaftaranJadwalKegiatan @relation(fields: [pendaftaranJadwalKegiatanId], references: [id])
pendaftaranJadwalKegiatanId String
pendaftaranjadwalkegiatan PendaftaranJadwalKegiatan? @relation(fields: [pendaftaranJadwalKegiatanId], references: [id])
pendaftaranJadwalKegiatanId String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime @default(now())

View File

@@ -26,14 +26,6 @@ const templateForm = z.object({
dokumenJadwalKegiatan: z.object({
content: z.string().min(1, "Content minimal 1 karakter"),
}),
pendaftaranJadwalKegiatan: z.object({
name: z.string().min(1, "Name minimal 1 karakter"),
tanggal: z.string().min(1, "Tanggal minimal 1 karakter"),
namaOrangtua: z.string().min(1, "Nama Orangtua minimal 1 karakter"),
nomor: z.string().min(1, "Nomor minimal 1 karakter"),
alamat: z.string().min(1, "Alamat minimal 1 karakter"),
catatan: z.string().min(1, "Catatan minimal 1 karakter"),
}),
});
const defaultForm = {
@@ -55,15 +47,7 @@ const defaultForm = {
},
dokumenJadwalKegiatan: {
content: "",
},
pendaftaranJadwalKegiatan: {
name: "",
tanggal: "",
namaOrangtua: "",
nomor: "",
alamat: "",
catatan: "",
},
}
};
const jadwalkegiatanState = proxy({
@@ -116,7 +100,6 @@ const jadwalkegiatanState = proxy({
deskripsijadwalkegiatan: true;
layananjadwalkegiatan: true;
dokumenjadwalkegiatan: true;
pendaftaranjadwalkegiatan: true;
};
}>[]
| null,
@@ -161,7 +144,6 @@ const jadwalkegiatanState = proxy({
layananjadwalkegiatan: true;
syaratketentuanjadwalkegiatan: true;
dokumenjadwalkegiatan: true;
pendaftaranjadwalkegiatan: true;
};
}> | null,
loading: false,
@@ -209,15 +191,7 @@ const jadwalkegiatanState = proxy({
},
dokumenJadwalKegiatan: {
content: data.dokumenjadwalkegiatan.content,
},
pendaftaranJadwalKegiatan: {
name: data.pendaftaranjadwalkegiatan.name,
tanggal: data.pendaftaranjadwalkegiatan.tanggal,
namaOrangtua: data.pendaftaranjadwalkegiatan.namaOrangtua,
nomor: data.pendaftaranjadwalkegiatan.nomor,
alamat: data.pendaftaranjadwalkegiatan.alamat,
catatan: data.pendaftaranjadwalkegiatan.catatan,
},
}
};
},
async submit() {
@@ -259,20 +233,6 @@ const jadwalkegiatanState = proxy({
content:
jadwalkegiatanState.edit.form.dokumenJadwalKegiatan.content,
},
pendaftaranJadwalKegiatan: {
name: jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.name,
tanggal:
jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.tanggal,
namaOrangtua:
jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan
.namaOrangtua,
nomor:
jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.nomor,
alamat:
jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.alamat,
catatan:
jadwalkegiatanState.edit.form.pendaftaranJadwalKegiatan.catatan,
},
};
const res = await fetch(

View File

@@ -114,12 +114,22 @@ function ListFasilitasKesehatan({ search }: { search: string }) {
filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>
<Text fw={500} truncate="end" lineClamp={1}>
{item.name}
</Text>
<Box w={150}>
<Text fw={500} truncate="end" lineClamp={1}>
{item.name}
</Text>
</Box>
</TableTd>
<TableTd>
<Box w={150}>
{item.dokterdantenagamedis?.name || '-'}
</Box>
</TableTd>
<TableTd>
<Box w={150}>
{item.tarifdanlayanan?.layanan || '-'}
</Box>
</TableTd>
<TableTd>{item.dokterdantenagamedis?.name || '-'}</TableTd>
<TableTd>{item.tarifdanlayanan?.layanan || '-'}</TableTd>
<TableTd>
<Button
variant="light"

View File

@@ -149,16 +149,30 @@ function ListGrafikHasilKepuasanMasyarakat({ search }: { search: string }) {
{filteredData.length > 0 ? (
filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.nama}</TableTd>
<TableTd>
{new Date(item.tanggal).toLocaleDateString('id-ID', {
day: '2-digit',
month: 'long',
year: 'numeric',
})}
<Box w={150}>
{item.nama}
</Box>
</TableTd>
<TableTd>
<Box w={150}>
{new Date(item.tanggal).toLocaleDateString('id-ID', {
day: '2-digit',
month: 'long',
year: 'numeric',
})}
</Box>
</TableTd>
<TableTd>
<Box w={150}>
{item.jenisKelamin}
</Box>
</TableTd>
<TableTd>
<Box w={150}>
{item.penyakit}
</Box>
</TableTd>
<TableTd>{item.jenisKelamin}</TableTd>
<TableTd>{item.penyakit}</TableTd>
<TableTd>
<Button
variant="light"
@@ -212,24 +226,26 @@ function ListGrafikHasilKepuasanMasyarakat({ search }: { search: string }) {
<Paper bg={colors['white-1']} p={'md'}>
<Title pb={10} order={4}>Grafik Hasil Kepuasan Masyarakat</Title>
{mounted && diseaseChartData.length > 0 ? (
<BarChart
width={isMobile ? 450 : isTablet ? 500 : 550}
height={350}
data={diseaseChartData}
>
<XAxis
dataKey="name"
tick={{ fontSize: 12 }}
interval={0}
angle={-45}
textAnchor="end"
height={70}
/>
<YAxis />
<ChartTooltip />
<Legend />
<Bar dataKey="count" fill={colors['blue-button']} name="Jumlah Kasus" />
</BarChart>
<Center>
<BarChart
width={isMobile ? 320 : isTablet ? 600 : 800} // kecilin biar muat
height={350}
data={diseaseChartData}
>
<XAxis
dataKey="name"
tick={{ fontSize: 12 }}
interval={0}
angle={-45}
textAnchor="end"
height={70}
/>
<YAxis />
<ChartTooltip />
<Legend />
<Bar dataKey="count" fill={colors['blue-button']} name="Jumlah Kasus" />
</BarChart>
</Center>
) : (
<Text c="dimmed">Belum ada data untuk ditampilkan dalam grafik</Text>
)}

View File

@@ -41,14 +41,6 @@ interface JadwalKegiatanFormBase {
dokumenJadwalKegiatan: {
content: string;
};
pendaftaranJadwalKegiatan: {
name: string;
tanggal: string;
namaOrangtua: string;
nomor: string;
alamat: string;
catatan: string;
};
}
function EditJadwalKegiatan() {
@@ -76,14 +68,6 @@ function EditJadwalKegiatan() {
dokumenJadwalKegiatan: {
content: stateJadwalKegiatan.edit.form.dokumenJadwalKegiatan?.content || '',
},
pendaftaranJadwalKegiatan: {
name: stateJadwalKegiatan.edit.form.pendaftaranJadwalKegiatan?.name || '',
tanggal: stateJadwalKegiatan.edit.form.pendaftaranJadwalKegiatan?.tanggal || '',
namaOrangtua: stateJadwalKegiatan.edit.form.pendaftaranJadwalKegiatan?.namaOrangtua || '',
nomor: stateJadwalKegiatan.edit.form.pendaftaranJadwalKegiatan?.nomor || '',
alamat: stateJadwalKegiatan.edit.form.pendaftaranJadwalKegiatan?.alamat || '',
catatan: stateJadwalKegiatan.edit.form.pendaftaranJadwalKegiatan?.catatan || '',
},
});
useEffect(() => {
@@ -115,14 +99,6 @@ function EditJadwalKegiatan() {
dokumenJadwalKegiatan: {
content: form.dokumenJadwalKegiatan?.content || '',
},
pendaftaranJadwalKegiatan: {
name: form.pendaftaranJadwalKegiatan?.name || '',
tanggal: form.pendaftaranJadwalKegiatan?.tanggal || '',
namaOrangtua: form.pendaftaranJadwalKegiatan?.namaOrangtua || '',
nomor: form.pendaftaranJadwalKegiatan?.nomor || '',
alamat: form.pendaftaranJadwalKegiatan?.alamat || '',
catatan: form.pendaftaranJadwalKegiatan?.catatan || '',
},
});
}
} catch (error) {
@@ -142,8 +118,7 @@ function EditJadwalKegiatan() {
deskripsiJadwalKegiatan: { ...formData.deskripsiJadwalKegiatan },
layananJadwalKegiatan: { ...formData.layananJadwalKegiatan },
syaratKetentuanJadwalKegiatan: { ...formData.syaratKetentuanJadwalKegiatan },
dokumenJadwalKegiatan: { ...formData.dokumenJadwalKegiatan },
pendaftaranJadwalKegiatan: { ...formData.pendaftaranJadwalKegiatan },
dokumenJadwalKegiatan: { ...formData.dokumenJadwalKegiatan }
};
const success = await stateJadwalKegiatan.edit.submit();
@@ -252,7 +227,7 @@ function EditJadwalKegiatan() {
{/* Dokumen */}
<Box>
<Text fz="md" fw="bold">Dokumen Jadwal Kegiatan</Text>
<Text fz="md" fw="bold">Dokumen Yang Perlu Dibawa</Text>
<EditEditor
value={formData.dokumenJadwalKegiatan.content}
onChange={(val) => setFormData((prev) => ({
@@ -262,41 +237,6 @@ function EditJadwalKegiatan() {
/>
</Box>
{/* Pendaftaran */}
<Box>
<Text fz="md" fw="bold">Pendaftaran Jadwal Kegiatan</Text>
<TextInput label="Nama" value={formData.pendaftaranJadwalKegiatan.name}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, name: e.target.value }
}))}
/>
<TextInput type="date" label="Tanggal" value={formData.pendaftaranJadwalKegiatan.tanggal}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, tanggal: e.target.value }
}))}
/>
<TextInput label="Nama Orangtua" value={formData.pendaftaranJadwalKegiatan.namaOrangtua}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, namaOrangtua: e.target.value }
}))}
/>
<TextInput label="Nomor" value={formData.pendaftaranJadwalKegiatan.nomor}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, nomor: e.target.value }
}))}
/>
<TextInput label="Alamat" value={formData.pendaftaranJadwalKegiatan.alamat}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, alamat: e.target.value }
}))}
/>
<TextInput label="Catatan" value={formData.pendaftaranJadwalKegiatan.catatan}
onChange={(e) => setFormData((prev) => ({
...prev, pendaftaranJadwalKegiatan: { ...prev.pendaftaranJadwalKegiatan, catatan: e.target.value }
}))}
/>
</Box>
{/* Submit */}
<Group justify="right">
<Button

View File

@@ -109,18 +109,7 @@ function DetailJadwalKegiatan() {
<Text fz="lg" fw="bold">Dokumen</Text>
<Text fz="md" c="dimmed" dangerouslySetInnerHTML={{ __html: data.dokumenjadwalkegiatan.content }} />
</Box>
{/* Prosedur Pendaftaran */}
<Box>
<Text fz="lg" fw="bold">Prosedur Pendaftaran</Text>
<Text fz="md" c="dimmed">{data.pendaftaranjadwalkegiatan.name}</Text>
<Text fz="md" c="dimmed">{data.pendaftaranjadwalkegiatan.tanggal}</Text>
<Text fz="md" c="dimmed">{data.pendaftaranjadwalkegiatan.namaOrangtua}</Text>
<Text fz="md" c="dimmed">{data.pendaftaranjadwalkegiatan.nomor}</Text>
<Text fz="md" c="dimmed">{data.pendaftaranjadwalkegiatan.alamat}</Text>
<Text fz="md" c="dimmed" dangerouslySetInnerHTML={{ __html: data.pendaftaranjadwalkegiatan.catatan }} />
</Box>
{/* Aksi */}
<Group gap="sm">
<Tooltip label="Hapus Data" withArrow position="top">

View File

@@ -42,15 +42,7 @@ function CreateJadwalKegiatan() {
},
dokumenJadwalKegiatan: {
content: '',
},
pendaftaranJadwalKegiatan: {
name: '',
tanggal: '',
namaOrangtua: '',
nomor: '',
alamat: '',
catatan: '',
},
}
};
};
@@ -173,7 +165,7 @@ function CreateJadwalKegiatan() {
</Box>
<Box>
<Text fz="md" fw="bold" mb="sm">Dokumen</Text>
<Text fz="md" fw="bold" mb="sm">Dokumen Yang Perlu Dibawa</Text>
<CreateEditor
value={stateJadwalKegiatan.create.form.dokumenJadwalKegiatan.content}
onChange={(e) => {
@@ -181,65 +173,6 @@ function CreateJadwalKegiatan() {
}}
/>
</Box>
<Box>
<Text fz="md" fw="bold" mb="sm">Pendaftaran Jadwal Kegiatan</Text>
<TextInput
label="Nama"
required
placeholder="Masukkan nama"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.name}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.name = e.target.value;
}}
/>
<TextInput
type="date"
required
label="Tanggal"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.tanggal}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.tanggal = e.target.value;
}}
/>
<TextInput
label="Nama Orangtua"
required
placeholder="Masukkan nama orangtua"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.namaOrangtua}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.namaOrangtua = e.target.value;
}}
/>
<TextInput
label="Nomor"
required
placeholder="Masukkan nomor"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.nomor}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.nomor = e.target.value;
}}
/>
<TextInput
label="Alamat"
required
placeholder="Masukkan alamat"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.alamat}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.alamat = e.target.value;
}}
/>
<TextInput
label="Catatan"
required
placeholder="Masukkan catatan"
value={stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.catatan}
onChange={(e) => {
stateJadwalKegiatan.create.form.pendaftaranJadwalKegiatan.catatan = e.target.value;
}}
/>
</Box>
{/* Save Button */}
<Group justify="right">
<Button

View File

@@ -111,11 +111,14 @@ function ListJadwalKegiatan({ search }: { search: string }) {
filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>
<Text fw={500} truncate="end" lineClamp={1}>
{item.informasijadwalkegiatan.name}
</Text>
<Box w={150}>
<Text fw={500} truncate="end" lineClamp={1}>
{item.informasijadwalkegiatan.name}
</Text>
</Box>
</TableTd>
<TableTd>
<Box w={150}>
{new Date(item.informasijadwalkegiatan.tanggal).toLocaleDateString(
'id-ID',
{
@@ -124,12 +127,19 @@ function ListJadwalKegiatan({ search }: { search: string }) {
year: 'numeric',
}
)}
</Box>
</TableTd>
<TableTd>{item.informasijadwalkegiatan.waktu}</TableTd>
<TableTd>
<Text truncate fz="sm" c="dimmed">
{item.informasijadwalkegiatan.lokasi}
</Text>
<Box w={150}>
{item.informasijadwalkegiatan.waktu}
</Box>
</TableTd>
<TableTd>
<Box w={150}>
<Text truncate fz="sm" c="dimmed">
{item.informasijadwalkegiatan.lokasi}
</Text>
</Box>
</TableTd>
<TableTd>
<Button

View File

@@ -124,22 +124,32 @@ function ListKelahiran({ search }: { search: string }) {
filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>
<Box w={150}>
<Text fw={500} truncate="end" lineClamp={1}>
{item.nama}
</Text>
</Box>
</TableTd>
<TableTd>
<Box w={150}>
{new Date(item.tanggal).toLocaleDateString('id-ID', {
day: '2-digit',
month: 'long',
year: 'numeric',
})}
</Box>
</TableTd>
<TableTd>{item.jenisKelamin}</TableTd>
<TableTd>
<Box w={150}>
{item.jenisKelamin}
</Box>
</TableTd>
<TableTd>
<Box w={150}>
<Text truncate fz="sm" c="dimmed">
{item.alamat}
</Text>
</Box>
</TableTd>
<TableTd>
<Button

View File

@@ -13,152 +13,150 @@ import colors from '@/con/colors';
function DetailKematian() {
const state = useProxy(persentaseKelahiranKematian.kematian);
const [modalHapus, setModalHapus] = useState(false);
const [selectedId, setSelectedId] = useState<string | null>(null);
const params = useParams();
const router = useRouter();
const state = useProxy(persentaseKelahiranKematian.kematian);
const [modalHapus, setModalHapus] = useState(false);
const [selectedId, setSelectedId] = useState<string | null>(null);
const params = useParams();
const router = useRouter();
useShallowEffect(() => {
state.findUnique.load(params?.id as string);
}, []);
useShallowEffect(() => {
state.findUnique.load(params?.id as string);
}, []);
const handleHapus = () => {
if (selectedId) {
state.delete.byId(selectedId);
setModalHapus(false);
setSelectedId(null);
router.push("/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran");
}
};
const handleHapus = () => {
if (selectedId) {
state.delete.byId(selectedId);
setModalHapus(false);
setSelectedId(null);
router.push("/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kelahiran");
}
};
if (!state.findUnique.data) {
return (
<Stack py={10}>
<Skeleton height={500} radius="md" />
</Stack>
);
}
if (!state.findUnique.data) {
return (
<Stack py={10}>
<Skeleton height={500} radius="md" />
</Stack>
);
}
const data = state.findUnique.data;
const data = state.findUnique.data;
return (
<Box py={10}>
{/* Tombol kembali */}
<Button
variant="subtle"
onClick={() => router.back()}
leftSection={<IconArrowBack size={24} color={colors['blue-button']} />}
mb={15}
>
Kembali
</Button>
return (
<Box py={10}>
{/* Tombol kembali */}
<Button
variant="subtle"
onClick={() => router.back()}
leftSection={<IconArrowBack size={24} color={colors['blue-button']} />}
mb={15}
>
Kembali
</Button>
<Paper
withBorder
w={{ base: "100%", md: "50%" }}
bg={colors['white-1']}
p="lg"
radius="md"
shadow="sm"
>
<Stack gap="md">
<Text fz="2xl" fw="bold" c={colors['blue-button']}>
Detail Data Kematian
</Text>
<Paper
withBorder
w={{ base: "100%", md: "50%" }}
bg={colors['white-1']}
p="lg"
radius="md"
shadow="sm"
>
<Stack gap="md">
<Text fz="2xl" fw="bold" c={colors['blue-button']}>
Detail Data Kematian
</Text>
<Paper bg="#ECEEF8" p="md" radius="md" shadow="xs">
<Stack gap="sm">
<Box>
<Text fz="lg" fw="bold">Nama</Text>
<Text fz="md" c="dimmed">{data?.nama || '-'}</Text>
</Box>
<Paper bg="#ECEEF8" p="md" radius="md" shadow="xs">
<Stack gap="sm">
<Box>
<Text fz="lg" fw="bold">Nama</Text>
<Text fz="md" c="dimmed">{data?.nama || '-'}</Text>
</Box>
<Box>
<Text fz="lg" fw="bold">Tanggal</Text>
<Text fz="md" c="dimmed">
{data?.tanggal instanceof Date
? data.tanggal.toLocaleDateString('id-ID', {
day: '2-digit',
month: 'long',
year: 'numeric'
})
: data?.tanggal || '-'}
</Text>
</Box>
<Box>
<Text fz="lg" fw="bold">Tanggal</Text>
<Text fz="md" c="dimmed">
{new Date(data.tanggal).toLocaleDateString("id-ID", {
day: "2-digit",
month: "long",
year: "numeric",
})}
</Text>
</Box>
<Box>
<Text fz="lg" fw="bold">Jenis Kelamin</Text>
<Text fz="md" c="dimmed">{data?.jenisKelamin || '-'}</Text>
</Box>
<Box>
<Text fz="lg" fw="bold">Jenis Kelamin</Text>
<Text fz="md" c="dimmed">{data?.jenisKelamin || '-'}</Text>
</Box>
<Box>
<Text fz="lg" fw="bold">Alamat</Text>
<Text fz="md" c="dimmed">{data?.alamat || '-'}</Text>
</Box>
<Box>
<Text fz="lg" fw="bold">Alamat</Text>
<Text fz="md" c="dimmed">{data?.alamat || '-'}</Text>
</Box>
<Box>
<Text fz="lg" fw="bold">Penyebab</Text>
<Text fz="md" c="dimmed" dangerouslySetInnerHTML={{ __html: data?.penyebab || '-' }} />
</Box>
<Box>
<Text fz="lg" fw="bold">Penyebab</Text>
<Text fz="md" c="dimmed" dangerouslySetInnerHTML={{ __html: data?.penyebab || '-' }} />
</Box>
<Group gap="sm">
<Tooltip label="Hapus Data" withArrow position="top">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Group gap="sm">
<Tooltip label="Hapus Data" withArrow position="top">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Tooltip label="Edit Data" withArrow position="top">
<Button
color="green"
onClick={() => router.push(
`/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/${data.id}/edit`
)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>
</Stack>
</Paper>
<Tooltip label="Edit Data" withArrow position="top">
<Button
color="green"
onClick={() => router.push(
`/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian/kematian/${data.id}/edit`
)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>
</Stack>
</Paper>
<ModalKonfirmasiHapus
opened={modalHapus}
onClose={() => setModalHapus(false)}
onConfirm={handleHapus}
text="Apakah Anda yakin ingin menghapus data ini?"
/>
</Box>
);
<ModalKonfirmasiHapus
opened={modalHapus}
onClose={() => setModalHapus(false)}
onConfirm={handleHapus}
text="Apakah Anda yakin ingin menghapus data ini?"
/>
</Box>
);
}

View File

@@ -122,19 +122,33 @@ function ListKematian({ search }: { search: string }) {
filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>
<Box w={150}>
<Text fw={500} truncate="end" lineClamp={1}>
{item.nama}
</Text>
</Box>
</TableTd>
<TableTd>
<Box w={150}>
{new Date(item.tanggal).toLocaleDateString('id-ID', {
day: '2-digit',
month: 'long',
year: 'numeric',
})}
</Box>
</TableTd>
<TableTd>
<Box w={150}>
{item.jenisKelamin}
</Box>
</TableTd>
<TableTd>
<Box w={150}>
<Text truncate fz="sm" c="dimmed">
{item.alamat}
</Text>
</Box>
</TableTd>
<TableTd>{item.jenisKelamin}</TableTd>
<TableTd>{item.alamat}</TableTd>
<TableTd>
<Button
variant="light"

View File

@@ -4,7 +4,7 @@ import {
Box,
Button,
Center,
Image,
Group,
Pagination,
Paper,
Skeleton,
@@ -17,16 +17,15 @@ import {
TableTr,
Text,
Title,
Tooltip,
Group,
Tooltip
} from '@mantine/core';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import HeaderSearch from '../../_com/header';
import { useRouter } from 'next/navigation';
import { useProxy } from 'valtio/utils';
import infoWabahPenyakit from '../../_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import HeaderSearch from '../../_com/header';
import infoWabahPenyakit from '../../_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit';
function InfoWabahPenyakit() {
const [search, setSearch] = useState("");
@@ -96,7 +95,6 @@ function ListInfoWabahPenyakit({ search }: { search: string }) {
<TableTr>
<TableTh>Judul</TableTh>
<TableTh>Deskripsi Singkat</TableTh>
<TableTh>Image</TableTh>
<TableTh>Aksi</TableTh>
</TableTr>
</TableThead>
@@ -105,17 +103,18 @@ function ListInfoWabahPenyakit({ search }: { search: string }) {
filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>
<Text fw={500} truncate="end" lineClamp={1}>
{item.name}
</Text>
<Box w={200}>
<Text fw={500} truncate="end" lineClamp={1}>
{item.name}
</Text>
</Box>
</TableTd>
<TableTd>
<Text truncate fz="sm" c="dimmed">
{item.deskripsiSingkat}
</Text>
</TableTd>
<TableTd>
<Image w={100} src={item.image?.link} alt="image" radius="md" loading="lazy"/>
<Box w={200}>
<Text truncate fz="sm" c="dimmed">
{item.deskripsiSingkat}
</Text>
</Box>
</TableTd>
<TableTd>
<Button

View File

@@ -4,7 +4,7 @@ import {
Box,
Button,
Center,
Image,
Group,
Pagination,
Paper,
Skeleton,
@@ -17,7 +17,7 @@ import {
TableTr,
Text,
Title,
Tooltip,
Tooltip
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
@@ -71,7 +71,7 @@ function ListKontakDarurat({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
{/* Judul + Tombol Tambah */}
<Stack mb="md" gap="sm">
<Box display="flex" style={{ justifyContent: "space-between", alignItems: "center" }}>
<Group justify="space-between">
<Title order={4}>Daftar Kontak Darurat</Title>
<Tooltip label="Tambah Kontak Darurat" withArrow>
<Button
@@ -83,7 +83,7 @@ function ListKontakDarurat({ search }: { search: string }) {
Tambah Baru
</Button>
</Tooltip>
</Box>
</Group>
</Stack>
{/* Tabel */}
@@ -93,7 +93,6 @@ function ListKontakDarurat({ search }: { search: string }) {
<TableTr>
<TableTh>Judul</TableTh>
<TableTh>Deskripsi</TableTh>
<TableTh>Image</TableTh>
<TableTh>Aksi</TableTh>
</TableTr>
</TableThead>
@@ -102,15 +101,16 @@ function ListKontakDarurat({ search }: { search: string }) {
filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>
<Text fw={500} truncate="end" lineClamp={1}>
{item.name}
</Text>
<Box w={150}>
<Text fw={500} truncate="end" lineClamp={1}>
{item.name}
</Text>
</Box>
</TableTd>
<TableTd>
<Text truncate fz="sm" c="dimmed" lineClamp={1} dangerouslySetInnerHTML={{ __html: item.deskripsi }} />
</TableTd>
<TableTd>
<Image w={100} src={item.image?.link} alt="image" radius="md" loading="lazy"/>
<Box w={200}>
<Text truncate fz="sm" c="dimmed" lineClamp={1} dangerouslySetInnerHTML={{ __html: item.deskripsi }} />
</Box>
</TableTd>
<TableTd>
<Button

View File

@@ -5,7 +5,6 @@ import {
Button,
Center,
Group,
Image,
Pagination,
Paper,
Skeleton,
@@ -18,15 +17,15 @@ import {
TableTr,
Text,
Title,
Tooltip,
Tooltip
} from '@mantine/core';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import HeaderSearch from '../../_com/header';
import { useRouter } from 'next/navigation';
import { useProxy } from 'valtio/utils';
import { useShallowEffect } from '@mantine/hooks';
import penangananDarurat from '../../_state/kesehatan/penanganan-darurat/penangananDarurat';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import HeaderSearch from '../../_com/header';
import penangananDarurat from '../../_state/kesehatan/penanganan-darurat/penangananDarurat';
function PenangananDarurat() {
const [search, setSearch] = useState("");
@@ -91,7 +90,6 @@ function ListPenangananDarurat({ search }: { search: string }) {
<TableTr>
<TableTh>Judul</TableTh>
<TableTh>Deskripsi</TableTh>
<TableTh>Gambar</TableTh>
<TableTh>Aksi</TableTh>
</TableTr>
</TableThead>
@@ -100,21 +98,22 @@ function ListPenangananDarurat({ search }: { search: string }) {
filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>
<Text fw={500} truncate="end" lineClamp={1}>
{item.name}
</Text>
<Box w={150}>
<Text fw={500} truncate="end" lineClamp={1}>
{item.name}
</Text>
</Box>
</TableTd>
<TableTd>
<Text
fz="sm"
c="dimmed"
truncate
lineClamp={1}
<Box w={200}>
<Text
fz="sm"
c="dimmed"
truncate
lineClamp={1}
dangerouslySetInnerHTML={{ __html: item.deskripsi }}
/>
</TableTd>
<TableTd>
<Image w={100} src={item.image?.link} alt="image" loading="lazy"/>
</Box>
</TableTd>
<TableTd>
<Button

View File

@@ -107,21 +107,28 @@ function ListPosyandu({ search }: { search: string }) {
filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd style={{ width: '25%' }}>
<Box w={150}>
<Text fw={500} truncate="end" lineClamp={1}>
{item.name}
</Text>
</Box>
</TableTd>
<TableTd style={{ width: '20%' }}>
<Box w={150}>
<Text truncate fz="sm" c="dimmed">
{item.nomor || '-'}
</Text>
</Box>
</TableTd>
<TableTd style={{ width: '30%' }}>
<Box w={150}>
<Text
lineClamp={1}
truncate
fz="sm"
dangerouslySetInnerHTML={{ __html: item.deskripsi }}
/>
</Box>
</TableTd>
<TableTd style={{ width: '15%' }}>
<Button

View File

@@ -5,7 +5,6 @@ import {
Button,
Center,
Group,
Image,
Pagination,
Paper,
Skeleton,
@@ -18,15 +17,15 @@ import {
TableTr,
Text,
Title,
Tooltip,
Tooltip
} from '@mantine/core';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import HeaderSearch from '../../_com/header';
import { useRouter } from 'next/navigation';
import programKesehatan from '../../_state/kesehatan/program-kesehatan/programKesehatan';
import { useProxy } from 'valtio/utils';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import HeaderSearch from '../../_com/header';
import programKesehatan from '../../_state/kesehatan/program-kesehatan/programKesehatan';
function ProgramKesehatan() {
const [search, setSearch] = useState("");
@@ -90,7 +89,7 @@ function ListProgramKesehatan({ search }: { search: string }) {
<TableTr>
<TableTh>Judul</TableTh>
<TableTh>Deskripsi Singkat</TableTh>
<TableTh>Image</TableTh>
<TableTh>Deskripsi</TableTh>
<TableTh>Aksi</TableTh>
</TableTr>
</TableThead>
@@ -105,11 +104,13 @@ function ListProgramKesehatan({ search }: { search: string }) {
</TableTd>
<TableTd>
<Box w={200}>
<Text fz="sm" truncate="end" lineClamp={2} dangerouslySetInnerHTML={{ __html: item.deskripsiSingkat }} />
<Text fz="sm" truncate="end" lineClamp={1} dangerouslySetInnerHTML={{ __html: item.deskripsiSingkat }} />
</Box>
</TableTd>
<TableTd>
<Image w={100} src={item.image?.link} alt="image" radius="md" loading="lazy"/>
<Box w={200}>
<Text fz="sm" truncate="end" lineClamp={1} dangerouslySetInnerHTML={{ __html: item.deskripsi }} />
</Box>
</TableTd>
<TableTd>
<Button

View File

@@ -78,8 +78,9 @@ function DetailPuskesmas() {
<Box>
<Text fz="lg" fw="bold">Jam Operasional</Text>
<Text fz="md" c="dimmed">{data?.jam?.workDays || '-'}</Text>
<Text fz="md" c="dimmed">{data?.jam?.weekDays || '-'}</Text>
<Text fz="md" c="dimmed">Senin - Jumat</Text>
<Text fz="md" c="dimmed">{data?.jam?.workDays || '-'} - {data?.jam?.weekDays || '-'}</Text>
<Text fz="md" c="dimmed">Sabtu - Minggu / Hari Libur</Text>
<Text fz="md" c="dimmed">{data?.jam?.holiday || '-'}</Text>
</Box>
@@ -94,9 +95,13 @@ function DetailPuskesmas() {
<Box>
<Text fz="lg" fw="bold">Kontak</Text>
<Text fz="md" c="dimmed">Kontak Puskesmas</Text>
<Text fz="md" c="dimmed">{data?.kontak?.kontakPuskesmas || '-'}</Text>
<Text fz="md" c="dimmed">Email</Text>
<Text fz="md" c="dimmed">{data?.kontak?.email || '-'}</Text>
<Text fz="md" c="dimmed">Facebook</Text>
<Text fz="md" c="dimmed">{data?.kontak?.facebook || '-'}</Text>
<Text fz="md" c="dimmed">Kontak UGD</Text>
<Text fz="md" c="dimmed">{data?.kontak?.kontakUGD || '-'}</Text>
</Box>

View File

@@ -5,7 +5,6 @@ import {
Button,
Center,
Group,
Image,
Pagination,
Paper,
Skeleton,
@@ -18,7 +17,7 @@ import {
TableTr,
Text,
Title,
Tooltip,
Tooltip
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
@@ -90,7 +89,7 @@ function ListPuskesmas({ search }: { search: string }) {
<TableTr>
<TableTh>Nama Puskesmas</TableTh>
<TableTh>Alamat</TableTh>
<TableTh>Image</TableTh>
<TableTh>Kontak</TableTh>
<TableTh>Aksi</TableTh>
</TableTr>
</TableThead>
@@ -99,13 +98,25 @@ function ListPuskesmas({ search }: { search: string }) {
filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>
<Text fw={500} truncate="end" lineClamp={1}>
{item.name}
</Text>
<Box w={150}>
<Text fw={500} truncate="end" lineClamp={1}>
{item.name}
</Text>
</Box>
</TableTd>
<TableTd>{item.alamat}</TableTd>
<TableTd>
<Image w={100} src={item.image.link} alt="image" radius="md" loading="lazy"/>
<Box w={150}>
<Text truncate fz="sm" c="dimmed" lineClamp={1}>
{item.alamat}
</Text>
</Box>
</TableTd>
<TableTd>
<Box w={150}>
<Text truncate fz="sm" c="dimmed" lineClamp={1}>
{item.kontak.kontakPuskesmas}
</Text>
</Box>
</TableTd>
<TableTd>
<Button

View File

@@ -8,7 +8,6 @@ type JadwalKegiatanInput = {
layananJadwalKegiatan: { content: string };
syaratKetentuanJadwalKegiatan: { content: string };
dokumenJadwalKegiatan: { content: string };
pendaftaranJadwalKegiatan: { name: string, tanggal: string, namaOrangtua: string, nomor: string, alamat: string, catatan: string };
}
const jadwalKegiatanCreate = async (context: Context) => {
@@ -21,16 +20,14 @@ const jadwalKegiatanCreate = async (context: Context) => {
layananJadwalKegiatan,
syaratKetentuanJadwalKegiatan,
dokumenJadwalKegiatan,
pendaftaranJadwalKegiatan,
} = body;
const [createdInformasiJadwalKegiatan, createdDeskripsiJadwalKegiatan, createdLayananJadwalKegiatan, createdSyaratKetentuanJadwalKegiatan, createdDokumenJadwalKegiatan, createdPendaftaranJadwalKegiatan] = await Promise.all([
const [createdInformasiJadwalKegiatan, createdDeskripsiJadwalKegiatan, createdLayananJadwalKegiatan, createdSyaratKetentuanJadwalKegiatan, createdDokumenJadwalKegiatan] = await Promise.all([
prisma.informasiJadwalKegiatan.create({ data: informasiJadwalKegiatan }),
prisma.deskripsiJadwalKegiatan.create({ data: deskripsiJadwalKegiatan }),
prisma.layananJadwalKegiatan.create({ data: layananJadwalKegiatan }),
prisma.syaratKetentuanJadwalKegiatan.create({ data: syaratKetentuanJadwalKegiatan }),
prisma.dokumenJadwalKegiatan.create({ data: dokumenJadwalKegiatan }),
prisma.pendaftaranJadwalKegiatan.create({ data: pendaftaranJadwalKegiatan }),
])
const jadwalKegiatan = await prisma.jadwalKegiatan.create({
@@ -41,7 +38,6 @@ const jadwalKegiatanCreate = async (context: Context) => {
layananJadwalKegiatanId: createdLayananJadwalKegiatan.id,
syaratKetentuanJadwalKegiatanId: createdSyaratKetentuanJadwalKegiatan.id,
dokumenJadwalKegiatanId: createdDokumenJadwalKegiatan.id,
pendaftaranJadwalKegiatanId: createdPendaftaranJadwalKegiatan.id,
},
include: {
informasijadwalkegiatan: true,
@@ -49,7 +45,6 @@ const jadwalKegiatanCreate = async (context: Context) => {
layananjadwalkegiatan: true,
syaratketentuanjadwalkegiatan: true,
dokumenjadwalkegiatan: true,
pendaftaranjadwalkegiatan: true,
}
})
return {

View File

@@ -19,7 +19,6 @@ const jadwalKegiatanDelete = async (context: Context) => {
layananjadwalkegiatan: true,
syaratketentuanjadwalkegiatan: true,
dokumenjadwalkegiatan: true,
pendaftaranjadwalkegiatan: true,
}
})

View File

@@ -20,7 +20,6 @@ export default async function jadwalKegiatanFindMany(context: Context) {
{layananjadwalkegiatan: { content: { contains: search, mode: "insensitive" } } },
{syaratketentuanjadwalkegiatan: { content: { contains: search, mode: "insensitive" } } },
{dokumenjadwalkegiatan: { content: { contains: search, mode: "insensitive" } } },
{pendaftaranjadwalkegiatan: { content: { contains: search, mode: "insensitive" } } },
];
}
try {
@@ -33,8 +32,7 @@ export default async function jadwalKegiatanFindMany(context: Context) {
layananjadwalkegiatan: true,
syaratketentuanjadwalkegiatan: true,
dokumenjadwalkegiatan: true,
pendaftaranjadwalkegiatan: true,
},
},
skip,
take: limit,
orderBy: { createdAt: "desc" },

View File

@@ -28,7 +28,6 @@ export default async function jadwalKegiatanFindUnique(request: Request) {
layananjadwalkegiatan: true,
syaratketentuanjadwalkegiatan: true,
dokumenjadwalkegiatan: true,
pendaftaranjadwalkegiatan: true,
}
})

View File

@@ -30,14 +30,6 @@ const JadwalKegiatan = new Elysia({
dokumenJadwalKegiatan: t.Object({
content: t.String(),
}),
pendaftaranJadwalKegiatan: t.Object({
name: t.String(),
tanggal: t.String(),
namaOrangtua: t.String(),
nomor: t.String(),
alamat: t.String(),
catatan: t.String(),
}),
}),
})
.get("/find-many", jadwalKegiatanFindMany)
@@ -75,14 +67,6 @@ const JadwalKegiatan = new Elysia({
dokumenJadwalKegiatan: t.Object({
content: t.String(),
}),
pendaftaranJadwalKegiatan: t.Object({
name: t.String(),
tanggal: t.String(),
namaOrangtua: t.String(),
nomor: t.String(),
alamat: t.String(),
catatan: t.String(),
}),
}),
}
);

View File

@@ -13,14 +13,6 @@ type JadwalKegiatanUpdateInput = {
layananJadwalKegiatan: { content: string };
syaratKetentuanJadwalKegiatan: { content: string };
dokumenJadwalKegiatan: { content: string };
pendaftaranJadwalKegiatan: {
name: string;
tanggal: string;
namaOrangtua: string;
nomor: string;
alamat: string;
catatan: string;
};
};
const jadwalKegiatanUpdate = async (context: Context) => {
@@ -50,7 +42,6 @@ const jadwalKegiatanUpdate = async (context: Context) => {
layananJadwalKegiatan,
syaratKetentuanJadwalKegiatan,
dokumenJadwalKegiatan,
pendaftaranJadwalKegiatan,
} = body;
await Promise.all([
@@ -74,10 +65,6 @@ const jadwalKegiatanUpdate = async (context: Context) => {
where: { id: existing.dokumenJadwalKegiatanId },
data: dokumenJadwalKegiatan
}),
prisma.pendaftaranJadwalKegiatan.update({
where: { id: existing.pendaftaranJadwalKegiatanId },
data: pendaftaranJadwalKegiatan,
}),
]);
const updated = await prisma.jadwalKegiatan.update({
@@ -91,7 +78,6 @@ const jadwalKegiatanUpdate = async (context: Context) => {
layananjadwalkegiatan: true,
syaratketentuanjadwalkegiatan: true,
dokumenjadwalkegiatan: true,
pendaftaranjadwalkegiatan: true,
},
});
return {

View File

@@ -2,7 +2,7 @@
import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
import colors from '@/con/colors';
import { Box, Divider, Group, List, ListItem, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import { Box, Divider, Group, Image, List, ListItem, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconAlertCircle, IconCalendar, IconInfoCircle } from '@tabler/icons-react';
import { useParams } from 'next/navigation';
@@ -42,6 +42,24 @@ function Page() {
</Text>
</Box>
<Box p="lg">
<Box style={{ position: 'relative', width: '100%', maxWidth: '800px', margin: '0 auto' }}>
<Image
src={state.findUnique.data.image?.link}
alt={state.findUnique.data.title}
height={0}
style={{
height: 'auto',
width: '100%',
maxHeight: '500px',
objectFit: 'contain',
borderRadius: '8px'
}}
loading="lazy"
/>
</Box>
</Box>
<Box p="lg">
<Stack gap="lg">
<Group gap="xs">
@@ -56,7 +74,7 @@ function Page() {
</Group>
<Stack gap="lg">
<Box>
<Text fz="h4" fw="bold">Pendahuluan</Text>
<Divider my="xs" />

View File

@@ -3,9 +3,9 @@
import fasilitasKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
import colors from '@/con/colors';
import { ActionIcon, Anchor, AspectRatio, Badge, Box, Button, Card, Chip, CopyButton, Divider, Grid, Group, List, ListItem, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, ThemeIcon, Title, Tooltip } from '@mantine/core';
import { ActionIcon, Anchor, AspectRatio, Badge, Box, Button, Card, Chip, CopyButton, Divider, Grid, Group, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, ThemeIcon, Title, Tooltip } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowRight, IconBrandWhatsapp, IconCheck, IconCopy, IconDeviceLandlinePhone, IconFileDownload, IconHeart, IconInfoCircle, IconMail, IconMapPin, IconMoodEmpty, IconSearch, IconStethoscope, IconUser, IconUsersGroup, IconWallet } from '@tabler/icons-react';
import { IconBrandWhatsapp, IconCheck, IconCopy, IconDeviceLandlinePhone, IconHeart, IconInfoCircle, IconMail, IconMapPin, IconMoodEmpty, IconSearch, IconStethoscope, IconUser, IconUsersGroup, IconWallet } from '@tabler/icons-react';
import { useParams } from 'next/navigation';
import { useMemo } from 'react';
import { useProxy } from 'valtio/utils';
@@ -16,14 +16,6 @@ interface Kontak {
email: string;
}
interface LayananItem {
nama: string;
keterangan?: string;
}
interface LayananUnggulan {
items: LayananItem[];
}
interface Lokasi {
mapsEmbed: string;
@@ -46,21 +38,23 @@ function Page() {
const data = state.findUnique.data as any; // Temporary any to fix type issues
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 as LayananUnggulan)?.items || [];
const layananUnggulan = data?.layananunggulan || '';
const tenaga = data?.dokterdantenagamedis || null;
const fasilitasPendukungHtml = data?.fasilitaspendukung?.content || '';
const tarif = (data?.tarifdanlayanan as TarifDanLayanan) || null;
const kontak = (data?.kontak as Kontak) || {
telepon: '(0361) 123456',
whatsapp: '6289647037426',
email: 'info@fasilitas-kesehatan.id'
const kontak = (data?.kontak as Kontak) || {
telepon: '(0361) 123456',
whatsapp: '6289647037426',
email: 'info@fasilitas-kesehatan.id'
};
const lokasi = (data?.lokasi as Lokasi) || {
const lokasi = (data?.lokasi as Lokasi) || {
mapsEmbed: 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3945.272172359321!2d115.21836257533302!3d-8.569807186941553!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x2dd23e9d99b9395f%3A0xb002795fdcb33b30!2sUPTD%20Puskesmas%20Abiansemal%20III!5e0!3m2!1sid!2sid!4v1744792682341!5m2!1sid!2sid'
};
const gratisBpjs = (data?.tarifdanlayanan as TarifDanLayanan)?.gratisBpjs ?? true;
const formatRupiah = useMemo(
@@ -187,22 +181,14 @@ function Page() {
</Group>
<Divider />
<Title order={4}>Layanan Unggulan</Title>
{Array.isArray(layananUnggulan) && layananUnggulan.length > 0 ? (
<List spacing="xs" icon={<ThemeIcon variant="light" radius="xl"><IconArrowRight size={16} /></ThemeIcon>}>
{layananUnggulan.map((x: any, idx: number) => (
<ListItem key={idx}>
<Group gap="xs" wrap="wrap">
<Text fw={600}>{x?.nama || 'Layanan'}</Text>
{x?.keterangan && <Badge variant="light" radius="sm">{x.keterangan}</Badge>}
</Group>
</ListItem>
))}
</List>
<Divider />
{layananUnggulan ? (
<Text fz="md" style={{ lineHeight: 1.7 }} dangerouslySetInnerHTML={{ __html: layananUnggulan }} />
) : (
<Paper withBorder radius="md" p="md">
<Group gap="sm">
<IconMoodEmpty />
<Text>Tidak ada layanan unggulan yang tercatat.</Text>
<Text>Belum ada informasi fasilitas pendukung.</Text>
</Group>
</Paper>
)}
@@ -322,9 +308,6 @@ function Page() {
<Text fw={600}>Gratis dengan BPJS Kesehatan</Text>
</Group>
)}
<Group>
<Button variant="gradient" gradient={{ from: 'blue', to: 'cyan' }} leftSection={<IconFileDownload size={18} />}>Unduh Brosur (PDF)</Button>
</Group>
</Stack>
</Card>
</Grid.Col>
@@ -336,13 +319,11 @@ function Page() {
<Stack gap="md">
<Title order={3}>Prosedur Pendaftaran</Title>
<Divider />
<List type="ordered" spacing="xs" icon={<ThemeIcon variant="light" radius="xl"><IconArrowRight size={16} /></ThemeIcon>}>
<ListItem>Pendaftaran dibuka pukul 07.30 WITA</ListItem>
<ListItem>Bawa KTP dan Kartu BPJS (jika ada)</ListItem>
<ListItem>Ambil nomor antrian di loket pendaftaran</ListItem>
<ListItem>Pengunjung baru mengisi formulir pendaftaran</ListItem>
<ListItem>Pendaftaran online tersedia melalui aplikasi S-Sehat</ListItem>
</List>
{prosedur ? (
<Text fz="md" style={{ lineHeight: 1.7 }} dangerouslySetInnerHTML={{ __html: prosedur }} />
) : (
<Text fz="md" c="dimmed">Belum ada prosedur pendaftaran</Text>
)}
</Stack>
</Paper>
</Box>

View File

@@ -4,7 +4,6 @@ import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
import colors from '@/con/colors';
import {
Box,
Button,
Divider,
Group,
Paper,
@@ -13,7 +12,7 @@ import {
Text
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDownload, IconMail, IconPhone, IconUser } from '@tabler/icons-react';
import { IconMail, IconPhone, IconUser } from '@tabler/icons-react';
import { useParams } from 'next/navigation';
import { useProxy } from 'valtio/utils';
import CreatePendaftaran from '../create/page';
@@ -107,12 +106,6 @@ function Page() {
</Group>
</Stack>
</Paper>
<Group>
<Button size="md" radius="lg" leftSection={<IconDownload size={18} />} color="green">
Unduh Jadwal Posyandu 2025 (PDF)
</Button>
</Group>
</Stack>
</Box>
</Paper>

View File

@@ -32,7 +32,7 @@ function Page() {
const { data, page, totalPages, loading, load } = state.findMany;
useShallowEffect(() => {
load(page, 6, search);
load(page, 3, search);
}, [page, search]);
if (loading || !data) {
@@ -153,7 +153,7 @@ function Page() {
)}
</Box>
{totalPages > 1 && (
<Center>
<Pagination
value={page}
@@ -164,7 +164,7 @@ function Page() {
mt="lg"
/>
</Center>
)}
</Stack>
);
}

View File

@@ -1,7 +1,7 @@
'use client'
import posyandustate from "@/app/admin/(dashboard)/_state/kesehatan/posyandu/posyandu";
import colors from "@/con/colors";
import { Badge, Box, Center, Flex, Image, List, ListItem, Pagination, Paper, SimpleGrid, Skeleton, Spoiler, Stack, Text, TextInput } from "@mantine/core";
import { Badge, Box, Center, Flex, Group, Image, List, ListItem, Pagination, Paper, SimpleGrid, Skeleton, Spoiler, Stack, Text, TextInput } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconCalendar, IconInfoCircle, IconPhone, IconSearch } from "@tabler/icons-react";
import { useState } from "react";
@@ -82,14 +82,14 @@ export default function Page() {
}}
>
<Stack gap="sm">
<Flex justify="space-between" align="center">
<Group justify="space-between" align="center">
<Text c={colors["blue-button"]} fw="bold" fz="lg" lineClamp={1}>
{v.name}
</Text>
<Badge color="blue" variant="light" size="sm" radius="sm">
Aktif
</Badge>
</Flex>
</Group>
<Center>
<Image
src={v.image.link}

View File

@@ -90,18 +90,25 @@ function Page() {
<Divider />
<Box>
<Stack gap={"xs"}>
<Title order={3} mb={10}>Jam Operasional</Title>
<Text fw="bold" fz="md">Senin - Jumat</Text>
<Group gap={8}>
<IconClock size={18} />
<Text fw="bold" fz="md">
{data.jam.workDays} - {data.jam.weekDays}
</Text>
<Text fw="bold" fz="md">{data.jam.workDays} - {data.jam.weekDays}</Text>
<Tooltip label="Hari aktif pelayanan puskesmas" position="top" withArrow>
<Badge size="sm" variant="light" color="blue">Aktif</Badge>
</Tooltip>
</Group>
</Box>
<Text fw="bold" fz="md">Sabtu - Minggu / Hari Libur</Text>
<Group gap={8}>
<IconClock size={18} />
<Text fw="bold" fz="md">{data.jam.holiday}</Text>
<Tooltip label="Hari aktif pelayanan puskesmas" position="top" withArrow>
<Badge size="sm" variant="light" color="blue">Aktif</Badge>
</Tooltip>
</Group>
</Stack>
</Stack>
</GridCol>

View File

@@ -27,11 +27,7 @@ function Page() {
if (loading || !data) {
return (
<Box py="xl" px={{ base: 'md', md: 100 }}>
<SimpleGrid cols={{ base: 1, md: 3 }} spacing="lg">
{Array.from({ length: 6 }).map((_, i) => (
<Skeleton key={i} height={320} radius="lg" />
))}
</SimpleGrid>
<Skeleton height={500} radius="lg" />
</Box>
)
}

View File

@@ -144,9 +144,9 @@ export default function SDGS() {
mt={40}
variant="gradient"
gradient={{ from: "#26667F", to: "#124170" }}
style={{ boxShadow: "0 6px 14px rgba(18,65,112,0.25)" }}
style={{ boxShadow: "0 6px 14px rgba(18,65,112,0.25)"}}
>
Jelajahi Semua Tujuan SDGs Desa
<Text c="white" fz={{ base: "md", md: "lg" }} fw="bold">Jelajahi Semua Tujuan SDGs Desa</Text>
</Button>
</Center>
</Box>