"use client";
import { useState } from "react";
import {
Filter,
X,
AlertTriangle,
Zap,
Grid,
List,
RefreshCw,
ArrowUpDown,
LayoutGrid,
Tag,
Beaker,
BarChart3,
} from "lucide-react";
import * as LucideIcons from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Checkbox } from "@/components/ui/checkbox";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Switch } from "@/components/ui/switch";
import { Slider } from "@/components/ui/slider";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { Badge } from "@/components/ui/badge";
import { Separator } from "@/components/ui/separator";
import { SortDropdown } from "@/app/components/SortDropdown";
import { FilterBadges } from "@/app/components/FilterBadge";
import {
ProductFilters,
NUTRITION_GRADES,
NOVA_GROUPS,
POPULAR_CATEGORIES_WITH_ICONS,
COMMON_ALLERGENS,
} from "@/lib/types";
interface FilterSidebarProps {
filters: ProductFilters;
onFiltersChange: (filters: ProductFilters) => void;
onClearFilters: () => void;
isLoading?: boolean;
totalResults?: number;
className?: string;
sortBy?: string;
onSortChange?: (sortBy: string) => void;
viewMode?: "grid" | "list";
onViewModeChange?: (mode: "grid" | "list") => void;
onRefresh?: () => void;
onClearCache?: () => void;
isCached?: boolean;
onRemoveFilter?: (key: string, value?: string) => void;
}
export function FilterSidebar({
filters,
onFiltersChange,
onClearFilters,
isLoading = false,
totalResults = 0,
className = "",
sortBy = "relevance",
onSortChange,
viewMode = "grid",
onViewModeChange,
onRefresh,
onClearCache,
isCached = false,
onRemoveFilter,
}: FilterSidebarProps) {
const [searchBrands, setSearchBrands] = useState("");
const [searchCategories, setSearchCategories] = useState("");
const [searchAllergens, setSearchAllergens] = useState("");
const updateFilter = (key: keyof ProductFilters, value: unknown) => {
onFiltersChange({ ...filters, [key]: value });
};
const updateArrayFilter = (
key: keyof ProductFilters,
value: string,
checked: boolean
) => {
const currentArray = (filters[key] as string[]) || [];
const newArray = checked
? [...currentArray, value]
: currentArray.filter((item) => item !== value);
updateFilter(key, newArray);
};
const updateNutritionRange = (
nutrient: string,
type: "min" | "max",
value: number
) => {
const currentRanges = filters.nutritionRanges || {};
const currentRange =
currentRanges[nutrient as keyof typeof currentRanges] || {};
updateFilter("nutritionRanges", {
...currentRanges,
[nutrient]: {
...currentRange,
[type]: value,
},
});
};
const hasActiveFilters = Object.values(filters).some((value) => {
if (Array.isArray(value)) return value.length > 0;
if (typeof value === "object" && value !== null) {
return Object.values(value).some((v) => v !== undefined && v !== null);
}
return value !== undefined && value !== null && value !== "";
});
return (
{/* ── Header ────────────────────────────────────────────────────────── */}
Filtros avançados
{hasActiveFilters && (
)}
{/* ── Result count ──────────────────────────────────────────────────── */}
{totalResults > 0 && (
{totalResults.toLocaleString()} produto{totalResults !== 1 ? "s" : ""} encontrado{totalResults !== 1 ? "s" : ""}
)}
{/* ── Active filter badges ───────────────────────────────────────────── */}
{onRemoveFilter && hasActiveFilters && (
)}
{/* ── Cache / Refresh controls ──────────────────────────────────────── */}
{(onRefresh || onClearCache) && (
{onRefresh && (
)}
{onClearCache && isCached && (
)}
)}
{/* ── View mode ─────────────────────────────────────────────────────── */}
{onViewModeChange && (
Visualização
{(["grid", "list"] as const).map((mode) => (
))}
)}
{/* ── Accordion sections ────────────────────────────────────────────── */}
{/* Ordenação */}
{onSortChange && (
)}
{/* Nutri-Score & NOVA */}
Classificação Nutricional
Nutri-Score
{NUTRITION_GRADES.map((grade) => (
updateArrayFilter("nutritionGrades", grade.grade, checked as boolean)}
/>
))}
NOVA — Nível de processamento
updateFilter("novaGroups", value ? [parseInt(value) as 1 | 2 | 3 | 4] : [])}
className="space-y-2"
>
{NOVA_GROUPS.map((group) => (
))}
{/* Categorias */}
Categorias
setSearchCategories(e.target.value)}
style={{ height: 34, fontSize: 13, borderColor: "var(--border-subtle, #e8e0d0)", background: "var(--bg-base, #f9f6f0)" }}
/>
{POPULAR_CATEGORIES_WITH_ICONS.filter(
(cat) =>
cat.label.toLowerCase().includes(searchCategories.toLowerCase()) ||
cat.value.toLowerCase().includes(searchCategories.toLowerCase())
).map((category) => {
const IconComponent = LucideIcons[category.icon as keyof typeof LucideIcons] as React.ComponentType<{ style?: React.CSSProperties }> | undefined;
return (
updateArrayFilter("categories", category.value, checked as boolean)}
/>
);
})}
{/* Marcas */}
Marcas
{/* Alérgenos */}
setSearchAllergens(e.target.value)}
style={{ height: 34, fontSize: 13, borderColor: "var(--border-subtle, #e8e0d0)", background: "var(--bg-base, #f9f6f0)" }}
/>
{COMMON_ALLERGENS.filter((allergen) =>
allergen.toLowerCase().includes(searchAllergens.toLowerCase())
).map((allergen) => (
updateArrayFilter("allergens", allergen, checked as boolean)}
/>
))}
{/* Aditivos */}
Aditivos
updateFilter("noAdditives", checked)}
/>
Mostrar apenas produtos sem aditivos
{/* Valores Nutricionais */}
Valores Nutricionais
{[
{ key: "energy", label: "Energia", unit: "kcal", max: 500, step: 10 },
{ key: "sugars", label: "Açúcares", unit: "g/100g", max: 50, step: 1 },
{ key: "sodium", label: "Sódio", unit: "g/100g", max: 3, step: 0.1 },
].map(({ key, label, unit, max, step }) => (
)?.[key]?.min || 0,
(filters.nutritionRanges as Record)?.[key]?.max || max,
]}
onValueChange={([min, maxVal]) => {
updateNutritionRange(key, "min", min);
updateNutritionRange(key, "max", maxVal);
}}
max={max}
step={step}
className="w-full"
/>
{(filters.nutritionRanges as Record)?.[key]?.min || 0}{key === "energy" ? " kcal" : "g"}
{(filters.nutritionRanges as Record)?.[key]?.max || max}{key === "energy" ? " kcal" : "g"}
))}
{/* ── Footer action ─────────────────────────────────────────────────── */}
);
}