diff --git a/lib/core/res/strings.dart b/lib/core/res/strings.dart index fd01dde..5b14437 100644 --- a/lib/core/res/strings.dart +++ b/lib/core/res/strings.dart @@ -19,4 +19,5 @@ class S { static const String networkException = "Request couldn't be completed. Make sure the device is online"; static const String unknownException = "Something went wrong. Please try again later."; + static const String wrongOtp = "Wrong OTP entered"; } diff --git a/lib/screens/change_number/change_number.dart b/lib/screens/change_number/change_number.dart new file mode 100644 index 0000000..9f541f9 --- /dev/null +++ b/lib/screens/change_number/change_number.dart @@ -0,0 +1,90 @@ +import 'package:ecellapp/screens/change_number/cubit/change_number_cubit.dart'; +import 'package:ecellapp/screens/change_number/widgets/mobile_number_field.dart'; +import 'package:ecellapp/screens/change_number/widgets/otp_field.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class ChangeNumberScreen extends StatelessWidget { + final TextEditingController mobileController = TextEditingController(); + final TextEditingController otpController = TextEditingController(); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: BlocConsumer( + listener: (context, state) { + if (state is ChangeNumberError) { + Scaffold.of(context).showSnackBar( + SnackBar(content: Text(state.error)), + ); + } else if (state is ChangeNumberWrongOtp) { + Scaffold.of(context).showSnackBar( + SnackBar(content: Text(state.error)), + ); + } else if (state is ChangeNumberOtpSuccessful) { + Scaffold.of(context).showSnackBar( + SnackBar(content: Text("Successful")), + ); + } + }, + builder: (context, state) { + if (state is ChangeNumberInitial) { + return _initial(context); + } else if (state is ChangeNumberOTP) { + return _enterOtp(context); + } else if (state is ChangeNumberOtpSuccessful) { + /// + return _success(); + } else { + return _initial(context); + } + }, + ), + ); + } + + Widget _initial(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(50.0), + child: Column( + children: [ + MobileNumberField(mobileController), + FlatButton( + onPressed: () { + final cubit = context.read(); + cubit.getOtp(mobileController.text); + }, + child: Text("Get otp")), + ], + ), + ); + } + + Widget _enterOtp(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(50.0), + child: Column( + children: [ + OtpField(otpController), + FlatButton( + onPressed: () { + final cubit = context.read(); + cubit.verifyOtp(otpController.text); + }, + child: Text("verify"), + ), + ], + ), + ); + } + + Widget _success() { + return Padding( + padding: const EdgeInsets.all(50.0), + child: Column( + children: [Text("Success")], + ), + ); + } +} diff --git a/lib/screens/change_number/change_number_repository.dart b/lib/screens/change_number/change_number_repository.dart new file mode 100644 index 0000000..1911852 --- /dev/null +++ b/lib/screens/change_number/change_number_repository.dart @@ -0,0 +1,33 @@ +import 'dart:math'; + +import 'package:ecellapp/core/res/errors.dart'; + +abstract class ChangeNumberRepository { + Future getOtp(String number); +} + +class FakeChangeNumberRepository extends ChangeNumberRepository { + String generated; + + @override + Future getOtp(String number) async { + await Future.delayed(Duration(seconds: 1)); + if (Random().nextBool()) { + //print("Fail"); + // Represents a network failure + throw NetworkException(); + } else { + generated = '1234'; + // returns a dummy otp + } + } + + Future verifyOtp(String sent) async { + await Future.delayed(Duration(seconds: 1)); + if (sent == generated) { + return 200; + } else { + throw ValidationException("Wrong OTP has been entered"); + } + } +} diff --git a/lib/screens/change_number/cubit/change_number_cubit.dart b/lib/screens/change_number/cubit/change_number_cubit.dart new file mode 100644 index 0000000..1eab519 --- /dev/null +++ b/lib/screens/change_number/cubit/change_number_cubit.dart @@ -0,0 +1,33 @@ +import 'package:bloc/bloc.dart'; +import 'package:ecellapp/core/res/errors.dart'; +import 'package:ecellapp/screens/change_number/change_number_repository.dart'; +import 'package:meta/meta.dart'; +import 'package:ecellapp/core/res/strings.dart'; + +part 'change_number_state.dart'; + +class ChangeNumberCubit extends Cubit { + FakeChangeNumberRepository _changeNumberRepository = FakeChangeNumberRepository(); + + ChangeNumberCubit() : super(ChangeNumberInitial()); + + Future getOtp(String number) async { + try { + await _changeNumberRepository.getOtp(number); + emit(ChangeNumberOTP()); + } on NetworkException { + emit(ChangeNumberError(S.unknownException)); + } + } + + Future verifyOtp(String otp) async { + try { + int x = await _changeNumberRepository.verifyOtp(otp); + if (x == 200) { + emit(ChangeNumberOtpSuccessful()); + } + } on ValidationException { + emit(ChangeNumberError(S.wrongOtp)); + } + } +} diff --git a/lib/screens/change_number/cubit/change_number_state.dart b/lib/screens/change_number/cubit/change_number_state.dart new file mode 100644 index 0000000..2dbf7de --- /dev/null +++ b/lib/screens/change_number/cubit/change_number_state.dart @@ -0,0 +1,24 @@ +part of 'change_number_cubit.dart'; + +@immutable +abstract class ChangeNumberState { + const ChangeNumberState(); +} + +class ChangeNumberInitial extends ChangeNumberState {} + +class ChangeNumberOTP extends ChangeNumberState {} + +class ChangeNumberError extends ChangeNumberState { + final String error; + + ChangeNumberError(this.error); +} + +class ChangeNumberWrongOtp extends ChangeNumberState { + final String error; + + ChangeNumberWrongOtp(this.error); +} + +class ChangeNumberOtpSuccessful extends ChangeNumberState {} diff --git a/lib/screens/change_number/widgets/mobile_number_field.dart b/lib/screens/change_number/widgets/mobile_number_field.dart new file mode 100644 index 0000000..79ceb14 --- /dev/null +++ b/lib/screens/change_number/widgets/mobile_number_field.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +class MobileNumberField extends StatelessWidget { + const MobileNumberField(this.controller); + + final TextEditingController controller; + + @override + Widget build(BuildContext context) { + return TextFormField( + controller: controller, + keyboardType: TextInputType.number, + decoration: InputDecoration( + suffixText: '*', + suffixStyle: TextStyle(color: Colors.red, fontSize: 20), + prefixIcon: Icon(Icons.phone), + border: OutlineInputBorder(), + labelText: "Mobile Number", + ), + ); + } +} diff --git a/lib/screens/change_number/widgets/otp_field.dart b/lib/screens/change_number/widgets/otp_field.dart new file mode 100644 index 0000000..40d28c1 --- /dev/null +++ b/lib/screens/change_number/widgets/otp_field.dart @@ -0,0 +1,15 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class OtpField extends StatelessWidget { + final TextEditingController controller; + + OtpField(this.controller); + + @override + Widget build(BuildContext context) { + return TextField( + controller: controller, + ); + } +} diff --git a/lib/screens/signup/cubit/signup_state.dart b/lib/screens/signup/cubit/signup_state.dart index c8bf387..727f4f2 100644 --- a/lib/screens/signup/cubit/signup_state.dart +++ b/lib/screens/signup/cubit/signup_state.dart @@ -3,6 +3,7 @@ part of 'signup_cubit.dart'; @immutable abstract class SignupState extends Equatable { const SignupState(); + @override List get props => []; } @@ -21,7 +22,9 @@ class SignupSuccess extends SignupState { class SignupError extends SignupState { final String message; + const SignupError(this.message); + @override List get props => [message]; }