DEV Community

Bryntum for Bryntum

Posted on

Using Bryntum Calendar to Coordinate Caregiver Availability in Health Care

The Bryntum Calendar is a web component that you can use to display and manage calendar events. It has type definitions using TypeScript as well as a well-documented API, making it easy to integrate with popular libraries and frameworks, including React and Vue.js.

The Bryntum Calendar component is beneficial for project management applications that need to show users a project timeline or applications that need resource management with a calendar view. This includes applications providing health-care or home care services, where resource allocation and coordination are essential.

In this article, you'll build an application to coordinate caregiver availability for family members using React, Tailwind CSS, and the Bryntum Calendar component. While doing so, you'll learn about working with JSON data, creating stateful React components, and displaying events in a calendar view using the Bryntum Calendar.

Building the Caregiver Application

Before you begin this tutorial, you'll need Node.js version 14 or newer as well as npm version 6 or newer installed on your computer. You'll also need a code editor like Visual Studio Code.

You can follow along with this tutorial using this GitHub repository.

Set Up the Project

To begin, run the following command to create a new React project, caregiver-app, using create-react-app:

npx create-react-app caregiver-app
Enter fullscreen mode Exit fullscreen mode

Then change the directory to the newly created project:

cd caregiver-app
Enter fullscreen mode Exit fullscreen mode

Run the following command to install Tailwind CSS and its dependencies:

npm install -D tailwindcss postcss autoprefixer
Enter fullscreen mode Exit fullscreen mode

Next, run npx tailwindcss init -p to initialize Tailwind CSS in the project. This command will generate tailwind.config.js and postcss.config.js files, where you can configure color schemes and plug-ins.

Update the content list in the tailwind.config.js file to watch for Tailwind CSS class updates in all files:

/** @type {import('tailwindcss').Config} */ 
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
Enter fullscreen mode Exit fullscreen mode

Finally, add @tailwind directives to the ./src/index.css so you can use Tailwind CSS classes in all our components:

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

Create Your Page Layout

Now that you've set up the project, it's time to create a simple app layout with a navigation bar at the top and a drop-down menu to select your desired family member. Here's a rough mock up:

App mockup

Before going further, you need a data source to fetch the list of caregivers and the caregiving schedules for family members. To do that, create a new src/data.json file. The data.json has two keys:

  • Caregivers, a list of caregiver details objects
  • The caregiving schedules for each family member

Each caregiving schedule item has a caregiver linked to it using the resourceId attribute that maps to the caregiver's id, as shown below.

Caregiver and schedule structure

The caregivers object structure is as follows:

{
  "id": "steve", // unique resource id

  "name": "Steve Rogers", // name of the caregiver

  "eventColor": "blue" // color for the calendar event
}

Enter fullscreen mode Exit fullscreen mode

The schedule object structure looks like this:


{
  "<family-member>": [
    {
      "startDate": "<appointment-start-date>",

      "id": "<unique-id-number>",
      "endDate": "<appointment-start-date>",

      "name": "<slot-name>",

      "resourceId": "<caregiver-id>"
    }

    // ... more appointments
  ]

  // ... other family member's schedules
}

Enter fullscreen mode Exit fullscreen mode

You can copy the below JSON as sample data for your data.json file.

