/** * Module de génération de fichiers ICS (iCalendar) pour les invitations Outlook */ interface ICSEvent { summary: string; description?: string; location: string; startDate: Date; endDate: Date; attendeeEmail: string; attendeeName: string; organizerEmail?: string; organizerName?: string; } /** * Formate une date au format iCalendar (YYYYMMDDTHHMMSSZ) */ function formatICSDate(date: Date): string { const year = date.getUTCFullYear(); const month = String(date.getUTCMonth() + 1).padStart(2, '0'); const day = String(date.getUTCDate()).padStart(2, '0'); const hours = String(date.getUTCHours()).padStart(2, '0'); const minutes = String(date.getUTCMinutes()).padStart(2, '0'); const seconds = String(date.getUTCSeconds()).padStart(2, '0'); return `${year}${month}${day}T${hours}${minutes}${seconds}Z`; } /** * Génère un UID unique pour l'événement */ function generateUID(): string { return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}@itinova.com`; } /** * Échappe les caractères spéciaux pour le format ICS */ function escapeICS(text: string): string { return text .replace(/\\/g, '\\\\') .replace(/;/g, '\\;') .replace(/,/g, '\\,') .replace(/\n/g, '\\n'); } /** * Génère un fichier ICS pour une invitation Outlook */ export function generateICS(event: ICSEvent): string { const now = new Date(); const uid = generateUID(); const icsContent = [ 'BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-//Itinova//Formation Manager//FR', 'CALSCALE:GREGORIAN', 'METHOD:REQUEST', 'BEGIN:VEVENT', `UID:${uid}`, `DTSTAMP:${formatICSDate(now)}`, `DTSTART:${formatICSDate(event.startDate)}`, `DTEND:${formatICSDate(event.endDate)}`, `SUMMARY:${escapeICS(event.summary)}`, event.description ? `DESCRIPTION:${escapeICS(event.description)}` : '', `LOCATION:${escapeICS(event.location)}`, 'STATUS:CONFIRMED', 'TRANSP:OPAQUE', // Marque comme "occupé" dans le calendrier 'SEQUENCE:0', `ORGANIZER;CN=${escapeICS(event.organizerName || 'Formation Itinova')}:mailto:${event.organizerEmail || 'formation@itinova.com'}`, `ATTENDEE;CN=${escapeICS(event.attendeeName)};RSVP=TRUE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:${event.attendeeEmail}`, 'BEGIN:VALARM', 'TRIGGER:-P1D', // Rappel 1 jour avant 'ACTION:DISPLAY', `DESCRIPTION:Rappel: ${escapeICS(event.summary)}`, 'END:VALARM', 'END:VEVENT', 'END:VCALENDAR', ].filter(line => line !== '').join('\r\n'); return icsContent; } /** * Génère un fichier ICS pour une session de formation */ export function generateFormationICS(params: { formationNom: string; sessionNom: string; dateDebut: Date; dateFin: Date; lieu: string; apprenantNom: string; apprenantPrenom: string; apprenantEmail: string; }): string { return generateICS({ summary: `Formation: ${params.formationNom} - ${params.sessionNom}`, description: `Vous êtes inscrit à la formation "${params.formationNom}".\n\nSession: ${params.sessionNom}\n\nMerci de vous présenter à l'heure indiquée.`, location: params.lieu, startDate: params.dateDebut, endDate: params.dateFin, attendeeEmail: params.apprenantEmail, attendeeName: `${params.apprenantPrenom} ${params.apprenantNom}`, }); }