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:
@@ -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 ? (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user