'How to load events from firebase for a specific user for tablecalendar

I am currently building a project where a list of trainers is displayed for a user. When tapped on a listtile showing the trainer a modalBottomSheet opens up showing the table calendar. While the trainers are able to add 'available times' to their calendar the data has to be dynamic and I save this in firestore. Every trainer has his own firebase generated UID.

The AvailableTime class is structured as followed:

class AvailableTime {
  String trainerID;
  DateTime date;
  DateTime startTime;
  DateTime endTime;

  AvailableTime(
      {@required this.trainerID,
      @required this.date,
      @required this.startTime,
      @required this.endTime});
}

And a AvailableTime is added as followed to firestore:

Future<void> addAvailableTime(
      DateTime date, DateTime startTime, DateTime endTime) async {
    var uid = FirebaseAuth.instance.currentUser.uid;
    await FirebaseFirestore.instance.collection('availableTimes').add({
      'trainerID': uid,
      'date': date,
      'startTime': startTime,
      'endTime': endTime
    });
  }

A events map is structured as:

Map<DateTime, List<dynamic>>

I need the available times on multiple screens so I must get the data through the provider I created. (The AvailableTime class and addAvailableTime() function are also in this provider.

How do I get the available times for every trainer who is shown, preferred by having a List with the UID of the trainer and every UID holding an events map.

Thanks in advance.

PS: A user is build up as followed in its own user data provider:

class User with ChangeNotifier {
  String uid;
  String email;
  String firstName;
  String lastName;
  bool isTrainer;
  double price;
  String bio;
  String location;
  String sportclub;
  List sports;
  bool isFavorite;

  User(
      {@required this.uid,
      @required this.email,
      @required this.firstName,
      @required this.lastName,
      @required this.isTrainer,
      @required this.price,
      @required this.bio,
      @required this.location,
      @required this.sportclub,
      @required this.sports,
      this.isFavorite = false});

  void toggleFavoriteStatus() {
    isFavorite = !isFavorite;
    notifyListeners();
  }
}


Solution 1:[1]

For getting specific user data from firestore you can perform such a query

Firestore.instance
        .collection('availableTimes')
        .where('trainerID', whereIn: trainerID)
        .orderBy('startTime');

to display the data using table calendar do append your code to match this

Map<DateTime, List<AvailableTime>> events;

// convert data to match Map<DateTime, List<dynamic>>

 Map<DateTime, List<AvailableTime>> _groupEvents(
      List<AvailableTime> allEvents) {
    Map<DateTime, List<AvailableTime>> data = {};
    allEvents.forEach((event) {
      var ds = format.parse(event.date);
      DateTime date = DateTime(
        ds.year,
        ds.month,
        ds.day,
      );
      if (data[date] == null) data[date] = [];
      data[date].add(event);
    });
    return data;
  }
// after getting the data from firebase either using streambuilder or bloc ...
//using bloc here .Data for [availableTime] is required in a list
if(state is AvailableTimeSuccess){
events = _groupEvents(state.avalaibleTimeList.availableTime);
return Column.. 
 showCalendar(eventss: events),

Expanded.. _buildEventList(), )//column }

//finally your calendar widget 

  Widget showCalendar({Map<DateTime, List<AttendanceCard>> eventss}) {
    return Container(
      child: TableCalendar(
        events: eventss,
        initialCalendarFormat: CalendarFormat.week,
        calendarStyle: CalendarStyle(
            canEventMarkersOverflow: true,
            todayColor: Colors.orange,
            selectedColor: Theme.of(context).primaryColor,
            todayStyle: TextStyle(
                fontWeight: FontWeight.bold,
                fontSize: 18.0,
                color: Colors.white)),
        headerStyle: HeaderStyle(
          centerHeaderTitle: true,
          formatButtonDecoration: BoxDecoration(
            color: Colors.orange,
            borderRadius: BorderRadius.circular(20.0),
          ),
          formatButtonTextStyle: TextStyle(color: Colors.white),
          formatButtonShowsNext: false,
        ),
        startingDayOfWeek: StartingDayOfWeek.monday,
        
        onDaySelected: (date, eventss, _) {
          setState(() {
            _selectedEvents = eventss;
          });
        },
        builders: CalendarBuilders(
          selectedDayBuilder: (context, date, events) => Container(
              margin: const EdgeInsets.all(4.0),
              alignment: Alignment.center,
              decoration: BoxDecoration(
                  color: Theme.of(context).primaryColor,
                  borderRadius: BorderRadius.circular(10.0)),
              child: Text(
                date.day.toString(),
                style: TextStyle(color: Colors.white),
              )),
          todayDayBuilder: (context, date, events) => Container(
              margin: const EdgeInsets.all(4.0),
              alignment: Alignment.center,
              decoration: BoxDecoration(
                  color: Colors.orange,
                  borderRadius: BorderRadius.circular(10.0)),
              child: Text(
                date.day.toString(),
                style: TextStyle(color: Colors.white),
              )),
        ),
        calendarController: _calendarController,
      ), 
    );
  }


//build events 
  Widget _buildEventList() {
    return ListView(
      children: _selectedEvents
          .map((event) =>ListTile(title:availableTime.startTime)
          .toList(),
    );
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 marc_s