Checkpoint: Checkpoint: Restauration de la procédure sequences.getDatesByFormateurToken et de la fonction getSequenceByFormateurToken dans db.ts. Le système d'émargement formateur fonctionne maintenant correctement avec chargement des dates. Prochaine étape : corriger l'affichage du message "[ERREUR MUTATION]" pour les doublons.

This commit is contained in:
Manus
2026-02-06 09:43:43 -05:00
parent 98c3b21ec1
commit a40e0bf6cd
23 changed files with 2749 additions and 13 deletions

View File

@@ -19,6 +19,7 @@ import SignaturePadComponent from "@/components/SignaturePad";
export default function EmargementFormateurScan() {
const { token } = useParams<{ token: string }>();
const [email, setEmail] = useState("");
const [selectedDateFormationId, setSelectedDateFormationId] = useState<number | null>(null);
const [selectedPeriode, setSelectedPeriode] = useState<"matin" | "apres_midi">("matin");
const [success, setSuccess] = useState(false);
const [heureEnregistrement, setHeureEnregistrement] = useState<Date | null>(null);
@@ -26,9 +27,24 @@ export default function EmargementFormateurScan() {
const [showSignaturePad, setShowSignaturePad] = useState(false);
const [signatureDataUrl, setSignatureDataUrl] = useState<string | null>(null);
// Récupérer les dates de formation pour cette séquence
const { data: sequenceData, isLoading: loadingDates } = trpc.sequences.getDatesByFormateurToken.useQuery(
{ token: token || "" },
{ enabled: !!token }
);
// Valider la présence formateur
const { mutate: validerPresence, isPending: validating } = trpc.presences.valider.useMutation({
onSuccess: () => {
onSuccess: (data) => {
// Vérifier si la validation a réussi
if (data.success === false) {
// Cas d'un doublon : afficher le message sans passer par l'erreur
setError(data.message || "Erreur lors de la validation");
toast.error(data.message || "Erreur lors de la validation");
return;
}
// Succès normal
const now = new Date();
setHeureEnregistrement(now);
setSuccess(true);
@@ -55,6 +71,11 @@ export default function EmargementFormateurScan() {
return;
}
if (!selectedDateFormationId) {
toast.error("Veuillez sélectionner une date de formation");
return;
}
// Afficher le pad de signature
setShowSignaturePad(true);
};
@@ -65,13 +86,18 @@ export default function EmargementFormateurScan() {
return;
}
if (!selectedDateFormationId) {
toast.error("Veuillez sélectionner une date de formation");
return;
}
validerPresence({
token: token || "",
email,
dateFormationId: selectedDateFormationId,
periode: selectedPeriode,
modeValidation: "qrcode",
signatureDataUrl: dataUrl,
typeUtilisateur: "formateur",
});
};
@@ -213,16 +239,54 @@ export default function EmargementFormateurScan() {
placeholder="formateur@exemple.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
disabled={validating}
disabled={validating || loadingDates}
/>
</div>
{loadingDates ? (
<div className="flex items-center justify-center p-4">
<Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
<span className="ml-2 text-sm text-muted-foreground">Chargement des dates...</span>
</div>
) : sequenceData && sequenceData.dates.length > 0 ? (
<div className="space-y-2">
<Label htmlFor="date">Date de formation</Label>
<Select
value={selectedDateFormationId?.toString() || ""}
onValueChange={(value) => setSelectedDateFormationId(Number(value))}
disabled={validating}
>
<SelectTrigger>
<SelectValue placeholder="Sélectionnez une date" />
</SelectTrigger>
<SelectContent>
{sequenceData.dates.map((date) => (
<SelectItem key={date.id} value={date.id.toString()}>
{new Date(date.dateDebut).toLocaleDateString("fr-FR", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
})}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
) : (
<div className="p-4 bg-yellow-50 border border-yellow-200 rounded-lg">
<p className="text-sm text-yellow-800">
Aucune date de formation disponible pour cette séquence.
</p>
</div>
)}
<div className="space-y-2">
<Label htmlFor="periode">Période</Label>
<Select
value={selectedPeriode}
onValueChange={(value: "matin" | "apres_midi") => setSelectedPeriode(value)}
disabled={validating}
disabled={validating || loadingDates}
>
<SelectTrigger>
<SelectValue />
@@ -237,7 +301,7 @@ export default function EmargementFormateurScan() {
<Button
className="w-full"
onClick={handleValider}
disabled={validating || !email}
disabled={validating || !email || !selectedDateFormationId || loadingDates}
>
{validating ? (
<>