feat: add filters
This commit is contained in:
parent
cdc41c4a51
commit
b4b74155c2
2 changed files with 105 additions and 149 deletions
|
|
@ -1,15 +1,14 @@
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { useState, useEffect } from "react";
|
import { useState } from "react";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import {
|
import {
|
||||||
ChevronLeft,
|
ChevronLeft,
|
||||||
ChevronRight,
|
ChevronRight,
|
||||||
Star,
|
Star,
|
||||||
Filter,
|
|
||||||
X,
|
|
||||||
Users,
|
Users,
|
||||||
User,
|
User,
|
||||||
ArrowUpDown,
|
SortAsc,
|
||||||
|
SortDesc,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
|
|
@ -18,13 +17,7 @@ import {
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "~/components/ui/select";
|
} from "~/components/ui/select";
|
||||||
import { Label } from "~/components/ui/label";
|
|
||||||
import { Tabs, TabsList, TabsTrigger } from "~/components/ui/tabs";
|
import { Tabs, TabsList, TabsTrigger } from "~/components/ui/tabs";
|
||||||
import {
|
|
||||||
Collapsible,
|
|
||||||
CollapsibleContent,
|
|
||||||
CollapsibleTrigger,
|
|
||||||
} from "~/components/ui/collapsible";
|
|
||||||
import DatePickerWithRange from "~/components/home/date-picker";
|
import DatePickerWithRange from "~/components/home/date-picker";
|
||||||
import BottomNavigation from "~/components/home/bottom-nav";
|
import BottomNavigation from "~/components/home/bottom-nav";
|
||||||
import Error from "~/components/error";
|
import Error from "~/components/error";
|
||||||
|
|
@ -74,13 +67,6 @@ export default function Home() {
|
||||||
// Fetch colles from API
|
// Fetch colles from API
|
||||||
const { studentColles, classColles, favoriteColles, error, isLoading } =
|
const { studentColles, classColles, favoriteColles, error, isLoading } =
|
||||||
useColles(startDate);
|
useColles(startDate);
|
||||||
console.log("Colles loaded:", {
|
|
||||||
studentColles,
|
|
||||||
classColles,
|
|
||||||
favoriteColles,
|
|
||||||
error,
|
|
||||||
isLoading,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Error handling (after all hooks)
|
// Error handling (after all hooks)
|
||||||
if (error)
|
if (error)
|
||||||
|
|
@ -95,30 +81,60 @@ export default function Home() {
|
||||||
|
|
||||||
// TODO: FAVORITES
|
// TODO: FAVORITES
|
||||||
const useToggleStar = (auth: any) => {};
|
const useToggleStar = (auth: any) => {};
|
||||||
// TODO: FILTERS
|
|
||||||
const getSessionFilter = (key: string) => {
|
// Filter state
|
||||||
const filter = sessionStorage.getItem(key);
|
const rawSubject = query.get("subject");
|
||||||
if (filter) {
|
|
||||||
return filter;
|
|
||||||
}
|
|
||||||
return "all";
|
|
||||||
};
|
|
||||||
const [subjectFilter, setSubjectFilter] = useState<string>(
|
const [subjectFilter, setSubjectFilter] = useState<string>(
|
||||||
getSessionFilter("subject")
|
rawSubject === "all" ? "" : rawSubject || ""
|
||||||
);
|
);
|
||||||
|
const setSubject = (subject: string) => {
|
||||||
|
updateQuery("subject", subject);
|
||||||
|
setSubjectFilter(subject);
|
||||||
|
};
|
||||||
|
const rawExaminer = query.get("examiner");
|
||||||
const [examinerFilter, setExaminerFilter] = useState<string>(
|
const [examinerFilter, setExaminerFilter] = useState<string>(
|
||||||
getSessionFilter("examiner")
|
rawExaminer === "all" ? "" : rawExaminer || ""
|
||||||
);
|
);
|
||||||
// const [studentFilter, setStudentFilter] = useState<string>("all")
|
const setExaminer = (examiner: string) => {
|
||||||
const [isFilterOpen, setIsFilterOpen] = useState(
|
updateQuery("examiner", examiner);
|
||||||
getSessionFilter("subject") !== "all" ||
|
setExaminerFilter(examiner);
|
||||||
getSessionFilter("examiner") !== "all"
|
};
|
||||||
|
const [sorted, setSort] = useState<string>(query.get("sort") || "desc");
|
||||||
|
const toggleSort = () => {
|
||||||
|
const newSort = sorted === "asc" ? "desc" : "asc";
|
||||||
|
updateQuery("sort", newSort);
|
||||||
|
setSort(newSort);
|
||||||
|
};
|
||||||
|
|
||||||
|
const keepUnique = (arr: any[]) => {
|
||||||
|
return [...new Set(arr)];
|
||||||
|
};
|
||||||
|
const subjects = keepUnique(classColles.map((colle) => colle.subject?.name));
|
||||||
|
const examiners = keepUnique(
|
||||||
|
classColles.map((colle) => colle.examiner?.name)
|
||||||
);
|
);
|
||||||
useEffect(() => {
|
|
||||||
sessionStorage.setItem("subject", subjectFilter);
|
const applyFilters = (colles: any[]) => {
|
||||||
sessionStorage.setItem("examiner", examinerFilter);
|
return colles
|
||||||
// sessionStorage.setItem('student', studentFilter)
|
.filter((colle) => {
|
||||||
}, [subjectFilter, examinerFilter]);
|
const subjectMatch =
|
||||||
|
subjectFilter === "all" || !subjectFilter
|
||||||
|
? true
|
||||||
|
: colle.subject?.name === subjectFilter;
|
||||||
|
const examinerMatch =
|
||||||
|
examinerFilter === "all" || !examinerFilter
|
||||||
|
? true
|
||||||
|
: colle.examiner?.name === examinerFilter;
|
||||||
|
return subjectMatch && examinerMatch;
|
||||||
|
})
|
||||||
|
.sort((a, b) => {
|
||||||
|
if (sorted === "asc") {
|
||||||
|
return a.date.localeCompare(b.date);
|
||||||
|
} else {
|
||||||
|
return b.date.localeCompare(a.date);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6 pb-20 md:pb-0">
|
<div className="space-y-6 pb-20 md:pb-0">
|
||||||
|
|
@ -164,118 +180,50 @@ export default function Home() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* TODO: Filter component */}
|
{/* TODO: Filter component */}
|
||||||
<Collapsible open={isFilterOpen} onOpenChange={setIsFilterOpen}>
|
<div className="flex gap-1 pb-0 pt-2">
|
||||||
<div className="flex justify-between">
|
<Select value={subjectFilter} onValueChange={setSubject}>
|
||||||
<div className="flex gap-2">
|
<SelectTrigger className="rounded-full data-[placeholder]:text-primary">
|
||||||
{activeTab === "class" && (
|
<SelectValue placeholder="Matière" />
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
// TODO: Implement sorting
|
|
||||||
onClick={() => {}}
|
|
||||||
>
|
|
||||||
<ArrowUpDown className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
<div className="flex mb-4">
|
|
||||||
<CollapsibleTrigger asChild>
|
|
||||||
<Button variant="outline" size="sm">
|
|
||||||
{isFilterOpen ? (
|
|
||||||
<>
|
|
||||||
<X className="h-4 w-4 mr-2" />
|
|
||||||
Fermer
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Filter className="h-4 w-4 mr-2" />
|
|
||||||
Recherche
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</CollapsibleTrigger>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{/* TODO: DEBUG */}
|
|
||||||
{/* {activeTab === "all" &&
|
|
||||||
(getWeekStart().getTime() != startDate.getTime() ? (
|
|
||||||
<Button variant="outline" size="sm" onClick={resetWeek}>
|
|
||||||
<CalendarArrowUp className="h-4 w-4 mr-2" />
|
|
||||||
Cette semaine
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button variant="outline" size="sm" onClick={goPastYear}>
|
|
||||||
<CalendarArrowDown className="h-4 w-4 mr-2" />
|
|
||||||
Colles des spés
|
|
||||||
</Button>
|
|
||||||
))} */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<CollapsibleContent className="space-y-4">
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label htmlFor="subject-filter">Filtrer par matière</Label>
|
|
||||||
<Select value={subjectFilter} onValueChange={setSubjectFilter}>
|
|
||||||
<SelectTrigger id="subject-filter">
|
|
||||||
<SelectValue placeholder="Toutes les matières" />
|
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="all">Toutes les matières</SelectItem>
|
<SelectItem value="all">Toutes</SelectItem>
|
||||||
{/* TODO: */}
|
{subjects.map((subject) => (
|
||||||
{/* {uniqueTopics.map((subject) => (
|
|
||||||
<SelectItem key={subject} value={subject}>
|
<SelectItem key={subject} value={subject}>
|
||||||
{subject}
|
{subject}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))} */}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label htmlFor="examiner-filter">Filtrer par colleur</Label>
|
|
||||||
<Select value={examinerFilter} onValueChange={setExaminerFilter}>
|
|
||||||
<SelectTrigger id="examiner-filter">
|
|
||||||
<SelectValue placeholder="Tous les colleurs" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="all">Tous les colleurs</SelectItem>
|
|
||||||
{/* TODO: */}
|
|
||||||
{/* {uniqueExaminers.map((examiner) => (
|
|
||||||
<SelectItem key={examiner} value={examiner}>
|
|
||||||
{examiner}
|
|
||||||
</SelectItem>
|
|
||||||
))} */}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* <div className="space-y-2">
|
|
||||||
<Label htmlFor="student-filter">Filtrer par élève</Label>
|
|
||||||
<Select value={studentFilter} onValueChange={setStudentFilter}>
|
|
||||||
<SelectTrigger id="student-filter">
|
|
||||||
<SelectValue placeholder="Tous les élèves" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="all">Tous les élèves</SelectItem>
|
|
||||||
{uniqueStudents.map((student) => (
|
|
||||||
<SelectItem key={student} value={student}>
|
|
||||||
{student}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div> */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<Select value={examinerFilter} onValueChange={setExaminer}>
|
||||||
<Button variant="outline" size="sm">
|
<SelectTrigger className="rounded-full data-[placeholder]:text-primary">
|
||||||
{/* //TODO: onClick={resetFilters} */}
|
<SelectValue placeholder="Colleur" />
|
||||||
Réinitialiser les filtres
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="all">Tous</SelectItem>
|
||||||
|
{/* TODO: */}
|
||||||
|
{examiners.map((examiner) => (
|
||||||
|
<SelectItem key={examiner} value={examiner}>
|
||||||
|
{examiner}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="rounded-full dark:bg-input/30 text-primary font-normal"
|
||||||
|
onClick={toggleSort}
|
||||||
|
>
|
||||||
|
{sorted == "asc" ? (
|
||||||
|
<SortAsc className="h-5 w-5" />
|
||||||
|
) : (
|
||||||
|
<SortDesc className="h-5 w-5" />
|
||||||
|
)}
|
||||||
|
Trier
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</CollapsibleContent>
|
|
||||||
</Collapsible>
|
|
||||||
|
|
||||||
{/* Tab Content */}
|
{/* Tab Content */}
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -285,7 +233,8 @@ export default function Home() {
|
||||||
tabTitle="Vos colles"
|
tabTitle="Vos colles"
|
||||||
emptyCollesText="Vous n'avez pas encore de colle cette semaine."
|
emptyCollesText="Vous n'avez pas encore de colle cette semaine."
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
colles={studentColles}
|
isSorted={sorted === "desc"}
|
||||||
|
colles={applyFilters(studentColles)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -306,7 +255,8 @@ export default function Home() {
|
||||||
tabTitle="Les colles de la classe"
|
tabTitle="Les colles de la classe"
|
||||||
emptyCollesText="Aucune colle trouvée."
|
emptyCollesText="Aucune colle trouvée."
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
colles={classColles}
|
isSorted={sorted === "desc"}
|
||||||
|
colles={applyFilters(classColles)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ type TabContentProps = {
|
||||||
emptyCollesText: string;
|
emptyCollesText: string;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
colles: Colle[];
|
colles: Colle[];
|
||||||
};
|
isSorted?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
const WEEK_DAYS = [
|
const WEEK_DAYS = [
|
||||||
"Lundi",
|
"Lundi",
|
||||||
|
|
@ -26,6 +27,7 @@ export default function TabContent({
|
||||||
emptyCollesText,
|
emptyCollesText,
|
||||||
isLoading,
|
isLoading,
|
||||||
colles,
|
colles,
|
||||||
|
isSorted
|
||||||
}: TabContentProps) {
|
}: TabContentProps) {
|
||||||
const collesByDay: Record<string, Colle[]> = {};
|
const collesByDay: Record<string, Colle[]> = {};
|
||||||
colles.forEach((colle) => {
|
colles.forEach((colle) => {
|
||||||
|
|
@ -40,6 +42,10 @@ export default function TabContent({
|
||||||
const days = WEEK_DAYS.filter(
|
const days = WEEK_DAYS.filter(
|
||||||
(day) => collesByDay[day] && collesByDay[day].length > 0
|
(day) => collesByDay[day] && collesByDay[day].length > 0
|
||||||
);
|
);
|
||||||
|
// If not sorted, reverse the order of days
|
||||||
|
if (!isSorted) {
|
||||||
|
days.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue