"use client"; import { loadSchedule } from "../lib/data"; import { useEffect, useState } from "react"; import Flag from "./flag"; import { COPY, COPY_SUCCESS, FILTER_BY_COUNTRY, FILTER_BY_SPORT, LANGUAGE, MADE_BY_FABRICE, NOT_AFFILIATED, NO_EVENT_FOR_FILTERS } from "../lib/text"; import useLocalStorage from "@/lib/local-storage"; import { GoogleAnalytics } from "@next/third-parties/google"; import { Google_Sans, SUSE_Mono } from "next/font/google"; const googleSans = Google_Sans({ variable: "--font-google-sans", subsets: ["latin"], }); const suseMono = SUSE_Mono({ variable: "--font-suse-mono", subsets: ["latin"], }); export interface MultilingualString { [key: string]: string; } export interface Language { code: string; name: string; code3: string; } export interface Sport { key: string; name: MultilingualString; order: number; } export interface NOC { key: string; name: MultilingualString; } export interface Competitor { noc: string; code: string; name: string; } export interface Event { key: string; start: string; end: string; sport: string; medal: "0" | "1" | "3"; name: MultilingualString; location: MultilingualString; nocs: string[]; competitors: string[]; } export interface Calendar { languages: Language[]; sports: Sport[]; nocs: NOC[]; competitors: Competitor[]; events: Event[]; } const COLORS = ['azzurro', 'giallo', 'rosa', 'rosso', 'verde', 'viola']; export default function Home() { const qs = typeof window !== 'undefined' ? window.location.search ? new URLSearchParams(window.location.search) : new URLSearchParams() : new URLSearchParams(); const [data, setData] = useState(null); const [language, setLanguage] = useLocalStorage('lang', (navigator.language || 'en').split('-')[0]); const [cookieConsent, setCookieConsent] = useLocalStorage('cookie-consent', 'null'); const translate = (text: MultilingualString) => { return text[`${language}`] || text['en'] || Object.values(text)[0] || ''; }; const generateLink = ({ noc, sport, lang }: { noc?: string; sport?: string, lang?: string }) => { const currentParams = new URLSearchParams(qs.toString()); if (noc !== undefined) { if (noc === "") { currentParams.delete('noc'); } else { currentParams.set('noc', noc); } } if (sport !== undefined) { if (sport === "") { currentParams.delete('sport'); } else { currentParams.set('sport', sport); } } if (lang !== undefined) { if (lang === "") { currentParams.delete('lang'); } else { currentParams.set('lang', lang); } } const paramString = currentParams.toString(); return paramString ? `./?${paramString}` : '.'; } const generateCalendarLink = () => { const host = typeof window !== 'undefined' ? window.location.host : ''; const noc = (qs.get('noc') || 'calendar').toLowerCase(); const sport = (qs.get('sport') || 'all-sports').toLowerCase(); return `http://${host}/api/data/${language}/${sport}/${noc}.ics`; }; const getColor = (i: number) => COLORS[i % COLORS.length]; useEffect(() => { if (data == null) { loadSchedule() .then(setData) .catch(console.log); } }, [data]); const filter = (event: Event) => { let visible = true; if (event.end < new Date().toISOString()) { return false; } const sport = qs.get('sport'); if (sport && event.sport !== sport) { visible = false; } const noc = qs.get('noc'); if (noc) { if (!event.nocs.includes(noc)) { visible = false; } } return visible; } const copyToClipboard = (text: string) => { if (typeof navigator !== 'undefined' && navigator.clipboard) { const button = document.getElementById('copy_button')!; navigator.clipboard.writeText(text).then(() => { button.textContent = translate(COPY_SUCCESS); button.classList.add('text-success'); button.classList.add('font-bold'); setTimeout(() => { button.textContent = translate(COPY); button.classList.remove('text-success'); button.classList.remove('font-bold'); }, 2000); }); } } const calendarLink = generateCalendarLink(); if (data) { let lastDay = ""; if (data.languages.find(lang => lang.code === language) === undefined) { setLanguage('en') } const events = data.events.filter(event => filter(event)); let main = (
{translate(NO_EVENT_FOR_FILTERS)}
) if (events.length) { main = (
Apple Calendar Google Calendar Office 365 Calendar Outlook Calendar Yahoo Calendar
{ events .sort((a, b) => a.start.localeCompare(b.start)) .map((event, i) => { const startDate = new Date(event.start); const endDate = new Date(event.end); const startHours = startDate.getHours().toString().padStart(2, '0'); const startMinutes = startDate.getMinutes().toString().padStart(2, '0'); const endHours = endDate.getHours().toString().padStart(2, '0'); const endMinutes = endDate.getMinutes().toString().padStart(2, '0'); let titleColor = "fg-main"; if (event.medal === '1') { titleColor = "bg-gold"; } else if (event.medal === '3') { titleColor = "bg-bronze"; } const day = event.start.split('T')[0]; let dayHeader = <>; if (lastDay !== day) { dayHeader = (

{new Date(event.start).toLocaleDateString(language, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}

); } // eslint-disable-next-line react-hooks/immutability lastDay = day; const getCompetitor = (competitorId: string) => { console.log(competitorId); if (competitorId.startsWith("team:")) { const team = data.nocs.find(noc => noc.key === competitorId.replace("team:", "")); return { noc: team!.key, name: translate(team!.name) }; } const competitor = data.competitors.find(comp => comp.code === competitorId); return { noc: competitor!.noc, name: competitor!.name }; }; let competitors = <>; if (event.competitors.length > 0) { competitors = ( ); } return (
{dayHeader}
{startHours}:{startMinutes}
{endHours}:{endMinutes}
{translate(data.sports.find(sport => sport.key === event.sport)?.name || {})}
{translate(event.name)}
{competitors}
) }) }
) } const header = (
Olympics Calendar
{/* */}
); const footer = ( ); let cookie = <>; if (cookieConsent === 'true') { cookie = ( ); } else if (cookieConsent === 'null') { cookie = (

This website uses cookies for statistics purposes and to enhance the user experience.

); } return (
{header} {main} {footer} {cookie}
{translate(FILTER_BY_COUNTRY)} {qs.get('noc') && ( )}
{translate(FILTER_BY_SPORT)} {qs.get('sport') && ( )}
{translate(LANGUAGE)}
); } return (
Loading
); }