feature: admin menu
This commit is contained in:
parent
8f90781acc
commit
81614e4449
15 changed files with 169 additions and 26 deletions
|
|
@ -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
|
|||
</Section>
|
||||
|
||||
<Blocks content={data.content} />
|
||||
<AdminMenu
|
||||
collection={"worship"}
|
||||
id={id}
|
||||
isAuthenticated={authenticated}
|
||||
/>
|
||||
|
||||
</>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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<string, string> = {
|
||||
"01": "Januar",
|
||||
|
|
@ -105,6 +107,8 @@ export default async function PrayerIntentionPage({ params }: { params: Promise<
|
|||
notFound();
|
||||
}
|
||||
|
||||
const authenticated = await isAuthenticated()
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader
|
||||
|
|
@ -138,6 +142,11 @@ export default async function PrayerIntentionPage({ params }: { params: Promise<
|
|||
}}
|
||||
/>
|
||||
</Section>
|
||||
<AdminMenu
|
||||
collection={"popePrayerIntentions"}
|
||||
id={prayer.id}
|
||||
isAuthenticated={authenticated}
|
||||
/>
|
||||
</>
|
||||
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<Parish
|
||||
title={name}
|
||||
slug={slug}
|
||||
image={typeof photo === "string" ? photo : photo.url || "notfound"}
|
||||
description={description}
|
||||
history={history}
|
||||
contactPersons={contactPersons || []}
|
||||
contact={contact}
|
||||
events={events?.docs || []}
|
||||
worship={worship?.docs || []}
|
||||
announcement={announcement && typeof announcement.document === "object" ? announcement.document.url || undefined : undefined}
|
||||
calendar={calendar && typeof calendar.document === "object" ? calendar.document.url || undefined : undefined}
|
||||
gallery={gallery ? transformGallery(gallery) : undefined}
|
||||
/>
|
||||
<>
|
||||
<Parish
|
||||
title={name}
|
||||
slug={slug}
|
||||
image={typeof photo === "string" ? photo : photo.url || "notfound"}
|
||||
description={description}
|
||||
history={history}
|
||||
contactPersons={contactPersons || []}
|
||||
contact={contact}
|
||||
events={events?.docs || []}
|
||||
worship={worship?.docs || []}
|
||||
announcement={announcement && typeof announcement.document === "object" ? announcement.document.url || undefined : undefined}
|
||||
calendar={calendar && typeof calendar.document === "object" ? calendar.document.url || undefined : undefined}
|
||||
gallery={gallery ? transformGallery(gallery) : undefined}
|
||||
/>
|
||||
<AdminMenu
|
||||
collection={"parish"}
|
||||
id={id}
|
||||
isAuthenticated={authenticated}
|
||||
/>
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
|
|
@ -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 (
|
||||
<Worship worship={worship} />
|
||||
<>
|
||||
<Worship
|
||||
worship={worship}
|
||||
/>
|
||||
<AdminMenu
|
||||
collection={"worship"}
|
||||
id={worship.id}
|
||||
isAuthenticated={authenticated}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
@ -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}: {
|
|||
}
|
||||
</Container>
|
||||
</Section>
|
||||
<AdminMenu
|
||||
collection={"worship"}
|
||||
isAuthenticated={authenticated}
|
||||
/>
|
||||
|
||||
{events.length > 0 &&
|
||||
<Section padding={"small"}>
|
||||
|
|
|
|||
|
|
@ -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 &&
|
||||
<Blocks content={content} />
|
||||
}
|
||||
|
||||
<AdminMenu
|
||||
collection={"group"}
|
||||
id={id}
|
||||
isAuthenticated={authenticated}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
@ -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',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<EventPage
|
||||
id={event.id}
|
||||
title={event.title}
|
||||
date={event.date}
|
||||
createdAt={event.createdAt}
|
||||
|
|
@ -52,6 +57,7 @@ export default async function Page({ params }: { params: Promise<{id: string}>})
|
|||
rsvpLink={event.rsvpLink || undefined}
|
||||
flyer={typeof event.flyer === 'object' ? event.flyer || undefined : undefined}
|
||||
photo={photo}
|
||||
isAuthenticated={authenticated}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
@ -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}: {
|
|||
</Row>
|
||||
</Container>
|
||||
</Section>
|
||||
<AdminMenu
|
||||
collection={"event"}
|
||||
isAuthenticated={authenticated}
|
||||
/>
|
||||
|
||||
{/*prevents bots indexing till infinity*/}
|
||||
{ events.length > 0 &&
|
||||
|
|
|
|||
26
src/components/AdminMenu/AdminMenu.tsx
Normal file
26
src/components/AdminMenu/AdminMenu.tsx
Normal file
|
|
@ -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 (
|
||||
<div className={styles.menu}>
|
||||
<a href={`/admin`}>Admin</a>
|
||||
<a href={`/admin/collections/${collection}/create`}>Neu erstellen</a>
|
||||
{id &&
|
||||
<a href={`/admin/collections/${collection}/${id}`}>Bearbeiten</a>
|
||||
|
||||
}
|
||||
<a href={`/admin/logout`}>Abmelden</a>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
19
src/components/AdminMenu/styles.module.scss
Normal file
19
src/components/AdminMenu/styles.module.scss
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ export const Footer = () => {
|
|||
</p>
|
||||
<ul className={styles.list}>
|
||||
<li><Link href={"/kontakt"}>Kontakt</Link></li>
|
||||
<li><Link href={"/gottesdienst"}>Gottesdiensten</Link></li>
|
||||
<li><Link href={"/gottesdienst"}>Gottesdienste</Link></li>
|
||||
<li><Link href={"/datenschutz"}>Datenschutz</Link></li>
|
||||
<li><Link href={"/schutzkonzept"}>Schutzkonzept</Link></li>
|
||||
<li><Link href={"/impressum"}>Impressum</Link></li>
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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(
|
|||
|
||||
</Section>
|
||||
<Section/>
|
||||
<AdminMenu
|
||||
collection={"event"}
|
||||
id={id}
|
||||
isAuthenticated={isAuthenticated}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
18
src/utils/auth.ts
Normal file
18
src/utils/auth.ts
Normal file
|
|
@ -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<boolean> => {
|
||||
const cookieStore = await cookies();
|
||||
const token = cookieStore.get("payload-token");
|
||||
|
||||
if(typeof token === "undefined") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Loading…
Reference in a new issue