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) {
composable<LoginRoute> {
val viewModel: LoginScreenViewModel by viewModels()
LoginScreen(
viewModel.loginState,
viewModel::updateLoginUsername
)
LoginScreen(viewModel)
}
}
}

View file

@ -10,10 +10,13 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.pager.HorizontalPager
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.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Tab
@ -23,15 +26,17 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
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 kotlinx.coroutines.flow.StateFlow
import software.makeshift.debtpirate.R
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@Composable
fun LoginScreen(
loginState: StateFlow<LoginState>,
updateLoginUsername: (String) -> Unit
viewModel: LoginScreenViewModel
) {
Scaffold(modifier = Modifier.fillMaxSize()) {
Column {
@ -42,7 +47,9 @@ fun LoginScreen(
)
LoginAndSignUpForms(
loginState,
loginState = viewModel.loginState,
onUsernameUpdate = viewModel::updateLoginUsername,
onPasswordUpdate = viewModel::updateLoginPassword,
modifier = Modifier
.weight(3f)
)
@ -62,7 +69,9 @@ private fun Banner(modifier: Modifier = Modifier) {
@Composable
private fun LoginAndSignUpForms(
loginTabState: StateFlow<LoginState>,
loginState: LoginState,
onUsernameUpdate: (String) -> Unit,
onPasswordUpdate: (String) -> Unit,
modifier: Modifier = Modifier
) {
Column(modifier = modifier) {
@ -72,13 +81,12 @@ private fun LoginAndSignUpForms(
selectedTabIndex = pagerState.currentPage,
modifier = Modifier.height(48.dp)
) {
val tabTextStyle = MaterialTheme.typography.titleLarge
Tab(
selected = pagerState.currentPage == 0,
onClick = { pagerState.requestScrollToPage(0) },
text = {
Text(
text = stringResource(id = R.string.loginscreen_logintab_logintitle)
text = stringResource(id = R.string.login_screen__login)
)
},
modifier = Modifier.fillMaxHeight()
@ -88,7 +96,7 @@ private fun LoginAndSignUpForms(
onClick = { pagerState.requestScrollToPage(1) },
text = {
Text(
text = stringResource(id = R.string.loginscreen_logintab_signuptitle),
text = stringResource(id = R.string.login_screen__signup),
)
},
modifier = Modifier.fillMaxHeight()
@ -97,11 +105,13 @@ private fun LoginAndSignUpForms(
HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize()
modifier = Modifier
.fillMaxSize()
.imePadding()
) { page ->
when (page) {
0 -> {
Text("Page 1!")
LoginForm(state = loginState, onUsernameUpdate, onPasswordUpdate)
}
1 -> {
@ -112,9 +122,43 @@ private fun LoginAndSignUpForms(
}
}
//@Composable
//private fun LoginForm(state: StateFlow<LoginState>, onUsernameUpdate: (String) -> Unit, onPasswordUpdate: (String) -> Unit) {
// Column {
// OutlinedTextField(value = , onValueChange = )
// }
//}
@Composable
private fun LoginForm(
state: LoginState,
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
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
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(
val username: String? = null,
@ -17,16 +15,22 @@ data class SignUpState(
)
class LoginScreenViewModel : ViewModel() {
private val _loginState = MutableStateFlow(LoginState())
val loginState = _loginState.asStateFlow()
var loginState by mutableStateOf(LoginState())
private set
val loginUsername: Flow<String?>
get() = loginState.map { loginState -> loginState.username }
val loginUsername: String
get() = loginState.username
fun updateLoginUsername(username: String) {
_loginState.update { state ->
val (_, password) = state
LoginState(username, password)
}
val (_, password) = loginState
loginState = 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>
<!-- Login Screen -->
<string name="loginscreen_logintab_logintitle">Login</string>
<string name="loginscreen_logintab_signuptitle">Sign Up</string>
<string name="login_screen__login">Login</string>
<string name="login_screen__signup">Sign Up</string>
<string name="login_screen__username">Username</string>
<string name="login_screen__password">Password</string>
</resources>