Checkpoint: ✅ Amélioration du test de rappels avec envoi multiple et indicateur de progression
- Modification du backend pour envoyer un email par inscrit confirmé (tous à l'adresse de test) - Ajout d'un indicateur de progression moderne avec animation (spinner + effet ping) - Message de succès affichant le nombre d'emails envoyés - Validation avec séquence "test 3" : 3 emails envoyés correctement (4ème inscrit sans email ignoré) - Synchronisation complète de la structure de la table logsrappels avec le VPS
This commit is contained in:
9
.manus/db/db-query-1769089721346.json
Normal file
9
.manus/db/db-query-1769089721346.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"query": "SELECT i.id, i.apprenantId, i.statut, a.nom, a.prenom, a.email \nFROM inscriptions i \nLEFT JOIN apprenants a ON i.apprenantId = a.id \nWHERE i.sequenceId = 330001 AND i.statut = 'confirme';",
|
||||
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute SELECT i.id, i.apprenantId, i.statut, a.nom, a.prenom, a.email \nFROM inscriptions i \nLEFT JOIN apprenants a ON i.apprenantId = a.id \nWHERE i.sequenceId = 330001 AND i.statut = 'confirme';",
|
||||
"rows": [],
|
||||
"messages": [],
|
||||
"stdout": "",
|
||||
"stderr": "",
|
||||
"execution_time_ms": 80
|
||||
}
|
||||
73
.manus/db/db-query-1769089734156.json
Normal file
73
.manus/db/db-query-1769089734156.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"query": "SELECT i.id, i.apprenantId, i.statut, i.dateInscription, a.nom, a.prenom, a.email \nFROM inscriptions i \nLEFT JOIN apprenants a ON i.apprenantId = a.id \nWHERE i.sequenceId = 330001;",
|
||||
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute SELECT i.id, i.apprenantId, i.statut, i.dateInscription, a.nom, a.prenom, a.email \nFROM inscriptions i \nLEFT JOIN apprenants a ON i.apprenantId = a.id \nWHERE i.sequenceId = 330001;",
|
||||
"rows": [
|
||||
{
|
||||
"id": "300001",
|
||||
"apprenantId": "1",
|
||||
"statut": "confirmee",
|
||||
"dateInscription": "2025-11-30 21:54:11",
|
||||
"nom": "JOHANSSON ",
|
||||
"prenom": "Scarlett",
|
||||
"email": "opareige@gmail.com"
|
||||
},
|
||||
{
|
||||
"id": "450001",
|
||||
"apprenantId": "60001",
|
||||
"statut": "confirmee",
|
||||
"dateInscription": "2026-01-22 12:39:20",
|
||||
"nom": "PITT",
|
||||
"prenom": "Brad",
|
||||
"email": "test2@gmail.com"
|
||||
},
|
||||
{
|
||||
"id": "420003",
|
||||
"apprenantId": "240001",
|
||||
"statut": "confirmee",
|
||||
"dateInscription": "2025-12-03 09:32:09",
|
||||
"nom": "monroe",
|
||||
"prenom": "marylin",
|
||||
"email": "o.pareige@itinova.org"
|
||||
},
|
||||
{
|
||||
"id": "420002",
|
||||
"apprenantId": "240001",
|
||||
"statut": "annulee",
|
||||
"dateInscription": "2025-12-03 09:23:59",
|
||||
"nom": "monroe",
|
||||
"prenom": "marylin",
|
||||
"email": "o.pareige@itinova.org"
|
||||
},
|
||||
{
|
||||
"id": "330001",
|
||||
"apprenantId": "180001",
|
||||
"statut": "annulee",
|
||||
"dateInscription": "2025-12-01 08:40:38",
|
||||
"nom": "NULL",
|
||||
"prenom": "NULL",
|
||||
"email": "NULL"
|
||||
},
|
||||
{
|
||||
"id": "360001",
|
||||
"apprenantId": "180001",
|
||||
"statut": "annulee",
|
||||
"dateInscription": "2025-12-01 09:47:25",
|
||||
"nom": "NULL",
|
||||
"prenom": "NULL",
|
||||
"email": "NULL"
|
||||
},
|
||||
{
|
||||
"id": "360002",
|
||||
"apprenantId": "180001",
|
||||
"statut": "confirmee",
|
||||
"dateInscription": "2025-12-01 09:48:55",
|
||||
"nom": "NULL",
|
||||
"prenom": "NULL",
|
||||
"email": "NULL"
|
||||
}
|
||||
],
|
||||
"messages": [],
|
||||
"stdout": "id\tapprenantId\tstatut\tdateInscription\tnom\tprenom\temail\n300001\t1\tconfirmee\t2025-11-30 21:54:11\tJOHANSSON \tScarlett\topareige@gmail.com\n450001\t60001\tconfirmee\t2026-01-22 12:39:20\tPITT\tBrad\ttest2@gmail.com\n420003\t240001\tconfirmee\t2025-12-03 09:32:09\tmonroe\tmarylin\to.pareige@itinova.org\n420002\t240001\tannulee\t2025-12-03 09:23:59\tmonroe\tmarylin\to.pareige@itinova.org\n330001\t180001\tannulee\t2025-12-01 08:40:38\tNULL\tNULL\tNULL\n360001\t180001\tannulee\t2025-12-01 09:47:25\tNULL\tNULL\tNULL\n360002\t180001\tconfirmee\t2025-12-01 09:48:55\tNULL\tNULL\tNULL\n",
|
||||
"stderr": "",
|
||||
"execution_time_ms": 54
|
||||
}
|
||||
@@ -36,6 +36,7 @@ export default function AdminSequences() {
|
||||
const [isConfirmTestOpen, setIsConfirmTestOpen] = useState(false);
|
||||
const [sequenceToTest, setSequenceToTest] = useState<number | null>(null);
|
||||
const [testEmail, setTestEmail] = useState("");
|
||||
const [sendingProgress, setSendingProgress] = useState<{ current: number; total: number } | null>(null);
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
formationId: "",
|
||||
@@ -91,13 +92,15 @@ export default function AdminSequences() {
|
||||
});
|
||||
|
||||
const testerRappelMutation = trpc.rappels.testerRappel.useMutation({
|
||||
onSuccess: () => {
|
||||
toast.success("Email de test envoyé avec succès");
|
||||
onSuccess: (data) => {
|
||||
setSendingProgress(null);
|
||||
toast.success(`${data.nbEnvoyes} email(s) de test envoyé(s) avec succès`);
|
||||
setIsConfirmTestOpen(false);
|
||||
setSequenceToTest(null);
|
||||
setTestEmail("");
|
||||
},
|
||||
onError: (error) => {
|
||||
setSendingProgress(null);
|
||||
toast.error(`Erreur lors de l'envoi du test : ${error.message}`);
|
||||
setIsConfirmTestOpen(false);
|
||||
setSequenceToTest(null);
|
||||
@@ -1104,6 +1107,27 @@ export default function AdminSequences() {
|
||||
disabled={testerRappelMutation.isPending}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Indicateur de progression */}
|
||||
{testerRappelMutation.isPending && (
|
||||
<div className="space-y-3 p-4 bg-muted/50 rounded-lg border">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="relative flex h-10 w-10 shrink-0">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-10 w-10 bg-primary items-center justify-center">
|
||||
<svg className="animate-spin h-5 w-5 text-primary-foreground" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-sm font-medium">Envoi en cours...</p>
|
||||
<p className="text-xs text-muted-foreground">Veuillez patienter pendant l'envoi des emails de test</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button
|
||||
|
||||
@@ -1471,10 +1471,10 @@ export const appRouter = router({
|
||||
let nbEchecs = 0;
|
||||
const erreurs: string[] = [];
|
||||
|
||||
// Si un email de test est fourni, envoyer à cet email uniquement
|
||||
// Sinon, envoyer à tous les inscrits confirmés
|
||||
// Si un email de test est fourni, envoyer un email par inscrit confirmé à cet email
|
||||
// Sinon, envoyer à l'email réel de chaque inscrit
|
||||
const destinataires = input.emailTest
|
||||
? [{ apprenant: inscritsConfirmes[0].apprenant, emailOverride: input.emailTest }]
|
||||
? inscritsConfirmes.map(i => ({ apprenant: i.apprenant, emailOverride: input.emailTest }))
|
||||
: inscritsConfirmes.map(i => ({ apprenant: i.apprenant, emailOverride: null }));
|
||||
|
||||
for (const { apprenant, emailOverride } of destinataires) {
|
||||
|
||||
1
todo.md
1
todo.md
@@ -1189,3 +1189,4 @@
|
||||
- [x] Corriger l'enregistrement des logs de rappels (table logsrappels reste vide après test)
|
||||
- [x] Ajouter une boîte de dialogue de confirmation avant l'envoi de test des rappels
|
||||
- [x] Modifier la boîte de dialogue de test de rappels pour permettre de saisir l'email du destinataire
|
||||
- [x] Modifier le test de rappels pour envoyer un email par inscrit à l'adresse de test avec indicateur de progression
|
||||
|
||||
Reference in New Issue
Block a user