feat: add option visibility list brand button.

This commit is contained in:
Mahen 2026-02-24 21:32:10 +07:00
parent bfc91e3a22
commit c8eb618a3a
3 changed files with 68 additions and 19 deletions

View File

@ -2,10 +2,19 @@
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { useBrandFilter } from "@/src/hooks/useBrandFilter"; import { useBrandFilter } from "@/src/hooks/useBrandFilter";
import { Button } from "../ui/button";
export function BrandFilter() { export function BrandFilter() {
const { brands, isLoading, totalCount, selectedBrand, handleSelect } = const {
useBrandFilter(); isLoading,
totalCount,
selectedBrand,
visibleBrands,
isExpanded,
validBrands,
setIsExpanded,
handleSelect,
} = useBrandFilter();
if (isLoading) { if (isLoading) {
return ( return (
@ -29,27 +38,52 @@ export function BrandFilter() {
Semua ({totalCount.toLocaleString()}) Semua ({totalCount.toLocaleString()})
</button> </button>
{brands.map((brand) => { <div className="flex flex-wrap gap-2">
if (brand.count === 0) return null; {visibleBrands.map((brand) => {
const isActive =
selectedBrand?.toLowerCase() === brand.name.toLowerCase();
const isActive = return (
selectedBrand?.toLowerCase() === brand.name.toLowerCase(); <button
key={brand.name}
onClick={() => handleSelect(brand.name)}
className={cn(
"rounded-lg border px-4 py-2 text-sm font-medium transition-all cursor-pointer",
isActive
? "border-primary bg-primary text-primary-foreground"
: "border-border bg-card text-muted-foreground hover:border-primary/50 hover:text-foreground",
)}
>
{brand.name} ({brand.count.toLocaleString()})
</button>
);
})}
return ( {!isExpanded && validBrands.length > 3 && (
<button <button
key={brand.name} onClick={() => setIsExpanded(true)}
onClick={() => handleSelect(brand.name)}
className={cn( className={cn(
"rounded-lg border px-4 py-2 text-sm font-medium transition-all cursor-pointer", "rounded-lg border border-dashed px-4 py-2 text-sm font-medium hover:bg-accent transition-all cursor-pointer",
isActive "flex-1 min-w-25 sm:flex-none",
? "border-primary bg-primary text-primary-foreground"
: "border-border bg-card text-muted-foreground hover:border-primary/50 hover:text-foreground",
)} )}
> >
{brand.name} ({brand.count.toLocaleString()}) {validBrands.length - 3} Lainnya
</button> </button>
); )}
})}
{isExpanded && (
<Button
type="button"
variant="ghost"
onClick={() => {
setIsExpanded(false);
}}
className="text-red-500 hover:text-red-700 hover:bg-red-50 shrink-0"
>
</Button>
)}
</div>
</div> </div>
); );
} }

View File

@ -50,10 +50,10 @@ export default function DashboardClient() {
<div className="mt-6 flex items-center justify-center gap-4 text-sm text-white/70"> <div className="mt-6 flex items-center justify-center gap-4 text-sm text-white/70">
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<TrendingUp className="h-4 w-4" /> <TrendingUp className="h-4 w-4" />
Akurasi 92.4% Akurasi 82.0%
</span> </span>
<span></span> <span></span>
<span>XGBoost + TF-IDF</span> <span>XGBoost + SMOTE + Chi-Square</span>
<span></span> <span></span>
<span>Real-time Analysis</span> <span>Real-time Analysis</span>
</div> </div>

View File

@ -6,6 +6,7 @@ export const useBrandFilter = () => {
const [brands, setBrands] = useState<{ name: string; count: number }[]>([]); const [brands, setBrands] = useState<{ name: string; count: number }[]>([]);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const { selectedBrand, handleSelect } = useSelectSearch(); const { selectedBrand, handleSelect } = useSelectSearch();
const [isExpanded, setIsExpanded] = useState(false);
useEffect(() => { useEffect(() => {
const fetchBrands = async () => { const fetchBrands = async () => {
@ -28,5 +29,19 @@ export const useBrandFilter = () => {
const totalCount = brands.reduce((sum, b) => sum + (b?.count || 0), 0); const totalCount = brands.reduce((sum, b) => sum + (b?.count || 0), 0);
return { brands, isLoading, totalCount, selectedBrand, handleSelect }; const validBrands = brands.filter((brand) => brand.count > 0);
const visibleBrands = isExpanded ? validBrands : validBrands.slice(0, 3);
return {
brands,
isLoading,
totalCount,
selectedBrand,
visibleBrands,
validBrands,
isExpanded,
handleSelect,
setIsExpanded,
};
}; };