Online CheckIn implementation contd.
parent
851bd569b4
commit
b10523dac3
File diff suppressed because one or more lines are too long
@ -1,44 +1,138 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_assets.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_page.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:barcode_scan2/barcode_scan2.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/nfc/nfc_reader_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
|
||||
|
||||
class AppointmentCheckinBottomSheet extends StatelessWidget {
|
||||
AppointmentCheckinBottomSheet({super.key, required this.patientAppointmentHistoryResponseModel});
|
||||
AppointmentCheckinBottomSheet({super.key, required this.patientAppointmentHistoryResponseModel, required this.myAppointmentsViewModel});
|
||||
|
||||
PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
|
||||
MyAppointmentsViewModel myAppointmentsViewModel;
|
||||
|
||||
bool _supportsNFC = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
FlutterNfcKit.nfcAvailability.then((value) {
|
||||
_supportsNFC = (value == NFCAvailability.available);
|
||||
});
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
checkInOptionCard(AppAssets.checkin_location_icon, "Live Location".needTranslation, "".needTranslation),
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_location_icon,
|
||||
"Live Location".needTranslation,
|
||||
"Verify your location to be at hospital to check in".needTranslation,
|
||||
).onPress(() {
|
||||
Navigator.of(context).pop();
|
||||
}),
|
||||
SizedBox(height: 16.h),
|
||||
checkInOptionCard(AppAssets.checkin_nfc_icon, "NFC (Near Field Communication)".needTranslation, "".needTranslation),
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_nfc_icon,
|
||||
"NFC (Near Field Communication)".needTranslation,
|
||||
"Scan your phone via NFC board to check in".needTranslation,
|
||||
).onPress(() {
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
showNfcReader(context, onNcfScan: (String nfcId) {
|
||||
Future.delayed(const Duration(milliseconds: 100), () {
|
||||
sendCheckInRequest(nfcId, context);
|
||||
});
|
||||
}, onCancel: () {});
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 16.h),
|
||||
checkInOptionCard(AppAssets.checkin_qr_icon, "QR Code".needTranslation, "".needTranslation),
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_qr_icon,
|
||||
"QR Code".needTranslation,
|
||||
"Scan QR code with your camera to check in".needTranslation,
|
||||
).onPress(() async {
|
||||
String onlineCheckInQRCode = (await BarcodeScanner.scan().then((value) => value.rawContent));
|
||||
if (onlineCheckInQRCode != "") {
|
||||
sendCheckInRequest(onlineCheckInQRCode, context);
|
||||
} else {}
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget checkInOptionCard(String icon, String title, String subTitle) {
|
||||
return Container(
|
||||
height: 120.h,
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.h,
|
||||
hasShadow: false,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Utils.buildSvgWithAssets(icon: icon, width: 40.h, height: 40.h, fit: BoxFit.fill),
|
||||
SizedBox(height: 16.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Utils.buildSvgWithAssets(icon: icon),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
title.toText16(isBold: true, color: AppColors.textColor),
|
||||
subTitle.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
|
||||
],
|
||||
),
|
||||
Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.forward_arrow_icon,
|
||||
iconColor: AppColors.blackColor,
|
||||
width: 18.h,
|
||||
height: 13.h,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
).paddingAll(16.h),
|
||||
);
|
||||
}
|
||||
|
||||
void sendCheckInRequest(String scannedCode, BuildContext context) async {
|
||||
showCommonBottomSheet(context,
|
||||
child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
|
||||
await myAppointmentsViewModel.sendCheckInNfcRequest(
|
||||
patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
|
||||
scannedCode: scannedCode,
|
||||
checkInType: 2,
|
||||
onSuccess: (apiResponse) {
|
||||
Navigator.of(context).pop();
|
||||
showCommonBottomSheetWithoutHeight(context, title: "Success".needTranslation, child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()), callBackFunc: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
FadePage(
|
||||
page: LandingNavigation(),
|
||||
),
|
||||
(r) => false);
|
||||
Navigator.of(context).push(
|
||||
FadePage(page: MyAppointmentsPage()),
|
||||
);
|
||||
}, isFullScreen: false);
|
||||
},
|
||||
onError: (error) {
|
||||
Navigator.of(context).pop();
|
||||
showCommonBottomSheetWithoutHeight(context, title: "Error".needTranslation, child: Utils.getErrorWidget(loadingText: error), callBackFunc: () {
|
||||
Navigator.of(context).pop();
|
||||
}, isFullScreen: false);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,212 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_assets.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
|
||||
|
||||
void showNfcReader(BuildContext context, {required Function onNcfScan, required VoidCallback onCancel}) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
enableDrag: false,
|
||||
isDismissible: true,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12)),
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
builder: (context) {
|
||||
return NfcLayout(
|
||||
onNcfScan: onNcfScan,
|
||||
onCancel: onCancel,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
class NfcLayout extends StatefulWidget {
|
||||
Function? onNcfScan;
|
||||
VoidCallback? onCancel;
|
||||
|
||||
NfcLayout({this.onNcfScan, this.onCancel});
|
||||
|
||||
@override
|
||||
_NfcLayoutState createState() => _NfcLayoutState();
|
||||
}
|
||||
|
||||
class _NfcLayoutState extends State<NfcLayout> {
|
||||
bool _reading = false;
|
||||
Widget? mainWidget;
|
||||
late String nfcId;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
readNFC();
|
||||
}
|
||||
|
||||
void readNFC() async {
|
||||
FlutterNfcKit.finish();
|
||||
FlutterNfcKit.poll(timeout: Duration(seconds: 10), androidPlatformSound: true, androidCheckNDEF: false, iosMultipleTagMessage: "Multiple tags found!").then((value) async {
|
||||
setState(() {
|
||||
_reading = true;
|
||||
mainWidget = doneNfc();
|
||||
});
|
||||
Future.delayed(const Duration(milliseconds: 500), () async {
|
||||
await FlutterNfcKit.finish();
|
||||
widget.onNcfScan!(nfcId);
|
||||
Navigator.pop(context);
|
||||
});
|
||||
nfcId = value.id;
|
||||
}).catchError((err) {
|
||||
print(err);
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// return SizedBox();
|
||||
(mainWidget == null && !_reading) ? mainWidget = scanNfc() : mainWidget = doneNfc();
|
||||
return Platform.isAndroid ? AnimatedSwitcher(duration: Duration(milliseconds: 500), child: mainWidget) : SizedBox.shrink();
|
||||
}
|
||||
|
||||
Widget scanNfc() {
|
||||
return Container(
|
||||
key: ValueKey(1),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Text(
|
||||
"Ready To Scan",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 24,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
SvgPicture.asset(
|
||||
"assets/images/nfc/contactless.svg",
|
||||
height: MediaQuery.of(context).size.width / 3,
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Text(
|
||||
"Approach an NFC Tag",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
ButtonTheme(
|
||||
minWidth: MediaQuery.of(context).size.width / 1.2,
|
||||
height: 45.0,
|
||||
buttonColor: Colors.grey[300],
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: CustomButton(
|
||||
text: LocaleKeys.cancel.tr(),
|
||||
onPressed: () {
|
||||
widget.onCancel!();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
backgroundColor: AppColors.primaryRedColor,
|
||||
borderColor: AppColors.primaryRedColor,
|
||||
textColor: AppColors.whiteColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
borderRadius: 12.h,
|
||||
height: 40.h,
|
||||
icon: AppAssets.cancel,
|
||||
iconColor: AppColors.whiteColor,
|
||||
iconSize: 16.h,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget doneNfc() {
|
||||
return Container(
|
||||
key: ValueKey(2),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Text(
|
||||
"Successfully Scanned",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 24,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Image.asset(
|
||||
"assets/images/nfc/ic_done.png",
|
||||
height: MediaQuery.of(context).size.width / 3,
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Text(
|
||||
"Approach an NFC Tag",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
ButtonTheme(
|
||||
minWidth: MediaQuery.of(context).size.width / 1.2,
|
||||
height: 45.0,
|
||||
buttonColor: Colors.grey[300],
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: CustomButton(
|
||||
text: LocaleKeys.done.tr(),
|
||||
onPressed: () {
|
||||
widget.onCancel!();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
backgroundColor: AppColors.primaryRedColor,
|
||||
borderColor: AppColors.primaryRedColor,
|
||||
textColor: AppColors.whiteColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
borderRadius: 12.h,
|
||||
height: 40.h,
|
||||
icon: AppAssets.cancel,
|
||||
iconColor: AppColors.whiteColor,
|
||||
iconSize: 16.h,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue