import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/enums.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/context_extensions.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/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/authentication/register.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart'; import 'package:hmg_patient_app_new/widgets/bottomsheet/generic_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/input_widget.dart'; import 'package:provider/provider.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override LoginScreenState createState() => LoginScreenState(); } class LoginScreenState extends State { late FocusNode _nationalIdFocusNode; @override void initState() { super.initState(); _nationalIdFocusNode = FocusNode(); // Clear errors when entering login screen WidgetsBinding.instance.addPostFrameCallback((_) { final authVm = context.read(); authVm.clearNationalIdError(); authVm.clearPhoneNumberError(); }); } @override void dispose() { _nationalIdFocusNode.dispose(); // Clear errors when leaving login screen // Use post frame callback to avoid calling notifyListeners during dispose WidgetsBinding.instance.addPostFrameCallback((_) { final authVm = context.read(); authVm.clearNationalIdError(); authVm.clearPhoneNumberError(); }); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColors.bgScaffoldColor, appBar: CustomAppBar( onBackPressed: () { Navigator.of(context).pop(); }, onLanguageChanged: (String value) { context.setLocale(value == 'en' ? Locale('en', 'US') : Locale('ar', 'SA')); }, ), body: Consumer( builder: (context, authVm, child) { return GestureDetector( onTap: () { // Dismiss the keyboard and unfocus any focused widget when tapping outside _nationalIdFocusNode.unfocus(); FocusScope.of(context).unfocus(); }, child: SingleChildScrollView( child: Padding( padding: EdgeInsets.symmetric(horizontal: 24.h), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Utils.showLottie(context: context, assetPath: AppAnimations.login, width: 200.h, height: 200.h, repeat: true, fit: BoxFit.cover), // SizedBox(height: 130.h), SizedBox(height: MediaQuery.of(context).size.height * 0.12), // based on the screen height Adjusted to sizer unit LocaleKeys.welcomeToDrSulaiman.tr(context: context).toText32(isBold: true, color: AppColors.textColor ), SizedBox(height: 32.h), Localizations.override(context: context, locale: Locale('en', 'US'), child: Container()), // Force English locale for this widget TextInputWidget( labelText: LocaleKeys.nationalIdFileNumber.tr(context: context), hintText: "xxxxxxxxx", controller: authVm.nationalIdController, focusNode: _nationalIdFocusNode, keyboardType: TextInputType.text, isEnable: true, prefix: null, autoFocus: true, isAllowRadius: true, isBorderAllowed: false, isAllowLeadingIcon: true, padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 10.h), leadingIcon: AppAssets.student_card, errorMessage: authVm.nationalIdError, hasError: authVm.nationalIdError != null, fontFamily: "Poppins", onChange: (value) { // Clear error when user starts typing authVm.clearNationalIdError(); }, ), SizedBox(height: 16.h), CustomButton( height: 50.h, text: LocaleKeys.login.tr(context: context), icon: AppAssets.login1, iconColor: Colors.white, onPressed: () { _nationalIdFocusNode.unfocus(); FocusScope.of(context).unfocus(); // Use ViewModel validation method if (authVm.validateNationalId()) { showLoginModelSheet( context: context, phoneNumberController: authVm.phoneNumberController, authViewModel: authVm, ); } }, ), SizedBox(height: 10.h), Center( child: RichText( textAlign: TextAlign.center, text: TextSpan( style: context.dynamicTextStyle(color: AppColors.textColor, fontSize: 14.f, height: 26 / 16, fontWeight: FontWeight.w600,), children: [ TextSpan(text: LocaleKeys.dontHaveAccount.tr(context: context), style: context.dynamicTextStyle()), TextSpan(text: " "), TextSpan( text: LocaleKeys.registernow.tr(context: context), style: context.dynamicTextStyle( color: AppColors.primaryRedColor, fontSize: 14.f, // Adjusted to sizer unit height: 26 / 16, // Ratio fontWeight: FontWeight.w600,), recognizer: TapGestureRecognizer() ..onTap = () { Navigator.of(context).push( MaterialPageRoute(builder: (BuildContext context) => RegisterNew()), ); }, ), ], ), ).withVerticalPadding(2.h), ), SizedBox(height: 20.h), ], ), ), ), ); }, ), ); } void showLoginModelSheet({ required BuildContext context, required TextEditingController? phoneNumberController, required AuthenticationViewModel authViewModel, }) async { AppState appState = getIt(); context.showBottomSheet( isScrollControlled: true, isDismissible: false, useSafeArea: true, constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width), backgroundColor: AppColors.transparent, child: StatefulBuilder(builder: (BuildContext context, StateSetter setModalState) { // Helper function to validate phone number with error handling void validatePhoneAndProceed(OTPTypeEnum otpType) { // Use ViewModel validation method bool isValid = authViewModel.validatePhoneNumber(); if (isValid) { Navigator.of(context).pop(); appState.setSelectDeviceByImeiRespModelElement(null); authViewModel.checkUserAuthentication(otpTypeEnum: otpType); } } return Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: SingleChildScrollView( child: Consumer( builder: (context, authVm, child) { return GenericBottomSheet( countryCode: authVm.selectedCountrySignup.countryCode, initialPhoneNumber: "", textController: phoneNumberController, isEnableCountryDropdown: true, onCountryChange: (country) { authVm.onCountryChange(country); // Clear error when country changes authVm.clearPhoneNumberError(); }, onChange: (value) { authVm.onPhoneNumberChange(value); // Clear error when user starts typing authVm.clearPhoneNumberError(); }, phoneNumberError: authVm.phoneNumberError, buttons: [ if (authVm.selectedCountrySignup != CountryEnum.others) Padding( padding: EdgeInsets.only(bottom: 10.h), child: CustomButton( text: LocaleKeys.sendOTPSMS.tr(context: context), onPressed: () async { validatePhoneAndProceed(OTPTypeEnum.sms); }, backgroundColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedBorderColor, textColor: Colors.white, iconColor: Colors.white, icon: AppAssets.message, ), ), if (authVm.selectedCountrySignup != CountryEnum.others) Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 8.h), child: LocaleKeys.oR.tr(context: context).toText16(color: AppColors.textColor), ), ], ), Padding( padding: EdgeInsets.only(bottom: 10.h, top: 10.h), child: CustomButton( text: LocaleKeys.sendOTPWHATSAPP.tr(context: context), onPressed: () async { validatePhoneAndProceed(OTPTypeEnum.whatsapp); }, backgroundColor: AppColors.whiteColor, borderColor: AppColors.textColor, textColor: AppColors.textColor, icon: AppAssets.whatsapp, iconColor: null, applyThemeColor: false, ), ), ], ); }, ), ), ); })); } }