owltide/components/EventCard.vue
Hornwitser ed67982ec0 Explicitly set locale to avoid hydration mismatch
Some functions in luxon default to the system's locale while other
functions default to "en-US".  Explicitly set the locale everywhere
the luxon objects are created to avoid possible mismatches and
unexpected behaviour should the system's locale be different.
2025-05-25 23:38:06 +02:00

83 lines
2.3 KiB
Vue

<template>
<section class="event">
<h3>{{ event.name }}</h3>
<p>{{ event.description ?? "No description provided" }}</p>
<p v-if="event.interested">
{{ event.interested }} interested
</p>
<p v-if="accountStore.interestedIds">
<button
class="interested"
:class="{ active: accountStore.interestedIds?.has(event.id) }"
@click="toggle(event.id, event.slots.map(slot => slot.id))"
>
{{ accountStore.interestedIds?.has(event.id) ? "✔ interested" : "🔔 interested?" }}
</button>
</p>
<h4>Timeslots</h4>
<ul>
<li v-for="slot in event.slots" :key="slot.id">
{{ formatTime(slot.start) }} - {{ formatTime(slot.end) }}
<button
v-if="accountStore.interestedIds && event.slots.length > 1"
class="interested"
:disabled="accountStore.interestedIds.has(event.id)"
:class="{ active: accountStore.interestedIds.has(event.id) || accountStore.interestedIds.has(slot.id) }"
@click="toggle(slot.id)"
>
{{ accountStore.interestedIds.has(event.id) || accountStore.interestedIds.has(slot.id) ? "✔ interested" : "🔔 interested?" }}
</button>
<template v-if="slot.interested">
({{ slot.interested }} interested)
</template>
<p v-if="slot.assigned">
Crew:
{{ slot.assigned.map(id => idToAccount.get(id)?.name).join(", ") }}
</p>
</li>
</ul>
</section>
</template>
<script lang="ts" setup>
import { DateTime } from 'luxon';
import type { ScheduleEvent } from '~/shared/types/schedule';
defineProps<{
event: ScheduleEvent
}>()
const accountStore = useAccountStore();
const { data: accounts } = await useAccounts();
const idToAccount = computed(() => new Map(accounts.value?.map(a => [a.id, a])));
function formatTime(time: string) {
return DateTime.fromISO(time, { zone: accountStore.activeTimezone, locale: "en-US" }).toFormat("yyyy-LL-dd HH:mm");
}
async function toggle(id: string, slotIds?: string[]) {
await accountStore.toggleInterestedId(id, slotIds);
}
</script>
<style scoped>
.event {
background: color-mix(in oklab, var(--background), grey 20%);
padding: 0.5rem;
border-radius: 0.5rem;
}
.event h3 {
margin: 0;
}
.event + .event {
margin-block-start: 0.5rem;
}
button {
padding-inline: 0.2em;
}
button.active {
color: color-mix(in oklab, var(--foreground), green 50%);
}
</style>