Tutorial Flutter Form Login dan Daftar dengan BLoC

Hai semua, kali ini kita akan membahas Tutorial Flutter Form Login dan Daftar dengan BLoC. Artikel ini hampir mirip seperti artikel kami sebelumnya yang berjudul Registrasi dan Login Firebase Auth dengan BLoC. Hanya saja pada artikel sebelumnya kita menggunakan firebase sebagai backend nya, kali ini kita akan menggunakan backend sendiri.

Tutorial Flutter Form Login dan Daftar dengan BLoC

Kita akan memulai dari bagian pendaftarannya.

Tutorial Flutter Form Daftar dengan BLoC

Kami menggunakan API sederhana untuk proses pendaftaran user, kami mengirimkan 4 parameter dengan metode POST.

Tutorial Flutter Form Daftar dengan BLoC

Kemudian, jika proses daftar berhasil kita akan mendapatkan balasan berupa json seperti ini

{
    "status": 1,
    "message": "Success",
    "user": {
        "id": "18",
        "email": "",
        "password": "d41d8cd98f00b204e9800998ecf8427e",
        "name": "",
        "phone": "",
        "imageFileName": "",
        "active": "1"
    }
}

Jika gagal karena email sudah terdaftar balasan json seperti ini

{
    "status": 0,
    "message": "Email already registered"
}

Dan jika gagal karena ada masalah di table atau database balasan akan seperti ini

{
    "status": 2,
    "message": "Something went wrong"
}

Mari mulai untuk membuat form nya. Sebelum itu buat 1 folder bernama register, kemudian simpan file-file dibawah ini ke dalamnya

register_screen.dart

class RegisterScreen extends StatelessWidget {
  final UserRepository _userRepository;

  RegisterScreen({Key key, @required UserRepository userRepository})
      : assert(userRepository != null),
        _userRepository = userRepository,
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: BlocProvider<RegisterBloc>(
          create: (context) => RegisterBloc(userRepository: _userRepository),
          child: RegisterForm(),
        ),
      ),
    );
  }
}

register_form.dart

class RegisterForm extends StatefulWidget {
  State<RegisterForm> createState() => _RegisterFormState();
}

class _RegisterFormState extends State<RegisterForm> {
  final TextEditingController _emailController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();
  final TextEditingController _nameController = TextEditingController();
  final TextEditingController _phoneController = TextEditingController();

  RegisterBloc _registerBloc;

  final _formKey = GlobalKey<FormState>();

  @override
  void initState() {
    super.initState();
    _registerBloc = BlocProvider.of<RegisterBloc>(context);
  }

