From 81614e4449b66a153502bf058eafbd328dbe0f73 Mon Sep 17 00:00:00 2001
From: Benno Tielen
Date: Mon, 10 Feb 2025 14:54:43 +0100
Subject: [PATCH] feature: admin menu
---
src/app/blog/[id]/page.tsx | 8 ++++
.../[year]/[month]/page.tsx | 9 +++++
src/app/gemeinde/[slug]/page.tsx | 39 ++++++++++++-------
src/app/gottesdienst/[id]/page.tsx | 14 ++++++-
src/app/gottesdienst/page.tsx | 7 ++++
src/app/gruppe/[slug]/page.tsx | 9 +++++
src/app/layout.tsx | 16 ++++----
src/app/veranstaltungen/[id]/page.tsx | 6 +++
src/app/veranstaltungen/page.tsx | 7 ++++
src/components/AdminMenu/AdminMenu.tsx | 26 +++++++++++++
src/components/AdminMenu/styles.module.scss | 19 +++++++++
src/compositions/Footer/Footer.tsx | 2 +-
src/pageComponents/Event/Event.stories.tsx | 1 +
src/pageComponents/Event/Event.tsx | 14 ++++++-
src/utils/auth.ts | 18 +++++++++
15 files changed, 169 insertions(+), 26 deletions(-)
create mode 100644 src/components/AdminMenu/AdminMenu.tsx
create mode 100644 src/components/AdminMenu/styles.module.scss
create mode 100644 src/utils/auth.ts
diff --git a/src/app/blog/[id]/page.tsx b/src/app/blog/[id]/page.tsx
index 0133bee..c36edad 100644
--- a/src/app/blog/[id]/page.tsx
+++ b/src/app/blog/[id]/page.tsx
@@ -9,6 +9,8 @@ import { HR } from '@/components/HorizontalRule/HorizontalRule'
import Image from 'next/image'
import styles from "./styles.module.scss"
import { Blocks } from '@/compositions/Blocks/Blocks'
+import { isAuthenticated } from '@/utils/auth'
+import { AdminMenu } from '@/components/AdminMenu/AdminMenu'
async function fetchBlog(id: string) {
const res = await fetch(`http://localhost:3000/api/blog/${id}`)
@@ -21,6 +23,7 @@ export default async function BlogPage({ params }: { params: Promise<{id: string
const id = (await params).id;
const data = await fetchBlog(id) as Blog;
const url = typeof data.photo === 'object' && data.photo?.sizes?.banner?.url;
+ const authenticated = await isAuthenticated();
if(!data) {
notFound();
@@ -51,6 +54,11 @@ export default async function BlogPage({ params }: { params: Promise<{id: string
+
>
)
diff --git a/src/app/gebetsanliegen-des-papstes/[year]/[month]/page.tsx b/src/app/gebetsanliegen-des-papstes/[year]/[month]/page.tsx
index bb01bca..1497c17 100644
--- a/src/app/gebetsanliegen-des-papstes/[year]/[month]/page.tsx
+++ b/src/app/gebetsanliegen-des-papstes/[year]/[month]/page.tsx
@@ -6,6 +6,8 @@ import { P } from '@/components/Text/Paragraph'
import { PageHeader } from '@/compositions/PageHeader/PageHeader'
import { NextPrevButtons } from '@/components/NextPrevButtons/NextPrevButtons'
import { notFound } from 'next/navigation'
+import { isAuthenticated } from '@/utils/auth'
+import { AdminMenu } from '@/components/AdminMenu/AdminMenu'
const months: Record = {
"01": "Januar",
@@ -105,6 +107,8 @@ export default async function PrayerIntentionPage({ params }: { params: Promise<
notFound();
}
+ const authenticated = await isAuthenticated()
+
return (
<>
+
>
)
diff --git a/src/app/gemeinde/[slug]/page.tsx b/src/app/gemeinde/[slug]/page.tsx
index 00b5073..05eaf67 100644
--- a/src/app/gemeinde/[slug]/page.tsx
+++ b/src/app/gemeinde/[slug]/page.tsx
@@ -6,6 +6,8 @@ import { fetchParish } from '@/fetch/parish'
import { fetchLastAnnouncement } from '@/fetch/announcement'
import { transformGallery } from '@/utils/dto/gallery'
import { fetchLastCalendar } from '@/fetch/calendar'
+import { isAuthenticated } from '@/utils/auth'
+import { AdminMenu } from '@/components/AdminMenu/AdminMenu'
export default async function ParishPage ({ params }: { params: Promise<{slug: string}>}) {
@@ -32,20 +34,29 @@ export default async function ParishPage ({ params }: { params: Promise<{slug: s
const worship = await fetchWorship({ locations: churchIds })
const announcement = await fetchLastAnnouncement(id);
const calendar = await fetchLastCalendar(id);
+ const authenticated = await isAuthenticated();
return (
-
+ <>
+
+
+ >
+
)
}
\ No newline at end of file
diff --git a/src/app/gottesdienst/[id]/page.tsx b/src/app/gottesdienst/[id]/page.tsx
index 6705058..1d12ec7 100644
--- a/src/app/gottesdienst/[id]/page.tsx
+++ b/src/app/gottesdienst/[id]/page.tsx
@@ -1,6 +1,8 @@
import { notFound } from 'next/navigation'
import { Worship as WorshipType } from '@/payload-types'
import { Worship } from '@/pageComponents/Worship/Worship'
+import { isAuthenticated } from '@/utils/auth'
+import { AdminMenu } from '@/components/AdminMenu/AdminMenu'
export default async function WorshipPage({ params }: { params: Promise<{id: string}>}) {
@@ -9,10 +11,20 @@ export default async function WorshipPage({ params }: { params: Promise<{id: str
if (!res.ok) {
notFound()
}
+ const authenticated = await isAuthenticated();
const worship = await res.json() as WorshipType;
return (
-
+ <>
+
+
+ >
)
}
\ No newline at end of file
diff --git a/src/app/gottesdienst/page.tsx b/src/app/gottesdienst/page.tsx
index d4ebf71..0656be1 100644
--- a/src/app/gottesdienst/page.tsx
+++ b/src/app/gottesdienst/page.tsx
@@ -9,6 +9,8 @@ import { EventRow } from '@/components/EventRow/EventRow'
import Error from '@/pages/_error'
import { fetchWorship } from '@/fetch/worship'
import { tranformWorship } from '@/utils/dto/worship'
+import { AdminMenu } from '@/components/AdminMenu/AdminMenu'
+import { isAuthenticated } from '@/utils/auth'
export default async function WorshipPage({searchParams}: {
@@ -20,6 +22,7 @@ export default async function WorshipPage({searchParams}: {
if (!week) {
week = weekNumber(moment());
}
+ const authenticated = await isAuthenticated();
const fromDate = moment(week, true);
@@ -76,6 +79,10 @@ export default async function WorshipPage({searchParams}: {
}
+
{events.length > 0 &&
diff --git a/src/app/gruppe/[slug]/page.tsx b/src/app/gruppe/[slug]/page.tsx
index 5e47c1d..e1c536f 100644
--- a/src/app/gruppe/[slug]/page.tsx
+++ b/src/app/gruppe/[slug]/page.tsx
@@ -15,6 +15,8 @@ import { Row } from '@/components/Flex/Row'
import { RawHTML } from '@/components/RawHTML/RawHTML'
import { Blocks } from '@/compositions/Blocks/Blocks'
import { getPhoto } from '@/utils/dto/gallery'
+import { isAuthenticated } from '@/utils/auth'
+import { AdminMenu } from '@/components/AdminMenu/AdminMenu'
export default async function GroupPage({ params }: { params: Promise<{slug: string}>}) {
@@ -29,6 +31,7 @@ export default async function GroupPage({ params }: { params: Promise<{slug: str
const media = getPhoto("tablet", photo)
const events = await fetchEvents({groupId: id})
+ const authenticated = await isAuthenticated();
return (
<>
@@ -90,6 +93,12 @@ export default async function GroupPage({ params }: { params: Promise<{slug: str
{ content && content.length > 0 &&
}
+
+
>
)
}
\ No newline at end of file
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 832425f..2e2bae5 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -60,7 +60,7 @@ export default function RootLayout({
items: [
{
title: "Kathoccino",
- description: "Brunchgruppe für Jungerwachsene",
+ description: "Brunchgruppe für junge Erwachsene",
href: "/gruppe/kathocchino"
},
{
@@ -127,7 +127,7 @@ export default function RootLayout({
},
groups: [
{
- title: "Sakramenten",
+ title: "Sakramente",
items: [
{
title: "Taufe",
@@ -146,7 +146,7 @@ export default function RootLayout({
},
{
title: "Ehe",
- description: "Bund in Liebe, Treue",
+ description: "Bund in Liebe und Treue",
href: "/sakramente/ehe"
},
{
@@ -196,7 +196,7 @@ export default function RootLayout({
items: [
{
title: "Alphakurs",
- description: "Freude am glauben entdecken",
+ description: "Freude am Glauben entdecken",
href: "/gruppe/alphakurs"
},
{
@@ -228,11 +228,11 @@ export default function RootLayout({
{
href: '/gruppe/waermestube',
title: 'Wärmestube',
- description: 'Kälteschutz für Bedurftigen',
+ description: 'Kälteschutz für Bedurftige',
},
{
href: '/gruppe/essen-ist-fertig',
- title: 'Essen ist Fertig',
+ title: 'Essen ist fertig',
description: 'Essensausgabe Neukölln',
},
{
@@ -252,8 +252,8 @@ export default function RootLayout({
},
{
href: '/gruppe/die-unterstuetzer',
- title: 'Anpacken & gutes tun',
- description: 'Kinderbertreuung, Hilfe bei.., Kirchenreinigung',
+ title: 'Anpacken & Gutes tun',
+ description: 'Hilfe bei Kirchenreinigung und anderem',
},
]
}
diff --git a/src/app/veranstaltungen/[id]/page.tsx b/src/app/veranstaltungen/[id]/page.tsx
index 864c3bd..712e4b3 100644
--- a/src/app/veranstaltungen/[id]/page.tsx
+++ b/src/app/veranstaltungen/[id]/page.tsx
@@ -3,6 +3,8 @@ import { Event } from '@/payload-types'
import { EventPage } from '@/pageComponents/Event/Event'
import { stringify } from 'qs-esm'
import { getPhoto } from '@/utils/dto/gallery'
+import { cookies } from 'next/headers'
+import { isAuthenticated } from '@/utils/auth'
export default async function Page({ params }: { params: Promise<{id: string}>}) {
@@ -33,12 +35,15 @@ export default async function Page({ params }: { params: Promise<{id: string}>})
notFound()
}
+ const authenticated = await isAuthenticated();
+
const event = await res.json() as Event;
const group = Array.isArray(event.group) && event.group.length > 0 && typeof event.group[0] == "object" ? event.group[0].slug : undefined;
const photo = getPhoto("tablet", event.photo);
return (
})
rsvpLink={event.rsvpLink || undefined}
flyer={typeof event.flyer === 'object' ? event.flyer || undefined : undefined}
photo={photo}
+ isAuthenticated={authenticated}
/>
)
}
\ No newline at end of file
diff --git a/src/app/veranstaltungen/page.tsx b/src/app/veranstaltungen/page.tsx
index 61af9e3..b3a5064 100644
--- a/src/app/veranstaltungen/page.tsx
+++ b/src/app/veranstaltungen/page.tsx
@@ -13,12 +13,15 @@ import { Row } from '@/components/Flex/Row'
import { Col } from '@/components/Flex/Col'
import { highlightLink } from '@/utils/dto/highlight'
import Error from '@/pages/_error'
+import { AdminMenu } from '@/components/AdminMenu/AdminMenu'
+import { isAuthenticated } from '@/utils/auth'
export default async function EventsPage({searchParams}: {
searchParams: Promise<{ week: string | undefined }>
}) {
+ const authenticated = await isAuthenticated();
const query = await searchParams;
const limit = 100;
let week = query.week;
@@ -116,6 +119,10 @@ export default async function EventsPage({searchParams}: {
+
{/*prevents bots indexing till infinity*/}
{ events.length > 0 &&
diff --git a/src/components/AdminMenu/AdminMenu.tsx b/src/components/AdminMenu/AdminMenu.tsx
new file mode 100644
index 0000000..da6234b
--- /dev/null
+++ b/src/components/AdminMenu/AdminMenu.tsx
@@ -0,0 +1,26 @@
+import styles from "./styles.module.scss"
+
+type AdminEditButtonProps = {
+ collection: string,
+ id?: string,
+ isAuthenticated: boolean,
+}
+
+export const AdminMenu = ({ collection, id, isAuthenticated}: AdminEditButtonProps) => {
+
+ if(!isAuthenticated)
+ return null;
+
+ return (
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/AdminMenu/styles.module.scss b/src/components/AdminMenu/styles.module.scss
new file mode 100644
index 0000000..f0f9a58
--- /dev/null
+++ b/src/components/AdminMenu/styles.module.scss
@@ -0,0 +1,19 @@
+.menu {
+ position: fixed;
+ bottom: 0;
+ width: 100%;
+ box-sizing: border-box;
+ left: 0;
+ background-color: rgba(238, 238, 238, 0.60);
+ backdrop-filter: blur(8px);
+ display: flex;
+ gap: 20px;
+ justify-content: flex-end;
+ padding-right: 20px;
+}
+
+.menu a {
+ padding: 10px 0;
+ font-size: 14px;
+ color: #23362c;
+}
\ No newline at end of file
diff --git a/src/compositions/Footer/Footer.tsx b/src/compositions/Footer/Footer.tsx
index 9b0daf0..f5bc3df 100644
--- a/src/compositions/Footer/Footer.tsx
+++ b/src/compositions/Footer/Footer.tsx
@@ -31,7 +31,7 @@ export const Footer = () => {
- Kontakt
- - Gottesdiensten
+ - Gottesdienste
- Datenschutz
- Schutzkonzept
- Impressum
diff --git a/src/pageComponents/Event/Event.stories.tsx b/src/pageComponents/Event/Event.stories.tsx
index dcbb9d4..b889e1e 100644
--- a/src/pageComponents/Event/Event.stories.tsx
+++ b/src/pageComponents/Event/Event.stories.tsx
@@ -11,6 +11,7 @@ export default meta
export const Default: Story = {
args: {
+ id: "testid",
title: "Sing & Pray",
date: "2024-12-02T09:21:19Z",
createdAt: "2024-12-02T09:21:19Z",
diff --git a/src/pageComponents/Event/Event.tsx b/src/pageComponents/Event/Event.tsx
index 45a5ca2..1e13861 100644
--- a/src/pageComponents/Event/Event.tsx
+++ b/src/pageComponents/Event/Event.tsx
@@ -15,8 +15,10 @@ import { StaticImageData } from 'next/image'
import { locationString } from '@/utils/dto/location'
import { ContactPerson2 } from '@/components/ContactPerson2/ContactPerson2'
import { getPhoto } from '@/utils/dto/gallery'
+import { AdminMenu } from '@/components/AdminMenu/AdminMenu'
type EventProps = {
+ id: string,
title: string,
date: string,
createdAt: string,
@@ -29,11 +31,13 @@ type EventProps = {
group?: string,
flyer?: Document,
photo?: StaticImageData,
- rsvpLink?: string
+ rsvpLink?: string,
+ isAuthenticated: boolean
}
export function EventPage(
{
+ id,
title,
date,
createdAt,
@@ -46,7 +50,8 @@ export function EventPage(
flyer,
group,
photo,
- rsvpLink
+ rsvpLink,
+ isAuthenticated
}: EventProps
) {
const published = useDate(createdAt)
@@ -165,6 +170,11 @@ export function EventPage(
+
>
)
}
\ No newline at end of file
diff --git a/src/utils/auth.ts b/src/utils/auth.ts
new file mode 100644
index 0000000..1db3b39
--- /dev/null
+++ b/src/utils/auth.ts
@@ -0,0 +1,18 @@
+import { cookies } from 'next/headers'
+
+/**
+ * Check if the current user is (trying to be) authenticated by
+ * checking if the `payload-token` is present.
+ *
+ * Warning: DO NOT USE THIS FUNCTION TO SECURE PARTS OF THE APPLICATION
+ */
+export const isAuthenticated = async (): Promise => {
+ const cookieStore = await cookies();
+ const token = cookieStore.get("payload-token");
+
+ if(typeof token === "undefined") {
+ return false;
+ }
+
+ return true;
+}
\ No newline at end of file