192 lines
4.9 KiB
Vue
192 lines
4.9 KiB
Vue
<script setup lang="ts">
|
||
import { useEventList } from '@/composables/api/useEvents'
|
||
import { dutchPlural } from '@/lib/dutch-plural'
|
||
import { useAuthStore } from '@/stores/useAuthStore'
|
||
import CreateEventDialog from '@/components/events/CreateEventDialog.vue'
|
||
import type { EventStatus, EventItem } from '@/types/event'
|
||
|
||
const router = useRouter()
|
||
const authStore = useAuthStore()
|
||
|
||
const orgId = computed(() => authStore.currentOrganisation?.id ?? '')
|
||
|
||
const { data: events, isLoading, isError, refetch } = useEventList(orgId)
|
||
|
||
const isCreateDialogOpen = ref(false)
|
||
|
||
// Filter: only top-level events (no sub-events)
|
||
const topLevelEvents = computed(() =>
|
||
events.value?.filter(e => !e.is_sub_event) ?? [],
|
||
)
|
||
|
||
const statusColor: Record<EventStatus, string> = {
|
||
draft: 'default',
|
||
published: 'info',
|
||
registration_open: 'cyan',
|
||
buildup: 'warning',
|
||
showday: 'success',
|
||
teardown: 'warning',
|
||
closed: 'error',
|
||
}
|
||
|
||
const eventTypeColor: Record<string, string> = {
|
||
festival: 'purple',
|
||
series: 'info',
|
||
}
|
||
|
||
const dateFormatter = new Intl.DateTimeFormat('nl-NL', {
|
||
day: '2-digit',
|
||
month: '2-digit',
|
||
year: 'numeric',
|
||
})
|
||
|
||
function formatDate(iso: string) {
|
||
return dateFormatter.format(new Date(iso))
|
||
}
|
||
|
||
function navigateToEvent(event: EventItem) {
|
||
router.push({ name: 'events-id', params: { id: event.id } })
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div>
|
||
<!-- No org selected -->
|
||
<VAlert
|
||
v-if="!orgId"
|
||
type="warning"
|
||
class="mb-4"
|
||
>
|
||
Selecteer eerst een organisatie.
|
||
<template #append>
|
||
<VBtn
|
||
variant="text"
|
||
:to="{ name: 'organisation' }"
|
||
>
|
||
Naar organisatie
|
||
</VBtn>
|
||
</template>
|
||
</VAlert>
|
||
|
||
<template v-else>
|
||
<div class="d-flex justify-space-between align-center mb-6">
|
||
<h4 class="text-h4">
|
||
Evenementen
|
||
</h4>
|
||
<VBtn
|
||
prepend-icon="tabler-plus"
|
||
@click="isCreateDialogOpen = true"
|
||
>
|
||
Nieuw aanmaken
|
||
</VBtn>
|
||
</div>
|
||
|
||
<!-- Loading -->
|
||
<VSkeletonLoader
|
||
v-if="isLoading"
|
||
type="card@4"
|
||
/>
|
||
|
||
<!-- Error -->
|
||
<VAlert
|
||
v-else-if="isError"
|
||
type="error"
|
||
class="mb-4"
|
||
>
|
||
Kon evenementen niet laden.
|
||
<template #append>
|
||
<VBtn
|
||
variant="text"
|
||
@click="refetch()"
|
||
>
|
||
Opnieuw proberen
|
||
</VBtn>
|
||
</template>
|
||
</VAlert>
|
||
|
||
<!-- Empty -->
|
||
<VCard
|
||
v-else-if="!topLevelEvents.length"
|
||
class="text-center pa-8"
|
||
>
|
||
<VIcon
|
||
icon="tabler-calendar-event"
|
||
size="48"
|
||
class="mb-4 text-disabled"
|
||
/>
|
||
<p class="text-body-1 text-disabled">
|
||
Nog geen evenementen. Maak je eerste evenement aan.
|
||
</p>
|
||
</VCard>
|
||
|
||
<!-- Event cards grid -->
|
||
<VRow v-else>
|
||
<VCol
|
||
v-for="event in topLevelEvents"
|
||
:key="event.id"
|
||
cols="12"
|
||
md="6"
|
||
>
|
||
<VCard
|
||
class="cursor-pointer"
|
||
hover
|
||
@click="navigateToEvent(event)"
|
||
>
|
||
<VCardText>
|
||
<div class="d-flex justify-space-between align-start mb-2">
|
||
<h5 class="text-h5">
|
||
{{ event.name }}
|
||
</h5>
|
||
<div class="d-flex gap-x-2">
|
||
<VChip
|
||
v-if="event.event_type === 'festival'"
|
||
color="purple"
|
||
size="small"
|
||
variant="tonal"
|
||
>
|
||
Festival
|
||
</VChip>
|
||
<VChip
|
||
v-else-if="event.event_type === 'series'"
|
||
color="info"
|
||
size="small"
|
||
variant="tonal"
|
||
>
|
||
Serie
|
||
</VChip>
|
||
<VChip
|
||
:color="statusColor[event.status]"
|
||
size="small"
|
||
>
|
||
{{ event.status }}
|
||
</VChip>
|
||
</div>
|
||
</div>
|
||
|
||
<p class="text-body-2 text-medium-emphasis mb-0">
|
||
{{ formatDate(event.start_date) }} – {{ formatDate(event.end_date) }}
|
||
</p>
|
||
|
||
<p
|
||
v-if="event.children_count && event.children_count > 0"
|
||
class="text-body-2 text-medium-emphasis d-flex align-center gap-x-1 mt-1 mb-0"
|
||
>
|
||
<VIcon
|
||
icon="tabler-layout-grid"
|
||
size="16"
|
||
/>
|
||
{{ event.children_count }} {{ event.sub_event_label ? dutchPlural(event.sub_event_label).toLowerCase() : 'programmaonderdelen' }}
|
||
</p>
|
||
</VCardText>
|
||
</VCard>
|
||
</VCol>
|
||
</VRow>
|
||
|
||
<CreateEventDialog
|
||
v-model="isCreateDialogOpen"
|
||
:org-id="orgId"
|
||
/>
|
||
</template>
|
||
</div>
|
||
</template>
|