feature: announcements and gallery in

This commit is contained in:
Benno Tielen 2024-11-26 14:00:30 +01:00
parent 8cc72d2722
commit d2ba8c4727
9 changed files with 202 additions and 61 deletions

View file

@ -1,42 +1,35 @@
import { PaginatedDocs } from 'payload'
import { Parish as ParishType } from '@/payload-types'
import { notFound } from 'next/navigation'
import { Parish } from "@/pageComponents/Parish/Parish"
import { stringify } from 'qs-esm'
import { Parish } from '@/pageComponents/Parish/Parish'
import { fetchEvents } from '@/fetch/events'
import { fetchWorship } from '@/fetch/worship'
async function fetchParish(slug: string) {
const query = {
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();
}
import { fetchParish } from '@/fetch/parish'
import { fetchLastAnnouncement } from '@/fetch/announcement'
import { transformGallery } from '@/utils/dto/gallery'
export default async function ParishPage ({ params }: { params: Promise<{slug: string}>}) {
const slug = (await params).slug;
const parish = await fetchParish(slug) as PaginatedDocs<ParishType>
const parish = await fetchParish(slug);
if(!parish.docs[0]) {
if(!parish || !parish.docs[0]) {
notFound();
}
const { id, name, description, history, contactPersons, contact, photo, churches } = parish.docs[0]
const {
id,
name,
description,
history,
contactPersons,
contact,
photo,
churches,
gallery
} = parish.docs[0]
const events = await fetchEvents(id)
const worship = await fetchWorship(churches.map(c => typeof c === "string" ? c : c.id))
const announcement = await fetchLastAnnouncement(id);
console.log(gallery)
return (
<Parish
title={name}
@ -48,6 +41,8 @@ export default async function ParishPage ({ params }: { params: Promise<{slug: s
contact={contact}
events={events?.docs || []}
worship={worship?.docs || []}
announcement={announcement && typeof announcement.document === "object" ? announcement.document.url || undefined : undefined}
gallery={gallery ? transformGallery(gallery) : undefined}
/>
)
}

View file

@ -2,7 +2,7 @@ import { CollectionConfig } from 'payload'
import { isAdminOrEmployee } from '@/collections/access/admin'
export const Announcements: CollectionConfig = {
slug: 'vermeldungen',
slug: 'announcement',
labels: {
singular: {
de: 'Vermeldung'
@ -30,9 +30,19 @@ export const Announcements: CollectionConfig = {
de: "Gemeinde"
},
admin: {
allowCreate: false
allowCreate: false,
allowEdit: false
}
},
{
name: 'document',
label: {
de: "PDF-Dokument"
},
type: 'upload',
relationTo: 'documents',
required: true
}
],
access: {
read: () => true,

View file

@ -110,10 +110,33 @@ export const Parish: CollectionConfig = {
},
{
name: 'photo',
label: {
de: "Hauptbild"
},
type: 'upload',
relationTo: 'media',
required: true
},
{
name: 'gallery',
label: {
de: 'Weitere Bilder'
},
type: 'array',
fields: [
{
name: 'photo',
label: {
de: 'Bild'
},
type: 'upload',
relationTo: 'media',
required: true
},
],
minRows: 3,
maxRows: 12
}
],
admin: {
useAsTitle: 'name',

View file

@ -36,7 +36,6 @@ const GalleryItem = ({ thumbnail, alt, onClick }: GalleryItemProps) => {
export const Gallery = ({ items }: GalleryProps) => {
const [display, setDisplay] = useState(false)
const [idx, setIdx] = useState(0)
const { image, alt } = items[idx]
const displayImage = useCallback((n: number) => {
setIdx(n);
setDisplay(true);
@ -46,6 +45,11 @@ export const Gallery = ({ items }: GalleryProps) => {
setIdx((idx + 1) % items.length)
}, [idx, setIdx, items])
if(items.length == 0) {
return null;
}
const { image, alt } = items[idx]
return (
<>
<div className={styles.container}>

41
src/fetch/announcement.ts Normal file
View file

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

22
src/fetch/parish.ts Normal file
View file

@ -0,0 +1,22 @@
import { stringify } from 'qs-esm'
import { PaginatedDocs } from 'payload'
import { Parish } from '@/payload-types'
export async function fetchParish(slug: string): Promise<PaginatedDocs<Parish> | undefined> {
const query = {
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

@ -11,8 +11,10 @@ import { MarginBottom } from '@/components/Margin/MarbinBottom'
import { ContactPersonList } from '@/components/ContactPerson/ContactPersonList'
import { Event, Worship } from '@/payload-types'
import { transformEvents } from '@/utils/dto/events'
import { ChurchWithContact } from '@/compositions/ChurchWithContact/ChurchWithContact'
import { tranformWorship } from '@/utils/dto/worship'
import { Button } from '@/components/Button/Button'
import { TextDiv } from '@/components/Text/TextDiv'
import { Gallery, GalleryItem } from '@/components/Gallery/Gallery'
type ParishProps = {
title: string,
@ -27,11 +29,28 @@ type ParishProps = {
contact: string
events: Event[],
worship: Worship[]
announcement?: string
gallery?: GalleryItem[]
}
export const Parish = ({title, slug, image, description, history, contactPersons, contact, events, worship}: ParishProps) => {
export const Parish = (
{
title,
slug,
image,
description,
history,
contactPersons,
contact,
events,
worship,
announcement,
gallery
}
: ParishProps
) => {
return (
<>
@ -53,6 +72,12 @@ export const Parish = ({title, slug, image, description, history, contactPersons
<Title title={"Ansprechpersonen"} size={"md"} />
<ContactPersonList persons={contactPersons} />
<Section padding={"small"}>
{ announcement &&
<Button href={announcement} size={"md"}>Aktuelle Vermeldungen</Button>
}
</Section>
</Col>
</Row>
</Container>
@ -65,9 +90,17 @@ export const Parish = ({title, slug, image, description, history, contactPersons
</Container>
</Section>
{ gallery && gallery.length > 0 &&
<Section>
<Gallery items={gallery} />
</Section>
}
<Section>
<Container>
<ChurchWithContact church={title} contact={contact} />
<Container textAlign={"center"}>
<Title title={"Kontakt"} size={"md"} align={"center"} />
<TextDiv text={contact} />
</Container>
</Section>
</>

View file

@ -14,7 +14,7 @@ export interface Config {
parish: Parish;
church: Church;
worship: Worship;
vermeldungen: Vermeldungen;
announcement: Announcement;
blog: Blog;
highlight: Highlight;
event: Event;
@ -34,7 +34,7 @@ export interface Config {
parish: ParishSelect<false> | ParishSelect<true>;
church: ChurchSelect<false> | ChurchSelect<true>;
worship: WorshipSelect<false> | WorshipSelect<true>;
vermeldungen: VermeldungenSelect<false> | VermeldungenSelect<true>;
announcement: AnnouncementSelect<false> | AnnouncementSelect<true>;
blog: BlogSelect<false> | BlogSelect<true>;
highlight: HighlightSelect<false> | HighlightSelect<true>;
event: EventSelect<false> | EventSelect<true>;
@ -102,6 +102,12 @@ export interface Parish {
history: string;
contact: string;
photo: string | Media;
gallery?:
| {
photo: string | Media;
id?: string | null;
}[]
| null;
updatedAt: string;
createdAt: string;
}
@ -202,15 +208,35 @@ export interface Worship {
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "vermeldungen".
* via the `definition` "announcement".
*/
export interface Vermeldungen {
export interface Announcement {
id: string;
date: string;
parish: (string | Parish)[];
document: string | Document;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "documents".
*/
export interface Document {
id: string;
name: string;
updatedAt: string;
createdAt: string;
url?: string | null;
thumbnailURL?: string | null;
filename?: string | null;
mimeType?: string | null;
filesize?: number | null;
width?: number | null;
height?: number | null;
focalX?: number | null;
focalY?: number | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "blog".
@ -272,25 +298,6 @@ export interface Blog {
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "documents".
*/
export interface Document {
id: string;
name: string;
updatedAt: string;
createdAt: string;
url?: string | null;
thumbnailURL?: string | null;
filename?: string | null;
mimeType?: string | null;
filesize?: number | null;
width?: number | null;
height?: number | null;
focalX?: number | null;
focalY?: number | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "highlight".
@ -459,8 +466,8 @@ export interface PayloadLockedDocument {
value: string | Worship;
} | null)
| ({
relationTo: 'vermeldungen';
value: string | Vermeldungen;
relationTo: 'announcement';
value: string | Announcement;
} | null)
| ({
relationTo: 'blog';
@ -564,6 +571,12 @@ export interface ParishSelect<T extends boolean = true> {
history?: T;
contact?: T;
photo?: T;
gallery?:
| T
| {
photo?: T;
id?: T;
};
updatedAt?: T;
createdAt?: T;
}
@ -595,11 +608,12 @@ export interface WorshipSelect<T extends boolean = true> {
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "vermeldungen_select".
* via the `definition` "announcement_select".
*/
export interface VermeldungenSelect<T extends boolean = true> {
export interface AnnouncementSelect<T extends boolean = true> {
date?: T;
parish?: T;
document?: T;
updatedAt?: T;
createdAt?: T;
}

View file

@ -33,7 +33,6 @@ import { Blog } from '@/collections/Blog'
import { Highlight } from '@/collections/Highlight'
import { Pages } from '@/collections/Pages'
import { Documents } from '@/collections/Documents'
import { Underdog } from 'next/dist/compiled/@next/font/dist/google'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)