import { slugify } from '@/utils/slugify' export interface IcalEvent { eventToken: string title: string dateTime: string location?: string description?: string } function escapeText(value: string): string { return value .replace(/\\/g, '\\\\') .replace(/;/g, '\\;') .replace(/,/g, '\\,') .replace(/\n/g, '\\n') } function toUtcString(isoDateTime: string): string { const d = new Date(isoDateTime) const pad = (n: number) => String(n).padStart(2, '0') return ( `${d.getUTCFullYear()}${pad(d.getUTCMonth() + 1)}${pad(d.getUTCDate())}` + `T${pad(d.getUTCHours())}${pad(d.getUTCMinutes())}${pad(d.getUTCSeconds())}Z` ) } export function generateIcs(event: IcalEvent): string { const lines: string[] = [ 'BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-//fete//EN', 'BEGIN:VEVENT', `UID:${event.eventToken}@fete`, `DTSTAMP:${toUtcString(new Date().toISOString())}`, `DTSTART:${toUtcString(event.dateTime)}`, `SUMMARY:${escapeText(event.title)}`, 'SEQUENCE:0', ] if (event.location) { lines.push(`LOCATION:${escapeText(event.location)}`) } if (event.description) { lines.push(`DESCRIPTION:${escapeText(event.description)}`) } lines.push('END:VEVENT', 'END:VCALENDAR', '') return lines.join('\r\n') } export function useIcalDownload() { function download(event: IcalEvent) { const ics = generateIcs(event) const blob = new Blob([ics], { type: 'text/calendar;charset=utf-8' }) const url = URL.createObjectURL(blob) const filename = `${slugify(event.title) || 'event'}.ics` const link = document.createElement('a') link.href = url link.download = filename document.body.appendChild(link) link.click() document.body.removeChild(link) URL.revokeObjectURL(url) } return { download } }