Files
desa-darmasaba/src/app/darmasaba/_com/main-page/landing-page/ModuleView.tsx

123 lines
3.2 KiB
TypeScript

"use client";
import profileLandingPageState from "@/app/admin/(dashboard)/_state/landing-page/profile";
import {
Box,
Center,
Image,
Paper,
ScrollArea,
SimpleGrid,
Skeleton,
Stack,
Text,
useMantineColorScheme
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { Prisma } from "@prisma/client";
import { IconPhotoOff } from "@tabler/icons-react";
import { motion } from "framer-motion";
import { useTransitionRouter } from "next-view-transitions";
import { useProxy } from "valtio/utils";
type ProgramInovasiItem = Prisma.ProgramInovasiGetPayload<{ include: { image: true } }>;
function ModuleItem({ data }: { data: ProgramInovasiItem }) {
const router = useTransitionRouter();
const { colorScheme } = useMantineColorScheme();
const isDark = colorScheme === "dark";
return (
<motion.div whileHover={{ scale: 1.03 }}>
<Paper
onClick={() => router.push(`/darmasaba/program-inovasi/${data.id}`)}
p="lg"
radius="xl"
shadow="sm"
role="button"
tabIndex={0}
className="cursor-pointer transition-all"
bg={isDark ? "dark.6" : "white"}
>
<Center h={160}>
{data.image?.link ? (
<Image
src={data.image.link}
alt={data.name}
radius="md"
fit="cover"
h={140}
w="100%"
loading="lazy"
/>
) : (
<Stack align="center" gap="xs">
<IconPhotoOff size={38} stroke={1.5} />
<Text size="sm" c="dimmed">
Belum ada gambar
</Text>
</Stack>
)}
</Center>
<Box mt="md">
<Text fw={600} ta="center" size="md">
{data.name}
</Text>
</Box>
</Paper>
</motion.div>
);
}
function ModuleView() {
const listImageState = useProxy(profileLandingPageState.programInovasi);
useShallowEffect(() => {
listImageState.findMany.load();
}, []);
if (listImageState.findMany.loading) {
return (
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="lg" mt="lg">
{Array.from({ length: 3 }).map((_, i) => (
<Skeleton key={i} height={220} radius="xl" />
))}
</SimpleGrid>
);
}
if (!listImageState.findMany.data?.length) {
return (
<Center h={320}>
<Stack align="center" gap="sm">
<IconPhotoOff size={54} stroke={1.5} />
<Text size="lg" fw={600}>
Belum ada program inovasi
</Text>
<Text size="sm" c="dimmed">
Tambahkan program inovasi untuk ditampilkan di sini
</Text>
</Stack>
</Center>
);
}
return (
<ScrollArea h={280} // ✅ tinggi fixed, bisa disesuaikan
scrollbarSize={2}
offsetScrollbars
styles={{
viewport: { paddingRight: 8 }, // kasih jarak biar scroll nggak dempet
}}
>
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="lg" mt="lg">
{listImageState.findMany.data?.map((item) => (
<ModuleItem key={item.id} data={item} />
))}
</SimpleGrid>
</ScrollArea>
);
}
export default ModuleView;