Waiting appointment implementation contd.

dev_3.13.6_CR6750
haroon amjad 3 months ago
parent 1094d297f4
commit b3f2904e9a

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 KiB

@ -22,8 +22,8 @@ var PACKAGES_ORDER_HISTORY = '/api/orders/items';
var PACKAGES_TAMARA_OPT = '/api/orders/paymentoptions/tamara';
// var BASE_URL = 'http://10.50.100.198:2018/';
// var BASE_URL = 'http://10.50.100.198:4422/';
// var BASE_URL = 'https://uat.hmgwebservices.com/';
var BASE_URL = 'https://hmgwebservices.com/';
var BASE_URL = 'https://uat.hmgwebservices.com/';
// var BASE_URL = 'https://hmgwebservices.com/';
// var BASE_URL = 'http://10.20.200.111:1010/';
// var BASE_URL = 'https://orash.cloudsolutions.com.sa/';
// var BASE_URL = 'https://vidauat.cloudsolutions.com.sa/';

@ -1976,4 +1976,11 @@ const Map localizedValues = {
"selectHospitalBloodDonation": {"en": "Please select the hospital you want to book an appointment with: ", "ar": "يرجى اختيار المستشفى الذي تريد حجز موعد معه:"},
"wecare": {"en": "We Care", "ar": "نحن نهتم"},
"myinstructions": {"en": "My Instructions", "ar": "تعليماتي"},
"waitingAppointment": {"en": "Waiting appointment", "ar": "انتظار الموعد"},
"whatWaitingAppointment": {"en": "What is Waiting appointment?", "ar": "ما هو انتظار الموعد؟"},
"waitingAppointmentText1": {"en": "The waiting appointments feature allows you to book an appointment while you are inside the hospital building, and in case there is no available slot in the doctors schedule.", "ar": "تتيح لك خاصية انتظار المواعيد حجز موعد أثناء تواجدك داخل مبنى المستشفى، وفي حالة عدم وجود وقت متاح في جدول الطبيب."},
"waitingAppointmentText2": {"en": "Waiting for an appointment can take more than 2 hours.", "ar": "يمكن أن يستغرق انتظار الموعد أكثر من ساعتين."},
"waitingAppointmentText3": {"en": "Note: You must have to pay within 10 minutes of booking, otherwise your appointment will be cancelled automatically", "ar": "ملحوظة: يجب عليك الدفع خلال 10 دقائق من الحجز، وإلا سيتم إلغاء موعدك تلقائيًا"},
"waitingAppointmentVerificationMethod": {"en": "Please select verification method", "ar": "الرجاء تحديد طريقة التحقق"},
"howToUseVerificationMethod": {"en": "How to use verification methods?", "ar": "كيفية استخدام طرق التحقق؟"},
};

