Sinkronisasi UI Admin & User Menu Landing Page, Submenu Profile, SDGSDesa

This commit is contained in:
2025-08-04 10:29:13 +08:00
parent 54312e9486
commit 1cdff53c56
17 changed files with 490 additions and 72 deletions

View File

@@ -112,7 +112,7 @@ function Footer() {
</Box>
</Paper>
</Center>
<Box py={20}>
<Box py={20} >
<SimpleGrid
p={20}
cols={{
@@ -123,7 +123,7 @@ function Footer() {
color: "white"
}}
>
<Box p={mobile ? 30 : 30}>
<Box p={mobile ? 30 : 30} style={{color: "white"}}>
<Stack justify='space-between'>
<Text fz={"md"} fw={"bold"}>Tentang Darmasaba</Text>
<Text fz={"xs"} >Desa Darmasaba adalah desa

View File

@@ -1,11 +1,14 @@
import images from "@/con/images";
import { ActionIcon, Flex, Image } from "@mantine/core";
import { Prisma } from "@prisma/client";
import { useTransitionRouter } from "next-view-transitions";
function SosmedView() {
const listSosmed = Object.values(images.sosmed);
function SosmedView({data} : {data : Prisma.MediaSosialGetPayload<{ include: { image: true } }>[]}) {
const router = useTransitionRouter();
return (
<Flex gap={"md"} justify={"center"} align={"center"}>
{listSosmed.map((item, k) => {
{data?.map((item, k) => {
return (
<ActionIcon
variant="transparent"
@@ -13,8 +16,11 @@ function SosmedView() {
w={32}
h={32}
pos={"relative"}
onClick={() => {
router.push(item.iconUrl || "");
}}
>
<Image src={item} alt="icon" loading="lazy" />
<Image src={item.image?.link || ""} alt="icon" loading="lazy" />
</ActionIcon>
);
})}

View File

@@ -1,8 +1,10 @@
"use client";
import colors from "@/con/colors";
import { Prisma } from "@prisma/client";
import {
Box,
Card,
Skeleton,
Flex,
Grid,
GridCol,
@@ -11,9 +13,9 @@ import {
Stack,
Text
} from "@mantine/core";
import { useEffect, useState } from "react";
import ModuleView from "./ModuleView";
import SosmedView from "./SosmedView";
import { useEffect, useState } from "react";
const getDayOfWeek = () => {
const days = ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'];
@@ -56,6 +58,38 @@ const getWorkStatus = (day: string, currentTime: string): { status: string; mess
function LandingPage() {
const [socialMedia, setSocialMedia] = useState<Prisma.MediaSosialGetPayload<{ include: { image: true } }>[]>([]);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const fetchSocialMedia = async () => {
try {
const response = await fetch('/api/landingpage/mediasosial/findMany');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
// Ensure the data is an array before setting it
if (Array.isArray(result.data)) {
setSocialMedia(result.data);
} else if (Array.isArray(result)) {
// In case the API returns the array directly
setSocialMedia(result);
} else {
console.error('Unexpected API response format:', result);
setSocialMedia([]);
}
} catch (error) {
console.error('Error fetching social media:', error);
setSocialMedia([]); // Ensure we always have an array
} finally {
setIsLoading(false);
}
};
fetchSocialMedia();
}, []);
const [workStatus, setWorkStatus] = useState<{ status: string; message: string }>
({ status: '', message: '' });
@@ -248,7 +282,13 @@ function LandingPage() {
</Flex>
<ModuleView />
<SosmedView />
{isLoading ? (
<Skeleton height={32} width="100%" />
) : socialMedia.length > 0 ? (
<SosmedView data={socialMedia} />
) : (
<div>No social media links available</div>
)}
<Text c={colors.trans.dark[2]} style={{
textAlign: "center"
}} >Sampaikan saran dan masukan guna kemajuan dalam pembangunan. Semua lebih mudah melalui fitur interaktif</Text>

View File

@@ -1,12 +1,51 @@
'use client'
import colors from "@/con/colors";
import { Box, Button, Center, Container, Image, Paper, SimpleGrid, Stack, Text, useMantineTheme } from "@mantine/core";
import { Box, Button, Center, Container, Image, Paper, SimpleGrid, Stack, Text, Title, useMantineTheme } from "@mantine/core";
import { useMediaQuery } from "@mantine/hooks";
import { Prisma } from "@prisma/client";
import Link from "next/link";
import { useEffect, useState } from "react";
export default function SDGS() {
const theme = useMantineTheme();
const mobile = useMediaQuery(`(max-width: ${theme.breakpoints.sm})`);
const [sdgsDesa, setSdgsDesa] = useState<Prisma.SDGSDesaGetPayload<{ include: { image: true } }>[] | null>(null);
useEffect(() => {
const fetchSdgsDesa = async () => {
try {
const response = await fetch('/api/landingpage/sdgsdesa/findMany');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
// Ensure the data is an array before setting it
let data = [];
if (Array.isArray(result.data)) {
data = result.data;
} else if (Array.isArray(result)) {
// In case the API returns the array directly
data = result;
} else {
console.error('Unexpected API response format:', result);
setSdgsDesa([]);
return;
}
// Sort by jumlah in descending order and take top 3
const top3Sdgs = [...data]
.sort((a, b) => parseInt(b.jumlah) - parseInt(a.jumlah))
.slice(0, 3);
setSdgsDesa(top3Sdgs);
} catch (error) {
console.error('Error fetching sdgs desa:', error);
setSdgsDesa([]);
}
};
fetchSdgsDesa();
}, []);
return (
<Stack p={"sm"}>
<Container w={{ base: "100%", md: "80%" }} p={"xl"}>
@@ -16,22 +55,82 @@ export default function SDGS() {
<Text fz={"1.4rem"} ta={"center"}>SDGs Desa adalah upaya menerapkan 17 Tujuan Pembangunan Berkelanjutan di tingkat desa.
Dengan fokus pada pengentasan kemiskinan, pendidikan, kesehatan, kesetaraan gender, dan pelestarian lingkungan, kami berkomitmen untuk menciptakan desa yang lebih baik bagi semua</Text>
<Box py={50}>
<Paper p={"lg"} bg={colors.Bg}>
<SimpleGrid
cols={{
base: 1,
sm: 3,
}}>
<Center>
<Image src={"/api/img/sgdesa-1.png"} alt="" w={mobile ? 250 : 200} />
</Center>
<Center>
<Image src={"/api/img/sgdesa-2.png"} alt="" w={mobile ? 250 : 220} />
</Center>
<Center>
<Image src={"/api/img/sgdesa-3.png"} alt="" w={mobile ? 250 : 190} />
</Center>
</SimpleGrid>
<Paper p={{ base: 'md', md: 'xl' }} bg={colors.Bg} radius="lg" shadow="sm">
{sdgsDesa && sdgsDesa.length > 0 ? (
<SimpleGrid
cols={{ base: 1, sm: 3 }}
spacing="xl"
verticalSpacing="xl"
>
{sdgsDesa.map((item) => (
<Box
key={item.id}
p="md"
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '100%',
transition: 'transform 0.2s',
'&:hover': {
transform: 'translateY(-5px)'
}
}}
>
<Box
p="md"
style={{
backgroundColor: 'white',
width: mobile ? 150 : 180,
height: mobile ? 150 : 180,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginBottom: '1.5rem',
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)'
}}
>
<Image
src={item.image?.link ? item.image.link : '/placeholder-sdgs.png'}
alt={item.name}
width={mobile ? 100 : 120}
height={mobile ? 100 : 120}
style={{
objectFit: 'contain',
maxWidth: '100%',
maxHeight: '100%'
}}
/>
</Box>
<Text
ta="center"
fz={{ base: 'lg', md: 'xl' }}
fw={700}
mb="xs"
style={{ lineHeight: 1.2 }}
>
{item.name}
</Text>
<Title
order={2}
ta="center"
c={colors['blue-button']}
style={{
fontSize: mobile ? '2.5rem' : '3rem',
lineHeight: 1,
margin: '0.5rem 0',
fontWeight: 800
}}
>
{item.jumlah}
</Title>
</Box>
))}
</SimpleGrid>
) : (
<Text>Tidak ada data SDGs Desa</Text>
)}
</Paper>
<Center>
<Button component={Link} href={"/darmasaba/sdgs-desa"} radius={"lg"} fz={"1.2rem"} mt={20} bg={colors["blue-button"]}>Selengkapnya</Button>