Checkpoint: Correction du problème d'aperçu de l'application

Corrections apportées :
- Correction des références à heureDebut/heureFin dans AdminRappels.tsx (utilisation de dateDebut/dateFin)
- Correction de l'accès à la propriété dates dans EmargementScan.tsx (cast de type)
- Ajout de l'import manquant de QrCode dans DashboardLayout.tsx
- Correction des erreurs TypeScript dans DashboardLayout.tsx (gestion de subItems)
- Ajout de downlevelIteration dans tsconfig.json
- Correction de l'utilisation de Set dans DateFormationMultiSelect.tsx (Array.from)
- Correction de l'appel à createAttestation (utilisation de enregistrerAttestation)

L'application fonctionne maintenant correctement sans erreurs TypeScript.
This commit is contained in:
Manus
2026-01-11 14:38:06 -05:00
parent b64dedc488
commit 3981d719e3
7 changed files with 44 additions and 24 deletions

View File

@@ -21,7 +21,7 @@ import {
} from "@/components/ui/sidebar"; } from "@/components/ui/sidebar";
import { APP_LOGO, APP_TITLE, getLoginUrl } from "@/const"; import { APP_LOGO, APP_TITLE, getLoginUrl } from "@/const";
import { useIsMobile } from "@/hooks/useMobile"; import { useIsMobile } from "@/hooks/useMobile";
import { LayoutDashboard, LogOut, PanelLeft, Users, GraduationCap, Calendar, CalendarDays, Bell, BarChart3, UserCog, Mail, Settings, TrendingUp, Building2, FileSpreadsheet, ClipboardList, ChevronDown, User, FileText } from "lucide-react"; import { LayoutDashboard, LogOut, PanelLeft, Users, GraduationCap, Calendar, CalendarDays, Bell, BarChart3, UserCog, Mail, Settings, TrendingUp, Building2, FileSpreadsheet, ClipboardList, ChevronDown, User, FileText, QrCode } from "lucide-react";
import { CSSProperties, useEffect, useRef, useState } from "react"; import { CSSProperties, useEffect, useRef, useState } from "react";
import { useLocation } from "wouter"; import { useLocation } from "wouter";
import { DashboardLayoutSkeleton } from './DashboardLayoutSkeleton'; import { DashboardLayoutSkeleton } from './DashboardLayoutSkeleton';
@@ -362,13 +362,13 @@ function DashboardLayoutContent({
<SidebarMenu className="px-2 py-1"> <SidebarMenu className="px-2 py-1">
{section.items.map(item => { {section.items.map(item => {
const isActive = location === item.path; const isActive = location === item.path;
const hasSubItems = 'subItems' in item && item.subItems && item.subItems.length > 0; const hasSubItems = 'subItems' in item && item.subItems && Array.isArray(item.subItems) && item.subItems.length > 0;
const isSubItemActive = hasSubItems && item.subItems.some((sub: any) => location === sub.path); const isSubItemActive = hasSubItems && Array.isArray(item.subItems) && item.subItems.some((sub: any) => location === sub.path);
return ( return (
<div key={item.path}> <div key={item.path}>
<SidebarMenuItem> <SidebarMenuItem>
<SidebarMenuButton <SidebarMenuButton
isActive={isActive || isSubItemActive} isActive={isActive || Boolean(isSubItemActive)}
onClick={() => setLocation(item.path)} onClick={() => setLocation(item.path)}
tooltip={item.label} tooltip={item.label}
className={`h-10 transition-all font-normal`} className={`h-10 transition-all font-normal`}
@@ -379,9 +379,9 @@ function DashboardLayoutContent({
<span>{item.label}</span> <span>{item.label}</span>
</SidebarMenuButton> </SidebarMenuButton>
</SidebarMenuItem> </SidebarMenuItem>
{hasSubItems && ( {(hasSubItems && Array.isArray(item.subItems) ? (
<div className="ml-6 mt-1 space-y-1"> <div className="ml-6 mt-1 space-y-1">
{item.subItems.map((subItem: any) => { {(item.subItems as any[]).map((subItem: any) => {
const isSubActive = location === subItem.path; const isSubActive = location === subItem.path;
return ( return (
<SidebarMenuItem key={subItem.path}> <SidebarMenuItem key={subItem.path}>
@@ -397,7 +397,7 @@ function DashboardLayoutContent({
); );
})} })}
</div> </div>
)} ) : null)}
</div> </div>
); );
})} })}

View File

@@ -62,7 +62,7 @@ export function DateFormationMultiSelect({
onSelectionChange(selectedDateIds.filter((id) => !sequenceDateIds.includes(id))); onSelectionChange(selectedDateIds.filter((id) => !sequenceDateIds.includes(id)));
} else { } else {
// Sélectionner toutes les dates de cette séquence // Sélectionner toutes les dates de cette séquence
const newSelection = [...new Set([...selectedDateIds, ...sequenceDateIds])]; const newSelection = Array.from(new Set([...selectedDateIds, ...sequenceDateIds]));
onSelectionChange(newSelection); onSelectionChange(newSelection);
} }
}; };

View File

@@ -596,11 +596,11 @@ export default function AdminRappels() {
id: seq.id, id: seq.id,
nom: seq.nom, nom: seq.nom,
formationNom: seq.formation?.nom || '', formationNom: seq.formation?.nom || '',
dates: seq.dates?.map(d => ({ dates: seq.dates?.map((d: any) => ({
id: d.id, id: d.id,
date: d.dateDebut, date: d.dateDebut ? new Date(d.dateDebut).toISOString() : '',
heureDebut: d.heureDebut || '', heureDebut: d.dateDebut ? new Date(d.dateDebut).toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }) : '',
heureFin: d.heureFin || '', heureFin: d.dateFin ? new Date(d.dateFin).toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }) : '',
})) || [], })) || [],
})) || []} })) || []}
selectedDateIds={formData.dateFormationIds} selectedDateIds={formData.dateFormationIds}
@@ -744,9 +744,9 @@ export default function AdminRappels() {
formationNom: seq.formation?.nom || '', formationNom: seq.formation?.nom || '',
dates: seq.dates?.map(d => ({ dates: seq.dates?.map(d => ({
id: d.id, id: d.id,
date: d.dateDebut, date: d.dateDebut ? new Date(d.dateDebut).toISOString() : '',
heureDebut: d.heureDebut || '', heureDebut: d.dateDebut ? new Date(d.dateDebut).toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }) : '',
heureFin: d.heureFin || '', heureFin: d.dateFin ? new Date(d.dateFin).toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }) : '',
})) || [], })) || [],
})) || []} })) || []}
selectedDateIds={formData.dateFormationIds} selectedDateIds={formData.dateFormationIds}

