Child registration flow complete

Hindi language variations handled
This commit is contained in:
2024-05-09 17:22:07 +05:30
parent cf82e1e9ed
commit 832a67d266
16 changed files with 171 additions and 47 deletions

View File

@@ -8,6 +8,7 @@ import com.woka.WokaApp.Companion.userPrefs
import com.woka.onboard.models.LoginResponse
import com.woka.utils.NO_INTERNET_MESSAGE
import com.woka.utils.UNKNOWN_ERROR_MESSAGE
import kotlinx.coroutines.delay
import okhttp3.Credentials
import okhttp3.Interceptor
import okhttp3.OkHttpClient
@@ -59,6 +60,7 @@ object RetrofitHelper {
// api caller
suspend fun <T>handleApiCall(apiCall: suspend () -> Response<ApiResponse<T>>): ApiResult<T> {
return try {
delay(3000)
val response = apiCall() // this api call can throw some exception
handleApiResponse(response) // handling the response
} catch (e: UnknownHostException) {

View File

@@ -6,28 +6,39 @@ import android.widget.TextView
import androidx.cardview.widget.CardView
import com.woka.R
class InterestTopicView(context: Context, topicName: String): LinearLayout(context) {
var isTopicSelected = false
private set
class InterestTopicView(
context: Context,
val topic_id: Int,
topicName: String,
var isTopicSelected: Boolean = false,
val selectCallback: ((selected: Boolean, id: Int) -> Unit)? = null
) : LinearLayout(context) {
init {
inflate(context, R.layout.layout_interest_topic, this)
findViewById<TextView>(R.id.interest_topic_txt).text = topicName
findViewById<CardView>(R.id.interest_card).setOnClickListener {
val card = it as CardView
if (!isTopicSelected){
card.setCardBackgroundColor(context.resources.getColor(R.color.white))
card.elevation = 5f
}else{
card.setCardBackgroundColor(context.resources.getColor(R.color.white_60))
card.elevation = 0f
}
selectInterestTopic(isTopicSelected, findViewById(R.id.interest_card))
findViewById<CardView>(R.id.interest_card).setOnClickListener {
selectInterestTopic(!isTopicSelected, it as CardView)
isTopicSelected = !isTopicSelected
}
}
constructor(context: Context): this(context, "None")
private fun selectInterestTopic(select: Boolean, card: CardView) {
if (select) {
card.setCardBackgroundColor(context.resources.getColor(R.color.white))
card.elevation = 5f
selectCallback?.invoke(true, topic_id)
} else {
card.setCardBackgroundColor(context.resources.getColor(R.color.white_60))
card.elevation = 0f
selectCallback?.invoke(false, topic_id)
}
}
constructor(context: Context) : this(context, -1, "None")
}

View File

@@ -21,6 +21,7 @@ import com.woka.networking.NoSuccessError
import com.woka.onboard.fragments.GetEmailFragment.Companion.IS_RESET_PASSWORD_INTENT
import com.woka.onboard.fragments.GetEmailFragment.Companion.IS_UNDER_16
import com.woka.onboard.mvvm.OnboardViewModel
import com.woka.utils.CHILD_TYPE
import com.woka.utils.PARENT_TYPE
import com.woka.utils.ProgressView
import com.woka.utils.closeKeyboard
@@ -38,7 +39,6 @@ class GetCodeFragment : Fragment() {
companion object {
const val UNIQUE_STRING_ARG = "unique_str_arg"
const val EMAIL_ARG = "unique_str_arg"
const val OTP_RESEND_COUNT_DOWN_TIME = 10 * 60 * 1000L // 10 min
}
private lateinit var binding: FragmentGetCodeBinding
@@ -90,11 +90,12 @@ class GetCodeFragment : Fragment() {
Toast.makeText(activity, "${it.errorMessage}", Toast.LENGTH_SHORT).show()
}
is ApiResult.Loading -> {
progressView.show("Sending OTP...")
progressView.show(getString(R.string.sending_otp))
}
is ApiResult.Success -> {
viewModel.startOTPTimeCountDown()
Toast.makeText(activity, "OTP sent successfully", Toast.LENGTH_SHORT).show()
Toast.makeText(activity,
getString(R.string.otp_sent_successfully), Toast.LENGTH_SHORT).show()
progressView.hide()
uniqueString = it.data?.unique_string?:""
@@ -111,22 +112,24 @@ class GetCodeFragment : Fragment() {
Toast.makeText(activity, "${it.errorMessage}", Toast.LENGTH_SHORT).show()
}
is ApiResult.Loading -> {
progressView.show("Validating OTP...")
progressView.show(getString(R.string.validating_otp))
}
is ApiResult.Success -> {
// OTP validation successful
if (isResetPasswordIntent){
progressView.hide()
Toast.makeText(activity, "OTP validation successful.", Toast.LENGTH_SHORT)
Toast.makeText(activity,
getString(R.string.otp_validation_successful), Toast.LENGTH_SHORT)
.show()
findNavController().navigate(R.id.action_getCodeFragment_to_newPasswordFragment2)
}else{
}else if (!isUnder16){
// parent type
lifecycleScope.launch {
val listOfChild = viewModel.getChildList(email)
progressView.hide()
Toast.makeText(activity, "OTP validation successful.", Toast.LENGTH_SHORT)
Toast.makeText(activity, getString(R.string.otp_validation_successful), Toast.LENGTH_SHORT)
.show()
if (listOfChild is ApiResult.Error){
@@ -157,6 +160,13 @@ class GetCodeFragment : Fragment() {
gotoSignUpFragment()
}
}
}else{
// child type
progressView.hide()
Toast.makeText(activity, getString(R.string.otp_validation_successful), Toast.LENGTH_SHORT)
.show()
gotoSignUpFragment()
}
}
@@ -176,7 +186,7 @@ class GetCodeFragment : Fragment() {
val rms = (it)/1000 // remaining time in second
val time = "%02d:%02d".format(rms/60, rms%60)
val text = "OTP is valid for $time Min"
val text = "${getString(R.string.otp_is_valid_for)} $time ${getString(R.string.min)}"
Log.d("aditya_testing", "onTick: $it")
binding.countdown.text = text
}
@@ -245,6 +255,8 @@ class GetCodeFragment : Fragment() {
resend.setOnClickListener {
if (!isUnder16){
viewModel.sendOTP(email, PARENT_TYPE)
}else{
viewModel.sendOTP(email, CHILD_TYPE)
}
}
}

View File

@@ -16,6 +16,7 @@ import com.woka.networking.ApiResult
import com.woka.onboard.fragments.GetCodeFragment.Companion.EMAIL_ARG
import com.woka.onboard.fragments.GetCodeFragment.Companion.UNIQUE_STRING_ARG
import com.woka.onboard.mvvm.OnboardViewModel
import com.woka.utils.CHILD_TYPE
import com.woka.utils.PARENT_TYPE
import com.woka.utils.ProgressView
@@ -78,12 +79,14 @@ class GetEmailFragment : Fragment() {
}
is ApiResult.Loading -> {
progressView.show(title = "Please wait...")
progressView.show(title = getString(R.string.please_wait))
}
is ApiResult.Success -> {
if (!isUnder16) {
viewModel.sendOTP(binding.email.text.toString(), PARENT_TYPE)
}else{
viewModel.sendOTP(binding.email.text.toString(), CHILD_TYPE)
}
}
@@ -100,7 +103,7 @@ class GetEmailFragment : Fragment() {
}
is ApiResult.Loading -> {
progressView.show(title = "Sending OTP")
progressView.show(title = getString(R.string.sending_otp))
}
is ApiResult.Success -> {
@@ -172,7 +175,8 @@ class GetEmailFragment : Fragment() {
// parent
viewModel.checkEmailExist(binding.email.text.toString(), PARENT_TYPE)
} else {
// viewModel.checkEmailExist(binding.email.text.toString(), PARENT_TYPE)
// child
viewModel.sendOTP(binding.email.text.toString(), CHILD_TYPE)
}
}

View File

@@ -15,6 +15,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import com.woka.R
import com.woka.databinding.FragmentGetMoreInfoBinding
import com.woka.networking.ApiResult
import com.woka.onboard.InterestTopicView
import com.woka.onboard.fragments.GetEmailFragment.Companion.IS_UNDER_16
import com.woka.onboard.models.Interest
@@ -52,6 +53,32 @@ class GetMoreInfoFragment : Fragment() {
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.interestTopicsLiveData.observe(viewLifecycleOwner) {
if (it is ApiResult.Success && it.data?.result != null) {
binding.apply {
interestView.visibility = VISIBLE
for (topic in it.data.result) {
interestsFlex.addView(
InterestTopicView(
root.context,
topic.id,
topic.topic_name,
viewModel.interestTopics.contains(topic.id)
){selected, id ->
// topic select callback
if (selected) viewModel.interestTopics.add(id)
else viewModel.interestTopics.remove(id)
}
)
}
}
}
}
}
private fun clickEvents() {
binding.apply {
genderM.setOnClickListener { selectGender(Gender.MALE) }
@@ -61,7 +88,7 @@ class GetMoreInfoFragment : Fragment() {
next.setOnClickListener {
if (viewModel.selectedGender == Gender.NONE) {
Toast.makeText(activity, "Select a gender", Toast.LENGTH_SHORT).show()
Toast.makeText(activity, getString(R.string.select_a_gender), Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
@@ -85,15 +112,8 @@ class GetMoreInfoFragment : Fragment() {
datePicker.maxDate =
Calendar.getInstance().apply { add(Calendar.YEAR, -3) }.timeInMillis
interestView.visibility = VISIBLE
// static
interestsFlex.apply {
addView(InterestTopicView(context, "English"))
addView(InterestTopicView(context, "Maths"))
addView(InterestTopicView(context, "Science"))
addView(InterestTopicView(context, "Entertainment"))
addView(InterestTopicView(context, "Education"))
if (!viewModel.interestTopicsLiveData.isInitialized){
viewModel.getInterestTopics()
}
} else {
@@ -106,6 +126,9 @@ class GetMoreInfoFragment : Fragment() {
name.text = viewModel.name
// selecting the max date
viewModel.selectedDOB = Calendar.getInstance().apply { timeInMillis = datePicker.maxDate }
datePicker.init(
viewModel.selectedDOB.get(Calendar.YEAR),
viewModel.selectedDOB.get(Calendar.MONTH),

View File

@@ -8,6 +8,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import com.woka.R
import com.woka.WokaApp.Companion.userPrefs
import com.woka.databinding.FragmentSelectAvatarBinding
import com.woka.networking.ApiResult
@@ -61,26 +62,29 @@ class SelectAvatarFragment : Fragment() {
next.setOnClickListener {
if (viewModel.selectedAvatarPos == null) {
Toast.makeText(activity, "Please select an avatar", Toast.LENGTH_SHORT).show()
Toast.makeText(activity,
getString(R.string.please_select_an_avatar), Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
val registerRequestData = with(viewModel){
RegisterRequestData(
add_child = if (isUnder16) null else "1",
add_child = "0",
avtar = adapter?.avatarList?.get(selectedAvatarPos!!)?.avatar_name,
birthdate = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(selectedDOB.time),
email = email,
full_name = name,
gender = if (selectedGender == Gender.MALE) "2" else "1",
guardian_email = null,
guardian_email = if (isUnder16) email else null,
language_id = if (userPrefs?.appLanguage == "en") "1" else "2",
password = password,
user_type = if (isUnder16) "1" else "2",
username = userName
username = userName,
interest_topic_id = if (isUnder16) interestTopics.toList() else null
)
}
Log.d("aditya_testing", "clickEvents: $registerRequestData")
viewModel.registerUser(registerRequestData)
}
}
@@ -96,7 +100,7 @@ class SelectAvatarFragment : Fragment() {
}
is ApiResult.Loading -> {
progressView.show("Loading avatars...")
progressView.show(getString(R.string.loading_avatars))
}
is ApiResult.Success -> {
@@ -124,7 +128,7 @@ class SelectAvatarFragment : Fragment() {
Toast.makeText(activity, "${it.errorMessage}", Toast.LENGTH_SHORT).show()
}
is ApiResult.Loading -> {
progressView.show("Please wait...")
progressView.show(getString(R.string.please_wait))
}
is ApiResult.Success -> {
progressView.hide()

View File

@@ -66,7 +66,7 @@ class SignUpFragment : Fragment() {
}
is ApiResult.Loading -> {
progressView.show("Validating details")
progressView.show(getString(R.string.validating_details))
}
is ApiResult.Success -> {
@@ -121,7 +121,8 @@ class SignUpFragment : Fragment() {
email?.let {
val userType = if (isUnder16) CHILD_TYPE else PARENT_TYPE
viewModel.checkUserNameExist(it, username.text.toString(), userType)
} ?: Toast.makeText(activity, "Something went wrong!", Toast.LENGTH_SHORT)
} ?: Toast.makeText(activity,
getString(R.string.something_went_wrong), Toast.LENGTH_SHORT)
.show()
}
}

View File

@@ -0,0 +1,6 @@
package com.woka.onboard.models
data class InterestTopic(
val id: Int,
val topic_name: String
)

View File

@@ -0,0 +1,6 @@
package com.woka.onboard.models
data class InterestTopicResponse(
val result: List<InterestTopic>,
val total_records: Int
)

View File

@@ -11,5 +11,6 @@ data class RegisterRequestData(
val language_id: String? = "1",
val password: String?,
val user_type: String?,
val username: String?
val username: String?,
val interest_topic_id: List<Int>?
)

View File

@@ -3,6 +3,7 @@ package com.woka.onboard.mvvm
import com.woka.networking.ApiResponse
import com.woka.onboard.models.AvatarList
import com.woka.onboard.models.ChildListResponse
import com.woka.onboard.models.InterestTopicResponse
import com.woka.onboard.models.LoginResponse
import com.woka.onboard.models.RegisterRequestData
import com.woka.onboard.models.RegisterResponse
@@ -42,4 +43,7 @@ interface OnboardApiService {
@POST("get_linked_child")
suspend fun getChildList(@Body body: FormBody): Response<ApiResponse<ChildListResponse>>
@POST("interest_topic_listing")
suspend fun getInterestedTopics(): Response<ApiResponse<InterestTopicResponse>>
}

View File

@@ -6,6 +6,7 @@ import com.woka.networking.RetrofitHelper.handleApiCall
import com.woka.networking.RetrofitHelper.handleApiResponse
import com.woka.onboard.models.AvatarList
import com.woka.onboard.models.ChildListResponse
import com.woka.onboard.models.InterestTopicResponse
import com.woka.onboard.models.LoginResponse
import com.woka.onboard.models.RegisterRequestData
import com.woka.onboard.models.RegisterResponse
@@ -107,4 +108,10 @@ class OnboardRepository(private val apiService: OnboardApiService) {
}
}
suspend fun getInterestTopics(): ApiResult<InterestTopicResponse>{
return handleApiCall {
apiService.getInterestedTopics()
}
}
}

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.InterestTopicResponse
import com.woka.onboard.models.LoginResponse
import com.woka.onboard.models.RegisterRequestData
import com.woka.onboard.models.RegisterResponse
@@ -34,6 +35,7 @@ class OnboardViewModel: ViewModel(){
var password: String? = null
var childList: List<Child>? = null
val interestTopics = mutableSetOf<Int>()
// live_data
/*
@@ -78,7 +80,6 @@ class OnboardViewModel: ViewModel(){
val checkUserNameExistLiveData: LiveData<ApiResult<Any>?>
get() = _checkUserNameExistLiveData
/*
SelectAvatarFragment
*/
@@ -91,6 +92,13 @@ class OnboardViewModel: ViewModel(){
val registerUserLiveData: LiveData<ApiResult<RegisterResponse>?>
get() = _registerUserLiveData
/*
GetMoreInfo Fragment
*/
private val _interestTopicsLiveData = MutableLiveData<ApiResult<InterestTopicResponse>?>()
val interestTopicsLiveData: LiveData<ApiResult<InterestTopicResponse>?>
get() = _interestTopicsLiveData
fun login(userName: String, password: String){
viewModelScope.launch {
_loginLiveData.postValue(ApiResult.Loading())
@@ -161,6 +169,14 @@ class OnboardViewModel: ViewModel(){
}.await()
}
fun getInterestTopics(){
viewModelScope.launch {
_interestTopicsLiveData.postValue(ApiResult.Loading())
val response = repository.getInterestTopics()
_interestTopicsLiveData.postValue(response)
}
}
// otp count down timer
private val OTP_RESEND_COUNT_DOWN_TIME = 10 * 60 * 1000L // 10 min

View File

@@ -14,7 +14,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="10dp"
android:layout_marginVertical="15dp"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
android:orientation="horizontal"
@@ -24,9 +24,10 @@
android:id="@+id/image"
android:layout_width="@dimen/_40sdp"
android:layout_height="@dimen/_40sdp"
tools:src="@mipmap/ic_launcher"
app:civ_circle_background_color="@color/white"
app:civ_border_color="@color/white"
app:civ_border_width="5dp"
/>
<TextView

View File

@@ -65,4 +65,19 @@
<string name="confirm_your_password">नया पासवर्ड पुन: दर्ज करें</string>
<string name="reset_password">पासवर्ड रीसेट</string>
<string name="enter_your_password">अपना पासवर्ड दर्ज करें</string>
<string name="please_wait">कृपया प्रतीक्षा करें...</string>
<string name="resend_otp">ओटीपी पुनः भेजें?</string>
<string name="your_email_looks_familiar">आपका ईमेल परिचित लग रहा है!</string>
<string name="we_found_below_usernames_linked_to_this_email_address">हमें नीचे इस ईमेल पते से जुड़े उपयोगकर्ता नाम मिले</string>
<string name="sending_otp">ओटीपी भेजा जा रहा है...</string>
<string name="otp_sent_successfully">ओटीपी सफलतापूर्वक भेजा गया</string>
<string name="validating_otp">ओटीपी मान्य किया जा रहा है...</string>
<string name="otp_validation_successful">ओटीपी सत्यापन सफल.</string>
<string name="otp_is_valid_for">ओटीपी</string>
<string name="min">मिनट के लिए वैध है</string>
<string name="validating_details">विवरणों का सत्यापन</string>
<string name="something_went_wrong">कुछ गलत हो गया!</string>
<string name="select_a_gender">एक लिंग चुनें</string>
<string name="please_select_an_avatar">कृपया एक अवतार चुनें</string>
<string name="loading_avatars">अवतार लोड हो रहे हैं...</string>
</resources>

View File

@@ -74,4 +74,15 @@
<string name="resend_otp">Resend OTP?</string>
<string name="your_email_looks_familiar">Your Email Looks Familiar!</string>
<string name="we_found_below_usernames_linked_to_this_email_address">WE FOUND BELOW USERNAMES LINKED TO THIS EMAIL ADDRESS</string>
<string name="sending_otp">Sending OTP...</string>
<string name="otp_sent_successfully">OTP sent successfully</string>
<string name="validating_otp">Validating OTP...</string>
<string name="otp_validation_successful">OTP validation successful.</string>
<string name="otp_is_valid_for">OTP is valid for</string>
<string name="min">Min</string>
<string name="validating_details">Validating details</string>
<string name="something_went_wrong">Something went wrong!</string>
<string name="select_a_gender">Select a gender</string>
<string name="please_select_an_avatar">Please select an avatar</string>
<string name="loading_avatars">Loading avatars...</string>
</resources>