diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index daa264b..799ce69 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -19,6 +19,9 @@ const preview: Preview = { }, ], parameters: { + nextjs: { + appDirectory: true, + }, controls: { matchers: { color: /(background|color)$/i, diff --git a/next.config.mjs b/next.config.mjs index 4942e4a..6bfa9db 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -4,9 +4,6 @@ import { withPayload } from '@payloadcms/next/withPayload' const nextConfig = { // Your Next.js config here output: 'standalone', - eslint: { - ignoreDuringBuilds: true, - }, images: { remotePatterns: [ { diff --git a/src/app/(home)/old/home2/page.tsx b/src/app/(home)/old/home2/page.tsx index 8f43789..db20949 100644 --- a/src/app/(home)/old/home2/page.tsx +++ b/src/app/(home)/old/home2/page.tsx @@ -1,40 +1,7 @@ -import { fetchEvents } from '@/fetch/events' -import { fetchWorship } from '@/fetch/worship' -import { fetchBlogPosts } from '@/fetch/blog' -import { fetchHighlights } from '@/fetch/highlights' import { Home } from '@/pageComponents/Home/Home' -import moment from 'moment' -import { fetchLastAnnouncement, fetchLastAnnouncements } from '@/fetch/announcement' -import { perParish } from '@/utils/dto/perParish' -import { fetchLastCalendars } from '@/fetch/calendar' export const dynamic = 'force-dynamic' export default async function HomePage() { - - const fromDate = moment().isoWeekday(1).hours(0).minutes(0); - const tillDate = moment().isoWeekday(7).hours(23).minutes(59); - const events = await fetchEvents() - const worship = await fetchWorship({ - fromDate: fromDate.toDate(), - tillDate: tillDate.toDate(), - }); - const blog = await fetchBlogPosts(true) - const highlights = await fetchHighlights() - const announcements = await fetchLastAnnouncements(); - const announcementsLinks = announcements ? perParish(announcements) : []; - const calendars = await fetchLastCalendars(); - const calendarsLinks = calendars ? perParish(calendars) : []; - - - return ( - - ) + return } diff --git a/src/components/Classifieds/Ad.stories.tsx b/src/components/Classifieds/Ad.stories.tsx index 4c2065c..e2051d7 100644 --- a/src/components/Classifieds/Ad.stories.tsx +++ b/src/components/Classifieds/Ad.stories.tsx @@ -40,7 +40,7 @@ const makeAdText = (text: string): SerializedEditorState => }, ], }, - }) as SerializedEditorState + }) as unknown as SerializedEditorState export const Default: Story = { args: { diff --git a/src/components/Classifieds/Classifieds.stories.tsx b/src/components/Classifieds/Classifieds.stories.tsx index 4250b87..8841df8 100644 --- a/src/components/Classifieds/Classifieds.stories.tsx +++ b/src/components/Classifieds/Classifieds.stories.tsx @@ -40,7 +40,7 @@ const makeAdText = (text: string): SerializedEditorState => }, ], }, - }) as SerializedEditorState + }) as unknown as SerializedEditorState export const Default: Story = { args: { diff --git a/src/components/Text/HTMLText.stories.tsx b/src/components/Text/HTMLText.stories.tsx index 37f30d7..250f7d5 100644 --- a/src/components/Text/HTMLText.stories.tsx +++ b/src/components/Text/HTMLText.stories.tsx @@ -39,7 +39,7 @@ const sampleState: SerializedEditorState = { }, ], }, -} as SerializedEditorState +} as unknown as SerializedEditorState export const ThreeFourth: Story = { args: { diff --git a/src/compositions/ContactForm/ContactForm.stories.tsx b/src/compositions/ContactForm/ContactForm.stories.tsx index 0d1b0e4..e9386ba 100644 --- a/src/compositions/ContactForm/ContactForm.stories.tsx +++ b/src/compositions/ContactForm/ContactForm.stories.tsx @@ -1,23 +1,28 @@ import { Meta, StoryObj } from '@storybook/nextjs-vite' -import { ContactForm } from './ContactForm' +import { ContactFormView, ContactFormState } from './ContactFormView' -const meta: Meta = { - component: ContactForm, +const noopAction = async (): Promise => ({ + message: 'Storybook: form submission is a no-op.', +}) + +const meta: Meta = { + component: ContactFormView, + args: { + action: noopAction, + }, } -type Story = StoryObj; +type Story = StoryObj export default meta export const Default: Story = { args: { schema: 'base', - toEmail: 'test@test.com' }, } export const Schema: Story = { args: { schema: 'contrast', - toEmail: 'test@test.com' - } -} \ No newline at end of file + }, +} diff --git a/src/compositions/ContactForm/ContactForm.tsx b/src/compositions/ContactForm/ContactForm.tsx index e70bf11..4057c0e 100644 --- a/src/compositions/ContactForm/ContactForm.tsx +++ b/src/compositions/ContactForm/ContactForm.tsx @@ -1,44 +1,14 @@ 'use client' -import { Input } from '@/components/Input/Input' -import { Button } from '@/components/Button/Button' -import styles from "./styles.module.scss" -import classNames from 'classnames' import { send } from '@/utils/actions' -import { useActionState } from 'react' +import { ContactFormView } from './ContactFormView' type ContactFormProps = { - schema?: "base" | "contrast", + schema?: 'base' | 'contrast' toEmail: string } -const initialState = { - message: '', +export const ContactForm = ({ schema, toEmail }: ContactFormProps) => { + const sendWithEmail = send.bind(null, toEmail) + return } - -export const ContactForm = ({schema, toEmail}: ContactFormProps) => { - - const sendWithEmail = send.bind(null, toEmail); - const [state, formAction, pending] = useActionState(sendWithEmail, initialState) - - return ( - - - - - - - - - - - - - {state.message} - - - Abschicken - - - ) -} \ No newline at end of file diff --git a/src/compositions/ContactForm/ContactFormView.tsx b/src/compositions/ContactForm/ContactFormView.tsx new file mode 100644 index 0000000..e221798 --- /dev/null +++ b/src/compositions/ContactForm/ContactFormView.tsx @@ -0,0 +1,51 @@ +'use client' + +import { Input } from '@/components/Input/Input' +import { Button } from '@/components/Button/Button' +import styles from './styles.module.scss' +import classNames from 'classnames' +import { useActionState } from 'react' + +export type ContactFormState = { + message: string + errors?: Record +} + +export type ContactFormAction = ( + prevState: ContactFormState, + formData: FormData, +) => Promise | ContactFormState + +type ContactFormViewProps = { + schema?: 'base' | 'contrast' + action: ContactFormAction +} + +const initialState: ContactFormState = { + message: '', +} + +export const ContactFormView = ({ schema, action }: ContactFormViewProps) => { + const [state, formAction, pending] = useActionState(action, initialState) + + return ( + + + + + + + + + + + + {state.message} + + + Abschicken + + + + ) +} diff --git a/src/compositions/ContactSection/ContactSection.stories.tsx b/src/compositions/ContactSection/ContactSection.stories.tsx index 69a3872..b013d07 100644 --- a/src/compositions/ContactSection/ContactSection.stories.tsx +++ b/src/compositions/ContactSection/ContactSection.stories.tsx @@ -1,17 +1,23 @@ import { Meta, StoryObj } from '@storybook/nextjs-vite' -import { ContactSection } from './ContactSection' +import { ContactSectionView } from './ContactSectionView' +import { ContactFormView, ContactFormState } from '@/compositions/ContactForm/ContactFormView' -const meta: Meta = { - component: ContactSection, +const noopAction = async (): Promise => ({ + message: 'Storybook: form submission is a no-op.', +}) + +const meta: Meta = { + component: ContactSectionView, } -type Story = StoryObj; +type Story = StoryObj export default meta export const Default: Story = { args: { - title: "Kontakt", - description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vel dolor semper, consectetur augue quis, elementum tellus. Nulla ut porta lorem. Nulla posuere quam nisi, ut porttitor diam dignissim eget. Morbi imperdiet et lectus quis dapibus. Cras sollicitudin est augue, vel rhoncus massa elementum vitae. Donec sagittis pulvinar nibh ultrices tincidunt. Interdum et malesuada fames ac ante ipsum primis in faucibus.', - toEmail: 'kontak@test.com' + title: 'Kontakt', + description: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vel dolor semper, consectetur augue quis, elementum tellus. Nulla ut porta lorem. Nulla posuere quam nisi, ut porttitor diam dignissim eget. Morbi imperdiet et lectus quis dapibus. Cras sollicitudin est augue, vel rhoncus massa elementum vitae. Donec sagittis pulvinar nibh ultrices tincidunt. Interdum et malesuada fames ac ante ipsum primis in faucibus.', + form: , }, -} \ No newline at end of file +} diff --git a/src/compositions/ContactSection/ContactSection.tsx b/src/compositions/ContactSection/ContactSection.tsx index 8606bd2..e820398 100644 --- a/src/compositions/ContactSection/ContactSection.tsx +++ b/src/compositions/ContactSection/ContactSection.tsx @@ -1,34 +1,28 @@ -import { Section } from '@/components/Section/Section' -import { Container } from '@/components/Container/Container' import { ContactForm } from '@/compositions/ContactForm/ContactForm' -import { Title } from '@/components/Title/Title' -import { Col } from '@/components/Flex/Col' -import { Row } from '@/components/Flex/Row' -import { TextDiv } from '@/components/Text/TextDiv' +import { ContactSectionView } from './ContactSectionView' type ContactSectionProps = { - title: string, - description: string, + title: string + description: string backgroundColor?: 'off-white' schema?: 'base' | 'contrast' toEmail: string } - -export const ContactSection = ({title, description, schema, backgroundColor, toEmail}: ContactSectionProps) => { +export const ContactSection = ({ + title, + description, + schema, + backgroundColor, + toEmail, +}: ContactSectionProps) => { return ( - - - - - - - - - - - - - + } + /> ) -} \ No newline at end of file +} diff --git a/src/compositions/ContactSection/ContactSectionView.tsx b/src/compositions/ContactSection/ContactSectionView.tsx new file mode 100644 index 0000000..2380183 --- /dev/null +++ b/src/compositions/ContactSection/ContactSectionView.tsx @@ -0,0 +1,37 @@ +import { Section } from '@/components/Section/Section' +import { Container } from '@/components/Container/Container' +import { Title } from '@/components/Title/Title' +import { Col } from '@/components/Flex/Col' +import { Row } from '@/components/Flex/Row' +import { TextDiv } from '@/components/Text/TextDiv' +import type { ReactNode } from 'react' + +type ContactSectionViewProps = { + title: string + description: string + backgroundColor?: 'off-white' + schema?: 'base' | 'contrast' + form: ReactNode +} + +export const ContactSectionView = ({ + title, + description, + schema, + backgroundColor, + form, +}: ContactSectionViewProps) => { + return ( + + + + + + + + {form} + + + + ) +} diff --git a/src/compositions/Footer/Footer.stories.tsx b/src/compositions/Footer/Footer.stories.tsx index 8615da0..2670c50 100644 --- a/src/compositions/Footer/Footer.stories.tsx +++ b/src/compositions/Footer/Footer.stories.tsx @@ -1,13 +1,45 @@ import { Meta, StoryObj } from '@storybook/nextjs-vite' -import { Footer } from './Footer' +import type { Footer } from '@/payload-types' +import { FooterView } from './FooterView' -const meta: Meta = { - component: Footer, +const mockFooter: Footer = { + id: 'mock-footer', + groups: [ + { + title: 'Pfarrei', + links: [ + { label: 'Über uns', href: '/ueber-uns' }, + { label: 'Kontakt', href: '/kontakt' }, + { label: 'Gemeinden', href: '/gemeinden' }, + ], + }, + { + title: 'Service', + links: [ + { label: 'Gottesdienste', href: '/gottesdienst' }, + { label: 'Veranstaltungen', href: '/veranstaltungen' }, + { label: 'Blog', href: '/blog' }, + ], + }, + ], } -type Story = StoryObj; +const mockPrayers = [ + 'Herr, gib mir heute die Gelassenheit, Dinge hinzunehmen, die ich nicht ändern kann.', + 'Vater unser im Himmel, geheiligt werde dein Name.', + 'Gegrüßet seist du, Maria, voll der Gnade.', +] + +const meta: Meta = { + component: FooterView, +} + +type Story = StoryObj export default meta export const Default: Story = { - args: {}, -} \ No newline at end of file + args: { + prayers: mockPrayers, + footer: mockFooter, + }, +} diff --git a/src/compositions/Footer/Footer.tsx b/src/compositions/Footer/Footer.tsx index 36ab206..29c1b82 100644 --- a/src/compositions/Footer/Footer.tsx +++ b/src/compositions/Footer/Footer.tsx @@ -1,13 +1,6 @@ -import { Section } from '@/components/Section/Section' -import { Container } from '@/components/Container/Container' -import { Logo } from '@/components/Logo/Logo' -import styles from './styles.module.scss' -import { Row } from '@/components/Flex/Row' -import { Col } from '@/components/Flex/Col' -import { RandomPrayer } from '@/components/RandomPrayer/RandomPrayer' -import Link from 'next/link' import { fetchPrayers } from '@/fetch/prayers' import { fetchFooter } from '@/fetch/footer' +import { FooterView } from './FooterView' export const Footer = async () => { const [prayers, footer] = await Promise.all([ @@ -15,48 +8,5 @@ export const Footer = async () => { fetchFooter(), ]) - return ( - - - - - - - - - - - - {footer.groups?.map((group, i) => ( - - - {group.title} - - - {group.links?.map((link, j) => ( - - {link.label} - - ))} - - - ))} - - - Stoßgebet - - - - - - - - - - ) + return } diff --git a/src/compositions/Footer/FooterView.tsx b/src/compositions/Footer/FooterView.tsx new file mode 100644 index 0000000..58488ac --- /dev/null +++ b/src/compositions/Footer/FooterView.tsx @@ -0,0 +1,61 @@ +import { Section } from '@/components/Section/Section' +import { Container } from '@/components/Container/Container' +import { Logo } from '@/components/Logo/Logo' +import styles from './styles.module.scss' +import { Row } from '@/components/Flex/Row' +import { Col } from '@/components/Flex/Col' +import { RandomPrayer } from '@/components/RandomPrayer/RandomPrayer' +import Link from 'next/link' +import type { Footer } from '@/payload-types' + +type FooterViewProps = { + prayers: string[] + footer: Footer +} + +export const FooterView = ({ prayers, footer }: FooterViewProps) => { + return ( + + + + + + + + + + + + {footer.groups?.map((group, i) => ( + + + {group.title} + + + {group.links?.map((link, j) => ( + + {link.label} + + ))} + + + ))} + + + Stoßgebet + + + + + + + + + + ) +} diff --git a/src/compositions/PublicationAndNewsletter/PublicationAndNewsletter.tsx b/src/compositions/PublicationAndNewsletter/PublicationAndNewsletter.tsx index c30084c..3e19542 100644 --- a/src/compositions/PublicationAndNewsletter/PublicationAndNewsletter.tsx +++ b/src/compositions/PublicationAndNewsletter/PublicationAndNewsletter.tsx @@ -1,87 +1,45 @@ -import { Section } from '@/components/Section/Section' -import { Container } from '@/components/Container/Container' -import { Row } from '@/components/Flex/Row' -import { Col } from '@/components/Flex/Col' -import { Title } from '@/components/Title/Title' -import { NewsletterItem } from '@/compositions/PublicationAndNewsletter/NewsletterItem' -import styles from "./styles.module.scss" -import Image from 'next/image' -import envelope from "./envelope.svg" import Sandbox from '@nyariv/sandboxjs' import { fetchLastMagazine } from '@/fetch/magazine' - -type NewsletterData = { - guid: string, - title: string, - link: string, - pubDate: string, -} +import { + PublicationAndNewsletterView, + NewsletterArchiveItem, +} from './PublicationAndNewsletterView' export const PublicationAndNewsletter = async () => { - - let archiveData: NewsletterData[] = [] + let archiveData: NewsletterArchiveItem[] = [] try { const response = await fetch( 'https://s3-eu-west-1.amazonaws.com/files.crsend.com/37000/37866/rss/mailings.js', - { cache: "force-cache", next: { revalidate: 3600 }} - ); - const jsContent = await response.text(); + { cache: 'force-cache', next: { revalidate: 3600 } }, + ) + const jsContent = await response.text() - // safe (?) alternative to `eval()` - const sandbox = new Sandbox(); - const scope: {cr_archive: NewsletterData[] } = { cr_archive: [] }; - const exec = sandbox.compile(jsContent); - exec(scope).run(); - - archiveData = scope.cr_archive.slice(0, 3); + const sandbox = new Sandbox() + const scope: { cr_archive: NewsletterArchiveItem[] } = { cr_archive: [] } + const exec = sandbox.compile(jsContent) + exec(scope).run() + archiveData = scope.cr_archive.slice(0, 3) } catch { - console.error("Could not fetch newsletters. Please check PublicationAndNewsletter component") + console.error( + 'Could not fetch newsletters. Please check PublicationAndNewsletter component', + ) } - const magazine = await fetchLastMagazine(); - const magazine_url = magazine && typeof magazine.document === "object" ? magazine.document.url || undefined : undefined; - const magazine_cover = magazine && typeof magazine.cover === "object" ? magazine.cover : undefined; + const magazine = await fetchLastMagazine() + const magazineUrl = + magazine && typeof magazine.document === 'object' + ? magazine.document.url || undefined + : undefined + const magazineCover = + magazine && typeof magazine.cover === 'object' ? magazine.cover : undefined return ( - - - - - {magazine_url && magazine_cover && magazine_cover.url && - - - - } - - - - - - - - {archiveData.map((item) => ( - - - ))} - - - - + ) -} \ No newline at end of file +} diff --git a/src/compositions/PublicationAndNewsletter/PublicationAndNewsletterView.stories.tsx b/src/compositions/PublicationAndNewsletter/PublicationAndNewsletterView.stories.tsx new file mode 100644 index 0000000..aa7ae09 --- /dev/null +++ b/src/compositions/PublicationAndNewsletter/PublicationAndNewsletterView.stories.tsx @@ -0,0 +1,66 @@ +import { Meta, StoryObj } from '@storybook/nextjs-vite' +import { PublicationAndNewsletterView } from './PublicationAndNewsletterView' + +const meta: Meta = { + component: PublicationAndNewsletterView, +} + +type Story = StoryObj +export default meta + +const archiveData = [ + { + guid: '1', + title: 'Newsletter aus dem Bistum – März 2026', + link: 'https://example.com/newsletter/march', + pubDate: '2026-03-01T00:00:00.000Z', + }, + { + guid: '2', + title: 'Newsletter aus dem Bistum – Februar 2026', + link: 'https://example.com/newsletter/february', + pubDate: '2026-02-01T00:00:00.000Z', + }, + { + guid: '3', + title: 'Newsletter aus dem Bistum – Januar 2026', + link: 'https://example.com/newsletter/january', + pubDate: '2026-01-01T00:00:00.000Z', + }, +] + +export const Default: Story = { + args: { + archiveData, + magazineUrl: 'https://example.com/magazine.pdf', + magazineCover: { + url: 'https://placehold.co/500x600/png', + width: 500, + height: 600, + }, + }, +} + +export const NewsletterOnly: Story = { + args: { + archiveData, + }, +} + +export const MagazineOnly: Story = { + args: { + archiveData: [], + magazineUrl: 'https://example.com/magazine.pdf', + magazineCover: { + url: 'https://placehold.co/500x600/png', + width: 500, + height: 600, + }, + }, +} + +export const Empty: Story = { + args: { + archiveData: [], + }, +} \ No newline at end of file diff --git a/src/compositions/PublicationAndNewsletter/PublicationAndNewsletterView.tsx b/src/compositions/PublicationAndNewsletter/PublicationAndNewsletterView.tsx new file mode 100644 index 0000000..d136984 --- /dev/null +++ b/src/compositions/PublicationAndNewsletter/PublicationAndNewsletterView.tsx @@ -0,0 +1,70 @@ +import { Section } from '@/components/Section/Section' +import { Container } from '@/components/Container/Container' +import { Row } from '@/components/Flex/Row' +import { Col } from '@/components/Flex/Col' +import { Title } from '@/components/Title/Title' +import { NewsletterItem } from '@/compositions/PublicationAndNewsletter/NewsletterItem' +import styles from './styles.module.scss' +import Image from 'next/image' +import envelope from './envelope.svg' + +export type NewsletterArchiveItem = { + guid: string + title: string + link: string + pubDate: string +} + +type PublicationAndNewsletterViewProps = { + archiveData: NewsletterArchiveItem[] + magazineUrl?: string + magazineCover?: { + url?: string | null + width?: number | null + height?: number | null + } +} + +export const PublicationAndNewsletterView = ({ + archiveData, + magazineUrl, + magazineCover, +}: PublicationAndNewsletterViewProps) => { + return ( + + + + + {magazineUrl && magazineCover?.url && ( + + + + )} + + + + + + + + {archiveData.map((item) => ( + + ))} + + + + + ) +} diff --git a/src/pageComponents/Home/Home.stories.tsx b/src/pageComponents/Home/Home.stories.tsx deleted file mode 100644 index ff7149d..0000000 --- a/src/pageComponents/Home/Home.stories.tsx +++ /dev/null @@ -1,175 +0,0 @@ -import { Meta, StoryObj } from '@storybook/nextjs-vite' -import { Home } from './Home' - -const meta: Meta = { - component: Home, -} - -type Story = StoryObj; -export default meta - -export const Default: Story = { - args: { - events: [ - { - id: '1', - title: 'Event 1', - date: '2024-12-02T09:21:24Z', - location: { - id: 'l1', - name: "St. Richard", - updatedAt: "", - createdAt: "" - }, - shortDescription: '', - description: "Some descripton", - cancelled: false, - updatedAt: '2024-12-02T09:21:24Z', - createdAt: '2024-12-02T09:21:24Z', - isRecurring: false - }, - { - id: '2', - title: 'Event 2', - date: '2024-12-05T09:21:24Z', - location: { - id: 'l1', - name: "St. Richard", - updatedAt: "", - createdAt: "" - }, - shortDescription: '', - description: "", - cancelled: false, - updatedAt: '2024-12-02T09:21:24Z', - createdAt: '2024-12-02T09:21:24Z', - isRecurring: false - }, - { - id: '2', - title: 'Event 2', - date: '2024-12-08T09:21:24Z', - location: { - id: 'l2', - name: "St. Hedwig", - updatedAt: "", - createdAt: "" - }, - shortDescription: '', - description: "", - cancelled: true, - updatedAt: '2024-12-02T09:21:24Z', - createdAt: '2024-12-02T09:21:24Z', - isRecurring: false - }, - ], - blog: [ - { - id: 'b1', - title: 'Blog 1', - content: { - excerpt: '', - content: [] - }, - configuration: { - showOnFrontpage: false, - }, - updatedAt: '', - createdAt: '', - }, - { - id: 'b2', - title: 'Blog 2', - content: { - excerpt: '', - content: [] - }, - configuration: { - showOnFrontpage: false, - }, - updatedAt: '', - createdAt: '', - }, - { - id: 'b3', - title: 'Blog 3', - content: { - excerpt: '', - content: [] - }, - configuration: { - showOnFrontpage: false, - }, - updatedAt: '', - createdAt: '', - }, - ], - worship: [ - { - id: 'w1', - date: '2024-12-02T09:21:24Z', - location: { - id: 'c1', - name: 'St Richard', - address: '', - createdAt: '', - updatedAt: '' - }, - type: 'MASS', - cancelled: false, - updatedAt: '', - createdAt: '', - }, - { - id: 'w1', - date: '2024-12-07T10:00:24Z', - location: { - id: 'c1', - name: 'St Richard', - address: '', - createdAt: '', - updatedAt: '' - }, - type: 'MASS', - cancelled: false, - updatedAt: '', - createdAt: '', - }, - ], - highlights: [], - announcements: [ - { - id: "link_1", - text: "St. Clara", - href: "https://disney.com" - }, - { - id: "link_2", - text: "St. Anna", - href: "https://disney.com" - }, - { - id: "link_3", - text: "St. Eduard", - href: "https://disney.com" - } - ], - calendars: [ - { - id: "link_1", - text: "St. Clara", - href: "https://disney.com" - }, - { - id: "link_2", - text: "St. Anna", - href: "https://disney.com" - }, - { - id: "link_3", - text: "St. Eduard", - href: "https://disney.com" - } - ], - } -} \ No newline at end of file diff --git a/src/pageComponents/Home/Home.tsx b/src/pageComponents/Home/Home.tsx index 33607e4..ed5ac63 100644 --- a/src/pageComponents/Home/Home.tsx +++ b/src/pageComponents/Home/Home.tsx @@ -1,198 +1,39 @@ -import { Blog, Worship, Event, Highlight } from '@/payload-types' -import { Banner } from '@/components/Banner/Banner' -import { Container } from '@/components/Container/Container' -import { Section } from '@/components/Section/Section' -import { MainText } from '@/components/MainText/MainText' -import { HR } from '@/components/HorizontalRule/HorizontalRule' -import { Title } from '@/components/Title/Title' -import { MassGrid } from '@/components/MassTable/MassGrid' -import { MassTable } from '@/components/MassTable/MassTable' -import { ImageCardSlider } from '@/compositions/ImageCardSlider/ImageCardSlider' -import { blogToSlides } from '@/utils/dto/blog' -import forest from '@/assets/map.jpg' -import { ContentWithSlider } from '@/compositions/ContentWithSlider/ContentWithSlider' -import { EventRow } from '@/components/EventRow/EventRow' -import { highlightLink } from '@/utils/dto/highlight' -import { Events } from '@/compositions/Events/Events' -import { transformEvents } from '@/utils/dto/events' -import { ContactSection } from '@/compositions/ContactSection/ContactSection' -import { CollapsibleImageWithText } from '@/compositions/CollapsibleImageWithText/CollapsibleImageWithText' -import { MoreInformation } from '@/pageComponents/Home/MoreInformation' -import { Button } from '@/components/Button/Button' -import styles from "./styles.module.scss" +import moment from 'moment' +import { fetchEvents } from '@/fetch/events' +import { fetchWorship } from '@/fetch/worship' +import { fetchBlogPosts } from '@/fetch/blog' +import { fetchHighlights } from '@/fetch/highlights' +import { fetchLastAnnouncements } from '@/fetch/announcement' +import { fetchLastCalendars } from '@/fetch/calendar' +import { perParish } from '@/utils/dto/perParish' import { PublicationAndNewsletter } from '@/compositions/PublicationAndNewsletter/PublicationAndNewsletter' -import { Link, PopupButton } from '@/components/PopupButton/PopupButton' +import { HomeView } from './HomeView' -type HomeProps = { - events: Event[], - worship: Worship[], - blog: Blog[], - highlights: Highlight[], - announcements: Link[], - calendars: Link[] -} +export const Home = async () => { + const fromDate = moment().isoWeekday(1).hours(0).minutes(0) + const tillDate = moment().isoWeekday(7).hours(23).minutes(59) -const sortWorship = (worship: Worship[]) => { - const map = new Map() - - worship.map(w => { - if (typeof w.location === 'object') { - const title = w.location.name - - if (map.has(title)) { - map.get(title)?.push(w) - } else { - map.set(title, [w]) - } - } + const events = await fetchEvents() + const worship = await fetchWorship({ + fromDate: fromDate.toDate(), + tillDate: tillDate.toDate(), }) - - return map -} - - -export const Home = ({ - events, - worship, - blog, - highlights, - announcements, - calendars -}: HomeProps) => { - const worshipPerLocation = Array.from( - sortWorship(worship).entries(), - ).sort( - (a, b) => { - const nameA = a[0] - const nameB = b[0] - - if (nameA < nameB) { - return -1 - } - if (nameA > nameB) { - return 1 - } - - // names must be equal - return 0 - }, - ) + const blog = await fetchBlogPosts(true) + const highlights = await fetchHighlights() + const announcements = await fetchLastAnnouncements() + const announcementsLinks = announcements ? perParish(announcements) : [] + const calendars = await fetchLastCalendars() + const calendarsLinks = calendars ? perParish(calendars) : [] return ( - <> - - - - - - - - - - - - {blog && blog.length > 0 && - - - - - } - - - - - - - - {worshipPerLocation.map(value => )} - - - - - - - { announcements.length > 0 && - - } - - { calendars.length > 0 && - - } - - Alle Gottesdienste - - - - - - } - /> - - - - {highlights.map(highlight => ( - - ))} - >}> - - - - - - - - - - > - + } + /> ) } - -export default Home; \ No newline at end of file diff --git a/src/pageComponents/Home/HomeView.tsx b/src/pageComponents/Home/HomeView.tsx new file mode 100644 index 0000000..37ef033 --- /dev/null +++ b/src/pageComponents/Home/HomeView.tsx @@ -0,0 +1,199 @@ +import { Blog, Worship, Event, Highlight } from '@/payload-types' +import { Banner } from '@/components/Banner/Banner' +import { Container } from '@/components/Container/Container' +import { Section } from '@/components/Section/Section' +import { MainText } from '@/components/MainText/MainText' +import { HR } from '@/components/HorizontalRule/HorizontalRule' +import { Title } from '@/components/Title/Title' +import { MassGrid } from '@/components/MassTable/MassGrid' +import { MassTable } from '@/components/MassTable/MassTable' +import { ImageCardSlider } from '@/compositions/ImageCardSlider/ImageCardSlider' +import { blogToSlides } from '@/utils/dto/blog' +import forest from '@/assets/map.jpg' +import { ContentWithSlider } from '@/compositions/ContentWithSlider/ContentWithSlider' +import { EventRow } from '@/components/EventRow/EventRow' +import { highlightLink } from '@/utils/dto/highlight' +import { Events } from '@/compositions/Events/Events' +import { transformEvents } from '@/utils/dto/events' +import { ContactSection } from '@/compositions/ContactSection/ContactSection' +import { CollapsibleImageWithText } from '@/compositions/CollapsibleImageWithText/CollapsibleImageWithText' +import { MoreInformation } from '@/pageComponents/Home/MoreInformation' +import { Button } from '@/components/Button/Button' +import styles from "./styles.module.scss" +import { Link, PopupButton } from '@/components/PopupButton/PopupButton' +import type { ReactNode } from 'react' + +type HomeViewProps = { + events: Event[], + worship: Worship[], + blog: Blog[], + highlights: Highlight[], + announcements: Link[], + calendars: Link[], + publicationAndNewsletter?: ReactNode +} + +const sortWorship = (worship: Worship[]) => { + const map = new Map() + + worship.map(w => { + if (typeof w.location === 'object') { + const title = w.location.name + + if (map.has(title)) { + map.get(title)?.push(w) + } else { + map.set(title, [w]) + } + } + }) + + return map +} + + +export const HomeView = ({ + events, + worship, + blog, + highlights, + announcements, + calendars, + publicationAndNewsletter, +}: HomeViewProps) => { + const worshipPerLocation = Array.from( + sortWorship(worship).entries(), + ).sort( + (a, b) => { + const nameA = a[0] + const nameB = b[0] + + if (nameA < nameB) { + return -1 + } + if (nameA > nameB) { + return 1 + } + + // names must be equal + return 0 + }, + ) + + return ( + <> + + + + + + + + + + + + {blog && blog.length > 0 && + + + + + } + + + + + + + + {worshipPerLocation.map(value => )} + + + + + + + { announcements.length > 0 && + + } + + { calendars.length > 0 && + + } + + Alle Gottesdienste + + + + + + } + /> + + + + {highlights.map(highlight => ( + + ))} + >}> + + + + + + + {publicationAndNewsletter} + + + > + + ) +} + diff --git a/src/pageComponents/Parish/Parish.stories.tsx b/src/pageComponents/Parish/Parish.stories.tsx index 2f7004f..a647743 100644 --- a/src/pageComponents/Parish/Parish.stories.tsx +++ b/src/pageComponents/Parish/Parish.stories.tsx @@ -2,7 +2,7 @@ import { Meta, StoryObj } from '@storybook/nextjs-vite' import chris from "../../assets/christophorus.jpeg" import { Parish } from './Parish' import { Menu } from '@/components/Menu/Menu' -import { Footer } from '@/compositions/Footer/Footer' +import { FooterView } from '@/compositions/Footer/FooterView' const meta: Meta = { component: Parish, @@ -28,7 +28,18 @@ const meta: Meta = { ] }}/> - + > ) ] diff --git a/src/pageComponents/Search/Search.stories.tsx b/src/pageComponents/Search/Search.stories.tsx index cb10179..4ea649a 100644 --- a/src/pageComponents/Search/Search.stories.tsx +++ b/src/pageComponents/Search/Search.stories.tsx @@ -27,26 +27,20 @@ export const WithResults: Story = { results: [ makeResult('1', 'Sonntagsgottesdienst', { relationTo: 'pages', - value: { - id: 'p1', - slug: 'gottesdienst', - } as Search['doc']['value'], - }), + value: { id: 'p1', slug: 'gottesdienst' }, + } as unknown as Search['doc']), makeResult('2', 'Ostern 2026 – Liturgische Feier', { relationTo: 'event', - value: { id: 'e1' } as Search['doc']['value'], - }), + value: { id: 'e1' }, + } as unknown as Search['doc']), makeResult('3', 'Ministrantengruppe', { relationTo: 'group', - value: { - id: 'g1', - slug: 'ministranten', - } as Search['doc']['value'], - }), + value: { id: 'g1', slug: 'ministranten' }, + } as unknown as Search['doc']), makeResult('4', 'Rundbrief Januar', { relationTo: 'blog', - value: { id: 'b1' } as Search['doc']['value'], - }), + value: { id: 'b1' }, + } as unknown as Search['doc']), ], }, } @@ -63,4 +57,4 @@ export const EmptyQuery: Story = { query: '', results: [], }, -} \ No newline at end of file +}
- {state.message} -
{state.message}
- {group.title} -
- Stoßgebet -
+ {group.title} +
+ Stoßgebet +