diff --git a/src/_payload/collections/Forms.ts b/src/_payload/collections/Forms.ts index 786a615..4504031 100644 --- a/src/_payload/collections/Forms.ts +++ b/src/_payload/collections/Forms.ts @@ -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 & { fields: (args: { defaultFields: Field[] }) => Field[] } = { +export const Forms: Omit & { + 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 @@ -26,15 +34,119 @@ export const Forms: Omit & { 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, @@ -56,4 +168,30 @@ export const Forms: Omit & { fields: (args: }, ] }, -} \ No newline at end of file + 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 + }, + ], + }, +} diff --git a/src/app/(app)/[slug]/page.tsx b/src/app/(app)/[slug]/page.tsx index 933ecb5..5d2e0b3 100644 --- a/src/app/(app)/[slug]/page.tsx +++ b/src/app/(app)/[slug]/page.tsx @@ -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 { const slug = (await params).slug @@ -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 ( diff --git a/src/payload-types.ts b/src/payload-types.ts index 59efa52..f49e149 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -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?: | ( | { @@ -453,6 +465,24 @@ export interface UsersSelect { */ export interface FormsSelect { title?: T; + basicInformation?: + | T + | { + visible?: T; + active?: T; + statusMessage?: T; + start?: + | T + | { + date?: T; + }; + end?: + | T + | { + date?: T; + skip?: T; + }; + }; fields?: | T | {