import 'dart:io'; import 'package:sefer_driver/views/auth/captin/contact_us_page.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import '../../../constant/box_name.dart'; import '../../../constant/colors.dart'; import '../../../constant/info.dart'; import '../../../constant/style.dart'; import '../../../controller/auth/apple_sigin.dart'; import '../../../controller/auth/captin/login_captin_controller.dart'; import '../../../controller/auth/google_sign.dart'; import '../../../controller/functions/encrypt_decrypt.dart'; import '../../../controller/functions/overlay_permisssion.dart'; import '../../../main.dart'; import '../../../print.dart'; import '../../widgets/elevated_btn.dart'; import '../../widgets/mycircular.dart'; import '../country_widget.dart'; class LoginCaptin extends StatelessWidget { final AuthController authController = Get.put(AuthController()); final LoginDriverController controller = Get.put(LoginDriverController()); LoginCaptin({super.key}); @override Widget build(BuildContext context) { return GetBuilder( builder: (controller) { return Scaffold( backgroundColor: AppColor.secondaryColor, body: SafeArea( child: Center( child: _buildBodyContent(context, controller), ), ), ); }, ); } /// Determines which UI to show based on the driver's progress. Widget _buildBodyContent( BuildContext context, LoginDriverController controller) { if (box.read(BoxName.agreeTerms) != 'agreed') { return _buildAgreementPage(context, controller); } if (box.read(BoxName.countryCode) == null) { return _buildCountryPickerPage(); // Improved wrapper for country picker } if (box.read(BoxName.locationPermission) != 'true') { return _buildLocationPermissionPage(context, controller); } // Main login flow return _buildLoginFlow(context, controller); } /// Manages the transition between social login options and the manual form. Widget _buildLoginFlow( BuildContext context, LoginDriverController controller) { return AnimatedSwitcher( duration: const Duration(milliseconds: 300), transitionBuilder: (child, animation) { return FadeTransition(opacity: animation, child: child); }, child: controller.showManualForm ? _buildManualFormUI( context, controller) // The new unified manual form : _buildLoginUI( context, controller), // Main screen with social options ); } /// Redesigned UI for the main login screen with social options. Widget _buildLoginUI(BuildContext context, LoginDriverController controller) { return SingleChildScrollView( key: const ValueKey('socialLogin'), padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 32.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ CircleAvatar( radius: 65, backgroundColor: Colors.white.withOpacity(0.9), child: ClipOval( child: Image.asset( 'assets/images/logo.png', // Using PNG for better quality and performance height: 120, width: 120, ), ), ), const SizedBox(height: 20), Text( 'Driver Portal'.tr, textAlign: TextAlign.center, style: AppStyle.headTitle2.copyWith(fontSize: 28), ), const SizedBox(height: 8), Text( 'Sign in to start your journey'.tr, textAlign: TextAlign.center, style: AppStyle.subtitle, ), const SizedBox(height: 40), _buildSocialLoginOptions(context, controller), const SizedBox(height: 32), Center( child: GestureDetector( onTap: () => Get.to(() => ContactUsPage()), child: Text( 'Need help? Contact Us'.tr, style: AppStyle.subtitle.copyWith( color: AppColor.blueColor, decoration: TextDecoration.underline, ), ), ), ), ], ), ); } /// Builds the social login buttons (Google, Apple, and manual option). Widget _buildSocialLoginOptions( BuildContext context, LoginDriverController controller) { return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Google Login _buildSocialButton( text: 'Sign In with Google'.tr, icon: FontAwesome.google, backgroundColor: AppColor.redColor, onPressed: () async { await GoogleSignInHelper().signInFromLogin(); }, ), // Apple Login (for iOS only) if (Platform.isIOS) ...[ const SizedBox(height: 16), _buildSocialButton( text: 'Sign in with Apple'.tr, icon: Icons.apple, backgroundColor: Colors.black, onPressed: () async { User? user = await authController.signInWithApple(); if (user != null) { box.write(BoxName.emailDriver, user.email.toString()); box.write(BoxName.driverID, user.uid); controller.loginWithGoogleCredential( user.uid, user.email.toString(), ); } }, ), ], const SizedBox(height: 24), // Divider with "OR" Row( children: [ const Expanded(child: Divider()), Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Text('Or'.tr, style: AppStyle.subtitle), ), const Expanded(child: Divider()), ], ), const SizedBox(height: 24), // Manual Login with Email/Password _buildSocialButton( text: 'Continue with Email'.tr, icon: Icons.email_outlined, backgroundColor: AppColor.primaryColor, onPressed: () => controller.toggleManualFormView(), // New simplified logic ), ], ); } /// A unified and dynamic UI for both Manual Login and Registration. Widget _buildManualFormUI( BuildContext context, LoginDriverController controller) { // Determine if it's in registration mode from the controller final isRegister = controller.isRegisterMode; return SingleChildScrollView( key: const ValueKey('manualForm'), child: Padding( padding: const EdgeInsets.all(16.0), child: Card( elevation: 8, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(20.0), child: Form( key: controller.formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Back button to return to social login options Align( alignment: Alignment.topLeft, child: IconButton( icon: const Icon(Icons.arrow_back, color: AppColor.primaryColor), onPressed: () => controller.toggleManualFormView(), ), ), const SizedBox(height: 10), Text( isRegister ? 'Create Driver Account'.tr : 'Driver Login'.tr, textAlign: TextAlign.center, style: AppStyle.headTitle2, ), const SizedBox(height: 24), _buildTextFormField( controller: controller.emailController, labelText: 'Email'.tr, hintText: 'Enter your email'.tr, prefixIcon: Icons.email_outlined, keyboardType: TextInputType.emailAddress, validator: (value) { if (value == null || !GetUtils.isEmail(value)) { return 'Please enter a valid email'.tr; } return null; }, ), const SizedBox(height: 20), GetBuilder( id: 'passwordVisibility', builder: (_) => _buildTextFormField( controller: controller.passwordController, labelText: 'Password'.tr, hintText: 'Enter your password'.tr, prefixIcon: Icons.lock_outline, obscureText: controller.isPasswordHidden, suffixIcon: IconButton( icon: Icon( controller.isPasswordHidden ? Icons.visibility_off : Icons.visibility, color: AppColor.primaryColor, ), onPressed: () => controller.togglePasswordVisibility(), ), validator: (value) { if (value == null || value.length < 6) { return 'Password must be at least 6 characters'.tr; } return null; }, ), ), const SizedBox(height: 30), controller.isloading ? const Center(child: MyCircularProgressIndicator()) : MyElevatedButton( title: isRegister ? 'Create Account'.tr : 'Login'.tr, onPressed: () { if (controller.formKey.currentState!.validate()) { if (isRegister) { // Registration Logic String email = controller.emailController.text; String uniqueId = controller.generateUniqueIdFromEmail(email); box.write(BoxName.driverID, uniqueId); box.write(BoxName.emailDriver, email); controller.loginUsingCredentialsWithoutGoogle( controller.passwordController.text, email, ); } else { // Login Logic controller.loginWithGoogleCredential( controller.passwordController.text, controller.emailController.text, ); } } }, ), const SizedBox(height: 20), // Dynamic toggle button for Login/Register Center( child: RichText( textAlign: TextAlign.center, text: TextSpan( style: AppStyle.subtitle.copyWith(color: Colors.grey[700]), children: [ TextSpan( text: isRegister ? 'Already have an account? '.tr : 'Don\'t have an account? '.tr, ), TextSpan( text: isRegister ? 'Login'.tr : 'Register'.tr, style: TextStyle( color: AppColor.primaryColor, fontWeight: FontWeight.bold, decoration: TextDecoration.underline, ), recognizer: TapGestureRecognizer() ..onTap = () => controller.toggleRegisterMode(), ), ], ), ), ) ], ), ), ), ), ), ); } /// A helper method to create styled TextFormFields. TextFormField _buildTextFormField({ required TextEditingController controller, required String labelText, required String hintText, required IconData prefixIcon, required String? Function(String?) validator, bool obscureText = false, Widget? suffixIcon, TextInputType keyboardType = TextInputType.text, }) { return TextFormField( controller: controller, validator: validator, obscureText: obscureText, keyboardType: keyboardType, decoration: InputDecoration( labelText: labelText, hintText: hintText, prefixIcon: Icon(prefixIcon, color: AppColor.primaryColor), suffixIcon: suffixIcon, border: OutlineInputBorder(borderRadius: BorderRadius.circular(12.0)), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12.0), borderSide: const BorderSide(color: AppColor.primaryColor, width: 2.0), ), ), ); } /// A helper for creating consistent social login buttons. Widget _buildSocialButton({ required String text, required IconData icon, required Color backgroundColor, required VoidCallback onPressed, }) { return ElevatedButton.icon( icon: Icon(icon, color: Colors.white), label: Text(text, style: const TextStyle(color: Colors.white, fontSize: 16)), onPressed: onPressed, style: ElevatedButton.styleFrom( backgroundColor: backgroundColor, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), padding: const EdgeInsets.symmetric(vertical: 14), ), ); } /// A wrapper page for the Country Picker for a better UX. Widget _buildCountryPickerPage() { return Scaffold( backgroundColor: AppColor.secondaryColor, appBar: AppBar( title: Text("Select Your Country".tr, style: AppStyle.headTitle2), centerTitle: true, backgroundColor: Colors.transparent, elevation: 0, ), body: CountryPicker(), // Your existing country picker widget ); } // --- The following pages are kept as they are well-designed --- /// UI for the Terms and Conditions agreement page. Widget _buildAgreementPage( BuildContext context, LoginDriverController controller) { return Padding( padding: const EdgeInsets.all(24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.policy_outlined, size: 80, color: AppColor.primaryColor), const SizedBox(height: 20), Text('Driver Agreement'.tr, textAlign: TextAlign.center, style: AppStyle.headTitle2), const SizedBox(height: 30), RichText( textAlign: TextAlign.center, text: TextSpan( style: AppStyle.title.copyWith(height: 1.5, color: Colors.black87), children: [ TextSpan( text: "To become a driver, you must review and agree to the " .tr), TextSpan( text: 'Terms of Use'.tr, style: const TextStyle( decoration: TextDecoration.underline, color: AppColor.blueColor, fontWeight: FontWeight.bold), recognizer: TapGestureRecognizer() ..onTap = () { Get.defaultDialog( title: 'Privacy Policy'.tr, content: SizedBox( height: Get.height * 0.6, child: SingleChildScrollView( child: HtmlWidget(AppInformation.privacyPolicy)), ), ); }), TextSpan(text: " and acknowledge our Privacy Policy.".tr), ], ), ), const Spacer(), CheckboxListTile( title: Text('I Agree'.tr, style: AppStyle.title), value: controller.isAgreeTerms, onChanged: (value) => controller.changeAgreeTerm(), activeColor: AppColor.primaryColor, controlAffinity: ListTileControlAffinity.leading, ), const SizedBox(height: 16), SizedBox( width: double.infinity, child: MyElevatedButton( title: 'Continue'.tr, onPressed: controller.isAgreeTerms ? () => controller.saveAgreementTerms() : () {}, // Button is disabled if not agreed ), ), ], ), ); } /// UI for the Location Permission request page. Widget _buildLocationPermissionPage( BuildContext context, LoginDriverController controller) { return Padding( padding: const EdgeInsets.all(24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Icon(Icons.location_on_outlined, size: 80, color: AppColor.primaryColor), const SizedBox(height: 20), Text( 'Location Access Required'.tr, textAlign: TextAlign.center, style: AppStyle.headTitle2, ), const SizedBox(height: 16), Text( 'We need access to your location to match you with nearby passengers and provide accurate navigation.' .tr, textAlign: TextAlign.center, style: AppStyle.title, ), const SizedBox(height: 24), Text( 'Please allow location access "all the time" to receive ride requests even when the app is in the background.' .tr, textAlign: TextAlign.center, style: AppStyle.title.copyWith( color: AppColor.greenColor, fontWeight: FontWeight.bold), ), const SizedBox(height: 40), MyElevatedButton( title: "Allow Location Access".tr, onPressed: () async { await getLocationPermission(); if (await Permission.location.isGranted) { box.write(BoxName.locationPermission, 'true'); controller.update(); } }, kolor: AppColor.greenColor, ), const SizedBox(height: 16), TextButton( onPressed: () => openAppSettings(), child: Text("Open Settings".tr, style: const TextStyle(color: AppColor.blueColor)), ), ], ), ); } }