diff --git a/lib/config/shared_pref_kay.dart b/lib/config/shared_pref_kay.dart index 4f83e7eb..50390ae2 100644 --- a/lib/config/shared_pref_kay.dart +++ b/lib/config/shared_pref_kay.dart @@ -32,3 +32,4 @@ const PHARMACY_AUTORZIE_TOKEN = 'PHARMACY_AUTORZIE_TOKEN'; const H2O_UNIT = 'H2O_UNIT'; const H2O_REMINDER = 'H2O_REMINDER'; const LIVECARE_CLINIC_DATA = 'LIVECARE_CLINIC_DATA'; +const DOCTOR_SCHEDULE_DATE_SEL = 'DOCTOR_SCHEDULE_DATE_SEL'; diff --git a/lib/core/service/medical/medical_service.dart b/lib/core/service/medical/medical_service.dart index a23519fa..5888fa0d 100644 --- a/lib/core/service/medical/medical_service.dart +++ b/lib/core/service/medical/medical_service.dart @@ -9,6 +9,7 @@ import 'package:diplomaticquarterapp/pages/MyAppointments/models/DoctorScheduleR class MedicalService extends BaseService { List appoitmentAllHistoryResultList = List(); List doctorScheduleResponse = List(); + List freeSlots = []; getAppointmentHistory({bool isActiveAppointment = false}) async { hasError = false; super.error = ""; @@ -46,7 +47,7 @@ class MedicalService extends BaseService { }, body: body); } - Future getSchedule(DoctorList doctorRequest) async { + getSchedule(DoctorList doctorRequest) async { Map request; request = { 'DoctorID': doctorRequest.doctorID, @@ -61,8 +62,29 @@ class MedicalService extends BaseService { }, onFailure: (String error, int statusCode) { throw error; }, body: request); - + doctorScheduleResponse.clear(); localRes['List_DoctorWorkingHoursTable'].forEach((item) => {doctorScheduleResponse.add(DoctorScheduleResponse.fromJson(item))}); } + + getFreeSlot(DoctorList doctorRequest) async { + Map request; + request = { + 'DoctorID': doctorRequest.doctorID, + 'ProjectID': doctorRequest.projectID, + 'ClinicID': doctorRequest.clinicID, + 'DoctorWorkingHoursDays': 7 + }; + dynamic localRes; + await baseAppClient.post(GET_DOCTOR_FREE_SLOTS, + onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + freeSlots.clear(); + localRes['FreeTimeSlots'].forEach((item) => freeSlots.add(item)); + // localRes['List_DoctorWorkingHoursTable'].forEach((item) => + // {doctorScheduleResponse.add(DoctorScheduleResponse.fromJson(item))}); + } } diff --git a/lib/core/viewModels/medical/medical_view_model.dart b/lib/core/viewModels/medical/medical_view_model.dart index b73e6a5f..647982d1 100644 --- a/lib/core/viewModels/medical/medical_view_model.dart +++ b/lib/core/viewModels/medical/medical_view_model.dart @@ -14,7 +14,7 @@ class MedicalViewModel extends BaseViewModel { _medicalService.appoitmentAllHistoryResultList; List get getDoctorScheduleList => _medicalService.doctorScheduleResponse; - + List get freeSlots => _medicalService.freeSlots; getAppointmentHistory() async { if (authenticatedUserObject.isLogin) { setState(ViewState.Busy); @@ -38,4 +38,16 @@ class MedicalViewModel extends BaseViewModel { setState(ViewState.Idle); } } + + getFreeSlots(DoctorList doctorRequest) async { + if (authenticatedUserObject.isLogin) { + setState(ViewState.Busy); + await _medicalService.getFreeSlot(doctorRequest); + if (_medicalService.hasError) { + error = _medicalService.error; + setState(ViewState.Error); + } else + setState(ViewState.Idle); + } + } } diff --git a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart index cd8bb789..e5fcfe31 100644 --- a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart +++ b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart @@ -21,9 +21,11 @@ class DocAvailableAppointments extends StatefulWidget { static String selectedDate; static String selectedTime; bool isLiveCareAppointment; - + final dynamic doctorSchedule; DocAvailableAppointments( - {@required this.doctor, @required this.isLiveCareAppointment}); + {@required this.doctor, + this.doctorSchedule, + @required this.isLiveCareAppointment}); @override _DocAvailableAppointmentsState createState() => @@ -67,6 +69,7 @@ class _DocAvailableAppointmentsState extends State WidgetsBinding.instance.addPostFrameCallback((_) async { getCurrentLanguage(); + if (widget.isLiveCareAppointment) getDoctorScheduledFreeSlots(context, widget.doctor); else { @@ -107,9 +110,7 @@ class _DocAvailableAppointmentsState extends State } void _onCalendarCreated( - DateTime first, DateTime last, CalendarFormat format) { - print('CALLBACK: _onCalendarCreated'); - } + DateTime first, DateTime last, CalendarFormat format) {} @override Widget build(BuildContext context) { @@ -350,9 +351,23 @@ class _DocAvailableAppointmentsState extends State freeSlotsResponse = res['FreeTimeSlots']; print("res['FreeTimeSlots']"); print(res['FreeTimeSlots'].length); - _getJSONSlots().then((value) => { - setState(() => {_events.clear(), _events = value}) - }); + _getJSONSlots().then((value) { + setState(() => { + _events.clear(), + _events = value, + if (widget.doctorSchedule != null) + { + _calendarController.setSelectedDay( + DateUtil.convertStringToDate( + widget.doctorSchedule['Date']), + isProgrammatic: true), + _onDaySelected( + DateUtil.convertStringToDate( + widget.doctorSchedule['Date']), + List()) + } + }); + }); } else { DocAvailableAppointments.areAppointmentsAvailable = false; } diff --git a/lib/pages/MyAppointments/AppointmentDetails.dart b/lib/pages/MyAppointments/AppointmentDetails.dart index 877192e6..c208efba 100644 --- a/lib/pages/MyAppointments/AppointmentDetails.dart +++ b/lib/pages/MyAppointments/AppointmentDetails.dart @@ -15,16 +15,17 @@ import 'package:diplomaticquarterapp/pages/MyAppointments/SchedulePage.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:rating_bar/rating_bar.dart'; - +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'widgets/AppointmentActions.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; class AppointmentDetails extends StatefulWidget { AppoitmentAllHistoryResultList appo; static bool isLoading = false; - + final dynamic doctorSchedule; static bool showFooterButton = false; - AppointmentDetails({@required this.appo}); + AppointmentDetails({@required this.appo, this.doctorSchedule}); @override _AppointmentDetailsState createState() => _AppointmentDetailsState(); @@ -34,13 +35,20 @@ class _AppointmentDetailsState extends State with SingleTickerProviderStateMixin { static TabController _tabController; + AppSharedPreferences sharedPref = AppSharedPreferences(); List doctorDetailsList = List(); @override void initState() { - _tabController = new TabController(length: 2, vsync: this); AppointmentDetails.showFooterButton = false; - print(widget.appo.clinicID); + if (widget.doctorSchedule != null) { + _tabController = + new TabController(length: 2, vsync: this, initialIndex: 1); + widget.appo.appointmentDate = widget.doctorSchedule['Date']; + } else { + _tabController = new TabController(length: 2, vsync: this); + } + setTab(); super.initState(); } @@ -233,6 +241,7 @@ class _AppointmentDetailsState extends State enableFooterButton: enableFooterButton), DocAvailableAppointments( doctor: getDoctorObject(), + doctorSchedule: widget.doctorSchedule, isLiveCareAppointment: widget.appo.isLiveCareAppointment) ], @@ -241,7 +250,7 @@ class _AppointmentDetailsState extends State ), ], ), - _tabController.index == 0 + _tabController.index == 1 ? Positioned( right: 30.0, //top: 30.0, @@ -607,6 +616,18 @@ class _AppointmentDetailsState extends State } void openSchedule() { - Navigator.push(context, FadePage(page: SchedulePage(getDoctorObject()))); + Navigator.push( + context, + FadePage( + page: SchedulePage( + appo: widget.appo, + doctorList: getDoctorObject(), + ))); + } + + setTab() async { + var scheduleDoctor = await sharedPref.getObject(DOCTOR_SCHEDULE_DATE_SEL); + + widget.appo.appointmentDate = scheduleDoctor['Date']; } } diff --git a/lib/pages/MyAppointments/SchedulePage.dart b/lib/pages/MyAppointments/SchedulePage.dart index e83e8408..6f6376dd 100644 --- a/lib/pages/MyAppointments/SchedulePage.dart +++ b/lib/pages/MyAppointments/SchedulePage.dart @@ -1,4 +1,5 @@ import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/pages/MyAppointments/AppointmentDetails.dart'; import 'package:diplomaticquarterapp/pages/MyAppointments/models/DoctorScheduleResponse.dart'; import 'package:diplomaticquarterapp/pages/MyAppointments/widgets/indicator.dart'; @@ -6,16 +7,22 @@ import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsLis import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; -import 'package:hexcolor/hexcolor.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/medical_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; class SchedulePage extends StatefulWidget { final DoctorList doctorList; - - SchedulePage(this.doctorList); + final AppoitmentAllHistoryResultList appo; + SchedulePage({ + this.appo, + this.doctorList, + }); @override _SchedulePageState createState() => _SchedulePageState(); } @@ -25,139 +32,226 @@ class _SchedulePageState extends State { PageController _pageController = PageController(); double currentPage = 0; int selectedindex = 0; - bool isLoading = true; + List weeks = []; List doctorScheduleResponse = []; - final List introWidgetsList = [ - Text('Hello'), - Text('Hi'), - Text('hey') - ]; + int weekMS = 604800 * 1000; + DoctorList doctorList; + List freeSlots = []; + bool isPageChange = false; + AppSharedPreferences sharedPref = AppSharedPreferences(); @override void initState() { - //getSchedule(widget.doctorList, context); - // _pageController.addListener(() { - // setState(() { - // currentPage = _pageController.page; - // }); - // }); + this.doctorList = widget.doctorList; + super.initState(); } @override Widget build(BuildContext context) { return BaseView( - onModelReady: (model) => model.getDoctorSchedule(widget.doctorList), - builder: (_, model, widget) => AppScaffold( - appBarTitle: TranslationBase.of(context).schedule, - isShowAppBar: true, - baseViewModel: model, - body: SizedBox( - height: MediaQuery.of(context).size.height, - child: Stack( - children: [ - Container( - child: PageView.builder( - controller: _pageController, - itemCount: 3, - onPageChanged: (index) { - setState(() { - this.currentPage = index.toDouble(); - }); - }, - itemBuilder: (context, index) { - return Container( - child: ListView.builder( - itemCount: model.getDoctorScheduleList.length, - itemBuilder: (context, index) => ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(20.0)), - child: Container( - padding: EdgeInsets.only( - left: 10, - right: 10, - top: 20, - bottom: 20), - margin: EdgeInsets.only( - left: 20, - right: 20, - top: 7, - bottom: 7), - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - color: Colors.green, - offset: Offset(-10, 0)), - ], - borderRadius: - const BorderRadius.all( - Radius.circular(10.0)), - color: Colors.white), - child: Row( - children: [ - Expanded( - child: Row(children: [ - Column( - children: [ - Texts( - model - .getDoctorScheduleList[ - index] - .dayName, - color: - HexColor('#0bb690'), - ), - Texts( - DateUtil - .getDayMonthYearDateFormatted( - DateUtil - .convertStringToDate( - model - .getDoctorScheduleList[ - index] - .date, - ), + onModelReady: (model) => model.getDoctorSchedule(doctorList), + builder: (_, model, widget) => BaseView( + onModelReady: (model2) => model2.getFreeSlots(doctorList), + builder: (_, model2, widget2) { + if (model.freeSlots.length > 0 && isPageChange == false) { + this.freeSlots = model.freeSlots; + this.doctorScheduleResponse = model.getDoctorScheduleList; + + this.generateWeeksSchedules(); + } + return AppScaffold( + appBarTitle: TranslationBase.of(context).schedule, + isShowAppBar: true, + baseViewModel: model2, + body: SizedBox( + height: MediaQuery.of(context).size.height, + child: Stack( + children: [ + Container( + margin: EdgeInsets.only(top: 40), + child: PageView.builder( + controller: _pageController, + itemCount: weeks.length, + onPageChanged: (index) { + setState(() { + isPageChange = true; + this.currentPage = index.toDouble(); + }); + }, + itemBuilder: (context, index) { + return Container( + child: ListView.builder( + itemCount: weeks[index].length, + itemBuilder: (context, index2) => + InkWell( + onTap: () { + openBookAppointment( + weeks[index][index2]); + }, + child: Row( + children: [ + Expanded( + flex: 1, + child: Padding( + padding: + EdgeInsets.only( + left: 20), + child: Row( + children: [ + Column( + children: [ + Texts( + weeks[index][index2] + [ + 'DayName'], + fontSize: + 13, + ), + Texts( + getDayMonths( + DateUtil + .convertStringToDate( + weeks[index][index2]['Date'], + ), + ), + fontWeight: + FontWeight.bold, + fontSize: + 18, + ) + ], + ) + ])), ), - color: - HexColor('#0bb690'), - ) - ], - ) - ]), - ), - Expanded( - child: Texts( - model - .getDoctorScheduleList[ - index] - .workingHours, - color: HexColor('#0bb690'), - ), - ) - ], - ))))); - }, - )), - PageViewIndicator( - isActive: true, - currentPage: this.currentPage, - length: introWidgetsList.length, - ) - ], - )))); + Expanded( + flex: 3, + child: ClipRRect( + borderRadius: + const BorderRadius + .all( + Radius.circular( + 20.0)), + child: Container( + padding: + EdgeInsets.only( + left: + 10, + right: + 10, + top: 20, + bottom: + 20), + margin: EdgeInsets.only( + left: 20, + right: 20, + top: 7, + bottom: 7), + decoration: BoxDecoration( + boxShadow: [ + weeks[index][index2]['fullDay'] == + false + ? BoxShadow( + color: Colors.green, + offset: Offset(-5, 0)) + : BoxShadow(), + ], + borderRadius: + const BorderRadius.all(Radius.circular( + 10.0)), + color: Colors + .white), + child: Row( + children: [ + Expanded( + child: + Texts( + weeks[index][index2] + [ + 'WorkingHours'], + fontWeight: + FontWeight.w400, + ), + ) + ], + ))), + ) + ], + )))); + }, + )), + PageViewIndicator( + isActive: true, + currentPage: this.currentPage, + length: weeks.length, + ) + ], + ))); + })); + } + + generateWeeksSchedules() { + this.weeks.clear(); + for (var i = 0; i < 8; i++) { + var weekSchedule = generateNewWeekSchedule(i); + this.markWeekFreeDays(weekSchedule); + this.weeks.add(weekSchedule); + } + //print(this.weeks); + } + + markWeekFreeDays(schedule) { + for (var workDay in schedule) { + workDay['fullDay'] = !this.hasFreeSlot(workDay['Date']); + } + } + + generateNewWeekSchedule(weekIndex) { + var weekMSOffset = weekIndex * weekMS; + + var newWeekSchedule = []; + for (var workDay in this.doctorScheduleResponse) { + Map newWorkDay = Map(); + newWorkDay['Date'] = DateUtil.convertDateMSToJsonDate( + DateUtil.convertStringToDate(workDay.date).millisecondsSinceEpoch + + weekMSOffset); + newWorkDay['DayName'] = workDay.dayName; + newWorkDay['WorkingHours'] = workDay.workingHours; + newWeekSchedule.add(newWorkDay); + } + return newWeekSchedule; + } + + hasFreeSlot(String jsonDate) { + var date = DateUtil.convertStringToDate(jsonDate); + var scheduleDay = date; + for (var event in this.freeSlots) { + var date = DateUtil.convertStringToDate(event); + var nDate = DateTime(date.year, date.month, date.day); + + if (nDate.millisecondsSinceEpoch == scheduleDay.millisecondsSinceEpoch) { + return true; + } + } + return false; + } + + String getDayMonths(DateTime dateTime) { + String dateFormat = + '${dateTime.day} ${DateUtil.getMonth(dateTime.month).toString().substring(0, 3)}'; + return dateFormat; } - //getSchedule(DoctorList doctor, BuildContext context) { - //GifLoaderDialogUtils.showMyDialog(context); - //service = new DoctorsListService(); - // service.getSchedule(doctor).then((value) { - // doctorScheduleResponse.clear(); - // setState(() { - // value['List_DoctorWorkingHoursTable'].forEach((item) => { - // doctorScheduleResponse.add(DoctorScheduleResponse.fromJson(item)) - // }); - // GifLoaderDialogUtils.hideDialog(context); - // }); - // }); - // } + openBookAppointment(selectedDate) { + //sharedPref.setObject(DOCTOR_SCHEDULE_DATE_SEL, selectedDate); + Navigator.push( + context, + FadePage( + page: AppointmentDetails( + appo: widget.appo, + doctorSchedule: selectedDate, + ), + ), + ); + } } diff --git a/lib/pages/MyAppointments/widgets/indicator.dart b/lib/pages/MyAppointments/widgets/indicator.dart index a19993cf..5976042f 100644 --- a/lib/pages/MyAppointments/widgets/indicator.dart +++ b/lib/pages/MyAppointments/widgets/indicator.dart @@ -17,11 +17,11 @@ class PageViewIndicator extends StatelessWidget { Widget _indicator(bool isActive) { return Positioned( - bottom: 10, + top: 20, left: 0, right: 0, child: Container( - margin: EdgeInsets.only(bottom: 35), + margin: EdgeInsets.only(top: 0), child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, @@ -37,7 +37,7 @@ class PageViewIndicator extends StatelessWidget { Widget circleBar(bool isActive) { return AnimatedContainer( duration: Duration(milliseconds: 150), - margin: EdgeInsets.symmetric(horizontal: 8), + margin: EdgeInsets.symmetric(horizontal: 3), height: isActive ? 12 : 8, width: isActive ? 12 : 8, decoration: BoxDecoration( diff --git a/lib/uitl/date_uitl.dart b/lib/uitl/date_uitl.dart index 48395df7..6deb3907 100644 --- a/lib/uitl/date_uitl.dart +++ b/lib/uitl/date_uitl.dart @@ -63,6 +63,15 @@ class DateUtil { return dateFormat; } + static String convertDateMSToJsonDate(utc) { + var dt = new DateTime.fromMicrosecondsSinceEpoch(utc); + + return "/Date(" + + (dt.millisecondsSinceEpoch * 1000).toString() + + '+0300' + + ")/"; + } + /// check Date /// [dateString] String we want to convert static String checkDate(DateTime checkedTime) {