Creating a custom calendar component
Author
james
Date Published

Forms are easily the most overlooked / misunderstood chapters in UX. With little action and knowledge of the DOM, you can perform surgery on a database if executed correctly, done properly it can cost million.
Simplified we are adding a pre made component to our site and displaying it on the front end to clients in order to request a booking
ReadΒ case study
Innovative client delivering prescribed medication according to a schedule
Step 2

Form submissions
Add the Shadcn premade component to your site in order to display it on front end
npm add shadcn-calendar
|_ π app
| |_ π components
| | |_ π ui
| | | |_ π card.tsx
| | | |_ π calendar.tsx
|_ π collections
|_ π fields
|_ π paylaod types.ts
|_ π payload.config.ts

Drag the calendar block into the from builder
1'use client'23import * as React from 'react'4import { ChevronLeft, ChevronRight } from 'lucide-react'5import { DayPicker } from 'react-day-picker'67import { cn } from '@/utilities/cn'8import { buttonVariants } from '@/components/ui/button'910export type CalendarProps = React.ComponentProps<typeof DayPicker>1112function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) {13 return (14 <DayPicker15 showOutsideDays={showOutsideDays}16 className={cn('p-3', className)}17 classNames={{18 months: 'flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0',19 month: 'space-y-4',20 caption: 'flex justify-center pt-1 relative items-center',21 caption_label: 'text-sm font-medium',22 nav: 'space-x-1 flex items-center',23 nav_button: cn(24 buttonVariants({ variant: 'outline' }),25 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',26 ),27 nav_button_previous: 'absolute left-1',28 nav_button_next: 'absolute right-1',29 table: 'w-full border-collapse space-y-1',30 head_row: 'flex',31 head_cell: 'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]',32 row: 'flex w-full mt-2',33 cell: 'h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20',34 day: cn(35 buttonVariants({ variant: 'ghost' }),36 'h-9 w-9 p-0 font-normal aria-selected:opacity-100',37 ),38 day_range_end: 'day-range-end',39 day_selected:40 'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',41 day_today: 'bg-accent text-accent-foreground',42 day_outside:43 'day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground',44 day_disabled: 'text-muted-foreground opacity-50',45 day_range_middle: 'aria-selected:bg-accent aria-selected:text-accent-foreground',46 day_hidden: 'invisible',47 ...classNames,48 }}49 components={{50 IconLeft: ({ className, ...props }) => (51 <ChevronLeft className={cn('h-4 w-4', className)} {...props} />52 ),53 IconRight: ({ className, ...props }) => (54 <ChevronRight className={cn('h-4 w-4', className)} {...props} />55 ),56 }}57 {...props}58 />59 )60}61Calendar.displayName = 'Calendar'6263export { Calendar }64
Submitting a booking including the user id using a hook
|_ π src
| |_ π components
| |_ π hooks
| | |_ π addCustomerIdToForm.ts
| | |_ π formatSlug.ts
| |_ π plugins
| |_ π providers
|_ π collections
|_ π fields
|_ π paylaod types.ts
|_ π payload.config.ts
1import { CollectionBeforeValidateHook } from 'payload'23// This hook will add the customer ID to the form if the user is logged in.4// FormIds are the id of forms for which this hook should run.5export const addCustomerToForm =6 (formIds: string[]): CollectionBeforeValidateHook =>7 ({ data, req: { user, payload } }) => {8 if (data && typeof data === 'object' && 'form' in data && formIds.includes(data.form) && user) {9 payload.logger.info(10 `User is logged in, adding customer to form. FormID: ${data.form}, CustomerID: ${user?.id}, SubmissionID: ${data?.id}`,11 )12 data.customer = user?.id13 }1415 console.log(data)16 return data17 }18
Create a form in payload and send a test message. you should see a form entry now includes the user who submitted the booking request using the hook which you can create a booking from manually

Coded theme examples. Customise the branding and initiate image storage. Own your own design system

Creating, reading and updating the bookings collection depending on the role of the user