Checkpoint: ✅ Modification de la boîte de dialogue de test de rappels
- Ajout d'un champ de saisie pour l'email du destinataire - Modification du texte : "Tous les rappels configurés pour cette séquence seront envoyés à l'adresse email que vous indiquez ci-dessous" - Validation de l'email avant envoi - Backend modifié pour envoyer à l'email saisi au lieu de tous les inscrits - Les logs enregistrent correctement l'email de test utilisé
This commit is contained in:
@@ -35,6 +35,7 @@ export default function AdminSequences() {
|
|||||||
const [isCompactView, setIsCompactView] = useState(true);
|
const [isCompactView, setIsCompactView] = useState(true);
|
||||||
const [isConfirmTestOpen, setIsConfirmTestOpen] = useState(false);
|
const [isConfirmTestOpen, setIsConfirmTestOpen] = useState(false);
|
||||||
const [sequenceToTest, setSequenceToTest] = useState<number | null>(null);
|
const [sequenceToTest, setSequenceToTest] = useState<number | null>(null);
|
||||||
|
const [testEmail, setTestEmail] = useState("");
|
||||||
|
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
formationId: "",
|
formationId: "",
|
||||||
@@ -94,17 +95,20 @@ export default function AdminSequences() {
|
|||||||
toast.success("Email de test envoyé avec succès");
|
toast.success("Email de test envoyé avec succès");
|
||||||
setIsConfirmTestOpen(false);
|
setIsConfirmTestOpen(false);
|
||||||
setSequenceToTest(null);
|
setSequenceToTest(null);
|
||||||
|
setTestEmail("");
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
toast.error(`Erreur lors de l'envoi du test : ${error.message}`);
|
toast.error(`Erreur lors de l'envoi du test : ${error.message}`);
|
||||||
setIsConfirmTestOpen(false);
|
setIsConfirmTestOpen(false);
|
||||||
setSequenceToTest(null);
|
setSequenceToTest(null);
|
||||||
|
setTestEmail("");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleTestRappel = (sequenceId: number, sequence: any) => {
|
const handleTestRappel = (sequenceId: number, sequence: any) => {
|
||||||
if (sequence.dates && sequence.dates.length > 0) {
|
if (sequence.dates && sequence.dates.length > 0) {
|
||||||
setSequenceToTest(sequenceId);
|
setSequenceToTest(sequenceId);
|
||||||
|
setTestEmail(""); // Réinitialiser l'email
|
||||||
setIsConfirmTestOpen(true);
|
setIsConfirmTestOpen(true);
|
||||||
} else {
|
} else {
|
||||||
toast.error("Cette séquence n'a pas de dates configurées");
|
toast.error("Cette séquence n'a pas de dates configurées");
|
||||||
@@ -113,7 +117,14 @@ export default function AdminSequences() {
|
|||||||
|
|
||||||
const confirmTestRappel = () => {
|
const confirmTestRappel = () => {
|
||||||
if (sequenceToTest !== null) {
|
if (sequenceToTest !== null) {
|
||||||
testerRappelMutation.mutate({ sequenceId: sequenceToTest });
|
if (!testEmail || !testEmail.includes('@')) {
|
||||||
|
toast.error("Veuillez saisir une adresse email valide");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
testerRappelMutation.mutate({
|
||||||
|
sequenceId: sequenceToTest,
|
||||||
|
emailTest: testEmail
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1076,17 +1087,31 @@ export default function AdminSequences() {
|
|||||||
<Dialog open={isConfirmTestOpen} onOpenChange={setIsConfirmTestOpen}>
|
<Dialog open={isConfirmTestOpen} onOpenChange={setIsConfirmTestOpen}>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Confirmer l'envoi du test</DialogTitle>
|
<DialogTitle>Tester l'envoi de rappels</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
Êtes-vous sûr de vouloir envoyer un email de test de rappel à tous les apprenants inscrits confirmés de cette séquence ?
|
Tous les rappels configurés pour cette séquence seront envoyés à l'adresse email que vous indiquez ci-dessous.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="flex justify-end gap-2 pt-4">
|
<div className="space-y-4 py-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="test-email">Adresse email du destinataire</Label>
|
||||||
|
<Input
|
||||||
|
id="test-email"
|
||||||
|
type="email"
|
||||||
|
placeholder="exemple@domaine.com"
|
||||||
|
value={testEmail}
|
||||||
|
onChange={(e) => setTestEmail(e.target.value)}
|
||||||
|
disabled={testerRappelMutation.isPending}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end gap-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsConfirmTestOpen(false);
|
setIsConfirmTestOpen(false);
|
||||||
setSequenceToTest(null);
|
setSequenceToTest(null);
|
||||||
|
setTestEmail("");
|
||||||
}}
|
}}
|
||||||
disabled={testerRappelMutation.isPending}
|
disabled={testerRappelMutation.isPending}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1418,6 +1418,7 @@ export const appRouter = router({
|
|||||||
testerRappel: adminProcedure
|
testerRappel: adminProcedure
|
||||||
.input(z.object({
|
.input(z.object({
|
||||||
sequenceId: z.number(),
|
sequenceId: z.number(),
|
||||||
|
emailTest: z.string().email().optional(),
|
||||||
}))
|
}))
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
const sequence = await db.getSequenceById(input.sequenceId);
|
const sequence = await db.getSequenceById(input.sequenceId);
|
||||||
@@ -1463,26 +1464,31 @@ export const appRouter = router({
|
|||||||
throw new TRPCError({ code: 'BAD_REQUEST', message: 'Aucun apprenant inscrit confirmé pour cette séquence' });
|
throw new TRPCError({ code: 'BAD_REQUEST', message: 'Aucun apprenant inscrit confirmé pour cette séquence' });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Envoyer le rappel de test à l'administrateur connecté
|
// Envoyer le rappel de test
|
||||||
// Envoyer le rappel de test à tous les inscrits confirmés
|
|
||||||
const { sendRappelEmail } = await import('./emailService');
|
const { sendRappelEmail } = await import('./emailService');
|
||||||
|
|
||||||
let nbEnvoyes = 0;
|
let nbEnvoyes = 0;
|
||||||
let nbEchecs = 0;
|
let nbEchecs = 0;
|
||||||
const erreurs: string[] = [];
|
const erreurs: string[] = [];
|
||||||
|
|
||||||
for (const inscrit of inscritsConfirmes) {
|
// Si un email de test est fourni, envoyer à cet email uniquement
|
||||||
const apprenant = inscrit.apprenant;
|
// Sinon, envoyer à tous les inscrits confirmés
|
||||||
|
const destinataires = input.emailTest
|
||||||
if (!apprenant || !apprenant.email) {
|
? [{ apprenant: inscritsConfirmes[0].apprenant, emailOverride: input.emailTest }]
|
||||||
|
: inscritsConfirmes.map(i => ({ apprenant: i.apprenant, emailOverride: null }));
|
||||||
|
|
||||||
|
for (const { apprenant, emailOverride } of destinataires) {
|
||||||
|
if (!apprenant || (!apprenant.email && !emailOverride)) {
|
||||||
nbEchecs++;
|
nbEchecs++;
|
||||||
erreurs.push(`Apprenant ${apprenant?.nom || 'inconnu'}: email manquant`);
|
erreurs.push(`Apprenant ${apprenant?.nom || 'inconnu'}: email manquant`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emailDestinataire = emailOverride || apprenant.email;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sendRappelEmail({
|
await sendRappelEmail({
|
||||||
apprenantEmail: apprenant.email,
|
apprenantEmail: emailDestinataire,
|
||||||
apprenantPrenom: apprenant.prenom,
|
apprenantPrenom: apprenant.prenom,
|
||||||
apprenantNom: apprenant.nom,
|
apprenantNom: apprenant.nom,
|
||||||
apprenantFonction: apprenant.fonction || '',
|
apprenantFonction: apprenant.fonction || '',
|
||||||
@@ -1506,7 +1512,7 @@ export const appRouter = router({
|
|||||||
rappelId: rappelAUtiliser.id,
|
rappelId: rappelAUtiliser.id,
|
||||||
sequenceId: input.sequenceId,
|
sequenceId: input.sequenceId,
|
||||||
apprenantId: apprenant.id,
|
apprenantId: apprenant.id,
|
||||||
email: apprenant.email,
|
email: emailDestinataire,
|
||||||
type: rappelAUtiliser.templateType,
|
type: rappelAUtiliser.templateType,
|
||||||
typeEnvoi: 'test',
|
typeEnvoi: 'test',
|
||||||
statut: 'succes',
|
statut: 'succes',
|
||||||
@@ -1524,7 +1530,7 @@ export const appRouter = router({
|
|||||||
rappelId: rappelAUtiliser.id,
|
rappelId: rappelAUtiliser.id,
|
||||||
sequenceId: input.sequenceId,
|
sequenceId: input.sequenceId,
|
||||||
apprenantId: apprenant.id,
|
apprenantId: apprenant.id,
|
||||||
email: apprenant.email,
|
email: emailDestinataire,
|
||||||
type: rappelAUtiliser.templateType,
|
type: rappelAUtiliser.templateType,
|
||||||
typeEnvoi: 'test',
|
typeEnvoi: 'test',
|
||||||
statut: 'echec',
|
statut: 'echec',
|
||||||
|
|||||||
1
todo.md
1
todo.md
@@ -1188,3 +1188,4 @@
|
|||||||
|
|
||||||
- [x] Corriger l'enregistrement des logs de rappels (table logsrappels reste vide après test)
|
- [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] 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
|
||||||
|
|||||||
Reference in New Issue
Block a user