Fix UI User Menu PPID & Kesehatan
This commit is contained in:
@@ -1,62 +1,95 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
"use client";
|
||||||
|
|
||||||
import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
|
import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { ActionIcon, Box, Divider, Flex, Skeleton, Text } from '@mantine/core';
|
import { ActionIcon, Box, Divider, Flex, Group, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||||
import { IconBrandFacebook, IconBrandInstagram, IconBrandTwitter, IconBrandWhatsapp } from '@tabler/icons-react';
|
import { IconBrandFacebook, IconBrandInstagram, IconBrandTwitter, IconBrandWhatsapp } from '@tabler/icons-react';
|
||||||
import React, { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function PelayananPendudukNonPermanent() {
|
function PelayananPendudukNonPermanent() {
|
||||||
const state = useProxy(stateLayananDesa)
|
const state = useProxy(stateLayananDesa);
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true)
|
setLoading(true);
|
||||||
await state.pelayananPendudukNonPermanen.findById.load('1')
|
await state.pelayananPendudukNonPermanen.findById.load('1');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading data:', error);
|
console.error('Gagal memuat data:', error);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
loadData()
|
loadData();
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
|
const data = state.pelayananPendudukNonPermanen.findById.data;
|
||||||
|
|
||||||
const data = state.pelayananPendudukNonPermanen.findById.data
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box py="lg">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Skeleton h={500} />
|
<Stack gap="lg">
|
||||||
|
<Skeleton height={40} radius="md" />
|
||||||
|
<Skeleton height={200} radius="md" />
|
||||||
|
<Skeleton height={30} radius="md" />
|
||||||
|
</Stack>
|
||||||
) : (
|
) : (
|
||||||
<Box>
|
<Stack gap="xl">
|
||||||
<Box py={15}>
|
<Box>
|
||||||
<Text fz={{ base: "h4", md: "h3" }} fw={"bold"}>{data?.name}</Text>
|
<Text fz={{ base: "xl", md: "2xl" }} fw={700} lh={1.3} c="dark">
|
||||||
|
{data?.name || "Judul belum tersedia"}
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Text pb={20} fz={{ base: "sm", md: 'h3' }} ta={"justify"} dangerouslySetInnerHTML={{__html: data?.deskripsi || ''}} />
|
|
||||||
<Divider color={colors["blue-button"]} />
|
<Box>
|
||||||
<Flex justify={"space-between"} py={20}>
|
{data?.deskripsi ? (
|
||||||
<Text fz={{ base: "sm", md: 'h3' }}>25 May 2021 . Darmasaba</Text>
|
<Text
|
||||||
<Box>
|
fz={{ base: "sm", md: "md" }}
|
||||||
<Flex gap={"lg"}>
|
lh={1.7}
|
||||||
<ActionIcon variant='transparent'>
|
ta="justify"
|
||||||
<IconBrandFacebook color={colors["blue-button"]} size={"30"} />
|
c="dimmed"
|
||||||
|
dangerouslySetInnerHTML={{ __html: data?.deskripsi }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Text fz="sm" c="gray">Deskripsi belum tersedia.</Text>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Divider color={colors["blue-button"]} size="sm" />
|
||||||
|
|
||||||
|
<Flex justify="space-between" align="center" wrap="wrap" gap="md">
|
||||||
|
<Text fz={{ base: "xs", md: "sm" }} c="dimmed">
|
||||||
|
25 Mei 2021 • Darmasaba
|
||||||
|
</Text>
|
||||||
|
<Group gap="md">
|
||||||
|
<Tooltip label="Bagikan ke Facebook" withArrow>
|
||||||
|
<ActionIcon size="lg" radius="xl" variant="subtle" color="blue">
|
||||||
|
<IconBrandFacebook size={24} />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
<ActionIcon variant='transparent'>
|
</Tooltip>
|
||||||
<IconBrandInstagram color={colors["blue-button"]} size={"30"} />
|
<Tooltip label="Bagikan ke Instagram" withArrow>
|
||||||
|
<ActionIcon size="lg" radius="xl" variant="subtle" color="pink">
|
||||||
|
<IconBrandInstagram size={24} />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
<ActionIcon variant='transparent'>
|
</Tooltip>
|
||||||
<IconBrandTwitter color={colors["blue-button"]} size={"30"} />
|
<Tooltip label="Bagikan ke Twitter" withArrow>
|
||||||
|
<ActionIcon size="lg" radius="xl" variant="subtle" color="blue">
|
||||||
|
<IconBrandTwitter size={24} />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
<ActionIcon variant='transparent'>
|
</Tooltip>
|
||||||
<IconBrandWhatsapp color={colors["blue-button"]} size={"30"} />
|
<Tooltip label="Bagikan ke WhatsApp" withArrow>
|
||||||
|
<ActionIcon size="lg" radius="xl" variant="subtle" color="green">
|
||||||
|
<IconBrandWhatsapp size={24} />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</Flex>
|
</Tooltip>
|
||||||
</Box>
|
</Group>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Divider color={colors["blue-button"]} pb={50} />
|
|
||||||
</Box>
|
<Divider color={colors["blue-button"]} size="sm" />
|
||||||
|
</Stack>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
|
import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
|
||||||
import { Box, Button, Center, Group, Skeleton, Stepper, StepperCompleted, StepperStep, Text } from '@mantine/core';
|
import { Box, Button, Center, Group, Loader, Stack, Stepper, StepperCompleted, StepperStep, Text, Title } from '@mantine/core';
|
||||||
|
import { IconArrowLeft, IconArrowRight, IconCheck } from '@tabler/icons-react';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ function PelayananPerizinanBerusaha() {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
await state.pelayananPerizinanBerusaha.findById.load('1')
|
await state.pelayananPerizinanBerusaha.findById.load('1')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading data:', error);
|
console.error('Gagal memuat data:', error);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
@@ -28,76 +29,87 @@ function PelayananPerizinanBerusaha() {
|
|||||||
|
|
||||||
const data = state.pelayananPerizinanBerusaha.findById.data;
|
const data = state.pelayananPerizinanBerusaha.findById.data;
|
||||||
|
|
||||||
if (!data) {
|
if (!data && !loading) {
|
||||||
return (
|
return (
|
||||||
<Center>
|
<Center mih={300}>
|
||||||
<Text>Data tidak tersedia</Text>
|
<Stack align="center" gap="sm">
|
||||||
|
<Text fz="lg" fw={500} c="dimmed">Belum ada informasi layanan yang tersedia</Text>
|
||||||
|
<Button component="a" href="https://oss.go.id" target="_blank" radius="xl">Kunjungi OSS</Button>
|
||||||
|
</Stack>
|
||||||
</Center>
|
</Center>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box px={{ base: 'md', md: 'xl' }} py="lg">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Center>
|
<Center mih={300}>
|
||||||
<Skeleton h={250} />
|
<Loader size="lg" color="blue" />
|
||||||
</Center>
|
</Center>
|
||||||
) : (
|
) : (
|
||||||
<Box>
|
<Stack gap="lg">
|
||||||
<Box py={15}>
|
<Box>
|
||||||
<Text fz={{ base: "h4", md: 'h2' }} fw={"bold"}>Pelayanan Perizinan Berusaha Berbasis Risiko Melalui Sistem ONLINE SINGLE SUBMISSION (OSS)</Text>
|
<Title order={2} fw={700} fz={{ base: 22, md: 32 }} mb="sm">
|
||||||
</Box>
|
Perizinan Berusaha Berbasis Risiko melalui OSS
|
||||||
<Text
|
</Title>
|
||||||
py={10}
|
<Text fz={{ base: 'sm', md: 'md' }} c="dimmed">
|
||||||
ta={"justify"}
|
Sistem Online Single Submission (OSS) untuk pendaftaran NIB
|
||||||
fz={{ base: "sm", md: 'h3' }}
|
</Text>
|
||||||
dangerouslySetInnerHTML={{ __html: data.deskripsi || '' }}
|
</Box>
|
||||||
/>
|
|
||||||
<Text py={10} fz={{ base: "sm", md: 'h3' }}>Proses pendaftaran NIB melalui OSS mencakup beberapa langkah umum, seperti:</Text>
|
|
||||||
<Box p={"xl"} w={{ base: "100%", md: "100%" }}>
|
|
||||||
<Stepper active={active} onStepClick={setActive} orientation="vertical"
|
|
||||||
styles={{
|
|
||||||
separator: {
|
|
||||||
marginLeft: 25
|
|
||||||
},
|
|
||||||
step: {
|
|
||||||
padding: '12px 0'
|
|
||||||
}
|
|
||||||
}}>
|
|
||||||
<StepperStep label="Langkah Pertama" description="Pendaftaran Akun">
|
|
||||||
Pendaftaran akun pada portal OSS
|
|
||||||
</StepperStep>
|
|
||||||
<StepperStep label="Langkah Kedua" description="Pengisian Data Perusahaan">
|
|
||||||
Mengisi informasi perusahaan, termasuk data pemegang saham, alamat perusahaan, dan lainnya
|
|
||||||
</StepperStep>
|
|
||||||
<StepperStep label="Langkah Ketiga" description="Pemilihan KBLI">
|
|
||||||
Memilih KBLI dengan jenis usaha yang akan didaftarkan
|
|
||||||
</StepperStep>
|
|
||||||
<StepperStep label="Langkah Keempat" description="Pengunggahan Dokumen">
|
|
||||||
Mengunggah dokumen-dokumen yang diperlukan, seperti akta pendirian perusahaan, surat izin usaha, dan dokumen lainnya sesuai dengan ketentuan yang berlaku
|
|
||||||
</StepperStep>
|
|
||||||
<StepperStep label="Langkah Kelima" description="Verifikasi dan Persetujuan">
|
|
||||||
Proses verifikasi dan persetujuan oleh instansi terkait
|
|
||||||
</StepperStep>
|
|
||||||
<StepperStep label="Langkah Keenam" description="Penerimaan NIB">
|
|
||||||
Jika proses sebelumnya berhasil, perusahaan akan menerima NIB sebagai identitas resmi usaha anda
|
|
||||||
</StepperStep>
|
|
||||||
<StepperCompleted>
|
|
||||||
Selesai, anda telah mengikuti proses pendaftaran NIB melalui OSS
|
|
||||||
</StepperCompleted>
|
|
||||||
</Stepper>
|
|
||||||
|
|
||||||
<Group justify="center" mt="xl">
|
<Text fz={{ base: 'sm', md: 'md' }} ta="justify" dangerouslySetInnerHTML={{ __html: data?.deskripsi || '' }} />
|
||||||
<Button variant="default" onClick={prevStep}>Back</Button>
|
|
||||||
<Button onClick={nextStep}>Next step</Button>
|
<Box>
|
||||||
</Group>
|
<Text fw={600} mb="sm" fz={{ base: 'sm', md: 'lg' }}>Alur pendaftaran NIB:</Text>
|
||||||
<Text py={35} ta={"justify"} fz={{ base: "sm", md: 'h3' }}>
|
<Stepper active={active} onStepClick={setActive} orientation="vertical" color="blue" radius="md"
|
||||||
Penting untuk diingat bahwa prosedur dan persyaratan dapat berubah
|
styles={{
|
||||||
seiring waktu. Untuk informasi yang lebih akurat dan terkini, saya sarankan untuk mengunjungi situs
|
step: { padding: '14px 0' },
|
||||||
resmi OSS <a href="https://oss.go.id/" target="_blank" rel="noopener noreferrer">(https://oss.go.id/)</a> atau menghubungi instansi terkait di pemerintah Indonesia yang bertanggung jawab atas urusan perizinan usaha.
|
stepBody: { marginLeft: 8 }
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<StepperStep label="Langkah 1" description="Daftar Akun">
|
||||||
|
<Text fz="sm">Membuat akun di portal OSS</Text>
|
||||||
|
</StepperStep>
|
||||||
|
<StepperStep label="Langkah 2" description="Isi Data Perusahaan">
|
||||||
|
<Text fz="sm">Lengkapi informasi perusahaan, data pemegang saham, dan alamat</Text>
|
||||||
|
</StepperStep>
|
||||||
|
<StepperStep label="Langkah 3" description="Pilih KBLI">
|
||||||
|
<Text fz="sm">Menentukan kode KBLI sesuai jenis usaha</Text>
|
||||||
|
</StepperStep>
|
||||||
|
<StepperStep label="Langkah 4" description="Unggah Dokumen">
|
||||||
|
<Text fz="sm">Unggah akta pendirian, surat izin, dan dokumen wajib lainnya</Text>
|
||||||
|
</StepperStep>
|
||||||
|
<StepperStep label="Langkah 5" description="Verifikasi Instansi">
|
||||||
|
<Text fz="sm">Menunggu verifikasi dan persetujuan dari pihak berwenang</Text>
|
||||||
|
</StepperStep>
|
||||||
|
<StepperStep label="Langkah 6" description="Terbit NIB">
|
||||||
|
<Text fz="sm">Menerima NIB sebagai identitas resmi usaha</Text>
|
||||||
|
</StepperStep>
|
||||||
|
<StepperCompleted>
|
||||||
|
<Center>
|
||||||
|
<Stack align="center" gap="xs">
|
||||||
|
<IconCheck size={40} color="green" />
|
||||||
|
<Text fz="sm" fw={500}>Proses pendaftaran selesai</Text>
|
||||||
|
</Stack>
|
||||||
|
</Center>
|
||||||
|
</StepperCompleted>
|
||||||
|
</Stepper>
|
||||||
|
|
||||||
|
<Group justify="center" mt="lg">
|
||||||
|
<Button variant="light" leftSection={<IconArrowLeft size={18} />} onClick={prevStep} disabled={active === 0}>
|
||||||
|
Kembali
|
||||||
|
</Button>
|
||||||
|
<Button rightSection={<IconArrowRight size={18} />} onClick={nextStep}>
|
||||||
|
Lanjut
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Text fz="sm" ta="justify" c="dimmed" mt="md">
|
||||||
|
Catatan: Persyaratan dan prosedur dapat berubah sewaktu-waktu. Untuk informasi resmi terbaru, silakan kunjungi situs{" "}
|
||||||
|
<a href="https://oss.go.id/" target="_blank" rel="noopener noreferrer">oss.go.id</a> atau hubungi instansi pemerintah terkait.
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Stack>
|
||||||
</Box>
|
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,96 +1,124 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
"use client";
|
||||||
|
|
||||||
import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
|
import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { BackgroundImage, Box, Button, Center, Group, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
|
import { BackgroundImage, Box, Button, Center, Group, SimpleGrid, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||||
|
import { IconFileDescription, IconInfoCircle } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function PelayananSuratKeterangan({ search }: { search: string }) {
|
function PelayananSuratKeterangan({ search }: { search: string }) {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const router = useRouter()
|
const router = useRouter();
|
||||||
const state = useProxy(stateLayananDesa)
|
const state = useProxy(stateLayananDesa);
|
||||||
|
|
||||||
const filteredData = useMemo(() => {
|
const filteredData = useMemo(() => {
|
||||||
if (!state.suratKeterangan.findMany.data) return [];
|
if (!state.suratKeterangan.findMany.data) return [];
|
||||||
return state.suratKeterangan.findMany.data.filter(item => {
|
return state.suratKeterangan.findMany.data.filter((item) => {
|
||||||
const keyword = search.toLowerCase();
|
const keyword = search.toLowerCase();
|
||||||
return (
|
return item.name?.toLowerCase().includes(keyword);
|
||||||
item.name?.toLowerCase().includes(keyword)
|
});
|
||||||
);
|
|
||||||
})
|
|
||||||
}, [state.suratKeterangan.findMany.data, search]);
|
}, [state.suratKeterangan.findMany.data, search]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
await state.suratKeterangan.findMany.load()
|
await state.suratKeterangan.findMany.load();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading data:', error);
|
console.error('Gagal memuat data:', error);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
loadData()
|
loadData();
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box pb={10}>
|
<Box pb="xl">
|
||||||
<Text fz={{ base: "h4", md: 'h2' }} fw={"bold"}>Pelayanan Surat Keterangan</Text>
|
<Group justify="space-between" align="center" mb="md">
|
||||||
|
<Group gap="xs">
|
||||||
|
<IconFileDescription size={28} stroke={1.8} color={colors["blue-button"]} />
|
||||||
|
<Text fz={{ base: "h4", md: "h2" }} fw={700}>
|
||||||
|
Layanan Surat Keterangan
|
||||||
|
</Text>
|
||||||
|
</Group>
|
||||||
|
<Tooltip label="Pilih layanan surat keterangan sesuai kebutuhan Anda" withArrow>
|
||||||
|
<IconInfoCircle size={22} stroke={1.8} color={colors["blue-button"]} />
|
||||||
|
</Tooltip>
|
||||||
|
</Group>
|
||||||
|
|
||||||
<SimpleGrid
|
<SimpleGrid
|
||||||
py={20}
|
py="lg"
|
||||||
cols={{
|
cols={{ base: 1, sm: 2, md: 3 }}
|
||||||
base: 1,
|
spacing="lg"
|
||||||
sm: 3
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Center>
|
Array.from({ length: 3 }).map((_, i) => (
|
||||||
<Skeleton h={250} />
|
<Skeleton key={i} h={250} radius="lg" />
|
||||||
|
))
|
||||||
|
) : filteredData.length === 0 ? (
|
||||||
|
<Center py="xl">
|
||||||
|
<Stack align="center" gap="xs">
|
||||||
|
<IconFileDescription size={40} stroke={1.5} color={colors["blue-button"]} />
|
||||||
|
<Text c="dimmed" ta="center">
|
||||||
|
Tidak ada layanan surat keterangan yang ditemukan
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
</Center>
|
</Center>
|
||||||
) : (
|
) : (
|
||||||
filteredData.map((v, k) => {
|
filteredData.map((v, k) => (
|
||||||
return (
|
<BackgroundImage
|
||||||
<BackgroundImage
|
key={k}
|
||||||
key={k}
|
src={v.image?.link || ''}
|
||||||
src={v.image?.link || ''}
|
h={250}
|
||||||
h={250}
|
radius="lg"
|
||||||
radius={16}
|
pos="relative"
|
||||||
pos={"relative"}
|
style={{
|
||||||
>
|
boxShadow: "0 4px 20px rgba(0,0,0,0.1)",
|
||||||
<Box
|
overflow: "hidden",
|
||||||
style={{
|
}}
|
||||||
borderRadius: 16,
|
>
|
||||||
zIndex: 0
|
<Box
|
||||||
}}
|
pos="absolute"
|
||||||
pos={"absolute"}
|
w="100%"
|
||||||
w={"100%"}
|
h="100%"
|
||||||
h={"100%"}
|
bg="rgba(0,0,0,0.45)"
|
||||||
bg={colors.trans.dark[2]}
|
style={{ borderRadius: 16 }}
|
||||||
/>
|
/>
|
||||||
<Stack justify='space-between' h={"100%"} gap={0} p={"lg"} pos={"relative"}>
|
<Stack justify="space-between" h="100%" gap="md" p="lg" pos="relative">
|
||||||
<Box p={"lg"}>
|
<Text
|
||||||
<Text
|
c="white"
|
||||||
c={"white"}
|
fw={600}
|
||||||
size={"1.5rem"}
|
fz="lg"
|
||||||
style={{
|
ta="center"
|
||||||
textAlign: "center",
|
lineClamp={2}
|
||||||
}}>{v.name}</Text>
|
>
|
||||||
</Box>
|
{v.name}
|
||||||
<Group justify="center">
|
</Text>
|
||||||
<Button px={20} radius={"100"} size="md" bg={colors["blue-button"]}
|
<Group justify="center">
|
||||||
onClick={() => router.push(`/darmasaba/desa/layanan/${v.id}`)}>
|
<Button
|
||||||
Detail
|
size="md"
|
||||||
</Button>
|
radius="xl"
|
||||||
</Group>
|
bg={colors["blue-button"]}
|
||||||
</Stack>
|
px="lg"
|
||||||
</BackgroundImage>
|
onClick={() => router.push(`/darmasaba/desa/layanan/${v.id}`)}
|
||||||
)
|
style={{
|
||||||
})
|
boxShadow: "0 0 12px rgba(59,130,246,0.6)",
|
||||||
|
transition: "all 0.2s ease",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Lihat Detail
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</BackgroundImage>
|
||||||
|
))
|
||||||
)}
|
)}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
|
import stateLayananDesa from '@/app/admin/(dashboard)/_state/desa/layananDesa';
|
||||||
import { Box, Flex, Skeleton, Text, Title } from '@mantine/core';
|
import { Box, Card, Flex, Grid, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
|
import { IconExternalLink } from '@tabler/icons-react';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
@@ -11,22 +12,22 @@ interface ServiceItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function PelayananTelunjukSaktiDesa() {
|
function PelayananTelunjukSaktiDesa() {
|
||||||
const state = useProxy(stateLayananDesa)
|
const state = useProxy(stateLayananDesa);
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true)
|
setLoading(true);
|
||||||
await state.pelayananTelunjukSaktiDesa.findMany.load()
|
await state.pelayananTelunjukSaktiDesa.findMany.load();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading data:', error);
|
console.error('Gagal memuat data:', error);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
loadData()
|
loadData();
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
const data = (state.pelayananTelunjukSaktiDesa.findMany.data || []) as Array<{
|
const data = (state.pelayananTelunjukSaktiDesa.findMany.data || []) as Array<{
|
||||||
name: string;
|
name: string;
|
||||||
@@ -37,28 +38,63 @@ function PelayananTelunjukSaktiDesa() {
|
|||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
deletedAt: Date | null;
|
deletedAt: Date | null;
|
||||||
}>
|
}>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Title fz="h2" py={10} mb="md">Terwujudnya Layanan umum bertajuk Sistim administrasi Kependudukan Terintegrasi di Desa berbasi Elektronik, Smart dan Aman. Layanan Telunjuk Sakti Desa meliputi :</Title>
|
<Title order={2} mb="lg" fz={{ base: 22, md: 28 }} fw={700} style={{ lineHeight: 1.4 }}>
|
||||||
|
Layanan Telunjuk Sakti Desa <br />
|
||||||
|
<Text span c="dimmed" fz="lg" fw={400}>
|
||||||
|
Terwujudnya sistem administrasi kependudukan terintegrasi berbasis elektronik, cerdas, dan aman
|
||||||
|
</Text>
|
||||||
|
</Title>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Skeleton h={500} />
|
<Skeleton h={400} radius="lg" />
|
||||||
|
) : data.length === 0 ? (
|
||||||
|
<Card shadow="sm" radius="lg" withBorder>
|
||||||
|
<Text c="dimmed" ta="center" py="xl">
|
||||||
|
Belum ada layanan tersedia untuk saat ini
|
||||||
|
</Text>
|
||||||
|
</Card>
|
||||||
) : (
|
) : (
|
||||||
data.map((v, k) => {
|
<Grid gutter="lg">
|
||||||
return (
|
{data.map((v, k) => (
|
||||||
<Box key={k}>
|
<Grid.Col span={{ base: 12, sm: 6, lg: 4 }} key={k}>
|
||||||
<Box py={10}>
|
<Card
|
||||||
<Flex gap={"3"} align={"center"}>
|
shadow="md"
|
||||||
<Text fz={{ base: "h4", md: "h3" }} fw={"bold"}>{v.name}
|
radius="xl"
|
||||||
|
withBorder
|
||||||
|
p="lg"
|
||||||
|
style={{
|
||||||
|
transition: 'all 0.3s ease',
|
||||||
|
background: 'linear-gradient(145deg, #ffffff, #f8f9fa)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack gap="sm">
|
||||||
|
<Text fw={700} fz="lg" lh={1.4}>
|
||||||
|
{v.name}
|
||||||
</Text>
|
</Text>
|
||||||
<Text span fz={{ base: "h4", md: "h3" }}>
|
<Flex gap="xs" align="center">
|
||||||
<a href={v.link} target="_blank" rel="noopener noreferrer" style={{ color: '#228be6' }}>{v.deskripsi}</a>
|
<IconExternalLink size={18} stroke={1.5} />
|
||||||
</Text>
|
<Text
|
||||||
</Flex>
|
component="a"
|
||||||
</Box>
|
href={v.link}
|
||||||
</Box>
|
target="_blank"
|
||||||
)
|
rel="noopener noreferrer"
|
||||||
})
|
fz="sm"
|
||||||
|
c="blue"
|
||||||
|
td="underline"
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
>
|
||||||
|
{v.deskripsi}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</Grid.Col>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import PelayananPendudukNonPermanent from "./_com/pelayananPendudukNonPermanent"
|
|||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const [search, setSearch] = useState("")
|
const [search, setSearch] = useState("")
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||||
@@ -40,14 +40,16 @@ export default function Page() {
|
|||||||
</Stack>
|
</Stack>
|
||||||
</Container>
|
</Container>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
{/* Bagian Pelayanan Surat Keterangan */}
|
<Stack gap={"xl"}>
|
||||||
<PelayananSuratKeterangan search={search} />
|
{/* Bagian Pelayanan Surat Keterangan */}
|
||||||
{/* Bagian Pelayanan Perizinan Berusaha */}
|
<PelayananSuratKeterangan search={search} />
|
||||||
<PelayananPerizinanBerusaha/>
|
{/* Bagian Pelayanan Perizinan Berusaha */}
|
||||||
{/* Bagian Pelayanan Telunjuk Sakti Desa */}
|
<PelayananPerizinanBerusaha />
|
||||||
<PelayananTelunjukSaktiDesa/>
|
{/* Bagian Pelayanan Telunjuk Sakti Desa */}
|
||||||
{/* Bagian Pelayanan Penduduk Non Permanent */}
|
<PelayananTelunjukSaktiDesa />
|
||||||
<PelayananPendudukNonPermanent/>
|
{/* Bagian Pelayanan Penduduk Non Permanent */}
|
||||||
|
<PelayananPendudukNonPermanent />
|
||||||
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,18 +2,18 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import potensiDesaState from '@/app/admin/(dashboard)/_state/desa/potensi';
|
import potensiDesaState from '@/app/admin/(dashboard)/_state/desa/potensi';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Center, Container, Image, Skeleton, Stack, Text } from '@mantine/core';
|
import { Box, Center, Container, Image, Loader, Paper, Stack, Text, Title } from '@mantine/core';
|
||||||
|
import { IconMoodSad } from '@tabler/icons-react';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import BackButton from '../../layanan/_com/BackButto';
|
import BackButton from '../../layanan/_com/BackButto';
|
||||||
|
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const params = useParams<{ id: string }>();
|
const params = useParams<{ id: string }>();
|
||||||
const id = Array.isArray(params.id) ? params.id[0] : params.id;
|
const id = Array.isArray(params.id) ? params.id[0] : params.id;
|
||||||
const state = useProxy(potensiDesaState.potensiDesa)
|
const state = useProxy(potensiDesaState.potensiDesa);
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
@@ -22,54 +22,66 @@ function Page() {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
await state.findUnique.load(id);
|
await state.findUnique.load(id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading data:', error);
|
console.error('Gagal memuat data:', error);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
loadData()
|
loadData();
|
||||||
}, [id])
|
}, [id]);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<Center>
|
<Center h="80vh">
|
||||||
<Skeleton height={500} />
|
<Stack align="center" gap="md">
|
||||||
|
<Loader size="lg" color="blue" />
|
||||||
|
<Text c="dimmed" fz="sm">Sedang memuat informasi...</Text>
|
||||||
|
</Stack>
|
||||||
</Center>
|
</Center>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.findUnique.data) {
|
if (!state.findUnique.data) {
|
||||||
return (
|
return (
|
||||||
<Center>
|
<Center h="80vh">
|
||||||
<Text>Data tidak ditemukan</Text>
|
<Stack align="center" gap="sm">
|
||||||
|
<IconMoodSad size={64} stroke={1.5} color="var(--mantine-color-blue-6)" />
|
||||||
|
<Title order={3}>Data Tidak Ditemukan</Title>
|
||||||
|
<Text c="dimmed" fz="sm">Mohon periksa kembali atau coba beberapa saat lagi</Text>
|
||||||
|
</Stack>
|
||||||
</Center>
|
</Center>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"} px={{ base: "md", md: 0 }}>
|
<Stack pos="relative" bg={colors.Bg} py="xl" gap="xl" px={{ base: "md", md: 0 }}>
|
||||||
<Box px={{ base: "md", md: 100 }}><BackButton /></Box>
|
|
||||||
<Container w={{ base: "100%", md: "50%" }} >
|
|
||||||
<Box pb={20}>
|
|
||||||
<Text ta={"center"} fz={"3.4rem"} c={colors["blue-button"]} fw={"bold"}>
|
|
||||||
{state.findUnique.data?.name}
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
ta={"center"}
|
|
||||||
fw={"bold"}
|
|
||||||
fz={"1.5rem"}
|
|
||||||
>
|
|
||||||
Informasi dan Pelayanan Administrasi Digital
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
<Image src={state.findUnique.data?.image?.link || ''} alt='' w={"100%"} />
|
|
||||||
</Container>
|
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
<Text py={20} fz={{ base: "sm", md: "lg" }} ta={"justify"}>
|
<BackButton />
|
||||||
{state.findUnique.data?.deskripsi || ''}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
</Box>
|
||||||
|
<Container w={{ base: "100%", md: "60%" }}>
|
||||||
|
<Paper radius="2xl" shadow="lg" p="xl" withBorder>
|
||||||
|
<Stack gap="lg" align="center">
|
||||||
|
<Title ta="center" fz={{ base: "2rem", md: "3rem" }} c={colors["blue-button"]} fw={800}>
|
||||||
|
{state.findUnique.data?.name}
|
||||||
|
</Title>
|
||||||
|
<Text ta="center" fw={600} fz={{ base: "md", md: "lg" }} c="dimmed">
|
||||||
|
Informasi & Pelayanan Potensi Desa Digital
|
||||||
|
</Text>
|
||||||
|
<Image
|
||||||
|
src={state.findUnique.data?.image?.link || ''}
|
||||||
|
alt={state.findUnique.data?.name || 'Potensi Desa'}
|
||||||
|
radius="lg"
|
||||||
|
fit="cover"
|
||||||
|
w="100%"
|
||||||
|
h={{ base: 220, md: 400 }}
|
||||||
|
fallbackSrc="https://placehold.co/800x400?text=Gambar+tidak+tersedia"
|
||||||
|
/>
|
||||||
|
<Text py="md" fz={{ base: "sm", md: "md" }} ta="justify" lh={1.8}>
|
||||||
|
{state.findUnique.data?.deskripsi || 'Belum ada deskripsi untuk potensi desa ini.'}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Container>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
|
import potensiDesaState from '@/app/admin/(dashboard)/_state/desa/potensi';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { BackgroundImage, Box, Button, Center, Flex, Group, Paper, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
|
import { BackgroundImage, Box, Button, Center, Flex, Group, Paper, SimpleGrid, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
||||||
|
import { IconEye } from '@tabler/icons-react';
|
||||||
import { useTransitionRouter } from 'next-view-transitions';
|
import { useTransitionRouter } from 'next-view-transitions';
|
||||||
import BackButton from '../layanan/_com/BackButto';
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import potensiDesaState from '@/app/admin/(dashboard)/_state/desa/potensi';
|
import BackButton from '../layanan/_com/BackButto';
|
||||||
|
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const router = useTransitionRouter()
|
const router = useTransitionRouter()
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const state = useProxy(potensiDesaState)
|
const state = useProxy(potensiDesaState)
|
||||||
|
|
||||||
useEffect(()=> {
|
useEffect(() => {
|
||||||
state.kategoriPotensi.findMany.load()
|
state.kategoriPotensi.findMany.load()
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
await state.potensiDesa.findMany.load()
|
await state.potensiDesa.findMany.load()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading data:', error);
|
console.error('Gagal memuat data:', error);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
@@ -30,104 +30,121 @@ function Page() {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const data = state.potensiDesa.findMany.data
|
const data = state.potensiDesa.findMany.data
|
||||||
// const kategoriData = state.kategoriPotensi.findMany.data
|
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"} >
|
<Stack pos="relative" bg={colors.Bg} py="xl" gap={48}>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
<Box>
|
<Flex justify="space-between" align="center" direction={{ base: "column", md: "row" }} gap="lg">
|
||||||
<Stack gap={0}>
|
<Stack gap="sm" maw={600}>
|
||||||
<Flex justify={"space-between"} align={"center"} >
|
<Text fz={{ base: "2rem", md: "3rem" }} fw={900} c={colors["blue-button"]} lh={1.2}>
|
||||||
|
Potensi Desa Darmasaba
|
||||||
|
</Text>
|
||||||
|
<Text fz="lg" c="dimmed" ta="justify">
|
||||||
|
Temukan berbagai potensi unggulan, peluang, dan daya tarik yang menjadikan Desa Darmasaba istimewa.
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
<Paper
|
||||||
|
radius="2xl"
|
||||||
|
px="xl"
|
||||||
|
py="md"
|
||||||
|
bg={colors["blue-button"]}
|
||||||
|
shadow="xl"
|
||||||
|
withBorder
|
||||||
|
>
|
||||||
|
<Flex justify="center" align="center" gap="xl">
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz={"3.4rem"} c={colors["blue-button"]} fw={"bold"}>
|
<Text ta="center" fz="2rem" fw={800} c="white">
|
||||||
Potensi Desa
|
{data?.filter(item => item.kategori?.nama.toLowerCase() !== 'wisata').length || 0}
|
||||||
</Text>
|
</Text>
|
||||||
<Text ta={"justify"} >
|
<Text ta="center" fz="sm" c="white" fw={500}>
|
||||||
Temukan berbagai potensi dan keunggulan yang dimiliki Desa Darmasaba.
|
Potensi
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Text ta="center" fz="2rem" fw={800} c="white">
|
||||||
|
{data?.filter(item => item.kategori?.nama.toLowerCase() === 'wisata').length || 0}
|
||||||
|
</Text>
|
||||||
|
<Text ta="center" fz="sm" c="white" fw={500}>
|
||||||
|
Wisata
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Paper radius={"md"} px={"xl"} py={5} bg={colors["blue-button"]} >
|
|
||||||
<Flex justify={"space-between"} align={"center"} gap={"xl"}>
|
|
||||||
<Box>
|
|
||||||
<Text ta={"center"} fz={"h2"} fw={"bold"} c={"white"}>
|
|
||||||
{data?.filter(item => item.kategori?.nama.toLowerCase() !== 'wisata' ).length || 0}
|
|
||||||
</Text>
|
|
||||||
<Text ta={"center"} fz={"sm"} c={"white"}>Potensi</Text>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<Text ta={"center"} fz={"h2"} fw={"bold"} c={"white"}>
|
|
||||||
{data?.filter(item => item.kategori?.nama.toLowerCase() === 'wisata' ).length || 0}
|
|
||||||
</Text>
|
|
||||||
<Text ta={"center"} fz={"sm"} c={"white"}>Wisata</Text>
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
|
||||||
</Paper>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Stack>
|
</Paper>
|
||||||
</Box>
|
</Flex>
|
||||||
|
|
||||||
<SimpleGrid
|
<SimpleGrid py={48} cols={{ base: 1, sm: 2, lg: 3 }} spacing="2xl">
|
||||||
py={20}
|
|
||||||
cols={{
|
|
||||||
base: 1,
|
|
||||||
sm: 3
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Center>
|
Array.from({ length: 6 }).map((_, i) => (
|
||||||
<Skeleton h={250} />
|
<Skeleton key={i} h={360} radius="xl" />
|
||||||
</Center>
|
))
|
||||||
) : (
|
) : data && data.length > 0 ? (
|
||||||
data?.map((v, k) => {
|
data.map((v, k) => (
|
||||||
return (
|
|
||||||
<BackgroundImage
|
<BackgroundImage
|
||||||
key={k}
|
key={k}
|
||||||
src={v.image?.link || ''}
|
src={v.image?.link || ''}
|
||||||
h={350}
|
h={360}
|
||||||
radius={16}
|
radius="xl"
|
||||||
pos={"relative"}
|
style={{ overflow: 'hidden', position: 'relative' }}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
style={{
|
pos="absolute"
|
||||||
borderRadius: 16,
|
inset={0}
|
||||||
zIndex: 0
|
bg="linear-gradient(180deg, rgba(0,0,0,0.25) 0%, rgba(0,0,0,0.7) 100%)"
|
||||||
}}
|
|
||||||
pos={"absolute"}
|
|
||||||
w={"100%"}
|
|
||||||
h={"100%"}
|
|
||||||
bg={colors.trans.dark[2]}
|
|
||||||
/>
|
/>
|
||||||
<Stack justify='space-between' h={"100%"} gap={0} p={"lg"} pos={"relative"}>
|
<Stack justify="space-between" h="100%" gap="md" p="lg" pos="relative">
|
||||||
<Group>
|
<Group>
|
||||||
<Paper radius={"lg"} py={7} px={10}>
|
<Paper radius="lg" py={6} px={12} shadow="md" withBorder bg="rgba(255,255,255,0.85)">
|
||||||
<Text>{v.kategori?.nama}</Text>
|
<Text fz="sm" fw={600}>{v.kategori?.nama}</Text>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Group>
|
</Group>
|
||||||
<Box p={"lg"}>
|
<Box>
|
||||||
<Text
|
<Text
|
||||||
fw={"bold"}
|
fw={800}
|
||||||
c={"white"}
|
c="white"
|
||||||
size={"1.8rem"}
|
fz="xl"
|
||||||
style={{
|
ta="center"
|
||||||
textAlign: "center",
|
lineClamp={2}
|
||||||
}}>{v.name}</Text>
|
lh={1.3}
|
||||||
|
>
|
||||||
|
{v.name}
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Group justify="center">
|
<Group justify="center">
|
||||||
<Button px={20} radius={"100"} size="md" bg={colors["blue-button"]}
|
<Tooltip label="Lihat detail potensi" withArrow>
|
||||||
onClick={() => router.push(`/darmasaba/desa/potensi/${v.id}`)}>
|
<Button
|
||||||
Detail
|
radius="xl"
|
||||||
</Button>
|
size="md"
|
||||||
|
leftSection={<IconEye size={18} />}
|
||||||
|
bg={colors["blue-button"]}
|
||||||
|
variant="gradient"
|
||||||
|
gradient={{ from: colors["blue-button"], to: "#4dabf7", deg: 45 }}
|
||||||
|
onClick={() => router.push(`/darmasaba/desa/potensi/${v.id}`)}
|
||||||
|
>
|
||||||
|
Lihat Detail
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</BackgroundImage>
|
</BackgroundImage>
|
||||||
)
|
))
|
||||||
})
|
) : (
|
||||||
)}
|
<Center h={240}>
|
||||||
|
<Stack align="center" gap="xs">
|
||||||
|
<Text fz="lg" fw={600} c="dimmed">
|
||||||
|
Belum ada potensi desa
|
||||||
|
</Text>
|
||||||
|
<Text fz="sm" c="dimmed">
|
||||||
|
Data potensi akan tampil di sini setelah tersedia.
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile'
|
||||||
import { Box, Stack, Paper, Image, Text, Center, Skeleton } from '@mantine/core';
|
import colors from '@/con/colors'
|
||||||
import React, { useEffect } from 'react';
|
import { Box, Center, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core'
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useEffect } from 'react'
|
||||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
import { useProxy } from 'valtio/utils'
|
||||||
|
|
||||||
function LambangDesa() {
|
function LambangDesa() {
|
||||||
const state = useProxy(stateProfileDesa.lambangDesa)
|
const state = useProxy(stateProfileDesa.lambangDesa)
|
||||||
@@ -17,26 +17,60 @@ function LambangDesa() {
|
|||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py="lg">
|
||||||
<Skeleton h={500} />
|
<Skeleton h={420} radius="xl" />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box pb={70}>
|
<Box pb={90}>
|
||||||
<Stack align='center' gap={0}>
|
<Stack align="center" gap="lg">
|
||||||
<Box pb={30}>
|
<Box pb="lg">
|
||||||
<Center>
|
<Center>
|
||||||
<Image src={"/darmasaba-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
<Image
|
||||||
|
src={"/darmasaba-icon.png"}
|
||||||
|
alt="Lambang resmi desa"
|
||||||
|
w={{ base: 180, md: 280 }}
|
||||||
|
radius="md"
|
||||||
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Lambang Desa</Text>
|
<Text
|
||||||
|
c={colors['blue-button']}
|
||||||
|
ta="center"
|
||||||
|
fw={800}
|
||||||
|
fz={{ base: 28, md: 40 }}
|
||||||
|
mt="sm"
|
||||||
|
style={{ letterSpacing: '-0.5px' }}
|
||||||
|
>
|
||||||
|
Lambang Desa
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
<Paper
|
||||||
<Text fz={{ base: "md", md: "h3"}} ta={"justify"} dangerouslySetInnerHTML={{__html: data.deskripsi}} />
|
p="xl"
|
||||||
|
radius="xl"
|
||||||
|
withBorder
|
||||||
|
shadow="sm"
|
||||||
|
w="100%"
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(135deg, #ffffff 0%, #f3f7ff 100%)',
|
||||||
|
borderColor: '#e0e9ff',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip label="Deskripsi lambang desa" position="top-start" withArrow>
|
||||||
|
<Text
|
||||||
|
fz={{ base: 'md', md: 'lg' }}
|
||||||
|
lh={1.8}
|
||||||
|
c="dark"
|
||||||
|
ta="justify"
|
||||||
|
style={{ fontWeight: 400 }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: data.deskripsi }}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box >
|
</Box>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LambangDesa;
|
export default LambangDesa
|
||||||
|
|||||||
@@ -1,59 +1,95 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||||
import colors from '@/con/colors';
|
import { Box, Card, Center, Group, Image, Loader, Paper, Stack, Text, Tooltip } from '@mantine/core';
|
||||||
import { Box, Card, Center, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import { IconPhoto } from '@tabler/icons-react';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
|
||||||
function MaskotDesa() {
|
function MaskotDesa() {
|
||||||
const state = useProxy(stateProfileDesa.maskotDesa)
|
const state = useProxy(stateProfileDesa.maskotDesa);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
state.findUnique.load("edit")
|
state.findUnique.load('edit');
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
const { data, loading } = state.findUnique
|
const { data, loading } = state.findUnique;
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Center mih={500}>
|
||||||
<Skeleton h={500} />
|
<Stack align="center" gap="sm">
|
||||||
</Box>
|
<Loader size="lg" color="blue" />
|
||||||
)
|
<Text c="dimmed" fz="sm">Sedang memuat data maskot desa...</Text>
|
||||||
|
</Stack>
|
||||||
|
</Center>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box pb={70}>
|
<Box pb={80}>
|
||||||
<Stack align='center' gap={0}>
|
<Stack align="center" gap="xl">
|
||||||
<Box pb={30}>
|
<Stack align="center" gap={10}>
|
||||||
<Center>
|
<Image src="/pudak-icon.png" alt="Ikon Desa" w={{ base: 160, md: 240 }} />
|
||||||
<Image src={"/pudak-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
<Text c={colors['blue-button']} ta="center" fw={700} fz={{ base: 28, md: 36 }}>Maskot Desa</Text>
|
||||||
</Center>
|
</Stack>
|
||||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Maskot Desa</Text>
|
|
||||||
</Box>
|
<Paper
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
p={{ base: 'md', md: 'xl' }}
|
||||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: data.deskripsi }} />
|
radius="lg"
|
||||||
<Group wrap="wrap" gap="md">
|
shadow="sm"
|
||||||
{data.images.map((img, index) => (
|
withBorder
|
||||||
<Card key={index} p="xs" w={220}>
|
style={{ background: 'linear-gradient(145deg, #ffffff, #f8f9fa)' }}
|
||||||
<Image
|
>
|
||||||
src={img.image.link}
|
<Text
|
||||||
alt={img.label}
|
fz={{ base: 'sm', md: 'lg' }}
|
||||||
w={200}
|
lh={1.7}
|
||||||
h={200}
|
ta="justify"
|
||||||
fit="cover"
|
c="dark"
|
||||||
radius="md"
|
dangerouslySetInnerHTML={{ __html: data.deskripsi }}
|
||||||
style={{ border: '1px solid #ccc', objectFit: 'cover' }}
|
/>
|
||||||
/>
|
|
||||||
<Text ta="center" mt="xs" fw="bold">{img.label}</Text>
|
<Group justify="center" gap="lg" mt="lg">
|
||||||
</Card>
|
{data.images.length > 0 ? (
|
||||||
))}
|
data.images.map((img, index) => (
|
||||||
|
<Tooltip key={index} label={img.label} position="bottom" withArrow>
|
||||||
|
<Card
|
||||||
|
radius="lg"
|
||||||
|
shadow="md"
|
||||||
|
withBorder
|
||||||
|
w={220}
|
||||||
|
p="sm"
|
||||||
|
style={{
|
||||||
|
transition: 'transform 200ms ease, box-shadow 200ms ease',
|
||||||
|
}}
|
||||||
|
className="hover:scale-105 hover:shadow-lg"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={img.image.link}
|
||||||
|
alt={img.label}
|
||||||
|
w="100%"
|
||||||
|
h={200}
|
||||||
|
fit="cover"
|
||||||
|
radius="md"
|
||||||
|
/>
|
||||||
|
<Text ta="center" mt="sm" fw={600} fz="sm" c="dark">
|
||||||
|
{img.label}
|
||||||
|
</Text>
|
||||||
|
</Card>
|
||||||
|
</Tooltip>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Stack align="center" gap="xs" mt="lg">
|
||||||
|
<IconPhoto size={48} stroke={1.5} color="gray" />
|
||||||
|
<Text c="dimmed" fz="sm">Belum ada gambar maskot yang ditambahkan</Text>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box >
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default MaskotDesa;
|
export default MaskotDesa;
|
||||||
|
|||||||
@@ -1,75 +1,133 @@
|
|||||||
import colors from '@/con/colors';
|
'use client'
|
||||||
import { ActionIcon, Box, Flex, Paper, SimpleGrid, Stack, Text } from '@mantine/core';
|
import { ActionIcon, Box, Flex, Paper, SimpleGrid, Stack, Text } from '@mantine/core';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { IconSparkles } from '@tabler/icons-react';
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
|
||||||
const dataText = [
|
const dataText = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "SANTUN",
|
title: "Santun",
|
||||||
description: "Memberikan pelayanan yang baik, penuh rasa empati, sopan, dan beretika"
|
description: "Pelayanan ramah, penuh empati, sopan, dan beretika."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
title: "ADAPTIF",
|
title: "Adaptif",
|
||||||
description: "Cepat menyesuaikan diri menghadapi perubahan dan bertindak proaktif"
|
description: "Cepat menyesuaikan diri terhadap perubahan dan selalu proaktif."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
title: "INOVATIF",
|
title: "Inovatif",
|
||||||
description: "Selalu berusaha menciptakan pembaruan atau kreasi baru"
|
description: "Berani menciptakan pembaruan dan ide-ide kreatif."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
title: "PROFESIONAL",
|
title: "Profesional",
|
||||||
description: "Memiliki pengetahuan, terampil dan bertanggung jawab"
|
description: "Berpengetahuan luas, terampil, dan bertanggung jawab."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
title: "GESIT",
|
title: "Gesit",
|
||||||
description: "Inisiatif dan cekatan dalam bekerja"
|
description: "Cekatan, sigap, dan penuh inisiatif dalam bekerja."
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
|
|
||||||
|
const letters = ["S", "I", "G", "A", "P"];
|
||||||
|
|
||||||
function MotoDesa() {
|
function MotoDesa() {
|
||||||
return (
|
return (
|
||||||
<Box pb={70}>
|
<Box pb={80} px={{ base: "md", md: "xl" }}>
|
||||||
<Stack align='center' gap={0} >
|
<Stack align="center" gap="lg">
|
||||||
<Box pb={30}>
|
<Box>
|
||||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={{ base: "h1", md: "2.5rem" }}>Moto Desa Darmasaba</Text>
|
<Text
|
||||||
</Box>
|
ta="center"
|
||||||
<Flex gap={50} pb={50} pt={20} justify={"space-evenly"} align={"center"} >
|
fw={800}
|
||||||
<ActionIcon bg={colors['blue-button']} radius={150} p={{ base: "lg", md: "xl" }}>
|
fz={{ base: "2rem", md: "2.8rem" }}
|
||||||
<Text c={colors['white-1']} ta={"center"} fw={"bold"} fz={{ base: "h2", md: "h1" }}>S</Text>
|
style={{
|
||||||
</ActionIcon>
|
background: "linear-gradient(90deg, #0D5594FF, #094678FF)",
|
||||||
<ActionIcon bg={colors['blue-button']} radius={150} p={{ base: "lg", md: "xl" }}>
|
WebkitBackgroundClip: "text",
|
||||||
<Text c={colors['white-1']} ta={"center"} fw={"bold"} fz={{ base: "h2", md: "h1" }}>I</Text>
|
WebkitTextFillColor: "transparent",
|
||||||
</ActionIcon>
|
|
||||||
<ActionIcon bg={colors['blue-button']} radius={150} p={{ base: "lg", md: "xl" }}>
|
|
||||||
<Text c={colors['white-1']} ta={"center"} fw={"bold"} fz={{ base: "h2", md: "h1" }}>G</Text>
|
|
||||||
</ActionIcon>
|
|
||||||
<ActionIcon bg={colors['blue-button']} radius={150} p={{ base: "lg", md: "xl" }}>
|
|
||||||
<Text c={colors['white-1']} ta={"center"} fw={"bold"} fz={{ base: "h2", md: "h1" }}>A</Text>
|
|
||||||
</ActionIcon>
|
|
||||||
<ActionIcon bg={colors['blue-button']} radius={150} p={{ base: "lg", md: "xl" }}>
|
|
||||||
<Text c={colors['white-1']} ta={"center"} fw={"bold"} fz={{ base: "h2", md: "h1" }}>P</Text>
|
|
||||||
</ActionIcon>
|
|
||||||
</Flex>
|
|
||||||
<Paper mb={50} p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
|
||||||
<SimpleGrid
|
|
||||||
cols={{
|
|
||||||
base: 1,
|
|
||||||
md: 2,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{dataText.map((v, k) => {
|
Moto Desa Darmasaba
|
||||||
return (
|
</Text>
|
||||||
<Box key={k}>
|
</Box>
|
||||||
<Text fw={"bold"} fz={{ base: "lg", md: "h3" }}>{v.title}</Text>
|
|
||||||
<Text fz={{ base: "sm", md: "md" }}>{v.description}</Text>
|
<Flex gap={30} pb={40} pt={10} wrap="wrap" justify="center">
|
||||||
</Box>
|
{letters.map((letter, i) => (
|
||||||
)
|
<motion.div
|
||||||
})}
|
key={i}
|
||||||
|
whileHover={{ scale: 1.15, rotate: 5 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
transition={{ type: "spring", stiffness: 300 }}
|
||||||
|
>
|
||||||
|
<ActionIcon
|
||||||
|
radius="xl"
|
||||||
|
size={90}
|
||||||
|
variant="gradient"
|
||||||
|
gradient={{ from: "blue", to: "cyan" }}
|
||||||
|
style={{
|
||||||
|
boxShadow: `0 0 18px ${colors['blue-button']}`,
|
||||||
|
backdropFilter: "blur(6px)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text c="white" fw={800} fz="xl">
|
||||||
|
{letter}
|
||||||
|
</Text>
|
||||||
|
</ActionIcon>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Paper
|
||||||
|
radius="lg"
|
||||||
|
p="xl"
|
||||||
|
withBorder
|
||||||
|
style={{
|
||||||
|
background: "linear-gradient(145deg, #ffffffcc, #f5faffcc)",
|
||||||
|
boxShadow: "0 8px 24px rgba(0,0,0,0.08)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SimpleGrid cols={{ base: 1, md: 2 }} spacing="xl">
|
||||||
|
{dataText.map((v) => (
|
||||||
|
<motion.div
|
||||||
|
key={v.id}
|
||||||
|
whileHover={{ scale: 1.02 }}
|
||||||
|
transition={{ duration: 0.2 }}
|
||||||
|
>
|
||||||
|
<Stack gap={4}>
|
||||||
|
<Flex align="center" gap="sm">
|
||||||
|
<IconSparkles size={20} color={colors['blue-button']} />
|
||||||
|
<Text fw={700} fz={{ base: "lg", md: "xl" }} c={colors['blue-button']}>
|
||||||
|
{v.title}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
<Text fz={{ base: "sm", md: "md" }} c="gray.7">
|
||||||
|
{v.description}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Paper>
|
</Paper>
|
||||||
<Text mb={40} c={colors['blue-button']} ta={"center"} fw={"bold"} fz={{ base: "h4", md: "h3" }}>"Berkomitmen memberikan pelayanan terbaik dengan prinsip SIGAP untuk masyarakat Desa Darmasaba"</Text>
|
|
||||||
|
<Text
|
||||||
|
ta="center"
|
||||||
|
fw={700}
|
||||||
|
fz={{ base: "md", md: "xl" }}
|
||||||
|
c="blue.8"
|
||||||
|
mt="md"
|
||||||
|
style={{
|
||||||
|
maxWidth: 720,
|
||||||
|
lineHeight: 1.6,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
"Berkomitmen menghadirkan pelayanan terbaik dengan semangat{" "}
|
||||||
|
<Text span fw={800} c="cyan.6">
|
||||||
|
SIGAP
|
||||||
|
</Text>{" "}
|
||||||
|
untuk masyarakat Desa Darmasaba."
|
||||||
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Image, Paper, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
|
import { Box, Image, Paper, SimpleGrid, Skeleton, Stack, Text, Divider, Tooltip } from '@mantine/core';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import { IconUser, IconBriefcase, IconUsers, IconTargetArrow } from '@tabler/icons-react';
|
||||||
|
|
||||||
function ProfilPerbekel() {
|
function ProfilPerbekel() {
|
||||||
const state = useProxy(stateProfileDesa.profilPerbekel)
|
const state = useProxy(stateProfileDesa.profilPerbekel)
|
||||||
@@ -17,77 +18,155 @@ function ProfilPerbekel() {
|
|||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py={20} px="md">
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} radius="lg" />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box pb={70}>
|
<Box pb={80} px="md">
|
||||||
<Stack align='center' gap={0}>
|
<Stack align="center" gap={0} mb={40}>
|
||||||
<Box pb={30}>
|
<Text
|
||||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Profil Perbekel</Text>
|
c={colors['blue-button']}
|
||||||
</Box>
|
ta="center"
|
||||||
|
fw="bold"
|
||||||
|
fz={{ base: "2rem", md: "2.8rem" }}
|
||||||
|
style={{ letterSpacing: "0.5px" }}
|
||||||
|
>
|
||||||
|
Profil Perbekel
|
||||||
|
</Text>
|
||||||
|
<Divider w={120} size="sm" color={colors['blue-button']} mt={10} />
|
||||||
</Stack>
|
</Stack>
|
||||||
<SimpleGrid
|
|
||||||
cols={{
|
<SimpleGrid cols={{ base: 1, md: 2 }} spacing="xl" pb={50}>
|
||||||
base: 1,
|
|
||||||
md: 2,
|
|
||||||
}}
|
|
||||||
pb={50}
|
|
||||||
>
|
|
||||||
<Box>
|
<Box>
|
||||||
<Paper bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
<Paper
|
||||||
|
bg={colors['white-trans-1']}
|
||||||
|
w="100%"
|
||||||
|
radius="xl"
|
||||||
|
shadow="md"
|
||||||
|
withBorder
|
||||||
|
>
|
||||||
<Stack gap={0}>
|
<Stack gap={0}>
|
||||||
<Image
|
<Image
|
||||||
pt={{ base: 0, md: 120 }}
|
pt={{ base: 0, md: 100 }}
|
||||||
px={"lg"}
|
px="lg"
|
||||||
src={data.image?.link || "/perbekel.png"}
|
src={data.image?.link || "/perbekel.png"}
|
||||||
sizes='100%'
|
alt="Foto Perbekel"
|
||||||
alt=''
|
radius="lg"
|
||||||
onError={(e) => {
|
onError={(e) => {
|
||||||
e.currentTarget.src = "/perbekel.png";
|
e.currentTarget.src = "/perbekel.png";
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Paper
|
<Paper
|
||||||
bg={colors['blue-button']}
|
bg={colors['blue-button']}
|
||||||
px={"lg"}
|
px="lg"
|
||||||
|
radius="0 0 var(--mantine-radius-xl) var(--mantine-radius-xl)"
|
||||||
className="glass3"
|
className="glass3"
|
||||||
py={{ base: 20, md: 50 }}
|
py={{ base: 20, md: 50 }}
|
||||||
|
|
||||||
>
|
>
|
||||||
<Text c={colors['white-1']} fz={{ base: "md", md: "h3" }}>Perbekel Desa Darmasaba</Text>
|
<Text c={colors['white-1']} fz={{ base: "lg", md: "h3" }}>
|
||||||
<Text c={colors['white-1']} fw={"bolder"} fz={{ base: "md", md: "h2" }}>
|
Perbekel Desa Darmasaba
|
||||||
I.B. Surya Prabhawa Manuaba, S.H.,M.H.,NL.P.
|
</Text>
|
||||||
|
<Text
|
||||||
|
c={colors['white-1']}
|
||||||
|
fw="bolder"
|
||||||
|
fz={{ base: "xl", md: "h2" }}
|
||||||
|
mt={8}
|
||||||
|
>
|
||||||
|
{"I.B. Surya Prabhawa Manuaba, S.H.,M.H.,NL.P."}
|
||||||
</Text>
|
</Text>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
|
||||||
<Box>
|
<Paper
|
||||||
<Text fz={{ base: "1.125rem", md: "1.6rem" }} fw={'bold'}>Biodata</Text>
|
p="xl"
|
||||||
<Text fz={{ base: "1rem", md: "1.5rem" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: data.biodata }} />
|
bg={colors['white-trans-1']}
|
||||||
</Box>
|
w="100%"
|
||||||
<Box>
|
radius="xl"
|
||||||
<Text fz={{ base: "1.125rem", md: "1.6rem" }} fw={'bold'}>Pengalaman</Text>
|
shadow="md"
|
||||||
<Text fz={{ base: "1rem", md: "1.5rem" }} dangerouslySetInnerHTML={{ __html: data.pengalaman }} />
|
withBorder
|
||||||
</Box>
|
>
|
||||||
|
<Stack gap="xl">
|
||||||
|
<Box>
|
||||||
|
<Tooltip label="Informasi pribadi perbekel" withArrow>
|
||||||
|
<Stack gap={6}>
|
||||||
|
<Stack align="center" gap={6}>
|
||||||
|
<IconUser size={22} color={colors['blue-button']} />
|
||||||
|
<Text fz={{ base: "1.2rem", md: "1.5rem" }} fw="bold">Biodata</Text>
|
||||||
|
</Stack>
|
||||||
|
<Text
|
||||||
|
fz={{ base: "1rem", md: "1.2rem" }}
|
||||||
|
ta="justify"
|
||||||
|
lh={1.6}
|
||||||
|
dangerouslySetInnerHTML={{ __html: data.biodata }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<Tooltip label="Pengalaman kerja perbekel" withArrow>
|
||||||
|
<Stack gap={6}>
|
||||||
|
<Stack align="center" gap={6}>
|
||||||
|
<IconBriefcase size={22} color={colors['blue-button']} />
|
||||||
|
<Text fz={{ base: "1.2rem", md: "1.5rem" }} fw="bold">Pengalaman</Text>
|
||||||
|
</Stack>
|
||||||
|
<Text
|
||||||
|
fz={{ base: "1rem", md: "1.2rem" }}
|
||||||
|
ta="justify"
|
||||||
|
lh={1.6}
|
||||||
|
dangerouslySetInnerHTML={{ __html: data.pengalaman }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</SimpleGrid >
|
</SimpleGrid>
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
|
||||||
<Box>
|
<Paper
|
||||||
<Text fz={{ base: "1.125rem", md: "1.6rem" }} fw={'bold'}>Pengalaman Organisasi</Text>
|
p="xl"
|
||||||
<Text fz={{ base: "1rem", md: "1.5rem" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: data.pengalamanOrganisasi }} />
|
bg={colors['white-trans-1']}
|
||||||
</Box>
|
w="100%"
|
||||||
<Box pb={20}>
|
radius="xl"
|
||||||
<Text fz={{ base: "1.125rem", md: "1.6rem" }} fw={'bold'}>Program Kerja Unggulan</Text>
|
shadow="md"
|
||||||
<Box px={20}>
|
withBorder
|
||||||
<Text fz={{ base: "1rem", md: "1.5rem" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: data.programUnggulan }} />
|
>
|
||||||
|
<Stack gap="xl">
|
||||||
|
<Box>
|
||||||
|
<Stack align="center" gap={6} >
|
||||||
|
<IconUsers size={22} color={colors['blue-button']} />
|
||||||
|
<Text fz={{ base: "1.2rem", md: "1.5rem" }} fw="bold">Pengalaman Organisasi</Text>
|
||||||
|
</Stack>
|
||||||
|
<Text
|
||||||
|
fz={{ base: "1rem", md: "1.2rem" }}
|
||||||
|
ta="justify"
|
||||||
|
lh={1.6}
|
||||||
|
dangerouslySetInnerHTML={{ __html: data.pengalamanOrganisasi }}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
|
||||||
|
<Box>
|
||||||
|
<Stack align="center" gap={6} mb={6}>
|
||||||
|
<IconTargetArrow size={22} color={colors['blue-button']} />
|
||||||
|
<Text fz={{ base: "1.2rem", md: "1.5rem" }} fw="bold">Program Kerja Unggulan</Text>
|
||||||
|
</Stack>
|
||||||
|
<Box px={10}>
|
||||||
|
<Text
|
||||||
|
fz={{ base: "1rem", md: "1.2rem" }}
|
||||||
|
ta="justify"
|
||||||
|
lh={1.6}
|
||||||
|
dangerouslySetInnerHTML={{ __html: data.programUnggulan }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box >
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,39 +7,69 @@ import { useEffect } from 'react';
|
|||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function SejarahDesa() {
|
function SejarahDesa() {
|
||||||
const state = useProxy(stateProfileDesa.sejarahDesa)
|
const state = useProxy(stateProfileDesa.sejarahDesa);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
state.findUnique.load("edit")
|
state.findUnique.load('edit');
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
const { data, loading } = state.findUnique
|
const { data, loading } = state.findUnique;
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py="lg">
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} radius="lg" />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Box py="xl">
|
||||||
<Box pb={70}>
|
<Stack align="center" gap="xl">
|
||||||
<Stack align='center' gap={0}>
|
<Stack align="center" gap="sm">
|
||||||
<Box pb={30}>
|
<Center>
|
||||||
<Center>
|
<Image
|
||||||
<Image src={"/darmasaba-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
src="/darmasaba-icon.png"
|
||||||
</Center>
|
alt="Ikon Desa Darmasaba"
|
||||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Sejarah Desa</Text>
|
w={{ base: 180, md: 260 }}
|
||||||
</Box>
|
radius="md"
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
style={{ filter: 'drop-shadow(0 4px 12px rgba(0,0,0,0.15))' }}
|
||||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: data.deskripsi }} />
|
/>
|
||||||
</Paper>
|
</Center>
|
||||||
|
<Center>
|
||||||
|
<Text
|
||||||
|
c={colors['blue-button']}
|
||||||
|
ta="center"
|
||||||
|
fw={700}
|
||||||
|
fz={{ base: '2rem', md: '2.8rem' }}
|
||||||
|
style={{ letterSpacing: '-0.5px' }}
|
||||||
|
>
|
||||||
|
Sejarah Desa
|
||||||
|
</Text>
|
||||||
|
</Center>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box >
|
<Paper
|
||||||
</>
|
p="xl"
|
||||||
|
radius="lg"
|
||||||
|
bg="white"
|
||||||
|
shadow="sm"
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(135deg, #ffffff 0%, #f9fbfd 100%)',
|
||||||
|
border: `1px solid ${colors['blue-button']}20`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack gap="md">
|
||||||
|
<Text
|
||||||
|
fz={{ base: 'md', md: 'lg' }}
|
||||||
|
lh={1.8}
|
||||||
|
ta="justify"
|
||||||
|
style={{ color: '#2a2a2a' }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: data.deskripsi }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +1,102 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
|
||||||
import { Box, Center, Image, Paper, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
|
|
||||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { Box, Center, Image, Paper, SimpleGrid, Skeleton, Stack, Text, Title, Tooltip } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IconUser } from '@tabler/icons-react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function SemuaPerbekel() {
|
function SemuaPerbekel() {
|
||||||
const state = useProxy(stateProfileDesa.mantanPerbekel)
|
const state = useProxy(stateProfileDesa.mantanPerbekel);
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
state.findMany.load()
|
state.findMany.load();
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
const {data, loading} = state.findMany
|
const { data, loading } = state.findMany;
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py="xl">
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} radius="xl" />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.length === 0) {
|
||||||
|
return (
|
||||||
|
<Center py="xl">
|
||||||
|
<Stack align="center" gap="sm">
|
||||||
|
<IconUser size={48} stroke={1.5} />
|
||||||
|
<Title fw="bold" order={2}>Belum ada data Perbekel</Title>
|
||||||
|
<Text c="dimmed" fz="sm" ta="center">Data mantan Perbekel akan muncul di sini ketika sudah tersedia</Text>
|
||||||
|
</Stack>
|
||||||
|
</Center>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box pb={50}>
|
<Box pb={80}>
|
||||||
<Stack align='center'>
|
<Stack align="center" gap="lg">
|
||||||
<Box pb={30}>
|
<Box>
|
||||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={{ base: "h1", md: "2.5rem" }}>Perbekel Dari Masa Ke Masa</Text>
|
<Text
|
||||||
|
ta="center"
|
||||||
|
fw={900}
|
||||||
|
fz={{ base: "2rem", md: "2.5rem" }}
|
||||||
|
variant="gradient"
|
||||||
|
gradient={{ from: "blue", to: "cyan", deg: 45 }}
|
||||||
|
>
|
||||||
|
Perbekel Dari Masa ke Masa
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<SimpleGrid
|
|
||||||
cols={{
|
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="xl" w="100%">
|
||||||
base: 1,
|
{data.map((v: any, k: number) => (
|
||||||
md: 3,
|
<Paper
|
||||||
}}
|
key={k}
|
||||||
>
|
radius="2xl"
|
||||||
{data.map((v, k) => {
|
shadow="md"
|
||||||
return (
|
withBorder
|
||||||
<Box key={k}>
|
p="lg"
|
||||||
<Paper h={620} mb={50} radius={26} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
bg="white"
|
||||||
<Box>
|
style={{
|
||||||
<Center>
|
transition: "all 250ms ease",
|
||||||
<Image src={v.image?.link} alt='' />
|
}}
|
||||||
</Center>
|
className="hover:shadow-xl hover:scale-[1.02]"
|
||||||
</Box>
|
>
|
||||||
<Box>
|
<Stack gap="md" align="center">
|
||||||
<Stack gap={"sm"} py={10}>
|
<Box w="100%" h={300} style={{ overflow: "hidden", borderRadius: "1rem" }}>
|
||||||
<Text ta={"center"} fw={"bold"} fz={{ base: "h3", md: "h3" }}>{v.nama}</Text>
|
<Image
|
||||||
<Text ta={"center"} fz={{ base: "h5", md: "h4" }}>{v.daerah}</Text>
|
src={v.image?.link}
|
||||||
<Text ta={"center"} fz={{ base: "h5", md: "h4" }}>{v.periode}</Text>
|
alt={v.nama || "Foto Perbekel"}
|
||||||
</Stack>
|
fit="cover"
|
||||||
</Box>
|
h="100%"
|
||||||
</Paper>
|
w="100%"
|
||||||
</Box>
|
/>
|
||||||
)
|
</Box>
|
||||||
})
|
|
||||||
}
|
<Stack gap={4} align="center">
|
||||||
|
<Tooltip label="Nama Perbekel" withArrow>
|
||||||
|
<Text fw={700} fz="lg" ta="center">
|
||||||
|
{v.nama}
|
||||||
|
</Text>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip label="Wilayah menjabat" withArrow>
|
||||||
|
<Text c="dimmed" fz="sm" ta="center">
|
||||||
|
{v.daerah}
|
||||||
|
</Text>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip label="Periode jabatan" withArrow>
|
||||||
|
<Text c="blue" fw={600} fz="sm" ta="center">
|
||||||
|
{v.periode}
|
||||||
|
</Text>
|
||||||
|
</Tooltip>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -6,43 +6,90 @@ import { Box, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function VisimisiDesa() {
|
function VisiMisiDesa() {
|
||||||
const state = useProxy(stateProfileDesa.visiMisiDesa)
|
const state = useProxy(stateProfileDesa.visiMisiDesa);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
state.findUnique.load("edit")
|
state.findUnique.load('edit');
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
const { data, loading } = state.findUnique
|
const { data, loading } = state.findUnique;
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
|
||||||
<Box py={10}>
|
|
||||||
<Skeleton h={500} />
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Box py="xl">
|
||||||
<Box pb={30}>
|
<Skeleton h={500} radius="lg" />
|
||||||
<Stack align='center' gap={0}>
|
</Box>
|
||||||
<Box pb={30}>
|
|
||||||
<Image src={"/darmasaba-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
|
||||||
</Box>
|
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
|
||||||
<Text c={colors['blue-button']} ta={"center"} fw={"lighter"} fz={"2.5rem"}>Visi Desa</Text>
|
|
||||||
<Text fz={"1.5rem"} ta={"center"} fw={"bold"} dangerouslySetInnerHTML={{ __html: data.visi }} />
|
|
||||||
</Paper>
|
|
||||||
<Paper my={20} p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
|
||||||
<Text c={colors['blue-button']} ta={"center"} fw={"lighter"} fz={"2.5rem"}>Misi Desa</Text>
|
|
||||||
<Box>
|
|
||||||
<Text fz={"1.5rem"} fw={"bold"} dangerouslySetInnerHTML={{ __html: data.misi }} />
|
|
||||||
</Box>
|
|
||||||
</Paper>
|
|
||||||
</Stack>
|
|
||||||
</Box >
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box py="xl">
|
||||||
|
<Stack align="center" gap="xl">
|
||||||
|
<Image
|
||||||
|
src="/darmasaba-icon.png"
|
||||||
|
alt="Lambang Desa Darmasaba"
|
||||||
|
w={{ base: 160, md: 240 }}
|
||||||
|
radius="md"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Paper
|
||||||
|
p="xl"
|
||||||
|
radius="lg"
|
||||||
|
shadow="md"
|
||||||
|
withBorder
|
||||||
|
w="100%"
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(145deg, #ffffff, #f5f7fa)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
c={colors['blue-button']}
|
||||||
|
ta="center"
|
||||||
|
fw={700}
|
||||||
|
fz={{ base: '2rem', md: '2.5rem' }}
|
||||||
|
mb="md"
|
||||||
|
>
|
||||||
|
Visi Desa
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
fz={{ base: '1.125rem', md: '1.375rem' }}
|
||||||
|
ta="center"
|
||||||
|
fw={500}
|
||||||
|
lh={1.6}
|
||||||
|
dangerouslySetInnerHTML={{ __html: data.visi }}
|
||||||
|
/>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
<Paper
|
||||||
|
p="xl"
|
||||||
|
radius="lg"
|
||||||
|
shadow="md"
|
||||||
|
withBorder
|
||||||
|
w="100%"
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(145deg, #ffffff, #f5f7fa)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
c={colors['blue-button']}
|
||||||
|
ta="center"
|
||||||
|
fw={700}
|
||||||
|
fz={{ base: '2rem', md: '2.5rem' }}
|
||||||
|
mb="md"
|
||||||
|
>
|
||||||
|
Misi Desa
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
fz={{ base: '1.125rem', md: '1.375rem' }}
|
||||||
|
fw={500}
|
||||||
|
lh={1.6}
|
||||||
|
dangerouslySetInnerHTML={{ __html: data.misi }}
|
||||||
|
/>
|
||||||
|
</Paper>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default VisimisiDesa;
|
export default VisiMisiDesa;
|
||||||
|
|||||||
@@ -2,158 +2,155 @@
|
|||||||
import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
|
import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
|
||||||
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
|
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
|
||||||
import colors from '@/con/colors';
|
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 { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IconAlertCircle, IconCalendar, IconInfoCircle } from '@tabler/icons-react';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const state = useProxy(artikelKesehatanState)
|
const state = useProxy(artikelKesehatanState);
|
||||||
const params = useParams()
|
const params = useParams();
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
state.findUnique.load(params?.id as string)
|
state.findUnique.load(params?.id as string);
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
if (!state.findUnique.data) {
|
if (!state.findUnique.data) {
|
||||||
return (
|
return (
|
||||||
<Stack py={10}>
|
<Stack py="xl" px="md">
|
||||||
<Skeleton h={500} />
|
<Skeleton h={420} radius="lg" />
|
||||||
|
<Skeleton h={20} mt="md" w="60%" />
|
||||||
|
<Skeleton h={20} w="40%" />
|
||||||
|
<Skeleton h={200} radius="md" />
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
|
||||||
<Stack gap={'lg'}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<Paper radius={10}>
|
<Stack gap="lg">
|
||||||
<Box style={{ borderTopLeftRadius: 10, borderTopRightRadius: 10 }} bg={colors['blue-button']}>
|
<Paper radius="xl" shadow="md" withBorder>
|
||||||
<Text p={'md'} fz={{ base: "h3", md: "h2" }} c={colors['white-1']} fw={"bold"}>
|
<Box style={{ borderTopLeftRadius: 16, borderTopRightRadius: 16 }} bg={colors['blue-button']}>
|
||||||
Detail Lengkap Fasilitas Kesehatan
|
<Text p="md" fz={{ base: 'h3', md: 'h2' }} c={colors['white-1']} fw="bold">
|
||||||
|
{state.findUnique.data.title || 'Detail Artikel Kesehatan'}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</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']}>
|
<Box p="lg">
|
||||||
<Text fz={'h3'} c={colors['white-1']} fw={'bold'}>Informasi Lebih Lanjut</Text>
|
<Stack gap="lg">
|
||||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
<Group gap="xs">
|
||||||
Hotline DBD : <Text span fz={'h4'}>(0361) 123456</Text>
|
<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>
|
||||||
<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>
|
</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>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
|
import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
|
||||||
import colors from '@/con/colors';
|
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 { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IconCalendar, IconChevronRight } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
@@ -16,36 +17,71 @@ function ArtikelKesehatanPage() {
|
|||||||
|
|
||||||
if(!state.findMany.data){
|
if(!state.findMany.data){
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py="xl" ta="center">
|
||||||
<Skeleton h={500}/>
|
<Loader size="lg" color={colors['blue-button']} />
|
||||||
|
<Text mt="md" c="dimmed" fz="md">Memuat artikel kesehatan...</Text>
|
||||||
</Box>
|
</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 (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Paper p={'xl'} h={'112vh'} bg={colors['white-trans-1']}>
|
<Paper p="xl" bg={colors['white-trans-1']} radius="xl" shadow="md">
|
||||||
<Stack gap={'xs'}>
|
<Stack gap="xl">
|
||||||
<Text ta={'center'} fw={"bold"} fz={'h3'} c={colors['blue-button']}>Artikel Kesehatan</Text>
|
<Title order={2} ta="center" c={colors['blue-button']}>Artikel Kesehatan</Title>
|
||||||
{state.findMany.data.map((item) => (
|
<Divider color={colors['blue-button']} />
|
||||||
<Box key={item.id}>
|
<Stack gap="lg">
|
||||||
<Image pt={5} src={'/api/img/dbd.png'} alt="" />
|
{state.findMany.data.map((item) => (
|
||||||
<Text fz={'h4'} fw={'bold'} >
|
<Card
|
||||||
{item.title}
|
key={item.id}
|
||||||
</Text>
|
withBorder
|
||||||
<Text fz={'h6'} pb={10}>
|
radius="lg"
|
||||||
Diposting: {new Date(item.createdAt).toLocaleDateString('id-ID', { year: 'numeric', month: 'long', day: 'numeric' })} | Dinas Kesehatan
|
shadow="sm"
|
||||||
</Text>
|
p="lg"
|
||||||
<Text fz={'h4'} pb={10} lineClamp={2}>
|
style={{ transition: 'transform 200ms ease' }}
|
||||||
{item.content}
|
onMouseEnter={(e) => (e.currentTarget.style.transform = 'translateY(-4px)')}
|
||||||
</Text>
|
onMouseLeave={(e) => (e.currentTarget.style.transform = 'translateY(0)')}
|
||||||
<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'} >
|
<Card.Section>
|
||||||
Baca Selengkapnya {'>>'}
|
<Image src={'/api/img/dbd.png'} alt={item.title} height={200} fit="cover" />
|
||||||
</Text>
|
</Card.Section>
|
||||||
</Anchor>
|
<Stack gap="xs" mt="md">
|
||||||
</Box>
|
<Text fw="bold" fz="xl" c="dark">{item.title}</Text>
|
||||||
))}
|
<Group gap="xs">
|
||||||
<Divider color={colors['blue-button']} px={'xl'} />
|
<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>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -1,160 +1,353 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
'use client'
|
'use client'
|
||||||
import fasilitasKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
|
import fasilitasKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
|
||||||
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
|
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
|
||||||
import colors from '@/con/colors';
|
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 { 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 { useParams } from 'next/navigation';
|
||||||
|
import { useMemo } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
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() {
|
function Page() {
|
||||||
const state = useProxy(fasilitasKesehatanState.fasilitasKesehatan)
|
const state = useProxy(fasilitasKesehatanState.fasilitasKesehatan);
|
||||||
const params = useParams()
|
const params = useParams();
|
||||||
|
|
||||||
useShallowEffect(() => {
|
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 (
|
return (
|
||||||
<Stack py={10}>
|
<Stack bg={colors.Bg} mih="100vh" p="lg" gap="lg">
|
||||||
<Skeleton h={500} />
|
<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>
|
</Stack>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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 }}>
|
<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>
|
||||||
<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 */}
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<Text fz={'h4'} fw={"bold"}>
|
<Card radius="xl" p="lg" withBorder style={{ backdropFilter: 'blur(6px)' }}>
|
||||||
Dokter & Tenaga Medis
|
<Stack gap="sm">
|
||||||
</Text>
|
<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 />
|
<Divider />
|
||||||
<Box pb={10}>
|
<Group gap="xl" align="start">
|
||||||
<Table highlightOnHover withTableBorder withColumnBorders>
|
<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>
|
<TableThead>
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTh fz={'h4'}>Nama</TableTh>
|
<TableTh>Nama</TableTh>
|
||||||
<TableTh fz={'h4'}>Spesialisasi</TableTh>
|
<TableTh>Spesialisasi</TableTh>
|
||||||
<TableTh fz={'h4'}>Jadwal</TableTh>
|
<TableTh>Jadwal</TableTh>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
</TableThead>
|
</TableThead>
|
||||||
<TableTbody>
|
<TableTbody>
|
||||||
{state.findUnique.data?.dokterdantenagamedis ? (
|
{tenaga ? (
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTd>{state.findUnique.data.dokterdantenagamedis.name}</TableTd>
|
<TableTd><Group gap="xs"><IconUser size={16} /><Text>{tenaga?.name || '-'}</Text></Group></TableTd>
|
||||||
<TableTd>{state.findUnique.data.dokterdantenagamedis.specialist}</TableTd>
|
<TableTd>{tenaga?.specialist || '-'}</TableTd>
|
||||||
<TableTd>{state.findUnique.data.dokterdantenagamedis.jadwal}</TableTd>
|
<TableTd>{tenaga?.jadwal || '-'}</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
) : (
|
) : (
|
||||||
<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>
|
</TableTr>
|
||||||
)}
|
)}
|
||||||
</TableTbody>
|
</TableTbody>
|
||||||
</Table>
|
</Table>
|
||||||
</Box>
|
</Stack>
|
||||||
{/* Fasilitas Pendukung */}
|
</Card>
|
||||||
<Text fz={'h4'} fw={"bold"}>
|
</Stack>
|
||||||
Fasilitas Pendukung
|
</Grid.Col>
|
||||||
</Text>
|
</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 />
|
<Divider />
|
||||||
<Text fz={"lg"} dangerouslySetInnerHTML={{ __html: state.findUnique.data?.fasilitaspendukung?.content }} />
|
{fasilitasPendukungHtml ? (
|
||||||
{/* Dokter */}
|
<Text fz="md" style={{ lineHeight: 1.7 }} dangerouslySetInnerHTML={{ __html: fasilitasPendukungHtml }} />
|
||||||
<Text fz={'h4'} fw={"bold"}>
|
) : (
|
||||||
Layanan & Tarif
|
<Paper withBorder radius="md" p="md">
|
||||||
</Text>
|
<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 />
|
<Divider />
|
||||||
<Table highlightOnHover withTableBorder withColumnBorders>
|
<Table highlightOnHover withTableBorder withColumnBorders aria-label="Tabel Layanan dan Tarif">
|
||||||
<TableThead>
|
<TableThead>
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTh fz={'h4'}>Layanan</TableTh>
|
<TableTh>Layanan</TableTh>
|
||||||
<TableTh fz={'h4'}>Tarif</TableTh>
|
<TableTh>Tarif</TableTh>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
</TableThead>
|
</TableThead>
|
||||||
<TableTbody>
|
<TableTbody>
|
||||||
<TableTr>
|
{tarif ? (
|
||||||
<TableTd>{state.findUnique?.data?.tarifdanlayanan.layanan}</TableTd>
|
<TableTr>
|
||||||
<TableTd>{state.findUnique?.data?.tarifdanlayanan.tarif}</TableTd>
|
<TableTd>{tarif?.layanan || '-'}</TableTd>
|
||||||
</TableTr>
|
<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>
|
</TableTbody>
|
||||||
</Table>
|
</Table>
|
||||||
<Text fz={'h6'} pb={10} fw={"bold"}>
|
{gratisBpjs && (
|
||||||
* Gratis dengan BPJS Kesehatan
|
<Group gap="xs">
|
||||||
</Text>
|
<ThemeIcon variant="light" radius="xl"><IconCheck size={18} /></ThemeIcon>
|
||||||
{/* Prosedur Pendaftaran */}
|
<Text fw={600}>Gratis dengan BPJS Kesehatan</Text>
|
||||||
<Text fz={'h4'} fw={"bold"}>
|
</Group>
|
||||||
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>
|
|
||||||
<Group>
|
<Group>
|
||||||
<Button fz={'lg'} bg={colors['blue-button']}>
|
<Button variant="gradient" gradient={{ from: 'blue', to: 'cyan' }} leftSection={<IconFileDownload size={18} />}>Unduh Brosur (PDF)</Button>
|
||||||
Download Brosur Layanan (PDF)
|
</Group>
|
||||||
</Button>
|
|
||||||
</Group> */}
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Card>
|
||||||
</Paper>
|
</Grid.Col>
|
||||||
</Stack>
|
</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>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
|
|||||||
@@ -1,50 +1,100 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import fasilitasKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
|
import fasilitasKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
|
||||||
import colors from '@/con/colors';
|
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 { useShallowEffect } from '@mantine/hooks';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import { IconMapPin, IconClock, IconArrowRight } from '@tabler/icons-react';
|
||||||
|
|
||||||
function FasilitasKesehatanPage() {
|
function FasilitasKesehatanPage() {
|
||||||
const state = useProxy(fasilitasKesehatanState.fasilitasKesehatan)
|
const state = useProxy(fasilitasKesehatanState.fasilitasKesehatan);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
state.findMany.load()
|
state.findMany.load();
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
if(!state.findMany.data){
|
if (!state.findMany.data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py="xl" px="md">
|
||||||
<Skeleton h={500} />
|
<Stack gap="md">
|
||||||
|
<Skeleton height={80} radius="lg" />
|
||||||
|
<Skeleton height={80} radius="lg" />
|
||||||
|
<Skeleton height={80} radius="lg" />
|
||||||
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Paper p={'xl'} h={'112vh'} bg={colors['white-trans-1']}>
|
<Paper p="xl" radius="xl" shadow="md" h="100%" bg="white">
|
||||||
<Stack gap={'xs'}>
|
<Stack gap="lg">
|
||||||
<Text ta={'center'} fw={"bold"} fz={'h3'} c={colors['blue-button']}>Fasilitas Kesehatan</Text>
|
<Text ta="center" fw={700} fz="32px" c={colors['blue-button']}>
|
||||||
{state.findMany.data.map((item) => (
|
Fasilitas Kesehatan
|
||||||
<Box key={item.id}>
|
</Text>
|
||||||
<Text fz={'h4'} fw={'bold'} c={colors['blue-button']}>
|
<Divider size="sm" color={colors['blue-button']} />
|
||||||
{item.name}
|
<Stack gap="lg">
|
||||||
</Text>
|
{state.findMany.data.map((item) => (
|
||||||
<Text fz={'h4'}>
|
<Card
|
||||||
{item.informasiumum.alamat}
|
key={item.id}
|
||||||
</Text>
|
withBorder
|
||||||
<Text fz={'h4'}>
|
radius="xl"
|
||||||
{item.informasiumum.jamOperasional}
|
shadow="sm"
|
||||||
</Text>
|
p="lg"
|
||||||
<Anchor onClick={() => router.push(`/darmasaba/kesehatan/data-kesehatan-warga/fasilitas-kesehatan-page/${item.id}`)} c={colors['blue-button']} variant='transparent'>
|
style={{
|
||||||
<Text c={colors['blue-button']} fz={'h4'}>
|
background: 'linear-gradient(135deg, #fdfdfd, #f7faff)',
|
||||||
Detail {'>>'}
|
transition: 'transform 0.2s ease, box-shadow 0.2s ease',
|
||||||
</Text>
|
}}
|
||||||
</Anchor>
|
onMouseEnter={(e) => {
|
||||||
</Box>
|
(e.currentTarget as HTMLElement).style.transform = 'translateY(-4px)';
|
||||||
))}
|
(e.currentTarget as HTMLElement).style.boxShadow = '0 8px 20px rgba(0,0,0,0.08)';
|
||||||
<Divider color={colors['blue-button']} px={'xl'} />
|
}}
|
||||||
|
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>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -2,10 +2,30 @@
|
|||||||
import jadwalkegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
|
import jadwalkegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
|
||||||
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
|
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
|
||||||
import colors from '@/con/colors';
|
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 { DateInput } from '@mantine/dates';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
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 { useParams } from 'next/navigation';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
@@ -17,6 +37,7 @@ const layanan = [
|
|||||||
'Konsultasi Gizi',
|
'Konsultasi Gizi',
|
||||||
'Pemeriksaan Kesehatan'
|
'Pemeriksaan Kesehatan'
|
||||||
];
|
];
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const combobox = useCombobox({
|
const combobox = useCombobox({
|
||||||
onDropdownClose: () => combobox.resetSelectedOption(),
|
onDropdownClose: () => combobox.resetSelectedOption(),
|
||||||
@@ -30,192 +51,160 @@ function Page() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [value, setValue] = useState<string | null>('');
|
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) => (
|
const options = layanan.map((item) => (
|
||||||
<ComboboxOption value={item} key={item} active={item === value}>
|
<ComboboxOption value={item} key={item} active={item === value}>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
{item === value && <CheckIcon size={12} />}
|
{item === value && <IconUser size={14} stroke={2} />}
|
||||||
<span>{item}</span>
|
<span>{item}</span>
|
||||||
</Group>
|
</Group>
|
||||||
</ComboboxOption>
|
</ComboboxOption>
|
||||||
));
|
));
|
||||||
const [dateInputOpened, setDateInputOpened] = useState(false);
|
|
||||||
|
|
||||||
const pickerControl = (
|
const pickerControl = (
|
||||||
<ActionIcon onClick={() => setDateInputOpened(true)} variant="subtle" color="gray">
|
<ActionIcon onClick={() => setDateInputOpened(true)} variant="light" color="blue">
|
||||||
<IconCalendar size={18} />
|
<IconCalendar size={18} />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
const params = useParams()
|
|
||||||
const state = useProxy(jadwalkegiatanState)
|
|
||||||
useShallowEffect(() => {
|
|
||||||
state.findUnique.load(params?.id as string)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
if (!state.findUnique.data) {
|
if (!state.findUnique.data) {
|
||||||
return (
|
return (
|
||||||
<Stack py={10}>
|
<Stack py="xl" px="lg">
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} radius="lg" />
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
<Stack gap={'lg'}>
|
<Stack gap="lg">
|
||||||
<Paper radius={10}>
|
<Paper radius="xl" shadow="md">
|
||||||
<Box style={{ borderTopLeftRadius: 10, borderTopRightRadius: 10 }} bg={colors['blue-button']}>
|
<Box
|
||||||
<Text p={'md'} fz={{ base: "h3", md: "h2" }} c={colors['white-1']} fw={"bold"}>
|
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
|
Detail & Pendaftaran Kegiatan
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box p={'md'} >
|
<Box p="lg">
|
||||||
<Stack gap={'xs'}>
|
<Stack gap="xl">
|
||||||
{/* Informasi Kegiatan */}
|
<Stack gap="sm">
|
||||||
<Text fz={'h4'} fw={"bold"}>
|
<Text fz="lg" fw="bold">Informasi Kegiatan</Text>
|
||||||
Informasi Kegiatan
|
<Divider />
|
||||||
</Text>
|
<Text fz="md" fw="bold">Nama Kegiatan: <Text span>{state.findUnique.data.informasijadwalkegiatan.name}</Text></Text>
|
||||||
<Divider />
|
<Text fz="md" fw="bold">Tanggal: <Text span>{state.findUnique.data.informasijadwalkegiatan.tanggal}</Text></Text>
|
||||||
<Text fz={'h4'} fw={"bold"}>
|
<Text fz="md" fw="bold">Waktu: <Text span>{state.findUnique.data.informasijadwalkegiatan.waktu}</Text></Text>
|
||||||
Nama Kegiatan : <Text span fz={'h4'}>{state.findUnique.data.informasijadwalkegiatan.name}</Text>
|
<Text fz="md" fw="bold">Lokasi: <Text span>{state.findUnique.data.informasijadwalkegiatan.lokasi}</Text></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>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
<Paper p={'lg'} bg={colors['blue-button-trans']}>
|
|
||||||
<Text fz={'h3'} c={colors['white-1']} fw={'bold'}>Informasi Kontak</Text>
|
<Stack gap="sm">
|
||||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
<Text fz="lg" fw="bold">Deskripsi Kegiatan</Text>
|
||||||
Penanggung Jawab : <Text span fz={'h4'}>Bidan Komang Ayu</Text>
|
<Divider />
|
||||||
</Text>
|
<Text ta="justify" fz="md" dangerouslySetInnerHTML={{ __html: state.findUnique.data.deskripsijadwalkegiatan.deskripsi }} />
|
||||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
</Stack>
|
||||||
Telepon : <Text span fz={'h4'}>081234567890</Text>
|
|
||||||
</Text>
|
<Stack gap="sm">
|
||||||
<Text fz={'h4'} c={colors['white-1']} fw={"bold"}>
|
<Text fz="lg" fw="bold">Layanan yang Tersedia</Text>
|
||||||
Email : <Text span fz={'h4'}>puskesmasabiansemal3@gmail.com</Text>
|
<Divider />
|
||||||
</Text>
|
<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>
|
</Paper>
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
<Button fz={'lg'} bg={'green'}>
|
<Button size="md" radius="lg" leftSection={<IconDownload size={18} />} color="green">
|
||||||
Download Jadwal Posyandu 2025 (PDF)
|
Unduh Jadwal Posyandu 2025 (PDF)
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -227,5 +216,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
|
|||||||
@@ -1,53 +1,101 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import jadwalkegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
|
import jadwalkegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
|
||||||
import colors from '@/con/colors';
|
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 { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IconChevronRight, IconClockHour4, IconMapPin } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function JadwalKegiatanPage() {
|
function JadwalKegiatanPage() {
|
||||||
const state = useProxy(jadwalkegiatanState)
|
const state = useProxy(jadwalkegiatanState);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useShallowEffect(()=> {
|
useShallowEffect(() => {
|
||||||
state.findMany.load()
|
state.findMany.load();
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
if(!state.findMany.data){
|
if (!state.findMany.data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py="lg">
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} radius="lg" />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Paper p={'xl'} h={'112vh'} bg={colors['white-trans-1']}>
|
<Paper p="xl" bg={colors['white-trans-1']} radius="xl" shadow="md" h="auto" mih="100vh">
|
||||||
<Stack gap={'xs'}>
|
<Stack gap="lg">
|
||||||
<Text ta={'center'} fw={"bold"} fz={'h3'} c={colors['blue-button']}>Jadwal Kegiatan</Text>
|
<Text ta="center" fw={700} fz="32px" c={colors['blue-button']}>
|
||||||
{state.findMany.data.map((item) => (
|
Jadwal Kegiatan Warga
|
||||||
<Box key={item.id}>
|
</Text>
|
||||||
<Text fz={'h4'} fw={'bold'}>
|
|
||||||
{item.informasijadwalkegiatan.name}
|
{state.findMany.data.length === 0 ? (
|
||||||
|
<Box py="xl" ta="center">
|
||||||
|
<Text fz="lg" c="dimmed">
|
||||||
|
Belum ada jadwal kegiatan yang tersedia
|
||||||
</Text>
|
</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>
|
</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>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -1,100 +1,169 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import infoWabahPenyakit from '@/app/admin/(dashboard)/_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit';
|
import infoWabahPenyakit from '@/app/admin/(dashboard)/_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit';
|
||||||
import colors from '@/con/colors';
|
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 { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconSearch } from '@tabler/icons-react';
|
import { IconSearch, IconInfoCircle } from '@tabler/icons-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const state = useProxy(infoWabahPenyakit)
|
const state = useProxy(infoWabahPenyakit);
|
||||||
const [search, setSearch] = useState('')
|
const [search, setSearch] = useState('');
|
||||||
|
|
||||||
const {
|
const { data, page, totalPages, loading, load } = state.findMany;
|
||||||
data,
|
|
||||||
page,
|
|
||||||
totalPages,
|
|
||||||
loading,
|
|
||||||
load,
|
|
||||||
} = state.findMany;
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
load(page, 3, search)
|
load(page, 6, search);
|
||||||
}, [page, search])
|
}, [page, search]);
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py="xl" px={{ base: 'md', md: 100 }}>
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} radius="lg" />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Grid align='center' px={{ base: 'md', md: 100 }}>
|
|
||||||
<GridCol span={{ base: 12, md: 9 }}>
|
<Grid align="center" px={{ base: 'md', md: 100 }}>
|
||||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<GridCol span={{ base: 12, md: 8 }}>
|
||||||
Info Wabah / Penyakit
|
<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>
|
</Text>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 3 }}>
|
<GridCol span={{ base: 12, md: 4 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
radius={"lg"}
|
radius="xl"
|
||||||
placeholder='Cari Info Wabah / Penyakit'
|
placeholder="Cari nama penyakit atau wabah..."
|
||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
leftSection={<IconSearch size={20} />}
|
leftSection={<IconSearch size={20} />}
|
||||||
w={{ base: "50%", md: "100%" }}
|
w="100%"
|
||||||
|
size="md"
|
||||||
/>
|
/>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
|
||||||
<Stack gap={'lg'}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<SimpleGrid
|
{data.length === 0 ? (
|
||||||
cols={{
|
<Center py="6xl">
|
||||||
base: 1,
|
<Stack align="center" gap="sm">
|
||||||
md: 3,
|
<IconInfoCircle size={50} color={colors['blue-button']} />
|
||||||
}}
|
<Text fz="lg" fw={500} c="dimmed">
|
||||||
>
|
Tidak ada data yang cocok dengan pencarian Anda.
|
||||||
{data.map((v, k) => {
|
</Text>
|
||||||
return (
|
</Stack>
|
||||||
<Paper key={k} p={'xl'} bg={colors['white-trans-1']}>
|
</Center>
|
||||||
<Stack gap={'xs'}>
|
) : (
|
||||||
<Box>
|
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="lg">
|
||||||
<Text fw={"bold"} fz={'h3'} c={colors['blue-button']}>{v.name}</Text>
|
{data.map((v, k) => (
|
||||||
<Image w={330} h={200} fit='contain' pt={5} src={v.image.link} alt={v.name} />
|
<Paper
|
||||||
<Text fz={'h4'} fw={'bold'} >
|
key={k}
|
||||||
{v.name}
|
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>
|
||||||
<Text fz={'h6'} pb={10}>
|
</HoverCard.Target>
|
||||||
Diposting: 12 Februari 2025 | Dinas Kesehatan
|
<HoverCard.Dropdown>
|
||||||
</Text>
|
<Text
|
||||||
<Text fz={'h4'} pb={10}>
|
fz="sm"
|
||||||
{v.deskripsiSingkat}
|
lh={1.6}
|
||||||
</Text>
|
dangerouslySetInnerHTML={{
|
||||||
<Text fz={'h4'} pb={10} dangerouslySetInnerHTML={{ __html: v.deskripsiLengkap }} />
|
__html: v.deskripsiLengkap,
|
||||||
</Box>
|
}}
|
||||||
</Stack>
|
/>
|
||||||
</Paper>
|
</HoverCard.Dropdown>
|
||||||
)
|
</HoverCard>
|
||||||
})}
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Stack>
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Center>
|
|
||||||
<Pagination
|
{totalPages > 1 && (
|
||||||
value={page}
|
<Center>
|
||||||
onChange={(newPage) => load(newPage)} // ini penting!
|
<Pagination
|
||||||
total={totalPages}
|
value={page}
|
||||||
mt="md"
|
onChange={(newPage) => load(newPage)}
|
||||||
mb="md"
|
total={totalPages}
|
||||||
/>
|
radius="xl"
|
||||||
</Center>
|
size="md"
|
||||||
|
mt="lg"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,106 +1,150 @@
|
|||||||
'use client'
|
'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 { useState } from 'react';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
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 kontakDarurat from '@/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat';
|
||||||
import { IconSearch } from '@tabler/icons-react';
|
import colors from '@/con/colors';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const state = useProxy(kontakDarurat)
|
const state = useProxy(kontakDarurat);
|
||||||
const [search, setSearch] = useState('')
|
const [search, setSearch] = useState('');
|
||||||
|
|
||||||
const {
|
const { data, page, totalPages, loading, load } = state.findMany;
|
||||||
data,
|
|
||||||
page,
|
|
||||||
totalPages,
|
|
||||||
loading,
|
|
||||||
load,
|
|
||||||
} = state.findMany;
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
load(page, 3, search)
|
load(page, 6, search);
|
||||||
}, [page, search])
|
}, [page, search]);
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py="xl" px={{ base: 'md', md: 100 }}>
|
||||||
<Skeleton h={500} />
|
<Skeleton height={500} radius="lg" />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Grid align='center' px={{ base: 'md', md: 100 }}>
|
|
||||||
<GridCol span={{ base: 12, md: 9 }}>
|
<Grid align="center" px={{ base: 'md', md: 100 }} gutter="lg">
|
||||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<GridCol span={{ base: 12, md: 8 }}>
|
||||||
Penanganan Darurat
|
<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>
|
</Text>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 3 }}>
|
<GridCol span={{ base: 12, md: 4 }}>
|
||||||
<TextInput
|
<Tooltip label="Cari berdasarkan nama atau deskripsi" withArrow>
|
||||||
radius={"lg"}
|
<TextInput
|
||||||
placeholder='Cari Penanganan Darurat'
|
radius="xl"
|
||||||
value={search}
|
size="md"
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
placeholder="Cari kontak darurat..."
|
||||||
leftSection={<IconSearch size={20} />}
|
value={search}
|
||||||
w={{ base: "50%", md: "100%" }}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
/>
|
leftSection={<IconSearch size={20} />}
|
||||||
|
w="100%"
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
|
||||||
<Stack gap={'lg'}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<SimpleGrid
|
{data.length === 0 ? (
|
||||||
pb={10}
|
<Center mih={300}>
|
||||||
cols={{
|
<Stack align="center" gap="xs">
|
||||||
base: 1,
|
<IconSearch size={50} color={colors['blue-button']} />
|
||||||
md: 3,
|
<Text fz="lg" fw={600} c={colors['blue-button']}>
|
||||||
}}>
|
Tidak ada kontak ditemukan
|
||||||
{data.map((v, k) => {
|
</Text>
|
||||||
return (
|
<Text fz="sm" c="dimmed">
|
||||||
<Paper radius={10} key={k} bg={colors["white-trans-1"]}>
|
Coba kata kunci lain untuk pencarian
|
||||||
<Stack gap={'xs'}>
|
</Text>
|
||||||
<Center py={40}>
|
</Stack>
|
||||||
<Image
|
</Center>
|
||||||
src={v.image.link}
|
) : (
|
||||||
alt={v.name}
|
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="xl" mt="lg">
|
||||||
w={200}
|
{data.map((v, k) => (
|
||||||
h={200}
|
<Paper
|
||||||
fit='contain'
|
key={k}
|
||||||
/>
|
radius="xl"
|
||||||
</Center>
|
shadow="md"
|
||||||
<Box px={'lg'}>
|
withBorder
|
||||||
<Box pb={20}>
|
p="lg"
|
||||||
<Text pb={10} c={colors["blue-button"]} fw={"bold"} fz={"h3"}>
|
bg={colors['white-trans-1']}
|
||||||
{v.name}
|
style={{
|
||||||
</Text>
|
transition: 'all 200ms ease',
|
||||||
<Box px={10}>
|
cursor: 'pointer',
|
||||||
<Text fz={"h4"} dangerouslySetInnerHTML={{ __html: v.deskripsi }} />
|
}}
|
||||||
</Box>
|
>
|
||||||
</Box>
|
<Stack align="center" gap="sm">
|
||||||
</Box>
|
<Image
|
||||||
</Stack>
|
src={v.image.link}
|
||||||
</Paper>
|
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>
|
</SimpleGrid>
|
||||||
</Stack>
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Center>
|
|
||||||
<Pagination
|
{totalPages > 1 && (
|
||||||
value={page}
|
<Center mt="xl">
|
||||||
onChange={(newPage) => load(newPage)} // ini penting!
|
<Pagination
|
||||||
total={totalPages}
|
value={page}
|
||||||
mt="md"
|
onChange={(newPage) => load(newPage, 6, search)}
|
||||||
mb="md"
|
total={totalPages}
|
||||||
/>
|
radius="xl"
|
||||||
</Center>
|
size="md"
|
||||||
|
styles={{
|
||||||
|
control: {
|
||||||
|
borderRadius: '999px',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,108 +1,162 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import penangananDarurat from '@/app/admin/(dashboard)/_state/kesehatan/penanganan-darurat/penangananDarurat'
|
||||||
import { Box, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
import colors from '@/con/colors'
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import {
|
||||||
import { useProxy } from 'valtio/utils';
|
Badge,
|
||||||
import { useState } from 'react';
|
Box,
|
||||||
|
Center,
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
Grid,
|
||||||
import penangananDarurat from '@/app/admin/(dashboard)/_state/kesehatan/penanganan-darurat/penangananDarurat';
|
GridCol,
|
||||||
import { IconSearch } from '@tabler/icons-react';
|
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() {
|
function Page() {
|
||||||
const state = useProxy(penangananDarurat)
|
const state = useProxy(penangananDarurat)
|
||||||
const [search, setSearch] = useState('')
|
const [search, setSearch] = useState('')
|
||||||
|
|
||||||
const {
|
const { data, page, totalPages, loading, load } = state.findMany
|
||||||
data,
|
|
||||||
page,
|
|
||||||
totalPages,
|
|
||||||
loading,
|
|
||||||
load,
|
|
||||||
} = state.findMany;
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
load(page, 3, search)
|
load(page, 6, search)
|
||||||
}, [page, search])
|
}, [page, search])
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py="xl" px={{ base: 'md', md: 100 }}>
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} radius="lg" />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</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 }}>
|
<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
|
Penanganan Darurat
|
||||||
</Text>
|
</Text>
|
||||||
|
<Text fz="md" c="dimmed" mt={4}>
|
||||||
|
Informasi cepat dan jelas untuk situasi darurat kesehatan
|
||||||
|
</Text>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 3 }}>
|
<GridCol span={{ base: 12, md: 3 }}>
|
||||||
<TextInput
|
<Tooltip label="Ketik kata kunci untuk mencari penanganan darurat">
|
||||||
radius={"lg"}
|
<TextInput
|
||||||
placeholder='Cari Penanganan Darurat'
|
radius="lg"
|
||||||
value={search}
|
placeholder="Cari penanganan darurat..."
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
value={search}
|
||||||
leftSection={<IconSearch size={20} />}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
w={{ base: "50%", md: "100%" }}
|
leftSection={<IconSearch size={20} />}
|
||||||
/>
|
w="100%"
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</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
|
<SimpleGrid
|
||||||
pb={10}
|
cols={{ base: 1, sm: 2, md: 3 }}
|
||||||
cols={{
|
spacing="xl"
|
||||||
base: 1,
|
verticalSpacing="xl"
|
||||||
md: 3,
|
pb={20}
|
||||||
}}>
|
>
|
||||||
{data.map((v, k) => {
|
{data.map((v, k) => (
|
||||||
return (
|
<Paper
|
||||||
<Paper radius={10} key={k} bg={colors["white-trans-1"]}>
|
key={k}
|
||||||
<Stack gap={'xs'}>
|
radius="xl"
|
||||||
<Center py={40}>
|
p="md"
|
||||||
<Image
|
shadow="sm"
|
||||||
src={v.image.link}
|
withBorder
|
||||||
alt={v.name}
|
bg={colors['white-trans-1']}
|
||||||
w={200}
|
style={{ transition: 'all 0.3s ease' }}
|
||||||
h={200}
|
>
|
||||||
fit='contain'
|
<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>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
<Badge radius="md" color="blue" variant="light" mt="sm">
|
||||||
)
|
Darurat
|
||||||
})}
|
</Badge>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Stack>
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Center>
|
|
||||||
<Pagination
|
{totalPages > 1 && (
|
||||||
value={page}
|
<Center mt="xl">
|
||||||
onChange={(newPage) => load(newPage)} // ini penting!
|
<Pagination
|
||||||
total={totalPages}
|
value={page}
|
||||||
mt="md"
|
onChange={(newPage) => load(newPage, 6, search)}
|
||||||
mb="md"
|
total={totalPages}
|
||||||
/>
|
size="lg"
|
||||||
</Center>
|
radius="xl"
|
||||||
|
styles={{
|
||||||
|
control: {
|
||||||
|
border: `1px solid ${colors['blue-button']}`,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page
|
||||||
|
|||||||
@@ -1,119 +1,166 @@
|
|||||||
'use client'
|
'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 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 { useShallowEffect } from "@mantine/hooks";
|
||||||
import { useProxy } from "valtio/utils";
|
import { IconCalendar, IconInfoCircle, IconPhone, IconSearch } from "@tabler/icons-react";
|
||||||
import { useState } from "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() {
|
export default function Page() {
|
||||||
const state = useProxy(posyandustate)
|
const state = useProxy(posyandustate);
|
||||||
// const router = useTransitionRouter()
|
const [search, setSearch] = useState("");
|
||||||
const [search, setSearch] = useState("")
|
|
||||||
|
|
||||||
const {
|
const { data, page, totalPages, loading, load } = state.findMany;
|
||||||
data,
|
|
||||||
page,
|
|
||||||
totalPages,
|
|
||||||
loading,
|
|
||||||
load,
|
|
||||||
} = state.findMany;
|
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
load(page, 6, search);
|
||||||
|
}, [page, search]);
|
||||||
|
|
||||||
useShallowEffect(() => {
|
if (loading || !data) {
|
||||||
load(page, 3, search)
|
|
||||||
}, [page, search])
|
|
||||||
|
|
||||||
if (loading || !data) {
|
|
||||||
return (
|
|
||||||
<Box py={10}>
|
|
||||||
<Skeleton h={500} />
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
<Box py="xl" px={{ base: "md", md: 100 }}>
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Skeleton h={500} radius="lg" />
|
||||||
<BackButton />
|
</Box>
|
||||||
<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>
|
|
||||||
|
|
||||||
)
|
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'
|
'use client'
|
||||||
import programKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan';
|
import programKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan';
|
||||||
import colors from '@/con/colors';
|
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 { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconCalendar, IconUser } from '@tabler/icons-react';
|
import { IconCalendar, IconUser } from '@tabler/icons-react';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
@@ -18,45 +18,75 @@ function Page() {
|
|||||||
|
|
||||||
if (!state.findUnique.data) {
|
if (!state.findUnique.data) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<Center mih="60vh">
|
||||||
<Skeleton h={500} />
|
<Stack align="center" gap="sm">
|
||||||
</div>
|
<Loader color={colors["blue-button"]} size="lg" />
|
||||||
|
<Text c="dimmed" fz="sm">Memuat data program kesehatan...</Text>
|
||||||
|
</Stack>
|
||||||
|
</Center>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Paper px={{ base: 'md', md: 100 }} radius={10} bg={colors["white-trans-1"]}>
|
<Paper
|
||||||
<Stack gap={'xs'}>
|
px={{ base: 'md', md: 100 }}
|
||||||
<Center my={20}>
|
py="xl"
|
||||||
<Image radius={"lg"} src={state.findUnique.data.image?.link} alt="" />
|
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>
|
</Center>
|
||||||
<Box px={'lg'}>
|
<Box>
|
||||||
<Box>
|
<Text pb="sm" c={colors["blue-button"]} fw="bold" fz={{ base: 24, md: 32 }} lh={1.2}>
|
||||||
<Text pb={10} c={colors["blue-button"]} fw={"bold"} fz={"h3"}>
|
{state.findUnique.data.name}
|
||||||
{state.findUnique.data.name}
|
</Text>
|
||||||
</Text>
|
<Text
|
||||||
<Text ta={'justify'} fz={'h4'} dangerouslySetInnerHTML={{ __html: state.findUnique.data.deskripsi }}></Text>
|
ta="justify"
|
||||||
</Box>
|
fz="md"
|
||||||
<Group py={20}>
|
lh={1.6}
|
||||||
<Group gap="xs">
|
dangerouslySetInnerHTML={{ __html: state.findUnique.data.deskripsi }}
|
||||||
<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>
|
</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>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,7 +1,31 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import colors from "@/con/colors";
|
import colors from "@/con/colors";
|
||||||
import { Box, Button, Center, Grid, GridCol, Group, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from "@mantine/core";
|
import {
|
||||||
import { IconBarbell, IconCalendar, IconOld, IconSearch, IconUser, IconUsersGroup } from "@tabler/icons-react";
|
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 BackButton from "../../desa/layanan/_com/BackButto";
|
||||||
import { useProxy } from "valtio/utils";
|
import { useProxy } from "valtio/utils";
|
||||||
import programKesehatan from "@/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan";
|
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 { useShallowEffect } from "@mantine/hooks";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
const data2 = [
|
const manfaatProgram = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
icon: <IconBarbell size={50} color={colors['BG-trans']} />,
|
icon: <IconBarbell size={40} color="#fff" />,
|
||||||
title: "Menjaga Kesehatan Tubuh",
|
title: "Menjaga Tubuh Bugar",
|
||||||
desc: "Program kesehatan desa dirancang untuk memelihara kesehatan fisik masyarakat melalui aktivitas rutin, pemeriksaan kesehatan berkala, dan edukasi gaya hidup sehat.",
|
desc: "Meningkatkan kesehatan fisik masyarakat melalui olahraga rutin, pemeriksaan berkala, dan edukasi gaya hidup sehat.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
icon: <IconUsersGroup size={50} color={colors['BG-trans']} />,
|
icon: <IconUsersGroup size={40} color="#fff" />,
|
||||||
title: "Mempererat Kebersamaan",
|
title: "Menguatkan Kebersamaan",
|
||||||
desc: "Kegiatan kesehatan komunal menjadi wadah interaksi sosial yang memperkuat ikatan antar warga desa, menumbuhkan rasa kepedulian dan gotong royong.",
|
desc: "Menciptakan interaksi sosial sehat, mempererat solidaritas, dan memperkuat budaya gotong royong antar warga.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
icon: <IconOld size={50} color={colors['BG-trans']} />,
|
icon: <IconOld size={40} color="#fff" />,
|
||||||
title: "Medukung Lansia Aktif",
|
title: "Dukungan untuk Lansia",
|
||||||
desc: "Program khusus bagi lansia membantu menjaga kebugaran, mengurangi risiko penyakit degeneratif, dan menciptakan komunitas pendukung untuk kehidupan yang sehat dan bahagia.",
|
desc: "Membantu lansia tetap aktif, sehat, dan bahagia melalui kegiatan komunitas yang aman dan menyenangkan.",
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const state = useProxy(programKesehatan)
|
const state = useProxy(programKesehatan);
|
||||||
const router = useRouter()
|
const router = useRouter();
|
||||||
const [search, setSearch] = useState('')
|
const [search, setSearch] = useState("");
|
||||||
const {
|
const { data, page, totalPages, loading, load } = state.findMany;
|
||||||
data,
|
|
||||||
page,
|
|
||||||
totalPages,
|
|
||||||
loading,
|
|
||||||
load,
|
|
||||||
} = state.findMany;
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
load(page, 3, search)
|
load(page, 3, search);
|
||||||
}, [page, search])
|
}, [page, search]);
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py="xl" px={{ base: "md", md: 100 }}>
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} radius="lg" />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Grid px={{ base: 'md', md: 100 }} align="center">
|
|
||||||
<GridCol span={{ base: 12, md: 9 }}>
|
<Grid px={{ base: "md", md: 100 }} align="center" gutter="lg">
|
||||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<GridCol span={{ base: 12, md: 8 }}>
|
||||||
Program Kesehatan Unggulan
|
<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>
|
</Text>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 3 }}>
|
<GridCol span={{ base: 12, md: 4 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder='Cari Program Kesehatan'
|
placeholder="Cari program kesehatan..."
|
||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
leftSection={<IconSearch size={20} />}
|
leftSection={<IconSearch size={20} />}
|
||||||
w={{ base: "50%", md: "100%" }}
|
radius="lg"
|
||||||
|
size="md"
|
||||||
|
aria-label="Pencarian program kesehatan"
|
||||||
/>
|
/>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
<Stack gap={'lg'}>
|
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="lg" pb="xl">
|
||||||
<SimpleGrid
|
{data.map((v, k) => (
|
||||||
pb={10}
|
<Transition
|
||||||
cols={{
|
key={k}
|
||||||
base: 1,
|
mounted
|
||||||
md: 3,
|
transition="fade-up"
|
||||||
}}>
|
duration={400}
|
||||||
{data.map((v, k) => {
|
timingFunction="ease"
|
||||||
return (
|
>
|
||||||
<Paper radius={10} key={k} bg={colors["white-trans-1"]}>
|
{(styles) => (
|
||||||
<Stack gap={'xs'}>
|
<Paper
|
||||||
<Center>
|
style={styles}
|
||||||
<Image src={v.image?.link} alt="" style={{ borderRadius: '14px 14px 0 0' }} />
|
radius="xl"
|
||||||
</Center>
|
withBorder
|
||||||
<Box px={'lg'}>
|
bg="white"
|
||||||
<Box>
|
shadow="md"
|
||||||
<Text pb={10} c={colors["blue-button"]} fw={"bold"} fz={"h3"}>
|
className="hover-scale"
|
||||||
{v.name}
|
>
|
||||||
</Text>
|
<Stack gap="md">
|
||||||
<Text ta={'justify'} fz={'h4'} dangerouslySetInnerHTML={{ __html: v.deskripsi }}></Text>
|
<Image
|
||||||
</Box>
|
src={v.image?.link}
|
||||||
<Box py={15} onClick={() => router.push(`/darmasaba/kesehatan/program-kesehatan/${v.id}`)}>
|
alt={v.name}
|
||||||
<Button fw={'bold'} fz={'h5'} c={colors["blue-button"]} bg={colors["BG-trans"]}>Detail Program</Button>
|
radius="xl"
|
||||||
</Box>
|
height={180}
|
||||||
<Group py={20}>
|
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">
|
<Group gap="xs">
|
||||||
<IconCalendar size={18} />
|
<IconCalendar size={18} />
|
||||||
<Text size="sm">
|
<Text size="sm">
|
||||||
{v.createdAt ? new Date(v.createdAt).toLocaleDateString('id-ID', {
|
{v.createdAt
|
||||||
day: 'numeric',
|
? new Date(v.createdAt).toLocaleDateString(
|
||||||
month: 'long',
|
"id-ID",
|
||||||
year: 'numeric',
|
{
|
||||||
}) : 'No date available'}
|
day: "numeric",
|
||||||
|
month: "long",
|
||||||
|
year: "numeric",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
: "Tanggal tidak tersedia"}
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
@@ -114,61 +168,99 @@ export default function Page() {
|
|||||||
<Text size="sm">Admin Desa</Text>
|
<Text size="sm">Admin Desa</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</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>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
)
|
)}
|
||||||
})}
|
</Transition>
|
||||||
</SimpleGrid>
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
|
|
||||||
|
{totalPages > 1 && (
|
||||||
<Center>
|
<Center>
|
||||||
<Pagination
|
<Pagination
|
||||||
value={page}
|
value={page}
|
||||||
onChange={(newPage) => load(newPage)} // ini penting!
|
onChange={(newPage) => load(newPage)}
|
||||||
total={totalPages}
|
total={totalPages}
|
||||||
mt="md"
|
mt="md"
|
||||||
mb="md"
|
size="lg"
|
||||||
|
radius="xl"
|
||||||
|
styles={{
|
||||||
|
control: {
|
||||||
|
borderRadius: "50%",
|
||||||
|
boxShadow: "0 0 10px rgba(0,0,0,0.1)",
|
||||||
|
},
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
</Stack>
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box py={10} px={{ base: "md", md: 100 }}>
|
|
||||||
<Box pb={10}>
|
<Box px={{ base: "md", md: 100 }} py="xl">
|
||||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<Stack gap="sm" mb="lg">
|
||||||
|
<Text
|
||||||
|
fz={{ base: "2rem", md: "2.5rem" }}
|
||||||
|
c={colors["blue-button"]}
|
||||||
|
fw="bold"
|
||||||
|
>
|
||||||
Manfaat Program Kesehatan
|
Manfaat Program Kesehatan
|
||||||
</Text>
|
</Text>
|
||||||
<Text fz={{ base: "h4", md: "h3" }} >
|
<Text fz="lg" c="dimmed" maw={700}>
|
||||||
Program kesehatan di Desa Darmasaba memiliki peran penting dalam meningkatkan kesejahteraan masyarakat.
|
Program kesehatan Desa Darmasaba berperan penting dalam meningkatkan
|
||||||
|
kesejahteraan dan kualitas hidup warganya.
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Stack>
|
||||||
<SimpleGrid
|
<SimpleGrid cols={{ base: 1, md: 3 }} spacing="lg">
|
||||||
pb={30}
|
{manfaatProgram.map((v) => (
|
||||||
cols={{
|
<Paper
|
||||||
base: 1,
|
key={v.id}
|
||||||
md: 3,
|
px="xl"
|
||||||
}}>
|
py="xl"
|
||||||
{data2.map((v, k) => {
|
radius="xl"
|
||||||
return (
|
shadow="sm"
|
||||||
<Paper key={k} px={"xl"} py={80} bg={colors['white-trans-1']} c={colors['blue-button']}>
|
withBorder
|
||||||
<Stack justify='space-between' >
|
bg="white"
|
||||||
<Group justify='center'>
|
className="hover-glow"
|
||||||
<Paper p={'xl'} radius={'100'} bg={colors['blue-button']}>
|
>
|
||||||
<Center >
|
<Stack align="center" gap="md">
|
||||||
{v.icon}
|
<Paper
|
||||||
</Center>
|
p="lg"
|
||||||
</Paper>
|
radius="50%"
|
||||||
</Group>
|
shadow="md"
|
||||||
<Text ta={"center"} fw={"bold"} fz={"h3"}>
|
bg={colors["blue-button"]}
|
||||||
{v.title}
|
className="pulse-icon"
|
||||||
</Text>
|
>
|
||||||
<Text ta={"center"} fz={'h4'}>
|
<Center>{v.icon}</Center>
|
||||||
{v.desc}
|
</Paper>
|
||||||
</Text>
|
<Text ta="center" fw="bold" fz="xl" c={colors["blue-button"]}>
|
||||||
</Stack>
|
{v.title}
|
||||||
</Paper>
|
</Text>
|
||||||
)
|
<Text ta="center" fz="sm" c="dimmed">
|
||||||
})}
|
{v.desc}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import puskesmasState from '@/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas';
|
import puskesmasState from '@/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas';
|
||||||
import colors from '@/con/colors';
|
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 { useShallowEffect } from '@mantine/hooks';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import { IconClock, IconMapPin, IconPhone, IconMail, IconBuildingHospital } from '@tabler/icons-react';
|
||||||
import BackButton from '../../../desa/layanan/_com/BackButto';
|
import BackButton from '../../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
@@ -17,95 +18,117 @@ function Page() {
|
|||||||
|
|
||||||
if (!state.findUnique.data) {
|
if (!state.findUnique.data) {
|
||||||
return (
|
return (
|
||||||
<Stack py={10}>
|
<Stack py="xl" px={{ base: 'md', md: 100 }}>
|
||||||
<Skeleton h={500} />
|
<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>
|
</Stack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const data = state.findUnique.data
|
||||||
|
|
||||||
return (
|
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 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Stack gap={'lg'} px={{ base: 'md', md: 100 }}>
|
|
||||||
<Box>
|
<Stack gap="xl" px={{ base: 'md', md: 100 }}>
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
<Paper p="lg" radius="xl" shadow="md" bg={colors['white-trans-1']} withBorder>
|
||||||
<Box pb={30}>
|
<Box pb="xl">
|
||||||
<BackgroundImage
|
<BackgroundImage
|
||||||
pb={30}
|
radius="lg"
|
||||||
radius={16}
|
h={{ base: 260, md: 480 }}
|
||||||
h={{ base: 250, md: 500 }}
|
src={data.image.link}
|
||||||
src={state.findUnique.data.image.link}
|
style={{ position: 'relative', overflow: 'hidden' }}
|
||||||
style={{ position: 'relative' }}
|
>
|
||||||
|
<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
|
<Text fw="bold" fz={{ base: 'lg', md: 'h2' }} c={colors['white-1']}>
|
||||||
style={{
|
{data.name}
|
||||||
borderRadius: 16,
|
</Text>
|
||||||
zIndex: 0
|
<Group gap={6}>
|
||||||
}}
|
<IconMapPin size={20} color="white" />
|
||||||
pos={"absolute"}
|
<Text fz={{ base: 'sm', md: 'md' }} c={colors['white-1']}>
|
||||||
w={"100%"}
|
{data.alamat}
|
||||||
h={"100%"}
|
</Text>
|
||||||
bg={colors.trans.dark[2]}
|
</Group>
|
||||||
/>
|
</Stack>
|
||||||
<Text style={{
|
</BackgroundImage>
|
||||||
position: 'absolute',
|
|
||||||
bottom: 35,
|
<Grid mt="xl" gutter="xl">
|
||||||
left: 15,
|
<GridCol span={{ base: 12, md: 6 }}>
|
||||||
}} fw={'bold'} fz={{ base: 'md', md: 'h3' }} c={colors['white-1']}>{state.findUnique.data.name}</Text>
|
<Stack gap="lg">
|
||||||
<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 }}>
|
|
||||||
<Box>
|
<Box>
|
||||||
<Stack>
|
<Title order={3} mb={10}>Informasi Kontak</Title>
|
||||||
<Title order={3}>Informasi</Title>
|
<Stack gap={8}>
|
||||||
<Box>
|
<Group gap={8}>
|
||||||
<Text>Alamat: {state.findUnique.data.alamat}</Text>
|
<IconPhone size={18} />
|
||||||
<Text>Telepon: {state.findUnique.data.kontak.kontakPuskesmas}</Text>
|
<Text fz="md">{data.kontak.kontakPuskesmas || '-'}</Text>
|
||||||
<Text>Email: {state.findUnique.data.kontak.email}</Text>
|
</Group>
|
||||||
</Box>
|
<Group gap={8}>
|
||||||
<Title order={3}>Jam Operasional</Title>
|
<IconMail size={18} />
|
||||||
<Box>
|
<Text fz="md">{data.kontak.email || '-'}</Text>
|
||||||
<Text pb={10} fz={'h4'} fw={"bold"}>
|
</Group>
|
||||||
Senin - Kamis: <Text span fz={'h4'}>{state.findUnique.data?.jam.workDays} - {state.findUnique.data?.jam.weekDays}</Text>
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</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>
|
<Divider />
|
||||||
</Box>
|
|
||||||
|
<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>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import puskesmasState from '@/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas';
|
import puskesmasState from '@/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas';
|
||||||
import colors from '@/con/colors';
|
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 { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconSearch } from '@tabler/icons-react';
|
import { IconSearch, IconMapPin, IconPhone, IconMail } from '@tabler/icons-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const state = useProxy(puskesmasState)
|
const state = useProxy(puskesmasState)
|
||||||
const [search, setSearch] = useState('')
|
const [search, setSearch] = useState('')
|
||||||
@@ -22,76 +21,122 @@ function Page() {
|
|||||||
} = state.findMany;
|
} = state.findMany;
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
load(page, 3, search)
|
load(page, 6, search)
|
||||||
}, [page, search])
|
}, [page, search])
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py="xl" px={{ base: 'md', md: 100 }}>
|
||||||
<Skeleton h={500} />
|
<SimpleGrid cols={{ base: 1, md: 3 }} spacing="lg">
|
||||||
|
{Array.from({ length: 6 }).map((_, i) => (
|
||||||
|
<Skeleton key={i} height={320} radius="lg" />
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Grid align='center' px={{ base: 'md', md: 100 }}>
|
|
||||||
<GridCol span={{ base: 12, md: 9 }}>
|
<Grid align="center" px={{ base: 'md', md: 100 }} mb="md">
|
||||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<GridCol span={{ base: 12, md: 8 }}>
|
||||||
Puskesmas Darmasaba
|
<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>
|
</Text>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 3 }}>
|
<GridCol span={{ base: 12, md: 4 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
radius={"lg"}
|
radius="xl"
|
||||||
placeholder='Cari Puskesmas'
|
placeholder="Cari nama puskesmas..."
|
||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
leftSection={<IconSearch size={20} />}
|
leftSection={<IconSearch size={18} />}
|
||||||
w={{ base: "50%", md: "100%" }}
|
aria-label="Cari Puskesmas"
|
||||||
/>
|
/>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
|
||||||
<SimpleGrid
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
cols={{
|
{data.length === 0 ? (
|
||||||
base: 1,
|
<Center py="xl">
|
||||||
md: 3,
|
<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>
|
||||||
{data.map((v, k) => {
|
</Stack>
|
||||||
return (
|
</Center>
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']} key={k}>
|
) : (
|
||||||
<Stack gap={"xs"}>
|
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="lg">
|
||||||
<Text fw={"bold"} fz={"h3"}>{v.name}</Text>
|
{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
|
<Image
|
||||||
src={v.image.link}
|
src={v.image.link}
|
||||||
alt={v.name}
|
alt={v.name}
|
||||||
|
radius="md"
|
||||||
|
height={160}
|
||||||
|
fit="cover"
|
||||||
/>
|
/>
|
||||||
<Box>
|
<Group justify="space-between">
|
||||||
<Text>Alamat: {v.alamat}</Text>
|
<Text fw={600} fz="lg" lineClamp={1}>{v.name}</Text>
|
||||||
<Text>Telepon: {v.kontak.kontakPuskesmas}</Text>
|
<Badge color="blue" variant="light" radius="sm" fz="xs">Aktif</Badge>
|
||||||
<Text>Email: {v.kontak.email}</Text>
|
</Group>
|
||||||
</Box>
|
<Stack gap={4}>
|
||||||
<Anchor c={colors['blue-button']} href={`/darmasaba/kesehatan/puskesmas/${v.id}`}>Lihat Detail ></Anchor>
|
<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>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
)
|
))}
|
||||||
})}
|
</SimpleGrid>
|
||||||
</SimpleGrid>
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Center>
|
|
||||||
<Pagination
|
{totalPages > 1 && (
|
||||||
value={page}
|
<Center>
|
||||||
onChange={(newPage) => load(newPage)} // ini penting!
|
<Pagination
|
||||||
total={totalPages}
|
value={page}
|
||||||
mt="md"
|
onChange={(newPage) => load(newPage, 6, search)}
|
||||||
mb="md"
|
total={totalPages}
|
||||||
/>
|
size="md"
|
||||||
</Center>
|
radius="xl"
|
||||||
|
mt="lg"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,26 @@
|
|||||||
|
|
||||||
import daftarInformasiPublik from '@/app/admin/(dashboard)/_state/ppid/daftar_informasi_publik/daftarInformasiPublik';
|
import daftarInformasiPublik from '@/app/admin/(dashboard)/_state/ppid/daftar_informasi_publik/daftarInformasiPublik';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Center, Image, Pagination, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, TextInput } from '@mantine/core';
|
import {
|
||||||
|
Box,
|
||||||
|
Center,
|
||||||
|
Image,
|
||||||
|
Pagination,
|
||||||
|
Skeleton,
|
||||||
|
Stack,
|
||||||
|
Table,
|
||||||
|
TableTbody,
|
||||||
|
TableTd,
|
||||||
|
TableTh,
|
||||||
|
TableThead,
|
||||||
|
TableTr,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
Paper,
|
||||||
|
Badge,
|
||||||
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconSearch } from '@tabler/icons-react';
|
import { IconSearch, IconFileInfo, IconMail, IconBrandWhatsapp } from '@tabler/icons-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
@@ -21,85 +38,122 @@ function Page() {
|
|||||||
load,
|
load,
|
||||||
} = listData.findMany
|
} = listData.findMany
|
||||||
|
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
load(page, 5, search)
|
load(page, 5, search)
|
||||||
}, [page, search])
|
}, [page, search])
|
||||||
|
|
||||||
if (loading || !data) return <Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
if (loading || !data) {
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
return (
|
||||||
<Skeleton h={40} />
|
<Stack pos="relative" bg={colors.Bg} py="xl" gap="lg">
|
||||||
</Box>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<Skeleton h={40} />
|
<Skeleton h={40} radius="xl" />
|
||||||
<Skeleton h={40} />
|
</Box>
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Skeleton h={50} radius="xl" />
|
||||||
<Skeleton h={40} />
|
<Skeleton h={50} radius="xl" />
|
||||||
</Box>
|
<Skeleton h={50} radius="xl" />
|
||||||
</Stack>
|
</Stack>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
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 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Center>
|
<Center>
|
||||||
<Image src={"/darmasaba-icon.png"} w={{ base: 70, md: 100 }} alt='' />
|
<Image src="/darmasaba-icon.png" w={{ base: 70, md: 100 }} alt="Logo Desa Darmasaba" />
|
||||||
</Center>
|
</Center>
|
||||||
<Text ta={"center"} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<Text ta="center" fz={{ base: "1.8rem", md: "2.5rem" }} c={colors["blue-button"]} fw="bold" lh={1.4}>
|
||||||
Daftar Informasi Publik Desa Darmasaba
|
Daftar Informasi Publik Desa Darmasaba
|
||||||
</Text>
|
</Text>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
<Stack gap={'lmd'}>
|
<Stack gap="lg">
|
||||||
<Text fz={{ base: 'h3', md: 'h2' }} fw={"bold"}>Tentang Informasi Publik</Text>
|
<Paper p="lg" radius="xl" shadow="sm" withBorder>
|
||||||
<Text fz={{ base: 'md', md: 'h3' }}>Daftar Informasi Publik Desa Darmasaba berupa kumpulan data yang dapat diakses oleh masyarakat sesuai dengan peraturan yang berlaku.</Text>
|
<Stack gap="sm">
|
||||||
|
<Text fz={{ base: 'lg', md: 'xl' }} fw="bold" c={colors["blue-button"]}>
|
||||||
|
Tentang Informasi Publik
|
||||||
|
</Text>
|
||||||
|
<Text fz={{ base: 'sm', md: 'md' }} c="dimmed">
|
||||||
|
Daftar Informasi Publik Desa Darmasaba adalah kumpulan data yang dapat diakses oleh masyarakat sesuai dengan ketentuan peraturan yang berlaku.
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder='Cari Informasi...'
|
placeholder="Cari informasi publik..."
|
||||||
leftSection={<IconSearch size={20} />}
|
aria-label="Pencarian informasi publik"
|
||||||
|
leftSection={<IconSearch size={20} stroke={1.5} />}
|
||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
style={{ marginBottom: 16 }}
|
radius="xl"
|
||||||
|
size="md"
|
||||||
/>
|
/>
|
||||||
<Table withRowBorders withColumnBorders withTableBorder>
|
|
||||||
<TableThead bg={colors['blue-button']}>
|
{data.length === 0 ? (
|
||||||
<TableTr c={colors['white-1']}>
|
<Center py="xl">
|
||||||
<TableTh ta={'center'}>No</TableTh>
|
<Stack align="center" gap="sm">
|
||||||
<TableTh ta={'center'}>Jenis Informasi</TableTh>
|
<IconFileInfo size={48} stroke={1.5} color={colors["blue-button"]} />
|
||||||
<TableTh ta={'center'}>Deskripsi</TableTh>
|
<Text fz="md" c="dimmed">Tidak ada informasi publik yang ditemukan.</Text>
|
||||||
<TableTh ta={'center'}>Tanggal Publikasi</TableTh>
|
</Stack>
|
||||||
</TableTr>
|
</Center>
|
||||||
</TableThead>
|
) : (
|
||||||
<TableTbody bg={colors['white-1']}>
|
<Table withRowBorders withColumnBorders withTableBorder highlightOnHover verticalSpacing="md">
|
||||||
{listData.findMany.data?.map((item, index) => (
|
<TableThead bg={colors['blue-button']}>
|
||||||
<TableTr key={item.id}>
|
<TableTr c={colors['white-1']}>
|
||||||
<TableTd ta={'center'}>{index + 1}</TableTd>
|
<TableTh fz="sm" ta="center" w="5%">No</TableTh>
|
||||||
<TableTd>
|
<TableTh fz="sm" ta="center" w="25%">Jenis Informasi</TableTh>
|
||||||
<Text fz={'md'}>
|
<TableTh fz="sm" ta="center" w="40%">Deskripsi</TableTh>
|
||||||
{item.jenisInformasi}
|
<TableTh fz="sm" ta="center" w="20%">Tanggal Publikasi</TableTh>
|
||||||
</Text>
|
|
||||||
</TableTd>
|
|
||||||
<TableTd>
|
|
||||||
<Text
|
|
||||||
fz={'md'}
|
|
||||||
dangerouslySetInnerHTML={{ __html: item.deskripsi }}
|
|
||||||
/>
|
|
||||||
</TableTd>
|
|
||||||
<TableTd style={{ width: '20%', textAlign: 'center' }}>{item.tanggal
|
|
||||||
? new Date(item.tanggal).toLocaleDateString('id-ID')
|
|
||||||
: '-'}</TableTd>
|
|
||||||
</TableTr>
|
</TableTr>
|
||||||
))}
|
</TableThead>
|
||||||
</TableTbody>
|
<TableTbody bg={colors['white-1']}>
|
||||||
</Table>
|
{data.map((item, index) => (
|
||||||
|
<TableTr key={item.id}>
|
||||||
|
<TableTd ta="center">{(page - 1) * 5 + index + 1}</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Badge variant="light" size="lg" color="blue">
|
||||||
|
{item.jenisInformasi}
|
||||||
|
</Badge>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Text fz="sm" c="dark" dangerouslySetInnerHTML={{ __html: item.deskripsi }} />
|
||||||
|
</TableTd>
|
||||||
|
<TableTd ta="center">
|
||||||
|
{item.tanggal ? new Date(item.tanggal).toLocaleDateString('id-ID', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: 'long',
|
||||||
|
year: 'numeric'
|
||||||
|
}) : '-'}
|
||||||
|
</TableTd>
|
||||||
|
</TableTr>
|
||||||
|
))}
|
||||||
|
</TableTbody>
|
||||||
|
</Table>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Center>
|
||||||
|
<Pagination
|
||||||
|
value={page}
|
||||||
|
onChange={(newPage) => load(newPage, 5, search)}
|
||||||
|
total={totalPages}
|
||||||
|
my="lg"
|
||||||
|
radius="xl"
|
||||||
|
size="md"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
|
||||||
|
<Paper p="lg" radius="xl" shadow="xs" withBorder>
|
||||||
|
<Stack gap="xs">
|
||||||
|
<Text fz="lg" fw="bold" c={colors["blue-button"]}>Kontak PPID</Text>
|
||||||
|
<Text fz="sm" c="dimmed" lh={1.6}>
|
||||||
|
<IconMail size={16} style={{ marginRight: 6 }} /> Email: <Text span fw="500">ppid@desadarmasaba.id</Text>
|
||||||
|
</Text>
|
||||||
|
<Text fz="sm" c="dimmed" lh={1.6}>
|
||||||
|
<IconBrandWhatsapp size={16} style={{ marginRight: 6 }} /> WhatsApp: <Text span fw="500">081-xxx-xxx-xxx</Text>
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Center>
|
|
||||||
<Pagination
|
|
||||||
value={page}
|
|
||||||
onChange={(newPage) => load(newPage)}
|
|
||||||
total={totalPages}
|
|
||||||
my={"md"}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
<Text pt={20} fz={'h4'} fw={"bold"}>Kontak PPID</Text>
|
|
||||||
<Text fz={'sm'}>Email: ppid@desadarmasaba.id | WhatsApp: 081-xxx-xxx-xxx</Text>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,100 +1,93 @@
|
|||||||
|
'use client'
|
||||||
|
import stateDasarHukum from '@/app/admin/(dashboard)/_state/ppid/dasar_hukum/dasarHukum';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, List, ListItem, Paper, Stack, Text } from '@mantine/core';
|
import { Box, Paper, Skeleton, Stack, Text, Transition } from '@mantine/core';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import { IconBook2 } from '@tabler/icons-react';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
|
const state = useProxy(stateDasarHukum);
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
state.findById.load("1");
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!state.findById.data) {
|
||||||
|
return (
|
||||||
|
<Stack p="xl" gap="md">
|
||||||
|
<Skeleton h={70} radius="xl" />
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataArray = Array.isArray(state.findById.data)
|
||||||
|
? state.findById.data
|
||||||
|
: [state.findById.data];
|
||||||
|
|
||||||
return (
|
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 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Text ta={"center"} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<Stack align="center" gap="xs">
|
||||||
Dasar Hukum
|
<IconBook2 size={42} stroke={1.5} color={colors["blue-button"]} />
|
||||||
</Text>
|
<Text
|
||||||
|
ta="center"
|
||||||
|
fz={{ base: "2rem", md: "2.5rem" }}
|
||||||
|
c={colors["blue-button"]}
|
||||||
|
fw="bold"
|
||||||
|
style={{ letterSpacing: "-0.5px" }}
|
||||||
|
>
|
||||||
|
Dasar Hukum
|
||||||
|
</Text>
|
||||||
|
<Text ta="center" fz="sm" c="dimmed">
|
||||||
|
Informasi regulasi dan kebijakan resmi yang menjadi dasar hukum
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
<Stack gap="lg">
|
||||||
<Box>
|
{dataArray.map((item, k) => (
|
||||||
<Text ta={"center"} fw={"bold"} fz={{ base: 'h4', md: 'h3' }}>DASAR HUKUM PEMBENTUKAN PPID DESA DARMASABA</Text>
|
<Transition
|
||||||
</Box>
|
key={k}
|
||||||
<List p={'lg'}>
|
mounted={true}
|
||||||
<ListItem fz={{ base: 'md', md: 'h4' }}>
|
transition="fade-up"
|
||||||
<Text ta={"justify"} fz={{ base: 'md', md: 'h4' }}>
|
duration={400}
|
||||||
<Text fw={"bold"} span>
|
timingFunction="ease"
|
||||||
UU Nomor 14 Tahun 2008
|
>
|
||||||
</Text>
|
{(styles) => (
|
||||||
{" "}tentang Keterbukaan Informasi Publik
|
<Paper
|
||||||
</Text>
|
p="xl"
|
||||||
</ListItem>
|
radius="xl"
|
||||||
<ListItem fz={{ base: 'md', md: 'h4' }}>
|
shadow="md"
|
||||||
<Text ta={"justify"} fz={{ base: 'md', md: 'h4' }}>
|
bg={colors['white-trans-1']}
|
||||||
<Text fw={"bold"} span>
|
style={{
|
||||||
PP Nomor 61 Tahun 2010
|
...styles,
|
||||||
</Text>
|
backdropFilter: "blur(10px)",
|
||||||
{" "}tentang Pelaksanaan UU 14 Tahun 2008 tentang Keterbukaan Informasi Publik
|
border: `1px solid ${colors["blue-button"]}20`,
|
||||||
</Text>
|
}}
|
||||||
</ListItem>
|
>
|
||||||
<ListItem fz={{ base: 'md', md: 'h4' }}>
|
<Stack gap="md">
|
||||||
<Text ta={"justify"} fz={{ base: 'md', md: 'h4' }}>
|
<Text
|
||||||
<Text fw={"bold"} span>
|
ta="center"
|
||||||
Permendagri Nomor 3 Tahun 2017
|
fw="bold"
|
||||||
</Text>
|
fz={{ base: 'lg', md: 'xl' }}
|
||||||
{" "}tentang Pedoman Pengelolaan Pelayanan Informasi dan Dokumentasi di Lingkungan Kemendagri
|
style={{ lineHeight: 1.4 }}
|
||||||
dan Pemerintah Daerah
|
>
|
||||||
</Text>
|
{item.judul}
|
||||||
</ListItem>
|
</Text>
|
||||||
<ListItem fz={{ base: 'md', md: 'h4' }}>
|
<Text
|
||||||
<Text ta={"justify"} fz={{ base: 'md', md: 'h4' }}>
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
<Text fw={"bold"} span>
|
style={{ lineHeight: 1.7 }}
|
||||||
Peraturan Komisi Informasi Nomor 1 Tahun 2010
|
dangerouslySetInnerHTML={{ __html: item.content }}
|
||||||
</Text>
|
/>
|
||||||
{" "} tentang Standar Layanan Informasi Publik
|
</Stack>
|
||||||
</Text>
|
</Paper>
|
||||||
</ListItem>
|
)}
|
||||||
<ListItem fz={{ base: 'md', md: 'h4' }}>
|
</Transition>
|
||||||
<Text ta={"justify"} fz={{ base: 'md', md: 'h4' }}>
|
))}
|
||||||
<Text fw={"bold"} span>
|
</Stack>
|
||||||
Peraturan Komisi Informasi Nomor 1 Tahun 2010
|
|
||||||
</Text>
|
|
||||||
{" "} tentang Standar Layanan Informasi Publik
|
|
||||||
</Text>
|
|
||||||
</ListItem>
|
|
||||||
<ListItem fz={{ base: 'md', md: 'h4' }}>
|
|
||||||
<Text ta={"justify"} fz={{ base: 'md', md: 'h4' }}>
|
|
||||||
<Text fw={"bold"} span>
|
|
||||||
Peraturan Bupati Badung No. 42 Tahun 2017
|
|
||||||
</Text>
|
|
||||||
{" "}Tentang Pedoman Pengelolaan Pelayanan Informasi Publik dan Dokumentasi
|
|
||||||
di Lingkungan Pemerintah Kabupaten Badung
|
|
||||||
</Text>
|
|
||||||
</ListItem>
|
|
||||||
<ListItem fz={{ base: 'md', md: 'h4' }}>
|
|
||||||
<Text ta={"justify"} fz={{ base: 'md', md: 'h4' }}>
|
|
||||||
<Text fw={"bold"} span>
|
|
||||||
Keputusan Bupati Badung Nomor 99/049/HK/2019
|
|
||||||
</Text>
|
|
||||||
{" "} Tentang Pengelola Layanan Informasi dan Dokumentasi Kabupaten Badung
|
|
||||||
</Text>
|
|
||||||
</ListItem>
|
|
||||||
<ListItem fz={{ base: 'md', md: 'h4' }}>
|
|
||||||
<Text ta={"justify"} fz={{ base: 'md', md: 'h4' }}>
|
|
||||||
<Text fw={"bold"} span>
|
|
||||||
Keputusan Perbekel Darmasaba Nomor 101 Tahun 2019
|
|
||||||
</Text>
|
|
||||||
{" "}tentang Penetapan Pelaksana Teknis/Administrasi Pengelola Layanan Informasi
|
|
||||||
Dan Dokumentasi Di Desa Punggul
|
|
||||||
</Text>
|
|
||||||
</ListItem>
|
|
||||||
<ListItem fz={{ base: 'md', md: 'h4' }}>
|
|
||||||
<Text ta={"justify"} fz={{ base: 'md', md: 'h4' }}>
|
|
||||||
<Text fw={"bold"} span>
|
|
||||||
Peraturan Perbekel Darmasaba Nomor 12 Tahun 2019
|
|
||||||
</Text>
|
|
||||||
{" "}tentang Pedoman Pengelolaan Pelayanan Informasi Publik Dan Dokumentasi
|
|
||||||
Di Lingkungan Pemerintah Desa Darmasaba
|
|
||||||
</Text>
|
|
||||||
</ListItem>
|
|
||||||
</List>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,21 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import statePermohonanInformasi from '@/app/admin/(dashboard)/_state/ppid/permohonan_informasi_publik/permohonanInformasiPublik';
|
import statePermohonanInformasi from '@/app/admin/(dashboard)/_state/ppid/permohonan_informasi_publik/permohonanInformasiPublik';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { ActionIcon, Box, Button, Center, Checkbox, Group, Paper, SimpleGrid, Stack, Text, TextInput } from '@mantine/core';
|
import {
|
||||||
import { IconDownload } from '@tabler/icons-react';
|
ActionIcon,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Checkbox,
|
||||||
|
Group,
|
||||||
|
Paper,
|
||||||
|
SimpleGrid,
|
||||||
|
Stack,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
Tooltip,
|
||||||
|
} from '@mantine/core';
|
||||||
|
import { IconDownload, IconSend2 } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
@@ -10,11 +23,31 @@ import JenisInformasiSelector from './jenis_infromasi/jenisInformasiSelector';
|
|||||||
import MemperolehInformasi from './memperoleh_informasi/memperolehInfromasi';
|
import MemperolehInformasi from './memperoleh_informasi/memperolehInfromasi';
|
||||||
import MemperolehSalinan from './salinan_informasi/salinanInformasi';
|
import MemperolehSalinan from './salinan_informasi/salinanInformasi';
|
||||||
|
|
||||||
const data = [
|
const steps = [
|
||||||
{ id: 1, number: '1', title: "Langkah 1", desc: "Pemohon informasi publik mengajukan permohonan informasi kepada badan publik baik langsung maupun melalui surat elektronik" },
|
{
|
||||||
{ id: 2, number: '2', title: "Langkah 2", desc: "Isi formulir permohonan informasi dengan data diri (nama, alamat, telepon), jenis, format, dan cara penyampaian informasi, serta lampiran fotokopi kartu identitas." },
|
id: 1,
|
||||||
{ id: 3, number: '3', title: "Langkah 3", desc: "PPID akan memproses permohonan sesuai dengan ketentuan" },
|
number: '1',
|
||||||
{ id: 4, number: '4', title: "Langkah 4", desc: "Petugas PPID menyampaikan informasi sesuai permohonan kepada pemohon informasi." },
|
title: 'Ajukan Permohonan',
|
||||||
|
desc: 'Pemohon mengajukan permohonan informasi kepada badan publik secara langsung atau melalui surat elektronik.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
number: '2',
|
||||||
|
title: 'Isi Formulir',
|
||||||
|
desc: 'Lengkapi formulir dengan identitas (nama, alamat, telepon, email), jenis, format, serta cara memperoleh informasi, dan lampirkan fotokopi identitas.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
number: '3',
|
||||||
|
title: 'Proses oleh PPID',
|
||||||
|
desc: 'PPID akan memproses permohonan sesuai ketentuan yang berlaku.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
number: '4',
|
||||||
|
title: 'Penyampaian Informasi',
|
||||||
|
desc: 'Petugas PPID memberikan informasi sesuai permohonan kepada pemohon.',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
@@ -24,87 +57,219 @@ function Page() {
|
|||||||
const submitForms = () => {
|
const submitForms = () => {
|
||||||
const { create } = permohonanInformasiPublikState.statepermohonanInformasiPublik;
|
const { create } = permohonanInformasiPublikState.statepermohonanInformasiPublik;
|
||||||
|
|
||||||
if (create.form.name && create.form.nik && create.form.notelp && create.form.alamat && create.form.email &&
|
if (
|
||||||
create.form.jenisInformasiDimintaId && create.form.caraMemperolehInformasiId && create.form.caraMemperolehSalinanInformasiId) {
|
create.form.name &&
|
||||||
|
create.form.nik &&
|
||||||
|
create.form.notelp &&
|
||||||
|
create.form.alamat &&
|
||||||
|
create.form.email &&
|
||||||
|
create.form.jenisInformasiDimintaId &&
|
||||||
|
create.form.caraMemperolehInformasiId &&
|
||||||
|
create.form.caraMemperolehSalinanInformasiId
|
||||||
|
) {
|
||||||
create.create();
|
create.create();
|
||||||
router.push('/darmasaba/permohonan/berhasil');
|
router.push('/darmasaba/permohonan/berhasil');
|
||||||
} else {
|
} else {
|
||||||
console.log("Validasi gagal, form tidak lengkap");
|
console.log('Validasi gagal, form tidak lengkap');
|
||||||
// Display error message to user
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
<Stack pos="relative" bg={colors.Bg} py="xl" gap={40}>
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Text ta={"center"} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
|
||||||
|
<Text
|
||||||
|
ta="center"
|
||||||
|
fz={{ base: '2rem', md: '2.5rem' }}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
fw="bold"
|
||||||
|
>
|
||||||
Permohonan Informasi Publik
|
Permohonan Informasi Publik
|
||||||
</Text>
|
</Text>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
|
||||||
<Stack gap={'lg'}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
<Stack gap="xl">
|
||||||
<Text pb={30} ta={'center'} fw={"bold"} fz={{ base: 'h3', md: 'h2' }}>Tata Cara Permohonan</Text>
|
<Paper
|
||||||
<SimpleGrid pb={30} cols={{ base: 1, md: 2, lg: 3, xl: 4 }}>
|
p="xl"
|
||||||
{data.map((v, k) => (
|
radius="lg"
|
||||||
<Paper key={k} p={"xl"} bg={colors['blue-button']}>
|
withBorder
|
||||||
<Stack justify='space-between'>
|
shadow="sm"
|
||||||
|
bg={colors['white-trans-1']}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
pb={30}
|
||||||
|
ta="center"
|
||||||
|
fw="bold"
|
||||||
|
fz={{ base: 'h4', md: 'h3' }}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
>
|
||||||
|
Tata Cara Permohonan
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<SimpleGrid pb={30} cols={{ base: 1, sm: 2, lg: 4 }} spacing="lg">
|
||||||
|
{steps.map((v) => (
|
||||||
|
<Paper
|
||||||
|
key={v.id}
|
||||||
|
p="lg"
|
||||||
|
radius="md"
|
||||||
|
shadow="md"
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
>
|
||||||
|
<Stack justify="space-between" gap="sm">
|
||||||
<Center>
|
<Center>
|
||||||
<ActionIcon bg={colors['white-1']} radius={150} size={50}>
|
<ActionIcon
|
||||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={{ base: "h3", md: "h2" }}>{v.number}</Text>
|
bg={colors['white-1']}
|
||||||
|
radius="xl"
|
||||||
|
size={60}
|
||||||
|
variant="light"
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
c={colors['blue-button']}
|
||||||
|
ta="center"
|
||||||
|
fw="bold"
|
||||||
|
fz="h3"
|
||||||
|
>
|
||||||
|
{v.number}
|
||||||
|
</Text>
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</Center>
|
</Center>
|
||||||
<Text ta={"center"} c={colors['white-1']} fw={"bold"} fz={"h3"}>{v.title}</Text>
|
<Text
|
||||||
<Text ta={"center"} c={colors['white-1']} fz={'h4'}>{v.desc}</Text>
|
ta="center"
|
||||||
|
c={colors['white-1']}
|
||||||
|
fw="bold"
|
||||||
|
fz="lg"
|
||||||
|
>
|
||||||
|
{v.title}
|
||||||
|
</Text>
|
||||||
|
<Text ta="center" c={colors['white-1']} fz="sm">
|
||||||
|
{v.desc}
|
||||||
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
))}
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
|
|
||||||
<Center pb={30}>
|
<Center pb={30}>
|
||||||
<Button fz={"h5"} bg={colors['blue-button']} leftSection={<IconDownload size={20} color={colors['white-1']} />}>
|
<Tooltip label="Unduh dokumen tata cara permohonan" withArrow>
|
||||||
Unduh Dokumen
|
<Button
|
||||||
</Button>
|
fz="sm"
|
||||||
|
size="md"
|
||||||
|
radius="md"
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
leftSection={
|
||||||
|
<IconDownload size={20} color={colors['white-1']} />
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Unduh Tata Cara
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
</Center>
|
</Center>
|
||||||
<Group justify='center'>
|
|
||||||
<Paper p={'xl'} bg={colors['white-1']}>
|
<Group justify="center">
|
||||||
<Stack gap={"xs"}>
|
<Paper
|
||||||
<Text fw={"bold"} fz={{ base: 'h4', md: 'h3' }} ta={"center"}>Formulir Permohonan Informasi</Text>
|
p="xl"
|
||||||
<TextInput label="Nama Lengkap" placeholder="masukkan nama lengkap" onChange={(val) => {
|
radius="lg"
|
||||||
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.name = val.target.value;
|
withBorder
|
||||||
}} />
|
shadow="sm"
|
||||||
<TextInput label="NIK" placeholder="masukkan NIK" onChange={(val) => {
|
bg={colors['white-1']}
|
||||||
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.nik = val.target.value;
|
w="100%"
|
||||||
}} />
|
maw={800}
|
||||||
<TextInput label="No.Telp" placeholder="masukkan no telp" onChange={(val) => {
|
>
|
||||||
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.notelp = val.target.value;
|
<Stack gap="md">
|
||||||
}} />
|
<Text
|
||||||
<TextInput label="Alamat" placeholder="masukkan alamat" onChange={(val) => {
|
fw="bold"
|
||||||
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.alamat = val.target.value;
|
fz={{ base: 'h4', md: 'h3' }}
|
||||||
}} />
|
ta="center"
|
||||||
<TextInput label="Email" placeholder="masukkan email" onChange={(val) => {
|
c={colors['blue-button']}
|
||||||
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.email = val.target.value;
|
>
|
||||||
}} />
|
Formulir Permohonan Informasi
|
||||||
<JenisInformasiSelector
|
</Text>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
label="Nama Lengkap"
|
||||||
|
placeholder="Masukkan nama lengkap Anda"
|
||||||
|
withAsterisk
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.jenisInformasiDimintaId = val.id;
|
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.name =
|
||||||
|
val.target.value;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<MemperolehInformasi
|
<TextInput
|
||||||
|
label="Nomor Induk Kependudukan (NIK)"
|
||||||
|
placeholder="Masukkan NIK"
|
||||||
|
withAsterisk
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.caraMemperolehInformasiId = val.id;
|
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.nik =
|
||||||
}}
|
val.target.value;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<MemperolehSalinan
|
<TextInput
|
||||||
|
label="Nomor Telepon"
|
||||||
|
placeholder="Masukkan nomor telepon aktif"
|
||||||
|
withAsterisk
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.caraMemperolehSalinanInformasiId = val.id;
|
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.notelp =
|
||||||
}}
|
val.target.value;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<Box py={10}>
|
<TextInput
|
||||||
<Checkbox label="Saya menyatakan bahwa informasi yang saya berikan adalah benar dan akan menggunakan informasi yang diminta" />
|
label="Alamat Lengkap"
|
||||||
|
placeholder="Masukkan alamat sesuai identitas"
|
||||||
|
withAsterisk
|
||||||
|
onChange={(val) => {
|
||||||
|
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.alamat =
|
||||||
|
val.target.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Alamat Email"
|
||||||
|
placeholder="Masukkan alamat email aktif"
|
||||||
|
withAsterisk
|
||||||
|
onChange={(val) => {
|
||||||
|
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.email =
|
||||||
|
val.target.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<JenisInformasiSelector
|
||||||
|
onChange={(val) => {
|
||||||
|
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.jenisInformasiDimintaId =
|
||||||
|
val.id;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<MemperolehInformasi
|
||||||
|
onChange={(val) => {
|
||||||
|
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.caraMemperolehInformasiId =
|
||||||
|
val.id;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<MemperolehSalinan
|
||||||
|
onChange={(val) => {
|
||||||
|
permohonanInformasiPublikState.statepermohonanInformasiPublik.create.form.caraMemperolehSalinanInformasiId =
|
||||||
|
val.id;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Box py="sm">
|
||||||
|
<Checkbox
|
||||||
|
size="sm"
|
||||||
|
color={colors['blue-button']}
|
||||||
|
label="Saya menyatakan bahwa data yang saya berikan benar adanya dan informasi yang diminta akan digunakan sesuai ketentuan."
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Group>
|
|
||||||
<Button bg={colors['blue-button']} onClick={submitForms}>Kirim Permohonan</Button>
|
<Group justify="center" pt="sm">
|
||||||
|
<Button
|
||||||
|
size="md"
|
||||||
|
radius="md"
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
leftSection={<IconSend2 size={20} color={colors['white-1']} />}
|
||||||
|
onClick={submitForms}
|
||||||
|
>
|
||||||
|
Kirim Permohonan
|
||||||
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -116,4 +281,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
|
|||||||
@@ -2,136 +2,243 @@
|
|||||||
import permohonanKeberatanInformasi from '@/app/admin/(dashboard)/_state/ppid/permohonan_keberatan_informasi_publik/permohonanKeberatanInformasi';
|
import permohonanKeberatanInformasi from '@/app/admin/(dashboard)/_state/ppid/permohonan_keberatan_informasi_publik/permohonanKeberatanInformasi';
|
||||||
import { PPIDTextEditor } from '@/app/admin/(dashboard)/ppid/_com/PPIDTextEditor';
|
import { PPIDTextEditor } from '@/app/admin/(dashboard)/ppid/_com/PPIDTextEditor';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Center, Group, Paper, SimpleGrid, Stack, Text, TextInput } from '@mantine/core';
|
import {
|
||||||
import { IconFileCheck, IconForms, IconHourglassOff, IconPhoneRinging } from '@tabler/icons-react';
|
Box,
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Group,
|
||||||
|
Paper,
|
||||||
|
SimpleGrid,
|
||||||
|
Stack,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
Tooltip,
|
||||||
|
} from '@mantine/core';
|
||||||
|
import {
|
||||||
|
IconFileCheck,
|
||||||
|
IconForms,
|
||||||
|
IconHourglassOff,
|
||||||
|
IconPhoneRinging,
|
||||||
|
} from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
icon: <IconForms size={50} color={colors['white-1']} />,
|
icon: IconForms,
|
||||||
title: "Formulir Online",
|
title: 'Isi Formulir',
|
||||||
desc: "Isi formulir keberatan secara online.",
|
desc: 'Lengkapi formulir keberatan secara online dengan mudah.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
icon: <IconFileCheck size={50} color={colors['white-1']} />,
|
icon: IconFileCheck,
|
||||||
title: "Verifikasi",
|
title: 'Verifikasi Data',
|
||||||
desc: "Tim PPID akan memverifikasi permohonan Anda.",
|
desc: 'Tim PPID akan memeriksa dan memverifikasi permohonan Anda.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
icon: <IconHourglassOff size={50} color={colors['white-1']} />,
|
icon: IconHourglassOff,
|
||||||
title: "Proses Keberatan",
|
title: 'Proses Keberatan',
|
||||||
desc: "Proses penyelesaian keberatan dalam waktu 30 hari kerja.",
|
desc: 'Keberatan diproses maksimal dalam 30 hari kerja.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
icon: <IconPhoneRinging size={50} color={colors['white-1']} />,
|
icon: IconPhoneRinging,
|
||||||
title: "Hasil",
|
title: 'Hasil Dikirim',
|
||||||
desc: "Hasil keberatan akan dikirim via email atau SMS.",
|
desc: 'Hasil keputusan dikirim melalui email atau WhatsApp.',
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const stateKeberatan = useProxy(permohonanKeberatanInformasi)
|
const stateKeberatan = useProxy(permohonanKeberatanInformasi);
|
||||||
const submit = () => {
|
const router = useRouter();
|
||||||
if (stateKeberatan.create.form.name && stateKeberatan.create.form.email && stateKeberatan.create.form.notelp && stateKeberatan.create.form.alasan) {
|
|
||||||
stateKeberatan.create.create()
|
const submit = () => {
|
||||||
router.push('/darmasaba/permohonan/berhasil')
|
if (
|
||||||
} else {
|
stateKeberatan.create.form.name &&
|
||||||
console.log("Validasi gagal, form tidak lengkap")
|
stateKeberatan.create.form.email &&
|
||||||
}
|
stateKeberatan.create.form.notelp &&
|
||||||
|
stateKeberatan.create.form.alasan
|
||||||
|
) {
|
||||||
|
stateKeberatan.create.create();
|
||||||
|
router.push('/darmasaba/permohonan/berhasil');
|
||||||
|
} else {
|
||||||
|
console.log('Formulir belum lengkap');
|
||||||
}
|
}
|
||||||
const router = useRouter();
|
};
|
||||||
return (
|
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
return (
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Stack bg={colors.Bg} py="xl" gap={40}>
|
||||||
<BackButton />
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
|
<BackButton />
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Stack align="center" px={{ base: 'md', md: 100 }}>
|
||||||
|
<Text
|
||||||
|
ta="center"
|
||||||
|
fz={{ base: '2rem', md: '2.8rem' }}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
fw={800}
|
||||||
|
style={{ letterSpacing: '-0.5px' }}
|
||||||
|
>
|
||||||
|
Permohonan Keberatan Informasi Publik
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Paper
|
||||||
|
p="xl"
|
||||||
|
radius="xl"
|
||||||
|
bg={colors['white-trans-1']}
|
||||||
|
shadow="sm"
|
||||||
|
withBorder
|
||||||
|
>
|
||||||
|
<Stack gap="xl">
|
||||||
|
<Box>
|
||||||
|
<Text fw={700} fz={{ base: 'lg', md: 'xl' }} mb={8}>
|
||||||
|
Tentang Permohonan Keberatan
|
||||||
|
</Text>
|
||||||
|
<Text ta="justify" fz={{ base: 'sm', md: 'md' }} lh={1.6}>
|
||||||
|
Jika Anda merasa permohonan informasi tidak ditanggapi dengan
|
||||||
|
baik atau ditolak, Anda berhak mengajukan keberatan melalui
|
||||||
|
formulir berikut.
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Text ta={"center"} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
|
||||||
Permohonan Keberatan Informasi Publik
|
<Stack>
|
||||||
</Text>
|
<Text
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
ta="center"
|
||||||
<Stack gap={'lg'}>
|
fw={700}
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
fz={{ base: 'xl', md: '2xl' }}
|
||||||
<Box pb={30}>
|
style={{ letterSpacing: '-0.5px' }}
|
||||||
<Text fw={"bold"} fz={{ base: 'h4', md: 'h3' }}>Tentang Permohonan Keberatan</Text>
|
>
|
||||||
<Text ta={"justify"} fz={{ base: 'md', md: 'h4' }}>Jika Anda merasa permohonan informasi yang diajukan tidak mendapatkan tanggapan yang memadai atau ditolak, anda berhak mengajukan
|
Alur Pengajuan Keberatan
|
||||||
keberatan melalui formulir di bawah ini.</Text>
|
</Text>
|
||||||
</Box>
|
|
||||||
<Text pb={20} ta={"center"} fw={"bold"} fz={{ base: 'h3', md: 'h2' }}>Bagaimana Mengajukan Keberatan?</Text>
|
<SimpleGrid cols={{ base: 1, md: 4 }} spacing="lg">
|
||||||
<SimpleGrid
|
{data.map((v) => (
|
||||||
pb={30}
|
<Paper
|
||||||
cols={{
|
key={v.id}
|
||||||
base: 1,
|
p="lg"
|
||||||
md: 4,
|
radius="lg"
|
||||||
}}>
|
bg={colors['blue-button']}
|
||||||
{data.map((v, k) => {
|
shadow="md"
|
||||||
return (
|
>
|
||||||
<Paper key={k} p={"xl"} bg={colors['blue-button']}>
|
<Stack align="center" gap="sm">
|
||||||
<Stack justify='space-between'>
|
<Center>
|
||||||
<Center>
|
<v.icon size={48} color={colors['white-1']} />
|
||||||
{v.icon}
|
</Center>
|
||||||
</Center>
|
<Text
|
||||||
<Text ta={"center"} c={colors['white-1']} fw={"bold"} fz={"h3"}>
|
ta="center"
|
||||||
{v.title}
|
c={colors['white-1']}
|
||||||
</Text>
|
fw={700}
|
||||||
<Text ta={"center"} c={colors['white-1']} fz={'h4'}>
|
fz="lg"
|
||||||
{v.desc}
|
>
|
||||||
</Text>
|
{v.title}
|
||||||
</Stack>
|
</Text>
|
||||||
</Paper>
|
<Text ta="center" c={colors['white-1']} fz="sm">
|
||||||
)
|
{v.desc}
|
||||||
})}
|
</Text>
|
||||||
</SimpleGrid>
|
</Stack>
|
||||||
<Group justify='center'>
|
</Paper>
|
||||||
<Paper p={'xl'} bg={colors['white-1']}>
|
))}
|
||||||
<Stack gap={"xs"}>
|
</SimpleGrid>
|
||||||
<Text fw={"bold"} fz={{ base: 'h4', md: 'h3' }} ta={"center"}>Formulir Permohonan Keberatan</Text>
|
</Stack>
|
||||||
<TextInput
|
|
||||||
label="Nama"
|
<Group justify="center">
|
||||||
placeholder="masukkan nama lengkap"
|
<Paper
|
||||||
onChange={(val) => {
|
p="xl"
|
||||||
stateKeberatan.create.form.name = val.target.value
|
radius="xl"
|
||||||
}}
|
bg={colors['white-1']}
|
||||||
/>
|
shadow="md"
|
||||||
<TextInput
|
withBorder
|
||||||
label="Email"
|
maw={600}
|
||||||
placeholder="masukkan email"
|
w="100%"
|
||||||
onChange={(val) => {
|
>
|
||||||
stateKeberatan.create.form.email = val.target.value
|
<Stack gap="md">
|
||||||
}}
|
<Text
|
||||||
/>
|
fw={700}
|
||||||
<TextInput
|
fz={{ base: 'lg', md: 'xl' }}
|
||||||
label="Nomor Telepon"
|
ta="center"
|
||||||
placeholder="masukkan nomor telepon"
|
mb={4}
|
||||||
onChange={(val) => {
|
>
|
||||||
stateKeberatan.create.form.notelp = val.target.value
|
Formulir Keberatan
|
||||||
}}
|
</Text>
|
||||||
/>
|
|
||||||
<Text fz={"sm"}>Alasan Permohonan Keberatan</Text>
|
<TextInput
|
||||||
<PPIDTextEditor
|
label="Nama Lengkap"
|
||||||
showSubmit={false}
|
placeholder="Tulis nama lengkap Anda"
|
||||||
onChange={(val) => {
|
radius="md"
|
||||||
stateKeberatan.create.form.alasan = val
|
size="md"
|
||||||
}}
|
withAsterisk
|
||||||
|
onChange={(val) =>
|
||||||
/>
|
(stateKeberatan.create.form.name = val.target.value)
|
||||||
<Group>
|
}
|
||||||
<Button onClick={submit} bg={'green'}>Kirim Permohonan</Button>
|
/>
|
||||||
</Group>
|
|
||||||
</Stack>
|
<TextInput
|
||||||
</Paper>
|
label="Alamat Email"
|
||||||
</Group>
|
placeholder="contoh: nama@email.com"
|
||||||
<Text pt={20} ta={"center"} fz={'h3'} fw={"bold"}>Kontak PPID</Text>
|
radius="md"
|
||||||
<Text ta={"center"} fz={"sm"}>Email: desadarmasaba@badungkab.go.id | WhatsApp: 081-xxx-xxx-xxx</Text>
|
size="md"
|
||||||
</Paper>
|
type="email"
|
||||||
|
withAsterisk
|
||||||
|
onChange={(val) =>
|
||||||
|
(stateKeberatan.create.form.email = val.target.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
label="Nomor Telepon"
|
||||||
|
placeholder="contoh: 0812-3456-7890"
|
||||||
|
radius="md"
|
||||||
|
size="md"
|
||||||
|
withAsterisk
|
||||||
|
onChange={(val) =>
|
||||||
|
(stateKeberatan.create.form.notelp = val.target.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<Text fw={600} fz="sm" mb={6}>
|
||||||
|
Alasan Keberatan
|
||||||
|
</Text>
|
||||||
|
<PPIDTextEditor
|
||||||
|
showSubmit={false}
|
||||||
|
onChange={(val) =>
|
||||||
|
(stateKeberatan.create.form.alasan = val)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Tooltip label="Pastikan semua data sudah diisi dengan benar">
|
||||||
|
<Button
|
||||||
|
onClick={submit}
|
||||||
|
size="md"
|
||||||
|
radius="md"
|
||||||
|
fw={600}
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
>
|
||||||
|
Kirim Permohonan
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Paper>
|
||||||
</Stack>
|
</Group>
|
||||||
);
|
|
||||||
|
<Stack gap={4} pt="lg" align="center">
|
||||||
|
<Text fw={700} fz="lg">
|
||||||
|
Kontak PPID
|
||||||
|
</Text>
|
||||||
|
<Text fz="sm" c="dimmed">
|
||||||
|
Email: desadarmasaba@badungkab.go.id | WhatsApp: 081-xxx-xxx-xxx
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
|
|||||||
@@ -1,58 +1,100 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import stateVisiMisiPPID from '@/app/admin/(dashboard)/_state/ppid/visi_misi_ppid/visimisiPPID';
|
import stateVisiMisiPPID from '@/app/admin/(dashboard)/_state/ppid/visi_misi_ppid/visimisiPPID';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Center, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
import { Box, Center, Image, Paper, Skeleton, Stack, Text, Divider, Transition } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
import { IconSparkles } from '@tabler/icons-react';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const allList = useProxy(stateVisiMisiPPID)
|
const allList = useProxy(stateVisiMisiPPID);
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
allList.findById.load("1") // Assuming "1" is your default ID, adjust as needed
|
allList.findById.load("1");
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
if (!allList.findById.data) return <Stack>
|
if (!allList.findById.data) {
|
||||||
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
|
return (
|
||||||
</Stack>
|
<Stack p="xl" gap="sm">
|
||||||
|
{Array.from({ length: 6 }).map((_, k) => (
|
||||||
|
<Skeleton key={k} h={60} radius="lg" />
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const dataArray = Array.isArray(allList.findById.data)
|
const dataArray = Array.isArray(allList.findById.data)
|
||||||
? allList.findById.data
|
? allList.findById.data
|
||||||
: [allList.findById.data];
|
: [allList.findById.data];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
<Stack bg={colors.Bg} py="xl" gap={40}>
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{dataArray.map((item) => (
|
{dataArray.map((item) => (
|
||||||
<Box key={item.id} px={{ base: "md", md: 100 }}>
|
<Box key={item.id} px={{ base: 'md', md: 100 }}>
|
||||||
<Stack gap={'lg'}>
|
<Transition mounted={true} transition="fade" duration={500} timingFunction="ease">
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
{(styles) => (
|
||||||
<Box pb={30}>
|
<Paper
|
||||||
<Center>
|
style={styles}
|
||||||
<Image src={"/darmasaba-icon.png"} w={{ base: 100, md: 150 }} alt='' />
|
p={{ base: 'lg', md: 'xl' }}
|
||||||
</Center>
|
radius="2xl"
|
||||||
<Text ta={"center"} fz={{ base: "h2", md: "2.5rem" }} fw={"bold"}>
|
shadow="xl"
|
||||||
MOTO PPID DESA DARMASABA
|
bg={colors['white-trans-1']}
|
||||||
</Text>
|
withBorder
|
||||||
<Text ta={"center"} fz={{ base: "h4", md: "h3" }} >
|
>
|
||||||
MEMBERIKAN INFORMASI YANG CEPAT, MUDAH, TEPAT DAN TRANSPARAN
|
<Stack gap="xl">
|
||||||
</Text>
|
<Box>
|
||||||
</Box>
|
<Center mb="md">
|
||||||
<Box px={{ base: 20, md: 50 }} pb={30}>
|
<Image src="/darmasaba-icon.png" w={{ base: 80, md: 130 }} alt="Logo Desa Darmasaba" />
|
||||||
<Text ta={"center"} fz={{ base: "h3", md: "h2" }} fw={"bold"}>
|
</Center>
|
||||||
VISI PPID
|
<Text
|
||||||
</Text>
|
ta="center"
|
||||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: item.visi }} />
|
fz={{ base: 28, md: 36 }}
|
||||||
</Box>
|
fw={800}
|
||||||
<Box px={{ base: 20, md: 50 }}>
|
variant="gradient"
|
||||||
<Text ta={"center"} fz={{ base: "h3", md: "h2" }} fw={"bold"}>
|
gradient={{ from: colors['blue-button'], to: 'cyan', deg: 45 }}
|
||||||
MISI PPID
|
>
|
||||||
</Text>
|
Moto PPID Desa Darmasaba
|
||||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: item.misi }} />
|
</Text>
|
||||||
</Box>
|
<Text ta="center" fz={{ base: 16, md: 20 }} mt="xs" c="dimmed">
|
||||||
</Paper>
|
Memberikan informasi yang cepat, mudah, tepat, dan transparan
|
||||||
</Stack>
|
</Text>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Divider my="sm" labelPosition="center" label={<IconSparkles size={18} />} />
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<Text ta="center" fz={{ base: 24, md: 30 }} fw={700} mb="sm">
|
||||||
|
Visi PPID
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
fz={{ base: 'md', md: 'lg' }}
|
||||||
|
lh={1.7}
|
||||||
|
ta="justify"
|
||||||
|
dangerouslySetInnerHTML={{ __html: item.visi }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Divider my="sm" />
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<Text ta="center" fz={{ base: 24, md: 30 }} fw={700} mb="sm">
|
||||||
|
Misi PPID
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
fz={{ base: 'md', md: 'lg' }}
|
||||||
|
lh={1.7}
|
||||||
|
ta="justify"
|
||||||
|
dangerouslySetInnerHTML={{ __html: item.misi }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
)}
|
||||||
|
</Transition>
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,98 +1,102 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { Box, Center, Container, Image, LoadingOverlay, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
|
import { Box, Center, Container, Image, LoadingOverlay, Paper, SimpleGrid, Stack, Text, Title, Tooltip } from '@mantine/core';
|
||||||
import { Prisma } from '@prisma/client';
|
import { Prisma } from '@prisma/client';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import { IconMoodSad } from '@tabler/icons-react';
|
||||||
import BackButton from '../../(pages)/desa/layanan/_com/BackButto';
|
import BackButton from '../../(pages)/desa/layanan/_com/BackButto';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const [sdgsDesa, setSdgsDesa] = useState<Prisma.SDGSDesaGetPayload<{ include: { image: true } }>[]>([]);
|
const [sdgsDesa, setSdgsDesa] = useState<Prisma.SDGSDesaGetPayload<{ include: { image: true } }>[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
useEffect(() => {
|
|
||||||
const fetchSdgsDesa = async () => {
|
|
||||||
try {
|
|
||||||
const response = await fetch('/api/landingpage/sdgsdesa/findMany');
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
const result = await response.json();
|
|
||||||
// Ensure the data is an array before setting it
|
|
||||||
let data = [];
|
|
||||||
if (Array.isArray(result.data)) {
|
|
||||||
data = result.data;
|
|
||||||
} else if (Array.isArray(result)) {
|
|
||||||
// In case the API returns the array directly
|
|
||||||
data = result;
|
|
||||||
} else {
|
|
||||||
console.error('Invalid data format:', result);
|
|
||||||
}
|
|
||||||
setSdgsDesa(data);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching sdgs desa:', error);
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchSdgsDesa();
|
useEffect(() => {
|
||||||
}, []);
|
const fetchSdgsDesa = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/landingpage/sdgsdesa/findMany');
|
||||||
|
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
const result = await response.json();
|
||||||
|
let data = [];
|
||||||
|
if (Array.isArray(result.data)) {
|
||||||
|
data = result.data;
|
||||||
|
} else if (Array.isArray(result)) {
|
||||||
|
data = result;
|
||||||
|
} else {
|
||||||
|
console.error('Format data tidak valid:', result);
|
||||||
|
}
|
||||||
|
setSdgsDesa(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Gagal mengambil data sdgs desa:', error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchSdgsDesa();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} py={"xl"} gap={22}>
|
<Stack pos="relative" py="xl" gap={32}>
|
||||||
<Box px={{ base: "md", md: 100 }}><BackButton /></Box>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<Container w={{ base: "100%", md: "50%" }}>
|
<BackButton />
|
||||||
<Stack align="center" gap={0}>
|
</Box>
|
||||||
<Text fz={"3.4rem"} fw={"bold"}>
|
|
||||||
|
<Container w={{ base: '100%', md: '60%' }}>
|
||||||
|
<Stack align="center" gap="sm">
|
||||||
|
<Title order={1} fz={{ base: '2.4rem', md: '3.4rem' }} fw={800} ta="center" style={{ letterSpacing: '-0.02em' }}>
|
||||||
SDGs Desa
|
SDGs Desa
|
||||||
|
</Title>
|
||||||
|
<Text ta="center" c="dimmed" fz="lg">
|
||||||
|
Pembangunan berkelanjutan yang inklusif, adil, dan berdaya saing di tingkat desa
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Container>
|
</Container>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
|
||||||
<Text
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
py={10}
|
<Text py={10} ta="justify" fz="md" lh={1.7}>
|
||||||
ta={"justify"}
|
SDGs Desa adalah upaya terpadu pemerintah dalam percepatan pencapaian tujuan pembangunan berkelanjutan di tingkat desa.
|
||||||
>
|
Ini merupakan adaptasi dari SDGs global dalam konteks pembangunan desa di Indonesia, yang bertujuan menciptakan desa
|
||||||
SDGs Desa adalah upaya terpadu pemerintah dalam percepatan pencapaian tujuan pembangunan berkelanjutan di tingkat desa. Ini merupakan terjemahan dari SDGs global dalam konteks pembangunan desa di Indonesia. SDGs Desa bertujuan untuk menciptakan desa yang lebih inklusif, berkelanjutan, dan tangguh menghadapi tantangan masa depan. Adapun
|
inklusif, berkelanjutan, dan tangguh menghadapi tantangan masa depan.
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text ta="justify" pb={20} fz="md" lh={1.7}>
|
||||||
ta={"justify"}
|
Berdasarkan Permendesa Nomor 21 Tahun 2020, SDGs Desa mencakup 18 tujuan yang harus dicapai pada tahun 2030.
|
||||||
pb={20}
|
Tujuan-tujuan tersebut meliputi pengentasan kemiskinan, peningkatan kesehatan dan pendidikan, kesetaraan gender,
|
||||||
>
|
pertumbuhan ekonomi, pembangunan infrastruktur, hingga pelestarian lingkungan.
|
||||||
SDGs Desa sebagaimana dijabarkan dalam Permendesa Nomor 21 tahun 2020 terdiri dari 18 tujuan yang harus dicapai pada tahun 2030. Tujuan-tujuan tersebut mencakup berbagai aspek kehidupan masyarakat desa, mulai dari pengentasan kemiskinan, peningkatan kesehatan dan pendidikan, kesetaraan gender, pertumbuhan ekonomi, infrastruktur, hingga kelestarian lingkungan. Adapun SDGs Desa terdiri dari tujuan-tujuan sebagai berikut:
|
|
||||||
</Text>
|
</Text>
|
||||||
</Box >
|
</Box>
|
||||||
<Box py={20} px={{ base: "md", md: 100 }}>
|
|
||||||
|
<Box py={20} px={{ base: 'md', md: 100 }}>
|
||||||
<Box pos="relative" style={{ minHeight: 200 }}>
|
<Box pos="relative" style={{ minHeight: 200 }}>
|
||||||
<LoadingOverlay visible={loading} overlayProps={{ blur: 2 }} />
|
<LoadingOverlay visible={loading} overlayProps={{ blur: 2 }} />
|
||||||
{!loading && sdgsDesa.length > 0 ? (
|
{!loading && sdgsDesa.length > 0 ? (
|
||||||
<SimpleGrid
|
<SimpleGrid cols={{ base: 1, sm: 2, md: 3, lg: 4 }} spacing="xl" verticalSpacing="xl">
|
||||||
cols={{ base: 1, sm: 2, md: 3, lg: 4 }}
|
|
||||||
spacing="xl"
|
|
||||||
verticalSpacing="xl"
|
|
||||||
>
|
|
||||||
{sdgsDesa.map((item) => (
|
{sdgsDesa.map((item) => (
|
||||||
<Paper
|
<Paper
|
||||||
key={item.id}
|
key={item.id}
|
||||||
p="md"
|
p="lg"
|
||||||
radius="md"
|
radius="xl"
|
||||||
shadow="sm"
|
shadow="md"
|
||||||
|
withBorder
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
transition: 'transform 0.2s',
|
transition: 'all 0.25s ease',
|
||||||
'&:hover': {
|
}}
|
||||||
transform: 'translateY(-5px)',
|
onMouseEnter={(e) => {
|
||||||
boxShadow: '0 8px 16px rgba(0,0,0,0.1)'
|
(e.currentTarget.style.transform = 'translateY(-6px) scale(1.02)');
|
||||||
}
|
(e.currentTarget.style.boxShadow = '0 12px 24px rgba(0,0,0,0.08)');
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
(e.currentTarget.style.transform = 'translateY(0) scale(1)');
|
||||||
|
(e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.05)');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
p="md"
|
p="md"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: '#f8f9fa',
|
background: 'linear-gradient(145deg, #f8f9fa, #ffffff)',
|
||||||
borderRadius: '8px',
|
borderRadius: '12px',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
@@ -105,13 +109,23 @@ function Page() {
|
|||||||
width={120}
|
width={120}
|
||||||
height={120}
|
height={120}
|
||||||
fit="contain"
|
fit="contain"
|
||||||
|
style={{ filter: 'drop-shadow(0px 2px 6px rgba(0,0,0,0.1))' }}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Stack gap="xs" style={{ width: '100%' }}>
|
<Stack gap="xs" align="center" style={{ width: '100%' }}>
|
||||||
<Title order={4} ta="center" c={"dimmed"} fw={600} lineClamp={2} style={{ minHeight: '3rem' }}>
|
<Tooltip label={item.name} position="top" withArrow>
|
||||||
{item.name}
|
<Title order={4} ta="center" c="dark" fw={600} lineClamp={2} style={{ minHeight: '3rem' }}>
|
||||||
</Title>
|
{item.name}
|
||||||
<Text ta="center" fw={"bold"} c={colors['blue-button']} fz={"h2"} lineClamp={3} style={{ minHeight: '4.5rem' }}>
|
</Title>
|
||||||
|
</Tooltip>
|
||||||
|
<Text
|
||||||
|
ta="center"
|
||||||
|
fw={700}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
fz="2rem"
|
||||||
|
lineClamp={2}
|
||||||
|
style={{ minHeight: '4rem' }}
|
||||||
|
>
|
||||||
{item.jumlah}
|
{item.jumlah}
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -119,13 +133,16 @@ function Page() {
|
|||||||
))}
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
) : !loading ? (
|
) : !loading ? (
|
||||||
<Center style={{ minHeight: 200 }}>
|
<Center style={{ minHeight: 200, flexDirection: 'column', gap: '0.5rem' }}>
|
||||||
<Text>Tidak ada data SDGs Desa yang tersedia</Text>
|
<IconMoodSad size={42} stroke={1.5} color="var(--mantine-color-dimmed)" />
|
||||||
|
<Text c="dimmed" fz="lg" fw={500}>
|
||||||
|
Belum ada data SDGs Desa
|
||||||
|
</Text>
|
||||||
</Center>
|
</Center>
|
||||||
) : null}
|
) : null}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack >
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import { Box, Button, Center, Container, Image, Paper, SimpleGrid, Stack, Text, Title, useMantineTheme } from "@mantine/core"
|
import { Box, Button, Center, Container, Image, Paper, SimpleGrid, Stack, Text, Title, useMantineTheme, Tooltip } from "@mantine/core"
|
||||||
import { useMediaQuery } from "@mantine/hooks"
|
import { useMediaQuery } from "@mantine/hooks"
|
||||||
import { Prisma } from "@prisma/client"
|
import { Prisma } from "@prisma/client"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
@@ -37,24 +37,32 @@ export default function SDGS() {
|
|||||||
<Stack p="sm">
|
<Stack p="sm">
|
||||||
<Container w={{ base: "100%", md: "80%" }} p="xl">
|
<Container w={{ base: "100%", md: "80%" }} p="xl">
|
||||||
<Center>
|
<Center>
|
||||||
<Title order={1} fz={{ base: "2.2rem", md: "3.4rem" }} fw={900}>
|
<Title
|
||||||
|
order={1}
|
||||||
|
fz={{ base: "2.4rem", md: "3.6rem" }}
|
||||||
|
fw={900}
|
||||||
|
style={{
|
||||||
|
background: "linear-gradient(90deg, #1A5F7A, #159895)",
|
||||||
|
WebkitBackgroundClip: "text",
|
||||||
|
WebkitTextFillColor: "transparent",
|
||||||
|
}}
|
||||||
|
>
|
||||||
SDGs Desa
|
SDGs Desa
|
||||||
</Title>
|
</Title>
|
||||||
</Center>
|
</Center>
|
||||||
<Text fz={{ base: "1rem", md: "1.3rem" }} ta="center" c="dimmed" mt="md" maw={800} mx="auto">
|
<Text fz={{ base: "1rem", md: "1.2rem" }} ta="center" c="dimmed" mt="md" maw={820} mx="auto">
|
||||||
SDGs Desa adalah penerapan 17 Tujuan Pembangunan Berkelanjutan di tingkat desa. Fokus pada pengentasan kemiskinan,
|
SDGs Desa merupakan langkah nyata untuk mewujudkan desa yang maju, inklusif, dan berkelanjutan melalui 17 tujuan pembangunan: dari pengentasan kemiskinan, pendidikan, kesehatan, kesetaraan gender, hingga pelestarian lingkungan.
|
||||||
pendidikan, kesehatan, kesetaraan gender, dan pelestarian lingkungan untuk menciptakan desa yang maju, inklusif, dan berkelanjutan.
|
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Box py={50}>
|
<Box py={50}>
|
||||||
<Paper
|
<Paper
|
||||||
p={{ base: "md", md: "xl" }}
|
p={{ base: "md", md: "xl" }}
|
||||||
radius="xl"
|
radius="2xl"
|
||||||
withBorder
|
withBorder
|
||||||
shadow="lg"
|
shadow="lg"
|
||||||
style={{
|
style={{
|
||||||
background: "linear-gradient(145deg, #FAF6E9, #FFFDF6)",
|
background: "linear-gradient(145deg, #FFFFFF, #F9FAFB)",
|
||||||
border: "1px solid rgba(255,255,255,0.05)",
|
border: "1px solid rgba(0,0,0,0.06)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{sdgsDesa && sdgsDesa.length > 0 ? (
|
{sdgsDesa && sdgsDesa.length > 0 ? (
|
||||||
@@ -63,20 +71,20 @@ export default function SDGS() {
|
|||||||
<Paper
|
<Paper
|
||||||
key={item.id}
|
key={item.id}
|
||||||
p="lg"
|
p="lg"
|
||||||
radius="lg"
|
radius="xl"
|
||||||
shadow="sm"
|
shadow="sm"
|
||||||
|
withBorder
|
||||||
style={{
|
style={{
|
||||||
background: "linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0.02))",
|
background: "linear-gradient(180deg, #FFFFFF, #F6F8FA)",
|
||||||
border: "1px solid rgba(255,255,255,0.08)",
|
border: "1px solid rgba(0,0,0,0.05)",
|
||||||
transition: "all 0.3s ease",
|
transition: "all 0.3s ease",
|
||||||
}}
|
}}
|
||||||
withBorder
|
|
||||||
>
|
>
|
||||||
<Center mb="lg">
|
<Center mb="lg">
|
||||||
<Box
|
<Box
|
||||||
p="md"
|
p="md"
|
||||||
style={{
|
style={{
|
||||||
background: "rgba(255,255,255,0.06)",
|
background: "rgba(240, 249, 255, 0.8)",
|
||||||
backdropFilter: "blur(6px)",
|
backdropFilter: "blur(6px)",
|
||||||
width: mobile ? 140 : 160,
|
width: mobile ? 140 : 160,
|
||||||
height: mobile ? 140 : 160,
|
height: mobile ? 140 : 160,
|
||||||
@@ -84,6 +92,7 @@ export default function SDGS() {
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
borderRadius: "1rem",
|
borderRadius: "1rem",
|
||||||
|
boxShadow: "0 6px 16px rgba(0,0,0,0.06)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
@@ -95,16 +104,19 @@ export default function SDGS() {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Center>
|
</Center>
|
||||||
<Text ta="center" fz={{ base: "lg", md: "xl" }} fw={700} mb="xs">
|
<Tooltip label="Nama tujuan SDGs Desa" position="top" withArrow>
|
||||||
{item.name}
|
<Text ta="center" fz={{ base: "lg", md: "xl" }} fw={700} mb="xs">
|
||||||
</Text>
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
</Tooltip>
|
||||||
<Title
|
<Title
|
||||||
order={2}
|
order={2}
|
||||||
ta="center"
|
ta="center"
|
||||||
style={{
|
style={{
|
||||||
fontSize: mobile ? "2.3rem" : "3rem",
|
fontSize: mobile ? "2.4rem" : "3.2rem",
|
||||||
fontWeight: 900,
|
fontWeight: 900,
|
||||||
letterSpacing: "-1px",
|
letterSpacing: "-0.5px",
|
||||||
|
color: "#124170",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item.jumlah}
|
{item.jumlah}
|
||||||
@@ -116,7 +128,7 @@ export default function SDGS() {
|
|||||||
<Center mih={200} style={{ flexDirection: "column" }}>
|
<Center mih={200} style={{ flexDirection: "column" }}>
|
||||||
<IconMoodSad size={48} stroke={1.5} style={{ marginBottom: "1rem" }} />
|
<IconMoodSad size={48} stroke={1.5} style={{ marginBottom: "1rem" }} />
|
||||||
<Text fz="lg" c="dimmed">
|
<Text fz="lg" c="dimmed">
|
||||||
Belum ada data SDGs Desa
|
Data SDGs Desa belum tersedia
|
||||||
</Text>
|
</Text>
|
||||||
</Center>
|
</Center>
|
||||||
)}
|
)}
|
||||||
@@ -128,11 +140,12 @@ export default function SDGS() {
|
|||||||
href="/darmasaba/sdgs-desa"
|
href="/darmasaba/sdgs-desa"
|
||||||
radius="xl"
|
radius="xl"
|
||||||
size="lg"
|
size="lg"
|
||||||
mt={30}
|
mt={40}
|
||||||
variant="gradient"
|
variant="gradient"
|
||||||
gradient={{ from: "#26667F", to: "#124170" }}
|
gradient={{ from: "#26667F", to: "#124170" }}
|
||||||
|
style={{ boxShadow: "0 6px 14px rgba(18,65,112,0.25)" }}
|
||||||
>
|
>
|
||||||
Lihat Semua SDGs Desa
|
Jelajahi Semua Tujuan SDGs Desa
|
||||||
</Button>
|
</Button>
|
||||||
</Center>
|
</Center>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
Reference in New Issue
Block a user