Skip to content
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
4b8ee59
Add events table component WIP
rchlfryn Nov 8, 2025
81f8d09
Add event table block
rchlfryn Nov 8, 2025
2438dfa
Add the ability to build out an events group page
rchlfryn Nov 10, 2025
122436b
Update table to be responsive
rchlfryn Nov 11, 2025
2f6631a
Change file name
rchlfryn Nov 11, 2025
10ef2e2
Update seed script for event group and event table
rchlfryn Nov 11, 2025
200506b
Move event group page to `/events/g/[slug]`
rchlfryn Nov 11, 2025
fa58802
Update breadcrumbs to ignore g
rchlfryn Nov 11, 2025
ad93fb0
Fix error: add key to fragment
rchlfryn Nov 11, 2025
1d4b0f5
Fix table on mobile view
rchlfryn Nov 11, 2025
c06499c
Fix seed file
rchlfryn Nov 11, 2025
17b4292
Move `validateMaxEvents` to reuse
rchlfryn Nov 11, 2025
533e384
Move `QueriedEventsComponent` to reuse
rchlfryn Nov 11, 2025
1cc78b1
Consolidate EventList and EventTable configs
rchlfryn Nov 11, 2025
5d9006a
Fix mobile expanded table
rchlfryn Nov 11, 2025
4a00681
Force dynamic for event group page
rchlfryn Nov 11, 2025
3fbf959
Add EventTable to other richText fields and add thumbnail
rchlfryn Nov 11, 2025
8d19360
Fix container class
rchlfryn Nov 11, 2025
8f74070
Add clickable title
rchlfryn Nov 11, 2025
1f63d5d
Update event group page top
rchlfryn Nov 11, 2025
ed6e615
Remove registration deadline
rchlfryn Nov 12, 2025
085aeee
Remove cost
rchlfryn Nov 12, 2025
fd41af4
Remove status column
rchlfryn Nov 12, 2025
70a11d4
Make title look clickable and update location info
rchlfryn Nov 12, 2025
01b12e2
Update registration button to be in accordion on small screens
rchlfryn Nov 12, 2025
e92b143
Make breakpoint for button smaller
rchlfryn Nov 12, 2025
1b43ed0
Fix z-index on group page
rchlfryn Nov 12, 2025
ba8c226
Move event query
rchlfryn Nov 13, 2025
595876e
Add tenant filter to groups and tags
rchlfryn Nov 13, 2025
da4f885
Remove events group page
rchlfryn Nov 13, 2025
4c53729
Update import map
rchlfryn Nov 13, 2025
0a21fe8
Remove sort field and add event tags and groups
rchlfryn Nov 13, 2025
d5cf47e
Fix seed script from page layout removal
rchlfryn Nov 13, 2025
57eb3dc
Merge branch 'events' into events-table
rchlfryn Nov 16, 2025
d7dd238
Update permissions and move events query to client
rchlfryn Nov 16, 2025
ac80dd1
Update component to use a hook to fetch events
rchlfryn Nov 16, 2025
417d26e
Add events table to blocks seed page
rchlfryn Nov 17, 2025
6b21c64
Remove showUpcomingOnly
rchlfryn Nov 17, 2025
50641a3
Revert group page removal changes
rchlfryn Nov 17, 2025
f20d8b8
Clean up event table - remove show more, open event registration in n…
rchlfryn Nov 17, 2025
0108f98
Create custom endpoint for event query
rchlfryn Nov 17, 2025
fa39d78
Update caching
rchlfryn Nov 17, 2025
ba36260
Remove path revalidation
rchlfryn Nov 17, 2025
361554b
Merge branch 'events' into events-table
rchlfryn Nov 17, 2025
a664a70
Rename events endpoint
rchlfryn Nov 17, 2025
5f2d833
WIP - fix events endpoint
rchlfryn Nov 18, 2025
a6a7e40
Consolidate events api route
rchlfryn Nov 20, 2025
34fb329
Remove queriedEvents & add startDate to params
rchlfryn Nov 20, 2025
5dfc45b
Remove complicated logic
rchlfryn Nov 20, 2025
2b6deca
Update events to check relationships
rchlfryn Nov 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/thumbnail/EventTableThumbnail.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 15 additions & 15 deletions src/app/(frontend)/[center]/events/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Redirects } from '@/components/Redirects'
import RichText from '@/components/RichText'
import configPromise from '@payload-config'
import { draftMode } from 'next/headers'
import { getPayload, Where } from 'payload'
import { getPayload } from 'payload'