  @override
  Widget build(BuildContext context) {
    return BlocListener<RegisterBloc, RegisterState>(
      listener: (context, state) async {
        if (state is isSubmitting) {
          Scaffold.of(context)
            ..hideCurrentSnackBar()
            ..showSnackBar(
              SnackBar(
                content: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text('Registering...'),
                    CircularProgressIndicator(),
                  ],
                ),
              ),
            );
        }
        if (state is isSuccess) {
          FocusScope.of(context).requestFocus(FocusNode());
          await Future.delayed(Duration(seconds: 3));
          Scaffold.of(context)
            ..hideCurrentSnackBar()
            ..showSnackBar(
              SnackBar(
                content: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text('Register Success'),
                    Icon(Icons.check),
                  ],
                ),
                backgroundColor: Colors.lightBlueAccent,
              ),
            );
          BlocProvider.of<AuthenticationBloc>(context).add(LoggedIn());
          Navigator.of(context).pop();
        }
        if (state is isFailure) {
          await Future.delayed(Duration(seconds: 3));

          Scaffold.of(context)
            ..hideCurrentSnackBar()
            ..showSnackBar(
              SnackBar(
                content: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(state.message),
                    Icon(Icons.error),
                  ],
                ),
                backgroundColor: Colors.red,
              ),
            );
        }
      },
      child: BlocBuilder<RegisterBloc, RegisterState>(
        builder: (context, state) {
          return Padding(
            padding: EdgeInsets.all(40),
            child: Form(
              key: _formKey,
              child: ListView(
                children: <Widget>[
                  Padding(
                    padding: EdgeInsets.symmetric(vertical: 20),
                    child: Image.asset('assets/images/logo.png', height: 200),
                  ),
                  TextFormField(
                    controller: _emailController,
                    decoration: InputDecoration(
                      icon: Icon(
                        Icons.email,
                        color: Colors.lightBlueAccent,
                      ),
                      labelText: 'Email',
                      hintText: "Enter your email",
                      labelStyle: new TextStyle(color: const Color(0xFF424242)),
                    ),
                    keyboardType: TextInputType.emailAddress,
                    autocorrect: false,
                    validator: validateEmail,
                  ),
                  TextFormField(
                    controller: _passwordController,
                    decoration: InputDecoration(
                      icon: Icon(
                        Icons.lock,
                        color: Colors.lightBlueAccent,
                      ),
                      labelText: 'Password',
                    ),
                    obscureText: true,
                    autocorrect: false,
                    validator: validatePassword,
                  ),
                  TextFormField(
                    validator: validateName,
                    keyboardType: TextInputType.text,
                    controller: _nameController,
                    decoration: InputDecoration(
                      icon: Icon(
                        Icons.person,
                        color: Colors.lightBlueAccent,
                      ),
                      labelText: 'Fullname',
                    ),
                    autocorrect: false,
                  ),
                  TextFormField(
                    keyboardType: TextInputType.phone,
                    controller: _phoneController,
                    decoration: InputDecoration(
                      icon: Icon(
                        Icons.phone_android,
                        color: Colors.lightBlueAccent,
                      ),
                      labelText: 'Phone',
                    ),
                    autocorrect: false,
                    validator: validatePhone,
                  ),
                  SizedBox(
                    height: 20,
                  ),
                  RaisedButton(
                    color: Colors.lightBlueAccent,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(30.0),
                    ),
                    onPressed: () {
                      if (_formKey.currentState.validate()) {
                        _formKey.currentState.save();
                        _registerBloc.add(
                          Submitted(
                              email: _emailController.text,
                              password: _passwordController.text,
                              name: _nameController.text,
                              phone: _phoneController.text),
                        );
                      }
                    },
                    child: Text('Register'),
                  )
                ],
              ),
            ),
          );
        },
      ),
    );
  }

  @override
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  String validateEmail(String value) {
    Pattern pattern =
        r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
    RegExp regex = new RegExp(pattern);
    if (!regex.hasMatch(value))
      return 'Enter a valid email';
    else
      return null;
  }

  String validatePassword(String value) {
    if (value.length < 6)
      return 'Minimal length is 6';
    else
      return null;
  }

  String validatePhone(String value) {
    Pattern pattern =
        r'\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{1,14}$';
    RegExp regex = new RegExp(pattern);
    if (!regex.hasMatch(value))
      return 'Enter a valid Phone';
    else
      return null;
  }

  String validateName(String value) {
    if (value.length < 1)
      return 'This field is required';
    else
      return null;
  }
}

register.dart

export './bloc/bloc.dart';
export './register_screen.dart';
export './register_form.dart';

Pada artikel ini kita masih akan menggunakan BLoC. Kita masih belum selesai, sekarang buatlah satu folder bernama bloc didalam folder register dan simpan script dibawah ini didalamnya

bloc.dart

export './bloc/bloc.dart';
export './register_screen.dart';
export './register_form.dart';

register_bloc.dart

