mirror of
https://github.com/LucasKalil-Programador/world-2026-hub.git
synced 2026-07-04 17:41:28 -03:00
49 lines
1.7 KiB
JavaScript
49 lines
1.7 KiB
JavaScript
// calendar.js — "Add to calendar" export (RFC 5545). One VEVENT per match,
|
|
// DTSTART/DTEND in UTC with a fixed 2h duration, CRLF line endings (required
|
|
// by the spec — some calendar apps reject \n). Knockout team names come from
|
|
// resolveBracketTeams().
|
|
|
|
import { matchDateUTC } from './app.js';
|
|
import { resolveBracketTeams } from './bracket.js';
|
|
import { translatePhase } from './i18n.js';
|
|
|
|
// Date → 20260611T160000Z
|
|
function icsDate(date) {
|
|
return date.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
|
|
}
|
|
|
|
// RFC 5545 TEXT escaping: backslash, comma, semicolon, newline
|
|
function icsEscape(text) {
|
|
return String(text).replace(/\\/g, '\\\\').replace(/,/g, '\\,').replace(/;/g, '\\;').replace(/\n/g, '\\n');
|
|
}
|
|
|
|
export function exportMatchToICS(match, stadium) {
|
|
const start = matchDateUTC(match);
|
|
const end = new Date(start.getTime() + 2 * 60 * 60 * 1000);
|
|
const { home, away } = resolveBracketTeams(match);
|
|
const location = stadium ? `${stadium.name}, ${stadium.city}` : match.city;
|
|
|
|
const lines = [
|
|
'BEGIN:VCALENDAR',
|
|
'VERSION:2.0',
|
|
'PRODID:-//WorldCup2026Hub//EN',
|
|
'BEGIN:VEVENT',
|
|
`UID:match-${match.id}@worldcup2026hub`,
|
|
`DTSTAMP:${icsDate(start)}`,
|
|
`DTSTART:${icsDate(start)}`,
|
|
`DTEND:${icsDate(end)}`,
|
|
`SUMMARY:${icsEscape(`${home.label} x ${away.label} — ${translatePhase(match.phase)}`)}`,
|
|
`LOCATION:${icsEscape(location)}`,
|
|
'END:VEVENT',
|
|
'END:VCALENDAR',
|
|
];
|
|
|
|
const blob = new Blob([lines.join('\r\n') + '\r\n'], { type: 'text/calendar' });
|
|
const link = document.createElement('a');
|
|
link.href = URL.createObjectURL(blob);
|
|
link.download = `match-${match.id}.ics`;
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
link.remove();
|
|
URL.revokeObjectURL(link.href);
|
|
}
|