Forgot Password module api integration

hindi error messages
This commit is contained in:
2024-05-10 16:22:04 +05:30
parent e113606649
commit 8e970d5ee8
12 changed files with 337 additions and 49 deletions

View File

@@ -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}"
}
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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
}

View File

@@ -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()
}

View File

@@ -50,4 +50,10 @@ interface OnboardApiService {
@POST("forgot_password_send_otp")
suspend fun forgotPasswordSendOTP(@Body body: FormBody): Response<ApiResponse<ForgotPasswrodOTPResponse>>
@POST("forgot_password_verify_otp")
suspend fun verifyForgetPwdOTP(@Body body: FormBody): Response<ApiResponse<Any>>
@POST("update_password")
suspend fun updatePassword(@Body body: FormBody): Response<ApiResponse<Any>>
}

View File

@@ -125,4 +125,27 @@ class OnboardRepository(private val apiService: OnboardApiService) {
}
}
suspend fun verifyForgotPwdOTP(userName: String, otp: String): ApiResult<Any>{
return handleApiCall {
apiService.verifyForgetPwdOTP(
FormBody.Builder()
.add("username", userName)
.add("otp", otp)
.build()
)
}
}
suspend fun updatePassword(userName: String, password: String, confirmPwd: String): ApiResult<Any>{
return handleApiCall {
apiService.updatePassword(
FormBody.Builder()
.add("username", userName)
.add("password", password)
.add("password_confirmation", confirmPwd)
.build()
)
}
}
}

View File

@@ -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<ApiResult<VerifyEmail>?>
get() = _sendOTPLiveData
private val _forgotPwdOTPLiveData = MutableLiveData<ApiResult<ForgotPasswrodOTPResponse>?>()
fun clearForgotPwdSendOTPData() = _forgotPwdOTPLiveData.postValue(null)
val forgotPwdOTPLiveData: LiveData<ApiResult<ForgotPasswrodOTPResponse>?>
get() = _forgotPwdOTPLiveData
/*
VerifyOTP Fragment
*/
@@ -72,6 +78,11 @@ class OnboardViewModel: ViewModel(){
val validateOTPLiveData: LiveData<ApiResult<Any>?>
get() = _validateOTPLiveData
private val _verifyForgotPwdOTPLiveData = MutableLiveData<ApiResult<Any>?>()
fun clearVerifyForgotPwdOTP() = _verifyForgotPwdOTPLiveData.postValue(null)
val verifyForgotPwdOTPLiveData: LiveData<ApiResult<Any>?>
get() = _verifyForgotPwdOTPLiveData
/*
SignUp Fragment
*/
@@ -99,6 +110,14 @@ class OnboardViewModel: ViewModel(){
val interestTopicsLiveData: LiveData<ApiResult<InterestTopicResponse>?>
get() = _interestTopicsLiveData
/*
Update password fragment
*/
private val _updatePasswordLiveData = MutableLiveData<ApiResult<Any>?>()
fun clearUpdatePasswordLiveData() = _updatePasswordLiveData.postValue(null)
val updatePasswordLiveData: LiveData<ApiResult<Any>?>
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

View File

@@ -120,6 +120,8 @@
android:textColorHint="@android:color/darker_gray"
android:textSize="@dimen/_13ssp"
android:maxLength="16"
/>
</com.google.android.material.textfield.TextInputLayout>
@@ -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"
/>
</com.google.android.material.textfield.TextInputLayout>

View File

@@ -85,4 +85,13 @@
<string name="do_you_want_to_continue_log_in">क्या आप लॉग इन जारी रखना चाहते हैं?</string>
<string name="yes">हाँ</string>
<string name="no">नहीं</string>
<string name="please_enter_otp_code">कृपया ओटीपी कोड दर्ज करें</string>
<string name="confirm_your_password_">अपने पासवर्ड की पुष्टि करें</string>
<string name="must_be_at_least_6_characters">कम से कम 6 अक्षर का होना चाहिए</string>
<string name="password_does_not_match">पासवर्ड मैच नहीं कर रहा है</string>
<string name="username_required">कृपया दर्ज करें</string>
<string name="invalid_email">कृपया दर्ज करें</string>
<string name="password_must_be_at_least_6_characters">पासवर्ड कम से कम 6 अंकों का होना चाहिए</string>
<string name="must_be_at_least_3_characters">कम से कम 3 अक्षर होने चाहिए</string>
<string name="required">कृपया दर्ज करें</string>
</resources>

View File

@@ -92,4 +92,13 @@
<string name="do_you_want_to_continue_log_in">Do you want to continue log in?</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="please_enter_otp_code">Please enter OTP code</string>
<string name="confirm_your_password_">CONFIRM YOUR PASSWORD</string>
<string name="must_be_at_least_6_characters">Must be at least 6 characters</string>
<string name="password_does_not_match">Password does not match</string>
<string name="username_required">username required</string>
<string name="invalid_email">Invalid email</string>
<string name="password_must_be_at_least_6_characters">Password must be at least 6 characters</string>
<string name="must_be_at_least_3_characters">Must be at least 3 characters</string>
<string name="required">Required</string>
</resources>