Compare commits

..

2 commits

Author SHA1 Message Date
Nathan Lamy
b5816155a4 feat: add upcoming colles
All checks were successful
Deploy to Netlify / Deploy to Netlify (push) Successful in 1m15s
2026-02-25 00:42:08 +01:00
Nathan Lamy
a9a752ea83 docs: add memo 2026-02-25 00:27:04 +01:00
3 changed files with 55 additions and 9 deletions

View file

@ -67,12 +67,19 @@ export default function Home({ user }: { user: User }) {
isLoading, isLoading,
} = useColles(startDate); } = useColles(startDate);
// Fetch upcoming colles from API
const {
classColles: upcomingClassColles,
error: upcomingError,
isLoading: upcomingIsLoading,
} = useColles(DateTime.now());
// Error handling (after all hooks) // Error handling (after all hooks)
if (error) if (error || upcomingError)
return ( return (
<Error <Error
title="Impossible de charger les colles" title="Impossible de charger les colles"
message={error?.toString()} message={error?.toString() || upcomingError?.toString()}
code={500} code={500}
description="Une erreur s'est produite lors du chargement de la liste des colles." description="Une erreur s'est produite lors du chargement de la liste des colles."
/> />
@ -98,6 +105,14 @@ export default function Home({ user }: { user: User }) {
updateQuery("examiner", examiner); updateQuery("examiner", examiner);
setExaminerFilter(examiner == "all" ? "" : examiner); setExaminerFilter(examiner == "all" ? "" : examiner);
}; };
const rawStudent = query.get("student");
const [studentFilter, setStudentFilter] = useState<string>(
rawStudent === "all" ? "" : rawStudent || ""
);
const setStudent = (student: string) => {
updateQuery("student", student);
setStudentFilter(student == "all" ? "" : student);
};
const [sorted, setSort] = useState<string>(query.get("sort") || "desc"); const [sorted, setSort] = useState<string>(query.get("sort") || "desc");
const toggleSort = () => { const toggleSort = () => {
const newSort = sorted === "asc" ? "desc" : "asc"; const newSort = sorted === "asc" ? "desc" : "asc";
@ -106,21 +121,29 @@ export default function Home({ user }: { user: User }) {
}; };
const generateFilter = (arr: string[], value: string) => { const generateFilter = (arr: string[], value: string) => {
const unique = [...new Set(arr)]; const unique = [...new Set(arr.filter(Boolean))];
if (value && !unique.includes(value)) { if (value && !unique.includes(value)) {
unique.push(value); unique.push(value);
} }
unique.sort((a, b) => a.localeCompare(b)); unique.sort((a, b) => a.localeCompare(b));
return unique; return unique;
}; };
const currentClassColles =
activeTab === "upcoming" ? upcomingClassColles : classColles;
const subjects = generateFilter( const subjects = generateFilter(
classColles.map((colle) => colle.subject?.name), currentClassColles.map((colle) => colle.subject?.name),
subjectFilter subjectFilter
); );
const examiners = generateFilter( const examiners = generateFilter(
classColles.map((colle) => colle.examiner?.name), currentClassColles.map((colle) => colle.examiner?.name),
examinerFilter examinerFilter
); );
const students = generateFilter(
upcomingClassColles.map((colle) => colle.student?.fullName),
studentFilter
);
const applyFilters = (colles: any[]) => { const applyFilters = (colles: any[]) => {
return colles return colles
@ -133,7 +156,11 @@ export default function Home({ user }: { user: User }) {
examinerFilter === "all" || !examinerFilter examinerFilter === "all" || !examinerFilter
? true ? true
: colle.examiner?.name === examinerFilter; : colle.examiner?.name === examinerFilter;
return subjectMatch && examinerMatch; const studentMatch =
activeTab !== "upcoming" || studentFilter === "all" || !studentFilter
? true
: colle.student?.fullName === studentFilter;
return subjectMatch && examinerMatch && studentMatch;
}) })
.sort((a, b) => { .sort((a, b) => {
if (sorted === "asc") { if (sorted === "asc") {
@ -218,6 +245,22 @@ export default function Home({ user }: { user: User }) {
</SelectContent> </SelectContent>
</Select> </Select>
{activeTab === "upcoming" && (
<Select value={studentFilter} onValueChange={setStudent}>
<SelectTrigger className="rounded-full data-[placeholder]:text-primary">
<SelectValue placeholder="Élève" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">Tous</SelectItem>
{students.map((student) => (
<SelectItem key={student} value={student}>
{student}
</SelectItem>
))}
</SelectContent>
</Select>
)}
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
@ -271,10 +314,10 @@ export default function Home({ user }: { user: User }) {
{activeTab === "upcoming" && ( {activeTab === "upcoming" && (
<TabContent <TabContent
tabTitle="Toutes les colles à venir" tabTitle="Toutes les colles à venir"
emptyCollesText="Cette fonctionnalité est en cours de développement. Bientôt, vous verrez ici toutes les colles à venir pour votre classe." emptyCollesText="Aucune colle à venir n'a été trouvée."
isLoading={false} isLoading={upcomingIsLoading}
isSorted={sorted === "desc"} isSorted={sorted === "desc"}
colles={[]} colles={applyFilters(upcomingClassColles)}
preferences={user.preferences} preferences={user.preferences}
/> />
)} )}

View file

@ -74,6 +74,7 @@ export function MatchStudent({
<p> <p>
Correspondance trouvée: {matchedStudent.fullName} Correspondance trouvée: {matchedStudent.fullName}
</p> </p>
{/* TODO: Improve UI */}
<button onClick={handleValidate}>Valider</button> <button onClick={handleValidate}>Valider</button>
</div> </div>
)} )}

View file

@ -203,6 +203,7 @@ interface CollePayload {
classColles: Colle[]; classColles: Colle[];
studentColles: Colle[]; studentColles: Colle[];
favoriteColles: Colle[]; favoriteColles: Colle[];
upcomingClassColles: Colle[];
healthyUntil: Date; healthyUntil: Date;
lastSync: Date; lastSync: Date;
} }
@ -238,6 +239,7 @@ export const useColles = (startDate: DateTime) => {
classColles: [], classColles: [],
studentColles: [], studentColles: [],
favoriteColles: [], favoriteColles: [],
upcomingClassColles: [],
healthyUntil: new Date(0), healthyUntil: new Date(0),
lastSync: new Date(0), lastSync: new Date(0),
}, },