Newer
Older
<ASection :title="t('showTimeslots.title')">
<template #header>
<Popover class="tw-relative">
<!-- TODO: this span is on purpose because headless ui seems to interfere with vue compat -->
<PopoverButton as="span">
<button type="button" class="btn btn-default">
<icon-system-uicons-filter />
{{ t('showTimeslots.filter') }}
</button>
</PopoverButton>
<PopoverPanel
:unmount="false"
class="tw-absolute tw-mt-3 tw-right-0 tw-w-max tw-max-w-sm tw-top-full tw-z-20 tw-bg-white tw-p-6 tw-shadow-lg tw-rounded-lg"
>

Konrad Mohrfeldt
committed
<TimeSlotFilter
v-model:number-of-timeslots="limit"
v-model:start-date="formattedStartDate"
v-model:end-date="formattedEndDate"
/>
</PopoverPanel>
</Popover>
</template>
<div class="aura-table-wrapper">
<table ref="tableEl" class="aura-table">
<thead class="tw-sticky tw-top-0 tw-bg-white">
<tr>
<th>{{ t('emissionTable.title') }}</th>
<th>{{ t('emissionTable.start') }}</th>
<th>{{ t('emissionTable.duration') }}</th>
<th>{{ t('emissionTable.playlist') }}</th>
<th class="tw-text-right">{{ t('emissionTable.actions') }}</th>

Konrad Mohrfeldt
committed
<template v-for="timeslot in result.items" :key="timeslot.id">
<TimeSlotRow class="tw-transition hover:tw-bg-gray-50" :timeslot="timeslot" />
</template>
<template v-if="!hasTimeslots">
<tr>
<td colspan="6">
<p class="tw-text-center tw-p-3 tw-m-0">
{{ t('showTimeslots.noTimeslotsScheduled') }}
</p>
</td>
</tr>
</template>
</tbody>
</table>
<div
class="tw-flex tw-items-center tw-px-6 tw-mt-3 tw-py-3 tw-border-0 tw-border-t tw-border-solid tw-border-gray-200 empty:tw-hidden"
>

Konrad Mohrfeldt
committed
<PaginationRange v-if="result.count > 0" :pagination-data="result" />
<Pagination
v-model="page"
class="tw-ml-auto"

Konrad Mohrfeldt
committed
:items-per-page="result.itemsPerPage"
:count="result.count"
</ASection>
</template>
<script lang="ts" setup>
import { computed, ref, watchEffect } from 'vue'
import { Popover, PopoverPanel, PopoverButton } from '@headlessui/vue'
import { useI18n } from '@/i18n'
import TimeSlotFilter from './TimeSlotFilter.vue'
import TimeSlotRow from '@/components/shows/TimeSlotRow.vue'
import Pagination from '@/components/generic/Pagination.vue'
import PaginationRange from '@/components/generic/PaginationRange.vue'
import ASection from '@/components/generic/ASection.vue'

Konrad Mohrfeldt
committed
import { Show } from '@/types'
import { useTimeSlotStore } from '@/stores/timeslots'
import { usePaginatedList } from '@rokoli/bnb/drf'
import { useFormattedISODate } from '@/util'
import { addDays } from 'date-fns'
const DEFAULT_TIMESLOT_LIMIT = parseInt(import.meta.env.VUE_APP_TIMESLOT_FILTER_DEFAULT_NUMSLOTS)
const DEFAULT_DATE_OFFSET = parseInt(import.meta.env.VUE_APP_TIMESLOT_FILTER_DEFAULT_DAYS)
defineOptions({
compatConfig: { MODE: 3 },
ATTR_FALSE_VALUE: false,
})

Konrad Mohrfeldt
committed
const props = defineProps<{
show: Show
}>()

Konrad Mohrfeldt
committed
const timeslotStore = useTimeSlotStore()

Konrad Mohrfeldt
committed
const limit = ref(DEFAULT_TIMESLOT_LIMIT)
const startDate = ref(new Date())
const formattedStartDate = useFormattedISODate(startDate)
const endDate = ref(addDays(startDate.value, DEFAULT_DATE_OFFSET))
const formattedEndDate = useFormattedISODate(endDate)
const tableEl = ref<HTMLTableElement>()
const hasPageBeenModified = ref(false)

Konrad Mohrfeldt
committed
const query = computed(
() =>
new URLSearchParams({
showIds: props.show.id.toString(),
start: formattedStartDate.value,
end: formattedEndDate.value,

Konrad Mohrfeldt
committed
}),
)
const { result } = usePaginatedList(timeslotStore.listIsolated, page, limit, {
query,
events: timeslotStore.events,
})
const hasTimeslots = computed(() => result.value.count > 0)
watchEffect(() => {
if (page.value !== 1) {
hasPageBeenModified.value = true
}
if (hasPageBeenModified.value && tableEl.value) {
tableEl.value.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' })
}
})
</script>