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 { 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}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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
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 { 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>
|
||||
<Container>
|
||||
<ChurchWithContact church={title} contact={contact} />
|
||||
<Gallery items={gallery} />
|
||||
</Section>
|
||||
}
|
||||
|
||||
|
||||
<Section>
|
||||
<Container textAlign={"center"}>
|
||||
<Title title={"Kontakt"} size={"md"} align={"center"} />
|
||||
<TextDiv text={contact} />
|
||||
</Container>
|
||||
</Section>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue