Add Fitur Search Di setiap menu

This commit is contained in:
2025-07-08 00:30:55 +08:00
parent 2725c2c064
commit 7e95d5fbb4
38 changed files with 792 additions and 182 deletions

View File

@@ -8,21 +8,25 @@ import { useRouter } from 'next/navigation';
import lowonganKerjaState from '../../_state/ekonomi/lowongan-kerja';
import { useProxy } from 'valtio/utils';
import { useShallowEffect } from '@mantine/hooks';
import { useState } from 'react';
function LowonganKerjaLokal() {
const [search, setSearch] = useState("");
return (
<Box>
<HeaderSearch
title='Lowongan Kerja Lokal'
placeholder='pencarian'
searchIcon={<IconSearch size={20} />}
value={search}
onChange={(e) => setSearch(e.currentTarget.value)}
/>
<ListLowonganKerjaLokal/>
<ListLowonganKerjaLokal search={search} />
</Box>
);
}
function ListLowonganKerjaLokal() {
function ListLowonganKerjaLokal({ search }: { search: string }) {
const lowonganState = useProxy(lowonganKerjaState)
const router = useRouter();
@@ -30,6 +34,15 @@ function ListLowonganKerjaLokal() {
lowonganState.findMany.load();
}, [])
const filteredData = (lowonganState.findMany.data || []).filter(item => {
const keyword = search.toLowerCase();
return (
item.posisi.toLowerCase().includes(keyword) ||
item.namaPerusahaan.toLowerCase().includes(keyword) ||
item.lokasi.toLowerCase().includes(keyword)
);
});
if (!lowonganState.findMany.data) {
return (
<Stack py={10}>
@@ -54,7 +67,7 @@ function ListLowonganKerjaLokal() {
</TableTr>
</TableThead>
<TableTbody>
{lowonganState.findMany.data?.map((item) => (
{filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.posisi}</TableTd>
<TableTd>{item.namaPerusahaan}</TableTd>

View File

@@ -11,20 +11,24 @@ import JudulList from '../../../_com/judulList';
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
import pasarDesaState from '../../../_state/ekonomi/pasar-desa/pasar-desa';
function PasarDesa() {
const [search, setSearch] = useState("")
return (
<Box>
<HeaderSearch
title='Kategori Produk'
placeholder='pencarian'
searchIcon={<IconSearch size={20} />}
value={search}
onChange={(e) => setSearch(e.currentTarget.value)}
/>
<ListPasarDesa />
<ListPasarDesa search={search} />
</Box>
);
}
function ListPasarDesa() {
function ListPasarDesa({ search }: { search: string }) {
const statePasar = useProxy(pasarDesaState.kategoriProduk)
const [modalHapus, setModalHapus] = useState(false)
const [selectedId, setSelectedId] = useState<string | null>(null)
@@ -43,6 +47,13 @@ function ListPasarDesa() {
}
}
const filteredData = (statePasar.findMany.data || []).filter(item => {
const keyword = search.toLowerCase();
return (
item.nama.toLowerCase().includes(keyword)
);
});
if (!statePasar.findMany.data) {
return (
<Stack py={10}>
@@ -67,11 +78,11 @@ function ListPasarDesa() {
</TableTr>
</TableThead>
<TableTbody>
{statePasar.findMany.data?.map((item) => (
{filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.nama}</TableTd>
<TableTd>
<Button onClick={() => router.push(`/admin/ekonomi/pasar-desa/kategori-produk/${item.id}`)}>
<Button color="green" onClick={() => router.push(`/admin/ekonomi/pasar-desa/kategori-produk/${item.id}`)}>
<IconEdit size={20} />
</Button>
</TableTd>

View File

@@ -8,21 +8,25 @@ import { useProxy } from 'valtio/utils';
import HeaderSearch from '../../../_com/header';
import JudulList from '../../../_com/judulList';
import pasarDesaState from '../../../_state/ekonomi/pasar-desa/pasar-desa';
import { useState } from 'react';
function PasarDesa() {
const [search, setSearch] = useState("");
return (
<Box>
<HeaderSearch
title='Produk Pasar Desa'
placeholder='pencarian'
searchIcon={<IconSearch size={20} />}
value={search}
onChange={(e) => setSearch(e.currentTarget.value)}
/>
<ListPasarDesa />
<ListPasarDesa search={search} />
</Box>
);
}
function ListPasarDesa() {
function ListPasarDesa({ search }: { search: string }) {
const statePasar = useProxy(pasarDesaState.pasarDesa)
const router = useRouter();
@@ -30,6 +34,16 @@ function ListPasarDesa() {
statePasar.findMany.load()
}, [])
const filteredData = (statePasar.findMany.data || []).filter(item => {
const keyword = search.toLowerCase();
return (
item.nama.toLowerCase().includes(keyword) ||
item.harga.toString().toLowerCase().includes(keyword) ||
item.rating.toString().toLowerCase().includes(keyword) ||
item.alamatUsaha.toLowerCase().includes(keyword)
);
});
if (!statePasar.findMany.data) {
return (
<Stack py={10}>
@@ -56,7 +70,7 @@ function ListPasarDesa() {
</TableTr>
</TableThead>
<TableTbody>
{statePasar.findMany.data?.map((item) => (
{filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.nama}</TableTd>
<TableTd>Rp.{item.harga}</TableTd>

View File

@@ -13,19 +13,22 @@ import { useEffect, useState } from 'react';
import { CartesianGrid, Legend, Line, LineChart, Tooltip, XAxis, YAxis } from 'recharts';
function ProgramKemiskinan() {
const [search, setSearch] = useState("");
return (
<Box>
<HeaderSearch
title='Program Kemiskinan'
placeholder='pencarian'
searchIcon={<IconSearch size={20} />}
value={search}
onChange={(e) => setSearch(e.currentTarget.value)}
/>
<ListProgramKemiskinan />
<ListProgramKemiskinan search={search}/>
</Box>
);
}
function ListProgramKemiskinan() {
function ListProgramKemiskinan({ search }: { search: string }) {
const programState = useProxy(programKemiskinanState)
const router = useRouter();
const [lineChart, setLineChart] = useState<any[]>([]);
@@ -51,6 +54,15 @@ function ListProgramKemiskinan() {
}
}, [programState.findMany.data])
const filteredData = (programState.findMany.data || []).filter(item => {
const keyword = search.toLowerCase();
return (
item.nama.toLowerCase().includes(keyword) ||
item.deskripsi.toLowerCase().includes(keyword) ||
item.statistik?.tahun.toString().includes(keyword)
);
});
if (!programState.findMany.data) {
return (
<Stack py={10}>
@@ -75,7 +87,7 @@ function ListProgramKemiskinan() {
</TableTr>
</TableThead>
<TableTbody>
{programState.findMany.data?.map((item) => (
{filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.nama}</TableTd>
<TableTd>

View File

@@ -12,44 +12,58 @@ import { useState } from 'react';
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
function HubunganOrganisasi() {
const [search, setSearch] = useState("");
return (
<Box>
<HeaderSearch
title='Hubungan Organisasi'
placeholder='pencarian'
searchIcon={<IconSearch size={20} />}
value={search}
onChange={(e) => setSearch(e.currentTarget.value)}
/>
<ListHubunganOrganisasi />
<ListHubunganOrganisasi search={search} />
</Box>
);
}
function ListHubunganOrganisasi() {
function ListHubunganOrganisasi({ search }: { search: string }) {
const stateOrganisasi = useProxy(strukturorganisasiState.hubunganOrganisasi);
const [modalHapus, setModalHapus] = useState(false)
const [selectedId, setSelectedId] = useState<string | null>(null)
// const params = useParams()
const router = useRouter()
const [modalHapus, setModalHapus] = useState(false);
const [selectedId, setSelectedId] = useState<string | null>(null);
const router = useRouter();
useShallowEffect(() => {
stateOrganisasi.findMany.load()
}, [])
stateOrganisasi.findMany.load();
}, []);
const handleHapus = () => {
if (selectedId) {
stateOrganisasi.delete.byId(selectedId)
setModalHapus(false)
setSelectedId(null)
stateOrganisasi.delete.byId(selectedId);
setModalHapus(false);
setSelectedId(null);
}
}
};
const filteredData = (stateOrganisasi.findMany.data || []).filter(item => {
const keyword = search.toLowerCase();
return (
item.atasan?.namaLengkap?.toLowerCase().includes(keyword) ||
item.bawahan?.namaLengkap?.toLowerCase().includes(keyword) ||
item.tipe?.toLowerCase().includes(keyword)
);
});
if (!stateOrganisasi.findMany.data) {
return (
<Stack py={10}>
<Skeleton h={500} />
</Stack>
)
);
}
return (
<Box py={10}>
<Paper bg={colors['white-1']} p={'md'}>
@@ -68,34 +82,40 @@ function ListHubunganOrganisasi() {
</TableTr>
</TableThead>
<TableTbody>
{([...stateOrganisasi.findMany.data || []]
.sort((a, b) => {
return a.atasan?.namaLengkap.localeCompare(b.atasan?.namaLengkap); // kalau status sama, urut nama
}) // Aktif di atas
).map((item) => (
<TableTr key={item.id}>
<TableTd>{item.atasan?.namaLengkap}</TableTd>
<TableTd>{item.bawahan?.namaLengkap}</TableTd>
<TableTd>{item.tipe}</TableTd>
<TableTd>
<Button bg={"green"} onClick={() => router.push(`/admin/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/hubungan-organisasi/${item.id}`)}>
<IconEdit size={25} />
</Button>
</TableTd>
<TableTd>
<Button color="red" onClick={() => {
setSelectedId(item.id)
setModalHapus(true)
}}>
<IconTrash size={20} />
</Button>
</TableTd>
</TableTr>
))}
{filteredData
.sort((a, b) =>
a.atasan?.namaLengkap.localeCompare(b.atasan?.namaLengkap)
)
.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.atasan?.namaLengkap}</TableTd>
<TableTd>{item.bawahan?.namaLengkap}</TableTd>
<TableTd>{item.tipe}</TableTd>
<TableTd>
<Button
bg="green"
onClick={() => router.push(`/admin/ekonomi/struktur-organisasi-dan-sk-pengurus-bumdesa/hubungan-organisasi/${item.id}`)}
>
<IconEdit size={25} />
</Button>
</TableTd>
<TableTd>
<Button
color="red"
onClick={() => {
setSelectedId(item.id);
setModalHapus(true);
}}
>
<IconTrash size={20} />
</Button>
</TableTd>
</TableTr>
))}
</TableTbody>
</Table>
</Paper>
{/* Modal Konfirmasi Hapus */}
<ModalKonfirmasiHapus
opened={modalHapus}
onClose={() => setModalHapus(false)}
@@ -106,4 +126,5 @@ function ListHubunganOrganisasi() {
);
}
export default HubunganOrganisasi;

View File

@@ -8,21 +8,25 @@ import { useProxy } from 'valtio/utils';
import HeaderSearch from '../../../_com/header';
import JudulList from '../../../_com/judulList';
import strukturorganisasiState from '../../../_state/ekonomi/struktur-organisasi/struktur-organisasi';
import { useState } from 'react';
function Pegawai() {
const [search, setSearch] = useState("");
return (
<Box>
<HeaderSearch
title='Pegawai'
placeholder='pencarian'
searchIcon={<IconSearch size={20} />}
value={search}
onChange={(e) => setSearch(e.currentTarget.value)}
/>
<ListPegawai />
<ListPegawai search={search} />
</Box>
);
}
function ListPegawai() {
function ListPegawai({ search }: { search: string }) {
const stateOrganisasi = useProxy(strukturorganisasiState.pegawai);
const router = useRouter();
@@ -59,8 +63,15 @@ function ListPegawai() {
};
}, []);
// Log render cycle
console.log('Rendering with data:', stateOrganisasi.findMany.data);
const filteredData = (stateOrganisasi.findMany.data || []).filter(item => {
const keyword = search.toLowerCase();
return (
item.namaLengkap?.toLowerCase().includes(keyword) ||
item.gelarAkademik?.toLowerCase().includes(keyword) ||
item.telepon?.toLowerCase().includes(keyword) ||
item.posisi?.nama?.toLowerCase().includes(keyword)
);
});
// Handle loading state
if (stateOrganisasi.findMany.data === null) {
@@ -107,7 +118,7 @@ function ListPegawai() {
console.log('Rendering table with items:', stateOrganisasi.findMany.data);
return null;
})()}
{([...stateOrganisasi.findMany.data || []]
{([...filteredData]
.sort((a, b) => {
if (a.isActive === b.isActive) {
return a.namaLengkap.localeCompare(b.namaLengkap); // kalau status sama, urut nama

View File

@@ -6,25 +6,28 @@ import { useRouter } from 'next/navigation';
import HeaderSearch from '../../../_com/header';
import JudulList from '../../../_com/judulList';
import { useProxy } from 'valtio/utils';
import { useState } from 'react';
import { useShallowEffect } from '@mantine/hooks';
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
import strukturorganisasiState from '../../../_state/ekonomi/struktur-organisasi/struktur-organisasi';
import { useState } from 'react';
function PosisiOrganisasi() {
const [search, setSearch] = useState("");
return (
<Box>
<HeaderSearch
title='Posisi Organisasi'
placeholder='pencarian'
searchIcon={<IconSearch size={20} />}
value={search}
onChange={(e) => setSearch(e.currentTarget.value)}
/>
<ListPosisiOrganisasi />
<ListPosisiOrganisasi search={search} />
</Box>
);
}
function ListPosisiOrganisasi() {
function ListPosisiOrganisasi({ search }: { search: string }) {
const stateOrganisasi = useProxy(strukturorganisasiState.posisiOrganisasi)
const router = useRouter();
const [modalHapus, setModalHapus] = useState(false)
@@ -42,6 +45,15 @@ function ListPosisiOrganisasi() {
}
}
const filteredData = (stateOrganisasi.findMany.data || []).filter(item => {
const keyword = search.toLowerCase();
return (
item.nama?.toLowerCase().includes(keyword) ||
item.deskripsi?.toLowerCase().includes(keyword) ||
item.hierarki?.toString().toLowerCase().includes(keyword)
);
});
if (!stateOrganisasi.findMany.data) {
return (
<Stack py={10}>
@@ -68,7 +80,7 @@ function ListPosisiOrganisasi() {
</TableTr>
</TableThead>
<TableTbody>
{stateOrganisasi.findMany.data?.map((item) => (
{filteredData.map((item) => (
<TableTr key={item.id}>
<TableTd>{item.nama}</TableTd>
<TableTd>