diff --git a/app/src/main/java/com/woka/onboard/fragments/GetCodeFragment.kt b/app/src/main/java/com/woka/onboard/fragments/GetCodeFragment.kt index 044ade4..d988a5e 100644 --- a/app/src/main/java/com/woka/onboard/fragments/GetCodeFragment.kt +++ b/app/src/main/java/com/woka/onboard/fragments/GetCodeFragment.kt @@ -83,24 +83,53 @@ class GetCodeFragment : Fragment() { super.onViewCreated(view, savedInstanceState) // observing live data - viewModel.sendOTPLiveData.observe(viewLifecycleOwner){ - when(it){ + viewModel.sendOTPLiveData.observe(viewLifecycleOwner) { + when (it) { is ApiResult.Error -> { progressView.hide() Toast.makeText(activity, "${it.errorMessage}", Toast.LENGTH_SHORT).show() } + is ApiResult.Loading -> { progressView.show(getString(R.string.sending_otp)) } + is ApiResult.Success -> { viewModel.startOTPTimeCountDown() - Toast.makeText(activity, - getString(R.string.otp_sent_successfully), Toast.LENGTH_SHORT).show() + Toast.makeText( + activity, + "${it.message}", Toast.LENGTH_SHORT + ).show() progressView.hide() - uniqueString = it.data?.unique_string?:"" + uniqueString = it.data?.unique_string ?: "" viewModel.clearSendOTPData() } + + null -> {} + } + } + + // observing live data + viewModel.forgotPwdOTPLiveData.observe(viewLifecycleOwner) { + when (it) { + is ApiResult.Error -> { + progressView.hide() + Toast.makeText(activity, "${it.errorMessage}", Toast.LENGTH_SHORT).show() + } + + is ApiResult.Loading -> { + progressView.show(getString(R.string.sending_otp)) + } + + is ApiResult.Success -> { + viewModel.startOTPTimeCountDown() + Toast.makeText(activity, "${it.message}", Toast.LENGTH_SHORT).show() + progressView.hide() + + viewModel.clearForgotPwdSendOTPData() + } + null -> {} } } @@ -111,32 +140,28 @@ class GetCodeFragment : Fragment() { progressView.hide() Toast.makeText(activity, "${it.errorMessage}", Toast.LENGTH_SHORT).show() } + is ApiResult.Loading -> { progressView.show(getString(R.string.validating_otp)) } + is ApiResult.Success -> { // OTP validation successful - if (isResetPasswordIntent){ - progressView.hide() - Toast.makeText(activity, - getString(R.string.otp_validation_successful), Toast.LENGTH_SHORT) - .show() - findNavController().navigate(R.id.action_getCodeFragment_to_newPasswordFragment2) - }else if (!isUnder16){ + if (!isUnder16) { // parent type lifecycleScope.launch { val listOfChild = viewModel.getChildList(email) progressView.hide() - Toast.makeText(activity, getString(R.string.otp_validation_successful), Toast.LENGTH_SHORT) + Toast.makeText(activity, "${it.message}", Toast.LENGTH_SHORT) .show() - if (listOfChild is ApiResult.Error){ - if (listOfChild.error is NoSuccessError){ + if (listOfChild is ApiResult.Error) { + if (listOfChild.error is NoSuccessError) { // no child list found gotoSignUpFragment() - }else{ + } else { // some other error happened Toast.makeText( activity, @@ -144,7 +169,7 @@ class GetCodeFragment : Fragment() { Toast.LENGTH_SHORT ).show() } - }else if (listOfChild is ApiResult.Success && listOfChild.data?.result != null){ + } else if (listOfChild is ApiResult.Success && listOfChild.data?.result != null) { // child list is available viewModel.childList = listOfChild.data.result val args = Bundle().apply { @@ -156,14 +181,14 @@ class GetCodeFragment : Fragment() { R.id.action_getCodeFragment_to_childListFragment, args ) - }else{ + } else { gotoSignUpFragment() } } - }else{ + } else { // child type progressView.hide() - Toast.makeText(activity, getString(R.string.otp_validation_successful), Toast.LENGTH_SHORT) + Toast.makeText(activity, "${it.message}", Toast.LENGTH_SHORT) .show() gotoSignUpFragment() @@ -174,19 +199,50 @@ class GetCodeFragment : Fragment() { } } - viewModel.otpResendTimeLiveData.observe(viewLifecycleOwner){ - if (it == 0L){ + viewModel.verifyForgotPwdOTPLiveData.observe(viewLifecycleOwner) { + when (it) { + is ApiResult.Error -> { + progressView.hide() + Toast.makeText(activity, "${it.errorMessage}", Toast.LENGTH_SHORT).show() + } + + is ApiResult.Loading -> { + progressView.show() + } + + is ApiResult.Success -> { + progressView.hide() + Toast.makeText( + activity, + "${it.message}", Toast.LENGTH_SHORT + ) + .show() + + findNavController().navigate(R.id.action_getCodeFragment_to_newPasswordFragment2, + Bundle().apply + { + putString(EMAIL_ARG, email) + }) + } + + null -> {} + } + } + + viewModel.otpResendTimeLiveData.observe(viewLifecycleOwner) { + if (it == 0L) { // no time is ticking binding.countdown.visibility = GONE binding.resend.visibility = VISIBLE - }else{ + } else { // time is ticking binding.countdown.visibility = VISIBLE binding.resend.visibility = GONE - val rms = (it)/1000 // remaining time in second - val time = "%02d:%02d".format(rms/60, rms%60) - val text = "${getString(R.string.otp_is_valid_for)} $time ${getString(R.string.min)}" + val rms = (it) / 1000 // remaining time in second + val time = "%02d:%02d".format(rms / 60, rms % 60) + val text = + "${getString(R.string.otp_is_valid_for)} $time ${getString(R.string.min)}" Log.d("aditya_testing", "onTick: $it") binding.countdown.text = text } @@ -197,6 +253,9 @@ class GetCodeFragment : Fragment() { super.onDestroyView() viewModel.clearValidateOTP() viewModel.clearSendOTPData() + + viewModel.clearForgotPwdSendOTPData() + viewModel.clearVerifyForgotPwdOTP() } private fun initViews() { @@ -249,20 +308,28 @@ class GetCodeFragment : Fragment() { } next.setOnClickListener { - viewModel.validateOTP(uniqueString, getOTP()) + val otp = getOTP() ?: return@setOnClickListener + + if (isResetPasswordIntent) { + viewModel.verifyForgotPwdOTP(email, otp) + } else { + viewModel.validateOTP(uniqueString, otp) + } } resend.setOnClickListener { - if (!isUnder16){ + if (isResetPasswordIntent) { + viewModel.forgotPwdSendOTP(email) + } else if (!isUnder16) { viewModel.sendOTP(email, PARENT_TYPE) - }else{ + } else { viewModel.sendOTP(email, CHILD_TYPE) } } } } - private fun gotoSignUpFragment(){ + private fun gotoSignUpFragment() { val args = Bundle().apply { putBoolean(IS_UNDER_16, isUnder16) putString(EMAIL_ARG, email) @@ -274,8 +341,15 @@ class GetCodeFragment : Fragment() { ) } - private fun getOTP(): String { + private fun getOTP(): String? { binding.apply { + if (et1.text.isEmpty() || et2.text.isEmpty() || et3.text.isEmpty() || et4.text.isEmpty()) { + Toast.makeText( + activity, + getString(R.string.please_enter_otp_code), Toast.LENGTH_SHORT + ).show() + return null + } return "${et1.text}${et2.text}${et3.text}${et4.text}" } } diff --git a/app/src/main/java/com/woka/onboard/fragments/GetEmailFragment.kt b/app/src/main/java/com/woka/onboard/fragments/GetEmailFragment.kt index 0b19817..3e644e9 100644 --- a/app/src/main/java/com/woka/onboard/fragments/GetEmailFragment.kt +++ b/app/src/main/java/com/woka/onboard/fragments/GetEmailFragment.kt @@ -111,21 +111,40 @@ class GetEmailFragment : Fragment() { viewModel.email = binding.email.text.toString() - val args = if (isResetPasswordIntent) { - Bundle().apply { - putBoolean(IS_RESET_PASSWORD_INTENT, isResetPasswordIntent) - } - } else { + findNavController().navigate( + R.id.action_getEmailFragment_to_getCodeFragment, Bundle().apply { putBoolean(IS_UNDER_16, isUnder16) putString(UNIQUE_STRING_ARG, it.data?.unique_string) putString(EMAIL_ARG, binding.email.text.toString()) } - } + ) + } + + null -> {} + } + } + + viewModel.forgotPwdOTPLiveData.observe(viewLifecycleOwner) { + when (it) { + is ApiResult.Error -> { + progressView.hide() + Toast.makeText(activity, "${it.errorMessage}", Toast.LENGTH_SHORT).show() + } + + is ApiResult.Loading -> { + progressView.show(title = getString(R.string.sending_otp)) + } + + is ApiResult.Success -> { + progressView.hide() findNavController().navigate( R.id.action_getEmailFragment_to_getCodeFragment, - args + Bundle().apply { + putBoolean(IS_RESET_PASSWORD_INTENT, isResetPasswordIntent) + putString(EMAIL_ARG, binding.email.text.toString()) + } ) } @@ -138,6 +157,8 @@ class GetEmailFragment : Fragment() { super.onDestroyView() // removing values from live data for a fresh data when new instance is created viewModel.clearCheckEmailExist() + viewModel.clearForgotPwdSendOTPData() + viewModel.clearSendOTPData() } private fun initViews() { @@ -166,12 +187,24 @@ class GetEmailFragment : Fragment() { binding.next.setOnClickListener { binding.email.error = null - if (!Patterns.EMAIL_ADDRESS.matcher(binding.email.text.toString()).matches()) { - binding.email.error = "Invalid email" - return@setOnClickListener + if (isResetPasswordIntent){ + // username check + if (binding.email.text.isEmpty()){ + binding.email.error = getString(R.string.username_required) + return@setOnClickListener + } + }else{ + // email check + if (!Patterns.EMAIL_ADDRESS.matcher(binding.email.text.toString()).matches()) { + binding.email.error = getString(R.string.invalid_email) + return@setOnClickListener + } } - if (!isUnder16) { + if (isResetPasswordIntent){ + // we are taking username from the same input box of email + viewModel.forgotPwdSendOTP(binding.email.text.toString()) + } else if (!isUnder16) { // parent viewModel.checkEmailExist(binding.email.text.toString(), PARENT_TYPE) } else { diff --git a/app/src/main/java/com/woka/onboard/fragments/GetMoreInfoFragment.kt b/app/src/main/java/com/woka/onboard/fragments/GetMoreInfoFragment.kt index 2af78dd..f92a65e 100644 --- a/app/src/main/java/com/woka/onboard/fragments/GetMoreInfoFragment.kt +++ b/app/src/main/java/com/woka/onboard/fragments/GetMoreInfoFragment.kt @@ -91,7 +91,7 @@ class GetMoreInfoFragment : Fragment() { Toast.makeText(activity, getString(R.string.select_a_gender), Toast.LENGTH_SHORT).show() return@setOnClickListener } - if (viewModel.interestTopics.isEmpty()){ + if (isUnder16 && viewModel.interestTopics.isEmpty()){ Toast.makeText(activity, getString(R.string.please_select_your_interests), Toast.LENGTH_SHORT).show() return@setOnClickListener diff --git a/app/src/main/java/com/woka/onboard/fragments/NewPasswordFragment.kt b/app/src/main/java/com/woka/onboard/fragments/NewPasswordFragment.kt index 677f5c9..3dee8c1 100644 --- a/app/src/main/java/com/woka/onboard/fragments/NewPasswordFragment.kt +++ b/app/src/main/java/com/woka/onboard/fragments/NewPasswordFragment.kt @@ -5,27 +5,113 @@ import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast +import androidx.lifecycle.ViewModelProvider +import androidx.navigation.fragment.findNavController import com.woka.R import com.woka.databinding.FragmentNewPasswordBinding +import com.woka.networking.ApiResult +import com.woka.onboard.fragments.GetCodeFragment.Companion.EMAIL_ARG +import com.woka.onboard.mvvm.OnboardViewModel +import com.woka.utils.ProgressView class NewPasswordFragment : Fragment() { private lateinit var binding: FragmentNewPasswordBinding + + private lateinit var viewModel: OnboardViewModel + + private lateinit var progressView: ProgressView + + private var username: String = "" + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + arguments?.let { + username = it.getString(EMAIL_ARG, "") + } + } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { binding = FragmentNewPasswordBinding.inflate(inflater, container, false) + activity?.let { + viewModel = ViewModelProvider(it)[OnboardViewModel::class.java] + progressView = ProgressView(it, getString(R.string.please_wait)) + } + clickEvents() return binding.root } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + viewModel.updatePasswordLiveData.observe(viewLifecycleOwner){ + when(it){ + is ApiResult.Error -> { + progressView.hide() + Toast.makeText(activity, "${it.errorMessage}", Toast.LENGTH_SHORT).show() + } + is ApiResult.Loading -> { + progressView.show() + } + is ApiResult.Success -> { + progressView.hide() + Toast.makeText(activity, "${it.message}", Toast.LENGTH_SHORT).show() + findNavController().popBackStack(R.id.signInFragment, false) + } + null -> {} + } + } + } + + override fun onDestroyView() { + super.onDestroyView() + viewModel.clearUpdatePasswordLiveData() + } + private fun clickEvents() { binding.apply { backBtn.setOnClickListener { activity?.onBackPressedDispatcher?.onBackPressed() } + + next.setOnClickListener { + if (allOkay()){ + password.text?.toString()?.let { pwdTxt -> + confirmPassword.text?.toString()?.let { cPwd -> + viewModel.updatePassword(username, pwdTxt, cPwd) + } + } + } + } } } + + private fun allOkay(): Boolean { + var allOkay = true + + binding.apply { + password.text?.let { pwdTxt -> + if (pwdTxt.length < 6){ + allOkay = false + Toast.makeText(activity, + getString(R.string.must_be_at_least_6_characters), Toast.LENGTH_SHORT).show() + }else { + // password is valid + confirmPassword.text?.let {confirmPwdTxt -> + if (confirmPwdTxt.toString() != pwdTxt.toString()){ + allOkay = false + Toast.makeText(activity, + getString(R.string.password_does_not_match), Toast.LENGTH_SHORT).show() + } + } + } + } + } + + return allOkay + } } \ No newline at end of file diff --git a/app/src/main/java/com/woka/onboard/fragments/SignInFragment.kt b/app/src/main/java/com/woka/onboard/fragments/SignInFragment.kt index b420e09..f525bf7 100644 --- a/app/src/main/java/com/woka/onboard/fragments/SignInFragment.kt +++ b/app/src/main/java/com/woka/onboard/fragments/SignInFragment.kt @@ -128,13 +128,14 @@ class SignInFragment : Fragment() { login.setOnClickListener { if (username.text.isEmpty()){ - username.error = "Username required" + username.error = getString(R.string.username_required) return@setOnClickListener } password.text?.let { password -> if (password.length < 6){ - Toast.makeText(activity, "Password must be at least 6 characters", Toast.LENGTH_SHORT).show() + Toast.makeText(activity, + getString(R.string.password_must_be_at_least_6_characters), Toast.LENGTH_SHORT).show() return@setOnClickListener } diff --git a/app/src/main/java/com/woka/onboard/fragments/SignUpFragment.kt b/app/src/main/java/com/woka/onboard/fragments/SignUpFragment.kt index 0abc3c1..647c3bc 100644 --- a/app/src/main/java/com/woka/onboard/fragments/SignUpFragment.kt +++ b/app/src/main/java/com/woka/onboard/fragments/SignUpFragment.kt @@ -135,19 +135,19 @@ class SignUpFragment : Fragment() { binding.apply { if (username.text.length < 2) { allOkay = false - username.error = "Must be at least 3 characters" + username.error = getString(R.string.must_be_at_least_3_characters) } if (name.text.trim().isEmpty()) { allOkay = false - name.error = "Required" + name.error = getString(R.string.required) } if (password.text != null && password.text!!.length < 6) { allOkay = false Toast.makeText( activity, - "Password must be at least 6 characters", + getString(R.string.password_must_be_at_least_6_characters), Toast.LENGTH_SHORT ).show() } diff --git a/app/src/main/java/com/woka/onboard/mvvm/OnboardApiService.kt b/app/src/main/java/com/woka/onboard/mvvm/OnboardApiService.kt index 7018145..e4a5d21 100644 --- a/app/src/main/java/com/woka/onboard/mvvm/OnboardApiService.kt +++ b/app/src/main/java/com/woka/onboard/mvvm/OnboardApiService.kt @@ -50,4 +50,10 @@ interface OnboardApiService { @POST("forgot_password_send_otp") suspend fun forgotPasswordSendOTP(@Body body: FormBody): Response> + @POST("forgot_password_verify_otp") + suspend fun verifyForgetPwdOTP(@Body body: FormBody): Response> + + @POST("update_password") + suspend fun updatePassword(@Body body: FormBody): Response> + } \ No newline at end of file diff --git a/app/src/main/java/com/woka/onboard/mvvm/OnboardRepository.kt b/app/src/main/java/com/woka/onboard/mvvm/OnboardRepository.kt index fcd37b4..b882327 100644 --- a/app/src/main/java/com/woka/onboard/mvvm/OnboardRepository.kt +++ b/app/src/main/java/com/woka/onboard/mvvm/OnboardRepository.kt @@ -125,4 +125,27 @@ class OnboardRepository(private val apiService: OnboardApiService) { } } + suspend fun verifyForgotPwdOTP(userName: String, otp: String): ApiResult{ + return handleApiCall { + apiService.verifyForgetPwdOTP( + FormBody.Builder() + .add("username", userName) + .add("otp", otp) + .build() + ) + } + } + + suspend fun updatePassword(userName: String, password: String, confirmPwd: String): ApiResult{ + return handleApiCall { + apiService.updatePassword( + FormBody.Builder() + .add("username", userName) + .add("password", password) + .add("password_confirmation", confirmPwd) + .build() + ) + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/woka/onboard/mvvm/OnboardViewModel.kt b/app/src/main/java/com/woka/onboard/mvvm/OnboardViewModel.kt index dafd4fa..c1e4043 100644 --- a/app/src/main/java/com/woka/onboard/mvvm/OnboardViewModel.kt +++ b/app/src/main/java/com/woka/onboard/mvvm/OnboardViewModel.kt @@ -10,6 +10,7 @@ import com.woka.networking.RetrofitHelper import com.woka.onboard.models.AvatarList import com.woka.onboard.models.Child import com.woka.onboard.models.ChildListResponse +import com.woka.onboard.models.ForgotPasswrodOTPResponse import com.woka.onboard.models.InterestTopicResponse import com.woka.onboard.models.LoginResponse import com.woka.onboard.models.RegisterRequestData @@ -64,6 +65,11 @@ class OnboardViewModel: ViewModel(){ val sendOTPLiveData: LiveData?> get() = _sendOTPLiveData + private val _forgotPwdOTPLiveData = MutableLiveData?>() + fun clearForgotPwdSendOTPData() = _forgotPwdOTPLiveData.postValue(null) + val forgotPwdOTPLiveData: LiveData?> + get() = _forgotPwdOTPLiveData + /* VerifyOTP Fragment */ @@ -72,6 +78,11 @@ class OnboardViewModel: ViewModel(){ val validateOTPLiveData: LiveData?> get() = _validateOTPLiveData + private val _verifyForgotPwdOTPLiveData = MutableLiveData?>() + fun clearVerifyForgotPwdOTP() = _verifyForgotPwdOTPLiveData.postValue(null) + val verifyForgotPwdOTPLiveData: LiveData?> + get() = _verifyForgotPwdOTPLiveData + /* SignUp Fragment */ @@ -99,6 +110,14 @@ class OnboardViewModel: ViewModel(){ val interestTopicsLiveData: LiveData?> get() = _interestTopicsLiveData + /* + Update password fragment + */ + private val _updatePasswordLiveData = MutableLiveData?>() + fun clearUpdatePasswordLiveData() = _updatePasswordLiveData.postValue(null) + val updatePasswordLiveData: LiveData?> + get() = _updatePasswordLiveData + fun login(userName: String, password: String){ viewModelScope.launch { _loginLiveData.postValue(ApiResult.Loading()) @@ -177,6 +196,30 @@ class OnboardViewModel: ViewModel(){ } } + fun forgotPwdSendOTP(userName: String){ + viewModelScope.launch { + _forgotPwdOTPLiveData.postValue(ApiResult.Loading()) + val response = repository.forgotPasswordSendOTP(userName) + _forgotPwdOTPLiveData.postValue(response) + } + } + + fun verifyForgotPwdOTP(userName: String, otp: String){ + viewModelScope.launch { + _verifyForgotPwdOTPLiveData.postValue(ApiResult.Loading()) + val response = repository.verifyForgotPwdOTP(userName, otp) + _verifyForgotPwdOTPLiveData.postValue(response) + } + } + + fun updatePassword(userName: String, password: String, confirmPwd: String){ + viewModelScope.launch { + _updatePasswordLiveData.postValue(ApiResult.Loading()) + val response = repository.updatePassword(userName, password, confirmPwd) + _updatePasswordLiveData.postValue(response) + } + } + // otp count down timer private val OTP_RESEND_COUNT_DOWN_TIME = 10 * 60 * 1000L // 10 min diff --git a/app/src/main/res/layout/fragment_new_password.xml b/app/src/main/res/layout/fragment_new_password.xml index 1723839..6a60729 100644 --- a/app/src/main/res/layout/fragment_new_password.xml +++ b/app/src/main/res/layout/fragment_new_password.xml @@ -120,6 +120,8 @@ android:textColorHint="@android:color/darker_gray" android:textSize="@dimen/_13ssp" + android:maxLength="16" + /> @@ -130,7 +132,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="@string/create_your_password" + android:text="@string/confirm_your_password_" android:fontFamily="@font/exo_2_bold" android:textSize="@dimen/_12ssp" android:textColor="@color/color_primary" @@ -181,6 +183,8 @@ android:paddingHorizontal="20dp" android:paddingVertical="15dp" + android:maxLength="16" + /> diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 614313c..203f2d7 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -85,4 +85,13 @@ क्या आप लॉग इन जारी रखना चाहते हैं? हाँ नहीं + कृपया ओटीपी कोड दर्ज करें + अपने पासवर्ड की पुष्टि करें + कम से कम 6 अक्षर का होना चाहिए + पासवर्ड मैच नहीं कर रहा है + कृपया दर्ज करें + कृपया दर्ज करें + पासवर्ड कम से कम 6 अंकों का होना चाहिए + कम से कम 3 अक्षर होने चाहिए + कृपया दर्ज करें \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8ce2d09..f6208a3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -92,4 +92,13 @@ Do you want to continue log in? Yes No + Please enter OTP code + CONFIRM YOUR PASSWORD + Must be at least 6 characters + Password does not match + username required + Invalid email + Password must be at least 6 characters + Must be at least 3 characters + Required \ No newline at end of file