feature: Worship page
This commit is contained in:
parent
ef913bc500
commit
a6a20fb7cc
18 changed files with 261 additions and 160 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -39,6 +39,9 @@ yarn-error.log*
|
|||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
# storybook
|
||||
/storybook-static
|
||||
|
||||
.env
|
||||
|
||||
/media
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
import { Section } from '@/components/Section/Section'
|
||||
import { Container } from '@/components/Container/Container'
|
||||
import { notFound } from 'next/navigation'
|
||||
import { Worship } from '@/payload-types'
|
||||
import { Title } from '@/components/Title/Title'
|
||||
import { HR } from '@/components/HorizontalRule/HorizontalRule'
|
||||
import { liturgicalDayName } from '@/hooks/liturgicalDayName'
|
||||
import { ChurchWithContact } from '@/compositions/ChurchWithContact/ChurchWithContact'
|
||||
import { transformCategory } from '@/utils/dto/worship'
|
||||
import { readableDateTime } from '@/utils/readableDate'
|
||||
import { Worship as WorshipType } from '@/payload-types'
|
||||
import { Worship } from '@/pageComponents/Worship/Worship'
|
||||
|
||||
export default async function WorshipPage({ params }: { params: Promise<{id: string}>}) {
|
||||
|
||||
|
|
@ -17,54 +10,9 @@ export default async function WorshipPage({ params }: { params: Promise<{id: str
|
|||
notFound()
|
||||
}
|
||||
|
||||
const event = await res.json() as Worship;
|
||||
const subtitle = event.title ? event.title : transformCategory(event.type);
|
||||
const title = event.liturgicalDay ? event.liturgicalDay : liturgicalDayName(event.date);
|
||||
const church = typeof event.location === "string" ? { name: "Unkown", address: "unknown"} : event.location;
|
||||
const worship = await res.json() as WorshipType;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Section>
|
||||
<Container>
|
||||
<Title title={title} subtitle={subtitle} />
|
||||
</Container>
|
||||
<HR/>
|
||||
</Section>
|
||||
|
||||
<Section backgroundColor={"off-white"}>
|
||||
<Container textAlign="center">
|
||||
<>
|
||||
<p>
|
||||
<strong>{church.name}</strong> <br/>
|
||||
{readableDateTime(event.date)}
|
||||
</p>
|
||||
|
||||
{ event.celebrant &&
|
||||
<p>
|
||||
<strong>Zelebrant</strong><br/>
|
||||
{event.celebrant}
|
||||
</p>
|
||||
}
|
||||
|
||||
{event.description &&
|
||||
<p>
|
||||
<strong>Hinweis</strong><br />
|
||||
{event.description}
|
||||
</p>
|
||||
}
|
||||
</>
|
||||
</Container>
|
||||
</Section>
|
||||
|
||||
|
||||
<Section>
|
||||
<Container>
|
||||
<ChurchWithContact
|
||||
church={church.name}
|
||||
contact={church.address}
|
||||
/>
|
||||
</Container>
|
||||
</Section>
|
||||
</>
|
||||
|
||||
<Worship worship={worship} />
|
||||
)
|
||||
}
|
||||
|
|
@ -38,6 +38,8 @@ export const Events: CollectionConfig = {
|
|||
admin: {
|
||||
date: {
|
||||
pickerAppearance: 'dayAndTime',
|
||||
timeIntervals: 15,
|
||||
timeFormat: 'HH:mm'
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
21
src/components/Cross/Cross.stories.tsx
Normal file
21
src/components/Cross/Cross.stories.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { Meta, StoryObj } from '@storybook/react'
|
||||
import { Cross } from './Cross'
|
||||
|
||||
const meta: Meta<typeof Cross> = {
|
||||
component: Cross,
|
||||
}
|
||||
|
||||
type Story = StoryObj<typeof Cross>;
|
||||
export default meta
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
schema: "base"
|
||||
},
|
||||
}
|
||||
|
||||
export const Contrast: Story = {
|
||||
args: {
|
||||
schema: "contrast"
|
||||
},
|
||||
}
|
||||
25
src/components/Cross/Cross.tsx
Normal file
25
src/components/Cross/Cross.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import styles from "./styles.module.scss"
|
||||
import classNames from 'classnames'
|
||||
|
||||
type CrossProps = {
|
||||
schema?: "base" | "contrast"
|
||||
}
|
||||
|
||||
export const Cross = ({schema = "base"}: CrossProps) => {
|
||||
const style = classNames({
|
||||
[styles.crossContrast]: schema === "contrast",
|
||||
[styles.crossBase]: schema === "base",
|
||||
})
|
||||
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 39.69 49.61"
|
||||
className={style}
|
||||
height={49.61}
|
||||
>
|
||||
<polygon
|
||||
points="33.89 14.81 19.89 14.81 19.89 0.8 18.89 0.8 18.89 14.81 4.89 14.81 4.89 15.81 18.89 15.81 18.89 48.8 19.89 48.8 19.89 15.81 33.89 15.81 33.89 14.81" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
9
src/components/Cross/styles.module.scss
Normal file
9
src/components/Cross/styles.module.scss
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
@import "template.scss";
|
||||
|
||||
.crossContrast {
|
||||
fill: $contrast-color;
|
||||
}
|
||||
|
||||
.crossBase {
|
||||
fill: $base-color;
|
||||
}
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
import styles from "./styles.module.scss"
|
||||
import Image from "next/image"
|
||||
import cross from "./cross2.svg"
|
||||
import { Cross } from '@/components/Cross/Cross'
|
||||
|
||||
export const HR = () => {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.line}></div>
|
||||
<Image src={cross} alt={"Cross"} className={styles.cross} />
|
||||
<Cross />
|
||||
<div className={styles.line}></div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="40"
|
||||
height="70"
|
||||
viewBox="0 0 10.583333 18.520834"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#426156FF;stroke-width:0.473399"
|
||||
id="rect846"
|
||||
width="0.80836952"
|
||||
height="16.864483"
|
||||
x="5.1093903"
|
||||
y="0.83949941" />
|
||||
<rect
|
||||
style="fill:#426156FF;stroke-width:0.454843"
|
||||
id="rect848"
|
||||
width="10"
|
||||
height="0.7728833"
|
||||
x="0.35068181"
|
||||
y="4.9346447" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 712 B |
|
|
@ -1,7 +0,0 @@
|
|||
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 39.69 49.61">
|
||||
<defs>
|
||||
<style>.cls-1{fill:#426156;}</style>
|
||||
</defs>
|
||||
<polygon class="cls-1"
|
||||
points="33.89 14.81 19.89 14.81 19.89 0.8 18.89 0.8 18.89 14.81 4.89 14.81 4.89 15.81 18.89 15.81 18.89 48.8 19.89 48.8 19.89 15.81 33.89 15.81 33.89 14.81"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 373 B |
|
|
@ -1,12 +1,10 @@
|
|||
import styles from './styles.module.css'
|
||||
import styles from './styles.module.scss'
|
||||
import { Container } from '@/components/Container/Container'
|
||||
import classNames from 'classnames'
|
||||
import { faustina } from '@/app/fonts'
|
||||
import Image from 'next/image'
|
||||
import quote from './quotes.svg'
|
||||
|
||||
type TestimonyProps = {
|
||||
name: string
|
||||
name?: string
|
||||
testimony: string
|
||||
occupation?: string
|
||||
}
|
||||
|
|
@ -16,18 +14,14 @@ export const Testimony = ({ name, testimony, occupation }: TestimonyProps) => {
|
|||
<Container>
|
||||
<div className={styles.testimony}>
|
||||
<div className={styles.container}>
|
||||
<Image
|
||||
src={quote}
|
||||
alt={'Quote'}
|
||||
width={100}
|
||||
className={classNames(styles.quote, styles.slidein)}
|
||||
/>
|
||||
<p className={classNames(styles.testimonyText, faustina.className)}>
|
||||
{testimony}
|
||||
</p>
|
||||
<p className={styles.name}>
|
||||
{name} {occupation && <>- {occupation}</>}
|
||||
</p>
|
||||
{typeof name === 'string' &&
|
||||
<p className={styles.name}>
|
||||
{name} {occupation && <>- {occupation}</>}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
.testimony {
|
||||
display: flex;
|
||||
padding: 80px 0 50px 0;
|
||||
gap: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.testimonyText {
|
||||
font-style: italic;
|
||||
line-height: 1.7em;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.person {
|
||||
height: 150px;
|
||||
width: 150px;
|
||||
background-color: #f6dc66;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.name {
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.quote {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: -10px;
|
||||
opacity: 0.5;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.slidein {
|
||||
transform: translateX(-100%);
|
||||
animation: slide-in 0.3s forwards;
|
||||
}
|
||||
|
||||
@keyframes slide-in {
|
||||
100% {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
}
|
||||
44
src/components/Testimony/styles.module.scss
Normal file
44
src/components/Testimony/styles.module.scss
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
@import "template.scss";
|
||||
|
||||
.testimony {
|
||||
display: flex;
|
||||
padding: 80px 0 50px 0;
|
||||
gap: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.testimonyText {
|
||||
font-size: 33px;
|
||||
color: $base-color;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.testimonyText::after {
|
||||
content: '”';
|
||||
color: $contrast-color;
|
||||
font-size: 120px;
|
||||
position: absolute;
|
||||
bottom: -20px;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.testimonyText::before {
|
||||
content: '“';
|
||||
color: $contrast-color;
|
||||
font-size: 120px;
|
||||
position: relative;
|
||||
line-height: 0;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 870px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.name {
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
color: $shade1;
|
||||
}
|
||||
|
|
@ -53,7 +53,8 @@ export const fetchWorship = async (args?: FetchWorshipArgs): Promise<PaginatedDo
|
|||
type: true,
|
||||
date: true,
|
||||
cancelled: true,
|
||||
location: true
|
||||
location: true,
|
||||
title: true,
|
||||
},
|
||||
limit: 15
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export const useCompactDate = (date: string) => {
|
|||
|
||||
/**
|
||||
* Return date in user friendly format
|
||||
* in format DD.MM.YYYY
|
||||
*
|
||||
*/
|
||||
export const useDate = (date: string) => {
|
||||
|
|
|
|||
31
src/pageComponents/Worship/Worship.stories.tsx
Normal file
31
src/pageComponents/Worship/Worship.stories.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import { Meta, StoryObj } from '@storybook/react'
|
||||
import { Worship } from './Worship'
|
||||
|
||||
const meta: Meta<typeof Worship> = {
|
||||
component: Worship,
|
||||
}
|
||||
|
||||
type Story = StoryObj<typeof Worship>;
|
||||
export default meta
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
worship: {
|
||||
id: "",
|
||||
date: "2024-12-16T10:42:16+0000",
|
||||
location: {
|
||||
id: "",
|
||||
name: "St. Clara",
|
||||
address: "Schudomastr 12\n12345 Berlin",
|
||||
createdAt: "",
|
||||
updatedAt: ""
|
||||
} ,
|
||||
type: 'MASS',
|
||||
title: null,
|
||||
cancelled: false,
|
||||
celebrant: "Pfr. M. Mustermann",
|
||||
updatedAt: "",
|
||||
createdAt: "",
|
||||
}
|
||||
},
|
||||
}
|
||||
85
src/pageComponents/Worship/Worship.tsx
Normal file
85
src/pageComponents/Worship/Worship.tsx
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import styles from "./styles.module.scss"
|
||||
import { Worship as WorshipType } from '@/payload-types'
|
||||
import { useDate } from '@/hooks/useCompactDate'
|
||||
import { Section } from '@/components/Section/Section'
|
||||
import { Title } from '@/components/Title/Title'
|
||||
import { liturgicalDayName } from '@/hooks/liturgicalDayName'
|
||||
import { EventExcerpt, EventExcerptRow } from '@/components/EventExcerpt/EventExcerpt'
|
||||
import { transformCategory } from '@/utils/dto/worship'
|
||||
import { TextDiv } from '@/components/Text/TextDiv'
|
||||
import { church } from '@/utils/church'
|
||||
import { ChurchIcon } from '@/components/ChurchIcon/ChurchIcon'
|
||||
import { Cross } from '@/components/Cross/Cross'
|
||||
import { Testimony } from '@/components/Testimony/Testimony'
|
||||
|
||||
type WorshipPageProps = {
|
||||
worship: WorshipType
|
||||
}
|
||||
|
||||
export const Worship = ({ worship }: WorshipPageProps) => {
|
||||
const date = new Date(worship.date);
|
||||
const day = date.toLocaleDateString('de-DE', {weekday: 'long'} )
|
||||
const localeDate = useDate(worship.date)
|
||||
const liturgicalDay = worship.liturgicalDay ? worship.liturgicalDay : liturgicalDayName(worship.date);
|
||||
const what = worship.title ? worship.title : transformCategory(worship.type);
|
||||
const time = date.toLocaleTimeString("de-DE", { timeStyle: "short" });
|
||||
|
||||
return (
|
||||
<>
|
||||
<Section>
|
||||
<div className={styles.textCenter}>
|
||||
<Cross schema={"contrast"} />
|
||||
</div>
|
||||
<Title
|
||||
title={`${day}, ${localeDate}`}
|
||||
size={'xl'}
|
||||
color={'contrast'}
|
||||
align={"center"}
|
||||
/>
|
||||
|
||||
<p className={styles.liturgicalDay}>
|
||||
{liturgicalDay}
|
||||
</p>
|
||||
</Section>
|
||||
|
||||
<Section padding={"medium"}>
|
||||
<EventExcerpt>
|
||||
<EventExcerptRow label={"Was:"}>
|
||||
{what}
|
||||
</EventExcerptRow>
|
||||
<EventExcerptRow label={"Wo:"}>
|
||||
{ typeof worship.location == "object" &&
|
||||
<TextDiv text={`${worship.location.name}\n${worship.location.address}\n${time} Uhr`} />
|
||||
}
|
||||
</EventExcerptRow>
|
||||
{ worship.celebrant &&
|
||||
<EventExcerptRow label={"Zelebrant:"}>
|
||||
{worship.celebrant}
|
||||
</EventExcerptRow>
|
||||
}
|
||||
|
||||
{ typeof worship.description === "string" && worship.description != "" &&
|
||||
<EventExcerptRow label={"Hinweise:"}>
|
||||
<TextDiv text={worship.description} />
|
||||
</EventExcerptRow>
|
||||
}
|
||||
|
||||
<div>
|
||||
<div className={styles.church}>
|
||||
<ChurchIcon
|
||||
church={church(typeof worship.location == "object" ? worship.location.name : "clara")}
|
||||
color={"#426156"}
|
||||
style={"filled"}
|
||||
stroke={3}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EventExcerpt>
|
||||
</Section>
|
||||
|
||||
<Section>
|
||||
<Testimony testimony={"Du bringst nichts mit hinein, Du nimmst nichts mit hinaus
Lass eine goldene Spur zurück, Im alten Erdenhaus"} />
|
||||
</Section>
|
||||
</>
|
||||
)
|
||||
}
|
||||
23
src/pageComponents/Worship/styles.module.scss
Normal file
23
src/pageComponents/Worship/styles.module.scss
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
@import "template.scss";
|
||||
|
||||
.textCenter {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.liturgicalDay {
|
||||
text-align: center;
|
||||
margin-top: -20px;
|
||||
}
|
||||
|
||||
.church {
|
||||
height: 144px;
|
||||
width: 144px;
|
||||
margin: 40px auto;
|
||||
border-radius: $border-radius;
|
||||
border: 1px solid $base-color;
|
||||
}
|
||||
|
||||
.church svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ export const tranformWorship = (worship: Worship[]): (EventRowProps & {id: strin
|
|||
return worship.map(w => {
|
||||
return {
|
||||
id: w.id,
|
||||
title: transformCategory(w.type),
|
||||
title: typeof w.title === "string" ? w.title : transformCategory(w.type),
|
||||
date: w.date,
|
||||
href: `/gottesdienst/${w.id}`,
|
||||
location: typeof w.location === 'string' ? w.location : w.location.name,
|
||||
|
|
|
|||
Loading…
Reference in a new issue