From bb32af93b2ab27a9a0a462a465897c2231674db7 Mon Sep 17 00:00:00 2001 From: Pablo Lara Date: Thu, 5 Sep 2024 13:12:20 +0200 Subject: [PATCH] feat: filters, search and sorting is working as expected --- actions/providers.ts | 8 ++-- app/(prowler)/providers/page.tsx | 16 ++++---- .../providers/table/DataTableColumnHeader.tsx | 15 +++++-- .../providers/table/FilterColumnTable.tsx | 40 ++++++++++++++++--- hooks/useDebounce.ts | 2 +- 5 files changed, 60 insertions(+), 21 deletions(-) diff --git a/actions/providers.ts b/actions/providers.ts index b69ce2e98a..2ee10763e8 100644 --- a/actions/providers.ts +++ b/actions/providers.ts @@ -26,11 +26,13 @@ export const getProvider = async ({ // Handle multiple filters Object.entries(filters).forEach(([key, value]) => { - url.searchParams.append(key, String(value)); + if (key !== "filter[search]") { + url.searchParams.append(key, String(value)); + } }); - console.log({ query }); + try { - const providers = await fetch(`${url.toString()}`, { + const providers = await fetch(url.toString(), { headers: { "X-Tenant-ID": `${tenantId}`, }, diff --git a/app/(prowler)/providers/page.tsx b/app/(prowler)/providers/page.tsx index a28d4ba08d..a234ffaa8c 100644 --- a/app/(prowler)/providers/page.tsx +++ b/app/(prowler)/providers/page.tsx @@ -1,5 +1,4 @@ import { Spacer } from "@nextui-org/react"; -import { redirect } from "next/navigation"; import { Suspense } from "react"; import { getProvider } from "@/actions"; @@ -41,25 +40,24 @@ const SSRDataTable = async ({ }: { searchParams: SearchParamsProps; }) => { - const query = searchParams?.query || ""; - const page = searchParams?.page || "1"; - const sort = searchParams?.sort || ""; + const page = parseInt(searchParams.page?.toString() || "1", 10); + const sort = searchParams.sort?.toString() || ""; // Extract all filter parameters const filters = Object.fromEntries( Object.entries(searchParams).filter(([key]) => key.startsWith("filter[")), ); - const providersData = await getProvider({ query, page, sort, filters }); - const [providers] = await Promise.all([providersData]); + // Extract query from filters + const query = (filters["filter[search]"] as string) || ""; - if (providers?.errors) redirect("/providers"); + const providersData = await getProvider({ query, page, sort, filters }); return ( ); }; diff --git a/components/providers/table/DataTableColumnHeader.tsx b/components/providers/table/DataTableColumnHeader.tsx index 6051a3ef87..3b460ae937 100644 --- a/components/providers/table/DataTableColumnHeader.tsx +++ b/components/providers/table/DataTableColumnHeader.tsx @@ -27,7 +27,8 @@ export const DataTableColumnHeader = ({ const searchParams = useSearchParams(); const getToggleSortingHandler = () => { - const currentSortParam = searchParams.get("sort"); + const currentParams = new URLSearchParams(searchParams.toString()); + const currentSortParam = currentParams.get("sort"); let newSortParam = ""; if (currentSortParam === `${param}`) { @@ -41,13 +42,21 @@ export const DataTableColumnHeader = ({ newSortParam = `${param}`; } - // Construct the new URL with the sorting parameter - const newUrl = newSortParam ? `${pathname}?sort=${newSortParam}` : pathname; + // Update or remove the sort parameter + if (newSortParam) { + currentParams.set("sort", newSortParam); + } else { + currentParams.delete("sort"); + } + + // Construct the new URL with all parameters + const newUrl = `${pathname}?${currentParams.toString()}`; router.push(newUrl, { scroll: false, }); }; + const renderSortIcon = () => { const currentSortParam = searchParams.get("sort"); if ( diff --git a/components/providers/table/FilterColumnTable.tsx b/components/providers/table/FilterColumnTable.tsx index 739d630d0f..02e7a54802 100644 --- a/components/providers/table/FilterColumnTable.tsx +++ b/components/providers/table/FilterColumnTable.tsx @@ -1,4 +1,5 @@ import { Button, Input } from "@nextui-org/react"; +import { XCircle } from "lucide-react"; // Import the clear icon import { useRouter, useSearchParams } from "next/navigation"; import { useCallback, useEffect, useMemo, useState } from "react"; @@ -11,7 +12,10 @@ interface FilterColumnTableProps { export function FilterColumnTable({ filters }: FilterColumnTableProps) { const router = useRouter(); const searchParams = useSearchParams(); - const [searchQuery, setSearchQuery] = useState(""); + const [searchQuery, setSearchQuery] = useState(() => { + // Initialize searchQuery with the current search filter value from URL + return searchParams.get("filter[search]") || ""; + }); const debouncedSearchQuery = useDebounce(searchQuery, 300); const activeFilters = useMemo(() => { @@ -54,19 +58,29 @@ export function FilterColumnTable({ filters }: FilterColumnTableProps) { } else { params.delete("filter[search]"); } - console.log(params.toString(), "en el apply search"); - router.push(`?${params.toString()}`, { scroll: false }); + router.replace(`?${params.toString()}`, { scroll: false }); }, [router, searchParams], ); + const clearAllFilters = useCallback(() => { + const params = new URLSearchParams(); + router.push(`?${params.toString()}`, { scroll: false }); + setSearchQuery(""); // Clear the search input + }, [router]); + + const clearIconSearch = () => { + setSearchQuery(""); + applySearch(""); + }; + useEffect(() => { applySearch(debouncedSearchQuery); }, [debouncedSearchQuery, applySearch]); return (
-
+
+ + + ) + } />
-
+
{filters.flatMap(({ key, values }) => values.map((value) => ( )), )} +
); diff --git a/hooks/useDebounce.ts b/hooks/useDebounce.ts index 3351cba2fc..f0d8d7c3bf 100644 --- a/hooks/useDebounce.ts +++ b/hooks/useDebounce.ts @@ -4,7 +4,7 @@ export function useDebounce(value: T, delay?: number): T { const [debouncedValue, setDebouncedValue] = useState(value); useEffect(() => { - const timer = setTimeout(() => setDebouncedValue(value), delay ?? 800); + const timer = setTimeout(() => setDebouncedValue(value), delay ?? 900); return () => { clearTimeout(timer);