Sinkronisasi UI & API Admin - User Submenu Pengumuman
This commit is contained in:
@@ -46,11 +46,15 @@ const category = proxy({
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: [] as Prisma.CategoryPengumumanGetPayload<{
|
||||
data: [] as (Prisma.CategoryPengumumanGetPayload<{
|
||||
omit: {
|
||||
isActive: true;
|
||||
};
|
||||
}>[],
|
||||
}> & {
|
||||
_count: {
|
||||
pengumumans: number;
|
||||
};
|
||||
})[],
|
||||
loading: false,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.kategoripengumuman["findMany"].get();
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
async function kategoriPengumumanFindMany() {
|
||||
const data = await prisma.categoryPengumuman.findMany();
|
||||
const data = await prisma.categoryPengumuman.findMany({
|
||||
include: {
|
||||
_count: {
|
||||
select: {
|
||||
pengumumans: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return { data };
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import colors from '@/con/colors';
|
||||
import { Calendar } from '@mantine/dates';
|
||||
import { Stack, Box, Container, Text, Grid, Paper, GridCol, Center, SimpleGrid } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import BackButton from '../../../layanan/_com/BackButto';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="md">
|
||||
{/* Header */}
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Container size="lg" px="md" >
|
||||
<Stack gap="0" >
|
||||
<Text fz={{ base: "2rem", md: "3.4rem" }} c={colors["blue-button"]} fw="bold" >
|
||||
Jadwal Rapat
|
||||
</Text>
|
||||
</Stack>
|
||||
</Container>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Grid>
|
||||
<GridCol span={{ base: 12, md: 6, lg: 5, xl: 4 }} >
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Center>
|
||||
<Calendar size='xl' />
|
||||
</Center>
|
||||
</Paper>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 6, lg: 7, xl: 8 }} >
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<SimpleGrid
|
||||
cols={{
|
||||
base: 1,
|
||||
xl: 3,
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Text fz={'lg'} fw={'bold'} c={colors['blue-button']}>Hari Ini</Text>
|
||||
<Text fz={'lg'} >Senin, 13 Februari 2023</Text>
|
||||
<Text fz={'lg'} >09:00 - 12:00</Text>
|
||||
<Text fz={'lg'} >12:00 - 15:00</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fz={'lg'} fw={'bold'} c={colors['blue-button']}>Besok</Text>
|
||||
<Text fz={'lg'} >Selasa, 14 Februari 2023</Text>
|
||||
<Text fz={'lg'} >09:00 - 12:00</Text>
|
||||
<Text fz={'lg'} >12:00 - 15:00</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fz={'lg'} fw={'bold'} c={colors['blue-button']}>Minggu Depan</Text>
|
||||
<Text fz={'lg'} >Senin, 20 Februari 2023</Text>
|
||||
<Text fz={'lg'} >09:00 - 12:00</Text>
|
||||
<Text fz={'lg'} >12:00 - 15:00</Text>
|
||||
</Box>
|
||||
</SimpleGrid>
|
||||
</Paper>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
@@ -1,49 +0,0 @@
|
||||
import colors from '@/con/colors';
|
||||
import { Stack, Box, Container, Text, Image, Grid, GridCol, Paper, TextInput, Center, Button } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import BackButton from '../../../layanan/_com/BackButto';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="md">
|
||||
{/* Header */}
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Container size="lg" px="md" >
|
||||
<Stack gap="0" >
|
||||
<Text fz={{ base: "2rem", md: "3.4rem" }} c={colors["blue-button"]} fw="bold" >
|
||||
Pendaftaran UMKM
|
||||
</Text>
|
||||
</Stack>
|
||||
</Container>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Grid>
|
||||
<GridCol span={{ base: 12, md: 6, lg: 7, xl: 8 }}>
|
||||
<Center>
|
||||
<Image src={'/api/img/market.png'} w={{ base: 300, md: 500, lg: 530, xl: 550 }} alt='' />
|
||||
</Center>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 6, lg: 5, xl: 4 }}>
|
||||
<Paper bg={colors['white-1']} p={'md'} h={'500'}>
|
||||
<Text ta={'center'} fz={{ base: "1.5rem", md: "2rem" }} c={colors["blue-button"]} fw="bold" >
|
||||
Pendaftaran UMKM
|
||||
</Text>
|
||||
<Stack pt={20}>
|
||||
<TextInput placeholder='Nama Lengkap' />
|
||||
<TextInput placeholder='Alamat' />
|
||||
<TextInput placeholder='No. Telepon' />
|
||||
<TextInput placeholder='Email' />
|
||||
<TextInput placeholder='Nama UMKM' />
|
||||
<Button bg={colors['blue-button']} fullWidth>Daftar Sekarang</Button>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
</GridCol>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,61 @@
|
||||
'use client'
|
||||
import stateDesaPengumuman from '@/app/admin/(dashboard)/_state/desa/pengumuman';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Container, Flex, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import BackButton from '../../../layanan/_com/BackButto';
|
||||
|
||||
function Page() {
|
||||
const detail = useProxy(stateDesaPengumuman.pengumuman.findUnique)
|
||||
|
||||
const params = useParams()
|
||||
|
||||
useShallowEffect(() => {
|
||||
stateDesaPengumuman.pengumuman.findUnique.load(params?.id as string)
|
||||
}, [])
|
||||
|
||||
if (!detail.data) {
|
||||
return (
|
||||
<Box>
|
||||
<Skeleton h={400} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="md">
|
||||
{/* Header */}
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Container size="lg" px="md">
|
||||
<Stack gap="xs" >
|
||||
<Flex justify={"space-between"} align={"center"}>
|
||||
<Text fz={{ base: "2rem", md: "2rem" }} c={colors["blue-button"]} fw="bold" >
|
||||
{detail.data?.judul}
|
||||
</Text>
|
||||
<Group justify='end'>
|
||||
<Paper bg={colors['blue-button']} p={5}>
|
||||
<Text c={colors['white-1']}>{detail.data?.CategoryPengumuman?.name}</Text>
|
||||
</Paper>
|
||||
</Group>
|
||||
</Flex>
|
||||
<Paper bg={colors["white-1"]} p="md">
|
||||
<Text fz={"md"} dangerouslySetInnerHTML={{ __html: detail.data?.content }} />
|
||||
<Text fz={"md"} c={colors["blue-button"]} fw="bold" >
|
||||
{new Date(detail.data?.createdAt).toLocaleDateString('id-ID', {
|
||||
weekday: 'long',
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
})}
|
||||
</Text>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Container>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
73
src/app/darmasaba/(pages)/desa/pengumuman/[name]/page.tsx
Normal file
73
src/app/darmasaba/(pages)/desa/pengumuman/[name]/page.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
'use client'
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import stateDesaPengumuman from '@/app/admin/(dashboard)/_state/desa/pengumuman';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Container, Group, Paper, Stack, Text } from '@mantine/core';
|
||||
import { IconCalendar } from '@tabler/icons-react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import BackButton from '../../layanan/_com/BackButto';
|
||||
import { useEffect } from 'react';
|
||||
import { useParams } from 'next/navigation';
|
||||
|
||||
|
||||
function Page() {
|
||||
const unwrappedParams = useParams();
|
||||
const kategoriState = useProxy(stateDesaPengumuman);
|
||||
const categoryName = decodeURIComponent(unwrappedParams.name as string);
|
||||
|
||||
useEffect(() => {
|
||||
kategoriState.category.findUnique.load(categoryName);
|
||||
kategoriState.pengumuman.findMany.load(1, 10, '', categoryName);
|
||||
}, [categoryName]);
|
||||
|
||||
return (
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="md">
|
||||
{/* Header */}
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
<Container size="lg" px="md" >
|
||||
<Stack align="center" gap="0" >
|
||||
<Text fz={{ base: "2rem", md: "3.4rem" }} c={colors["blue-button"]} fw="bold" ta="center">
|
||||
{categoryName.split('-').map(word =>
|
||||
word.charAt(0).toUpperCase() + word.slice(1)
|
||||
).join(' ')}
|
||||
</Text>
|
||||
<Text ta="center" px="md" pb={10}>
|
||||
Informasi dan pengumuman resmi terkait {categoryName.split('-').join(' ')}
|
||||
</Text>
|
||||
</Stack>
|
||||
</Container>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
{!kategoriState.pengumuman.findMany.data?.length ? (
|
||||
<Paper p="lg" radius="md" shadow="md" bg={colors["white-1"]}>
|
||||
Tidak ada pengumuman yang ditemukan
|
||||
</Paper>
|
||||
) : kategoriState.pengumuman.findMany.data?.map((v, k) => {
|
||||
return (
|
||||
<Paper mb={10} key={k} withBorder p="lg" radius="md" shadow="md" bg={colors["white-1"]}>
|
||||
<Text fz={'h3'}>{v.judul}</Text>
|
||||
<Group style={{ color: 'black' }} pb={20}>
|
||||
<Group gap="xs">
|
||||
<IconCalendar size={18} />
|
||||
<Text size="sm">
|
||||
{v.createdAt ? new Date(v.createdAt).toLocaleDateString('id-ID', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
}) : 'No date available'}
|
||||
</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
<Text ta={'justify'}>
|
||||
{v.deskripsi}
|
||||
</Text>
|
||||
</Paper>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
@@ -1,171 +1,299 @@
|
||||
'use client';
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import stateDesaPengumuman from '@/app/admin/(dashboard)/_state/desa/pengumuman';
|
||||
import colors from '@/con/colors';
|
||||
import { Anchor, Box, Container, Flex, Group, Notification, Paper, SimpleGrid, Stack, Text, TextInput, UnstyledButton } from '@mantine/core';
|
||||
import {
|
||||
Anchor,
|
||||
Box,
|
||||
Center,
|
||||
Container,
|
||||
Divider,
|
||||
Flex,
|
||||
Grid,
|
||||
GridCol,
|
||||
Group,
|
||||
Notification,
|
||||
Pagination,
|
||||
Paper,
|
||||
SimpleGrid,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
UnstyledButton,
|
||||
} from '@mantine/core';
|
||||
import { IconCalendar, IconClock, IconSearch } from '@tabler/icons-react';
|
||||
import BackButton from '../layanan/_com/BackButto';
|
||||
import { useTransitionRouter } from 'next-view-transitions';
|
||||
import Link from 'next/link';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import BackButton from '../layanan/_com/BackButto';
|
||||
|
||||
const dataKategori = [
|
||||
{
|
||||
id: 1,
|
||||
kategori: 'Sosial & Kesehatan',
|
||||
jumlah: 5,
|
||||
link: '/darmasaba/desa/pengumuman/sosial-&-kesehatan'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
kategori: 'Ekonomi & UMKM',
|
||||
jumlah: 7,
|
||||
link: '/darmasaba/desa/pengumuman/ekonomi-&-umkm'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
kategori: 'Pendidikan & Kepemudaan',
|
||||
jumlah: 9,
|
||||
link: '/darmasaba/desa/pengumuman/pendidikan-&-kepemudaan'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
kategori: 'Lingkungan & Bencana',
|
||||
jumlah: 6,
|
||||
link: '/darmasaba/desa/pengumuman/lingkungan-&-bencana'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
kategori: 'Adat & Budaya',
|
||||
jumlah: 8,
|
||||
link: '/darmasaba/desa/pengumuman/adat-&-budaya'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
kategori: 'Digitalisasi Desa',
|
||||
jumlah: 6,
|
||||
link: '/darmasaba/desa/pengumuman/digitalisasi-desa'
|
||||
},
|
||||
]
|
||||
const dataPenting = [
|
||||
{
|
||||
id: 1,
|
||||
judul: 'Jadwal Rapat',
|
||||
jumlah: 5,
|
||||
link: '/darmasaba/desa/pengumuman/jadwal-rapat'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
judul: 'Pendaftaran UMKM',
|
||||
jumlah: 7,
|
||||
link: '/darmasaba/desa/pengumuman/pendaftaran-umkm'
|
||||
}
|
||||
]
|
||||
function Page() {
|
||||
const router = useTransitionRouter();
|
||||
|
||||
// State lokal
|
||||
const [search, setSearch] = useState('');
|
||||
const [searchInput, setSearchInput] = useState('');
|
||||
const [page, setPage] = useState(1);
|
||||
|
||||
const state = useProxy(stateDesaPengumuman.pengumuman);
|
||||
const totalPages = state.findMany.totalPages || 1;
|
||||
const recent = useProxy(stateDesaPengumuman.pengumuman.findRecent);
|
||||
|
||||
// ✅ Baca URL saat pertama kali mount
|
||||
useEffect(() => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const urlSearch = urlParams.get('search') || '';
|
||||
const urlPage = parseInt(urlParams.get('page') || '1');
|
||||
|
||||
setSearch(urlSearch);
|
||||
setSearchInput(urlSearch);
|
||||
setPage(Math.max(1, urlPage)); // Pastikan page >= 1
|
||||
}, []);
|
||||
|
||||
// ✅ Sinkronkan URL saat `search` atau `page` berubah
|
||||
useEffect(() => {
|
||||
const url = new URL(window.location.href);
|
||||
if (search) {
|
||||
url.searchParams.set('search', search);
|
||||
} else {
|
||||
url.searchParams.delete('search');
|
||||
}
|
||||
if (page > 1) {
|
||||
url.searchParams.set('page', page.toString());
|
||||
} else {
|
||||
url.searchParams.delete('page');
|
||||
}
|
||||
router.replace(url.toString());
|
||||
}, [search, page, router]);
|
||||
|
||||
// ✅ Debounce untuk pencarian
|
||||
useEffect(() => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (searchInput !== search) {
|
||||
setSearch(searchInput);
|
||||
setPage(1); // Reset ke halaman 1 saat pencarian baru
|
||||
}
|
||||
}, 500);
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
}, [searchInput, search]);
|
||||
|
||||
// ✅ Load data dari state (valtio)
|
||||
useEffect(() => {
|
||||
stateDesaPengumuman.category.findMany.load();
|
||||
stateDesaPengumuman.pengumuman.findRecent.load();
|
||||
state.findMany.load(page, 3, search);
|
||||
}, [search, page]); // 🔁 Depend pada `search` dan `page`
|
||||
|
||||
return (
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="md">
|
||||
{/* Header */}
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<BackButton />
|
||||
</Box>
|
||||
|
||||
<Container size="lg" px="md">
|
||||
<Stack align="center" gap="0" >
|
||||
<Text fz={{ base: "2rem", md: "3.4rem" }} c={colors["blue-button"]} fw="bold" ta="center">
|
||||
<Stack align="center" gap="0">
|
||||
<Text fz={{ base: '2rem', md: '3.4rem' }} c={colors['blue-button']} fw="bold" ta="center">
|
||||
Pengumuman Desa Darmasaba
|
||||
</Text>
|
||||
<Text ta="center" px="md" pb={10}>
|
||||
Informasi dan pengumuman resmi terkait kegiatan dan kebijakan Desa Darmasaba
|
||||
</Text>
|
||||
<TextInput
|
||||
placeholder='Cari Pengumuman'
|
||||
radius="lg"
|
||||
leftSection={<IconSearch size={20} />}
|
||||
w={{ base: "55%", md: "70%" }}
|
||||
/>
|
||||
</Stack>
|
||||
</Container>
|
||||
|
||||
<Box px={{ base: "md", md: 100 }}>
|
||||
<SimpleGrid
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 2,
|
||||
}}
|
||||
>
|
||||
<Notification styles={{ title: { fontWeight: "bold" } }} withCloseButton={false} title="Penting">
|
||||
<Stack gap={"xs"}>
|
||||
<Text fz={"sm"} fw={"bold"} c={"black"}>PENGUMUMAN LOWONGAN KERJA TPS3R PUDAK MESARI DESA DARMASABA</Text>
|
||||
<Text ta={"justify"} fz={"sm"} c={"black"}>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis nec arcu ac ornare. Praesent a porttitor felis. Proin varius ex nisl, in hendrerit odio tristique vel. </Text>
|
||||
</Stack>
|
||||
<Flex pt={20} gap={"md"} justify={"space-between"}>
|
||||
<Group style={{ color: 'black' }}>
|
||||
<Group gap="xs">
|
||||
<IconCalendar size={18} />
|
||||
<Text size="sm">Kamis, 13 Januari 2025</Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<IconClock size={18} />
|
||||
<Text size="sm">09:00 WITA</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
<Anchor>
|
||||
<Text fs={'unset'} c={colors["blue-button"]} fz={"sm"}>Baca Selengkapnya</Text>
|
||||
</Anchor>
|
||||
</Flex>
|
||||
</Notification>
|
||||
<Paper p={"md"}>
|
||||
<Stack gap={"xs"}>
|
||||
<Text fw={"bold"} fz={"lg"} c={colors['blue-button']}>Kategori</Text>
|
||||
{dataKategori.map((v, k) => {
|
||||
{/* Recent & Kategori */}
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
||||
<Stack>
|
||||
{!recent.data?.length ? (
|
||||
<Notification withCloseButton={false} h={100}>
|
||||
Tidak ada pengumuman yang ditemukan
|
||||
</Notification>
|
||||
) : (
|
||||
recent.data
|
||||
?.slice(0, 2)
|
||||
.map((item, index) => (
|
||||
<Notification
|
||||
key={item.id}
|
||||
color={index === 0 ? undefined : 'yellow'}
|
||||
styles={{ title: { fontWeight: 'bold' } }}
|
||||
withCloseButton={false}
|
||||
title={item.CategoryPengumuman?.name || 'Pengumuman'}
|
||||
>
|
||||
<Stack gap={"xs"}>
|
||||
<Text fz="sm" fw="bold" c="black" style={{ textTransform: 'uppercase' }}>
|
||||
{item.judul}
|
||||
</Text>
|
||||
<Text ta="justify" fz="sm" c="black" lineClamp={3} dangerouslySetInnerHTML={{ __html: item.content }} />
|
||||
</Stack>
|
||||
<Flex pt={20} gap="md" justify="space-between">
|
||||
<Group style={{ color: 'black' }}>
|
||||
<Group gap="xs">
|
||||
<IconCalendar size={18} />
|
||||
<Text size="sm">
|
||||
{new Date(item.createdAt).toLocaleDateString('id-ID', {
|
||||
weekday: 'long',
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
})}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<IconClock size={18} />
|
||||
<Text size="sm">
|
||||
{new Date(item.createdAt).toLocaleTimeString('id-ID', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
timeZoneName: 'short',
|
||||
})}
|
||||
</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
<Anchor variant="transparent" href={`/darmasaba/desa/pengumuman/${item.CategoryPengumuman?.name}/${item.id}`}>
|
||||
<Text fs="unset" c={colors['blue-button']} fz="sm">
|
||||
Baca Selengkapnya
|
||||
</Text>
|
||||
</Anchor>
|
||||
</Flex>
|
||||
</Notification>
|
||||
))
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
<Paper p="md">
|
||||
<Stack gap="xs">
|
||||
<Text fw="bold" fz="lg" c={colors['blue-button']}>
|
||||
Kategori
|
||||
</Text>
|
||||
{stateDesaPengumuman.category.findMany.data?.map((v: any, k) => {
|
||||
const count = v._count?.pengumumans || 0;
|
||||
return (
|
||||
<UnstyledButton component={Link} href={v.link} key={k}>
|
||||
<Paper bg={colors["BG-trans"]} p={5}>
|
||||
<Group px={3} justify={"space-between"}>
|
||||
<Text fz={"md"} c={"black"}>{v.kategori}</Text>
|
||||
<Text fz={"md"} c={"black"}>{v.jumlah}</Text>
|
||||
<UnstyledButton component={Link} href={`/darmasaba/desa/pengumuman/${v.name}`} key={k}>
|
||||
<Paper bg={colors['BG-trans']} p={5}>
|
||||
<Group px={3} justify="space-between">
|
||||
<Text fz="md" c="black">
|
||||
{v.name}
|
||||
</Text>
|
||||
<Text fz="md" c="black">
|
||||
{count}
|
||||
</Text>
|
||||
</Group>
|
||||
</Paper>
|
||||
</UnstyledButton>
|
||||
)
|
||||
})}
|
||||
</Stack>
|
||||
</Paper>
|
||||
<Notification color='yellow' styles={{ title: { fontWeight: "bold" } }} withCloseButton={false} title="Informasi">
|
||||
<Stack gap={"xs"}>
|
||||
<Text fz={"sm"} fw={"bold"} c={"black"}>LELANG PEMASANGAN CCTV DESA DARMASABA</Text>
|
||||
<Text ta={"justify"} fz={"sm"} c={"black"}>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis nec arcu ac ornare. Praesent a porttitor felis. Proin varius ex nisl, in hendrerit odio tristique vel. </Text>
|
||||
</Stack>
|
||||
<Flex pt={20} gap={"md"} justify={"space-between"}><Group style={{ color: 'black' }}>
|
||||
<Group gap="xs">
|
||||
<IconCalendar size={18} />
|
||||
<Text size="sm">Kamis, 2 Februari 2025</Text>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<IconClock size={18} />
|
||||
<Text size="sm">10:00 WITA</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
<Anchor>
|
||||
<Text fs={'unset'} c={colors["blue-button"]} fz={"sm"}>Baca Selengkapnya</Text>
|
||||
</Anchor>
|
||||
</Flex>
|
||||
</Notification>
|
||||
<Paper p={"md"}>
|
||||
<Stack gap={"xs"}>
|
||||
<Text fw={"bold"} fz={"lg"} c={colors['blue-button']}>Pengumuman Penting</Text>
|
||||
{dataPenting.map((v, k) => {
|
||||
return (
|
||||
<UnstyledButton component={Link} href={v.link} key={k}>
|
||||
<Paper bg={colors["BG-trans"]} p={5}>
|
||||
<Group px={3} justify={"space-between"}>
|
||||
<Text fz={"md"} c={"black"}>{v.judul}</Text>
|
||||
<Text fz={"md"} c={"black"}>{v.jumlah}</Text>
|
||||
</Group>
|
||||
</Paper>
|
||||
</UnstyledButton>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
|
||||
{/* Daftar Pengumuman */}
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Stack gap="xs">
|
||||
<Divider mb={10} color={colors['blue-button']} />
|
||||
<Grid>
|
||||
<GridCol span={{ base: 12, md: 8 }}>
|
||||
<Title order={3}>Daftar Pengumuman</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 4 }}>
|
||||
<TextInput
|
||||
placeholder="Cari Pengumuman"
|
||||
radius="lg"
|
||||
leftSection={<IconSearch size={20} />}
|
||||
w="100%"
|
||||
value={searchInput}
|
||||
onChange={(e) => setSearchInput(e.target.value)}
|
||||
/>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
{/* Loading */}
|
||||
{state.findMany.loading ? (
|
||||
<SimpleGrid cols={{ base: 1, md: 3 }}>
|
||||
{[1, 2, 3].map((i) => (
|
||||
<Skeleton key={i} h={400} />
|
||||
))}
|
||||
</SimpleGrid>
|
||||
) : !state.findMany.data?.length ? (
|
||||
<Notification withCloseButton={false} h={100}>
|
||||
Tidak ada pengumuman yang ditemukan
|
||||
</Notification>
|
||||
) : (
|
||||
<SimpleGrid cols={{ base: 1, md: 3 }} spacing="lg" verticalSpacing="lg">
|
||||
{state.findMany.data.map((item) => (
|
||||
<Paper key={item.id} p="md" withBorder radius="md" h="100%">
|
||||
<Stack h="100%" justify="space-between">
|
||||
<div>
|
||||
<Text fw={600} c={colors['blue-button']} mb={5}>
|
||||
{item.CategoryPengumuman?.name || 'Pengumuman'}
|
||||
</Text>
|
||||
<Text fz="lg" fw={700} mb="sm" lineClamp={2} style={{ textTransform: 'uppercase' }}>
|
||||
{item.judul}
|
||||
</Text>
|
||||
<Text
|
||||
fz="sm"
|
||||
c="dimmed"
|
||||
lineClamp={4}
|
||||
dangerouslySetInnerHTML={{ __html: item.content }}
|
||||
mb="md"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Group mb="sm" c="dimmed">
|
||||
<Group gap={5}>
|
||||
<IconCalendar size={16} />
|
||||
<Text size="xs">
|
||||
{new Date(item.createdAt).toLocaleDateString('id-ID', {
|
||||
day: 'numeric',
|
||||
month: 'short',
|
||||
year: 'numeric',
|
||||
})}
|
||||
</Text>
|
||||
</Group>
|
||||
<Group gap={5}>
|
||||
<IconClock size={16} />
|
||||
<Text size="xs">
|
||||
{new Date(item.createdAt).toLocaleTimeString('id-ID', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
})}
|
||||
</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
<Anchor variant="transparent" href={`/darmasaba/desa/pengumuman/${item.CategoryPengumuman?.name}/${item.id}`}>
|
||||
<Text fw={600} c={colors['blue-button']} size="sm">
|
||||
Baca Selengkapnya →
|
||||
</Text>
|
||||
</Anchor>
|
||||
</div>
|
||||
</Stack>
|
||||
</Paper>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
)}
|
||||
|
||||
{/* Pagination */}
|
||||
<Center mt="xl">
|
||||
<Pagination
|
||||
total={totalPages}
|
||||
value={page}
|
||||
onChange={setPage}
|
||||
siblings={1}
|
||||
boundaries={1}
|
||||
withEdges
|
||||
/>
|
||||
</Center>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
export default Page;
|
||||
Reference in New Issue
Block a user