feat: header links driven by payload

This commit is contained in:
Yehoshua Sandler 2025-05-04 11:02:46 -05:00
parent 461df9d7ba
commit 014e3eaa7c
4 changed files with 44 additions and 31 deletions

View File

@ -1,5 +1,8 @@
import SiteNavigation from '@/components/SiteNavigation' import SiteNavigation from '@/components/SiteNavigation'
import React from 'react' import React from 'react'
import { getPayload } from 'payload'
import config from '@/payload.config'
import { Header } from '@/payload-types'
export const metadata = { export const metadata = {
description: 'House of Study for Temple Beth El', description: 'House of Study for Temple Beth El',
@ -9,5 +12,19 @@ export const metadata = {
export default async function RootLayout(props: { children: React.ReactNode }) { export default async function RootLayout(props: { children: React.ReactNode }) {
const { children } = props const { children } = props
return <SiteNavigation>{children}</SiteNavigation> const payloadConfig = await config
const payload = await getPayload({ config: payloadConfig })
const headerGlobals = (await payload.findGlobal({
slug: 'header',
})) as Header
const navItems =
headerGlobals.headerLinks?.map((l) => ({
label: l.label || '',
href: l.href || '',
newTab: l.newTab || false,
})) || []
return <SiteNavigation navItems={navItems}>{children}</SiteNavigation>
} }

View File

@ -28,21 +28,24 @@ import {
import { StackedLayout } from '@/components/stacked-layout' import { StackedLayout } from '@/components/stacked-layout'
import { Media } from '@/payload-types' import { Media } from '@/payload-types'
import { useGlobal } from '@/providers/GlobalProvider' import { useGlobal } from '@/providers/GlobalProvider'
import { ArrowRightStartOnRectangleIcon, LightBulbIcon, UserIcon } from '@heroicons/react/16/solid' import { ArrowRightStartOnRectangleIcon, UserIcon } from '@heroicons/react/16/solid'
import { MagnifyingGlassIcon, SunIcon, MoonIcon } from '@heroicons/react/20/solid' import { MagnifyingGlassIcon, SunIcon, MoonIcon } from '@heroicons/react/20/solid'
import { useTheme } from 'next-themes' import { useTheme } from 'next-themes'
import Link from 'next/link' import Link from 'next/link'
import React, { useMemo } from 'react' import React, { ReactNode, useMemo } from 'react'
const navItems = [ type NavItem = {
{ label: 'Home', url: '/' }, label: string
{ label: 'Browse', url: '/books' }, href: string
{ label: 'Events', url: '/events' }, newTab: boolean
{ label: 'Settings', url: '/settings' }, }
]
export default function SiteNavigation(props: { children: React.ReactNode }) { type Props = {
const { children } = props children: ReactNode
navItems: NavItem[]
}
export default function SiteNavigation(props: Props) {
const { children, navItems } = props
const { theme, setTheme } = useTheme() const { theme, setTheme } = useTheme()
const { user, setUser } = useGlobal() const { user, setUser } = useGlobal()
@ -70,19 +73,17 @@ export default function SiteNavigation(props: { children: React.ReactNode }) {
navbar={ navbar={
<Navbar> <Navbar>
<Dropdown> <Dropdown>
<DropdownButton <DropdownButton as={NavbarItem} className="max-lg:hidden">
as={NavbarItem} <Link href="/" className="flex items-center justify-around gap-3">
onClick={() => (window.location.href = '/')} <Avatar src="/api/media/file/bethel-logo.jpg" className="size-8" />
className="max-lg:hidden"
>
<Avatar src="/api/media/file/bethel-logo.jpg" />
<NavbarLabel>Midrashim</NavbarLabel> <NavbarLabel>Midrashim</NavbarLabel>
</Link>
</DropdownButton> </DropdownButton>
</Dropdown> </Dropdown>
<NavbarDivider className="max-lg:hidden" /> <NavbarDivider className="max-lg:hidden" />
<NavbarSection className="max-lg:hidden"> <NavbarSection className="max-lg:hidden">
{navItems.map(({ label, url }) => ( {navItems.map(({ label, href, newTab }) => (
<NavbarItem key={label} href={url}> <NavbarItem key={label} target={newTab ? '_blank' : ''} href={href}>
{label} {label}
</NavbarItem> </NavbarItem>
))} ))}
@ -116,10 +117,6 @@ export default function SiteNavigation(props: { children: React.ReactNode }) {
<DropdownLabel>My profile</DropdownLabel> <DropdownLabel>My profile</DropdownLabel>
</DropdownItem> </DropdownItem>
)} )}
<DropdownItem href="/feedback">
<LightBulbIcon />
<DropdownLabel>Share feedback</DropdownLabel>
</DropdownItem>
{!!user && ( {!!user && (
<> <>
@ -149,8 +146,8 @@ export default function SiteNavigation(props: { children: React.ReactNode }) {
</SidebarHeader> </SidebarHeader>
<SidebarBody> <SidebarBody>
<SidebarSection> <SidebarSection>
{navItems.map(({ label, url }) => ( {navItems.map(({ label, href, newTab }) => (
<SidebarItem key={label} href={url}> <SidebarItem key={label} href={href} target={newTab ? '_blank' : ''}>
{label} {label}
</SidebarItem> </SidebarItem>
))} ))}

View File

@ -21,9 +21,8 @@ export const Header: GlobalConfig = {
type: 'text', type: 'text',
}, },
{ {
name: 'page', name: 'href',
type: 'relationship', type: 'text'
relationTo: 'pages'
}, },
{ {
name: 'newTab', name: 'newTab',

View File

@ -678,7 +678,7 @@ export interface Header {
headerLinks?: headerLinks?:
| { | {
label?: string | null; label?: string | null;
page?: (number | null) | Page; href?: string | null;
newTab?: boolean | null; newTab?: boolean | null;
id?: string | null; id?: string | null;
}[] }[]
@ -696,7 +696,7 @@ export interface HeaderSelect<T extends boolean = true> {
| T | T
| { | {
label?: T; label?: T;
page?: T; href?: T;
newTab?: T; newTab?: T;
id?: T; id?: T;
}; };