Checkpoint: Ajout d'un encart dédié pour afficher les signatures des formateurs sur la page d'émargement numérique
Modifications apportées : - Backend : Ajout de la fonction getSignaturesFormateursBySequence dans presenceDb.ts - Backend : Ajout de la procédure tRPC presences.listSignaturesFormateurs dans routers.ts - Frontend : Ajout de l'encart visuel des signatures formateurs dans FormateurEmargement.tsx - L'encart affiche les signatures avec date, période (matin/après-midi), heure et image de signature - Rafraîchissement automatique toutes les 30 secondes - Design distinct avec bordure bleue pour différencier des signatures apprenants - Déployé sur recette (108.143.67.56) et production (98.71.216.234)
This commit is contained in:
@@ -69,6 +69,12 @@ export default function FormateurEmargement() {
|
||||
{ enabled: !!selectedSequenceId }
|
||||
);
|
||||
|
||||
// Récupérer les signatures formateurs de la séquence
|
||||
const { data: signaturesFormateurs, refetch: refetchSignaturesFormateurs } = trpc.presences.listSignaturesFormateurs.useQuery(
|
||||
{ sequenceId: selectedSequenceId || 0 },
|
||||
{ enabled: !!selectedSequenceId }
|
||||
);
|
||||
|
||||
// Rafraîchissement automatique toutes les 30 secondes
|
||||
useEffect(() => {
|
||||
if (!selectedSequenceId) return;
|
||||
@@ -76,12 +82,13 @@ export default function FormateurEmargement() {
|
||||
const interval = setInterval(() => {
|
||||
refetchInscrits();
|
||||
refetchPresences();
|
||||
refetchSignaturesFormateurs();
|
||||
setLastRefreshTime(new Date());
|
||||
setSecondsSinceRefresh(0);
|
||||
}, 30000); // 30 secondes
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [selectedSequenceId, refetchInscrits, refetchPresences]);
|
||||
}, [selectedSequenceId, refetchInscrits, refetchPresences, refetchSignaturesFormateurs]);
|
||||
|
||||
// Compteur pour "Mis à jour il y a X secondes"
|
||||
useEffect(() => {
|
||||
@@ -262,6 +269,7 @@ export default function FormateurEmargement() {
|
||||
onClick={() => {
|
||||
refetchInscrits();
|
||||
refetchPresences();
|
||||
refetchSignaturesFormateurs();
|
||||
setLastRefreshTime(new Date());
|
||||
setSecondsSinceRefresh(0);
|
||||
}}
|
||||
@@ -485,6 +493,67 @@ export default function FormateurEmargement() {
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Encart des signatures formateurs */}
|
||||
{selectedSequenceId && signaturesFormateurs && signaturesFormateurs.length > 0 && (
|
||||
<Card className="border-2 border-blue-200 bg-blue-50/30">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-blue-700">Signatures Formateurs</CardTitle>
|
||||
<CardDescription>
|
||||
Signatures tactiles des formateurs pour cette séquence
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
{signaturesFormateurs.map((signature: any) => (
|
||||
<div
|
||||
key={signature.presenceId}
|
||||
className="border border-blue-200 rounded-lg p-4 bg-white space-y-3"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="font-medium text-blue-900">
|
||||
{new Date(signature.dateDebut).toLocaleDateString("fr-FR", {
|
||||
weekday: "long",
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
})}
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{signature.periode === "matin" ? "🌅 Matin" : "🌆 Après-midi"}
|
||||
</p>
|
||||
</div>
|
||||
<Badge variant="outline" className="bg-blue-100 text-blue-700 border-blue-300">
|
||||
{new Date(signature.heurePresence).toLocaleTimeString("fr-FR", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
})}
|
||||
</Badge>
|
||||
</div>
|
||||
{signature.signatureUrl && (
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-xs text-muted-foreground">Signature tactile :</p>
|
||||
<div className="border-2 border-blue-200 rounded-lg p-2 bg-white cursor-pointer hover:border-blue-400 transition-colors"
|
||||
onClick={() => {
|
||||
setSelectedSignature(signature.signatureUrl!);
|
||||
setShowSignatureDialog(true);
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={signature.signatureUrl}
|
||||
alt="Signature formateur"
|
||||
className="w-full h-24 object-contain"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Dialog QR Code Apprenants */}
|
||||
<Dialog open={showQRDialog} onOpenChange={setShowQRDialog}>
|
||||
<DialogContent className="max-w-md">
|
||||
|
||||
Reference in New Issue
Block a user