diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index 92c1ebd..b268ef3 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -5,9 +5,6 @@ - - \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d7b113c..04421a8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -49,6 +49,7 @@ dependencies { implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) + testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) @@ -56,4 +57,12 @@ dependencies { androidTestImplementation(libs.androidx.ui.test.junit4) debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) + + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2") + implementation("com.squareup.retrofit2:retrofit:2.11.0") + implementation("com.squareup.retrofit2:converter-gson:2.11.0") + implementation("androidx.datastore:datastore-preferences:1.0.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0") + implementation("androidx.navigation:navigation-compose:2.7.0") } \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/AuthRemoteSourceImpl.kt b/app/src/main/java/com/example/shoesapptest/AuthRemoteSourceImpl.kt new file mode 100644 index 0000000..78f8d19 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/AuthRemoteSourceImpl.kt @@ -0,0 +1,19 @@ +package com.example.shoesapptest + +import com.example.shoesapptest.data.model.RegistrationRequest +import com.example.shoesapptest.data.model.TokenResponse +import com.example.shoesapptest.data.remote.AuthRemoteSource +import com.example.shoesapptest.data.remote.retrofit.Auth +import com.example.shoesapptest.data.remote.retrofit.RetrofitClient +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class AuthRemoteSourceImpl :AuthRemoteSource { + private val api: Auth = RetrofitClient.retrofit + + override suspend fun registration(registrationRequest: RegistrationRequest): TokenResponse { + return withContext(Dispatchers.IO) { + api.registration(registrationRequest) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/MainActivity.kt b/app/src/main/java/com/example/shoesapptest/MainActivity.kt index 53c2e0f..928a12b 100644 --- a/app/src/main/java/com/example/shoesapptest/MainActivity.kt +++ b/app/src/main/java/com/example/shoesapptest/MainActivity.kt @@ -1,30 +1,64 @@ -package com.example.shoesapptest +package com.example.shoesapptest.ui import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import com.example.shoesapp.ui.screen.SignInContent -import com.example.shoesapp.ui.screen.SigninScreen +import androidx.lifecycle.ViewModelProvider +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController import com.example.shoesapp.ui.theme.MatuleTheme -import com.example.shoesapptest.screen.ForgotPasswordScreen -import com.example.shoesapptest.screen.RegistrtionScreen +import com.example.shoesapptest.AuthRemoteSourceImpl +import com.example.shoesapptest.RegistrationViewModelFactory +import com.example.shoesapptest.data.local.datastore.LocalDataStore +import com.example.shoesapptest.data.repository.AuthRepositoryImpl +import com.example.shoesapptest.screen.RegistrationScreen +import com.example.shoesapptest.screen.TestScreen +import com.example.shoesapptest.screen.registrationscreen.RegistrationViewModel + + class MainActivity : ComponentActivity() { + private lateinit var authLocalStore: LocalDataStore + private lateinit var authRemoteSource: AuthRemoteSourceImpl + private lateinit var authRepository: AuthRepositoryImpl + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() + + // Инициализация зависимостей + authLocalStore = LocalDataStore(applicationContext) + authRemoteSource = AuthRemoteSourceImpl() + authRepository = AuthRepositoryImpl(authLocalStore, authRemoteSource) + setContent { MatuleTheme { - RegistrtionScreen() + val navController = rememberNavController() + NavHost( + navController = navController, + startDestination = "register" + ) { + composable("register") { + // Создание и передача ViewModel + val registrationViewModel: RegistrationViewModel = ViewModelProvider( + this@MainActivity, + RegistrationViewModelFactory(authRepository) + ).get(RegistrationViewModel::class.java) + + RegistrationScreen( + navController = navController, + registrationViewModel = registrationViewModel + ) + } + + composable("test") { + TestScreen() + } + } } } } -} \ No newline at end of file +} + diff --git a/app/src/main/java/com/example/shoesapptest/RegitrationViewModelFactory.kt b/app/src/main/java/com/example/shoesapptest/RegitrationViewModelFactory.kt new file mode 100644 index 0000000..b3109f7 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/RegitrationViewModelFactory.kt @@ -0,0 +1,18 @@ +package com.example.shoesapptest + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.example.shoesapptest.data.repository.AuthRepository +import com.example.shoesapptest.screen.registrationscreen.RegistrationViewModel + +class RegistrationViewModelFactory( + private val authRepository: AuthRepository +) : ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(RegistrationViewModel::class.java)) { + @Suppress("UNCHECKED_CAST") + return RegistrationViewModel(authRepository) as T + } + throw IllegalArgumentException("Unknown ViewModel class") + } +} diff --git a/app/src/main/java/com/example/shoesapptest/common/CommonButton.kt b/app/src/main/java/com/example/shoesapptest/common/CommonButton.kt new file mode 100644 index 0000000..8750ef0 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/common/CommonButton.kt @@ -0,0 +1,35 @@ +package com.example.shoesapptest.common + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonColors +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.focus.focusModifier +import androidx.compose.ui.unit.dp +import com.example.shoesapp.ui.theme.MatuleTheme + +@Composable +fun CommonButton( + modifier: Modifier = Modifier, + onClick: () -> Unit, + buttonColors: ButtonColors, + content: @Composable () -> Unit +){ + Button( + modifier = modifier.padding(horizontal = 20.dp) + .fillMaxWidth() + .height(50.dp) + .clip(RoundedCornerShape(14.dp)) + .background(MatuleTheme.colors.accent), + colors = buttonColors, + onClick = onClick + ){ + content() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/common/CommonTextField.kt b/app/src/main/java/com/example/shoesapptest/common/CommonTextField.kt new file mode 100644 index 0000000..5ead839 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/common/CommonTextField.kt @@ -0,0 +1,71 @@ +package com.example.shoesapptest.common + +import android.view.ViewAnimationUtils +import androidx.compose.foundation.background +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Text +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.example.shoesapp.ui.theme.MatuleTheme + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun CommonTextField( + value: String, + onChangeValue: (String) -> Unit, + modifier: Modifier = Modifier, + isError: Boolean = false, + visualTransformation: VisualTransformation = VisualTransformation.None, + trailingIcon: @Composable ()-> Unit = {}, + supportingText: @Composable ()-> Unit = {}, + placeHolder: @Composable ()-> Unit = {}, +){ + + val interaction = remember { MutableInteractionSource() } + BasicTextField( + value = value, + onValueChange = { onChangeValue(it) }, + modifier = modifier + .fillMaxWidth() + .clip(RoundedCornerShape(14.dp)) + .background(MatuleTheme.colors.background) + ){ innerTextField -> + TextFieldDefaults.DecorationBox( + value = value, + singleLine = true, + innerTextField = innerTextField, + enabled = true, + visualTransformation = visualTransformation, + interactionSource = interaction, + trailingIcon = trailingIcon, + isError = isError, + supportingText = if (isError) supportingText else null, + colors = TextFieldDefaults.colors( + focusedContainerColor = MatuleTheme.colors.background, + disabledContainerColor = MatuleTheme.colors.background, + unfocusedContainerColor = MatuleTheme.colors.background, + errorContainerColor = MatuleTheme.colors.background, + unfocusedIndicatorColor = Color.Transparent, + focusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + errorIndicatorColor = Color.Red + ), + placeholder = placeHolder + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/data/local/AuthLocalStore.kt b/app/src/main/java/com/example/shoesapptest/data/local/AuthLocalStore.kt new file mode 100644 index 0000000..d3fc738 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/data/local/AuthLocalStore.kt @@ -0,0 +1,9 @@ +package com.example.shoesapptest.data.local + +import com.example.shoesapptest.data.model.SaveTokenRequest +import com.example.shoesapptest.data.model.TokenResponse + +interface AuthLocalStore { + suspend fun getToken(): TokenResponse + suspend fun setToken(saveTokenRequest: SaveTokenRequest): Boolean +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/data/local/datastore/LocalDataStore.kt b/app/src/main/java/com/example/shoesapptest/data/local/datastore/LocalDataStore.kt new file mode 100644 index 0000000..6a9627d --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/data/local/datastore/LocalDataStore.kt @@ -0,0 +1,30 @@ +package com.example.shoesapptest.data.local.datastore + +import android.content.Context +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.preferencesDataStore +import com.example.shoesapptest.data.local.AuthLocalStore +import com.example.shoesapptest.data.model.SaveTokenRequest +import com.example.shoesapptest.data.model.TokenResponse +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map + + +private val Context.dataStore by preferencesDataStore(name="auth") + +class LocalDataStore(context: Context): AuthLocalStore { + private val dataStore = context.dataStore + + override suspend fun getToken(): TokenResponse { + val token = dataStore.data.map { preferences -> + preferences[stringPreferencesKey("token")] ?: "" + }.first() + return TokenResponse("token") + } + + override suspend fun setToken(saveTokenRequest: SaveTokenRequest): Boolean { + dataStore.edit { prefences -> prefences[stringPreferencesKey("token")] = saveTokenRequest.tokenAuthentication } + return true + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/data/model/RegistrationRequest.kt b/app/src/main/java/com/example/shoesapptest/data/model/RegistrationRequest.kt new file mode 100644 index 0000000..38dda16 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/data/model/RegistrationRequest.kt @@ -0,0 +1,7 @@ +package com.example.shoesapptest.data.model + +data class RegistrationRequest( + val userName: String, + val email: String, + val password: String +) diff --git a/app/src/main/java/com/example/shoesapptest/data/model/SaveTokenRequest.kt b/app/src/main/java/com/example/shoesapptest/data/model/SaveTokenRequest.kt new file mode 100644 index 0000000..a6617fd --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/data/model/SaveTokenRequest.kt @@ -0,0 +1,5 @@ +package com.example.shoesapptest.data.model + +data class SaveTokenRequest( + val tokenAuthentication: String +) diff --git a/app/src/main/java/com/example/shoesapptest/data/model/TokenResponse.kt b/app/src/main/java/com/example/shoesapptest/data/model/TokenResponse.kt new file mode 100644 index 0000000..f8c4e02 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/data/model/TokenResponse.kt @@ -0,0 +1,5 @@ +package com.example.shoesapptest.data.model + +data class TokenResponse( + val tokenAuthentication: String +) diff --git a/app/src/main/java/com/example/shoesapptest/data/remote/AuthRemoteSource.kt b/app/src/main/java/com/example/shoesapptest/data/remote/AuthRemoteSource.kt new file mode 100644 index 0000000..b13ca46 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/data/remote/AuthRemoteSource.kt @@ -0,0 +1,8 @@ +package com.example.shoesapptest.data.remote + +import com.example.shoesapptest.data.model.RegistrationRequest +import com.example.shoesapptest.data.model.TokenResponse + +interface AuthRemoteSource { + suspend fun registration(registrationRequest: RegistrationRequest):TokenResponse +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/data/remote/retrofit/Auth.kt b/app/src/main/java/com/example/shoesapptest/data/remote/retrofit/Auth.kt new file mode 100644 index 0000000..6f5f6cb --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/data/remote/retrofit/Auth.kt @@ -0,0 +1,12 @@ +package com.example.shoesapptest.data.remote.retrofit + +import com.example.shoesapptest.data.model.RegistrationRequest +import com.example.shoesapptest.data.model.TokenResponse +import com.example.shoesapptest.data.remote.AuthRemoteSource +import retrofit2.http.Body +import retrofit2.http.POST + +interface Auth:AuthRemoteSource { + @POST("/registration") + override suspend fun registration(@Body registrationRequest: RegistrationRequest): TokenResponse +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/data/remote/retrofit/RetrofitClient.kt b/app/src/main/java/com/example/shoesapptest/data/remote/retrofit/RetrofitClient.kt new file mode 100644 index 0000000..7874d90 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/data/remote/retrofit/RetrofitClient.kt @@ -0,0 +1,15 @@ +package com.example.shoesapptest.data.remote.retrofit + +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +private const val URL = "http://172.18.112.1:8080" +object RetrofitClient { + private val retrofitBuilder = Retrofit.Builder() + .baseUrl(URL) + .addConverterFactory(GsonConverterFactory.create()) + .build() + val retrofit by lazy { + retrofitBuilder.create(Auth::class.java) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/data/repository/AuthRepository.kt b/app/src/main/java/com/example/shoesapptest/data/repository/AuthRepository.kt new file mode 100644 index 0000000..1e081db --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/data/repository/AuthRepository.kt @@ -0,0 +1,10 @@ +package com.example.shoesapptest.data.repository + +import com.example.shoesapptest.data.model.RegistrationRequest +import com.example.shoesapptest.data.model.TokenResponse + + +interface AuthRepository { + suspend fun registration(registrationRequest: RegistrationRequest): TokenResponse + suspend fun login() +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/example/shoesapptest/data/repository/AuthRepositoryImpl.kt new file mode 100644 index 0000000..ffd8f30 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/data/repository/AuthRepositoryImpl.kt @@ -0,0 +1,23 @@ +package com.example.shoesapptest.data.repository + +import com.example.shoesapptest.data.local.AuthLocalStore +import com.example.shoesapptest.data.model.RegistrationRequest +import com.example.shoesapptest.data.model.SaveTokenRequest +import com.example.shoesapptest.data.model.TokenResponse +import com.example.shoesapptest.data.remote.AuthRemoteSource + +class AuthRepositoryImpl( + private val authLocalStore: AuthLocalStore, + private val authRemoteSource: AuthRemoteSource +):AuthRepository { + + override suspend fun registration(registrationRequest: RegistrationRequest): TokenResponse { + val tokenResponse = authRemoteSource.registration(registrationRequest) + authLocalStore.setToken(SaveTokenRequest(tokenResponse.tokenAuthentication)) + return tokenResponse + } + + override suspend fun login() { + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/TestScreen.kt b/app/src/main/java/com/example/shoesapptest/screen/TestScreen.kt new file mode 100644 index 0000000..3b61d6b --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/TestScreen.kt @@ -0,0 +1,18 @@ +package com.example.shoesapptest.screen + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier + +@Composable +fun TestScreen() { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text(text = "Добро пожаловать!") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/ChangePass.kt b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/ChangePass.kt new file mode 100644 index 0000000..de737bb --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/ChangePass.kt @@ -0,0 +1,6 @@ +package com.example.shoesapptest.screen.forgotscreen + +data class ChangePass( + var email: String = "", + var errorMessage: String? = null +) diff --git a/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/ForgotPasswordScreen.kt b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/ForgotPasswordScreen.kt new file mode 100644 index 0000000..b5694e1 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/ForgotPasswordScreen.kt @@ -0,0 +1,166 @@ +package com.example.shoesapptest.screen + +import android.app.Dialog +import androidx.compose.foundation.background +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.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonColors +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.example.shoesapp.ui.theme.MatuleTheme +import com.example.shoesapptest.R +import androidx.compose.material3.AlertDialog +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import androidx.compose.ui.input.pointer.motionEventSpy +import androidx.compose.ui.res.colorResource +import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.shoesapptest.screen.forgotscreen.ForgotPasswordViewModel +import com.example.shoesapptest.screen.forgotscreen.component.TitleWithSubtitleText +import com.example.shoesapptest.screen.forgotscreen.component.EmailTextField +import com.example.shoesapptest.screen.forgotscreen.component.SendButton + + +@Composable +fun ForgotPasswordScreen(){ + val forgotPasswordViewModel: ForgotPasswordViewModel = viewModel() + val showDialog = remember { mutableStateOf(false) } + + + Scaffold( + topBar = { + Row( + modifier = Modifier + .padding(top = 35.dp) + .fillMaxWidth() + .height(40.dp) + ) { + IconButton(onClick = {}) { + Icon(painter= painterResource(R.drawable.back_arrow), + contentDescription = null) + } + } + } + ){ paddingValues -> + ForgotPasswordContent(paddingValues, showDialog, forgotPasswordViewModel) + } + + if (showDialog.value){ + CheckEmailDialog(onDismiss = {showDialog.value=false}) + } +} + +@Composable +fun ForgotPasswordContent( + paddingValues: PaddingValues, + showDialog: MutableState, + forgotPasswordViewModel: ForgotPasswordViewModel +){ + val changePass = forgotPasswordViewModel.changePass + Column( + modifier = Modifier.fillMaxWidth() + .padding(paddingValues), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ){ + TitleWithSubtitleText( + title = stringResource(R.string.title_forgot_password), + subTitle = stringResource(R.string.subtitle_forgot_password) + ) + Spacer(modifier = Modifier.height(35.dp)) + EmailTextField( + value = changePass.value.email, + onChangeValue = {forgotPasswordViewModel.setEmail(it)}, + isError = forgotPasswordViewModel.emailHasError.value, + supportingText = {Text(text = stringResource(R.string.wrong_email))}, + placeholder = { Text(text = stringResource(R.string.placeholder_email))}, + label = { Text(text = stringResource(R.string.email))} + ) + SendButton(onClick = {showDialog.value = true}) { Text(text="Отправить") } + } +} + +@Composable +fun CheckEmailDialog(onDismiss: () -> Unit) { + AlertDialog( + onDismissRequest = onDismiss, + confirmButton = {}, + title = { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier.padding(bottom = 8.dp), + horizontalArrangement = Arrangement.Center + ) { + Icon( + painter = painterResource(R.drawable.email_image), + contentDescription = null, + tint = MatuleTheme.colors.accent, + modifier = Modifier.size(40.dp) + ) + } + Text( + text = "Проверьте Ваш Email", + style = MatuleTheme.typography.bodyRegular16.copy(color = MatuleTheme.colors.text), + textAlign = TextAlign.Center + ) + } + }, + text = { + Text( + text = "Мы отправили код восстановления пароля на вашу электронную почту.", + textAlign = TextAlign.Center, + style = MatuleTheme.typography.bodyRegular14.copy(color = MatuleTheme.colors.hint) + ) + }, + modifier = Modifier.clip(RoundedCornerShape(14.dp)), + containerColor = Color.White + ) +} + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/ForgotPasswordViewModel.kt b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/ForgotPasswordViewModel.kt new file mode 100644 index 0000000..ec5ff68 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/ForgotPasswordViewModel.kt @@ -0,0 +1,16 @@ +package com.example.shoesapptest.screen.forgotscreen + +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.mutableStateOf + +class ForgotPasswordViewModel { + var changePass = mutableStateOf(ChangePass()) + private set + val emailHasError = derivedStateOf { + if(changePass.value.email.isEmpty()) return@derivedStateOf false + !android.util.Patterns.EMAIL_ADDRESS.matcher(changePass.value.email).matches() + } + fun setEmail(email: String){ + changePass.value = changePass.value.copy(email=email) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/component/EmailTextField.kt b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/component/EmailTextField.kt new file mode 100644 index 0000000..61406ab --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/component/EmailTextField.kt @@ -0,0 +1,34 @@ +package com.example.shoesapptest.screen.forgotscreen.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.example.shoesapptest.common.CommonTextField + +@Composable +fun EmailTextField(value: String, + onChangeValue: (String)->Unit, + isError: Boolean, + supportingText: @Composable () -> Unit, + placeholder: @Composable () -> Unit, + label: @Composable () -> Unit) { + Column( + modifier = Modifier + .padding(20.dp) + .wrapContentSize(), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + label() + CommonTextField( + value = value, + onChangeValue = onChangeValue, + isError = isError, + supportingText = supportingText, + placeHolder = placeholder + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/component/SendButton.kt b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/component/SendButton.kt new file mode 100644 index 0000000..a00ed58 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/component/SendButton.kt @@ -0,0 +1,29 @@ +package com.example.shoesapptest.screen.forgotscreen.component + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ButtonColors +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.example.shoesapp.ui.theme.MatuleTheme +import com.example.shoesapptest.common.CommonButton + +@Composable +fun SendButton( + modifier: Modifier = Modifier, + onClick: () -> Unit, + content: @Composable () -> Unit +){ + CommonButton( + onClick = onClick, + modifier = modifier.padding(50.dp), + buttonColors = ButtonColors( + containerColor = MatuleTheme.colors.accent, + contentColor = MatuleTheme.colors.background, + disabledContentColor = MatuleTheme.colors.accent, + disabledContainerColor = MatuleTheme.colors.accent + ) + ) { + content() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/component/TitleWithSubtitle.kt b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/component/TitleWithSubtitle.kt new file mode 100644 index 0000000..95fbf24 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/forgotscreen/component/TitleWithSubtitle.kt @@ -0,0 +1,37 @@ +package com.example.shoesapptest.screen.forgotscreen.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.example.shoesapp.ui.theme.MatuleTheme + +@Composable +fun TitleWithSubtitleText(title: String, subTitle:String){ + Column( + modifier = Modifier + .padding(horizontal = 20.dp) + .padding(top = 50.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) + { + Text( + text = title, + style = MatuleTheme.typography.headingBold32.copy(color = MatuleTheme.colors.text), + textAlign = TextAlign.Center + ) + Text( + text = subTitle, + maxLines = 2, + style = MatuleTheme.typography.subTitleRegular16.copy(color = MatuleTheme.colors.subTextDark), + textAlign = TextAlign.Center + ) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/Registration.kt b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/Registration.kt new file mode 100644 index 0000000..d02b465 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/Registration.kt @@ -0,0 +1,13 @@ +package com.example.shoesapptest.screen.registrationscreen + +import android.provider.ContactsContract.CommonDataKinds.Email +import com.example.shoesapptest.screen.forgotscreen.ChangePass +import java.lang.Error + +data class Registration( + var email: String = "", + var password: String = "", + var name: String = "", + var isVisiblePassword: Boolean = false, + var errorMessage: String? = null +) diff --git a/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/RegistrationScreen.kt b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/RegistrationScreen.kt new file mode 100644 index 0000000..bda142d --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/RegistrationScreen.kt @@ -0,0 +1,197 @@ +package com.example.shoesapptest.screen + +import androidx.compose.foundation.background +import androidx.compose.foundation.interaction.MutableInteractionSource +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.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.ClickableText +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonColors +import androidx.compose.material3.Checkbox +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import com.example.shoesapptest.R +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.text.style.TextAlign +import androidx.navigation.NavController +import com.example.shoesapp.ui.theme.MatuleTheme +import com.example.shoesapptest.screen.forgotscreen.component.TitleWithSubtitleText +import com.example.shoesapptest.screen.registrationscreen.RegistrationViewModel +import com.example.shoesapptest.screen.registrationscreen.component.RegistrationBtn +import com.example.shoesapptest.screen.registrationscreen.component.RegistrationTextField + +@Composable +fun RegistrationScreen( + navController: NavController, + registrationViewModel: RegistrationViewModel +){ + Scaffold( + topBar = { + Row( + modifier = Modifier + .padding(top = 35.dp) + .fillMaxWidth() + .height(40.dp) + ){ + IconButton(onClick={}) { + Icon(painter = painterResource(R.drawable.back_arrow), + contentDescription = null) + } + } + }, + bottomBar = { + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .padding(bottom = 50.dp) + .fillMaxWidth() + .height(40.dp) + ) { + Text( + text= stringResource(R.string.sign_in_on_reg), + style=MatuleTheme.typography.bodyRegular16.copy(MatuleTheme.colors.text), + textAlign = TextAlign.Center + ) + } + } + ) { paddingValues -> + RegistrationScreen( + paddingValues=paddingValues, + registrationViewModel=registrationViewModel, + onRegistrationSuccess = {navController.navigate("test")}, + onRegistrationError = {errorMessage -> } + ) + } +} + +@Composable +fun RegistrationScreen(paddingValues: PaddingValues, + registrationViewModel: RegistrationViewModel, + onRegistrationSuccess: () -> Unit, + onRegistrationError: (String) -> Unit){ + val register = registrationViewModel.registration + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(20.dp) + ) { + TitleWithSubtitleText( + title = "Регистрация", + subTitle = "Заполните Свои данные или продолжите через социальные медиа" + ) + + Spacer(modifier = Modifier.height(20.dp)) + + RegistrationTextField( + value = register.value.name, + onChangeValue = { registrationViewModel.setUserName(it) }, + isError = false, + supportingText = { Text(text = stringResource(R.string.wrong_name)) }, + placeholder = { Text(text = stringResource(R.string.template_name)) }, + label = { Text(text = stringResource(R.string.name)) } + ) + RegistrationTextField( + value = register.value.email, + onChangeValue = { registrationViewModel.setEmail(it) }, + isError = registrationViewModel.emailHasError.value, + supportingText = { Text(text = stringResource(R.string.wrong_email)) }, + placeholder = { Text(text = stringResource(R.string.template_email)) }, + label = { Text(text = stringResource(R.string.email)) } + ) + RegistrationTextField( + value = register.value.password, + onChangeValue = { registrationViewModel.setPassword(it) }, + isError = false, + supportingText = { Text(text = stringResource(R.string.wrong_password)) }, + placeholder = { Text(text = stringResource(R.string.template_password)) }, + label = { Text(text = stringResource(R.string.password)) } + ) + + SimpleCheckbox() + + RegistrationBtn(onClick = { + registrationViewModel.registration( + onSuccess = { + onRegistrationSuccess() + }, + onError = { errorMessage -> + + onRegistrationError(errorMessage) + } + ) + } + ) { + Text(text = stringResource(R.string.sign_up_on_reg)) + } + } +} + +@Composable +fun SimpleCheckbox(){ + val isChecked = remember { mutableStateOf(false) } + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + .padding(16.dp) + ){ + Checkbox( + checked = isChecked.value, + onCheckedChange = {isChecked.value = it} + ) + ClickableText( + text = AnnotatedString( + "Даю согласие на обработку персональных данных" + ), + onClick={}, + style = MatuleTheme.typography.bodyRegular16.copy(color = MatuleTheme.colors.text), + modifier = Modifier.padding(start = 8.dp) + ) + } +} + + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/RegistrationViewModel.kt b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/RegistrationViewModel.kt new file mode 100644 index 0000000..1bd31b5 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/RegistrationViewModel.kt @@ -0,0 +1,47 @@ +package com.example.shoesapptest.screen.registrationscreen + +import androidx.compose.animation.core.animateDecay +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.shoesapptest.data.model.RegistrationRequest +import com.example.shoesapptest.data.repository.AuthRepository +import kotlinx.coroutines.launch +import java.lang.Error + +class RegistrationViewModel( + private val authRepository: AuthRepository +):ViewModel() { + var registration = mutableStateOf(Registration()) + private set + val emailHasError = derivedStateOf { + if (registration.value.email.isEmpty()) return@derivedStateOf false + !android.util.Patterns.EMAIL_ADDRESS.matcher(registration.value.email).matches() + } + fun setEmail(email: String){ + registration.value=registration.value.copy(email=email) + } + fun setPassword(password: String){ + registration.value = registration.value.copy(password=password) + } + fun setUserName(name: String){ + registration.value = registration.value.copy(name=name) + } + fun registration(onSuccess: () -> Unit, onError: (String) -> Unit){ + viewModelScope.launch { + try { + val registrationRequest = RegistrationRequest( + userName = registration.value.name, + email = registration.value.email, + password = registration.value.password + ) + + authRepository.registration(registrationRequest) + onSuccess() + } catch (e: Exception) { + onError(e.message ?: "Ошибка регистрации") + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/component/RegistrationBtn.kt b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/component/RegistrationBtn.kt new file mode 100644 index 0000000..c4a3db1 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/component/RegistrationBtn.kt @@ -0,0 +1,26 @@ +package com.example.shoesapptest.screen.registrationscreen.component + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ButtonColors +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.example.shoesapp.ui.theme.MatuleTheme +import com.example.shoesapptest.common.CommonButton + +@Composable +fun RegistrationBtn( + onClick: () -> Unit, + content: @Composable () -> Unit +){ + CommonButton( + modifier = Modifier.padding(50.dp), + onClick = onClick, + buttonColors = ButtonColors( + containerColor = MatuleTheme.colors.accent, + contentColor = MatuleTheme.colors.background, + disabledContainerColor = MatuleTheme.colors.accent, + disabledContentColor = MatuleTheme.colors.accent + ) + ) { content()} +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/component/RegistrationTextField.kt b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/component/RegistrationTextField.kt new file mode 100644 index 0000000..0a9fa77 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/component/RegistrationTextField.kt @@ -0,0 +1,36 @@ +package com.example.shoesapptest.screen.registrationscreen.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.Placeholder +import androidx.compose.ui.unit.dp +import androidx.datastore.preferences.protobuf.Internal.BooleanList +import com.example.shoesapptest.common.CommonTextField +import java.lang.Error + +@Composable +fun RegistrationTextField( + value: String, + onChangeValue: (String) -> Unit, + isError: Boolean, + supportingText: @Composable () -> Unit, + placeholder: @Composable () -> Unit, + label: @Composable () -> Unit +){ + Column(Modifier.padding(50.dp) + .wrapContentSize(), + verticalArrangement = Arrangement.spacedBy(12.dp)){ + label() + CommonTextField( + value=value, + onChangeValue=onChangeValue, + isError = isError, + supportingText = supportingText, + placeHolder = placeholder + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/component/TitleWithSubtitle.kt b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/component/TitleWithSubtitle.kt new file mode 100644 index 0000000..6573177 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/registrationscreen/component/TitleWithSubtitle.kt @@ -0,0 +1,35 @@ +package com.example.shoesapptest.screen.registrationscreen.component + +import android.icu.text.CaseMap.Title +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ModifierLocalBeyondBoundsLayout +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.example.shoesapp.ui.theme.MatuleTheme + +@Composable +fun TextWithSubTitle(title: String, + subtitle:String){ + Column( + modifier = Modifier.padding(horizontal = 20.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(8.dp) + ){ + Text( + text = title, + style = MatuleTheme.typography.headingBold32.copy(color = MatuleTheme.colors.text), + textAlign = TextAlign.Center + ) + Text( + text = subtitle, + style = MatuleTheme.typography.subTitleRegular16.copy(color = MatuleTheme.colors.subTextDark), + textAlign = TextAlign.Center + ) + } +} diff --git a/app/src/main/java/com/example/shoesapptest/screen/signin/SignInState.kt b/app/src/main/java/com/example/shoesapptest/screen/signin/SignInState.kt new file mode 100644 index 0000000..85836bf --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/signin/SignInState.kt @@ -0,0 +1,10 @@ +package com.example.shoesapptest.screen.signin + +data class SignInState ( + var email: String = "", + var password: String = "", + var isVisiblePassword: Boolean = false, + var isLoading: Boolean = false, + var isSignIn: Boolean = false, + var errorMessage: String? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/signin/SignInViewModel.kt b/app/src/main/java/com/example/shoesapptest/screen/signin/SignInViewModel.kt new file mode 100644 index 0000000..3675971 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/signin/SignInViewModel.kt @@ -0,0 +1,27 @@ +package com.example.shoesapptest.screen.signin + +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.ViewModel + +class SignInViewMode: ViewModel(){ + var signInState = mutableStateOf(SignInState()) + private set + + val emailHasError = derivedStateOf { + if(signInState.value.email.isEmpty()) return@derivedStateOf false + !android.util.Patterns.EMAIL_ADDRESS.matcher(signInState.value.email).matches() + } + + fun setEmail(email: String){ + signInState.value = signInState.value.copy(email = email) + } + + + fun setPassword(password: String){ + signInState.value = signInState.value.copy(password = password) + } + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/signin/SigninScreen.kt b/app/src/main/java/com/example/shoesapptest/screen/signin/SigninScreen.kt new file mode 100644 index 0000000..369eaf5 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/signin/SigninScreen.kt @@ -0,0 +1,128 @@ +package com.example.shoesapp.ui.screen + + +import androidx.compose.foundation.background +import androidx.compose.foundation.interaction.MutableInteractionSource +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.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonColors +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.shoesapp.ui.theme.MatuleTheme +import com.example.shoesapptest.R +import com.example.shoesapptest.screen.signin.SignInViewMode +import com.example.shoesapptest.screen.signin.component.AuthButton +import com.example.shoesapptest.screen.signin.component.AuthTextField +import com.example.shoesapptest.screen.signin.component.TitleWithSubtitleText + + +@Composable +fun SigninScreen() { + val signInViewModel: SignInViewMode = viewModel() + Scaffold( + topBar = { + Row( + modifier = Modifier + .padding(top = 35.dp) + .fillMaxWidth() + .height(40.dp) + ) { + IconButton(onClick = {}) { + Icon( + painter = painterResource(R.drawable.back_arrow), + contentDescription = null + ) + } + } + }, + bottomBar = { + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .padding(bottom = 50.dp) + .fillMaxWidth() + .height(40.dp) + ) { + Text( + stringResource(R.string.sign_up), + style = MatuleTheme.typography.bodyRegular16.copy(color = MatuleTheme.colors.text), + textAlign = TextAlign.Center + ) + } + } + ) { paddingValues -> + SignInContent(paddingValues, signInViewModel) + } +} + +@Composable +fun SignInContent(paddingValues: PaddingValues, signInViewMode: SignInViewMode) { + val signInState = signInViewMode.signInState + Column( + modifier = Modifier.padding(paddingValues = paddingValues), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + TitleWithSubtitleText( + title = stringResource(R.string.hello), + subText = stringResource(R.string.sign_in_subtitle) + ) + Spacer(modifier = Modifier.height(35.dp)) + + + AuthTextField( + value = signInState.value.email, + onChangeValue = { signInViewMode.setEmail(it) }, + isError = signInViewMode.emailHasError.value, + supportingText = { Text(text = stringResource(R.string.wrong_email))}, + placeholder = { Text(text = stringResource(R.string.template_email)) }, + label = { Text(text = stringResource(R.string.email)) + } + ) + + AuthTextField( + value = signInState.value.password, + onChangeValue = { signInViewMode.setPassword(it)}, + isError = false, + supportingText = { Text(text = "Неверный пароль")}, + placeholder = { Text(text = stringResource(R.string.template_password))}, + label = { Text(text = stringResource(R.string.password))} + ) + AuthButton(onClick = {}) { + Text(stringResource(R.string.sign_in)) + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/signin/component/AuthButton.kt b/app/src/main/java/com/example/shoesapptest/screen/signin/component/AuthButton.kt new file mode 100644 index 0000000..a820b9d --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/signin/component/AuthButton.kt @@ -0,0 +1,27 @@ +package com.example.shoesapptest.screen.signin.component + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ButtonColors +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.example.shoesapp.ui.theme.MatuleTheme +import com.example.shoesapptest.common.CommonButton + +@Composable +fun AuthButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + content: @Composable () -> Unit +){ + CommonButton( + onClick = onClick, + buttonColors = ButtonColors( + contentColor = MatuleTheme.colors.background, + containerColor = MatuleTheme.colors.accent, + disabledContainerColor = MatuleTheme.colors.accent, + disabledContentColor = MatuleTheme.colors.accent + ), + modifier = modifier.padding(50.dp) + ) { content()} +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/signin/component/AuthTextField.kt b/app/src/main/java/com/example/shoesapptest/screen/signin/component/AuthTextField.kt new file mode 100644 index 0000000..65c65f9 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/signin/component/AuthTextField.kt @@ -0,0 +1,36 @@ +package com.example.shoesapptest.screen.signin.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.example.shoesapptest.common.CommonTextField + +@Composable +fun AuthTextField( + value: String, + onChangeValue: (String)-> Unit, + isError: Boolean, + supportingText: @Composable () -> Unit, + placeholder: @Composable () -> Unit, + label: @Composable () -> Unit) +{ + Column( + modifier = Modifier + .padding(horizontal = 20.dp) + .wrapContentSize(), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + label() + CommonTextField( + value = value, + onChangeValue = onChangeValue, + isError = isError, + supportingText = supportingText, + placeHolder = placeholder + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/screen/signin/component/TitleWithSubtitleText.kt b/app/src/main/java/com/example/shoesapptest/screen/signin/component/TitleWithSubtitleText.kt new file mode 100644 index 0000000..0669115 --- /dev/null +++ b/app/src/main/java/com/example/shoesapptest/screen/signin/component/TitleWithSubtitleText.kt @@ -0,0 +1,33 @@ +package com.example.shoesapptest.screen.signin.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.example.shoesapp.ui.theme.MatuleTheme + +@Composable +fun TitleWithSubtitleText(title: String, subText: String) { + Column( + modifier = Modifier.padding(horizontal = 20.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = title, + style = MatuleTheme.typography.headingBold32.copy(color = MatuleTheme.colors.text), + textAlign = TextAlign.Center, + ) + Text( + text = subText, + maxLines = 2, + style = MatuleTheme.typography.subTitleRegular16.copy(color = MatuleTheme.colors.subTextDark), + textAlign = TextAlign.Center, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/ui/common/CommonButton.kt b/app/src/main/java/com/example/shoesapptest/ui/common/CommonButton.kt deleted file mode 100644 index 7c54ce8..0000000 --- a/app/src/main/java/com/example/shoesapptest/ui/common/CommonButton.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.example.shoesapptest.ui.common - diff --git a/app/src/main/java/com/example/shoesapptest/ui/common/CommonTextField.kt b/app/src/main/java/com/example/shoesapptest/ui/common/CommonTextField.kt deleted file mode 100644 index 2ed45a8..0000000 --- a/app/src/main/java/com/example/shoesapptest/ui/common/CommonTextField.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.example.shoesapptest.ui.screen.signin.component - diff --git a/app/src/main/java/com/example/shoesapptest/ui/screen/forgotscreen/ForgotPasswordScreen.kt b/app/src/main/java/com/example/shoesapptest/ui/screen/forgotscreen/ForgotPasswordScreen.kt deleted file mode 100644 index 1c68ee3..0000000 --- a/app/src/main/java/com/example/shoesapptest/ui/screen/forgotscreen/ForgotPasswordScreen.kt +++ /dev/null @@ -1,260 +0,0 @@ -package com.example.shoesapptest.screen - -import android.app.Dialog -import androidx.compose.foundation.background -import androidx.compose.foundation.interaction.MutableInteractionSource -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.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.BasicTextField -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonColors -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.ModalBottomSheetDefaults -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.TextFieldDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.DialogProperties -import com.example.shoesapp.ui.theme.MatuleTheme -import com.example.shoesapptest.R -import androidx.compose.material3.AlertDialog -import androidx.compose.runtime.getValue -import androidx.compose.runtime.setValue - -@Composable -fun ForgotPasswordScreen(){ - Scaffold( - topBar = { - Row( - modifier = Modifier - .padding(top = 35.dp) - .fillMaxWidth() - .height(40.dp) - ) { - IconButton(onClick = {}) { - Icon(painter= painterResource(R.drawable.back_arrow), - contentDescription = null) - } - } - } - ){ paddingValues -> - ScreenContent(paddingValues) - } - -} - -@Composable -fun ScreenContent(paddingValues: PaddingValues){ -Column( - modifier = Modifier.padding(paddingValues = paddingValues) -){ - TitleWithSubtitleText( - title = stringResource(R.string.title_forgot_password), - subTitle = stringResource(R.string.subtitle_forgot_password) - ) - val email = remember { mutableStateOf("") } - Spacer(modifier = Modifier.height(35.dp)) - EmailTextField( - placeHolderText = stringResource(R.string.placeholder_email), - EmailValue = email.value, - onEmailChange = { - email.value=it - } - ) -} -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun EmailTextField(EmailValue: String, - onEmailChange: (String) -> Unit, - placeHolderText: String){ - Column( - modifier = Modifier - .padding(20.dp) - .wrapContentSize(), - verticalArrangement = Arrangement.spacedBy(8.dp) - ){ - val email = remember { MutableInteractionSource() } - BasicTextField( - value=EmailValue, - onValueChange = {onEmailChange(it)}, - modifier = Modifier - .padding(horizontal = 20.dp) - .fillMaxWidth() - .clip(RoundedCornerShape(14.dp)) - .background(MatuleTheme.colors.background) - ){ innerTextField -> - TextFieldDefaults.DecorationBox( - value = EmailValue, - singleLine = true, - innerTextField = innerTextField, - colors = TextFieldDefaults.colors( - focusedContainerColor = MatuleTheme.colors.background, - disabledContainerColor = MatuleTheme.colors.background, - unfocusedContainerColor = MatuleTheme.colors.background, - errorContainerColor = MatuleTheme.colors.background, - unfocusedIndicatorColor = Color.Transparent, - focusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - errorIndicatorColor = Color.Transparent - ), - visualTransformation = VisualTransformation.None, - interactionSource = email, - enabled = true, - placeholder = { - if (placeHolderText != null) - Text( - text = placeHolderText, - style = MatuleTheme.typography.bodyRegular14.copy(color = MatuleTheme.colors.hint) - ) - } - ) - } - CommonButton( - modifier = Modifier.padding(top=30.dp), - buttonLabel = stringResource(R.string.send_email_forgot) - ) {} - } -} - -@Composable -fun TitleWithSubtitleText(title: String, subTitle:String){ - Column( - modifier = Modifier - .padding(horizontal = 20.dp) - .padding(top = 50.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(10.dp) - ) - { - Text( - text = title, - style = MatuleTheme.typography.headingBold32.copy(color = MatuleTheme.colors.text), - textAlign = TextAlign.Center - ) - Text( - text = subTitle, - maxLines = 2, - style = MatuleTheme.typography.subTitleRegular16.copy(color = MatuleTheme.colors.subTextDark), - textAlign = TextAlign.Center - ) - } - -} - - -@Composable -fun CommonButton(modifier: Modifier, buttonLabel: String, onClick: () -> Unit){ - var showDialog by remember { mutableStateOf(false) } - Button( - - modifier = modifier - .padding(horizontal = 20.dp) - .fillMaxWidth() - .height(50.dp) - .clip(RoundedCornerShape(14.dp)) - .background(MatuleTheme.colors.accent) - , - colors = ButtonColors( - containerColor = MatuleTheme.colors.accent, - disabledContentColor = Color.Transparent, - disabledContainerColor = MatuleTheme.colors.accent, - contentColor = Color.Transparent - ), - onClick= {showDialog=true} - ){ - Text( - text=buttonLabel, - style = MatuleTheme.typography.bodyRegular14.copy(color= MatuleTheme.colors.background), - textAlign = TextAlign.Center - ) - } - if (showDialog) { - CheckEmailDialog(onDismiss = { showDialog = false }) - } -} - -@Composable -fun CheckEmailDialog(onDismiss: () -> Unit) { - AlertDialog( - onDismissRequest = onDismiss, - confirmButton = {}, - title = { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.fillMaxWidth() - ) { - Row( - modifier = Modifier.padding(bottom = 8.dp), - horizontalArrangement = Arrangement.Center - ) { - Icon( - painter = painterResource(R.drawable.email_image), - contentDescription = null, - tint = MatuleTheme.colors.accent, - modifier = Modifier.size(40.dp) - ) - } - Text( - text = "Проверьте Ваш Email", - style = MatuleTheme.typography.bodyRegular16.copy(color = MatuleTheme.colors.text), - textAlign = TextAlign.Center - ) - } - }, - text = { - Text( - text = "Мы отправили код восстановления пароля на вашу электронную почту.", - textAlign = TextAlign.Center, - style = MatuleTheme.typography.bodyRegular14.copy(color = MatuleTheme.colors.hint) - ) - }, - modifier = Modifier.clip(RoundedCornerShape(14.dp)), - containerColor = Color.White - ) -} - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/java/com/example/shoesapptest/ui/screen/registrationscreen/RegistrationScreen.kt b/app/src/main/java/com/example/shoesapptest/ui/screen/registrationscreen/RegistrationScreen.kt deleted file mode 100644 index 7bed55f..0000000 --- a/app/src/main/java/com/example/shoesapptest/ui/screen/registrationscreen/RegistrationScreen.kt +++ /dev/null @@ -1,350 +0,0 @@ -package com.example.shoesapptest.screen - -import androidx.compose.foundation.background -import androidx.compose.foundation.interaction.MutableInteractionSource -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.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.safeGesturesPadding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.BasicTextField -import androidx.compose.foundation.text.ClickableText -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonColors -import androidx.compose.material3.CenterAlignedTopAppBar -import androidx.compose.material3.Checkbox -import androidx.compose.material3.CheckboxColors -import androidx.compose.material3.CheckboxDefaults -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.IconButton -import androidx.compose.material3.Scaffold -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp -import com.example.shoesapptest.R -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.material3.TextFieldColors -import androidx.compose.material3.TextFieldDefaults -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.ui.text.style.TextAlign -import com.example.shoesapp.ui.theme.MatuleTheme -import com.example.shoesapp.ui.theme.matuleFontFamily -import kotlin.math.sin - -@Composable -fun RegistrtionScreen(){ - Scaffold( - topBar = { - Row( - modifier = Modifier - .padding(top = 35.dp) - .fillMaxWidth() - .height(40.dp) - ){ - IconButton(onClick={}) { - Icon(painter = painterResource(R.drawable.back_arrow), - contentDescription = null) - } - } - }, - bottomBar = { - Row( - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .padding(bottom = 50.dp) - .fillMaxWidth() - .height(40.dp) - ) { - Text( - text= stringResource(R.string.sign_in_on_reg), - style=MatuleTheme.typography.bodyRegular16.copy(MatuleTheme.colors.text), - textAlign = TextAlign.Center - ) - } - } - ) { paddingValues -> - RegistrationScreen(paddingValues) - } -} - -@Composable -fun RegistrationScreen(paddingValues: PaddingValues){ - Column( - modifier = Modifier.padding(paddingValues=paddingValues) - ) { - val title= stringResource(R.string.sign_up_on_reg) - val subtitle= stringResource(R.string.sign_in_subtitle) - TitleWithSubtitleText(title, subtitle) - val name = remember { mutableStateOf("") } - val email = remember { mutableStateOf("") } - val password = remember { mutableStateOf("") } - RegistrationTextFields( - labelNameText = stringResource(R.string.name), - labelEmailText = stringResource(R.string.email), - labelPasswordText = stringResource(R.string.password), - nameValue = name.value, - emailValue = email.value, - passwordValue = password.value, - onNameChange = {name.value=it}, - onEmailChange = {email.value=it}, - onPasswordChange = {password.value=it}, - placeholderTextName = stringResource(R.string.template_name), - placeholderTextEmail = stringResource(R.string.template_email), - placeholderTextPassword = stringResource(R.string.template_password) - ) - RegButton(modifier = Modifier.padding(top = 50.dp), - buttonLabel = stringResource(R.string.sign_up_btn) - ) { } - } -} - -@Composable -fun RegButton(modifier: Modifier, buttonLabel: String, onClick: () -> Unit){ - Button( - modifier = modifier - .padding(horizontal = 20.dp) - .fillMaxWidth() - .height(50.dp) - .clip(RoundedCornerShape(14.dp)) - .background(MatuleTheme.colors.background) - , - colors=ButtonColors( - containerColor = MatuleTheme.colors.accent, - disabledContainerColor = MatuleTheme.colors.accent, - contentColor = Color.Transparent, - disabledContentColor = Color.Transparent - ), - onClick=onClick - ){ - Text( - text=buttonLabel, - style = MatuleTheme.typography.bodyRegular14.copy(color=MatuleTheme.colors.background), - textAlign = TextAlign.Center - ) - } -} - - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun RegistrationTextFields(nameValue: String, - onNameChange: (String) -> Unit, - placeholderTextName: String, - labelNameText: String, - emailValue: String, - onEmailChange: (String) -> Unit, - placeholderTextEmail: String, - labelEmailText: String, - passwordValue: String, - onPasswordChange: (String) -> Unit, - placeholderTextPassword: String, - labelPasswordText: String){ - Column( - modifier = Modifier - .padding(horizontal = 20.dp) - .wrapContentSize(), - verticalArrangement = Arrangement.spacedBy(8.dp) - ){ - if (labelNameText!=null){ - Text( - text=labelNameText, - style=MatuleTheme.typography.bodyRegular16.copy(MatuleTheme.colors.text), - textAlign = TextAlign.Right - ) - } - val name = remember { MutableInteractionSource() } - BasicTextField( - value = nameValue, - onValueChange = { onNameChange(it) }, - modifier = Modifier - .padding(horizontal = 20.dp) - .fillMaxWidth() - .clip(RoundedCornerShape(14.dp)) - .background(MatuleTheme.colors.background) - ){ - innerTextField -> - TextFieldDefaults.DecorationBox( - value=nameValue, - singleLine = true, - innerTextField = innerTextField, - enabled = true, - colors= TextFieldDefaults.colors( - focusedContainerColor = MatuleTheme.colors.background, - disabledContainerColor = MatuleTheme.colors.background, - unfocusedContainerColor = MatuleTheme.colors.background, - errorContainerColor = MatuleTheme.colors.background, - unfocusedIndicatorColor = Color.Transparent, - focusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - errorIndicatorColor = Color.Transparent - ), - visualTransformation = VisualTransformation.None, - interactionSource = name, - placeholder = { - if (placeholderTextName!=null) - Text( - text=placeholderTextName, - style = MatuleTheme.typography.bodyRegular14.copy(MatuleTheme.colors.hint) - ) - } - ) - } - if(labelEmailText!=null){ - Text( - text = labelEmailText, - style = MatuleTheme.typography.bodyRegular16.copy(MatuleTheme.colors.text), - textAlign = TextAlign.Right - ) - } - val email = remember { MutableInteractionSource() } - BasicTextField( - value=emailValue, - onValueChange = {onEmailChange(it)}, - modifier = Modifier - .padding(horizontal = 20.dp) - .fillMaxWidth() - .clip(RoundedCornerShape(14.dp)) - .background(MatuleTheme.colors.background) - ){ - innerTextField -> - TextFieldDefaults.DecorationBox( - value = emailValue, - singleLine = true, - innerTextField = innerTextField, - enabled = true, - colors = TextFieldDefaults.colors( - focusedContainerColor = MatuleTheme.colors.background, - disabledContainerColor = MatuleTheme.colors.background, - unfocusedContainerColor = MatuleTheme.colors.background, - errorContainerColor = MatuleTheme.colors.background, - unfocusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - focusedIndicatorColor = Color.Transparent, - errorIndicatorColor = Color.Transparent - ), - visualTransformation = VisualTransformation.None, - interactionSource = email, - placeholder = { - if(placeholderTextEmail!=null) - Text( - text = placeholderTextEmail, - style = MatuleTheme.typography.bodyRegular14.copy(MatuleTheme.colors.hint) - ) - } - ) - } - if (labelPasswordText!=null){ - Text( - text = labelPasswordText, - style = MatuleTheme.typography.bodyRegular16.copy(MatuleTheme.colors.text), - textAlign = TextAlign.Center - ) - } - val password = remember { MutableInteractionSource() } - var passwordVisible by remember { mutableStateOf(false) } - Row( - modifier = Modifier - .padding(horizontal = 20.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ){ - BasicTextField( - value=passwordValue, - onValueChange = { onPasswordChange(it) }, - visualTransformation = if(passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), - modifier = Modifier - .weight(1f) - .clip(RoundedCornerShape(14.dp)) - .background(MatuleTheme.colors.background) - ){ innerTextField -> - TextFieldDefaults.DecorationBox( - value = passwordValue, - singleLine = true, - innerTextField = innerTextField, - enabled = true, - colors = TextFieldDefaults.colors( - focusedContainerColor = MatuleTheme.colors.background, - disabledContainerColor = MatuleTheme.colors.background, - unfocusedContainerColor = MatuleTheme.colors.background, - errorContainerColor = MatuleTheme.colors.background, - unfocusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - focusedIndicatorColor = Color.Transparent, - errorIndicatorColor = Color.Transparent - ), - visualTransformation = if(passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), - interactionSource = password, - placeholder = { - if (placeholderTextPassword!=null){ - Text( - text = placeholderTextPassword, - style = MatuleTheme.typography.bodyRegular14.copy(MatuleTheme.colors.hint) - ) - } - } - ) - - } - IconButton( - onClick = {passwordVisible = !passwordVisible} - ){ - Icon( - painter = painterResource(if(passwordVisible) R.drawable.eye_close else R.drawable.eye_open), - contentDescription = null - ) - } - } - val checkedState = remember { mutableStateOf(false) } - Row { - Checkbox( - checked = checkedState.value, - onCheckedChange = { checkedState.value = it } - ) - - ClickableText( - text = AnnotatedString(stringResource(R.string.personal_data)), - style = MatuleTheme.typography.bodyRegular16.copy(MatuleTheme.colors.text), - modifier = Modifier - .padding(top=8.dp), - onClick = {}) - } - - } -} - - - - - - - - - - - - - - - diff --git a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/SignInState.kt b/app/src/main/java/com/example/shoesapptest/ui/screen/signin/SignInState.kt deleted file mode 100644 index 37be426..0000000 --- a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/SignInState.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.example.shoesapptest.ui.screen.signin - -data class SignInState() diff --git a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/SignInViewModel.kt b/app/src/main/java/com/example/shoesapptest/ui/screen/signin/SignInViewModel.kt deleted file mode 100644 index 8927f04..0000000 --- a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/SignInViewModel.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.example.shoesapptest.ui.screen.signin - -class SignInViewModel { -} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/SigninScreen.kt b/app/src/main/java/com/example/shoesapptest/ui/screen/signin/SigninScreen.kt deleted file mode 100644 index 7c4ca2f..0000000 --- a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/SigninScreen.kt +++ /dev/null @@ -1,294 +0,0 @@ -package com.example.shoesapp.ui.screen - - -import androidx.compose.foundation.background -import androidx.compose.foundation.interaction.MutableInteractionSource -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.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.BasicTextField -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonColors -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.TextFieldDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import com.example.shoesapp.ui.theme.MatuleTheme -import com.example.shoesapptest.R - - -@Composable -fun SigninScreen(){ - Scaffold( - topBar = { - Row( - modifier = Modifier - .padding(top = 35.dp) - .fillMaxWidth() - .height(40.dp) - ) { - IconButton(onClick = {}) { - Icon(painter= painterResource(R.drawable.back_arrow), - contentDescription = null) - } - } - }, - bottomBar = { - Row( - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .padding(bottom = 50.dp) - .fillMaxWidth() - .height(40.dp) - ) { - Text( - text= stringResource(R.string.sign_up), - style = MatuleTheme.typography.bodyRegular16.copy(color=MatuleTheme.colors.text), - textAlign = TextAlign.Center - ) - } - } - ) { paddingValues -> - SignInContent(paddingValues) - } -} - - - -@Composable -fun SignInContent(paddingValues: PaddingValues) { - Column( - modifier = Modifier.padding(paddingValues = paddingValues) - ) { - - TitleWithSubtitleText( - title = stringResource(R.string.hello), - subTitle = stringResource(R.string.sign_in_subtitle) - ) - val email = remember { mutableStateOf("") } - val password = remember { mutableStateOf("")} - Spacer(modifier = Modifier.height(35.dp)) - AuthTextField( - labelTextEmail = stringResource(R.string.email), - labelTextPassword = stringResource(R.string.password), - placeHolderTextEmail = stringResource(R.string.template_email), - placeHolderTextPassword= stringResource(R.string.template_password), - emailValue = email.value, - onEmailChange = { - email.value = it - }, - passwordValue = password.value, - onPasswordChange = { - password.value = it - } - ) - CommonButton( - modifier = Modifier.padding(top=50.dp), - buttonLabel = stringResource(R.string.sign_in)){ - - } - } -} - -@Composable -fun TitleWithSubtitleText(title: String, subTitle:String){ - Column( - modifier = Modifier.run { padding(horizontal = 20.dp) }, - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(10.dp) - ) - { - Text( - text = title, - style = MatuleTheme.typography.headingBold32.copy(color = MatuleTheme.colors.text), - textAlign = TextAlign.Center, - - ) - Text( - text = subTitle, - maxLines = 2, - style = MatuleTheme.typography.subTitleRegular16.copy(color = MatuleTheme.colors.subTextDark), - textAlign = TextAlign.Center - ) - - - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun AuthTextField( emailValue: String, - onEmailChange: (String) -> Unit, - passwordValue: String, - onPasswordChange: (String) -> Unit, - placeHolderTextEmail: String? = null, - placeHolderTextPassword: String? = null, - labelTextEmail: String? = null, - labelTextPassword: String? = null){ - Column ( - modifier = Modifier - .padding(horizontal = 20.dp) - .wrapContentSize(), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - if (labelTextEmail != null) { - Text( - text = labelTextEmail, - style = MatuleTheme.typography.bodyRegular16.copy(MatuleTheme.colors.text), - textAlign = TextAlign.Right - ) - } - val interaction = remember { MutableInteractionSource() } - BasicTextField( - value = emailValue, - onValueChange = { onEmailChange(it) }, - modifier = Modifier - .padding(horizontal = 20.dp) - .fillMaxWidth() - .clip(RoundedCornerShape(14.dp)) - .background(MatuleTheme.colors.background) - ) { innerTextField -> - TextFieldDefaults.DecorationBox( - value = emailValue, - singleLine = true, - innerTextField = innerTextField, - enabled = true, - colors = TextFieldDefaults.colors( - focusedContainerColor = MatuleTheme.colors.background, - disabledContainerColor = MatuleTheme.colors.background, - unfocusedContainerColor = MatuleTheme.colors.background, - errorContainerColor = MatuleTheme.colors.background, - unfocusedIndicatorColor = Color.Transparent, - focusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - errorIndicatorColor = Color.Transparent - ), - visualTransformation = VisualTransformation.None, - interactionSource = interaction, - placeholder = { - if (placeHolderTextEmail != null) - Text( - text = placeHolderTextEmail, - style = MatuleTheme.typography.bodyRegular14.copy(color = MatuleTheme.colors.hint) - ) - } - ) - } - if (labelTextPassword != null) { - Text( - text = labelTextPassword, - style = MatuleTheme.typography.bodyRegular16.copy(MatuleTheme.colors.text), - textAlign = TextAlign.Right - ) - } - val password = remember { MutableInteractionSource() } - var passwordVisible by remember { mutableStateOf(false) } - Row( - modifier = Modifier - .padding(horizontal = 20.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) - { - BasicTextField( - value = passwordValue, - onValueChange = { onPasswordChange(it) }, - visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), - modifier = Modifier - .weight(1f) - .clip(RoundedCornerShape(14.dp)) - .background(MatuleTheme.colors.background) - ) { innerTextField -> - TextFieldDefaults.DecorationBox( - value = passwordValue, - singleLine = true, - innerTextField = innerTextField, - enabled = true, - colors = TextFieldDefaults.colors( - focusedContainerColor = MatuleTheme.colors.background, - disabledContainerColor = MatuleTheme.colors.background, - unfocusedContainerColor = MatuleTheme.colors.background, - errorContainerColor = MatuleTheme.colors.background, - unfocusedIndicatorColor = Color.Transparent, - focusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - errorIndicatorColor = Color.Transparent - ), - visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), - interactionSource = password, - placeholder = { - if (placeHolderTextPassword != null) - Text( - text = placeHolderTextPassword, - style = MatuleTheme.typography.bodyRegular14.copy(color = MatuleTheme.colors.hint) - ) - } - ) - } - - IconButton( - onClick={passwordVisible = !passwordVisible} - ) { - Icon( - painter= painterResource(if (passwordVisible) R.drawable.eye_close else R.drawable.eye_open), - contentDescription = "Показать пароль" - ) - } - } - } -} - -@Composable -fun CommonButton(modifier: Modifier, buttonLabel: String, onClick: () -> Unit){ - Button( - - modifier = modifier - .padding(horizontal = 20.dp) - .fillMaxWidth() - .height(50.dp) - .clip(RoundedCornerShape(14.dp)) - .background(MatuleTheme.colors.accent) - , - colors = ButtonColors( - containerColor = MatuleTheme.colors.accent, - disabledContentColor = Color.Transparent, - disabledContainerColor = MatuleTheme.colors.accent, - contentColor = Color.Transparent - ), - onClick=onClick - ){ - Text( - text=buttonLabel, - style = MatuleTheme.typography.bodyRegular14.copy(color= MatuleTheme.colors.background), - textAlign = TextAlign.Center - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/component/AuthButton.kt b/app/src/main/java/com/example/shoesapptest/ui/screen/signin/component/AuthButton.kt deleted file mode 100644 index 2ed45a8..0000000 --- a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/component/AuthButton.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.example.shoesapptest.ui.screen.signin.component - diff --git a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/component/AuthTextField.kt b/app/src/main/java/com/example/shoesapptest/ui/screen/signin/component/AuthTextField.kt deleted file mode 100644 index 2ed45a8..0000000 --- a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/component/AuthTextField.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.example.shoesapptest.ui.screen.signin.component - diff --git a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/component/TitleWithSubtitleText.kt b/app/src/main/java/com/example/shoesapptest/ui/screen/signin/component/TitleWithSubtitleText.kt deleted file mode 100644 index 2ed45a8..0000000 --- a/app/src/main/java/com/example/shoesapptest/ui/screen/signin/component/TitleWithSubtitleText.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.example.shoesapptest.ui.screen.signin.component - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0365c77..751ca9f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8,7 +8,7 @@ Вы впервые? Создать пользователя •••••••• Пароль - Забыл Пароль + Забыли Пароль Введите Свою Учётную Запись Для Сброса xyz@gmail.com Отправить @@ -16,6 +16,9 @@ Регистрация XXXXXXXX Зарегистрироваться - Имя + Ваше Имя Даю согласие на обработку персональных данных + Неверный Логин + Неверный пароль + Неверное имя пользователя \ No newline at end of file