skip to Main Content

I’m new to flutter and I’m trying to make auth app with dio.dart , I hosted laravel api and test it by postman, it works well but I dont know better way on how to do auth for for the flutter from this api dynamically, I mean how can i trigger each error from the server/api I made and showing it to client UI

on auth service already defined header to accept json, and url for my api now the problem is how to get exactly each error and success message from the above to show on ui, i.e error for email and password, other defined error and success message or i need to modify what

my backend api for auth login and request from flutter

public function login(Request $request) {
    // Validate the input data
    $validated = $request->validate([
        'email' => 'required|string|email|max:255',
        'password' => 'required|string|min:8',
    ]);

    // Find the user by email
    $user = User::where('email', $validated['email'])->first();

    // User not found, return a 404 with specific error message
    if (!$user) {
        return response()->json([
            'message' => 'User not found.',
            'type' => 'error',  // Indicating it's an error
        ], 404);
    }

    // Check if the password is correct
    if (!Hash::check($validated['password'], $user->password)) {
        return response()->json([
            'message' => 'Please check your password.',
            'type' => 'error',  // Indicating it's an error
        ], 401);
    }

    // Check if the user is verified
    if (!$user->email_verified_at) {
        // User is not verified, resend the verification code
        $verificationCode = random_int(100000, 999999);
        $user->verification_code = $verificationCode;
        $user->save();

        // Resend the verification email
        Mail::to($user->email)->send(new VerifyEmailMail($verificationCode));

        // Return a 400 with informational message
        return response()->json([
            'message' => 'Please verify your email.',
            'type' => 'info',  // Informational message
        ], 400);
    }

    // If the user is verified, generate an API token
    $token = $user->createToken('auth_token')->plainTextToken;

    // Return 200 (OK) with success message, token, and user data
    return response()->json([
        'message' => 'Login successful!.',
        'type' => 'success',  // Success message
        'token' => $token,
        'user' => $user,
    ], 200);  // OK
}
//flutter code is here
Future<bool> login(String email, String password) async { 
    try { 
        final response = await _dio.post( loginUrl, data: json.encode({ 'email': email, 'password': password, }), );

      if (response.statusCode == 200) {
        final token = response.data['token'];
        await _secureStorage.write(key: 'auth_token', value: token);
        return true; // Successfully logged in
      } else {
        return false; // Something went wrong with login, no errors returned
      }
    } catch (e) {
      if (e is DioException && e.response != null) {
        // Check for validation errors (422)
        if (e.response?.statusCode == 422) {
          // Returning the errors as a map
          throw ValidationException(e.response?.data['errors']);
        }
      }
      print('Login failed: $e');
      return false; // Return false for other types of errors
    }

}


2

Answers


  1. You need to parse the backend response correctly and handle specific error or success cases. Modify your code as follows:

    Future<Map<String, dynamic>> login(String email, String password) async {
      try {
        final response = await _dio.post(
          loginUrl,
          data: json.encode({
            'email': email,
            'password': password,
          }),
        );
    
        if (response.statusCode == 200) {
          final token = response.data['data']['token'];
          await _secureStorage.write(key: 'auth_token', value: token);
          return {
            "success": true,
            "message": response.data['message'],
          };
        } else {
          return {
            "success": false,
            "message": response.data['message'] ?? "An error occurred",
          };
        }
      } catch (e) {
        if (e is DioException && e.response != null) {
          if (e.response?.statusCode == 422) {
            // Returning validation errors
            return {
              "success": false,
              "errors": e.response?.data['errors'],
              "message": e.response?.data['message'] ?? "Validation failed",
            };
          }
        }
        print('Login failed: $e');
        return {
          "success": false,
          "message": "An unexpected error occurred",
        };
      }
    }
    
    
    void handleLogin(BuildContext context, String email, String password) async {
      final result = await login(email, password);
    
      if (result['success']) {
        // Show success message
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(result['message'])),
        );
        // Navigate to the next screen (e.g., replace with your navigation logic)
        // Navigator.pushReplacementNamed(context, '/home');
      } else if (result.containsKey('errors')) {
        // Show validation errors
        final errors = result['errors'] as Map<String, dynamic>;
        if (errors['email'] != null) {
          print("Email error: ${errors['email'].join(', ')}");
        }
        if (errors['password'] != null) {
          print("Password error: ${errors['password'].join(', ')}");
        }
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(result['message'])),
        );
      } else {
        // Show generic error message
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(result['message'])),
        );
      }
    }
    

    The above method use on the onTap of your login button

    onPressed: () {
      handleLogin(
        context,
        emailController.text,
        passwordController.text,
      );
    },
    
    Login or Signup to reply.
  2. I understand you might be facing challenges with implementing a login function in Flutter. Based on your scenario, I believe the following solution might help streamline your implementation:

      Future<Map<String, dynamic>> login(String email, String password) async {
        try {
          final response = await _dio.post( loginUrl, data: json.encode({ 'email': email, 'password': password, }), );
    
          if (response.statusCode == 200) {
            final token = response.data['token'];
            await _secureStorage.write(key: 'auth_token', value: token);
          }
          return response.data ?? {}; // Successfully logged in or error
        } catch (e) {
          if (e is DioException && e.response != null) {
    
            // Check for validation errors (422)
            if (e.response?.statusCode == 422) {
              // Returning the errors as a map
              throw ValidationException(e.response?.data['errors']);
            }
          return e.response?.data ?? {};
          }
          print('Login failed: $e');
          return {}; // Return false for other types of errors
        }
    
      }
    

    By making these adjustments, you can improve the robustness and reliability of your login function. Let me know if you need further clarification or additional guidance.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search