---
title: "React Event calendar Property Booking Calendar Example | Mobiscroll"
component: "Event calendar"
framework: "React"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/react/eventcalendar/property-booking-calendar"
---

# Property Booking Calendar - React Event calendar demo

Show property reservations in a monthly React booking calendar — exact check-in/check-out time labels, color-coded by platform (Airbnb, Booking). For React and Next.JS.

- [Live demo](https://demo.mobiscroll.com/react/eventcalendar/property-booking-calendar)
- [View React JS code on GitHub](https://github.com/acidb/mobiscroll-demos-react/tree/main/src/demos/eventcalendar/calendar-view/property-booking-calendar)
- [View React TS code on GitHub](https://github.com/acidb/mobiscroll-demos-react-ts/tree/main/src/demos/eventcalendar/calendar-view/property-booking-calendar)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/eventcalendar/property-booking-calendar.md), [jQuery](https://demo.mobiscroll.com/jquery/eventcalendar/property-booking-calendar.md), [Angular](https://demo.mobiscroll.com/angular/eventcalendar/property-booking-calendar.md), [Vue](https://demo.mobiscroll.com/vue/eventcalendar/property-booking-calendar.md)

## Description

When keeping records of bookings, the event calendar with exact label displays can come in handy. The labels accurately mark the exact start (e.g. 14:00) and end times (e.g. 11:00) of bookings, consolidating all booking records in a single, clear view.

By combining the `eventDisplay: 'exact'` setting under the [`view`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-view) option with customizable [`renderCalendarEventContent`](https://mobiscroll.com/docs/react/eventcalendar/api#renderer-renderCalendarEventContent) , you can tailor the calendar to your specific needs. This allows you to create an efficient and user-friendly booking planning UI, ensuring all your bookings are easily managed and clearly displayed.

## What this demo shows

- A full month Eventcalendar for reservation tracking, with booking labels rendered directly inside the day cells and positioned by exact check-in and check-out times.
- **Header controls** The calendar includes standard month and year navigation, previous and next arrows, and a Today button.
- **Event labels** Reservation labels use exact timing, so they appear inside the day cells according to their start and end times.
- **Event label content** Each booking label shows the reservation guest name and the logo of the platform where the booking was made, such as Airbnb, Booking.com, or MakeMyTrip.
- **Platform colors** Label colors identify the booking platform: yellow for Airbnb, red for Booking.com, and green for MakeMyTrip.
- **Event selection** Clicking a reservation label selects it and highlights the selected booking.
- **Cell hover state** Hovering over a day cell highlights the day number in the top-right corner.
- **Day selection** Clicking empty space in a day cell selects that day and highlights the day number with a blue background.
- **Creating reservations** Double-clicking empty space or clicking and dragging across empty space creates a new event.
- **Exact-time placement** Newly created events start at 12:00 AM by default because exact label display is enabled, so they appear around the middle of the selected or dragged day cell.
- **Overlap validation** If a new reservation would overlap an existing one, the calendar shows a toast message explaining that reservations cannot overlap in the same time period.

## Best for

- **Single-unit reservation overview** Room, property, and short-stay booking interfaces where users need to see reservations directly in a month grid.
- **Reservation management** Booking systems that need to display reservations with exact time labels instead of all-day occupancy blocks.
- **Multi-platform booking records** Workflows that collect reservations from platforms such as Airbnb, Booking.com, and MakeMyTrip into one calendar view.
- **Operational overview** Monthly planning screens where users need to review existing bookings, spot availability, and keep reservation records organized.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-themeVariant) - option
- [`cssClass`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-cssClass) - option
- [`view`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-view) - option
- [`data`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-data) - option
- [`clickToCreate`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-clickToCreate) - option
- [`dragToCreate`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-dragToCreate) - option
- [`dragToMove`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-dragToMove) - option
- [`dragToResize`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-dragToResize) - option
- [`eventOverlap`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-eventOverlap) - option
- [`extendDefaultEvent`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-extendDefaultEvent) - option
- [`renderCalendarEventContent`](https://mobiscroll.com/docs/react/eventcalendar/api#renderer-renderCalendarEventContent) - renderer
- [`onEventCreateFailed`](https://mobiscroll.com/docs/react/eventcalendar/api#event-onEventCreateFailed) - event
- [`onEventUpdateFailed`](https://mobiscroll.com/docs/react/eventcalendar/api#event-onEventUpdateFailed) - event
- [`onClose`](https://mobiscroll.com/docs/react/notifications/toast#event-onClose) - event

## Code

### JSX

```jsx
import { Eventcalendar, setOptions, Toast } from '@mobiscroll/react';
import { useCallback, useMemo, useState } from 'react';

setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

const airBnB = 'https://img.mobiscroll.com/demos/air-bnb-icon.png';
const booking = 'https://img.mobiscroll.com/demos/booking-icon.png';
const makeMyTrip = 'https://img.mobiscroll.com/demos/make-my-trip-icon.png';

function App() {
  const [isToastOpen, setToastOpen] = useState(false);

  const myEvents = useMemo(
    () => [
      {
        start: '2026-10-05T12:00',
        end: '2026-10-08T12:00',
        icon: airBnB,
        title: 'Mary Smith',
        color: '#fffa61',
      },
      {
        start: '2026-10-16T12:00',
        end: '2026-10-22T12:00',
        title: 'James Johnson',
        icon: airBnB,
        color: '#fffa61',
      },
      {
        start: '2026-10-11T12:00',
        end: '2026-10-14T12:00',
        title: 'Patricia Williams',
        icon: airBnB,
        color: '#fffa61',
      },
      {
        start: '2026-10-26T12:00',
        end: '2026-10-28T12:00',
        title: 'Michael Brown',
        icon: airBnB,
        color: '#fffa61',
      },
      {
        start: '2026-11-02T12:00',
        end: '2026-11-03T12:00',
        title: 'Jennifer Jones',
        icon: booking,
        color: '#ff9999',
      },
      {
        start: '2026-10-23T12:00',
        end: '2026-10-26T12:00',
        title: 'Robert Garcia',
        icon: booking,
        color: '#ff9999',
      },
      {
        start: '2026-11-11T12:00',
        end: '2026-11-12T12:00',
        title: 'Linda Miller',
        icon: booking,
        color: '#ff9999',
      },
      {
        start: '2026-11-18T12:00',
        end: '2026-11-19T12:00',
        title: 'John Davis',
        icon: booking,
        color: '#ff9999',
      },
      {
        start: '2026-10-08T12:00',
        end: '2026-10-10T12:00',
        title: 'Elizabeth Rodriguez',
        icon: makeMyTrip,
        color: '#a0efaa',
      },
      {
        start: '2026-11-05T12:00',
        end: '2026-11-07T12:00',
        title: 'David Martinez',
        icon: makeMyTrip,
        color: '#a0efaa',
      },
      {
        start: '2026-11-08T12:00',
        end: '2026-11-10T12:00',
        title: 'Barbara Wilson',
        icon: makeMyTrip,
        color: '#a0efaa',
      },
      {
        start: '2026-10-14T12:00',
        end: '2026-10-15T12:00',
        title: 'William Anderson',
        icon: makeMyTrip,
        color: '#a0efaa',
      },
      {
        start: '2026-11-15T12:00',
        end: '2026-11-18T12:00',
        title: 'Susan Taylor',
        icon: makeMyTrip,
        color: '#a0efaa',
      },
      {
        start: '2026-10-29T12:00',
        end: '2026-11-01T12:00',
        title: 'Richard Jackson',
        icon: airBnB,
        color: '#fffa61',
      },
    ],
    [],
  );

  const myView = useMemo(
    () => ({
      calendar: {
        type: 'month',
        eventDisplay: 'exact',
      },
    }),
    [],
  );

  const customDefaultEvent = useCallback((args) => {
    const start = new Date(args.start.setHours(12));
    const end = new Date(args.start.getFullYear(), args.start.getMonth(), args.start.getDate() + 1, 12);
    return {
      title: 'New reservation',
      start,
      end,
    };
  }, []);

  const customLabelContent = useCallback(
    (event) => (
      <div className="mbsc-flex mds-booking-item mbsc-align-items-center">
        {event.original.icon && <img className="mds-booking-icon" draggable="false" src={event.original.icon} />}
        <span>{event.title}</span>
      </div>
    ),
    [],
  );

  const handleOverlap = useCallback(() => {
    setToastOpen(true);
  }, []);

  const handleCloseToast = useCallback(() => {
    setToastOpen(false);
  }, []);

  return (
    <>
      <Eventcalendar
        cssClass="mds-booking-calendar"
        view={myView}
        data={myEvents}
        clickToCreate={true}
        dragToCreate={true}
        dragToMove={true}
        dragToResize={true}
        eventOverlap={false}
        extendDefaultEvent={customDefaultEvent}
        renderCalendarEventContent={customLabelContent}
        onEventCreateFailed={handleOverlap}
        onEventUpdateFailed={handleOverlap}
      />
      <Toast message="Reservations cannot overlap" isOpen={isToastOpen} onClose={handleCloseToast} />
    </>
  );
}

export default App;
```

### TSX

```tsx
import {
  Eventcalendar,
  MbscCalendarEvent,
  MbscCalendarEventData,
  MbscEventcalendarView,
  MbscNewEventData,
  setOptions,
  Toast,
} from '@mobiscroll/react';
import { useCallback, useMemo, useState } from 'react';

setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

const airBnB = 'https://img.mobiscroll.com/demos/air-bnb-icon.png';
const booking = 'https://img.mobiscroll.com/demos/booking-icon.png';
const makeMyTrip = 'https://img.mobiscroll.com/demos/make-my-trip-icon.png';

function App() {
  const [isToastOpen, setToastOpen] = useState(false);

  const myEvents = useMemo<MbscCalendarEvent[]>(
    () => [
      {
        start: '2026-10-05T12:00',
        end: '2026-10-08T12:00',
        icon: airBnB,
        title: 'Mary Smith',
        color: '#fffa61',
      },
      {
        start: '2026-10-16T12:00',
        end: '2026-10-22T12:00',
        title: 'James Johnson',
        icon: airBnB,
        color: '#fffa61',
      },
      {
        start: '2026-10-11T12:00',
        end: '2026-10-14T12:00',
        title: 'Patricia Williams',
        icon: airBnB,
        color: '#fffa61',
      },
      {
        start: '2026-10-26T12:00',
        end: '2026-10-28T12:00',
        title: 'Michael Brown',
        icon: airBnB,
        color: '#fffa61',
      },
      {
        start: '2026-11-02T12:00',
        end: '2026-11-03T12:00',
        title: 'Jennifer Jones',
        icon: booking,
        color: '#ff9999',
      },
      {
        start: '2026-10-23T12:00',
        end: '2026-10-26T12:00',
        title: 'Robert Garcia',
        icon: booking,
        color: '#ff9999',
      },
      {
        start: '2026-11-11T12:00',
        end: '2026-11-12T12:00',
        title: 'Linda Miller',
        icon: booking,
        color: '#ff9999',
      },
      {
        start: '2026-11-18T12:00',
        end: '2026-11-19T12:00',
        title: 'John Davis',
        icon: booking,
        color: '#ff9999',
      },
      {
        start: '2026-10-08T12:00',
        end: '2026-10-10T12:00',
        title: 'Elizabeth Rodriguez',
        icon: makeMyTrip,
        color: '#a0efaa',
      },
      {
        start: '2026-11-05T12:00',
        end: '2026-11-07T12:00',
        title: 'David Martinez',
        icon: makeMyTrip,
        color: '#a0efaa',
      },
      {
        start: '2026-11-08T12:00',
        end: '2026-11-10T12:00',
        title: 'Barbara Wilson',
        icon: makeMyTrip,
        color: '#a0efaa',
      },
      {
        start: '2026-10-14T12:00',
        end: '2026-10-15T12:00',
        title: 'William Anderson',
        icon: makeMyTrip,
        color: '#a0efaa',
      },
      {
        start: '2026-11-15T12:00',
        end: '2026-11-18T12:00',
        title: 'Susan Taylor',
        icon: makeMyTrip,
        color: '#a0efaa',
      },
      {
        start: '2026-10-29T12:00',
        end: '2026-11-01T12:00',
        title: 'Richard Jackson',
        icon: airBnB,
        color: '#fffa61',
      },
    ],
    [],
  );

  const myView = useMemo<MbscEventcalendarView>(
    () => ({
      calendar: {
        type: 'month',
        eventDisplay: 'exact',
      },
    }),
    [],
  );

  const customDefaultEvent = useCallback((args: MbscNewEventData) => {
    const start = new Date(args.start.setHours(12));
    const end = new Date(args.start.getFullYear(), args.start.getMonth(), args.start.getDate() + 1, 12);
    return {
      title: 'New reservation',
      start,
      end,
    };
  }, []);

  const customLabelContent = useCallback(
    (event: MbscCalendarEventData) => (
      <div className="mbsc-flex mds-booking-item mbsc-align-items-center">
        {event.original!.icon && <img className="mds-booking-icon" draggable="false" src={event.original!.icon} />}
        <span>{event.title}</span>
      </div>
    ),
    [],
  );

  const handleOverlap = useCallback(() => {
    setToastOpen(true);
  }, []);

  const handleCloseToast = useCallback(() => {
    setToastOpen(false);
  }, []);

  return (
    <>
      <Eventcalendar
        cssClass="mds-booking-calendar"
        view={myView}
        data={myEvents}
        clickToCreate={true}
        dragToCreate={true}
        dragToMove={true}
        dragToResize={true}
        eventOverlap={false}
        extendDefaultEvent={customDefaultEvent}
        renderCalendarEventContent={customLabelContent}
        onEventCreateFailed={handleOverlap}
        onEventUpdateFailed={handleOverlap}
      />
      <Toast message="Reservations cannot overlap" isOpen={isToastOpen} onClose={handleCloseToast} />
    </>
  );
}

export default App;
```

### CSS

```css
.mds-booking-calendar .mbsc-calendar-day .mbsc-calendar-text {
  height: 30px;
  line-height: 30px;
  margin: 0 0.2em 0.2em 0.3em;
}

.mds-booking-item {
  font-size: 16px;
}

.mds-booking-icon {
  margin-right: 8px;
  width: 24px;
  height: 24px;
}
```

## Implementation notes

- Use `calendar: { type: 'month', eventDisplay: 'exact' }` in the view config so each booking renders as a proportional bar spanning its exact check-in-to-check-out date range.
- Give each event a custom `icon` property (platform logo URL), a `title` (guest name), a per-platform `color`, and `start`/`end` both set to 12:00 to represent noon check-in and noon check-out.
- Use `renderCalendarEventContent` (Angular: `calendarEventContentTemplate`, Vue: `calendarEventContent`) to render each label as the platform icon image followed by the guest name.
- Set `extendDefaultEvent` to snap newly created reservations to noon boundaries: set `start` to 12:00 on the drag-start day and `end` to 12:00 on the following day.
- Enable `clickToCreate`, `dragToCreate`, `dragToMove`, and `dragToResize`; set `eventOverlap: false` to prevent bookings from overlapping.
- In `onEventCreateFailed` and `onEventUpdateFailed`, show a `Toast` with an overlap error message.

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-react.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config react
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   npm run dev
   ```

On a trial, add `--trial` to the config command: `mobiscroll config react --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/react/getting-started/installation

## Related demos

- Next: [Day Cell Summary View](https://demo.mobiscroll.com/react/eventcalendar/day-cell-aggregate-information.md) - Display color-coded daily event summaries in a React event calendar — each cell shows meetings and workload density, with drill-down to day and week views.
