speedclimbing/website

View on GitHub
src/routes/competition/+page.svelte

Summary

Maintainability
Test Coverage
<script lang="ts">
    import type { PageData } from './$types';
    import { mounted } from 'utils/mounted';
    import { browser } from '$app/environment';
    import { updateSearchParams } from 'utils/updateSearchParams';
    import CompetitionCalendar from 'components/competitions/CompetitionCalendar.svelte';
    import EventCard from 'components/shared/content/EventCard.svelte';
    import { Spinner } from 'flowbite-svelte';
    import { navigating } from '$app/stores';
    import DebouncedInput from 'components/shared/inputs/DebouncedInput.svelte';
    import SelectFilter from 'components/shared/inputs/SelectFilter.svelte';
    import SwitchButton from 'components/shared/buttons/SwitchButton.svelte';

    export let data: PageData;
    let view: 'List' | 'Calendar' = 'List';
    let calendarDate: Date | undefined = undefined;

    const isMounted = () => $mounted;

    const updateCalendarDateOnYearChange = (newYear: string) => {
        if (calendarDate && newYear === calendarDate.getFullYear().toString()) {
            return;
        }

        const currentDate = new Date();
        if (newYear === currentDate.getFullYear().toString()) {
            calendarDate = currentDate;
        } else {
            calendarDate = undefined;
        }
    };

    const updateYearOnCalendarDateChange = (newCalendarDate: Date | undefined) => {
        if (
            view !== 'Calendar' ||
            newCalendarDate === undefined ||
            data.params.year === newCalendarDate.getFullYear().toString()
        ) {
            return;
        }

        data.params.year = newCalendarDate.getFullYear().toString();
    };

    $: {
        updateCalendarDateOnYearChange(data.params.year);
    }

    $: {
        updateYearOnCalendarDateChange(calendarDate);
    }

    $: {
        if (!browser || !isMounted()) break $;
        updateSearchParams(data.params);
    }
</script>

<svelte:head>
    <title>Competitions - Overview</title>
    <meta
        name="description"
        content="Everything about past and upcoming competitions. Get an overview of the whole schedule of speedclimbing events!"
    />
</svelte:head>

<section id="competition-filter" class="xl:grid-cols-5 md:grid-cols-2 grid gap-[10px] mt-10">
    <DebouncedInput
        type="text"
        placeholder="Competition Name"
        inputClass="rounded-sm font-Raleway bg-black/5"
        bind:value={data.params.name}
    />
    {#each data.filters as filter}
        <SelectFilter bind:value={data.params[filter.name]} {filter} />
    {/each}
    <SwitchButton
        options={['List', 'Calendar']}
        bind:value={view}
        class="md:col-span-2 ml-auto xl:col-span-1"
    />
</section>

<section id="competitions">
    {#if $navigating}
        <div class="flex justify-center items-center my-10">
            <Spinner />
        </div>
    {:else if data.competitions.length === 0}
        <div class="flex justify-center items-center my-10">
            <p class="text-2xl font-semibold">No competitions found</p>
        </div>
    {:else if view === 'List'}
        <div class="grid grid-cols-1 lg:grid-cols-2 gap-5 my-10">
            {#each data.competitions as competition, index (index)}
                <EventCard {competition} />
            {/each}
        </div>
    {:else if view === 'Calendar'}
        <CompetitionCalendar competitions={data.competitions} bind:date={calendarDate} />
    {/if}
</section>