{
  "caregivers": [
    {
      "id": "steve",
      "name": "Steve Rogers",
      "eventColor": "blue"
    },
    {
      "id": "tony",
      "name": "Tony Stark",
      "eventColor": "orange"
    },
    {
      "id": "bruce",
      "name": "Bruce Banner",
      "eventColor": "green"
    },
    {
      "id": "natasha",
      "name": "Natasha Romano ff",
      "eventColor": "pink"
    }
  ],
  "schedule": {
    "Grand Pa": [
      {
        "startDate": "Thu Sep 08 2022 16:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 96,
        "endDate": "Thu Sep 08 2022 18:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "tony"
      },
      {
        "startDate": "Fri Sep 09 2022 06:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 91,
        "endDate": "Fri Sep 09 2022 07:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "natasha"
      },
      {
        "startDate": "Thu Sep 08 2022 05:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 82,
        "endDate": "Thu Sep 08 2022 07:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "steve"
      },
      {
        "startDate": "Mon Sep 05 2022 18:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 62,
        "endDate": "Mon Sep 05 2022 20:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "bruce"
      },
      {
        "startDate": "Tue Sep 06 2022 11:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 93,
        "endDate": "Tue Sep 06 2022 12:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "tony"
      },
      {
        "startDate": "Fri Sep 09 2022 08:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 2,
        "endDate": "Fri Sep 09 2022 10:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "natasha"
      },
      {
        "startDate": "Mon Sep 05 2022 16:30:00 GMT+0000 (Coordinated Universal Time)",
        "id": 79,
        "endDate": "Mon Sep 05 2022 17:30:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "bruce"
      },
      {
        "startDate": "Sun Sep 04 2022 09:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 15,
        "endDate": "Sun Sep 04 2022 10:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "natasha"
      }
    ],
    "Grand Ma": [
      {
        "startDate": "Fri Sep 09 2022 18:30:00 GMT+0000 (Coordinated Universal Time)",
        "id": 12,
        "endDate": "Fri Sep 09 2022 20:30:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "bruce"
      },
      {
        "startDate": "Fri Sep 09 2022 17:30:00 GMT+0000 (Coordinated Universal Time)",
        "id": 96,
        "endDate": "Fri Sep 09 2022 19:30:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "natasha"
      },
      {
        "startDate": "Mon Sep 05 2022 05:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 98,
        "endDate": "Mon Sep 05 2022 07:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "tony"
      },
      {
        "startDate": "Fri Sep 09 2022 06:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 91,
        "endDate": "Fri Sep 09 2022 07:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "natasha"
      },
      {
        "startDate": "Thu Sep 08 2022 05:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 65,
        "endDate": "Thu Sep 08 2022 07:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "steve"
      },
      {
        "startDate": "Mon Sep 05 2022 18:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 62,
        "endDate": "Mon Sep 05 2022 20:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "bruce"
      },
      {
        "startDate": "Wed Sep 07 2022 11:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 18,
        "endDate": "Wed Sep 07 2022 13:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "steve"
      }
    ],
    "Uncle": [
      {
        "startDate": "Sun Sep 04 2022 17:30:00 GMT+0000 (Coordinated Universal Time)",
        "id": 47,
        "endDate": "Sun Sep 04 2022 18:30:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "steve"
      },
      {
        "startDate": "Tue Sep 06 2022 04:30:00 GMT+0000 (Coordinated Universal Time)",
        "id": 24,
        "endDate": "Tue Sep 06 2022 06:30:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "natasha"
      },
      {
        "startDate": "Thu Sep 08 2022 06:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 83,
        "endDate": "Thu Sep 08 2022 07:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "bruce"
      },
      {
        "startDate": "Sun Sep 04 2022 16:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 52,
        "endDate": "Sun Sep 04 2022 18:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "tony"
      },
      {
        "startDate": "Wed Sep 07 2022 12:30:00 GMT+0000 (Coordinated Universal Time)",
        "id": 53,
        "endDate": "Wed Sep 07 2022 13:30:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "natasha"
      },
      {
        "startDate": "Sun Sep 04 2022 04:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 48,
        "endDate": "Sun Sep 04 2022 06:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "steve"
      },
      {
        "startDate": "Sun Sep 04 2022 02:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 19,
        "endDate": "Sun Sep 04 2022 03:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "tony"
      }
    ],
    "Dad": [
      {
        "startDate": "Fri Sep 09 2022 10:30:00 GMT+0000 (Coordinated Universal Time)",
        "id": 86,
        "endDate": "Fri Sep 09 2022 12:30:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "natasha"
      },
      {
        "startDate": "Sun Sep 04 2022 12:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 26,
        "endDate": "Sun Sep 04 2022 14:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "tony"
      },
      {
        "startDate": "Wed Sep 07 2022 07:30:00 GMT+0000 (Coordinated Universal Time)",
        "id": 87,
        "endDate": "Wed Sep 07 2022 08:30:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "bruce"
      },
      {
        "startDate": "Thu Sep 08 2022 20:30:00 GMT+0000 (Coordinated Universal Time)",
        "id": 37,
        "endDate": "Thu Sep 08 2022 21:30:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "natasha"
      },
      {
        "startDate": "Mon Sep 05 2022 01:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 3,
        "endDate": "Mon Sep 05 2022 02:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "tony"
      },
      {
        "startDate": "Mon Sep 05 2022 00:00:00 GMT+0000 (Coordinated Universal Time)",
        "id": 93,
        "endDate": "Mon Sep 05 2022 01:00:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "steve"
      },
      {
        "startDate": "Tue Sep 06 2022 08:30:00 GMT+0000 (Coordinated Universal Time)",
        "id": 10,
        "endDate": "Tue Sep 06 2022 10:30:00 GMT+0000 (Coordinated Universal Time)",
        "name": "Caregiver assigned",
        "resourceId": "bruce"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

This example uses a static JSON file, but you can also use an API or database as the source.

Import the data.json file in the App.js and retrieve the list of members using the Object.keys method:

import "./App.css";
import { useState } from "react";
import data from "./data.json";

const ALL_MEMBERS = Object.keys(data.schedule); // get list of members from object
Enter fullscreen mode Exit fullscreen mode

Then create a simple navigation bar at the top using Tailwind CSS classes:

import "./App.css";
import { useState } from "react";
import data from "./data.json";

const ALL_MEMBERS = Object.keys(data.schedule); // get list of members from object

function App() {
  return (
    <div className={"flex flex-col max-w-[1200px] mx-auto"}>
      <nav
        className={
          "flex flex-row items-center bg-green-600 p-2 py-3 text-white shadow shadow-sm shadow-gray-500"
        }
      >
        <p className={"text-lg"}>Caregiver PRO</p>
        <p className={"mx-10"}>|</p>
        <i className={"font-light text-sm"}>
          We ensure the best care for your loved ones.
        </i>
      </nav>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Run npm start to start the application:

Navigation bar

Now create a drop-down menu using the <select> HTML element and populate it with the <option> elements by mapping over the ALL_MEMBERS array:

import "./App.css";
import { useState } from "react";
import data from "./data.json";

const ALL_MEMBERS = Object.keys(data.schedule); // get list of members from object

function App() {
  return (
    <div className={"flex flex-col max-w-[1200px] mx-auto"}>
      <nav
        className={
          "flex flex-row items-center bg-green-600 p-2 py-3 text-white shadow shadow-sm shadow-gray-500"
        }
      >
        <p className={"text-lg"}>Caregiver PRO</p>
        <p className={"mx-10"}>|</p>
        <i className={"font-light text-sm"}>
          We ensure the best care for your loved ones.
        </i>
      </nav>
      <main className={"mt-10"}>
        <div className={"mb-10"}>
          <label htmlFor={"member"}>Select member</label>
          <select
            id={"member"}
            value={member}
            className={"ml-2 bg-gray-100 border-2 rounded border-green-600"}
          >
            {ALL_MEMBERS.map((member) => (
              <option key={member} value={member}>
                {member}
              </option>
            ))}
          </select>
        </div>
        <div className={"bg-gray-200 h-[500px] text-lg"}>
          Calendar goes here
        </div>
      </main>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Create a member state variable using the useState React hook to allow users to select a family member. Add an onChange event handler to the <select> element to update the member state whenever the user selects a new member:

import "./App.css";
import { useState } from "react";
import data from "./data.json";

const ALL_MEMBERS = Object.keys(data.schedule); // get list of members from object

function App() {
  const [member, setMember] = useState("Grand Ma");
  return (
    <div className={"flex flex-col max-w-[1200px] mx-auto"}>
      <nav
        className={
          "flex flex-row items-center bg-green-600 p-2 py-3 text-white shadow shadow-sm shadow-gray-500"
        }
      >
        <p className={"text-lg"}>Caregiver PRO</p>
        <p className={"mx-10"}>|</p>
        <i className={"font-light text-sm"}>
          We ensure the best care for your loved ones.
        </i>
      </nav>
      <main className={"mt-10"}>
        <div className={"mb-10"}>
          <label htmlFor={"member"}>Select member</label>
          <select
            id={"member"}
            value={member}
            onChange={(e) => setMember(e.target.value)}
            className={"ml-2 bg-gray-100 border-2 rounded border-green-600"}
          >
            {ALL_MEMBERS.map((member) => (
              <option key={member} value={member}>
                {member}
              </option>
            ))}
          </select>
        </div>
        <div className={"bg-gray-200 h-[500px] text-lg"}>
          Calendar goes here
        </div>
      </main>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Basic application layout

The application layout is ready. Now you need to plug in the Bryntum Calendar to show user-friendly schedules.

Add the Bryntum Calendar Layout

To add the Bryntum Calendar layout, you need to sign up for a free trial of the Bryntum Calendar. Bryntum serves the calendar component from a private registry, so you need to specify the registry URL to npm using the following command:

npm config set "@bryntum:registry=https://npm.bryntum.com"
Enter fullscreen mode Exit fullscreen mode

Since Bryntum's registry is authenticated, you need to log in using the credentials you signed up with:

npm login --registry=https://npm.bryntum.com
Enter fullscreen mode Exit fullscreen mode

Please note: The "@" should be replaced with ".." in the login email. For example, "someone@example.com" will become "someone..example.com" with "trial" as the password.

Now, run the following command to install the Bryntum Calendar dependencies:

npm i @bryntum/calendar@npm:@bryntum/calendar-trial@^5.1.2 @bryntum/calendar-react@5.1.2
Enter fullscreen mode Exit fullscreen mode

Import the Stockholm theme for Bryntum Calendar in the index.css file:

@tailwind base;
@tailwind components;
@tailwind utilities;

@import "@bryntum/calendar/calendar.stockholm.css"; # add this line
Enter fullscreen mode Exit fullscreen mode

Then import the BryntumCalendar component in the App.js file and create a CALENDAR_CONFIG object with the date that the calendar will open:

import "./App.css";
import { useState } from "react";
import data from "./data.json";
import { BryntumCalendar } from "@bryntum/calendar-react";

const CALENDAR_CONFIG = {
  date: new Date(2022, 8, 4), // calendar will open at this date
};

const ALL_MEMBERS = Object.keys(data.schedule); // get list of members from object
Enter fullscreen mode Exit fullscreen mode

Pass the CALENDAR_CONFIG as config, caregivers as the resources, and the data.schedule[member] as the events prop to the BryntumCalendar:

import "./App.css";
import { useState } from "react";
import data from "./data.json";
import { BryntumCalendar } from "@bryntum/calendar-react";

const CALENDAR_CONFIG = {
  date: new Date(2022, 8, 4),
};
const ALL_MEMBERS = Object.keys(data.schedule); // get list of members from object

function App() {
  const [member, setMember] = useState("Grand Ma");
  return (
    <div className={"flex flex-col max-w-[1200px] mx-auto"}>
      <nav
        className={
          "flex flex-row items-center bg-green-600 p-2 py-3 text-white shadow shadow-sm shadow-gray-500"
        }
      >
        <p className={"text-lg"}>Caregiver PRO</p>
        <p className={"mx-10"}>|</p>
        <i className={"font-light text-sm"}>
          We ensure the best care for your loved ones.
        </i>
      </nav>
      <main className={"mt-10"}>
        <div className={"mb-10"}>
          <label htmlFor={"member"}>Select member</label>
          <select
            id={"member"}
            value={member}
            onChange={(e) => setMember(e.target.value)}
            className={"ml-2 bg-gray-100 border-2 rounded border-green-600"}
          >
            {ALL_MEMBERS.map((member) => (
              <option key={member} value={member}>
                {member}
              </option>
            ))}
          </select>
        </div>
        <BryntumCalendar
          config={CALENDAR_CONFIG}
          resources={data.caregivers}
          events={data.schedule[member]}
        />
      </main>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

In this case, since the member is in a React state, whenever the user selects a new member from the drop-down, the calendar will re-render and show the caregiver schedule for the selected member. And with this final step, the Caregiver PRO is ready:

Final application

The users can add new caregiver appointments by checking the missing slots and selecting a caregiver from the list while making the appointment. Or they can change the view to daily or monthly, or see it as a list by selecting the Agenda view.

Here, you can see the Caregiver PRO in action:

Caregiver in action

Conclusion

Upon completion of this tutorial, you will have a fully functioning Caregiver PRO application. To create this application, you learned how to set up a React project with Tailwind CSS styling, and you used a JSON file as the data source to display the list of events. Later, you used the Bryntum Calendar component to display calendar events and make booking caregivers for family members simpler. You can extend this example further and use Bryntum Calendar events to read or store events from a remote API.

Are you already using the Bryntum Calendar? We would love to hear how it's making your life easier.

Bryntum is a software company specializing in creating beautiful and performant web components, including the Calendar, Scheduler, and Gantt chart. Want to learn more? Try our scheduling and Gantt components at bryntum.com.

Top comments (0)