diff --git a/package.json b/package.json
index 526c98b..06a4e87 100644
--- a/package.json
+++ b/package.json
@@ -26,6 +26,7 @@
"cross-env": "^7.0.3",
"graphql": "^16.8.1",
"mapbox-gl": "^3.5.2",
+ "moment": "^2.30.1",
"next": "15.0.0",
"payload": "^3.3.0",
"qs-esm": "^7.0.2",
diff --git a/src/app/gemeinde/[slug]/page.tsx b/src/app/gemeinde/[slug]/page.tsx
index 6e05c1a..0232c42 100644
--- a/src/app/gemeinde/[slug]/page.tsx
+++ b/src/app/gemeinde/[slug]/page.tsx
@@ -26,8 +26,9 @@ export default async function ParishPage ({ params }: { params: Promise<{slug: s
churches,
gallery
} = parish.docs[0]
- const events = await fetchEvents(id)
- const worship = await fetchWorship(churches.map(c => typeof c === "string" ? c : c.id))
+ const events = await fetchEvents({ parishId: id })
+ const churchIds = churches.map(c => typeof c === "string" ? c : c.id)
+ const worship = await fetchWorship({ locations: churchIds })
const announcement = await fetchLastAnnouncement(id);
return (
+}) {
+
+ const query = await searchParams;
+ let week = query.week;
+ if (!week) {
+ week = weekNumber(moment());
+ }
+
+ const fromDate = moment(week, true);
+
+ if (!fromDate.isValid()) {
+ return
+ }
+
+ const toDate = moment(week).add(1, 'week');
+ const lastWeek = moment(week).subtract(1, 'week');
+
+ const paginatedWorship = await fetchWorship(
+ {
+ fromDate: fromDate.toDate(),
+ tillDate: toDate.toDate()
+ }
+ );
+
+ if (!paginatedWorship) {
+ return ;
+ }
+
+ const events = tranformWorship(paginatedWorship.docs)
+
+ return (
+ <>
+
+
+
+
+
+
+ {events.map(e =>
+
+ )}
+
+ {events.length == 0 &&
+
+ Keine Gottesdienste gefunden
+
+ }
+
+
+
+
+ >
+ )
+}
\ No newline at end of file
diff --git a/src/app/gruppe/[slug]/page.tsx b/src/app/gruppe/[slug]/page.tsx
index e0ff915..5e47c1d 100644
--- a/src/app/gruppe/[slug]/page.tsx
+++ b/src/app/gruppe/[slug]/page.tsx
@@ -28,7 +28,7 @@ export default async function GroupPage({ params }: { params: Promise<{slug: str
const {id, shortDescription, photo,name, text_html, content } = groups.docs[0]
const media = getPhoto("tablet", photo)
- const events = await fetchEvents(undefined, id)
+ const events = await fetchEvents({groupId: id})
return (
<>
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 1af95b4..21e1b97 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -144,7 +144,7 @@ export default function RootLayout({
{
title: "Gottesdienste",
description: "Begegnung mit Gott",
- href: "https://"
+ href: "/gottesdienst"
},
{
title: "Rosenkranz",
@@ -237,6 +237,10 @@ export default function RootLayout({
]
}
},
+ {
+ text: 'Veranstaltungen',
+ href: '/veranstaltungen'
+ },
{
text: 'Kontakt',
href: '/kontakt'
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 326b10f..b431fbf 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -8,7 +8,7 @@ export const dynamic = 'force-dynamic'
export default async function HomePage() {
- const events = await fetchEvents(undefined)
+ const events = await fetchEvents()
const worship = await fetchWorship()
const blog = await fetchBlog()
const highlights = await fetchHighlights()
diff --git a/src/app/veranstaltungen/page.tsx b/src/app/veranstaltungen/page.tsx
new file mode 100644
index 0000000..61d8644
--- /dev/null
+++ b/src/app/veranstaltungen/page.tsx
@@ -0,0 +1,134 @@
+import { fetchEvents } from '@/fetch/events'
+import { PageHeader } from '@/compositions/PageHeader/PageHeader'
+import { Section } from '@/components/Section/Section'
+import { Container } from '@/components/Container/Container'
+import { Title } from '@/components/Title/Title'
+import { NextPrevButtons } from '@/components/NextPrevButtons/NextPrevButtons'
+import moment from 'moment'
+import { transformEvents } from '@/utils/dto/events'
+import { weekNumber } from '@/utils/week'
+import { EventRow } from '@/components/EventRow/EventRow'
+import { fetchHighlightsBetweenDates } from '@/fetch/highlights'
+import { Row } from '@/components/Flex/Row'
+import { Col } from '@/components/Flex/Col'
+import { highlightLink } from '@/utils/dto/highlight'
+import Error from '@/pages/_error'
+
+
+export default async function EventsPage({searchParams}: {
+ searchParams: Promise<{ week: string | undefined }>
+}) {
+
+ const query = await searchParams;
+ const limit = 100;
+ let week = query.week;
+ if (!week) {
+ week = weekNumber(moment());
+ }
+
+ const fromDate = moment(week, true);
+
+ if (!fromDate.isValid()) {
+ return
+ }
+
+ const toDate = moment(week).add(1, 'week');
+ const lastWeek = moment(week).subtract(1, 'week');
+
+ const paginatedEvents = await fetchEvents(
+ {
+ limit: limit,
+ fromDate: fromDate.toDate(),
+ toDate: toDate.toDate()
+ }
+ );
+
+ const paginatedHighlights = ((await fetchHighlightsBetweenDates(
+ fromDate.toDate(),
+ toDate.toDate(),
+ ))?.docs) || [];
+
+ if (!paginatedEvents) {
+ return ;
+ }
+
+ const events = transformEvents(paginatedEvents.docs)
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {events.map(e =>
+
+ )}
+
+ {events.length == 0 &&
+
+ Keine Veranstaltungen gefunden
+
+ }
+
+
+ { paginatedHighlights.length > 0 &&
+ <>
+
+
+ { paginatedHighlights.map(h =>
+
+ )}
+ >
+
+ }
+
+
+
+
+
+
+
+ >
+ )
+}
\ No newline at end of file
diff --git a/src/components/Container/styles.module.scss b/src/components/Container/styles.module.scss
index 4d6e522..4c9a475 100644
--- a/src/components/Container/styles.module.scss
+++ b/src/components/Container/styles.module.scss
@@ -12,7 +12,13 @@ $width: 1100px;
@media screen and (max-width: $width) {
.container {
- padding: 0 20px;
+ padding: 0 40px;
margin: 0;
}
}
+
+@media screen and (max-width: 576px) {
+ .container {
+ padding: 0 20px;
+ }
+}
diff --git a/src/components/EventRow/EventRow.tsx b/src/components/EventRow/EventRow.tsx
index 1453e29..7526b97 100644
--- a/src/components/EventRow/EventRow.tsx
+++ b/src/components/EventRow/EventRow.tsx
@@ -8,6 +8,7 @@ import Link from 'next/link'
export type EventRowProps = {
/** datetime 8601 format */
date: string,
+ showDate?: boolean
title: string,
href?: string,
location?: string,
@@ -41,7 +42,7 @@ const shortMonth = (date: string) => {
-export const EventRow = ({date, title, location, cancelled, href, color = "base"}: EventRowProps) => {
+export const EventRow = ({date, title, location, cancelled, href, color = "base", showDate = true}: EventRowProps) => {
const day = useMemo(() => date.substring(8, 10), [date]);
const dateObj = useMemo(() => new Date(date), [date]);
const month = useMemo(() => shortMonth(date), [date]);
@@ -75,9 +76,13 @@ export const EventRow = ({date, title, location, cancelled, href, color = "base"
[styles.cancelled]: cancelled
})}>
{title}
- {dateObj.toLocaleDateString("de-DE", { weekday: "long" })}
- {dayFormat === "long" && " " + dateObj.toLocaleDateString("de-DE", { dateStyle: "medium" })}, {dateObj.toLocaleTimeString("de-DE", { timeStyle: "short" })} Uhr
-
+ { showDate &&
+ <>
+ {dateObj.toLocaleDateString("de-DE", { weekday: "long" })}
+ {dayFormat === "long" && " " + dateObj.toLocaleDateString("de-DE", { dateStyle: "medium" })}, {dateObj.toLocaleTimeString("de-DE", { timeStyle: "short" })} Uhr
+
+ >
+ }
{location}
diff --git a/src/components/EventRow/styles.module.scss b/src/components/EventRow/styles.module.scss
index 28a80f9..aad0b5a 100644
--- a/src/components/EventRow/styles.module.scss
+++ b/src/components/EventRow/styles.module.scss
@@ -7,6 +7,7 @@
text-align: center;
width: 93px;
transition: color 0.2s ease-in;
+ flex-shrink: 0;
}
.dayBase {
diff --git a/src/components/Flex/styles.module.scss b/src/components/Flex/styles.module.scss
index c51e927..9d319ea 100644
--- a/src/components/Flex/styles.module.scss
+++ b/src/components/Flex/styles.module.scss
@@ -8,6 +8,12 @@
flex: 1 1 0;
}
+@media screen and (max-width: 1024px) {
+ .row {
+ gap: 40px;
+ }
+}
+
@media screen and (max-width: 576px) {
.col {
flex: 0 0 100%;
diff --git a/src/components/Menu/styles.module.scss b/src/components/Menu/styles.module.scss
index 733e45c..a3d84d6 100644
--- a/src/components/Menu/styles.module.scss
+++ b/src/components/Menu/styles.module.scss
@@ -75,7 +75,7 @@
max-height: 1000px;
}
-@media screen and (max-width: 1000px) {
+@media screen and (max-width: 1100px) {
.nav {
flex-direction: column;
padding: 15px 15px;
diff --git a/src/compositions/Footer/Footer.tsx b/src/compositions/Footer/Footer.tsx
index 266d1fe..9b0daf0 100644
--- a/src/compositions/Footer/Footer.tsx
+++ b/src/compositions/Footer/Footer.tsx
@@ -31,7 +31,7 @@ export const Footer = () => {
- Kontakt
- - Gottesdiensten
+ - Gottesdiensten
- Datenschutz
- Schutzkonzept
- Impressum
diff --git a/src/fetch/events.ts b/src/fetch/events.ts
index 9e16984..ca15d17 100644
--- a/src/fetch/events.ts
+++ b/src/fetch/events.ts
@@ -2,23 +2,43 @@ import { stringify } from 'qs-esm'
import { PaginatedDocs } from 'payload'
import { Event } from '@/payload-types'
+type Args = {
+ parishId?: string;
+ groupId?: string;
+ limit?: number;
+ page?: number;
+ fromDate?: Date
+ toDate?: Date
+}
+
+
/**
* Fetch a list of events
*
*/
-export async function fetchEvents(parishId: string | undefined, groupId?: string): Promise | undefined> {
- const date = new Date()
+export async function fetchEvents(args?: Args): Promise | undefined> {
+
+ const {parishId, groupId, limit = 30, page = 0, fromDate = new Date(), toDate} = args || {};
+
const query: any = {
and: [
{
date: {
- greater_than_equal: date.toISOString(),
+ greater_than_equal: fromDate.toISOString(),
},
}
],
}
+ if (toDate) {
+ query.and.push({
+ date: {
+ less_than: toDate.toISOString(),
+ }
+ })
+ }
+
if (parishId) {
query.and.push({
"parish": {
@@ -46,7 +66,9 @@ export async function fetchEvents(parishId: string | undefined, groupId?: string
title: true,
cancelled: true
},
- depth: 1
+ depth: 1,
+ limit,
+ page
},
{ addQueryPrefix: true },
)
diff --git a/src/fetch/highlights.ts b/src/fetch/highlights.ts
index 3bf04c8..53f10b6 100644
--- a/src/fetch/highlights.ts
+++ b/src/fetch/highlights.ts
@@ -28,6 +28,36 @@ export const fetchHighlights = async (): Promise | unde
{ addQueryPrefix: true },
)
+ const response = await fetch(`http://localhost:3000/api/highlight${stringifiedQuery}`)
+ if (!response.ok) return undefined
+ return response.json()
+}
+
+export const fetchHighlightsBetweenDates = async (from: Date, until: Date): Promise | undefined> => {
+ const query: any = {
+ and: [
+ {
+ date: {
+ greater_than_equal: from.toISOString(),
+ }
+ },
+ {
+ date: {
+ less_than: until.toISOString(),
+ }
+ }
+ ],
+ }
+
+ const stringifiedQuery = stringify(
+ {
+ sort: "date",
+ where: query,
+ limit: 5
+ },
+ { addQueryPrefix: true },
+ )
+
const response = await fetch(`http://localhost:3000/api/highlight${stringifiedQuery}`)
if (!response.ok) return undefined
return response.json()
diff --git a/src/fetch/worship.ts b/src/fetch/worship.ts
index ede9a0d..2b131aa 100644
--- a/src/fetch/worship.ts
+++ b/src/fetch/worship.ts
@@ -2,9 +2,22 @@ import { stringify } from 'qs-esm'
import { PaginatedDocs } from 'payload'
import { Worship } from '@/payload-types'
-export const fetchWorship = async (locations?: string[]): Promise | undefined> => {
- const date = new Date();
- date.setHours(0, 0, 0, 0);
+type FetchWorshipArgs = {
+ fromDate?: Date,
+ tillDate?: Date,
+ locations?: string[]
+}
+
+export const fetchWorship = async (args?: FetchWorshipArgs): Promise | undefined> => {
+
+ const {fromDate, tillDate, locations} = args || {}
+
+ let date = fromDate;
+ if (!date) {
+ date = new Date();
+ date.setHours(0, 0, 0, 0);
+ }
+
const query: any = {
and: [
@@ -16,6 +29,14 @@ export const fetchWorship = async (locations?: string[]): Promise
+
+
+
+
+ Fehler {statusCode}
+
+
+
+
+ >
+ )
+}
\ No newline at end of file
diff --git a/src/utils/dto/events.ts b/src/utils/dto/events.ts
index 2fe3e66..7c79792 100644
--- a/src/utils/dto/events.ts
+++ b/src/utils/dto/events.ts
@@ -1,7 +1,15 @@
import { Event } from '@/payload-types'
-import { EventRowProps } from '@/components/EventRow/EventRow'
-export const transformEvents = (events: Event[]): EventRowProps[] => {
+type EventWithId = {
+ id: string,
+ date: string,
+ title: string,
+ href: string,
+ location: string,
+ cancelled: boolean
+}
+
+export const transformEvents = (events: Event[]): EventWithId[] => {
return events.map(e => {
return {
id: e.id,
diff --git a/src/utils/dto/worship.ts b/src/utils/dto/worship.ts
index 6a8eda0..af6f1f2 100644
--- a/src/utils/dto/worship.ts
+++ b/src/utils/dto/worship.ts
@@ -17,7 +17,7 @@ export const transformCategory = (category: "MASS" | "FAMILY" | "WORD"): string
/**
* Transform worship data to `EventRow` component properties
*/
-export const tranformWorship = (worship: Worship[]): EventRowProps[] => {
+export const tranformWorship = (worship: Worship[]): (EventRowProps & {id: string})[] => {
return worship.map(w => {
return {
diff --git a/src/utils/week.ts b/src/utils/week.ts
new file mode 100644
index 0000000..ac8a520
--- /dev/null
+++ b/src/utils/week.ts
@@ -0,0 +1,13 @@
+import moment from 'moment/moment'
+
+/**
+ * Get week number string
+ *
+ * e.G. "2024W05"
+ */
+export const weekNumber = (date: moment.Moment) => {
+ const year = date.isoWeekYear()
+ const weekNr = date.isoWeek()
+ const leadingZero = weekNr < 10 ? '0' : ''
+ return `${year}W${leadingZero}${weekNr}`
+}
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index b28dedc..c80ea98 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7652,6 +7652,7 @@ __metadata:
eslint-plugin-storybook: "npm:^0.8.0"
graphql: "npm:^16.8.1"
mapbox-gl: "npm:^3.5.2"
+ moment: "npm:^2.30.1"
next: "npm:15.0.0"
payload: "npm:^3.3.0"
qs-esm: "npm:^7.0.2"
@@ -12175,6 +12176,13 @@ __metadata:
languageName: node
linkType: hard
+"moment@npm:^2.30.1":
+ version: 2.30.1
+ resolution: "moment@npm:2.30.1"
+ checksum: 10c0/865e4279418c6de666fca7786607705fd0189d8a7b7624e2e56be99290ac846f90878a6f602e34b4e0455c549b85385b1baf9966845962b313699e7cb847543a
+ languageName: node
+ linkType: hard
+
"ms@npm:2.0.0":
version: 2.0.0
resolution: "ms@npm:2.0.0"