speedclimbing/website

View on GitHub
src/components/competitions/CompetitionCalendar.svelte

Summary

Maintainability
Test Coverage
<script lang="ts">
    import type { Competition } from 'types/Competition';
    import { Calendar } from 'fullcalendar';
    import dayGridPlugin from '@fullcalendar/daygrid';
    import { onMount } from 'svelte';
    import { stringToHex } from 'utils/stringToHex';
    import { mounted } from 'utils/mounted';
    import CalendarSubscriptionModal from './CalendarSubscriptionModal.svelte';

    export let competitions: Competition[];
    export let date: Date | undefined = undefined;
    let calendarEl: HTMLElement;
    let calendar: Calendar;
    let showModal: boolean;
    const isMounted = () => $mounted;

    onMount(() => {
        calendar = new Calendar(calendarEl, {
            plugins: [dayGridPlugin],
            headerToolbar: {
                left: 'title',
                right: 'customprev,customnext'
            },
            footerToolbar: {
                right: 'subscribeToCalendar'
            },
            initialView: 'dayGridMonth',
            height: 'auto',
            displayEventTime: false,
            eventClick: (info) => {
                console.log(info.el);
            },
            eventContent: function (arg) {
                let p1 = document.createElement('p');
                p1.innerHTML = arg.event.title;
                p1.style.overflow = 'clip';
                return { domNodes: [p1] };
            },
            customButtons: {
                customprev: {
                    icon: 'chevron-left',
                    click: function () {
                        calendar.prev();
                        date = calendar.getDate();
                    }
                },
                customnext: {
                    icon: 'chevron-right',
                    click: function () {
                        calendar.next();
                        date = calendar.getDate();
                    }
                },
                subscribeToCalendar: {
                    text: 'Subscribe to calendar',
                    click: () => (showModal = true)
                }
            }
        });

        updateCalendarEvents(competitions);
        calendar.render();
    });

    function updateCalendarEvents(competitions: Competition[]) {
        calendar.removeAllEvents();
        competitions.forEach((c) => {
            calendar.addEvent({
                title: c.name,
                start: c.from,
                end: c.to,
                backgroundColor: stringToHex(c.league_id),
                borderColor: 'transparent',
                extendedProps: {
                    location: c.location,
                    nation: c.nation_code
                }
            });
        });

        if (date || competitions.length > 0) {
            calendar.gotoDate(date ?? competitions[0].from);
        }
    }
    $: {
        if (!isMounted()) break $;
        updateCalendarEvents(competitions);
        calendar.render();
    }
</script>

<div id="calendar" class="py-10" bind:this={calendarEl} />
<CalendarSubscriptionModal bind:open={showModal} />