frontend/app/components/home/index.tsx
2025-07-30 17:05:07 +02:00

352 lines
11 KiB
TypeScript

import { DateTime } from "luxon";
import { useState, useEffect } from "react";
import { Button } from "~/components/ui/button";
import {
ChevronLeft,
ChevronRight,
Star,
Filter,
X,
Users,
User,
ArrowUpDown,
} from "lucide-react";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "~/components/ui/select";
import { Label } from "~/components/ui/label";
import { Tabs, TabsList, TabsTrigger } from "~/components/ui/tabs";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "~/components/ui/collapsible";
import DatePickerWithRange from "~/components/home/date-picker";
import BottomNavigation from "~/components/home/bottom-nav";
import Error from "~/components/error";
import { useSearchParams } from "react-router";
import { useColles } from "~/lib/api";
import TabContent from "~/components/home/tab-content";
export default function Home() {
// Handle query parameters
const [query, setQuery] = useSearchParams();
const updateQuery = (key: string, value: string) => {
if (query.get(key) !== value) {
setQuery((prev) => {
const newQuery = new URLSearchParams(prev);
newQuery.set(key, value);
return newQuery;
});
}
};
// Tabs
const activeTab = query.get("view") || "you";
const setActiveTab = (tab: string) => updateQuery("view", tab);
// Date
const rawStartDate = query.get("start");
const startDate = rawStartDate
? DateTime.fromISO(rawStartDate, { zone: "local" })
: DateTime.now().startOf("week");
const setStartDate = (date: DateTime) =>
updateQuery("start", date.startOf("week").toISODate()!);
const handlePreviousWeek = () => {
const previousWeek = startDate.minus({ weeks: 1 });
setStartDate(previousWeek);
};
const handleNextWeek = () => {
const nextWeek = startDate.plus({ weeks: 1 });
setStartDate(nextWeek);
};
// Fetch colles from API
const { studentColles, classColles, favoriteColles, error, isLoading } =
useColles(startDate);
console.log("Colles loaded:", {
studentColles,
classColles,
favoriteColles,
error,
isLoading,
});
// Error handling (after all hooks)
if (error)
return (
<Error
title="Impossible de charger les colles"
message={error?.toString()}
code={500}
description="Une erreur s'est produite lors du chargement de la liste des colles."
/>
);
// TODO: FAVORITES
const useToggleStar = (auth: any) => {};
// TODO: FILTERS
const getSessionFilter = (key: string) => {
const filter = sessionStorage.getItem(key);
if (filter) {
return filter;
}
return "all";
};
const [subjectFilter, setSubjectFilter] = useState<string>(
getSessionFilter("subject")
);
const [examinerFilter, setExaminerFilter] = useState<string>(
getSessionFilter("examiner")
);
// const [studentFilter, setStudentFilter] = useState<string>("all")
const [isFilterOpen, setIsFilterOpen] = useState(
getSessionFilter("subject") !== "all" ||
getSessionFilter("examiner") !== "all"
);
useEffect(() => {
sessionStorage.setItem("subject", subjectFilter);
sessionStorage.setItem("examiner", examinerFilter);
// sessionStorage.setItem('student', studentFilter)
}, [subjectFilter, examinerFilter]);
// Restore scroll position
// TODO: Test and check if needed!!
// // SCROLL
// const setScrollPosition = (colleId: number) => {
// sessionStorage.setItem("colles_position", colleId.toString());
// };
// const restoreScrollPosition = () => {
// const position = sessionStorage.getItem("colles_position");
// if (position) {
// const element = document.getElementById(`colle-${position}`);
// if (element) {
// element.scrollIntoView({ behavior: "smooth", block: "center" });
// sessionStorage.removeItem("colles_position");
// }
// }
// };
// const location = useLocation();
// useEffect(() => {
// setTimeout(restoreScrollPosition, 500);
// }, [location]);
return (
<div className="space-y-6 pb-20 md:pb-0">
{/* Week Navigation */}
<div className="mb-4">
<div className="flex flex-row items-center justify-between gap-4">
<div className="flex-1">
<DatePickerWithRange
startDate={startDate}
setStartDate={setStartDate}
/>
</div>
<div className="flex items-center space-x-2">
<Button variant="outline" size="sm" onClick={handlePreviousWeek}>
<ChevronLeft className="h-4 w-4" />
</Button>
<Button variant="outline" size="sm" onClick={handleNextWeek}>
<ChevronRight className="h-4 w-4" />
</Button>
</div>
</div>
</div>
<Tabs
defaultValue="all"
value={activeTab}
onValueChange={setActiveTab}
className="hidden md:block"
>
<div className="mb-4">
<TabsList className="w-full">
<TabsTrigger
value="you"
className="flex-1 flex items-center justify-center gap-1"
>
<User className="h-4 w-4" />
Vos colles ({studentColles.length})
</TabsTrigger>
<TabsTrigger
value="favorites"
className="flex-1 flex items-center justify-center gap-1"
>
<Star className="h-4 w-4" />
Vos favoris ({0 /* TODO: stars.length */})
</TabsTrigger>
<TabsTrigger
value="class"
className="flex-1 flex items-center justify-center gap-1"
>
<Users className="h-4 w-4" />
Votre classe ({classColles.length})
</TabsTrigger>
</TabsList>
</div>
</Tabs>
{/* TODO: Filter component */}
<Collapsible open={isFilterOpen} onOpenChange={setIsFilterOpen}>
<div className="flex justify-between">
<div className="flex gap-2">
{activeTab === "all" && (
<>
<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>
<SelectContent>
<SelectItem value="all">Toutes les matières</SelectItem>
{/* TODO: */}
{/* {uniqueTopics.map((subject) => (
<SelectItem key={subject} value={subject}>
{subject}
</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>
</Select>
</div> */}
</div>
<div className="flex justify-end">
<Button variant="outline" size="sm">
{/* //TODO: onClick={resetFilters} */}
Réinitialiser les filtres
</Button>
</div>
</CollapsibleContent>
</Collapsible>
{/* Tab Content */}
<div>
{/* Your Colles Tab */}
{activeTab === "you" && (
<TabContent
tabTitle="Vos colles"
emptyCollesText="Vous n'avez pas encore de colle cette semaine."
isLoading={isLoading}
colles={studentColles}
/>
)}
{/* Favorites Tab */}
{activeTab === "favorites" && (
<TabContent
tabTitle="Vos favoris"
emptyCollesText="Vous n'avez pas encore de colle favorite, cliquez sur l'étoile pour ajouter une colle à vos favoris."
isLoading={isLoading}
colles={favoriteColles}
/>
)}
</div>
{/* Class Colles Tab */}
{activeTab === "class" && (
<TabContent
tabTitle="Les colles de la classe"
emptyCollesText="Aucune colle trouvée."
isLoading={isLoading}
colles={classColles}
/>
)}
{/* Bottom Navigation for Mobile */}
<BottomNavigation
activeTab={activeTab}
onTabChange={setActiveTab}
// TODO: Implement favorite count
favoriteCount={0}
/>
</div>
);
}