feat: Local API instead of fetch

This commit is contained in:
Benno Tielen 2026-03-11 11:29:16 +01:00
parent d5eca3f876
commit 267e3f9e05
30 changed files with 473 additions and 862 deletions

2
package-lock.json generated
View file

@ -11,7 +11,7 @@
"dependencies": { "dependencies": {
"@nyariv/sandboxjs": "0.8.28", "@nyariv/sandboxjs": "0.8.28",
"@payloadcms/db-postgres": "^3.74.0", "@payloadcms/db-postgres": "^3.74.0",
"@payloadcms/live-preview-react": "^3.79.0", "@payloadcms/live-preview-react": "^3.74.0",
"@payloadcms/next": "^3.74.0", "@payloadcms/next": "^3.74.0",
"@payloadcms/richtext-lexical": "^3.74.0", "@payloadcms/richtext-lexical": "^3.74.0",
"@payloadcms/storage-gcs": "^3.74.0", "@payloadcms/storage-gcs": "^3.74.0",

View file

@ -20,7 +20,7 @@
"dependencies": { "dependencies": {
"@nyariv/sandboxjs": "0.8.28", "@nyariv/sandboxjs": "0.8.28",
"@payloadcms/db-postgres": "^3.74.0", "@payloadcms/db-postgres": "^3.74.0",
"@payloadcms/live-preview-react": "^3.79.0", "@payloadcms/live-preview-react": "^3.74.0",
"@payloadcms/next": "^3.74.0", "@payloadcms/next": "^3.74.0",
"@payloadcms/richtext-lexical": "^3.74.0", "@payloadcms/richtext-lexical": "^3.74.0",
"@payloadcms/storage-gcs": "^3.74.0", "@payloadcms/storage-gcs": "^3.74.0",
@ -31,7 +31,6 @@
"moment": "^2.30.1", "moment": "^2.30.1",
"next": "15.4.11", "next": "15.4.11",
"payload": "^3.74.0", "payload": "^3.74.0",
"qs-esm": "^7.0.3",
"react": "19.2.4", "react": "19.2.4",
"react-dom": "19.2.4", "react-dom": "19.2.4",
"resend": "^6.9.1", "resend": "^6.9.1",

View file

@ -1,40 +0,0 @@
'use client'
import { useEffect, useState } from 'react'
import moment from 'moment'
import Day from '@/admin/components/calendar/Day'
const Calendar = () => {
const weekNr = moment().isoWeek();
const [week, setWeek] = useState(weekNr.toString())
const [days, setDays] = useState<string[]>([])
// on week change => sey days
useEffect(() => {
const date = moment().isoWeek(Number(week));
const newDays = [];
for(let i=0; i<7; i++) {
let day = date.weekday(i).toISOString();
newDays.push(day)
}
setDays(newDays)
}, [week, setDays])
return (
<div>
<div>
<select value={week} onChange={e => setWeek(e.currentTarget.value)}>
{[...Array(51).keys()].map(i => <option key={i} value={i.toString()}>Woche {i}</option>)}
</select>
</div>
{days.map(day => <Day key={day} date={day} mass={[]} />)}
</div>
)
}
export default Calendar

View file

@ -1,22 +0,0 @@
import { useSyncExternalStore } from 'react'
import { churchStore } from '@/admin/components/calendar/ChurchSelect/churchStore'
type ChurchSelectProps = {
value: string,
className?: string,
onChange: (value: string) => void,
}
export const ChurchSelect = ({value, onChange, className}: ChurchSelectProps) => {
const churches = useSyncExternalStore(churchStore.subscribe, churchStore.getSnapshot)
return (
<select
className={className}
value={value}
onChange={e => onChange(e.target.value)}
>
{churches.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
</select>
)
}

View file

@ -1,42 +0,0 @@
import { fetchChurches } from '@/fetch/churches'
type Church = {
id: string,
name: string
}
let churches: Church[] = [];
const listeners = new Set<() => void>();
/**
* ChurchStore to use with Reacts `useSyncExternalStore`
*/
export const churchStore = {
// fetch all churches from API
async init() {
const data = await fetchChurches();
if (data) {
churches = data.docs.map(c => {
return { id: c.id, name: c.name }
});
emitChange()
}
},
subscribe: (listener: () => void) => {
listeners.add(listener);
return () => listeners.delete(listener);
},
getSnapshot() {
return churches;
}
}
function emitChange() {
for (let listener of listeners) {
listener();
}
}
await churchStore.init();

View file

@ -1,36 +0,0 @@
import { liturgicalDayName } from '@/hooks/liturgicalDayName'
import styles from "./styles.module.scss"
import MassForm from '@/admin/components/calendar/MassForm'
type DayProps = {
date: string,
mass: Mass[]
}
type Mass = {
id: string,
}
export const Day = ({date}: DayProps) => {
const dayName = liturgicalDayName(date)
const dateObj = new Date(date);
return (
<div className={styles.container}>
<div className={styles.day}>
<strong>{dateObj.toLocaleDateString("de-De", {weekday: "long"})}</strong> <br/>
{dayName}
</div>
<div className={styles.date}>
{date.substring(8, 10)}
</div>
<div>
<MassForm />
</div>
</div>
)
}
export default Day

View file

@ -1,54 +0,0 @@
import styles from "./form.module.scss"
import { ChurchSelect } from '@/admin/components/calendar/ChurchSelect/ChurchSelect'
const MassForm = () => {
return (
<div className={styles.container}>
<div className={styles.time}>
<div className={styles.formRow}>
<select name="time" className={styles.select}>
<option>10:00 Uhr</option>
<option>20:00 Uhr</option>
</select>
</div>
<div>
<ChurchSelect
className={styles.select}
value={"23"}
onChange={() => console.log("chage")}
/>
</div>
</div>
<div>
<div className={styles.formRow}>
<input type="radio" id="heilige_messe" name="massType" value="Heilige Messe" required />
<label htmlFor="heilige_messe">Heilige Messe</label>
<input type="radio" id="wort_gottes_feier" name="massType" value="Wort-Gottes-Feier" required />
<label htmlFor="wort_gottes_feier">Wort-Gottes-Feier</label>
<input type="radio" id="familienmesse" name="massType" value="Familienmesse" required />
<label htmlFor="familienmesse">Familienmesse</label>
</div>
<div className={styles.formRow}>
<input type="text" id="title" name="title" placeholder={"Titel"} className={styles.input} required />
</div>
<div className={styles.formRow}>
<input type="text" id="celebrant" name="celebrant" placeholder={"Zelebrant"} className={styles.input}/>
</div>
<div className={styles.formRow}>
<textarea id="description" name="description" placeholder={"Hinweise"} className={styles.input} rows={4}></textarea>
</div>
</div>
<div>
<button>Entfernen</button>
</div>
</div>
)
}
export default MassForm

View file

@ -1,30 +0,0 @@
.container {
display: flex;
}
.time {
width: 130px;
text-align: center;
}
.formRow {
margin-bottom: 5px;
}
.input {
font-size: 12px;
padding: 3px;
width: 350px;
border: 1px solid #ababab;
border-radius: 4px;
}
.select {
font-size: 12px;
padding: 3px;
border: 1px solid #ababab;
border-radius: 4px;
width: 100px;
background-color: #ffffff;
font-family: inherit;
}

View file

@ -1,13 +0,0 @@
.container {
display: flex;
margin-bottom: 20px;
}
.day {
width: 300px;
}
.date {
font-size: 18px;
font-weight: bold;
}

View file

@ -1,40 +0,0 @@
import { Gutter } from '@payloadcms/ui'
import { DefaultTemplate } from '@payloadcms/next/templates'
import { AdminViewProps } from 'payload'
import Calendar from '@/admin/components/calendar/Calendar'
export default function TestPage({
initPageResult,
params,
searchParams,
}: AdminViewProps) {
const {
req: {
user
}
} = initPageResult
if (!user) {
return <p>You must be logged in to view this page.</p>
}
return (
<DefaultTemplate
i18n={initPageResult.req.i18n}
locale={initPageResult.locale}
params={params}
payload={initPageResult.req.payload}
permissions={initPageResult.permissions}
searchParams={searchParams}
user={initPageResult.req.user || undefined}
visibleEntities={initPageResult.visibleEntities}
>
<Gutter>
<h1>Gottesdiensten</h1>
<p>This view uses the Default Template.</p>
<Calendar />
</Gutter>
</DefaultTemplate>
)
}

View file

@ -1,19 +1,19 @@
import { notFound } from 'next/navigation' import { notFound } from 'next/navigation'
import { Worship as WorshipType } from '@/payload-types'
import { Worship } from '@/pageComponents/Worship/Worship' import { Worship } from '@/pageComponents/Worship/Worship'
import { isAuthenticated } from '@/utils/auth' import { isAuthenticated } from '@/utils/auth'
import { AdminMenu } from '@/components/AdminMenu/AdminMenu' import { AdminMenu } from '@/components/AdminMenu/AdminMenu'
import { fetchWorshipById } from '@/fetch/worship'
export default async function WorshipPage({ params }: { params: Promise<{id: string}>}) { export default async function WorshipPage({ params }: { params: Promise<{id: string}>}) {
const id = (await params).id; const id = (await params).id;
const res = await fetch(`http://localhost:3000/api/worship/${id}`); const worship = await fetchWorshipById(id)
if (!res.ok) {
if (!worship) {
notFound() notFound()
} }
const authenticated = await isAuthenticated();
const worship = await res.json() as WorshipType; const authenticated = await isAuthenticated();
return ( return (
<> <>

View file

@ -1,43 +1,20 @@
import { notFound } from 'next/navigation' import { notFound } from 'next/navigation'
import { Event } from '@/payload-types'
import { EventPage } from '@/pageComponents/Event/Event' import { EventPage } from '@/pageComponents/Event/Event'
import { stringify } from 'qs-esm'
import { getPhoto } from '@/utils/dto/gallery' import { getPhoto } from '@/utils/dto/gallery'
import { cookies } from 'next/headers'
import { isAuthenticated } from '@/utils/auth' import { isAuthenticated } from '@/utils/auth'
import { fetchEventById } from '@/fetch/events'
export default async function Page({ params }: { params: Promise<{id: string}>}) { export default async function Page({ params }: { params: Promise<{id: string}>}) {
const id = (await params).id; const id = (await params).id;
const stringifiedQuery = stringify( const event = await fetchEventById(id)
{
select: {
title: true,
date: true,
createdAt: true,
cancelled: true,
isRecurring: true,
location: true,
description: true,
shortDescription: true,
contact: true,
flyer: true,
photo: true,
group: true,
rsvpLink: true
},
},
{ addQueryPrefix: true },
)
const res = await fetch(`http://localhost:3000/api/event/${id}${stringifiedQuery}`);
if (!res.ok) { if (!event) {
notFound() notFound()
} }
const authenticated = await isAuthenticated(); const authenticated = await isAuthenticated();
const event = await res.json() as Event;
const group = Array.isArray(event.group) && event.group.length > 0 && typeof event.group[0] == "object" ? event.group[0].slug : undefined; const group = Array.isArray(event.group) && event.group.length > 0 && typeof event.group[0] == "object" ? event.group[0].slug : undefined;
const photo = getPhoto("tablet", event.photo); const photo = getPhoto("tablet", event.photo);

View file

@ -1,6 +1,6 @@
import { CollectionConfig } from 'payload' import { CollectionConfig } from 'payload'
import { stringify } from 'qs-esm' import { Group, User } from '@/payload-types'
import { Event, Group, User } from '@/payload-types' import { fetchEventById } from '@/fetch/events'
export const Events: CollectionConfig = { export const Events: CollectionConfig = {
slug: 'event', slug: 'event',
@ -198,7 +198,7 @@ export const Events: CollectionConfig = {
return false return false
} }
const event = await fetchEvent(id) const event = await fetchEventById(id)
if (hasGroup(user, event)) { if (hasGroup(user, event)) {
return true return true
} }
@ -235,20 +235,3 @@ const hasGroup = (user: null | User , data: Partial<any> | undefined) => {
}) })
} }
/**
* Fetch event
* @param id
*/
const fetchEvent = async (id: string): Promise<undefined|Event> => {
const stringifiedQuery = stringify(
{
select: {
group: true,
},
},
{ addQueryPrefix: true },
)
const res = await fetch(`http://localhost:3000/api/event/${id}${stringifiedQuery}`);
if (!res.ok) return undefined
return res.json()
}

View file

@ -1,87 +1,75 @@
import { stringify } from 'qs-esm' import { getPayload } from 'payload'
import config from '@/payload.config'
import { Announcement } from '@/payload-types' import { Announcement } from '@/payload-types'
import { PaginatedDocs } from 'payload'
/** /**
* Fetch last announcement for a parish * Fetch last announcement for a parish
*/ */
export const fetchLastAnnouncement = async (parishId: string): Promise<Announcement | undefined> => { export const fetchLastAnnouncement = async (
const date = new Date(); parishId: string,
): Promise<Announcement | undefined> => {
const date = new Date()
date.setDate(date.getDate() - 14) date.setDate(date.getDate() - 14)
const tomorrow = new Date(); const tomorrow = new Date()
tomorrow.setDate(tomorrow.getDate() + 1); tomorrow.setDate(tomorrow.getDate() + 1)
tomorrow.setHours(23,59,59,59); tomorrow.setHours(23, 59, 59, 59)
const query: any = { const payload = await getPayload({ config })
const result = await payload.find({
collection: 'announcement',
sort: '-date',
where: {
and: [ and: [
{ {
parish: { parish: {
equals: parishId equals: parishId,
} },
}, },
{ {
date: { date: {
greater_than_equal: date.toISOString(), greater_than_equal: date.toISOString(),
} },
}, },
{ {
date: { date: {
less_than_equal: tomorrow.toISOString() less_than_equal: tomorrow.toISOString(),
}
}
]
}
const stringifiedQuery = stringify(
{
sort: "-date",
where: query,
limit: 1,
}, },
{ addQueryPrefix: true }, },
) ],
},
const response = await fetch(`http://localhost:3000/api/announcement${stringifiedQuery}`) limit: 1,
if (!response.ok) return undefined })
const announcements = await response.json() as PaginatedDocs<Announcement> return result.docs[0]
return announcements.docs[0]
} }
/** /**
* Fetch the last few announcements * Fetch the last few announcements
*/ */
export const fetchLastAnnouncements = async (): Promise<PaginatedDocs<Announcement> | undefined> => { export const fetchLastAnnouncements = async () => {
const date = new Date(); const date = new Date()
date.setDate(date.getDate() - 14) date.setDate(date.getDate() - 14)
const tomorrow = new Date(); const tomorrow = new Date()
tomorrow.setDate(tomorrow.getDate() + 1); tomorrow.setDate(tomorrow.getDate() + 1)
tomorrow.setHours(23,59,59,59); tomorrow.setHours(23, 59, 59, 59)
const query: any = { const payload = await getPayload({ config })
return payload.find({
collection: 'announcement',
sort: '-date',
where: {
and: [ and: [
{ {
date: { date: {
greater_than_equal: date.toISOString(), greater_than_equal: date.toISOString(),
} },
}, },
{ {
date: { date: {
less_than_equal: tomorrow.toISOString() less_than_equal: tomorrow.toISOString(),
}
}
]
}
const stringifiedQuery = stringify(
{
sort: "-date",
where: query,
limit: 3,
}, },
{ addQueryPrefix: true }, },
) ],
},
const response = await fetch(`http://localhost:3000/api/announcement${stringifiedQuery}`) limit: 3,
if (!response.ok) return undefined })
return await response.json() as PaginatedDocs<Announcement>
} }

View file

@ -1,73 +1,67 @@
import { Blog } from '@/payload-types' import { getPayload } from 'payload'
import { PaginatedDocs } from 'payload' import config from '@/payload.config'
import { stringify } from 'qs-esm'
/** /**
* Fetches blog posts based on given criteria. * Fetches blog posts based on given criteria.
* *
* @param {boolean} displayOnFrontpage - Indicates whether to display posts on the front page. * @param {boolean} displayOnFrontpage - Indicates whether to display posts on the front page.
* @returns {Promise<PaginatedDocs<Blog> | undefined>} - A Promise that resolves to the paginated list of blog posts, or undefined if an error occurs.
*/ */
export const fetchBlogPosts = async (displayOnFrontpage: boolean): Promise<PaginatedDocs<Blog> | undefined> => { export const fetchBlogPosts = async (displayOnFrontpage: boolean) => {
const today = new Date(); const today = new Date()
today.setHours(23, 59); today.setHours(23, 59)
const query: any = const query: any = {
{
sort: "-date",
select: {
title: true,
date: true,
photo: true,
content: displayOnFrontpage ? undefined : true, // hack to fetch content only for the `/blog` page
},
where: {
and: [ and: [
{ {
or: [ or: [
{ {
"configuration.displayFromDate": { 'configuration.displayFromDate': {
equals: null equals: null,
} },
}, },
{ {
"configuration.displayFromDate": { 'configuration.displayFromDate': {
less_than_equal: today.toISOString(), less_than_equal: today.toISOString(),
} },
} },
] ],
}, },
{ {
or: [ or: [
{ {
"configuration.displayTillDate": { 'configuration.displayTillDate': {
equals: null equals: null,
} },
}, },
{ {
"configuration.displayTillDate": { 'configuration.displayTillDate': {
greater_than_equal: today.toISOString(), greater_than_equal: today.toISOString(),
} },
} },
]
}
], ],
}, },
limit: 18 ],
}; }
if (displayOnFrontpage) { if (displayOnFrontpage) {
query.where.and.push({ query.and.push({
"configuration.showOnFrontpage": { 'configuration.showOnFrontpage': {
equals: true equals: true,
}, },
}) })
} }
const stringifiedQuery = stringify(query, {addQueryPrefix: true}) const payload = await getPayload({ config })
return payload.find({
collection: 'blog',
const resp = await fetch(`http://localhost:3000/api/blog${stringifiedQuery}`); sort: '-date',
if (!resp.ok) return undefined; select: {
return resp.json(); title: true,
date: true,
photo: true,
content: displayOnFrontpage ? undefined : true,
},
where: query,
limit: 18,
})
} }

View file

@ -1,89 +1,75 @@
import { stringify } from 'qs-esm' import { getPayload } from 'payload'
import { PaginatedDocs } from 'payload' import config from '@/payload.config'
import { Calendar } from '@/payload-types' import { Calendar } from '@/payload-types'
/** /**
* Fetch last calendar for a parish * Fetch last calendar for a parish
*/ */
export const fetchLastCalendar = async (parishId: string): Promise<Calendar | undefined> => { export const fetchLastCalendar = async (
const date = new Date(); parishId: string,
date.setDate(date.getDate() - 14); ): Promise<Calendar | undefined> => {
const tomorrow = new Date(); const date = new Date()
tomorrow.setDate(tomorrow.getDate() + 1); date.setDate(date.getDate() - 14)
tomorrow.setHours(23,59,59,59); const tomorrow = new Date()
tomorrow.setDate(tomorrow.getDate() + 1)
tomorrow.setHours(23, 59, 59, 59)
const query: any = { const payload = await getPayload({ config })
const result = await payload.find({
collection: 'calendar',
sort: '-date',
where: {
and: [ and: [
{ {
parish: { parish: {
equals: parishId equals: parishId,
} },
}, },
{ {
date: { date: {
greater_than_equal: date.toISOString(), greater_than_equal: date.toISOString(),
} },
}, },
{ {
date: { date: {
less_than_equal: tomorrow.toISOString() less_than_equal: tomorrow.toISOString(),
}
}
]
}
const stringifiedQuery = stringify(
{
sort: "-date",
where: query,
limit: 1,
}, },
{ addQueryPrefix: true }, },
) ],
},
const response = await fetch(`http://localhost:3000/api/calendar${stringifiedQuery}`) limit: 1,
if (!response.ok) return undefined })
const announcements = await response.json() as PaginatedDocs<Calendar> return result.docs[0]
return announcements.docs[0]
} }
/** /**
* Fetch last calendars * Fetch last calendars
*/ */
export const fetchLastCalendars = async (): Promise<PaginatedDocs<Calendar> | undefined> => { export const fetchLastCalendars = async () => {
const date = new Date(); const date = new Date()
date.setDate(date.getDate() - 14); date.setDate(date.getDate() - 14)
const tomorrow = new Date(); const tomorrow = new Date()
tomorrow.setDate(tomorrow.getDate() + 1); tomorrow.setDate(tomorrow.getDate() + 1)
tomorrow.setHours(23,59,59,59); tomorrow.setHours(23, 59, 59, 59)
const query: any = { const payload = await getPayload({ config })
return payload.find({
collection: 'calendar',
sort: '-date',
where: {
and: [ and: [
{ {
date: { date: {
greater_than_equal: date.toISOString(), greater_than_equal: date.toISOString(),
} },
}, },
{ {
date: { date: {
less_than_equal: tomorrow.toISOString() less_than_equal: tomorrow.toISOString(),
}
}
]
}
const stringifiedQuery = stringify(
{
sort: "-date",
where: query,
limit: 3,
}, },
{ addQueryPrefix: true }, },
) ],
},
const response = await fetch(`http://localhost:3000/api/calendar${stringifiedQuery}`) limit: 3,
if (!response.ok) return undefined })
return await response.json() as PaginatedDocs<Calendar>
} }

View file

@ -1,17 +0,0 @@
import { Church } from '@/payload-types'
import { PaginatedDocs } from 'payload'
import { stringify } from 'qs-esm'
export const fetchChurches = async (): Promise<PaginatedDocs<Church> | undefined> => {
const stringifiedQuery = stringify(
{
sort: "name",
limit: 50
},
{ addQueryPrefix: true },
)
const resp = await fetch(`http://localhost:3000/api/church`);
if (!resp.ok) return undefined;
return resp.json();
}

View file

@ -1,27 +1,19 @@
import { PaginatedDocs } from 'payload' import { getPayload } from 'payload'
import { Classified } from '@/payload-types' import config from '@/payload.config'
import { stringify } from 'qs-esm'
export const fetchClassifieds = async (): Promise<PaginatedDocs<Classified> | undefined> => { export const fetchClassifieds = async () => {
const date = new Date(); const date = new Date()
date.setHours(0, 0, 0, 0); date.setHours(0, 0, 0, 0)
const query = { const payload = await getPayload({ config })
return payload.find({
collection: 'classifieds',
sort: 'date',
where: {
until: { until: {
greater_than_equal: date.toISOString(), greater_than_equal: date.toISOString(),
}
}
const stringifiedQuery = stringify(
{
sort: "date",
where: query,
limit: 50
}, },
{ addQueryPrefix: true }, },
) limit: 50,
})
const response = await fetch(`http://localhost:3000/api/classifieds${stringifiedQuery}`)
if (!response.ok) return undefined
return response.json()
} }

View file

@ -1,13 +1,13 @@
import { unstable_cache } from 'next/cache'
import { getPayload } from 'payload'
import config from '@/payload.config'
import { Menu } from '@/payload-types' import { Menu } from '@/payload-types'
export const fetchMenu = async (): Promise<Menu> => { export const fetchMenu = unstable_cache(
const rep = await fetch( async (): Promise<Menu> => {
"http://localhost:3000/api/globals/menu", const payload = await getPayload({ config })
{ next: { tags: ['menu'] } } // cache fetch result return payload.findGlobal({ slug: 'menu' })
); },
['menu'],
if (!rep.ok) { { tags: ['menu'] },
throw new Error("Could not fetch menu") )
}
return await rep.json()
}

View file

@ -1,21 +1,17 @@
import { getPayload } from 'payload'
import config from '@/payload.config'
import { DonationForm } from '@/payload-types' import { DonationForm } from '@/payload-types'
export async function fetchDonationForm(id: string): Promise<DonationForm | undefined> { export async function fetchDonationForm(
// const query = { id: string,
// id: { ): Promise<DonationForm | undefined> {
// equals: id, try {
// }, const payload = await getPayload({ config })
// } return await payload.findByID({
// collection: 'donation-form',
// const stringifiedQuery = stringify( id,
// { })
// where: query, } catch {
// }, return undefined
// { addQueryPrefix: true }, }
// )
const res = await fetch(`http://localhost:3000/api/donation-form/${id}`);
if (!res.ok) return undefined
const response = await res.json() as DonationForm;
return response
} }

View file

@ -1,25 +1,30 @@
import { stringify } from 'qs-esm' import { getPayload, PaginatedDocs } from 'payload'
import { PaginatedDocs } from 'payload' import config from '@/payload.config'
import { Event } from '@/payload-types' import { Event } from '@/payload-types'
type Args = { type Args = {
parishId?: string; parishId?: string
groupId?: string; groupId?: string
limit?: number; limit?: number
page?: number; page?: number
fromDate?: Date fromDate?: Date
toDate?: Date toDate?: Date
} }
/** /**
* Fetch a list of events * Fetch a list of events
*
*/ */
export async function fetchEvents(args?: Args): Promise<PaginatedDocs<Event> | undefined> { export async function fetchEvents(
args?: Args,
const {parishId, groupId, limit = 30, page = 0, fromDate = new Date(), toDate} = args || {}; ): Promise<PaginatedDocs<Event>> {
const {
parishId,
groupId,
limit = 30,
page = 0,
fromDate = new Date(),
toDate,
} = args || {}
const query: any = { const query: any = {
and: [ and: [
@ -27,7 +32,7 @@ export async function fetchEvents(args?: Args): Promise<PaginatedDocs<Event> | u
date: { date: {
greater_than_equal: fromDate.toISOString(), greater_than_equal: fromDate.toISOString(),
}, },
} },
], ],
} }
@ -35,45 +40,53 @@ export async function fetchEvents(args?: Args): Promise<PaginatedDocs<Event> | u
query.and.push({ query.and.push({
date: { date: {
less_than: toDate.toISOString(), less_than: toDate.toISOString(),
} },
}) })
} }
if (parishId) { if (parishId) {
query.and.push({ query.and.push({
"parish": { parish: {
equals: parishId equals: parishId,
}, },
}) })
} }
if (groupId) { if (groupId) {
query.and.push({ query.and.push({
"group": { group: {
equals: groupId equals: groupId,
} },
}) })
} }
const payload = await getPayload({ config })
const stringifiedQuery = stringify( return payload.find({
{ collection: 'event',
sort: "date", sort: 'date',
where: query, where: query,
select: { select: {
location: true, location: true,
date: true, date: true,
title: true, title: true,
cancelled: true cancelled: true,
}, },
depth: 1, depth: 1,
limit, limit,
page page,
}, }) as Promise<PaginatedDocs<Event>>
{ addQueryPrefix: true }, }
)
/**
const response = await fetch(`http://localhost:3000/api/event${stringifiedQuery}`) * Fetch a single event by ID
if (!response.ok) return undefined */
return response.json() export async function fetchEventById(
id: string,
): Promise<Event | undefined> {
try {
const payload = await getPayload({ config })
return await payload.findByID({ collection: 'event', id })
} catch {
return undefined
}
} }

View file

@ -1,13 +1,13 @@
import { unstable_cache } from 'next/cache'
import { getPayload } from 'payload'
import config from '@/payload.config'
import { Footer } from '@/payload-types' import { Footer } from '@/payload-types'
export async function fetchFooter(): Promise<Footer> { export const fetchFooter = unstable_cache(
const res = await fetch('http://localhost:3000/api/globals/footer', { async (): Promise<Footer> => {
next: { tags: ['footer'] }, const payload = await getPayload({ config })
}) return payload.findGlobal({ slug: 'footer' })
},
if (!res.ok) { ['footer'],
throw new Error('Could not fetch footer') { tags: ['footer'] },
} )
return res.json()
}

View file

@ -1,22 +1,14 @@
import { stringify } from 'qs-esm' import { getPayload } from 'payload'
import { PaginatedDocs } from 'payload' import config from '@/payload.config'
import { Group } from '@/payload-types'
export async function fetchGroup(slug: string): Promise<PaginatedDocs<Group> | undefined> { export async function fetchGroup(slug: string) {
const query = { const payload = await getPayload({ config })
return payload.find({
collection: 'group',
where: {
slug: { slug: {
equals: slug, equals: slug,
}, },
}
const stringifiedQuery = stringify(
{
where: query,
}, },
{ addQueryPrefix: true }, })
)
const res = await fetch(`http://localhost:3000/api/group${stringifiedQuery}`)
if (!res.ok) return undefined
return res.json()
} }

View file

@ -1,12 +1,15 @@
import { stringify } from 'qs-esm' import { getPayload } from 'payload'
import { PaginatedDocs } from 'payload' import config from '@/payload.config'
import { Highlight } from '@/payload-types'
export const fetchHighlights = async (): Promise<PaginatedDocs<Highlight> | undefined> => { export const fetchHighlights = async () => {
const date = new Date(); const date = new Date()
date.setHours(0, 0, 0, 0); date.setHours(0, 0, 0, 0)
const query: any = { const payload = await getPayload({ config })
return payload.find({
collection: 'highlight',
sort: 'date',
where: {
and: [ and: [
{ {
from: { from: {
@ -14,51 +17,36 @@ export const fetchHighlights = async (): Promise<PaginatedDocs<Highlight> | unde
}, },
until: { until: {
greater_than_equal: date.toISOString(), greater_than_equal: date.toISOString(),
}
}
],
}
const stringifiedQuery = stringify(
{
sort: "date",
where: query,
limit: 3
}, },
{ addQueryPrefix: true }, },
) ],
},
const response = await fetch(`http://localhost:3000/api/highlight${stringifiedQuery}`) limit: 3,
if (!response.ok) return undefined })
return response.json()
} }
export const fetchHighlightsBetweenDates = async (from: Date, until: Date): Promise<PaginatedDocs<Highlight> | undefined> => { export const fetchHighlightsBetweenDates = async (
const query: any = { from: Date,
until: Date,
) => {
const payload = await getPayload({ config })
return payload.find({
collection: 'highlight',
sort: 'date',
where: {
and: [ and: [
{ {
date: { date: {
greater_than_equal: from.toISOString(), greater_than_equal: from.toISOString(),
} },
}, },
{ {
date: { date: {
less_than: until.toISOString(), 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}`) limit: 5,
if (!response.ok) return undefined })
return response.json()
} }

View file

@ -1,27 +1,20 @@
import { stringify } from 'qs-esm' import { getPayload } from 'payload'
import { PaginatedDocs } from 'payload' import config from '@/payload.config'
import { Magazine } from '@/payload-types' import { Magazine } from '@/payload-types'
/** /**
* Asynchronously fetches the last magazine entry from the specified API endpoint. * Asynchronously fetches the last magazine entry.
* *
* This function sends a request to the specified API endpoint to fetch the last magazine based on the given sorting criteria. * @returns {Promise<Magazine | undefined>} The last magazine entry if successful, or undefined.
*
* @returns {Promise<Magazine | undefined>} A Promise that resolves to the last fetched magazine entry if successful, or undefined if an error occurs.
*/ */
export const fetchLastMagazine = async (): Promise<Magazine | undefined> => { export const fetchLastMagazine = async (): Promise<
Magazine | undefined
const stringifiedQuery = stringify( > => {
{ const payload = await getPayload({ config })
sort: "-date", const result = await payload.find({
collection: 'magazine',
sort: '-date',
limit: 1, limit: 1,
}, })
{ addQueryPrefix: true }, return result.docs[0]
)
const response = await fetch(`http://localhost:3000/api/magazine${stringifiedQuery}`)
if (!response.ok) return undefined
const announcements = await response.json() as PaginatedDocs<Magazine>
return announcements.docs[0]
} }

View file

@ -1,25 +1,26 @@
import { unstable_cache } from 'next/cache'
import { getPayload } from 'payload'
import config from '@/payload.config'
import { Page } from '@/payload-types' import { Page } from '@/payload-types'
import { stringify } from 'qs-esm'
export async function fetchPageBySlug( export async function fetchPageBySlug(
slug: string, slug: string,
): Promise<Page | undefined> { ): Promise<Page | undefined> {
const query = stringify( return unstable_cache(
{ async () => {
const payload = await getPayload({ config })
const data = await payload.find({
collection: 'pages',
where: { where: {
slug: { slug: {
equals: slug, equals: slug,
}, },
}, },
limit: 1, limit: 1,
},
{ addQueryPrefix: true },
)
const res = await fetch(`http://localhost:3000/api/pages${query}`, {
next: { tags: ['pages', `pages-${slug}`] },
}) })
if (!res.ok) return undefined return data.docs?.[0] ?? undefined
const data = await res.json() },
return data.docs?.[0] ['pages', slug],
{ tags: ['pages', `pages-${slug}`] },
)()
} }

View file

@ -1,22 +1,14 @@
import { stringify } from 'qs-esm' import { getPayload } from 'payload'
import { PaginatedDocs } from 'payload' import config from '@/payload.config'
import { Parish } from '@/payload-types'
export async function fetchParish(slug: string): Promise<PaginatedDocs<Parish> | undefined> { export async function fetchParish(slug: string) {
const query = { const payload = await getPayload({ config })
return payload.find({
collection: 'parish',
where: {
slug: { slug: {
equals: slug, equals: slug,
}, },
}
const stringifiedQuery = stringify(
{
where: query,
}, },
{ addQueryPrefix: true }, })
)
const res = await fetch(`http://localhost:3000/api/parish${stringifiedQuery}`)
if (!res.ok) return undefined
return res.json()
} }

View file

@ -1,4 +1,5 @@
import { stringify } from 'qs-esm' import { getPayload } from 'payload'
import config from '@/payload.config'
import { PopePrayerIntention } from '@/payload-types' import { PopePrayerIntention } from '@/payload-types'
/** /**
@ -7,30 +8,26 @@ import { PopePrayerIntention } from '@/payload-types'
* @param year * @param year
* @param month - in the form of '01' for january, '02' for february ... * @param month - in the form of '01' for january, '02' for february ...
*/ */
export const fetchPopePrayerIntentions = async (year: number, month: string): Promise<PopePrayerIntention | undefined> => { export const fetchPopePrayerIntentions = async (
const query: any = { year: number,
month: string,
): Promise<PopePrayerIntention | undefined> => {
const payload = await getPayload({ config })
const result = await payload.find({
collection: 'popePrayerIntentions',
where: {
and: [ and: [
{ {
month: { month: {
equals: month, equals: month,
}, },
year: { year: {
equals: year equals: year,
}
}
],
}
const stringifiedQuery = stringify(
{
where: query,
limit: 1
}, },
{ addQueryPrefix: true }, },
) ],
},
const response = await fetch(`http://localhost:3000/api/popePrayerIntentions${stringifiedQuery}`) limit: 1,
if (!response.ok) return undefined })
let data = await response.json() return result.docs[0]
return data.docs[0]
} }

View file

@ -1,11 +1,16 @@
import { Prayer } from '@/payload-types' import { unstable_cache } from 'next/cache'
import { getPayload } from 'payload'
import config from '@/payload.config'
export async function fetchPrayers(): Promise<string[]> { export const fetchPrayers = unstable_cache(
const res = await fetch( async (): Promise<string[]> => {
'http://localhost:3000/api/prayers?limit=0', const payload = await getPayload({ config })
{ next: { tags: ['prayers'] } }, const data = await payload.find({
collection: 'prayers',
limit: 0,
})
return data.docs.map((p) => p.text)
},
['prayers'],
{ tags: ['prayers'] },
) )
if (!res.ok) return []
const data = await res.json()
return (data.docs as Prayer[]).map((p) => p.text)
}

View file

@ -1,53 +1,54 @@
import { stringify } from 'qs-esm' import { getPayload, PaginatedDocs } from 'payload'
import { PaginatedDocs } from 'payload' import config from '@/payload.config'
import { Worship } from '@/payload-types' import { Worship } from '@/payload-types'
type FetchWorshipArgs = { type FetchWorshipArgs = {
fromDate?: Date, fromDate?: Date
tillDate?: Date, tillDate?: Date
locations?: string[] locations?: string[]
} }
export const fetchWorship = async (args?: FetchWorshipArgs): Promise<PaginatedDocs<Worship> | undefined> => { export const fetchWorship = async (
args?: FetchWorshipArgs,
): Promise<PaginatedDocs<Worship>> => {
const { fromDate, tillDate, locations } = args || {} const { fromDate, tillDate, locations } = args || {}
let date = fromDate; let date = fromDate
if (!date) { if (!date) {
date = new Date(); date = new Date()
date.setHours(0, 0, 0, 0); date.setHours(0, 0, 0, 0)
} }
const query: any = { const query: any = {
and: [ and: [
{ {
date: { date: {
greater_than_equal: date.toISOString(), greater_than_equal: date.toISOString(),
}, },
} },
], ],
} }
if (tillDate) { if (tillDate) {
query.and.push({ query.and.push({
date: { date: {
less_than: tillDate.toISOString() less_than: tillDate.toISOString(),
} },
}) })
} }
if (locations) { if (locations) {
query.and.push({ query.and.push({
location: { location: {
in: locations in: locations,
} },
}) })
} }
const stringifiedQuery = stringify( const payload = await getPayload({ config })
{ return payload.find({
sort: "date", collection: 'worship',
sort: 'date',
where: query, where: query,
select: { select: {
type: true, type: true,
@ -56,12 +57,20 @@ export const fetchWorship = async (args?: FetchWorshipArgs): Promise<PaginatedDo
location: true, location: true,
title: true, title: true,
}, },
limit: 15 limit: 15,
}, }) as Promise<PaginatedDocs<Worship>>
{ addQueryPrefix: true }, }
)
/**
const response = await fetch(`http://localhost:3000/api/worship${stringifiedQuery}`) * Fetch a single worship entry by ID
if (!response.ok) return undefined */
return response.json() export async function fetchWorshipById(
id: string,
): Promise<Worship | undefined> {
try {
const payload = await getPayload({ config })
return await payload.findByID({ collection: 'worship', id })
} catch {
return undefined
}
} }