Snapshot is giving an error but there shouldn't be any data in my flutter app

65 Views Asked by At

I am trying to implement a TableCalendar widget in my flutter app. This is old code so the events collection does not exist yet so the snapshot.hasdata should be "false" but it is goes into the "true" code.

Here is the code and the error message: enter image description here

Why is it acting as if snapshot.hasdata = true?

Here is the code for the TableCalendar implementation:

// Example holidays
final Map<DateTime, List> _holidays = {
  DateTime(2020, 1, 1): ['New Year\'s Day'],
  DateTime(2020, 1, 6): ['Epiphany'],
  DateTime(2020, 2, 14): ['Valentine\'s Day'],
  DateTime(2020, 4, 21): ['Easter Sunday'],
  DateTime(2020, 4, 22): ['Easter Monday'],
};

final kNow = DateTime.now();
final kFirstDay = DateTime(kNow.year, kNow.month - 3, kNow.day);
final kLastDay = DateTime(kNow.year, kNow.month + 12, kNow.day);

final _db = FirebaseFirestore.instance;
bool showSpinner = false;
DateTime? _selectedDay;
DateTime _focusedDay = DateTime.now();
LinkedHashMap<DateTime, List<Events>> kEvents =
    LinkedHashMap<DateTime, List<Events>>();

class AppointmentCalendarScreen extends ConsumerStatefulWidget {
  const AppointmentCalendarScreen({Key? key, this.title}) : super(key: key);

  final String? title;

  @override
  ConsumerState<AppointmentCalendarScreen> createState() =>
      _AppointmentCalendarScreenState();
}

