From 9bbbf4e45e5a5c34a8dbf97b65d0e39a40d79dbe Mon Sep 17 00:00:00 2001 From: Sabda Yagra Date: Wed, 5 Nov 2025 11:35:04 +0700 Subject: [PATCH] fix: fixing filter in all content, image, video, text, audio and spit --- .../content/audio/components/table-audio.tsx | 274 +++++++++++++-- .../content/image/components/table-image.tsx | 293 ++++++++++++++-- .../content/spit/table-spit/table-spit.tsx | 25 +- .../content/teks/components/table-teks.tsx | 281 ++++++++++++++-- .../content/video/components/table-video.tsx | 313 +++++++++++++++--- 5 files changed, 1056 insertions(+), 130 deletions(-) diff --git a/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx b/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx index c00b3e16..42488d40 100644 --- a/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx +++ b/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx @@ -47,9 +47,9 @@ const TableAudio = () => { const router = useRouter(); const searchParams = useSearchParams(); const MySwal = withReactContent(Swal); - const [dataTable, setDataTable] = React.useState([]); const [totalData, setTotalData] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] @@ -59,10 +59,8 @@ const TableAudio = () => { const [rowSelection, setRowSelection] = React.useState({}); const [showData, setShowData] = React.useState("10"); const [page, setPage] = React.useState(1); - const [totalPage, setTotalPage] = React.useState(1); const [search, setSearch] = React.useState(""); const searchTimeout = React.useRef(null); - const [categories, setCategories] = React.useState([]); const [selectedCategories, setSelectedCategories] = React.useState( [] @@ -74,10 +72,13 @@ const TableAudio = () => { const [filterByCreator, setFilterByCreator] = React.useState(""); const [filterBySource, setFilterBySource] = React.useState(""); const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState(""); - const userLevelId = getCookiesDecrypt("ulie"); const roleId = getCookiesDecrypt("urie"); const columns = useTableColumns(); + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: Number(showData), + }); const table = useReactTable({ data: dataTable, @@ -90,11 +91,13 @@ const TableAudio = () => { getFilteredRowModel: getFilteredRowModel(), onColumnVisibilityChange: setColumnVisibility, onRowSelectionChange: setRowSelection, + onPaginationChange: setPagination, state: { sorting, columnFilters, columnVisibility, rowSelection, + pagination, }, }); @@ -108,28 +111,27 @@ const TableAudio = () => { getCategories(); }, [categoryFilter, statusFilter, page, showData, startDate, endDate]); + React.useEffect(() => { + fetchData(); + }, [ + categoryFilter, + statusFilter, + startDate, + endDate, + filterByCreator, + filterBySource, + filterByCreatorGroup, + search, + showData, + page, + ]); + async function getCategories() { const category = await listEnableCategory("4"); const resCategory = category?.data?.data?.content; setCategories(resCategory || []); } - const handleCheckboxChange = (categoryId: number) => { - setSelectedCategories((prev) => - prev.includes(categoryId) - ? prev.filter((id) => id !== categoryId) - : [...prev, categoryId] - ); - - setCategoryFilter((prev) => { - const updated = prev.split(",").filter(Boolean).map(Number); - const newList = updated.includes(categoryId) - ? updated.filter((id) => id !== categoryId) - : [...updated, categoryId]; - return newList.join(","); - }); - }; - async function fetchData(showLoader = false, customSearch?: string) { const formattedStartDate = startDate ? format(new Date(startDate), "yyyy-MM-dd") @@ -150,7 +152,7 @@ const TableAudio = () => { const isForSelf = Number(roleId) === 4; const res = await listDataAudio( - showData, + parseInt(showData) || 10, page - 1, isForSelf, !isForSelf, @@ -181,11 +183,10 @@ const TableAudio = () => { } } - // โœ… Debounced search + SweetAlert besar + // โœ… Debounced search const handleSearch = (e: React.ChangeEvent) => { const value = e.target.value; setSearch(value); - if (searchTimeout.current) clearTimeout(searchTimeout.current); searchTimeout.current = setTimeout(() => { fetchData(true, value); @@ -195,30 +196,59 @@ const TableAudio = () => { const handleSearchFilterBySource = ( e: React.ChangeEvent ) => { - const value = e.target.value; - setFilterBySource(value); + setFilterBySource(e.target.value); fetchData(true); }; const handleSearchFilterByCreator = ( e: React.ChangeEvent ) => { - const value = e.target.value; - setFilterByCreator(value); + setFilterByCreator(e.target.value); fetchData(true); }; - function handleStatusCheckboxChange(value: any) { + const handleCheckboxChange = (categoryId: number) => { + setSelectedCategories((prev) => + prev.includes(categoryId) + ? prev.filter((id) => id !== categoryId) + : [...prev, categoryId] + ); + + setCategoryFilter((prev) => { + const updated = prev.split(",").filter(Boolean).map(Number); + const newList = updated.includes(categoryId) + ? updated.filter((id) => id !== categoryId) + : [...updated, categoryId]; + return newList.join(","); + }); + }; + + const handleStatusCheckboxChange = (value: any) => { setStatusFilter((prev: any) => prev.includes(value) ? prev.filter((status: any) => status !== value) : [...prev, value] ); - } + }; + + // ๐Ÿงน Reset semua filter + const handleResetFilters = () => { + setSelectedCategories([]); + setCategoryFilter(""); + setStatusFilter([]); + setStartDate(""); + setEndDate(""); + setFilterByCreator(""); + setFilterBySource(""); + setFilterByCreatorGroup(""); + setPage(1); + fetchData(true); + }; return (
+ {/* ๐Ÿ” Search bar */}
@@ -226,15 +256,197 @@ const TableAudio = () => {
+ + {/* Filter + Columns + ShowData */} +
+ {/* Show Data Dropdown */} +
+ + + + + + { + setShowData(value); + setPagination((prev) => ({ + ...prev, + pageSize: Number(value), + pageIndex: 0, + })); + setPage(1); + }} + > + + 10 Data + + + 50 Data + + + 100 Data + + + 250 Data + + + + +
+ + {/* Filter Dropdown */} + + + + + + {/* ๐Ÿงน Reset All Button */} +
+ +
+ + + {categories.length > 0 ? ( + categories.map((category) => ( +
+ handleCheckboxChange(category.id)} + /> + +
+ )) + ) : ( +

+ Tidak ada kategori. +

+ )} + +
+ + setStartDate(e.target.value)} + /> +
+
+ + setEndDate(e.target.value)} + /> +
+ +
+ + +
+ +
+ + +
+ + + {[1, 2, 3, 4].map((id) => { + const label = + id === 1 + ? "Menunggu Review" + : id === 2 + ? "Diterima" + : id === 3 + ? "Minta Update" + : "Ditolak"; + return ( +
+ handleStatusCheckboxChange(id)} + /> + +
+ ); + })} +
+
+ + {/* Columns Dropdown */} + + + + + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => ( + + column.toggleVisibility(!!value) + } + > + {column.id} + + ))} + + +
+ {/* === TABLE === */} {table.getHeaderGroups().map((headerGroup) => ( @@ -271,7 +483,7 @@ const TableAudio = () => { ) : ( - No results. + Tidak ada hasil ditemukan. )} diff --git a/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx b/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx index b399a8c4..2d056bd2 100644 --- a/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx +++ b/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx @@ -34,7 +34,7 @@ import { } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; -import { useParams, useRouter, useSearchParams } from "next/navigation"; +import { useParams } from "next/navigation"; import TablePagination from "@/components/table/table-pagination"; import { listDataImage, listEnableCategory } from "@/service/content/content"; import Swal from "sweetalert2"; @@ -44,14 +44,14 @@ import { format } from "date-fns"; import useTableColumns from "./columns"; const TableImage = () => { - const router = useRouter(); - const searchParams = useSearchParams(); const params = useParams(); const locale = params?.locale; const MySwal = withReactContent(Swal); + // === STATES === const [dataTable, setDataTable] = React.useState([]); const [totalData, setTotalData] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] @@ -61,10 +61,9 @@ const TableImage = () => { const [rowSelection, setRowSelection] = React.useState({}); const [showData, setShowData] = React.useState("10"); const [page, setPage] = React.useState(1); - const [totalPage, setTotalPage] = React.useState(1); const [search, setSearch] = React.useState(""); - const searchTimeout = React.useRef(null); + // === FILTER STATES === const [categories, setCategories] = React.useState([]); const [selectedCategories, setSelectedCategories] = React.useState( [] @@ -76,6 +75,10 @@ const TableImage = () => { const [filterByCreator, setFilterByCreator] = React.useState(""); const [filterBySource, setFilterBySource] = React.useState(""); const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState(""); + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: Number(showData), + }); const roleId = getCookiesDecrypt("urie"); const userLevelId = getCookiesDecrypt("ulie"); const columns = useTableColumns(); @@ -90,20 +93,38 @@ const TableImage = () => { getSortedRowModel: getSortedRowModel(), getFilteredRowModel: getFilteredRowModel(), onColumnVisibilityChange: setColumnVisibility, + onPaginationChange: setPagination, onRowSelectionChange: setRowSelection, state: { sorting, columnFilters, columnVisibility, rowSelection, + pagination, }, }); + // === EFFECTS === React.useEffect(() => { fetchData(); getCategories(); }, [categoryFilter, statusFilter, page, showData, startDate, endDate]); + React.useEffect(() => { + fetchData(); + }, [ + categoryFilter, + statusFilter, + startDate, + endDate, + filterByCreator, + filterBySource, + filterByCreatorGroup, + search, + showData, + page, + ]); + async function getCategories() { const category = await listEnableCategory("1"); const resCategory = category?.data?.data?.content; @@ -124,15 +145,13 @@ const TableImage = () => { title: "Memuat data...", html: "Mohon tunggu sebentar", allowOutsideClick: false, - didOpen: () => { - MySwal.showLoading(); - }, + didOpen: () => MySwal.showLoading(), }); } const isForSelf = Number(roleId) === 4; const res = await listDataImage( - showData, + parseInt(showData) || 10, page - 1, isForSelf, !isForSelf, @@ -143,18 +162,19 @@ const TableImage = () => { filterBySource, formattedStartDate, formattedEndDate, - customSearch ?? search, // โœ… gunakan customSearch jika ada + customSearch ?? search, filterByCreatorGroup, locale == "en" ); const data = res?.data?.data; const contentData = data?.content || []; - contentData.forEach((item: any, index: number) => { - item.no = (page - 1) * Number(showData) + index + 1; - }); + const newData = contentData.map((item: any, index: number) => ({ + ...item, + no: (page - 1) * Number(showData) + index + 1, + })); - setDataTable(contentData); + setDataTable([...newData]); setTotalData(data?.totalElements || 0); setTotalPage(data?.totalPages || 1); } catch (error) { @@ -164,23 +184,70 @@ const TableImage = () => { } } + // === HANDLERS === + const handleCheckboxChange = (categoryId: number) => { + setSelectedCategories((prev) => + prev.includes(categoryId) + ? prev.filter((id) => id !== categoryId) + : [...prev, categoryId] + ); + + setCategoryFilter((prev) => { + const updated = prev.split(",").filter(Boolean).map(Number); + const newCategories = updated.includes(categoryId) + ? updated.filter((id) => id !== categoryId) + : [...updated, categoryId]; + return newCategories.join(","); + }); + }; + + const handleStatusCheckboxChange = (value: any) => { + setStatusFilter((prev: any) => + prev.includes(value) + ? prev.filter((status: any) => status !== value) + : [...prev, value] + ); + }; + const handleSearch = (e: React.ChangeEvent) => { const value = e.target.value; setSearch(value); + fetchData(true, value); + }; - if (searchTimeout.current) clearTimeout(searchTimeout.current); + const handleSearchFilterByCreator = ( + e: React.ChangeEvent + ) => { + setFilterByCreator(e.target.value); + fetchData(); + }; - searchTimeout.current = setTimeout(() => { - // โœ… panggil fetchData dengan nilai search terkini (bukan dari state lama) - fetchData(true, value); - }, 500); + const handleSearchFilterBySource = ( + e: React.ChangeEvent + ) => { + setFilterBySource(e.target.value); + fetchData(); + }; + + // ๐Ÿงน RESET FILTER + const handleResetFilters = () => { + setSelectedCategories([]); + setCategoryFilter(""); + setStatusFilter([]); + setStartDate(""); + setEndDate(""); + setFilterByCreator(""); + setFilterBySource(""); + setFilterByCreatorGroup(""); + setPage(1); + fetchData(true); }; return (
-
- {/* Search bar */} -
+ {/* ๐Ÿ” FILTER & SEARCH BAR */} +
+
@@ -194,9 +261,189 @@ const TableImage = () => { />
+ + {/* FILTER BUTTONS */} +
+ {/* Show Data Dropdown */} +
+ + + + + + { + setShowData(value); + setPagination((prev) => ({ + ...prev, + pageSize: Number(value), + pageIndex: 0, + })); + setPage(1); + }} + > + + 10 Data + + + 50 Data + + + 100 Data + + + 250 Data + + + + +
+ + {/* Filter Dropdown */} + + + + + + {/* ๐Ÿงน Reset All Button */} +
+ +
+ + + {categories.length > 0 ? ( + categories.map((category) => ( +
+ handleCheckboxChange(category.id)} + /> + +
+ )) + ) : ( +

+ Tidak ada kategori. +

+ )} + +
+ + setStartDate(e.target.value)} + /> +
+
+ + setEndDate(e.target.value)} + /> +
+ +
+ + +
+
+ + +
+ + + {[1, 2, 3, 4].map((id) => { + const label = + id === 1 + ? "Menunggu Review" + : id === 2 + ? "Diterima" + : id === 3 + ? "Minta Update" + : "Ditolak"; + return ( +
+ handleStatusCheckboxChange(id)} + /> + +
+ ); + })} +
+
+ + {/* Columns Dropdown */} + + + + + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => ( + + column.toggleVisibility(!!value) + } + > + {column.id} + + ))} + + +
- {/* Table */} + {/* === TABLE === */}
{table.getHeaderGroups().map((headerGroup) => ( diff --git a/app/[locale]/(protected)/contributor/content/spit/table-spit/table-spit.tsx b/app/[locale]/(protected)/contributor/content/spit/table-spit/table-spit.tsx index 00d73202..58e019a1 100644 --- a/app/[locale]/(protected)/contributor/content/spit/table-spit/table-spit.tsx +++ b/app/[locale]/(protected)/contributor/content/spit/table-spit/table-spit.tsx @@ -187,6 +187,13 @@ const TableSPIT = () => { setCategories(resCategory || []); } + // Panggil fetchData otomatis ketika dateFilter berubah + React.useEffect(() => { + if (dateFilter) { + fetchData(); + } + }, [dateFilter]); + async function fetchData() { let isPublish; if (statusFilter.length === 0) { @@ -198,7 +205,7 @@ const TableSPIT = () => { } const formattedStartDate = dateFilter - ? format(parseISO(dateFilter), "yyyy-MM-dd") + ? format(new Date(dateFilter + "T00:00:00"), "yyyy-MM-dd") : ""; try { @@ -305,7 +312,7 @@ const TableSPIT = () => {

Filter

-
+ {/*
{ onChange={(e) => setDateFilter(e.target.value)} className="max-w-sm" /> +
*/} +
+ + { + const value = e.target.value; + setDateFilter(value); + fetchData(); // langsung panggil data baru + }} + className="max-w-sm" + />
+
{ const [dataTable, setDataTable] = React.useState([]); const [totalData, setTotalData] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] @@ -59,10 +60,10 @@ const TableTeks = () => { const [rowSelection, setRowSelection] = React.useState({}); const [showData, setShowData] = React.useState("10"); const [page, setPage] = React.useState(1); - const [totalPage, setTotalPage] = React.useState(1); const [search, setSearch] = React.useState(""); const searchTimeout = React.useRef(null); + // === FILTER STATES === const [categories, setCategories] = React.useState([]); const [selectedCategories, setSelectedCategories] = React.useState( [] @@ -74,11 +75,15 @@ const TableTeks = () => { const [filterByCreator, setFilterByCreator] = React.useState(""); const [filterBySource, setFilterBySource] = React.useState(""); const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState(""); - const userLevelId = getCookiesDecrypt("ulie"); const roleId = getCookiesDecrypt("urie"); const columns = useTableColumns(); + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: Number(showData), + }); + const table = useReactTable({ data: dataTable, columns, @@ -90,11 +95,13 @@ const TableTeks = () => { getFilteredRowModel: getFilteredRowModel(), onColumnVisibilityChange: setColumnVisibility, onRowSelectionChange: setRowSelection, + onPaginationChange: setPagination, state: { sorting, columnFilters, columnVisibility, rowSelection, + pagination, }, }); @@ -108,28 +115,27 @@ const TableTeks = () => { getCategories(); }, [categoryFilter, statusFilter, page, showData, startDate, endDate]); + React.useEffect(() => { + fetchData(); + }, [ + categoryFilter, + statusFilter, + startDate, + endDate, + filterByCreator, + filterBySource, + filterByCreatorGroup, + search, + showData, + page, + ]); + async function getCategories() { const category = await listEnableCategory("3"); const resCategory = category?.data?.data?.content; setCategories(resCategory || []); } - const handleCheckboxChange = (categoryId: number) => { - setSelectedCategories((prev) => - prev.includes(categoryId) - ? prev.filter((id) => id !== categoryId) - : [...prev, categoryId] - ); - - setCategoryFilter((prev) => { - const updated = prev.split(",").filter(Boolean).map(Number); - const newList = updated.includes(categoryId) - ? updated.filter((id) => id !== categoryId) - : [...updated, categoryId]; - return newList.join(","); - }); - }; - async function fetchData(showLoader = false, customSearch?: string) { const formattedStartDate = startDate ? format(new Date(startDate), "yyyy-MM-dd") @@ -150,7 +156,7 @@ const TableTeks = () => { const isForSelf = Number(roleId) === 4; const res = await listDataTeks( - showData, + parseInt(showData) || 10, page - 1, isForSelf, !isForSelf, @@ -181,13 +187,11 @@ const TableTeks = () => { } } - // โœ… Debounced search + SweetAlert besar + // โœ… Debounced search const handleSearch = (e: React.ChangeEvent) => { const value = e.target.value; setSearch(value); - if (searchTimeout.current) clearTimeout(searchTimeout.current); - searchTimeout.current = setTimeout(() => { fetchData(true, value); }, 500); @@ -196,30 +200,59 @@ const TableTeks = () => { const handleSearchFilterBySource = ( e: React.ChangeEvent ) => { - const value = e.target.value; - setFilterBySource(value); + setFilterBySource(e.target.value); fetchData(true); }; - function handleStatusCheckboxChange(value: any) { + const handleSearchFilterByCreator = ( + e: React.ChangeEvent + ) => { + setFilterByCreator(e.target.value); + fetchData(true); + }; + + const handleCheckboxChange = (categoryId: number) => { + setSelectedCategories((prev) => + prev.includes(categoryId) + ? prev.filter((id) => id !== categoryId) + : [...prev, categoryId] + ); + + setCategoryFilter((prev) => { + const updated = prev.split(",").filter(Boolean).map(Number); + const newList = updated.includes(categoryId) + ? updated.filter((id) => id !== categoryId) + : [...updated, categoryId]; + return newList.join(","); + }); + }; + + const handleStatusCheckboxChange = (value: any) => { setStatusFilter((prev: any) => prev.includes(value) ? prev.filter((status: any) => status !== value) : [...prev, value] ); - } + }; - const handleSearchFilterByCreator = ( - e: React.ChangeEvent - ) => { - const value = e.target.value; - setFilterByCreator(value); + // ๐Ÿงน Reset semua filter + const handleResetFilters = () => { + setSelectedCategories([]); + setCategoryFilter(""); + setStatusFilter([]); + setStartDate(""); + setEndDate(""); + setFilterByCreator(""); + setFilterBySource(""); + setFilterByCreatorGroup(""); + setPage(1); fetchData(true); }; return (
+ {/* ๐Ÿ” Search bar */}
@@ -227,15 +260,197 @@ const TableTeks = () => {
+ + {/* Filter + Columns + ShowData */} +
+ {/* Show Data Dropdown */} +
+ + + + + + { + setShowData(value); + setPagination((prev) => ({ + ...prev, + pageSize: Number(value), + pageIndex: 0, + })); + setPage(1); + }} + > + + 10 Data + + + 50 Data + + + 100 Data + + + 250 Data + + + + +
+ + {/* Filter Dropdown */} + + + + + + {/* ๐Ÿงน Reset All Button */} +
+ +
+ + + {categories.length > 0 ? ( + categories.map((category) => ( +
+ handleCheckboxChange(category.id)} + /> + +
+ )) + ) : ( +

+ Tidak ada kategori. +

+ )} + +
+ + setStartDate(e.target.value)} + /> +
+
+ + setEndDate(e.target.value)} + /> +
+ +
+ + +
+ +
+ + +
+ + + {[1, 2, 3, 4].map((id) => { + const label = + id === 1 + ? "Menunggu Review" + : id === 2 + ? "Diterima" + : id === 3 + ? "Minta Update" + : "Ditolak"; + return ( +
+ handleStatusCheckboxChange(id)} + /> + +
+ ); + })} +
+
+ + {/* Columns Dropdown */} + + + + + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => ( + + column.toggleVisibility(!!value) + } + > + {column.id} + + ))} + + +
+ {/* === TABLE === */}
{table.getHeaderGroups().map((headerGroup) => ( @@ -272,7 +487,7 @@ const TableTeks = () => { ) : ( - No results. + Tidak ada hasil ditemukan. )} diff --git a/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx b/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx index 92ae45e9..343b81bb 100644 --- a/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx +++ b/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx @@ -21,6 +21,15 @@ import { TableHeader, TableRow, } from "@/components/ui/table"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; import { ChevronDown, Search } from "lucide-react"; import { getCookiesDecrypt } from "@/lib/utils"; import { Input } from "@/components/ui/input"; @@ -31,6 +40,7 @@ import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; import { format } from "date-fns"; import useTableColumns from "./columns"; +import { Label } from "@/components/ui/label"; import { useRouter } from "@/i18n/routing"; import { useSearchParams } from "next/navigation"; @@ -38,8 +48,10 @@ const TableVideo = () => { const router = useRouter(); const searchParams = useSearchParams(); const MySwal = withReactContent(Swal); + const [dataTable, setDataTable] = React.useState([]); const [totalData, setTotalData] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] @@ -49,9 +61,10 @@ const TableVideo = () => { const [rowSelection, setRowSelection] = React.useState({}); const [showData, setShowData] = React.useState("10"); const [page, setPage] = React.useState(1); - const [totalPage, setTotalPage] = React.useState(1); const [search, setSearch] = React.useState(""); const searchTimeout = React.useRef(null); + + // === FILTER STATES === const [categories, setCategories] = React.useState([]); const [selectedCategories, setSelectedCategories] = React.useState( [] @@ -63,9 +76,14 @@ const TableVideo = () => { const [filterByCreator, setFilterByCreator] = React.useState(""); const [filterBySource, setFilterBySource] = React.useState(""); const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState(""); + const userLevelId = getCookiesDecrypt("ulie"); const roleId = getCookiesDecrypt("urie"); const columns = useTableColumns(); + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: Number(showData), + }); const table = useReactTable({ data: dataTable, @@ -78,11 +96,13 @@ const TableVideo = () => { getFilteredRowModel: getFilteredRowModel(), onColumnVisibilityChange: setColumnVisibility, onRowSelectionChange: setRowSelection, + onPaginationChange: setPagination, state: { sorting, columnFilters, columnVisibility, rowSelection, + pagination, }, }); @@ -96,28 +116,27 @@ const TableVideo = () => { getCategories(); }, [categoryFilter, statusFilter, page, showData, startDate, endDate]); + React.useEffect(() => { + fetchData(); + }, [ + categoryFilter, + statusFilter, + startDate, + endDate, + filterByCreator, + filterBySource, + filterByCreatorGroup, + search, + showData, + page, + ]); + async function getCategories() { const category = await listEnableCategory("2"); const resCategory = category?.data?.data?.content; setCategories(resCategory || []); } - const handleCheckboxChange = (categoryId: number) => { - setSelectedCategories((prev) => - prev.includes(categoryId) - ? prev.filter((id) => id !== categoryId) - : [...prev, categoryId] - ); - - setCategoryFilter((prev) => { - const updated = prev.split(",").filter(Boolean).map(Number); - const newList = updated.includes(categoryId) - ? updated.filter((id) => id !== categoryId) - : [...updated, categoryId]; - return newList.join(","); - }); - }; - async function fetchData(showLoader = false, customSearch?: string) { const formattedStartDate = startDate ? format(new Date(startDate), "yyyy-MM-dd") @@ -138,7 +157,7 @@ const TableVideo = () => { const isForSelf = Number(roleId) === 4; const res = await listDataVideo( - showData, + parseInt(showData) || 10, page - 1, isForSelf, !isForSelf, @@ -155,11 +174,12 @@ const TableVideo = () => { const data = res?.data?.data; const contentData = data?.content || []; - contentData.forEach((item: any, index: number) => { - item.no = (page - 1) * Number(showData) + index + 1; - }); + const newData = contentData.map((item: any, index: number) => ({ + ...item, + no: (page - 1) * Number(showData) + index + 1, + })); - setDataTable(contentData); + setDataTable([...newData]); setTotalData(data?.totalElements || 0); setTotalPage(data?.totalPages || 1); } catch (error) { @@ -169,24 +189,21 @@ const TableVideo = () => { } } - // โœ… Debounced search + SweetAlert besar - const handleSearch = (e: React.ChangeEvent) => { - const value = e.target.value; - setSearch(value); + // === HANDLERS === + const handleCheckboxChange = (categoryId: number) => { + setSelectedCategories((prev) => + prev.includes(categoryId) + ? prev.filter((id) => id !== categoryId) + : [...prev, categoryId] + ); - if (searchTimeout.current) clearTimeout(searchTimeout.current); - - searchTimeout.current = setTimeout(() => { - fetchData(true, value); - }, 500); - }; - - const handleSearchFilterBySource = ( - e: React.ChangeEvent - ) => { - const value = e.target.value; - setFilterBySource(value); - fetchData(true); + setCategoryFilter((prev) => { + const updated = prev.split(",").filter(Boolean).map(Number); + const newList = updated.includes(categoryId) + ? updated.filter((id) => id !== categoryId) + : [...updated, categoryId]; + return newList.join(","); + }); }; function handleStatusCheckboxChange(value: any) { @@ -197,6 +214,15 @@ const TableVideo = () => { ); } + const handleSearch = (e: React.ChangeEvent) => { + const value = e.target.value; + setSearch(value); + if (searchTimeout.current) clearTimeout(searchTimeout.current); + searchTimeout.current = setTimeout(() => { + fetchData(true, value); + }, 500); + }; + const handleSearchFilterByCreator = ( e: React.ChangeEvent ) => { @@ -205,9 +231,32 @@ const TableVideo = () => { fetchData(true); }; + const handleSearchFilterBySource = ( + e: React.ChangeEvent + ) => { + const value = e.target.value; + setFilterBySource(value); + fetchData(true); + }; + + // ๐Ÿงน Reset semua filter + const handleResetFilters = () => { + setSelectedCategories([]); + setCategoryFilter(""); + setStatusFilter([]); + setStartDate(""); + setEndDate(""); + setFilterByCreator(""); + setFilterBySource(""); + setFilterByCreatorGroup(""); + setPage(1); + fetchData(true); + }; + return (
+ {/* ๐Ÿ” Search bar */}
@@ -215,15 +264,197 @@ const TableVideo = () => {
+ + {/* Filter & Columns & ShowData */} +
+ {/* Show Data Dropdown */} +
+ + + + + + { + setShowData(value); + setPagination((prev) => ({ + ...prev, + pageSize: Number(value), + pageIndex: 0, + })); + setPage(1); + }} + > + + 10 Data + + + 50 Data + + + 100 Data + + + 250 Data + + + + +
+ + {/* Filter Dropdown */} + + + + + + {/* ๐Ÿงน Reset All Button */} +
+ +
+ + + {categories.length > 0 ? ( + categories.map((category) => ( +
+ handleCheckboxChange(category.id)} + /> + +
+ )) + ) : ( +

+ Tidak ada kategori. +

+ )} + +
+ + setStartDate(e.target.value)} + /> +
+
+ + setEndDate(e.target.value)} + /> +
+ +
+ + +
+ +
+ + +
+ + + {[1, 2, 3, 4].map((id) => { + const label = + id === 1 + ? "Menunggu Review" + : id === 2 + ? "Diterima" + : id === 3 + ? "Minta Update" + : "Ditolak"; + return ( +
+ handleStatusCheckboxChange(id)} + /> + +
+ ); + })} +
+
+ + {/* Columns Toggle */} + + + + + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => ( + + column.toggleVisibility(!!value) + } + > + {column.id} + + ))} + + +
+ {/* === TABLE === */}
{table.getHeaderGroups().map((headerGroup) => ( @@ -260,7 +491,7 @@ const TableVideo = () => { ) : ( - No results. + Tidak ada hasil ditemukan. )}