Checkpoint: Améliorations du tableau des rappels : renommage de la colonne "Template" en "Template d'email" et ajout d'une colonne "Dates concernées" affichant les formations, séquences et dates spécifiques associées à chaque rappel. La fonction getRappels a été enrichie pour récupérer automatiquement les détails des dates de formation (formation, séquence, ordre). L'affichage groupé permet de voir en un coup d'œil si un rappel s'applique à toutes les dates ou seulement à des dates spécifiques.
This commit is contained in:
@@ -183,6 +183,40 @@ export default function AdminRappels() {
|
|||||||
return TEMPLATE_TYPES.find(t => t.value === type)?.label || type;
|
return TEMPLATE_TYPES.find(t => t.value === type)?.label || type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const formatDatesInfo = (rappel: any) => {
|
||||||
|
if (!rappel.datesDetails || rappel.datesDetails.length === 0) {
|
||||||
|
return <span className="text-muted-foreground italic">Toutes les dates</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grouper par formation et séquence
|
||||||
|
const grouped = rappel.datesDetails.reduce((acc: any, date: any) => {
|
||||||
|
const key = `${date.formationNom} - ${date.sequenceNom}`;
|
||||||
|
if (!acc[key]) {
|
||||||
|
acc[key] = [];
|
||||||
|
}
|
||||||
|
acc[key].push(date);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="text-sm space-y-1">
|
||||||
|
{Object.entries(grouped).map(([key, dates]: [string, any]) => (
|
||||||
|
<div key={key}>
|
||||||
|
<div className="font-medium">{key}</div>
|
||||||
|
<div className="text-muted-foreground">
|
||||||
|
{dates.map((d: any, idx: number) => (
|
||||||
|
<span key={d.dateFormationId}>
|
||||||
|
Date {d.ordre}
|
||||||
|
{idx < dates.length - 1 && ", "}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayout>
|
<DashboardLayout>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
@@ -214,9 +248,10 @@ export default function AdminRappels() {
|
|||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>Nom</TableHead>
|
<TableHead>Nom</TableHead>
|
||||||
<TableHead>Template</TableHead>
|
<TableHead>Template d'email</TableHead>
|
||||||
<TableHead>Délai</TableHead>
|
<TableHead>Délai</TableHead>
|
||||||
<TableHead>Heure</TableHead>
|
<TableHead>Heure</TableHead>
|
||||||
|
<TableHead>Dates concernées</TableHead>
|
||||||
<TableHead>Statut</TableHead>
|
<TableHead>Statut</TableHead>
|
||||||
<TableHead className="text-right">Actions</TableHead>
|
<TableHead className="text-right">Actions</TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
@@ -231,6 +266,9 @@ export default function AdminRappels() {
|
|||||||
{rappel.timing === "post_formation" ? `J+${rappel.joursAvant}` : `J-${rappel.joursAvant}`}
|
{rappel.timing === "post_formation" ? `J+${rappel.joursAvant}` : `J-${rappel.joursAvant}`}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>{rappel.heureEnvoi}</TableCell>
|
<TableCell>{rappel.heureEnvoi}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{formatDatesInfo(rappel)}
|
||||||
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleToggleActif(rappel.id, rappel.actif)}
|
onClick={() => handleToggleActif(rappel.id, rappel.actif)}
|
||||||
@@ -265,7 +303,7 @@ export default function AdminRappels() {
|
|||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={6} className="text-center text-muted-foreground">
|
<TableCell colSpan={7} className="text-center text-muted-foreground">
|
||||||
Aucun rappel configuré
|
Aucun rappel configuré
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|||||||
33
server/db.ts
33
server/db.ts
@@ -972,13 +972,44 @@ export async function getRappels() {
|
|||||||
|
|
||||||
const allRappels = await db.select().from(rappels).orderBy(rappels.joursAvant);
|
const allRappels = await db.select().from(rappels).orderBy(rappels.joursAvant);
|
||||||
|
|
||||||
// Pour chaque rappel, récupérer les dates de formation associées
|
// Pour chaque rappel, récupérer les dates de formation associées avec leurs infos
|
||||||
const rappelsWithDates = await Promise.all(
|
const rappelsWithDates = await Promise.all(
|
||||||
allRappels.map(async (rappel) => {
|
allRappels.map(async (rappel) => {
|
||||||
const dateFormationIds = await getRappelDates(rappel.id);
|
const dateFormationIds = await getRappelDates(rappel.id);
|
||||||
|
|
||||||
|
// Récupérer les détails des dates de formation
|
||||||
|
const datesDetails = await Promise.all(
|
||||||
|
dateFormationIds.map(async (dateId) => {
|
||||||
|
const dateFormationResult = await db.select().from(datesFormation).where(eq(datesFormation.id, dateId)).limit(1);
|
||||||
|
if (dateFormationResult.length === 0) return null;
|
||||||
|
|
||||||
|
const dateFormation = dateFormationResult[0];
|
||||||
|
const sequenceResult = await db.select().from(sequences).where(eq(sequences.id, dateFormation.sequenceId)).limit(1);
|
||||||
|
if (sequenceResult.length === 0) return null;
|
||||||
|
|
||||||
|
const sequence = sequenceResult[0];
|
||||||
|
const formationResult = await db.select().from(formations).where(eq(formations.id, sequence.formationId)).limit(1);
|
||||||
|
if (formationResult.length === 0) return null;
|
||||||
|
|
||||||
|
const formation = formationResult[0];
|
||||||
|
|
||||||
|
return {
|
||||||
|
dateFormationId: dateFormation.id,
|
||||||
|
dateDebut: dateFormation.dateDebut,
|
||||||
|
dateFin: dateFormation.dateFin,
|
||||||
|
ordre: dateFormation.ordre,
|
||||||
|
sequenceId: sequence.id,
|
||||||
|
sequenceNom: sequence.nom,
|
||||||
|
formationId: formation.id,
|
||||||
|
formationNom: formation.nom,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...rappel,
|
...rappel,
|
||||||
dateFormationIds,
|
dateFormationIds,
|
||||||
|
datesDetails: datesDetails.filter(d => d !== null),
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
6
todo.md
6
todo.md
@@ -560,3 +560,9 @@
|
|||||||
- [x] Modifier le scheduler pour filtrer par dateFormationId
|
- [x] Modifier le scheduler pour filtrer par dateFormationId
|
||||||
- [ ] Tester la création avec dates spécifiques
|
- [ ] Tester la création avec dates spécifiques
|
||||||
- [ ] Vérifier l'affichage et l'édition
|
- [ ] Vérifier l'affichage et l'édition
|
||||||
|
|
||||||
|
## Améliorations tableau des rappels
|
||||||
|
- [x] Renommer la colonne "Template" en "Template d'email"
|
||||||
|
- [x] Ajouter une colonne "Dates concernées" avec formations, séquences et dates
|
||||||
|
- [x] Modifier la procédure tRPC pour inclure les informations de dates
|
||||||
|
- [x] Tester l'affichage avec plusieurs rappels
|
||||||
|
|||||||
Reference in New Issue
Block a user