class _AppointmentCalendarScreenState
    extends ConsumerState<AppointmentCalendarScreen>
    with TickerProviderStateMixin {
  late final ValueNotifier<List<Events>> _selectedEvents;
  Map<DateTime, List>? _selectedEventsMap;
  late StreamController<Map<DateTime, List>> _streamController;
  var eventDoc;
  var trxnDoc;
  Map<DateTime, List>? eventsMap;

  @override
  void initState() {
    super.initState();

    _streamController = StreamController();
    _selectedDay = _focusedDay;
  }

  @override
  void dispose() {
    _selectedEvents.dispose();
    _streamController.close();

    super.dispose();
  }

  List<Events>? _getTrxnEventsForDay(DateTime day, List<Trxn>? trxns) {
    DateTime? trxnDate;
    DateTime trxnDateUTC;

    for (int i = 0; i < trxnDoc.length; i++) {
      if (trxnDoc[i].contractDate != null && trxnDoc[i].contractDate != "") {
        trxnDate = DateTime.tryParse(trxnDoc[i].contractDate);
        trxnDateUTC = trxnDate!.toUtc();
        if (day.year == trxnDate.year &&
            day.day == trxnDate.day &&
            day.month == trxnDate.month) {
          List<Events> eventList = [];
          eventList.add(trxnDoc[i].contractDate);
          (kEvents.putIfAbsent(trxnDateUTC, () => eventList));
        }
      }

      if (trxnDoc[i].closingDate != null && trxnDoc[i].closingDate != "") {
        trxnDate = DateTime.tryParse(trxnDoc[i].closingDate);
        trxnDateUTC = trxnDate!.toUtc();
        if (day.year == trxnDate.year &&
            day.day == trxnDate.day &&
            day.month == trxnDate.month) {
          List<Events> eventList = [];
          eventList.add(trxnDoc[i].closingDate);
          (kEvents.putIfAbsent(trxnDateUTC, () => eventList));
        }
      }

      if (trxnDoc[i].dueDiligence24b != null &&
          trxnDoc[i].dueDiligence24b != "") {
        trxnDate = DateTime.tryParse(trxnDoc[i].dueDiligence24b);
        trxnDateUTC = trxnDate!.toUtc();
        if (day.year == trxnDate.year &&
            day.day == trxnDate.day &&
            day.month == trxnDate.month) {
          List<Events> eventList = [];
          eventList.add(trxnDoc[i].dueDiligence24b);
          (kEvents.putIfAbsent(trxnDateUTC, () => eventList));
        }
      }

      if (trxnDoc[i].financing24c != null && trxnDoc[i].financing24c != "") {
        trxnDate = DateTime.tryParse(trxnDoc[i].financing24c);
        trxnDateUTC = trxnDate!.toUtc();
        if (day.year == trxnDate.year &&
            day.day == trxnDate.day &&
            day.month == trxnDate.month) {
          List<Events> eventList = [];
          eventList.add(trxnDoc[i].financing24c);
          (kEvents.putIfAbsent(trxnDateUTC, () => eventList));
        }
      }

      if (trxnDoc[i].inspectionDate != null &&
          trxnDoc[i].inspectionDate != "") {
        trxnDate = DateTime.tryParse(trxnDoc[i].inspectionDate);
        trxnDateUTC = trxnDate!.toUtc();
        if (day.year == trxnDate.year &&
            day.day == trxnDate.day &&
            day.month == trxnDate.month) {
          List<Events> eventList = [];
          eventList.add(trxnDoc['inspectionDate']);
          (kEvents.putIfAbsent(trxnDateUTC, () => eventList));
        }
      }

      if (trxnDoc[i].appraisalDate != null && trxnDoc[i].appraisalDate != "") {
        trxnDate = DateTime.tryParse(trxnDoc[i].appraisalDate);
        trxnDateUTC = trxnDate!.toUtc();
        if (day.year == trxnDate.year &&
            day.day == trxnDate.day &&
            day.month == trxnDate.month) {
          List<Events> eventList = [];
          eventList.add(trxnDoc[i].appraisalDate);
          (kEvents.putIfAbsent(trxnDateUTC, () => eventList));
        }
      }

      if (trxnDoc[i].sellerDisclosure24a != null &&
          trxnDoc[i].sellerDisclosure24a != "") {
        trxnDate = DateTime.tryParse(trxnDoc[i].sellerDisclosure24a);
        trxnDateUTC = trxnDate!.toUtc();
        if (day.year == trxnDate.year &&
            day.day == trxnDate.day &&
            day.month == trxnDate.month) {
          List<Events> eventList = [];
          eventList.add(trxnDoc[i].sellerDisclosure24a);
          (kEvents.putIfAbsent(trxnDateUTC, () => eventList));
        }
      }

      if (trxnDoc[i].walkThroughDate != null &&
          trxnDoc[i].walkThroughDate != "") {
        trxnDate = DateTime.tryParse(trxnDoc[i].walkThroughDate);
        trxnDateUTC = trxnDate!.toUtc();
        if (day.year == trxnDate.year &&
            day.day == trxnDate.day &&
            day.month == trxnDate.month) {
          List<Events> eventList = [];
          eventList.add(trxnDoc[i].walkThroughDate);
          (kEvents.putIfAbsent(trxnDateUTC, () => eventList));
        }
      }
      //eventList.add(trxnDoc[i]);
      //(kEvents.putIfAbsent(trxnDateUTC, () => eventList))??[];
    }

    return [];
  }

  List<Events> _getEventsForDay(DateTime day,
      [List<Events>? events, List<Trxn>? trxns]) {
    // kEvents is a linkedHashMap
    // Calendar events
    for (int i = 0; i < eventDoc.length; i++) {
      DateTime eventDate = eventDoc[i].eventDate;
      DateTime eventDateUTC = eventDate.toUtc();
      if (day.yearListMap == eventDate.year &&
          day.day == eventDate.day &&
          day.month == eventDate.month) {
        List<Events> eventList = [];
        eventList.add(eventDoc[i]);

        return (kEvents.putIfAbsent(eventDateUTC, () => eventList)) ?? [];
      }
    }
    return [];
  }

  void _onDaySelected(DateTime selectedDay, DateTime focusedDay) {
    if (!isSameDay(_selectedDay, selectedDay)) {
      setState(() {
        _selectedDay = selectedDay;
        _focusedDay = focusedDay;
      });
      _selectedEvents.value = _getEventsForDay(selectedDay);
    }
  }

  void _onVisibleDaysChanged(
      DateTime first, DateTime last, CalendarFormat format) {}

  void _onCalendarCreated(
      DateTime first, DateTime last, CalendarFormat format) {}

  @override
  Widget build(BuildContext context) {
    FirebaseFirestore _db = FirebaseFirestore.instance;

    return Scaffold(
      appBar: CustomAppBar(),
      backgroundColor: Colors.white,
      resizeToAvoidBottomInset: false,
      body: Column(
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          StreamBuilder<QuerySnapshot>(
            stream: _db
                .collection('users')
                .doc(ref.read(globalsNotifierProvider).currentUserId)
                .collection('events')
                .where('eventDate', isGreaterThanOrEqualTo: kFirstDay)
                .where('eventDate', isLessThanOrEqualTo: kLastDay)
                .snapshots(),
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if (snapshot.hasData) {
                List<Events> itemEvent = snapshot.data;
                eventsMap = convertToMap(snapshot.data);
                return _buildTableCalendar(snapshot.data as List<Events>?);
              } else {
                return const CircularProgressIndicator();
              }
            },
          ),
          const SizedBox(height: 8.0),
          ElevatedButton(
            onPressed: () async {
              setState(() {
                showSpinner = true;
              });
              try {
                ref.read(globalsNotifierProvider.notifier).updatenewEvent(true);

                Navigator.of(context).pushReplacement(
                    MaterialPageRoute(builder: (context) => AddEventScreen()));

                setState(() {
                  showSpinner = false;
                });
              } catch (e) {
                // todo: add better error handling
                print(e);
              }
            },
            child: const Text('Add Event'),
          ),
          const SizedBox(height: 8.0),
          Expanded(child: _buildEventList()),
        ],
      ),
    );
  }

  // Simple TableCalendar configuration (using Styles)
  Widget _buildTableCalendar([List<Events>? events, List<Trxn>? trxns]) {
    return TableCalendar(
      firstDay: kFirstDay,
      lastDay: kLastDay,
      focusedDay: _focusedDay,
      selectedDayPredicate: (day) => isSameDay(_selectedDay, day),
      locale: 'en_US',
      eventLoader: (day) {
        return _getEventsForDay(day, events, trxns);
      },
      startingDayOfWeek: StartingDayOfWeek.sunday,
      calendarStyle: CalendarStyle(
        isTodayHighlighted: true,
        selectedDecoration: BoxDecoration(color: Colors.deepOrange[400]),
        todayDecoration: BoxDecoration(color: Colors.deepOrange[200]),
        markerDecoration: const BoxDecoration(color: Colors.deepPurpleAccent),
        outsideDaysVisible: false,
      ),
      headerStyle: HeaderStyle(
        formatButtonTextStyle:
            const TextStyle().copyWith(color: Colors.white, fontSize: 15.0),
        formatButtonDecoration: BoxDecoration(
          color: Colors.deepOrange[400],
          borderRadius: BorderRadius.circular(16.0),
        ),
      ),
      onDaySelected: (selectedDay, focusedDay) {
        setState(() {
          _selectedDay = selectedDay;
          _focusedDay = focusedDay; // update `_focusedDay` here as well
        });
      },
      onPageChanged: (focusedDay) {
        _focusedDay = focusedDay;
      },
    );
  }

  Widget _buildHolidaysMarker() {
    return Icon(
      Icons.add_box,
      size: 20.0,
      color: Colors.blueGrey[800],
    );
  }

  Widget _buildEventList() {
    final _db = FirebaseFirestore.instance;

    return Container(
      child: StreamBuilder<QuerySnapshot>(
        stream: _db
            .collection('users')
            .doc(ref.read(globalsNotifierProvider).currentUserId)
            .collection('event')
            .where('eventDate',
                isGreaterThanOrEqualTo: DateTime(
                    _focusedDay.year, _focusedDay.month, _focusedDay.day, 0, 0))
            .where('eventDate',
                isLessThan: DateTime(_focusedDay.year, _focusedDay.month,
                    _focusedDay.day + 1, 0, 0))
            .snapshots(),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return const Center(
                child: Text(
              'Loading...',
              style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
            ));
          } else {
            var doc = snapshot.data!.docs;
            return ListView.builder(
                itemCount: doc.length,
                itemBuilder: (BuildContext context, int index) {
                  return Padding(
                    padding: const EdgeInsets.all(20.0),
                    child: ListTile(
                      isThreeLine: true,
                      title: Text(
                        '${doc[index]['eventName'] ?? 'n/a'}',
                        style: const TextStyle(
                            fontWeight: FontWeight.w900,
                            color: Colors.blueAccent),
                      ),
                      subtitle: Text.rich(TextSpan(
                          text:
                              '${DateFormat('EE MM-dd-yyyy').format(doc[index]['eventDate']) ?? 'n/a'}\n'
                              '${DateFormat('h:mm a').format(doc[index]['eventStartTime']) ?? 'n/a'}, '
                              'Duration: ${doc[index]['eventDuration'] ?? 'n/a'} minutes',
                          children: <TextSpan>[
                            TextSpan(
                              text:
                                  '\n${doc[index]['eventDescription'] ?? 'n/a'}',
                              style: const TextStyle(
                                  fontWeight: FontWeight.w900,
                                  color: Colors.blueGrey),
                            )
                          ])),
                      //trailing: Text('MLS#: ${_event.mlsNumber ?? 'n/a'}'),
                      onTap: () {
                        ref
                            .read(globalsNotifierProvider.notifier)
                            .updatenewEvent(false);
                        Navigator.of(context).push(MaterialPageRoute(
                            builder: (context) => AddEventScreen()));
                      },
                    ),
                  );
                });
          }
        },
      ),
    );
  }

  Map<DateTime, List>? convertToMap(List<Events> item) {
    Map<DateTime, List>? result;

    for (int i = 0; i < item.length; i++) {
      Events data = item[i];
      DateTime currentDate = DateTime(
          data.eventDate!.year,
          data.eventDate!.month,
          data.eventDate!.day,
          data.eventDate!.hour,
          data.eventDate!.minute);

      List eventNames = [];
      for (int j = 0; j < item.length; j++) {
        //create temp calendarItemData object.
        Events temp = item[j];
        //establish that the temp date is equal to the current date
        if (data.eventDate == temp.eventDate) {
          //add the event name to the event List.
          eventNames.add(temp.eventName);
        } //else continue
      }

      //add the date and the event to the map if the date is not contained in the map
      if (result == null) {
        result = {currentDate: eventNames};
      } else {
        result[currentDate] = eventNames;
      }
      return result;
    }
  }
}

UPDATE:

As the building of the widget goes through it's iterations of building, it eventually creates an instance of the snapshot. When I check to see of the snapshot.data is null I find that it is not but it has no docs, which is what I would expect. However, I see this when I hover over the ".data":

_delegate:
MethodChannelQuerySnapshot
_firestore:
FirebaseFirestore (FirebaseFirestore(app: [DEFAULT]))
docChanges:
List (0 items)
docs:
List (0 items)
hashCode:
479850384
metadata:
SnapshotMetadata
runtimeType:
Type (_JsonQuerySnapshot)
size:
0
0

There are 0 best solutions below