From bab607a898fdbda3cb249392cd62d108350f2a1c Mon Sep 17 00:00:00 2001 From: "Z. Charles Dziura" Date: Tue, 20 Aug 2024 21:06:07 -0400 Subject: [PATCH] Separate the registration and sign in screens --- .../makeshift/debtpirate/MainActivity.kt | 8 +- .../debtpirate/screens/login/LoginScreen.kt | 88 +++++++----- .../debtpirate/screens/login/SignUpForm.kt | 136 ------------------ .../screens/login/SignUpFormViewModel.kt | 55 ------- .../screens/login/signup/SignUpForm.kt | 78 ++++++++++ .../screens/login/signup/SignUpViewModel.kt | 25 ++++ app/app/src/main/res/values/strings.xml | 3 +- 7 files changed, 158 insertions(+), 235 deletions(-) delete mode 100644 app/app/src/main/java/software/makeshift/debtpirate/screens/login/SignUpForm.kt delete mode 100644 app/app/src/main/java/software/makeshift/debtpirate/screens/login/SignUpFormViewModel.kt create mode 100644 app/app/src/main/java/software/makeshift/debtpirate/screens/login/signup/SignUpForm.kt create mode 100644 app/app/src/main/java/software/makeshift/debtpirate/screens/login/signup/SignUpViewModel.kt diff --git a/app/app/src/main/java/software/makeshift/debtpirate/MainActivity.kt b/app/app/src/main/java/software/makeshift/debtpirate/MainActivity.kt index 9de4bc6..a245b62 100644 --- a/app/app/src/main/java/software/makeshift/debtpirate/MainActivity.kt +++ b/app/app/src/main/java/software/makeshift/debtpirate/MainActivity.kt @@ -9,9 +9,9 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import kotlinx.serialization.Serializable -import software.makeshift.debtpirate.screens.login.`LoginFormViewModel.kt` +import software.makeshift.debtpirate.screens.login.LoginFormViewModel import software.makeshift.debtpirate.screens.login.LoginScreen -import software.makeshift.debtpirate.screens.login.SignUpFormViewModel +import software.makeshift.debtpirate.screens.login.signup.SignUpFormViewModel import software.makeshift.debtpirate.ui.theme.DebtPirateTheme @Serializable @@ -28,8 +28,8 @@ class MainActivity : ComponentActivity() { NavHost(navController = navController, startDestination = LoginRoute) { composable { LoginScreen( - `loginFormViewModel.kt` = viewModel<`LoginFormViewModel.kt`>(), - viewModel = viewModel() + loginFormViewModel = viewModel(), + signUpFormViewModel = viewModel() ) } } diff --git a/app/app/src/main/java/software/makeshift/debtpirate/screens/login/LoginScreen.kt b/app/app/src/main/java/software/makeshift/debtpirate/screens/login/LoginScreen.kt index 9c884d6..f789c06 100644 --- a/app/app/src/main/java/software/makeshift/debtpirate/screens/login/LoginScreen.kt +++ b/app/app/src/main/java/software/makeshift/debtpirate/screens/login/LoginScreen.kt @@ -7,6 +7,8 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -21,6 +23,7 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.SecondaryTabRow import androidx.compose.material3.Tab import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment @@ -29,65 +32,77 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import software.makeshift.debtpirate.R +import software.makeshift.debtpirate.screens.login.signup.SignUpForm +import software.makeshift.debtpirate.screens.login.signup.SignUpFormViewModel @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable fun LoginScreen( - `loginFormViewModel.kt`: `LoginFormViewModel.kt`, - viewModel: SignUpFormViewModel + loginFormViewModel: LoginFormViewModel, + signUpFormViewModel: SignUpFormViewModel ) { - Scaffold(modifier = Modifier.fillMaxSize()) { + Scaffold( + modifier = Modifier.fillMaxSize() + ) { innerPadding -> Column { - Banner( + LoginTopBar( + innerPadding, modifier = Modifier .fillMaxWidth() .weight(1f) ) - LoginAndSignUpForms( - `loginFormViewModel.kt`, - viewModel, + val displayName = signUpFormViewModel.displayName.collectAsState() + val emailAddress = signUpFormViewModel.emailAddress.collectAsState() + SignUpForm( + displayName, + onDisplayNameUpdate = signUpFormViewModel::updateDisplayName, + emailAddress, + onEmailAddressUpdate = signUpFormViewModel::updateEmailAddress, modifier = Modifier .weight(3f) + .padding(16.dp) ) } } } @Composable -private fun Banner(modifier: Modifier = Modifier) { +private fun LoginTopBar(innerPadding: PaddingValues, modifier: Modifier = Modifier) { Box(modifier = modifier.background(Color.Green)) { Text( text = "Hello from Login! I'm in a box!", modifier = Modifier.align(Alignment.Center) ) + + Row( + modifier = Modifier + .align(Alignment.TopEnd) + .padding(innerPadding) + .padding(16.dp) + ) + { + TextButton(onClick = { /*TODO*/ }) { + Text("Sign In") + } + } } } @OptIn(ExperimentalLayoutApi::class) @Composable private fun LoginAndSignUpForms( - `loginFormViewModel.kt`: `LoginFormViewModel.kt`, - viewModel: SignUpFormViewModel, + loginFormViewModel: LoginFormViewModel, + signUpFormViewModel: SignUpFormViewModel, modifier: Modifier = Modifier ) { Column(modifier = modifier) { - val pagerState = rememberPagerState(initialPage = 0) { 2 } + val pagerState = rememberPagerState(initialPage = 0) { 1 } SecondaryTabRow( selectedTabIndex = pagerState.currentPage, modifier = Modifier.height(48.dp) ) { - Tab( - selected = pagerState.currentPage == 0, - onClick = { pagerState.requestScrollToPage(0) }, - text = { - Text( - text = stringResource(id = R.string.login_screen__login) - ) - }, - modifier = Modifier.fillMaxHeight() - ) Tab( selected = pagerState.currentPage == 1, onClick = { pagerState.requestScrollToPage(1) }, @@ -98,6 +113,16 @@ private fun LoginAndSignUpForms( }, modifier = Modifier.fillMaxHeight() ) +// Tab( +// selected = pagerState.currentPage == 0, +// onClick = { pagerState.requestScrollToPage(0) }, +// text = { +// Text( +// text = stringResource(id = R.string.login_screen__login) +// ) +// }, +// modifier = Modifier.fillMaxHeight() +// ) } HorizontalPager( @@ -114,24 +139,11 @@ private fun LoginAndSignUpForms( when (page) { 0 -> { - LoginForm( - `loginFormViewModel.kt`.username, - `loginFormViewModel.kt`.password, - `loginFormViewModel.kt`::updateUsername, - `loginFormViewModel.kt`::updateLoginPassword, - formContainerModifier - ) - } - - 1 -> { - val signUpState = viewModel.signUpState.collectAsState() SignUpForm( - state = signUpState, - viewModel::updateFirstName, - viewModel::updateLastName, - viewModel::updateEmailAddress, - viewModel::updatePassword, - viewModel::updateConfirmPassword, + signUpFormViewModel.displayName.collectAsState(), + signUpFormViewModel::updateDisplayName, + signUpFormViewModel.emailAddress.collectAsState(), + signUpFormViewModel::updateEmailAddress, formContainerModifier ) } diff --git a/app/app/src/main/java/software/makeshift/debtpirate/screens/login/SignUpForm.kt b/app/app/src/main/java/software/makeshift/debtpirate/screens/login/SignUpForm.kt deleted file mode 100644 index 9765910..0000000 --- a/app/app/src/main/java/software/makeshift/debtpirate/screens/login/SignUpForm.kt +++ /dev/null @@ -1,136 +0,0 @@ -package software.makeshift.debtpirate.screens.login - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Lock -import androidx.compose.material.icons.outlined.Mail -import androidx.compose.material.icons.outlined.Password -import androidx.compose.material.icons.outlined.Person -import androidx.compose.material3.Button -import androidx.compose.material3.Icon -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.ui.Modifier -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 software.makeshift.debtpirate.R - -@Composable -internal fun SignUpForm( - state: State, - onFirstNameUpdate: (String) -> Unit, - onLastNameUpdate: (String) -> Unit, - onEmailUpdate: (String) -> Unit, - onPasswordUpdate: (String) -> Unit, - onPasswordConfirmedUpdate: (String) -> Unit, - modifier: Modifier = Modifier -) { - Column(modifier.verticalScroll(rememberScrollState())) - { - OutlinedTextField( - value = state.value.firstName, - label = { Text(stringResource(id = R.string.login_screen__first_name)) }, - placeholder = { Text(stringResource(id = R.string.login_screen__first_name)) }, - leadingIcon = { Icon(Icons.Outlined.Person, "person") }, - singleLine = true, - keyboardOptions = KeyboardOptions( - capitalization = KeyboardCapitalization.Words, - keyboardType = KeyboardType.Text, - imeAction = ImeAction.Next - ), - onValueChange = onFirstNameUpdate, - modifier = Modifier.fillMaxWidth() - ) - - OutlinedTextField( - value = state.value.lastName, - label = { Text(stringResource(id = R.string.login_screen__last_name)) }, - placeholder = { Text(stringResource(id = R.string.login_screen__last_name)) }, - leadingIcon = { Icon(Icons.Outlined.Person, "person") }, - singleLine = true, - keyboardOptions = KeyboardOptions( - capitalization = KeyboardCapitalization.Words, - keyboardType = KeyboardType.Text, - imeAction = ImeAction.Next - ), - onValueChange = onLastNameUpdate, - modifier = Modifier - .fillMaxWidth() - .padding(PaddingValues(top = 8.dp)) - ) - - OutlinedTextField( - value = state.value.email, - label = { Text(stringResource(id = R.string.login_screen__email)) }, - placeholder = { Text(stringResource(id = R.string.login_screen__email)) }, - leadingIcon = { Icon(Icons.Outlined.Mail, "email") }, - singleLine = true, - keyboardOptions = KeyboardOptions( - capitalization = KeyboardCapitalization.Unspecified, - keyboardType = KeyboardType.Email, - imeAction = ImeAction.Next - ), - onValueChange = onEmailUpdate, - modifier = Modifier - .fillMaxWidth() - .padding(PaddingValues(top = 8.dp)) - ) - - OutlinedTextField( - value = state.value.password, - label = { Text(stringResource(id = R.string.login_screen__password)) }, - placeholder = { Text(stringResource(id = R.string.login_screen__password)) }, - leadingIcon = { Icon(Icons.Outlined.Lock, "password") }, - singleLine = true, - keyboardOptions = KeyboardOptions( - capitalization = KeyboardCapitalization.Unspecified, - keyboardType = KeyboardType.Password, - imeAction = ImeAction.Next - ), - visualTransformation = PasswordVisualTransformation(), - onValueChange = onPasswordUpdate, - modifier = Modifier - .fillMaxWidth() - .padding(PaddingValues(top = 8.dp)) - ) - - OutlinedTextField( - value = state.value.passwordConfirmed, - label = { Text(stringResource(id = R.string.login_screen__confirm_password)) }, - placeholder = { Text(stringResource(id = R.string.login_screen__confirm_password)) }, - leadingIcon = { Icon(Icons.Outlined.Password, "confirm password") }, - singleLine = true, - keyboardOptions = KeyboardOptions( - capitalization = KeyboardCapitalization.Unspecified, - keyboardType = KeyboardType.Password, - imeAction = ImeAction.Send - ), - visualTransformation = PasswordVisualTransformation(), - onValueChange = onPasswordConfirmedUpdate, - modifier = Modifier - .fillMaxWidth() - .padding(PaddingValues(top = 8.dp)) - ) - - Button( - onClick = { /*TODO*/ }, - modifier = Modifier - .padding(PaddingValues(top = 32.dp)) - .fillMaxWidth() - ) { - Text(stringResource(id = R.string.login_screen__signup)) - } - } -} \ No newline at end of file diff --git a/app/app/src/main/java/software/makeshift/debtpirate/screens/login/SignUpFormViewModel.kt b/app/app/src/main/java/software/makeshift/debtpirate/screens/login/SignUpFormViewModel.kt deleted file mode 100644 index a37606f..0000000 --- a/app/app/src/main/java/software/makeshift/debtpirate/screens/login/SignUpFormViewModel.kt +++ /dev/null @@ -1,55 +0,0 @@ -package software.makeshift.debtpirate.screens.login - -import androidx.lifecycle.ViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow - -data class SignUpState( - val firstName: String = "", - val lastName: String = "", - val email: String = "", - val password: String = "", - val passwordConfirmed: String = "" -) - -class SignUpFormViewModel : ViewModel() { - private val _firstName = MutableStateFlow("") - val firstName = _firstName.asStateFlow() - - private val _lastName = MutableStateFlow("") - val lastName = _lastName.asStateFlow() - - private val _emailAddress = MutableStateFlow("") - val emailAddress = _emailAddress.asStateFlow() - - private val _password = MutableStateFlow("") - val password = _password.asStateFlow() - - private val _confirmPassword = MutableStateFlow("") - val confirmPassword = _confirmPassword.asStateFlow() - - - fun updateFirstName(firstName: String) { - _firstName.value = firstName - } - - fun updateLastName(lastName: String) { - _lastName.value = lastName - } - - fun updateEmailAddress(emailAddress: String) { - _emailAddress.value = emailAddress - } - - fun updatePassword(password: String) { - _password.value = password - } - - fun updateConfirmPassword(confirmPassword: String) { - _confirmPassword.value = confirmPassword - } - - fun isValidPassword() { - - } -} \ No newline at end of file diff --git a/app/app/src/main/java/software/makeshift/debtpirate/screens/login/signup/SignUpForm.kt b/app/app/src/main/java/software/makeshift/debtpirate/screens/login/signup/SignUpForm.kt new file mode 100644 index 0000000..09cf3fc --- /dev/null +++ b/app/app/src/main/java/software/makeshift/debtpirate/screens/login/signup/SignUpForm.kt @@ -0,0 +1,78 @@ +package software.makeshift.debtpirate.screens.login.signup + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Mail +import androidx.compose.material.icons.outlined.Person +import androidx.compose.material3.Button +import androidx.compose.material3.Icon +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.ui.Modifier +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.unit.dp +import software.makeshift.debtpirate.R + +@Composable +internal fun SignUpForm( + displayName: State, + onDisplayNameUpdate: (String) -> Unit, + emailAddress: State, + onEmailAddressUpdate: (String) -> Unit, + modifier: Modifier = Modifier +) { + Column(modifier.verticalScroll(rememberScrollState())) + { + OutlinedTextField( + value = displayName.value, + label = { Text(stringResource(id = R.string.login_screen__display_name)) }, + placeholder = { Text(stringResource(id = R.string.login_screen__display_name)) }, + leadingIcon = { Icon(Icons.Outlined.Person, "person") }, + singleLine = true, + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.Words, + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Next + ), + onValueChange = onDisplayNameUpdate, + modifier = Modifier.fillMaxWidth() + ) + + OutlinedTextField( + value = emailAddress.value, + label = { Text(stringResource(id = R.string.login_screen__email)) }, + placeholder = { Text(stringResource(id = R.string.login_screen__email)) }, + leadingIcon = { Icon(Icons.Outlined.Mail, "email") }, + singleLine = true, + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.Unspecified, + keyboardType = KeyboardType.Email, + imeAction = ImeAction.Next + ), + onValueChange = onEmailAddressUpdate, + modifier = Modifier + .fillMaxWidth() + .padding(PaddingValues(top = 8.dp)) + ) + + Button( + onClick = { /*TODO*/ }, + modifier = Modifier + .padding(PaddingValues(top = 32.dp)) + .fillMaxWidth() + ) { + Text(stringResource(id = R.string.login_screen__signup)) + } + } +} \ No newline at end of file diff --git a/app/app/src/main/java/software/makeshift/debtpirate/screens/login/signup/SignUpViewModel.kt b/app/app/src/main/java/software/makeshift/debtpirate/screens/login/signup/SignUpViewModel.kt new file mode 100644 index 0000000..5d613ec --- /dev/null +++ b/app/app/src/main/java/software/makeshift/debtpirate/screens/login/signup/SignUpViewModel.kt @@ -0,0 +1,25 @@ +package software.makeshift.debtpirate.screens.login.signup + +import androidx.lifecycle.ViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +class SignUpFormViewModel : ViewModel() { + private val _displayName = MutableStateFlow("") + val displayName = _displayName.asStateFlow() + + private val _emailAddress = MutableStateFlow("") + val emailAddress = _emailAddress.asStateFlow() + + fun updateDisplayName(firstName: String) { + _displayName.value = firstName + } + + fun updateEmailAddress(emailAddress: String) { + _emailAddress.value = emailAddress + } + + fun isValidPassword() { + + } +} \ No newline at end of file diff --git a/app/app/src/main/res/values/strings.xml b/app/app/src/main/res/values/strings.xml index f0cdae3..55f06c6 100644 --- a/app/app/src/main/res/values/strings.xml +++ b/app/app/src/main/res/values/strings.xml @@ -8,8 +8,7 @@ Email Address Password Confirm Password - First Name - Last Name + Display Name Forgot Password? \ No newline at end of file