Fix QC Kak Inno 24 Okt 25

Fix QC Kak Ayu 24 Okt 25
Fix QC Keano 24 Okt 25
Fix Detail Lowongan Kerja
This commit is contained in:
2025-10-27 22:15:55 +08:00
parent f82c7b86e0
commit ed371bd0d9
37 changed files with 751 additions and 710 deletions

View File

@@ -47,13 +47,13 @@ function PelayananSuratKeterangan({ search }: { search: string }) {
<Box pb="xl">
<Group justify="space-between" align="center" mb="md">
<Group gap="xs">
<IconFileDescription size={28} stroke={1.8} color={colors["blue-button"]} />
<IconFileDescription size={28} stroke={1.8} />
<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"]} />
<IconInfoCircle size={22} stroke={1.8} />
</Tooltip>
</Group>

View File

@@ -43,7 +43,7 @@ function Page() {
<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">
<Text fz="lg" ta="justify">
Temukan berbagai potensi unggulan, peluang, dan daya tarik yang menjadikan Desa Darmasaba istimewa.
</Text>
</Stack>

View File

@@ -2,7 +2,7 @@
'use client'
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile'
import colors from '@/con/colors'
import { Box, Center, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core'
import { Box, Center, Image, Paper, Skeleton, Stack, Text } from '@mantine/core'
import { useEffect } from 'react'
import { useProxy } from 'valtio/utils'
@@ -58,7 +58,6 @@ function LambangDesa() {
borderColor: '#e0e9ff',
}}
>
<Tooltip label="Deskripsi lambang desa" position="top-start" withArrow>
<Text
fz={{ base: 'md', md: 'lg' }}
lh={1.8}
@@ -67,7 +66,6 @@ function LambangDesa() {
style={{ fontWeight: 400, wordBreak: "break-word", whiteSpace: "normal", }}
dangerouslySetInnerHTML={{ __html: data.deskripsi }}
/>
</Tooltip>
</Paper>
</Stack>
</Box>

View File

@@ -1,11 +1,11 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
import { Box, Card, Center, Group, Image, Loader, Paper, Stack, Text, Tooltip } from '@mantine/core';
import colors from '@/con/colors';
import { Box, Card, Center, Group, Image, Loader, Paper, Stack, Text } from '@mantine/core';
import { IconPhoto } from '@tabler/icons-react';
import { useEffect } from 'react';
import { useProxy } from 'valtio/utils';
import { IconPhoto } from '@tabler/icons-react';
import colors from '@/con/colors';
function MaskotDesa() {
const state = useProxy(stateProfileDesa.maskotDesa);
@@ -54,8 +54,8 @@ function MaskotDesa() {
<Group justify="center" gap="lg" mt="lg">
{data.images.length > 0 ? (
data.images.map((img, index) => (
<Tooltip key={index} label={img.label} position="bottom" withArrow>
<Card
key={index}
radius="lg"
shadow="md"
withBorder
@@ -79,7 +79,6 @@ function MaskotDesa() {
{img.label}
</Text>
</Card>
</Tooltip>
))
) : (
<Stack align="center" gap="xs" mt="lg">

View File

@@ -2,10 +2,10 @@
'use client'
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
import colors from '@/con/colors';
import { Box, Image, Paper, SimpleGrid, Skeleton, Stack, Text, Divider, Tooltip } from '@mantine/core';
import { Box, Divider, Image, Paper, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
import { IconBriefcase, IconTargetArrow, IconUser, IconUsers } from '@tabler/icons-react';
import { useEffect } from 'react';
import { useProxy } from 'valtio/utils';
import { IconUser, IconBriefcase, IconUsers, IconTargetArrow } from '@tabler/icons-react';
function ProfilPerbekel() {
const state = useProxy(stateProfileDesa.profilPerbekel)
@@ -27,10 +27,10 @@ function ProfilPerbekel() {
return (
<Box pb={80} px="md">
<Stack align="center" gap={0} mb={40}>
<Text
c={colors['blue-button']}
ta="center"
fw="bold"
<Text
c={colors['blue-button']}
ta="center"
fw="bold"
fz={{ base: "2rem", md: "2.8rem" }}
style={{ letterSpacing: "0.5px" }}
>
@@ -41,11 +41,11 @@ function ProfilPerbekel() {
<SimpleGrid cols={{ base: 1, md: 2 }} spacing="xl" pb={50}>
<Box>
<Paper
bg={colors['white-trans-1']}
w="100%"
radius="xl"
shadow="md"
<Paper
bg={colors['white-trans-1']}
w="100%"
radius="xl"
shadow="md"
withBorder
>
<Stack gap={0}>
@@ -70,9 +70,9 @@ function ProfilPerbekel() {
<Text c={colors['white-1']} fz={{ base: "lg", md: "h3" }}>
Perbekel Desa Darmasaba
</Text>
<Text
c={colors['white-1']}
fw="bolder"
<Text
c={colors['white-1']}
fw="bolder"
fz={{ base: "xl", md: "h2" }}
mt={8}
>
@@ -83,60 +83,56 @@ function ProfilPerbekel() {
</Paper>
</Box>
<Paper
p="xl"
bg={colors['white-trans-1']}
w="100%"
radius="xl"
shadow="md"
<Paper
p="xl"
bg={colors['white-trans-1']}
w="100%"
radius="xl"
shadow="md"
withBorder
>
<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 }}
style={{wordBreak: "break-word", whiteSpace: "normal"}}
/>
<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>
</Tooltip>
<Text
fz={{ base: "1rem", md: "1.2rem" }}
ta="justify"
lh={1.6}
dangerouslySetInnerHTML={{ __html: data.biodata }}
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
/>
</Stack>
</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 }}
style={{wordBreak: "break-word", whiteSpace: "normal"}}
/>
<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>
</Tooltip>
<Text
fz={{ base: "1rem", md: "1.2rem" }}
ta="justify"
lh={1.6}
dangerouslySetInnerHTML={{ __html: data.pengalaman }}
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
/>
</Stack>
</Box>
</Stack>
</Paper>
</SimpleGrid>
<Paper
p="xl"
bg={colors['white-trans-1']}
w="100%"
radius="xl"
shadow="md"
<Paper
p="xl"
bg={colors['white-trans-1']}
w="100%"
radius="xl"
shadow="md"
withBorder
>
<Stack gap="xl">
@@ -145,27 +141,27 @@ function ProfilPerbekel() {
<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"
<Text
fz={{ base: "1rem", md: "1.2rem" }}
ta="justify"
lh={1.6}
dangerouslySetInnerHTML={{ __html: data.pengalamanOrganisasi }}
style={{wordBreak: "break-word", whiteSpace: "normal"}}
dangerouslySetInnerHTML={{ __html: data.pengalamanOrganisasi }}
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
/>
</Box>
<Box>
<Stack align="center" gap={6} mb={6}>
<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"
<Text
fz={{ base: "1rem", md: "1.2rem" }}
ta="justify"
lh={1.6}
dangerouslySetInnerHTML={{ __html: data.programUnggulan }}
style={{wordBreak: "break-word", whiteSpace: "normal"}}
dangerouslySetInnerHTML={{ __html: data.programUnggulan }}
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
/>
</Box>
</Box>

View File

@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
'use client'
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
import { Box, Center, Image, Paper, SimpleGrid, Skeleton, Stack, Text, Title, Tooltip } from '@mantine/core';
import { Box, Center, Image, Paper, SimpleGrid, Skeleton, Stack, Text, Title } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconUser } from '@tabler/icons-react';
import { useProxy } from 'valtio/utils';
@@ -77,23 +77,17 @@ function SemuaPerbekel() {
</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">
<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">
<Text c="blue" fw={600} fz="sm" ta="center">
{v.periode}
</Text>
</Tooltip>
</Stack>
</Stack>
</Paper>

View File

@@ -0,0 +1,136 @@
'use client'
import lowonganKerjaState from '@/app/admin/(dashboard)/_state/ekonomi/lowongan-kerja';
import colors from '@/con/colors';
import { Box, Button, Center, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconBrandWhatsapp, IconBriefcase, IconCurrencyDollar, IconMapPin, IconPhone } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
function DetailLowonganKerjaUser() {
const state = useProxy(lowonganKerjaState);
const router = useRouter();
const params = useParams();
const [loading, setLoading] = useState(true);
useShallowEffect(() => {
const loadData = async () => {
await state.findUnique.load(params?.id as string);
setLoading(false);
};
loadData();
}, []);
const data = state.findUnique.data;
if (loading || !data) {
return (
<Center py="xl">
<Skeleton height={500} w={{ base: '90%', md: '70%' }} radius="lg" />
</Center>
);
}
return (
<Stack bg={colors.Bg} py="xl" px={{ base: 'md', md: 100 }} align="center">
<Box w={{ base: '100%', md: '70%' }}>
<Button
variant="subtle"
color="blue"
leftSection={<IconArrowBack size={20} />}
mb="md"
onClick={() => router.back()}
>
Kembali
</Button>
<Paper
radius="lg"
shadow="md"
withBorder
p="xl"
bg={colors['white-1']}
>
<Stack gap="lg">
{/* Judul */}
<Text fz={{ base: '1.6rem', md: '2rem' }} fw={700} c={colors['blue-button']}>
{data.posisi}
</Text>
<Text c="dimmed" fz="sm">
Diposting: {new Date(data.createdAt).toLocaleDateString('id-ID', {
day: '2-digit',
month: 'long',
year: 'numeric'
})}
</Text>
{/* Info Ringkas */}
<Stack gap="sm" mt="md">
<Group gap="xs">
<IconBriefcase size={20} color={colors['blue-button']} />
<Text fz="md" fw={600}>{data.namaPerusahaan}</Text>
</Group>
<Group gap="xs">
<IconMapPin size={20} color={colors['blue-button']} />
<Text fz="md">{data.lokasi}</Text>
</Group>
<Group gap="xs">
<IconPhone size={20} color={colors['blue-button']} />
<Text fz="md">{data.notelp}</Text>
</Group>
<Group gap="xs">
<IconCurrencyDollar size={20} color={colors['blue-button']} />
<Text fz="md">{data.gaji || '-'}</Text>
</Group>
<Group gap="xs">
<IconBriefcase size={20} color={colors['blue-button']} />
<Text fz="md">{data.tipePekerjaan}</Text>
</Group>
</Stack>
<Box>
<Text fw={600} fz="lg" mb={4}>
Deskripsi Pekerjaan
</Text>
<Text
fz="sm"
lh={1.6}
style={{ wordBreak: 'break-word' }}
dangerouslySetInnerHTML={{ __html: data.deskripsi || '-' }}
/>
</Box>
<Box>
<Text fw={600} fz="lg" mb={4}>
Kualifikasi
</Text>
<Text
fz="sm"
lh={1.6}
style={{ wordBreak: 'break-word' }}
dangerouslySetInnerHTML={{ __html: data.kualifikasi || '-' }}
/>
</Box>
<Center>
<Button
radius="md"
size="md"
mt="md"
bg={colors['blue-button']}
onClick={() => window.open(`https://wa.me/${data.notelp}`, '_blank')}
leftSection={<IconBrandWhatsapp size={20} />}
>
Hubungi Sekarang
</Button>
</Center>
</Stack>
</Paper>
</Box>
</Stack>
);
}
export default DetailLowonganKerjaUser;

View File

@@ -12,13 +12,13 @@ import BackButton from '../../desa/layanan/_com/BackButto';
const formatCurrency = (value: string | number) => {
// Convert to string if it's a number
const numStr = typeof value === 'number' ? value.toString() : value;
// Remove all non-digit characters
const digitsOnly = numStr.replace(/\D/g, '');
// Format with thousand separators
const formatted = digitsOnly.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
return `Rp.${formatted}`;
};
@@ -103,7 +103,7 @@ function Page() {
</Box>
</Flex>
</Box>
<Button onClick={() => router.push(`https://wa.me/${v.notelp?.replace(/\D/g, '')}`)}>Lamar Sekarang</Button>
<Button onClick={() => router.push(`/darmasaba/ekonomi/lowongan-kerja-lokal/${v.id}`)}>Detail</Button>
</Stack>
</Paper>
)

View File

@@ -30,6 +30,7 @@ function DetailProdukPasarUser() {
return (
<Box py={20}>
{/* Tombol kembali */}
<Box px={{ base: 'md', md: 100 }}>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -38,6 +39,7 @@ function DetailProdukPasarUser() {
>
Kembali ke daftar produk
</Button>
</Box>
<Paper
w={{ base: '100%', md: '70%' }}
@@ -54,7 +56,7 @@ function DetailProdukPasarUser() {
src={data.image.link}
alt={data.nama}
radius="md"
h={300}
h={250}
w="100%"
fit="cover"
loading="lazy"

View File

@@ -71,8 +71,11 @@ function Page() {
/>
</GridCol>
</Grid>
<Text px={{ base: 'md', md: 100 }} ta={"justify"} fz={{ base: "h4", md: "h3" }} >
Pasar Desa Online merupakan Media Promosi yang bertujuan untuk membantu warga desa dalam memasarkan dan memperkenalkan produknya kepada masyarakat.
<Text px={{ base: 'md', md: 100 }} ta={"justify"} fz="md" >
Pasar Desa Online adalah media promosi untuk membantu warga memasarkan
</Text>
<Text px={{ base: 'md', md: 100 }} ta={"justify"} fz="md" >
dan memperkenalkan produk mereka.
</Text>
</Box>
<Box px={{ base: "md", md: 100 }}>

View File

@@ -56,7 +56,8 @@ function Page() {
/>
</GridCol>
</Grid>
<Text fz={'h4'}>Mewujudkan Desa Darmasaba sebagai pusat inovasi digital yang memberdayakan masyarakat, meningkatkan kesejahteraan, dan menciptakan peluang ekonomi berbasis teknologi.</Text>
<Text fz={'md'}>Menjadikan Desa Darmasaba pusat inovasi digital untuk pemberdayaan masyarakat</Text>
<Text fz={'md'}>dan peningkatan ekonomi berbasis teknologi.</Text>
</Box>
<Box px={{ base: "md", md: 100 }}>
<Stack gap={'lg'} justify='center'>

View File

@@ -64,8 +64,8 @@ function Page() {
/>
</GridCol>
</Grid>
<Text px={{ base: 'md', md: 100 }} ta={"justify"} fz={{ base: "h4", md: "h3" }} >
Keamanan dan ketertiban lingkungan di Desa Darmasaba dijaga melalui peran aktif Pecalang dan Patwal (Patroli Pengawal). Mereka bertugas memastikan desa tetap aman, tertib, dan kondusif bagi seluruh warga.
<Text px={{ base: 'md', md: 100 }} ta={"justify"} fz="md" mt={4} >
Pecalang dan Patwal (Patroli Pengawal) bertugas memastikan desa tetap aman, tertib, dan kondusif bagi seluruh warga.
</Text>
</Box>
<Box px={{ base: "md", md: 100 }}>

View File

@@ -45,7 +45,7 @@ function DetailPencegahanKriminalitas() {
const data = kriminalitasState.findUnique.data;
return (
<Box py="md" px="md">
<Box py="md" px={{ base: 'md', md: 100 }}>
<Group mb="md">
<Button
variant="light"

View File

@@ -48,7 +48,7 @@ function Page() {
<Text fz={{ base: 'h1', md: '2.5rem' }} c={colors['blue-button']} fw="bold">
Pencegahan Kriminalitas
</Text>
<Text c={colors['blue-button']} fz={{ base: 'h4', md: 'h3' }}>
<Text fz='md'>
Keamanan Komunitas & Pencegahan Kriminal
</Text>
</Box>
@@ -78,7 +78,7 @@ function Page() {
<Text fz={{ base: 'h1', md: '2.5rem' }} c={colors['blue-button']} fw="bold">
Pencegahan Kriminalitas
</Text>
<Text c={colors['blue-button']} fz={{ base: 'h4', md: 'h3' }}>
<Text fz='md'>
Keamanan Komunitas & Pencegahan Kriminal
</Text>
</Box>
@@ -92,31 +92,63 @@ function Page() {
Program Keamanan Berjalan
</Text>
<Stack pt={30} gap="lg">
{data.length > 0 ? (
data.map((item) => (
<a key={item.id} href={`/darmasaba/keamanan/pencegahan-kriminalitas/${item.id}`}>
<Paper p="md" bg={colors['blue-button']} radius="md" shadow="sm">
<Stack gap={"xs"}>
<Box
style={{
minHeight: 300, // sesuaikan: tinggi area yg muat 3 item
}}
>
{data.length > 0 ? (
data.map((item) => (
<Paper
key={item.id}
p="md"
radius="md"
shadow="sm"
style={{
cursor: 'pointer',
backgroundColor: colors['blue-button'],
transition: 'all 0.2s ease',
}}
onClick={() =>
router.push(`/darmasaba/keamanan/pencegahan-kriminalitas/${item.id}`)
}
onMouseEnter={(e) =>
(e.currentTarget.style.backgroundColor = '#1a3e7a')
}
onMouseLeave={(e) =>
(e.currentTarget.style.backgroundColor = colors['blue-button'])
}
>
<Stack gap="xs">
<Text fz="h3" c={colors['white-1']}>
{item.judul}
</Text>
</Stack>
</Paper>
</a>
))
) : (
<Text color="dimmed">
Tidak ada data pencegahan kriminalitas yang cocok
</Text>
)}
))
) : (
<Text c="dimmed">Tidak ada data pencegahan kriminalitas yang cocok</Text>
)}
</Box>
<Button
mt={20}
fullWidth
radius="xl"
size="md"
bg={colors['blue-button']}
rightSection={<IconArrowRight size={20} color={colors['white-1']} />}
onClick={() => router.push(`/darmasaba/keamanan/pencegahan-kriminalitas/program-lainnya`)}
variant="outline"
color="blue"
rightSection={<IconArrowRight size={20} />}
styles={{
root: {
fontWeight: 600,
borderWidth: 2,
},
}}
onClick={() =>
router.push(
`/darmasaba/keamanan/pencegahan-kriminalitas/program-lainnya`
)
}
>
Jelajahi Program Lainnya
</Button>
@@ -142,9 +174,7 @@ function Page() {
<Text py={10} fz={{ base: 'h3', md: 'h2' }} fw="bold" c={colors['blue-button']}>
{findFirst.data?.judul}
</Text>
<Text fz="h4" c={colors['blue-button']}>
{findFirst.data?.deskripsiSingkat}
</Text>
<Text fz="h4" dangerouslySetInnerHTML={{ __html: findFirst.data?.deskripsiSingkat }} />
</Paper>
) : null}
</Box>

View File

@@ -21,12 +21,23 @@ import pencegahanKriminalitasState from '@/app/admin/(dashboard)/_state/keamanan
import { useShallowEffect } from '@mantine/hooks';
import { useState } from 'react';
import HeaderSearch from '@/app/admin/(dashboard)/_com/header';
import { IconArrowLeft } from '@tabler/icons-react';
function PencegahanKriminalitas() {
const [search, setSearch] = useState("");
const router = useRouter();
return (
<Box>
<Box pt={20} px={{ base: 'md', md: 100 }}>
<Group mb="md">
<Button
variant="light"
color="blue"
onClick={() => router.back()}
leftSection={<IconArrowLeft size={20} />}
>
Kembali
</Button>
</Group>
<HeaderSearch
title="Program Pencegahan Kriminalitas"
placeholder="Cari program atau deskripsi..."
@@ -82,7 +93,7 @@ function ListPencegahanKriminalitas({ search }: { search: string }) {
c="dimmed"
lineClamp={2}
dangerouslySetInnerHTML={{ __html: item.deskripsiSingkat || '' }}
style={{wordBreak: "break-word", whiteSpace: "normal"}}
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
/>
<Group justify="flex-end" mt="sm">
<Tooltip label="Lihat detail program" withArrow>

View File

@@ -43,7 +43,7 @@ function Page() {
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
Kantor Polisi Terdekat
</Text>
<Text pb={15} fz={'h4'} >
<Text pb={15} fz={'md'} >
Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung
</Text>
</Box>

View File

@@ -78,9 +78,7 @@ function Page() {
<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>
<Text fz="md" lh={1.6} ta="justify" dangerouslySetInnerHTML={{ __html: state.findUnique.data.introduction?.content }} />
</Box>
<Box>

View File

@@ -1,7 +1,7 @@
'use client'
import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
import colors from '@/con/colors';
import { Anchor, Box, Card, Divider, Group, Image, Loader, Paper, Stack, Text, Title, Tooltip } from '@mantine/core';
import { Box, Button, Card, Divider, Group, Image, Loader, Paper, Stack, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconCalendar, IconChevronRight } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -28,9 +28,9 @@ function ArtikelKesehatanPage() {
<Box>
<Paper p="xl" bg={colors['white-trans-1']} radius="xl" shadow="md">
<Stack gap="lg">
<Title order={2} ta="center" c={colors['blue-button']}>
<Text ta="center" fw={700} fz="32px" c={colors['blue-button']}>
Artikel Kesehatan
</Title>
</Text>
<Divider size="sm" color={colors['blue-button']} />
{state.findMany.data.length === 0 ? (
<Box py="xl" ta="center">
@@ -51,7 +51,7 @@ function ArtikelKesehatanPage() {
onMouseLeave={(e) => (e.currentTarget.style.transform = 'translateY(0)')}
>
<Card.Section>
<Image src={item.image?.link} alt={item.title} height={200} fit="cover" loading="lazy"/>
<Image style={{ borderTopLeftRadius: '10px', borderTopRightRadius: '10px' }} src={item.image?.link} alt={item.title} height={200} fit="cover" loading="lazy" />
</Card.Section>
<Stack gap="xs" mt="md">
<Text fw="bold" fz="xl" c="dark">{item.title}</Text>
@@ -64,18 +64,17 @@ function ArtikelKesehatanPage() {
<Text fz="md" c="dark" lineClamp={3}>
{item.content}
</Text>
<Tooltip label="Baca artikel lengkap">
<Anchor
<Group justify="flex-start">
<Button
bg={colors['blue-button']}
radius="lg"
size="sm"
rightSection={<IconChevronRight size={18} />}
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>
Baca Selengkapnya
</Button>
</Group>
</Stack>
</Card>
))

View File

@@ -1,11 +1,11 @@
'use client'
import fasilitasKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import colors from '@/con/colors';
import { Anchor, Badge, Box, Card, Divider, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { Badge, Box, Button, Card, Divider, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconChevronRight, IconClock, IconMapPin } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useProxy } from 'valtio/utils';
import { IconMapPin, IconClock, IconArrowRight } from '@tabler/icons-react';
function FasilitasKesehatanPage() {
const state = useProxy(fasilitasKesehatanState.fasilitasKesehatan);
@@ -36,72 +36,73 @@ function FasilitasKesehatanPage() {
</Text>
<Divider size="sm" color={colors['blue-button']} />
<Stack gap="lg">
{state.findMany.data.length === 0 ? (
<Box py="xl" ta="center">
<Text fz="lg" c="dimmed">
Belum ada fasilitas kesehatan yang tersedia
</Text>
</Box>
) : (
state.findMany.data.map((item) => (
<Card
key={item.id}
withBorder
radius="xl"
shadow="sm"
p="lg"
style={{
background: 'linear-gradient(135deg, #fdfdfd, #f7faff)',
transition: 'transform 0.2s ease, box-shadow 0.2s ease',
}}
onMouseEnter={(e) => {
(e.currentTarget as HTMLElement).style.transform = 'translateY(-4px)';
(e.currentTarget as HTMLElement).style.boxShadow = '0 8px 20px rgba(0,0,0,0.08)';
}}
onMouseLeave={(e) => {
(e.currentTarget as HTMLElement).style.transform = 'translateY(0px)';
(e.currentTarget as HTMLElement).style.boxShadow = '0 4px 12px rgba(0,0,0,0.05)';
}}
>
<Stack gap="sm">
<Group justify="space-between" align="center">
<Text fw={700} fz="lg" c={colors['blue-button']}>
{item.name}
</Text>
<Badge color="blue" radius="sm" variant="light" fz="xs">
Aktif
</Badge>
</Group>
<Group gap="xs">
<IconMapPin size={18} stroke={1.5} color={colors['blue-button']} />
<Text fz="sm" c="dimmed">
{item.informasiumum.alamat}
</Text>
</Group>
<Group gap="xs">
<IconClock size={18} stroke={1.5} color={colors['blue-button']} />
<Text fz="sm" c="dimmed">
{item.informasiumum.jamOperasional}
</Text>
</Group>
<Anchor
onClick={() =>
router.push(
`/darmasaba/kesehatan/data-kesehatan-warga/fasilitas-kesehatan-page/${item.id}`
)
}
c={colors['blue-button']}
fz="sm"
fw={600}
style={{ display: 'inline-flex', alignItems: 'center', gap: '4px' }}
>
Lihat Detail
<IconArrowRight size={16} stroke={1.5} />
</Anchor>
</Stack>
</Card>
))
)}
{state.findMany.data.length === 0 ? (
<Box py="xl" ta="center">
<Text fz="lg" c="dimmed">
Belum ada fasilitas kesehatan yang tersedia
</Text>
</Box>
) : (
state.findMany.data.map((item) => (
<Card
key={item.id}
withBorder
radius="xl"
shadow="sm"
p="lg"
style={{
background: 'linear-gradient(135deg, #fdfdfd, #f7faff)',
transition: 'transform 0.2s ease, box-shadow 0.2s ease',
}}
onMouseEnter={(e) => {
(e.currentTarget as HTMLElement).style.transform = 'translateY(-4px)';
(e.currentTarget as HTMLElement).style.boxShadow = '0 8px 20px rgba(0,0,0,0.08)';
}}
onMouseLeave={(e) => {
(e.currentTarget as HTMLElement).style.transform = 'translateY(0px)';
(e.currentTarget as HTMLElement).style.boxShadow = '0 4px 12px rgba(0,0,0,0.05)';
}}
>
<Stack gap="sm">
<Group justify="space-between" align="center">
<Text fw={700} fz="lg" c={colors['blue-button']}>
{item.name}
</Text>
<Badge color="blue" radius="sm" variant="light" fz="xs">
Aktif
</Badge>
</Group>
<Group gap="xs">
<IconMapPin size={18} stroke={1.5} color={colors['blue-button']} />
<Text fz="sm" c="dimmed">
{item.informasiumum.alamat}
</Text>
</Group>
<Group gap="xs">
<IconClock size={18} stroke={1.5} color={colors['blue-button']} />
<Text fz="sm" c="dimmed">
{item.informasiumum.jamOperasional}
</Text>
</Group>
<Group justify="flex-start">
<Button
bg={colors['blue-button']}
radius="lg"
size="sm"
rightSection={<IconChevronRight size={18} />}
onClick={() =>
router.push(
`/darmasaba/kesehatan/data-kesehatan-warga/fasilitas-kesehatan-page/${item.id}`
)
}
>
Lihat Detail
</Button>
</Group>
</Stack>
</Card>
))
)}
</Stack>
</Stack>
</Paper>

View File

@@ -73,9 +73,9 @@ function JadwalKegiatanPage() {
<Divider my="sm" />
<Group justify="flex-end">
<Group justify="flex-start">
<Button
variant="light"
bg={colors['blue-button']}
radius="lg"
size="sm"
rightSection={<IconChevronRight size={18} />}
@@ -84,14 +84,6 @@ function JadwalKegiatanPage() {
`/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>

View File

@@ -28,16 +28,18 @@ function DetailInfoWabahPenyakitUser() {
const data = state.findUnique.data;
return (
<Box py={10}>
<Box py={10} px={{ base: 'md', md: 100 }}>
{/* Tombol Back */}
<Button
variant="subtle"
onClick={() => router.back()}
leftSection={<IconArrowBack size={22} color={colors['blue-button']} />}
mb={15}
>
Kembali
</Button>
<Box>
<Button
variant="subtle"
onClick={() => router.back()}
leftSection={<IconArrowBack size={22} color={colors['blue-button']} />}
mb={15}
>
Kembali
</Button>
</Box>
{/* Wrapper Detail */}
<Paper

View File

@@ -61,7 +61,7 @@ function Page() {
>
Informasi Wabah & Penyakit
</Text>
<Text fz="md" c="dimmed" mt={4}>
<Text fz="md" mt={4}>
Dapatkan informasi terbaru mengenai wabah dan penyakit yang sedang
diawasi.
</Text>
@@ -84,7 +84,7 @@ function Page() {
<Center py="6xl">
<Stack align="center" gap="sm">
<IconInfoCircle size={50} color={colors['blue-button']} />
<Text fz="lg" fw={500} c="dimmed">
<Text fz="lg" fw={500} >
Tidak ada data yang cocok dengan pencarian Anda.
</Text>
</Stack>
@@ -101,17 +101,35 @@ function Page() {
bg={colors['white-trans-1']}
style={{
transition: 'transform 200ms ease, box-shadow 200ms ease',
display: 'flex',
flexDirection: 'column',
}}
>
<Stack gap="sm">
<Image
radius="md"
<Stack gap="sm" style={{ flex: 1 }}>
{/* Gambar */}
<Box
h={180}
src={v.image.link}
alt={v.name}
fit="cover"
loading="lazy"
/>
w="100%"
style={{
overflow: 'hidden',
borderRadius: '8px',
}}
>
<Image
src={v.image?.link}
alt={v.name}
fit="cover"
w="100%"
h="100%"
style={{
objectFit: 'cover',
objectPosition: 'center',
}}
loading="lazy"
/>
</Box>
{/* Judul dan badge */}
<Group justify="space-between" mt="sm">
<Text fw={700} fz="lg" c={colors['blue-button']}>
{v.name}
@@ -120,23 +138,46 @@ function Page() {
Wabah
</Badge>
</Group>
<Text fz="sm" c="dimmed">
Diposting: {new Date(v.createdAt).toLocaleDateString('id-ID', {
Diposting:{' '}
{new Date(v.createdAt).toLocaleDateString('id-ID', {
day: '2-digit',
month: 'long',
year: 'numeric',
})}
</Text>
<Divider />
<Text fz="sm" lh={1.5} lineClamp={3} truncate="end" dangerouslySetInnerHTML={{ __html: v.deskripsiSingkat }} />
<Button variant="light" radius="md" size="md" onClick={() => router.push(`/darmasaba/kesehatan/info-wabah-penyakit/${v.id}`)}>
Selengkapnya
</Button>
{/* Bagian deskripsi dan tombol */}
<Box style={{ display: 'flex', flexDirection: 'column', flexGrow: 1 }}>
<Text
fz="sm"
lh={1.5}
lineClamp={3}
dangerouslySetInnerHTML={{ __html: v.deskripsiSingkat }}
style={{ flexGrow: 1 }}
/>
<Button
variant="light"
radius="md"
size="md"
mt="md"
onClick={() =>
router.push(`/darmasaba/kesehatan/info-wabah-penyakit/${v.id}`)
}
>
Selengkapnya
</Button>
</Box>
</Stack>
</Paper>
))}
</SimpleGrid>
)}
</Box>

View File

@@ -0,0 +1,86 @@
'use client';
import penangananDarurat from '@/app/admin/(dashboard)/_state/kesehatan/penanganan-darurat/penangananDarurat';
import colors from '@/con/colors';
import { Box, Button, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useProxy } from 'valtio/utils';
function DetailPenangananDaruratUser() {
const state = useProxy(penangananDarurat);
const router = useRouter();
const params = useParams();
useShallowEffect(() => {
state.findUnique.load(params?.id as string);
}, []);
if (!state.findUnique.data) {
return (
<Stack py={40}>
<Skeleton height={400} radius="md" />
<Skeleton height={20} width="80%" radius="md" />
<Skeleton height={20} width="60%" radius="md" />
</Stack>
);
}
const data = state.findUnique.data;
return (
<Box py={20}>
{/* Tombol Back */}
<Box px={{ base: 'md', md: 100 }}>
<Button
variant="subtle"
onClick={() => router.back()}
leftSection={<IconArrowBack size={22} color={colors['blue-button']} />}
mb={20}
>
Kembali
</Button>
</Box>
{/* Wrapper Detail */}
<Paper
withBorder
w={{ base: '100%', md: '70%', lg: '60%' }}
mx="auto"
bg={colors['white-1']}
p="xl"
radius="lg"
shadow="sm"
>
<Stack gap="md" align="center" ta="center">
<Text fz="xl" fw={700} c={colors['blue-button']}>
{data.name || 'Penanganan Darurat'}
</Text>
{data.image?.link && (
<Image
src={data.image.link}
alt={data.name}
radius="md"
mah={300}
fit="contain"
loading="lazy"
mb="md"
/>
)}
<Box>
<Text
fz="md"
ta="justify"
dangerouslySetInnerHTML={{ __html: data.deskripsi }}
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
/>
</Box>
</Stack>
</Paper>
</Box>
);
}
export default DetailPenangananDaruratUser;

View File

@@ -3,6 +3,7 @@ import penangananDarurat from '@/app/admin/(dashboard)/_state/kesehatan/penangan
import colors from '@/con/colors'
import {
Box,
Button,
Center,
Grid,
GridCol,
@@ -148,11 +149,19 @@ function Page() {
<Text
fz="sm"
c="dimmed"
lineClamp={4}
lineClamp={3}
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
/>
</Box>
<Button
radius="xl"
size="md"
component="a"
href={`/darmasaba/kesehatan/penanganan-darurat/${v.id}`}
>
Lihat Detail
</Button>
</Stack>
</Stack>
</Paper>

View File

@@ -42,6 +42,7 @@ export default function DetailPosyanduUser() {
</Button>
</Group>
{/* Konten utama */}
<Paper
withBorder
p="xl"
@@ -85,15 +86,15 @@ export default function DetailPosyanduUser() {
{/* Info utama */}
<Stack gap="sm" mt="md">
<Flex align="flex-start" gap="xs">
<IconPhone size={18} stroke={1.5} style={{ marginTop: 3 }} />
<Flex align="center" gap="xs">
<IconPhone size={18} stroke={1.5} />
<Text fz="sm" c="dimmed">
{data.nomor || 'Nomor tidak tersedia'}
</Text>
</Flex>
<Flex align="flex-start" gap="xs">
<IconCalendar size={18} stroke={1.5} style={{ marginTop: 3 }} />
<Flex align="center" gap="xs">
<IconCalendar size={18} stroke={1.5} />
<Text
fz="sm"
c="dimmed"
@@ -102,8 +103,8 @@ export default function DetailPosyanduUser() {
/>
</Flex>
<Flex align="flex-start" gap="xs">
<IconInfoCircle size={18} stroke={1.5} style={{ marginTop: 3 }} />
<Flex align="center" gap="xs">
<IconInfoCircle size={18} stroke={1.5} />
<Text
fz="sm"
c="dimmed"

View File

@@ -88,7 +88,7 @@ export default function Page() {
>
Program Kesehatan Desa
</Text>
<Text fz="lg" c="dimmed" mt="xs">
<Text fz="lg" mt="xs">
Temukan berbagai program kesehatan untuk mendukung kualitas hidup
masyarakat Darmasaba.
</Text>
@@ -168,7 +168,7 @@ export default function Page() {
</Text>
<Text
fz="sm"
c="dimmed"
ta={"justify"}
lineClamp={3}
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
@@ -249,7 +249,7 @@ export default function Page() {
>
Manfaat Program Kesehatan
</Text>
<Text fz="lg" c="dimmed" maw={700}>
<Text fz="lg" maw={700}>
Program kesehatan Desa Darmasaba berperan penting dalam meningkatkan
kesejahteraan dan kualitas hidup warganya.
</Text>
@@ -279,7 +279,7 @@ export default function Page() {
<Text ta="center" fw="bold" fz="xl" c={colors["blue-button"]}>
{v.title}
</Text>
<Text ta="center" fz="sm" c="dimmed">
<Text ta="center" fz="sm">
{v.desc}
</Text>
</Stack>

View File

@@ -43,7 +43,7 @@ function Page() {
<Text fz={{ base: "2rem", md: "2.5rem" }} c={colors["blue-button"]} fw="bold">
Daftar Puskesmas
</Text>
<Text fz="sm" c="dimmed">
<Text fz="md">
Temukan informasi lengkap mengenai layanan, kontak, dan lokasi Puskesmas Darmasaba
</Text>
</GridCol>

View File

@@ -71,8 +71,11 @@ function Page() {
onChange={(e) => setSearch(e.currentTarget.value)}
/>
</Group>
<Text fz="lg" c={'black'}>
Desa Darmasaba menjaga dan mengembangkan lingkungan demi kesejahteraan warganya. Fokus utama meliputi penghijauan, pengelolaan sampah, dan perlindungan kawasan hijau.
<Text fz="md" >
Desa Darmasaba menjaga dan mengembangkan lingkungan demi kesejahteraan warganya.
</Text>
<Text fz="md">
Fokus utama meliputi penghijauan, pengelolaan sampah, dan perlindungan kawasan hijau.
</Text>
</Box>
<Box px={{ base: 'md', md: 100 }}>

View File

@@ -0,0 +1,66 @@
// Create a new component: components/EdukasiCard.tsx
'use client';
import { Box, Paper, Stack, Text, Tooltip } from '@mantine/core';
import { ReactNode } from 'react';
interface EdukasiCardProps {
icon: ReactNode;
title: string;
description: string;
color?: string;
}
export function EdukasiCard({ icon, title, description, color = '#1e88e5' }: EdukasiCardProps) {
return (
<Paper
p={{ base: 'md', md: 'lg' }}
radius="md"
shadow="sm"
withBorder
style={{
height: '100%',
transition: 'transform 0.2s, box-shadow 0.2s',
'&:hover': {
transform: 'translateY(-4px)',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)'
}
}}
>
<Stack h="100%" justify="space-between" gap="md">
<Box>
<Stack align="center" gap="xs" mb="md">
<Box style={{ color }}>{icon}</Box>
<Tooltip label={title} maw={250} multiline withArrow position="top">
<Text
fz={{ base: 'h5', md: 'h4' }}
fw={700}
c={color}
ta="center"
lineClamp={2}
style={{
wordBreak: 'break-word',
minHeight: '3.5rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
>
{title}
</Text>
</Tooltip>
</Stack>
<Text
size="sm"
style={{
wordBreak: 'break-word',
lineHeight: 1.6,
color: 'var(--mantine-color-gray-7)'
}}
dangerouslySetInnerHTML={{ __html: description }}
/>
</Box>
</Stack>
</Paper>
);
}

View File

@@ -1,126 +1,104 @@
'use client'
import stateEdukasiLingkungan from '@/app/admin/(dashboard)/_state/lingkungan/edukasi-lingkungan';
import colors from '@/con/colors';
import { Box, Paper, SimpleGrid, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
'use client';
import { Box, Container, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconLeaf, IconPlant2, IconRecycle } from '@tabler/icons-react';
import { useProxy } from 'valtio/utils';
import BackButton from '../../desa/layanan/_com/BackButto';
function Page() {
const tujuan = useProxy(stateEdukasiLingkungan.stateTujuanEdukasi.findById)
const materi = useProxy(stateEdukasiLingkungan.stateMateriEdukasiLingkungan.findById)
const contoh = useProxy(stateEdukasiLingkungan.stateContohEdukasiLingkungan.findById)
import stateEdukasiLingkungan from '@/app/admin/(dashboard)/_state/lingkungan/edukasi-lingkungan';
import colors from '@/con/colors';
import { EdukasiCard } from './component/edukasiCard';
function LoadingSkeleton() {
return (
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="lg">
{[1, 2, 3].map((item) => (
<Skeleton key={item} height={300} radius="md" />
))}
</SimpleGrid>
);
}
export default function EdukasiLingkunganPage() {
const tujuan = useProxy(stateEdukasiLingkungan.stateTujuanEdukasi.findById);
const materi = useProxy(stateEdukasiLingkungan.stateMateriEdukasiLingkungan.findById);
const contoh = useProxy(stateEdukasiLingkungan.stateContohEdukasiLingkungan.findById);
useShallowEffect(() => {
tujuan.load('edit')
materi.load('edit')
contoh.load('edit')
}, [])
tujuan.load('edit');
materi.load('edit');
contoh.load('edit');
}, []);
if (tujuan.loading || !tujuan.data || materi.loading || !materi.data || contoh.loading || !contoh.data) {
const isLoading = tujuan.loading || !tujuan.data ||
materi.loading || !materi.data ||
contoh.loading || !contoh.data;
if (isLoading) {
return (
<Stack py={20}>
<Skeleton radius="md" height={600} />
<Stack py="xl" px={{ base: 'md', md: 'xl' }}>
<BackButton />
<LoadingSkeleton />
</Stack>
);
}
return (
<Stack pos="relative" bg={colors.Bg} py="xl" gap="22">
<Stack bg={colors.Bg} py="xl" gap="xl" px={{ base: 'md', md: 'xl' }}>
<Box px={{ base: 'md', md: 100 }}>
<BackButton />
</Box>
<Box px={{ base: 'md', md: 100 }} pb={20}>
<Text ta={'center'} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw="bold">
<Container size="lg" ta="center">
<Text
component="h1"
fz={{ base: 'h2', md: '2.5rem' }}
c={colors['blue-button']}
fw={700}
mb="md"
>
Edukasi Lingkungan
</Text>
<Text ta={'center'} fz="h4" c="black">
<Text
fz={{ base: 'md', md: 'lg' }}
c="dimmed"
maw={800}
mx="auto"
>
Program edukasi ini membimbing masyarakat untuk peduli dan bertanggung jawab terhadap alam,
meningkatkan kesehatan, kenyamanan, dan keberlanjutan hidup bersama.
</Text>
</Box>
</Container>
<Box px={{ base: 'md', md: 100 }}>
<SimpleGrid cols={{ base: 1, md: 3 }} spacing="lg" style={{ alignItems: 'stretch' }}>
{/* Tujuan Edukasi Lingkungan */}
<Box style={{ display: 'flex', height: '100%' }}>
<Paper p={20} bg={colors['white-trans-1']} shadow="md" radius="md" style={{ width: '100%', display: 'flex', flexDirection: 'column' }}>
<Stack gap="md">
<Box>
<Tooltip label={<Text fz={"sm"} c={"white"} dangerouslySetInnerHTML={{ __html: tujuan.data?.judul || '' }} /> } position="top" withArrow>
<Stack gap={4} align="center">
<IconLeaf size={28} color={colors['blue-button']} />
<Text dangerouslySetInnerHTML={{ __html: tujuan.data?.judul || '' }} fz="h3" fw="bold" c={colors['blue-button']} ta="center" />
</Stack>
</Tooltip>
</Box>
<Text
style={{
wordBreak: "break-word",
whiteSpace: "normal",
flexGrow: 1
}}
dangerouslySetInnerHTML={{ __html: tujuan.data?.deskripsi || '' }}
/>
<Box style={{ flexGrow: 1 }} />
</Stack>
</Paper>
</Box>
{/* Materi Edukasi Lingkungan */}
<Box style={{ display: 'flex', height: '100%' }}>
<Paper p={20} bg={colors['white-trans-1']} shadow="md" radius="md">
<Stack gap="md">
<Box>
<Tooltip label={materi.data?.judul} position="top" withArrow>
<Stack gap={4} align="center">
<IconRecycle size={28} color={colors['blue-button']} />
<Text fz="h3" fw="bold" c={colors['blue-button']} ta="center" dangerouslySetInnerHTML={{ __html: materi.data?.judul || '' }} />
</Stack>
</Tooltip>
</Box>
<Text
style={{
wordBreak: "break-word",
whiteSpace: "normal",
flexGrow: 1
}}
dangerouslySetInnerHTML={{ __html: materi.data?.deskripsi || '' }}
/>
<Box style={{ flexGrow: 1 }} />
</Stack>
</Paper>
</Box>
{/* Contoh Edukasi Lingkungan */}
<Box style={{ display: 'flex', height: '100%' }}>
<Paper p={20} bg={colors['white-trans-1']} shadow="md" radius="md">
<Stack gap="md">
<Box>
<Tooltip label={contoh.data?.judul} position="top" withArrow>
<Stack gap={4} align="center">
<IconPlant2 size={28} color={colors['blue-button']} />
<Text fz="h3" fw="bold" c={colors['blue-button']} ta="center">
{contoh.data?.judul}
</Text>
</Stack>
</Tooltip>
</Box>
<Text
style={{
wordBreak: "break-word",
whiteSpace: "normal",
flexGrow: 1
}}
dangerouslySetInnerHTML={{ __html: contoh.data?.deskripsi || '' }}
/>
</Stack>
</Paper>
</Box>
<Container size="xl">
<SimpleGrid
cols={{ base: 1, sm: 2, lg: 3 }}
spacing="xl"
verticalSpacing={{ base: 'md', md: 'xl' }}
>
<EdukasiCard
icon={<IconLeaf size={32} />}
title={tujuan.data?.judul || ''}
description={tujuan.data?.deskripsi || ''}
color={colors['blue-button']}
/>
<EdukasiCard
icon={<IconRecycle size={32} />}
title={materi.data?.judul || ''}
description={materi.data?.deskripsi || ''}
color={colors['blue-button']}
/>
<EdukasiCard
icon={<IconPlant2 size={32} />}
title={contoh.data?.judul || ''}
description={contoh.data?.deskripsi || ''}
color={colors['blue-button']}
/>
</SimpleGrid>
</Box>
</Container>
</Stack>
);
}
export default Page;
}

View File

@@ -1,323 +1,5 @@
// 'use client'
// import colors from '@/con/colors';
// import { Box, Container, Grid, GridCol, Stack, Tabs, TabsList, TabsTab, Text, TextInput } from '@mantine/core';
// import { IconSearch } from '@tabler/icons-react';
// import { usePathname, useRouter, useSearchParams } from 'next/navigation';
// import React, { useEffect, useState } from 'react';
// import BackButton from '../../../desa/layanan/_com/BackButto';
// type HeaderSearchProps = {
// placeholder?: string;
// searchIcon?: React.ReactNode;
// value?: string;
// onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
// children?: React.ReactNode;
// };
// function LayoutTabsGotongRoyong({
// children,
// placeholder = "pencarian",
// searchIcon = <IconSearch size={20} />
// }: HeaderSearchProps) {
// const router = useRouter();
// const pathname = usePathname();
// const searchParams = useSearchParams();
// // Get active tab from URL path
// const activeTab = pathname.split('/').pop() || 'semua';
// // Get initial search value from URL
// const initialSearch = searchParams.get('search') || '';
// const [searchValue, setSearchValue] = useState(initialSearch);
// const [searchTimeout, setSearchTimeout] = useState<number | null>(null);
// // Update active tab state when pathname changes
// const [activeTabState, setActiveTabState] = useState(activeTab);
// useEffect(() => {
// setActiveTabState(activeTab);
// }, [activeTab]);
// // Clean up timeouts on unmount
// useEffect(() => {
// return () => {
// if (searchTimeout !== null) {
// clearTimeout(searchTimeout);
// }
// };
// }, [searchTimeout]);
// // Handle search input change with debounce
// const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
// const value = event.target.value;
// setSearchValue(value);
// // Clear previous timeout
// if (searchTimeout !== null) {
// clearTimeout(searchTimeout);
// }
// // Set new timeout
// const newTimeout = window.setTimeout(() => {
// const params = new URLSearchParams(searchParams.toString());
// if (value) {
// params.set('search', value);
// } else {
// params.delete('search');
// }
// // Only update URL if the search value has actually changed
// if (params.toString() !== searchParams.toString()) {
// router.push(`/darmasaba/lingkungan/gotong-royong/${activeTab}?${params.toString()}`);
// }
// }, 500); // 500ms debounce delay
// setSearchTimeout(newTimeout);
// };
// const tabs = [
// {
// label: "Semua",
// value: "semua",
// href: "/darmasaba/lingkungan/gotong-royong/semua"
// },
// {
// label: "Kebersihan",
// value: "kebersihan",
// href: "/darmasaba/lingkungan/gotong-royong/kebersihan"
// },
// {
// label: "Infrastruktur",
// value: "infrastruktur",
// href: "/darmasaba/lingkungan/gotong-royong/infrastruktur"
// },
// {
// label: "Sosial",
// value: "sosial",
// href: "/darmasaba/lingkungan/gotong-royong/sosial"
// },
// {
// label: "Lingkungan",
// value: "lingkungan",
// href: "/darmasaba/lingkungan/gotong-royong/lingkungan"
// }
// ];
// const handleTabChange = (value: string | null) => {
// if (!value) return;
// const tab = tabs.find(t => t.value === value);
// if (tab) {
// const params = new URLSearchParams(searchParams.toString());
// router.push(`/darmasaba/lingkungan/gotong-royong/${value}${params.toString() ? `?${params.toString()}` : ''}`);
// }
// };
// return (
// <Stack pos="relative" bg={colors.Bg} py="xl" gap="22">
// {/* Header */}
// <Box px={{ base: "md", md: 100 }}>
// <BackButton />
// </Box>
// <Container size="lg" px="md">
// <Stack align="center" gap="0" >
// <Text fz={{ base: "2rem", md: "3.4rem" }} c={colors["blue-button"]} fw="bold" ta="center">
// Gotong Royong Desa Darmasaba
// </Text>
// <Text ta="center" px="md">
// Gotong royong rutin dilakukan oleh warga desa untuk meningkatkan kualitas hidup dan kesejahteraan masyarakat Desa Darmasaba
// </Text>
// </Stack>
// </Container>
// <Tabs
// color={colors['blue-button']}
// variant="pills"
// value={activeTabState}
// onChange={handleTabChange}
// >
// <Box px={{ base: "md", md: 100 }} py="md" bg={colors['BG-trans']}>
// <Grid>
// <GridCol span={{ base: 12, md: 9, lg: 8, xl: 9 }}>
// <TabsList>
// {tabs.map((tab, index) => (
// <TabsTab
// key={index}
// value={tab.value}
// onClick={() => router.push(tab.href)}
// >
// {tab.label}
// </TabsTab>
// ))}
// </TabsList>
// </GridCol>
// <GridCol span={{ base: 12, md: 3, lg: 4, xl: 3 }}>
// <TextInput
// radius="lg"
// placeholder={placeholder}
// leftSection={searchIcon}
// w="100%"
// value={searchValue}
// onChange={handleSearchChange}
// />
// </GridCol>
// </Grid>
// </Box>
// {children}
// </Tabs>
// </Stack>
// );
// }
// export default LayoutTabsGotongRoyong;
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable @typescript-eslint/no-explicit-any */
// 'use client'
// import colors from '@/con/colors';
// import { Box, Group, Stack, Tabs, TabsList, TabsTab, Text, TextInput } from '@mantine/core';
// import { IconSearch } from '@tabler/icons-react';
// import { usePathname, useRouter, useSearchParams } from 'next/navigation';
// import React, { useEffect, useState } from 'react';
// import BackButton from '../../layanan/_com/BackButto';
// type HeaderSearchProps = {
// placeholder?: string;
// searchIcon?: React.ReactNode;
// value?: string;
// onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
// children?: React.ReactNode;
// };
// function LayoutTabsBerita({
// children,
// placeholder = "pencarian",
// searchIcon = <IconSearch size={20} />
// }: HeaderSearchProps) {
// const router = useRouter();
// const pathname = usePathname();
// const searchParams = useSearchParams();
// const activeTab = pathname.split('/').pop() || 'semua';
// const initialSearch = searchParams.get('search') || '';
// const [searchValue, setSearchValue] = useState(initialSearch);
// const [searchTimeout, setSearchTimeout] = useState<number | null>(null);
// const [activeTabState, setActiveTabState] = useState(activeTab);
// useEffect(() => {
// setActiveTabState(activeTab);
// }, [activeTab]);
// useEffect(() => {
// return () => {
// if (searchTimeout !== null) clearTimeout(searchTimeout);
// };
// }, [searchTimeout]);
// const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
// const value = event.target.value;
// setSearchValue(value);
// if (searchTimeout !== null) clearTimeout(searchTimeout);
// const newTimeout = window.setTimeout(() => {
// const params = new URLSearchParams(searchParams.toString());
// if (value) params.set('search', value);
// else params.delete('search');
// if (params.toString() !== searchParams.toString()) {
// router.push(`/darmasaba/desa/berita/${activeTab}?${params.toString()}`);
// }
// }, 500);
// setSearchTimeout(newTimeout);
// };
// const tabs = [
// { label: "Semua", value: "semua", href: "/darmasaba/desa/berita/semua" },
// { label: "Budaya", value: "budaya", href: "/darmasaba/desa/berita/budaya" },
// { label: "Pemerintahan", value: "pemerintahan", href: "/darmasaba/desa/berita/pemerintahan" },
// { label: "Ekonomi", value: "ekonomi", href: "/darmasaba/desa/berita/ekonomi" },
// { label: "Pembangunan", value: "pembangunan", href: "/darmasaba/desa/berita/pembangunan" },
// { label: "Sosial", value: "sosial", href: "/darmasaba/desa/berita/sosial" },
// { label: "Teknologi", value: "teknologi", href: "/darmasaba/desa/berita/teknologi" },
// ];
// const handleTabChange = (value: string | null) => {
// if (!value) return;
// const tab = tabs.find(t => t.value === value);
// if (tab) {
// const params = new URLSearchParams(searchParams.toString());
// router.push(`/darmasaba/desa/berita/${value}${params.toString() ? `?${params.toString()}` : ''}`);
// }
// };
// return (
// <Stack pos="relative" bg={colors.Bg} py="xl" gap="22">
// {/* Header */}
// <Box px={{ base: "md", md: 100 }}>
// <BackButton />
// </Box>
// <Box px={{ base: 'md', md: 100 }}>
// <Group justify='space-between' align="center">
// <Stack gap="0">
// <Text fz={{ base: "2rem", md: "3.4rem" }} c={colors["blue-button"]} fw="bold" >
// Portal Berita Darmasaba
// </Text>
// <Text>
// Temukan berbagai potensi dan keunggulan yang dimiliki Desa Darmasaba
// </Text>
// </Stack>
// <Box>
// <TextInput
// radius="lg"
// placeholder={placeholder}
// leftSection={searchIcon}
// w="100%"
// value={searchValue}
// onChange={handleSearchChange}
// />
// </Box>
// </Group>
// </Box>
// <Tabs
// color={colors['blue-button']}
// variant="pills"
// value={activeTabState}
// onChange={handleTabChange}
// >
// <Box px={{ base: "md", md: 100 }} py="md" bg={colors['BG-trans']}>
// {/* SCROLLABLE TABS */}
// <Box style={{ overflowX: 'auto', whiteSpace: 'nowrap' }}>
// <TabsList style={{ display: 'flex', flexWrap: 'nowrap', gap: '0.5rem' }}>
// {tabs.map((tab, index) => (
// <TabsTab
// key={index}
// value={tab.value}
// onClick={() => router.push(tab.href)}
// style={{
// flex: '0 0 auto', // Prevent shrinking
// minWidth: 100, // optional: makes them touch-friendly
// textAlign: 'center'
// }}
// >
// {tab.label}
// </TabsTab>
// ))}
// </TabsList>
// </Box>
// </Box>
// {children}
// </Tabs>
// </Stack>
// );
// }
// export default LayoutTabsBerita;
'use client'
import gotongRoyongState from '@/app/admin/(dashboard)/_state/lingkungan/gotong-royong';
@@ -402,7 +84,7 @@ function LayoutTabsGotongRoyong({ children }: { children: React.ReactNode }) {
<Text fz={{ base: "2rem", md: "3.4rem" }} c={colors["blue-button"]} fw="bold">
Portal Gotong royong Darmasaba
</Text>
<Text>Temukan berbagai kegiatan lingkungan yang dimiliki Desa Darmasaba</Text>
<Text fz="md">Temukan berbagai kegiatan lingkungan yang dimiliki Desa Darmasaba</Text>
</Stack>
<Box>
<TextInput

View File

@@ -66,8 +66,11 @@ function Page() {
/>
</Group>
</Box>
<Text c="dimmed" fz={{ base: 'sm', md: 'lg' }} mt="sm">
Mari berpartisipasi menanam dan merawat pohon untuk menciptakan lingkungan hijau, sehat, dan seimbang bagi seluruh warga desa.
<Text fz="md" mt="sm">
Mari berpartisipasi menanam dan merawat pohon untuk menciptakan lingkungan hijau,
</Text>
<Text fz="md">
sehat, dan seimbang bagi seluruh warga desa.
</Text>
</Box>
<Box px={{ base: 'md', md: 100 }} pb={60}>

View File

@@ -3,6 +3,7 @@
'use client'
import stateStrukturPPID from '@/app/admin/(dashboard)/_state/ppid/struktur_ppid/struktur_PPID'
import ScrollToTopButton from '@/app/darmasaba/_com/scrollToTopButton'
import colors from '@/con/colors'
import {
Box,
@@ -18,25 +19,23 @@ import {
Text,
TextInput,
Title,
Tooltip,
Transition,
Transition
} from '@mantine/core'
import {
IconArrowsMaximize,
IconArrowsMinimize,
IconRefresh,
IconSearch,
IconUsers,
IconZoomIn,
IconZoomOut,
IconArrowsMaximize,
IconArrowsMinimize,
} from '@tabler/icons-react'
import { debounce } from 'lodash'
import { useTransitionRouter } from 'next-view-transitions'
import { OrganizationChart } from 'primereact/organizationchart'
import { useEffect, useRef, useState } from 'react'
import { useProxy } from 'valtio/utils'
import BackButton from '../../desa/layanan/_com/BackButto'
import { useTransitionRouter } from 'next-view-transitions'
import ScrollToTopButton from '@/app/darmasaba/_com/scrollToTopButton'
import { debounce } from 'lodash'
export default function Page() {
return (
@@ -346,7 +345,6 @@ function nodeTemplate(node: any, router: ReturnType<typeof useTransitionRouter>)
<Text size="xs" c="dimmed" mt={8} lineClamp={3}>
{description || 'Belum ada deskripsi.'}
</Text>
<Tooltip label="Lihat Detail" withArrow position="bottom">
<Button
variant="light"
size="xs"
@@ -358,7 +356,6 @@ function nodeTemplate(node: any, router: ReturnType<typeof useTransitionRouter>)
>
Lihat Detail
</Button>
</Tooltip>
</Card>
)}
</Transition>

View File

@@ -66,7 +66,8 @@ function Page() {
<Divider my="sm" labelPosition="center" label={<IconSparkles size={18} />} />
<Box>
<Text ta="center" fz={{ base: 24, md: 30 }} fw={700} mb="sm">
<Text ta="center" fz={{ base: 24, md: 30 }} fw={800}
c={colors['blue-button']} mb="sm">
Visi PPID
</Text>
<Text
@@ -81,7 +82,8 @@ function Page() {
<Divider my="sm" />
<Box>
<Text ta="center" fz={{ base: 24, md: 30 }} fw={700} mb="sm">
<Text ta="center" fz={{ base: 24, md: 30 }} fw={800}
c={colors['blue-button']} mb="sm">
Misi PPID
</Text>
<Text