Fix QC Kak Inno 16 Des
Fix QC Kak Ayu 16 Des FIx UI Admin Mobile Menu PPID Fix Search Admin Menu Landing Page & Menu PPID
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
|
||||
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
@@ -106,7 +106,7 @@ function DetailSDGSDesa() {
|
||||
size="md"
|
||||
disabled={sdgsState.delete.loading}
|
||||
>
|
||||
<IconX size={20} />
|
||||
<IconTrash size={20} />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
@@ -28,6 +28,8 @@ function SdgsDesa() {
|
||||
function ListSdgsDesa({ search }: { search: string }) {
|
||||
const listState = useProxy(sdgsDesa);
|
||||
const router = useRouter();
|
||||
const [debouncedSearch] = useDebouncedValue(search, 1000);
|
||||
|
||||
|
||||
const {
|
||||
data,
|
||||
@@ -38,8 +40,8 @@ function ListSdgsDesa({ search }: { search: string }) {
|
||||
} = listState.findMany;
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 10, search);
|
||||
}, [page, search]);
|
||||
load(page, 10, debouncedSearch);
|
||||
}, [page, debouncedSearch]);
|
||||
|
||||
const filteredData = data || [];
|
||||
|
||||
@@ -63,7 +65,7 @@ function ListSdgsDesa({ search }: { search: string }) {
|
||||
</Title>
|
||||
<Button
|
||||
leftSection={<IconPlus size={18} />}
|
||||
color={colors['blue-button']}
|
||||
color='blue'
|
||||
variant="light"
|
||||
onClick={() => router.push('/admin/landing-page/SDGs/create')}
|
||||
>
|
||||
@@ -147,12 +149,18 @@ function ListSdgsDesa({ search }: { search: string }) {
|
||||
{filteredData.map((item) => (
|
||||
<Paper key={item.id} withBorder p="md" radius="md">
|
||||
<Stack gap={4}>
|
||||
<Text fz="sm" fw={600} lh={1.4}>
|
||||
{item.name}
|
||||
</Text>
|
||||
<Text fz="xs" c="dark.6" lh={1.4}>
|
||||
Jumlah: {item.jumlah || '0'}
|
||||
</Text>
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Nama SDGs Desa</Text>
|
||||
<Text fz="sm" fw={500} lh={1.4}>
|
||||
{item.name}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Jumlah</Text>
|
||||
<Text fz="xs" c="dark.6" lh={1.4}>
|
||||
{item.jumlah || '0'}
|
||||
</Text>
|
||||
</Box>
|
||||
<Group justify="flex-end" mt="xs">
|
||||
<Button
|
||||
size="xs"
|
||||
|
||||
@@ -368,6 +368,13 @@ function EditAPBDes() {
|
||||
{ value: '2', label: 'Level 2 (Sub-kelompok)' },
|
||||
{ value: '3', label: 'Level 3 (Detail)' },
|
||||
]}
|
||||
styles={{
|
||||
option: {
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
},
|
||||
}}
|
||||
value={String(newItem.level)}
|
||||
onChange={(val) => setNewItem({ ...newItem, level: Number(val) || 1 })}
|
||||
/>
|
||||
@@ -378,6 +385,13 @@ function EditAPBDes() {
|
||||
{ value: 'belanja', label: 'Belanja' },
|
||||
{ value: 'pembiayaan', label: 'Pembiayaan' },
|
||||
]}
|
||||
styles={{
|
||||
option: {
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
},
|
||||
}}
|
||||
value={newItem.tipe}
|
||||
onChange={(val) => setNewItem({ ...newItem, tipe: (val as any) || 'pendapatan' })}
|
||||
/>
|
||||
|
||||
@@ -353,6 +353,13 @@ function CreateAPBDes() {
|
||||
{ value: '2', label: 'Level 2 (Sub-kelompok)' },
|
||||
{ value: '3', label: 'Level 3 (Detail)' },
|
||||
]}
|
||||
styles={{
|
||||
option: {
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
},
|
||||
}}
|
||||
value={String(newItem.level)}
|
||||
onChange={(val) => setNewItem({ ...newItem, level: Number(val) || 1 })}
|
||||
/>
|
||||
@@ -363,6 +370,13 @@ function CreateAPBDes() {
|
||||
{ value: 'belanja', label: 'Belanja' },
|
||||
{ value: 'pembiayaan', label: 'Pembiayaan' },
|
||||
]}
|
||||
styles={{
|
||||
option: {
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
},
|
||||
}}
|
||||
value={newItem.level === 1 ? null : newItem.tipe}
|
||||
onChange={(val) => setNewItem({ ...newItem, tipe: val as any })}
|
||||
disabled={newItem.level === 1}
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
Text,
|
||||
Title,
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImacCog, IconFile, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
@@ -45,12 +45,13 @@ function APBDes() {
|
||||
function ListAPBDes({ search }: { search: string }) {
|
||||
const listState = useProxy(apbdes);
|
||||
const router = useRouter();
|
||||
const [debouncedSearch] = useDebouncedValue(search, 1000);
|
||||
|
||||
const { data, page, totalPages, loading, load } = listState.findMany;
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 10, search);
|
||||
}, [page, search]);
|
||||
load(page, 10, debouncedSearch);
|
||||
}, [page, debouncedSearch]);
|
||||
|
||||
const filteredData = data || [];
|
||||
|
||||
@@ -197,17 +198,17 @@ function ListAPBDes({ search }: { search: string }) {
|
||||
<Text fz="sm" fw={600} lh={1.4}>
|
||||
APBDes {item.tahun}
|
||||
</Text>
|
||||
<Group justify="space-between" wrap="nowrap">
|
||||
<Text fz="sm" c="dimmed" lh={1.4}>
|
||||
<Box>
|
||||
<Text fz="sm"fw={600} lh={1.4}>
|
||||
Tahun
|
||||
</Text>
|
||||
<Text fz="sm" fw={500} lh={1.4}>
|
||||
{item.tahun || '-'}
|
||||
</Text>
|
||||
</Group>
|
||||
</Box>
|
||||
|
||||
<Group justify="space-between" wrap="nowrap">
|
||||
<Text fz="sm" c="dimmed" lh={1.4}>
|
||||
<Box>
|
||||
<Text fz="sm"fw={600} lh={1.4}>
|
||||
Dokumen
|
||||
</Text>
|
||||
{item.file?.link ? (
|
||||
@@ -230,7 +231,7 @@ function ListAPBDes({ search }: { search: string }) {
|
||||
Tidak ada
|
||||
</Text>
|
||||
)}
|
||||
</Group>
|
||||
</Box>
|
||||
|
||||
<Button
|
||||
size="xs"
|
||||
|
||||
@@ -151,7 +151,7 @@ function ListKategoriKegiatan({ search }: { search: string }) {
|
||||
{item.name}
|
||||
</Text>
|
||||
</TableTd>
|
||||
<TableTd w={60}>
|
||||
<TableTd w={120}>
|
||||
<Button
|
||||
variant="light"
|
||||
color="green"
|
||||
@@ -161,7 +161,7 @@ function ListKategoriKegiatan({ search }: { search: string }) {
|
||||
<IconEdit size={18} />
|
||||
</Button>
|
||||
</TableTd>
|
||||
<TableTd w={60}>
|
||||
<TableTd w={120}>
|
||||
<Button
|
||||
variant="light"
|
||||
color="red"
|
||||
@@ -191,7 +191,7 @@ function ListKategoriKegiatan({ search }: { search: string }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<Box py={{ base: 'xl', md: 'xl' }}>
|
||||
<Box py={{ base: 20, md: 20 }}>
|
||||
<Paper bg={colors['white-1']} p={{ base: 'md', md: 'xl' }} shadow="md" radius="md">
|
||||
<Group justify="space-between" mb={{ base: 'md', md: 'lg' }}>
|
||||
<Title order={2} lh={1.2}>
|
||||
|
||||
@@ -150,12 +150,18 @@ function ListDesaAntiKorupsi({ search }: { search: string }) {
|
||||
filteredData.map((item) => (
|
||||
<Paper key={item.id} p="sm" radius="md" withBorder shadow="xs">
|
||||
<Stack gap="xs">
|
||||
<Text fw={500} fz="sm" lh={1.5} lineClamp={1}>
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Nama Program</Text>
|
||||
<Text fw={500} fz="sm" lh={1.5} lineClamp={1}>
|
||||
{item.name || '-'}
|
||||
</Text>
|
||||
<Text fz="xs" c="dimmed" lh={1.5} lineClamp={1}>
|
||||
Kategori: {item.kategori?.name || '-'}
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Kategori</Text>
|
||||
<Text fz="xs" c="dimmed" lh={1.5} lineClamp={1}>
|
||||
{item.kategori?.name || '-'}
|
||||
</Text>
|
||||
</Box>
|
||||
<Group justify="flex-end">
|
||||
<Button
|
||||
size="xs"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
@@ -32,6 +32,7 @@ function ListKategoriPrestasi({ search }: { search: string }) {
|
||||
const [modalHapus, setModalHapus] = useState(false)
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null)
|
||||
const router = useRouter()
|
||||
const [debouncedSearch] = useDebouncedValue(search, 1000); // 500ms delay
|
||||
|
||||
const handleHapus = () => {
|
||||
if (selectedId) {
|
||||
@@ -50,8 +51,8 @@ function ListKategoriPrestasi({ search }: { search: string }) {
|
||||
} = stateKategori.findMany
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 10, search)
|
||||
}, [page, search])
|
||||
load(page, 10, debouncedSearch)
|
||||
}, [page, debouncedSearch])
|
||||
|
||||
const filteredData = data || []
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||
import { useMediaQuery, useShallowEffect } from '@mantine/hooks';
|
||||
import { useDebouncedValue, useMediaQuery, useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
@@ -29,6 +29,7 @@ function ListPrestasi({ search }: { search: string }) {
|
||||
const listState = useProxy(prestasiState.prestasiDesa)
|
||||
const router = useRouter();
|
||||
const isMobile = useMediaQuery('(max-width: 768px)');
|
||||
const [debouncedSearch] = useDebouncedValue(search, 1000); // 500ms delay
|
||||
|
||||
const {
|
||||
data,
|
||||
@@ -39,8 +40,8 @@ function ListPrestasi({ search }: { search: string }) {
|
||||
} = listState.findMany
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 10, search);
|
||||
}, []);
|
||||
load(page, 10, debouncedSearch);
|
||||
}, [page, debouncedSearch]);
|
||||
|
||||
const filteredData = data || []
|
||||
|
||||
@@ -71,44 +72,46 @@ function ListPrestasi({ search }: { search: string }) {
|
||||
</Group>
|
||||
|
||||
{/* Desktop Table */}
|
||||
<Box visibleFrom="md">
|
||||
<Table highlightOnHover miw={0}>
|
||||
<Box visibleFrom="md" style={{ overflowX: 'auto' }}>
|
||||
<Table highlightOnHover striped verticalSpacing="sm" miw={800}>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh w="25%">Nama Prestasi</TableTh>
|
||||
<TableTh w="25%">Deskripsi</TableTh>
|
||||
<TableTh w="25%">Kategori</TableTh>
|
||||
<TableTh w="25%" ta="center">Aksi</TableTh>
|
||||
<TableTh>Nama Prestasi</TableTh>
|
||||
<TableTh>Deskripsi</TableTh>
|
||||
<TableTh>Kategori</TableTh>
|
||||
<TableTh ta="center">Aksi</TableTh>
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>
|
||||
{filteredData.length > 0 ? (
|
||||
filteredData.map((item) => (
|
||||
<TableTr key={item.id}>
|
||||
<TableTd w="25%">
|
||||
<TableTd style={{ maxWidth: 250 }}>
|
||||
<Text truncate="end" fz="md" lh={1.5}>
|
||||
{item.name}
|
||||
</Text>
|
||||
</TableTd>
|
||||
<TableTd w="25%">
|
||||
<TableTd style={{ maxWidth: 250 }}>
|
||||
<Text lineClamp={1} fz="md" c="dimmed" lh={1.5} dangerouslySetInnerHTML={{ __html: item.deskripsi }} />
|
||||
</TableTd>
|
||||
<TableTd w="25%">
|
||||
<TableTd>
|
||||
<Text truncate="end" fz="md" lh={1.5}>
|
||||
{item.kategori?.name || 'Tidak ada kategori'}
|
||||
</Text>
|
||||
</TableTd>
|
||||
<TableTd w="25%" ta="center">
|
||||
<Button
|
||||
size="xs"
|
||||
radius="md"
|
||||
variant="light"
|
||||
color="blue"
|
||||
leftSection={<IconDeviceImacCog size={16} />}
|
||||
onClick={() => router.push(`/admin/landing-page/prestasi-desa/list-prestasi-desa/${item.id}`)}
|
||||
>
|
||||
Detail
|
||||
</Button>
|
||||
<TableTd ta="center">
|
||||
<Center>
|
||||
<Button
|
||||
size="sm"
|
||||
radius="md"
|
||||
variant="light"
|
||||
color="blue"
|
||||
leftSection={<IconDeviceImacCog size={16} />}
|
||||
onClick={() => router.push(`/admin/landing-page/prestasi-desa/list-prestasi-desa/${item.id}`)}
|
||||
>
|
||||
Detail
|
||||
</Button>
|
||||
</Center>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
))
|
||||
@@ -127,39 +130,48 @@ function ListPrestasi({ search }: { search: string }) {
|
||||
|
||||
{/* Mobile Cards */}
|
||||
<Stack hiddenFrom="md" gap="xs">
|
||||
{filteredData.length > 0 ? (
|
||||
filteredData.map((item) => (
|
||||
<Paper key={item.id} withBorder p="sm" radius="sm">
|
||||
<Stack gap={4}>
|
||||
<Text fz="sm" fw={600} lh={1.4}>
|
||||
{filteredData.length > 0 ? (
|
||||
filteredData.map((item) => (
|
||||
<Paper key={item.id} withBorder p="sm" radius="sm">
|
||||
<Stack gap={"xs"}>
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Nama Prestasi</Text>
|
||||
<Text fz="sm" fw={500} lh={1.4} lineClamp={2}>
|
||||
{item.name}
|
||||
</Text>
|
||||
<Text fz="xs" c="dimmed" lh={1.5} lineClamp={1} dangerouslySetInnerHTML={{ __html: item.deskripsi }} />
|
||||
<Text fz="xs" c="dimmed" lh={1.4}>
|
||||
Kategori: {item.kategori?.name || 'Tidak ada kategori'}
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Deskripsi</Text>
|
||||
<Text fz="sm" fw={500} lh={1.5} lineClamp={1} dangerouslySetInnerHTML={{ __html: item.deskripsi }} />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Kategori</Text>
|
||||
<Text fz="sm" fw={500} lh={1.4}>
|
||||
{item.kategori?.name || 'Tidak ada kategori'}
|
||||
</Text>
|
||||
<Group justify="flex-end" mt="xs">
|
||||
<Button
|
||||
size="xs"
|
||||
radius="md"
|
||||
variant="light"
|
||||
color="blue"
|
||||
leftSection={<IconDeviceImacCog size={14} />}
|
||||
onClick={() => router.push(`/admin/landing-page/prestasi-desa/list-prestasi-desa/${item.id}`)}
|
||||
>
|
||||
Detail
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
))
|
||||
) : (
|
||||
<Center py="md">
|
||||
<Text c="dimmed" fz="sm" lh={1.4}>
|
||||
Tidak ada data prestasi
|
||||
</Text>
|
||||
</Center>
|
||||
)}
|
||||
</Box>
|
||||
<Group justify="flex-end" mt="xs">
|
||||
<Button
|
||||
size="xs"
|
||||
radius="md"
|
||||
variant="light"
|
||||
color="blue"
|
||||
leftSection={<IconDeviceImacCog size={14} />}
|
||||
onClick={() => router.push(`/admin/landing-page/prestasi-desa/list-prestasi-desa/${item.id}`)}
|
||||
>
|
||||
Detail
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
))
|
||||
) : (
|
||||
<Center py="md">
|
||||
<Text c="dimmed" fz="sm" lh={1.4}>
|
||||
Tidak ada data prestasi
|
||||
</Text>
|
||||
</Center>
|
||||
)}
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
Text,
|
||||
Title,
|
||||
} from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
@@ -48,6 +48,7 @@ function MediaSosial() {
|
||||
function ListMediaSosial({ search }: { search: string }) {
|
||||
const stateMediaSosial = useProxy(profileLandingPageState.mediaSosial);
|
||||
const router = useRouter();
|
||||
const [debouncedSearch] = useDebouncedValue(search, 1000); // 500ms delay
|
||||
|
||||
const getIconSource = (item: any) => {
|
||||
if (item.image?.link) return item.image.link;
|
||||
@@ -66,8 +67,8 @@ function ListMediaSosial({ search }: { search: string }) {
|
||||
} = stateMediaSosial.findMany;
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 10, search);
|
||||
}, [page, search]);
|
||||
load(page, 10, debouncedSearch);
|
||||
}, [page, debouncedSearch]);
|
||||
|
||||
const filteredData = data || [];
|
||||
|
||||
@@ -195,12 +196,15 @@ function ListMediaSosial({ search }: { search: string }) {
|
||||
{filteredData.length > 0 ? (
|
||||
filteredData.map((item) => (
|
||||
<Paper key={item.id} withBorder p="sm" radius="md">
|
||||
<Group justify="space-between" wrap="nowrap" align='center'>
|
||||
<Box>
|
||||
<Text fw={600} fz="sm" lh={1.45}>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Nama Media Sosial / Kontak</Text>
|
||||
<Text fw={500} fz="sm" lh={1.45}>
|
||||
{item.name}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Gambar</Text>
|
||||
</Box>
|
||||
<Box w={40} h={40} style={{ borderRadius: 6, overflow: 'hidden' }}>
|
||||
{(() => {
|
||||
const src = getIconSource(item);
|
||||
@@ -217,8 +221,8 @@ function ListMediaSosial({ search }: { search: string }) {
|
||||
return <Box bg={colors['blue-button']} w="100%" h="100%" />;
|
||||
})()}
|
||||
</Box>
|
||||
</Group>
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Link / No. Telepon</Text>
|
||||
<a
|
||||
href={item.link}
|
||||
target="_blank"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title, Tooltip } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
@@ -29,12 +29,13 @@ function ProgramInovasi() {
|
||||
function ListProgramInovasi({ search }: { search: string }) {
|
||||
const stateProgramInovasi = useProxy(profileLandingPageState.programInovasi);
|
||||
const router = useRouter();
|
||||
const [debouncedSearch] = useDebouncedValue(search, 1000); // 500ms delay
|
||||
|
||||
const { data, page, totalPages, loading, load } = stateProgramInovasi.findMany;
|
||||
|
||||
useShallowEffect(() => {
|
||||
load(page, 10, search);
|
||||
}, [page, search]);
|
||||
load(page, 10, debouncedSearch);
|
||||
}, [page, debouncedSearch]);
|
||||
|
||||
const filteredData = data || [];
|
||||
|
||||
@@ -135,15 +136,22 @@ function ListProgramInovasi({ search }: { search: string }) {
|
||||
>
|
||||
<Stack gap={6}>
|
||||
{/* Title */}
|
||||
<Text fw={600}>{item.name}</Text>
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Nama Program</Text>
|
||||
<Text fw={500} lh={1.4}>{item.name}</Text>
|
||||
</Box>
|
||||
|
||||
{/* Description */}
|
||||
<Text fz="sm" c="gray.7" lineClamp={2}>
|
||||
{item.description || '-'}
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Deskripsi</Text>
|
||||
<Text fz="sm" c="gray.7" lineClamp={2}>
|
||||
{item.description || '-'}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{/* Link */}
|
||||
<Box>
|
||||
<Text fz="sm" fw={600} lh={1.4}>Link</Text>
|
||||
<a
|
||||
href={item.link}
|
||||
target="_blank"
|
||||
|
||||
Reference in New Issue
Block a user