@ -18,6 +18,8 @@ import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_datetime_picker_plus/flutter_datetime_picker_plus.dart';
import '../../models/Appointments/DoctorListResponse.dart';
bool isAppArabic = false;
class ProjectViewModel extends BaseViewModel {
GAnalytics get analytics => locator<GAnalytics>();
@ -45,6 +47,20 @@ class ProjectViewModel extends BaseViewModel {
GetAdmissionInfoResponseModel getAdmissionInfoResponseModel = GetAdmissionInfoResponseModel();
GetAdmissionRequestInfoResponseModel getAdmissionRequestInfoResponseModel = GetAdmissionRequestInfoResponseModel();
int waitingAppointmentProjectID = 0;
DoctorList? waitingAppointmentDoctor;
setWaitingAppointmentDoctor(DoctorList waitingAppointmentDoctor) {
this.waitingAppointmentDoctor = waitingAppointmentDoctor;
notifyListeners();
}
setWaitingAppointmentProjectID(int projectID) {
this.waitingAppointmentProjectID = projectID;
notifyListeners();
}
void setIsAllAppointmentsLoaded(bool value) {
_isAllAppointmentsLoaded = value;
notifyListeners();

@ -10,6 +10,7 @@ import 'package:diplomaticquarterapp/models/Clinics/ClinicListResponse.dart';
import 'package:diplomaticquarterapp/models/header_model.dart';
import 'package:diplomaticquarterapp/pages/BookAppointment/DentalComplaints.dart';
import 'package:diplomaticquarterapp/pages/BookAppointment/doctor_post_pre_images_page.dart';
import 'package:diplomaticquarterapp/pages/BookAppointment/waiting_appointment/waiting_appointment_info.dart';
import 'package:diplomaticquarterapp/pages/MyAppointments/SchedulePage.dart';
import 'package:diplomaticquarterapp/routes.dart';
import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart';
@ -520,28 +521,32 @@ class _DoctorProfileState extends State<DoctorProfile> with TickerProviderStateM
// if (widget.isDoctorNameSearch && widget.doctor.clinicID == 17) {
// navigateToDentalComplaints(context);
// } else {
if (DocAvailableAppointments.areSlotsAvailable) {
if (projectViewModel.isLogin) {
if (widget.isDoctorNameSearch && widget.doctor.clinicID == 17 && projectViewModel.user!.age! > 12) {
navigateToDentalComplaints(context);
if (DocAvailableAppointments.selectedTime == TranslationBase.of(context).waitingAppointment) {
navigateToWaitingAppointment(context);
} else {
if (DocAvailableAppointments.areSlotsAvailable) {
if (projectViewModel.isLogin) {
if (widget.isDoctorNameSearch && widget.doctor.clinicID == 17 && projectViewModel.user!.age! > 12) {
navigateToDentalComplaints(context);
} else {
final timeSlot = DocAvailableAppointments.selectedAppoDateTime;
navigateToBookConfirm(context);
projectViewModel.analytics.appointment.book_appointment_review(appointment_type: 'regular', dateTime: timeSlot!, doctor: widget.doctor);
}
} else {
final timeSlot = DocAvailableAppointments.selectedAppoDateTime;
navigateToBookConfirm(context);
projectViewModel.analytics.appointment.book_appointment_review(appointment_type: 'regular', dateTime: timeSlot!, doctor: widget.doctor);
ConfirmDialog dialog = new ConfirmDialog(
context: context,
confirmMessage: TranslationBase.of(context).loginToUseService,
okText: TranslationBase.of(context).confirm,
cancelText: TranslationBase.of(context).cancel_nocaps,
okFunction: () => {navigateToLogin()},
cancelFunction: () => {});
dialog.showAlertDialog(context);
}
} else {
ConfirmDialog dialog = new ConfirmDialog(
context: context,
confirmMessage: TranslationBase.of(context).loginToUseService,
okText: TranslationBase.of(context).confirm,
cancelText: TranslationBase.of(context).cancel_nocaps,
okFunction: () => {navigateToLogin()},
cancelFunction: () => {});
dialog.showAlertDialog(context);
AppToast.showErrorToast(message: TranslationBase.of(context).selectSlot);
}
} else
AppToast.showErrorToast(message: TranslationBase.of(context).selectSlot);
// }
}
}
Future navigateToDentalComplaints(BuildContext context) async {
@ -590,4 +595,15 @@ class _DoctorProfileState extends State<DoctorProfile> with TickerProviderStateM
),
);
}
Future navigateToWaitingAppointment(context) async {
projectViewModel.setWaitingAppointmentProjectID(widget.doctor.projectID!);
projectViewModel.setWaitingAppointmentDoctor(widget.doctor);
Navigator.push(
context,
FadePage(
page: WaitingAppointmentInfo(),
),
);
}
}

@ -60,6 +60,8 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
var language;
bool isLiveCareSchedule = false;
bool isWaitingAppointmentAvailable = false;
// String selectedLogSlots ='';
@override
@ -206,7 +208,9 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
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) {
dayEvents.add(TimeSlot(isoTime: TranslationBase.of(context).waitingAppointment, start: DateTime.now(), end: DateTime.now(), vidaDate: ""));
}
freeSlots.forEach((v) {
if (v.start == dateStartObj) dayEvents.add(v);
});
@ -349,6 +353,7 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
GifLoaderDialogUtils.hideDialog(context);
if (res['MessageStatus'] == 1) {
if (res['FreeTimeSlots'].length != 0) {
isWaitingAppointmentAvailable = res['IsAllowToBookWaitingAppointment']; // true;
DocAvailableAppointments.initialSlotDuration = res['InitialSlotDuration'];
DocAvailableAppointments.areAppointmentsAvailable = true;
freeSlotsResponse = res['FreeTimeSlots'];
@ -362,7 +367,7 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
_calendarController.selectedDate = DateUtil.convertStringToDate(
widget.doctorSchedule['Date'],
)
}
},
});
});
} else {

@ -0,0 +1,113 @@
import 'package:diplomaticquarterapp/pages/BookAppointment/waiting_appointment/waiting_appointment_verification.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class WaitingAppointmentInfo extends StatelessWidget {
const WaitingAppointmentInfo({super.key});
@override
Widget build(BuildContext context) {
return AppScaffold(
appBarTitle: TranslationBase.of(context).waitingAppointment,
isShowAppBar: true,
isShowDecPage: false,
showNewAppBar: true,
showNewAppBarTitle: true,
backgroundColor: CustomColors.appBackgroudGreyColor,
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: MediaQuery.of(context).size.width,
decoration: containerRadius(Colors.white, 10),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SvgPicture.asset(
"assets/images/new/waitingAppo.svg",
width: 52.0,
height: 52.0,
),
mHeight(11),
Text(
TranslationBase.of(context).whatWaitingAppointment,
maxLines: 1,
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w700, color: Color(0xff2B353E), letterSpacing: -1.44, height: 35 / 24),
),
mHeight(11),
Container(
width: MediaQuery.of(context).size.width * 0.8,
child: Text(
TranslationBase.of(context).waitingAppointmentText1,
style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
),
),
mHeight(18),
Container(
width: MediaQuery.of(context).size.width * 0.8,
child: Text(
TranslationBase.of(context).waitingAppointmentText2,
style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
),
),
mHeight(24),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(
Icons.warning,
size: 20,
color: Color(0xffA78618),
),
mWidth(10),
Container(
width: MediaQuery.of(context).size.width * 0.7,
child: Text(
TranslationBase.of(context).waitingAppointmentText3,
style: TextStyle(
fontSize: 14, fontStyle: FontStyle.italic, fontWeight: FontWeight.w600, color: Color(0xffA78618), letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
),
),
],
),
],
),
),
),
],
),
),
),
bottomSheet: Container(
height: 80,
color: CustomColors.white,
padding: EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 25.0),
child: Container(
child: DefaultButton(
TranslationBase.of(context).continues,
() {
Navigator.push(
context,
FadePage(
page: WaitingAppointmentVerification(),
),
);
},
color: CustomColors.accentColor,
),
),
),
);
}
}

