The Simplest way to build reservation calendars on React with Gott Calendar UI

Atul Ranjan
5 min readSep 20, 2024

--

A Short Introduction and the Motivation

Building reservation calendars can especially be difficult in React, because of the nature of calendars itself. Calendars are one of those trivial things you don’t want to spend too much time on, so you start searching the web for packages with good calendars, and to your surprise, you find none.

When you sit down and start writing one yourself, you realize that building calendars is not as simple as they seem, especially one with all the logic required for your reservation system, and then you end up spending a lot of time on the trivial thing you wanted to avoid in the first place.

What I just described was exactly what happened to me, and led me to develop gott-calendar-ui. A complete UI component for all the kinds of calendars you are ever going to need in your project so you don’t have to waste time on it.

To get started, install gott-calendar-ui with npm or yarn.

npm install gott-calendar-ui
yarn add gott-calendar-ui

A Simple Reservation Calendar

You can build the reservation calendar with the SimpleReservationCalendar component. Here is an example of it

With this component you can:
1. Pass Reservation dates and timings that the component can display
2. Pass additional field names for any user who wishes to make a reservation.

First, let's set up some sample data for us to use in SimpleReservationCalendar

export const sampleReservationDates: ReservationDate[] = [
{
date: new Date(2024, 8, 20), // September 20, 2024
numSlots: 3,
timings: ["09:00 AM", "02:00 PM", "06:00 PM"],
},
{
date: new Date(2024, 8, 21), // September 21, 2024
numSlots: 2,
timings: ["10:00 AM", "03:00 PM"],
},
{
date: new Date(2024, 8, 23), // September 23, 2024
numSlots: 4,
timings: ["08:00 AM", "11:00 AM", "02:00 PM", "05:00 PM"],
},
];


export const sampleFormFields: FormData[] = [
{
name: "fullName",
labelName: "Full name",
placeholder: "Enter your full name",
},
{
name: "email",
labelName: "Email Address",
placeholder: "Enter your email address",
},
{
name: "organization",
labelName: "Organization",
placeholder: "Enter your organization name",
},
];

Implementing the component itself

import React from 'react';
import { SimpleReservationCalendar } from 'gott-calendar-ui';
import { sampleReservationDates, sampleFormFields } from './sampleData';

function App() {
const validateDate = (date) => {
// Custom date validation logic
const today = new Date();
return date >= today && date <= new Date(today.getFullYear(), today.getMonth() + 3, today.getDate());
};

const handleDateSelect = (date, timing) => {
console.log('Reservation selected for:', date, 'at', timing);
};

const handleError = (errorMessage) => {
// Display error in your preferred UI component
alert(errorMessage);
};

const handleFormSubmit = (formData) => {
console.log('Form submitted with data:', formData);
// Process the form data (e.g., send to backend)
};

const customProceed = () => {
console.log('Custom proceed action triggered');
// Implement your custom logic here
};

return (
<SimpleReservationCalendar
validateDateFunction={validateDate}
onDateSelect={handleDateSelect}
handleError={handleError}
errorMessage="Selected date is not available or out of range."
darkMode={false}
reservationDates={sampleReservationDates}
formFillData={sampleFormFields}
onFormFillAction={handleFormSubmit}
customProceedFunction={customProceed}
/>
);
}

export default App;

For Reference, these are the interfaces used by the component:

export interface ReservationDate {
date: Date;
numSlots: number;
timings?: string[];
}

export interface FormData {
name: string;
labelName: string;
placeholder: string;
}

interface SimpleReservationCalendarProps {
validateDateFunction: (date: Date) => boolean;
errorMessage: string;
handleError: (msg: string) => void;
darkMode?: boolean;
onDateSelect: (date: Date, timing?: string) => void;
reservationDates?: ReservationDate[];

// Function to execute when user has decided to
// make their custom function to proceed
customProceedFunction?: () => void;
// If no custom function is to be called, take in the
// form data from the user to display the form
formFillData?: FormData[];
// Function after the form is filled and needs to be executes
// The object should be of the format { formName: value }
onFormFillAction?: (formData: { [key: string]: string }) => {};
}

You can leave out the timings key in ReservationDate, when you do so, the timings section of the calendar won’t appear. Similarly, if you don’t want the user to fill a form, or implement a function on your own, you can implement the customProceedFunction, in which case you can implement your own logic after the user has picked out the date and time.

Implement the onFormFillAction function for actions you want to be accomplished upon submission of the reservation request.

In real scenarios, you would maybe get reservations from the database, and then pass on the data to this component.

A Simple Date Range Picker

The SimpleRangePicker component can be used when date ranges are to be picked. The implementation is quite straightforward:

import SimpleRangePicker from "./SimpleRangePicker";

const handleRangeSelection = (startDate, endDate) => {
console.log(`Selected range: ${startDate} to ${endDate}`);
};

const handleError = (msg) => {
console.error(msg);
};

const App = () => (
<SimpleRangePicker
validateDateFunction={(date) => date >= new Date()}
errorMessage="Selected date is in the past."
handleError={handleError}
validateRange={(startDate, endDate) => {
return true;
}}
rangeSelected={handleRangeSelection}
handleRangeInvalidError={(msg) => alert(msg)}
rangeInvalidErrorMessage="The selected range is too long."
darkMode={false}
/>
);

Implement the validateDateFunction and validateRange function to validate the selected date and selected date range respectively. Handle additional functionality with the rangeSelected function.

Finally, a Simple Calendar

The Simple Calendar component is all a simple calendar should be for React. It renders a calendar from which dates can be picked. Its implementation too, is quite straightforward.

const handleDateError = (msg: string) => {
console.error(msg);
};

const handleDateSelect = (date: Date) => {
console.log("Selected date:", date);
};

const App = () => (
<SimpleCalendar
validateDateFunction={(date) => date >= new Date()}
errorMessage="Selected date is in the past."
handleError={handleDateError}
handleDateSelect={handleDateSelect}
darkMode={true}
/>
);

Ending Notes

Gott Calendar UI is evolving to be a complete UI library for calendars for reservation systems, contributions are always welcome! The next step to this library is to build a functional website for documentation since one README is getting quite cluttered. Stay tuned for more updates!

For contributions:
https://github.com/Atul-Ranjan12/calendar-ui

If you like my work, or want to learn more, visit:
gottdata.com/blogs

Finally, drop me a line on:
https://www.linkedin.com/in/atul-ranjan-gott-data/

--

--

No responses yet