Additional logic for the login form

This commit is contained in:
Z. Charles Dziura 2024-08-18 01:29:47 -04:00
parent 7c5c11b430
commit 085634c95a
4 changed files with 85 additions and 37 deletions

View file

@ -27,10 +27,7 @@ class MainActivity : ComponentActivity() {
NavHost(navController = navController, startDestination = LoginRoute) { NavHost(navController = navController, startDestination = LoginRoute) {
composable<LoginRoute> { composable<LoginRoute> {
val viewModel: LoginScreenViewModel by viewModels() val viewModel: LoginScreenViewModel by viewModels()
LoginScreen( LoginScreen(viewModel)
viewModel.loginState,
viewModel::updateLoginUsername
)
} }
} }
} }

View file

@ -10,10 +10,13 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SecondaryTabRow import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Tab import androidx.compose.material3.Tab
@ -23,15 +26,17 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import kotlinx.coroutines.flow.StateFlow
import software.makeshift.debtpirate.R import software.makeshift.debtpirate.R
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@Composable @Composable
fun LoginScreen( fun LoginScreen(
loginState: StateFlow<LoginState>, viewModel: LoginScreenViewModel
updateLoginUsername: (String) -> Unit
) { ) {
Scaffold(modifier = Modifier.fillMaxSize()) { Scaffold(modifier = Modifier.fillMaxSize()) {
Column { Column {
@ -42,7 +47,9 @@ fun LoginScreen(
) )
LoginAndSignUpForms( LoginAndSignUpForms(
loginState, loginState = viewModel.loginState,
onUsernameUpdate = viewModel::updateLoginUsername,
onPasswordUpdate = viewModel::updateLoginPassword,
modifier = Modifier modifier = Modifier
.weight(3f) .weight(3f)
) )
@ -62,7 +69,9 @@ private fun Banner(modifier: Modifier = Modifier) {
@Composable @Composable
private fun LoginAndSignUpForms( private fun LoginAndSignUpForms(
loginTabState: StateFlow<LoginState>, loginState: LoginState,
onUsernameUpdate: (String) -> Unit,
onPasswordUpdate: (String) -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
Column(modifier = modifier) { Column(modifier = modifier) {
@ -72,13 +81,12 @@ private fun LoginAndSignUpForms(
selectedTabIndex = pagerState.currentPage, selectedTabIndex = pagerState.currentPage,
modifier = Modifier.height(48.dp) modifier = Modifier.height(48.dp)
) { ) {
val tabTextStyle = MaterialTheme.typography.titleLarge
Tab( Tab(
selected = pagerState.currentPage == 0, selected = pagerState.currentPage == 0,
onClick = { pagerState.requestScrollToPage(0) }, onClick = { pagerState.requestScrollToPage(0) },
text = { text = {
Text( Text(
text = stringResource(id = R.string.loginscreen_logintab_logintitle) text = stringResource(id = R.string.login_screen__login)
) )
}, },
modifier = Modifier.fillMaxHeight() modifier = Modifier.fillMaxHeight()
@ -88,7 +96,7 @@ private fun LoginAndSignUpForms(
onClick = { pagerState.requestScrollToPage(1) }, onClick = { pagerState.requestScrollToPage(1) },
text = { text = {
Text( Text(
text = stringResource(id = R.string.loginscreen_logintab_signuptitle), text = stringResource(id = R.string.login_screen__signup),
) )
}, },
modifier = Modifier.fillMaxHeight() modifier = Modifier.fillMaxHeight()
@ -97,11 +105,13 @@ private fun LoginAndSignUpForms(
HorizontalPager( HorizontalPager(
state = pagerState, state = pagerState,
modifier = Modifier.fillMaxSize() modifier = Modifier
.fillMaxSize()
.imePadding()
) { page -> ) { page ->
when (page) { when (page) {
0 -> { 0 -> {
Text("Page 1!") LoginForm(state = loginState, onUsernameUpdate, onPasswordUpdate)
} }
1 -> { 1 -> {
@ -112,9 +122,43 @@ private fun LoginAndSignUpForms(
} }
} }
//@Composable @Composable
//private fun LoginForm(state: StateFlow<LoginState>, onUsernameUpdate: (String) -> Unit, onPasswordUpdate: (String) -> Unit) { private fun LoginForm(
// Column { state: LoginState,
// OutlinedTextField(value = , onValueChange = ) onUsernameUpdate: (String) -> Unit,
// } onPasswordUpdate: (String) -> Unit
//} ) {
val (username, password) = state
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.fillMaxSize()) {
OutlinedTextField(
value = username,
label = { Text(stringResource(id = R.string.login_screen__username)) },
placeholder = { Text(stringResource(id = R.string.login_screen__username)) },
singleLine = true,
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Unspecified,
keyboardType = KeyboardType.Email,
imeAction = ImeAction.Next
),
onValueChange = onUsernameUpdate
)
OutlinedTextField(
value = password,
label = { Text(stringResource(id = R.string.login_screen__password)) },
placeholder = { Text(stringResource(id = R.string.login_screen__password)) },
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Unspecified,
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Send
),
visualTransformation = PasswordVisualTransformation(),
onValueChange = onPasswordUpdate
)
Button(onClick = { /*TODO*/ }) {
Text(stringResource(id = R.string.login_screen__login))
}
}
}

View file

@ -1,13 +1,11 @@
package software.makeshift.debtpirate.usecases.login package software.makeshift.debtpirate.usecases.login
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
data class LoginState(val username: String? = null, val password: String? = null) data class LoginState(val username: String = "", val password: String = "")
data class SignUpState( data class SignUpState(
val username: String? = null, val username: String? = null,
@ -17,16 +15,22 @@ data class SignUpState(
) )
class LoginScreenViewModel : ViewModel() { class LoginScreenViewModel : ViewModel() {
private val _loginState = MutableStateFlow(LoginState()) var loginState by mutableStateOf(LoginState())
val loginState = _loginState.asStateFlow() private set
val loginUsername: Flow<String?> val loginUsername: String
get() = loginState.map { loginState -> loginState.username } get() = loginState.username
fun updateLoginUsername(username: String) { fun updateLoginUsername(username: String) {
_loginState.update { state -> val (_, password) = loginState
val (_, password) = state loginState = LoginState(username, password)
LoginState(username, password) }
}
val loginPassword: String
get() = loginState.password
fun updateLoginPassword(password: String) {
val (username, _) = loginState
loginState = LoginState(username, password)
} }
} }

View file

@ -2,6 +2,9 @@
<string name="app_name">Debt Pirate</string> <string name="app_name">Debt Pirate</string>
<!-- Login Screen --> <!-- Login Screen -->
<string name="loginscreen_logintab_logintitle">Login</string> <string name="login_screen__login">Login</string>
<string name="loginscreen_logintab_signuptitle">Sign Up</string> <string name="login_screen__signup">Sign Up</string>
<string name="login_screen__username">Username</string>
<string name="login_screen__password">Password</string>
</resources> </resources>