add auth-code validation
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package ru.myitschool.work.ui
|
package ru.myitschool.work.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@@ -25,6 +26,8 @@ import androidx.compose.ui.unit.sp
|
|||||||
import ru.myitschool.work.R
|
import ru.myitschool.work.R
|
||||||
import ru.myitschool.work.ui.theme.Black
|
import ru.myitschool.work.ui.theme.Black
|
||||||
import ru.myitschool.work.ui.theme.Gray
|
import ru.myitschool.work.ui.theme.Gray
|
||||||
|
import ru.myitschool.work.ui.theme.LightBlue
|
||||||
|
import ru.myitschool.work.ui.theme.LightGray
|
||||||
import ru.myitschool.work.ui.theme.Typography
|
import ru.myitschool.work.ui.theme.Typography
|
||||||
import ru.myitschool.work.ui.theme.White
|
import ru.myitschool.work.ui.theme.White
|
||||||
|
|
||||||
@@ -120,16 +123,14 @@ fun BaseText14(
|
|||||||
@Composable
|
@Composable
|
||||||
fun BaseInputText(
|
fun BaseInputText(
|
||||||
placeholder: String= "",
|
placeholder: String= "",
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier,
|
||||||
|
valueChange: (String) -> Unit,
|
||||||
|
value: String
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var textState by remember { mutableStateOf("") }
|
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
value = textState,
|
value = value,
|
||||||
onValueChange = {
|
onValueChange = valueChange,
|
||||||
textState = it
|
|
||||||
},
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
shape = RoundedCornerShape(16.dp),
|
||||||
placeholder = {
|
placeholder = {
|
||||||
BaseText16(
|
BaseText16(
|
||||||
@@ -139,6 +140,8 @@ fun BaseInputText(
|
|||||||
},
|
},
|
||||||
textStyle = Typography.bodySmall.copy(fontSize = 16.sp),
|
textStyle = Typography.bodySmall.copy(fontSize = 16.sp),
|
||||||
colors = TextFieldDefaults.colors(
|
colors = TextFieldDefaults.colors(
|
||||||
|
focusedContainerColor = LightBlue,
|
||||||
|
unfocusedContainerColor = LightBlue,
|
||||||
focusedIndicatorColor = Color.Transparent,
|
focusedIndicatorColor = Color.Transparent,
|
||||||
unfocusedIndicatorColor = Color.Transparent,
|
unfocusedIndicatorColor = Color.Transparent,
|
||||||
disabledIndicatorColor = Color.Transparent,
|
disabledIndicatorColor = Color.Transparent,
|
||||||
@@ -169,6 +172,7 @@ fun BaseText20(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BaseButton(
|
fun BaseButton(
|
||||||
|
enable: Boolean = true,
|
||||||
text: String,
|
text: String,
|
||||||
btnColor: Color,
|
btnColor: Color,
|
||||||
btnContentColor: Color,
|
btnContentColor: Color,
|
||||||
@@ -177,12 +181,13 @@ fun BaseButton(
|
|||||||
modifier: Modifier = Modifier.fillMaxWidth()
|
modifier: Modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Button(
|
Button(
|
||||||
|
enabled = enable,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = btnColor,
|
containerColor = btnColor,
|
||||||
contentColor = btnContentColor,
|
contentColor = btnContentColor,
|
||||||
disabledContainerColor = btnColor,
|
disabledContainerColor = LightGray,
|
||||||
disabledContentColor = btnContentColor
|
disabledContentColor = Gray
|
||||||
),
|
),
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
shape = RoundedCornerShape(16.dp),
|
shape = RoundedCornerShape(16.dp),
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import androidx.compose.ui.platform.testTag
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import ru.myitschool.work.R
|
import ru.myitschool.work.R
|
||||||
@@ -40,7 +41,6 @@ import ru.myitschool.work.ui.theme.Blue
|
|||||||
import ru.myitschool.work.ui.theme.Red
|
import ru.myitschool.work.ui.theme.Red
|
||||||
import ru.myitschool.work.ui.theme.White
|
import ru.myitschool.work.ui.theme.White
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AuthScreen(
|
fun AuthScreen(
|
||||||
viewModel: AuthViewModel = viewModel(),
|
viewModel: AuthViewModel = viewModel(),
|
||||||
@@ -62,15 +62,25 @@ fun AuthScreen(
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(vertical = 20.dp)
|
modifier = Modifier.padding(vertical = 20.dp)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
val textState by viewModel.textState.collectAsStateWithLifecycle()
|
||||||
|
val errorState by viewModel.errorState.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
BaseInputText(
|
BaseInputText(
|
||||||
|
value = textState,
|
||||||
placeholder = stringResource(R.string.auth_label),
|
placeholder = stringResource(R.string.auth_label),
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Auth.CODE_INPUT)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
valueChange = {viewModel.updateText(it)}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (errorState) {
|
||||||
BaseText12(
|
BaseText12(
|
||||||
text = "Недействительный код сотрудника",
|
text = "Недействительный код сотрудника",
|
||||||
color = Red,
|
color = Red,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Auth.ERROR)
|
||||||
.padding(
|
.padding(
|
||||||
start = 10.dp,
|
start = 10.dp,
|
||||||
top = 5.dp,
|
top = 5.dp,
|
||||||
@@ -79,12 +89,19 @@ fun AuthScreen(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val isButtonEnabled by viewModel.isButtonEnabled.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
BaseButton(
|
BaseButton(
|
||||||
text = stringResource(R.string.auth_sign_in),
|
text = stringResource(R.string.auth_sign_in),
|
||||||
onClick = { navController.navigate(MainScreenDestination)},
|
onClick = { navController.navigate(MainScreenDestination)},
|
||||||
btnColor = Blue,
|
btnColor = Blue,
|
||||||
btnContentColor = White
|
enable = isButtonEnabled,
|
||||||
|
btnContentColor = White,
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Auth.SIGN_BUTTON)
|
||||||
|
.fillMaxWidth()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,66 @@
|
|||||||
package ru.myitschool.work.ui.screen.auth
|
package ru.myitschool.work.ui.screen.auth
|
||||||
|
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import ru.myitschool.work.data.repo.AuthRepository
|
import ru.myitschool.work.data.repo.AuthRepository
|
||||||
import ru.myitschool.work.domain.auth.CheckAndSaveAuthCodeUseCase
|
import ru.myitschool.work.domain.auth.CheckAndSaveAuthCodeUseCase
|
||||||
|
|
||||||
class AuthViewModel : ViewModel() {
|
class AuthViewModel : ViewModel() {
|
||||||
private val checkAndSaveAuthCodeUseCase by lazy { CheckAndSaveAuthCodeUseCase(AuthRepository) }
|
// private val checkAndSaveAuthCodeUseCase by lazy { CheckAndSaveAuthCodeUseCase(AuthRepository) }
|
||||||
private val _uiState = MutableStateFlow<AuthState>(AuthState.Data)
|
// private val _uiState = MutableStateFlow<AuthState>(AuthState.Data)
|
||||||
val uiState: StateFlow<AuthState> = _uiState.asStateFlow()
|
// val uiState: StateFlow<AuthState> = _uiState.asStateFlow()
|
||||||
|
//
|
||||||
|
// private val _actionFlow: MutableSharedFlow<Unit> = MutableSharedFlow()
|
||||||
|
// val actionFlow: SharedFlow<Unit> = _actionFlow
|
||||||
|
//
|
||||||
|
// fun onIntent(intent: AuthIntent) {
|
||||||
|
// when (intent) {
|
||||||
|
// is AuthIntent.Send -> {
|
||||||
|
// viewModelScope.launch(Dispatchers.Default) {
|
||||||
|
// _uiState.update { AuthState.Loading }
|
||||||
|
// checkAndSaveAuthCodeUseCase.invoke("9999").fold(
|
||||||
|
// onSuccess = {
|
||||||
|
// _actionFlow.emit(Unit)
|
||||||
|
// },
|
||||||
|
// onFailure = { error ->
|
||||||
|
// error.printStackTrace()
|
||||||
|
// _actionFlow.emit(Unit)
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// is AuthIntent.TextInput -> Unit
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
private val _actionFlow: MutableSharedFlow<Unit> = MutableSharedFlow()
|
private val _textState = MutableStateFlow("")
|
||||||
val actionFlow: SharedFlow<Unit> = _actionFlow
|
val textState: StateFlow<String> = _textState.asStateFlow()
|
||||||
|
|
||||||
fun onIntent(intent: AuthIntent) {
|
private val _errorState = MutableStateFlow(false)
|
||||||
when (intent) {
|
val errorState: StateFlow<Boolean> = _errorState.asStateFlow()
|
||||||
is AuthIntent.Send -> {
|
|
||||||
viewModelScope.launch(Dispatchers.Default) {
|
fun updateText(newText: String) {
|
||||||
_uiState.update { AuthState.Loading }
|
_textState.value = newText
|
||||||
checkAndSaveAuthCodeUseCase.invoke("9999").fold(
|
_errorState.value = false
|
||||||
onSuccess = {
|
|
||||||
_actionFlow.emit(Unit)
|
|
||||||
},
|
|
||||||
onFailure = { error ->
|
|
||||||
error.printStackTrace()
|
|
||||||
_actionFlow.emit(Unit)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isButtonEnabled: StateFlow<Boolean> =
|
||||||
|
_textState.map { it.length == 4 && it.matches(Regex("^[a-zA-Z0-9]*\$"))}
|
||||||
|
.stateIn(
|
||||||
|
scope = viewModelScope,
|
||||||
|
started = SharingStarted.WhileSubscribed(5000),
|
||||||
|
initialValue = false
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
is AuthIntent.TextInput -> Unit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,8 @@ val Blue = Color(0xFF004BFF)
|
|||||||
|
|
||||||
val Gray = Color(0xFF777777)
|
val Gray = Color(0xFF777777)
|
||||||
|
|
||||||
|
val LightBlue = Color(0xFFF2EFFF)
|
||||||
|
|
||||||
val White = Color(0xFFFFFFFF)
|
val White = Color(0xFFFFFFFF)
|
||||||
|
|
||||||
val Red = Color(0xFFFF4D4D)
|
val Red = Color(0xFFFF4D4D)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Work</string>
|
<string name="app_name">Work</string>
|
||||||
<string name="title_activity_root">RootActivity</string>
|
<string name="title_activity_root">RootActivity</string>
|
||||||
<string name="auth_title">Привет! Введи код для авторизации</string>
|
<string name="auth_title">Введите код для авторизации</string>
|
||||||
<string name="auth_label">Код</string>
|
<string name="auth_label">Код</string>
|
||||||
<string name="auth_sign_in">Войти</string>
|
<string name="auth_sign_in">Войти</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user