Skip to content
Snippets Groups Projects
Commit 15837f1e authored by Konrad Mohrfeldt's avatar Konrad Mohrfeldt :koala:
Browse files

refactor: re-work TimeslotFilter/TimeslotList for new timeslot Pinia store

parent d09585da
No related branches found
No related tags found
No related merge requests found
<template> <template>
<div class="tw-flex tw-gap-6 tw-whitespace-nowrap"> <div class="tw-whitespace-nowrap">
<label class="form-group tw-mb-0"> <FormGroup v-slot="attrs" :label="t('showTimeslots.numberOfSlots')">
<span class="form-label">{{ t('showTimeslots.numberOfSlots') }}</span> <input v-model.number="numberOfTimeslots" type="number" v-bind="attrs" />
<input v-model.number="numberOfTimeslots" type="number" class="form-control" /> </FormGroup>
</label>
<FormGroup v-slot="attrs" :label="t('showTimeslots.from')">
<label class="form-group tw-mb-0"> <input v-model="startDate" type="date" v-bind="attrs" />
<span class="form-label">{{ t('showTimeslots.from') }}</span> </FormGroup>
<input v-model="formattedStartDate" type="date" class="form-control" />
</label> <FormGroup v-slot="attrs" :label="t('showTimeslots.to')">
<input v-model="endDate" type="date" v-bind="attrs" />
<label class="form-group tw-mb-0"> </FormGroup>
<span class="form-label">{{ t('showTimeslots.to') }}</span>
<input v-model="formattedEndDate" type="date" class="form-control" />
</label>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { addDays } from 'date-fns'
import { computed, ref, watch, watchEffect } from 'vue'
import { useStore } from 'vuex'
import { useI18n } from '@/i18n' import { useI18n } from '@/i18n'
import { useSelectedShow } from '@/utilities' import FormGroup from '@/components/generic/FormGroup.vue'
import { useFormattedISODate } from '@/util'
import { PaginationData } from '@/types'
const DEFAULT_DATE_OFFSET = parseInt(import.meta.env.VUE_APP_TIMESLOT_FILTER_DEFAULT_DAYS)
const DEFAULT_TIMESLOT_LIMIT = parseInt(import.meta.env.VUE_APP_TIMESLOT_FILTER_DEFAULT_NUMSLOTS)
type PaginationResponseData = { defineOptions({ compatConfig: { MODE: 3 } })
count: number
next: string | null
previous: string | null
}
const props = defineProps<{ const numberOfTimeslots = defineModel<number>('numberOfTimeslots', { required: true })
modelValue: number const startDate = defineModel<string>('startDate', { required: true })
}>() const endDate = defineModel<string>('endDate', { required: true })
const emit = defineEmits<{
(e: 'update:modelValue', value: number): void
(e: 'paginate', value: PaginationData): void
}>()
const store = useStore()
const { t } = useI18n() const { t } = useI18n()
const selectedShow = useSelectedShow()
const numberOfTimeslots = 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 page = computed({
get: () => props.modelValue,
set: (page: number) => {
emit('update:modelValue', page)
},
})
watch([numberOfTimeslots, startDate, endDate], () => (page.value = 1))
watchEffect(
() => {
store.dispatch('shows/fetchTimeslots', {
id: selectedShow.value.id,
start: formattedStartDate.value,
end: formattedEndDate.value,
limit: numberOfTimeslots.value,
offset: (page.value - 1) * numberOfTimeslots.value,
callback({ data }: { data: PaginationResponseData }) {
emit('paginate', {
count: data.count,
hasNext: data.next !== null,
hasPrevious: data.previous !== null,
itemsPerPage: numberOfTimeslots.value,
itemRange: [
(page.value - 1) * numberOfTimeslots.value + 1,
Math.min(data.count, page.value * numberOfTimeslots.value),
],
page: page.value,
})
},
})
},
{ flush: 'post' },
)
</script>
<script lang="ts">
export default {
compatConfig: {
MODE: 3,
},
}
</script> </script>
...@@ -14,7 +14,11 @@ ...@@ -14,7 +14,11 @@
:unmount="false" :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" 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"
> >
<TimeSlotFilter v-model="page" class="tw-flex-col" @paginate="paginationData = $event" /> <TimeSlotFilter
v-model:number-of-timeslots="limit"
v-model:start-date="formattedStartDate"
v-model:end-date="formattedEndDate"
/>
</PopoverPanel> </PopoverPanel>
</Popover> </Popover>
</template> </template>
...@@ -32,7 +36,7 @@ ...@@ -32,7 +36,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<template v-for="timeslot in timeslots" :key="timeslot.id"> <template v-for="timeslot in result.items" :key="timeslot.id">
<TimeSlotRow class="tw-transition hover:tw-bg-gray-50" :timeslot="timeslot" /> <TimeSlotRow class="tw-transition hover:tw-bg-gray-50" :timeslot="timeslot" />
</template> </template>
<template v-if="!hasTimeslots"> <template v-if="!hasTimeslots">
...@@ -48,15 +52,14 @@ ...@@ -48,15 +52,14 @@
</table> </table>
<div <div
v-if="paginationData"
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" 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"
> >
<PaginationRange v-if="paginationData.count > 0" :pagination-data="paginationData" /> <PaginationRange v-if="result.count > 0" :pagination-data="result" />
<Pagination <Pagination
v-model="page" v-model="page"
class="tw-ml-auto" class="tw-ml-auto"
:items-per-page="paginationData.itemsPerPage" :items-per-page="result.itemsPerPage"
:count="paginationData.count" :count="result.count"
/> />
</div> </div>
</div> </div>
...@@ -65,29 +68,56 @@ ...@@ -65,29 +68,56 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref, watchEffect } from 'vue' import { computed, ref, watchEffect } from 'vue'
import { useStore } from 'vuex'
import { Popover, PopoverPanel, PopoverButton } from '@headlessui/vue' import { Popover, PopoverPanel, PopoverButton } from '@headlessui/vue'
import { useI18n } from '@/i18n' import { useI18n } from '@/i18n'
import TimeSlotFilter from './TimeSlotFilter.vue' import TimeSlotFilter from './TimeSlotFilter.vue'
import TimeSlotRow from '@/components/shows/TimeSlotRow.vue' import TimeSlotRow from '@/components/shows/TimeSlotRow.vue'
import { PaginationData } from '@/types'
import Pagination from '@/components/generic/Pagination.vue' import Pagination from '@/components/generic/Pagination.vue'
import PaginationRange from '@/components/generic/PaginationRange.vue' import PaginationRange from '@/components/generic/PaginationRange.vue'
import ASection from '@/components/generic/ASection.vue' import ASection from '@/components/generic/ASection.vue'
import { Show } from '@/types'
import { useTimeSlotStore } from '@/stores/timeslots'
import { usePaginatedList } from '@rokoli/bnb/drf'
import { useFormattedISODate } from '@/util'
import { addDays } from 'date-fns'
import { useEventListener } from '@vueuse/core'
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({ defineOptions({
compatConfig: { MODE: 3 }, compatConfig: { MODE: 3 },
ATTR_FALSE_VALUE: false, ATTR_FALSE_VALUE: false,
}) })
const props = defineProps<{
show: Show
}>()
const { t } = useI18n() const { t } = useI18n()
const store = useStore() const timeslotStore = useTimeSlotStore()
const page = ref(1) const page = ref(1)
const paginationData = ref<PaginationData>() const limit = ref(DEFAULT_TIMESLOT_LIMIT)
const timeslots = computed(() => store.getters['shows/timeslots']) 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 tableEl = ref<HTMLTableElement>()
const hasPageBeenModified = ref(false) const hasPageBeenModified = ref(false)
const hasTimeslots = computed(() => paginationData.value?.count !== 0) const query = computed(
() =>
new URLSearchParams({
showIds: props.show.id.toString(),
start: formattedStartDate.value,
end: formattedEndDate.value,
}),
)
const { result } = usePaginatedList(timeslotStore.listIsolated, page, limit, {
query,
events: timeslotStore.events,
})
const hasTimeslots = computed(() => result.value.count > 0)
watchEffect(() => { watchEffect(() => {
if (page.value !== 1) { if (page.value !== 1) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment