Penambahan fungsi search disetiap menu & submenu,
Menu Landing Page Menu PPID Menu Desa
This commit is contained in:
@@ -121,13 +121,13 @@ function Page() {
|
||||
</Badge>
|
||||
</Group>
|
||||
<Text fz="sm" c="dimmed">
|
||||
Diposting: 12 Februari 2025 · Dinas Kesehatan
|
||||
Diposting: {v.createdAt.toLocaleDateString()}
|
||||
</Text>
|
||||
<Divider />
|
||||
<Text fz="sm" lh={1.5}>
|
||||
<Text fz="sm" lh={1.5} lineClamp={3} truncate="end">
|
||||
{v.deskripsiSingkat}
|
||||
</Text>
|
||||
<Button variant="light" radius="md" size="md" onClick={() => router.push(`/admin/kesehatan/info-wabah-penyakit/${v.id}`)}>
|
||||
<Button variant="light" radius="md" size="md" onClick={() => router.push(`/darmasaba/kesehatan/info-wabah-penyakit/${v.id}`)}>
|
||||
Selengkapnya
|
||||
</Button>
|
||||
</Stack>
|
||||
|
||||
@@ -97,18 +97,23 @@ function Page() {
|
||||
shadow="sm"
|
||||
withBorder
|
||||
bg={colors['white-trans-1']}
|
||||
style={{ transition: 'all 0.3s ease' }}
|
||||
style={{
|
||||
transition: 'all 0.3s ease',
|
||||
transform: 'translateY(0)',
|
||||
}}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.transform = 'translateY(-5px)')}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.transform = 'translateY(0)')}
|
||||
>
|
||||
<Stack align="center" gap="md">
|
||||
<Center>
|
||||
<Image
|
||||
src={v.image.link}
|
||||
alt={v.name}
|
||||
w={160}
|
||||
h={160}
|
||||
fit="contain"
|
||||
h={180}
|
||||
w="100%"
|
||||
radius="md"
|
||||
loading="lazy"
|
||||
fit="cover"
|
||||
style={{ aspectRatio: '4/3' }}
|
||||
/>
|
||||
</Center>
|
||||
<Stack gap={4} w="100%">
|
||||
@@ -151,8 +156,11 @@ function Page() {
|
||||
styles={{
|
||||
control: {
|
||||
border: `1px solid ${colors['blue-button']}`,
|
||||
transition: 'all 0.3s ease',
|
||||
'&:hover': { backgroundColor: colors['blue-button'], color: 'white' },
|
||||
},
|
||||
}}
|
||||
|
||||
/>
|
||||
</Center>
|
||||
|
||||
|
||||
@@ -28,11 +28,31 @@ export default function Page() {
|
||||
|
||||
if (data.length === 0) {
|
||||
return (
|
||||
<Box py="xl" px={{ base: "md", md: 100 }}>
|
||||
<Text fz="lg" fw="bold" c={colors["blue-button"]}>
|
||||
Tidak ada posyandu yang ditemukan
|
||||
</Text>
|
||||
</Box>
|
||||
<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>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import stateNav from "@/state/state-nav";
|
||||
import { Container, Stack, TextInput, Tooltip } from "@mantine/core";
|
||||
import { IconSearch } from "@tabler/icons-react";
|
||||
import { Container, Stack, Tooltip } from "@mantine/core";
|
||||
import GlobalSearch from "./globalSearch";
|
||||
|
||||
export function NavbarSearch() {
|
||||
return (
|
||||
@@ -12,14 +12,7 @@ export function NavbarSearch() {
|
||||
>
|
||||
<Stack pt="xl">
|
||||
<Tooltip label="Type to search across the site" position="bottom-start" withArrow>
|
||||
<TextInput
|
||||
autoFocus
|
||||
size="lg"
|
||||
variant="filled"
|
||||
radius="xl"
|
||||
placeholder="Search anything..."
|
||||
leftSection={<IconSearch size={20} />}
|
||||
/>
|
||||
<GlobalSearch />
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</Container>
|
||||
|
||||
97
src/app/darmasaba/_com/globalSearch.tsx
Normal file
97
src/app/darmasaba/_com/globalSearch.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
'use client';
|
||||
import { TextInput, Loader, Stack, Box, Text } from '@mantine/core';
|
||||
import { useSnapshot } from 'valtio';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect } from 'react';
|
||||
import searchState from '@/app/api/[[...slugs]]/_lib/search/searchState';
|
||||
|
||||
// Mapping type ke URL
|
||||
const getDetailUrl = (item: { type?: string; id: string | number; [key: string]: unknown }) => {
|
||||
const { type, id, kategori } = item;
|
||||
|
||||
const typeUrlMap: Record<string, string> = {
|
||||
programinovasi: `/darmasaba/program-inovasi/${id}`,
|
||||
desaantikorupsi: '/darmasaba/desa-anti-korupsi',
|
||||
sdgsdesa: '/darmasaba/sdgs-desa',
|
||||
apbdes: '/darmasaba/apbdes',
|
||||
prestasidesa: '/darmasaba/prestasi-desa',
|
||||
pejabatdesa: '/darmasaba/profile/pejabat-desa',
|
||||
strukturppid: '/darmasaba/ppid/struktur-ppid',
|
||||
visimisippid: '/darmasaba/ppid/visi-misi',
|
||||
dasarhukumppid: '/darmasaba/ppid/dasar-hukum',
|
||||
profileppid: '/darmasaba/ppid/profile',
|
||||
daftarinformasipublik: '/darmasaba/ppid/daftar-informasi-publik',
|
||||
perbekeldarmasaba: '/darmasaba/desa/profile',
|
||||
berita: `/darmasaba/desa/berita/${kategori}/${id}`,
|
||||
pengumuman: `/darmasaba/desa/pengumuman/${kategori}/${id}`,
|
||||
sejarahdesa: '/darmasaba/desa/profile',
|
||||
visimisidesa: '/darmasaba/desa/profile',
|
||||
lambangdesa: '/darmasaba/desa/profile',
|
||||
maskotdesa: '/darmasaba/desa/profile',
|
||||
profilperbekel: '/darmasaba/desa/profile',
|
||||
potensi: '/darmasaba/desa/potensi-desa',
|
||||
galleryFoto: '/darmasaba/desa/gallery/foto',
|
||||
galleryVideo: '/darmasaba/desa/gallery/video',
|
||||
pelayananSuratKeterangan: '/darmasaba/desa/layanan',
|
||||
pelayananPerizinanBerusaha: '/darmasaba/desa/layanan',
|
||||
pelayananTelunjukSaktiDesa: '/darmasaba/desa/layanan',
|
||||
pelayananPendudukNonPermanent: '/darmasaba/desa/layanan',
|
||||
penghargaan: '/darmasaba/desa/penghargaan',
|
||||
};
|
||||
|
||||
return type ? typeUrlMap[type] || '/darmasaba' : '/darmasaba';
|
||||
};
|
||||
|
||||
|
||||
export default function GlobalSearch() {
|
||||
const snap = useSnapshot(searchState);
|
||||
const router = useRouter();
|
||||
|
||||
// Infinite scroll listener
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
const bottom =
|
||||
window.innerHeight + window.scrollY >= document.body.offsetHeight - 200;
|
||||
if (bottom && !snap.loading) searchState.next();
|
||||
};
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
return () => window.removeEventListener('scroll', handleScroll);
|
||||
}, [snap.loading]);
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<TextInput
|
||||
placeholder="Cari apapun..."
|
||||
value={snap.query}
|
||||
onChange={(e) => (searchState.query = e.currentTarget.value)}
|
||||
/>
|
||||
|
||||
{snap.results.map((item, i) => (
|
||||
<Box
|
||||
key={i}
|
||||
p="sm"
|
||||
style={{
|
||||
borderBottom: '1px solid #eee',
|
||||
cursor: 'pointer',
|
||||
transition: 'background 0.2s',
|
||||
}}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.background = '#f5f5f5')}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}
|
||||
onClick={() => {
|
||||
const url = getDetailUrl(item);
|
||||
router.push(url);
|
||||
}}
|
||||
>
|
||||
<Text size="sm" fw={500}>
|
||||
{item.judul || item.namaPasar || item.nama || item.name}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed">
|
||||
dari modul: {item.type}
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
|
||||
{snap.loading && <Loader size="sm" />}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user