popularSneakersWindow;CategorySneakersWindow;MainViewModel;routeBuySneakers

This commit is contained in:
Your Name 2025-06-04 14:22:53 +03:00
parent d67c5c7289
commit 15b372db55
13 changed files with 509 additions and 89 deletions

View File

@ -4,16 +4,20 @@ 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.activity.viewModels
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.matuletest.ui.auth.FirstScreen import com.example.matuletest.ui.auth.FirstScreen
import com.example.matuletest.ui.auth.SliderScreen import com.example.matuletest.ui.auth.SliderScreen
import com.example.testktor.ViewModel.MainViewModel
import com.example.testktor.screen.auth.AuthScreen import com.example.testktor.screen.auth.AuthScreen
import com.example.testktor.screen.auth.ForgotPasswordScreen import com.example.testktor.screen.auth.ForgotPasswordScreen
import com.example.testktor.screen.main.MainSneakersScreen import com.example.testktor.screen.main.MainSneakersScreen
import com.example.testktor.screen.auth.RegScreen import com.example.testktor.screen.auth.RegScreen
import com.example.testktor.screen.auth.ResetPasswordScreen import com.example.testktor.screen.auth.ResetPasswordScreen
import com.example.testktor.screen.main.CategorySneakersScreen
import com.example.testktor.screen.main.PopularSneakersScreen
//import com.example.testktor.auth.AuthScreen //import com.example.testktor.auth.AuthScreen
//import com.example.testktor.auth.RegistrationScreen //import com.example.testktor.auth.RegistrationScreen
import com.example.testktor.ui.theme.TestKtorTheme import com.example.testktor.ui.theme.TestKtorTheme
@ -21,6 +25,9 @@ import com.example.testktor.ui.theme.TestKtorTheme
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val viewModel: MainViewModel by viewModels()
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
TestKtorTheme { TestKtorTheme {
@ -50,7 +57,13 @@ class MainActivity : ComponentActivity() {
ForgotPasswordScreen(navController) ForgotPasswordScreen(navController)
} }
composable("mainSneakers_screen") { composable("mainSneakers_screen") {
MainSneakersScreen(navController) MainSneakersScreen(navController, viewModel)
}
composable("popularSneakers_screen") {
PopularSneakersScreen(navController, viewModel)
}
composable("categorySneakers_screen") {
CategorySneakersScreen(navController, viewModel)
} }
} }
} }

View File

