Fix Konsisten teks di tampilan mobile dan desktop

Fix QC Kak Inno tgl 10 Des
Fix QC Kak Ayu tgl 10 Des
This commit is contained in:
2025-12-11 17:58:03 +08:00
parent 242ea86f77
commit a00481152c
43 changed files with 1725 additions and 1093 deletions

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 { Box, Button, Card, Divider, Group, Image, Loader, Paper, Stack, Text } from '@mantine/core';
import { Box, Button, Card, Divider, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconCalendar, IconChevronRight } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -17,9 +17,8 @@ function ArtikelKesehatanPage() {
if (!state.findMany.data) {
return (
<Box py="xl" ta="center">
<Loader size="lg" color={colors['blue-button']} />
<Text mt="md" c="dimmed" fz="md">Memuat artikel kesehatan...</Text>
<Box py="lg">
<Skeleton h={500} radius="lg" />
</Box>
)
}

View File

@@ -1,7 +1,7 @@
'use client'
import fasilitasKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/fasilitasKesehatan';
import colors from '@/con/colors';
import { Badge, Box, Button, Card, Divider, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { Badge, Box, Button, Card, Divider, Group, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconChevronRight, IconClock, IconMapPin } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -17,12 +17,8 @@ function FasilitasKesehatanPage() {
if (!state.findMany.data) {
return (
<Box py="xl" px="md">
<Stack gap="md">
<Skeleton height={80} radius="lg" />
<Skeleton height={80} radius="lg" />
<Skeleton height={80} radius="lg" />
</Stack>
<Box py="lg">
<Skeleton h={500} radius="lg" />
</Box>
);
}
@@ -31,14 +27,20 @@ function FasilitasKesehatanPage() {
<Box>
<Paper bg={colors['white-trans-1']} p="xl" radius="xl" shadow="md" h="100%">
<Stack gap="lg">
<Text ta="center" fw={700} fz="32px" c={colors['blue-button']}>
<Title
order={1}
ta="center"
fw={700}
c={colors['blue-button']}
style={{ lineHeight: '1.2' }}
>
Fasilitas Kesehatan
</Text>
</Title>
<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">
<Text size="lg" c="dimmed" lh="1.5">
Belum ada fasilitas kesehatan yang tersedia
</Text>
</Box>
@@ -65,22 +67,20 @@ function FasilitasKesehatanPage() {
>
<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">
<Title order={3} fw={700} c={colors['blue-button']} lh="1.3" />
<Badge color="blue" radius="sm" variant="light" size="xs">
Aktif
</Badge>
</Group>
<Group gap="xs">
<IconMapPin size={18} stroke={1.5} />
<Text fz="sm">
<Text size="sm" lh="1.5">
{item.informasiumum.alamat}
</Text>
</Group>
<Group gap="xs">
<IconClock size={18} stroke={1.5} />
<Text fz="sm">
<Text size="sm" lh="1.5">
{item.informasiumum.jamOperasional}
</Text>
</Group>
@@ -110,4 +110,4 @@ function FasilitasKesehatanPage() {
);
}
export default FasilitasKesehatanPage;
export default FasilitasKesehatanPage;

View File

@@ -6,9 +6,7 @@ import { Box, Center, ColorSwatch, Flex, Paper, SimpleGrid, Skeleton, Stack, Tex
import { useEffect, useState } from 'react';
import BackButton from '../../desa/layanan/_com/BackButto';
// import { useRouter } from 'next/navigation';
import { useMediaQuery, useShallowEffect } from '@mantine/hooks';
import persentasekelahiran from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/persentaseKelahiran';
import { useProxy } from 'valtio/utils';
@@ -17,7 +15,6 @@ import GrafikPenyakit from './grafik-penyakit/page';
import JadwalKegiatan from './jadwal-kegiatan-page/page';
import ArtikelKesehatanPage from './artikel-kesehatan-page/page';
function Page() {
type DataTahunan = {
tahun: string;
@@ -31,7 +28,6 @@ function Page() {
}>;
};
// Count occurrences per year
const countByYear = (data: any[], dateField: string) => {
const counts: Record<string, number> = {};
data?.forEach(item => {
@@ -43,28 +39,23 @@ function Page() {
const statePersentase = useProxy(persentasekelahiran);
const [chartData, setChartData] = useState<DataTahunan[]>([]);
const isTablet = useMediaQuery('(max-width: 1024px)');
const isMobile = useMediaQuery('(max-width: 768px)');
useShallowEffect(() => {
statePersentase.kelahiran.findMany.load(1, 1000); // Load all kelahiran data
statePersentase.kematian.findMany.load(1, 1000); // Load all kematian data
statePersentase.kelahiran.findMany.load(1, 1000);
statePersentase.kematian.findMany.load(1, 1000);
}, []);
useEffect(() => {
if (statePersentase.kelahiran.findMany.data && statePersentase.kematian.findMany.data) {
// Count kelahiran and kematian by year
const kelahiranByYear = countByYear(statePersentase.kelahiran.findMany.data, 'tanggal');
const kematianByYear = countByYear(statePersentase.kematian.findMany.data, 'tanggal');
// Get all unique years
const allYears = new Set([
...Object.keys(kelahiranByYear),
...Object.keys(kematianByYear)
]);
// Create data structure for the chart
const dataByYear = Array.from(allYears).reduce<Record<string, DataTahunan>>((acc, year) => {
acc[year] = {
tahun: year,
@@ -93,32 +84,44 @@ function Page() {
</Stack>
);
}
return (
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
<Stack pos="relative" bg={colors.Bg} py="xl" gap="22">
<Box px={{ base: 'md', md: 100 }}>
<BackButton />
</Box>
<Text ta={"center"} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
{/* Page Title */}
<Title
order={1}
ta="center"
c={colors['blue-button']}
fw="bold"
lh={1.2}
>
Data Kesehatan Masyarakat Puskesmas Darmasaba
</Text>
<Box px={{ base: "md", md: 100 }}>
<Stack gap={'lg'}>
</Title>
<Box px={{ base: 'md', md: 100 }}>
<Stack gap="lg">
{/* Bar Chart Kematian Kelahiran */}
<Box>
<Paper p={"xl"} bg={colors['white-trans-1']}>
<Paper p="xl" bg={colors['white-trans-1']}>
<Box pb={30}>
<Title order={2} mb="md">Data Kematian dan Kelahiran</Title>
<Title order={2} mb="md" ta="center">
Data Kematian dan Kelahiran
</Title>
{chartData.length === 0 ? (
<Text c="dimmed" ta="center" py="xl">
<Text c="dimmed" ta="center" py="xl" size="md">
Belum ada data yang tersedia untuk ditampilkan
</Text>
) : (
<>
{/* Main Chart */}
<Center>
<Box h={400}>
<Box style={{
width: isMobile ? '90vw' : isTablet ? '700px' : '800px',
width: isMobile ? '90vw' : '800px',
maxWidth: '100%',
margin: '0 auto'
}}>
@@ -137,16 +140,21 @@ function Page() {
</Center>
</>
)}
<Flex pb={30} justify={'center'} gap={'xl'} align={'center'}>
<Flex pb={30} justify="center" gap="xl" align="center" wrap="wrap">
<Box>
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Angka Kematian</Text>
<ColorSwatch color="#EF3E3E" size={30} />
<Flex gap={{ base: 'xs', md: 'sm' }} align="center">
<Text fw="bold" fz={{ base: 'sm', md: 'md' }}>
Angka Kematian
</Text>
<ColorSwatch color="#EF3E3E" size={30} />
</Flex>
</Box>
<Box>
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Angka Kelahiran</Text>
<Flex gap={{ base: 'xs', md: 'sm' }} align="center">
<Text fw="bold" fz={{ base: 'sm', md: 'md' }}>
Angka Kelahiran
</Text>
<ColorSwatch color="#3290CA" size={30} />
</Flex>
</Box>
@@ -154,20 +162,13 @@ function Page() {
</Box>
</Paper>
</Box>
<GrafikPenyakit />
{/* Artikel Kesehatan */}
<Box>
<SimpleGrid
cols={{
base: 1,
md: 3,
}}
>
{/* Fasilitas Kesehatan */}
<SimpleGrid cols={{ base: 1, md: 3 }}>
<FasilitasKesehatan />
{/* Jadwal Kegiatan */}
<JadwalKegiatan />
{/* Artikel Kesehatan */}
<ArtikelKesehatanPage />
</SimpleGrid>
</Box>
@@ -177,4 +178,4 @@ function Page() {
);
}
export default Page;
export default Page;

View File

@@ -1,7 +1,7 @@
'use client'
import infoWabahPenyakit from '@/app/admin/(dashboard)/_state/kesehatan/info-wabah-penyakit/infoWabahPenyakit';
import colors from '@/con/colors';
import { Box, Button, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { Box, Button, Image, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -51,10 +51,15 @@ function DetailInfoWabahPenyakitUser() {
shadow="sm"
>
<Stack gap="lg">
{/* Judul */}
<Text fz="xl" fw="bold" c={colors['blue-button']} ta="center">
{/* Judul — H1 */}
<Title
order={1}
fw="bold"
c={colors['blue-button']}
ta="center"
>
{data.name || 'Kontak Darurat'}
</Text>
</Title>
{/* Gambar */}
{data.image?.link && (
@@ -70,10 +75,16 @@ function DetailInfoWabahPenyakitUser() {
{/* Deskripsi */}
<Box>
<Text fz="lg" fw="bold">Deskripsi</Text>
{/* Section Title — H2 */}
<Title order={2} fw="bold" fz={{ base: 'md', md: 'lg' }} lh="1.4">
Deskripsi
</Title>
<Box pl={20}>
<Text
fz="md"
fz={{ base: 'sm', md: 'md' }}
lh="1.6"
c="dimmed"
ta={"justify"}
dangerouslySetInnerHTML={{ __html: data.deskripsiLengkap || '-' }}
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
/>
@@ -85,4 +96,4 @@ function DetailInfoWabahPenyakitUser() {
);
}
export default DetailInfoWabahPenyakitUser;
export default DetailInfoWabahPenyakitUser;

View File

@@ -1,7 +1,18 @@
'use client';
import colors from '@/con/colors';
import { Button, Center, Flex, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
import {
Button,
Center,
Flex,
Group,
Image,
Paper,
Skeleton,
Stack,
Text,
Title,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconCalendar, IconInfoCircle, IconPhone } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -53,15 +64,14 @@ export default function DetailPosyanduUser() {
mx="auto"
>
<Stack gap="md">
{/* Header */}
<Text
{/* Header — Dijadikan Title */}
<Title
ta="center"
fz={{ base: '1.8rem', md: '2.2rem' }}
fw={700}
order={1}
c={colors['blue-button']}
>
{data.name || 'Posyandu Desa'}
</Text>
</Title>
{/* Gambar */}
{data.image?.link ? (
@@ -78,7 +88,7 @@ export default function DetailPosyanduUser() {
</Center>
) : (
<Center>
<Text fz="sm" c="dimmed">
<Text fz={{ base: 'xs', md: 'sm' }} c="dimmed">
Tidak ada gambar
</Text>
</Center>
@@ -88,7 +98,11 @@ export default function DetailPosyanduUser() {
<Stack gap="sm" mt="md">
<Flex align="center" gap="xs">
<IconPhone size={18} stroke={1.5} />
<Text fz="sm" c="dimmed">
<Text
fz={{ base: 'xs', md: 'sm' }}
c="dimmed"
lh={{ base: 1.5, md: 1.6 }}
>
{data.nomor || 'Nomor tidak tersedia'}
</Text>
</Flex>
@@ -96,8 +110,9 @@ export default function DetailPosyanduUser() {
<Flex align="center" gap="xs">
<IconCalendar size={18} stroke={1.5} />
<Text
fz="sm"
fz={{ base: 'xs', md: 'sm' }}
c="dimmed"
lh={{ base: 1.5, md: 1.6 }}
dangerouslySetInnerHTML={{ __html: data.jadwalPelayanan || '-' }}
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
/>
@@ -106,9 +121,9 @@ export default function DetailPosyanduUser() {
<Flex align="center" gap="xs">
<IconInfoCircle size={18} stroke={1.5} />
<Text
fz="sm"
fz={{ base: 'xs', md: 'sm' }}
c="dimmed"
lh={1.6}
lh={{ base: 1.5, md: 1.6 }}
dangerouslySetInnerHTML={{ __html: data.deskripsi || '-' }}
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
/>
@@ -118,4 +133,4 @@ export default function DetailPosyanduUser() {
</Paper>
</Stack>
);
}
}

View File

@@ -1,7 +1,7 @@
'use client'
import posyandustate from "@/app/admin/(dashboard)/_state/kesehatan/posyandu/posyandu";
import colors from "@/con/colors";
import { Badge, Box, Button, Center, Flex, Group, Image, List, ListItem, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from "@mantine/core";
import { Badge, Box, Button, Center, Flex, Group, Image, List, ListItem, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Title } from "@mantine/core";
import { useDebouncedValue, useShallowEffect } from "@mantine/hooks";
import { IconCalendar, IconInfoCircle, IconPhone, IconSearch } from "@tabler/icons-react";
import { useState } from "react";
@@ -12,8 +12,8 @@ import { useTransitionRouter } from "next-view-transitions";
export default function Page() {
const state = useProxy(posyandustate);
const [search, setSearch] = useState("");
const [debouncedSearch] = useDebouncedValue(search, 1000); // 500ms delay
const router = useTransitionRouter()
const [debouncedSearch] = useDebouncedValue(search, 1000);
const router = useTransitionRouter();
const { data, page, totalPages, loading, load } = state.findMany;
@@ -35,14 +35,13 @@ export default function Page() {
<Box px={{ base: "md", md: 100 }}>
<BackButton />
<Flex mt="md" justify="space-between" align="center" wrap="wrap" gap="md">
<Text
<Title
order={1}
ta="left"
fz={{ base: "1.8rem", md: "2.5rem" }}
c={colors["blue-button"]}
fw="bold"
>
Posyandu Desa Darmasaba
</Text>
</Title>
<TextInput
placeholder="Cari posyandu berdasarkan nama..."
aria-label="Pencarian Posyandu"
@@ -55,6 +54,7 @@ export default function Page() {
/>
</Flex>
</Box>
<Title c={"dimmed"} order={3} ta={"center"}>Belum ada posyandu yang terdaftar</Title>
</Stack>
);
}
@@ -64,14 +64,13 @@ export default function Page() {
<Box px={{ base: "md", md: 100 }}>
<BackButton />
<Flex mt="md" justify="space-between" align="center" wrap="wrap" gap="md">
<Text
<Title
order={1}
ta="left"
fz={{ base: "1.8rem", md: "2.5rem" }}
c={colors["blue-button"]}
fw="bold"
>
Posyandu Desa Darmasaba
</Text>
</Title>
<TextInput
placeholder="Cari posyandu berdasarkan nama..."
aria-label="Pencarian Posyandu"
@@ -116,9 +115,9 @@ export default function Page() {
>
<Stack gap="sm">
<Group justify="space-between" align="center">
<Text c={colors["blue-button"]} fw="bold" fz="lg" lineClamp={1}>
<Title order={3} c={colors["blue-button"]} fw="bold" lineClamp={1}>
{v.name}
</Text>
</Title>
<Badge color="blue" variant="light" size="sm" radius="sm">
Aktif
</Badge>
@@ -137,7 +136,7 @@ export default function Page() {
<Flex align="flex-start" gap="xs">
<IconPhone size={18} stroke={1.5} style={{ marginTop: 3 }} />
<Box>
<Text fz="sm" c="dimmed" lh={1.4}>
<Text fz={{ base: "xs", md: "sm" }} c="dimmed" lh={1.4}>
{v.nomor || "Tidak tersedia"}
</Text>
</Box>
@@ -146,7 +145,7 @@ export default function Page() {
<Flex align="flex-start" gap="xs">
<IconCalendar size={18} stroke={1.5} style={{ marginTop: 3 }} />
<Box>
<Text fz="sm" c="dimmed" lh={1.4}>
<Text fz={{ base: "xs", md: "sm" }} c="dimmed" lh={1.4}>
<strong>Jadwal:</strong>{" "}
<span
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
@@ -159,7 +158,7 @@ export default function Page() {
<Flex align="flex-start" gap="xs">
<IconInfoCircle size={18} stroke={1.5} style={{ marginTop: 3 }} />
<Text
fz="sm"
fz={{ base: "xs", md: "sm" }}
lh={1.5}
c="dimmed"
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
@@ -168,7 +167,9 @@ export default function Page() {
truncate="end"
/>
</Flex>
<Button radius="lg" size="md" variant="outline" onClick={() => router.push(`/darmasaba/kesehatan/posyandu/${v.id}`)}>Detail</Button>
<Button radius="lg" size="md" variant="outline" onClick={() => router.push(`/darmasaba/kesehatan/posyandu/${v.id}`)}>
Detail
</Button>
</Stack>
</Paper>
))}
@@ -191,11 +192,11 @@ export default function Page() {
<Stack gap="sm">
<Flex align="center" gap="xs">
<IconInfoCircle size={22} color={colors["blue-button"]} />
<Text fz="lg" fw="bold" c={colors["blue-button"]}>
<Title order={2} c={colors["blue-button"]}>
Layanan Utama Posyandu
</Text>
</Title>
</Flex>
<List spacing="xs" size="sm" center>
<List spacing="xs" fz={{ base: "xs", md: "sm" }} center>
<ListItem>Penimbangan bayi dan balita</ListItem>
<ListItem>Pemantauan status gizi</ListItem>
<ListItem>Imunisasi dasar lengkap</ListItem>