Fix Menu Lingkungan Darmasaba User
This commit is contained in:
@@ -1,64 +1,81 @@
|
||||
import profileLandingPageState from "@/app/admin/(dashboard)/_state/landing-page/profile";
|
||||
import { Center, Image, Paper, SimpleGrid, Text } from "@mantine/core";
|
||||
import { Box, Center, Image, Paper, SimpleGrid, Stack, Text, Tooltip } from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTransitionRouter } from 'next-view-transitions';
|
||||
import { motion } from "framer-motion";
|
||||
import { useTransitionRouter } from "next-view-transitions";
|
||||
import { useProxy } from "valtio/utils";
|
||||
import { Prisma } from "@prisma/client";
|
||||
|
||||
import { IconPhotoOff } from "@tabler/icons-react";
|
||||
|
||||
type ProgramInovasiItem = Prisma.ProgramInovasiGetPayload<{ include: { image: true } }>;
|
||||
|
||||
function ModuleItem({ data }: { data: ProgramInovasiItem }) {
|
||||
const router = useTransitionRouter();
|
||||
return (
|
||||
<Paper
|
||||
onClick={() => {
|
||||
router.push(`/${data.name}`);
|
||||
}}
|
||||
p={"md"}
|
||||
bg={"white"}
|
||||
radius={"32"}
|
||||
pos={"relative"}
|
||||
>
|
||||
<Center h={"100%"}>
|
||||
<motion.div
|
||||
whileHover={{ scale: 1.05 }}
|
||||
<motion.div whileHover={{ scale: 1.04 }}>
|
||||
<Tooltip label={`Lihat ${data.name}`} withArrow>
|
||||
<Paper
|
||||
onClick={() => router.push(`/${data.name}`)}
|
||||
p="xl"
|
||||
radius="2xl"
|
||||
bg="white"
|
||||
className="cursor-pointer transition-all shadow-md hover:shadow-xl"
|
||||
>
|
||||
{data.image?.link ? (
|
||||
<Image src={data.image.link} alt="icon"
|
||||
fit="contain"
|
||||
sizes="100%"
|
||||
loading="lazy"
|
||||
style={{
|
||||
objectFit: "contain",
|
||||
objectPosition: "center"
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Text>
|
||||
-
|
||||
</Text>
|
||||
)}
|
||||
</motion.div>
|
||||
</Center>
|
||||
</Paper>
|
||||
<Center h={180}>
|
||||
{data.image?.link ? (
|
||||
<Image
|
||||
src={data.image.link}
|
||||
alt={data.name}
|
||||
fit="contain"
|
||||
radius="lg"
|
||||
loading="lazy"
|
||||
style={{ objectFit: "contain", objectPosition: "center" }}
|
||||
/>
|
||||
) : (
|
||||
<Stack align="center" gap="xs">
|
||||
<IconPhotoOff size={40} stroke={1.5} />
|
||||
<Text size="sm" c="dimmed">
|
||||
Belum ada gambar
|
||||
</Text>
|
||||
</Stack>
|
||||
)}
|
||||
</Center>
|
||||
<Box mt="md">
|
||||
<Text fw={600} ta="center" size="lg" c="black">
|
||||
{data.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Paper>
|
||||
</Tooltip>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
function ModuleView() {
|
||||
const listImageState = useProxy(profileLandingPageState.programInovasi)
|
||||
const listImageState = useProxy(profileLandingPageState.programInovasi);
|
||||
|
||||
useShallowEffect(() => {
|
||||
listImageState.findMany.load()
|
||||
}, [])
|
||||
listImageState.findMany.load();
|
||||
}, []);
|
||||
|
||||
if (!listImageState.findMany.loading && !listImageState.findMany.data?.length) {
|
||||
return (
|
||||
<Center h={320}>
|
||||
<Stack align="center" gap="sm">
|
||||
<IconPhotoOff size={54} stroke={1.5} />
|
||||
<Text size="lg" fw={600} c="white">
|
||||
Belum ada program inovasi
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
Tambahkan program inovasi untuk ditampilkan di sini
|
||||
</Text>
|
||||
</Stack>
|
||||
</Center>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SimpleGrid
|
||||
cols={{
|
||||
base: 2,
|
||||
md: 3,
|
||||
}}
|
||||
>
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="xl" mt="lg">
|
||||
{listImageState.findMany.data?.map((item) => (
|
||||
<ModuleItem key={item.id} data={item} />
|
||||
))}
|
||||
|
||||
@@ -1,15 +1,28 @@
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Card, Image, Stack, Text } from '@mantine/core';
|
||||
import { Box, Card, Image, Stack, Text, Tooltip } from '@mantine/core';
|
||||
import { IconUserCircle } from '@tabler/icons-react';
|
||||
import React from 'react';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import colors from '@/con/colors';
|
||||
|
||||
interface ProfileViewProps {
|
||||
data: Prisma.PejabatDesaGetPayload<{ include: { image: true } }> | null;
|
||||
}
|
||||
|
||||
function ProfileView({ data }: ProfileViewProps) {
|
||||
export default function ProfileView({ data }: ProfileViewProps) {
|
||||
if (!data) {
|
||||
return <div>No profile data available</div>;
|
||||
return (
|
||||
<Card radius="2xl" className="glass3" py="xl" px="lg" withBorder>
|
||||
<Stack align="center" gap="sm">
|
||||
<IconUserCircle size={72} stroke={1.4} />
|
||||
<Text fw={500} c="dimmed">
|
||||
Profil belum tersedia
|
||||
</Text>
|
||||
<Text fz="sm" c="dimmed">
|
||||
Data pejabat desa akan muncul di sini
|
||||
</Text>
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -17,42 +30,38 @@ function ProfileView({ data }: ProfileViewProps) {
|
||||
justify="end"
|
||||
align="end"
|
||||
pos="relative"
|
||||
w={{
|
||||
base: "100%",
|
||||
md: "40%",
|
||||
}}
|
||||
w={{ base: '100%', md: '40%' }}
|
||||
px="xl"
|
||||
>
|
||||
{data.image?.link ? (
|
||||
<Image
|
||||
src={data.image.link}
|
||||
alt={data.name || "Profile image"}
|
||||
sizes="100%"
|
||||
fit="contain"
|
||||
alt={data.name || 'Foto profil'}
|
||||
fit="cover"
|
||||
radius="lg"
|
||||
/>
|
||||
): (
|
||||
<Text>
|
||||
-
|
||||
</Text>
|
||||
) : (
|
||||
<Stack align="center" gap="xs" w="100%" py="xl">
|
||||
<IconUserCircle size={96} stroke={1.5} />
|
||||
<Text c="dimmed" fz="sm">
|
||||
Belum ada foto
|
||||
</Text>
|
||||
</Stack>
|
||||
)}
|
||||
<Box
|
||||
pos="absolute"
|
||||
bottom={0}
|
||||
p={{
|
||||
base: "xs",
|
||||
md: "md",
|
||||
}}
|
||||
>
|
||||
<Box pos="absolute" bottom={0} w="100%" p={{ base: 'xs', md: 'md' }}>
|
||||
<Card
|
||||
px="lg"
|
||||
radius="32"
|
||||
radius="2xl"
|
||||
withBorder
|
||||
className="glass3"
|
||||
style={{
|
||||
border: `1px solid white`,
|
||||
}}
|
||||
style={{ border: '1px solid rgba(255,255,255,0.15)' }}
|
||||
>
|
||||
<Text>{data.position}</Text>
|
||||
<Text c={colors["blue-button"]} fw="bolder" fz="1rem">
|
||||
<Tooltip label="Jabatan Resmi" withArrow>
|
||||
<Text fz="sm" c="dimmed">
|
||||
{data.position || 'Tidak ada jabatan'}
|
||||
</Text>
|
||||
</Tooltip>
|
||||
<Text c={colors['blue-button']} fw={700} fz="xl" mt={4}>
|
||||
{data.name}
|
||||
</Text>
|
||||
</Card>
|
||||
@@ -60,5 +69,3 @@ function ProfileView({ data }: ProfileViewProps) {
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProfileView;
|
||||
@@ -1,35 +1,79 @@
|
||||
import { ActionIcon, Flex, Image, Text } from "@mantine/core";
|
||||
import { ActionIcon, Card, Flex, Image, Text, Tooltip } from "@mantine/core";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { useTransitionRouter } from "next-view-transitions";
|
||||
import { IconBrandInstagram, IconBrandFacebook, IconBrandTwitter, IconWorld } from "@tabler/icons-react";
|
||||
|
||||
|
||||
|
||||
function SosmedView({data} : {data : Prisma.MediaSosialGetPayload<{ include: { image: true } }>[]}) {
|
||||
function SosmedView({
|
||||
data,
|
||||
}: {
|
||||
data: Prisma.MediaSosialGetPayload<{ include: { image: true } }>[];
|
||||
}) {
|
||||
const router = useTransitionRouter();
|
||||
|
||||
const fallbackIcon = (platform?: string) => {
|
||||
switch (platform?.toLowerCase()) {
|
||||
case "instagram":
|
||||
return <IconBrandInstagram size={22} />;
|
||||
case "facebook":
|
||||
return <IconBrandFacebook size={22} />;
|
||||
case "twitter":
|
||||
return <IconBrandTwitter size={22} />;
|
||||
default:
|
||||
return <IconWorld size={22} />;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex gap={"md"} justify={"center"} align={"center"}>
|
||||
{data?.map((item, k) => {
|
||||
return (
|
||||
<Flex gap="lg" justify="center" align="center" wrap="wrap">
|
||||
{data && data.length > 0 ? (
|
||||
data.map((item, k) => (
|
||||
<Tooltip
|
||||
key={k}
|
||||
label={item.name || "Tautan Sosial"}
|
||||
withArrow
|
||||
position="top"
|
||||
transitionProps={{ transition: "pop", duration: 150 }}
|
||||
>
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
key={k}
|
||||
w={32}
|
||||
h={32}
|
||||
pos={"relative"}
|
||||
onClick={() => {
|
||||
router.push(item.iconUrl || "");
|
||||
variant="light"
|
||||
radius="xl"
|
||||
size="xl"
|
||||
onClick={() => item.iconUrl && router.push(item.iconUrl)}
|
||||
style={{
|
||||
transition: "all 0.3s ease",
|
||||
boxShadow: "0 0 12px rgba(28, 110, 164, 0.6)",
|
||||
}}
|
||||
>
|
||||
{item.image?.link ? (
|
||||
<Image src={item.image.link} alt="icon" loading="lazy" />
|
||||
<Image
|
||||
src={item.image.link}
|
||||
alt={item.name || "ikon"}
|
||||
w={24}
|
||||
h={24}
|
||||
fit="contain"
|
||||
loading="lazy"
|
||||
/>
|
||||
) : (
|
||||
<Text>
|
||||
none
|
||||
</Text>
|
||||
fallbackIcon(item.name)
|
||||
)}
|
||||
</ActionIcon>
|
||||
);
|
||||
})}
|
||||
</Tooltip>
|
||||
))
|
||||
) : (
|
||||
<Card
|
||||
shadow="md"
|
||||
radius="xl"
|
||||
p="lg"
|
||||
withBorder
|
||||
style={{
|
||||
background: "linear-gradient(135deg, #1C6EA4 0%, #000 100%)",
|
||||
}}
|
||||
>
|
||||
<Text ta="center" c="dimmed" size="sm">
|
||||
Belum ada media sosial yang terhubung
|
||||
</Text>
|
||||
</Card>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,79 +11,77 @@ import {
|
||||
Image,
|
||||
Paper,
|
||||
Stack,
|
||||
Text
|
||||
Text,
|
||||
Center,
|
||||
Tooltip,
|
||||
Badge,
|
||||
} from "@mantine/core";
|
||||
import { IconCalendarTime, IconInfoCircle } from "@tabler/icons-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import ModuleView from "./ModuleView";
|
||||
import SosmedView from "./SosmedView";
|
||||
import ProfileView from "./ProfileView";
|
||||
|
||||
const getDayOfWeek = () => {
|
||||
const days = ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'];
|
||||
const days = ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"];
|
||||
const today = new Date();
|
||||
return days[today.getDay()];
|
||||
}
|
||||
};
|
||||
|
||||
const getCurrentTime = () => {
|
||||
const now = new Date();
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, "0");
|
||||
const minutes = String(now.getMinutes()).padStart(2, "0");
|
||||
return `${hours}:${minutes}`;
|
||||
}
|
||||
};
|
||||
|
||||
const isWorkingHours = (currentTime: string): boolean => {
|
||||
const [openTime, closeTime] = ['08:00', '16:00'];
|
||||
|
||||
const [openTime, closeTime] = ["08:00", "16:00"];
|
||||
const compareTimes = (time1: string, time2: string) => {
|
||||
const [hour1, minute1] = time1.split(':').map(Number);
|
||||
const [hour2, minute2] = time2.split(':').map(Number);
|
||||
|
||||
const [hour1, minute1] = time1.split(":").map(Number);
|
||||
const [hour2, minute2] = time2.split(":").map(Number);
|
||||
if (hour1 < hour2) return true;
|
||||
if (hour1 > hour2) return false;
|
||||
return minute1 <= minute2;
|
||||
};
|
||||
return compareTimes(currentTime, closeTime) && !compareTimes(currentTime, openTime);
|
||||
}
|
||||
};
|
||||
|
||||
const getWorkStatus = (day: string, currentTime: string): { status: string; message: string } => {
|
||||
const workingDays = ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat'];
|
||||
|
||||
const workingDays = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat"];
|
||||
if (!workingDays.includes(day)) {
|
||||
return {
|
||||
status: 'Tutup',
|
||||
message: 'Sabtu - Minggu'
|
||||
}
|
||||
return { status: "Tutup", message: "Libur Akhir Pekan" };
|
||||
}
|
||||
const isOpen = isWorkingHours(currentTime)
|
||||
return isOpen ? { status: 'Buka', message: '08:00 - 16:00' } : { status: 'Tutup', message: '08:00 - 16:00' };
|
||||
}
|
||||
|
||||
const isOpen = isWorkingHours(currentTime);
|
||||
return isOpen
|
||||
? { status: "Buka", message: "08:00 - 16:00" }
|
||||
: { status: "Tutup", message: "08:00 - 16:00" };
|
||||
};
|
||||
|
||||
function LandingPage() {
|
||||
const [socialMedia, setSocialMedia] = useState<Prisma.MediaSosialGetPayload<{ include: { image: true } }>[]>([]);
|
||||
const [profile, setProfile] = useState<Prisma.PejabatDesaGetPayload<{ include: { image: true } }> | null>(null);
|
||||
const [socialMedia, setSocialMedia] = useState<
|
||||
Prisma.MediaSosialGetPayload<{ include: { image: true } }>[]
|
||||
>([]);
|
||||
const [profile, setProfile] = useState<
|
||||
Prisma.PejabatDesaGetPayload<{ include: { image: true } }> | null
|
||||
>(null);
|
||||
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 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
|
||||
} catch {
|
||||
setSocialMedia([]);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -92,22 +90,22 @@ function LandingPage() {
|
||||
const fetchProfile = async () => {
|
||||
try {
|
||||
const response = await fetch(`/api/landingpage/pejabatdesa/edit`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||
const result = await response.json();
|
||||
setProfile(result.data || null); // Handle single object response
|
||||
} catch (error) {
|
||||
console.error('Error fetching profile:', error);
|
||||
setProfile(result.data || null);
|
||||
} catch {
|
||||
setProfile(null);
|
||||
}
|
||||
};
|
||||
|
||||
fetchSocialMedia();
|
||||
fetchProfile();
|
||||
}, []);
|
||||
|
||||
const [workStatus, setWorkStatus] = useState<{ status: string; message: string }>
|
||||
({ status: '', message: '' });
|
||||
const [workStatus, setWorkStatus] = useState<{ status: string; message: string }>({
|
||||
status: "",
|
||||
message: "",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const updateWorkStatus = () => {
|
||||
@@ -115,212 +113,110 @@ function LandingPage() {
|
||||
const time = getCurrentTime();
|
||||
const status = getWorkStatus(day, time);
|
||||
setWorkStatus(status);
|
||||
}
|
||||
};
|
||||
updateWorkStatus();
|
||||
const intervalId = setInterval(updateWorkStatus, 60 * 1000);
|
||||
return () => clearInterval(intervalId);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Stack bg={colors["Bg"]}>
|
||||
<Flex
|
||||
gap={"md"}
|
||||
wrap={{
|
||||
base: "wrap",
|
||||
md: "nowrap",
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
gap={"xl"}
|
||||
w={{
|
||||
base: "100%",
|
||||
md: "60%",
|
||||
}}
|
||||
py={{
|
||||
base: "xs",
|
||||
md: "40",
|
||||
}}
|
||||
px={{
|
||||
base: "xs",
|
||||
md: "100",
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
radius={"32"}
|
||||
bg={colors.grey[1]}
|
||||
p={{
|
||||
base: "xs",
|
||||
md: "32",
|
||||
}}
|
||||
>
|
||||
<Stack gap={42}>
|
||||
<Flex
|
||||
gap={"md"}
|
||||
wrap={{
|
||||
base: "wrap",
|
||||
md: "nowrap",
|
||||
}}
|
||||
>
|
||||
<Grid
|
||||
>
|
||||
<Grid.Col span={{
|
||||
base: 3,
|
||||
lg: 2,
|
||||
md: 3,
|
||||
}}>
|
||||
<Box
|
||||
pos={"relative"}
|
||||
bg={"white"}
|
||||
w={{
|
||||
base: 64,
|
||||
md: 72,
|
||||
}}
|
||||
h={{
|
||||
base: 64,
|
||||
md: 72,
|
||||
}}
|
||||
style={{
|
||||
borderRadius: 24,
|
||||
}}
|
||||
p={"sm"}
|
||||
>
|
||||
<Image
|
||||
src={"/darmasaba-icon.png"}
|
||||
alt="icon"
|
||||
sizes="100%"
|
||||
/>
|
||||
<Stack bg={colors.Bg} p="md" gap="xl">
|
||||
<Flex gap="lg" wrap={{ base: "wrap", md: "nowrap" }}>
|
||||
<Stack w={{ base: "100%", md: "65%" }} gap="lg">
|
||||
<Card radius="xl" bg={colors.grey[1]} p="lg" shadow="xl">
|
||||
<Stack gap="xl">
|
||||
<Flex gap="md" wrap="wrap">
|
||||
<Grid w="100%">
|
||||
<Grid.Col span={{ base: 3, sm: 2 }}>
|
||||
<Box bg="white" w={72} h={72} p="sm" style={{ borderRadius: 24 }}>
|
||||
<Image src="/darmasaba-icon.png" alt="Logo Darmasaba" fit="contain" />
|
||||
</Box>
|
||||
</Grid.Col>
|
||||
|
||||
<Grid.Col span={{
|
||||
base: 3,
|
||||
lg: 2,
|
||||
md: 3,
|
||||
}}>
|
||||
<Box
|
||||
pos={"relative"}
|
||||
w={{
|
||||
base: 64,
|
||||
md: 72,
|
||||
}}
|
||||
h={{
|
||||
base: 64,
|
||||
md: 72,
|
||||
}}
|
||||
style={{
|
||||
borderRadius: 24,
|
||||
}}
|
||||
p={"sm"}
|
||||
bg={"white"}
|
||||
>
|
||||
<Image
|
||||
src={"/pudak-icon.png"}
|
||||
alt="icon"
|
||||
sizes={"100%"}
|
||||
fit="contain"
|
||||
/>
|
||||
<Grid.Col span={{ base: 9, sm: 10 }}>
|
||||
<Box bg="white" w={72} h={72} p="sm" style={{ borderRadius: 24 }}>
|
||||
<Image src="/pudak-icon.png" alt="Logo Pudak" fit="contain" />
|
||||
</Box>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{
|
||||
base: 12,
|
||||
lg: 12,
|
||||
md: 12,
|
||||
}}>
|
||||
<Grid.Col span={12}>
|
||||
<Paper
|
||||
pos={"relative"}
|
||||
bg={colors["blue-button"]}
|
||||
p={10}
|
||||
w={{ base: "100%", sm: "auto", md: "auto" }}
|
||||
flex={{ base: "1", sm: "1", md: "1" }}
|
||||
p="md"
|
||||
radius="lg"
|
||||
shadow="md"
|
||||
style={{ position: "relative", overflow: "hidden" }}
|
||||
>
|
||||
<Grid
|
||||
>
|
||||
<GridCol span={{
|
||||
base: 12,
|
||||
lg: 6,
|
||||
md: 6,
|
||||
}}>
|
||||
<Box>
|
||||
<Text c={colors["white-1"]} fz={"sm"}>
|
||||
Jadwal Kerja
|
||||
</Text>
|
||||
<Paper
|
||||
w={{ base: "100%", sm: "100%", md: "auto" }}
|
||||
p={5}
|
||||
bg={colors["white-1"]}
|
||||
>
|
||||
<Flex justify={"space-between"} align={"center"}>
|
||||
<Paper
|
||||
w={{ base: "100%", sm: "100%", md: "auto" }}
|
||||
p={5}
|
||||
bg={colors["white-1"]}
|
||||
<Grid gutter="md">
|
||||
<GridCol span={{ base: 12, md: 6 }}>
|
||||
<Stack gap="xs">
|
||||
<Flex align="center" gap="xs">
|
||||
<IconCalendarTime size={16} color="white" />
|
||||
<Text c="white" fz="sm">Jam Operasional</Text>
|
||||
</Flex>
|
||||
<Paper p="sm" radius="md" bg="white">
|
||||
<Tooltip label="Status saat ini berdasarkan jam operasional kantor">
|
||||
<Badge
|
||||
color={workStatus.status === "Buka" ? "green" : "red"}
|
||||
radius="sm"
|
||||
variant="filled"
|
||||
>
|
||||
|
||||
<Box>
|
||||
<Text fw="bold" fz="sm" c={workStatus.status === 'Buka' ? "black" : "red"}>
|
||||
{workStatus.status}
|
||||
</Text>
|
||||
<Text fw="bold" fz="lg" >
|
||||
{workStatus.message}
|
||||
</Text>
|
||||
</Box>
|
||||
</Paper>
|
||||
</Flex>
|
||||
{workStatus.status}
|
||||
</Badge>
|
||||
</Tooltip>
|
||||
<Text fw="bold" fz="lg">{workStatus.message}</Text>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Stack>
|
||||
</GridCol>
|
||||
{/* Edit yang ini */}
|
||||
<GridCol span={{ base: 12, lg: 6, md: 6 }}>
|
||||
<Box>
|
||||
<Text c={colors["white-1"]} fz={"sm"}>
|
||||
{new Intl.DateTimeFormat('id-ID', {
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
}).format(new Date())}
|
||||
</Text>
|
||||
<Paper bg={colors["white-1"]} p={10}>
|
||||
<Text fz="sm" >
|
||||
Status
|
||||
</Text>
|
||||
<Text fw="bold" fz="lg" >
|
||||
{workStatus.status === 'Buka' ? 'Operasional' : 'Tutup'}
|
||||
<GridCol span={{ base: 12, md: 6 }}>
|
||||
<Stack gap="xs">
|
||||
<Flex align="center" gap="xs">
|
||||
<IconInfoCircle size={16} color="white" />
|
||||
<Text c="white" fz="sm">Hari Ini</Text>
|
||||
</Flex>
|
||||
<Paper p="sm" radius="md" bg="white">
|
||||
<Text fz="sm">Status Kantor</Text>
|
||||
<Text fw="bold" fz="lg">
|
||||
{workStatus.status === "Buka" ? "Sedang Beroperasi" : "Tidak Beroperasi"}
|
||||
</Text>
|
||||
</Paper>
|
||||
|
||||
</Box>
|
||||
</Stack>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
</Paper>
|
||||
</Grid.Col>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Flex>
|
||||
|
||||
<ModuleView />
|
||||
|
||||
{isLoading ? (
|
||||
<Skeleton height={32} width="100%" />
|
||||
) : socialMedia.length > 0 ? (
|
||||
<SosmedView data={socialMedia} />
|
||||
) : (
|
||||
<div>No social media links available</div>
|
||||
<Center>
|
||||
<Text c="dimmed">Belum ada tautan media sosial yang tersedia</Text>
|
||||
</Center>
|
||||
)}
|
||||
<Text c={colors.trans.dark[2]} style={{
|
||||
textAlign: "center"
|
||||
}} >Sampaikan saran dan masukan guna kemajuan dalam pembangunan. Semua lebih mudah melalui fitur interaktif</Text>
|
||||
|
||||
<Text ta="center" c={colors.trans.dark[2]}>
|
||||
Bagikan ide, kritik, atau saran Anda untuk mendukung pembangunan desa.
|
||||
Semua lebih mudah dengan fitur interaktif yang kami sediakan.
|
||||
</Text>
|
||||
</Stack>
|
||||
</Card>
|
||||
|
||||
</Stack>
|
||||
|
||||
{isLoading ? (
|
||||
<Skeleton height={32} width="100%" />
|
||||
<Skeleton height={300} width="100%" radius="lg" />
|
||||
) : profile ? (
|
||||
<ProfileView data={profile} />
|
||||
) : (
|
||||
<div>No profile available</div>
|
||||
<Center w="100%">
|
||||
<Text c="dimmed">Informasi profil belum tersedia</Text>
|
||||
</Center>
|
||||
)}
|
||||
</Flex>
|
||||
</Stack >
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user