71 lines
2.8 KiB
TypeScript
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,
|
|
};
|
|
}
|