I have a bookings collection in Firebase and I am trying to populate the events in TableCalendar using it, my listview Is successfully showing all bookings when I click on a date I I just need the markers to show for each date so the admin knows if there is a booking there or not
The booking model:
import 'package:cloud_firestore/cloud_firestore.dart';
class Booking {
final String serviceTitle;
final DateTime bookingDate;
final DateTime startTime;
final DateTime endTime;
final String userEmail; // Added field for user's email
Booking({
required this.serviceTitle,
required this.bookingDate,
required this.startTime,
required this.endTime,
required this.userEmail, // Included user's email
});
// Constructor to initialize from Firestore document
Booking.fromFirestore(QueryDocumentSnapshot<Map<String, dynamic>> doc)
: serviceTitle = doc['serviceTitle'],
bookingDate = (doc['bookingDate'] as Timestamp).toDate(),
startTime = (doc['startTime'] as Timestamp).toDate(),
endTime = (doc['endTime'] as Timestamp).toDate(),
userEmail = doc['userEmail']; // Initialize user's email field
}
The Way I get data from Firebase in dbhandler class:
//Return all listing from all Users
Future<List<Booking>> getAllBookings() async {
List<Booking> allBookings = [];
try {
QuerySnapshot querySnapshot =
await FirebaseFirestore.instance.collection('bookings').get();
allBookings = querySnapshot.docs.map((doc) {
Map<String, dynamic> bookingData = doc.data() as Map<String, dynamic>;
return Booking(
serviceTitle: bookingData['serviceTitle'],
bookingDate: (bookingData['bookingDate'] as Timestamp).toDate(),
startTime: (bookingData['startTime'] as Timestamp).toDate(),
endTime: (bookingData['endTime'] as Timestamp).toDate(),
userEmail: bookingData['userEmail'],
// You can include other fields as needed
);
}).toList();
} catch (e) {
print('Error retrieving all bookings: $e');
}
return allBookings;
}
The admin page:
import 'package:flutter/material.dart';
import 'package:mona/pages/models/booking.dart';
import 'package:mona/services/auth/db_handler.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:intl/intl.dart';
class AdminPage extends StatefulWidget {
const AdminPage({super.key});
@override
State<AdminPage> createState() => _AdminPageState();
}
class _AdminPageState extends State<AdminPage> {
CalendarFormat _calendarFormat = CalendarFormat.month;
DateTime _focusedDay = DateTime.now();
DateTime _selectedDay = DateTime.now();
DBHandler dbhandler = DBHandler();
List<Booking> allBookings = [];
List<Booking> filteredBooking = [];
//now i neeed a selected events where it returns events for a certain day when clciked
Map<DateTime, List<Booking>> _events = {};
@override
void initState() {
super.initState();
fetchAllBookings();
//Starting off with Todays List
filteredBooking = filterBookingsByDate(DateTime.now());
}
Future<void> fetchAllBookings() async {
List<Booking> bookings = await dbhandler.getAllBookings();
setState(() {
allBookings = bookings;
organizeBookings(allBookings);
print(_events.toString());
});
}
//organising bookings into events method
void organizeBookings(List<Booking> allBookings) {
for (var booking in allBookings) {
DateTime date = booking.bookingDate;
if (_events.containsKey(date)) {
_events[date]!.add(booking);
} else {
_events[date] = [booking];
}
}
}
List<Booking> filterBookingsByDate(DateTime selectedDate) {
List<Booking> filteredBookings = [];
for (var booking in allBookings) {
if (isSameDay(booking.bookingDate, selectedDate)) {
filteredBookings.add(booking);
}
}
return filteredBookings;
}
//need a method here to get bookings for a particular Date
//I can interate thourhg the Bookings list trying to match the bookingDate to selectedDay
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Calendar'),
),
body: Center(
child: Column(
children: [
TableCalendar(
firstDay: DateTime.utc(2010, 10, 16),
lastDay: DateTime.utc(2030, 3, 14),
focusedDay: DateTime.now(),
calendarFormat: _calendarFormat,
onFormatChanged: (format) {
setState(() {
_calendarFormat = format;
});
},
selectedDayPredicate: (day) {
return isSameDay(_selectedDay, day);
},
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay; // Update focused day as well
filteredBooking = filterBookingsByDate(selectedDay);
//use the Selected Day to get List of bookings below
});
},
onPageChanged: (focusedDay) {
_focusedDay = focusedDay;
},
eventLoader: (day) {
return _events[day] ?? [];
},
),
const SizedBox(height: 16.0), // Add spacing
Expanded(
child: ListView.builder(
itemCount: filteredBooking.length,
itemBuilder: (context, index) {
Booking booking = filteredBooking[index];
return Container(
color: Colors.grey[200],
margin: EdgeInsets.all(10),
child: ListTile(
title: Text('Service: ${booking.serviceTitle}'),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Date: ${DateFormat('dd-MM-yyyy').format(booking.bookingDate)}'),
Text(
'Start Time: ${DateFormat('HH:mm').format(booking.startTime)}'),
Text(
'End Time: ${DateFormat('HH:mm').format(booking.endTime)}'),
Text('User Email: ${booking.userEmail}'),
],
),
),
);
},
),
),
const SizedBox(height: 8.0),
],
),
),
);
}
}
And this is what the bookings collection looks like:
bookingDate
August 15, 2023 at 1:36:18 PM UTC+1
(timestamp)
bookingId
"ExlESetu1qLXPBFn2q62"
endTime
August 15, 2023 at 12:00:00 PM UTC+1
serviceTitle
"Service A"
startTime
August 15, 2023 at 11:30:00 AM UTC+1
userEmail
"jondoe@gmail.com"
userId
"lQe76eOCCrYy14ahbmEh5p8HTnM2"