You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
HMG_Patient_App/lib/pages/login/welcome.dart

752 lines
29 KiB
Dart

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import 'package:flutter/gestures.dart';
import 'package:hmg_patient_app/analytics/google-analytics.dart';
import 'package:hmg_patient_app/config/config.dart';
import 'package:hmg_patient_app/config/shared_pref_kay.dart';
import 'package:hmg_patient_app/core/service/AuthenticatedUserObject.dart';
import 'package:hmg_patient_app/core/viewModels/appointment_rate_view_model.dart';
import 'package:hmg_patient_app/core/viewModels/project_view_model.dart';
import 'package:hmg_patient_app/locator.dart';
import 'package:hmg_patient_app/models/Appointments/toDoCountProviderModel.dart';
import 'package:hmg_patient_app/models/Authentication/check_activation_code_response.dart';
import 'package:hmg_patient_app/models/Authentication/check_paitent_authentication_req.dart';
import 'package:hmg_patient_app/models/Authentication/select_device_imei_res.dart';
import 'package:hmg_patient_app/models/Authentication/send_activation_request.dart';
import 'package:hmg_patient_app/models/InPatientServices/get_admission_info_response_model.dart';
import 'package:hmg_patient_app/models/InPatientServices/get_admission_request_info_response_model.dart';
import 'package:hmg_patient_app/new_ui/otp/otp_validation_bootmsheet_widget.dart';
import 'package:hmg_patient_app/pages/AlHabibMedicalService/health_calculator/carbs/carbs.dart';
import 'package:hmg_patient_app/pages/landing/landing_page.dart';
import 'package:hmg_patient_app/pages/login/login-type.dart';
import 'package:hmg_patient_app/pages/login/register.dart';
import 'package:hmg_patient_app/pages/login/register_new.dart';
import 'package:hmg_patient_app/pages/login/user-login-agreement-page.dart';
import 'package:hmg_patient_app/pages/rateAppointment/rate_appointment_doctor.dart';
import 'package:hmg_patient_app/services/authentication/auth_provider.dart';
import 'package:hmg_patient_app/services/clinic_services/get_clinic_service.dart';
import 'package:hmg_patient_app/theme/colors.dart';
import 'package:hmg_patient_app/uitl/app_shared_preferences.dart';
import 'package:hmg_patient_app/uitl/app_toast.dart';
import 'package:hmg_patient_app/uitl/gif_loader_dialog_utils.dart';
import 'package:hmg_patient_app/uitl/translations_delegate_base.dart';
import 'package:hmg_patient_app/uitl/utils.dart';
import 'package:hmg_patient_app/widgets/buttons/defaultButton.dart';
import 'package:hmg_patient_app/widgets/others/app_scaffold_widget.dart';
import 'package:hmg_patient_app/widgets/otp/sms-popup.dart';
import 'package:hmg_patient_app/widgets/text/app_texts_widget.dart';
import 'package:hmg_patient_app/widgets/transitions/fade_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:intl/src/intl/date_format.dart';
import 'package:provider/provider.dart';
enum OTPType { sms, whatsapp }
class WelcomeLogin extends StatefulWidget {
@override
_WelcomeLogin createState() => _WelcomeLogin();
}
class _WelcomeLogin extends State<WelcomeLogin> {
bool isLoading = true;
TextEditingController nationIdController = TextEditingController();
TextEditingController phoneController = TextEditingController();
bool isDubai = false;
var _availableBiometrics;
final authService = AuthProvider();
var sharedPref = AppSharedPreferences();
bool authenticated = false;
late int mobileNumber;
String errorMsg = '';
SelectDeviceIMEIRES? user;
var registerd_data;
bool isMoreOption = false;
var zipCode;
var patientOutSA;
var loginTokenID;
var loginType;
var deviceToken;
var lastLogin;
AuthenticatedUserObject authenticatedUserObject = locator<AuthenticatedUserObject>();
AppointmentRateViewModel appointmentRateViewModel = locator<AppointmentRateViewModel>();
late ProjectViewModel projectViewModel;
late ToDoCountProviderModel toDoProvider;
late int selectedOption;
bool onlySMSBox = false;
var userData;
late BuildContext _context;
late bool _loading;
int fingrePrintBefore = 0;
var dob;
late int isHijri;
var healthId;
@override
void initState() {
isLoading = true;
super.initState();
}
Widget build(BuildContext context) {
projectViewModel = Provider.of(context);
toDoProvider = Provider.of<ToDoCountProviderModel>(context);
return AppScaffold(
appBarTitle: TranslationBase.of(context).welcome,
isShowDecPage: false,
isShowAppBar: true,
isshowBackButton: false,
showNewAppBar: true,
backgroundColor: Color(0xffF8F8F8),
showNewAppBarTitle: false,
body: Column(
children: <Widget>[
Expanded(
child: ListView(
padding: EdgeInsets.only(left: 21, right: 21),
physics: BouncingScrollPhysics(),
children: [
SizedBox(height: 30),
Row(
children: [
SvgPicture.asset(
"assets/images/new/hmg_icon.svg",
height: 62,
width: 62,
),
],
),
],
),
),
Spacer(),
Expanded(
child: Container(
padding: EdgeInsets.only(top: 30, bottom: 0, right: 21, left: 21),
child: Text(
// TranslationBase.of(context).welcome,
"Welcome to Dr. Sulaiman Al Habib Medical Group",
style: TextStyle(fontSize: 36, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.4, height: 47 / 36),
),
),
),
Container(
padding: EdgeInsets.only(top: 16, bottom: 10, right: 21, left: 21),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Directionality(
textDirection: TextDirection.ltr,
child: inputWidget(
"National ID. or File No",
"1xxxxxxxx",
nationIdController,
isEnable: true,
prefix: null,
hasSelection: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
leadingIcon: "assets/images/svg/student-card.svg",
),
),
],
),
),
SizedBox(
height: 15,
),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.only(top: 0, bottom: 16, right: 21, left: 21),
child: DefaultButton(
TranslationBase.of(context).login,
() {
bool isValid = validateIqama(nationIdController.text);
print("Iqama is valid: $isValid");
if (isValid) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
isDismissible: false,
backgroundColor: Colors.transparent,
builder: (context) => Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: SingleChildScrollView(
child: GenericBottomSheet(
countryCode: "966", // Default is +966 as in your example
initialPhoneNumber: "", //
textController: phoneController,
buttons: [
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: CustomButton(
text: "Send me OTP on SMS",
onPressed: () {
onOtpBtnPressed(OTPType.sms);
},
backgroundColor: Colors.red,
borderColor: Colors.red,
textColor: Colors.white,
icon: "assets/images/svg/message.svg",
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: AppText(
"OR",
fontSize: 16,
fontFamily: 'poppins',
color: Color(0xFF2E3039),
fontWeight: FontWeight.w500,
),
),
],
),
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: CustomButton(
text: "Send me OTP on WhatsApp",
onPressed: () {
onOtpBtnPressed(OTPType.whatsapp);
},
backgroundColor: Colors.white,
borderColor: Color(0xFF2E3039),
textColor: Color(0xFF2E3039),
icon: "assets/images/svg/whatsapp.svg",
),
),
],
),
),
));
} else {
Utils.showErrorToast("Please enter a valid Iqama number.");
}
},
// color: CustomColors.,
textColor: Colors.white,
),
),
),
// SizedBox(width: 8),
// Expanded(
// child: DefaultButton(
// TranslationBase.of(context).yes,
// () => {
// Navigator.of(context).push(FadePage(page: LoginType())),
// locator<GAnalytics>().loginRegistration.visited_alhabib_group(true),
// },
// color: CustomColors.green,
// ),
// ),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
color: Colors.black,
fontSize: 16,
height: 26 / 16,
fontFamily: 'poppins',
fontWeight: FontWeight.w500,
),
children: <TextSpan>[
TextSpan(text: 'Dont have an account? '),
TextSpan(
text: 'Register now',
style: const TextStyle(
color: Colors.red,
fontSize: 16,
height: 26 / 16,
fontFamily: 'poppins',
fontWeight: FontWeight.w500,
),
recognizer: TapGestureRecognizer()
..onTap = () {
Navigator.of(context).push(FadePage(page: RegisterNew()));
// Example: Navigator.push(context, MaterialPageRoute(builder: (context) => RegisterScreen()));
},
),
],
),
),
],
)
],
),
);
}
void onOtpBtnPressed(OTPType type) {
if (phoneController.text.isEmpty) {
Utils.showErrorToast("Please enter your phone number.");
return;
}
if (type == OTPType.whatsapp && !phoneController.text.startsWith("+966")) {
Utils.showErrorToast("WhatsApp OTP requires a phone number starting with +966.");
return;
}
print("Requesting OTP for ${phoneController.text} via ${type == OTPType.whatsapp ? "WhatsApp" : "SMS"} and ${nationIdController.text}");
// Navigator.pop(context);
checkUserAuthentication(type == OTPType.sms ? 1 : 2);
}
bool validateIqama(String iqamaNumber) {
// Remove any non-digit characters
String cleanedIqama = iqamaNumber.replaceAll(RegExp(r'[^0-9]'), '');
// Check if length is 10 digits
if (cleanedIqama.length != 10) {
return false;
}
// Check if first digit is 2 or 1 (common for Iqama)
int firstDigit = int.parse(cleanedIqama[0]);
if (firstDigit != 2 && firstDigit != 1) {
return false;
}
// Checksum validation (similar to Saudi National ID)
int sum = 0;
for (int i = 0; i < 10; i++) {
int digit = int.parse(cleanedIqama[i]);
int weight = (i % 2 == 0) ? 2 : 1; // Alternate weights: 2, 1, 2, 1...
int product = digit * weight;
sum += (product > 9) ? product - 9 : product; // Sum digits if product > 9
}
return sum % 10 == 0;
}
checkUserAuthentication(type) {
showLoader(true);
var req = getCommonRequest(type: type);
req.logInTokenID = "";
var request = CheckPatientAuthenticationReq.fromJson(req.toJson());
sharedPref.setObject(REGISTER_DATA_FOR_REGISTER, request);
authService
.checkPatientAuthentication(request)
.then((value) => {
GifLoaderDialogUtils.hideDialog(context),
if (value['isSMSSent'])
{
sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']),
this.loginTokenID = value['LogInTokenID'],
sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request),
// Future.delayed(Duration(seconds: 1), () {
this.sendActivationCode(type)
// })
}
else
{
if (value['IsAuthenticated']) {this.checkActivationCode()}
}
})
.catchError((err) {
print(err);
GifLoaderDialogUtils.hideDialog(context);
});
}
sendActivationCode(type) async {
var request = this.getCommonRequest(type: type);
request.sMSSignature = await SMSOTP.getSignature();
GifLoaderDialogUtils.showMyDialog(context);
if (healthId != null || isDubai) {
if (!isDubai) {
request.dob = dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob));
}
request.healthId = healthId;
request.isHijri = isHijri;
await this.authService.sendActivationCodeRegister(request).then((result) {
GifLoaderDialogUtils.hideDialog(context);
if (result != null && result['isSMSSent'] == true) {
this.startSMSService(type);
}
}).catchError((r) {
GifLoaderDialogUtils.hideDialog(context);
AppToast.showErrorToast(message: r);
});
} else {
request.dob = "";
request.healthId = "";
request.isHijri = 0;
await this.authService.sendActivationCode(request).then((result) {
GifLoaderDialogUtils.hideDialog(context);
if (result != null && result['isSMSSent'] == true) {
this.startSMSService(type);
}
}).catchError((r) {
GifLoaderDialogUtils.hideDialog(context);
AppToast.showErrorToast(message: r.toString());
});
}
}
checkActivationCode({value}) async {
// Navigator.pop(context);
GifLoaderDialogUtils.showMyDialog(context);
var request = this.getCommonRequest().toJson();
dynamic res;
if (healthId != null || isDubai) {
if (isDubai) {
request['DOB'] = dob;
}
request['HealthId'] = healthId;
request['IsHijri'] = isHijri;
authService
.checkActivationCodeRegister(request, value)
.then((result) => {
res = result,
if (result is Map)
{
result = CheckActivationCode.fromJson(result as Map<String, dynamic>),
if (this.registerd_data != null && this.registerd_data.isRegister == true)
{
// if(widget.isDubai ==false){
// widget.changePageViewIndex!(1),
// if(widget.isDubai ==false){
Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)),
}
}
else
{
Navigator.of(context).pop(),
GifLoaderDialogUtils.hideDialog(context),
Future.delayed(Duration(seconds: 1), () {
AppToast.showErrorToast(message: result);
}),
// projectViewModel.analytics.loginRegistration.login_fail(error: result),
// projectViewModel.analytics.errorTracking.log('otp_verification_at_confirm_login', error: result),
}
})
.catchError((err) {
print(err);
GifLoaderDialogUtils.hideDialog(context);
Future.delayed(Duration(seconds: 1), () {
AppToast.showErrorToast(message: err);
// startSMSService(tempType);
});
});
} else {
authService
.checkActivationCode(request, value)
.then((result) async => {
res = result,
if (result is Map)
{
result = CheckActivationCode.fromJson(result as Map<String, dynamic>),
if (result.errorCode == '699')
{
//699 block run here
GifLoaderDialogUtils.hideDialog(context),
Future.delayed(Duration(seconds: 2), () {
AppToast.showErrorToast(message: result.errorEndUserMessage);
Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: WelcomeLogin));
})
}
else if (this.registerd_data != null && this.registerd_data.isRegister == true)
{
// widget.changePageViewIndex!(1),
Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)),
}
else
{
sharedPref.remove(FAMILY_FILE),
result.list.isFamily = false,
userData = result.list,
sharedPref.setString(BLOOD_TYPE, result.patientBloodType ?? ""),
//Remove o+ from here Added by Aamir
authenticatedUserObject.user = result.list,
projectViewModel.setPrivilege(privilegeList: res),
await sharedPref.setObject(MAIN_USER, result.list),
await sharedPref.setObject(USER_PROFILE, result.list),
loginTokenID = result.logInTokenID,
await sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID),
await sharedPref.setString(TOKEN, result.authenticationTokenID),
checkIfUserAgreedBefore(result),
// projectViewModel.analytics.loginRegistration.login_successful(),
}
}
else
{
// Navigator.of(context).pop(),
GifLoaderDialogUtils.hideDialog(context),
Future.delayed(Duration(seconds: 1), () {
Navigator.of(context).pop();
AppToast.showErrorToast(message: result, localContext: context);
startSMSService(tempType);
}),
// projectViewModel.analytics.loginRegistration.login_fail(error: result),
// projectViewModel.analytics.errorTracking.log('otp_verification_at_confirm_login', error: result)
}
})
.catchError((err) {
GifLoaderDialogUtils.hideDialog(context);
Future.delayed(Duration(seconds: 1), () {
print(err);
AppToast.showErrorToast(message: err);
// startSMSService(tempType);
});
});
}
}
var tempType;
startSMSService(type) {
tempType = type;
SMSOTP(
context,
type,
phoneController.text,
(value) {
this.checkActivationCode(value: value);
},
() => {
Navigator.pop(context),
},
).displayDialog(context);
}
showLoader(bool isTrue) {
setState(() {
isLoading = isTrue;
});
}
setDefault() async {
showLoader(true);
if (await sharedPref.getObject(IMEI_USER_DATA) != null) user = SelectDeviceIMEIRES.fromJson(await sharedPref.getObject(IMEI_USER_DATA));
if (await sharedPref.getObject(REGISTER_DATA_FOR_LOGIIN) != null) {
isMoreOption = true;
this.registerd_data = await CheckPatientAuthenticationReq.fromJson(await sharedPref.getObject(REGISTER_DATA_FOR_LOGIIN));
}
this.mobileNumber = this.registerd_data != null ? this.registerd_data.patientMobileNumber : int.parse(this.user!.mobile!);
this.zipCode = this.registerd_data != null
? this.registerd_data.zipCode
: this.user!.outSA == true
? "971"
: "966";
this.patientOutSA = this.registerd_data != null
? this.registerd_data.zipCode == "966"
? 0
: 1
: this.user!.outSA;
if (this.registerd_data != null) {
this.loginTokenID = await sharedPref.getString(LOGIN_TOKEN_ID);
this.loginType = this.registerd_data.searchType;
}
var nhic = await sharedPref.getObject(NHIC_DATA);
if (nhic != null) {
final DateFormat dateFormat = DateFormat('MM/dd/yyyy');
final DateFormat dateFormat2 = DateFormat('dd/MM/yyyy');
dob = nhic['IsHijri'] ? nhic['DateOfBirth'] : dateFormat2.format(dateFormat.parse(nhic['DateOfBirth']));
isHijri = nhic['IsHijri'] ? 1 : 0;
healthId = nhic['HealthId'];
}
this.deviceToken = await sharedPref.getString(PUSH_TOKEN);
this.lastLogin = await sharedPref.getInt(LAST_LOGIN) != null
? await sharedPref.getInt(LAST_LOGIN)
: user != null
? user!.logInType
: null;
showLoader(false);
//this.cs.sharedService.getStorage(AuthenticationService.LAST_LOGIN);
}
getCommonRequest({type}) {
var fileNo = false;
var request = SendActivationRequest();
request.patientMobileNumber = int.parse(phoneController.text);
request.mobileNo = '0' + phoneController.text.toString();
request.deviceToken = this.deviceToken;
request.projectOutSA = this.patientOutSA == true ? true : false;
request.loginType = type == 1 ? type : 2;
request.oTPSendType = type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2;
request.zipCode = "966";
request.logInTokenID = this.loginTokenID ?? "";
if (this.registerd_data != null) {
request.searchType = this.registerd_data.searchType != null ? this.registerd_data.searchType : 1;
request.patientID = this.registerd_data.patientID != null ? this.registerd_data.patientID : 0;
request.patientIdentificationID = request.nationalID = this.registerd_data.patientIdentificationID != null ? this.registerd_data.patientIdentificationID : '0';
request.dob = this.registerd_data.dob;
request.isRegister = this.registerd_data.isRegister;
} else {
request.searchType = request.searchType != null ? request.searchType : 1;
if (fileNo) {
request.patientID = this.user!.patientID != null ? this.user!.patientID : 0;
} else {
request.patientID = 0;
}
request.nationalID = nationIdController != null ? nationIdController.text : '0';
request.patientIdentificationID = nationIdController != null ? nationIdController.text : '0';
request.isRegister = false;
}
request.deviceTypeID = request.searchType;
return request;
}
checkIfUserAgreedBefore(CheckActivationCode result) {
if (projectViewModel.havePrivilege(109)) {
this.authService.checkIfUserAgreed().then((result) {
if (result['IsPatientAlreadyAgreed']) {
goToHome();
} else {
this.authService.getUserAgreementContent().then((result) {
GifLoaderDialogUtils.hideDialog(AppGlobal.context);
Navigator.pushAndRemoveUntil(
context,
FadePage(
page: UserLoginAgreementPage(
userAgreementText: result['UserAgreementContent'],
authenticatedUserObject: authenticatedUserObject,
appointmentRateViewModel: appointmentRateViewModel,
selectedOption: selectedOption,
isArabic: projectViewModel.isArabic,
),
),
(r) => false);
}).catchError((err) {
GifLoaderDialogUtils.hideDialog(context);
print(err);
});
}
}).catchError((err) {
GifLoaderDialogUtils.hideDialog(context);
print(err);
});
} else {
goToHome();
}
}
Future<void> goToHome() async {
authenticatedUserObject.isLogin = true;
appointmentRateViewModel.isLogin = true;
projectViewModel.isLogin = true;
projectViewModel.user = authenticatedUserObject.user;
await authenticatedUserObject.getUser(getUser: true);
getToDoCount();
checkIfIsInPatient();
appointmentRateViewModel
.getIsLastAppointmentRatedList(projectViewModel.isArabic ? 1 : 2)
.then((_) {
GifLoaderDialogUtils.hideDialog(AppGlobal.context);
if (appointmentRateViewModel.isHaveAppointmentNotRate) {
Navigator.pushAndRemoveUntil(
context,
FadePage(page: RateAppointmentDoctor()),
(route) => false,
);
} else {
Navigator.pushAndRemoveUntil(
context,
FadePage(page: LandingPage()),
(route) => false,
);
}
insertIMEI();
}).catchError((error) {
print(error);
});
}
void getToDoCount() {
toDoProvider.setState(0, 0, true, "0");
ClinicListService()
.getActiveAppointmentNo(context)
.then((res) {
if (res['MessageStatus'] == 1) {
toDoProvider.setState(
res['AppointmentActiveNumber'],
res['AncillaryOrderListCount'],
true,
"0",
);
}
}).catchError((err) => print(err));
}
insertIMEI() {
authService.insertDeviceImei(selectedOption).then((value) => {}).catchError((err) {
print(err);
});
}
void checkIfIsInPatient() {
final service = ClinicListService();
service.checkIfInPatientAPI(context).then((res) {
if (res['MessageStatus'] != 1) return;
final isAdmitted = res['isAdmitted'] == true;
final hasAdmissionRequest = res['hasAdmissionRequests'] == true;
print("IS ADMITTED: $isAdmitted");
print("Has Admission Request: $hasAdmissionRequest");
if (isAdmitted && res['PatientAdmittedInformation']?.isNotEmpty == true) {
final info = GetAdmissionInfoResponseModel.fromJson(res['PatientAdmittedInformation'][0]);
projectViewModel.setInPatientProjectID(res['PatientAdmittedInformation'][0]['ProjectID']);
projectViewModel.setInPatientAdmissionInfo(info);
projectViewModel.setIsPatientAdmitted(true);
}
if (hasAdmissionRequest && res['MedicalInstruction']?.isNotEmpty == true) {
final reqInfo = GetAdmissionRequestInfoResponseModel.fromJson(res['MedicalInstruction'][0]);
projectViewModel.setInPatientProjectID(res['MedicalInstruction'][0]['projectId']);
projectViewModel.setInPatientAdmissionRequest(reqInfo);
projectViewModel.setPatientHasAdmissionRequest(true);
}
});
}
}