feat: add past year colles
All checks were successful
Deploy to Netlify / Deploy to Netlify (push) Successful in 1m21s

This commit is contained in:
Nathan Lamy 2026-02-24 23:13:30 +01:00
parent 316875afdc
commit 85d550a11d
4 changed files with 122 additions and 0 deletions

View file

@ -0,0 +1,84 @@
import { useEffect, useState } from "react";
import { Combobox } from "~/components/combobox";
import { Label } from "~/components/ui/label";
import { getStudentMatch, mergeStudent } from "~/lib/api";
type Student = {
id: string;
fistName: string;
lastName: string;
};
export function MatchStudent({
firstName,
lastName,
onSuccess,
}: {
firstName: string;
lastName: string;
onSuccess: (student: Student) => void;
}) {
const [pastClasses, setPastClasses] = useState<
{ value: string; label: string }[]
>([]);
useEffect(() => {
fetch("/past_classes.json")
.then((res) => res.json())
.then((data) => {
setPastClasses(data);
});
}, []);
const [pastClassName, setPastClassName] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [matchedStudent, setMatchedStudent] = useState<Student | null>(null);
useEffect(() => {
if (pastClassName) {
setIsLoading(true);
getStudentMatch(firstName, lastName, pastClassName)
.then((student) => {
setMatchedStudent(student);
setIsLoading(false);
})
.catch(() => {
setMatchedStudent(null);
setIsLoading(false);
});
}
}, [pastClassName, firstName, lastName]);
const handleValidate = () => {
if (matchedStudent) {
mergeStudent(matchedStudent.id).then(() => {
onSuccess(matchedStudent);
});
}
};
return (
<div className="space-y-2">
<Label>Classe de l'année dernière</Label>
<div className="block">
<Combobox
defaultText="Sélectionnez votre classe..."
values={pastClasses}
emptyText="Aucune classe trouvée"
placeholderText="Rechercher"
current={pastClassName}
setValue={setPastClassName}
/>
</div>
{isLoading && <p>Recherche en cours...</p>}
{matchedStudent && (
<div className="flex items-center justify-between">
<p>
Correspondance trouvée: {matchedStudent.fistName}{" "}
{matchedStudent.lastName}
</p>
<button onClick={handleValidate}>Valider</button>
</div>
)}
</div>
);
}

View file

@ -8,6 +8,8 @@ import { Label } from "../ui/label";
import { Badge } from "../ui/badge";
import { useQueryClient } from "@tanstack/react-query";
import { useNavigate } from "react-router";
import { MatchStudent } from "./match-student";
import { Separator } from "../ui/separator";
export default function Profile({ user }: { user: User }) {
const navigate = useNavigate();
@ -64,6 +66,18 @@ export default function Profile({ user }: { user: User }) {
</div>
</div>
<Separator />
<MatchStudent
firstName={user.firstName}
lastName={user.lastName}
onSuccess={() => {
window.location.reload();
}}
/>
<Separator />
{/* Logout Button */}
<Button
variant="destructive"

View file

@ -86,6 +86,20 @@ export const getNames = async (className: string) => {
);
};
export const getStudentMatch = async (
firstName: string,
lastName: string,
classId: string
) => {
return makeRequest(
`/api/match-student?firstName=${firstName}&lastName=${lastName}&classId=${classId}`
);
};
export const mergeStudent = async (studentId: string) => {
return makePostRequest("/api/merge-student", { studentId });
};
/**
* === USER API ===
*/

10
public/past_classes.json Normal file
View file

@ -0,0 +1,10 @@
[
{
"value": "MPSI-1",
"label": "MPSI 1 (Sigma)"
},
{
"value": "MPSI-2",
"label": "MPSI 2 (Taupe)"
}
]