feature: announcements and gallery in
This commit is contained in:
parent
8cc72d2722
commit
d2ba8c4727
9 changed files with 202 additions and 61 deletions
|
|
@ -1,42 +1,35 @@
|
||||||
import { PaginatedDocs } from 'payload'
|
|
||||||
import { Parish as ParishType } from '@/payload-types'
|
|
||||||
import { notFound } from 'next/navigation'
|
import { notFound } from 'next/navigation'
|
||||||
import { Parish } from "@/pageComponents/Parish/Parish"
|
import { Parish } from '@/pageComponents/Parish/Parish'
|
||||||
import { stringify } from 'qs-esm'
|
|
||||||
import { fetchEvents } from '@/fetch/events'
|
import { fetchEvents } from '@/fetch/events'
|
||||||
import { fetchWorship } from '@/fetch/worship'
|
import { fetchWorship } from '@/fetch/worship'
|
||||||
|
import { fetchParish } from '@/fetch/parish'
|
||||||
async function fetchParish(slug: string) {
|
import { fetchLastAnnouncement } from '@/fetch/announcement'
|
||||||
const query = {
|
import { transformGallery } from '@/utils/dto/gallery'
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function ParishPage ({ params }: { params: Promise<{slug: string}>}) {
|
export default async function ParishPage ({ params }: { params: Promise<{slug: string}>}) {
|
||||||
|
|
||||||
const slug = (await params).slug;
|
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();
|
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 events = await fetchEvents(id)
|
||||||
const worship = await fetchWorship(churches.map(c => typeof c === "string" ? c : c.id))
|
const worship = await fetchWorship(churches.map(c => typeof c === "string" ? c : c.id))
|
||||||
|
const announcement = await fetchLastAnnouncement(id);
|
||||||
|
console.log(gallery)
|
||||||
return (
|
return (
|
||||||
<Parish
|
<Parish
|
||||||
title={name}
|
title={name}
|
||||||
|
|
@ -48,6 +41,8 @@ export default async function ParishPage ({ params }: { params: Promise<{slug: s
|
||||||
contact={contact}
|
contact={contact}
|
||||||
events={events?.docs || []}
|
events={events?.docs || []}
|
||||||
worship={worship?.docs || []}
|
worship={worship?.docs || []}
|
||||||
|
announcement={announcement && typeof announcement.document === "object" ? announcement.document.url || undefined : undefined}
|
||||||
|
gallery={gallery ? transformGallery(gallery) : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ import { CollectionConfig } from 'payload'
|
||||||
import { isAdminOrEmployee } from '@/collections/access/admin'
|
import { isAdminOrEmployee } from '@/collections/access/admin'
|
||||||
|
|
||||||
export const Announcements: CollectionConfig = {
|
export const Announcements: CollectionConfig = {
|
||||||
slug: 'vermeldungen',
|
slug: 'announcement',
|
||||||
labels: {
|
labels: {
|
||||||
singular: {
|
singular: {
|
||||||
de: 'Vermeldung'
|
de: 'Vermeldung'
|
||||||
|
|
@ -30,9 +30,19 @@ export const Announcements: CollectionConfig = {
|
||||||
de: "Gemeinde"
|
de: "Gemeinde"
|
||||||
},
|
},
|
||||||
admin: {
|
admin: {
|
||||||
allowCreate: false
|
allowCreate: false,
|
||||||
|
allowEdit: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'document',
|
||||||
|
label: {
|
||||||
|
de: "PDF-Dokument"
|
||||||
|
},
|
||||||
|
type: 'upload',
|
||||||
|
relationTo: 'documents',
|
||||||
|
required: true
|
||||||
|
}
|
||||||
],
|
],
|
||||||
access: {
|
access: {
|
||||||
read: () => true,
|
read: () => true,
|
||||||
|
|
|
||||||
|
|
@ -110,10 +110,33 @@ export const Parish: CollectionConfig = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'photo',
|
name: 'photo',
|
||||||
|
label: {
|
||||||
|
de: "Hauptbild"
|
||||||
|
},
|
||||||
type: 'upload',
|
type: 'upload',
|
||||||
relationTo: 'media',
|
relationTo: 'media',
|
||||||
required: true
|
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: {
|
admin: {
|
||||||
useAsTitle: 'name',
|
useAsTitle: 'name',
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ const GalleryItem = ({ thumbnail, alt, onClick }: GalleryItemProps) => {
|
||||||
export const Gallery = ({ items }: GalleryProps) => {
|
export const Gallery = ({ items }: GalleryProps) => {
|
||||||
const [display, setDisplay] = useState(false)
|
const [display, setDisplay] = useState(false)
|
||||||
const [idx, setIdx] = useState(0)
|
const [idx, setIdx] = useState(0)
|
||||||
const { image, alt } = items[idx]
|
|
||||||
const displayImage = useCallback((n: number) => {
|
const displayImage = useCallback((n: number) => {
|
||||||
setIdx(n);
|
setIdx(n);
|
||||||
setDisplay(true);
|
setDisplay(true);
|
||||||
|
|
@ -46,6 +45,11 @@ export const Gallery = ({ items }: GalleryProps) => {
|
||||||
setIdx((idx + 1) % items.length)
|
setIdx((idx + 1) % items.length)
|
||||||
}, [idx, setIdx, items])
|
}, [idx, setIdx, items])
|
||||||
|
|
||||||
|
if(items.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { image, alt } = items[idx]
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
|
|
|
||||||
41
src/fetch/announcement.ts
Normal file
41
src/fetch/announcement.ts
Normal 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
22
src/fetch/parish.ts
Normal 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()
|
||||||
|
}
|
||||||
|
|
@ -11,8 +11,10 @@ import { MarginBottom } from '@/components/Margin/MarbinBottom'
|
||||||
import { ContactPersonList } from '@/components/ContactPerson/ContactPersonList'
|
import { ContactPersonList } from '@/components/ContactPerson/ContactPersonList'
|
||||||
import { Event, Worship } from '@/payload-types'
|
import { Event, Worship } from '@/payload-types'
|
||||||
import { transformEvents } from '@/utils/dto/events'
|
import { transformEvents } from '@/utils/dto/events'
|
||||||
import { ChurchWithContact } from '@/compositions/ChurchWithContact/ChurchWithContact'
|
|
||||||
import { tranformWorship } from '@/utils/dto/worship'
|
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 = {
|
type ParishProps = {
|
||||||
title: string,
|
title: string,
|
||||||
|
|
@ -27,11 +29,28 @@ type ParishProps = {
|
||||||
contact: string
|
contact: string
|
||||||
events: Event[],
|
events: Event[],
|
||||||
worship: Worship[]
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -53,6 +72,12 @@ export const Parish = ({title, slug, image, description, history, contactPersons
|
||||||
<Title title={"Ansprechpersonen"} size={"md"} />
|
<Title title={"Ansprechpersonen"} size={"md"} />
|
||||||
|
|
||||||
<ContactPersonList persons={contactPersons} />
|
<ContactPersonList persons={contactPersons} />
|
||||||
|
|
||||||
|
<Section padding={"small"}>
|
||||||
|
{ announcement &&
|
||||||
|
<Button href={announcement} size={"md"}>Aktuelle Vermeldungen</Button>
|
||||||
|
}
|
||||||
|
</Section>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
@ -65,9 +90,17 @@ export const Parish = ({title, slug, image, description, history, contactPersons
|
||||||
</Container>
|
</Container>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
|
{ gallery && gallery.length > 0 &&
|
||||||
|
<Section>
|
||||||
|
<Gallery items={gallery} />
|
||||||
|
</Section>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
<Section>
|
<Section>
|
||||||
<Container>
|
<Container textAlign={"center"}>
|
||||||
<ChurchWithContact church={title} contact={contact} />
|
<Title title={"Kontakt"} size={"md"} align={"center"} />
|
||||||
|
<TextDiv text={contact} />
|
||||||
</Container>
|
</Container>
|
||||||
</Section>
|
</Section>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export interface Config {
|
||||||
parish: Parish;
|
parish: Parish;
|
||||||
church: Church;
|
church: Church;
|
||||||
worship: Worship;
|
worship: Worship;
|
||||||
vermeldungen: Vermeldungen;
|
announcement: Announcement;
|
||||||
blog: Blog;
|
blog: Blog;
|
||||||
highlight: Highlight;
|
highlight: Highlight;
|
||||||
event: Event;
|
event: Event;
|
||||||
|
|
@ -34,7 +34,7 @@ export interface Config {
|
||||||
parish: ParishSelect<false> | ParishSelect<true>;
|
parish: ParishSelect<false> | ParishSelect<true>;
|
||||||
church: ChurchSelect<false> | ChurchSelect<true>;
|
church: ChurchSelect<false> | ChurchSelect<true>;
|
||||||
worship: WorshipSelect<false> | WorshipSelect<true>;
|
worship: WorshipSelect<false> | WorshipSelect<true>;
|
||||||
vermeldungen: VermeldungenSelect<false> | VermeldungenSelect<true>;
|
announcement: AnnouncementSelect<false> | AnnouncementSelect<true>;
|
||||||
blog: BlogSelect<false> | BlogSelect<true>;
|
blog: BlogSelect<false> | BlogSelect<true>;
|
||||||
highlight: HighlightSelect<false> | HighlightSelect<true>;
|
highlight: HighlightSelect<false> | HighlightSelect<true>;
|
||||||
event: EventSelect<false> | EventSelect<true>;
|
event: EventSelect<false> | EventSelect<true>;
|
||||||
|
|
@ -102,6 +102,12 @@ export interface Parish {
|
||||||
history: string;
|
history: string;
|
||||||
contact: string;
|
contact: string;
|
||||||
photo: string | Media;
|
photo: string | Media;
|
||||||
|
gallery?:
|
||||||
|
| {
|
||||||
|
photo: string | Media;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
|
@ -202,15 +208,35 @@ export interface Worship {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* 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;
|
id: string;
|
||||||
date: string;
|
date: string;
|
||||||
parish: (string | Parish)[];
|
parish: (string | Parish)[];
|
||||||
|
document: string | Document;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: 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
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "blog".
|
* via the `definition` "blog".
|
||||||
|
|
@ -272,25 +298,6 @@ export interface Blog {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: 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
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "highlight".
|
* via the `definition` "highlight".
|
||||||
|
|
@ -459,8 +466,8 @@ export interface PayloadLockedDocument {
|
||||||
value: string | Worship;
|
value: string | Worship;
|
||||||
} | null)
|
} | null)
|
||||||
| ({
|
| ({
|
||||||
relationTo: 'vermeldungen';
|
relationTo: 'announcement';
|
||||||
value: string | Vermeldungen;
|
value: string | Announcement;
|
||||||
} | null)
|
} | null)
|
||||||
| ({
|
| ({
|
||||||
relationTo: 'blog';
|
relationTo: 'blog';
|
||||||
|
|
@ -564,6 +571,12 @@ export interface ParishSelect<T extends boolean = true> {
|
||||||
history?: T;
|
history?: T;
|
||||||
contact?: T;
|
contact?: T;
|
||||||
photo?: T;
|
photo?: T;
|
||||||
|
gallery?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
photo?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
|
@ -595,11 +608,12 @@ export interface WorshipSelect<T extends boolean = true> {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* 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;
|
date?: T;
|
||||||
parish?: T;
|
parish?: T;
|
||||||
|
document?: T;
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ import { Blog } from '@/collections/Blog'
|
||||||
import { Highlight } from '@/collections/Highlight'
|
import { Highlight } from '@/collections/Highlight'
|
||||||
import { Pages } from '@/collections/Pages'
|
import { Pages } from '@/collections/Pages'
|
||||||
import { Documents } from '@/collections/Documents'
|
import { Documents } from '@/collections/Documents'
|
||||||
import { Underdog } from 'next/dist/compiled/@next/font/dist/google'
|
|
||||||
|
|
||||||
const filename = fileURLToPath(import.meta.url)
|
const filename = fileURLToPath(import.meta.url)
|
||||||
const dirname = path.dirname(filename)
|
const dirname = path.dirname(filename)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue