Tambahan fix menu prestasi desa

This commit is contained in:
2025-09-25 11:14:38 +08:00
parent cac146471a
commit d8fa56d923
2 changed files with 111 additions and 89 deletions

View File

@@ -1,47 +1,58 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import colors from '@/con/colors';
import { BackgroundImage, Box, Button, Center, Container, Group, Paper, SimpleGrid, Stack, Text } from '@mantine/core';
import BackButton from '../../(pages)/desa/layanan/_com/BackButto';
import { useRouter } from 'next/navigation';
import prestasiState from '@/app/admin/(dashboard)/_state/landing-page/prestasi-desa';
import colors from '@/con/colors';
import { BackgroundImage, Box, Button, Center, Group, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
import { useRouter } from 'next/navigation';
import { useProxy } from 'valtio/utils';
import { useEffect, useState } from 'react';
import BackButton from '../../(pages)/desa/layanan/_com/BackButto';
import { IconSearch } from '@tabler/icons-react';
import { useState } from 'react';
function Page() {
const state = useProxy(prestasiState.prestasiDesa);
const [loading, setLoading] = useState(true);
const [prestasiData, setPrestasiData] = useState<any[]>([]);
const router = useRouter();
const [search, setSearch] = useState("");
const [debouncedSearch] = useDebouncedValue(search, 500); // 500ms delay
const { data, page, totalPages, loading, load } = state.findMany;
useShallowEffect(() => {
load(page, 3, debouncedSearch)
}, [page, debouncedSearch])
if (loading || !data) {
return (
<Stack py={10}>
<Skeleton height={600} radius="md" />
</Stack>
)
}
useEffect(() => {
const loadData = async () => {
try {
setLoading(true);
await prestasiState.kategoriPrestasi.findMany.load();
await state.findMany.load();
setPrestasiData(state.findMany.data || []);
} catch (error) {
console.error('Error loading data:', error);
} finally {
setLoading(false);
}
};
loadData();
}, []);
return (
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"} >
<Box px={{ base: "md", md: 100 }}><BackButton /></Box>
<Container w={{ base: "100%", md: "50%" }}>
<Text ta={"center"} fz={"3.4rem"} c={colors["blue-button"]} fw={"bold"}>
Prestasi Desa
</Text>
<Text ta={"center"} py={10}>
Temukan berbagai prestasi dan keunggulan yang dimiliki Desa Darmasaba.
</Text>
</Container>
<Group justify='space-between' px={{ base: "md", md: 100 }}>
<Box>
<Text fz={"2.4rem"} c={colors["blue-button"]} fw={"bold"}>
Prestasi Desa
</Text>
<Text py={10}>
Temukan berbagai prestasi dan keunggulan yang dimiliki Desa Darmasaba.
</Text>
</Box>
<Box>
<TextInput
radius="xl"
placeholder="Cari prestasi atau kategori prestasi..."
value={search}
onChange={(e) => setSearch(e.target.value)}
leftSection={<IconSearch size={20} />}
w={300}
size="md"
/>
</Box>
</Group>
<SimpleGrid
px={{ base: "md", md: 100 }}
pb={20}
@@ -50,65 +61,77 @@ function Page() {
md: 3,
}}
>
{loading ? (
<Center>
<Text fz={"2.4rem"}>Memuat Data...</Text>
</Center>
{data.length === 0 ? (
<Text fz={"1.4rem"}>Tidak ada prestasi yang ditemukan</Text>
) : (
prestasiData.map((v, k) => {
data.map((v, k) => {
return (
<BackgroundImage
key={k}
src={v.image?.link}
radius={16}
pos={"relative"}
>
<Box
style={{
borderRadius: 16,
zIndex: 0
}}
pos={"absolute"}
w={"100%"}
h={"100%"}
bg={colors.trans.dark[2]}
/>
<Stack justify='space-between' h={"100%"} gap={0} p={"lg"} pos={"relative"}>
<Group>
<Paper radius={"lg"} py={7} px={10}>
<Text>{v.kategori?.name}</Text>
</Paper>
</Group>
<Box p={"lg"}>
<Text
fw={"bold"}
c={"white"}
size={"1.8rem"}
style={{
textAlign: "center",
lineHeight: 1.4,
minHeight: '5.4rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
lineClamp={3}
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
/>
</Box>
<Group justify="center">
<Button px={20} radius={"100"} size="md" bg={colors["blue-button"]}
onClick={() => router.push(`/darmasaba/prestasi-desa/${v.id}`)}>
Detail
</Button>
</Group>
</Stack>
</BackgroundImage>
)
})
)}
src={v.image?.link || ''}
radius={16}
pos={"relative"}
>
<Box
style={{
borderRadius: 16,
zIndex: 0
}}
pos={"absolute"}
w={"100%"}
h={"100%"}
bg={colors.trans.dark[2]}
/>
<Stack justify='space-between' h={"100%"} gap={0} p={"lg"} pos={"relative"}>
<Group>
<Paper radius={"lg"} py={7} px={10}>
<Text>{v.kategori?.name}</Text>
</Paper>
</Group>
<Box p={"lg"}>
<Text
fw={"bold"}
c={"white"}
size={"1.8rem"}
style={{
textAlign: "center",
lineHeight: 1.4,
minHeight: '5.4rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
lineClamp={3}
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
/>
</Box>
<Group justify="center">
<Button px={20} radius={"100"} size="md" bg={colors["blue-button"]}
onClick={() => router.push(`/darmasaba/prestasi-desa/${v.id}`)}>
Detail
</Button>
</Group>
</Stack>
</BackgroundImage>
)
})
)}
</SimpleGrid>
<Center>
<Pagination
value={page}
onChange={(newPage) => {
load(newPage, 10)
window.scrollTo({ top: 0, behavior: 'smooth' })
}}
total={totalPages}
mt="md"
mb="md"
color="blue"
radius="md"
/>
</Center>
</Stack>
);
}

View File

@@ -107,9 +107,8 @@ function ModuleView() {
return (
<ScrollArea h={280} // ✅ tinggi fixed, bisa disesuaikan
scrollbarSize={8}
scrollbarSize={2}
offsetScrollbars
type="never"
styles={{
viewport: { paddingRight: 8 }, // kasih jarak biar scroll nggak dempet
}}