View File

@@ -75,7 +75,7 @@ export default function EmargementScan() {
}; };
// Déterminer les dates disponibles // Déterminer les dates disponibles
const datesDisponibles = selectedInscription?.sequence?.dates || []; const datesDisponibles = (selectedInscription?.sequence as any)?.dates || [];
if (success) { if (success) {
return ( return (

View File

@@ -2132,18 +2132,26 @@ export const appRouter = router({
// Si toutes les présences sont validées, générer l'attestation automatiquement // Si toutes les présences sont validées, générer l'attestation automatiquement
if (allValidated) { if (allValidated) {
try { try {
const { genererAttestationPDF } = await import("./attestationService"); const { genererAttestationPDF, enregistrerAttestation } = await import("./attestationService");
const { createAttestation } = await import("./attestationService");
// Générer le PDF // Générer le PDF
const { s3Key, pdfUrl } = await genererAttestationPDF(input.inscriptionId); const { s3Key, pdfUrl } = await genererAttestationPDF(input.inscriptionId);
// Enregistrer l'attestation en base // Récupérer les données de l'inscription
await createAttestation({ const db = await getDb();
inscriptionId: input.inscriptionId, if (db) {
s3Key, const inscriptionData = await db.select().from(inscriptions).where(eq(inscriptions.id, input.inscriptionId)).limit(1);
pdfUrl, if (inscriptionData.length > 0) {
}); // Enregistrer l'attestation en base
await enregistrerAttestation(
input.inscriptionId,
inscriptionData[0].apprenantId,
inscriptionData[0].sequenceId,
s3Key,
pdfUrl
);
}
}
return { return {
...result, ...result,

11
todo.md
View File

@@ -668,3 +668,14 @@
- [x] Générer automatiquement après validation de toutes les présences - [x] Générer automatiquement après validation de toutes les présences
- [x] Envoyer par email aux apprenants - [x] Envoyer par email aux apprenants
- [x] Permettre le téléchargement depuis l'espace formateur - [x] Permettre le téléchargement depuis l'espace formateur
## Corrections techniques
- [x] Corriger le problème d'aperçu de l'application (erreurs TypeScript)
- [x] Corriger les références à heureDebut/heureFin dans AdminRappels.tsx
- [x] Corriger l'accès à la propriété dates dans EmargementScan.tsx
- [x] Corriger l'import manquant de QrCode dans DashboardLayout.tsx
- [x] Corriger les erreurs TypeScript dans DashboardLayout.tsx (subItems)
- [x] Ajouter downlevelIteration dans tsconfig.json
- [x] Corriger l'utilisation de Set dans DateFormationMultiSelect.tsx
- [x] Corriger l'appel à createAttestation (utiliser enregistrerAttestation)

View File

@@ -11,6 +11,7 @@
"jsx": "preserve", "jsx": "preserve",
"esModuleInterop": true, "esModuleInterop": true,
"skipLibCheck": true, "skipLibCheck": true,
"downlevelIteration": true,
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"moduleResolution": "bundler", "moduleResolution": "bundler",
"baseUrl": ".", "baseUrl": ".",