149 lines
4.8 KiB
TypeScript
149 lines
4.8 KiB
TypeScript
import moment from 'moment'
|
|
import { fetchUpcomingOccurrences } from '@/fetch/eventOccurrences'
|
|
import { fetchGroup, fetchAllGroups } from '@/fetch/group'
|
|
import { fetchParish, fetchAllParishes } from '@/fetch/parish'
|
|
import { transformOccurrences } from '@/utils/dto/events'
|
|
import { PageHeader } from '@/compositions/PageHeader/PageHeader'
|
|
import { Section } from '@/components/Section/Section'
|
|
import { Container } from '@/components/Container/Container'
|
|
import { EventRow } from '@/components/EventRow/EventRow'
|
|
import { NextPrevButtons } from '@/components/NextPrevButtons/NextPrevButtons'
|
|
import { EventFilterBar } from '@/compositions/EventFilterBar/EventFilterBar'
|
|
import { AdminMenu } from '@/components/AdminMenu/AdminMenu'
|
|
import Error from '@/components/Error/Error'
|
|
import { isAuthenticated } from '@/utils/auth'
|
|
import { Title } from '@/components/Title/Title'
|
|
import { HR } from '@/components/HorizontalRule/HorizontalRule'
|
|
import { P } from '@/components/Text/Paragraph'
|
|
|
|
const DATE_FMT = 'YYYY-MM-DD'
|
|
const PAGE_SIZE = 10
|
|
|
|
type Query = {
|
|
group?: string
|
|
parish?: string
|
|
from?: string
|
|
to?: string
|
|
page?: string
|
|
}
|
|
|
|
const parseDate = (value: string | undefined): Date | undefined => {
|
|
if (!value) return undefined
|
|
const m = moment(value, DATE_FMT, true)
|
|
return m.isValid() ? m.toDate() : undefined
|
|
}
|
|
|
|
const buildHref = (q: Query, page: number): string => {
|
|
const params = new URLSearchParams()
|
|
if (q.group) params.set('group', q.group)
|
|
if (q.parish) params.set('parish', q.parish)
|
|
if (q.from) params.set('from', q.from)
|
|
if (q.to) params.set('to', q.to)
|
|
if (page > 1) params.set('page', String(page))
|
|
const qs = params.toString()
|
|
return qs ? `/veranstaltungen?${qs}` : '/veranstaltungen'
|
|
}
|
|
|
|
export default async function EventsOverviewPage({
|
|
searchParams,
|
|
}: {
|
|
searchParams: Promise<Query>
|
|
}) {
|
|
const authenticated = await isAuthenticated()
|
|
const query = await searchParams
|
|
|
|
const fromDate = parseDate(query.from) ?? moment().startOf('day').toDate()
|
|
const toDate = parseDate(query.to)
|
|
|
|
const parsedPage = parseInt(query.page ?? '1', 10)
|
|
const page = Number.isFinite(parsedPage) && parsedPage > 0 ? parsedPage : 1
|
|
|
|
const [allGroups, allParishes, groupDoc, parishDoc] = await Promise.all([
|
|
fetchAllGroups(),
|
|
fetchAllParishes(),
|
|
query.group ? fetchGroup(query.group) : Promise.resolve(null),
|
|
query.parish ? fetchParish(query.parish) : Promise.resolve(null),
|
|
])
|
|
|
|
const paginated = await fetchUpcomingOccurrences({
|
|
limit: PAGE_SIZE,
|
|
page,
|
|
fromDate,
|
|
toDate,
|
|
groupId: groupDoc?.id,
|
|
parishId: parishDoc?.id,
|
|
})
|
|
|
|
if (!paginated) {
|
|
return <Error statusCode={503} message={'Veranstaltungen konnten nicht geladen werden.'} />
|
|
}
|
|
|
|
const events = transformOccurrences(paginated.docs)
|
|
|
|
const initial = {
|
|
group: groupDoc?.slug ?? undefined,
|
|
parish: parishDoc?.slug ?? undefined,
|
|
from: query.from && parseDate(query.from) ? query.from : undefined,
|
|
to: query.to && parseDate(query.to) ? query.to : undefined,
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Section paddingBottom={"small"}>
|
|
<Container>
|
|
<Title
|
|
title={`Veranstaltungen`}
|
|
size={"lg"}
|
|
color={"contrast"}
|
|
/>
|
|
<P width={"3/4"}>
|
|
Entdecken Sie unsere kommenden Veranstaltungen und seien Sie dabei! Hier finden Sie alle Termine, Informationen und Highlights auf einen Blick.
|
|
</P>
|
|
<EventFilterBar
|
|
groups={allGroups.docs.map((g) => ({ slug: g.slug, name: g.name }))}
|
|
parishes={allParishes.docs.map((p) => ({ slug: p.slug, name: p.name }))}
|
|
initial={initial}
|
|
/>
|
|
</Container>
|
|
<HR />
|
|
</Section>
|
|
|
|
<Section padding={'small'} paddingBottom={'large'}>
|
|
<Container>
|
|
{events.map((e) => (
|
|
<EventRow
|
|
key={e.id}
|
|
date={e.date}
|
|
end={e.end}
|
|
title={e.title}
|
|
href={e.href}
|
|
location={e.location}
|
|
cancelled={e.cancelled}
|
|
/>
|
|
))}
|
|
|
|
{events.length === 0 && <p>Keine Veranstaltungen gefunden</p>}
|
|
</Container>
|
|
</Section>
|
|
|
|
<AdminMenu collection={'event'} isAuthenticated={authenticated} />
|
|
|
|
{(paginated.hasPrevPage || paginated.hasNextPage) && (
|
|
<Section padding={'small'}>
|
|
<NextPrevButtons
|
|
prev={
|
|
paginated.hasPrevPage && paginated.prevPage
|
|
? { href: buildHref(query, paginated.prevPage), text: 'Vorige Seite' }
|
|
: undefined
|
|
}
|
|
next={
|
|
paginated.hasNextPage && paginated.nextPage
|
|
? { href: buildHref(query, paginated.nextPage), text: 'Nächste Seite' }
|
|
: undefined
|
|
}
|
|
/>
|
|
</Section>
|
|
)}
|
|
</>
|
|
)
|
|
}
|