summaryrefslogtreecommitdiff
path: root/src/components/AppEventDate.svelte
blob: 41ee248c2abb5afac3fb41266a9936df8fb3d021 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<script lang="ts">
    import { onMount } from 'svelte';
    import { fade } from 'svelte/transition';
    import type { Optional } from '@jet/environment/types/optional';
    import type { AppEvent } from '@jet-app/app-store/api/models';
    import { getJet } from '~/jet';
    import {
        chooseAppEventDate,
        renderDate,
        computeAppEventFormattedDates,
        type RequiredAppEventFormattedDate,
    } from '~/jet/utils/app-event-formatted-date';

    const jet = getJet();

    /**
     * New pattern (*prefered*): accept appEvent object and compute formattedDates on client-side.
     * This avoids timezone differences in SSR server (UTC) which cause incorrect event date and time.
     * By computing dates in the browser, we ensure the user sees dates in their local timezone.
     */
    export let appEvent:
        | Pick<AppEvent, 'appEventBadgeKind' | 'startDate' | 'endDate'>
        | undefined = undefined;

    // Legacy pattern: accept pre-computed formattedDates from Jet
    export let formattedDates: RequiredAppEventFormattedDate[] | undefined =
        undefined;

    let appEventDate: Optional<RequiredAppEventFormattedDate>;

    onMount(() => {
        const dates = appEvent
            ? computeAppEventFormattedDates(
                  jet.objectGraph,
                  appEvent.appEventBadgeKind,
                  appEvent.startDate,
                  appEvent.endDate,
              )
            : formattedDates;

        if (dates) {
            appEventDate = chooseAppEventDate(dates);
        }
    });

    /**
     * `Date` instances in the view-model will have been serialized to `string`
     * instances by ServerKit when delivered to the client; we need to normalize
     * this so that we have a `string` both client- and server-side.
     */
    function normalizeDate(date: Date | string): string {
        return typeof date === 'string' ? date : date.toISOString();
    }
</script>

{#if appEventDate}
    <time
        transition:fade={{ duration: 210 }}
        datetime={appEventDate.displayFromDate &&
            normalizeDate(appEventDate.displayFromDate)}
    >
        {renderDate(jet.objectGraph.loc, appEventDate)}
    </time>
{:else}
    <span aria-hidden="true">&hellip;</span>
{/if}

<style>
    span {
        color: transparent;
    }
</style>