Overview
React TypeScript project that uses a React Scheduler component to display reservations for multiple locations
The TypeScript definitions provide real-time code completion (including suggestions and type checks) in your IDE (e.g. Visual Studio, IntelliJ WebStorm)
Reservation locations are displayed on the vertical axis
Includes a trial version of DayPilot Pro for JavaScript (see License below)
License
Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript.
New React Project with TypeScript Support
Lets start with creating a new React project using create-react-app
. The --template typescript
switch will add TypeScript support to our new React project.
npx create-react-app my-app --template typescript
When using the --typescript template
switch the project source code files will end with *.tsx
instead of *.js
and the TypeScript code will be automatically compiled during builds.
Creating a React Scheduler Component in TypeScript
In order to create the Scheduler component that will display and manage our reservations it is necessary to import daypilot-pro-react
package. This package includes a React version of DayPilot Pro for JavaScript and it includes the React Scheduler component which will help us create the reservation UI.
The daypilot-pro-react
package is hosted at npm.daypilot.org and we can add it to our project using npm
:
npm install https://npm.daypilot.org/daypilot-pro-react/trial/2023.2.5582.tar.gz
Now we can create a functional React component (with Hooks API) that will wrap DayPilot Scheduler:
src/scheduler/Scheduler.tsx
import React, { FC } from 'react';
import { DayPilotScheduler } from "daypilot-pro-react";
interface SchedulerProps {}
const Scheduler: FC<SchedulerProps> = () => {
return <DayPilotScheduler />;
}
export default Scheduler;
We can add our Scheduler component to App.tsx
to test it:
src/App.tsx
import React from 'react';
import './App.css';
import Scheduler from "./scheduler/Scheduler";
const App: React.FC = () => {
return (
<div>
<Scheduler />
</div>
);
}
export default App;
It doesn't display much at this moment but we got it working!
Displaying Locations on the Y Axis
Now that our Scheduler is initialized we can start adding features.
The first thing to configure is the Y axis which will display the reservation locations. In the Scheduler component, the rows are defined using resources property and this property is also available in the React component. So lets load the resources as a static array first:
import React, { FC } from 'react';
import { DayPilotScheduler } from "daypilot-pro-react";
interface SchedulerProps {}
const Scheduler: FC<SchedulerProps> = () => {
return (
<DayPilotScheduler
resources={[
{name: "Location A", id: "A"},
{name: "Location B", id: "B"},
{name: "Location C", id: "C"},
{name: "Location D", id: "D"},
{name: "Location E", id: "E"},
{name: "Location F", id: "F"},
]}
/>
);
}
export default Scheduler;
If you open the React web application in the browser now you will see the rows with our locations:
Defining the Time Axis of the Scheduler
By default, the Scheduler displays a single day and one cell per hour. The default start of the time line is today.
We want it to show the full year and one cell per day instead. This can be set using startDate, days, and scale properties. Lets also adjust the time headers on the X axis using timeHeaders property:
import React, { FC } from 'react';
import { DayPilotScheduler } from "daypilot-pro-react";
interface SchedulerProps {}
const Scheduler: FC<SchedulerProps> = () => {
return (
<DayPilotScheduler
startDate={"2023-01-01"}
days={365}
scale={"Day"}
timeHeaders={[
{groupBy: "Month"},
{groupBy: "Day", format: "d"}
]}
resources={[
{name: "Location A", id: "A"},
{name: "Location B", id: "B"},
{name: "Location C", id: "C"},
{name: "Location D", id: "D"},
{name: "Location E", id: "E"},
{name: "Location F", id: "F"},
]}
/>
);
}
export default Scheduler;
Our updated reservation scheduler looks like this now:
Loading Reservations
The last step of this tutorial will be adding the reservation data that will be displayed in the Scheduler grid.
The reservations are defined using the events
attribute of the Scheduler component:
import React, { FC } from 'react';
import { DayPilotScheduler } from "daypilot-pro-react";
interface SchedulerProps {}
const Scheduler: FC<SchedulerProps> = () => {
return (
<DayPilotScheduler
startDate={"2023-01-01"}
days={365}
scale={"Day"}
timeHeaders={[
{groupBy: "Month"},
{groupBy: "Day", format: "d"}
]}
resources={[
{name: "Location A", id: "A"},
{name: "Location B", id: "B"},
{name: "Location C", id: "C"},
{name: "Location D", id: "D"},
{name: "Location E", id: "E"},
{name: "Location F", id: "F"},
]}
events={[
{
id: 1,
text: "Reservation 1",
start: "2023-11-03T00:00:00",
end: "2023-11-09T00:00:00",
resource: "A",
barColor: "#3d85c6"
},
{
id: 2,
text: "Reservation 2",
start: "2023-11-04T00:00:00",
end: "2023-11-08T00:00:00",
resource: "C",
barColor: "#38761d"
}
]}
/>
);
}
export default Scheduler;
You can see that the reservations are now displayed in the matching rows:
Full TypeScript Source Code
Here is the full TypeScript source code of our Scheduler component:
import React, { useState, useEffect, useRef } from 'react';
import { DayPilot, DayPilotScheduler } from "daypilot-pro-react";
const Scheduler: React.FC = () => {
const [config, setConfig] = useState<DayPilot.SchedulerConfig>({
startDate: "2023-01-01",
days: 365,
scale: "Day",
eventHeight: 50,
timeHeaders: [
{ groupBy: "Month" },
{ groupBy: "Day", format: "d" }
],
cellWidth: 50,
resources: [
{ name: "Location A", id: "A" },
{ name: "Location B", id: "B" },
{ name: "Location C", id: "C" },
{ name: "Location D", id: "D" },
{ name: "Location E", id: "E" },
{ name: "Location F", id: "F" },
],
events: [
{
id: 1,
text: "Reservation 1",
start: "2023-11-03T00:00:00",
end: "2023-11-09T00:00:00",
resource: "A",
barColor: "#3d85c6"
},
{
id: 2,
text: "Reservation 2",
start: "2023-11-04T00:00:00",
end: "2023-11-08T00:00:00",
resource: "C",
barColor: "#38761d"
},
{
id: 3,
text: "Reservation 3",
start: "2023-11-02T00:00:00",
end: "2023-11-05T00:00:00",
resource: "D",
barColor: "#f1c232"
},
{
id: 4,
text: "Reservation 4",
start: "2023-11-03T00:00:00",
end: "2023-11-06T00:00:00",
resource: "E",
barColor: "#cc0000"
}
],
onEventMoved: async (args: DayPilot.SchedulerEventMovedArgs) => {
schedulerRef.current!.control.message("Event moved: " + args.e.data.text);
},
onEventResized: async (args: DayPilot.SchedulerEventResizedArgs) => {
schedulerRef.current!.control.message("Event resized: " + args.e.data.text);
},
onTimeRangeSelected: async (args: DayPilot.SchedulerTimeRangeSelectedArgs) => {
const modal = await DayPilot.Modal.prompt("New reservation:", "Reservation");
schedulerRef.current!.control.clearSelection();
if (modal.canceled) {
return;
}
schedulerRef.current!.control.events.add({
id: DayPilot.guid(),
text: modal.result,
start: args.start,
end: args.end,
resource: args.resource
});
},
onEventClicked: async (args: any) => {
let e = args.e;
const modal = await DayPilot.Modal.prompt("Edit reservation:", e.data.text);
schedulerRef.current!.control.clearSelection();
if (modal.canceled) {
return;
}
e.data.text = modal.result;
schedulerRef.current!.control.events.update(e);
}
});
const schedulerRef = useRef<DayPilotScheduler>(null);
useEffect(() => {
if (schedulerRef.current) {
schedulerRef.current.control.scrollTo("2023-11-01");
}
}, []);
return (
<div>
<DayPilotScheduler
{...config}
ref={schedulerRef}
/>
</div>
);
}
export default Scheduler;
History
May 29, 2023: Upgraded to React 18, Hooks API, DayPilot Pro 2023.2.5582
December 16, 2020: Upgraded to React 17, DayPilot Pro 2020.4.4817
October 1, 2019: Initial release. React 16.