88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import type { JSXConvertersFunction } from '@payloadcms/richtext-lexical/react'
|
|
import { LinkJSXConverter } from '@payloadcms/richtext-lexical/react'
|
|
import type { SerializedLinkNode } from '@payloadcms/richtext-lexical'
|
|
import Image from 'next/image'
|
|
import { Button } from '@/components/Button/Button'
|
|
import { getPhoto } from '@/utils/dto/gallery'
|
|
|
|
type LinkFields = SerializedLinkNode['fields'] & {
|
|
appearance?: 'link' | 'button'
|
|
}
|
|
|
|
// Maps an internal Payload document to its public URL based on collection slug.
|
|
const internalDocToHref = ({ linkNode }: { linkNode: SerializedLinkNode }): string => {
|
|
const { doc } = linkNode.fields
|
|
if (!doc?.value || typeof doc.value !== 'object') return '#'
|
|
|
|
const document = doc.value as Record<string, unknown>
|
|
|
|
switch (doc.relationTo) {
|
|
case 'group':
|
|
return `/gruppe/${document.slug ?? document.id}`
|
|
case 'event':
|
|
return `/veranstaltungen/${document.id}`
|
|
case 'worship':
|
|
return `/gottesdienst/${document.id}`
|
|
case 'pages':
|
|
return `/${document.slug ?? ''}`
|
|
case 'parish':
|
|
return `/gemeinde/${document.slug ?? document.id}`
|
|
case 'blog':
|
|
return `/blog/${document.id}`
|
|
default:
|
|
return '#'
|
|
}
|
|
}
|
|
|
|
const linkConverters = LinkJSXConverter({ internalDocToHref })
|
|
|
|
export const jsxConverters: JSXConvertersFunction = ({ defaultConverters }) => ({
|
|
...defaultConverters,
|
|
...linkConverters,
|
|
// Render uploaded media at the "gallery" size (500px tall, variable width).
|
|
upload: ({ node }) => {
|
|
if (node.relationTo !== 'media' || typeof node.value !== 'object') {
|
|
return null
|
|
}
|
|
|
|
const photo = getPhoto('gallery', node.value)
|
|
if (!photo) return null
|
|
|
|
return (
|
|
<Image
|
|
src={photo.src}
|
|
width={photo.width}
|
|
height={photo.height}
|
|
alt={node.value.alt}
|
|
unoptimized={true}
|
|
/>
|
|
)
|
|
},
|
|
link: (args) => {
|
|
const { node, nodesToJSX } = args
|
|
const fields = node.fields as LinkFields
|
|
|
|
// Normal link → delegate to the internalDocToHref-aware link converter.
|
|
if (fields?.appearance !== 'button') {
|
|
const linkConverter = linkConverters.link
|
|
return typeof linkConverter === 'function' ? linkConverter(args) : linkConverter
|
|
}
|
|
|
|
// Button link → resolve href using internalDocToHref for internal links.
|
|
const href =
|
|
fields.linkType === 'internal'
|
|
? internalDocToHref({ linkNode: node })
|
|
: (fields.url ?? '#')
|
|
|
|
return (
|
|
<Button
|
|
href={href}
|
|
size="md"
|
|
schema="contrast"
|
|
target={fields.newTab ? '_blank' : '_self'}
|
|
>
|
|
{nodesToJSX({ nodes: node.children })}
|
|
</Button>
|
|
)
|
|
},
|
|
})
|