class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
  final UserRepository _userRepository;

  RegisterBloc({@required UserRepository userRepository})
      : assert(userRepository != null),
        _userRepository = userRepository;

  @override
  RegisterState get initialState => RegisterInitial();

  @override
  Stream<RegisterState> mapEventToState(
    RegisterEvent event,
  ) async* {
   if (event is Submitted) {
      yield* _mapFormSubmittedToState(
          event.email, event.password, event.name, event.phone);
    }
  }

  Stream<RegisterState> _mapFormSubmittedToState(
      String email, String password, String name, String phone) async* {
    yield isSubmitting();
    try {
     final result = await _userRepository.signUp(
        email: email,
        password: password,
        name: name,
        phone: phone
      );

      yield isSuccess();
    } catch (e) {
      print(e.toString());
      yield isFailure(e.toString());
    }
  }
}

register_event.dart

abstract class RegisterEvent extends Equatable {
  const RegisterEvent();

  @override
  List<Object> get props => [];
}

class Submitted extends RegisterEvent {
  final String email;
  final String password;
  final String name;
  final String phone;

  const Submitted({
    @required this.email,
    @required this.password,
    @required this.name,
    @required this.phone,
  });

  @override
  List<Object> get props => [email, password, name, password];
}

register_state.dart

abstract class RegisterState extends Equatable {
  const RegisterState();

  @override
  List<Object> get props => [];
}

class RegisterInitial extends RegisterState {}

class isSubmitting extends RegisterState {}

class isSuccess extends RegisterState {}

class isFailure extends RegisterState {
  final String message;

  isFailure(this.message);

  @override
  List<Object> get props => [message];
}

Form daftar kita memiliki 4 state, yaitu

  • RegisterInitial => Ketika pertama kali halaman atau form terbuka
  • isSubmitting => Melakukan proses pendaftar
  • isSuccess => Proses pendaftaran berhasil
  • isFailure => Proses pendaftaran gagal

Lalu kita memiliki 1 event yaitu Submitted, event ini jalan ketika kita user menekan tombol Register. Event itu akan menjalankan script dibawah ini

Stream<RegisterState> _mapFormSubmittedToState(
     String email, String password, String name, String phone) async* {
   yield isSubmitting();
   try {
    final result = await _userRepository.signUp(
       email: email,
       password: password,
       name: name,
       phone: phone
     );
     yield isSuccess();
   } catch (e) {
     print(e.toString());
     yield isFailure(e.toString());
   }
 }

Dalam script di atas kita menjalankan proses signUpyang ada di dalam UserRepository. dari proses signUpitu kita akan mendapatkan data berupa json seperti yang kita bahas di atas.

_mapFormSubmittedToState akan mengganti state menjadi isSuccessatau isFailuretergantung dari proses diatas.

user_repository.dart

simpan file user_repositiry.dart sejajar dengan main.dart

class UserRepository {
  Future<void> signUp(
      {String email, String password, String name, String phone}) async {
    var result =
        await http.post(Configuration.url + 'Api/register_user', body: {
      'email': email,
      'password': password,
      'name': name,
      'phone': phone,
    });

    var datauser = json.decode(result.body);
    User user;
    if (datauser['status'] == 0 || datauser['status'] == 2) {
      throw (datauser['message']); // error thrown
    } else {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      prefs.setString('name', datauser['user']["name"]);
      prefs.setString('phone', datauser['user']["phone"]);
      prefs.setString('email', datauser['user']["email"]);
      prefs.setString('imageFileName', datauser['user']["imageFileName"]);
      user = new User(
          fullName: name,
          phone: phone,
          email: email,
          active: 0,
          imageFileName: "");
    }
    return user;
  }

  Future<void> logIn({String email, String password}) async {
    var result = await http.post(Configuration.url + 'Api/login_user',
        body: {'email': email, 'password': password});

    var datauser = json.decode(result.body);
    User user;
    if (datauser['status'] == 0 || datauser['status'] == 2) {
      throw ("Woopsy"); // error thrown
    } else {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      prefs.setString('name', datauser['user']["name"]);
      prefs.setString('phone', datauser['user']["phone"]);
      prefs.setString('email', datauser['user']["email"]);
      prefs.setString('imageFileName', datauser['user']["imageFileName"]);
      user = new User(
          fullName: datauser['user']["name"],
          phone: datauser['user']["phone"],
          email: email,
          active: 0,
          imageFileName: "");
    }
    return user;
  }

