110 lines
3.3 KiB
TypeScript
110 lines
3.3 KiB
TypeScript
/**
|
|
* 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}`,
|
|
});
|
|
}
|