import { EventInfo } from '@/components/EventInfo'
import { LivePreviewListener } from '@/components/LivePreviewListener'
Expand Down Expand Up @@ -166,19 +166,6 @@ const queryEventBySlug = async ({ center, slug }: { center: string; slug: string

const payload = await getPayload({ config: configPromise })

const conditions: Where[] = [
{
'tenant.slug': {
equals: center,
},
},
{
slug: {
equals: slug,
},
},
]

const result = await payload.find({
collection: 'events',
draft,
Expand All @@ -191,7 +178,20 @@ const queryEventBySlug = async ({ center, slug }: { center: string; slug: string
customDomain: true,
},
},
where: { and: conditions },
where: {
and: [
{
'tenant.slug': {
equals: center,
},
},
{
slug: {
equals: slug,
},
},
],
},
})

return result.docs?.[0] || null
Expand Down
3 changes: 0 additions & 3 deletions src/app/(payload)/admin/importMap.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { QueriedPostsComponent as QueriedPostsComponent_a2ad38d8499118f1bebc7752c0fff51e } from '@/blocks/BlogList/fields/QueriedPostsComponent'
import { DefaultColumnAdder as DefaultColumnAdder_006f8c6c8800e6fe3753b3785f2c4a01 } from '@/blocks/Content/components/DefaultColumnAdder'
import { QueriedEventsComponent as QueriedEventsComponent_65bd30cc675f775ebce6af07a79e525c } from '@/blocks/EventList/fields/QueriedEventsComponent'
import { SponsorsLayoutDescription as SponsorsLayoutDescription_6f00823041b5b0999b9929fb565110de } from '@/blocks/SponsorsBlock/components/SponsorsLayoutDescription'
import { CourseTypeField as CourseTypeField_348fff62462d32a00f93a0ac5be86e99 } from '@/collections/Courses/components/CourseTypeField'
import { DuplicatePageFor as DuplicatePageFor_8f1d8961a356bec6784e5c591c016925 } from '@/collections/Pages/components/DuplicatePageFor'
Expand Down Expand Up @@ -104,8 +103,6 @@ export const importMap = {
'@/components/ColumnLayoutPicker#default': default_923dc5ccc0b72de4298251644cbfe39e,
'@/blocks/Content/components/DefaultColumnAdder#DefaultColumnAdder':
DefaultColumnAdder_006f8c6c8800e6fe3753b3785f2c4a01,
'@/blocks/EventList/fields/QueriedEventsComponent#QueriedEventsComponent':
QueriedEventsComponent_65bd30cc675f775ebce6af07a79e525c,
'@payloadcms/plugin-seo/client#OverviewComponent':
OverviewComponent_a8a977ebc872c5d5ea7ee689724c0860,
'@payloadcms/plugin-seo/client#MetaImageComponent':
Expand Down
2 changes: 2 additions & 0 deletions src/blocks/Content/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ButtonBlock } from '../Button/config'
import { CalloutBlock } from '../Callout/config'
import { DocumentBlock } from '../DocumentBlock/config'
import { EventListBlockLexical } from '../EventList/config'
import { EventTableBlock } from '../EventTable/config'
import { GenericEmbedLexical } from '../GenericEmbed/config'
import { HeaderBlock } from '../Header/config'
import { MediaBlockLexical } from '../MediaBlock/config'
Expand Down Expand Up @@ -131,6 +132,7 @@ export const Content: Block = {
CalloutBlock,
DocumentBlock,
EventListBlockLexical,
EventTableBlock,
SingleEventBlockLexical,
GenericEmbedLexical,
HeaderBlock,
Expand Down
102 changes: 77 additions & 25 deletions src/blocks/EventList/Component.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,95 @@
'use client'

import { EventPreviewSmallRow } from '@/components/EventPreviewSmallRow'
import RichText from '@/components/RichText'
import { Button } from '@/components/ui/button'
import type { Event, EventListBlock as EventListBlockProps } from '@/payload-types'
import { useTenant } from '@/providers/TenantProvider'
import { cn } from '@/utilities/ui'
import { format } from 'date-fns'
import Link from 'next/link'
import { useEffect, useState } from 'react'

type EventListComponentProps = EventListBlockProps & {
className?: string
wrapInContainer?: boolean
}

export const EventListBlockComponent = async (args: EventListComponentProps) => {
const { heading, belowHeadingContent, backgroundColor, className, wrapInContainer = true } = args
export const EventListBlockComponent = (args: EventListComponentProps) => {
const {
heading,
belowHeadingContent,
backgroundColor,
className,
wrapInContainer = true,
eventOptions,
} = args

const { filterByEventTypes, sortBy, queriedEvents } = args.dynamicOptions || {}
const { filterByEventTypes, filterByEventGroups, filterByEventTags, maxEvents } =
args.dynamicOptions || {}
const { staticEvents } = args.staticOptions || {}

let events = staticEvents?.filter(
(event): event is Event => typeof event === 'object' && event !== null,
)
const { tenant } = useTenant()
const [fetchedEvents, setFetchedEvents] = useState<Event[]>([])
const [eventParams, setEventParams] = useState<string>('')

const hasStaticEvents = staticEvents && staticEvents.length > 0
useEffect(() => {
if (eventOptions !== 'dynamic') return

if (!staticEvents || (staticEvents.length === 0 && queriedEvents && queriedEvents.length > 0)) {
events = queriedEvents?.filter(
(event): event is Event => typeof event === 'object' && event !== null,
)
}
const fetchEvents = async () => {
const tenantSlug = typeof tenant === 'object' && tenant?.slug
if (!tenantSlug) return

const eventsLinkQueryParams = new URLSearchParams()
if (sortBy !== undefined) {
eventsLinkQueryParams.set('sort', sortBy)
}
const params = new URLSearchParams({
center: tenantSlug,
limit: String(maxEvents || 4),
depth: '1',
})

if (filterByEventTypes && filterByEventTypes.length > 0) {
eventsLinkQueryParams.set('types', filterByEventTypes.join(','))
}
if (filterByEventTypes?.length) {
params.append('types', filterByEventTypes.join(','))
}

if (filterByEventGroups?.length) {
const groupIds = filterByEventGroups
.map((g) => (typeof g === 'object' ? g.id : g))
.filter(Boolean)
if (groupIds.length) {
params.append('groups', groupIds.join(','))
}
}

if (filterByEventTags?.length) {
const tagIds = filterByEventTags
.map((t) => (typeof t === 'object' ? t.id : t))
.filter(Boolean)
if (tagIds.length) {
params.append('tags', tagIds.join(','))
}
}
params.append('startDate', format(new Date(), 'MM-dd-yyyy'))
setEventParams(params.toString())

const response = await fetch(`/api/${tenantSlug}/events?${params.toString()}`, {
cache: 'no-store',
})

if (!response.ok) {
throw new Error('Failed to fetch events')
}

const data = await response.json()
setFetchedEvents(data.events || [])
}

fetchEvents()
}, [eventOptions, filterByEventTypes, filterByEventGroups, filterByEventTags, maxEvents, tenant])

let displayEvents
if (eventOptions === 'static') displayEvents = staticEvents as Event[]
if (eventOptions === 'dynamic') displayEvents = fetchedEvents

if (!events) {
if (!displayEvents) {
return null
}

Expand All @@ -62,20 +114,20 @@ export const EventListBlockComponent = async (args: EventListComponentProps) =>
<div
className={cn(
'grid gap-4 lg:gap-6 not-prose max-h-[400px] overflow-y-auto',
events && events.length > 1 && '@3xl:grid-cols-2 @6xl:grid-cols-3',
displayEvents && displayEvents.length > 1 && '@3xl:grid-cols-2 @6xl:grid-cols-3',
)}
>
{events && events?.length > 0 ? (
events?.map((event, index) => (
{displayEvents && displayEvents?.length > 0 ? (
displayEvents?.map((event, index) => (
<EventPreviewSmallRow doc={event} key={`${event.id}__${index}`} />
))
) : (
<h3>There are no events matching these results.</h3>
)}
</div>
{!hasStaticEvents && (
{eventOptions === 'static' && (
<Button asChild className="not-prose md:self-start">
<Link href={`/events?${eventsLinkQueryParams.toString()}`}>View all {heading}</Link>
<Link href={`/events?${eventParams}`}>View all {heading}</Link>
</Button>
)}
</div>
Expand Down
Loading