diff --git a/src/components/dashboards/BrandFilter.tsx b/src/components/dashboards/BrandFilter.tsx index a6df500..bff385c 100644 --- a/src/components/dashboards/BrandFilter.tsx +++ b/src/components/dashboards/BrandFilter.tsx @@ -1,14 +1,11 @@ "use client"; import { cn } from "@/lib/utils"; -import { BrandFilterProps } from "@/src/types"; import { useBrandFilter } from "@/src/hooks/useBrandFilter"; -export function BrandFilter({ - selectedBrand, - onSelect, -}: Omit) { - const { brands, isLoading, totalCount } = useBrandFilter(); +export function BrandFilter() { + const { brands, isLoading, totalCount, selectedBrand, handleSelect } = + useBrandFilter(); if (isLoading) { return ( @@ -21,7 +18,7 @@ export function BrandFilter({ return (
- {brands.map((brand) => ( - - ))} + {brands.map((brand) => { + const isActive = + selectedBrand?.toLowerCase() === brand.name.toLowerCase(); + + return ( + + ); + })}
); } diff --git a/src/components/dashboards/DashboardClient.tsx b/src/components/dashboards/DashboardClient.tsx index b249b71..9c65611 100644 --- a/src/components/dashboards/DashboardClient.tsx +++ b/src/components/dashboards/DashboardClient.tsx @@ -3,11 +3,7 @@ import { Header } from "./Header"; import { Frown, Meh, MessageSquareText, Smile, TrendingUp } from "lucide-react"; import { StatCard } from "./StatCard"; -import { - brandData, - sentimentDistribution, - trendData, -} from "@/src/app/dashboard/lib/data"; +import { sentimentDistribution, trendData } from "@/src/app/dashboard/lib/data"; import { ModelInfoSkeleton } from "../skeletons/ModelInfoSkeleton"; import { ModelInfo } from "./ModelInfo"; import { BrandFilter } from "./BrandFilter"; @@ -24,10 +20,8 @@ export default function DashboardClient() { positiveCount, negativeCount, neutralCount, - selectedBrand, loading, modelData, - setSelectedBrand, percentage, } = useDashboards(); @@ -142,10 +136,7 @@ export default function DashboardClient() { Hasil klasifikasi sentimen ulasan produk laptop

- + diff --git a/src/components/dashboards/ReviewTable.tsx b/src/components/dashboards/ReviewTable.tsx index b07ad63..25b5a8f 100644 --- a/src/components/dashboards/ReviewTable.tsx +++ b/src/components/dashboards/ReviewTable.tsx @@ -26,9 +26,15 @@ import { PaginationNext, PaginationPrevious, } from "../ui/pagination"; +import { useSearchParams } from "next/navigation"; export function ReviewTable() { - const { currentData, isLoading, pagination } = useReviewTable(10); + const searchParams = useSearchParams(); + const selectedBrand = searchParams.get("brand"); + const { currentData, isLoading, pagination } = useReviewTable( + 10, + selectedBrand, + ); const { currentPage, totalPages, nextPage, prevPage, goToPage } = pagination; if (isLoading) { @@ -41,7 +47,7 @@ export function ReviewTable() { } return ( -
+
diff --git a/src/hooks/useBrandFilter.ts b/src/hooks/useBrandFilter.ts index 143a9b5..625fb6b 100644 --- a/src/hooks/useBrandFilter.ts +++ b/src/hooks/useBrandFilter.ts @@ -1,9 +1,11 @@ import { useEffect, useState } from "react"; import { getTotalBrandAnalysis } from "../app/dashboard/lib/actions"; +import { useSelectSearch } from "./useSelectSearch"; export const useBrandFilter = () => { const [brands, setBrands] = useState<{ name: string; count: number }[]>([]); const [isLoading, setIsLoading] = useState(true); + const { selectedBrand, handleSelect } = useSelectSearch(); useEffect(() => { const fetchBrands = async () => { @@ -24,5 +26,5 @@ export const useBrandFilter = () => { const totalCount = brands.reduce((sum, b) => sum + (b?.count || 0), 0); - return { brands, isLoading, totalCount }; + return { brands, isLoading, totalCount, selectedBrand, handleSelect }; }; diff --git a/src/hooks/useReviewTable.ts b/src/hooks/useReviewTable.ts index 9101558..c21305e 100644 --- a/src/hooks/useReviewTable.ts +++ b/src/hooks/useReviewTable.ts @@ -1,7 +1,10 @@ import { useEffect, useState, useMemo } from "react"; import { ApiResponse, ReviewItem } from "../types"; -export const useReviewTable = (itemsPerPage: number = 10) => { +export const useReviewTable = ( + itemsPerPage: number = 10, + selectedBrand: string | null = null, +) => { const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(true); const [currentPage, setCurrentPage] = useState(1); @@ -27,34 +30,43 @@ export const useReviewTable = (itemsPerPage: number = 10) => { getReviewData(); }, []); + useEffect(() => { + setCurrentPage(1); + }, [selectedBrand]); + const { currentData, totalPages } = useMemo(() => { - const total = Math.ceil(data.length / itemsPerPage); - const start = (currentPage - 1) * itemsPerPage; + const filteredData = selectedBrand + ? data.filter( + (review) => + review.product?.brand?.toLowerCase() === + selectedBrand.toLowerCase(), + ) + : data; + + const total = Math.ceil(filteredData.length / itemsPerPage) || 1; + + const safePage = currentPage > total ? total : currentPage; + + const start = (safePage - 1) * itemsPerPage; const end = start + itemsPerPage; - const slicedData = data.slice(start, end); return { - currentData: slicedData, + currentData: filteredData.slice(start, end), totalPages: total, }; - }, [data, currentPage, itemsPerPage]); + }, [data, currentPage, itemsPerPage, selectedBrand]); const nextPage = () => { if (currentPage < totalPages) setCurrentPage((prev) => prev + 1); }; - const prevPage = () => { if (currentPage > 1) setCurrentPage((prev) => prev - 1); }; - const goToPage = (pageNumber: number) => { - if (pageNumber >= 1 && pageNumber <= totalPages) { - setCurrentPage(pageNumber); - } + if (pageNumber >= 1 && pageNumber <= totalPages) setCurrentPage(pageNumber); }; return { - data, currentData, isLoading, pagination: { diff --git a/src/hooks/useSelectSearch.ts b/src/hooks/useSelectSearch.ts new file mode 100644 index 0000000..74a938a --- /dev/null +++ b/src/hooks/useSelectSearch.ts @@ -0,0 +1,23 @@ +import { usePathname, useRouter, useSearchParams } from "next/navigation"; + +export const useSelectSearch = () => { + const router = useRouter(); + const pathname = usePathname(); + const searchParams = useSearchParams(); + + const selectedBrand = searchParams.get("brand"); + + const handleSelect = (brandName: string | null) => { + const params = new URLSearchParams(searchParams.toString()); + + if (brandName) { + params.set("brand", brandName); + } else { + params.delete("brand"); + } + + router.push(`${pathname}?${params.toString()}`, { scroll: false }); + }; + + return { selectedBrand, handleSelect }; +};