feat: add option visibility list brand button.
This commit is contained in:
parent
bfc91e3a22
commit
c8eb618a3a
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue