Fix UI User Menu PPID & Kesehatan
This commit is contained in:
@@ -2,158 +2,155 @@
|
||||
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, Button, Center, Divider, Group, Image, List, ListItem, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
|
||||
import { Box, Divider, Group, 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';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
function Page() {
|
||||
const state = useProxy(artikelKesehatanState)
|
||||
const params = useParams()
|
||||
const state = useProxy(artikelKesehatanState);
|
||||
const params = useParams();
|
||||
|
||||
useShallowEffect(() => {
|
||||
state.findUnique.load(params?.id as string)
|
||||
}, [])
|
||||
state.findUnique.load(params?.id as string);
|
||||
}, []);
|
||||
|
||||
if (!state.findUnique.data) {
|
||||
return (
|
||||
<Stack py={10}>
|
||||
<Skeleton h={500} />
|
||||
<Stack py="xl" px="md">
|
||||
<Skeleton h={420} radius="lg" />
|
||||
<Skeleton h={20} mt="md" w="60%" />
|
||||
<Skeleton h={20} w="40%" />
|
||||
<Skeleton h={200} radius="md" />
|
||||
</Stack>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="xl">
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper radius={10}>
|
||||
<Box style={{ borderTopLeftRadius: 10, borderTopRightRadius: 10 }} bg={colors['blue-button']}>
|
||||
<Text p={'md'} fz={{ base: "h3", md: "h2" }} c={colors['white-1']} fw={"bold"}>
|
||||
Detail Lengkap Fasilitas Kesehatan
|
||||
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Stack gap="lg">
|
||||
<Paper radius="xl" shadow="md" withBorder>
|
||||
<Box style={{ borderTopLeftRadius: 16, borderTopRightRadius: 16 }} bg={colors['blue-button']}>
|
||||
<Text p="md" fz={{ base: 'h3', md: 'h2' }} c={colors['white-1']} fw="bold">
|
||||
{state.findUnique.data.title || 'Detail Artikel Kesehatan'}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box p={'md'} >
|
||||
<Stack gap={'xs'}>
|
||||
<Center bg={'#DEE3E3FF'}>
|
||||
<Image
|
||||
w={'100%'}
|
||||
src={'/api/img/dbd.png'}
|
||||
alt='' />
|
||||
</Center>
|
||||
<Box>
|
||||
<Text c={'#9A9D9DFF'} fz={{ base: 'h6', md: 'h5' }}>
|
||||
{new Date(state.findUnique.data.createdAt).toLocaleDateString('id-ID', { year: 'numeric', month: 'long', day: 'numeric' })}
|
||||
</Text>
|
||||
</Box>
|
||||
{/* Pendahuluan */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Pendahuluan
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text pb={10} fz={'h4'} ta={'justify'}>
|
||||
{state.findUnique.data.introduction?.content}
|
||||
</Text>
|
||||
{/* Kenali Gejala DBD */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Kenali Gejala DBD
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text fz={'h4'}>
|
||||
{state.findUnique.data.symptom?.title}
|
||||
</Text>
|
||||
<Text fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.symptom?.content }} />
|
||||
{/* Cara Mencegah DBD */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
{state.findUnique.data.prevention?.title}
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.prevention?.content }} />
|
||||
{/* Pertolongan Pertama Pada Penderita DBD */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
{state.findUnique.data.firstaid?.title}
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.firstaid?.content }} />
|
||||
{/* Mitos dan Fakta tentang DBD */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
{state.findUnique.data.mythvsfact?.title}
|
||||
</Text>
|
||||
<Divider />
|
||||
<Box pb={10}>
|
||||
<Table highlightOnHover withTableBorder withColumnBorders>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh fz={'h4'}>Mitos</TableTh>
|
||||
<TableTh fz={'h4'}>Fakta</TableTh>
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>
|
||||
{state.findUnique.data?.mythvsfact ? (
|
||||
<TableTr>
|
||||
<TableTd>
|
||||
<Text fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.mythvsfact.mitos }} />
|
||||
</TableTd>
|
||||
<TableTd>
|
||||
<Text fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.mythvsfact.fakta }} />
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
) : (
|
||||
<TableTr>
|
||||
<TableTd colSpan={3} style={{ textAlign: 'center' }}>Tidak ada data mitos dan fakta</TableTd>
|
||||
</TableTr>
|
||||
)}
|
||||
</TableTbody>
|
||||
</Table>
|
||||
</Box>
|
||||
{/* Kapan Harus ke Dokter */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Kapan Harus ke Dokter?
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text fz={'h4'}>
|
||||
Segera bawa penderita ke fasilitas kesehatan jika mengalami:
|
||||
</Text>
|
||||
<Text fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.doctorsign.content }} />
|
||||
{/* Kasus DBD di Wilayah Abiansemal */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Kasus DBD di Wilayah Abiansemal
|
||||
</Text>
|
||||
<Divider />
|
||||
|
||||
<Paper p={'lg'} bg={colors['blue-button-trans']}>
|
||||
<Text fz={'h3'} c={colors['white-1']} fw={'bold'}>Informasi Lebih Lanjut</Text>
|
||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
||||
Hotline DBD : <Text span fz={'h4'}>(0361) 123456</Text>
|
||||
<Box p="lg">
|
||||
<Stack gap="lg">
|
||||
<Group gap="xs">
|
||||
<IconCalendar size={18} color={colors['blue-button']} />
|
||||
<Text c="dimmed" fz="sm">
|
||||
{new Date(state.findUnique.data.createdAt).toLocaleDateString('id-ID', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
})}
|
||||
</Text>
|
||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
||||
WhatsApp Center : <Text span fz={'h4'}>081234567890</Text>
|
||||
</Text>
|
||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
||||
Email : <Text span fz={'h4'}>
|
||||
p2p@dinkes.badungkab.go.id</Text>
|
||||
</Text>
|
||||
</Paper>
|
||||
{/* Referensi */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Referensi
|
||||
</Text>
|
||||
<Divider />
|
||||
<List pb={10} type='ordered'>
|
||||
<ListItem fz={'h4'}>Kementerian Kesehatan RI. (2024). Pedoman Pencegahan dan Pengendalian DBD.</ListItem>
|
||||
<ListItem fz={'h4'}>World Health Organization. (2024). Dengue Guidelines for Diagnosis, Treatment, Prevention and Control.</ListItem>
|
||||
<ListItem fz={'h4'}>Dinas Kesehatan Kabupaten Badung. (2025). Laporan Surveilans DBD Triwulan I 2025.</ListItem>
|
||||
</List>
|
||||
<Group>
|
||||
<Button fz={'lg'} bg={colors['blue-button']}>
|
||||
Download Infografis Pencegahan DBD (PDF)
|
||||
</Button>
|
||||
<Button fz={'lg'} bg={'green'}>
|
||||
Bagikan Artikel Ini
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
<Stack gap="lg">
|
||||
<Box>
|
||||
<Text fz="h4" fw="bold">Pendahuluan</Text>
|
||||
<Divider my="xs" />
|
||||
<Text fz="md" lh={1.6} ta="justify">
|
||||
{state.findUnique.data.introduction?.content}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text fz="h4" fw="bold">Kenali Gejala DBD</Text>
|
||||
<Divider my="xs" />
|
||||
<Text fz="md" fw="semibold">{state.findUnique.data.symptom?.title}</Text>
|
||||
<Text fz="md" lh={1.6} ta="justify" dangerouslySetInnerHTML={{ __html: state.findUnique.data.symptom?.content }} />
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text fz="h4" fw="bold">{state.findUnique.data.prevention?.title}</Text>
|
||||
<Divider my="xs" />
|
||||
<Text fz="md" lh={1.6} ta="justify" dangerouslySetInnerHTML={{ __html: state.findUnique.data.prevention?.content }} />
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text fz="h4" fw="bold">{state.findUnique.data.firstaid?.title}</Text>
|
||||
<Divider my="xs" />
|
||||
<Text fz="md" lh={1.6} ta="justify" dangerouslySetInnerHTML={{ __html: state.findUnique.data.firstaid?.content }} />
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text fz="h4" fw="bold">{state.findUnique.data.mythvsfact?.title}</Text>
|
||||
<Divider my="xs" />
|
||||
<Box pb="md">
|
||||
<Table highlightOnHover withTableBorder withColumnBorders striped>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh fz="sm" fw="bold">Mitos</TableTh>
|
||||
<TableTh fz="sm" fw="bold">Fakta</TableTh>
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>
|
||||
{state.findUnique.data?.mythvsfact ? (
|
||||
<TableTr>
|
||||
<TableTd>
|
||||
<Text fz="sm" lh={1.6} dangerouslySetInnerHTML={{ __html: state.findUnique.data.mythvsfact.mitos }} />
|
||||
</TableTd>
|
||||
<TableTd>
|
||||
<Text fz="sm" lh={1.6} dangerouslySetInnerHTML={{ __html: state.findUnique.data.mythvsfact.fakta }} />
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
) : (
|
||||
<TableTr>
|
||||
<TableTd colSpan={2} ta="center" c="dimmed">Belum ada data mitos dan fakta</TableTd>
|
||||
</TableTr>
|
||||
)}
|
||||
</TableTbody>
|
||||
</Table>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text fz="h4" fw="bold">Kapan Harus ke Dokter?</Text>
|
||||
<Divider my="xs" />
|
||||
<Group gap="xs" mb="xs">
|
||||
<IconAlertCircle size={18} color="red" />
|
||||
<Text fz="md">Segera bawa penderita ke fasilitas kesehatan jika mengalami:</Text>
|
||||
</Group>
|
||||
<Text fz="md" lh={1.6} dangerouslySetInnerHTML={{ __html: state.findUnique.data.doctorsign.content }} />
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text fz="h4" fw="bold">Kasus DBD di Wilayah Abiansemal</Text>
|
||||
<Divider my="xs" />
|
||||
|
||||
<Paper p="lg" radius="md" bg={colors['blue-button-trans']} withBorder>
|
||||
<Group gap="xs" mb="sm">
|
||||
<IconInfoCircle size={20} color={colors['white-1']} />
|
||||
<Text fz="h4" c={colors['white-1']} fw="bold">Informasi Lebih Lanjut</Text>
|
||||
</Group>
|
||||
<Stack gap={4}>
|
||||
<Text fz="sm" c={colors['white-1']}>Hotline DBD: <b>(0361) 123456</b></Text>
|
||||
<Text fz="sm" c={colors['white-1']}>WhatsApp Center: <b>081234567890</b></Text>
|
||||
<Text fz="sm" c={colors['white-1']}>Email: <b>p2p@dinkes.badungkab.go.id</b></Text>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text fz="h4" fw="bold">Referensi</Text>
|
||||
<Divider my="xs" />
|
||||
<List spacing="xs" size="sm" type="ordered">
|
||||
<ListItem>Kementerian Kesehatan RI. (2024). Pedoman Pencegahan dan Pengendalian DBD.</ListItem>
|
||||
<ListItem>World Health Organization. (2024). Dengue Guidelines for Diagnosis, Treatment, Prevention and Control.</ListItem>
|
||||
<ListItem>Dinas Kesehatan Kabupaten Badung. (2025). Laporan Surveilans DBD Triwulan I 2025.</ListItem>
|
||||
</List>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Paper>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
'use client'
|
||||
import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
|
||||
import colors from '@/con/colors';
|
||||
import { Anchor, Box, Divider, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { Anchor, Box, Card, Divider, Group, Image, Loader, Paper, Stack, Text, Title, Tooltip } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconCalendar, IconChevronRight } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
@@ -16,36 +17,71 @@ function ArtikelKesehatanPage() {
|
||||
|
||||
if(!state.findMany.data){
|
||||
return (
|
||||
<Box py={10}>
|
||||
<Skeleton h={500}/>
|
||||
<Box py="xl" ta="center">
|
||||
<Loader size="lg" color={colors['blue-button']} />
|
||||
<Text mt="md" c="dimmed" fz="md">Memuat artikel kesehatan...</Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
if(state.findMany.data.length === 0){
|
||||
return (
|
||||
<Box py="xl" ta="center">
|
||||
<Image src="/empty-state.svg" alt="Tidak ada data" w={220} mx="auto" />
|
||||
<Text mt="md" fw="bold" fz="lg">Belum ada artikel kesehatan</Text>
|
||||
<Text c="dimmed" fz="sm">Artikel akan tampil di sini setelah tersedia.</Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Paper p={'xl'} h={'112vh'} bg={colors['white-trans-1']}>
|
||||
<Stack gap={'xs'}>
|
||||
<Text ta={'center'} fw={"bold"} fz={'h3'} c={colors['blue-button']}>Artikel Kesehatan</Text>
|
||||
{state.findMany.data.map((item) => (
|
||||
<Box key={item.id}>
|
||||
<Image pt={5} src={'/api/img/dbd.png'} alt="" />
|
||||
<Text fz={'h4'} fw={'bold'} >
|
||||
{item.title}
|
||||
</Text>
|
||||
<Text fz={'h6'} pb={10}>
|
||||
Diposting: {new Date(item.createdAt).toLocaleDateString('id-ID', { year: 'numeric', month: 'long', day: 'numeric' })} | Dinas Kesehatan
|
||||
</Text>
|
||||
<Text fz={'h4'} pb={10} lineClamp={2}>
|
||||
{item.content}
|
||||
</Text>
|
||||
<Anchor c={'black'} onClick={()=> router.push(`/darmasaba/kesehatan/data-kesehatan-warga/artikel-kesehatan-page/${item.id}`)} variant='transparent'>
|
||||
<Text c={colors['blue-button']} fz={'h4'} >
|
||||
Baca Selengkapnya {'>>'}
|
||||
</Text>
|
||||
</Anchor>
|
||||
</Box>
|
||||
))}
|
||||
<Divider color={colors['blue-button']} px={'xl'} />
|
||||
<Paper p="xl" bg={colors['white-trans-1']} radius="xl" shadow="md">
|
||||
<Stack gap="xl">
|
||||
<Title order={2} ta="center" c={colors['blue-button']}>Artikel Kesehatan</Title>
|
||||
<Divider color={colors['blue-button']} />
|
||||
<Stack gap="lg">
|
||||
{state.findMany.data.map((item) => (
|
||||
<Card
|
||||
key={item.id}
|
||||
withBorder
|
||||
radius="lg"
|
||||
shadow="sm"
|
||||
p="lg"
|
||||
style={{ transition: 'transform 200ms ease' }}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.transform = 'translateY(-4px)')}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.transform = 'translateY(0)')}
|
||||
>
|
||||
<Card.Section>
|
||||
<Image src={'/api/img/dbd.png'} alt={item.title} height={200} fit="cover" />
|
||||
</Card.Section>
|
||||
<Stack gap="xs" mt="md">
|
||||
<Text fw="bold" fz="xl" c="dark">{item.title}</Text>
|
||||
<Group gap="xs">
|
||||
<IconCalendar size={16} color={colors['blue-button']} />
|
||||
<Text fz="sm" c="dimmed">
|
||||
{new Date(item.createdAt).toLocaleDateString('id-ID', { year: 'numeric', month: 'long', day: 'numeric' })} • Dinas Kesehatan
|
||||
</Text>
|
||||
</Group>
|
||||
<Text fz="md" c="dark" lineClamp={3}>
|
||||
{item.content}
|
||||
</Text>
|
||||
<Tooltip label="Baca artikel lengkap">
|
||||
<Anchor
|
||||
onClick={()=> router.push(`/darmasaba/kesehatan/data-kesehatan-warga/artikel-kesehatan-page/${item.id}`)}
|
||||
variant="light"
|
||||
c={colors['blue-button']}
|
||||
>
|
||||
<Group gap="xs">
|
||||
<Text fw="bold" fz="md">Baca Selengkapnya</Text>
|
||||
<IconChevronRight size={18} />
|
||||
</Group>
|
||||
</Anchor>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</Card>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
@@ -1,160 +1,353 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
'use client'
|
||||
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 { Box, Divider, List, ListItem, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
|
||||
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 { 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 { useParams } from 'next/navigation';
|
||||
import { useMemo } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
interface Kontak {
|
||||
telepon: string;
|
||||
whatsapp: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
interface LayananItem {
|
||||
nama: string;
|
||||
keterangan?: string;
|
||||
}
|
||||
|
||||
interface LayananUnggulan {
|
||||
items: LayananItem[];
|
||||
}
|
||||
|
||||
interface Lokasi {
|
||||
mapsEmbed: string;
|
||||
}
|
||||
|
||||
interface TarifDanLayanan {
|
||||
layanan: string;
|
||||
tarif: string | number;
|
||||
gratisBpjs?: boolean;
|
||||
}
|
||||
|
||||
function Page() {
|
||||
const state = useProxy(fasilitasKesehatanState.fasilitasKesehatan)
|
||||
const params = useParams()
|
||||
const state = useProxy(fasilitasKesehatanState.fasilitasKesehatan);
|
||||
const params = useParams();
|
||||
|
||||
useShallowEffect(() => {
|
||||
state.findUnique.load(params?.id as string)
|
||||
}, [])
|
||||
state.findUnique.load(params?.id as string);
|
||||
}, []);
|
||||
|
||||
if (!state.findUnique.data) {
|
||||
const data = state.findUnique.data as any; // Temporary any to fix type issues
|
||||
|
||||
const nama = data?.name || 'Fasilitas Kesehatan';
|
||||
const alamat = data?.informasiumum?.alamat || '-';
|
||||
const jam = data?.informasiumum?.jamOperasional || '-';
|
||||
const layananUnggulan = (data?.layananunggulan as LayananUnggulan)?.items || [];
|
||||
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: '081234567890',
|
||||
email: 'info@fasilitas-kesehatan.id'
|
||||
};
|
||||
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(
|
||||
() => (v?: number | string) => {
|
||||
if (v === null || v === undefined || v === '') return '-';
|
||||
const n = typeof v === 'string' ? Number(v) : v;
|
||||
if (Number.isNaN(n as number)) return String(v);
|
||||
return new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', maximumFractionDigits: 0 }).format(n as number);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
if (state.findUnique.loading || !data) {
|
||||
return (
|
||||
<Stack py={10}>
|
||||
<Skeleton h={500} />
|
||||
<Stack bg={colors.Bg} mih="100vh" p="lg" gap="lg">
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Skeleton h={32} w={220} />
|
||||
</Box>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Skeleton h={64} radius="lg" />
|
||||
</Box>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Grid gutter="lg">
|
||||
<Grid.Col span={{ base: 12, md: 8 }}>
|
||||
<Skeleton h={320} radius="lg" />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{ base: 12, md: 4 }}>
|
||||
<Skeleton h={320} radius="lg" />
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Box>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Skeleton h={420} radius="lg" />
|
||||
</Box>
|
||||
</Stack>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Stack bg={colors.Bg} py="xl" gap="xl">
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
<Group justify="space-between">
|
||||
<Group gap="xs">
|
||||
<BackButton />
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<Badge variant="gradient" gradient={{ from: 'blue', to: 'cyan' }} radius="xl" size="lg" leftSection={<IconHeart size={16} />}>Pelayanan Aktif</Badge>
|
||||
<Badge variant="light" radius="xl" size="lg" leftSection={<IconInfoCircle size={16} />}>Jam: {jam}</Badge>
|
||||
</Group>
|
||||
</Group>
|
||||
</Box>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper radius={10}>
|
||||
<Box style={{ borderTopLeftRadius: 10, borderTopRightRadius: 10 }} bg={colors['blue-button']}>
|
||||
<Text p={'md'} fz={{ base: "h3", md: "h2" }} c={colors['white-1']} fw={"bold"}>
|
||||
Detail Lengkap Fasilitas Kesehatan
|
||||
</Text>
|
||||
</Box>
|
||||
<Box p={'md'} >
|
||||
<Stack gap={'xs'}>
|
||||
{/* Informasi Umum */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Informasi Umum
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Nama Fasilitas : <Text span fz={'h4'}>{state.findUnique.data?.name}</Text>
|
||||
</Text>
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Alamat : <Text span fz={'h4'}>{state.findUnique.data?.informasiumum.alamat}</Text>
|
||||
</Text>
|
||||
<Text pb={10} fz={'h4'} fw={"bold"}>
|
||||
Jam Operasional: : <Text span fz={'h4'}>{state.findUnique.data?.informasiumum.jamOperasional}</Text>
|
||||
</Text>
|
||||
{/* Layanan Unggulan */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Layanan Unggulan
|
||||
</Text>
|
||||
<Divider />
|
||||
|
||||
{/* Tenaga Medis */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Dokter & Tenaga Medis
|
||||
</Text>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Card radius="xl" p="lg" withBorder style={{ backdropFilter: 'blur(6px)' }}>
|
||||
<Stack gap="sm">
|
||||
<Title order={2}>{nama}</Title>
|
||||
<Group gap="md" wrap="wrap">
|
||||
<Group gap="xs">
|
||||
<ThemeIcon variant="light" radius="xl"><IconMapPin size={18} /></ThemeIcon>
|
||||
<Text>{alamat}</Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<ThemeIcon variant="light" radius="xl"><IconDeviceLandlinePhone size={18} /></ThemeIcon>
|
||||
<Text>{kontak.telepon}</Text>
|
||||
<CopyButton value={kontak.telepon}>
|
||||
{({ copied, copy }) => (
|
||||
<Tooltip label={copied ? 'Disalin' : 'Salin nomor'}>
|
||||
<ActionIcon variant="subtle" onClick={copy}>{copied ? <IconCheck size={18} /> : <IconCopy size={18} />}</ActionIcon>
|
||||
</Tooltip>
|
||||
)}
|
||||
</CopyButton>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<ThemeIcon variant="light" radius="xl"><IconBrandWhatsapp size={18} /></ThemeIcon>
|
||||
<Text>{kontak.whatsapp}</Text>
|
||||
<CopyButton value={kontak.whatsapp}>
|
||||
{({ copied, copy }) => (
|
||||
<Tooltip label={copied ? 'Disalin' : 'Salin WhatsApp'}>
|
||||
<ActionIcon variant="subtle" onClick={copy}>{copied ? <IconCheck size={18} /> : <IconCopy size={18} />}</ActionIcon>
|
||||
</Tooltip>
|
||||
)}
|
||||
</CopyButton>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<ThemeIcon variant="light" radius="xl"><IconMail size={18} /></ThemeIcon>
|
||||
<Text>{kontak.email}</Text>
|
||||
<CopyButton value={kontak.email}>
|
||||
{({ copied, copy }) => (
|
||||
<Tooltip label={copied ? 'Disalin' : 'Salin email'}>
|
||||
<ActionIcon variant="subtle" onClick={copy}>{copied ? <IconCheck size={18} /> : <IconCopy size={18} />}</ActionIcon>
|
||||
</Tooltip>
|
||||
)}
|
||||
</CopyButton>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group gap="xs" mt="sm" wrap="wrap">
|
||||
<Chip defaultChecked radius="xl" variant="light" icon={<IconStethoscope size={16} />}>Layanan Medis</Chip>
|
||||
<Chip radius="xl" variant="light" icon={<IconUsersGroup size={16} />}>Ramah Keluarga</Chip>
|
||||
<Chip radius="xl" variant="light" icon={<IconWallet size={16} />}>Pembayaran Non-Tunai</Chip>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Card>
|
||||
</Box>
|
||||
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Grid gutter="lg">
|
||||
<Grid.Col span={{ base: 12, md: 8 }}>
|
||||
<Card radius="xl" p="lg" withBorder>
|
||||
<Stack gap="md">
|
||||
<Group justify="space-between" align="center">
|
||||
<Title order={3}>Informasi Umum</Title>
|
||||
<Badge variant="gradient" gradient={{ from: 'cyan', to: 'blue' }} radius="xl">Terverifikasi</Badge>
|
||||
</Group>
|
||||
<Divider />
|
||||
<Box pb={10}>
|
||||
<Table highlightOnHover withTableBorder withColumnBorders>
|
||||
<Group gap="xl" align="start">
|
||||
<Stack gap={2}>
|
||||
<Text c="dimmed" fz="sm">Nama Fasilitas</Text>
|
||||
<Text fw={600}>{nama}</Text>
|
||||
</Stack>
|
||||
<Stack gap={2}>
|
||||
<Text c="dimmed" fz="sm">Jam Operasional</Text>
|
||||
<Text fw={600}>{jam}</Text>
|
||||
</Stack>
|
||||
</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>
|
||||
) : (
|
||||
<Paper withBorder radius="md" p="md">
|
||||
<Group gap="sm">
|
||||
<IconMoodEmpty />
|
||||
<Text>Tidak ada layanan unggulan yang tercatat.</Text>
|
||||
</Group>
|
||||
</Paper>
|
||||
)}
|
||||
<Divider />
|
||||
<Title order={4}>Peta Lokasi</Title>
|
||||
<AspectRatio ratio={16 / 9}>
|
||||
<iframe src={lokasi.mapsEmbed} style={{ border: 0, width: '100%', height: '100%', borderRadius: 16 }} loading="lazy" aria-label="Peta Lokasi" />
|
||||
</AspectRatio>
|
||||
</Stack>
|
||||
</Card>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col span={{ base: 12, md: 4 }}>
|
||||
<Stack gap="lg">
|
||||
<Card radius="xl" p="lg" withBorder>
|
||||
<Stack gap="md">
|
||||
<Title order={4}>Kontak Cepat</Title>
|
||||
<Group gap="sm" wrap="wrap">
|
||||
<Button variant="light" leftSection={<IconDeviceLandlinePhone size={18} />} component="a" href={`tel:${kontak.telepon}`} aria-label="Hubungi Telepon">Telepon</Button>
|
||||
<Button variant="light" leftSection={<IconBrandWhatsapp size={18} />} component="a" href={`https://wa.me/${kontak.whatsapp.replace(/\D/g, '')}`} target="_blank" aria-label="Hubungi WhatsApp">WhatsApp</Button>
|
||||
<Button variant="light" leftSection={<IconMail size={18} />} component="a" href={`mailto:${kontak.email}`} aria-label="Kirim Email">Email</Button>
|
||||
</Group>
|
||||
<Anchor target="_blank" underline="hover">Kunjungi situs resmi</Anchor>
|
||||
</Stack>
|
||||
</Card>
|
||||
|
||||
<Card radius="xl" p="lg" withBorder>
|
||||
<Stack gap="md">
|
||||
<Title order={4}>Dokter & Tenaga Medis</Title>
|
||||
<Table highlightOnHover withTableBorder withColumnBorders stickyHeader stickyHeaderOffset={0} aria-label="Tabel Dokter">
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh fz={'h4'}>Nama</TableTh>
|
||||
<TableTh fz={'h4'}>Spesialisasi</TableTh>
|
||||
<TableTh fz={'h4'}>Jadwal</TableTh>
|
||||
<TableTh>Nama</TableTh>
|
||||
<TableTh>Spesialisasi</TableTh>
|
||||
<TableTh>Jadwal</TableTh>
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>
|
||||
{state.findUnique.data?.dokterdantenagamedis ? (
|
||||
{tenaga ? (
|
||||
<TableTr>
|
||||
<TableTd>{state.findUnique.data.dokterdantenagamedis.name}</TableTd>
|
||||
<TableTd>{state.findUnique.data.dokterdantenagamedis.specialist}</TableTd>
|
||||
<TableTd>{state.findUnique.data.dokterdantenagamedis.jadwal}</TableTd>
|
||||
<TableTd><Group gap="xs"><IconUser size={16} /><Text>{tenaga?.name || '-'}</Text></Group></TableTd>
|
||||
<TableTd>{tenaga?.specialist || '-'}</TableTd>
|
||||
<TableTd>{tenaga?.jadwal || '-'}</TableTd>
|
||||
</TableTr>
|
||||
) : (
|
||||
<TableTr>
|
||||
<TableTd colSpan={3} style={{ textAlign: 'center' }}>Tidak ada data dokter/tenaga medis</TableTd>
|
||||
<TableTd colSpan={3}>
|
||||
<Group justify="center" gap="xs" c="dimmed">
|
||||
<IconSearch size={18} />
|
||||
<Text>Tidak ada data tenaga medis.</Text>
|
||||
</Group>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
)}
|
||||
</TableTbody>
|
||||
</Table>
|
||||
</Box>
|
||||
{/* Fasilitas Pendukung */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Fasilitas Pendukung
|
||||
</Text>
|
||||
</Stack>
|
||||
</Card>
|
||||
</Stack>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Grid gutter="lg">
|
||||
<Grid.Col span={{ base: 12, md: 8 }}>
|
||||
<Card radius="xl" p="lg" withBorder>
|
||||
<Stack gap="md">
|
||||
<Title order={3}>Fasilitas Pendukung</Title>
|
||||
<Divider />
|
||||
<Text fz={"lg"} dangerouslySetInnerHTML={{ __html: state.findUnique.data?.fasilitaspendukung?.content }} />
|
||||
{/* Dokter */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Layanan & Tarif
|
||||
</Text>
|
||||
{fasilitasPendukungHtml ? (
|
||||
<Text fz="md" style={{ lineHeight: 1.7 }} dangerouslySetInnerHTML={{ __html: fasilitasPendukungHtml }} />
|
||||
) : (
|
||||
<Paper withBorder radius="md" p="md">
|
||||
<Group gap="sm">
|
||||
<IconMoodEmpty />
|
||||
<Text>Belum ada informasi fasilitas pendukung.</Text>
|
||||
</Group>
|
||||
</Paper>
|
||||
)}
|
||||
</Stack>
|
||||
</Card>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{ base: 12, md: 4 }}>
|
||||
<Card radius="xl" p="lg" withBorder>
|
||||
<Stack gap="md">
|
||||
<Title order={3}>Layanan & Tarif</Title>
|
||||
<Divider />
|
||||
<Table highlightOnHover withTableBorder withColumnBorders>
|
||||
<Table highlightOnHover withTableBorder withColumnBorders aria-label="Tabel Layanan dan Tarif">
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh fz={'h4'}>Layanan</TableTh>
|
||||
<TableTh fz={'h4'}>Tarif</TableTh>
|
||||
<TableTh>Layanan</TableTh>
|
||||
<TableTh>Tarif</TableTh>
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>
|
||||
<TableTr>
|
||||
<TableTd>{state.findUnique?.data?.tarifdanlayanan.layanan}</TableTd>
|
||||
<TableTd>{state.findUnique?.data?.tarifdanlayanan.tarif}</TableTd>
|
||||
</TableTr>
|
||||
{tarif ? (
|
||||
<TableTr>
|
||||
<TableTd>{tarif?.layanan || '-'}</TableTd>
|
||||
<TableTd>{formatRupiah(tarif?.tarif)}</TableTd>
|
||||
</TableTr>
|
||||
) : (
|
||||
<TableTr>
|
||||
<TableTd colSpan={2}>
|
||||
<Group justify="center" gap="xs" c="dimmed">
|
||||
<IconSearch size={18} />
|
||||
<Text>Tidak ada data tarif.</Text>
|
||||
</Group>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
)}
|
||||
</TableTbody>
|
||||
</Table>
|
||||
<Text fz={'h6'} pb={10} fw={"bold"}>
|
||||
* Gratis dengan BPJS Kesehatan
|
||||
</Text>
|
||||
{/* Prosedur Pendaftaran */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Prosedur Pendaftaran
|
||||
</Text>
|
||||
<Divider />
|
||||
<List type='ordered' pb={10} >
|
||||
<ListItem fz={'h4'}>Pendaftaran dibuka pukul 07:30 WITA</ListItem>
|
||||
<ListItem fz={'h4'}>Bawa KTP dan Kartu BPJS (jika ada)</ListItem>
|
||||
<ListItem fz={'h4'}>Ambil nomor antrian di loket pendaftaran</ListItem>
|
||||
<ListItem fz={'h4'}>Pengunjung baru wajib mengisi formulir pendaftaran</ListItem>
|
||||
<ListItem fz={'h4'}>Pendaftaran online tersedia melalui aplikasi S-Sehat</ListItem>
|
||||
</List>
|
||||
<Paper p={'lg'} bg={colors['blue-button-trans']}>
|
||||
<Text fz={'h3'} c={colors['white-1']} fw={'bold'}>Kontak Darurat</Text>
|
||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
||||
Telepon : <Text span fz={'h4'}>(0361) 123456</Text>
|
||||
</Text>
|
||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
||||
WhatsApp : <Text span fz={'h4'}>081234567890</Text>
|
||||
</Text>
|
||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
||||
Email : <Text span fz={'h4'}>puskesmasabiansemal3@gmail.com</Text>
|
||||
</Text>
|
||||
</Paper>
|
||||
{/* <Paper p={'lg'} w={{ base: "100%", md: "100%" }}>
|
||||
<iframe src="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" width="600" height="450" style={{ border: 2, width: "100%", borderRadius: 10 }} loading="lazy"></iframe>
|
||||
</Paper>
|
||||
{gratisBpjs && (
|
||||
<Group gap="xs">
|
||||
<ThemeIcon variant="light" radius="xl"><IconCheck size={18} /></ThemeIcon>
|
||||
<Text fw={600}>Gratis dengan BPJS Kesehatan</Text>
|
||||
</Group>
|
||||
)}
|
||||
<Group>
|
||||
<Button fz={'lg'} bg={colors['blue-button']}>
|
||||
Download Brosur Layanan (PDF)
|
||||
</Button>
|
||||
</Group> */}
|
||||
<Button variant="gradient" gradient={{ from: 'blue', to: 'cyan' }} leftSection={<IconFileDownload size={18} />}>Unduh Brosur (PDF)</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Card>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
<Box px={{ base: 'md', md: 100 }} pb="xl">
|
||||
<Paper radius="xl" p="lg" withBorder>
|
||||
<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>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default Page;
|
||||
|
||||
@@ -1,50 +1,100 @@
|
||||
'use client'
|
||||
import fasilitasKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
|
||||
import colors from '@/con/colors';
|
||||
import { Anchor, Box, Divider, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { Anchor, Badge, Box, Card, Divider, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { IconMapPin, IconClock, IconArrowRight } from '@tabler/icons-react';
|
||||
|
||||
function FasilitasKesehatanPage() {
|
||||
const state = useProxy(fasilitasKesehatanState.fasilitasKesehatan)
|
||||
const state = useProxy(fasilitasKesehatanState.fasilitasKesehatan);
|
||||
const router = useRouter();
|
||||
|
||||
useShallowEffect(() => {
|
||||
state.findMany.load()
|
||||
}, [])
|
||||
state.findMany.load();
|
||||
}, []);
|
||||
|
||||
if(!state.findMany.data){
|
||||
if (!state.findMany.data) {
|
||||
return (
|
||||
<Box py={10}>
|
||||
<Skeleton h={500} />
|
||||
<Box py="xl" px="md">
|
||||
<Stack gap="md">
|
||||
<Skeleton height={80} radius="lg" />
|
||||
<Skeleton height={80} radius="lg" />
|
||||
<Skeleton height={80} radius="lg" />
|
||||
</Stack>
|
||||
</Box>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Paper p={'xl'} h={'112vh'} bg={colors['white-trans-1']}>
|
||||
<Stack gap={'xs'}>
|
||||
<Text ta={'center'} fw={"bold"} fz={'h3'} c={colors['blue-button']}>Fasilitas Kesehatan</Text>
|
||||
{state.findMany.data.map((item) => (
|
||||
<Box key={item.id}>
|
||||
<Text fz={'h4'} fw={'bold'} c={colors['blue-button']}>
|
||||
{item.name}
|
||||
</Text>
|
||||
<Text fz={'h4'}>
|
||||
{item.informasiumum.alamat}
|
||||
</Text>
|
||||
<Text fz={'h4'}>
|
||||
{item.informasiumum.jamOperasional}
|
||||
</Text>
|
||||
<Anchor onClick={() => router.push(`/darmasaba/kesehatan/data-kesehatan-warga/fasilitas-kesehatan-page/${item.id}`)} c={colors['blue-button']} variant='transparent'>
|
||||
<Text c={colors['blue-button']} fz={'h4'}>
|
||||
Detail {'>>'}
|
||||
</Text>
|
||||
</Anchor>
|
||||
</Box>
|
||||
))}
|
||||
<Divider color={colors['blue-button']} px={'xl'} />
|
||||
<Paper p="xl" radius="xl" shadow="md" h="100%" bg="white">
|
||||
<Stack gap="lg">
|
||||
<Text ta="center" fw={700} fz="32px" c={colors['blue-button']}>
|
||||
Fasilitas Kesehatan
|
||||
</Text>
|
||||
<Divider size="sm" color={colors['blue-button']} />
|
||||
<Stack gap="lg">
|
||||
{state.findMany.data.map((item) => (
|
||||
<Card
|
||||
key={item.id}
|
||||
withBorder
|
||||
radius="xl"
|
||||
shadow="sm"
|
||||
p="lg"
|
||||
style={{
|
||||
background: 'linear-gradient(135deg, #fdfdfd, #f7faff)',
|
||||
transition: 'transform 0.2s ease, box-shadow 0.2s ease',
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
(e.currentTarget as HTMLElement).style.transform = 'translateY(-4px)';
|
||||
(e.currentTarget as HTMLElement).style.boxShadow = '0 8px 20px rgba(0,0,0,0.08)';
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
(e.currentTarget as HTMLElement).style.transform = 'translateY(0px)';
|
||||
(e.currentTarget as HTMLElement).style.boxShadow = '0 4px 12px rgba(0,0,0,0.05)';
|
||||
}}
|
||||
>
|
||||
<Stack gap="sm">
|
||||
<Group justify="space-between" align="center">
|
||||
<Text fw={700} fz="lg" c={colors['blue-button']}>
|
||||
{item.name}
|
||||
</Text>
|
||||
<Badge color="blue" radius="sm" variant="light" fz="xs">
|
||||
Aktif
|
||||
</Badge>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<IconMapPin size={18} stroke={1.5} color={colors['blue-button']} />
|
||||
<Text fz="sm" c="dimmed">
|
||||
{item.informasiumum.alamat}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<IconClock size={18} stroke={1.5} color={colors['blue-button']} />
|
||||
<Text fz="sm" c="dimmed">
|
||||
{item.informasiumum.jamOperasional}
|
||||
</Text>
|
||||
</Group>
|
||||
<Anchor
|
||||
onClick={() =>
|
||||
router.push(
|
||||
`/darmasaba/kesehatan/data-kesehatan-warga/fasilitas-kesehatan-page/${item.id}`
|
||||
)
|
||||
}
|
||||
c={colors['blue-button']}
|
||||
fz="sm"
|
||||
fw={600}
|
||||
style={{ display: 'inline-flex', alignItems: 'center', gap: '4px' }}
|
||||
>
|
||||
Lihat Detail
|
||||
<IconArrowRight size={16} stroke={1.5} />
|
||||
</Anchor>
|
||||
</Stack>
|
||||
</Card>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
@@ -2,10 +2,30 @@
|
||||
import jadwalkegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
|
||||
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
|
||||
import colors from '@/con/colors';
|
||||
import { ActionIcon, Box, Button, CheckIcon, Combobox, ComboboxChevron, ComboboxOption, ComboboxOptions, ComboboxTarget, Divider, Group, InputBase, InputPlaceholder, Paper, Skeleton, Stack, Text, Textarea, TextInput, useCombobox } from '@mantine/core';
|
||||
import {
|
||||
ActionIcon,
|
||||
Box,
|
||||
Button,
|
||||
Combobox,
|
||||
ComboboxChevron,
|
||||
ComboboxOption,
|
||||
ComboboxOptions,
|
||||
ComboboxTarget,
|
||||
Divider,
|
||||
Group,
|
||||
InputBase,
|
||||
InputPlaceholder,
|
||||
Paper,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
Textarea,
|
||||
TextInput,
|
||||
useCombobox
|
||||
} from '@mantine/core';
|
||||
import { DateInput } from '@mantine/dates';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconCalendar } from '@tabler/icons-react';
|
||||
import { IconCalendar, IconDownload, IconPhone, IconMail, IconUser } from '@tabler/icons-react';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
@@ -17,6 +37,7 @@ const layanan = [
|
||||
'Konsultasi Gizi',
|
||||
'Pemeriksaan Kesehatan'
|
||||
];
|
||||
|
||||
function Page() {
|
||||
const combobox = useCombobox({
|
||||
onDropdownClose: () => combobox.resetSelectedOption(),
|
||||
@@ -30,192 +51,160 @@ function Page() {
|
||||
});
|
||||
|
||||
const [value, setValue] = useState<string | null>('');
|
||||
const [dateInputOpened, setDateInputOpened] = useState(false);
|
||||
const params = useParams();
|
||||
const state = useProxy(jadwalkegiatanState);
|
||||
|
||||
useShallowEffect(() => {
|
||||
state.findUnique.load(params?.id as string);
|
||||
}, []);
|
||||
|
||||
const options = layanan.map((item) => (
|
||||
<ComboboxOption value={item} key={item} active={item === value}>
|
||||
<Group gap="xs">
|
||||
{item === value && <CheckIcon size={12} />}
|
||||
{item === value && <IconUser size={14} stroke={2} />}
|
||||
<span>{item}</span>
|
||||
</Group>
|
||||
</ComboboxOption>
|
||||
));
|
||||
const [dateInputOpened, setDateInputOpened] = useState(false);
|
||||
|
||||
const pickerControl = (
|
||||
<ActionIcon onClick={() => setDateInputOpened(true)} variant="subtle" color="gray">
|
||||
<ActionIcon onClick={() => setDateInputOpened(true)} variant="light" color="blue">
|
||||
<IconCalendar size={18} />
|
||||
</ActionIcon>
|
||||
);
|
||||
|
||||
|
||||
const params = useParams()
|
||||
const state = useProxy(jadwalkegiatanState)
|
||||
useShallowEffect(() => {
|
||||
state.findUnique.load(params?.id as string)
|
||||
}, [])
|
||||
|
||||
if (!state.findUnique.data) {
|
||||
return (
|
||||
<Stack py={10}>
|
||||
<Skeleton h={500} />
|
||||
<Stack py="xl" px="lg">
|
||||
<Skeleton h={500} radius="lg" />
|
||||
</Stack>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="lg">
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper radius={10}>
|
||||
<Box style={{ borderTopLeftRadius: 10, borderTopRightRadius: 10 }} bg={colors['blue-button']}>
|
||||
<Text p={'md'} fz={{ base: "h3", md: "h2" }} c={colors['white-1']} fw={"bold"}>
|
||||
<Stack gap="lg">
|
||||
<Paper radius="xl" shadow="md">
|
||||
<Box
|
||||
style={{ borderTopLeftRadius: 16, borderTopRightRadius: 16 }}
|
||||
bg={colors['blue-button']}
|
||||
>
|
||||
<Text p="md" fz={{ base: "h3", md: "h2" }} c={colors['white-1']} fw="bold">
|
||||
Detail & Pendaftaran Kegiatan
|
||||
</Text>
|
||||
</Box>
|
||||
<Box p={'md'} >
|
||||
<Stack gap={'xs'}>
|
||||
{/* Informasi Kegiatan */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Informasi Kegiatan
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Nama Kegiatan : <Text span fz={'h4'}>{state.findUnique.data.informasijadwalkegiatan.name}</Text>
|
||||
</Text>
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Tanggal : <Text span fz={'h4'}>{state.findUnique.data.informasijadwalkegiatan.tanggal}</Text>
|
||||
</Text>
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Waktu : <Text span fz={'h4'}>{state.findUnique.data.informasijadwalkegiatan.waktu}</Text>
|
||||
</Text>
|
||||
<Text pb={10} fz={'h4'} fw={"bold"}>
|
||||
Lokasi : <Text span fz={'h4'}>{state.findUnique.data.informasijadwalkegiatan.lokasi}</Text>
|
||||
</Text>
|
||||
{/* Deskripsi Kegiatan */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Deskripsi Kegiatan
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text pb={10} ta={'justify'} fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.deskripsijadwalkegiatan.deskripsi }} />
|
||||
{/* Layanan Yang Tersedia */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Layanan Yang Tersedia
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text pb={10} ta={'justify'} fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.layananjadwalkegiatan.content }} />
|
||||
{/* Syarat dan Ketentuan */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Syarat dan Ketentuan
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text pb={10} ta={'justify'} fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.syaratketentuanjadwalkegiatan.content }} />
|
||||
{/* Dokumen yang Perlu Dibawa */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Dokumen yang Perlu Dibawa
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text pb={10} ta={'justify'} fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.dokumenjadwalkegiatan.content }} />
|
||||
{/* Pendaftaran */}
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Pendaftaran
|
||||
</Text>
|
||||
<Divider />
|
||||
<Stack gap={'xs'} pb={20}>
|
||||
<TextInput
|
||||
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }}
|
||||
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
|
||||
label="Nama Balita"
|
||||
placeholder='Masukkan nama balita'
|
||||
/>
|
||||
<DateInput
|
||||
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }}
|
||||
placeholder='dd/mm/yyyy'
|
||||
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
|
||||
label="Tanggal Lahir"
|
||||
popoverProps={{ opened: dateInputOpened, onChange: setDateInputOpened }}
|
||||
rightSection={pickerControl}
|
||||
/>
|
||||
<TextInput
|
||||
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }}
|
||||
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
|
||||
label="Nama Orang Tua / Wali"
|
||||
placeholder='Masukkan nama orang tua / wali'
|
||||
/>
|
||||
<TextInput
|
||||
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }}
|
||||
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
|
||||
label="No. Telepon"
|
||||
placeholder='Masukkan no. telepon'
|
||||
/>
|
||||
<TextInput
|
||||
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }}
|
||||
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
|
||||
label="Alamat"
|
||||
placeholder='Masukkan alamat lengkap'
|
||||
/>
|
||||
{/* Layanan */}
|
||||
<Text fz={'16px'} fw={"bold"}>
|
||||
Layananan Yang Dibutuhkan
|
||||
</Text>
|
||||
<Box
|
||||
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
|
||||
>
|
||||
<Combobox
|
||||
store={combobox}
|
||||
resetSelectionOnOptionHover
|
||||
withinPortal={false}
|
||||
onOptionSubmit={(val) => {
|
||||
setValue(val);
|
||||
combobox.updateSelectedOptionIndex('active');
|
||||
}}
|
||||
>
|
||||
<ComboboxTarget targetType="button">
|
||||
<InputBase
|
||||
component="button"
|
||||
type="button"
|
||||
pointer
|
||||
rightSection={<ComboboxChevron />}
|
||||
rightSectionPointerEvents="none"
|
||||
onClick={() => combobox.toggleDropdown()}
|
||||
>
|
||||
{value || <InputPlaceholder>Layanan</InputPlaceholder>}
|
||||
</InputBase>
|
||||
</ComboboxTarget>
|
||||
|
||||
<Combobox.Dropdown>
|
||||
<ComboboxOptions>{options}</ComboboxOptions>
|
||||
</Combobox.Dropdown>
|
||||
</Combobox>
|
||||
</Box>
|
||||
<Textarea
|
||||
pb={10}
|
||||
styles={{ label: { fontSize: '16px', fontWeight: 'bold' }, }} w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
|
||||
label="Catatan Khusus (Opsional)"
|
||||
placeholder='Masukkan catatan jika ada'
|
||||
/>
|
||||
<Button
|
||||
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
|
||||
fz={'md'} bg={colors['blue-button']}>
|
||||
Daftar Sekarang
|
||||
</Button>
|
||||
<Box p="lg">
|
||||
<Stack gap="xl">
|
||||
<Stack gap="sm">
|
||||
<Text fz="lg" fw="bold">Informasi Kegiatan</Text>
|
||||
<Divider />
|
||||
<Text fz="md" fw="bold">Nama Kegiatan: <Text span>{state.findUnique.data.informasijadwalkegiatan.name}</Text></Text>
|
||||
<Text fz="md" fw="bold">Tanggal: <Text span>{state.findUnique.data.informasijadwalkegiatan.tanggal}</Text></Text>
|
||||
<Text fz="md" fw="bold">Waktu: <Text span>{state.findUnique.data.informasijadwalkegiatan.waktu}</Text></Text>
|
||||
<Text fz="md" fw="bold">Lokasi: <Text span>{state.findUnique.data.informasijadwalkegiatan.lokasi}</Text></Text>
|
||||
</Stack>
|
||||
<Paper p={'lg'} bg={colors['blue-button-trans']}>
|
||||
<Text fz={'h3'} c={colors['white-1']} fw={'bold'}>Informasi Kontak</Text>
|
||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
||||
Penanggung Jawab : <Text span fz={'h4'}>Bidan Komang Ayu</Text>
|
||||
</Text>
|
||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
||||
Telepon : <Text span fz={'h4'}>081234567890</Text>
|
||||
</Text>
|
||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
||||
Email : <Text span fz={'h4'}>puskesmasabiansemal3@gmail.com</Text>
|
||||
</Text>
|
||||
|
||||
<Stack gap="sm">
|
||||
<Text fz="lg" fw="bold">Deskripsi Kegiatan</Text>
|
||||
<Divider />
|
||||
<Text ta="justify" fz="md" dangerouslySetInnerHTML={{ __html: state.findUnique.data.deskripsijadwalkegiatan.deskripsi }} />
|
||||
</Stack>
|
||||
|
||||
<Stack gap="sm">
|
||||
<Text fz="lg" fw="bold">Layanan yang Tersedia</Text>
|
||||
<Divider />
|
||||
<Text ta="justify" fz="md" dangerouslySetInnerHTML={{ __html: state.findUnique.data.layananjadwalkegiatan.content }} />
|
||||
</Stack>
|
||||
|
||||
<Stack gap="sm">
|
||||
<Text fz="lg" fw="bold">Syarat & Ketentuan</Text>
|
||||
<Divider />
|
||||
<Text ta="justify" fz="md" dangerouslySetInnerHTML={{ __html: state.findUnique.data.syaratketentuanjadwalkegiatan.content }} />
|
||||
</Stack>
|
||||
|
||||
<Stack gap="sm">
|
||||
<Text fz="lg" fw="bold">Dokumen yang Perlu Dibawa</Text>
|
||||
<Divider />
|
||||
<Text ta="justify" fz="md" dangerouslySetInnerHTML={{ __html: state.findUnique.data.dokumenjadwalkegiatan.content }} />
|
||||
</Stack>
|
||||
|
||||
<Stack gap="sm">
|
||||
<Text fz="lg" fw="bold">Formulir Pendaftaran</Text>
|
||||
<Divider />
|
||||
<Stack gap="md">
|
||||
<TextInput label="Nama Balita" placeholder="Masukkan nama balita" size="md" />
|
||||
<DateInput
|
||||
label="Tanggal Lahir"
|
||||
placeholder="dd/mm/yyyy"
|
||||
size="md"
|
||||
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
|
||||
popoverProps={{ opened: dateInputOpened, onChange: setDateInputOpened }}
|
||||
rightSection={pickerControl}
|
||||
/>
|
||||
<TextInput label="Nama Orang Tua / Wali" placeholder="Masukkan nama orang tua / wali" size="md" />
|
||||
<TextInput label="Nomor Telepon" placeholder="Masukkan nomor telepon" size="md" />
|
||||
<TextInput label="Alamat" placeholder="Masukkan alamat lengkap" size="md" />
|
||||
<Box w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}>
|
||||
<Text fz="sm" fw="bold" pb={4}>Pilih Layanan</Text>
|
||||
<Combobox
|
||||
store={combobox}
|
||||
resetSelectionOnOptionHover
|
||||
withinPortal={false}
|
||||
onOptionSubmit={(val) => {
|
||||
setValue(val);
|
||||
combobox.updateSelectedOptionIndex('active');
|
||||
}}
|
||||
>
|
||||
<ComboboxTarget targetType="button">
|
||||
<InputBase
|
||||
component="button"
|
||||
type="button"
|
||||
pointer
|
||||
rightSection={<ComboboxChevron />}
|
||||
rightSectionPointerEvents="none"
|
||||
onClick={() => combobox.toggleDropdown()}
|
||||
>
|
||||
{value || <InputPlaceholder>Pilih layanan</InputPlaceholder>}
|
||||
</InputBase>
|
||||
</ComboboxTarget>
|
||||
<Combobox.Dropdown>
|
||||
<ComboboxOptions>{options}</ComboboxOptions>
|
||||
</Combobox.Dropdown>
|
||||
</Combobox>
|
||||
</Box>
|
||||
<Textarea label="Catatan Khusus (Opsional)" placeholder="Masukkan catatan jika ada" size="md" />
|
||||
<Button size="md" radius="lg" bg={colors['blue-button']}>
|
||||
Daftar Sekarang
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
<Paper p="lg" radius="md" bg={colors['blue-button-trans']} shadow="sm">
|
||||
<Stack gap="xs">
|
||||
<Text fz="lg" c={colors['white-1']} fw="bold">Informasi Kontak</Text>
|
||||
<Group gap="xs">
|
||||
<IconUser size={18} color="white" />
|
||||
<Text fz="md" c={colors['white-1']}>Penanggung Jawab: <Text span fw="bold">Bidan Komang Ayu</Text></Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<IconPhone size={18} color="white" />
|
||||
<Text fz="md" c={colors['white-1']}>081234567890</Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<IconMail size={18} color="white" />
|
||||
<Text fz="md" c={colors['white-1']}>puskesmasabiansemal3@gmail.com</Text>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
<Group>
|
||||
<Button fz={'lg'} bg={'green'}>
|
||||
Download Jadwal Posyandu 2025 (PDF)
|
||||
<Button size="md" radius="lg" leftSection={<IconDownload size={18} />} color="green">
|
||||
Unduh Jadwal Posyandu 2025 (PDF)
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
@@ -227,5 +216,4 @@ function Page() {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default Page;
|
||||
|
||||
@@ -1,53 +1,101 @@
|
||||
'use client'
|
||||
import jadwalkegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
|
||||
import colors from '@/con/colors';
|
||||
import { Anchor, Box, Divider, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { Box, Button, Card, Divider, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconChevronRight, IconClockHour4, IconMapPin } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
function JadwalKegiatanPage() {
|
||||
const state = useProxy(jadwalkegiatanState)
|
||||
const state = useProxy(jadwalkegiatanState);
|
||||
const router = useRouter();
|
||||
|
||||
useShallowEffect(()=> {
|
||||
state.findMany.load()
|
||||
}, [])
|
||||
useShallowEffect(() => {
|
||||
state.findMany.load();
|
||||
}, []);
|
||||
|
||||
if(!state.findMany.data){
|
||||
if (!state.findMany.data) {
|
||||
return (
|
||||
<Box py={10}>
|
||||
<Skeleton h={500} />
|
||||
<Box py="lg">
|
||||
<Skeleton h={500} radius="lg" />
|
||||
</Box>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Paper p={'xl'} h={'112vh'} bg={colors['white-trans-1']}>
|
||||
<Stack gap={'xs'}>
|
||||
<Text ta={'center'} fw={"bold"} fz={'h3'} c={colors['blue-button']}>Jadwal Kegiatan</Text>
|
||||
{state.findMany.data.map((item) => (
|
||||
<Box key={item.id}>
|
||||
<Text fz={'h4'} fw={'bold'}>
|
||||
{item.informasijadwalkegiatan.name}
|
||||
<Paper p="xl" bg={colors['white-trans-1']} radius="xl" shadow="md" h="auto" mih="100vh">
|
||||
<Stack gap="lg">
|
||||
<Text ta="center" fw={700} fz="32px" c={colors['blue-button']}>
|
||||
Jadwal Kegiatan Warga
|
||||
</Text>
|
||||
|
||||
{state.findMany.data.length === 0 ? (
|
||||
<Box py="xl" ta="center">
|
||||
<Text fz="lg" c="dimmed">
|
||||
Belum ada jadwal kegiatan yang tersedia
|
||||
</Text>
|
||||
<Text fz={'h4'}>
|
||||
{item.informasijadwalkegiatan.waktu}
|
||||
</Text>
|
||||
<Text fz={'h4'}>
|
||||
{item.informasijadwalkegiatan.lokasi}
|
||||
</Text>
|
||||
<Text fz={'h6'} fw={'bold'} c={colors['blue-button']}>
|
||||
{item.informasijadwalkegiatan.tanggal}
|
||||
</Text>
|
||||
<Anchor onClick={()=> router.push(`/darmasaba/kesehatan/data-kesehatan-warga/jadwal-kegiatan-page/${item.id}`)} c={colors['blue-button']} variant='transparent'>
|
||||
<Text c={colors['blue-button']} fz={'h4'} >
|
||||
Detail & Pendaftaran
|
||||
</Text>
|
||||
</Anchor>
|
||||
</Box>
|
||||
))}
|
||||
<Divider color={colors['blue-button']} px={'xl'} />
|
||||
) : (
|
||||
state.findMany.data.map((item) => (
|
||||
<Card
|
||||
key={item.id}
|
||||
withBorder
|
||||
radius="xl"
|
||||
shadow="sm"
|
||||
p="lg"
|
||||
style={{ backdropFilter: 'blur(8px)' }}
|
||||
>
|
||||
<Stack gap="sm">
|
||||
<Group justify="space-between">
|
||||
<Text fw={700} fz="xl">
|
||||
{item.informasijadwalkegiatan.name}
|
||||
</Text>
|
||||
<Text fw={600} fz="sm" c={colors['blue-button']}>
|
||||
{item.informasijadwalkegiatan.tanggal}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
<Group gap="xs">
|
||||
<IconClockHour4 size={18} color={colors['blue-button']} />
|
||||
<Text fz="sm">{item.informasijadwalkegiatan.waktu}</Text>
|
||||
</Group>
|
||||
|
||||
<Group gap="xs">
|
||||
<IconMapPin size={18} color={colors['blue-button']} />
|
||||
<Text fz="sm">{item.informasijadwalkegiatan.lokasi}</Text>
|
||||
</Group>
|
||||
|
||||
<Divider my="sm" />
|
||||
|
||||
<Group justify="flex-end">
|
||||
<Button
|
||||
variant="light"
|
||||
radius="lg"
|
||||
size="sm"
|
||||
rightSection={<IconChevronRight size={18} />}
|
||||
onClick={() =>
|
||||
router.push(
|
||||
`/darmasaba/kesehatan/data-kesehatan-warga/jadwal-kegiatan-page/${item.id}`
|
||||
)
|
||||
}
|
||||
styles={{
|
||||
root: {
|
||||
background: colors['blue-button'],
|
||||
color: 'white',
|
||||
boxShadow: '0 0 12px rgba(0, 123, 255, 0.4)',
|
||||
transition: 'all 0.2s ease',
|
||||
},
|
||||
}}
|
||||
>
|
||||
Lihat Detail & Daftar
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Card>
|
||||
))
|
||||
)}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
@@ -1,100 +1,169 @@
|
||||
'use client'
|
||||
import infoWabahPenyakit from '@/app/admin/(dashboard)/_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
||||
import {
|
||||
Box,
|
||||
Center,
|
||||
Grid,
|
||||
GridCol,
|
||||
Image,
|
||||
Pagination,
|
||||
Paper,
|
||||
SimpleGrid,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Badge,
|
||||
HoverCard,
|
||||
Divider,
|
||||
Group,
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconSearch } from '@tabler/icons-react';
|
||||
import { IconSearch, IconInfoCircle } from '@tabler/icons-react';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||
|
||||
function Page() {
|
||||
const state = useProxy(infoWabahPenyakit)
|
||||
const [search, setSearch] = useState('')
|
||||
const state = useProxy(infoWabahPenyakit);
|
||||
const [search, setSearch] = useState('');
|
||||
|
||||
const {
|
||||
data,
|
||||
page,
|
||||
totalPages,
|
||||
loading,
|
||||
load,
|
||||
} = state.findMany;
|
||||
const { data, page, totalPages, loading, load } = state.findMany;
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 3, search)
|
||||
}, [page, search])
|
||||
load(page, 6, search);
|
||||
}, [page, search]);
|
||||
|
||||
if (loading || !data) {
|
||||
return (
|
||||
<Box py={10}>
|
||||
<Skeleton h={500} />
|
||||
<Box py="xl" px={{ base: 'md', md: 100 }}>
|
||||
<Skeleton h={500} radius="lg" />
|
||||
</Box>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="lg">
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Grid align='center' px={{ base: 'md', md: 100 }}>
|
||||
<GridCol span={{ base: 12, md: 9 }}>
|
||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
||||
Info Wabah / Penyakit
|
||||
|
||||
<Grid align="center" px={{ base: 'md', md: 100 }}>
|
||||
<GridCol span={{ base: 12, md: 8 }}>
|
||||
<Text
|
||||
fz={{ base: '1.8rem', md: '2.8rem' }}
|
||||
c={colors['blue-button']}
|
||||
fw="bold"
|
||||
lh={1.2}
|
||||
>
|
||||
Informasi Wabah & Penyakit
|
||||
</Text>
|
||||
<Text fz="md" c="dimmed" mt={4}>
|
||||
Dapatkan informasi terbaru mengenai wabah dan penyakit yang sedang
|
||||
diawasi.
|
||||
</Text>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 3 }}>
|
||||
<GridCol span={{ base: 12, md: 4 }}>
|
||||
<TextInput
|
||||
radius={"lg"}
|
||||
placeholder='Cari Info Wabah / Penyakit'
|
||||
radius="xl"
|
||||
placeholder="Cari nama penyakit atau wabah..."
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftSection={<IconSearch size={20} />}
|
||||
w={{ base: "50%", md: "100%" }}
|
||||
w="100%"
|
||||
size="md"
|
||||
/>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Stack gap={'lg'}>
|
||||
<SimpleGrid
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 3,
|
||||
}}
|
||||
>
|
||||
{data.map((v, k) => {
|
||||
return (
|
||||
<Paper key={k} p={'xl'} bg={colors['white-trans-1']}>
|
||||
<Stack gap={'xs'}>
|
||||
<Box>
|
||||
<Text fw={"bold"} fz={'h3'} c={colors['blue-button']}>{v.name}</Text>
|
||||
<Image w={330} h={200} fit='contain' pt={5} src={v.image.link} alt={v.name} />
|
||||
<Text fz={'h4'} fw={'bold'} >
|
||||
{v.name}
|
||||
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
{data.length === 0 ? (
|
||||
<Center py="6xl">
|
||||
<Stack align="center" gap="sm">
|
||||
<IconInfoCircle size={50} color={colors['blue-button']} />
|
||||
<Text fz="lg" fw={500} c="dimmed">
|
||||
Tidak ada data yang cocok dengan pencarian Anda.
|
||||
</Text>
|
||||
</Stack>
|
||||
</Center>
|
||||
) : (
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="lg">
|
||||
{data.map((v, k) => (
|
||||
<Paper
|
||||
key={k}
|
||||
radius="lg"
|
||||
shadow="md"
|
||||
p="lg"
|
||||
withBorder
|
||||
bg={colors['white-trans-1']}
|
||||
style={{
|
||||
transition: 'transform 200ms ease, box-shadow 200ms ease',
|
||||
}}
|
||||
>
|
||||
<Stack gap="sm">
|
||||
<Image
|
||||
radius="md"
|
||||
h={180}
|
||||
src={v.image.link}
|
||||
alt={v.name}
|
||||
fit="cover"
|
||||
/>
|
||||
<Group justify="space-between" mt="sm">
|
||||
<Text fw={700} fz="lg" c={colors['blue-button']}>
|
||||
{v.name}
|
||||
</Text>
|
||||
<Badge color="blue" variant="light" radius="sm">
|
||||
Wabah
|
||||
</Badge>
|
||||
</Group>
|
||||
<Text fz="sm" c="dimmed">
|
||||
Diposting: 12 Februari 2025 · Dinas Kesehatan
|
||||
</Text>
|
||||
<Divider />
|
||||
<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>
|
||||
<Text fz={'h6'} pb={10}>
|
||||
Diposting: 12 Februari 2025 | Dinas Kesehatan
|
||||
</Text>
|
||||
<Text fz={'h4'} pb={10}>
|
||||
{v.deskripsiSingkat}
|
||||
</Text>
|
||||
<Text fz={'h4'} pb={10} dangerouslySetInnerHTML={{ __html: v.deskripsiLengkap }} />
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
})}
|
||||
</HoverCard.Target>
|
||||
<HoverCard.Dropdown>
|
||||
<Text
|
||||
fz="sm"
|
||||
lh={1.6}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: v.deskripsiLengkap,
|
||||
}}
|
||||
/>
|
||||
</HoverCard.Dropdown>
|
||||
</HoverCard>
|
||||
</Stack>
|
||||
</Paper>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={(newPage) => load(newPage)} // ini penting!
|
||||
total={totalPages}
|
||||
mt="md"
|
||||
mb="md"
|
||||
/>
|
||||
</Center>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={(newPage) => load(newPage)}
|
||||
total={totalPages}
|
||||
radius="xl"
|
||||
size="md"
|
||||
mt="lg"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,106 +1,150 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import {
|
||||
Box,
|
||||
Center,
|
||||
Grid,
|
||||
GridCol,
|
||||
Image,
|
||||
Pagination,
|
||||
Paper,
|
||||
SimpleGrid,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Tooltip,
|
||||
Badge,
|
||||
} from '@mantine/core';
|
||||
import { IconSearch, IconPhone } from '@tabler/icons-react';
|
||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||
import kontakDarurat from '@/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat';
|
||||
import { IconSearch } from '@tabler/icons-react';
|
||||
import colors from '@/con/colors';
|
||||
|
||||
function Page() {
|
||||
const state = useProxy(kontakDarurat)
|
||||
const [search, setSearch] = useState('')
|
||||
const state = useProxy(kontakDarurat);
|
||||
const [search, setSearch] = useState('');
|
||||
|
||||
const {
|
||||
data,
|
||||
page,
|
||||
totalPages,
|
||||
loading,
|
||||
load,
|
||||
} = state.findMany;
|
||||
const { data, page, totalPages, loading, load } = state.findMany;
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 3, search)
|
||||
}, [page, search])
|
||||
load(page, 6, search);
|
||||
}, [page, search]);
|
||||
|
||||
if (loading || !data) {
|
||||
return (
|
||||
<Box py={10}>
|
||||
<Skeleton h={500} />
|
||||
<Box py="xl" px={{ base: 'md', md: 100 }}>
|
||||
<Skeleton height={500} radius="lg" />
|
||||
</Box>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="lg">
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Grid align='center' px={{ base: 'md', md: 100 }}>
|
||||
<GridCol span={{ base: 12, md: 9 }}>
|
||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
||||
Penanganan Darurat
|
||||
|
||||
<Grid align="center" px={{ base: 'md', md: 100 }} gutter="lg">
|
||||
<GridCol span={{ base: 12, md: 8 }}>
|
||||
<Text fz={{ base: '2rem', md: '2.8rem' }} c={colors['blue-button']} fw={800}>
|
||||
Kontak Darurat
|
||||
</Text>
|
||||
<Text c="dimmed" fz="md" mt={4}>
|
||||
Hubungi layanan penting dengan cepat dan mudah
|
||||
</Text>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 3 }}>
|
||||
<TextInput
|
||||
radius={"lg"}
|
||||
placeholder='Cari Penanganan Darurat'
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftSection={<IconSearch size={20} />}
|
||||
w={{ base: "50%", md: "100%" }}
|
||||
/>
|
||||
<GridCol span={{ base: 12, md: 4 }}>
|
||||
<Tooltip label="Cari berdasarkan nama atau deskripsi" withArrow>
|
||||
<TextInput
|
||||
radius="xl"
|
||||
size="md"
|
||||
placeholder="Cari kontak darurat..."
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftSection={<IconSearch size={20} />}
|
||||
w="100%"
|
||||
/>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Stack gap={'lg'}>
|
||||
<SimpleGrid
|
||||
pb={10}
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 3,
|
||||
}}>
|
||||
{data.map((v, k) => {
|
||||
return (
|
||||
<Paper radius={10} key={k} bg={colors["white-trans-1"]}>
|
||||
<Stack gap={'xs'}>
|
||||
<Center py={40}>
|
||||
<Image
|
||||
src={v.image.link}
|
||||
alt={v.name}
|
||||
w={200}
|
||||
h={200}
|
||||
fit='contain'
|
||||
/>
|
||||
</Center>
|
||||
<Box px={'lg'}>
|
||||
<Box pb={20}>
|
||||
<Text pb={10} c={colors["blue-button"]} fw={"bold"} fz={"h3"}>
|
||||
{v.name}
|
||||
</Text>
|
||||
<Box px={10}>
|
||||
<Text fz={"h4"} dangerouslySetInnerHTML={{ __html: v.deskripsi }} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
})}
|
||||
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
{data.length === 0 ? (
|
||||
<Center mih={300}>
|
||||
<Stack align="center" gap="xs">
|
||||
<IconSearch size={50} color={colors['blue-button']} />
|
||||
<Text fz="lg" fw={600} c={colors['blue-button']}>
|
||||
Tidak ada kontak ditemukan
|
||||
</Text>
|
||||
<Text fz="sm" c="dimmed">
|
||||
Coba kata kunci lain untuk pencarian
|
||||
</Text>
|
||||
</Stack>
|
||||
</Center>
|
||||
) : (
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="xl" mt="lg">
|
||||
{data.map((v, k) => (
|
||||
<Paper
|
||||
key={k}
|
||||
radius="xl"
|
||||
shadow="md"
|
||||
withBorder
|
||||
p="lg"
|
||||
bg={colors['white-trans-1']}
|
||||
style={{
|
||||
transition: 'all 200ms ease',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
<Stack align="center" gap="sm">
|
||||
<Image
|
||||
src={v.image.link}
|
||||
alt={v.name}
|
||||
w={140}
|
||||
h={140}
|
||||
fit="contain"
|
||||
radius="md"
|
||||
/>
|
||||
<Text ta="center" fw={700} fz="lg" c={colors['blue-button']}>
|
||||
{v.name}
|
||||
</Text>
|
||||
<Text fz="sm" c="dimmed" ta="center" lineClamp={3}>
|
||||
<span dangerouslySetInnerHTML={{ __html: v.deskripsi }} />
|
||||
</Text>
|
||||
<Badge
|
||||
color="blue"
|
||||
leftSection={<IconPhone size={14} />}
|
||||
variant="light"
|
||||
mt="sm"
|
||||
>
|
||||
Panggil Sekarang
|
||||
</Badge>
|
||||
</Stack>
|
||||
</Paper>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={(newPage) => load(newPage)} // ini penting!
|
||||
total={totalPages}
|
||||
mt="md"
|
||||
mb="md"
|
||||
/>
|
||||
</Center>
|
||||
|
||||
{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>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,108 +1,162 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import penangananDarurat from '@/app/admin/(dashboard)/_state/kesehatan/penanganan-darurat/penangananDarurat';
|
||||
import { IconSearch } from '@tabler/icons-react';
|
||||
import penangananDarurat from '@/app/admin/(dashboard)/_state/kesehatan/penanganan-darurat/penangananDarurat'
|
||||
import colors from '@/con/colors'
|
||||
import {
|
||||
Badge,
|
||||
Box,
|
||||
Center,
|
||||
Grid,
|
||||
GridCol,
|
||||
Image,
|
||||
Pagination,
|
||||
Paper,
|
||||
SimpleGrid,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Tooltip
|
||||
} from '@mantine/core'
|
||||
import { useShallowEffect } from '@mantine/hooks'
|
||||
import { IconSearch } from '@tabler/icons-react'
|
||||
import { useState } from 'react'
|
||||
import { useProxy } from 'valtio/utils'
|
||||
import BackButton from '../../desa/layanan/_com/BackButto'
|
||||
|
||||
function Page() {
|
||||
const state = useProxy(penangananDarurat)
|
||||
const [search, setSearch] = useState('')
|
||||
|
||||
const {
|
||||
data,
|
||||
page,
|
||||
totalPages,
|
||||
loading,
|
||||
load,
|
||||
} = state.findMany;
|
||||
const { data, page, totalPages, loading, load } = state.findMany
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 3, search)
|
||||
load(page, 6, search)
|
||||
}, [page, search])
|
||||
|
||||
if (loading || !data) {
|
||||
return (
|
||||
<Box py={10}>
|
||||
<Skeleton h={500} />
|
||||
<Box py="xl" px={{ base: 'md', md: 100 }}>
|
||||
<Skeleton h={500} radius="lg" />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Stack bg={colors.Bg} py="xl" gap="xl" pos="relative">
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Grid align='center' px={{ base: 'md', md: 100 }}>
|
||||
|
||||
<Grid align="center" px={{ base: 'md', md: 100 }} mb="lg">
|
||||
<GridCol span={{ base: 12, md: 9 }}>
|
||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
||||
<Text fz={{ base: 30, md: 40 }} c={colors['blue-button']} fw={800} lh={1.2}>
|
||||
Penanganan Darurat
|
||||
</Text>
|
||||
<Text fz="md" c="dimmed" mt={4}>
|
||||
Informasi cepat dan jelas untuk situasi darurat kesehatan
|
||||
</Text>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 3 }}>
|
||||
<TextInput
|
||||
radius={"lg"}
|
||||
placeholder='Cari Penanganan Darurat'
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftSection={<IconSearch size={20} />}
|
||||
w={{ base: "50%", md: "100%" }}
|
||||
/>
|
||||
<Tooltip label="Ketik kata kunci untuk mencari penanganan darurat">
|
||||
<TextInput
|
||||
radius="lg"
|
||||
placeholder="Cari penanganan darurat..."
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftSection={<IconSearch size={20} />}
|
||||
w="100%"
|
||||
/>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Stack gap={'lg'}>
|
||||
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
{data.length === 0 ? (
|
||||
<Center py={100}>
|
||||
<Stack align="center" gap="xs">
|
||||
<Text fz="lg" fw={600} c={colors['blue-button']}>
|
||||
Tidak ada data ditemukan
|
||||
</Text>
|
||||
<Text fz="sm" c="dimmed">
|
||||
Coba gunakan kata kunci lain
|
||||
</Text>
|
||||
</Stack>
|
||||
</Center>
|
||||
) : (
|
||||
<SimpleGrid
|
||||
pb={10}
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 3,
|
||||
}}>
|
||||
{data.map((v, k) => {
|
||||
return (
|
||||
<Paper radius={10} key={k} bg={colors["white-trans-1"]}>
|
||||
<Stack gap={'xs'}>
|
||||
<Center py={40}>
|
||||
<Image
|
||||
src={v.image.link}
|
||||
alt={v.name}
|
||||
w={200}
|
||||
h={200}
|
||||
fit='contain'
|
||||
cols={{ base: 1, sm: 2, md: 3 }}
|
||||
spacing="xl"
|
||||
verticalSpacing="xl"
|
||||
pb={20}
|
||||
>
|
||||
{data.map((v, k) => (
|
||||
<Paper
|
||||
key={k}
|
||||
radius="xl"
|
||||
p="md"
|
||||
shadow="sm"
|
||||
withBorder
|
||||
bg={colors['white-trans-1']}
|
||||
style={{ transition: 'all 0.3s ease' }}
|
||||
>
|
||||
<Stack align="center" gap="md">
|
||||
<Center>
|
||||
<Image
|
||||
src={v.image.link}
|
||||
alt={v.name}
|
||||
w={160}
|
||||
h={160}
|
||||
fit="contain"
|
||||
radius="md"
|
||||
/>
|
||||
</Center>
|
||||
<Stack gap={4} w="100%">
|
||||
<Text
|
||||
fz="lg"
|
||||
fw={700}
|
||||
c={colors['blue-button']}
|
||||
ta="center"
|
||||
lineClamp={2}
|
||||
>
|
||||
{v.name}
|
||||
</Text>
|
||||
<Box>
|
||||
<Text
|
||||
fz="sm"
|
||||
c="dimmed"
|
||||
lineClamp={4}
|
||||
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
|
||||
/>
|
||||
</Center>
|
||||
<Box px={'lg'}>
|
||||
<Box pb={20}>
|
||||
<Text pb={10} c={colors["blue-button"]} fw={"bold"} fz={"h3"}>
|
||||
{v.name}
|
||||
</Text>
|
||||
<Box px={10}>
|
||||
<Text fz={"h4"} dangerouslySetInnerHTML={{ __html: v.deskripsi }} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
})}
|
||||
<Badge radius="md" color="blue" variant="light" mt="sm">
|
||||
Darurat
|
||||
</Badge>
|
||||
</Stack>
|
||||
</Paper>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={(newPage) => load(newPage)} // ini penting!
|
||||
total={totalPages}
|
||||
mt="md"
|
||||
mb="md"
|
||||
/>
|
||||
</Center>
|
||||
|
||||
{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>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
export default Page;
|
||||
export default Page
|
||||
|
||||
@@ -1,119 +1,166 @@
|
||||
'use client'
|
||||
import colors from "@/con/colors";
|
||||
import { Box, Center, Flex, Image, List, ListItem, Pagination, Paper, SimpleGrid, Skeleton, Spoiler, Stack, Text, TextInput } from "@mantine/core";
|
||||
import BackButton from "../../desa/layanan/_com/BackButto";
|
||||
// import { useTransitionRouter } from "next-view-transitions";
|
||||
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 { useShallowEffect } from "@mantine/hooks";
|
||||
import { useProxy } from "valtio/utils";
|
||||
import { IconCalendar, IconInfoCircle, IconPhone, IconSearch } from "@tabler/icons-react";
|
||||
import { useState } from "react";
|
||||
import { IconSearch } from "@tabler/icons-react";
|
||||
import { useProxy } from "valtio/utils";
|
||||
import BackButton from "../../desa/layanan/_com/BackButto";
|
||||
|
||||
export default function Page() {
|
||||
const state = useProxy(posyandustate)
|
||||
// const router = useTransitionRouter()
|
||||
const [search, setSearch] = useState("")
|
||||
const state = useProxy(posyandustate);
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
const {
|
||||
data,
|
||||
page,
|
||||
totalPages,
|
||||
loading,
|
||||
load,
|
||||
} = state.findMany;
|
||||
const { data, page, totalPages, loading, load } = state.findMany;
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 6, search);
|
||||
}, [page, search]);
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 3, search)
|
||||
}, [page, search])
|
||||
|
||||
if (loading || !data) {
|
||||
return (
|
||||
<Box py={10}>
|
||||
<Skeleton h={500} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
if (loading || !data) {
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
<Flex mt={10} justify={"space-between"} align={"center"}>
|
||||
<Text ta={"center"} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
||||
Posyandu Darmasaba
|
||||
</Text>
|
||||
<TextInput
|
||||
placeholder="Cari Posyandu"
|
||||
radius="lg"
|
||||
leftSection={<IconSearch size={20} />}
|
||||
w={{ base: "25%", md: "30%" }}
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.currentTarget.value)}
|
||||
/>
|
||||
</Flex>
|
||||
</Box>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Stack gap={'lg'}>
|
||||
<SimpleGrid
|
||||
pb={10}
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 3,
|
||||
}}>
|
||||
{data?.map((v, k) => {
|
||||
return (
|
||||
<Paper key={k} p={"xl"} bg={colors["white-trans-1"]}>
|
||||
<Stack gap={'xs'}>
|
||||
<Text c={colors["blue-button"]} fw={"bold"} fz={"h3"}>
|
||||
{v.name}
|
||||
</Text>
|
||||
<Center>
|
||||
<Image src={v.image.link} alt="" />
|
||||
</Center>
|
||||
<Text fz={'h4'}>
|
||||
No.Telp : {v.nomor}
|
||||
</Text>
|
||||
<Box>
|
||||
<Text fz={'h4'}>
|
||||
Jadwal Pelayanan
|
||||
</Text>
|
||||
<Text fz={'h4'} dangerouslySetInnerHTML={{ __html: v.jadwalPelayanan }} />
|
||||
</Box>
|
||||
<Spoiler
|
||||
maxHeight={60} // tinggi maksimum sebelum di-collapse
|
||||
showLabel="Read more"
|
||||
hideLabel="Read less"
|
||||
>
|
||||
<Text fz={'h4'} dangerouslySetInnerHTML={{ __html: v.deskripsi }} />
|
||||
</Spoiler>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
})}
|
||||
</SimpleGrid>
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={(newPage) => load(newPage)} // ini penting!
|
||||
total={totalPages}
|
||||
mt="md"
|
||||
mb="md"
|
||||
/>
|
||||
</Center>
|
||||
<Text fz={'h4'} fw={"bold"}>
|
||||
Pelayanan Posyandu
|
||||
</Text>
|
||||
<List type="ordered">
|
||||
<ListItem fz={'h4'}>Penimbangan bayi dan balita</ListItem>
|
||||
<ListItem fz={'h4'}>Pemantuan status gizi</ListItem>
|
||||
<ListItem fz={'h4'}>Imunisasi dasar lengkap</ListItem>
|
||||
<ListItem fz={'h4'}>Konseling</ListItem>
|
||||
<ListItem fz={'h4'}>Pemantuan kesehatan ibu hamil</ListItem>
|
||||
</List>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Box py="xl" px={{ base: "md", md: 100 }}>
|
||||
<Skeleton h={500} radius="lg" />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="xl">
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<BackButton />
|
||||
<Flex mt="md" justify="space-between" align="center" wrap="wrap" gap="md">
|
||||
<Text
|
||||
ta="left"
|
||||
fz={{ base: "1.8rem", md: "2.5rem" }}
|
||||
c={colors["blue-button"]}
|
||||
fw="bold"
|
||||
>
|
||||
Posyandu Desa Darmasaba
|
||||
</Text>
|
||||
<TextInput
|
||||
placeholder="Cari posyandu berdasarkan nama..."
|
||||
aria-label="Pencarian Posyandu"
|
||||
radius="xl"
|
||||
size="md"
|
||||
leftSection={<IconSearch size={20} />}
|
||||
w={{ base: "100%", md: "35%" }}
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.currentTarget.value)}
|
||||
/>
|
||||
</Flex>
|
||||
</Box>
|
||||
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Stack gap="xl">
|
||||
<SimpleGrid
|
||||
pb="lg"
|
||||
cols={{ base: 1, sm: 2, md: 3 }}
|
||||
spacing="lg"
|
||||
>
|
||||
{data?.map((v, k) => (
|
||||
<Paper
|
||||
key={k}
|
||||
p="xl"
|
||||
radius="lg"
|
||||
shadow="md"
|
||||
withBorder
|
||||
bg={colors["white-trans-1"]}
|
||||
style={{
|
||||
transition: "transform 0.2s ease, box-shadow 0.2s ease",
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
(e.currentTarget as HTMLElement).style.transform = "translateY(-4px)";
|
||||
(e.currentTarget as HTMLElement).style.boxShadow =
|
||||
"0 8px 24px rgba(0,0,0,0.12)";
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
(e.currentTarget as HTMLElement).style.transform = "translateY(0)";
|
||||
(e.currentTarget as HTMLElement).style.boxShadow =
|
||||
"0 4px 12px rgba(0,0,0,0.08)";
|
||||
}}
|
||||
>
|
||||
<Stack gap="sm">
|
||||
<Flex 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>
|
||||
<Center>
|
||||
<Image
|
||||
src={v.image.link}
|
||||
alt={`Gambar ${v.name}`}
|
||||
radius="md"
|
||||
w="100%"
|
||||
h={180}
|
||||
fit="cover"
|
||||
/>
|
||||
</Center>
|
||||
<Flex align="center" gap="xs">
|
||||
<IconPhone size={18} stroke={1.5} />
|
||||
<Text fz="sm" c="dimmed">
|
||||
{v.nomor || "Tidak tersedia"}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Flex align="center" gap="xs">
|
||||
<IconCalendar size={18} stroke={1.5} />
|
||||
<Text fz="sm" c="dimmed">
|
||||
Jadwal:{" "}
|
||||
<span dangerouslySetInnerHTML={{ __html: v.jadwalPelayanan }} />
|
||||
</Text>
|
||||
</Flex>
|
||||
<Spoiler
|
||||
maxHeight={70}
|
||||
showLabel="Lihat selengkapnya"
|
||||
hideLabel="Sembunyikan"
|
||||
transitionDuration={300}
|
||||
>
|
||||
<Text
|
||||
fz="sm"
|
||||
lh={1.5}
|
||||
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
|
||||
/>
|
||||
</Spoiler>
|
||||
</Stack>
|
||||
</Paper>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={(newPage) => load(newPage)}
|
||||
total={totalPages}
|
||||
radius="lg"
|
||||
size="md"
|
||||
withControls
|
||||
mt="md"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
|
||||
<Stack gap="sm">
|
||||
<Flex align="center" gap="xs">
|
||||
<IconInfoCircle size={22} color={colors["blue-button"]} />
|
||||
<Text fz="lg" fw="bold" c={colors["blue-button"]}>
|
||||
Layanan Utama Posyandu
|
||||
</Text>
|
||||
</Flex>
|
||||
<List spacing="xs" size="sm" center>
|
||||
<ListItem>Penimbangan bayi dan balita</ListItem>
|
||||
<ListItem>Pemantauan status gizi</ListItem>
|
||||
<ListItem>Imunisasi dasar lengkap</ListItem>
|
||||
<ListItem>Konseling kesehatan</ListItem>
|
||||
<ListItem>Pemantauan kesehatan ibu hamil</ListItem>
|
||||
</List>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
import programKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Center, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { Box, Center, Group, Image, Loader, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconCalendar, IconUser } from '@tabler/icons-react';
|
||||
import { useParams } from 'next/navigation';
|
||||
@@ -18,45 +18,75 @@ function Page() {
|
||||
|
||||
if (!state.findUnique.data) {
|
||||
return (
|
||||
<div>
|
||||
<Skeleton h={500} />
|
||||
</div>
|
||||
<Center mih="60vh">
|
||||
<Stack align="center" gap="sm">
|
||||
<Loader color={colors["blue-button"]} size="lg" />
|
||||
<Text c="dimmed" fz="sm">Memuat data program kesehatan...</Text>
|
||||
</Stack>
|
||||
</Center>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="xl">
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Paper px={{ base: 'md', md: 100 }} radius={10} bg={colors["white-trans-1"]}>
|
||||
<Stack gap={'xs'}>
|
||||
<Center my={20}>
|
||||
<Image radius={"lg"} src={state.findUnique.data.image?.link} alt="" />
|
||||
<Paper
|
||||
px={{ base: 'md', md: 100 }}
|
||||
py="xl"
|
||||
radius="xl"
|
||||
shadow="md"
|
||||
bg={colors["white-trans-1"]}
|
||||
>
|
||||
<Stack gap="lg">
|
||||
<Center>
|
||||
{state.findUnique.data.image?.link ? (
|
||||
<Image
|
||||
radius="xl"
|
||||
src={state.findUnique.data.image?.link}
|
||||
alt={state.findUnique.data.name}
|
||||
w="100%"
|
||||
maw={800}
|
||||
fit="cover"
|
||||
/>
|
||||
) : (
|
||||
<Skeleton h={300} w="100%" radius="xl" />
|
||||
)}
|
||||
</Center>
|
||||
<Box px={'lg'}>
|
||||
<Box>
|
||||
<Text pb={10} c={colors["blue-button"]} fw={"bold"} fz={"h3"}>
|
||||
{state.findUnique.data.name}
|
||||
</Text>
|
||||
<Text ta={'justify'} fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.deskripsi }}></Text>
|
||||
</Box>
|
||||
<Group py={20}>
|
||||
<Group gap="xs">
|
||||
<IconCalendar size={18} />
|
||||
<Text size="sm">
|
||||
{state.findUnique.data.createdAt ? new Date(state.findUnique.data.createdAt).toLocaleDateString('id-ID', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
}) : 'No date available'}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<IconUser size={18} />
|
||||
<Text size="sm">Admin Desa</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
<Box>
|
||||
<Text pb="sm" c={colors["blue-button"]} fw="bold" fz={{ base: 24, md: 32 }} lh={1.2}>
|
||||
{state.findUnique.data.name}
|
||||
</Text>
|
||||
<Text
|
||||
ta="justify"
|
||||
fz="md"
|
||||
lh={1.6}
|
||||
dangerouslySetInnerHTML={{ __html: state.findUnique.data.deskripsi }}
|
||||
/>
|
||||
</Box>
|
||||
<Group gap="xl">
|
||||
<Group gap="xs">
|
||||
<Tooltip label="Tanggal dibuat" withArrow>
|
||||
<IconCalendar size={20} stroke={1.5} />
|
||||
</Tooltip>
|
||||
<Text size="sm" c="dimmed">
|
||||
{state.findUnique.data.createdAt
|
||||
? new Date(state.findUnique.data.createdAt).toLocaleDateString('id-ID', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
})
|
||||
: 'Tanggal tidak tersedia'}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<Tooltip label="Dibuat oleh" withArrow>
|
||||
<IconUser size={20} stroke={1.5} />
|
||||
</Tooltip>
|
||||
<Text size="sm" c="dimmed">Admin Desa</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Stack>
|
||||
|
||||
@@ -1,7 +1,31 @@
|
||||
'use client'
|
||||
import colors from "@/con/colors";
|
||||
import { Box, Button, Center, Grid, GridCol, Group, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from "@mantine/core";
|
||||
import { IconBarbell, IconCalendar, IconOld, IconSearch, IconUser, IconUsersGroup } from "@tabler/icons-react";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Center,
|
||||
Grid,
|
||||
GridCol,
|
||||
Group,
|
||||
Image,
|
||||
Pagination,
|
||||
Paper,
|
||||
SimpleGrid,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Tooltip,
|
||||
Transition,
|
||||
} from "@mantine/core";
|
||||
import {
|
||||
IconBarbell,
|
||||
IconCalendar,
|
||||
IconOld,
|
||||
IconSearch,
|
||||
IconUser,
|
||||
IconUsersGroup,
|
||||
} from "@tabler/icons-react";
|
||||
import BackButton from "../../desa/layanan/_com/BackButto";
|
||||
import { useProxy } from "valtio/utils";
|
||||
import programKesehatan from "@/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan";
|
||||
@@ -9,104 +33,134 @@ import { useState } from "react";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
const data2 = [
|
||||
const manfaatProgram = [
|
||||
{
|
||||
id: 1,
|
||||
icon: <IconBarbell size={50} color={colors['BG-trans']} />,
|
||||
title: "Menjaga Kesehatan Tubuh",
|
||||
desc: "Program kesehatan desa dirancang untuk memelihara kesehatan fisik masyarakat melalui aktivitas rutin, pemeriksaan kesehatan berkala, dan edukasi gaya hidup sehat.",
|
||||
icon: <IconBarbell size={40} color="#fff" />,
|
||||
title: "Menjaga Tubuh Bugar",
|
||||
desc: "Meningkatkan kesehatan fisik masyarakat melalui olahraga rutin, pemeriksaan berkala, dan edukasi gaya hidup sehat.",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
icon: <IconUsersGroup size={50} color={colors['BG-trans']} />,
|
||||
title: "Mempererat Kebersamaan",
|
||||
desc: "Kegiatan kesehatan komunal menjadi wadah interaksi sosial yang memperkuat ikatan antar warga desa, menumbuhkan rasa kepedulian dan gotong royong.",
|
||||
icon: <IconUsersGroup size={40} color="#fff" />,
|
||||
title: "Menguatkan Kebersamaan",
|
||||
desc: "Menciptakan interaksi sosial sehat, mempererat solidaritas, dan memperkuat budaya gotong royong antar warga.",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
icon: <IconOld size={50} color={colors['BG-trans']} />,
|
||||
title: "Medukung Lansia Aktif",
|
||||
desc: "Program khusus bagi lansia membantu menjaga kebugaran, mengurangi risiko penyakit degeneratif, dan menciptakan komunitas pendukung untuk kehidupan yang sehat dan bahagia.",
|
||||
icon: <IconOld size={40} color="#fff" />,
|
||||
title: "Dukungan untuk Lansia",
|
||||
desc: "Membantu lansia tetap aktif, sehat, dan bahagia melalui kegiatan komunitas yang aman dan menyenangkan.",
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
export default function Page() {
|
||||
const state = useProxy(programKesehatan)
|
||||
const router = useRouter()
|
||||
const [search, setSearch] = useState('')
|
||||
const {
|
||||
data,
|
||||
page,
|
||||
totalPages,
|
||||
loading,
|
||||
load,
|
||||
} = state.findMany;
|
||||
const state = useProxy(programKesehatan);
|
||||
const router = useRouter();
|
||||
const [search, setSearch] = useState("");
|
||||
const { data, page, totalPages, loading, load } = state.findMany;
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 3, search)
|
||||
}, [page, search])
|
||||
load(page, 3, search);
|
||||
}, [page, search]);
|
||||
|
||||
if (loading || !data) {
|
||||
return (
|
||||
<Box py={10}>
|
||||
<Skeleton h={500} />
|
||||
<Box py="xl" px={{ base: "md", md: 100 }}>
|
||||
<Skeleton h={500} radius="lg" />
|
||||
</Box>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Stack bg={colors.Bg} py="xl" gap="xl">
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Grid px={{ base: 'md', md: 100 }} align="center">
|
||||
<GridCol span={{ base: 12, md: 9 }}>
|
||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
||||
Program Kesehatan Unggulan
|
||||
|
||||
<Grid px={{ base: "md", md: 100 }} align="center" gutter="lg">
|
||||
<GridCol span={{ base: 12, md: 8 }}>
|
||||
<Text
|
||||
fz={{ base: "2rem", md: "2.8rem" }}
|
||||
c={colors["blue-button"]}
|
||||
fw="bold"
|
||||
>
|
||||
Program Kesehatan Desa
|
||||
</Text>
|
||||
<Text fz="lg" c="dimmed" mt="xs">
|
||||
Temukan berbagai program kesehatan untuk mendukung kualitas hidup
|
||||
masyarakat Darmasaba.
|
||||
</Text>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 3 }}>
|
||||
<GridCol span={{ base: 12, md: 4 }}>
|
||||
<TextInput
|
||||
placeholder='Cari Program Kesehatan'
|
||||
placeholder="Cari program kesehatan..."
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftSection={<IconSearch size={20} />}
|
||||
w={{ base: "50%", md: "100%" }}
|
||||
radius="lg"
|
||||
size="md"
|
||||
aria-label="Pencarian program kesehatan"
|
||||
/>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Stack gap={'lg'}>
|
||||
<SimpleGrid
|
||||
pb={10}
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 3,
|
||||
}}>
|
||||
{data.map((v, k) => {
|
||||
return (
|
||||
<Paper radius={10} key={k} bg={colors["white-trans-1"]}>
|
||||
<Stack gap={'xs'}>
|
||||
<Center>
|
||||
<Image src={v.image?.link} alt="" style={{ borderRadius: '14px 14px 0 0' }} />
|
||||
</Center>
|
||||
<Box px={'lg'}>
|
||||
<Box>
|
||||
<Text pb={10} c={colors["blue-button"]} fw={"bold"} fz={"h3"}>
|
||||
{v.name}
|
||||
</Text>
|
||||
<Text ta={'justify'} fz={'h4'} dangerouslySetInnerHTML={{ __html: v.deskripsi }}></Text>
|
||||
</Box>
|
||||
<Box py={15} onClick={() => router.push(`/darmasaba/kesehatan/program-kesehatan/${v.id}`)}>
|
||||
<Button fw={'bold'} fz={'h5'} c={colors["blue-button"]} bg={colors["BG-trans"]}>Detail Program</Button>
|
||||
</Box>
|
||||
<Group py={20}>
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="lg" pb="xl">
|
||||
{data.map((v, k) => (
|
||||
<Transition
|
||||
key={k}
|
||||
mounted
|
||||
transition="fade-up"
|
||||
duration={400}
|
||||
timingFunction="ease"
|
||||
>
|
||||
{(styles) => (
|
||||
<Paper
|
||||
style={styles}
|
||||
radius="xl"
|
||||
withBorder
|
||||
bg="white"
|
||||
shadow="md"
|
||||
className="hover-scale"
|
||||
>
|
||||
<Stack gap="md">
|
||||
<Image
|
||||
src={v.image?.link}
|
||||
alt={v.name}
|
||||
radius="xl"
|
||||
height={180}
|
||||
fit="cover"
|
||||
/>
|
||||
<Box px="lg" pb="lg">
|
||||
<Text
|
||||
fw="bold"
|
||||
fz="xl"
|
||||
c={colors["blue-button"]}
|
||||
mb="xs"
|
||||
>
|
||||
{v.name}
|
||||
</Text>
|
||||
<Text
|
||||
fz="sm"
|
||||
c="dimmed"
|
||||
lineClamp={3}
|
||||
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
|
||||
/>
|
||||
<Group justify="space-between" mt="md">
|
||||
<Group gap="xs">
|
||||
<IconCalendar size={18} />
|
||||
<Text size="sm">
|
||||
{v.createdAt ? new Date(v.createdAt).toLocaleDateString('id-ID', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
}) : 'No date available'}
|
||||
{v.createdAt
|
||||
? new Date(v.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)
|
||||
: "Tanggal tidak tersedia"}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
@@ -114,61 +168,99 @@ export default function Page() {
|
||||
<Text size="sm">Admin Desa</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
<Tooltip label="Lihat detail program" withArrow>
|
||||
<Button
|
||||
mt="lg"
|
||||
fullWidth
|
||||
radius="lg"
|
||||
size="md"
|
||||
fw="bold"
|
||||
variant="gradient"
|
||||
gradient={{ from: colors["blue-button"], to: "#4dabf7" }}
|
||||
onClick={() =>
|
||||
router.push(
|
||||
`/darmasaba/kesehatan/program-kesehatan/${v.id}`
|
||||
)
|
||||
}
|
||||
>
|
||||
Lihat Detail
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
})}
|
||||
</SimpleGrid>
|
||||
)}
|
||||
</Transition>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={(newPage) => load(newPage)} // ini penting!
|
||||
onChange={(newPage) => load(newPage)}
|
||||
total={totalPages}
|
||||
mt="md"
|
||||
mb="md"
|
||||
size="lg"
|
||||
radius="xl"
|
||||
styles={{
|
||||
control: {
|
||||
borderRadius: "50%",
|
||||
boxShadow: "0 0 10px rgba(0,0,0,0.1)",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Center>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
<Box py={10} px={{ base: "md", md: 100 }}>
|
||||
<Box pb={10}>
|
||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
||||
|
||||
<Box px={{ base: "md", md: 100 }} py="xl">
|
||||
<Stack gap="sm" mb="lg">
|
||||
<Text
|
||||
fz={{ base: "2rem", md: "2.5rem" }}
|
||||
c={colors["blue-button"]}
|
||||
fw="bold"
|
||||
>
|
||||
Manfaat Program Kesehatan
|
||||
</Text>
|
||||
<Text fz={{ base: "h4", md: "h3" }} >
|
||||
Program kesehatan di Desa Darmasaba memiliki peran penting dalam meningkatkan kesejahteraan masyarakat.
|
||||
<Text fz="lg" c="dimmed" maw={700}>
|
||||
Program kesehatan Desa Darmasaba berperan penting dalam meningkatkan
|
||||
kesejahteraan dan kualitas hidup warganya.
|
||||
</Text>
|
||||
</Box>
|
||||
<SimpleGrid
|
||||
pb={30}
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 3,
|
||||
}}>
|
||||
{data2.map((v, k) => {
|
||||
return (
|
||||
<Paper key={k} px={"xl"} py={80} bg={colors['white-trans-1']} c={colors['blue-button']}>
|
||||
<Stack justify='space-between' >
|
||||
<Group justify='center'>
|
||||
<Paper p={'xl'} radius={'100'} bg={colors['blue-button']}>
|
||||
<Center >
|
||||
{v.icon}
|
||||
</Center>
|
||||
</Paper>
|
||||
</Group>
|
||||
<Text ta={"center"} fw={"bold"} fz={"h3"}>
|
||||
{v.title}
|
||||
</Text>
|
||||
<Text ta={"center"} fz={'h4'}>
|
||||
{v.desc}
|
||||
</Text>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
})}
|
||||
</Stack>
|
||||
<SimpleGrid cols={{ base: 1, md: 3 }} spacing="lg">
|
||||
{manfaatProgram.map((v) => (
|
||||
<Paper
|
||||
key={v.id}
|
||||
px="xl"
|
||||
py="xl"
|
||||
radius="xl"
|
||||
shadow="sm"
|
||||
withBorder
|
||||
bg="white"
|
||||
className="hover-glow"
|
||||
>
|
||||
<Stack align="center" gap="md">
|
||||
<Paper
|
||||
p="lg"
|
||||
radius="50%"
|
||||
shadow="md"
|
||||
bg={colors["blue-button"]}
|
||||
className="pulse-icon"
|
||||
>
|
||||
<Center>{v.icon}</Center>
|
||||
</Paper>
|
||||
<Text ta="center" fw="bold" fz="xl" c={colors["blue-button"]}>
|
||||
{v.title}
|
||||
</Text>
|
||||
<Text ta="center" fz="sm" c="dimmed">
|
||||
{v.desc}
|
||||
</Text>
|
||||
</Stack>
|
||||
</Paper>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
</Stack>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
'use client'
|
||||
import puskesmasState from '@/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas';
|
||||
import colors from '@/con/colors';
|
||||
import { BackgroundImage, Box, Grid, GridCol, Paper, SimpleGrid, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||
import { BackgroundImage, Box, Grid, GridCol, Paper, SimpleGrid, Skeleton, Stack, Text, Title, Tooltip, Badge, Divider, Group } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { IconClock, IconMapPin, IconPhone, IconMail, IconBuildingHospital } from '@tabler/icons-react';
|
||||
import BackButton from '../../../desa/layanan/_com/BackButto';
|
||||
|
||||
function Page() {
|
||||
@@ -17,95 +18,117 @@ function Page() {
|
||||
|
||||
if (!state.findUnique.data) {
|
||||
return (
|
||||
<Stack py={10}>
|
||||
<Skeleton h={500} />
|
||||
<Stack py="xl" px={{ base: 'md', md: 100 }}>
|
||||
<Skeleton h={500} radius="lg" />
|
||||
<Stack gap="sm">
|
||||
<Skeleton h={20} w="40%" />
|
||||
<Skeleton h={20} w="60%" />
|
||||
<Skeleton h={20} w="50%" />
|
||||
</Stack>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
const data = state.findUnique.data
|
||||
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap={32}>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Stack gap={'lg'} px={{ base: 'md', md: 100 }}>
|
||||
<Box>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
<Box pb={30}>
|
||||
<BackgroundImage
|
||||
pb={30}
|
||||
radius={16}
|
||||
h={{ base: 250, md: 500 }}
|
||||
src={state.findUnique.data.image.link}
|
||||
style={{ position: 'relative' }}
|
||||
|
||||
<Stack gap="xl" px={{ base: 'md', md: 100 }}>
|
||||
<Paper p="lg" radius="xl" shadow="md" bg={colors['white-trans-1']} withBorder>
|
||||
<Box pb="xl">
|
||||
<BackgroundImage
|
||||
radius="lg"
|
||||
h={{ base: 260, md: 480 }}
|
||||
src={data.image.link}
|
||||
style={{ position: 'relative', overflow: 'hidden' }}
|
||||
>
|
||||
<Box
|
||||
pos="absolute"
|
||||
w="100%"
|
||||
h="100%"
|
||||
bg={colors.trans.dark[2]}
|
||||
style={{ borderRadius: 16 }}
|
||||
/>
|
||||
<Stack
|
||||
pos="absolute"
|
||||
bottom={20}
|
||||
left={20}
|
||||
gap={6}
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
borderRadius: 16,
|
||||
zIndex: 0
|
||||
}}
|
||||
pos={"absolute"}
|
||||
w={"100%"}
|
||||
h={"100%"}
|
||||
bg={colors.trans.dark[2]}
|
||||
/>
|
||||
<Text style={{
|
||||
position: 'absolute',
|
||||
bottom: 35,
|
||||
left: 15,
|
||||
}} fw={'bold'} fz={{ base: 'md', md: 'h3' }} c={colors['white-1']}>{state.findUnique.data.name}</Text>
|
||||
<Text style={{
|
||||
position: 'absolute',
|
||||
bottom: 10,
|
||||
left: 15,
|
||||
}} fw={'bold'} fz={{ base: 'md', md: 'h4' }} c={colors['white-1']}>{state.findUnique.data.alamat}</Text>
|
||||
</BackgroundImage>
|
||||
<Grid
|
||||
py={20}>
|
||||
<GridCol span={{ base: 12, md: 6 }}>
|
||||
<Text fw="bold" fz={{ base: 'lg', md: 'h2' }} c={colors['white-1']}>
|
||||
{data.name}
|
||||
</Text>
|
||||
<Group gap={6}>
|
||||
<IconMapPin size={20} color="white" />
|
||||
<Text fz={{ base: 'sm', md: 'md' }} c={colors['white-1']}>
|
||||
{data.alamat}
|
||||
</Text>
|
||||
</Group>
|
||||
</Stack>
|
||||
</BackgroundImage>
|
||||
|
||||
<Grid mt="xl" gutter="xl">
|
||||
<GridCol span={{ base: 12, md: 6 }}>
|
||||
<Stack gap="lg">
|
||||
<Box>
|
||||
<Stack>
|
||||
<Title order={3}>Informasi</Title>
|
||||
<Box>
|
||||
<Text>Alamat: {state.findUnique.data.alamat}</Text>
|
||||
<Text>Telepon: {state.findUnique.data.kontak.kontakPuskesmas}</Text>
|
||||
<Text>Email: {state.findUnique.data.kontak.email}</Text>
|
||||
</Box>
|
||||
<Title order={3}>Jam Operasional</Title>
|
||||
<Box>
|
||||
<Text pb={10} fz={'h4'} fw={"bold"}>
|
||||
Senin - Kamis: <Text span fz={'h4'}>{state.findUnique.data?.jam.workDays} - {state.findUnique.data?.jam.weekDays}</Text>
|
||||
</Text>
|
||||
</Box>
|
||||
<Title order={3} mb={10}>Informasi Kontak</Title>
|
||||
<Stack gap={8}>
|
||||
<Group gap={8}>
|
||||
<IconPhone size={18} />
|
||||
<Text fz="md">{data.kontak.kontakPuskesmas || '-'}</Text>
|
||||
</Group>
|
||||
<Group gap={8}>
|
||||
<IconMail size={18} />
|
||||
<Text fz="md">{data.kontak.email || '-'}</Text>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Box>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 6 }}>
|
||||
<Box>
|
||||
<Paper p={"xl"} bg={'#B1C5F2'}>
|
||||
<SimpleGrid
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 2
|
||||
}}>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
<Text fw={"bold"} fz={'h3'} ta={'center'}>Poliklinik Umum</Text>
|
||||
<Text ta={'center'} fz={{ base: 45, md: 65 }} fw={'bold'} c={colors['blue-button']}>26</Text>
|
||||
</Paper>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
<Text ta={'center'} fz={'h3'} fw={"bold"}>Poli Gigi</Text>
|
||||
<Text ta={'center'} fz={{ base: 45, md: 65 }} fw={'bold'} c={colors['blue-button']}>26</Text>
|
||||
</Paper>
|
||||
</SimpleGrid>
|
||||
</Paper>
|
||||
</Box>
|
||||
</GridCol>
|
||||
<Box>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
</Paper>
|
||||
</Box>
|
||||
<Divider />
|
||||
|
||||
<Box>
|
||||
<Title order={3} mb={10}>Jam Operasional</Title>
|
||||
<Group gap={8}>
|
||||
<IconClock size={18} />
|
||||
<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>
|
||||
</Stack>
|
||||
</GridCol>
|
||||
|
||||
<GridCol span={{ base: 12, md: 6 }}>
|
||||
<Paper p="xl" radius="lg" bg="linear-gradient(135deg, #EAF0FB, #BFD4F5)" shadow="sm">
|
||||
<Title order={3} mb="lg" ta="center" c="dark">Layanan Unggulan</Title>
|
||||
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="lg">
|
||||
<Paper p="lg" radius="lg" withBorder bg={colors['white-trans-1']} shadow="xs">
|
||||
<Stack align="center" gap={8}>
|
||||
<IconBuildingHospital size={36} color={colors['blue-button']} />
|
||||
<Text fw="bold" fz="lg">Poliklinik Umum</Text>
|
||||
<Text fz={{ base: 36, md: 48 }} fw="bold" c={colors['blue-button']}>26</Text>
|
||||
</Stack>
|
||||
</Paper>
|
||||
<Paper p="lg" radius="lg" withBorder bg={colors['white-trans-1']} shadow="xs">
|
||||
<Stack align="center" gap={8}>
|
||||
<IconBuildingHospital size={36} color={colors['blue-button']} />
|
||||
<Text fw="bold" fz="lg">Poli Gigi</Text>
|
||||
<Text fz={{ base: 36, md: 48 }} fw="bold" c={colors['blue-button']}>26</Text>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</SimpleGrid>
|
||||
</Paper>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
'use client'
|
||||
import puskesmasState from '@/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas';
|
||||
import colors from '@/con/colors';
|
||||
import { Anchor, Box, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
||||
import { Anchor, Box, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Badge, Group } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconSearch } from '@tabler/icons-react';
|
||||
import { IconSearch, IconMapPin, IconPhone, IconMail } from '@tabler/icons-react';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||
|
||||
|
||||
function Page() {
|
||||
const state = useProxy(puskesmasState)
|
||||
const [search, setSearch] = useState('')
|
||||
@@ -22,76 +21,122 @@ function Page() {
|
||||
} = state.findMany;
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 3, search)
|
||||
load(page, 6, search)
|
||||
}, [page, search])
|
||||
|
||||
if (loading || !data) {
|
||||
return (
|
||||
<Box py={10}>
|
||||
<Skeleton h={500} />
|
||||
<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>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="lg">
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Grid align='center' px={{ base: 'md', md: 100 }}>
|
||||
<GridCol span={{ base: 12, md: 9 }}>
|
||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
||||
Puskesmas Darmasaba
|
||||
|
||||
<Grid align="center" px={{ base: 'md', md: 100 }} mb="md">
|
||||
<GridCol span={{ base: 12, md: 8 }}>
|
||||
<Text fz={{ base: "2rem", md: "2.5rem" }} c={colors["blue-button"]} fw="bold">
|
||||
Daftar Puskesmas
|
||||
</Text>
|
||||
<Text fz="sm" c="dimmed">
|
||||
Temukan informasi lengkap mengenai layanan, kontak, dan lokasi Puskesmas Darmasaba
|
||||
</Text>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 3 }}>
|
||||
<GridCol span={{ base: 12, md: 4 }}>
|
||||
<TextInput
|
||||
radius={"lg"}
|
||||
placeholder='Cari Puskesmas'
|
||||
radius="xl"
|
||||
placeholder="Cari nama puskesmas..."
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftSection={<IconSearch size={20} />}
|
||||
w={{ base: "50%", md: "100%" }}
|
||||
leftSection={<IconSearch size={18} />}
|
||||
aria-label="Cari Puskesmas"
|
||||
/>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<SimpleGrid
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 3,
|
||||
}}
|
||||
>
|
||||
{data.map((v, k) => {
|
||||
return (
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']} key={k}>
|
||||
<Stack gap={"xs"}>
|
||||
<Text fw={"bold"} fz={"h3"}>{v.name}</Text>
|
||||
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
{data.length === 0 ? (
|
||||
<Center py="xl">
|
||||
<Stack align="center" gap="xs">
|
||||
<Text fz="lg" fw={500} c="dimmed">Tidak ada data ditemukan</Text>
|
||||
<Text fz="sm" c="dimmed">Coba gunakan kata kunci pencarian yang berbeda</Text>
|
||||
</Stack>
|
||||
</Center>
|
||||
) : (
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="lg">
|
||||
{data.map((v, k) => (
|
||||
<Paper
|
||||
key={k}
|
||||
p="lg"
|
||||
radius="xl"
|
||||
withBorder
|
||||
shadow="md"
|
||||
bg={colors['white-trans-1']}
|
||||
style={{ transition: 'transform 200ms ease' }}
|
||||
className="hover:scale-[1.02]"
|
||||
>
|
||||
<Stack gap="sm">
|
||||
<Image
|
||||
src={v.image.link}
|
||||
alt={v.name}
|
||||
radius="md"
|
||||
height={160}
|
||||
fit="cover"
|
||||
/>
|
||||
<Box>
|
||||
<Text>Alamat: {v.alamat}</Text>
|
||||
<Text>Telepon: {v.kontak.kontakPuskesmas}</Text>
|
||||
<Text>Email: {v.kontak.email}</Text>
|
||||
</Box>
|
||||
<Anchor c={colors['blue-button']} href={`/darmasaba/kesehatan/puskesmas/${v.id}`}>Lihat Detail ></Anchor>
|
||||
<Group justify="space-between">
|
||||
<Text fw={600} fz="lg" lineClamp={1}>{v.name}</Text>
|
||||
<Badge color="blue" variant="light" radius="sm" fz="xs">Aktif</Badge>
|
||||
</Group>
|
||||
<Stack gap={4}>
|
||||
<Group gap="xs">
|
||||
<IconMapPin size={16} />
|
||||
<Text fz="sm" c="dimmed" lineClamp={2}>{v.alamat}</Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<IconPhone size={16} />
|
||||
<Text fz="sm" c="dimmed">{v.kontak.kontakPuskesmas}</Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<IconMail size={16} />
|
||||
<Text fz="sm" c="dimmed">{v.kontak.email}</Text>
|
||||
</Group>
|
||||
</Stack>
|
||||
<Anchor
|
||||
href={`/darmasaba/kesehatan/puskesmas/${v.id}`}
|
||||
fz="sm"
|
||||
fw={500}
|
||||
c={colors['blue-button']}
|
||||
>
|
||||
Lihat detail →
|
||||
</Anchor>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
})}
|
||||
</SimpleGrid>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
)}
|
||||
</Box>
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={(newPage) => load(newPage)} // ini penting!
|
||||
total={totalPages}
|
||||
mt="md"
|
||||
mb="md"
|
||||
/>
|
||||
</Center>
|
||||
|
||||
{totalPages > 1 && (
|
||||
<Center>
|
||||
<Pagination
|
||||
value={page}
|
||||
onChange={(newPage) => load(newPage, 6, search)}
|
||||
total={totalPages}
|
||||
size="md"
|
||||
radius="xl"
|
||||
mt="lg"
|
||||
/>
|
||||
</Center>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user