  Future<void> deleteSession() async {
    SharedPreferences preferences = await SharedPreferences.getInstance();
    preferences.clear();
    return;
  }

  Future<User> getUser() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    User user = new User(
      fullName: prefs.getString("name"),
      phone: prefs.getString("phone"),
      email: prefs.getString("email"),
      active: prefs.getInt("active"),
      imageFileName: prefs.getString("imageFileName"),
    );
    return user;
  }
}

main.dart

void main() {
  final userRepository = UserRepository();
  runApp(
    BlocProvider<AuthenticationBloc>(
      create: (context) {
        return AuthenticationBloc(userRepository: userRepository)
          ..add(AppStarted());
      },
      child: MyApp(userRepository: userRepository),
    ),
  );
}

class MyApp extends StatelessWidget {
  final UserRepository userRepository;

  MyApp({Key key, @required this.userRepository}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Register dan Login dengan BLoC',
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
        textTheme: GoogleFonts.latoTextTheme(
          Theme.of(context).textTheme,
        ),
      ),
      home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
        builder: (context, state) {
          if (state is Authenticated) {
            return Scaffold(
              body: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text("Login berhasil"),
                    FlatButton(
                      color: Colors.red,
                      child: Text("Logout"),
                      onPressed: (){
                        BlocProvider.of<AuthenticationBloc>(context).add(
                          LoggedOut(),
                        );
                      },
                    ),
                  ],
                ),
              ),
            );
          }
          if (state is Unauthenticated) {
            return LoginScreen(userRepository: userRepository);
          }
          if (state is Uninitialized) {
            return CircularProgressIndicator();
          }
          return SplashScreen();
        },
      ),
    );
  }
}

class Configuration {
  static String url = "http://10.0.2.2/web_api/";
}

Kami menggunakan AuthenticationBloc sebagai pengatur untuk file main.dart dalam kata lain disinilah kita melakukan pengecekan login atau tidak nya si user.

sekarang buatlah folder bernama authentication, kemudian simpan script dibawah ini

authentication_bloc.dart

class AuthenticationBloc
    extends Bloc<AuthenticationEvent, AuthenticationState> {
  final UserRepository userRepository;

  AuthenticationBloc({@required this.userRepository})
      : assert(userRepository != null);

  @override
  AuthenticationState get initialState => Uninitialized();

  @override
  Stream<AuthenticationState> mapEventToState(
    AuthenticationEvent event,
  ) async* {
    if (event is AppStarted) {
      User user = await userRepository.getUser();
      if (user.email != null) {
        yield Authenticated(user);
      } else {
        yield Unauthenticated();
      }
    }

    if (event is LoggedIn) {
      User user = await userRepository.getUser();
      yield Authenticated(user);
    }

    if (event is LoggedOut) {
//      yield AuthenticationLoading();
      await userRepository.deleteSession();
      yield Unauthenticated();
    }
  }
}

authentication_event.dart

abstract class AuthenticationEvent{
  const AuthenticationEvent();

  @override
  List<Object> get props => [];
}

class AppStarted extends AuthenticationEvent {}

class LoggedIn extends AuthenticationEvent {
  final String token;

  const LoggedIn({@required this.token});

  @override
  List<Object> get props => [token];

  @override
  String toString() => 'LoggedIn { token: $token }';
}

class LoggedOut extends AuthenticationEvent {}

authentication_state.dart

abstract class AuthenticationState {
  const AuthenticationState();

  @override
  List<Object> get props => [];
}

class Uninitialized extends AuthenticationState {}

class Authenticated extends AuthenticationState {
  final User user;

  const Authenticated(this.user);

  @override
  List<Object> get props => [user];
}