@ -29,6 +29,12 @@ data class SneakerShop(
var likeOrNot: Boolean var likeOrNot: Boolean
) )
@Serializable
data class BuySneakerRequest(val sneakerId: Int, val count: Int)
@Serializable
data class BuySneakersRequest(val sneakers: List<BuySneakerRequest>)
@Serializable @Serializable
data class Category( data class Category(
val id: Int, val id: Int,

View File

@ -1,7 +1,11 @@
package com.example.testktor.ViewModel package com.example.testktor.ViewModel
import android.util.Log
import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.text.ClickableText
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
@ -16,12 +20,18 @@ fun ClickableTextVM(
screen: String, screen: String,
style: TextStyle style: TextStyle
) { ) {
val isClick = remember { mutableStateOf(false) }
if(isClick.value){
if (navController != null){
navController.navigate(screen)
Log.d("lala", "ClickableTextVM: ")
isClick.value = false
}
}
ClickableText( ClickableText(
text = buildAnnotatedString { append(text) }, text = buildAnnotatedString { append(text) },
onClick = { onClick = {
if (navController != null){ isClick.value = !isClick.value
navController.navigate(screen)
}
}, },
style = style style = style
) )

View File

@ -0,0 +1,37 @@
package com.example.testktor.ViewModel
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testktor.Category
import com.example.testktor.SneakerCategoryResponse
import com.example.testktor.getSneakers
import io.ktor.client.HttpClient
import io.ktor.client.engine.android.Android
import kotlinx.coroutines.launch
class MainViewModel : ViewModel() {
var sneakersCategories by mutableStateOf(SneakerCategoryResponse(emptyList(), emptyList()))
private set
private val client = HttpClient(Android)
// var selectedCategory by mutableStateOf<Int?>(null)
var selectedCategory by mutableStateOf<Category?>(null)
init {
viewModelScope.launch {
sneakersCategories = getSneakers(client) ?: SneakerCategoryResponse(emptyList(), emptyList())
}
}
fun refreshData() {
viewModelScope.launch {
sneakersCategories = getSneakers(client) ?: SneakerCategoryResponse(emptyList(), emptyList())
}
}
}

View File

@ -72,7 +72,8 @@ suspend fun regUser(client: HttpClient, email: String, password: String, name: S
val json = Json { ignoreUnknownKeys = true } val json = Json { ignoreUnknownKeys = true }
val responseMap = json.decodeFromString<Map<String, String>>(responseBody) val responseMap = json.decodeFromString<Map<String, String>>(responseBody)
return responseMap["message"] == "Регистрация успешна" // return responseMap["message"] == "Регистрация успешна"
return true
} catch (e: Exception){ } catch (e: Exception){
Log.e("regUser", "Error during registration request", e) Log.e("regUser", "Error during registration request", e)
return false return false
@ -138,3 +139,26 @@ suspend fun getSneakers(client: HttpClient): SneakerCategoryResponse?{
null null
} }
} }
suspend fun buySneakers(client: HttpClient, order: BuySneakersRequest): Boolean {
return try {
val response: HttpResponse = client.post("http://10.0.2.2:8080/buySneakers") {
headers {
append(HttpHeaders.ContentType, "application/json")
}
setBody(order)
}
val responseBody = response.bodyAsText()
Log.d("buySneakers", "Response: $responseBody")
val json = Json { ignoreUnknownKeys = true }
val result = json.decodeFromString<Map<String, String>>(responseBody)
result["message"] == "Куплено"
} catch (e: Exception) {
Log.e("buySneakers", "Ошибка при покупке кроссовок", e)
false
}
}

View File

@ -0,0 +1,96 @@
package com.example.testktor.method.main
import androidx.compose.foundation.Canvas
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.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
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.SneakerShop
import com.example.testktor.ViewModel.MainViewModel
@Composable
fun TopWriteNavigationBar(navController: NavController, message: String, viewModel: MainViewModel) {
Row (
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
){
CategoryButtonBack(navController, "mainSneakers_screen", viewModel)
Box(
modifier = Modifier
.fillMaxWidth()
.weight(1f),
contentAlignment = Alignment.Center
) {
Text(
text = message,
fontSize = 30.sp
)
}
}
}
@Composable
fun SneakerCategorySelection(sneakers: List<SneakerShop>) {
Column(modifier = Modifier.fillMaxWidth()) {
sneakers.chunked(2).forEach { sneakerPair ->
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
sneakerPair.forEach { sneakerShop ->
SneakerButton(
sneakerShop = sneakerShop,
onClick = { /* TODO */ },
onFavoriteClick = { /* TODO */ }
)
}
}
}
}
}
@Composable
fun CategoryButtonBack(navController: NavController, screen: String, viewModel: MainViewModel){
IconButton(onClick = {
viewModel.selectedCategory = null
navController.navigate(screen) {
popUpTo(screen) { inclusive = true }
}
}) {
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
)
}
}
}

View File

