church-website/src/compositions/Blocks/Blocks.tsx
2026-04-17 09:57:45 +02:00

311 lines
10 KiB
TypeScript

import { Blog, Page } from '@/payload-types'
import { Container } from '@/components/Container/Container'
import { HTMLText } from '@/components/Text/HTMLText'
import { Section } from '@/components/Section/Section'
import { Button } from '@/components/Button/Button'
import { ContactSection } from '@/compositions/ContactSection/ContactSection'
import { Gallery } from '@/components/Gallery/Gallery'
import { transformGallery } from '@/utils/dto/gallery'
import { DonationForm } from '@/components/DonationForm/DonationForm'
import { YoutubePlayer } from '@/components/YoutubePlayer/YoutubePlayer'
import { PageHeader } from '@/compositions/PageHeader/PageHeader'
import { Title } from '@/components/Title/Title'
import { Banner } from '@/components/Banner/Banner'
import { MainText } from '@/components/MainText/MainText'
import { HR } from '@/components/HorizontalRule/HorizontalRule'
import { CollapsibleImageWithText } from '@/compositions/CollapsibleImageWithText/CollapsibleImageWithText'
import { Collapsible } from '@/components/Collapsible/Collapsible'
import { PublicationAndNewsletter } from '@/compositions/PublicationAndNewsletter/PublicationAndNewsletter'
import { ContactPersonCard } from '@/components/ContactPersonCard/ContactPersonCard'
import { getPhoto } from '@/utils/dto/gallery'
import { BlogSliderBlock } from '@/compositions/Blocks/BlogSliderBlock'
import { MassTimesBlock } from '@/compositions/Blocks/MassTimesBlock'
import { EventsBlock } from '@/compositions/Blocks/EventsBlock'
import { ImageCardsBlock } from '@/compositions/Blocks/ImageCardsBlock'
import { ClassifiedsFromApi } from '@/components/Classifieds/ClassifiedsFromApi'
import { NextPrevButtons } from '@/components/NextPrevButtons/NextPrevButtons'
type BlocksProps = {
content: Blog['content']['content'] | NonNullable<Page['content']>
}
export function Blocks({ content }: BlocksProps) {
// determine if some margin at the bottom should be added
const length = content.length;
const shouldAddMargin = content[length - 1].blockType === 'text'
return (
<>
<div>
{content.map(item => {
if (item.blockType === 'text') {
return (
<Container key={item.id}>
<HTMLText width={item.width} data={item.content} />
</Container>
);
}
if (item.blockType === 'document' && typeof item.file === 'object') {
return (
<Container key={item.id}>
<Section padding={'medium'}>
<Button size={'lg'} href={item.file.url || 'notfound'} schema={'contrast'}>{item.button}</Button>
</Section>
</Container>
)
}
if (item.blockType === 'contactform') {
return (
<ContactSection
key={item.id}
title={item.title}
description={item.description}
toEmail={item.email}
backgroundColor={'off-white'}
/>
)
}
if (item.blockType === 'gallery') {
return (
<Section key={item.id}>
<Gallery items={transformGallery(item.items)} />
</Section>
)
}
if (item.blockType === 'donation') {
return <Section key={item.id} padding={'small'} paddingBottom={'large'}>
<DonationForm />
</Section>
}
if (item.blockType === 'youtube') {
return <Section key={item.id} padding={'small'}>
<Container>
<YoutubePlayer id={item.youtube_id} />
</Container>
</Section>
}
if (item.blockType === 'button') {
return <Section key={item.id} padding={'small'}>
<Container>
<Button
size={'lg'}
type={'button'}
href={item.url}
target={'_blank'}
>
{item.text}
</Button>
</Container>
</Section>
}
if (item.blockType === 'pageHeader') {
const imageUrl = typeof item.image === 'object' && item.image?.url
? item.image.url
: undefined
return (
<PageHeader
key={item.id}
title={item.title}
description={item.description}
image={imageUrl}
/>
)
}
if (item.blockType === 'section') {
const bg = item.backgroundColor === 'none'
? undefined
: item.backgroundColor as 'soft' | 'off-white' | undefined
return (
<Section
key={item.id}
backgroundColor={bg}
padding={item.padding as 'small' | 'medium' | 'large' | undefined}
/>
)
}
if (item.blockType === 'title') {
return (
<Container key={item.id}>
<Title
title={item.title}
subtitle={item.subtitle || undefined}
size={item.size as 'xl' | 'lg' | 'md' | 'sm' | undefined}
align={item.align as 'left' | 'center' | undefined}
color={item.color as 'base' | 'shade1' | 'shade2' | 'shade3' | 'contrast' | 'contrastShade1' | undefined}
/>
</Container>
)
}
if (item.blockType === 'banner') {
const bannerImageUrl =
typeof item.backgroundImage === 'object' &&
item.backgroundImage?.url
? item.backgroundImage.url
: undefined
return (
<Banner
key={item.id}
textLine1={item.textLine1}
textLine2={item.textLine2}
textLine3={item.textLine3}
backgroundColor={item.backgroundColor}
backgroundImage={bannerImageUrl}
backgroundPosition={item.backgroundPosition}
backgroundSize={item.backgroundSize}
/>
)
}
if (item.blockType === 'mainText') {
return (
<Container key={item.id}>
<Section>
<MainText text={item.text} />
</Section>
</Container>
)
}
if (item.blockType === 'horizontalRule') {
return <HR key={item.id} color={item.color} />
}
if (item.blockType === 'blogSlider') {
return (
<BlogSliderBlock
key={item.id}
title={item.title}
/>
)
}
if (item.blockType === 'massTimes') {
return (
<MassTimesBlock
key={item.id}
title={item.title}
subtitle={item.subtitle}
churches={item.churches}
/>
)
}
if (item.blockType === 'collapsibleImageWithText') {
const imageUrl = typeof item.image === 'object' && item.image?.url
? item.image.url
: ''
const colorStyle = item.colorStyle || 'default'
const bg = colorStyle === 'soft' || colorStyle === 'off-white'
? colorStyle as 'soft' | 'off-white'
: undefined
const schema = colorStyle === 'contrast'
? 'contrast' as const
: 'base' as const
return (
<CollapsibleImageWithText
key={item.id}
title={item.title}
text={item.text}
image={imageUrl}
backgroundColor={bg}
schema={schema}
content={
item.content
? <HTMLText width={'3/4'} data={item.content} />
: <></>
}
/>
)
}
if (item.blockType === 'collapsibles') {
return (
<Section key={item.id} padding={'small'}>
<Container>
{item.items.map(entry => (
<Collapsible key={entry.id} title={entry.title}>
<HTMLText width={'3/4'} data={entry.content} />
</Collapsible>
))}
</Container>
</Section>
)
}
if (item.blockType === 'events') {
return (
<EventsBlock
key={item.id}
title={item.title}
itemsPerPage={item.itemsPerPage}
/>
)
}
if (item.blockType === 'imageCards') {
return <ImageCardsBlock key={item.id} items={item.items} />
}
if (item.blockType === 'classifieds') {
return (
<Section key={item.id} padding={'small'}>
<Container>
<ClassifiedsFromApi />
</Container>
</Section>
)
}
if (item.blockType === 'nextPrevButtons') {
const prev = item.prev?.href && item.prev?.text
? { href: item.prev.href, text: item.prev.text }
: undefined
const next = item.next?.href && item.next?.text
? { href: item.next.href, text: item.next.text }
: undefined
return (
<Section key={item.id} padding={'small'}>
<NextPrevButtons prev={prev} next={next} />
</Section>
)
}
if (item.blockType === 'contactPersonBlock') {
const contact = typeof item.contact === 'object'
? item.contact
: undefined
const photo = contact
? getPhoto('thumbnail', contact.photo)
: undefined
return (
<Section key={item.id} padding={'small'}>
<Container>
<ContactPersonCard contact={contact} photo={photo} />
</Container>
</Section>
)
}
// if (item.blockType === 'publicationAndNewsletter') {
// return <PublicationAndNewsletter key={item.id} />
// }
})}
</div>
{ shouldAddMargin &&
<Section></Section>
}
</>
)
}