diff --git a/src/app/admin/(dashboard)/_state/desa/pengumuman.ts b/src/app/admin/(dashboard)/_state/desa/pengumuman.ts index 8a89aa19..0fcffb7e 100644 --- a/src/app/admin/(dashboard)/_state/desa/pengumuman.ts +++ b/src/app/admin/(dashboard)/_state/desa/pengumuman.ts @@ -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(); diff --git a/src/app/api/[[...slugs]]/_lib/desa/pengumuman/kategori-pengumuman/findMany.ts b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/kategori-pengumuman/findMany.ts index 2646b2ee..c54ad743 100644 --- a/src/app/api/[[...slugs]]/_lib/desa/pengumuman/kategori-pengumuman/findMany.ts +++ b/src/app/api/[[...slugs]]/_lib/desa/pengumuman/kategori-pengumuman/findMany.ts @@ -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 }; } diff --git a/src/app/darmasaba/(pages)/desa/pengumuman/(penting)/jadwal-rapat/page.tsx b/src/app/darmasaba/(pages)/desa/pengumuman/(penting)/jadwal-rapat/page.tsx deleted file mode 100644 index ed8e840a..00000000 --- a/src/app/darmasaba/(pages)/desa/pengumuman/(penting)/jadwal-rapat/page.tsx +++ /dev/null @@ -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 ( - - {/* Header */} - - - - - - - Jadwal Rapat - - - - - - - -
- -
-
-
- - - - - Hari Ini - Senin, 13 Februari 2023 - 09:00 - 12:00 - 12:00 - 15:00 - - - Besok - Selasa, 14 Februari 2023 - 09:00 - 12:00 - 12:00 - 15:00 - - - Minggu Depan - Senin, 20 Februari 2023 - 09:00 - 12:00 - 12:00 - 15:00 - - - - -
-
-
- ); -} - -export default Page; diff --git a/src/app/darmasaba/(pages)/desa/pengumuman/(penting)/pendaftaran-umkm/page.tsx b/src/app/darmasaba/(pages)/desa/pengumuman/(penting)/pendaftaran-umkm/page.tsx deleted file mode 100644 index 5deb13c5..00000000 --- a/src/app/darmasaba/(pages)/desa/pengumuman/(penting)/pendaftaran-umkm/page.tsx +++ /dev/null @@ -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 ( - - {/* Header */} - - - - - - - Pendaftaran UMKM - - - - - - -
- -
-
- - - - Pendaftaran UMKM - - - - - - - - - - - - -
-
-
- ); -} - -export default Page; diff --git a/src/app/darmasaba/(pages)/desa/pengumuman/[name]/[id]/page.tsx b/src/app/darmasaba/(pages)/desa/pengumuman/[name]/[id]/page.tsx new file mode 100644 index 00000000..efdc7e9b --- /dev/null +++ b/src/app/darmasaba/(pages)/desa/pengumuman/[name]/[id]/page.tsx @@ -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 ( + + + + ) + } + return ( + + {/* Header */} + + + + + + + + {detail.data?.judul} + + + + {detail.data?.CategoryPengumuman?.name} + + + + + + + {new Date(detail.data?.createdAt).toLocaleDateString('id-ID', { + weekday: 'long', + day: 'numeric', + month: 'long', + year: 'numeric' + })} + + + + + + ); +} + +export default Page; diff --git a/src/app/darmasaba/(pages)/desa/pengumuman/[name]/page.tsx b/src/app/darmasaba/(pages)/desa/pengumuman/[name]/page.tsx new file mode 100644 index 00000000..6bdd20a1 --- /dev/null +++ b/src/app/darmasaba/(pages)/desa/pengumuman/[name]/page.tsx @@ -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 ( + + {/* Header */} + + + + + + + {categoryName.split('-').map(word => + word.charAt(0).toUpperCase() + word.slice(1) + ).join(' ')} + + + Informasi dan pengumuman resmi terkait {categoryName.split('-').join(' ')} + + + + + {!kategoriState.pengumuman.findMany.data?.length ? ( + + Tidak ada pengumuman yang ditemukan + + ) : kategoriState.pengumuman.findMany.data?.map((v, k) => { + return ( + + {v.judul} + + + + + {v.createdAt ? new Date(v.createdAt).toLocaleDateString('id-ID', { + day: 'numeric', + month: 'long', + year: 'numeric', + }) : 'No date available'} + + + + + {v.deskripsi} + + + ) + })} + + + ); +} + +export default Page; diff --git a/src/app/darmasaba/(pages)/desa/pengumuman/page.tsx b/src/app/darmasaba/(pages)/desa/pengumuman/page.tsx index 5f18a7a8..b3ecb8fb 100644 --- a/src/app/darmasaba/(pages)/desa/pengumuman/page.tsx +++ b/src/app/darmasaba/(pages)/desa/pengumuman/page.tsx @@ -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 ( {/* Header */} - + + - - + + Pengumuman Desa Darmasaba Informasi dan pengumuman resmi terkait kegiatan dan kebijakan Desa Darmasaba - } - w={{ base: "55%", md: "70%" }} - /> - - - - - PENGUMUMAN LOWONGAN KERJA TPS3R PUDAK MESARI DESA DARMASABA - 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. - - - - - - Kamis, 13 Januari 2025 - - - - 09:00 WITA - - - - Baca Selengkapnya - - - - - - Kategori - {dataKategori.map((v, k) => { + {/* Recent & Kategori */} + + + + {!recent.data?.length ? ( + + Tidak ada pengumuman yang ditemukan + + ) : ( + recent.data + ?.slice(0, 2) + .map((item, index) => ( + + + + {item.judul} + + + + + + + + + {new Date(item.createdAt).toLocaleDateString('id-ID', { + weekday: 'long', + day: 'numeric', + month: 'long', + year: 'numeric', + })} + + + + + + {new Date(item.createdAt).toLocaleTimeString('id-ID', { + hour: '2-digit', + minute: '2-digit', + timeZoneName: 'short', + })} + + + + + + Baca Selengkapnya + + + + + )) + )} + + + + + + Kategori + + {stateDesaPengumuman.category.findMany.data?.map((v: any, k) => { + const count = v._count?.pengumumans || 0; return ( - - - - {v.kategori} - {v.jumlah} + + + + + {v.name} + + + {count} + - ) - })} - - - - - LELANG PEMASANGAN CCTV DESA DARMASABA - 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. - - - - - Kamis, 2 Februari 2025 - - - - 10:00 WITA - - - - Baca Selengkapnya - - - - - - Pengumuman Penting - {dataPenting.map((v, k) => { - return ( - - - - {v.judul} - {v.jumlah} - - - - ) + ); })} + + {/* Daftar Pengumuman */} + + + + + + Daftar Pengumuman + + + } + w="100%" + value={searchInput} + onChange={(e) => setSearchInput(e.target.value)} + /> + + + + {/* Loading */} + {state.findMany.loading ? ( + + {[1, 2, 3].map((i) => ( + + ))} + + ) : !state.findMany.data?.length ? ( + + Tidak ada pengumuman yang ditemukan + + ) : ( + + {state.findMany.data.map((item) => ( + + +
+ + {item.CategoryPengumuman?.name || 'Pengumuman'} + + + {item.judul} + + +
+
+ + + + + {new Date(item.createdAt).toLocaleDateString('id-ID', { + day: 'numeric', + month: 'short', + year: 'numeric', + })} + + + + + + {new Date(item.createdAt).toLocaleTimeString('id-ID', { + hour: '2-digit', + minute: '2-digit', + })} + + + + + + Baca Selengkapnya → + + +
+
+
+ ))} +
+ )} + + {/* Pagination */} +
+ +
+
+
); } -export default Page; +export default Page; \ No newline at end of file