feature: group page

This commit is contained in:
Benno Tielen 2024-12-03 16:24:09 +01:00
parent 388ab0b2e6
commit 9ac5c43e65
10 changed files with 303 additions and 74 deletions

View file

@ -13,6 +13,7 @@ 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 { Blocks } from '@/compositions/Blocks/Blocks'
async function fetchBlog(id: string) {
const res = await fetch(`http://localhost:3000/api/blog/${id}`)
@ -54,50 +55,8 @@ export default async function BlogPage({ params }: { params: Promise<{id: string
</Container>
</Section>
<div>
{data.content.map(item => {
if (item.blockType === "text" && item.content_html) {
return (
<Container key={item.id}>
<HTMLText width={item.width} html={item.content_html} />
</Container>
);
}
<Blocks content={data.content} />
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}
backgroundColor={"off-white"}
/>
)
}
if (item.blockType === "gallery") {
return (
<Section key={item.id}>
<Gallery items={transformGallery(item.items)} />
</Section>
)
}
})}
</div>
{ shouldAddMargin &&
<Section></Section>
}
</>
)
}

View file

@ -1,3 +1,4 @@
import styles from "./styles.module.scss"
import { ImageWithText } from '@/compositions/ImageWithText/ImageWithText'
import { fetchGroup } from '@/fetch/group'
import { notFound } from 'next/navigation'
@ -9,6 +10,10 @@ import { transformEvents } from '@/utils/dto/events'
import { Container } from '@/components/Container/Container'
import { HR } from '@/components/HorizontalRule/HorizontalRule'
import { TextDiv } from '@/components/Text/TextDiv'
import { Col } from '@/components/Flex/Col'
import { Row } from '@/components/Flex/Row'
import { RawHTML } from '@/components/RawHTML/RawHTML'
import { Blocks } from '@/compositions/Blocks/Blocks'
export default async function GroupPage({ params }: { params: Promise<{slug: string}>}) {
@ -19,7 +24,7 @@ export default async function GroupPage({ params }: { params: Promise<{slug: str
notFound();
}
const {id, description, photo,name } = groups.docs[0]
const {id, shortDescription, photo,name, text_html, content } = groups.docs[0]
const media = {
src: typeof photo === "object" && photo ? photo.url || "" : "",
width: typeof photo === "object" && photo ? photo.width || 0 : 0,
@ -35,8 +40,9 @@ export default async function GroupPage({ params }: { params: Promise<{slug: str
<ImageWithText
title={name}
backgroundColor={"soft"}
text={description}
text={shortDescription}
image={media}
schema={"contrast"}
/>
}
@ -46,7 +52,7 @@ export default async function GroupPage({ params }: { params: Promise<{slug: str
<Container>
<Title title={name} />
<strong>
<TextDiv text={description} />
<TextDiv text={shortDescription} />
</strong>
</Container>
@ -56,16 +62,39 @@ export default async function GroupPage({ params }: { params: Promise<{slug: str
}
{ events && events.docs.length > 0 &&
<Section>
<Container>
<Title title={"Veranstaltungen"} size={"md"} />
<Events events={transformEvents(events.docs)} n={3} />
<Row>
<Col>
<div className={styles.content}>
{ text_html &&
<RawHTML html={text_html} />
}
</div>
</Col>
<Col>
{ events && events.docs.length > 0 &&
<>
<Title
title={"Veranstaltungen"}
size={"md"}
color={"contrast"}
/>
<Events
events={transformEvents(events.docs)}
n={3}
schema={"contrast"}
/>
</>
}
</Col>
</Row>
</Container>
<Section></Section>
</Section>
}
{ content && content.length > 0 &&
<Blocks content={content} />
}
</>
)
}

View file

@ -0,0 +1,5 @@
@import "template.scss";
.content h3, .content h4, .content h5, .content h6 {
color: $base-color;
}

View file

@ -57,23 +57,23 @@ export default function RootLayout({
items: [
{
title: "Kathoccino",
description: "Begegnung mit Gott",
description: "Brunchgruppe für Jungerwachsene",
href: "/gruppe/kathocchino"
},
{
title: "Credo & Agape",
description: "Gebet der Meditation",
href: "https://"
description: "Gesprächskreis für Erwachsene ab 45 Jahren",
href: "/gruppe/credo-agape"
},
{
title: "Mädchengruppe",
description: "Stille Begegnung mit Gott",
href: "https://"
description: "Zusammen die Welt entdecken",
href: "/gruppe/maedchen"
},
{
title: "Alphakurs",
description: "Dank, Ehre und Freude",
href: "https://"
description: "Freude am glauben entdecken",
href: "/gruppe/alphakurs"
},
]
},
@ -81,14 +81,14 @@ export default function RootLayout({
title: "Musik",
items: [
{
title: "Little Richards",
description: "Der Hausband von St. Richard",
href: "https://"
title: "Chor St. Clara",
description: "Singen und mitgestalten",
href: "/gruppe/chor-st-clara"
},
{
title: "Kindergruppe",
description: "Jeden Freitag singen und spielen",
href: "https://"
href: "/gruppe/kinder-musik"
}
]
}
@ -154,12 +154,12 @@ export default function RootLayout({
{
title: "Anbetung",
description: "Stille Begegnung mit Gott",
href: "https://"
href: "/gruppe/eucharistische-anbetung"
},
{
title: "Lobpreis",
title: "Holy Hour",
description: "Dank, Ehre und Freude",
href: "https://"
href: "/gruppe/lobpreis"
},
]
}
@ -178,12 +178,12 @@ export default function RootLayout({
title: "Ehrenamt",
items: [
{
href: 'http://',
href: '/gruppe/waermestube',
title: 'Wärmestube',
description: 'Kälteschutz für Bedurftigen',
},
{
href: 'http://',
href: '/gruppe/essen-ist-fertig',
title: 'Essen ist Fertig',
description: 'Essensausgabe Neukölln',
},
@ -195,7 +195,22 @@ export default function RootLayout({
]
},
{
title: "Aktivitaten",
title: "Projekte",
items: [
{
title: "Umgekehrter Advent",
description: "Geben statt nehmen ",
href: "/gruppe/umgekehrter-advent"
},
{
title: "Dicke Linda",
description: "Marktstand auf dem Kranoldplatz",
href: "/gruppe/dicke-linda"
},
]
},
{
title: "Aktivitäten",
items: [
{
title: "Kochen",

View file

@ -1,5 +1,10 @@
import { CollectionConfig } from 'payload'
import { isAdminOrEmployee } from '@/collections/access/admin'
import { ParagraphBlock } from '@/collections/blocks/Paragraph'
import { GalleryBlock } from '@/collections/blocks/Gallery'
import { ContactformBlock } from '@/collections/blocks/Contactform'
import { DocumentBlock } from '@/collections/blocks/Document'
import { lexicalHTML } from '@payloadcms/richtext-lexical'
export const Groups: CollectionConfig = {
slug: 'group',
@ -38,13 +43,32 @@ export const Groups: CollectionConfig = {
unique: true
},
{
name: 'description',
name: 'shortDescription',
type: 'textarea',
label: {
de: 'Umschreibung',
de: 'Kurzumschreibung',
},
required: true,
},
{
name: 'text',
type: 'richText',
label: {
de: 'Umschreibung',
},
required: false,
},
lexicalHTML('text', { name: 'text_html' }),
{
name: 'content',
type: 'blocks',
blocks: [
ParagraphBlock,
GalleryBlock,
DocumentBlock,
ContactformBlock
]
}
],
admin: {
useAsTitle: 'name',

View file

@ -1,9 +1,14 @@
import styles from "./styles.module.scss"
type RawHTMLProps = {
html: string
}
export const RawHTML = ({html}: RawHTMLProps) => {
return (
<div dangerouslySetInnerHTML={{__html: html}}></div>
<div
className={styles.content}
dangerouslySetInnerHTML={{__html: html}}
></div>
)
}

View file

@ -0,0 +1,14 @@
@import "template.scss";
.content a {
color: inherit;
}
.content a:hover {
color: $base-color;
}
.content h3 {
font-size: 33px;
margin: 33px 0 20px 0;
}

View file

@ -0,0 +1,68 @@
import { Blog } 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'
type BlocksProps = {
content: Blog['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" && item.content_html) {
return (
<Container key={item.id}>
<HTMLText width={item.width} html={item.content_html} />
</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}
backgroundColor={"off-white"}
/>
)
}
if (item.blockType === "gallery") {
return (
<Section key={item.id}>
<Gallery items={transformGallery(item.items)} />
</Section>
)
}
})}
</div>
{ shouldAddMargin &&
<Section></Section>
}
</>
)
}

View file

@ -376,7 +376,73 @@ export interface Group {
photo?: (string | null) | Media;
name: string;
slug: string;
description: string;
shortDescription: string;
text?: {
root: {
type: string;
children: {
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
version: number;
};
[k: string]: unknown;
} | null;
text_html?: string | null;
content?:
| (
| {
content: {
root: {
type: string;
children: {
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
version: number;
};
[k: string]: unknown;
};
content_html?: string | null;
width: '1/2' | '3/4';
id?: string | null;
blockName?: string | null;
blockType: 'text';
}
| {
items: {
photo: string | Media;
id?: string | null;
}[];
id?: string | null;
blockName?: string | null;
blockType: 'gallery';
}
| {
file: string | Document;
button: string;
id?: string | null;
blockName?: string | null;
blockType: 'document';
}
| {
title: string;
description: string;
email: string;
id?: string | null;
blockName?: string | null;
blockType: 'contactform';
}
)[]
| null;
updatedAt: string;
createdAt: string;
}
@ -768,7 +834,51 @@ export interface GroupSelect<T extends boolean = true> {
photo?: T;
name?: T;
slug?: T;
description?: T;
shortDescription?: T;
text?: T;
text_html?: T;
content?:
| T
| {
text?:
| T
| {
content?: T;
content_html?: T;
width?: T;
id?: T;
blockName?: T;
};
gallery?:
| T
| {
items?:
| T
| {
photo?: T;
id?: T;
};
id?: T;
blockName?: T;
};
document?:
| T
| {
file?: T;
button?: T;
id?: T;
blockName?: T;
};
contactform?:
| T
| {
title?: T;
description?: T;
email?: T;
id?: T;
blockName?: T;
};
};
updatedAt?: T;
createdAt?: T;
}

View file

@ -14,7 +14,7 @@ export const highlightLink = (highlight: Highlight) => {
case 'worship':
return `/gottesdienst/${highlight.link.value.id}`;
case 'event':
return `/event/${highlight.link.value.id}`;
return `/veranstaltungen/${highlight.link.value.id}`;
case 'blog':
return `/blog/${highlight.link.value.id}`;
default: