Create a Meeting Room Calendar Using Flutter Event Calendar
Detailed Blog page Skeleton loader
Create a Meeting Room Calendar Using Flutter Event Calendar

Meeting rooms are an essential part of any office. We may not have an individual meeting room for every team, though, and mostly meeting rooms will be shared among different teams. To effectively share a meeting room and avoid conflicts in using it, a schedule for it becomes mandatory.

The Flutter meeting room calendar app that we are going to develop in this blog will allow everyone in your workplace to effectively share the meeting room without any conflict. Let’s walk through the steps to customize the Syncfusion Flutter Calendar widget to design a meeting room calendar.

Timeline resource grouping—overview

In our previous blog, Introducing Timeline Resource Grouping in Flutter Event Calendar, we gave a basic overview of the resource grouping support in the Flutter event Calendar and its usage in a real-time scenario. In this blog, I’ll continue with an overview of the timeline resource concept and how to utilize this feature in designing a meeting room calendar.

Designing a meeting room calendar

We are going to display only the Calendar timeline day in this example. First, let’s list the restrictions we need to implement in this app:

  • A reserved timeslot should be non-accessible.
  • The meeting rooms cannot be reserved during lunch break or scheduled maintenance.
  • Meeting events in the past cannot be edited.
Designing a Meeting Room Calendar with Flutter Event Calendar
Designing a Meeting Room Calendar with Flutter Event Calendar

Getting started

Follow these steps to create a resource view calendar in your Flutter application:

Step 1: Follow the getting started documentation to add a Flutter Calendar widget to your application.

Step 2: Then, set the following properties in the calendar:

  • Set the view property of the controller as timelineDay and assign it to the controller of the calendar.
  • Set the data source with the resource collection of the calendar.

Refer to the following code example.

return SfCalendar(
   view: CalendarView. timelineDay,
   controller: _calendarController,
   dataSource: _calendarDataSource,
   );

Populating resource data

Now, let’s see how to customize the calendar to display the meeting rooms. The meeting rooms are defined as resources and each room will be displayed vertically against the common timescale.

Imagine that an office has five meeting rooms within its premises, and everyone should share those rooms. As soon as a person books a room, they own it for the entire booked time range and no other person can reserve the same room during that specific time.

To start with, let’s assume that the resource data holds some common room information such as room name, room ID, and specific color to denote resource appointments. This information is apart from the default resource fields.

Add the resource collection and set this to the data source class. Assign the data source to the dataSource property of SfCalendar. Here for demo purposes, we have added random data.

void _addResources() {
    final Random random = Random();
    for (int i = 0; i < _nameCollection.length; i++) {
      _meetingRoomCollection.add(CalendarResource(
          displayName: _nameCollection[i],
          id: '000' + i.toString(),
          color: Color.fromRGBO(random.nextInt(255), random.nextInt(255),
              random.nextInt(255), 1)));
    }
  }
class _MeetingDataSource extends CalendarDataSource {
  _MeetingDataSource(
      List<Appointment> source, List<CalendarResource> resourceColl) {
    appointments = source;
    resources = resourceColl;
  }
}
return SfCalendar(
      controller: _calendarController,
      dataSource: _calendarDataSource,
    );

Designing the resource header view

You can design your own custom view and assign it to the resource header view of the calendar using the resourceViewHeaderBuilder property of the calendar.

Refer to the following code example.

Widget _resourceHeaderBuilder(
    BuildContext context, ResourceViewHeaderDetails details) {
  final Random random = Random();

  int capacity = 0;
  if (_visibleAppointments.isNotEmpty) {
    capacity = 0;
    for (int i = 0; i < _visibleAppointments.length; i++) {
      final Appointment visibleApp = _visibleAppointments[i];
      if (visibleApp.resourceIds != null &&
          visibleApp.resourceIds!.isNotEmpty &&
          visibleApp.resourceIds!.contains(details.resource.id)) {
        capacity++;
      }
    }
  }

  String capacityString = 'Events';
  if (capacity >= 5) {
    capacityString = 'Conference';
  }

  return Container(
    color: details.resource.color,
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        icons[random.nextInt(5).toInt()],
        Text(
          details.resource.displayName,
          style: const TextStyle(
              color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),
        ),
        Padding(
          padding: const EdgeInsets.only(top: 5),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              const Text(
                'Events: ',
                textAlign: TextAlign.center,
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 10,
                ),
              ),
              Container(
                child: Text(
                  capacity.toString(),
                  textAlign: TextAlign.center,
                  style: const TextStyle(
                      color: Colors.white,
                      fontSize: 12,
                      fontWeight: FontWeight.bold),
                ),
              )
            ],
          ),
        )
      ],
    ),
  );
}
return SfCalendar(
      controller: _calendarController,
      dataSource: _calendarDataSource,
      resourceViewHeaderBuilder: _resourceHeaderBuilder,
    );
Customizing the Resource View Header in Flutter Event Calendar
Customizing the Resource View Header in Flutter Event Calendar

Populating the meeting data

