Files
Academia-Front/src/hooks/useFilters.ts
T
2026-08-28 16:25:37 -05:00

71 lines
2.8 KiB
TypeScript

"use client";
import { useState, useMemo } from "react";
import { useSearchParams } from "next/navigation";
import { mockCourses } from "@/data/mockCourses";
function toggleItem(arr: string[], val: string): string[] {
return arr.includes(val) ? arr.filter((x) => x !== val) : [...arr, val];
}
export function useFilters() {
const searchParams = useSearchParams();
const [search, setSearch] = useState(searchParams.get("q") ?? "");
const [selectedCategories, setSelectedCategories] = useState<string[]>(() => {
const cat = searchParams.get("cat");
return cat ? [cat] : [];
});
const [selectedLevels, setSelectedLevels] = useState<string[]>([]);
const [minRating, setMinRating] = useState<number | null>(null);
const [maxPrice, setMaxPrice] = useState<number | null>(null);
const [sort, setSort] = useState("popular");
const toggleCategory = (val: string) => setSelectedCategories((prev) => toggleItem(prev, val));
const toggleLevel = (val: string) => setSelectedLevels((prev) => toggleItem(prev, val));
const toggleRating = (r: number) => setMinRating((prev) => (prev === r ? null : r));
const togglePrice = (p: number) => setMaxPrice((prev) => (prev === p ? null : p));
const activeFiltersCount =
selectedCategories.length + selectedLevels.length + (minRating ? 1 : 0) + (maxPrice ? 1 : 0);
const clearAll = () => {
setSearch("");
setSelectedCategories([]);
setSelectedLevels([]);
setMinRating(null);
setMaxPrice(null);
};
const filtered = useMemo(() => {
let list = [...mockCourses];
if (search)
list = list.filter(
(c) =>
c.title.toLowerCase().includes(search.toLowerCase()) ||
c.subtitle.toLowerCase().includes(search.toLowerCase()),
);
if (selectedCategories.length) list = list.filter((c) => selectedCategories.includes(c.category));
if (selectedLevels.length) list = list.filter((c) => selectedLevels.includes(c.level));
if (minRating) list = list.filter((c) => c.rating >= minRating);
if (maxPrice) list = list.filter((c) => c.price <= maxPrice);
switch (sort) {
case "rating": list.sort((a, b) => b.rating - a.rating); break;
case "price_lo": list.sort((a, b) => a.price - b.price); break;
case "price_hi": list.sort((a, b) => b.price - a.price); break;
case "newest": list.sort((a, b) => (b.badge === "Nuevo" ? 1 : 0) - (a.badge === "Nuevo" ? 1 : 0)); break;
default: list.sort((a, b) => b.studentsCount - a.studentsCount);
}
return list;
}, [search, selectedCategories, selectedLevels, minRating, maxPrice, sort]);
return {
search, setSearch,
selectedCategories, toggleCategory,
selectedLevels, toggleLevel,
minRating, toggleRating,
maxPrice, togglePrice,
sort, setSort,
activeFiltersCount, clearAll, filtered,
};
}