2025-03-05 15:36:50 +01:00
|
|
|
<template>
|
|
|
|
<section class="event">
|
|
|
|
<h3>{{ event.name }}</h3>
|
|
|
|
<p>{{ event.description ?? "No description provided" }}</p>
|
2025-03-07 20:15:41 +01:00
|
|
|
<p v-if="event.interested">
|
|
|
|
{{ event.interested }} interested
|
|
|
|
</p>
|
2025-05-24 17:53:33 +02:00
|
|
|
<p v-if="sessionStore.account">
|
2025-03-07 20:15:41 +01:00
|
|
|
<button
|
|
|
|
class="interested"
|
|
|
|
:class="{ active: interestedIds.has(event.id) }"
|
|
|
|
@click="toggle(event.id, event.slots.map(slot => slot.id))"
|
|
|
|
>
|
|
|
|
{{ interestedIds.has(event.id) ? "✔ interested" : "🔔 interested?" }}
|
|
|
|
</button>
|
|
|
|
</p>
|
|
|
|
|
2025-03-05 15:36:50 +01:00
|
|
|
<h4>Timeslots</h4>
|
|
|
|
<ul>
|
|
|
|
<li v-for="slot in event.slots" :key="slot.id">
|
2025-03-09 18:35:38 +01:00
|
|
|
{{ formatTime(slot.start) }} - {{ formatTime(slot.end) }}
|
2025-03-07 20:15:41 +01:00
|
|
|
<button
|
2025-05-24 17:53:33 +02:00
|
|
|
v-if="sessionStore.account && event.slots.length > 1"
|
2025-03-07 20:15:41 +01:00
|
|
|
class="interested"
|
|
|
|
:disabled="interestedIds.has(event.id)"
|
|
|
|
:class="{ active: interestedIds.has(event.id) || interestedIds.has(slot.id) }"
|
|
|
|
@click="toggle(slot.id)"
|
|
|
|
>
|
|
|
|
{{ interestedIds.has(event.id) || interestedIds.has(slot.id) ? "✔ interested" : "🔔 interested?" }}
|
|
|
|
</button>
|
|
|
|
<template v-if="slot.interested">
|
|
|
|
({{ slot.interested }} interested)
|
|
|
|
</template>
|
2025-03-15 20:37:08 +01:00
|
|
|
<p v-if="slot.assigned">
|
|
|
|
Crew:
|
|
|
|
{{ slot.assigned.map(id => idToAccount.get(id)?.name).join(", ") }}
|
|
|
|
</p>
|
2025-03-05 15:36:50 +01:00
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</section>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2025-03-09 18:35:38 +01:00
|
|
|
import { DateTime } from 'luxon';
|
2025-03-05 15:36:50 +01:00
|
|
|
import type { ScheduleEvent } from '~/shared/types/schedule';
|
|
|
|
|
|
|
|
defineProps<{
|
|
|
|
event: ScheduleEvent
|
|
|
|
}>()
|
2025-03-07 20:15:41 +01:00
|
|
|
|
2025-03-09 18:35:38 +01:00
|
|
|
const runtimeConfig = useRuntimeConfig();
|
2025-05-24 17:53:33 +02:00
|
|
|
const sessionStore = useSessionStore();
|
|
|
|
const interestedIds = computed(() => new Set(sessionStore.account?.interestedIds ?? []));
|
|
|
|
const timezone = computed(() => sessionStore.account?.timezone ?? runtimeConfig.public.defaultTimezone);
|
2025-03-15 20:37:08 +01:00
|
|
|
const { data: accounts } = await useAccounts();
|
|
|
|
const idToAccount = computed(() => new Map(accounts.value?.map(a => [a.id, a])));
|
2025-03-09 18:35:38 +01:00
|
|
|
|
|
|
|
function formatTime(time: string) {
|
|
|
|
return DateTime.fromISO(time, { zone: timezone.value }).toFormat("yyyy-LL-dd HH:mm");
|
|
|
|
}
|
2025-03-07 20:15:41 +01:00
|
|
|
|
|
|
|
async function toggle(id: string, slotIds?: string[]) {
|
2025-05-24 17:53:33 +02:00
|
|
|
let newIds = [...sessionStore.account!.interestedIds ?? []];
|
2025-03-07 20:15:41 +01:00
|
|
|
if (interestedIds.value.has(id)) {
|
|
|
|
newIds = newIds.filter(newId => newId !== id);
|
|
|
|
} else {
|
|
|
|
newIds.push(id);
|
|
|
|
if (slotIds) {
|
|
|
|
const filterIds = new Set(slotIds);
|
|
|
|
newIds = newIds.filter(newId => !filterIds.has(newId));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
await $fetch("/api/account", {
|
|
|
|
method: "PATCH",
|
|
|
|
body: { interestedIds: newIds },
|
|
|
|
})
|
2025-05-24 17:53:33 +02:00
|
|
|
await sessionStore.fetch();
|
2025-03-07 20:15:41 +01:00
|
|
|
}
|
2025-03-05 15:36:50 +01:00
|
|
|
</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;
|
|
|
|
}
|
2025-03-07 20:15:41 +01:00
|
|
|
|
|
|
|
button {
|
|
|
|
padding-inline: 0.2em;
|
|
|
|
}
|
|
|
|
button.active {
|
|
|
|
color: color-mix(in oklab, var(--foreground), green 50%);
|
|
|
|
}
|
2025-03-05 15:36:50 +01:00
|
|
|
</style>
|