class Unauthenticated extends AuthenticationState {}

Tutorial Flutter Form Login dengan BLoC

Setelah Form daftar selesai sekarang kita akan membuat form untuk login nya. Kita akan menggunakan email dan password untuk login. Pertama buat folder login lalu simpan script-script dibawah ini

login_screen.dart

class LoginScreen extends StatelessWidget {
  final UserRepository _userRepository;

  LoginScreen({Key key, @required UserRepository userRepository})
      : assert(userRepository != null),
        _userRepository = userRepository,
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body:  SafeArea(
        child: BlocProvider<LoginBloc>(
            create: (context) => LoginBloc(userRepository: _userRepository),
            child: Container(

              child: LoginForm(userRepository: _userRepository),
            )
        ),
      ),
    );
  }
}

login_form.dart

class LoginForm extends StatefulWidget {
  final UserRepository _userRepository;

  LoginForm({Key key, @required UserRepository userRepository})
      : assert(userRepository != null),
        _userRepository = userRepository,
        super(key: key);

  State<LoginForm> createState() => _LoginFormState();
}

class _LoginFormState extends State<LoginForm> {
  final TextEditingController _emailController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  LoginBloc _loginBloc;

  UserRepository get _userRepository => widget._userRepository;

  bool get isPopulated =>
      _emailController.text.isNotEmpty && _passwordController.text.isNotEmpty;

  final _formKey = GlobalKey<FormState>();

  @override
  void initState() {
    super.initState();
    _loginBloc = BlocProvider.of<LoginBloc>(context);
  }

  @override
  Widget build(BuildContext context) {
    return BlocListener<LoginBloc, LoginState>(
      listener: (context, state) async {
        if (state is isFailure) {
          Scaffold.of(context)
            ..hideCurrentSnackBar()
            ..showSnackBar(
              SnackBar(
                content: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [Text('Login Failure'), Icon(Icons.error)],
                ),
                backgroundColor: Colors.red,
              ),
            );
        }
        if (state is isSubmitting) {
          Scaffold.of(context)
            ..hideCurrentSnackBar()
            ..showSnackBar(
              SnackBar(
                content: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text('Logging In...'),
                    CircularProgressIndicator(),
                  ],
                ),
              ),
            );
        }
        if (state is isSuccess) {
          FocusScope.of(context).requestFocus(FocusNode());

          await Future.delayed(Duration(seconds: 3));

          BlocProvider.of<AuthenticationBloc>(context).add(LoggedIn());
        }
      },
      child: BlocBuilder<LoginBloc, LoginState>(
        builder: (context, state) {
          return Padding(
            padding: EdgeInsets.all(40.0),
            child: Form(
              key: _formKey,
              child: ListView(
                children: <Widget>[
                  Padding(
                    padding: EdgeInsets.symmetric(vertical: 20),
                    child: Image.asset('assets/images/logo.png', height: 200),
                  ),
                  TextFormField(
                      controller: _emailController,
                      decoration: InputDecoration(
                        icon: Icon(
                          Icons.email,
                          color: Colors.lightBlueAccent,
                        ),
                        labelText: 'Email',
                      ),
                      keyboardType: TextInputType.emailAddress,
                      autocorrect: false,
                      validator: validateEmail),
                  TextFormField(
                      controller: _passwordController,
                      decoration: InputDecoration(
                        icon: Icon(
                          Icons.lock,
                          color: Colors.lightBlueAccent,
                        ),
                        labelText: 'Password',
                      ),
                      obscureText: true,
                      autocorrect: false,
                      validator: validatePassword),
                  SizedBox(
                    height: 20,
                  ),
                  Padding(
                    padding: EdgeInsets.symmetric(vertical: 20),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: <Widget>[
                        RaisedButton(
                          color: Colors.lightBlueAccent,

                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(30.0),
                          ),
                          onPressed: () {
                            if (_formKey.currentState.validate()) {
                              _formKey.currentState.save();
                              _loginBloc.add(
                                Submitted(
                                    email: _emailController.text,
                                    password: _passwordController.text),
                              );
                            }
                          },
                          child: Text('Login'),
                        ),
                        FlatButton(
                          child: Text(
                            'Create an Account',
                          ),
                          onPressed: () {
                            Navigator.of(context).push(
                              MaterialPageRoute(builder: (context) {
                                return RegisterScreen(
                                    userRepository: _userRepository);
                              }),
                            );
                          },
                        )
                      ],
                    ),
                  ),
                ],
              ),
            ),
          );
        },
      ),
    );
  }

  String validateEmail(String value) {
    Pattern pattern =
        r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
    RegExp regex = new RegExp(pattern);
    if (!regex.hasMatch(value))
      return 'Enter a valid email';
    else
      return null;
  }

  String validatePassword(String value) {
    if (value.length < 6)
      return 'Minimal length is 6';
    else
      return null;
  }

  @override
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }
}

