diff --git a/lib/domain/use_cases/auth_use_case.dart b/lib/domain/use_cases/auth_use_case.dart index a6d27b8c..72fc6c01 100644 --- a/lib/domain/use_cases/auth_use_case.dart +++ b/lib/domain/use_cases/auth_use_case.dart @@ -56,7 +56,7 @@ class AuthUseCase extends _$AuthUseCase { ); } - Future login(String email, String pw) async { + Future login(String email, String pw) async { final session = await _repo.login(email, pw); final localPrefs = await getIt.call().get(); if (localPrefs != null) { @@ -66,6 +66,7 @@ class AuthUseCase extends _$AuthUseCase { ); } state = AsyncData(session); + return session; // Return the session with user details. } Future logout() async { diff --git a/lib/presentation/Screens/changepassword.dart b/lib/presentation/Screens/changepassword.dart index 8c0155e0..9c17e7a9 100644 --- a/lib/presentation/Screens/changepassword.dart +++ b/lib/presentation/Screens/changepassword.dart @@ -1,11 +1,15 @@ -import 'dart:convert'; -import 'package:http/http.dart' as http; +import 'dart:math'; + import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; import 'package:pocketbase/pocketbase.dart'; +import 'dart:convert'; import 'otp_verification.dart'; class Changepassword extends StatefulWidget { - const Changepassword({Key? key}) : super(key: key); + // final String email; + final String userId; + const Changepassword({Key? key, required this.userId}); @override State createState() => _ResetPasswordScreenState(); @@ -53,7 +57,7 @@ class _ResetPasswordScreenState extends State { //print('userDetails ->: $userData'); if (userData['items'].isNotEmpty) { // Email exists; retrieve user ID - final userId = userData['items'][0]['id']; + //final userId = userData['items'][0]['id']; // Proceed with OTP request final otpResponse = await http.post( @@ -87,7 +91,7 @@ class _ResetPasswordScreenState extends State { MaterialPageRoute( builder: (context) => EmailVerificationScreen( email: email, - userId: userId, // Pass user ID to the next screen + userId: widget.userId, // Pass user ID to the next screen otp: otp, otpId: otpId, sendVerificationCode: sendVerificationCode, diff --git a/lib/presentation/Screens/confirm_password.dart b/lib/presentation/Screens/confirm_password.dart index 6bb6b26d..87a71c0f 100644 --- a/lib/presentation/Screens/confirm_password.dart +++ b/lib/presentation/Screens/confirm_password.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'dart:async'; import 'package:pocketbase/pocketbase.dart'; import 'package:uae_stat/presentation/Screens/profilepage.dart'; @@ -12,7 +13,7 @@ class ConfirmPassword extends StatefulWidget { } class _ConfirmPasswordState extends State { - final _pb = PocketBase('https://pb.venbait.in'); + final pb = PocketBase('https://pb.venbait.in'); // final pb = PocketBase('http://127.0.0.1:8090'); final _formKey = GlobalKey(); bool _obscurePassword = true; @@ -44,8 +45,7 @@ class _ConfirmPasswordState extends State { //print('userRecord- $userId'); // Authenticate as admin - - final adminAuth = await _pb.admins + final adminAuth = await pb.admins .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com'); final token = adminAuth.token; @@ -53,10 +53,9 @@ class _ConfirmPasswordState extends State { 'Authorization': 'Bearer $token', }; - final userRecord = await _pb.collection('users').getOne(userId); + final userRecord = await pb.collection('users').getOne(userId); //print('userRecord- $userRecord'); final oldPassword = userRecord.data['password']; - print(oldPassword); // Check if the new password is the same as the old password if (oldPassword == newPassword) { @@ -71,10 +70,14 @@ class _ConfirmPasswordState extends State { } // Update password - await _pb.collection('users').update( - userId, // User ID - body: {'password': newPassword}, // Updated password - ); + await pb.collection('users').update( + userId, // User ID + body: { + 'password': newPassword, + 'passwordConfirm': newPassword, + }, // Updated password + headers: headers, + ); // Show success Snackbar ScaffoldMessenger.of(context).showSnackBar( diff --git a/lib/presentation/Screens/demo_home.dart b/lib/presentation/Screens/demo_home.dart new file mode 100644 index 00000000..402bc535 --- /dev/null +++ b/lib/presentation/Screens/demo_home.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:uae_stat/domain/use_cases/language.dart'; + +import '../components/my_drawer.dart'; + +class DemoHome extends StatefulWidget { + @override + State createState() => _DemoHomeState(); +} + +class _DemoHomeState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + drawer: const MyDrawer(), + appBar: AppBar( + backgroundColor: const Color(0xFFf8f9ff), + title: Text(context.translate('Home', 'نموذج الملاحظات')), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Center( + child: Text('Home Page'), + )), + ); + } +} diff --git a/lib/presentation/Screens/otp_verification.dart b/lib/presentation/Screens/otp_verification.dart index f5c4c6c8..d04fcb3b 100644 --- a/lib/presentation/Screens/otp_verification.dart +++ b/lib/presentation/Screens/otp_verification.dart @@ -1,8 +1,7 @@ import 'dart:async'; - +import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; import 'package:pocketbase/pocketbase.dart'; - import 'confirm_password.dart'; class EmailVerificationScreen extends StatefulWidget { @@ -23,8 +22,8 @@ class EmailVerificationScreen extends StatefulWidget { } class _EmailVerificationScreenState extends State { + final pb = PocketBase('https://pb.venbait.in'); // final pb = PocketBase('http://127.0.0.1:8090'); - final _pb = PocketBase('https://pb.venbait.in'); final List _otpControllers = List.generate(4, (_) => TextEditingController()); int _secondsRemaining = 120; // 2 minutes timer @@ -131,7 +130,7 @@ class _EmailVerificationScreenState extends State { ), SizedBox(height: 8), Text( - "Please Enter the 4 digit Code Sent to\nrjosh289778@gmail.com", + "Please Enter the 4 digit Code Sent to ${widget.email}", textAlign: TextAlign.center, style: TextStyle( fontSize: 16, @@ -181,7 +180,7 @@ class _EmailVerificationScreenState extends State { SizedBox(height: 16), Text.rich( TextSpan( - text: "Code Expires in ", + text: "Code Expires in ", style: TextStyle(color: Colors.grey[600]), children: [ TextSpan( @@ -207,7 +206,8 @@ class _EmailVerificationScreenState extends State { child: Text( "Resend Code", style: TextStyle( - color: Colors.brown, fontWeight: FontWeight.bold), + color: _canResend ? Colors.brown : Colors.grey, + fontWeight: FontWeight.bold), ), ), SizedBox(height: 5), diff --git a/lib/presentation/Screens/profilepage.dart b/lib/presentation/Screens/profilepage.dart index f0ab349f..e4afc43d 100644 --- a/lib/presentation/Screens/profilepage.dart +++ b/lib/presentation/Screens/profilepage.dart @@ -4,12 +4,17 @@ import 'dart:io'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:go_router/go_router.dart'; import 'package:http/http.dart' as http; import 'package:image_picker/image_picker.dart'; import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/domain/use_cases/language.dart'; +import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart'; +import '../components/my_bottom_nav_bar.dart'; import 'changepassword.dart'; +import 'demo_home.dart'; class ProfileScreen extends StatefulWidget { final String userId; // Add this field to hold the user ID @@ -67,6 +72,7 @@ class _ProfileScreenState extends State { final adminAuth = await _pb.admins .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com'); final adminToken = adminAuth.token; + print('adminToken- ${adminToken}'); final userDetailsResponse = await _pb.collection('users').getOne( widget.userId, headers: { @@ -200,6 +206,10 @@ class _ProfileScreenState extends State { _resetFormFields(); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Profile updated successfully!"))); + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => DemoHome()), + ); } catch (error) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Failed to update profile: $error"))); @@ -518,7 +528,8 @@ class _ProfileScreenState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => Changepassword()), + builder: (context) => + Changepassword(userId: widget.userId)), ); }, child: Text( diff --git a/lib/presentation/Screens/registration.dart b/lib/presentation/Screens/registration.dart index d87b0562..a4f18a07 100644 --- a/lib/presentation/Screens/registration.dart +++ b/lib/presentation/Screens/registration.dart @@ -1,3 +1,4 @@ +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; @@ -6,6 +7,7 @@ import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/presentation/Screens/profilepage.dart'; import '../../infrastructure/services/pocketbase_service.dart'; +import '../routes/auth_routes/login_route.dart'; class RegisterScreen extends StatefulWidget { @override @@ -17,6 +19,8 @@ class _RegisterScreenState extends State { final _usernameController = TextEditingController(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); + final _confirmpasswordController = TextEditingController(); + bool _obscurePassword = true; bool _obscureConfirmPassword = true; bool isChecked = false; @@ -25,56 +29,153 @@ class _RegisterScreenState extends State { bool registrationSuccess = false; bool registrationFailed = false; dynamic userID; + final pb = PocketBase('https://pb.venbait.in'); // final pb = PocketBase('http://127.0.0.1:8090'); + // Add focus nodes and hint states + final List _focusNodes = List.generate(4, (_) => FocusNode()); + final List _showHints = [ + true, + true, + true, + true + ]; // One for each TextField + + String _getControllerText(int index) { + if (index == 0) return _usernameController.text; + if (index == 1) return _emailController.text; + if (index == 2) return _passwordController.text; + if (index == 3) return _confirmpasswordController.text; + return ''; + } + @override void initState() { super.initState(); + + // Add listeners for focus nodes + for (int i = 0; i < _focusNodes.length; i++) { + _focusNodes[i].addListener(() { + setState(() { + // Hide hint when focused and text is not empty + _showHints[i] = + !_focusNodes[i].hasFocus && (_getControllerText(i).isEmpty); + }); + }); + + // Listen to text changes + if (i == 0) { + _usernameController.addListener(() { + setState(() { + _showHints[i] = + !_focusNodes[i].hasFocus && (_getControllerText(i).isEmpty); + }); + }); + } else if (i == 1) { + _emailController.addListener(() { + setState(() { + _showHints[i] = + !_focusNodes[i].hasFocus && (_getControllerText(i).isEmpty); + }); + }); + } else if (i == 2) { + _passwordController.addListener(() { + setState(() { + _showHints[i] = + !_focusNodes[i].hasFocus && (_getControllerText(i).isEmpty); + }); + }); + } else if (i == 3) { + _confirmpasswordController.addListener(() { + setState(() { + _showHints[i] = + !_focusNodes[i].hasFocus && (_getControllerText(i).isEmpty); + }); + }); + } + } } @override void dispose() { + for (var focusNode in _focusNodes) { + focusNode.dispose(); + } _usernameController.dispose(); _emailController.dispose(); _passwordController.dispose(); + _confirmpasswordController.dispose(); super.dispose(); } String? _validateUsername(String? value) { if (value == null || value.isEmpty) { return 'Required'; - } else if (RegExp(r'[^a-zA-Z0-9]').hasMatch(value)) { + } else if (value.length > 40) { + return 'Must not exceed 40 characters'; + } else if (!RegExp(r"^[a-zA-Z0-9'\-\u0627\u0639~\u00C0-\u00FF]+$") + .hasMatch(value)) { return 'Invalid Characters'; } return null; } + //else if (RegExp(r'[^a-zA-Z0-9]').hasMatch(value)) + String? _validateEmail(String? value) { + // Regex to allow special characters, accented characters, and alphanumeric characters + final emailRegex = + r'^[a-zA-Z0-9àèìòùÀÈÌÒÙéàç~!#$%^&*()_+=-{}|;,.?<>]+@[a-zA-Z0-9àèìòùÀÈÌÒÙéàç~!#$%^&*()_+=-{}|;,.?<>]+\.[a-zA-Z]{2,}$'; + if (value == null || value.isEmpty) { return 'Required'; - } else if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) { + } else if (!RegExp(emailRegex).hasMatch(value)) { return 'Invalid Email'; } return null; } String? _validatePassword(String? value) { + // Define the regular expression for allowed characters + final regex = RegExp( + r'^[A-Za-z0-9~!@#$%^&*()_+=[\]{}|;:,.<>?/-àèìòùáéíóúÀÈÌÒÙÁÉÍÓÚ]*$'); + if (value == null || value.isEmpty) { return 'Required'; - } else if (value.length < 6) { - return 'Password must be at least 6 characters'; + } else if (value.length < 8) { + return 'Password must be at least 8characters'; } + + // Check the length constraint + if (value.length < 8 || value.length > 40) { + return 'Password must be between 8 and 64 characters'; + } + + // Check the regular expression + if (!regex.hasMatch(value)) { + return 'Password contains invalid characters'; + } + _password = value; // Store the password for confirm password validation return null; } String? _validateConfirmPassword(String? value) { + // Define the regular expression for allowed characters + final regex = RegExp( + r'^[A-Za-z0-9~!@#$%^&*()_+=[\]{}|;:,.<>?/-àèìòùáéíóúÀÈÌÒÙÁÉÍÓÚ]*$'); + if (value == null || value.isEmpty) { return 'Required'; + } else if (value.length < 8 || value.length > 40) { + return 'Password must be at least 8characters'; + } else if (!regex.hasMatch(value)) { + return 'Password contains invalid characters'; } else if (value != _password) { return 'Passwords do not match'; } + return null; } @@ -84,14 +185,16 @@ class _RegisterScreenState extends State { try { final adminAuth = await pb.admins .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com'); + final adminToken = adminAuth.token; + print('adminToken- ${adminToken}'); // Create user in PocketBase final response = await pb.collection('users').create(body: { 'username': _usernameController.text, 'email': _emailController.text, 'password': _passwordController.text, - 'passwordConfirm': _passwordController - .text, // PocketBase requires password confirmation + 'passwordConfirm': _passwordController.text, + // 'verified': true, }, headers: { 'Authorization': adminToken }); @@ -194,9 +297,10 @@ class _RegisterScreenState extends State { onPressed: () => { Navigator.pushReplacement( context, - MaterialPageRoute( - builder: (context) => - ProfileScreen(userId: userID)), + MaterialPageRoute(builder: (context) => LoginRoute() + + //ProfileScreen(userId: userID) + ), ), }, child: Text( @@ -247,9 +351,17 @@ class _RegisterScreenState extends State { ), SizedBox(height: 10), ElevatedButton( - onPressed: () => context.go( - '/${context.language}/login', - ), + onPressed: () => { + setState(() { + registrationFailed = false; + registrationSuccess = false; + _usernameController.clear(); + _emailController.clear(); + _passwordController.clear(); + _confirmpasswordController.clear(); + isChecked = false; + }) + }, child: Text( 'Retry', ), @@ -286,12 +398,14 @@ class _RegisterScreenState extends State { ), SizedBox(height: 10), Text('Please enter your details'), + SizedBox(height: 20), // Display this if registration is pending approval TextFormField( controller: _usernameController, + focusNode: _focusNodes[0], decoration: InputDecoration( - hintText: 'Username', + hintText: _showHints[0] ? 'Username' : null, prefixIcon: Icon( Icons.person, color: Colors.blue, @@ -307,22 +421,34 @@ class _RegisterScreenState extends State { SizedBox(height: 15), TextFormField( controller: _emailController, + focusNode: _focusNodes[1], decoration: InputDecoration( - hintText: 'Enter your email', + // hintText: 'Enter your email', + hintText: + _showHints[1] ? 'Enter your email' : null, prefixIcon: Icon( Icons.email, color: Colors.blue, ), border: OutlineInputBorder(), + counterText: '', ), validator: _validateEmail, + maxLength: 320, + maxLengthEnforcement: MaxLengthEnforcement.enforced, + inputFormatters: [ + LengthLimitingTextInputFormatter( + 320), // Limit to 320 characters + ], ), SizedBox(height: 15), TextFormField( controller: _passwordController, + focusNode: _focusNodes[2], obscureText: _obscurePassword, decoration: InputDecoration( - hintText: 'Enter your password', + hintText: + _showHints[2] ? 'Enter your password' : null, prefixIcon: Icon( Icons.lock, color: Colors.blue, @@ -341,14 +467,20 @@ class _RegisterScreenState extends State { }, ), border: OutlineInputBorder(), + counterText: '', ), validator: _validatePassword, + maxLength: 40, + maxLengthEnforcement: MaxLengthEnforcement.enforced, ), SizedBox(height: 15), TextFormField( + controller: _confirmpasswordController, + focusNode: _focusNodes[3], obscureText: _obscureConfirmPassword, decoration: InputDecoration( - hintText: 'Confirm password', + hintText: + _showHints[3] ? 'Confirm password' : null, prefixIcon: Icon( Icons.lock, color: Colors.blue, @@ -368,8 +500,15 @@ class _RegisterScreenState extends State { }, ), border: OutlineInputBorder(), + counterText: '', ), validator: _validateConfirmPassword, + maxLength: 40, + maxLengthEnforcement: MaxLengthEnforcement.enforced, + inputFormatters: [ + LengthLimitingTextInputFormatter( + 64), // Limit to 40 characters + ], ), SizedBox(height: 10), Row( @@ -414,7 +553,7 @@ class _RegisterScreenState extends State { Padding( padding: const EdgeInsets.only(left: 10.0), child: Text( - 'Required', + 'Please agree to terms and conditions.', style: TextStyle( color: Colors.red[700], fontSize: 12, @@ -470,18 +609,48 @@ class _RegisterScreenState extends State { borderRadius: BorderRadius.circular(10), ), ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - "Login", - style: TextStyle( - fontSize: 16, color: Colors.white), - ), - SizedBox(width: 8), - Icon(Icons.arrow_forward, - color: Colors.white), - ], + // child: Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // Text( + // "Login", + // style: TextStyle( + // fontSize: 16, color: Colors.white + // ), + // + // + // ), + // SizedBox(width: 8), + // Icon(Icons.arrow_forward, + // color: Colors.white), + // ], + // ), + + child: GestureDetector( + onTap: () { + // Navigate to LoginRoute + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => LoginRoute()), + // MaterialPageRoute(builder: (context) => LoginRoute(userId: userID)), + ); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "Login", + style: TextStyle( + fontSize: 16, + color: Colors.white, + ), + ), + SizedBox(width: 8), + Icon(Icons.arrow_forward, + color: Colors.white), + ], + ), ), ), ), diff --git a/lib/presentation/routes/auth_routes/login_route.dart b/lib/presentation/routes/auth_routes/login_route.dart index d05e1348..3460183b 100644 --- a/lib/presentation/routes/auth_routes/login_route.dart +++ b/lib/presentation/routes/auth_routes/login_route.dart @@ -9,18 +9,57 @@ import 'package:uae_stat/domain/use_cases/auth_use_case.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/banner_asset_path.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; +import 'package:uae_stat/presentation/Screens/demo_home.dart'; import 'package:uae_stat/presentation/components/dialogs.dart'; import 'package:uae_stat/presentation/components/lang_toggle.dart'; import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart'; import 'package:uae_stat/presentation/components/space.dart'; import 'package:uae_stat/presentation/components/themed_text_field.dart'; -import 'package:uae_stat/presentation/routes/drawer_routes/profile/profile_route.dart'; +import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart'; + +import '../../Screens/profilepage.dart'; +import '../../Screens/registration.dart'; +import 'package:pocketbase/pocketbase.dart'; class LoginRoute extends HookConsumerWidget { - const LoginRoute({super.key}); + final pb = PocketBase('https://pb.venbait.in'); + // final _pb = PocketBase('http://127.0.0.1:8090'); + LoginRoute({super.key}); static final formKey = GlobalKey(); + Future profileStatus(String userId) async { + try { + // Authenticate admin + final adminAuth = await pb.admins.authWithPassword( + 'pb@venbainfotech.com', + 'pb@venbainfotech.com', + ); + final String adminToken = adminAuth.token; + print('adminToken: $adminToken'); + + // Fetch user details + final userDetailsResponse = await pb.collection('users').getOne( + userId, + headers: { + 'Authorization': 'Bearer $adminToken', + }, + ); + print('userDetailsLogin: $userDetailsResponse'); + + // Check if 'is_profile_completed' is true or false + if (userDetailsResponse != null && + userDetailsResponse.data['is_profile_completed'] != null) { + return userDetailsResponse.data['is_profile_completed']; + } else { + return false; // Default to false if the field is missing or response is null + } + } catch (e) { + print('Error fetching user details: $e'); + return false; // Return false on error + } + } + @override Widget build(BuildContext context, WidgetRef ref) { final emailCtl = useTextEditingController(); @@ -119,76 +158,95 @@ class LoginRoute extends HookConsumerWidget { width: double.infinity, child: ElevatedButton( onPressed: () async { - // final isValid = formKey.currentState!.validate(); - // if (!isValid) return; - // await context.loaderWithErrorDialog( - // () => ref - // .read( - // authUseCaseProvider.notifier, - // ) - // .login( - // emailCtl.text, - // pwCtl.text, - // ), - // errorDialogBuilder: ( - // error, [ - // StackTrace? stackTrace, - // ]) { - // if (error == LoginError.invalidEmailPw) { - // return context.simpleDialog( - // title: context.translate( - // 'Incorrect credentials', - // 'أوراق غير صحيحة', - // ), - // content: context.translate( - // 'Your email or password is invalid. Please try again.', - // 'بريدك الإلكتروني أو كلمة المرور غير صالحة. حاول مرة اخرى.', - // ), - // ); - // } - // if (error == LoginError.emailAddressNotVerified) { - // return context.simpleDialog( - // title: context.translate( - // 'Verification Error', - // 'خطأ التحقق', - // ), - // content: context.translate( - // '${emailCtl.text} is not a verified email address. Please check your email for a verification link.', - // '${emailCtl.text} ليس عنوان بريد إلكتروني تم التحقق منه. يرجى التحقق من بريدك الإلكتروني للحصول على رابط التحقق.', - // ), - // extraAction: ElevatedButton( - // onPressed: () async { - // Navigator.of( - // context, - // rootNavigator: true, - // ).pop(); - // await context.loaderWithErrorDialog( - // () => ref - // .read(authUseCaseProvider.notifier) - // .requestVerificationEmail(emailCtl.text), - // ); - // if (!context.mounted) return; - // context.simpleDialog( - // title: 'Email Re-sent', - // content: - // 'We\'ve sent you the verification email at ${emailCtl.text} again.', - // ); - // }, - // child: Text( - // context.translate( - // 'I did not receive an email', - // 'لم أتلق بريدًا إلكترونيًا', - // ), - // ), - // ), - // ); - // } - // return context.simpleDialog(); - // }, - // ); - // if (!context.mounted) return; + final isValid = formKey.currentState!.validate(); + if (!isValid) return; + final session = await context.loaderWithErrorDialog( + () => ref + .read( + authUseCaseProvider.notifier, + ) + .login( + emailCtl.text, + pwCtl.text, + ), + errorDialogBuilder: ( + error, [ + StackTrace? stackTrace, + ]) { + if (error == LoginError.invalidEmailPw) { + return context.simpleDialog( + title: context.translate( + 'Incorrect credentials', + 'أوراق غير صحيحة', + ), + content: context.translate( + 'Your email or password is invalid. Please try again.', + 'بريدك الإلكتروني أو كلمة المرور غير صالحة. حاول مرة اخرى.', + ), + ); + } + if (error == LoginError.emailAddressNotVerified) { + return context.simpleDialog( + title: context.translate( + 'Verification Error', + 'خطأ التحقق', + ), + content: context.translate( + '${emailCtl.text} is not a verified email address. Please check your email for a verification link.', + '${emailCtl.text} ليس عنوان بريد إلكتروني تم التحقق منه. يرجى التحقق من بريدك الإلكتروني للحصول على رابط التحقق.', + ), + extraAction: ElevatedButton( + onPressed: () async { + Navigator.of( + context, + rootNavigator: true, + ).pop(); + await context.loaderWithErrorDialog( + () => ref + .read(authUseCaseProvider.notifier) + .requestVerificationEmail(emailCtl.text), + ); + if (!context.mounted) return; + context.simpleDialog( + title: 'Email Re-sent', + content: + 'We\'ve sent you the verification email at ${emailCtl.text} again.', + ); + }, + child: Text( + context.translate( + 'I did not receive an email', + 'لم أتلق بريدًا إلكترونيًا', + ), + ), + ), + ); + } + return context.simpleDialog(); + }, + ); + if (!context.mounted || session == null) return; + // Extract userId from the session + final userId = session.id; + + final bool isUpdate = await profileStatus(userId); + + print('Is profile completed: $isUpdate'); + + if (isUpdate) { + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => DemoHome()), + ); + } else { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => ProfileScreen(userId: userId)), + ); + } + // context.go('/${context.language}/${BottomNavBarItem.home.routePath}'); - context.go('/Profile'); }, style: ButtonStyle( shape: WidgetStatePropertyAll( @@ -224,7 +282,7 @@ class LoginRoute extends HookConsumerWidget { children: [ Text( context.translate( - 'Login log', + 'Login', 'تسجيل الدخول', ), ), @@ -309,7 +367,12 @@ class LoginRoute extends HookConsumerWidget { ], ); final dontHaveAnAccountRegisterBtn = TextButton( - onPressed: () => context.go('/${context.language}/register'), + onPressed: () => { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => RegisterScreen()), + ), + }, child: Text.rich( textAlign: TextAlign.center, TextSpan(