@ -0,0 +1,275 @@
import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:diplomaticquarterapp/core/model/privilege/ProjectDetailListModel.dart';
import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:diplomaticquarterapp/pages/BookAppointment/BookConfirm.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:diplomaticquarterapp/uitl/location_util.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/nfc/nfc_reader_sheet.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import '../../../uitl/utils.dart';
class WaitingAppointmentVerification extends StatefulWidget {
const WaitingAppointmentVerification({super.key});
@override
State<WaitingAppointmentVerification> createState() => _WaitingAppointmentVerificationState();
}
class _WaitingAppointmentVerificationState extends State<WaitingAppointmentVerification> {
String selectedVerificationMethod = "QR";
late ProjectViewModel projectViewModel;
late LocationUtils locationUtils;
ProjectDetailListModel projectDetailListModel = ProjectDetailListModel();
@override
Widget build(BuildContext context) {
projectViewModel = Provider.of(context);
return AppScaffold(
appBarTitle: TranslationBase.of(context).waitingAppointment,
isShowAppBar: true,
isShowDecPage: false,
showNewAppBar: true,
showNewAppBarTitle: true,
backgroundColor: CustomColors.appBackgroudGreyColor,
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
mHeight(11),
Text(
TranslationBase.of(context).waitingAppointmentVerificationMethod,
maxLines: 1,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w700, color: Color(0xff2B353E), letterSpacing: -1.04, height: 35 / 24),
),
mHeight(12),
Container(
width: MediaQuery.of(context).size.width,
decoration: containerRadius(Colors.white, 10),
child: Padding(
padding: const EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 0.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InkWell(
onTap: () {
setState(() {
selectedVerificationMethod = "QR";
});
},
child: Row(
children: [
Container(
width: 20,
height: 20,
decoration: containerColorRadiusBorderWidth(selectedVerificationMethod == "QR" ? CustomColors.accentColor : Colors.transparent, 100, Colors.grey, 0.5),
),
mWidth(6),
Container(
height: 40.0,
width: 40.0,
padding: EdgeInsets.all(7.0),
child: SvgPicture.asset(
"assets/images/new/services/qr_code.svg",
),
),
Text(
TranslationBase.of(context).pharmaLiveCareScanQR,
style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, fontWeight: FontWeight.w600, letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
),
],
),
),
Divider(),
InkWell(
onTap: () {
setState(() {
selectedVerificationMethod = "NFC";
});
},
child: Row(
children: [
Container(
width: 20,
height: 20,
decoration: containerColorRadiusBorderWidth(selectedVerificationMethod == "NFC" ? CustomColors.accentColor : Colors.transparent, 100, Colors.grey, 0.5),
),
mWidth(6),
Container(
height: 40.0,
width: 40.0,
padding: EdgeInsets.all(7.0),
child: SvgPicture.asset(
"assets/images/new/services/contactless.svg",
),
),
Text(
TranslationBase.of(context).scanNFC,
style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, fontWeight: FontWeight.w600, letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
),
],
),
),
Divider(),
InkWell(
onTap: () {
setState(() {
selectedVerificationMethod = "Location";
});
},
child: Row(
children: [
Container(
width: 20,
height: 20,
decoration: containerColorRadiusBorderWidth(selectedVerificationMethod == "Location" ? CustomColors.accentColor : Colors.transparent, 100, Colors.grey, 0.5),
),
mWidth(6),
Container(
height: 40.0,
width: 40.0,
padding: EdgeInsets.all(7.0),
child: SvgPicture.asset(
"assets/images/new/services/location.svg",
),
),
Text(
TranslationBase.of(context).checkInViaLocation,
style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, fontWeight: FontWeight.w600, letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
),
],
),
),
mHeight(6),
],
),
),
),
mHeight(12),
Container(
width: MediaQuery.of(context).size.width,
decoration: containerRadius(Colors.white, 10),
child: Padding(
padding: const EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 0.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
mHeight(12),
Text(
TranslationBase.of(context).howToUseVerificationMethod,
maxLines: 1,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -1.04, height: 35 / 24),
),
mHeight(12),
Image.asset(
'assets/images/new/NFCCheckIn_QR_gps_HMG.png',
fit: BoxFit.fitWidth,
width: MediaQuery.of(context).size.width,
),
mHeight(12),
],
),
),
),
],
),
),
),
bottomSheet: Container(
height: 80,
color: CustomColors.white,
padding: EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 25.0),
child: Container(
child: DefaultButton(
TranslationBase.of(context).continues,
() {
startVerification();
},
color: CustomColors.accentColor,
),
),
),
);
}
startVerification() {
switch (selectedVerificationMethod) {
case "QR":
startQRCodeScan();
break;
case "NFC":
startNFCScan();
break;
case "Location":
startLocationCheckIn();
break;
}
}
Future navigateToBookConfirm(context) async {
final DateFormat formatter = DateFormat('yyyy-MM-dd');
Navigator.push(
context,
FadePage(
page: BookConfirm(
doctor: projectViewModel.waitingAppointmentDoctor!,
isLiveCareAppointment: false,
selectedDate: formatter.format(DateTime.now()),
selectedTime: TranslationBase.of(context).waitingAppointment,
initialSlotDuration: 15,
),
),
);
}
startLocationCheckIn() async {
GifLoaderDialogUtils.showMyDialog(context);
locationUtils = new LocationUtils(isShowConfirmDialog: true, context: context);
locationUtils.getCurrentLocation(callBack: (value) {
projectDetailListModel = Utils.getProjectDetailObj(projectViewModel, projectViewModel.waitingAppointmentProjectID);
double dist = Utils.distance(value.latitude, value.longitude, double.parse(projectDetailListModel.latitude!), double.parse(projectDetailListModel.longitude!)).ceilToDouble() * 1000;
print(dist);
if (dist <= projectDetailListModel.geofenceRadius!) {
GifLoaderDialogUtils.hideDialog(context);
navigateToBookConfirm(context);
} else {
GifLoaderDialogUtils.hideDialog(context);
AppToast.showErrorToast(message: TranslationBase.of(context).locationCheckInError);
}
});
}
startNFCScan() {
Future.delayed(const Duration(milliseconds: 500), () {
showNfcReader(context, onNcfScan: (String nfcId) {
Future.delayed(const Duration(milliseconds: 100), () {
navigateToBookConfirm(context);
});
}, onCancel: () {
// Navigator.of(context).pop();
// locator<GAnalytics>().todoList.to_do_list_nfc_cancel(widget.appointment!);
});
});
}
startQRCodeScan() async {
String onlineCheckInQRCode = (await BarcodeScanner.scan().then((value) => value.rawContent));
if (onlineCheckInQRCode != "") {
navigateToBookConfirm(context);
} else {}
}
}

@ -2963,6 +2963,13 @@ class TranslationBase {
String get selectHospitalBloodDonation => localizedValues["selectHospitalBloodDonation"][locale.languageCode];
String get wecare => localizedValues["wecare"][locale.languageCode];
String get myinstructions => localizedValues["myinstructions"][locale.languageCode];
String get waitingAppointment => localizedValues["waitingAppointment"][locale.languageCode];
String get whatWaitingAppointment => localizedValues["whatWaitingAppointment"][locale.languageCode];
String get waitingAppointmentText1 => localizedValues["waitingAppointmentText1"][locale.languageCode];
String get waitingAppointmentText2 => localizedValues["waitingAppointmentText2"][locale.languageCode];
String get waitingAppointmentText3 => localizedValues["waitingAppointmentText3"][locale.languageCode];
String get waitingAppointmentVerificationMethod => localizedValues["waitingAppointmentVerificationMethod"][locale.languageCode];
String get howToUseVerificationMethod => localizedValues["howToUseVerificationMethod"][locale.languageCode];
}

Loading…
Cancel
Save