@ -51,10 +51,10 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.example.testktor.Category import com.example.testktor.Category
import com.example.testktor.R import com.example.testktor.R
import com.example.testktor.Sneaker
import com.example.testktor.SneakerShop import com.example.testktor.SneakerShop
@Preview(showBackground = true) @Preview(showBackground = true)
@ -146,7 +146,7 @@ fun Searchbar(searchBox: String, onSearchChange: (String) -> Unit){
} }
@Composable @Composable
fun OverSmth(smth: String){ fun OverSmth(smth: String, navController: NavController?){
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -165,7 +165,9 @@ fun OverSmth(smth: String){
ClickableText( ClickableText(
text = buildAnnotatedString { append("Все") }, text = buildAnnotatedString { append("Все") },
onClick = {/* TODO: действие кнопки */}, onClick = { if (navController != null){
navController.navigate("popularSneakers_screen")
}},
style = TextStyle( style = TextStyle(
fontSize = 12.sp, fontSize = 12.sp,
color = Color.Cyan color = Color.Cyan
@ -182,7 +184,7 @@ fun SalesBar() {
.fillMaxWidth() .fillMaxWidth()
.padding(16.dp) .padding(16.dp)
) { ) {
OverSmth("Акции") OverSmth("Акции", null)
Box( Box(
modifier = Modifier modifier = Modifier
@ -300,7 +302,7 @@ fun CategoryButton(category: Category, isSelected: Boolean, onClick: () -> Unit)
modifier = Modifier modifier = Modifier
.padding(8.dp), .padding(8.dp),
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(
containerColor = if (isSelected) Color.Blue else Color.White containerColor = if (isSelected) Color.Cyan else Color.White
) )
) { ) {
Text(text = category.name, color = Color.Black) Text(text = category.name, color = Color.Black)

View File

@ -0,0 +1,2 @@
package com.example.testktor.method.main

View File

@ -36,20 +36,37 @@ fun AuthScreen(navController: NavController) {
var authSuccess by remember { mutableStateOf<String?>(null) } var authSuccess by remember { mutableStateOf<String?>(null) }
var email by remember { mutableStateOf("") } var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") } var password by remember { mutableStateOf("") }
var shouldAuth by remember { mutableStateOf(false) }
val client = HttpClient(Android) val client = HttpClient(Android)
LaunchedEffect(email, password) { LaunchedEffect(shouldAuth) {
if (email.isNotEmpty() && password.isNotEmpty()) { if (shouldAuth) {
val result = authUser(client, email, password) val result = authUser(client, email, password)
authSuccess = if (result) "Success" else "Failed" authSuccess = if (result) "Success" else "Failed"
shouldAuth = false
} }
} }
AuthContent(navController, authSuccess, email, password) { newEmail, newPassword -> LaunchedEffect(authSuccess) {
email = newEmail if (authSuccess == "Success") {
password = newPassword navController.navigate("mainSneakers_screen") {
popUpTo("auth_screen") { inclusive = true }
}
}
} }
AuthContent(
navController = navController,
authSuccess = authSuccess,
email = email,
password = password,
onAuth = { newEmail, newPassword ->
email = newEmail
password = newPassword
shouldAuth = true
}
)
} }
@Composable @Composable
@ -72,26 +89,24 @@ fun AuthContent(
Spacer(modifier = Modifier.height(20.dp)) Spacer(modifier = Modifier.height(20.dp))
if (authSuccess != null){ if (authSuccess == "Failed") {
if (authSuccess == "Success") { Text(
navController.navigate("mainSneakers_screen") text = "Ошибка авторизации",
} else{ modifier = Modifier
Text( .padding(start = 16.dp, top = 16.dp)
text = "Error", .align(Alignment.Start),
modifier = Modifier color = Color.Red,
.padding(start = 16.dp, top = 16.dp) style = TextStyle(fontSize = 18.sp, fontWeight = FontWeight.Bold)
.align(Alignment.Start), )
color = Color.Green,
style = TextStyle(fontSize = 18.sp, fontWeight = FontWeight.Bold)
)
}
} }
TopBar(emailIn, {emailIn = it}, passwordIn, {passwordIn = it}) TopBar(emailIn, { emailIn = it }, passwordIn, { passwordIn = it })
Restore(navController) Restore(navController)
Button( Button(
modifier = Modifier.width(350.dp).height(50.dp), modifier = Modifier
.width(350.dp)
.height(50.dp),
colors = androidx.compose.material3.ButtonDefaults.buttonColors( colors = androidx.compose.material3.ButtonDefaults.buttonColors(
containerColor = Color(0xFF48B2E7), containerColor = Color(0xFF48B2E7),
contentColor = Color.White contentColor = Color.White

View File

@ -30,6 +30,29 @@ import com.example.testktor.regUser
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.engine.android.Android import io.ktor.client.engine.android.Android
//@Composable
//fun RegScreen(navController: NavController) {
// var regSuccess by remember { mutableStateOf<String?>(null) }
// var email by remember { mutableStateOf("") }
// var password by remember { mutableStateOf("") }
// var name by remember { mutableStateOf("") }
//
// val client = HttpClient(Android)
//
// LaunchedEffect(email, password) {
// if (email.isNotEmpty() && password.isNotEmpty()) {
// val result = regUser(client, email, password, name)
// regSuccess = if (result) "Success" else "Failed"
// }
// }
//
// RegContent(navController, regSuccess, email, password, name) { newEmail, newPassword, newName ->
// email = newEmail
// password = newPassword
// name = newName
// }
//}
@Composable @Composable
fun RegScreen(navController: NavController) { fun RegScreen(navController: NavController) {
var regSuccess by remember { mutableStateOf<String?>(null) } var regSuccess by remember { mutableStateOf<String?>(null) }
@ -39,18 +62,29 @@ fun RegScreen(navController: NavController) {
val client = HttpClient(Android) val client = HttpClient(Android)
LaunchedEffect(email, password) { var shouldRegister by remember { mutableStateOf(false) }
if (email.isNotEmpty() && password.isNotEmpty()) {
LaunchedEffect(shouldRegister) {
if (shouldRegister) {
val result = regUser(client, email, password, name) val result = regUser(client, email, password, name)
regSuccess = if (result) "Success" else "Failed" regSuccess = if (result) "Success" else "Failed"
shouldRegister = false
} }
} }
RegContent(navController, regSuccess, email, password, name) { newEmail, newPassword, newName -> RegContent(
email = newEmail navController = navController,
password = newPassword regSuccess = regSuccess,
name = newName email = email,
} password = password,
name = name,
onReg = { newEmail, newPassword, newName ->
email = newEmail
password = newPassword
name = newName
shouldRegister = true
}
)
} }
@Composable @Composable
@ -66,6 +100,14 @@ fun RegContent(
var passwordIn by remember { mutableStateOf(password) } var passwordIn by remember { mutableStateOf(password) }
var nameIn by remember { mutableStateOf(name) } var nameIn by remember { mutableStateOf(name) }
LaunchedEffect(regSuccess) {
if (regSuccess == "Success") {
navController.navigate("auth_screen") {
popUpTo("reg_screen") { inclusive = true }
}
}
}
Column( Column(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
@ -75,30 +117,37 @@ fun RegContent(
Spacer(modifier = Modifier.height(20.dp)) Spacer(modifier = Modifier.height(20.dp))
if (regSuccess != null){ if (regSuccess == "Failed") {
if (regSuccess == "Success") { Text(
navController.navigate("auth_screen") text = "Ошибка регистрации",
} else{ modifier = Modifier
Text( .padding(start = 16.dp, top = 16.dp)
text = "Error", .align(Alignment.Start),
modifier = Modifier color = Color.Red,
.padding(start = 16.dp, top = 16.dp) style = TextStyle(fontSize = 18.sp, fontWeight = FontWeight.Bold)
.align(Alignment.Start), )
color = Color.Green,
style = TextStyle(fontSize = 18.sp, fontWeight = FontWeight.Bold)
)
}
} }
TopBarReg(nameIn, {nameIn = it}, emailIn, {emailIn = it}, passwordIn, {passwordIn = it}) TopBarReg(
name = nameIn,
onNameChange = { nameIn = it },
email = emailIn,
onEmailChange = { emailIn = it },
password = passwordIn,
onPasswordChange = { passwordIn = it }
)
Button( Button(
modifier = Modifier.width(350.dp).height(50.dp), modifier = Modifier
.width(350.dp)
.height(50.dp),
colors = androidx.compose.material3.ButtonDefaults.buttonColors( colors = androidx.compose.material3.ButtonDefaults.buttonColors(
containerColor = Color(0xFF48B2E7), containerColor = Color(0xFF48B2E7),
contentColor = Color.White contentColor = Color.White
), ),
onClick = { onReg(emailIn, passwordIn, nameIn) } onClick = {
onReg(emailIn, passwordIn, nameIn)
}
) { ) {
Text("Зарегистрироваться") Text("Зарегистрироваться")
} }
@ -108,3 +157,59 @@ fun RegContent(
BotBarReg(navController) BotBarReg(navController)
} }
} }
//@Composable
//fun RegContent(
// navController: NavController,
// regSuccess: String?,
// email: String,
// password: String,
// name: String,
// onReg: @Composable (String, String, String) -> Unit
//) {
// var emailIn by remember { mutableStateOf(email) }
// var passwordIn by remember { mutableStateOf(password) }
// var nameIn by remember { mutableStateOf(name) }
//
// Column(
// modifier = Modifier.fillMaxSize(),
// horizontalAlignment = Alignment.CenterHorizontally,
// verticalArrangement = Arrangement.Center
// ) {
// ButtonBack(navController, "auth_screen")
//
// Spacer(modifier = Modifier.height(20.dp))
//
// if (regSuccess != null){
// if (regSuccess == "Success") {
// navController.navigate("auth_screen")
// } else{
// Text(
// text = "Error",
// modifier = Modifier
// .padding(start = 16.dp, top = 16.dp)
// .align(Alignment.Start),
// color = Color.Green,
// style = TextStyle(fontSize = 18.sp, fontWeight = FontWeight.Bold)
// )
// }
// }
//
// TopBarReg(nameIn, {nameIn = it}, emailIn, {emailIn = it}, passwordIn, {passwordIn = it})
//
// Button(
// modifier = Modifier.width(350.dp).height(50.dp),
// colors = androidx.compose.material3.ButtonDefaults.buttonColors(
// containerColor = Color(0xFF48B2E7),
// contentColor = Color.White
// ),
// onClick = { onReg(emailIn, passwordIn, nameIn) }
// ) {
// Text("Зарегистрироваться")
// }
//
// Spacer(modifier = Modifier.height(140.dp))
//
// BotBarReg(navController)
// }
//}

View File

@ -0,0 +1,68 @@
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.material3.Text
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.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.example.testktor.SneakerShop
import com.example.testktor.ViewModel.MainViewModel
import com.example.testktor.method.main.CategorySelection
import com.example.testktor.method.main.SneakerCategorySelection
import com.example.testktor.method.main.TopWriteNavigationBar
@Composable
fun CategorySneakersScreen(
navController: NavController,
viewModel: MainViewModel
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFFF7F7F9))
) {
CategorySneakersContent(navController, viewModel)
}
}
@Composable
fun CategorySneakersContent(
navController: NavController,
viewModel: MainViewModel
){
var sneakers by remember(viewModel.selectedCategory) {
mutableStateOf(
viewModel.sneakersCategories.sneakers.filter {
viewModel.selectedCategory == null || it.categoryId == viewModel.selectedCategory?.id
}.map { sneaker ->
SneakerShop(sneaker, false)
}
)
}
Column {
TopWriteNavigationBar(navController, "outdoor", viewModel)
Text(text = "Категории", fontSize = 16.sp)
CategorySelection(
categories = viewModel.sneakersCategories.categories,
selectedCategory = viewModel.selectedCategory,
onCategorySelected = { category ->
viewModel.selectedCategory = category
}
)
SneakerCategorySelection(sneakers)
}
}

View File

@ -7,24 +7,18 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.navigation.NavController import androidx.navigation.NavController
import com.example.testktor.Category
import com.example.testktor.Sneaker
import com.example.testktor.SneakerCategoryResponse import com.example.testktor.SneakerCategoryResponse
import com.example.testktor.SneakerShop import com.example.testktor.SneakerShop
import com.example.testktor.getSneakers import com.example.testktor.ViewModel.MainViewModel
import com.example.testktor.method.main.BottomNavigationBar import com.example.testktor.method.main.BottomNavigationBar
import com.example.testktor.method.main.CategorySelection import com.example.testktor.method.main.CategorySelection
import com.example.testktor.method.main.OverSmth import com.example.testktor.method.main.OverSmth
@ -32,41 +26,33 @@ import com.example.testktor.method.main.SalesBar
import com.example.testktor.method.main.Searchbar import com.example.testktor.method.main.Searchbar
import com.example.testktor.method.main.SneakerSelection import com.example.testktor.method.main.SneakerSelection
import com.example.testktor.method.main.TopNavigationBar import com.example.testktor.method.main.TopNavigationBar
import io.ktor.client.HttpClient
import io.ktor.client.engine.android.Android
@Composable @Composable
fun MainSneakersScreen(navController: NavController) { fun MainSneakersScreen(navController: NavController, viewModel: MainViewModel) {
val sneakersCategories = viewModel.sneakersCategories
val searchBox by remember { mutableStateOf("") } val searchBox by remember { mutableStateOf("") }
var sneakersCategories by remember { mutableStateOf(SneakerCategoryResponse(emptyList(), emptyList())) }
val coroutineScope = rememberCoroutineScope()
val client = remember { HttpClient(Android) }
LaunchedEffect(Unit) { Box(
sneakersCategories = getSneakers(client) ?: SneakerCategoryResponse(emptyList(), emptyList()) modifier = Modifier
.fillMaxSize()
.background(Color(0xFFF7F7F9))
) {
SneakersContent(sneakersCategories, searchBox, navController, viewModel)
} }
Box(modifier = Modifier
.fillMaxSize()
.background(Color(0xFFF7F7F9))) {
SneakersContent(sneakersCategories, searchBox)
}
} }
@Composable @Composable
fun SneakersContent( fun SneakersContent(
sneakersCategories: SneakerCategoryResponse, sneakersCategories: SneakerCategoryResponse,
searchBox: String searchBox: String,
navController: NavController,
viewModel: MainViewModel
) { ) {
var searchBoxIn by remember { mutableStateOf(searchBox) } var searchBoxIn by remember { mutableStateOf(searchBox) }
var selectedCategory by remember { mutableStateOf<Category?>(null) } var sneakers by remember(viewModel.sneakersCategories) {
var sneakers by remember(selectedCategory) {
mutableStateOf( mutableStateOf(
sneakersCategories.sneakers.filter { viewModel.sneakersCategories.sneakers.map { sneaker ->
selectedCategory == null || it.categoryId == selectedCategory?.id SneakerShop(sneaker, false)
}.map {
sneaker -> SneakerShop(sneaker, false)
} }
) )
} }
@ -75,23 +61,27 @@ fun SneakersContent(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(16.dp), .padding(16.dp),
) ) {
{
TopNavigationBar() TopNavigationBar()
Searchbar(searchBoxIn, {searchBoxIn = it}) Searchbar(searchBoxIn, { searchBoxIn = it })
Column { Column {
Text(text = "Категории", fontSize = 16.sp) Text(text = "Категории", fontSize = 16.sp)
CategorySelection( CategorySelection(
categories = sneakersCategories.categories, categories = sneakersCategories.categories,
selectedCategory = selectedCategory, selectedCategory = viewModel.selectedCategory,
onCategorySelected = { selectedCategory = it } onCategorySelected = { category ->
viewModel.selectedCategory = category
if (category != null) {
navController.navigate("categorySneakers_screen")
}
}
) )
} }
OverSmth("Популярное") OverSmth("Популярное", navController)
SneakerSelection(sneakers = sneakers) SneakerSelection(sneakers = sneakers)
SalesBar() SalesBar()
BottomNavigationBar() BottomNavigationBar()

View File

@ -0,0 +1,52 @@
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.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.Modifier
import androidx.compose.ui.graphics.Color
import androidx.navigation.NavController
import com.example.testktor.SneakerShop
import com.example.testktor.ViewModel.MainViewModel
import com.example.testktor.method.main.SneakerCategorySelection
import com.example.testktor.method.main.TopWriteNavigationBar
@Composable
fun PopularSneakersScreen(
navController: NavController,
viewModel: MainViewModel
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFFF7F7F9))
) {
FavouriteSneakersContent(navController, viewModel)
}
}
@Composable
fun FavouriteSneakersContent(
navController: NavController,
viewModel: MainViewModel
) {
var sneakers by remember(viewModel.sneakersCategories) {
mutableStateOf(
viewModel.sneakersCategories.sneakers.map { sneaker ->
SneakerShop(sneaker, false)
}
)
}
Column {
TopWriteNavigationBar(navController, "Популярное", viewModel)
SneakerCategorySelection(sneakers)
}
}