diff --git a/src/app/admin/layout.tsx b/src/app/admin/layout.tsx index bcc49834..e2396825 100644 --- a/src/app/admin/layout.tsx +++ b/src/app/admin/layout.tsx @@ -132,7 +132,7 @@ export default function Layout({ children }: { children: React.ReactNode }) { { - router.push("/login"); + router.push("/darmasaba"); }} color={colors["blue-button"]} radius="xl" diff --git a/src/app/api/[[...slugs]]/_lib/search/searchState.ts b/src/app/api/[[...slugs]]/_lib/search/searchState.ts index d4951d64..42fa0cff 100644 --- a/src/app/api/[[...slugs]]/_lib/search/searchState.ts +++ b/src/app/api/[[...slugs]]/_lib/search/searchState.ts @@ -25,26 +25,40 @@ const searchState = proxy({ searchState.results = []; return; } - + searchState.loading = true; + + try { + const res = await ApiFetch.api.search.findMany.get({ + query: { + query: searchState.query, + page: searchState.page, + limit: searchState.limit, + type: searchState.type, + }, + }); + + console.log("Search API Response:", res); + const rawItems = res.data?.data || []; + const parsedItems = structuredClone(rawItems); // โœ… penting! + + console.log("โœ… Parsed items:", parsedItems); + + if (searchState.page === 1) { + searchState.results = parsedItems; + } else { + searchState.results.push(...parsedItems); + } - const res = await ApiFetch.api.search.findMany.get({ - query: { - query: searchState.query, - page: searchState.page, - limit: searchState.limit, - type: searchState.type, - }, - }); + console.log("Search results render:", searchState.results); - if (searchState.page === 1) { - searchState.results = res.data?.data || []; - } else { - searchState.results.push(...(res.data?.data || [])); + + searchState.nextPage = res.data?.nextPage || null; + } catch (error) { + console.error("Search fetch error:", error); + } finally { + searchState.loading = false; } - - searchState.nextPage = res.data?.nextPage || null; - searchState.loading = false; }, async next() { diff --git a/src/app/darmasaba/(pages)/ekonomi/demografi-pekerjaan/page.tsx b/src/app/darmasaba/(pages)/ekonomi/demografi-pekerjaan/page.tsx index 18d9dcca..61db456e 100644 --- a/src/app/darmasaba/(pages)/ekonomi/demografi-pekerjaan/page.tsx +++ b/src/app/darmasaba/(pages)/ekonomi/demografi-pekerjaan/page.tsx @@ -48,7 +48,7 @@ function Page() { p={10} mb={50} h={400} - w={150} + w={Math.max(data.length * 120, 800)} // auto lebar sesuai jumlah data data={data.map((item) => ({ id: item.id, Pekerjaan: item.pekerjaan, diff --git a/src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/page.tsx b/src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/page.tsx index f17cbe8d..b78e8a60 100644 --- a/src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/page.tsx +++ b/src/app/darmasaba/(pages)/kesehatan/info-wabah-penyakit/page.tsx @@ -121,7 +121,12 @@ function Page() { - Diposting: {v.createdAt.toLocaleDateString()} + Diposting: {new Date(v.createdAt).toLocaleDateString('id-ID', { + day: '2-digit', + month: 'long', + year: 'numeric', + })} + diff --git a/src/app/darmasaba/(pages)/kesehatan/posyandu/[id]/page.tsx b/src/app/darmasaba/(pages)/kesehatan/posyandu/[id]/page.tsx new file mode 100644 index 00000000..043667fa --- /dev/null +++ b/src/app/darmasaba/(pages)/kesehatan/posyandu/[id]/page.tsx @@ -0,0 +1,120 @@ +'use client'; + +import colors from '@/con/colors'; +import { Button, Center, Flex, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; +import { IconArrowBack, IconCalendar, IconInfoCircle, IconPhone } from '@tabler/icons-react'; +import { useParams, useRouter } from 'next/navigation'; +import { useProxy } from 'valtio/utils'; +import posyanduState from '@/app/admin/(dashboard)/_state/kesehatan/posyandu/posyandu'; + +export default function DetailPosyanduUser() { + const statePosyandu = useProxy(posyanduState); + const params = useParams(); + const router = useRouter(); + + useShallowEffect(() => { + statePosyandu.findUnique.load(params?.id as string); + }, []); + + if (!statePosyandu.findUnique.data) { + return ( + + + + ); + } + + const data = statePosyandu.findUnique.data; + + return ( + + {/* Tombol Kembali */} + + + + + + + {/* Header */} + + {data.name || 'Posyandu Desa'} + + + {/* Gambar */} + {data.image?.link ? ( +
+ {`Gambar +
+ ) : ( +
+ + Tidak ada gambar + +
+ )} + + {/* Info utama */} + + + + + {data.nomor || 'Nomor tidak tersedia'} + + + + + + + + + + + + + +
+
+
+ ); +} diff --git a/src/app/darmasaba/(pages)/kesehatan/posyandu/page.tsx b/src/app/darmasaba/(pages)/kesehatan/posyandu/page.tsx index 189ab309..1048dcb2 100644 --- a/src/app/darmasaba/(pages)/kesehatan/posyandu/page.tsx +++ b/src/app/darmasaba/(pages)/kesehatan/posyandu/page.tsx @@ -1,18 +1,19 @@ 'use client' import posyandustate from "@/app/admin/(dashboard)/_state/kesehatan/posyandu/posyandu"; import colors from "@/con/colors"; -import { Badge, Box, Center, Flex, Group, Image, List, ListItem, Pagination, Paper, SimpleGrid, Skeleton, Spoiler, Stack, Text, TextInput } from "@mantine/core"; -import { useShallowEffect } from "@mantine/hooks"; +import { Badge, Box, Button, Center, Flex, Group, Image, List, ListItem, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from "@mantine/core"; +import { useDebouncedValue, useShallowEffect } from "@mantine/hooks"; import { IconCalendar, IconInfoCircle, IconPhone, IconSearch } from "@tabler/icons-react"; import { useState } from "react"; import { useProxy } from "valtio/utils"; import BackButton from "../../desa/layanan/_com/BackButto"; -import { useDebouncedValue } from "@mantine/hooks"; +import { useTransitionRouter } from "next-view-transitions"; export default function Page() { const state = useProxy(posyandustate); const [search, setSearch] = useState(""); const [debouncedSearch] = useDebouncedValue(search, 500); // 500ms delay + const router = useTransitionRouter() const { data, page, totalPages, loading, load } = state.findMany; @@ -133,33 +134,41 @@ export default function Page() { loading="lazy" /> - - - - {v.nomor || "Tidak tersedia"} - + + + + + {v.nomor || "Tidak tersedia"} + + - - - - Jadwal:{" "} - - + + + + + + Jadwal:{" "} + + + - + + + - + + ))} diff --git a/src/app/darmasaba/(pages)/lingkungan/gotong-royong/semua/page.tsx b/src/app/darmasaba/(pages)/lingkungan/gotong-royong/semua/page.tsx index 09cf0b93..785e5b92 100644 --- a/src/app/darmasaba/(pages)/lingkungan/gotong-royong/semua/page.tsx +++ b/src/app/darmasaba/(pages)/lingkungan/gotong-royong/semua/page.tsx @@ -43,15 +43,48 @@ export default function Page() { const loadingGrid = state.findMany.loading; const loadingFeatured = featured.loading; + // Load featured data once on component mount useEffect(() => { - if (!featured.data && !loadingFeatured) { - gotongRoyongState.kegiatanDesa.findFirst.load(); + let mounted = true; + + const loadFeatured = async () => { + try { + if (!featured.data && !loadingFeatured) { + await gotongRoyongState.kegiatanDesa.findFirst.load(); + } + } catch (error) { + console.error('Error loading featured data:', error); + } + }; + + if (mounted) { + loadFeatured(); } - }, [featured.data, loadingFeatured]); + + return () => { + mounted = false; + }; + }, []); // Empty dependency array to run only once on mount useEffect(() => { - const limit = 3; - state.findMany.load(page, limit, search); + let mounted = true; + + const loadData = async () => { + try { + const limit = 3; + await state.findMany.load(page, limit, search); + } catch (error) { + console.error('Error loading data:', error); + } + }; + + if (mounted) { + loadData(); + } + + return () => { + mounted = false; + }; }, [page, search]); const handlePageChange = (newPage: number) => { @@ -59,7 +92,9 @@ export default function Page() { if (search) url.set('search', search); if (newPage > 1) url.set('page', newPage.toString()); else url.delete('page'); - router.replace(`?${url.toString()}`); + + // Use push instead of replace to keep browser history + router.push(`?${url.toString()}`, { scroll: false }); }; const featuredData = featured.data; diff --git a/src/app/darmasaba/(pages)/lingkungan/pengelolaan-sampah-bank-sampah/page.tsx b/src/app/darmasaba/(pages)/lingkungan/pengelolaan-sampah-bank-sampah/page.tsx index 1e56633b..48d4baf9 100644 --- a/src/app/darmasaba/(pages)/lingkungan/pengelolaan-sampah-bank-sampah/page.tsx +++ b/src/app/darmasaba/(pages)/lingkungan/pengelolaan-sampah-bank-sampah/page.tsx @@ -1,9 +1,9 @@ 'use client' import pengelolaanSampahState from '@/app/admin/(dashboard)/_state/lingkungan/pengelolaan-sampah'; import colors from '@/con/colors'; -import { Box, Center, Flex, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core'; +import { Box, Center, Flex, Group, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core'; import { useDebouncedValue, useShallowEffect } from '@mantine/hooks'; -import { Icon, IconChartLine, IconClipboardTextFilled, IconLeaf, IconRecycle, IconScale, IconSearch, IconTent, IconTrashFilled, IconTrophy, IconTruckFilled } from '@tabler/icons-react'; +import { Icon, IconChartLine, IconClipboardTextFilled, IconLeaf, IconRecycle, IconRoute, IconScale, IconSearch, IconTent, IconTrashFilled, IconTrophy, IconTruckFilled } from '@tabler/icons-react'; import React, { useState } from 'react'; import { useProxy } from 'valtio/utils'; import BackButton from '../../desa/layanan/_com/BackButto'; @@ -122,20 +122,28 @@ function Page() { {data2?.map((v, k) => ( - {v.namaTempatMaps} - {v.alamat} - {v.lat && v.lng ? ( - - ๐Ÿ“Œ Buka di Google Maps - - ) : ( - Koordinat belum tersedia - )} + + + {v.namaTempatMaps} + {v.alamat} + + + + Rute + + + {v.lat && v.lng ? ( + + ๐Ÿ“Œ Lihat Peta Lebih Besar + + ) : ( + Koordinat belum tersedia + )} ))} diff --git a/src/app/darmasaba/(pages)/pendidikan/data-pendidikan/page.tsx b/src/app/darmasaba/(pages)/pendidikan/data-pendidikan/page.tsx index 0772bd13..8c696b82 100644 --- a/src/app/darmasaba/(pages)/pendidikan/data-pendidikan/page.tsx +++ b/src/app/darmasaba/(pages)/pendidikan/data-pendidikan/page.tsx @@ -92,7 +92,7 @@ function Page() { cursor={{ fill: 'var(--mantine-color-gray-1)' }} /> - + diff --git a/src/app/darmasaba/(pages)/pendidikan/pendidikan-non-formal/page.tsx b/src/app/darmasaba/(pages)/pendidikan/pendidikan-non-formal/page.tsx index 0d08b1cf..6709e947 100644 --- a/src/app/darmasaba/(pages)/pendidikan/pendidikan-non-formal/page.tsx +++ b/src/app/darmasaba/(pages)/pendidikan/pendidikan-non-formal/page.tsx @@ -1,7 +1,7 @@ 'use client' import pendidikanNonFormalState from '@/app/admin/(dashboard)/_state/pendidikan/pendidikan-non-formal'; import colors from '@/con/colors'; -import { Box, Paper, SimpleGrid, Skeleton, Stack, Text, Title, Tooltip } from '@mantine/core'; +import { Box, Group, Paper, SimpleGrid, Skeleton, Stack, Text, Title, Tooltip } from '@mantine/core'; import { useShallowEffect } from '@mantine/hooks'; import { useProxy } from 'valtio/utils'; import { IconMapPin, IconTarget, IconBook2 } from '@tabler/icons-react'; @@ -59,13 +59,17 @@ function Page() { withBorder > - - - <IconTarget size={28} style={{ marginRight: 8 }} /> + <Group align="center" gap={8} wrap="nowrap"> + <Tooltip label="Fokus utama program" withArrow> + <Box display="flex" style={{ alignItems: "center" }}> + <IconTarget color={colors['blue-button']} size={26} /> + </Box> + </Tooltip> + <Text fw={700} fz="xl" c={colors['blue-button']}> {stateTujuanPendidikanNonFormal.findById.data?.judul} - - - + + + - - - <IconMapPin size={28} style={{ marginRight: 8 }} /> + <Group align="center" gap={8} wrap="nowrap"> + <Tooltip label="Lokasi pelaksanaan kegiatan" withArrow> + <Box display="flex" style={{ alignItems: "center" }}> + <IconMapPin color={colors['blue-button']} size={26} /> + </Box> + </Tooltip> + <Text fw={700} fz="xl" c={colors['blue-button']}> {stateTempatKegiatan.findById.data?.judul} - - - + + + @@ -95,13 +103,17 @@ function Page() { withBorder > - - - <IconBook2 size={28} style={{ marginRight: 8 }} /> + <Group align="center" gap={8} wrap="nowrap"> + <Tooltip label="Ragam jenis program yang tersedia" withArrow> + <Box display="flex" style={{ alignItems: "center" }}> + <IconBook2 color={colors['blue-button']} size={26} /> + </Box> + </Tooltip> + <Text fw={700} fz="xl" c={colors['blue-button']}> {stateJenisProgram.findById.data?.judul} - - - + + + diff --git a/src/app/darmasaba/(pages)/ppid/permohonan-informasi-publik/jenis_infromasi/jenisInformasiSelector.tsx b/src/app/darmasaba/(pages)/ppid/permohonan-informasi-publik/jenis_infromasi/jenisInformasiSelector.tsx index 3b81266f..95014e2c 100644 --- a/src/app/darmasaba/(pages)/ppid/permohonan-informasi-publik/jenis_infromasi/jenisInformasiSelector.tsx +++ b/src/app/darmasaba/(pages)/ppid/permohonan-informasi-publik/jenis_infromasi/jenisInformasiSelector.tsx @@ -32,7 +32,7 @@ export default function JenisInformasiSelector({ onChange }: { return ( ({ value: item.id, diff --git a/src/app/darmasaba/(pages)/ppid/permohonan-informasi-publik/salinan_informasi/salinanInformasi.tsx b/src/app/darmasaba/(pages)/ppid/permohonan-informasi-publik/salinan_informasi/salinanInformasi.tsx index c88dda51..5a42f163 100644 --- a/src/app/darmasaba/(pages)/ppid/permohonan-informasi-publik/salinan_informasi/salinanInformasi.tsx +++ b/src/app/darmasaba/(pages)/ppid/permohonan-informasi-publik/salinan_informasi/salinanInformasi.tsx @@ -26,7 +26,7 @@ function MemperolehSalinan({ onChange }: { return (