diff --git a/.idea/vcs.xml b/.idea/vcs.xml index d843f34..94a25f7 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,4 +1,6 @@ - + + + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5e830da..2fae56b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -50,6 +50,7 @@ dependencies { implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) + implementation(libs.androidx.navigation.compose) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) @@ -66,4 +67,22 @@ dependencies { // Kotlinx serialization dependencies implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0") + +// implementation("libs.androidx.navigation.compose") + val voyagerVersion = "1.1.0-beta02" + implementation("cafe.adriel.voyager:voyager-navigator:$voyagerVersion") + implementation("cafe.adriel.voyager:voyager-screenmodel:$voyagerVersion") + + + testImplementation("junit:junit:4.13.2") + testImplementation ("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.0") + + + + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1") + + + implementation(platform("io.github.jan-tennert.supabase:bom:3.0.3")) + implementation("io.github.jan-tennert.supabase:postgrest-kt") + implementation("io.ktor:ktor-client-android:3.0.3") } \ No newline at end of file diff --git a/app/src/main/java/com/example/testktor/MainActivity.kt b/app/src/main/java/com/example/testktor/MainActivity.kt index e2e852a..21c4783 100644 --- a/app/src/main/java/com/example/testktor/MainActivity.kt +++ b/app/src/main/java/com/example/testktor/MainActivity.kt @@ -51,68 +51,6 @@ // } //} // -//@Composable -//fun UserScreen(modifier: Modifier = Modifier, client: HttpClient) { -// var user by remember { mutableStateOf(null) } -// var isLoading by remember { mutableStateOf(true) } -// var errorMessage by remember { mutableStateOf(null) } -// -// val scope = rememberCoroutineScope() -// -// LaunchedEffect(Unit) { -// try { -// val fetchedUser = getUser(client) // Получаем одного пользователя -// user = fetchedUser -// } catch (e: Exception) { -// errorMessage = "Error fetching user: ${e.localizedMessage}" -// Log.e("UserScreen", "Error: ${e.localizedMessage}", e) -// } -// isLoading = false -// } -// -// if (isLoading) { -// CircularProgressIndicator() -// } -// -// errorMessage?.let { -// Text(text = it) -// } -// -// user?.let { -// Text(text = "User: ${it.name}, ID: ${it.id}") // Отображаем имя пользователя -// } ?: run { -// Text(text = "No user found or failed to load.") -// } -//} -// -//suspend fun getUser(client: HttpClient): User { -// val response: HttpResponse = client.get("http://10.0.2.2:8080/user") { -// contentType(ContentType.Application.Json) -// } -// val responseBody = response.bodyAsText() -// Log.d("getUser", "Response: $responseBody") // Логируем ответ сервера -// -// val json = Json { ignoreUnknownKeys = true } -// -// val buba = json.decodeFromString(responseBody) // Десериализуем в объект User -// Log.d("json", buba.name) -// -// return try { -// json.decodeFromString(responseBody) // Десериализуем в объект User -// } catch (e: Exception) { -// Log.e("getUser", "Error deserializing response", e) -// throw e // Повторно выбрасываем ошибку, чтобы она была обработана в UserScreen -// } -//} -// -//@Preview(showBackground = true) -//@Composable -//fun UserScreenPreview() { -// TestKtorTheme { -// UserScreen(client = HttpClient(Android)) -// } -//} - package com.example.testktor @@ -129,6 +67,14 @@ import androidx.compose.material3.CircularProgressIndicator import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import com.example.matuletest.ui.auth.FirstScreen +import com.example.matuletest.ui.auth.SliderScreen +import com.example.testktor.auth.AuthScreen +//import com.example.testktor.auth.AuthScreen +//import com.example.testktor.auth.RegistrationScreen import com.example.testktor.ui.theme.TestKtorTheme import io.ktor.client.* import io.ktor.client.request.* @@ -144,86 +90,54 @@ import io.ktor.serialization.kotlinx.json.* import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json -@Serializable -data class User(val id: Int, val name: String) +//class MainActivity : ComponentActivity() { +// private val client = HttpClient(Android) { +// install(ContentNegotiation) { +// json(Json { prettyPrint = true }) +// } +// } +// +// override fun onCreate(savedInstanceState: Bundle?) { +// super.onCreate(savedInstanceState) +// enableEdgeToEdge() +// setContent { +// TestKtorTheme { +// Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> +// UserScreen(modifier = Modifier.padding(innerPadding), client = client) +// } +// } +// } +// } +//} class MainActivity : ComponentActivity() { - private val client = HttpClient(Android) { - install(ContentNegotiation) { - json(Json { prettyPrint = true }) - } - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { TestKtorTheme { - Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> - UserScreen(modifier = Modifier.padding(innerPadding), client = client) + val navController = rememberNavController() + + NavHost(navController = navController, startDestination = "first_screen") { + composable("first_screen") { + FirstScreen(onNavigateToSliderScreen = { + navController.navigate("slider_screen") + }) + } + composable("slider_screen") { + SliderScreen(onNavigateToAuthScreen = { + navController.navigate("auth_screen") + }) + } + composable("auth_screen") { + AuthScreen(navController) + } +// composable("registration_screen") { +// RegistrationScreen() +// } } } } } } -@Composable -fun UserScreen(modifier: Modifier = Modifier, client: HttpClient) { - var users by remember { mutableStateOf?>(null) } - var isLoading by remember { mutableStateOf(true) } - var errorMessage by remember { mutableStateOf(null) } - - val scope = rememberCoroutineScope() - - LaunchedEffect(Unit) { - try { - val fetchedUsers = getUsers(client) - users = fetchedUsers - } catch (e: Exception) { - errorMessage = "Error fetching users: ${e.localizedMessage}" - Log.e("UserScreen", "Error: ${e.localizedMessage}", e) - } - isLoading = false - } - - if (isLoading) { - CircularProgressIndicator() - } - - errorMessage?.let { - Text(text = it) - } - - users?.let { - it.forEach { user -> - Text(text = "User: ${user.name}, ID: ${user.id}") - } - } ?: run { - Text(text = "No users found or failed to load.") - } -} - -suspend fun getUsers(client: HttpClient): List { - val response: HttpResponse = client.get("http://212.67.10.54:8080/users") { - contentType(ContentType.Application.Json) - } - val responseBody = response.bodyAsText() - Log.d("getUsers", "Response: $responseBody") // Логируем ответ сервера - - val json = Json { ignoreUnknownKeys = true } - - return try { - json.decodeFromString>(responseBody) // Десериализуем в List - } catch (e: Exception) { - Log.e("getUsers", "Error deserializing response", e) - throw e // Повторно выбрасываем ошибку, чтобы она была обработана в UserScreen - } -} - -@Preview(showBackground = true) -@Composable -fun UserScreenPreview() { - TestKtorTheme { - UserScreen(client = HttpClient(Android)) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/testktor/auth/AuthScreen.kt b/app/src/main/java/com/example/testktor/auth/AuthScreen.kt new file mode 100644 index 0000000..29d3772 --- /dev/null +++ b/app/src/main/java/com/example/testktor/auth/AuthScreen.kt @@ -0,0 +1,153 @@ +package com.example.testktor.auth + +import androidx.compose.foundation.hoverable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.ClickableText +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +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.graphics.Color +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.unit.dp +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController +import com.example.testktor.authUser +import com.example.testktor.getUser +import io.ktor.client.HttpClient +import io.ktor.client.engine.android.Android + +@Composable +fun AuthScreen(navController: NavController) { + var authSuccess by remember { mutableStateOf(null) } + var email by remember { mutableStateOf("") } + var password by remember { mutableStateOf("") } + + val client = HttpClient(Android) + + LaunchedEffect(email, password) { + if (email.isNotEmpty() && password.isNotEmpty()) { + val result = authUser(client, email, password) + authSuccess = if (result) "Success" else "Failed" + } + } + + AuthContent(navController, authSuccess, email, password) { newEmail, newPassword -> + email = newEmail + password = newPassword + } +} + +@Composable +fun AuthContent( + navController: NavController, + authSuccess: String?, + email: String, + password: String, + onAuth: (String, String) -> Unit +) { + var emailIn by remember { mutableStateOf(email) } + var passwordIn by remember { mutableStateOf(password) } + + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + // Отображение текста "Success" в левом верхнем углу + if (authSuccess == "Success") { + Text( + text = "Success", + modifier = Modifier + .padding(start = 16.dp, top = 16.dp) + .align(Alignment.Start), + color = Color.Green, + style = TextStyle(fontSize = 18.sp, fontWeight = FontWeight.Bold) + ) + } + + Text( + text = "Привет!", + style = TextStyle(fontSize = 32.sp, fontWeight = FontWeight.Bold), + modifier = Modifier.height(60.dp).padding(bottom = 20.dp) + ) + + Text( + text = "Заполните Свои данные или продолжите через социальные медиа", + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 20.dp), + style = TextStyle(fontSize = 16.sp), + textAlign = TextAlign.Center, + maxLines = 2 + ) + + Text(text = "Email", modifier = Modifier.padding(end = 255.dp)) + TextField( + modifier = Modifier.width(300.dp).height(70.dp).padding(bottom = 16.dp), + value = emailIn, + onValueChange = { emailIn = it } + ) + + Text(text = "Password", modifier = Modifier.padding(end = 225.dp)) + TextField( + modifier = Modifier.width(300.dp).height(70.dp).padding(bottom = 16.dp), + value = passwordIn, + onValueChange = { passwordIn = it }, + visualTransformation = PasswordVisualTransformation() + ) + + Button( + modifier = Modifier.width(350.dp).height(50.dp), + colors = androidx.compose.material3.ButtonDefaults.buttonColors( + containerColor = Color(0xFF48B2E7), + contentColor = Color.White + ), + onClick = { onAuth(emailIn, passwordIn) } + ) { + Text("Войти") + } + + Row( + modifier = Modifier + .padding(top = 16.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = "Вы впервые? ", + style = TextStyle(fontSize = 16.sp, color = Color.Black) + ) + + ClickableText( + text = buildAnnotatedString { append("Создать пользователя") }, + onClick = { + navController.navigate("registration_screen") + }, + style = TextStyle( + fontSize = 16.sp, + color = Color.Black + ), + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/testktor/auth/BeforeAuthScreen.kt b/app/src/main/java/com/example/testktor/auth/BeforeAuthScreen.kt new file mode 100644 index 0000000..7ad5f32 --- /dev/null +++ b/app/src/main/java/com/example/testktor/auth/BeforeAuthScreen.kt @@ -0,0 +1,146 @@ +package com.example.matuletest.ui.auth + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +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.width +import androidx.compose.material3.Button +import androidx.compose.material3.Slider +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +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.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.LineHeightStyle +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.example.testktor.R +import io.ktor.websocket.Frame +import java.lang.reflect.Modifier + +@Composable +fun FirstScreen(onNavigateToSliderScreen: () -> Unit) { + LaunchedEffect(Unit) { + kotlinx.coroutines.delay(3000) + onNavigateToSliderScreen() + } + Box( + modifier = androidx.compose.ui.Modifier + .fillMaxSize() + .background(Brush.horizontalGradient(listOf(Color(0xFF48B2E7), Color(0xFF0076B1)))), + ) { + Text( + text = "MATULEme", + fontSize = 32.sp, + color = Color.White, + modifier = androidx.compose.ui.Modifier.align(Alignment.Center) + ) + } +} + +@Composable +fun SliderScreen(onNavigateToAuthScreen: () -> Unit) { + var sliderValue by remember { mutableStateOf(0f) } + val textList = listOf("ДОБРО ПОЖАЛОВАТЬ", "Начнем путешествие", "У вас есть сила, чтобы") + val textList2 = listOf("", "Умная, великолепная и модная коллекция Изучите сейчас", "В вашей комнате много красивых и привлекательных растений") + val maxIndex = textList.size - 1 + + val currentIndex = sliderValue.toInt() + + val imageId = when (currentIndex) { + 0 -> R.drawable.kros1 + 1 -> R.drawable.kros2 + 2 -> R.drawable.kros3 + else -> return + } + + Column( + modifier = androidx.compose.ui.Modifier + .fillMaxSize() + .background(Brush.horizontalGradient(listOf(Color(0xFF48B2E7), Color(0xFF0076B1)))), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + painter = painterResource(id = imageId), + contentDescription = "Изображение", + modifier = androidx.compose.ui.Modifier.width(670.dp).height(600.dp).padding(start = 20.dp) + ) + + Text( + color = Color.White, + fontStyle = FontStyle.Italic, + text = textList[currentIndex], + fontSize = 24.sp, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center, + modifier = androidx.compose.ui.Modifier + .fillMaxWidth() + .padding(top = 40.dp) + .width(700.dp).height(30.dp) + ) + Text( + color = Color.White, + fontStyle = FontStyle.Italic, + text = textList2[currentIndex], + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center, + modifier = androidx.compose.ui.Modifier + .fillMaxWidth() + .padding(top = 40.dp) + ) + + Spacer(modifier = androidx.compose.ui.Modifier.weight(1f)) + + Slider( + value = sliderValue, + onValueChange = { newValue -> sliderValue = newValue }, + valueRange = 0f..maxIndex.toFloat(), + steps = maxIndex - 1, + colors = androidx.compose.material3.SliderDefaults.colors( + thumbColor = Color.White, + activeTrackColor = Color(0xFF0076B1), + inactiveTrackColor = Color(0xFFB0B0B0) + ), + modifier = androidx.compose.ui.Modifier.fillMaxWidth() + ) + +// Spacer(modifier = androidx.compose.ui.Modifier.height(20.dp)) + + Button( + onClick = { + if (sliderValue < maxIndex) { + sliderValue++ + } else { + onNavigateToAuthScreen() + }}, + colors = androidx.compose.material3.ButtonDefaults.buttonColors( + containerColor = Color.White, + contentColor = Color.Black + ), + modifier = androidx.compose.ui.Modifier + .fillMaxWidth() + .padding(bottom = 40.dp) + ) { + Text(text = "Далее", color = Color.Black) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/testktor/auth/RegistrationScreen.kt b/app/src/main/java/com/example/testktor/auth/RegistrationScreen.kt new file mode 100644 index 0000000..d405fd0 --- /dev/null +++ b/app/src/main/java/com/example/testktor/auth/RegistrationScreen.kt @@ -0,0 +1,127 @@ +//package com.example.testktor.auth +// +//import androidx.compose.foundation.layout.Arrangement +//import androidx.compose.foundation.layout.Column +//import androidx.compose.foundation.layout.Row +//import androidx.compose.foundation.layout.fillMaxSize +//import androidx.compose.foundation.layout.fillMaxWidth +//import androidx.compose.foundation.layout.height +//import androidx.compose.foundation.layout.padding +//import androidx.compose.foundation.layout.width +//import androidx.compose.foundation.text.ClickableText +//import androidx.compose.material3.Button +//import androidx.compose.material3.Text +//import androidx.compose.material3.TextField +//import androidx.compose.runtime.Composable +//import androidx.compose.runtime.collectAsState +//import androidx.compose.ui.Alignment +//import androidx.compose.ui.Modifier +//import androidx.compose.ui.graphics.Color +//import androidx.compose.ui.text.TextStyle +//import androidx.compose.ui.text.buildAnnotatedString +//import androidx.compose.ui.text.font.FontWeight +//import androidx.compose.ui.text.input.PasswordVisualTransformation +//import androidx.compose.ui.text.style.TextAlign +//import androidx.compose.ui.unit.dp +//import androidx.compose.ui.unit.sp +//import androidx.lifecycle.viewmodel.compose.viewModel +//import androidx.navigation.NavController +//import com.example.matuletest.ui.auth.AuthScreenViewModel +// +//@Composable +//fun RegistrationScreen(navController: NavController) { +// val viewModel: AuthScreenViewModel = viewModel() +// RegistrationContent(viewModel, navController) +//} +// +//@Composable +//fun RegistrationContent(viewModel: AuthScreenViewModel, navController: NavController){ +// val regState = viewModel.registrationScreenState.collectAsState() +// +// if (regState.value.isSignUp) { +// Text("Success Registration") +// } +// +// Column( +// modifier = Modifier.fillMaxSize(), +// horizontalAlignment = Alignment.CenterHorizontally, +// verticalArrangement = Arrangement.Center +// ) { +// Text( +// text = "Регистрация!", +// style = TextStyle(fontSize = 32.sp, fontWeight = FontWeight.Bold), +// modifier = Modifier.height(60.dp).padding(bottom = 20.dp) +// ) +// +// Text( +// text = "Заполните Свои данные или продолжите через социальные медиа", +// modifier = Modifier +// .fillMaxWidth() +// .padding(bottom = 20.dp), +// style = TextStyle(fontSize = 16.sp), +// textAlign = TextAlign.Center, +// maxLines = 2 +// ) +// +//// Text(text = "Ваше имя", modifier = Modifier.padding(end = 255.dp)) +//// TextField( +//// modifier = Modifier.width(300.dp).height(70.dp).padding(bottom = 16.dp), +//// value = regState.value.email, +//// onValueChange = { +//// viewModel.setEmail(it) +//// }) +// +// Text(text = "Email", modifier = Modifier.padding(end = 255.dp)) +// TextField( +// modifier = Modifier.width(300.dp).height(70.dp).padding(bottom = 16.dp), +// value = regState.value.email, +// onValueChange = { +// viewModel.setEmail(it, true) +// }) +// +// Text(text = "Password", modifier = Modifier.padding(end = 225.dp)) +// TextField( +// modifier = Modifier.width(300.dp).height(70.dp).padding(bottom = 16.dp), +// value = regState.value.password, +// onValueChange = { +// viewModel.setPassword(it, true) +// }, +// visualTransformation = PasswordVisualTransformation() +// ) +// +// Button( +// modifier = Modifier.width(350.dp).height(50.dp), +// colors = androidx.compose.material3.ButtonDefaults.buttonColors( +// containerColor = Color(0xFF48B2E7), +// contentColor = Color.White +// ), +// onClick = { +// viewModel.reg() +// }) { +// Text("Зарегестрироваться") +// } +// +// Row( +// modifier = Modifier +// .padding(top = 16.dp) +// .fillMaxWidth(), +// horizontalArrangement = Arrangement.Center +// ) { +// Text( +// text = "Есть аккаунт? ", +// style = TextStyle(fontSize = 16.sp, color = Color.Black) +// ) +// +// ClickableText( +// text = buildAnnotatedString { append("Войти") }, +// onClick = { +// navController.navigate("auth_screen") +// }, +// style = TextStyle( +// fontSize = 16.sp, +// color = Color.Black +// ), +// ) +// } +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/example/testktor/getUser.kt b/app/src/main/java/com/example/testktor/getUser.kt new file mode 100644 index 0000000..772035a --- /dev/null +++ b/app/src/main/java/com/example/testktor/getUser.kt @@ -0,0 +1,178 @@ +package com.example.testktor + +import android.util.Log +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.example.testktor.ui.theme.TestKtorTheme +import io.ktor.client.HttpClient +import io.ktor.client.engine.android.Android +import io.ktor.client.request.get +import io.ktor.client.statement.HttpResponse +import io.ktor.client.statement.bodyAsText +import io.ktor.http.ContentType +import io.ktor.http.contentType +import kotlinx.serialization.Serializable +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json + + +@Serializable +data class User(val id: Int, val email: String, val password: String) + +//@Composable +//fun UserScreen(modifier: Modifier = Modifier, client: HttpClient) { +// var users by remember { mutableStateOf?>(null) } +// var isLoading by remember { mutableStateOf(true) } +// var errorMessage by remember { mutableStateOf(null) } +// +// val scope = rememberCoroutineScope() +// +// LaunchedEffect(Unit) { +// try { +// val fetchedUsers = getUsers(client) +// users = fetchedUsers +// } catch (e: Exception) { +// errorMessage = "Error fetching users: ${e.localizedMessage}" +// Log.e("UserScreen", "Error: ${e.localizedMessage}", e) +// } +// isLoading = false +// } +// +// if (isLoading) { +// CircularProgressIndicator() +// } +// +// errorMessage?.let { +// Text(text = it) +// } +// +// users?.let { +// it.forEach { user -> +// Text(text = "User: ${user.name}, ID: ${user.id}") +// } +// } ?: run { +// Text(text = "No users found or failed to load.") +// } +//} +// +//suspend fun getUsers(client: HttpClient): List { +// val response: HttpResponse = client.get("http://212.67.10.54:8080/users") { +// contentType(ContentType.Application.Json) +// } +// val responseBody = response.bodyAsText() +// Log.d("getUsers", "Response: $responseBody") // Логируем ответ сервера +// +// val json = Json { ignoreUnknownKeys = true } +// +// return try { +// json.decodeFromString>(responseBody) // Десериализуем в List +// } catch (e: Exception) { +// Log.e("getUsers", "Error deserializing response", e) +// throw e // Повторно выбрасываем ошибку, чтобы она была обработана в UserScreen +// } +//} +// +//@Preview(showBackground = true) +//@Composable +//fun UserScreenPreview() { +// TestKtorTheme { +// UserScreen(client = HttpClient(Android)) +// } +//} + +@Composable +fun UserScreen(modifier: Modifier = Modifier, client: HttpClient) { + var user by remember { mutableStateOf(null) } + var isLoading by remember { mutableStateOf(true) } + var errorMessage by remember { mutableStateOf(null) } + + val scope = rememberCoroutineScope() + + LaunchedEffect(Unit) { + try { + val fetchedUser = getUser(client) // Получаем одного пользователя + user = fetchedUser + } catch (e: Exception) { + errorMessage = "Error fetching user: ${e.localizedMessage}" + Log.e("UserScreen", "Error: ${e.localizedMessage}", e) + } + isLoading = false + } + + if (isLoading) { + CircularProgressIndicator() + } + + errorMessage?.let { + Text(text = it) + } + + user?.let { + Text(text = "User: ${it.email}, ID: ${it.id}") // Отображаем имя пользователя + } ?: run { + Text(text = "No user found or failed to load.") + } +} + +suspend fun getUser(client: HttpClient): User { + val response: HttpResponse = client.get("http://10.0.2.2:8080/user") { + contentType(ContentType.Application.Json) + } + val responseBody = response.bodyAsText() + Log.d("getUser", "Response: $responseBody") // Логируем ответ сервера + + val json = Json { ignoreUnknownKeys = true } + + val buba = json.decodeFromString(responseBody) // Десериализуем в объект User + Log.d("json", buba.email) + + return try { + json.decodeFromString(responseBody) // Десериализуем в объект User + } catch (e: Exception) { + Log.e("getUser", "Error deserializing response", e) + throw e // Повторно выбрасываем ошибку, чтобы она была обработана в UserScreen + } +} + +suspend fun authUser(client: HttpClient, email: String, password: String): Boolean { + val response: HttpResponse = client.get("http://10.0.2.2:8080/user2?email=$email") { + contentType(ContentType.Application.Json) + } + + val responseBody = response.bodyAsText() + Log.d("authUser", "Response: $responseBody") // Логируем ответ сервера + + val json = Json { ignoreUnknownKeys = true } + + return try { + val user = json.decodeFromString(responseBody) // Десериализуем в объект User + + // Проверяем, совпадает ли пароль + if (user.password == password) { + true // Возвращаем true, если пароль совпадает + } else { + Log.e("authUser", "Incorrect password") + false // Возвращаем false, если пароль неверный + } + } catch (e: Exception) { + Log.e("authUser", "Error deserializing response", e) + false // Возвращаем false в случае ошибки + } +} + +@Preview(showBackground = true) +@Composable +fun UserScreenPreview() { + TestKtorTheme { + UserScreen(client = HttpClient(Android)) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/kros1.png b/app/src/main/res/drawable/kros1.png new file mode 100644 index 0000000..e748c16 Binary files /dev/null and b/app/src/main/res/drawable/kros1.png differ diff --git a/app/src/main/res/drawable/kros2.png b/app/src/main/res/drawable/kros2.png new file mode 100644 index 0000000..0f954f8 Binary files /dev/null and b/app/src/main/res/drawable/kros2.png differ diff --git a/app/src/main/res/drawable/kros3.png b/app/src/main/res/drawable/kros3.png new file mode 100644 index 0000000..e268b9a Binary files /dev/null and b/app/src/main/res/drawable/kros3.png differ diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e164b3b..aa6c917 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,7 @@ espressoCore = "3.6.1" lifecycleRuntimeKtx = "2.8.7" activityCompose = "1.10.0" composeBom = "2024.04.01" +navigationCompose = "2.8.7" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -24,6 +25,7 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-material3 = { group = "androidx.compose.material3", name = "material3" } +androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }