diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ace528d..acd9028 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -90,4 +90,6 @@ dependencies { 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") + + implementation("io.coil-kt:coil-compose:2.4.0") } \ 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 54ee8a0..1c0fddb 100644 --- a/app/src/main/java/com/example/testktor/MainActivity.kt +++ b/app/src/main/java/com/example/testktor/MainActivity.kt @@ -1,18 +1,9 @@ package com.example.testktor import android.os.Bundle -import android.util.Log 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.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 @@ -20,25 +11,12 @@ import com.example.matuletest.ui.auth.FirstScreen import com.example.matuletest.ui.auth.SliderScreen import com.example.testktor.screen.auth.AuthScreen import com.example.testktor.screen.auth.ForgotPasswordScreen -import com.example.testktor.screen.auth.MainSneakersScreen +import com.example.testktor.screen.main.MainSneakersScreen import com.example.testktor.screen.auth.RegScreen import com.example.testktor.screen.auth.ResetPasswordScreen //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.* -import io.ktor.client.engine.android.* -import io.ktor.client.plugins.contentnegotiation.* -import io.ktor.client.statement.HttpResponse -import io.ktor.client.statement.bodyAsText -import io.ktor.http.ContentType -import io.ktor.http.contentType -import kotlinx.coroutines.launch -import kotlinx.serialization.Serializable -import io.ktor.serialization.kotlinx.json.* -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.json.Json class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/example/testktor/Models.kt b/app/src/main/java/com/example/testktor/Models.kt new file mode 100644 index 0000000..430a32d --- /dev/null +++ b/app/src/main/java/com/example/testktor/Models.kt @@ -0,0 +1,45 @@ +package com.example.testktor + +import kotlinx.serialization.Serializable + +@Serializable +data class User( + val id: Int, + val name: String, + val email: String, + val password: String, + val resetToken: String) + +@Serializable +data class Sneaker( + val id: Int, + val name: String, + val description: String, + val cost: Double, + val discount: Int, + val photo: String, + val gender: Char, + val bootSize: Int, + val categoryId: Int +) + +@Serializable +data class SneakerShop( + val sneaker: Sneaker, + var likeOrNot: Boolean +) + +@Serializable +data class Category( + val id: Int, + val name: String, + val description: String +) + +@Serializable +data class SneakerCategoryResponse( + val sneakers: List, + val categories: List +) + +var Token: String = ""; \ 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 index d3e34d4..304f80f 100644 --- a/app/src/main/java/com/example/testktor/getUser.kt +++ b/app/src/main/java/com/example/testktor/getUser.kt @@ -34,40 +34,6 @@ import kotlinx.serialization.json.Json import java.math.BigDecimal import java.sql.Time -@Serializable -data class User( - val id: Int, - val name: String, - val email: String, - val password: String, - val resetToken: String) - -//@Serializable -//data class Sneaker( -// val id: Int, -// val name: String, -// val description: String, -// @Contextual val cost: BigDecimal, -// val discount: Int, -// val photo: String, -// val gender: Char, -// val bootSize: Int -//) - -@Serializable -data class Sneaker( - val id: Int, - val name: String, - val description: String, - val cost: Double, - val discount: Int, - val photo: String, - val gender: Char, - val bootSize: Int -) - -var Token: String = ""; - suspend fun authUser(client: HttpClient, email: String, password: String): Boolean { try { val response: HttpResponse = client.post("http://10.0.2.2:8080/login") { @@ -153,8 +119,8 @@ suspend fun resetPassword(client: HttpClient, code: String, newPassword: String) } } -suspend fun getSneakers(client: HttpClient): List{ - try { +suspend fun getSneakers(client: HttpClient): SneakerCategoryResponse?{ + return try { val response: HttpResponse = client.get("http://10.0.2.2:8080/mainWindow") { headers { append(HttpHeaders.Authorization, "Bearer $Token") @@ -165,11 +131,10 @@ suspend fun getSneakers(client: HttpClient): List{ Log.d("getSneakers", "Response: $responseBody") val json = Json { ignoreUnknownKeys = true } - val responseMap = json.decodeFromString>>(responseBody) + json.decodeFromString(responseBody) - return responseMap["sneakers"] ?: emptyList() } catch (e: Exception) { - Log.e("getSneakers", "error fetching sneakers", e) - return emptyList() + Log.e("getSneakers", "error fetching sneakers or category", e) + null } } diff --git a/app/src/main/java/com/example/testktor/method/auth/AuthMethods.kt b/app/src/main/java/com/example/testktor/method/auth/AuthMethods.kt new file mode 100644 index 0000000..e00c411 --- /dev/null +++ b/app/src/main/java/com/example/testktor/method/auth/AuthMethods.kt @@ -0,0 +1,166 @@ +package com.example.testktor.method.auth + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +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.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.text.ClickableText +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.filled.Lock +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +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.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.input.VisualTransformation +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController + +@Composable +fun ButtonBack(navController: NavController){ + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 20.dp, top = 20.dp), + horizontalArrangement = Arrangement.Start + ) { + IconButton(onClick = { navController.navigate("slider_screen") }) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.size(56.dp) + ) { + Canvas(modifier = Modifier.matchParentSize()) { + drawCircle(color = Color.LightGray) + } + Icon( + imageVector = Icons.Default.ArrowBack, + contentDescription = "Назад", + modifier = Modifier.size(28.dp), + tint = Color.Black + ) + } + } + } +} + +@Composable +fun TopBar(email: String, + onEmailChange: (String) -> Unit, + password: String, + onPasswordChange: (String) -> Unit +){ + var passwordVisible by remember { mutableStateOf(false) } + + Text( + text = "Привет!", + style = TextStyle(fontSize = 32.sp, fontWeight = FontWeight.Bold), + modifier = Modifier.height(60.dp).padding(bottom = 8.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 = 280.dp)) + TextField( + modifier = Modifier.width(350.dp).height(70.dp).padding(bottom = 16.dp), + value = email, + onValueChange = { onEmailChange(it)}, + ) + + Text(text = "Password", modifier = Modifier.padding(end = 250.dp)) + TextField( + modifier = Modifier.width(350.dp).height(70.dp).padding(bottom = 16.dp), + value = password, + onValueChange = {onPasswordChange(it)}, + visualTransformation = if (!passwordVisible) PasswordVisualTransformation() else VisualTransformation.None, + trailingIcon = { + IconButton(onClick = { passwordVisible = !passwordVisible }) { + Icon( + imageVector = Icons.Default.Lock, + contentDescription = "Lock", + tint = Color.Gray + ) + } + } + ) +} + +@Composable +fun Restore(navController: NavController) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 6.dp, bottom = 20.dp, end = 16.dp), + horizontalArrangement = Arrangement.End + ) { + ClickableText( + text = buildAnnotatedString { append("Восстановить") }, + onClick = { + navController.navigate("forgotPassword_screen") + }, + style = TextStyle( + fontSize = 16.sp, + color = Color.LightGray + ), + ) + } +} + +@Composable +fun BotBar(navController: NavController) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) { + Row( + modifier = Modifier + .align(Alignment.BottomCenter) + .padding(bottom = 16.dp), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = "Вы впервые? ", + style = TextStyle(fontSize = 16.sp, color = Color.Gray) + ) + + 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/method/auth/BeforeAuthMethods.kt b/app/src/main/java/com/example/testktor/method/auth/BeforeAuthMethods.kt new file mode 100644 index 0000000..a0f05fd --- /dev/null +++ b/app/src/main/java/com/example/testktor/method/auth/BeforeAuthMethods.kt @@ -0,0 +1,66 @@ +package com.example.testktor.method.auth + +import androidx.compose.foundation.Image +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.material3.Slider +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +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.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +@Composable +fun Textik(imageId: Int, textList: List, textList2: List, currentIndex: Int){ + 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) + ) +} + +@Composable +fun Sliderik(sliderValue: Float, maxIndex: Int, onClick: (Float) -> Unit, ){ + Slider( + value = sliderValue, + onValueChange = onClick, + 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() + ) +} diff --git a/app/src/main/java/com/example/testktor/method/auth/ForgotPasswordMethods.kt b/app/src/main/java/com/example/testktor/method/auth/ForgotPasswordMethods.kt new file mode 100644 index 0000000..2e90472 --- /dev/null +++ b/app/src/main/java/com/example/testktor/method/auth/ForgotPasswordMethods.kt @@ -0,0 +1,42 @@ +package com.example.testktor.method.auth + +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.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + + +@Composable +fun BarForgot(emailIn: String, onEmailChane: (String) -> Unit){ + 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 = {onEmailChane(it)} + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/testktor/method/auth/RegistrationMethods.kt b/app/src/main/java/com/example/testktor/method/auth/RegistrationMethods.kt new file mode 100644 index 0000000..2cdfbdb --- /dev/null +++ b/app/src/main/java/com/example/testktor/method/auth/RegistrationMethods.kt @@ -0,0 +1,163 @@ +package com.example.testktor.method.auth + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +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.width +import androidx.compose.foundation.text.ClickableText +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Lock +import androidx.compose.material3.Checkbox +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +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.graphics.Color +import androidx.compose.ui.text.SpanStyle +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.input.VisualTransformation +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController + +@Composable +fun TopBarReg(name: String, + onNameChange: (String) -> Unit, + email: String, + onEmailChange: (String) -> Unit, + password: String, + onPasswordChange: (String) -> Unit +){ + var passwordVisible by remember { mutableStateOf(false) } + var isChecked by remember { mutableStateOf(false) } + + 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 = 270.dp)) + TextField( + modifier = Modifier.width(350.dp).height(70.dp).padding(bottom = 16.dp), + value = name, + onValueChange = {onNameChange(it)} + ) + + Text(text = "Email", modifier = Modifier.padding(end = 290.dp)) + TextField( + modifier = Modifier.width(350.dp).height(70.dp).padding(bottom = 16.dp), + value = email, + onValueChange = {onEmailChange(it)} + ) + + Text(text = "Password", modifier = Modifier.padding(end = 260.dp)) + TextField( + modifier = Modifier.width(350.dp).height(70.dp).padding(bottom = 16.dp), + value = password, + onValueChange = {onPasswordChange(it)}, + visualTransformation = if (!passwordVisible) PasswordVisualTransformation() else VisualTransformation.None, + trailingIcon = { + IconButton(onClick = { passwordVisible = !passwordVisible }) { + Icon( + imageVector = Icons.Default.Lock, + contentDescription = "Lock", + tint = Color.Gray + ) + } + } + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically + ) { + Checkbox( + checked = isChecked, + onCheckedChange = { isChecked = it } + ) + + Spacer(modifier = Modifier.width(8.dp)) + + ClickableText( + text = buildAnnotatedString { + append("Даю согласие на обработку персональных данных") + addStyle( + style = SpanStyle( + color = Color.Black, + textDecoration = TextDecoration.Underline + ), + start = 0, + end = this.length + ) + }, + onClick = { /* */ }, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 20.dp), + style = TextStyle(fontSize = 16.sp, textAlign = TextAlign.Center) + ) + } +} + +@Composable +fun BotBarReg(navController: NavController) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) { + Row( + modifier = Modifier + .align(Alignment.BottomCenter) + .padding(bottom = 16.dp), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = "Есть аккаунт? ", + style = TextStyle(fontSize = 16.sp, color = Color.Gray) + ) + + 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/method/auth/ResetPasswordMethods.kt b/app/src/main/java/com/example/testktor/method/auth/ResetPasswordMethods.kt new file mode 100644 index 0000000..60a6cab --- /dev/null +++ b/app/src/main/java/com/example/testktor/method/auth/ResetPasswordMethods.kt @@ -0,0 +1,55 @@ +package com.example.testktor.method.auth + +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.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +@Composable +fun TopBarReset(){ + 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 = 3 + ) +} + + +@Composable +fun TextFieldsReset(codeIn: String, + onCodeChange: (String) -> Unit, + newPassword: String, + onNewPasswordChange: (String) -> Unit){ + Text(text = "OTP Code", modifier = Modifier.padding(end = 255.dp)) + TextField( + modifier = Modifier.width(350.dp).height(70.dp).padding(bottom = 16.dp), + value = codeIn, + onValueChange = {onCodeChange(it)} + ) + + Text(text = "New Password", modifier = Modifier.padding(end = 255.dp)) + TextField( + modifier = Modifier.width(300.dp).height(70.dp).padding(bottom = 16.dp), + value = newPassword, + onValueChange = {onNewPasswordChange(it)} + ) +} diff --git a/app/src/main/java/com/example/testktor/method/main/MainSneakersMethods.kt b/app/src/main/java/com/example/testktor/method/main/MainSneakersMethods.kt new file mode 100644 index 0000000..462dc81 --- /dev/null +++ b/app/src/main/java/com/example/testktor/method/main/MainSneakersMethods.kt @@ -0,0 +1,381 @@ +package com.example.testktor.method.main + +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.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.ClickableText +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.Favorite +import androidx.compose.material.icons.filled.FavoriteBorder +import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.Notifications +import androidx.compose.material.icons.filled.Person +import androidx.compose.material.icons.filled.Search +import androidx.compose.material.icons.filled.ShoppingCart +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +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.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import coil.compose.AsyncImage +import com.example.testktor.Category +import com.example.testktor.R +import com.example.testktor.Sneaker +import com.example.testktor.SneakerShop + +@Preview(showBackground = true) +@Composable +fun TopNavigationBar(){ + Row ( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically + ){ + IconButton(onClick = { /* TODO: действие кнопки */ }) { + Image( + painter = painterResource(id = R.drawable.hamburger), + contentDescription = "menu", + modifier = Modifier.size(40.dp) + ) + } + + Box( + modifier = Modifier + .fillMaxWidth() + .weight(1f), + contentAlignment = Alignment.Center + ) { + Text( + text = "Главная", + fontSize = 30.sp + ) + } + + IconButton(onClick = { /* TODO: действие кнопки */ }) { + Image( + painter = painterResource(id = R.drawable.frame31), + contentDescription = "menu", + modifier = Modifier.size(40.dp) + ) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun Searchbar(searchBox: String, onSearchChange: (String) -> Unit){ + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically + ){ + TextField( + modifier = Modifier + .width(300.dp) + .height(70.dp) + .padding(bottom = 16.dp), + value = searchBox, + onValueChange = { onSearchChange(it) }, + placeholder = { + Text( + text = "Поиск", + color = Color.Gray, + fontSize = 14.sp + ) + }, + colors = TextFieldDefaults.textFieldColors( + containerColor = Color.White, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + cursorColor = Color.Black + ), + shape = RoundedCornerShape(12.dp), + leadingIcon = { + Icon( + imageVector = Icons.Default.Search, + contentDescription = "Search", + tint = Color.Gray + ) + } + ) + + IconButton(onClick = { /* TODO: действие кнопки */ }) { + Image( + painter = painterResource(id = R.drawable.group12), + contentDescription = "settings", + modifier = Modifier.size(60.dp) + ) + } + } +} + +@Composable +fun OverSmth(smth: String){ + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + ClickableText( + modifier = Modifier.weight(1f), + text = buildAnnotatedString { append(smth) }, + onClick = {/* TODO: действие кнопки */}, + style = TextStyle( + fontSize = 16.sp, + color = Color.Black + ), + ) + + ClickableText( + text = buildAnnotatedString { append("Все") }, + onClick = {/* TODO: действие кнопки */}, + style = TextStyle( + fontSize = 12.sp, + color = Color.Cyan + ), + ) + } +} + +@Preview(showBackground = true) +@Composable +fun SalesBar() { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + OverSmth("Акции") + + Box( + modifier = Modifier + .fillMaxWidth() + .height(160.dp) + .background(Color(0xFFF7F7F9)), + contentAlignment = Alignment.Center, + ) { + Image( + painter = painterResource(id = R.drawable.img), + contentDescription = "sales", + modifier = Modifier.fillMaxSize(), + contentScale = ContentScale.Fit + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun BottomNavigationBar() { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.BottomCenter + ) { + Image( + painter = painterResource(id = R.drawable.bottom), + contentDescription = null, + contentScale = ContentScale.FillWidth, + modifier = Modifier + .fillMaxWidth() + .aspectRatio(3f) + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + IconButton(onClick = { /* TODO: действие кнопки */ }) { + Icon( + imageVector = Icons.Default.Home, + contentDescription = "home", + modifier = Modifier.size(40.dp) + ) + } + Spacer(modifier = Modifier.width(20.dp)) + IconButton(onClick = { /* TODO: действие кнопки */ }) { + Icon( + imageVector = Icons.Default.FavoriteBorder, + contentDescription = "favourite", + modifier = Modifier.size(40.dp) + ) + } + Spacer(modifier = Modifier.width(20.dp)) + IconButton( + onClick = { /* TODO: действие кнопки */ }, + modifier = Modifier.offset(y = (-20).dp).size(80.dp) + ) { + Image( + painter = painterResource(id = R.drawable.group123), + contentDescription = "korzina", + modifier = Modifier.size(80.dp) + ) + } + Spacer(modifier = Modifier.width(20.dp)) + IconButton(onClick = { /* TODO: действие кнопки */ }) { + Icon( + imageVector = Icons.Default.Notifications, + contentDescription = "notice", + modifier = Modifier.size(40.dp) + ) + } + Spacer(modifier = Modifier.width(20.dp)) + IconButton(onClick = { /* TODO: действие кнопки */ }) { + Icon( + imageVector = Icons.Default.Person, + contentDescription = "profile", + modifier = Modifier.size(40.dp) + ) + } + } + } +} + +@Composable +fun CategorySelection( + categories: List, + selectedCategory: Category?, + onCategorySelected: (Category?) -> Unit +) { + LazyRow { + items(categories) { category -> + CategoryButton( + category = category, + isSelected = category == selectedCategory, + onClick = { + if (selectedCategory == category) { + onCategorySelected(null) + } else { + onCategorySelected(category) + } + } + ) + } + } +} + +@Composable +fun CategoryButton(category: Category, isSelected: Boolean, onClick: () -> Unit) { + Button( + onClick = onClick, + modifier = Modifier + .padding(8.dp), + colors = ButtonDefaults.buttonColors( + containerColor = if (isSelected) Color.Blue else Color.White + ) + ) { + Text(text = category.name, color = Color.Black) + } +} + +@Composable +fun SneakerSelection(sneakers: List) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + sneakers.take(2).forEachIndexed { index ,sneakerShop -> + SneakerButton( + sneakerShop = sneakerShop, + onClick = { /* TODO: Действие кнопки */ }, + onFavoriteClick = { /* TODO: Действие кнопки */ } + ) + } + } +} + +@Composable +fun SneakerButton(sneakerShop: SneakerShop, onClick: () -> Unit, onFavoriteClick: () -> Unit) { + val cost = "₽${sneakerShop.sneaker.cost}" + + var isLiked by remember { mutableStateOf(false) } + var isAddedToCart by remember { mutableStateOf(false) } + + Box(modifier = Modifier.padding(8.dp)) { + Button( + onClick = onClick, + modifier = Modifier + .width(140.dp) + .height(180.dp), + colors = ButtonDefaults.buttonColors( + containerColor = Color.White + ), + shape = RoundedCornerShape(12.dp) + ) { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + AsyncImage( + model = sneakerShop.sneaker.photo, + contentDescription = "Sneaker Image", + modifier = Modifier + .width(200.dp) + .height(90.dp) + ) + Text(text = sneakerShop.sneaker.name, fontSize = 20.sp, color = Color.DarkGray) + Text(text = cost, fontSize = 15.sp, color = Color.Black) + } + } + + IconButton( + onClick = {isLiked = !isLiked}, + modifier = Modifier + .align(Alignment.TopStart) + .size(28.dp) + .padding(4.dp) + ) { + val iconRes = if (sneakerShop.likeOrNot) Icons.Default.Favorite else Icons.Default.FavoriteBorder + Icon(imageVector = iconRes, contentDescription = "Favourite", tint = Color.Red) + } + + IconButton( + onClick = { + isAddedToCart = !isAddedToCart + }, + modifier = Modifier + .align(Alignment.BottomEnd) + .size(32.dp) + .padding(4.dp) + ) { + val iconRes = if (isAddedToCart) Icons.Default.ShoppingCart else Icons.Default.Add + Icon(imageVector = iconRes, contentDescription = "Favourite", tint = Color.Cyan) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/testktor/screen/auth/AuthScreen.kt b/app/src/main/java/com/example/testktor/screen/auth/AuthScreen.kt index c317886..ce1c8a1 100644 --- a/app/src/main/java/com/example/testktor/screen/auth/AuthScreen.kt +++ b/app/src/main/java/com/example/testktor/screen/auth/AuthScreen.kt @@ -1,21 +1,16 @@ package com.example.testktor.screen.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.Spacer 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 @@ -23,15 +18,16 @@ 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.method.auth.BotBar +import com.example.testktor.method.auth.ButtonBack +import com.example.testktor.method.auth.Restore +import com.example.testktor.method.auth.TopBar import io.ktor.client.HttpClient import io.ktor.client.engine.android.Android @@ -72,17 +68,12 @@ fun AuthContent( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { - // Отображение текста "Success" в левом верхнем углу + ButtonBack(navController) + + Spacer(modifier = Modifier.height(140.dp)) + if (authSuccess != null){ 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) -// ) navController.navigate("mainSneakers_screen") } else{ Text( @@ -96,36 +87,8 @@ fun AuthContent( } } - 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() - ) + TopBar(emailIn, {emailIn = it}, passwordIn, {passwordIn = it}) + Restore(navController) Button( modifier = Modifier.width(350.dp).height(50.dp), @@ -138,45 +101,6 @@ fun AuthContent( 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 - ), - ) - } - - Row( - modifier = Modifier - .padding(top = 8.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - ClickableText( - text = buildAnnotatedString { append("Восстановить") }, - onClick = { - navController.navigate("forgotPassword_screen") - }, - style = TextStyle( - fontSize = 16.sp, - color = Color.LightGray - ), - ) - } + BotBar(navController) } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/example/testktor/screen/auth/BeforeAuthScreen.kt b/app/src/main/java/com/example/testktor/screen/auth/BeforeAuthScreen.kt index 7ad5f32..6e69d2f 100644 --- a/app/src/main/java/com/example/testktor/screen/auth/BeforeAuthScreen.kt +++ b/app/src/main/java/com/example/testktor/screen/auth/BeforeAuthScreen.kt @@ -1,19 +1,13 @@ 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 @@ -24,17 +18,11 @@ 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 +import com.example.testktor.method.auth.Sliderik +import com.example.testktor.method.auth.Textik @Composable fun FirstScreen(onNavigateToSliderScreen: () -> Unit) { @@ -78,52 +66,11 @@ fun SliderScreen(onNavigateToAuthScreen: () -> Unit) { .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) - ) + Textik(imageId, textList, textList2, currentIndex) 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)) + Sliderik(sliderValue, maxIndex){ newValue -> sliderValue = newValue } Button( onClick = { diff --git a/app/src/main/java/com/example/testktor/screen/auth/ForgotPasswordScreen.kt b/app/src/main/java/com/example/testktor/screen/auth/ForgotPasswordScreen.kt index b13d9f5..ddcc53d 100644 --- a/app/src/main/java/com/example/testktor/screen/auth/ForgotPasswordScreen.kt +++ b/app/src/main/java/com/example/testktor/screen/auth/ForgotPasswordScreen.kt @@ -30,6 +30,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController import com.example.testktor.forgotPassword +import com.example.testktor.method.auth.BarForgot import com.example.testktor.resetPassword import io.ktor.client.HttpClient import io.ktor.client.engine.android.Android @@ -67,7 +68,6 @@ fun ForgotPasswordContent( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { - // Отображение текста "Success" в левом верхнем углу if (forgotSuccess != null){ if (forgotSuccess == "Success") { navController.navigate("resetPassword_screen") @@ -83,28 +83,7 @@ fun ForgotPasswordContent( } } - 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 } - ) + BarForgot(emailIn){emailIn = it} Button( modifier = Modifier.width(350.dp).height(50.dp), diff --git a/app/src/main/java/com/example/testktor/screen/auth/MainSneakersScreen.kt b/app/src/main/java/com/example/testktor/screen/auth/MainSneakersScreen.kt deleted file mode 100644 index 6e2b14c..0000000 --- a/app/src/main/java/com/example/testktor/screen/auth/MainSneakersScreen.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.example.testktor.screen.auth - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -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.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import com.example.testktor.Sneaker -import com.example.testktor.authUser -import com.example.testktor.getSneakers -import io.ktor.client.HttpClient -import io.ktor.client.engine.android.Android -import kotlinx.coroutines.launch - -@Composable -fun MainSneakersScreen(navController: NavController) { - var sneakers by remember { mutableStateOf>(emptyList()) } - val coroutineScope = rememberCoroutineScope() - - val client = HttpClient(Android) - - LaunchedEffect(Unit) { - coroutineScope.launch { - sneakers = getSneakers(client) - } - } - - SneakersContent(sneakers) -} - -@Composable -fun SneakersContent( - sneakers: List -) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text(text = "Список кроссовок", fontSize = 24.sp, modifier = Modifier.padding(bottom = 16.dp)) - - LazyColumn(modifier = Modifier.fillMaxWidth()) { - items(sneakers) { sneaker -> - Text(text = sneaker.name, fontSize = 18.sp, modifier = Modifier.padding(8.dp)) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/testktor/screen/auth/RegistrationScreen.kt b/app/src/main/java/com/example/testktor/screen/auth/RegistrationScreen.kt index 084c49b..92e783f 100644 --- a/app/src/main/java/com/example/testktor/screen/auth/RegistrationScreen.kt +++ b/app/src/main/java/com/example/testktor/screen/auth/RegistrationScreen.kt @@ -2,19 +2,15 @@ package com.example.testktor.screen.auth import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row +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.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.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -23,15 +19,12 @@ 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.testktor.authUser +import com.example.testktor.method.auth.BotBarReg +import com.example.testktor.method.auth.TopBarReg import com.example.testktor.regUser import io.ktor.client.HttpClient import io.ktor.client.engine.android.Android @@ -77,17 +70,9 @@ fun RegContent( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { - // Отображение текста "Success" в левом верхнем углу if (regSuccess != null){ if (regSuccess == "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) - ) + navController.navigate("auth_screen") } else{ Text( text = "Error", @@ -100,42 +85,9 @@ fun RegContent( } } - Text( - text = "Регистрация!", - style = TextStyle(fontSize = 32.sp, fontWeight = FontWeight.Bold), - modifier = Modifier.height(60.dp).padding(bottom = 20.dp) - ) + Spacer(modifier = Modifier.height(140.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 = nameIn, - onValueChange = { nameIn = it } - ) - - 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 } - ) + TopBarReg(nameIn, {nameIn = it}, emailIn, {emailIn = it}, passwordIn, {passwordIn = it}) Button( modifier = Modifier.width(350.dp).height(50.dp), @@ -148,120 +100,8 @@ fun RegContent( Text("Зарегистрироваться") } - Row( - modifier = Modifier - .padding(top = 16.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - Text( - text = "Есть аккаунт? ", - style = TextStyle(fontSize = 16.sp, color = Color.Black) - ) + Spacer(modifier = Modifier.height(140.dp)) - ClickableText( - text = buildAnnotatedString { append("Войти") }, - onClick = { - navController.navigate("auth_screen") - }, - style = TextStyle( - fontSize = 16.sp, - color = Color.Black - ), - ) - } + BotBarReg(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/screen/auth/ResetPasswordScreen.kt b/app/src/main/java/com/example/testktor/screen/auth/ResetPasswordScreen.kt index 690c06e..3203456 100644 --- a/app/src/main/java/com/example/testktor/screen/auth/ResetPasswordScreen.kt +++ b/app/src/main/java/com/example/testktor/screen/auth/ResetPasswordScreen.kt @@ -25,7 +25,10 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController +import com.android.identity.cbor.Uint import com.example.testktor.authUser +import com.example.testktor.method.auth.TextFieldsReset +import com.example.testktor.method.auth.TopBarReset import com.example.testktor.resetPassword import io.ktor.client.HttpClient import io.ktor.client.engine.android.Android @@ -67,17 +70,9 @@ fun ResetPasswordContent( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { - // Отображение текста "Success" в левом верхнем углу if (resetSuccess != null){ if (resetSuccess == "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) - ) + navController.navigate("auth_screen") } else{ Text( text = "Error", @@ -90,35 +85,8 @@ fun ResetPasswordContent( } } - 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 = 3 - ) - - Text(text = "OTP Code", modifier = Modifier.padding(end = 255.dp)) - TextField( - modifier = Modifier.width(300.dp).height(70.dp).padding(bottom = 16.dp), - value = codeIn, - onValueChange = { codeIn = it } - ) - - Text(text = "New Password", modifier = Modifier.padding(end = 255.dp)) - TextField( - modifier = Modifier.width(300.dp).height(70.dp).padding(bottom = 16.dp), - value = newPasswordIn, - onValueChange = { newPasswordIn = it } - ) + TopBarReset() + TextFieldsReset(codeIn, {codeIn = it}, newPasswordIn, {newPasswordIn = it}) Button( modifier = Modifier.width(350.dp).height(50.dp), diff --git a/app/src/main/java/com/example/testktor/screen/main/MainSneakersScreen.kt b/app/src/main/java/com/example/testktor/screen/main/MainSneakersScreen.kt new file mode 100644 index 0000000..f128cee --- /dev/null +++ b/app/src/main/java/com/example/testktor/screen/main/MainSneakersScreen.kt @@ -0,0 +1,99 @@ +package com.example.testktor.screen.main + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateListOf +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.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController +import com.example.testktor.Category +import com.example.testktor.Sneaker +import com.example.testktor.SneakerCategoryResponse +import com.example.testktor.SneakerShop +import com.example.testktor.getSneakers +import com.example.testktor.method.main.BottomNavigationBar +import com.example.testktor.method.main.CategorySelection +import com.example.testktor.method.main.OverSmth +import com.example.testktor.method.main.SalesBar +import com.example.testktor.method.main.Searchbar +import com.example.testktor.method.main.SneakerSelection +import com.example.testktor.method.main.TopNavigationBar +import io.ktor.client.HttpClient +import io.ktor.client.engine.android.Android + +@Composable +fun MainSneakersScreen(navController: NavController) { + val searchBox by remember { mutableStateOf("") } + var sneakersCategories by remember { mutableStateOf(SneakerCategoryResponse(emptyList(), emptyList())) } + val coroutineScope = rememberCoroutineScope() + val client = remember { HttpClient(Android) } + + LaunchedEffect(Unit) { + sneakersCategories = getSneakers(client) ?: SneakerCategoryResponse(emptyList(), emptyList()) + } + + Box(modifier = Modifier + .fillMaxSize() + .background(Color(0xFFF7F7F9))) { + SneakersContent(sneakersCategories, searchBox) + } + +} + +@Composable +fun SneakersContent( + sneakersCategories: SneakerCategoryResponse, + searchBox: String +) { + var searchBoxIn by remember { mutableStateOf(searchBox) } + var selectedCategory by remember { mutableStateOf(null) } + var sneakers by remember(selectedCategory) { + mutableStateOf( + sneakersCategories.sneakers.filter { + selectedCategory == null || it.categoryId == selectedCategory?.id + }.map { + sneaker -> SneakerShop(sneaker, false) + } + ) + } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + ) + { + TopNavigationBar() + Searchbar(searchBoxIn, {searchBoxIn = it}) + + + Column { + Text(text = "Категории", fontSize = 16.sp) + + CategorySelection( + categories = sneakersCategories.categories, + selectedCategory = selectedCategory, + onCategorySelected = { selectedCategory = it } + ) + } + + OverSmth("Популярное") + SneakerSelection(sneakers = sneakers) + SalesBar() + BottomNavigationBar() + } +} diff --git a/app/src/main/res/drawable/add_sneaker.png b/app/src/main/res/drawable/add_sneaker.png new file mode 100644 index 0000000..48f2d7a Binary files /dev/null and b/app/src/main/res/drawable/add_sneaker.png differ diff --git a/app/src/main/res/drawable/bottom.png b/app/src/main/res/drawable/bottom.png new file mode 100644 index 0000000..26077f3 Binary files /dev/null and b/app/src/main/res/drawable/bottom.png differ diff --git a/app/src/main/res/drawable/buy_sneaker.png b/app/src/main/res/drawable/buy_sneaker.png new file mode 100644 index 0000000..637db4b Binary files /dev/null and b/app/src/main/res/drawable/buy_sneaker.png differ diff --git a/app/src/main/res/drawable/frame.png b/app/src/main/res/drawable/frame.png new file mode 100644 index 0000000..29e0098 Binary files /dev/null and b/app/src/main/res/drawable/frame.png differ diff --git a/app/src/main/res/drawable/frame31.png b/app/src/main/res/drawable/frame31.png new file mode 100644 index 0000000..d95ad26 Binary files /dev/null and b/app/src/main/res/drawable/frame31.png differ diff --git a/app/src/main/res/drawable/group12.png b/app/src/main/res/drawable/group12.png new file mode 100644 index 0000000..9e5af62 Binary files /dev/null and b/app/src/main/res/drawable/group12.png differ diff --git a/app/src/main/res/drawable/group123.png b/app/src/main/res/drawable/group123.png new file mode 100644 index 0000000..06845fd Binary files /dev/null and b/app/src/main/res/drawable/group123.png differ diff --git a/app/src/main/res/drawable/hamburger.png b/app/src/main/res/drawable/hamburger.png new file mode 100644 index 0000000..5dd0a50 Binary files /dev/null and b/app/src/main/res/drawable/hamburger.png differ diff --git a/app/src/main/res/drawable/heart.png b/app/src/main/res/drawable/heart.png new file mode 100644 index 0000000..d082c13 Binary files /dev/null and b/app/src/main/res/drawable/heart.png differ diff --git a/app/src/main/res/drawable/heart_sneaker.png b/app/src/main/res/drawable/heart_sneaker.png new file mode 100644 index 0000000..f1e458e Binary files /dev/null and b/app/src/main/res/drawable/heart_sneaker.png differ diff --git a/app/src/main/res/drawable/home.png b/app/src/main/res/drawable/home.png new file mode 100644 index 0000000..dfbd0f3 Binary files /dev/null and b/app/src/main/res/drawable/home.png differ diff --git a/app/src/main/res/drawable/icon.png b/app/src/main/res/drawable/icon.png new file mode 100644 index 0000000..ff1199c Binary files /dev/null and b/app/src/main/res/drawable/icon.png differ diff --git a/app/src/main/res/drawable/img.png b/app/src/main/res/drawable/img.png new file mode 100644 index 0000000..735b366 Binary files /dev/null and b/app/src/main/res/drawable/img.png differ diff --git a/app/src/main/res/drawable/img_1.png b/app/src/main/res/drawable/img_1.png new file mode 100644 index 0000000..735b366 Binary files /dev/null and b/app/src/main/res/drawable/img_1.png differ