import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/models/Appointments/FreeSlot.dart'; import 'package:diplomaticquarterapp/models/Appointments/timeSlot.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:table_calendar/table_calendar.dart'; import '../../../uitl/date_uitl.dart'; class DocAvailableAppointments extends StatefulWidget { DoctorList doctor; static bool areSlotsAvailable = false; static bool areAppointmentsAvailable = false; static DateTime selectedAppoDateTime; static String selectedDate; static String selectedTime; bool isLiveCareAppointment; DocAvailableAppointments( {@required this.doctor, @required this.isLiveCareAppointment}); @override _DocAvailableAppointmentsState createState() => _DocAvailableAppointmentsState(); } class _DocAvailableAppointmentsState extends State with TickerProviderStateMixin { Map _events; AnimationController _animationController; CalendarController _calendarController; AppSharedPreferences sharedPref = new AppSharedPreferences(); var selectedDate = ""; dynamic selectedDateJSON; dynamic jsonFreeSlots; List docFreeSlots = []; List dayEvents = []; int selectedButtonIndex = 0; dynamic freeSlotsResponse; ScrollController _scrollController; var language; @override void initState() { // TODO: implement initState super.initState(); final _selectedDay = DateTime.now(); _scrollController = new ScrollController(); _events = { _selectedDay: ['Event A0'] }; WidgetsBinding.instance.addPostFrameCallback((_) async { getCurrentLanguage(); if (widget.isLiveCareAppointment) getDoctorScheduledFreeSlots(context, widget.doctor); else { getDoctorFreeSlots(context, widget.doctor); } }); _calendarController = CalendarController(); _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 50), ); _animationController.forward(); } @override void dispose() { _animationController.dispose(); _calendarController.dispose(); super.dispose(); } void _onDaySelected(DateTime day, List events) { final DateFormat formatter = DateFormat('yyyy-MM-dd'); setState(() { this.selectedDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day, language); openTimeSlotsPickerForDate(day, docFreeSlots); DocAvailableAppointments.selectedDate = formatter.format(day); print(DocAvailableAppointments.selectedDate); }); } void _onVisibleDaysChanged( DateTime first, DateTime last, CalendarFormat format) { print('CALLBACK: _onVisibleDaysChanged'); } void _onCalendarCreated( DateTime first, DateTime last, CalendarFormat format) { print('CALLBACK: _onCalendarCreated'); } @override Widget build(BuildContext context) { return SingleChildScrollView( child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10.0)), margin: EdgeInsets.all(20.0), padding: EdgeInsets.only(bottom: 10.0, top: 10.0), child: Column( mainAxisSize: MainAxisSize.max, children: [ Text(selectedDate, style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold)), Container( height: 50, margin: EdgeInsets.all(20.0), child: ListView.builder( controller: _scrollController, scrollDirection: Axis.horizontal, itemCount: dayEvents.length, itemBuilder: (context, index) { return Container( margin: EdgeInsets.only(right: 10.0), child: ButtonTheme( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5.0), side: BorderSide( color: Color(0xff76cfb7), //Color of the border style: BorderStyle.solid, //Style of the border width: 1.5, //width of the border ), ), minWidth: MediaQuery.of(context).size.width * 0.2, child: index == selectedButtonIndex ? getSelectedButton(index) : getNormalButton(index)), ); }, ), ), _buildTableCalendarWithBuilders(), ], ), ), ); } Widget _buildTableCalendarWithBuilders() { return TableCalendar( locale: language == "en" ? 'en_US' : 'ar_SA', calendarController: _calendarController, events: _events, initialCalendarFormat: CalendarFormat.month, startDay: DateTime.now(), formatAnimation: FormatAnimation.slide, startingDayOfWeek: StartingDayOfWeek.sunday, weekendDays: [DateTime.friday, DateTime.saturday], availableGestures: AvailableGestures.horizontalSwipe, availableCalendarFormats: const { CalendarFormat.month: '', CalendarFormat.week: '', }, calendarStyle: CalendarStyle( outsideDaysVisible: false, weekendStyle: TextStyle().copyWith(color: Colors.blue[800]), holidayStyle: TextStyle().copyWith(color: Colors.blue[800]), ), daysOfWeekStyle: DaysOfWeekStyle( weekendStyle: TextStyle().copyWith(color: Colors.black, fontSize: 14.0), weekdayStyle: TextStyle().copyWith(color: Colors.black, fontSize: 14.0), ), headerStyle: HeaderStyle( centerHeaderTitle: true, formatButtonVisible: false, ), builders: CalendarBuilders( selectedDayBuilder: (context, date, _) { return FadeTransition( opacity: Tween(begin: 0.0, end: 1.0).animate(_animationController), child: Container( margin: const EdgeInsets.all(4.0), padding: const EdgeInsets.only(top: 5.0, left: 5.0), color: Colors.transparent, width: 0, height: 0, child: Text( '${date.day}', style: TextStyle().copyWith(fontSize: 16.0), ), ), ); }, todayDayBuilder: (context, date, _) { return Container( decoration: BoxDecoration( shape: BoxShape.circle, color: _calendarController.isSelected(date) ? Colors.green[400] : _calendarController.isToday(date) ? Colors.transparent : Color(0xff76cfb7), ), width: 40.0, height: 40.0, child: Center( child: Text( '${date.day}', style: TextStyle().copyWith( color: Colors.white, fontSize: 14.0, ), ), ), ); }, markersBuilder: (context, date, events, _) { final children = []; if (events.isNotEmpty) { children.add( Positioned( right: 4, bottom: 4, child: _buildEventsMarker(date, events), ), ); } return children; }, ), onDaySelected: (date, event, _) { _onDaySelected(date, event); _animationController.forward(from: 0.0); }, onVisibleDaysChanged: _onVisibleDaysChanged, onCalendarCreated: _onCalendarCreated, ); } openTimeSlotsPickerForDate(DateTime dateStart, List freeSlots) { dayEvents.clear(); DateTime dateStartObj = new DateTime( dateStart.year, dateStart.month, dateStart.day, 0, 0, 0, 0, 0); freeSlots.forEach((v) { if (v.start == dateStartObj) dayEvents.add(v); }); setState(() { if (dayEvents.length != 0) DocAvailableAppointments.areSlotsAvailable = true; else DocAvailableAppointments.areSlotsAvailable = false; selectedButtonIndex = 0; DocAvailableAppointments.selectedTime = dayEvents[selectedButtonIndex].isoTime; // _scrollController.animateTo(0.0, duration: new Duration(seconds: 1), curve: Curves.ease); }); } Future> _getJSONSlots() async { Map _eventsParsed; List slotsList = []; DateTime date; final DateFormat formatter = DateFormat('HH:mm'); final DateFormat dateFormatter = DateFormat('yyyy-MM-dd'); for (var i = 0; i < freeSlotsResponse.length; i++) { date = DateUtil.convertStringToDate(freeSlotsResponse[i]); slotsList.add(FreeSlot(date, ['slot'])); docFreeSlots.add(TimeSlot( isoTime: formatter.format(date), start: new DateTime(date.year, date.month, date.day, 0, 0, 0, 0), end: date)); } _eventsParsed = Map.fromIterable(slotsList, key: (e) => e.slot, value: (e) => e.event); setState(() { DocAvailableAppointments.selectedDate = dateFormatter .format(DateUtil.convertStringToDate(freeSlotsResponse[0])); selectedDate = DateUtil.getWeekDayMonthDayYearDateFormatted( DateUtil.convertStringToDate(freeSlotsResponse[0]), language); selectedDateJSON = freeSlotsResponse[0]; }); openTimeSlotsPickerForDate( DateUtil.convertStringToDate(selectedDateJSON), docFreeSlots); _calendarController .setFocusedDay(DateUtil.convertStringToDate(selectedDateJSON)); return _eventsParsed; } Widget getNormalButton(int index) { return RaisedButton( color: Colors.white, textColor: new Color(0xFF60686b), onPressed: () { setState(() { selectedButtonIndex = index; DocAvailableAppointments.selectedTime = dayEvents[index].isoTime; print(DocAvailableAppointments.selectedTime); }); }, child: Text(dayEvents[index].isoTime, style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold)), ); } Widget getSelectedButton(int index) { return RaisedButton( color: Color(0xff76cfb7), //Color of the border textColor: Colors.white, onPressed: () { setState(() { selectedButtonIndex = index; DocAvailableAppointments.selectedTime = dayEvents[index].isoTime; print(DocAvailableAppointments.selectedTime); }); }, child: Text(dayEvents[index].isoTime, style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold)), ); } getDoctorFreeSlots(context, DoctorList docObject) { GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); service .getDoctorFreeSlots(docObject.doctorID, docObject.clinicID, docObject.projectID, context) .then((res) { GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { if (res['FreeTimeSlots'].length != 0) { DocAvailableAppointments.areAppointmentsAvailable = true; freeSlotsResponse = res['FreeTimeSlots']; print("res['FreeTimeSlots']"); print(res['FreeTimeSlots'].length); _getJSONSlots().then((value) => { setState(() => {_events.clear(), _events = value}) }); } else { DocAvailableAppointments.areAppointmentsAvailable = false; } } else { AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); AppToast.showErrorToast(message: err); print(err); }); } getDoctorScheduledFreeSlots(context, DoctorList docObject) { GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); service .getDoctorScheduledFreeSlots(docObject.doctorID, docObject.clinicID, docObject.projectID, docObject.serviceID, context) .then((res) { GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { if (res['PatientER_DoctorFreeSlots'].length != 0) { DocAvailableAppointments.areAppointmentsAvailable = true; freeSlotsResponse = res['PatientER_DoctorFreeSlots']; print("res['PatientER_DoctorFreeSlots']"); print(res['PatientER_DoctorFreeSlots'].length); _getJSONSlots().then((value) => { setState(() => {_events.clear(), _events = value}) }); } else { DocAvailableAppointments.areAppointmentsAvailable = false; } } else { AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); AppToast.showErrorToast(message: err); print(err); }); } getCurrentLanguage() async { var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); setState(() { this.language = languageID; }); } Widget _buildEventsMarker(DateTime date, List events) { return Container( decoration: BoxDecoration( shape: BoxShape.circle, color: _calendarController.isSelected(date) ? Color(0xffB8382C) : _calendarController.isToday(date) ? Colors.brown[300] : Color(0xff76cfb7), ), width: 40.0, height: 40.0, child: Center( child: Text( '${date.day}', style: TextStyle().copyWith( color: Colors.white, fontSize: 14.0, ), ), ), ); } }