Skip to content
This repository was archived by the owner on Oct 9, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
166 changes: 152 additions & 14 deletions src/_payload/collections/Forms.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
import { CollectionConfig, Field } from "payload";
import { cancellationEmailContentField, confirmationEmailContentField } from "../globals/EmailTemplates";
import { UserConfirmationRequired } from "./UserConfirmationRequired";
import { getPayload } from "payload";
import config from '@payload-config';
import { CollectionConfig, Field } from 'payload'
import {
cancellationEmailContentField,
confirmationEmailContentField,
} from '../globals/EmailTemplates'
import { UserConfirmationRequired } from './UserConfirmationRequired'
import { getPayload } from 'payload'
import config from '@payload-config'
import { Form } from '@/payload-types'

export const Forms: Omit<CollectionConfig, 'fields' | 'slug'> & { fields: (args: { defaultFields: Field[] }) => Field[] } = {
export const Forms: Omit<CollectionConfig, 'fields' | 'slug'> & {
fields: (args: { defaultFields: Field[] }) => Field[]
} = {
fields: ({ defaultFields }) => {
const emailField = defaultFields[defaultFields.length - 1]
const confirmationFields = defaultFields.slice(3, -1)
const otherFields = defaultFields.slice(0, 3)
const [titleField, ...otherFields] = defaultFields.slice(0, 3)

const getDefaultEmailContent = (type: 'confirmation' | 'cancellation') => async () => {
try {
const payload = await getPayload({ config })
const emailTemplates = await payload.findGlobal({
slug: 'email-templates'
slug: 'email-templates',
})
return type === 'confirmation' ? emailTemplates.confirmationEmail : emailTemplates.cancellationEmail
return type === 'confirmation'
? emailTemplates.confirmationEmail
: emailTemplates.cancellationEmail
} catch (err) {
console.error(`Error getting ${type} email content:`, err)
return null
Expand All @@ -26,15 +34,119 @@ export const Forms: Omit<CollectionConfig, 'fields' | 'slug'> & { fields: (args:
const getDefaultConfirmationEmailContent = getDefaultEmailContent('confirmation')
const getDefaultCancellationEmailContent = getDefaultEmailContent('cancellation')
return [
...otherFields,
titleField,
{
name: 'basicInformation',
type: 'group',
name: 'confirmation',
label: 'Basic Information',
fields: [
...confirmationFields,
UserConfirmationRequired,
{
type: 'row',
fields: [
{
name: 'visible',
type: 'checkbox',
label: 'Visible',
defaultValue: true,
admin: {
description: 'If the form is visible, it will be displayed in the event list.',
},
},
{
name: 'active',
type: 'checkbox',
label: 'Active',
defaultValue: true,
admin: {
width: '50%',
},
},
],
},
{
name: 'statusMessage',
type: 'text',
label: 'Status Message',
admin: {
description:
'This message will be displayed underneath to the form in the event list.',
},
},
{
type: 'row',
fields: [
{
type: 'group',
name: 'start',
label: '',
fields: [
{
name: 'date',
type: 'date',
label: 'Start Date',
admin: {
width: '50%',
date: {
pickerAppearance: 'dayAndTime',
displayFormat: 'MMM d, yyyy h:mma',
},
},
validate: (val, { data }: { data: Form }) => {
if (!val) return true
if (data.basicInformation?.end?.skip) return true
const start = new Date(val)
const end = new Date(data.basicInformation?.end?.date as string)

if (start > end) {
return 'Start date must be before end date'
}
return true
},
},
],
admin: {
width: '50%',
}
},
{
type: 'group',
name: 'end',
label: '',
fields: [
{
name: 'date',
type: 'date',
label: 'End Date',
admin: {
date: {
pickerAppearance: 'dayAndTime',
displayFormat: 'MMM d, yyyy h:mma',
},
description:
'After end date, form will be automatically set to hidden and inactive.',
},
},
{
name: 'skip',
type: 'checkbox',
label: 'No End Date',
defaultValue: false,
},
],
admin: {
width: '50%',
}
},
],
},
],
},
...otherFields,
{
type: 'group',
name: 'confirmation',
fields: [...confirmationFields, UserConfirmationRequired],
},
emailField,
{
...confirmationEmailContentField,
Expand All @@ -56,4 +168,30 @@ export const Forms: Omit<CollectionConfig, 'fields' | 'slug'> & { fields: (args:
},
]
},
}
hooks: {
beforeRead: [
async ({ doc, req }) => {
if (doc.basicInformation?.dueDate && !doc.basicInformation.noDueDate) {
const now = new Date()
const dueDate = new Date(doc.basicInformation.dueDate)

if (now > dueDate) {
const updatedDoc = await req.payload.update({
collection: 'forms',
id: doc.id,
data: {
basicInformation: {
active: false,
visible: false,
},
},
})

return updatedDoc
}
}
return doc
},
],
},
}
7 changes: 7 additions & 0 deletions src/app/(app)/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getPayload } from 'payload'
import { Metadata } from 'next'
import Blocks from '../../../components/Blocks'
import { metadata } from '../metadata.constants'
import { Form } from '@/payload-types'

export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
const slug = (await params).slug
Expand All @@ -29,6 +30,12 @@ export default async function Page({ params }: { params: Promise<{ slug: string
return notFound()
}

const formBlock = page.layout.find((block) => block.blockType === 'formBlock')
const isFormVisible = (formBlock?.form as Form)?.basicInformation?.visible
if (!isFormVisible) {
return notFound()
}

return (
<React.Fragment>
<Blocks blocks={page.layout} />
Expand Down
30 changes: 30 additions & 0 deletions src/payload-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@ export interface Page {
export interface Form {
id: string;
title: string;
basicInformation?: {
visible?: boolean | null;
active?: boolean | null;
statusMessage?: string | null;
start?: {
date?: string | null;
};
end?: {
date?: string | null;
skip?: boolean | null;
};
};
fields?:
| (
| {
Expand Down Expand Up @@ -453,6 +465,24 @@ export interface UsersSelect<T extends boolean = true> {
*/
export interface FormsSelect<T extends boolean = true> {
title?: T;
basicInformation?:
| T
| {
visible?: T;
active?: T;
statusMessage?: T;
start?:
| T
| {
date?: T;
};
end?:
| T
| {
date?: T;
skip?: T;
};
};
fields?:
| T
| {
Expand Down