calendar implementation contd.
							parent
							
								
									73f8baa77e
								
							
						
					
					
						commit
						6f745f3666
					
				| @ -0,0 +1,8 @@ | |||||||
|  | class TimeSlot { | ||||||
|  |   String? isoTime; | ||||||
|  |   DateTime? start; | ||||||
|  |   DateTime? end; | ||||||
|  |   String? vidaDate; | ||||||
|  | 
 | ||||||
|  |   TimeSlot({required this.isoTime, required this.start, required this.end, this.vidaDate}); | ||||||
|  | } | ||||||
| @ -0,0 +1,242 @@ | |||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
|  | import 'package:easy_localization/easy_localization.dart'; | ||||||
|  | import 'package:flutter/cupertino.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/core/app_export.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/core/app_state.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/core/dependencies.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/core/utils/date_util.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/features/book_appointments/models/free_slot.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/features/book_appointments/models/timeslots.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/theme/colors.dart'; | ||||||
|  | import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  | import 'package:smooth_corner/smooth_corner.dart'; | ||||||
|  | import 'package:syncfusion_flutter_calendar/calendar.dart'; | ||||||
|  | 
 | ||||||
|  | class AppointmentCalendar extends StatefulWidget { | ||||||
|  |   const AppointmentCalendar({super.key}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   State<AppointmentCalendar> createState() => _AppointmentCalendarState(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _AppointmentCalendarState extends State<AppointmentCalendar> { | ||||||
|  |   late CalendarController _calendarController; | ||||||
|  | 
 | ||||||
|  |   late AppState appState; | ||||||
|  |   late BookAppointmentsViewModel bookAppointmentsViewModel; | ||||||
|  | 
 | ||||||
|  |   var selectedDate = ""; | ||||||
|  |   var selectedNextDate = ""; | ||||||
|  | 
 | ||||||
|  |   int selectedButtonIndex = 0; | ||||||
|  |   int selectedNextDayButtonIndex = -1; | ||||||
|  | 
 | ||||||
|  |   List<TimeSlot> dayEvents = []; | ||||||
|  |   List<TimeSlot> nextDayEvents = []; | ||||||
|  | 
 | ||||||
|  |   late Map<DateTime, List> _events; | ||||||
|  | 
 | ||||||
|  |   static String? selectedTime; | ||||||
|  | 
 | ||||||
|  |   bool isWaitingAppointmentAvailable = false; | ||||||
|  |   final _selectedDay = DateTime.now(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   void initState() { | ||||||
|  |     scheduleMicrotask(() { | ||||||
|  |       _calendarController = CalendarController(); | ||||||
|  |       _events = { | ||||||
|  |         _selectedDay: ['Event A0'] | ||||||
|  |       }; | ||||||
|  |       _onDaySelected(DateUtil.convertStringToDate(bookAppointmentsViewModel.freeSlotsResponse[0])); | ||||||
|  |     }); | ||||||
|  |     super.initState(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     bookAppointmentsViewModel = Provider.of<BookAppointmentsViewModel>(context, listen: false); | ||||||
|  |     appState = getIt.get<AppState>(); | ||||||
|  |     return Column( | ||||||
|  |       crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |       children: [ | ||||||
|  |         SizedBox( | ||||||
|  |           height: 380.h, | ||||||
|  |           child: SfCalendar( | ||||||
|  |             controller: _calendarController, | ||||||
|  |             minDate: DateTime.now(), | ||||||
|  |             showNavigationArrow: true, | ||||||
|  |             headerHeight: 60.h, | ||||||
|  |             headerStyle: CalendarHeaderStyle( | ||||||
|  |               backgroundColor: AppColors.scaffoldBgColor, | ||||||
|  |               textAlign: TextAlign.start, | ||||||
|  |               textStyle: TextStyle(fontSize: 18.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.primaryRedColor, fontFamily: "Poppins"), | ||||||
|  |             ), | ||||||
|  |             viewHeaderStyle: ViewHeaderStyle( | ||||||
|  |               backgroundColor: AppColors.scaffoldBgColor, | ||||||
|  |               dayTextStyle: TextStyle(fontSize: 14.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.textColor), | ||||||
|  |             ), | ||||||
|  |             view: CalendarView.month, | ||||||
|  |             todayHighlightColor: Colors.transparent, | ||||||
|  |             todayTextStyle: TextStyle(color: AppColors.textColor), | ||||||
|  |             selectionDecoration: ShapeDecoration( | ||||||
|  |               color: AppColors.transparent, | ||||||
|  |               shape: SmoothRectangleBorder( | ||||||
|  |                 borderRadius: BorderRadius.circular(12 ?? 0), | ||||||
|  |                 smoothness: 1, | ||||||
|  |                 side: BorderSide(color: AppColors.primaryRedColor, width: 1.5), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             cellBorderColor: AppColors.transparent, | ||||||
|  |             dataSource: MeetingDataSource(_getDataSource()), | ||||||
|  |             monthCellBuilder: (context, details) => Padding( | ||||||
|  |               padding: EdgeInsets.all(12.h), | ||||||
|  |               child: details.date.day.toString().toText14( | ||||||
|  |                     isCenter: true, | ||||||
|  |                     color: details.date == _calendarController.selectedDate ? AppColors.primaryRedColor : AppColors.textColor, | ||||||
|  |                   ), | ||||||
|  |             ), | ||||||
|  |             monthViewSettings: MonthViewSettings( | ||||||
|  |               dayFormat: "EEE", | ||||||
|  |               appointmentDisplayMode: MonthAppointmentDisplayMode.indicator, | ||||||
|  |               showTrailingAndLeadingDates: false, | ||||||
|  |               appointmentDisplayCount: 1, | ||||||
|  |               monthCellStyle: MonthCellStyle( | ||||||
|  |                 textStyle: TextStyle(fontSize: 19.fSize), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             onTap: (CalendarTapDetails details) { | ||||||
|  |               _calendarController.selectedDate = details.date; | ||||||
|  |               _onDaySelected(details.date!); | ||||||
|  |             }, | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |         //TODO: Add Next Day Span here | ||||||
|  |         Container( | ||||||
|  |           height: 40, | ||||||
|  |           child: ListView.builder( | ||||||
|  |             scrollDirection: Axis.horizontal, | ||||||
|  |             itemCount: dayEvents.length, | ||||||
|  |             itemBuilder: (context, index) { | ||||||
|  |               return Container( | ||||||
|  |                 margin: EdgeInsets.only(right: (index == dayEvents.length - 1) ? 16 : 5.0, left: index == 0 ? 16 : 5), | ||||||
|  |                 child: AppCustomChipWidget( | ||||||
|  |                   labelText: dayEvents[index].isoTime, | ||||||
|  |                   backgroundColor: AppColors.whiteColor, | ||||||
|  |                 ), | ||||||
|  |                 // index == selectedButtonIndex ? getSelectedButton(index) : getNormalButton(index), | ||||||
|  |               ); | ||||||
|  |             }, | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |       ], | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   List<Meeting> _getDataSource() { | ||||||
|  |     final List<Meeting> meetings = <Meeting>[]; | ||||||
|  |     for (var slot in bookAppointmentsViewModel.freeSlotsResponse) { | ||||||
|  |       final startTime = DateUtil.convertStringToDate(slot); | ||||||
|  | 
 | ||||||
|  |       final endTime = startTime.add(const Duration(minutes: 15)); | ||||||
|  | 
 | ||||||
|  |       meetings.add(Meeting( | ||||||
|  |           "Available", // Or leave empty with "" | ||||||
|  |           startTime, | ||||||
|  |           endTime, | ||||||
|  |           AppColors.primaryRedColor, | ||||||
|  |           false, | ||||||
|  |           "" // Optional notes | ||||||
|  |           )); | ||||||
|  |     } | ||||||
|  |     return meetings; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // TODO: | ||||||
|  |   openTimeSlotsPickerForDate(DateTime dateStart, List<TimeSlot> freeSlots) { | ||||||
|  |     dayEvents.clear(); | ||||||
|  |     DateTime dateStartObj = new DateTime(dateStart.year, dateStart.month, dateStart.day, 0, 0, 0, 0, 0); | ||||||
|  |     if (isWaitingAppointmentAvailable && DateUtils.isSameDay(dateStart, DateTime.now())) { | ||||||
|  |       dayEvents.add(TimeSlot(isoTime: "Waiting Appointment", start: DateTime.now(), end: DateTime.now(), vidaDate: "")); | ||||||
|  |     } | ||||||
|  |     freeSlots.forEach((v) { | ||||||
|  |       if (v.start == dateStartObj) dayEvents.add(v); | ||||||
|  |     }); | ||||||
|  |     selectedButtonIndex = 0; | ||||||
|  |     List<Map<String, dynamic>> timeList = []; | ||||||
|  |     for (var i = 0; i < dayEvents.length; i++) { | ||||||
|  |       Map<String, dynamic> timeSlot = {"isoTime": dayEvents[i].isoTime, "start": dayEvents[i].start.toString(), "end": dayEvents[i].end.toString(), "vidaDate": dayEvents[i].vidaDate}; | ||||||
|  |       timeList.add(timeSlot); | ||||||
|  |     } | ||||||
|  |     selectedTime = dayEvents[selectedButtonIndex].isoTime; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _onDaySelected(DateTime day) { | ||||||
|  |     final DateFormat formatter = DateFormat('yyyy-MM-dd'); | ||||||
|  |     setState(() { | ||||||
|  |       selectedDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day, "en"); | ||||||
|  |       selectedNextDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day.add(Duration(days: 1)), "en"); | ||||||
|  |       _calendarController.selectedDate = day; | ||||||
|  |       openTimeSlotsPickerForDate(day, bookAppointmentsViewModel.docFreeSlots); | ||||||
|  |       selectedDate = formatter.format(day); | ||||||
|  |       selectedNextDayButtonIndex = -1; | ||||||
|  |       print(_calendarController.selectedDate); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class MeetingDataSource extends CalendarDataSource { | ||||||
|  |   MeetingDataSource(List<Meeting> source) { | ||||||
|  |     appointments = source; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   DateTime getStartTime(int index) { | ||||||
|  |     return _getMeetingData(index)!.from; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   DateTime getEndTime(int index) { | ||||||
|  |     return _getMeetingData(index)!.to; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   String getSubject(int index) { | ||||||
|  |     return _getMeetingData(index)!.eventName; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Color getColor(int index) { | ||||||
|  |     return _getMeetingData(index)!.background; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   bool isAllDay(int index) { | ||||||
|  |     return _getMeetingData(index)!.isAllDay; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Meeting? _getMeetingData(int index) { | ||||||
|  |     final dynamic meeting = appointments?[index]; | ||||||
|  |     Meeting? meetingData; | ||||||
|  |     if (meeting is Meeting) { | ||||||
|  |       meetingData = meeting; | ||||||
|  |     } | ||||||
|  |     return meetingData; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class Meeting { | ||||||
|  |   Meeting(this.eventName, this.from, this.to, this.background, this.isAllDay, this.notes); | ||||||
|  | 
 | ||||||
|  |   String eventName; | ||||||
|  |   DateTime from; | ||||||
|  |   DateTime to; | ||||||
|  |   Color background; | ||||||
|  |   bool isAllDay; | ||||||
|  |   String notes; | ||||||
|  | } | ||||||
					Loading…
					
					
				
		Reference in New Issue