Checkpoint: V1.20 - Amélioration de l'envoi d'attestations par groupe. Le bouton d'envoi par séquence est maintenant toujours visible dès qu'il y a des attestations disponibles, permettant d'envoyer les nouvelles attestations ou de renvoyer celles déjà envoyées. Message de confirmation adapté selon la situation.

This commit is contained in:
Manus
2026-02-26 07:53:53 -05:00
parent 198656947f
commit bf12b9b680
2 changed files with 45 additions and 20 deletions

View File

@@ -442,22 +442,37 @@ export default function AdminGestionAttestations() {
// Envoyer toutes les attestations d'une séquence // Envoyer toutes les attestations d'une séquence
const handleSendSequence = (sequenceId: number, sequenceApprenants: any[]) => { const handleSendSequence = (sequenceId: number, sequenceApprenants: any[]) => {
const attestationsReady = sequenceApprenants.filter(item => { const attestationsWithDocument = sequenceApprenants.filter(item => {
const hasDocument = item.attestation && (item.attestation.documentUrl || item.attestation.urlPdf); const hasDocument = item.attestation && (item.attestation.documentUrl || item.attestation.urlPdf);
return hasDocument && !item.attestation.emailEnvoye; return hasDocument;
}); });
if (attestationsReady.length === 0) { if (attestationsWithDocument.length === 0) {
toast.error("Aucune attestation prête à envoyer pour cette séquence"); toast.error("Aucune attestation disponible pour cette séquence");
return; return;
} }
if (confirm(`Êtes-vous sûr de vouloir envoyer ${attestationsReady.length} attestation(s) pour cette séquence ?`)) { const attestationsNotSent = attestationsWithDocument.filter(item => !item.attestation.emailEnvoye);
// Envoyer chaque attestation de la séquence const attestationsAlreadySent = attestationsWithDocument.filter(item => item.attestation.emailEnvoye);
let successCount = 0;
let errorCount = 0;
const sendPromises = attestationsReady.map(item => { let confirmMessage = '';
if (attestationsNotSent.length > 0 && attestationsAlreadySent.length > 0) {
confirmMessage = `Êtes-vous sûr de vouloir envoyer ${attestationsNotSent.length} attestation(s) et renvoyer ${attestationsAlreadySent.length} attestation(s) déjà envoyée(s) ?`;
} else if (attestationsNotSent.length > 0) {
confirmMessage = `Êtes-vous sûr de vouloir envoyer ${attestationsNotSent.length} attestation(s) pour cette séquence ?`;
} else {
confirmMessage = `Êtes-vous sûr de vouloir renvoyer ${attestationsAlreadySent.length} attestation(s) déjà envoyée(s) ?`;
}
if (!confirm(confirmMessage)) {
return;
}
// Envoyer chaque attestation de la séquence
let successCount = 0;
let errorCount = 0;
const sendPromises = attestationsWithDocument.map(item => {
const pdfUrl = item.attestation.documentUrl || item.attestation.urlPdf; const pdfUrl = item.attestation.documentUrl || item.attestation.urlPdf;
return sendAttestationMutation.mutateAsync({ return sendAttestationMutation.mutateAsync({
attestationId: item.attestation.id, attestationId: item.attestation.id,
@@ -475,13 +490,12 @@ export default function AdminGestionAttestations() {
}); });
}); });
Promise.all(sendPromises).finally(() => { Promise.all(sendPromises).finally(() => {
if (successCount > 0) { if (successCount > 0) {
toast.success(`${successCount} attestation(s) envoyée(s) avec succès${errorCount > 0 ? `, ${errorCount} échec(s)` : ''}`); toast.success(`${successCount} attestation(s) envoyée(s) avec succès${errorCount > 0 ? `, ${errorCount} échec(s)` : ''}`);
} }
refetchApprenants(); refetchApprenants();
}); });
}
}; };
// Ouvrir le dialogue d'upload // Ouvrir le dialogue d'upload
@@ -748,7 +762,7 @@ export default function AdminGestionAttestations() {
<Badge variant="outline" className="bg-white"> <Badge variant="outline" className="bg-white">
{attestationsEnvoyees} / {sequenceApprenants.length} envoyé(es) {attestationsEnvoyees} / {sequenceApprenants.length} envoyé(es)
</Badge> </Badge>
{modeEnvoi === "manuel" && attestationsPretesNonEnvoyees > 0 && ( {modeEnvoi === "manuel" && sequenceApprenants.some(a => a.attestation && (a.attestation.documentUrl || a.attestation.urlPdf)) && (
<Button <Button
size="sm" size="sm"
onClick={() => handleSendSequence(sequenceId, sequenceApprenants)} onClick={() => handleSendSequence(sequenceId, sequenceApprenants)}
@@ -756,7 +770,10 @@ export default function AdminGestionAttestations() {
className="bg-green-600 hover:bg-green-700 text-white" className="bg-green-600 hover:bg-green-700 text-white"
> >
<Send className="h-3 w-3 mr-1" /> <Send className="h-3 w-3 mr-1" />
Envoyer la séquence ({attestationsPretesNonEnvoyees}) {attestationsPretesNonEnvoyees > 0
? `Envoyer la séquence (${attestationsPretesNonEnvoyees})`
: `Renvoyer la séquence (${attestationsEnvoyees})`
}
</Button> </Button>
)} )}
</div> </div>

10
todo.md
View File

@@ -1646,4 +1646,12 @@
- [x] Ajouter l'URL dans le retour de la procédure generateQRCode - [x] Ajouter l'URL dans le retour de la procédure generateQRCode
- [x] Afficher l'URL sous le QR code (texte cliquable) - [x] Afficher l'URL sous le QR code (texte cliquable)
- [x] Déployer sur TEST pour validation - [x] Déployer sur TEST pour validation
- [ ] Déployer sur PROD - [x] Déployer sur PROD
## Envoi d'attestations par groupe
- [x] Analyser la page des attestations pour identifier l'emplacement du bouton
- [x] Modifier le bouton existant pour permettre l'envoi/renvoi de toutes les attestations du groupe
- [x] Adapter la logique pour gérer les attestations déjà envoyées (renvoi)
- [x] Déployer sur TEST (recette)
- [x] Déployer sur sandbox (dev local) - déjà actif