The resource header view customization is over, and now it’s time to fill the calendar with room reservation data. Let’s create some data with meeting-related fields: meeting summary, start time, end time. Then, we’ll assign them to the calendar’s dataSource property. Each appointment in the calendar denotes a confirmed booking to convey the room reservation status at a specific time.

Refer to the following code example. Here, for demo purposes, we have added some random data.

void _addAppointments() {
  final Random random = Random();
  for (int i = 0; i < _meetingRoomCollection.length; i++) {
    final List<Object> _roomId = <Object>[_meetingRoomCollection[i].id];
    if (i == _meetingRoomCollection.length - 1 || i.isEven) {
      int index = random.nextInt(5);
      index = index == i ? index + 1 : index;
      final Object roomId = _meetingRoomCollection[index].id;
      if (roomId is String) {
        _roomId.add(roomId);
      }

    }

    for (int k = 0; k < 365; k++) {
      if (_roomId.length > 1 && k.isEven) {
        continue;
      }
      for (int j = 0; j < 10; j++) {

        final DateTime date = DateTime.now().add(Duration(days: k + j));
        int startHour = 9 + random.nextInt(6);
        startHour =
            startHour >= 13 && startHour <= 14 ? startHour + 1 : startHour;
        final DateTime _startTime =
            DateTime(date.year, date.month, date.day, startHour, 0, 0);
        if (_startTime.isBefore(_minDate)) {
          continue;
        }

        _meetingCollection.add(Appointment(
            startTime: _startTime,
            endTime: _startTime.add(const Duration(hours: 1)),
            subject: _subjectCollection[random.nextInt(8)],
            color: _meetingRoomCollection[i % 5].color,
            startTimeZone: '',
            endTimeZone: '',
            resourceIds: _roomId));
      }
    }
  }
}
Populating Meeting Data in Flutter Event Calendar
Populating Meeting Data in Flutter Event Calendar

Blocking reservations at certain times

Now, we need to concentrate on another important action: making certain cells inaccessible to users. We can do this by adding the specialRegions to the calendar.

To prevent an appointment from being dropped into slots you want to be inaccessible, set the enterPointerInteraction property as false.

Refer to the following code example.

void _addSpecialRegions() {
    final DateTime date = DateTime.now();
    final Random random = Random();
    for (int i = 0; i < _meetingRoomCollection.length; i++) {
      _specialTimeRegions.add(TimeRegion(
          startTime: DateTime(date.year, date.month, date.day, 13, 0, 0),
          endTime: DateTime(date.year, date.month, date.day, 14, 0, 0),
          text: 'Lunch',
          color: Colors.grey.withOpacity(0.2),
          resourceIds: <Object>[_meetingRoomCollection[i].id],
          recurrenceRule: 'FREQ=DAILY;INTERVAL=1'));

      if (i.isEven) {
        continue;
      }

      final DateTime startDate = DateTime(
          date.year, date.month, date.day, 17 + random.nextInt(7), 0, 0);

      _specialTimeRegions.add(TimeRegion(
        startTime: startDate,
        endTime: startDate.add(const Duration(hours: 1)),
        text: 'Not Available',
        color: Colors.grey.withOpacity(0.2),
        enablePointerInteraction: false,
        resourceIds: <Object>[_meetingRoomCollection[i].id],
      ));
    }
  }
Blocking Reservations on Inaccessible Time in Flutter Event Calendar
Blocking Reservations on Inaccessible Time in Flutter Event Calendar

Also, to prevent appointments from being rescheduled to dates in the past set the minDate to the current date.

Refer to the following code example.

return SfCalendar(
      showDatePickerButton: true,
      controller: _calendarController,
      allowDragAndDrop: true,
      allowedViews: _allowedViews,
      minDate: _minDate,
      timeRegionBuilder: _getSpecialRegionWidget,
      specialRegions: _specialTimeRegions,
      showNavigationArrow: true,
      dataSource: _calendarDataSource,
      onViewChanged: viewChangedCallback,
      resourceViewHeaderBuilder: _resourceHeaderBuilder,
    );
Restricting Users to Reschedule Appointments in the Past Dates in Flutter Event Calendar
Restricting Users to Reschedule Appointments in the Past Dates in Flutter Event Calendar

GitHub reference

For more information, you can download the complete example for designing a meeting room calendar using Flutter Calendar.

Conclusion

To summarize, we have seen how to customize the Syncfusion Flutter Calendar to design a meeting room calendar by using additional styling options. Keep checking with us, as more useful blogs are waiting in our queue to show you more customizing options available in the Calendar.

Browse our documentation to learn more about our other Flutter widgets. You can also see our Syncfusion Flutter app with many examples in this GitHub repo. Don’t miss our demo app in Google Play, the App Store, the Windows Store, on our website, for macOS, and for Snapcraft (Linux).

If you aren’t a customer yet, you can try our 30-day free trial to check out these features.

Also, you can contact us through our support forumfeedback portal, or support portal. We are always happy to assist you!

Related blogs

Be the first to get updates

Nijamudeen

Meet the Author

Nijamudeen

Nijamudeen is the product manager for the Syncfusion Xamarin and Flutter platforms, who build highly scalable custom controls that drive Syncfusion's product vision forward.