diff --git a/app/build.gradle b/app/build.gradle index e276955ac..6c97f265a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -116,6 +116,7 @@ dependencies { //Country Code picker implementation "com.hbb20:ccp:$rootProject.countryCodePicker" + implementation 'com.github.ParveshSandila:CountryCodeChooser:1.0' //Square dependencies implementation("com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion") { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1ca6da262..533e1b8ba 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -72,7 +72,7 @@ android:windowSoftInputMode="adjustResize" /> diff --git a/app/src/main/java/org/mifos/mobile/ui/fragments/RegistrationFragment.kt b/app/src/main/java/org/mifos/mobile/ui/fragments/RegistrationFragment.kt deleted file mode 100644 index 5e700f1d5..000000000 --- a/app/src/main/java/org/mifos/mobile/ui/fragments/RegistrationFragment.kt +++ /dev/null @@ -1,304 +0,0 @@ -package org.mifos.mobile.ui.fragments - -import android.graphics.PorterDuff -import android.os.Bundle -import android.text.Editable -import android.text.TextWatcher -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.RadioButton -import android.widget.TextView -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle -import com.hbb20.CountryCodePicker -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.launch -import org.mifos.mobile.R -import org.mifos.mobile.databinding.FragmentRegistrationBinding -import org.mifos.mobile.ui.activities.base.BaseActivity -import org.mifos.mobile.ui.fragments.base.BaseFragment -import org.mifos.mobile.utils.Network -import org.mifos.mobile.utils.PasswordStrength -import org.mifos.mobile.utils.RegistrationUiState -import org.mifos.mobile.utils.Toaster -import org.mifos.mobile.viewModels.RegistrationViewModel - -/** - * Created by dilpreet on 31/7/17. - */ -@AndroidEntryPoint -class RegistrationFragment : BaseFragment() { - private var _binding: FragmentRegistrationBinding? = null - private val binding get() = _binding!! - private lateinit var viewModel: RegistrationViewModel - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { - _binding = FragmentRegistrationBinding.inflate(inflater, container, false) - val rootView = binding.root - viewModel = ViewModelProvider(this)[RegistrationViewModel::class.java] - with(binding) { - etPassword.addTextChangedListener(object : TextWatcher { - override fun beforeTextChanged( - charSequence: CharSequence, i: Int, i1: Int, i2: Int - ) { - } - - override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) { - if (charSequence.isEmpty()) { - progressBar.visibility = View.GONE - passwordStrength.visibility = View.GONE - } else { - progressBar.visibility = View.VISIBLE - passwordStrength.visibility = View.VISIBLE - updatePasswordStrengthView(charSequence.toString()) - } - } - - override fun afterTextChanged(editable: Editable) {} - }) - } - return rootView - } - - private fun updatePasswordStrengthView(password: String) { - with(binding) { - if (TextView.VISIBLE != passwordStrength.visibility) return - if (password.isEmpty()) { - passwordStrength.text = "" - progressBar.progress = 0 - return - } - val str = PasswordStrength.calculateStrength(password) - passwordStrength.text = str.getText(context) - passwordStrength.setTextColor(str.color) - val mode = PorterDuff.Mode.SRC_IN - progressBar.progressDrawable?.setColorFilter(str.color, mode) - when (str.getText(context)) { - getString(R.string.password_strength_weak) -> progressBar.progress = 25 - getString(R.string.password_strength_medium) -> progressBar.progress = 50 - getString(R.string.password_strength_strong) -> progressBar.progress = 75 - else -> progressBar.progress = 100 - } - } - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - viewLifecycleOwner.lifecycleScope.launch { - repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.registrationUiState.collect { state -> - when (state) { - RegistrationUiState.Loading -> showProgress() - - RegistrationUiState.Success -> { - hideProgress() - showRegisteredSuccessfully() - } - - is RegistrationUiState.Error -> { - hideProgress() - showError(getString(state.exception)) - } - - RegistrationUiState.Initial -> {} - } - } - } - } - - binding.btnRegister.setOnClickListener { - registerClicked() - } - } - - private fun registerClicked() { - if (areFieldsValidated()) { - with(binding) { - val radioButton = rgVerificationMode.checkedRadioButtonId.let { - root.findViewById(it) - } - val accountNumber = etAccountNumber.text.toString() - val authenticationMode = radioButton?.text.toString() - val email = etEmail.text.toString() - val firstName = etFirstName.text.toString() - val lastName = etLastName.text.toString() - val mobileNumber = - countryCodePicker.selectedCountryCode.toString() + etPhoneNumber.text.toString() - if (etPassword.text.toString() != etConfirmPassword.text.toString()) { - Toaster.show(root, getString(R.string.error_password_not_match)) - return - } - val password = etPassword.text.toString() - val username = etUsername.text.toString().replace(" ", "") - - if (Network.isConnected(context)) { - viewModel.registerUser( - accountNumber, - authenticationMode, - email, - firstName, - lastName, - mobileNumber, - password, - username - ) - } else { - Toaster.show(root, getString(R.string.no_internet_connection)) - } - } - } - } - - private fun areFieldsValidated(): Boolean { - val rootView = binding.root - with(binding) { - return when { - viewModel.isInputFieldBlank(etAccountNumber.text.toString()) -> { - Toaster.show( - rootView, - getString( - R.string.error_validation_blank, getString(R.string.account_number) - ), - ) - false - } - - viewModel.isInputFieldBlank(etUsername.text.toString()) -> { - Toaster.show( - rootView, - getString(R.string.error_validation_blank, getString(R.string.username)), - ) - false - } - - viewModel.isInputLengthInadequate(etUsername.text.toString()) -> { - Toaster.show(rootView, getString(R.string.error_username_greater_than_six)) - false - } - - viewModel.inputHasSpaces(etUsername.text.toString()) -> { - Toaster.show( - rootView, - getString( - R.string.error_validation_cannot_contain_spaces, - getString(R.string.username), - getString(R.string.not_contain_username), - ), - ) - false - } - - viewModel.isInputFieldBlank(etFirstName.text.toString()) -> { - Toaster.show( - rootView, - getString(R.string.error_validation_blank, getString(R.string.first_name)), - ) - false - } - - viewModel.isInputFieldBlank(etLastName.text.toString()) -> { - Toaster.show( - rootView, - getString(R.string.error_validation_blank, getString(R.string.last_name)), - ) - false - } - - viewModel.isInputFieldBlank(etEmail.text.toString()) -> { - Toaster.show( - rootView, - getString(R.string.error_validation_blank, getString(R.string.email)), - ) - false - } - - viewModel.isInputFieldBlank(etPassword.text.toString()) -> { - Toaster.show( - rootView, - getString(R.string.error_validation_blank, getString(R.string.password)), - ) - false - } - - viewModel.hasLeadingTrailingSpaces(etPassword.text.toString()) -> { - Toaster.show( - rootView, - getString( - R.string.error_validation_cannot_contain_leading_or_trailing_spaces, - getString(R.string.password), - ), - ) - false - } - - viewModel.isEmailInvalid(etEmail.text.toString()) -> { - Toaster.show(rootView, getString(R.string.error_invalid_email)) - false - } - - viewModel.isInputLengthInadequate(etPassword.text.toString()) -> { - Toaster.show( - rootView, - getString( - R.string.error_validation_minimum_chars, - getString(R.string.password), - resources.getInteger(R.integer.password_minimum_length), - ), - ) - return false - } - - (!isPhoneNumberValid(countryCodePicker)) -> { - Toaster.show(rootView, getString(R.string.invalid_phn_number)) - return false - } - - else -> true - } - } - } - - private fun showRegisteredSuccessfully() { - (activity as BaseActivity?)?.replaceFragment( - RegistrationVerificationFragment.newInstance(), - true, - R.id.container, - ) - } - - fun showError(msg: String?) { - Toaster.show(binding.root, msg) - } - - fun showProgress() { - showMifosProgressDialog(getString(R.string.sign_up)) - } - - fun hideProgress() { - hideMifosProgressDialog() - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } - - private fun isPhoneNumberValid(ccp: CountryCodePicker): Boolean { - binding.countryCodePicker.registerCarrierNumberEditText(binding.etPhoneNumber) - return ccp.isValidFullNumber - } - - companion object { - fun newInstance(): RegistrationFragment { - return RegistrationFragment() - } - } -} diff --git a/app/src/main/java/org/mifos/mobile/ui/fragments/RegistrationVerificationFragment.kt b/app/src/main/java/org/mifos/mobile/ui/fragments/RegistrationVerificationFragment.kt index 0907a3a14..9f0cbc77b 100644 --- a/app/src/main/java/org/mifos/mobile/ui/fragments/RegistrationVerificationFragment.kt +++ b/app/src/main/java/org/mifos/mobile/ui/fragments/RegistrationVerificationFragment.kt @@ -18,7 +18,7 @@ import org.mifos.mobile.ui.login.LoginActivity import org.mifos.mobile.ui.fragments.base.BaseFragment import org.mifos.mobile.utils.RegistrationUiState import org.mifos.mobile.utils.Toaster -import org.mifos.mobile.viewModels.RegistrationViewModel +import org.mifos.mobile.ui.registration.RegistrationViewModel /** * Created by dilpreet on 31/7/17. diff --git a/app/src/main/java/org/mifos/mobile/ui/login/LoginActivity.kt b/app/src/main/java/org/mifos/mobile/ui/login/LoginActivity.kt index 7e6ebdbec..b1301642b 100644 --- a/app/src/main/java/org/mifos/mobile/ui/login/LoginActivity.kt +++ b/app/src/main/java/org/mifos/mobile/ui/login/LoginActivity.kt @@ -14,7 +14,7 @@ import org.mifos.mobile.MifosSelfServiceApp.Companion.context import org.mifos.mobile.R import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.ui.activities.PassCodeActivity -import org.mifos.mobile.ui.activities.RegistrationActivity +import org.mifos.mobile.ui.registration.RegistrationActivity import org.mifos.mobile.ui.activities.base.BaseActivity import org.mifos.mobile.utils.Constants import org.mifos.mobile.utils.LoginUiState diff --git a/app/src/main/java/org/mifos/mobile/ui/activities/RegistrationActivity.kt b/app/src/main/java/org/mifos/mobile/ui/registration/RegistrationActivity.kt similarity index 88% rename from app/src/main/java/org/mifos/mobile/ui/activities/RegistrationActivity.kt rename to app/src/main/java/org/mifos/mobile/ui/registration/RegistrationActivity.kt index 31c8d2f1c..46aecc922 100644 --- a/app/src/main/java/org/mifos/mobile/ui/activities/RegistrationActivity.kt +++ b/app/src/main/java/org/mifos/mobile/ui/registration/RegistrationActivity.kt @@ -1,11 +1,10 @@ -package org.mifos.mobile.ui.activities +package org.mifos.mobile.ui.registration -import android.content.DialogInterface import android.os.Bundle import org.mifos.mobile.R import org.mifos.mobile.databinding.ActivityRegistrationBinding import org.mifos.mobile.ui.activities.base.BaseActivity -import org.mifos.mobile.ui.fragments.RegistrationFragment +import org.mifos.mobile.ui.registration.RegistrationFragment import org.mifos.mobile.utils.MaterialDialog class RegistrationActivity : BaseActivity() { diff --git a/app/src/main/java/org/mifos/mobile/ui/registration/RegistrationFragment.kt b/app/src/main/java/org/mifos/mobile/ui/registration/RegistrationFragment.kt new file mode 100644 index 000000000..66d58b960 --- /dev/null +++ b/app/src/main/java/org/mifos/mobile/ui/registration/RegistrationFragment.kt @@ -0,0 +1,256 @@ +package org.mifos.mobile.ui.registration + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch +import org.mifos.mobile.R +import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.ui.activities.base.BaseActivity +import org.mifos.mobile.ui.fragments.RegistrationVerificationFragment +import org.mifos.mobile.ui.fragments.base.BaseFragment +import org.mifos.mobile.utils.Network +import org.mifos.mobile.utils.PasswordStrength +import org.mifos.mobile.utils.RegistrationUiState +import org.mifos.mobile.utils.Toaster + +/** + * Created by dilpreet on 31/7/17. + */ +@AndroidEntryPoint +class RegistrationFragment : BaseFragment() { + + private lateinit var viewModel: RegistrationViewModel + + private lateinit var accountNumberContent: String + private lateinit var usernameContent: String + private lateinit var firstNameContent: String + private lateinit var lastNameContent: String + private lateinit var phoneNumberContent: String + private lateinit var emailContent: String + private lateinit var passwordContent: String + private lateinit var authenticationModeContent: String + private lateinit var countryCodeContent: String + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + viewModel = ViewModelProvider(this)[RegistrationViewModel::class.java] + return ComposeView(requireContext()).apply { + setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) + setContent { + MifosMobileTheme { + RegistrationScreen( + register = { account, username, firstname, lastname, phoneNumber, email, password, authenticationMode, countryCode -> + accountNumberContent = account + usernameContent = username + firstNameContent = firstname + lastNameContent = lastname + phoneNumberContent = phoneNumber + emailContent = email + passwordContent = password + authenticationModeContent = authenticationMode + countryCodeContent = countryCode + registerClicked() + }, + progress = { updatePasswordStrengthView(it) } + ) + } + } + } + } + + private fun updatePasswordStrengthView(password: String): Float { + val str = PasswordStrength.calculateStrength(password) + return when (str.getText(context)) { + getString(R.string.password_strength_weak) -> 0.25f + getString(R.string.password_strength_medium) -> 0.5f + getString(R.string.password_strength_strong) -> 0.75f + else -> 1f + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + viewLifecycleOwner.lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.registrationUiState.collect { state -> + when (state) { + RegistrationUiState.Loading -> showProgress() + + RegistrationUiState.Success -> { + hideProgress() + showRegisteredSuccessfully() + } + + is RegistrationUiState.Error -> { + hideProgress() + showError(getString(state.exception)) + } + + RegistrationUiState.Initial -> {} + } + } + } + } + + } + + private fun registerClicked() { + if (areFieldsValidated()) { + if (Network.isConnected(context)) { + viewModel.registerUser( + accountNumberContent, + authenticationModeContent, + emailContent, + firstNameContent, + lastNameContent, + phoneNumberContent, + passwordContent, + usernameContent + ) + } else { + Toaster.show(view, getString(R.string.no_internet_connection)) + } + + } + } + + private fun areFieldsValidated(): Boolean { + return when { + viewModel.isInputFieldBlank(accountNumberContent) -> { + Toaster.show( + view, + getString( + R.string.error_validation_blank, getString(R.string.account_number) + ), + ) + false + } + + viewModel.isInputFieldBlank(usernameContent) -> { + Toaster.show( + view, + getString(R.string.error_validation_blank, getString(R.string.username)), + ) + false + } + + viewModel.isInputLengthInadequate(usernameContent) -> { + Toaster.show(view, getString(R.string.error_username_greater_than_six)) + false + } + + viewModel.inputHasSpaces(usernameContent) -> { + Toaster.show( + view, + getString( + R.string.error_validation_cannot_contain_spaces, + getString(R.string.username), + getString(R.string.not_contain_username), + ), + ) + false + } + + viewModel.isInputFieldBlank(firstNameContent) -> { + Toaster.show( + view, + getString(R.string.error_validation_blank, getString(R.string.first_name)), + ) + false + } + + viewModel.isInputFieldBlank(lastNameContent) -> { + Toaster.show( + view, + getString(R.string.error_validation_blank, getString(R.string.last_name)), + ) + false + } + + viewModel.isInputFieldBlank(emailContent) -> { + Toaster.show( + view, + getString(R.string.error_validation_blank, getString(R.string.email)), + ) + false + } + + viewModel.isInputFieldBlank(passwordContent) -> { + Toaster.show( + view, + getString(R.string.error_validation_blank, getString(R.string.password)), + ) + false + } + + viewModel.hasLeadingTrailingSpaces(passwordContent) -> { + Toaster.show( + view, + getString( + R.string.error_validation_cannot_contain_leading_or_trailing_spaces, + getString(R.string.password), + ), + ) + false + } + + viewModel.isEmailInvalid(emailContent) -> { + Toaster.show(view, getString(R.string.error_invalid_email)) + false + } + + viewModel.isInputLengthInadequate(passwordContent) -> { + Toaster.show( + view, + getString( + R.string.error_validation_minimum_chars, + getString(R.string.password), + resources.getInteger(R.integer.password_minimum_length), + ), + ) + return false + } + + else -> true + } + } + + private fun showRegisteredSuccessfully() { + (activity as BaseActivity?)?.replaceFragment( + RegistrationVerificationFragment.newInstance(), + true, + R.id.container, + ) + } + + fun showError(msg: String?) { + Toaster.show(view, msg) + } + + fun showProgress() { + showMifosProgressDialog(getString(R.string.sign_up)) + } + + fun hideProgress() { + hideMifosProgressDialog() + } + + companion object { + fun newInstance(): RegistrationFragment { + return RegistrationFragment() + } + } +} diff --git a/app/src/main/java/org/mifos/mobile/ui/registration/RegistrationScreen.kt b/app/src/main/java/org/mifos/mobile/ui/registration/RegistrationScreen.kt new file mode 100644 index 000000000..55f6b0f1e --- /dev/null +++ b/app/src/main/java/org/mifos/mobile/ui/registration/RegistrationScreen.kt @@ -0,0 +1,271 @@ +package org.mifos.mobile.ui.registration + +import android.content.res.Configuration +import androidx.compose.foundation.border +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Visibility +import androidx.compose.material.icons.filled.VisibilityOff +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.RadioButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.owlbuddy.www.countrycodechooser.CountryCodeChooser +import com.owlbuddy.www.countrycodechooser.utils.enums.CountryCodeType +import org.mifos.mobile.R +import org.mifos.mobile.core.ui.component.MifosOutlinedTextField + +/** + * @author pratyush + * @since 28/12/2023 + */ + +@Composable +fun RegistrationScreen( + register: (accountNumber: String, username: String, firstName: String, lastName: String, phoneNumber: String, email: String, password: String, authMode: String, countryCode: String) -> Unit, + progress: (String) -> Float, +) { + + val keyboardController = LocalSoftwareKeyboardController.current + + var accountNumber by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue("")) + } + var username by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue("")) + } + var firstName by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue("")) + } + var lastName by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue("")) + } + var phoneNumber by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue("")) + } + var email by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue("")) + } + var password by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue("")) + } + var onValueChangePassword by rememberSaveable { + mutableStateOf(false) + } + var confirmPassword by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue("")) + } + var countryCode by rememberSaveable { + mutableStateOf("") + } + val radioOptions = + listOf(stringResource(id = R.string.rb_email), stringResource(id = R.string.rb_mobile)) + var authenticationMode by remember { mutableStateOf(radioOptions[0]) } + + val progressIndicator = progress(password.text) + var passwordVisibility: Boolean by remember { mutableStateOf(false) } + var confirmPasswordVisibility: Boolean by remember { mutableStateOf(false) } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 12.dp) + .pointerInput(Unit) { + detectTapGestures(onTap = { + keyboardController?.hide() + }) + }) { + MifosOutlinedTextField( + value = accountNumber, + onValueChange = { accountNumber = it }, + label = R.string.account_number, + supportingText = "" + ) + MifosOutlinedTextField( + value = username, + onValueChange = { username = it }, + label = R.string.username, + supportingText = "" + ) + MifosOutlinedTextField( + value = firstName, + onValueChange = { firstName = it }, + label = R.string.first_name, + supportingText = "" + ) + MifosOutlinedTextField( + value = lastName, + onValueChange = { lastName = it }, + label = R.string.last_name, + supportingText = "" + ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + CountryCodeChooser( + modifier = Modifier + .padding(start = 16.dp) + .border( + width = 1.dp, + shape = RoundedCornerShape(5.dp), + color = Color.Gray + ) + .padding(10.dp), + defaultCountryCode = "91", + countryCodeType = CountryCodeType.FLAG, + onCountyCodeSelected = { code, codeWithPrefix -> + countryCode = code + } + ) + MifosOutlinedTextField( + value = phoneNumber, + onValueChange = { phoneNumber = it }, + label = R.string.phone_number, + supportingText = "" + ) + } + MifosOutlinedTextField( + value = email, + onValueChange = { email = it }, + label = R.string.email, + supportingText = "" + ) + MifosOutlinedTextField( + value = password, + onValueChange = { + password = it + onValueChangePassword = true + }, + label = R.string.password, + supportingText = "", + visualTransformation = if (passwordVisibility) VisualTransformation.None else PasswordVisualTransformation(), + trailingIcon = { + val image = if (passwordVisibility) + Icons.Filled.Visibility + else Icons.Filled.VisibilityOff + IconButton(onClick = { passwordVisibility = !passwordVisibility }) { + Icon(imageVector = image, null) + } + } + ) + + if (onValueChangePassword) { + LinearProgressIndicator( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp), + color = when (progressIndicator) { + 0.25f -> Color.Red + 0.5f -> Color(alpha = 255, red = 220, green = 185, blue = 0) + 0.75f -> Color.Green + else -> Color.Blue + }, + progress = progressIndicator, + trackColor = Color.White + ) + } + + MifosOutlinedTextField( + value = confirmPassword, + onValueChange = { confirmPassword = it }, + label = R.string.confirm_password, + supportingText = "", + visualTransformation = if (confirmPasswordVisibility) VisualTransformation.None else PasswordVisualTransformation(), + trailingIcon = { + val image = if (confirmPasswordVisibility) + Icons.Filled.Visibility + else Icons.Filled.VisibilityOff + IconButton(onClick = { confirmPasswordVisibility = !confirmPasswordVisibility }) { + Icon(imageVector = image, null) + } + } + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource(id = R.string.verification_mode), + modifier = Modifier.padding(end = 8.dp), + color = if (isSystemInDarkTheme()) Color.White else Color.Black + ) + radioOptions.forEach { authMode -> + RadioButton( + selected = (authMode == authenticationMode), + onClick = { authenticationMode = authMode } + ) + Text( + text = authMode, + color = if (isSystemInDarkTheme()) Color.White else Color.Black + ) + } + } + + Button( + onClick = { + register.invoke( + accountNumber.text, + username.text, + firstName.text, + lastName.text, + phoneNumber.text, + email.text, + password.text, + authenticationMode, + countryCode + ) + keyboardController?.hide() + }, + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, top = 4.dp), + contentPadding = PaddingValues(12.dp), + colors = ButtonDefaults.buttonColors( + containerColor = if (isSystemInDarkTheme()) Color( + 0xFF9bb1e3 + ) else Color(0xFF325ca8) + ) + ) { + Text(text = stringResource(id = R.string.register)) + } + } +} + +@Preview(showSystemUi = true, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +fun RegistrationScreenPreview() { + RegistrationScreen({ _, _, _, _, _, _, _, _, _ -> }, { 0f }) +} \ No newline at end of file diff --git a/app/src/main/java/org/mifos/mobile/viewModels/RegistrationViewModel.kt b/app/src/main/java/org/mifos/mobile/ui/registration/RegistrationViewModel.kt similarity index 96% rename from app/src/main/java/org/mifos/mobile/viewModels/RegistrationViewModel.kt rename to app/src/main/java/org/mifos/mobile/ui/registration/RegistrationViewModel.kt index 2fbaac8cc..2b4299f99 100644 --- a/app/src/main/java/org/mifos/mobile/viewModels/RegistrationViewModel.kt +++ b/app/src/main/java/org/mifos/mobile/ui/registration/RegistrationViewModel.kt @@ -1,8 +1,6 @@ -package org.mifos.mobile.viewModels +package org.mifos.mobile.ui.registration import androidx.core.util.PatternsCompat -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel diff --git a/app/src/main/res/layout/activity_registration.xml b/app/src/main/res/layout/activity_registration.xml index 6950fd158..3183031d2 100644 --- a/app/src/main/res/layout/activity_registration.xml +++ b/app/src/main/res/layout/activity_registration.xml @@ -2,8 +2,7 @@ + android:layout_height="match_parent">