login.dart

export './bloc/bloc.dart';
export './login_form.dart';
export './login_screen.dart';

Kemudian buat file bernama bloc didalam folder login, lalu simpan sciprt-script dibawah ini

login_bloc.dart

class LoginBloc extends Bloc<LoginEvent, LoginState> {
  UserRepository _userRepository;

  LoginBloc({
    @required UserRepository userRepository,
  })  : assert(userRepository != null),
        _userRepository = userRepository;

  @override
  LoginState get initialState => LoginInitial();


  @override
  Stream<LoginState> mapEventToState(LoginEvent event) async* {
    if (event is Submitted) {
      yield* _mapLoginWithCredentialsPressedToState(
        email: event.email,
        password: event.password,
      );
    }
  }
  Stream<LoginState> _mapLoginWithCredentialsPressedToState({
    String email,
    String password,
  }) async* {
    yield isSubmitting();
    try {
     await _userRepository.logIn(email : email,password: password);
      yield isSuccess();
    } catch (e) {
      yield isFailure(e);
    }
  }
}

login_event.dart

abstract class LoginEvent extends Equatable {
  const LoginEvent();

  @override
  List<Object> get props => [];
}


class Submitted extends LoginEvent {
  final String email;
  final String password;

  const Submitted({
    @required this.email,
    @required this.password,
  });

  @override
  List<Object> get props => [email, password];

  @override
  String toString() {
    return 'Submitted { email: $email, password: $password }';
  }
}

login_state.dart

abstract class LoginState extends Equatable {
  const LoginState();

  @override
  List<Object> get props => [];
}

class LoginInitial extends LoginState {}

class isSubmitting extends LoginState {}

class isSuccess extends LoginState {}

class isFailure extends LoginState {
  final String message;

  isFailure(this.message);

  @override
  List<Object> get props => [message];
}

konsepnya hampir sama dengan form daftar,

Untuk Login sini kita juga menggunakan api. Kita hanya mengirimkan 2 parameter yaitu email dan password.

post login

Jika login sukses

{
    "status": 1,
    "message": "Success",
    "user": {
        "id": "17",
        "email": "boby12kurniawan@gmail.com",
        "password": "e10adc3949ba59abbe56e057f20f883e",
        "name": "Boby",
        "phone": "+6289688965164",
        "imageFileName": "",
        "active": "1"
    }
}

Jika login gagal karena salah email atau password

{
    "status": 0,
    "message": "Incorrect email or password"
}

jika ada error karena kesalahan di table atau database

{
    "status": 2,
    "message": "Something went wrong"
}

Sekian artikel tentang Tutorial Flutter Form Login dan Daftar dengan BLoC, semoga bermanfaat

Tinggalkan Balasan

Subscribe To Our Newsletter

Subscribe To Our Newsletter

Kami memberikan tutorial baru tiap harinya !!!

You have Successfully Subscribed!

%d blogger menyukai ini: