This commit is contained in:
IsaykinEugene 2025-03-25 15:34:44 +03:00
parent 26e0b74bf3
commit 5c6f4c7815
48 changed files with 533 additions and 512 deletions

View File

@ -42,6 +42,11 @@ android {
dependencies { dependencies {
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation("androidx.datastore:datastore-preferences:1.1.3")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("com.squareup.retrofit2:converter-kotlinx-serialization:2.11.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0")
implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom)) implementation(platform(libs.androidx.compose.bom))
@ -49,7 +54,6 @@ dependencies {
implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3) implementation(libs.androidx.material3)
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.androidx.espresso.core)
@ -57,12 +61,37 @@ dependencies {
androidTestImplementation(libs.androidx.ui.test.junit4) androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest) debugImplementation(libs.androidx.ui.test.manifest)
implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
implementation("androidx.navigation:navigation-compose:2.8.9")
implementation("androidx.datastore:datastore-preferences:1.1.3")
implementation("androidx.navigation:navigation-compose:2.8.9")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
implementation("com.squareup.retrofit2:retrofit:2.11.0") implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("com.squareup.retrofit2:converter-gson:2.11.0") implementation("com.squareup.retrofit2:converter-kotlinx-serialization:2.11.0")
implementation("androidx.datastore:datastore-preferences:1.0.0") // https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") implementation("com.squareup.okhttp3:okhttp:4.7.2")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0")
implementation("androidx.navigation:navigation-compose:2.7.0")
implementation("io.insert-koin:koin-compose:4.1.0-Beta5")
implementation("io.insert-koin:koin-compose-viewmodel:4.1.0-Beta5")
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
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)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
} }

View File

@ -1,19 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<application <application
android:name=".MainApplication"
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.ShoesappTest" android:theme="@style/Theme.ShoesappTest"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".MainActivity" android:name=".ui.MainActivity"
android:exported="true" android:exported="true"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/Theme.ShoesappTest"> android:theme="@style/Theme.ShoesappTest">

View File

@ -1,19 +0,0 @@
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)
}
}
}

View File

@ -4,61 +4,59 @@ import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.example.shoesapp.ui.screen.SigninScreen
import com.example.shoesapp.ui.theme.MatuleTheme import com.example.shoesapp.ui.theme.MatuleTheme
import com.example.shoesapptest.AuthRemoteSourceImpl import com.example.shoesapptest.Screen
import com.example.shoesapptest.RegistrationViewModelFactory import com.example.shoesapptest.data.local.DataStore
import com.example.shoesapptest.data.local.datastore.LocalDataStore import com.example.shoesapptest.data.remote.RetrofitClient
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
import com.example.shoesapptest.data.AuthRepository
import com.example.shoesapptest.domain.usecase.AuthUseCase
import com.example.shoesapptest.screen.ForgotPasswordScreen
import com.example.shoesapptest.screen.regscreen.RegistrationScreen
import com.example.shoesapptest.ui.screen.registrationscreen.Registration
import com.example.shoesapptest.ui.screen.registrationscreen.RegistrationViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
private lateinit var authLocalStore: LocalDataStore
private lateinit var authRemoteSource: AuthRemoteSourceImpl
private lateinit var authRepository: AuthRepositoryImpl
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enableEdgeToEdge() enableEdgeToEdge()
// Инициализация зависимостей val registrationViewModel: RegistrationViewModel by viewModel()
authLocalStore = LocalDataStore(applicationContext)
authRemoteSource = AuthRemoteSourceImpl()
authRepository = AuthRepositoryImpl(authLocalStore, authRemoteSource)
setContent { setContent {
val navController = rememberNavController()
MatuleTheme { MatuleTheme {
val navController = rememberNavController()
NavHost( NavHost(
navController = navController, navController = navController,
startDestination = "register" startDestination = "signin"
) { ) {
composable("register") { composable(Screen.SignIn.route) {
// Создание и передача ViewModel SigninScreen(
val registrationViewModel: RegistrationViewModel = ViewModelProvider( onNavigationToRegScreen = {
this@MainActivity, navController.navigate("registration")
RegistrationViewModelFactory(authRepository) },
).get(RegistrationViewModel::class.java) navController = navController
RegistrationScreen(
navController = navController,
registrationViewModel = registrationViewModel
) )
} }
composable(Screen.ForgotPass.route) {
composable("test") { ForgotPasswordScreen(onNavigateToSignInScreen = {
TestScreen() navController.navigate("signin")
})
}
composable(Screen.Registration.route) {
RegistrationScreen(
onNavigationToSigninScreen = {
navController.popBackStack()
}
)
} }
} }
} }
} }
} }
} }

View File

@ -0,0 +1,16 @@
package com.example.shoesapptest
import android.app.Application
import com.example.shoesapptest.di.appModules
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin
class MainApplication: Application() {
override fun onCreate(){
super.onCreate()
startKoin{
androidContext(applicationContext)
modules(appModules)
}
}
}

View File

@ -1,18 +0,0 @@
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 <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(RegistrationViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return RegistrationViewModel(authRepository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}

View File

@ -0,0 +1,7 @@
package com.example.shoesapptest
sealed class Screen (val route: String) {
object SignIn : Screen("signin")
object ForgotPass : Screen("forgotpass")
object Registration : Screen("registration")
}

View File

@ -0,0 +1,13 @@
package com.example.shoesapptest.data
import com.example.shoesapptest.data.remote.auth.AuthApi
import com.example.shoesapptest.data.remote.dto.request.RegistrationRequest
import com.example.shoesapptest.data.remote.dto.response.RegistrationResponse
import kotlinx.coroutines.delay
class AuthRepository(private val api: AuthApi) {
suspend fun registration(registrationRequest: RegistrationRequest): RegistrationResponse {
delay(3000)
return api.registration(registrationRequest)
}
}

View File

@ -1,9 +0,0 @@
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
}

View File

@ -0,0 +1,23 @@
package com.example.shoesapptest.data.local
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
class DataStore(private val context: Context) {
val TOKEN_KEY = stringPreferencesKey("token_key")
val tokenFlow : Flow<String> = context.dataStore.data.map { pref ->
pref[TOKEN_KEY] ?: ""
}
suspend fun setToken(token: String){
context.dataStore.edit { pref ->
pref[TOKEN_KEY] = token
}
}
}

View File

@ -1,30 +0,0 @@
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
}
}

View File

@ -1,7 +0,0 @@
package com.example.shoesapptest.data.model
data class RegistrationRequest(
val userName: String,
val email: String,
val password: String
)

View File

@ -1,5 +0,0 @@
package com.example.shoesapptest.data.model
data class SaveTokenRequest(
val tokenAuthentication: String
)

View File

@ -1,5 +0,0 @@
package com.example.shoesapptest.data.model
data class TokenResponse(
val tokenAuthentication: String
)

View File

@ -1,8 +0,0 @@
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
}

View File

@ -0,0 +1,7 @@
package com.example.shoesapptest.data.remote
sealed class NetworkResponse {
data class Success<T>(val data: T): NetworkResponse()
data object Loading:NetworkResponse()
data class Error(val errorMessage: String): NetworkResponse()
}

View File

@ -0,0 +1,22 @@
package com.example.shoesapptest.data.remote
import com.example.shoesapptest.data.remote.auth.AuthApi
import com.example.shoesapptest.data.remote.auth.AuthRemoteSource
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import retrofit2.Retrofit
import retrofit2.converter.kotlinx.serialization.asConverterFactory
object RetrofitClient {
private const val URL = "http://26.197.138.194:8080"
private val retrofit = Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(
Json.asConverterFactory(
"application/json; charset=UTF8".toMediaType()))
.build()
val auth by lazy {
retrofit.create(AuthApi::class.java)
}
}

View File

@ -0,0 +1,11 @@
package com.example.shoesapptest.data.remote.auth
import com.example.shoesapptest.data.remote.dto.request.RegistrationRequest
import com.example.shoesapptest.data.remote.dto.response.RegistrationResponse
import retrofit2.http.Body
import retrofit2.http.POST
interface AuthApi {
@POST("/regitstration")
suspend fun registration(@Body registrationRequest: RegistrationRequest): RegistrationResponse
}

View File

@ -0,0 +1,11 @@
package com.example.shoesapptest.data.remote.auth
import com.example.shoesapptest.data.remote.dto.request.RegistrationRequest
import com.example.shoesapptest.data.remote.dto.response.RegistrationResponse
import retrofit2.http.Body
import retrofit2.http.POST
interface AuthRemoteSource {
@POST("/registration")
suspend fun registration(@Body registrationRequest: RegistrationRequest): RegistrationResponse
}

View File

@ -0,0 +1,10 @@
package com.example.shoesapptest.data.remote.dto.request
import kotlinx.serialization.Serializable
@Serializable
data class RegistrationRequest(
val userName: String,
val email: String,
val password: String
)

View File

@ -0,0 +1,9 @@
package com.example.shoesapptest.data.remote.dto.response
import kotlinx.serialization.Serializable
@Serializable
data class RegistrationResponse (
val first: String,
val second: String
)

View File

@ -1,12 +0,0 @@
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
}

View File

@ -1,15 +0,0 @@
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)
}
}

View File

@ -1,10 +0,0 @@
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()
}

View File

@ -1,23 +0,0 @@
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() {
}
}

View File

@ -0,0 +1,18 @@
package com.example.shoesapptest.di
import com.example.shoesapptest.data.AuthRepository
import com.example.shoesapptest.data.local.DataStore
import com.example.shoesapptest.data.remote.RetrofitClient
import com.example.shoesapptest.domain.usecase.AuthUseCase
import com.example.shoesapptest.screen.regscreen.RegistrationScreen
import com.example.shoesapptest.ui.screen.registrationscreen.RegistrationViewModel
import org.koin.core.module.dsl.viewModel
import org.koin.dsl.module
val appModules = module {
single { DataStore(get()) }
single { RetrofitClient.auth }
single<AuthRepository> { AuthRepository(get()) }
single { AuthUseCase(get(),get()) }
viewModel { RegistrationViewModel(get())}
}

View File

@ -0,0 +1,28 @@
package com.example.shoesapptest.domain.usecase
import com.example.shoesapptest.data.AuthRepository
import com.example.shoesapptest.data.local.DataStore
import com.example.shoesapptest.data.remote.NetworkResponse
import com.example.shoesapptest.data.remote.dto.request.RegistrationRequest
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class AuthUseCase (private val localStorage: DataStore,
private val authRepository: AuthRepository) {
val token: Flow<String> = localStorage.tokenFlow
suspend fun registration(registrationRequest: RegistrationRequest): Flow<NetworkResponse> = flow{
try{
emit(NetworkResponse.Loading)
val result = authRepository.registration(registrationRequest)
localStorage.setToken(result.second)
emit(NetworkResponse.Success(result))
}
catch (e:Exception){
e.message?.let{
emit(NetworkResponse.Error(it))
return@flow
}
emit(NetworkResponse.Error("Unknown Error"))
}
}
}

View File

@ -1,18 +0,0 @@
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 = "Добро пожаловать!")
}
}

View File

@ -1,13 +0,0 @@
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
)

View File

@ -1,197 +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.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)
)
}
}

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.forgotscreen package com.example.shoesapptest.ui.screen.forgotscreen
data class ChangePass( data class ChangePass(
var email: String = "", var email: String = "",

View File

@ -38,14 +38,15 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.input.pointer.motionEventSpy import androidx.compose.ui.input.pointer.motionEventSpy
import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.colorResource
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.shoesapptest.screen.forgotscreen.ForgotPasswordViewModel import androidx.navigation.NavController
import com.example.shoesapptest.screen.forgotscreen.component.TitleWithSubtitleText import com.example.shoesapptest.ui.screen.forgotscreen.ForgotPasswordViewModel
import com.example.shoesapptest.screen.forgotscreen.component.EmailTextField import com.example.shoesapptest.ui.screen.forgotscreen.component.TitleWithSubtitleText
import com.example.shoesapptest.screen.forgotscreen.component.SendButton import com.example.shoesapptest.ui.screen.forgotscreen.component.EmailTextField
import com.example.shoesapptest.ui.screen.forgotscreen.component.SendButton
@Composable @Composable
fun ForgotPasswordScreen(){ fun ForgotPasswordScreen(onNavigateToSignInScreen: () -> Unit) {
val forgotPasswordViewModel: ForgotPasswordViewModel = viewModel() val forgotPasswordViewModel: ForgotPasswordViewModel = viewModel()
val showDialog = remember { mutableStateOf(false) } val showDialog = remember { mutableStateOf(false) }
@ -141,26 +142,4 @@ fun CheckEmailDialog(onDismiss: () -> Unit) {
modifier = Modifier.clip(RoundedCornerShape(14.dp)), modifier = Modifier.clip(RoundedCornerShape(14.dp)),
containerColor = Color.White containerColor = Color.White
) )
} }

View File

@ -1,16 +1,19 @@
package com.example.shoesapptest.screen.forgotscreen package com.example.shoesapptest.ui.screen.forgotscreen
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
class ForgotPasswordViewModel { class ForgotPasswordViewModel: ViewModel(){
var changePass = mutableStateOf(ChangePass()) var changePass = mutableStateOf(ChangePass())
private set private set
val emailHasError = derivedStateOf { val emailHasError = derivedStateOf {
if(changePass.value.email.isEmpty()) return@derivedStateOf false if(changePass.value.email.isEmpty()) return@derivedStateOf false
!android.util.Patterns.EMAIL_ADDRESS.matcher(changePass.value.email).matches() !android.util.Patterns.EMAIL_ADDRESS.matcher(changePass.value.email).matches()
} }
fun setEmail(email: String){ fun setEmail(email: String){
changePass.value = changePass.value.copy(email=email) changePass.value = changePass.value.copy(email = email)
} }
} }

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.forgotscreen.component package com.example.shoesapptest.ui.screen.forgotscreen.component
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.forgotscreen.component package com.example.shoesapptest.ui.screen.forgotscreen.component
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonColors

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.forgotscreen.component package com.example.shoesapptest.ui.screen.forgotscreen.component
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column

View File

@ -0,0 +1,16 @@
package com.example.shoesapptest.ui.screen.registrationscreen
import android.provider.ContactsContract.CommonDataKinds.Email
import com.example.shoesapptest.ui.screen.forgotscreen.ChangePass
import java.lang.Error
data class Registration(
var email: String = "",
var name: String = "",
var password: String = "",
var isVisiblePassword: Boolean = false,
var errorMessage: String? = null,
var isLoading: Boolean = false,
var isSignedIn: Boolean = false,
var emailHasError: Boolean = false
)

View File

@ -0,0 +1,192 @@
package com.example.shoesapptest.screen.regscreen
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
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.Checkbox
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
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.platform.LocalContext
import androidx.compose.ui.res.painterResource
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.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.shoesapp.ui.theme.MatuleTheme
import com.example.shoesapptest.R
import com.example.shoesapptest.ui.screen.registrationscreen.RegistrationViewModel
import com.example.shoesapptest.ui.screen.registrationscreen.component.RegistrationBtn
import com.example.shoesapptest.ui.screen.registrationscreen.component.RegistrationTextField
import com.example.shoesapptest.ui.screen.registrationscreen.component.TextWithSubTitle
import org.koin.compose.viewmodel.koinViewModel
@Composable
fun RegistrationScreen(
onNavigationToSigninScreen: () -> Unit,
viewModel: RegistrationViewModel = koinViewModel()
) {
val snackbarHostState = remember { SnackbarHostState() }
Scaffold(
snackbarHost = { SnackbarHost(snackbarHostState) },
topBar = {
Row(
modifier = Modifier
.padding(top = 35.dp)
.fillMaxWidth()
.height(40.dp)
) {
IconButton(onClick = onNavigationToSigninScreen) {
Icon(
painter = painterResource(R.drawable.back_arrow),
contentDescription = null
)
}
}
},
bottomBar = {
Row(
modifier = Modifier
.padding(bottom = 50.dp)
.fillMaxWidth()
.height(40.dp)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) { onNavigationToSigninScreen() },
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "Есть аккаунт? Войти",
style = MatuleTheme.typography.bodyRegular16.copy(color = MatuleTheme.colors.text),
textAlign = TextAlign.Center
)
}
}
) { paddingValues ->
val state = viewModel.registration.value
LaunchedEffect(state.isSignedIn) {
if (state.isSignedIn) {
onNavigationToSigninScreen()
}
}
LaunchedEffect(state.errorMessage) {
state.errorMessage?.let {
snackbarHostState.showSnackbar(it)
viewModel.setErrorMessage(null)
}
}
Column(
modifier = Modifier
.padding(paddingValues)
.fillMaxWidth()
.padding(20.dp)
) {
TextWithSubTitle(
title = "Регистрация",
subtitle = "Заполните Свои данные или продолжите через социальные медиа"
)
Spacer(modifier = Modifier.height(20.dp))
RegistrationTextField(
value = state.name,
onChangeValue = { viewModel.setUserName(it) },
isError = false,
supportingText = { Text(text = "Неверное имя пользователя") },
placeholder = { Text(text = stringResource(R.string.template_password)) },
label = { Text(text = "Ваше имя") }
)
RegistrationTextField(
value = state.email,
onChangeValue = { viewModel.setEmail(it) },
isError = state.emailHasError,
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 = state.password,
onChangeValue = { viewModel.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 = { viewModel.registration { } }) {
if (state.isLoading) {
CircularProgressIndicator()
} else {
Text(text = stringResource(R.string.sign_up_on_reg))
}
}
}
}
}
@Composable
private 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 }
)
Text(
text = "Даю согласие на обработку персональных данных",
style = MatuleTheme.typography.bodyRegular16.copy(color = MatuleTheme.colors.text),
modifier = Modifier.padding(start = 8.dp)
)
}
}

View File

@ -1,18 +1,18 @@
package com.example.shoesapptest.screen.registrationscreen package com.example.shoesapptest.ui.screen.registrationscreen
import androidx.compose.animation.core.animateDecay
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.shoesapptest.data.model.RegistrationRequest import com.example.shoesapptest.data.remote.dto.request.RegistrationRequest
import com.example.shoesapptest.data.repository.AuthRepository import com.example.shoesapptest.data.AuthRepository
import com.example.shoesapptest.screen.regscreen.RegistrationScreen
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.lang.Error
class RegistrationViewModel( class RegistrationViewModel(
private val authRepository: AuthRepository private val authRepository: AuthRepository
):ViewModel() { ):ViewModel() {
var registration = mutableStateOf(Registration()) var registration = mutableStateOf(Registration())
private set private set
val emailHasError = derivedStateOf { val emailHasError = derivedStateOf {
@ -28,7 +28,10 @@ class RegistrationViewModel(
fun setUserName(name: String){ fun setUserName(name: String){
registration.value = registration.value.copy(name=name) registration.value = registration.value.copy(name=name)
} }
fun registration(onSuccess: () -> Unit, onError: (String) -> Unit){ fun setErrorMessage(message: String?){
registration.value=registration.value.copy(errorMessage = message)
}
fun registration(onSuccess: () -> Unit){
viewModelScope.launch { viewModelScope.launch {
try { try {
val registrationRequest = RegistrationRequest( val registrationRequest = RegistrationRequest(
@ -36,11 +39,9 @@ class RegistrationViewModel(
email = registration.value.email, email = registration.value.email,
password = registration.value.password password = registration.value.password
) )
authRepository.registration(registrationRequest)
onSuccess() onSuccess()
} catch (e: Exception) { } catch (e: Exception) {
onError(e.message ?: "Ошибка регистрации") registration.value = registration.value.copy(errorMessage = "Ошибка регистрации: ${e.message}")
} }
} }
} }

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.registrationscreen.component package com.example.shoesapptest.ui.screen.registrationscreen.component
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonColors
@ -11,8 +11,8 @@ import com.example.shoesapptest.common.CommonButton
@Composable @Composable
fun RegistrationBtn( fun RegistrationBtn(
onClick: () -> Unit, onClick: () -> Unit,
content: @Composable () -> Unit modifier: Modifier = Modifier,
){ content: @Composable () -> Unit){
CommonButton( CommonButton(
modifier = Modifier.padding(50.dp), modifier = Modifier.padding(50.dp),
onClick = onClick, onClick = onClick,

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.registrationscreen.component package com.example.shoesapptest.ui.screen.registrationscreen.component
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -8,7 +8,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.Placeholder import androidx.compose.ui.text.Placeholder
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.datastore.preferences.protobuf.Internal.BooleanList
import com.example.shoesapptest.common.CommonTextField import com.example.shoesapptest.common.CommonTextField
import java.lang.Error import java.lang.Error
@ -21,7 +20,7 @@ fun RegistrationTextField(
placeholder: @Composable () -> Unit, placeholder: @Composable () -> Unit,
label: @Composable () -> Unit label: @Composable () -> Unit
){ ){
Column(Modifier.padding(50.dp) Column(Modifier.padding(horizontal = 20.dp)
.wrapContentSize(), .wrapContentSize(),
verticalArrangement = Arrangement.spacedBy(12.dp)){ verticalArrangement = Arrangement.spacedBy(12.dp)){
label() label()

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.registrationscreen.component package com.example.shoesapptest.ui.screen.registrationscreen.component
import android.icu.text.CaseMap.Title import android.icu.text.CaseMap.Title
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.signin package com.example.shoesapptest.ui.screen.signin
data class SignInState ( data class SignInState (
var email: String = "", var email: String = "",

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.signin package com.example.shoesapptest.ui.screen.signin
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf

View File

@ -1,7 +1,7 @@
package com.example.shoesapp.ui.screen package com.example.shoesapp.ui.screen
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -15,8 +15,7 @@ import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
@ -24,10 +23,8 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
@ -40,16 +37,17 @@ import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import com.example.shoesapp.ui.theme.MatuleTheme import com.example.shoesapp.ui.theme.MatuleTheme
import com.example.shoesapptest.R import com.example.shoesapptest.R
import com.example.shoesapptest.screen.signin.SignInViewMode import com.example.shoesapptest.common.CommonButton
import com.example.shoesapptest.screen.signin.component.AuthButton import com.example.shoesapptest.ui.screen.signin.SignInViewMode
import com.example.shoesapptest.screen.signin.component.AuthTextField import com.example.shoesapptest.ui.screen.signin.component.AuthButton
import com.example.shoesapptest.screen.signin.component.TitleWithSubtitleText import com.example.shoesapptest.ui.screen.signin.component.AuthTextField
import com.example.shoesapptest.ui.screen.signin.component.TitleWithSubtitleText
@Composable @Composable
fun SigninScreen() { fun SigninScreen(onNavigationToRegScreen: () -> Unit, navController: NavController) {
val signInViewModel: SignInViewMode = viewModel() val signInViewModel: SignInViewMode = viewModel()
Scaffold( Scaffold(
topBar = { topBar = {
@ -79,17 +77,18 @@ fun SigninScreen() {
Text( Text(
stringResource(R.string.sign_up), stringResource(R.string.sign_up),
style = MatuleTheme.typography.bodyRegular16.copy(color = MatuleTheme.colors.text), style = MatuleTheme.typography.bodyRegular16.copy(color = MatuleTheme.colors.text),
textAlign = TextAlign.Center textAlign = TextAlign.Center,
modifier = Modifier.clickable { onNavigationToRegScreen() }
) )
} }
} }
) { paddingValues -> ) { paddingValues ->
SignInContent(paddingValues, signInViewModel) SignInContent(paddingValues, signInViewModel, navController)
} }
} }
@Composable @Composable
fun SignInContent(paddingValues: PaddingValues, signInViewMode: SignInViewMode) { fun SignInContent(paddingValues: PaddingValues, signInViewMode: SignInViewMode, navController: NavController) {
val signInState = signInViewMode.signInState val signInState = signInViewMode.signInState
Column( Column(
modifier = Modifier.padding(paddingValues = paddingValues), modifier = Modifier.padding(paddingValues = paddingValues),
@ -101,28 +100,45 @@ fun SignInContent(paddingValues: PaddingValues, signInViewMode: SignInViewMode)
) )
Spacer(modifier = Modifier.height(35.dp)) Spacer(modifier = Modifier.height(35.dp))
AuthTextField( AuthTextField(
value = signInState.value.email, value = signInState.value.email,
onChangeValue = { signInViewMode.setEmail(it) }, onChangeValue = { signInViewMode.setEmail(it) },
isError = signInViewMode.emailHasError.value, isError = signInViewMode.emailHasError.value,
supportingText = { Text(text = stringResource(R.string.wrong_email))}, supportingText = { Text(text = stringResource(R.string.wrong_email))},
placeholder = { Text(text = stringResource(R.string.template_email)) }, placeholder = { Text(text = stringResource(R.string.template_email)) },
label = { Text(text = stringResource(R.string.email)) label = { Text(text = stringResource(R.string.email)) }
}
) )
AuthTextField( AuthTextField(
value = signInState.value.password, value = signInState.value.password,
onChangeValue = { signInViewMode.setPassword(it)}, onChangeValue = { signInViewMode.setPassword(it) },
isError = false, isError = false,
supportingText = { Text(text = "Неверный пароль")}, supportingText = { Text(text = "Неверный пароль")},
placeholder = { Text(text = stringResource(R.string.template_password))}, placeholder = { Text(text = stringResource(R.string.template_password)) },
label = { Text(text = stringResource(R.string.password))} label = { Text(text = stringResource(R.string.password)) }
) )
Text(
text = "Забыл пароль",
style = MatuleTheme.typography.bodyRegular16.copy(color = MatuleTheme.colors.text),
modifier = Modifier
.clickable {
navController.navigate("forgotpass")
}
.padding(top = 8.dp)
)
AuthButton(onClick = {}) { AuthButton(onClick = {}) {
Text(stringResource(R.string.sign_in)) Text(stringResource(R.string.sign_in))
} }
} }
} }

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.signin.component package com.example.shoesapptest.ui.screen.signin.component
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonColors

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.signin.component package com.example.shoesapptest.ui.screen.signin.component
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column

View File

@ -1,4 +1,4 @@
package com.example.shoesapptest.screen.signin.component package com.example.shoesapptest.ui.screen.signin.component
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column